effect-orpc 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,55 +2,32 @@ import type {
2
2
  AnySchema,
3
3
  ContractRouter,
4
4
  ErrorMap,
5
- HTTPPath,
6
- InferSchemaOutput,
7
5
  Meta,
8
- Route,
9
6
  Schema,
10
7
  } from "@orpc/contract";
11
- import { mergeMeta, mergePrefix, mergeRoute, mergeTags } from "@orpc/contract";
12
- import type {
13
- AnyMiddleware,
14
- BuilderConfig,
15
- BuilderDef,
16
- Context,
17
- DecoratedMiddleware,
18
- Lazy,
19
- MapInputMiddleware,
20
- MergedCurrentContext,
21
- MergedInitialContext,
22
- Middleware,
23
- ProcedureHandler,
24
- Router,
25
- } from "@orpc/server";
26
- import {
27
- addMiddleware,
28
- Builder,
29
- decorateMiddleware,
30
- fallbackConfig,
31
- lazy,
32
- } from "@orpc/server";
33
- import type { IntersectPick } from "@orpc/shared";
8
+ import type { Context, Router } from "@orpc/server";
9
+ import { Builder, fallbackConfig, lazy } from "@orpc/server";
34
10
  import type { ManagedRuntime } from "effect";
35
11
 
36
12
  import { enhanceEffectRouter } from "./effect-enhance-router";
37
13
  import { EffectDecoratedProcedure } from "./effect-procedure";
38
14
  import { createEffectProcedureHandler } from "./effect-runtime";
39
- import type {
40
- EffectErrorConstructorMap,
41
- EffectErrorMap,
42
- MergedEffectErrorMap,
43
- } from "./tagged-error";
15
+ import {
16
+ createNodeProxy,
17
+ unhandled,
18
+ type NodeProxyContext,
19
+ } from "./extension/create-node-proxy";
20
+ import {
21
+ attachEffectState,
22
+ getEffectErrorMap,
23
+ unwrapEffectUpstream,
24
+ type EffectProxyTarget,
25
+ } from "./extension/state";
26
+ import type { EffectErrorMap, MergedEffectErrorMap } from "./tagged-error";
44
27
  import { effectErrorMapToErrorMap } from "./tagged-error";
