effect-orpc 0.2.2 → 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/dist/node.js CHANGED
@@ -1,19 +1,20 @@
1
1
  import {
2
2
  installFiberContextBridge
3
- } from "./chunk-VOWRLWZZ.js";
3
+ } from "./chunk-IJP6L2XR.js";
4
4
 
5
5
  // src/node.ts
6
6
  import { AsyncLocalStorage } from "async_hooks";
7
7
  import { Effect } from "effect";
8
8
  var fiberRefsStorage = new AsyncLocalStorage();
9
9
  var bridge = {
10
- getCurrentFiberRefs: () => fiberRefsStorage.getStore()
10
+ getCurrentFiberRefs: () => fiberRefsStorage.getStore(),
11
+ runWithFiberRefs: (fiberRefs, fn) => fiberRefsStorage.run(fiberRefs, fn)
11
12
  };
12
13
  installFiberContextBridge(bridge);
13
14
  function withFiberContext(fn) {
14
15
  return Effect.flatMap(
15
16
  Effect.getFiberRefs,
16
- (fiberRefs) => Effect.promise(() => fiberRefsStorage.run(fiberRefs, fn))
17
+ (fiberRefs) => Effect.promise(() => bridge.runWithFiberRefs(fiberRefs, fn))
17
18
  );
18
19
  }
19
20
  export {
package/dist/node.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/node.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { FiberRefs } from \"effect\";\nimport { Effect } from \"effect\";\n\nimport {\n installFiberContextBridge,\n type FiberContextBridge,\n} from \"./fiber-context-bridge\";\n\nconst fiberRefsStorage = new AsyncLocalStorage<FiberRefs.FiberRefs>();\n\nconst bridge: FiberContextBridge = {\n getCurrentFiberRefs: () => fiberRefsStorage.getStore(),\n};\n\ninstallFiberContextBridge(bridge);\n\nexport function withFiberContext<T>(fn: () => Promise<T>): Effect.Effect<T> {\n return Effect.flatMap(Effect.getFiberRefs, (fiberRefs) =>\n Effect.promise(() => fiberRefsStorage.run(fiberRefs, fn)),\n );\n}\n"],"mappings":";;;;;AAAA,SAAS,yBAAyB;AAGlC,SAAS,cAAc;AAOvB,IAAM,mBAAmB,IAAI,kBAAuC;AAEpE,IAAM,SAA6B;AAAA,EACjC,qBAAqB,MAAM,iBAAiB,SAAS;AACvD;AAEA,0BAA0B,MAAM;AAEzB,SAAS,iBAAoB,IAAwC;AAC1E,SAAO,OAAO;AAAA,IAAQ,OAAO;AAAA,IAAc,CAAC,cAC1C,OAAO,QAAQ,MAAM,iBAAiB,IAAI,WAAW,EAAE,CAAC;AAAA,EAC1D;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/node.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { FiberRefs } from \"effect\";\nimport { Effect } from \"effect\";\n\nimport {\n installFiberContextBridge,\n type FiberContextBridge,\n} from \"./fiber-context-bridge\";\n\nconst fiberRefsStorage = new AsyncLocalStorage<FiberRefs.FiberRefs>();\n\nconst bridge: FiberContextBridge = {\n getCurrentFiberRefs: () => fiberRefsStorage.getStore(),\n runWithFiberRefs: (fiberRefs, fn) => fiberRefsStorage.run(fiberRefs, fn),\n};\n\ninstallFiberContextBridge(bridge);\n\nexport function withFiberContext<T>(fn: () => Promise<T>): Effect.Effect<T> {\n return Effect.flatMap(Effect.getFiberRefs, (fiberRefs) =>\n Effect.promise(() => bridge.runWithFiberRefs!(fiberRefs, fn)),\n );\n}\n"],"mappings":";;;;;AAAA,SAAS,yBAAyB;AAGlC,SAAS,cAAc;AAOvB,IAAM,mBAAmB,IAAI,kBAAuC;AAEpE,IAAM,SAA6B;AAAA,EACjC,qBAAqB,MAAM,iBAAiB,SAAS;AAAA,EACrD,kBAAkB,CAAC,WAAW,OAAO,iBAAiB,IAAI,WAAW,EAAE;AACzE;AAEA,0BAA0B,MAAM;AAEzB,SAAS,iBAAoB,IAAwC;AAC1E,SAAO,OAAO;AAAA,IAAQ,OAAO;AAAA,IAAc,CAAC,cAC1C,OAAO,QAAQ,MAAM,OAAO,iBAAkB,WAAW,EAAE,CAAC;AAAA,EAC9D;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effect-orpc",
3
- "version": "0.2.2",
3
+ "version": "0.4.0",
4
4
  "keywords": [
5
5
  "effect",
6
6
  "orpc",
package/src/contract.ts CHANGED
@@ -27,13 +27,18 @@ import type {
27
27
  } from "@orpc/server";
28
28
  import { implement } from "@orpc/server";
29
29
  import type { IntersectPick } from "@orpc/shared";
30
- import type { ManagedRuntime } from "effect";
30
+ import type { Layer, ManagedRuntime } from "effect";
31
31
 
32
32
  import { addSpanStackTrace } from "./effect-builder";
33
33
  import { enhanceEffectRouter } from "./effect-enhance-router";
34
34
  import { EffectDecoratedProcedure } from "./effect-procedure";
35
35
  import { createEffectProcedureHandler } from "./effect-runtime";
36
36
  import { effectContractSymbol, getEffectContractErrorMap } from "./eoc";
37
+ import type {
38
+ EffectRuntimeRunner,
39
+ EffectRuntimeSource,
40
+ } from "./runtime-source";
41
+ import { makeEffectRuntimeRunner } from "./runtime-source";
37
42
  import type { EffectErrorMap } from "./tagged-error";
38
43
  import { effectErrorMapToErrorMap } from "./tagged-error";
39
44
  import type { EffectErrorMapToErrorMap, EffectProcedureHandler } from "./types";
@@ -314,13 +319,13 @@ const CONTRACT_HIDDEN_METHODS = new Set([
314
319
  ]);
315
320
 
316
321
  function makeEnhanceOptions<TRequirementsProvided, TRuntimeError>(
317
- runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>,
322
+ runner: EffectRuntimeRunner<TRequirementsProvided, TRuntimeError>,
318
323
  ) {
319
324
  return {
320
325
  middlewares: [],
321
326
  errorMap: {},
322
327
  dedupeLeadingMiddlewares: true,
323
- runtime,
328
+ runner,
324
329
  } as const;
325
330
  }
326
331
 
@@ -331,7 +336,7 @@ function wrapContractNode<
331
336
  >(
332
337
  contract: TContract,
333
338
  target: any,
334
- runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>,
339
+ runner: EffectRuntimeRunner<TRequirementsProvided, TRuntimeError>,
335
340
  ): EffectImplementerInternal<
336
341
  TContract,
337
342
  Context,
@@ -360,9 +365,9 @@ function wrapContractNode<
360
365
  ...currentTarget["~orpc"],
361
366
  errorMap: effectErrorMapToErrorMap(effectErrorMap),
362
367
  effectErrorMap,
363
- runtime,
368
+ runner,
364
369
  handler: createEffectProcedureHandler({
365
- runtime,
370
+ runner,
366
371
  effectErrorMap,
367
372
  effectFn,
368
373
  defaultCaptureStackTrace: addSpanStackTrace(),
@@ -383,7 +388,7 @@ function wrapContractNode<
383
388
  currentTarget,
384
389
  args,
385
390
  ),
386
- runtime,
391
+ runner,
387
392
  );
388
393
 
389
394
  cache.set(prop, use);
@@ -403,7 +408,7 @@ function wrapContractNode<
403
408
  currentTarget,
404
409
  args,
405
410
  ),