45
28
  import type {
46
29
  AnyBuilderLike,
47
30
  EffectBuilderDef,
48
- EffectErrorMapToErrorMap,
49
- EffectProcedureBuilderWithInput,
50
- EffectProcedureBuilderWithOutput,
51
- EffectProcedureHandler,
52
- EffectRouterBuilder,
53
- EnhancedEffectRouter,
54
31
  InferBuilderCurrentContext,
55
32
  InferBuilderErrorMap,
56
33
  InferBuilderInitialContext,
@@ -58,12 +35,215 @@ import type {
58
35
  InferBuilderMeta,
59
36
  InferBuilderOutputSchema,
60
37
  } from "./types";
38
+ import type { EffectBuilderSurface } from "./types/effect-builder-surface";
39
+
40
+ const builderVirtualDescriptors = {
41
+ "~effect": { enumerable: true },
42
+ effect: { enumerable: false },
43
+ errors: { enumerable: false },
44
+ handler: { enumerable: false },
45
+ lazy: { enumerable: false },
46
+ router: { enumerable: false },
47
+ traced: { enumerable: false },
48
+ } as const;
49
+
50
+ const builderVirtualKeys = [
51
+ "~effect",
52
+ "errors",
53
+ "effect",
54
+ "traced",
55
+ "handler",
56
+ "router",
57
+ "lazy",
58
+ ] as const;
59
+
60
+ type EffectBuilderTarget = EffectBuilder<
61
+ any,
62
+ any,
63
+ any,
64
+ any,
65
+ any,
66
+ any,
67
+ any,
68
+ any
69
+ > &
70
+ EffectProxyTarget<AnyBuilderLike>;
71
+
72
+ function isBuilderLike(value: unknown): value is AnyBuilderLike {
73
+ return typeof value === "object" && value !== null && "~orpc" in value;
74
+ }
75
+
76
+ function getOrCreateVirtualMethod<T>(
77
+ context: NodeProxyContext<EffectBuilderTarget, AnyBuilderLike>,
78
+ prop: PropertyKey,
79
+ factory: () => T,
80
+ ): T {
81
+ const cache = context.methodCache;
82
+ if (cache.has(prop)) {
83
+ return cache.get(prop) as T;
84
+ }
85
+
86
+ const value = factory();
87
+ cache.set(prop, value);
88
+ return value;
89
+ }
90
+
91
+ function getEffectBuilderDef(
92
+ context: NodeProxyContext<EffectBuilderTarget, AnyBuilderLike>,
93
+ ): EffectBuilderDef<any, any, any, any, any, any> {
94
+ return {
95
+ ...context.upstream["~orpc"],
96
+ effectErrorMap: context.state.effectErrorMap,
97
+ runtime: context.state.runtime,
98
+ spanConfig: context.state.spanConfig,
99
+ };
100
+ }
101
+
102
+ function wrapBuilderLike(
103
+ builder: AnyBuilderLike,
104
+ state: NodeProxyContext<EffectBuilderTarget, AnyBuilderLike>["state"],
105
+ ): EffectBuilder<any, any, any, any, any, any, any, any> {
106
+ return new EffectBuilder(
107
+ {
108
+ ...builder["~orpc"],
109
+ effectErrorMap: state.effectErrorMap,
110
+ runtime: state.runtime,
111
+ spanConfig: state.spanConfig,
112
+ },
113
+ unwrapEffectUpstream(builder),
114
+ );
115
+ }
116
+
117
+ function createEffectBuilderProxy(
118
+ target: EffectBuilderTarget,
119
+ ): EffectBuilderTarget {
120
+ return createNodeProxy<EffectBuilderTarget, AnyBuilderLike>(target, {
121
+ getVirtual(context, prop) {
122
+ const effectDef = getEffectBuilderDef(context);
123
+ if (prop === "~effect") {
124
+ return getEffectBuilderDef(context);
125
+ }
126
+
127
+ const { upstream: source, state } = context;
128
+
129
+ switch (prop) {
130
+ case "errors":
131
+ return getOrCreateVirtualMethod(context, prop, () => {
132
+ return <U extends EffectErrorMap>(errors: U) => {
133
+ const nextEffectErrorMap: MergedEffectErrorMap<
134
+ typeof state.effectErrorMap,
135
+ U
136
+ > = {
137
+ ...state.effectErrorMap,
138
+ ...errors,
139
+ };
140
+ const nextBuilder: AnyBuilderLike = Reflect.apply(
141
+ Reflect.get(source, "errors", source),
142
+ source,
143
+ [effectErrorMapToErrorMap(errors)],
144
+ );
145
+
146
+ return wrapBuilderLike(nextBuilder, {
147
+ ...state,
148
+ effectErrorMap: nextEffectErrorMap,
149
+ });
150
+ };
151
+ });
152
+ case "effect":
153
+ return getOrCreateVirtualMethod(context, prop, () => {
154
+ return (
155
+ effectFn: Parameters<
156
+ EffectBuilderSurface<
157
+ any,
158
+ any,
159
+ any,
160
+ any,
161
+ any,
162
+ any,
163
+ any,
164
+ any
165
+ >["effect"]
166
+ >[0],
167
+ ) => {
168
+ const defaultCaptureStackTrace = addSpanStackTrace();
169
+ return new EffectDecoratedProcedure({
170
+ ...effectDef,
171
+ handler: async (opts) => {
172
+ return createEffectProcedureHandler({
173
+ defaultCaptureStackTrace,
174
+ effectErrorMap: state.effectErrorMap,
175
+ effectFn,
176
+ runtime: state.runtime,
177
+ spanConfig: state.spanConfig,
178
+ })(opts as any);
179
+ },
180
+ });
181
+ };
182
+ });
183
+ case "traced":
184
+ return getOrCreateVirtualMethod(context, prop, () => {
185
+ return (spanName: string) =>
186
+ wrapBuilderLike(source, {
187
+ ...state,
188
+ spanConfig: {
189
+ captureStackTrace: addSpanStackTrace(),
190
+ name: spanName,
191
+ },
192
+ });
193
+ });
194
+ case "handler":
195
+ return getOrCreateVirtualMethod(context, prop, () => {
196
+ return (
197
+ handler: Parameters<
198
+ EffectBuilderSurface<
199
+ any,
200
+ any,
201
+ any,
202
+ any,
203
+ any,
204
+ any,
205
+ any,
206
+ any
207
+ >["handler"]
208
+ >[0],
209
+ ) =>
210
+ new EffectDecoratedProcedure({
211
+ ...effectDef,
212
+ handler,
213
+ });
214
+ });
215
+ case "router":
216
+ return getOrCreateVirtualMethod(context, prop, () => {
217
+ return (router: Router<ContractRouter<any>, any>) =>
218
+ enhanceEffectRouter(router, effectDef) as any;
219
+ });
220
+ case "lazy":
221
+ return getOrCreateVirtualMethod(context, prop, () => {
222
+ return (
223
+ loader: () => Promise<{
224
+ default: Router<ContractRouter<any>, any>;
225
+ }>,
226
+ ) => enhanceEffectRouter(lazy(loader), effectDef) as any;
227
+ });
228
+ default:
229
+ return unhandled();
230
+ }
231
+ },
232
+ virtualDescriptors: builderVirtualDescriptors,
233
+ virtualKeys: builderVirtualKeys,
234
+ wrapResult(context, _prop, result) {
235
+ if (!isBuilderLike(result)) {
236
+ return result;
237
+ }
238
+
239
+ return wrapBuilderLike(result, context.state);
240
+ },
241
+ });
242
+ }
61
243
 
62
244
  /**
63
245
  * Captures the stack trace at the call site for better error reporting in spans.
64
246
  * This is called at procedure definition time to capture where the procedure was defined.
65
- *
66
- * @returns A function that lazily extracts the relevant stack frame
67
247
  */
68
248
  export function addSpanStackTrace(): () => string | undefined {
69
249
  const ErrorConstructor = Error as typeof Error & {
@@ -102,49 +282,23 @@ export class EffectBuilder<
102
282
  TMeta extends Meta,
103
283
  TRequirementsProvided,
104
284
  TRuntimeError,
285
+ > implements EffectBuilderSurface<
286
+ TInitialContext,
287
+ TCurrentContext,
288
+ TInputSchema,
289
+ TOutputSchema,
290
+ TEffectErrorMap,
291
+ TMeta,
292
+ TRequirementsProvided,
293
+ TRuntimeError
105
294
  > {
106
- /**
107
- * This property holds the defined options and the effect-specific properties.
108
- */
109
- declare "~effect": EffectBuilderDef<
110
- TInputSchema,
111
- TOutputSchema,
112
- TEffectErrorMap,
113
- TMeta,
114
- TRequirementsProvided,
115
- TRuntimeError
116
- >;
117
- declare "~orpc": BuilderDef<
118
- TInputSchema,
119
- TOutputSchema,
120
- EffectErrorMapToErrorMap<TEffectErrorMap>,
121
- TMeta
122
- >;
123
-
124
- constructor(
125
- def: EffectBuilderDef<
126
- TInputSchema,
127
- TOutputSchema,
128
- TEffectErrorMap,
129
- TMeta,
130
- TRequirementsProvided,
131
- TRuntimeError
132
- >,
133
- ) {
134
- const { runtime, spanConfig, effectErrorMap, ...orpcDef } = def;
135
- this["~orpc"] = orpcDef;
136
- this["~effect"] = { runtime, spanConfig, effectErrorMap, ...orpcDef };
137
- }
138
-
139
295
  /**
140
296
  * Sets or overrides the config.
141
297
  *
142
298
  * @see {@link https://orpc.dev/docs/client/server-side#middlewares-order Middlewares Order Docs}
143
299
  * @see {@link https://orpc.dev/docs/best-practices/dedupe-middleware#configuration Dedupe Middleware Docs}
144
300
  */
145
- $config(
146
- config: BuilderConfig,
147
- ): EffectBuilder<
301
+ declare $config: EffectBuilderSurface<
148
302
  TInitialContext,
149
303
  TCurrentContext,
150
304
  TInputSchema,
@@ -153,100 +307,37 @@ export class EffectBuilder<
153
307
  TMeta,
154
308
  TRequirementsProvided,
155
309
  TRuntimeError
156
- > {
157
- const inputValidationCount =
158
- this["~effect"].inputValidationIndex -
159
- fallbackConfig(
160
- "initialInputValidationIndex",
161
- this["~effect"].config.initialInputValidationIndex,
162
- );
163
- const outputValidationCount =
164
- this["~effect"].outputValidationIndex -
165
- fallbackConfig(
166
- "initialOutputValidationIndex",
167
- this["~effect"].config.initialOutputValidationIndex,
168
- );
169
-
170
- return new EffectBuilder({
171
- ...this["~effect"],
172
- config,
173
- dedupeLeadingMiddlewares: fallbackConfig(
174
- "dedupeLeadingMiddlewares",
175
- config.dedupeLeadingMiddlewares,
176
- ),
177
- inputValidationIndex:
178
- fallbackConfig(
179
- "initialInputValidationIndex",
180
- config.initialInputValidationIndex,
181
- ) + inputValidationCount,
182
- outputValidationIndex:
183
- fallbackConfig(
184
- "initialOutputValidationIndex",
185
- config.initialOutputValidationIndex,
186
- ) + outputValidationCount,
187
- });
188
- }
189
-
310
+ >["$config"];
190
311
  /**
191
312
  * Set or override the initial context.
192
313
  *
193
314
  * @see {@link https://orpc.dev/docs/context Context Docs}
194
315
  */
195
- $context<U extends Context>(): EffectBuilder<
196
- U & Record<never, never>,
197
- U,
316
+ declare $context: EffectBuilderSurface<
317
+ TInitialContext,
318
+ TCurrentContext,
198
319
  TInputSchema,
199
320
  TOutputSchema,
200
321
  TEffectErrorMap,
201
322
  TMeta,
202
323
  TRequirementsProvided,
203
324
  TRuntimeError
204
- > {
205
- /**
206
- * We need `& Record<never, never>` to deal with `has no properties in common with type` error
207
- */
208
-
209
- return new EffectBuilder({
210
- ...this["~effect"],
211
- middlewares: [],
212
- inputValidationIndex: fallbackConfig(
213
- "initialInputValidationIndex",
214
- this["~effect"].config.initialInputValidationIndex,
215
- ),
216
- outputValidationIndex: fallbackConfig(
217
- "initialOutputValidationIndex",
218
- this["~effect"].config.initialOutputValidationIndex,
219
- ),
220
- });
221
- }
222
-
325
+ >["$context"];
223
326
  /**
224
327
  * Sets or overrides the initial meta.
225
328
  *
226
329
  * @see {@link https://orpc.dev/docs/metadata Metadata Docs}
227
330
  */
228
- $meta<U extends Meta>(
229
- initialMeta: U,
230
- ): EffectBuilder<
331
+ declare $meta: EffectBuilderSurface<
231
332
  TInitialContext,
232
333
  TCurrentContext,
233
334
  TInputSchema,
234
335
  TOutputSchema,
235
336
  TEffectErrorMap,
236
- U & Record<never, never>,
337
+ TMeta,
237
338
  TRequirementsProvided,
238
339
  TRuntimeError
239
- > {
240
- /**
241
- * We need `& Record<never, never>` to deal with `has no properties in common with type` error
242
- */
243
-
244
- return new EffectBuilder({
245
- ...this["~effect"],
246
- meta: initialMeta,
247
- });
248
- }
249
-
340
+ >["$meta"];
250
341
  /**
251
342
  * Sets or overrides the initial route.
252
343
  * This option is typically relevant when integrating with OpenAPI.
@@ -254,9 +345,7 @@ export class EffectBuilder<
254
345
  * @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}
255
346
  * @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
256
347
  */
257
- $route(
258
- initialRoute: Route,
259
- ): EffectBuilder<
348
+ declare $route: EffectBuilderSurface<
260
349
  TInitialContext,
261
350
  TCurrentContext,
262
351
  TInputSchema,
@@ -265,65 +354,61 @@ export class EffectBuilder<
265
354
  TMeta,
266
355
  TRequirementsProvided,
267
356
  TRuntimeError
268
- > {
269
- return new EffectBuilder({
270
- ...this["~effect"],
271
- route: initialRoute,
272
- });
273
- }
274
-
357
+ >["$route"];
275
358
  /**
276
359
  * Sets or overrides the initial input schema.
277
360
  *
278
361
  * @see {@link https://orpc.dev/docs/procedure#initial-configuration Initial Procedure Configuration Docs}
279
362
  */
280
- $input<U extends AnySchema>(
281
- initialInputSchema?: U,
282
- ): EffectBuilder<
363
+ declare $input: EffectBuilderSurface<
283
364
  TInitialContext,
284
365
  TCurrentContext,
285
- U,
366
+ TInputSchema,
286
367
  TOutputSchema,
287
368
  TEffectErrorMap,
288
369
  TMeta,
289
370
  TRequirementsProvided,
290
371
  TRuntimeError
291
- > {
292
- return new EffectBuilder({
293
- ...this["~effect"],
294
- inputSchema: initialInputSchema,
295
- });
296
- }
297
-
372
+ >["$input"];
373
+ /**
374
+ * This property holds the defined options and the effect-specific properties.
375
+ */
376
+ declare "~effect": EffectBuilderDef<
377
+ TInputSchema,
378
+ TOutputSchema,
379
+ TEffectErrorMap,
380
+ TMeta,
381
+ TRequirementsProvided,
382
+ TRuntimeError
383
+ >;
384
+ /**
385
+ * This property holds the defined options.
386
+ */
387
+ declare "~orpc": EffectBuilderSurface<
388
+ TInitialContext,
389
+ TCurrentContext,
390
+ TInputSchema,
391
+ TOutputSchema,
392
+ TEffectErrorMap,
393
+ TMeta,
394
+ TRequirementsProvided,
395
+ TRuntimeError
396
+ >["~orpc"];
298
397
  /**
299
398
  * Creates a middleware.
300
399
  *
301
400
  * @see {@link https://orpc.dev/docs/middleware Middleware Docs}
302
401
  */
303
- middleware<
304
- UOutContext extends IntersectPick<TCurrentContext, UOutContext>,
305
- TInput,
306
- TOutput = any,
307
- >(
308
- middleware: Middleware<
309
- TInitialContext,
310
- UOutContext,
311
- TInput,
312
- TOutput,
313
- EffectErrorConstructorMap<TEffectErrorMap>,
314
- TMeta
315
- >,
316
- ): DecoratedMiddleware<
402
+ declare middleware: EffectBuilderSurface<
317
403
  TInitialContext,
318
- UOutContext,
319
- TInput,
320
- TOutput,
321
- any,
322
- TMeta
323
- > {
324
- return decorateMiddleware(middleware);
325
- }
326
-
404
+ TCurrentContext,
405
+ TInputSchema,
406
+ TOutputSchema,
407
+ TEffectErrorMap,
408
+ TMeta,
409
+ TRequirementsProvided,
410
+ TRuntimeError
411
+ >["middleware"];
327
412
  /**
328
413
  * Adds type-safe custom errors.
329
414
  * Supports both traditional oRPC error definitions and ORPCTaggedError classes.
@@ -345,29 +430,16 @@ export class EffectBuilder<
345
430
  *
346
431
  * @see {@link https://orpc.dev/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}
347
432
  */
348
- errors<U extends EffectErrorMap>(
349
- errors: U,
350
- ): EffectBuilder<
433
+ declare errors: EffectBuilderSurface<
351
434
  TInitialContext,
352
435
  TCurrentContext,
353
436
  TInputSchema,
354
437
  TOutputSchema,
355
- MergedEffectErrorMap<TEffectErrorMap, U>,
438
+ TEffectErrorMap,
356
439
  TMeta,
357
440
  TRequirementsProvided,
358
441
  TRuntimeError
359
- > {
360
- const newEffectErrorMap: MergedEffectErrorMap<TEffectErrorMap, U> = {
361
- ...this["~effect"].effectErrorMap,
362
- ...errors,
363
- };
364
- return new EffectBuilder({
365
- ...this["~effect"],
366
- errorMap: effectErrorMapToErrorMap(newEffectErrorMap),
367
- effectErrorMap: newEffectErrorMap,
368
- });
369
- }
370
-
442
+ >["errors"];
371
443
  /**
372
444
  * Uses a middleware to modify the context or improve the pipeline.
373
445
  *
@@ -375,52 +447,23 @@ export class EffectBuilder<
375
447
  * @note The current context must be satisfy middleware dependent-context
376
448
  * @see {@link https://orpc.dev/docs/middleware Middleware Docs}
377
449
  */
378
- use<
379
- UOutContext extends IntersectPick<TCurrentContext, UOutContext>,
380
- UInContext extends Context = TCurrentContext,
381
- >(
382
- middleware: Middleware<
383
- UInContext | TCurrentContext,
384
- UOutContext,
385
- InferSchemaOutput<TInputSchema>,
386
- unknown,
387
- EffectErrorConstructorMap<TEffectErrorMap>,
388
- TMeta
389
- >,
390
- ): EffectBuilder<
391
- MergedInitialContext<TInitialContext, UInContext, TCurrentContext>,
392
- MergedCurrentContext<TCurrentContext, UOutContext>,
450
+ declare use: EffectBuilderSurface<
451
+ TInitialContext,
452
+ TCurrentContext,
393
453
  TInputSchema,
394
454
  TOutputSchema,
395
455
  TEffectErrorMap,
396
456
  TMeta,
397
457
  TRequirementsProvided,
398
458
  TRuntimeError
399
- >;
400
-
401
- use(
402
- middleware: AnyMiddleware,
403
- mapInput?: MapInputMiddleware<any, any>,
404
- ): EffectBuilder<any, any, any, any, any, any, any, any> {
405
- const mapped = mapInput
406
- ? decorateMiddleware(middleware).mapInput(mapInput)
407
- : middleware;
408
-
409
- return new EffectBuilder({
410
- ...this["~effect"],
411
- middlewares: addMiddleware(this["~effect"].middlewares, mapped),
412
- });
413
- }
414
-
459
+ >["use"];
415
460
  /**
416
461
  * Sets or updates the metadata.
417
462
  * The provided metadata is spared-merged with any existing metadata.
418
463
  *
419
464
  * @see {@link https://orpc.dev/docs/metadata Metadata Docs}
420
465
  */
421
- meta(
422
- meta: TMeta,
423
- ): EffectBuilder<
466
+ declare meta: EffectBuilderSurface<
424
467
  TInitialContext,
425
468
  TCurrentContext,
426
469
  TInputSchema,
@@ -429,13 +472,7 @@ export class EffectBuilder<
429
472
  TMeta,
430
473
  TRequirementsProvided,
431
474
  TRuntimeError
432
- > {
433
- return new EffectBuilder({
434
- ...this["~effect"],
435
- meta: mergeMeta(this["~effect"].meta, meta),
436
- });
437
- }
438
-
475
+ >["meta"];
439
476
  /**
440
477
  * Sets or updates the route definition.
441
478
  * The provided route is spared-merged with any existing route.
@@ -444,9 +481,7 @@ export class EffectBuilder<
444
481
  * @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}
445
482
  * @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
446
483
  */
447
- route(
448
- route: Route,
449
- ): EffectBuilder<
484
+ declare route: EffectBuilderSurface<
450
485
  TInitialContext,
451
486
  TCurrentContext,
452
487
  TInputSchema,
@@ -455,76 +490,37 @@ export class EffectBuilder<
455
490
  TMeta,
456
491
  TRequirementsProvided,
457
492
  TRuntimeError
458
- > {
459
- return new EffectBuilder({
460
- ...this["~effect"],
461
- route: mergeRoute(this["~effect"].route, route),
462
- });
463
- }
464
-
493
+ >["route"];
465
494
  /**
466
495
  * Defines the input validation schema.
467
496
  *
468
497
  * @see {@link https://orpc.dev/docs/procedure#input-output-validation Input Validation Docs}
469
498
  */
470
- input<USchema extends AnySchema>(
471
- schema: USchema,
472
- ): EffectProcedureBuilderWithInput<
499
+ declare input: EffectBuilderSurface<
473
500
  TInitialContext,
474
501
  TCurrentContext,
475
- USchema,
502
+ TInputSchema,
476
503
  TOutputSchema,
477
504
  TEffectErrorMap,
478
505
  TMeta,
479
506
  TRequirementsProvided,
480
507
  TRuntimeError
481
- > {
482
- return new EffectBuilder({
483
- ...this["~effect"],
484
- inputSchema: schema,
485
- inputValidationIndex:
486
- fallbackConfig(
487
- "initialInputValidationIndex",
488
- this["~effect"].config.initialInputValidationIndex,
489
- ) + this["~effect"].middlewares.length,
490
- // we cast to any because EffectProcedureBuilderWithInput is expecting
491
- // use() input type to be defined, and EffectBuilder types its use() input
492
- // to unknown to allow any middleware to be passed
493
- // ---
494
- // note: the original implentation of the builder also uses any for the same reason
495
- }) as any;
496
- }
497
-
508
+ >["input"];
498
509
  /**
499
510
  * Defines the output validation schema.
500
511
  *
501
512
  * @see {@link https://orpc.dev/docs/procedure#input-output-validation Output Validation Docs}
502
513
  */
503
- output<USchema extends AnySchema>(
504
- schema: USchema,
505
- ): EffectProcedureBuilderWithOutput<
514
+ declare output: EffectBuilderSurface<
506
515
  TInitialContext,
507
516
  TCurrentContext,
508
517
  TInputSchema,
509
- USchema,
518
+ TOutputSchema,
510
519
  TEffectErrorMap,
511
520
  TMeta,
512
521
  TRequirementsProvided,
513
522
  TRuntimeError
514
- > {
515
- // We cast to any because EffectProcedureBuilderWithOutput narrows
516
- // handler/effect output typing based on the declared output schema.
517
- return new EffectBuilder({
518
- ...this["~effect"],
519
- outputSchema: schema,
520
- outputValidationIndex:
521
- fallbackConfig(
522
- "initialOutputValidationIndex",
523
- this["~effect"].config.initialOutputValidationIndex,
524
- ) + this["~effect"].middlewares.length,
525
- }) as any;
526
- }
527
-
523
+ >["output"];
528
524
  /**
529
525
  * Adds a traceable span to the procedure for telemetry.
530
526
  * The span name is used for Effect tracing via `Effect.withSpan`.
@@ -544,9 +540,7 @@ export class EffectBuilder<
544
540
  * })
545
541
  * ```
546
542
  */
547
- traced(
548
- spanName: string,
549
- ): EffectBuilder<
543
+ declare traced: EffectBuilderSurface<
550
544
  TInitialContext,
551
545
  TCurrentContext,
552
546
  TInputSchema,
@@ -555,40 +549,22 @@ export class EffectBuilder<
555
549
  TMeta,
556
550
  TRequirementsProvided,
557
551
  TRuntimeError
558
- > {
559
- return new EffectBuilder({
560
- ...this["~effect"],
561
- spanConfig: {
562
- name: spanName,
563
- captureStackTrace: addSpanStackTrace(),
564
- },
565
- });
566
- }
567
-
568
- handler<UFuncOutput>(
569
- handler: ProcedureHandler<
570
- TCurrentContext,
571
- InferSchemaOutput<TInputSchema>,
572
- UFuncOutput,
573
- EffectErrorMapToErrorMap<TEffectErrorMap>,
574
- TMeta
575
- >,
576
- ): EffectDecoratedProcedure<
552
+ >["traced"];
553
+ /**
554
+ * Defines the handler of the procedure using a standard async/sync function.
555
+ *
556
+ * @see {@link https://orpc.dev/docs/procedure Procedure Docs}
557
+ */
558
+ declare handler: EffectBuilderSurface<
577
559
  TInitialContext,
578
560
  TCurrentContext,
579
561
  TInputSchema,
580
- Schema<UFuncOutput, UFuncOutput>,
562
+ TOutputSchema,
581
563
  TEffectErrorMap,
582
564
  TMeta,
583
565
  TRequirementsProvided,
584
566
  TRuntimeError
585
- > {
586
- return new EffectDecoratedProcedure({
587
- ...this["~effect"],
588
- handler,
589
- });
590
- }
591
-
567
+ >["handler"];
592
568
  /**
593
569
  * Defines the handler of the procedure using an Effect.
594
570
  * The Effect is executed using the ManagedRuntime provided during builder creation.
@@ -596,42 +572,16 @@ export class EffectBuilder<
596
572
  *
597
573
  * @see {@link https://orpc.dev/docs/procedure Procedure Docs}
598
574
  */
599
- effect<UFuncOutput>(
600
- effectFn: EffectProcedureHandler<
601
- TCurrentContext,
602
- TInputSchema,
603
- UFuncOutput,
604
- TEffectErrorMap,
605
- TRequirementsProvided,
606
- TMeta
607
- >,
608
- ): EffectDecoratedProcedure<
575
+ declare effect: EffectBuilderSurface<
609
576
  TInitialContext,
610
577
  TCurrentContext,
611
578
  TInputSchema,
612
- Schema<UFuncOutput, UFuncOutput>,
579
+ TOutputSchema,
613
580
  TEffectErrorMap,
614
581
  TMeta,
615
582
  TRequirementsProvided,
616
583
  TRuntimeError
617
- > {
618
- const { runtime, spanConfig } = this["~effect"];
619
- // Capture stack trace at definition time for default tracing
620
- const defaultCaptureStackTrace = addSpanStackTrace();
621
- return new EffectDecoratedProcedure({
622
- ...this["~effect"],
623
- handler: async (opts) => {
624
- return createEffectProcedureHandler({
625
- runtime,
626
- effectErrorMap: this["~effect"].effectErrorMap,
627
- effectFn,
628
- spanConfig,
629
- defaultCaptureStackTrace,
630
- })(opts as any);
631
- },
632
- });
633
- }
634
-
584
+ >["effect"];
635
585
  /**
636
586
  * Prefixes all procedures in the router.
637
587
  * The provided prefix is post-appended to any existing router prefix.
@@ -640,85 +590,90 @@ export class EffectBuilder<
640
590
  *
641
591
  * @see {@link https://orpc.dev/docs/openapi/routing#route-prefixes OpenAPI Route Prefixes Docs}
642
592
  */
643
- prefix(
644
- prefix: HTTPPath,
645
- ): EffectRouterBuilder<
593
+ declare prefix: EffectBuilderSurface<
646
594
  TInitialContext,
647
595
  TCurrentContext,
596
+ TInputSchema,
597
+ TOutputSchema,
648
598
  TEffectErrorMap,
649
599
  TMeta,
650
600
  TRequirementsProvided,
651
601
  TRuntimeError
652
- > {
653
- return new EffectBuilder({
654
- ...this["~effect"],
655
- prefix: mergePrefix(this["~effect"].prefix, prefix),
656
- }) as any;
657
- }
658
-
602
+ >["prefix"];
659
603
  /**
660
604
  * Adds tags to all procedures in the router.
661
605
  * This helpful when you want to group procedures together in the OpenAPI specification.
662
606
  *
663
607
  * @see {@link https://orpc.dev/docs/openapi/openapi-specification#operation-metadata OpenAPI Operation Metadata Docs}
664
608
  */
665
- tag(
666
- ...tags: string[]
667
- ): EffectRouterBuilder<
609
+ declare tag: EffectBuilderSurface<
668
610
  TInitialContext,
669
611
  TCurrentContext,
612
+ TInputSchema,
613
+ TOutputSchema,
670
614
  TEffectErrorMap,
671
615
  TMeta,
672
616
  TRequirementsProvided,
673
617
  TRuntimeError
674
- > {
675
- return new EffectBuilder({
676
- ...this["~effect"],
677
- tags: mergeTags(this["~effect"].tags, tags),
678
- }) as any;
679
- }
680
-
618
+ >["tag"];
681
619
  /**
682
620
  * Applies all of the previously defined options to the specified router.
683
621
  *
684
622
  * @see {@link https://orpc.dev/docs/router#extending-router Extending Router Docs}
685
623
  */
686
- router<U extends Router<ContractRouter<TMeta>, TCurrentContext>>(
687
- router: U,
688
- ): EnhancedEffectRouter<
689
- U,
624
+ declare router: EffectBuilderSurface<
690
625
  TInitialContext,
691
626
  TCurrentContext,
692
- TEffectErrorMap
693
- > {
694
- return enhanceEffectRouter(router, {
695
- ...this["~effect"],
696
- }) as any; // Type instantiation is excessively deep and possibly infinite
697
- }
698
-
627
+ TInputSchema,
628
+ TOutputSchema,
629
+ TEffectErrorMap,
630
+ TMeta,
631
+ TRequirementsProvided,
632
+ TRuntimeError
633
+ >["router"];
699
634
  /**
700
635
  * Create a lazy router
701
636
  * And applies all of the previously defined options to the specified router.
702
637
  *
703
638
  * @see {@link https://orpc.dev/docs/router#extending-router Extending Router Docs}
704
639
  */
705
- lazy<U extends Router<ContractRouter<TMeta>, TCurrentContext>>(
706
- loader: () => Promise<{ default: U }>,
707
- ): EnhancedEffectRouter<
708
- Lazy<U>,
640
+ declare lazy: EffectBuilderSurface<
709
641
  TInitialContext,
710
642
  TCurrentContext,
711
- TEffectErrorMap
712
- > {
713
- return enhanceEffectRouter(lazy(loader), {
714
- ...this["~effect"],
715
- }) as any; // Type instantiation is excessively deep and possibly infinite
643
+ TInputSchema,
644
+ TOutputSchema,
645
+ TEffectErrorMap,
646
+ TMeta,
647
+ TRequirementsProvided,
648
+ TRuntimeError
649
+ >["lazy"];
650
+
651
+ constructor(
652
+ def: EffectBuilderDef<
653
+ TInputSchema,
654
+ TOutputSchema,
655
+ TEffectErrorMap,
656
+ TMeta,
657
+ TRequirementsProvided,
658
+ TRuntimeError
659
+ >,
660
+ builder?: AnyBuilderLike,
661
+ ) {
662
+ const { runtime, spanConfig, effectErrorMap, ...orpcDef } = def;
663
+
664
+ attachEffectState(this, builder ?? new Builder(orpcDef), {
665
+ effectErrorMap,
666
+ runtime,
667
+ spanConfig,
668
+ });
669
+
670
+ return createEffectBuilderProxy(this);
716
671
  }
717
672
  }
718
673
 
719
674
  /**
720
675
  * Creates an Effect-aware procedure builder with the specified ManagedRuntime.
721
- * Uses the default `os` builder from `@orpc/server`.
676
+ * Uses the default builder shape from `@orpc/server`.
722
677
  *
723
678
  * @param runtime - The ManagedRuntime that provides services for Effect procedures
724
679
  * @returns An EffectBuilder instance for creating Effect-native procedures
@@ -819,23 +774,27 @@ export function makeEffectORPC<TRequirementsProvided, TRuntimeError>(
819
774
  TRuntimeError
820
775
  > {
821
776
  const resolvedBuilder = builder ?? emptyBuilder();
822
- return new EffectBuilder({
823
- ...resolvedBuilder["~orpc"],
824
- errorMap: effectErrorMapToErrorMap(resolvedBuilder["~orpc"].errorMap),
825
- effectErrorMap: resolvedBuilder["~orpc"].errorMap,
826
- runtime,
827
- });
777
+ const effectErrorMap = getEffectErrorMap(resolvedBuilder);
778
+ return new EffectBuilder(
779
+ {
780
+ ...resolvedBuilder["~orpc"],
781
+ effectErrorMap: effectErrorMap,
782
+ errorMap: effectErrorMapToErrorMap(effectErrorMap),
783
+ runtime,
784
+ },
785
+ unwrapEffectUpstream(resolvedBuilder),
786
+ );
828
787
  }
829
788
 
830
789
  function emptyBuilder(): AnyBuilderLike {
831
790
  return new Builder({
832
791
  config: {},
833
- route: {},
834
- meta: {},
792
+ dedupeLeadingMiddlewares: true,
835
793
  errorMap: {},
836
794
  inputValidationIndex: fallbackConfig("initialInputValidationIndex"),
837
- outputValidationIndex: fallbackConfig("initialOutputValidationIndex"),
795
+ meta: {},
838
796
  middlewares: [],
839
- dedupeLeadingMiddlewares: true,
797
+ outputValidationIndex: fallbackConfig("initialOutputValidationIndex"),
798
+ route: {},
840
799
  });
841
800
  }