406
- runtime,
411
+ runner,
407
412
  );
408
413
 
409
414
  cache.set(prop, wrappedMethod);
@@ -418,7 +423,7 @@ function wrapContractNode<
418
423
  currentTarget,
419
424
  args,
420
425
  ) as any,
421
- makeEnhanceOptions(runtime),
426
+ makeEnhanceOptions(runner),
422
427
  );
423
428
 
424
429
  cache.set(prop, wrappedMethod);
@@ -429,7 +434,7 @@ function wrapContractNode<
429
434
  const child = wrapContractNode(
430
435
  (contract as Record<string, AnyContractRouter>)[prop]!,
431
436
  Reflect.get(currentTarget, prop, receiver),
432
- runtime,
437
+ runner,
433
438
  );
434
439
 
435
440
  cache.set(prop, child);
@@ -463,6 +468,21 @@ function wrapContractNode<
463
468
  >;
464
469
  }
465
470
 
471
+ export function implementEffect<
472
+ TContract extends AnyContractRouter,
473
+ TRequirementsProvided,
474
+ TRuntimeError,
475
+ >(
476
+ contract: TContract,
477
+ layer: Layer.Layer<TRequirementsProvided, TRuntimeError, never>,
478
+ ): EffectImplementer<
479
+ TContract,
480
+ Record<never, never>,
481
+ Record<never, never>,
482
+ TRequirementsProvided,
483
+ TRuntimeError
484
+ >;
485
+
466
486
  export function implementEffect<
467
487
  TContract extends AnyContractRouter,
468
488
  TRequirementsProvided,
@@ -476,11 +496,26 @@ export function implementEffect<
476
496
  Record<never, never>,
477
497
  TRequirementsProvided,
478
498
  TRuntimeError
499
+ >;
500
+
501
+ export function implementEffect<
502
+ TContract extends AnyContractRouter,
503
+ TRequirementsProvided,
504
+ TRuntimeError,
505
+ >(
506
+ contract: TContract,
507
+ source: EffectRuntimeSource<TRequirementsProvided, TRuntimeError>,
508
+ ): EffectImplementer<
509
+ TContract,
510
+ Record<never, never>,
511
+ Record<never, never>,
512
+ TRequirementsProvided,
513
+ TRuntimeError
479
514
  > {
480
515
  return wrapContractNode(
481
516
  contract,
482
517
  implement(contract),
483
- runtime,
518
+ makeEffectRuntimeRunner(source),
484
519
  ) as EffectImplementer<
485
520
  TContract,
486
521
  Record<never, never>,
@@ -7,11 +7,15 @@ import type {
7
7
  } from "@orpc/contract";
8
8
  import type { Context, Router } from "@orpc/server";
9
9
  import { Builder, fallbackConfig, lazy } from "@orpc/server";
10
- import type { ManagedRuntime } from "effect";
10
+ import { Layer, ManagedRuntime } from "effect";
11
11
 
12
12
  import { enhanceEffectRouter } from "./effect-enhance-router";
13
13
  import { EffectDecoratedProcedure } from "./effect-procedure";
14
- import { createEffectProcedureHandler } from "./effect-runtime";
14
+ import {
15
+ createEffectPipelineMiddleware,
16
+ createEffectProcedureHandler,
17
+ isEffectMiddleware,
18
+ } from "./effect-runtime";
15
19
  import {
16
20
  createNodeProxy,
17
21
  unhandled,
@@ -23,6 +27,8 @@ import {
23
27
  unwrapEffectUpstream,
24
28
  type EffectProxyTarget,
25
29
  } from "./extension/state";
30
+ import type { EffectRuntimeSource } from "./runtime-source";
31
+ import { makeEffectRuntimeRunner } from "./runtime-source";
26
32
  import type { EffectErrorMap, MergedEffectErrorMap } from "./tagged-error";
27
33
  import { effectErrorMapToErrorMap } from "./tagged-error";
28
34
  import type {
@@ -43,6 +49,9 @@ const builderVirtualDescriptors = {
43
49
  errors: { enumerable: false },
44
50
  handler: { enumerable: false },
45
51
  lazy: { enumerable: false },
52
+ middleware: { enumerable: false },
53
+ provide: { enumerable: false },
54
+ provideOptional: { enumerable: false },
46
55
  router: { enumerable: false },
47
56
  traced: { enumerable: false },
48
57
  } as const;
@@ -51,6 +60,9 @@ const builderVirtualKeys = [
51
60
  "~effect",
52
61
  "errors",
53
62
  "effect",
63
+ "middleware",
64
+ "provide",
65
+ "provideOptional",
54
66
  "traced",
55
67
  "handler",
56
68
  "router",
@@ -94,8 +106,10 @@ function getEffectBuilderDef(
94
106
  return {
95
107
  ...context.upstream["~orpc"],
96
108
  effectErrorMap: context.state.effectErrorMap,
97
- runtime: context.state.runtime,
109
+ runner: context.state.runner,
98
110
  spanConfig: context.state.spanConfig,
111
+ effectSteps: context.state.effectSteps,
112
+ effectHandler: context.state.effectHandler,
99
113
  };
100
114
  }
101
115
 
@@ -107,13 +121,57 @@ function wrapBuilderLike(
107
121
  {
108
122
  ...builder["~orpc"],
109
123
  effectErrorMap: state.effectErrorMap,
110
- runtime: state.runtime,
124
+ runner: state.runner,
111
125
  spanConfig: state.spanConfig,
126
+ effectSteps: state.effectSteps,
127
+ effectHandler: state.effectHandler,
112
128
  },
113
129
  unwrapEffectUpstream(builder),
114
130
  );
115
131
  }
116
132
 
133
+ function appendEffectStep(
134
+ state: NodeProxyContext<EffectBuilderTarget, AnyBuilderLike>["state"],
135
+ step: NonNullable<
136
+ NodeProxyContext<
137
+ EffectBuilderTarget,
138
+ AnyBuilderLike
139
+ >["state"]["effectSteps"]
140
+ >[number],
141
+ ): NodeProxyContext<EffectBuilderTarget, AnyBuilderLike>["state"] {
142
+ return {
143
+ ...state,
144
+ effectSteps: [...(state.effectSteps ?? []), step],
145
+ };
146
+ }
147
+
148
+ function flushEffectSteps(
149
+ builder: AnyBuilderLike,
150
+ state: NodeProxyContext<EffectBuilderTarget, AnyBuilderLike>["state"],
151
+ ): {
152
+ builder: AnyBuilderLike;
153
+ state: NodeProxyContext<EffectBuilderTarget, AnyBuilderLike>["state"];
154
+ } {
155
+ if (!state.effectSteps?.length) {
156
+ return { builder, state };
157
+ }
158
+
159
+ const middleware = createEffectPipelineMiddleware({
160
+ effectErrorMap: state.effectErrorMap,
161
+ runner: state.runner,
162
+ steps: state.effectSteps,
163
+ });
164
+ return {
165
+ builder: Reflect.apply(Reflect.get(builder, "use", builder), builder, [
166
+ middleware,
167
+ ]) as AnyBuilderLike,
168
+ state: {
169
+ ...state,
170
+ effectSteps: undefined,
171
+ },
172
+ };
173
+ }
174
+
117
175
  function createEffectBuilderProxy(
118
176
  target: EffectBuilderTarget,
119
177
  ): EffectBuilderTarget {
@@ -166,20 +224,103 @@ function createEffectBuilderProxy(
166
224
  >[0],
167
225
  ) => {
168
226
  const defaultCaptureStackTrace = addSpanStackTrace();
227
+ const effectHandler = {
228
+ defaultCaptureStackTrace,
229
+ effectFn,
230
+ spanConfig: state.spanConfig,
231
+ };
169
232
  return new EffectDecoratedProcedure({
170
233
  ...effectDef,
234
+ effectHandler,
171
235
  handler: async (opts) => {
172
236
  return createEffectProcedureHandler({
173
237
  defaultCaptureStackTrace,
174
238
  effectErrorMap: state.effectErrorMap,
175
239
  effectFn,
176
- runtime: state.runtime,
240
+ effectSteps: state.effectSteps,
241
+ runner: state.runner,
177
242
  spanConfig: state.spanConfig,
178
243
  })(opts as any);
179
244
  },
180
245
  });
181
246
  };
182
247
  });
248
+ case "middleware":
249
+ return getOrCreateVirtualMethod(context, prop, () => {
250
+ return (middleware: any) => {
251
+ if (isEffectMiddleware(middleware)) {
252
+ const effectMiddleware = createEffectPipelineMiddleware({
253
+ effectErrorMap: state.effectErrorMap,
254
+ runner: state.runner,
255
+ steps: [
256
+ ...(state.effectSteps ?? []),
257
+ { _tag: "middleware" as const, middleware },
258
+ ],
259
+ });
260
+
261
+ return Reflect.apply(
262
+ Reflect.get(source, "middleware", source),
263
+ source,
264
+ [effectMiddleware],
265
+ );
266
+ }
267
+
268
+ return Reflect.apply(
269
+ Reflect.get(source, "middleware", source),
270
+ source,
271
+ [middleware],
272
+ );
273
+ };
274
+ });
275
+ case "provide":
276
+ return getOrCreateVirtualMethod(context, prop, () => {
277
+ return (tagOrLayer: any, provider?: any) => {
278
+ return wrapBuilderLike(
279
+ source,
280
+ appendEffectStep(
281
+ state,
282
+ Layer.isLayer(tagOrLayer)
283
+ ? { _tag: "provideLayer", layer: tagOrLayer }
284
+ : { _tag: "provide", provider, tag: tagOrLayer },
285
+ ),
286
+ );
287
+ };
288
+ });
289
+ case "provideOptional":
290
+ return getOrCreateVirtualMethod(context, prop, () => {
291
+ return (tag: any, provider: any) => {
292
+ return wrapBuilderLike(
293
+ source,
294
+ appendEffectStep(state, {
295
+ _tag: "provideOptional",
296
+ provider,
297
+ tag,
298
+ }),
299
+ );
300
+ };
301
+ });
302
+ case "use":
303
+ return getOrCreateVirtualMethod(context, prop, () => {
304
+ return (middleware: any, ...rest: unknown[]) => {
305
+ if (isEffectMiddleware(middleware) && rest.length === 0) {
306
+ return wrapBuilderLike(
307
+ source,
308
+ appendEffectStep(state, {
309
+ _tag: "middleware",
310
+ middleware,
311
+ }),
312
+ );
313
+ }
314
+
315
+ const flushed = flushEffectSteps(source, state);
316
+ const nextBuilder: AnyBuilderLike = Reflect.apply(
317
+ Reflect.get(flushed.builder, "use", flushed.builder),
318
+ flushed.builder,
319
+ [middleware, ...rest],
320
+ );
321
+ return wrapBuilderLike(nextBuilder, flushed.state);
322
+ };
323
+ });
183
324
  case "traced":
184
325
  return getOrCreateVirtualMethod(context, prop, () => {
185
326
  return (spanName: string) =>
@@ -457,6 +598,32 @@ export class EffectBuilder<
457
598
  TRequirementsProvided,
458
599
  TRuntimeError
459
600
  >["use"];
601
+ /**
602
+ * Provides a request-scoped Effect service to downstream procedures.
603
+ */
604
+ declare provide: EffectBuilderSurface<
605
+ TInitialContext,
606
+ TCurrentContext,
607
+ TInputSchema,
608
+ TOutputSchema,
609
+ TEffectErrorMap,
610
+ TMeta,
611
+ TRequirementsProvided,
612
+ TRuntimeError
613
+ >["provide"];
614
+ /**
615
+ * Optionally provides a request-scoped Effect service to downstream procedures.
616
+ */
617
+ declare provideOptional: EffectBuilderSurface<
618
+ TInitialContext,
619
+ TCurrentContext,
620
+ TInputSchema,
621
+ TOutputSchema,
622
+ TEffectErrorMap,
623
+ TMeta,
624
+ TRequirementsProvided,
625
+ TRuntimeError
626
+ >["provideOptional"];
460
627
  /**
461
628
  * Sets or updates the metadata.
462
629
  * The provided metadata is spared-merged with any existing metadata.
@@ -531,7 +698,7 @@ export class EffectBuilder<
531
698
  *
532
699
  * @example
533
700
  * ```ts
534
- * const getUser = effectOs
701
+ * const getUser = effectProcedure
535
702
  * .input(z.object({ id: z.string() }))
536
703
  * .traced('users.getUser')
537
704
  * .effect(function* ({ input }) {
@@ -567,7 +734,7 @@ export class EffectBuilder<
567
734
  >["handler"];
568
735
  /**
569
736
  * Defines the handler of the procedure using an Effect.
570
- * The Effect is executed using the ManagedRuntime provided during builder creation.
737
+ * The Effect is executed using the configured Effect runtime source.
571
738
  * The effect is automatically wrapped with `Effect.withSpan`.
572
739
  *
573
740
  * @see {@link https://orpc.dev/docs/procedure Procedure Docs}
@@ -659,11 +826,13 @@ export class EffectBuilder<
659
826
  >,
660
827
  builder?: AnyBuilderLike,
661
828
  ) {
662
- const { runtime, spanConfig, effectErrorMap, ...orpcDef } = def;
829
+ const { runner, spanConfig, effectErrorMap, effectSteps, ...orpcDef } = def;
663
830
 
664
831
  attachEffectState(this, builder ?? new Builder(orpcDef), {
832
+ effectSteps,
833
+ effectHandler: def.effectHandler,
665
834
  effectErrorMap,
666
- runtime,
835
+ runner,
667
836
  spanConfig,
668
837
  });
669
838
 
@@ -672,23 +841,76 @@ export class EffectBuilder<
672
841
  }
673
842
 
674
843
  /**
675
- * Creates an Effect-aware procedure builder with the specified ManagedRuntime.
844
+ * Creates an Effect-aware procedure builder with the specified Layer.
676
845
  * Uses the default builder shape from `@orpc/server`.
677
846
  *
678
- * @param runtime - The ManagedRuntime that provides services for Effect procedures
847
+ * @param layer - The Layer that provides services for Effect procedures
679
848
  * @returns An EffectBuilder instance for creating Effect-native procedures
680
849
  *
681
850
  * @example
682
851
  * ```ts
683
852
  * import { makeEffectORPC } from '@orpc/effect'
684
- * import { Effect, Layer, ManagedRuntime } from 'effect'
853
+ * import { Effect, Layer } from 'effect'
685
854
  *
686
- * const runtime = ManagedRuntime.make(Layer.empty)
687
- * const effectOs = makeEffectORPC(runtime)
855
+ * const effectProcedure = makeEffectORPC(Layer.empty)
688
856
  *
689
- * const hello = effectOs.effect(() => Effect.succeed('Hello!'))
857
+ * const hello = effectProcedure.effect(() => Effect.succeed('Hello!'))
690
858
  * ```
691
859
  */
860
+ export function makeEffectORPC(): EffectBuilder<
861
+ Context,
862
+ Context,
863
+ Schema<unknown, unknown>,
864
+ Schema<unknown, unknown>,
865
+ Record<never, never>,
866
+ Record<never, never>,
867
+ never,
868
+ never
869
+ >;
870
+
871
+ export function makeEffectORPC<
872
+ TBuilder extends AnyBuilderLike<
873
+ TInputSchema,
874
+ TOutputSchema,
875
+ TErrorMap,
876
+ TMeta
877
+ >,
878
+ TInputSchema extends AnySchema,
879
+ TOutputSchema extends AnySchema,
880
+ TErrorMap extends ErrorMap,
881
+ TMeta extends Meta,
882
+ >(
883
+ builder: TBuilder,
884
+ ): EffectBuilder<
885
+ InferBuilderInitialContext<TBuilder>,
886
+ InferBuilderCurrentContext<TBuilder>,
887
+ InferBuilderInputSchema<TBuilder>,
888
+ InferBuilderOutputSchema<TBuilder>,
889
+ InferBuilderErrorMap<TBuilder>,
890
+ InferBuilderMeta<TBuilder>,
891
+ never,
892
+ never
893
+ >;
894
+
895
+ export function makeEffectORPC<TRequirementsProvided, TRuntimeError>(
896
+ layer: Layer.Layer<TRequirementsProvided, TRuntimeError, never>,
897
+ ): EffectBuilder<
898
+ Context,
899
+ Context,
900
+ Schema<unknown, unknown>,
901
+ Schema<unknown, unknown>,
902
+ Record<never, never>,
903
+ Record<never, never>,
904
+ TRequirementsProvided,
905
+ TRuntimeError
906
+ >;
907
+
908
+ /**
909
+ * Creates an Effect-aware procedure builder with the specified ManagedRuntime.
910
+ * Uses the default builder shape from `@orpc/server`.
911
+ *
912
+ * @param runtime - The ManagedRuntime that provides services for Effect procedures
913
+ */
692
914
  export function makeEffectORPC<TRequirementsProvided, TRuntimeError>(
693
915
  runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>,
694
916
  ): EffectBuilder<
@@ -704,9 +926,9 @@ export function makeEffectORPC<TRequirementsProvided, TRuntimeError>(
704
926
 
705
927
  /**
706
928
  * Creates an Effect-aware procedure builder by wrapping an existing oRPC Builder
707
- * with the specified ManagedRuntime.
929
+ * with the specified Layer.
708
930
  *
709
- * @param runtime - The ManagedRuntime that provides services for Effect procedures
931
+ * @param layer - The Layer that provides services for Effect procedures
710
932
  * @param builder - The oRPC Builder instance to wrap (e.g., a customized `os`)
711
933
  * @returns An EffectBuilder instance that extends the original builder with Effect support
712
934
  *
@@ -714,16 +936,15 @@ export function makeEffectORPC<TRequirementsProvided, TRuntimeError>(
714
936
  * ```ts
715
937
  * import { makeEffectORPC } from '@orpc/effect'
716
938
  * import { os } from '@orpc/server'
717
- * import { Effect, Layer, ManagedRuntime } from 'effect'
939
+ * import { Effect, Layer } from 'effect'
718
940
  *
719
941
  * // Create a customized builder
720
942
  * const authedOs = os.use(authMiddleware)
721
943
  *
722
944
  * // Wrap it with Effect support
723
- * const runtime = ManagedRuntime.make(UserServiceLive)
724
- * const effectOs = makeEffectORPC(runtime, authedOs)
945
+ * const effectProcedure = makeEffectORPC(UserServiceLive, authedOs)
725
946
  *
726
- * const getUser = effectOs
947
+ * const getUser = effectProcedure
727
948
  * .input(z.object({ id: z.string() }))
728
949
  * .effect(
729
950
  * Effect.fn(function* ({ input }) {
@@ -747,7 +968,7 @@ export function makeEffectORPC<
747
968
  TRequirementsProvided,
748
969
  TRuntimeError,
749
970
  >(
750
- runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>,
971
+ layer: Layer.Layer<TRequirementsProvided, TRuntimeError, never>,
751
972
  builder: TBuilder,
752
973
  ): EffectBuilder<
753
974
  InferBuilderInitialContext<TBuilder>,
@@ -760,27 +981,59 @@ export function makeEffectORPC<
760
981
  TRuntimeError
761
982
  >;
762
983
 
763
- export function makeEffectORPC<TRequirementsProvided, TRuntimeError>(
984
+ /**
985
+ * Creates an Effect-aware procedure builder by wrapping an existing oRPC Builder
986
+ * with the specified ManagedRuntime.
987
+ *
988
+ * @param runtime - The ManagedRuntime that provides services for Effect procedures
989
+ * @param builder - The oRPC Builder instance to wrap (e.g., a customized `os`)
990
+ */
991
+ export function makeEffectORPC<
992
+ TBuilder extends AnyBuilderLike<
993
+ TInputSchema,
994
+ TOutputSchema,
995
+ TErrorMap,
996
+ TMeta
997
+ >,
998
+ TInputSchema extends AnySchema,
999
+ TOutputSchema extends AnySchema,
1000
+ TErrorMap extends ErrorMap,
1001
+ TMeta extends Meta,
1002
+ TRequirementsProvided,
1003
+ TRuntimeError,
1004
+ >(
764
1005
  runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>,
765
- builder?: AnyBuilderLike,
1006
+ builder: TBuilder,
766
1007
  ): EffectBuilder<
767
- any,
768
- any,
769
- any,
770
- any,
771
- any,
772
- any,
1008
+ InferBuilderInitialContext<TBuilder>,
1009
+ InferBuilderCurrentContext<TBuilder>,
1010
+ InferBuilderInputSchema<TBuilder>,
1011
+ InferBuilderOutputSchema<TBuilder>,
1012
+ InferBuilderErrorMap<TBuilder>,
1013
+ InferBuilderMeta<TBuilder>,
773
1014
  TRequirementsProvided,
774
1015
  TRuntimeError
775
- > {
776
- const resolvedBuilder = builder ?? emptyBuilder();
1016
+ >;
1017
+
1018
+ export function makeEffectORPC(
1019
+ source?: EffectRuntimeSource<any, any> | AnyBuilderLike,
1020
+ builder?: AnyBuilderLike,
1021
+ ): any {
1022
+ const sourceIsBuilder = source !== undefined && isBuilderLike(source);
1023
+ const resolvedBuilder = sourceIsBuilder
1024
+ ? source
1025
+ : (builder ?? emptyBuilder());
777
1026
  const effectErrorMap = getEffectErrorMap(resolvedBuilder);
1027
+ const runner =
1028
+ sourceIsBuilder || source === undefined
1029
+ ? makeEffectRuntimeRunner()
1030
+ : makeEffectRuntimeRunner(source);
778
1031
  return new EffectBuilder(
779
1032
  {
780
1033
  ...resolvedBuilder["~orpc"],
781
1034
  effectErrorMap: effectErrorMap,
782
1035
  errorMap: effectErrorMapToErrorMap(effectErrorMap),
783
- runtime,
1036
+ runner,
784
1037
  },
785
1038
  unwrapEffectUpstream(resolvedBuilder),
786
1039
  );
@@ -798,3 +1051,12 @@ function emptyBuilder(): AnyBuilderLike {
798
1051
  route: {},
799
1052
  });
800
1053
  }
1054
+
1055
+ /**
1056
+ * Runtime-less Effect oRPC builder, analogous to oRPC's `os` export.
1057
+ *
1058
+ * Provide application services with `.provide(layer)` or use
1059
+ * `makeEffectORPC(runtime)` when you need explicit ManagedRuntime lifecycle
1060
+ * control.
1061
+ */
1062
+ export const eos = makeEffectORPC();