effect-orpc 0.0.4 → 0.0.6

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
@@ -8,6 +8,7 @@ Inspired by [effect-trpc](https://github.com/mikearnaldi/effect-trpc).
8
8
 
9
9
  - **Effect-native procedures** - Write oRPC procedures using generators with `yield*` syntax
10
10
  - **Type-safe service injection** - Use `ManagedRuntime<R>` to provide services to procedures with compile-time safety
11
+ - **Tagged errors** - Create Effect-native error classes with `ORPCTaggedError` that integrate with oRPC's error handling
11
12
  - **Full oRPC compatibility** - Mix Effect procedures with standard oRPC procedures in the same router
12
13
  - **Builder pattern preserved** - All oRPC builder methods (`.errors()`, `.meta()`, `.route()`, `.input()`, `.output()`, `.use()`) work seamlessly
13
14
  - **Callable procedures** - Make procedures directly invocable while preserving Effect types
@@ -57,29 +58,22 @@ const effectOs = makeEffectORPC(runtime)
57
58
  // Define your procedures
58
59
  const getUser = effectOs
59
60
  .input(z.object({ id: z.string() }))
60
- .effect(
61
- Effect.fn(function* ({ input }) {
62
- const userService = yield* UserService
63
- return yield* userService.findById(input.id)
64
- })
65
- )
61
+ .effect(function* ({ input }) {
62
+ const userService = yield* UserService
63
+ return yield* userService.findById(input.id)
64
+ })
66
65
 
67
- const listUsers = effectOs
68
- .effect(
69
- Effect.fn(function* () {
70
- const userService = yield* UserService
71
- return yield* userService.findAll()
72
- })
73
- )
66
+ const listUsers = effectOs.effect(function* () {
67
+ const userService = yield* UserService
68
+ return yield* userService.findAll()
69
+ })
74
70
 
75
71
  const createUser = effectOs
76
72
  .input(z.object({ name: z.string() }))
77
- .effect(
78
- Effect.fn(function* ({ input }) {
79
- const userService = yield* UserService
80
- return yield* userService.create(input.name)
81
- })
82
- )
73
+ .effect(function* ({ input }) {
74
+ const userService = yield* UserService
75
+ return yield* userService.create(input.name)
76
+ })
83
77
 
84
78
  // Create router with mixed procedures
85
79
  const router = os.router({
@@ -119,87 +113,16 @@ const runtime = ManagedRuntime.make(Layer.succeed(ProvidedService, {
119
113
  const effectOs = makeEffectORPC(runtime)
120
114
 
121
115
  // ✅ This compiles - ProvidedService is in the runtime
122
- const works = effectOs
123
- .effect(
124
- Effect.fn(function* () {
125
- const svc = yield* ProvidedService
126
- return yield* svc.doSomething()
127
- })
128
- )
129
-
130
- // ❌ This fails to compile - MissingService is not in the runtime
131
- const fails = effectOs
132
- .effect(
133
- Effect.fn(function* () {
134
- const svc = yield* MissingService // Type error!
135
- return yield* svc.doSomething()
136
- })
137
- )
138
- ```
139
-
140
- ## Using Services
141
-
142
- ```ts
143
- import { makeEffectORPC } from 'effect-orpc'
144
- import { Context, Effect, Layer, ManagedRuntime } from 'effect'
145
- import { z } from 'zod'
146
-
147
- // Define services
148
- class DatabaseService extends Context.Tag('DatabaseService')<
149
- DatabaseService,
150
- {
151
- query: <T>(sql: string) => Effect.Effect<T[]>
152
- execute: (sql: string) => Effect.Effect<void>
153
- }
154
- >() {}
155
-
156
- class CacheService extends Context.Tag('CacheService')<
157
- CacheService,
158
- {
159
- get: <T>(key: string) => Effect.Effect<T | undefined>
160
- set: <T>(key: string, value: T, ttl?: number) => Effect.Effect<void>
161
- }
162
- >() {}
163
-
164
- // Create layers
165
- const DatabaseServiceLive = Layer.succeed(DatabaseService, {
166
- query: sql => Effect.succeed([]),
167
- execute: sql => Effect.succeed(undefined),
116
+ const works = effectOs.effect(function* () {
117
+ const service = yield* ProvidedService
118
+ return yield* service.doSomething()
168
119
  })
169
120
 
170
- const CacheServiceLive = Layer.succeed(CacheService, {
171
- get: key => Effect.succeed(undefined),
172
- set: (key, value, ttl) => Effect.succeed(undefined),
121
+ // This fails to compile - MissingService is not in the runtime
122
+ const fails = effectOs.effect(function* () {
123
+ const service = yield* MissingService // Type error!
124
+ return yield* service.doSomething()
173
125
  })
174
-
175
- // Compose layers
176
- const AppLive = Layer.mergeAll(DatabaseServiceLive, CacheServiceLive)
177
-
178
- // Create runtime with all services
179
- const runtime = ManagedRuntime.make(AppLive)
180
- const effectOs = makeEffectORPC(runtime)
181
-
182
- // Use multiple services in a procedure
183
- const getUserWithCache = effectOs
184
- .input(z.object({ id: z.string() }))
185
- .effect(
186
- Effect.fn(function* ({ input }) {
187
- const cache = yield* CacheService
188
- const db = yield* DatabaseService
189
-
190
- // Try cache first
191
- const cached = yield* cache.get<User>(`user:${input.id}`)
192
- if (cached)
193
- return cached
194
-
195
- // Fall back to database
196
- const [user] = yield* db.query<User>(`SELECT * FROM users WHERE id = '${input.id}'`)
197
- if (user) {
198
- yield* cache.set(`user:${input.id}`, user, 3600)
199
- }
200
- return user
201
- })
202
- )
203
126
  ```
204
127
 
205
128
  ## Wrapping a Customized Builder
@@ -228,22 +151,17 @@ const authedOs = os
228
151
  const effectAuthedOs = makeEffectORPC(runtime, authedOs)
229
152
 
230
153
  // All procedures inherit the auth middleware and error definitions
231
- const getProfile = effectAuthedOs
232
- .effect(
233
- Effect.fn(function* ({ context }) {
234
- const userService = yield* UserService
235
- return yield* userService.findById(context.userId)
236
- })
237
- )
154
+ const getProfile = effectAuthedOs.effect(function* ({ context }) {
155
+ const userService = yield* UserService
156
+ return yield* userService.findById(context.userId)
157
+ })
238
158
 
239
159
  const updateProfile = effectAuthedOs
240
160
  .input(z.object({ name: z.string() }))
241
- .effect(
242
- Effect.fn(function* ({ context, input }) {
243
- const userService = yield* UserService
244
- return yield* userService.update(context.userId, input)
245
- })
246
- )
161
+ .effect(function* ({ context, input }) {
162
+ const userService = yield* UserService
163
+ return yield* userService.update(context.userId, input)
164
+ })
247
165
  ```
248
166
 
249
167
  ## Chaining Builder Methods
@@ -278,23 +196,21 @@ const createPost = effectOs
278
196
  createdAt: z.date(),
279
197
  }))
280
198
  // Define Effect handler
281
- .effect(({ input, errors }) =>
282
- Effect.gen(function* () {
283
- const userService = yield* UserService
284
- const user = yield* userService.findById(input.authorId)
285
-
286
- if (!user) {
287
- throw errors.NOT_FOUND()
288
- }
289
-
290
- const postService = yield* PostService
291
- return yield* postService.create({
292
- title: input.title,
293
- content: input.content,
294
- authorId: input.authorId,
295
- })
199
+ .effect(function* ({ input, errors }) {
200
+ const userService = yield* UserService
201
+ const user = yield* userService.findById(input.authorId)
202
+
203
+ if (!user) {
204
+ return yield Effect.Fail(errors.NOT_FOUND())
205
+ }
206
+
207
+ const postService = yield* PostService
208
+ return yield* postService.create({
209
+ title: input.title,
210
+ content: input.content,
211
+ authorId: input.authorId,
296
212
  })
297
- )
213
+ })
298
214
  ```
299
215
 
300
216
  ## Making Procedures Callable
@@ -304,7 +220,9 @@ Use `.callable()` to make procedures directly invocable:
304
220
  ```ts
305
221
  const greet = effectOs
306
222
  .input(z.object({ name: z.string() }))
307
- .effect(({ input }) => Effect.succeed(`Hello, ${input.name}!`))
223
+ .effect(function* ({ input }) {
224
+ return `Hello, ${input.name}!`
225
+ })
308
226
  .callable()
309
227
 
310
228
  // Can be called directly as a function
@@ -322,12 +240,10 @@ Use `.actionable()` for framework server actions (Next.js, etc.):
322
240
  ```tsx
323
241
  const createTodo = effectOs
324
242
  .input(z.object({ title: z.string() }))
325
- .effect(
326
- Effect.fn(function* ({ input }) {
327
- const todoService = yield* TodoService
328
- return yield* todoService.create(input.title)
329
- })
330
- )
243
+ .effect(function* ({ input }) {
244
+ const todoService = yield* TodoService
245
+ return yield* todoService.create(input.title)
246
+ })
331
247
  .actionable({ context: async () => ({ user: await getSession() }) })
332
248
 
333
249
  // Use in React Server Components
@@ -343,16 +259,9 @@ export async function TodoForm() {
343
259
 
344
260
  ## Error Handling
345
261
 
346
- Effect errors are properly propagated through oRPC's error handling:
262
+ Effect errors are properly propagated through oRPC's error handling. You can use the `errors` object passed to your handler:
347
263
 
348
264
  ```ts
349
- import { Effect } from 'effect'
350
-
351
- class NotFoundError extends Effect.Tag('NotFoundError')<
352
- NotFoundError,
353
- { readonly _tag: 'NotFoundError', readonly id: string }
354
- >() {}
355
-
356
265
  const getUser = effectOs
357
266
  .errors({
358
267
  NOT_FOUND: {
@@ -361,54 +270,199 @@ const getUser = effectOs
361
270
  },
362
271
  })
363
272
  .input(z.object({ id: z.string() }))
364
- .effect(({ input, errors }) =>
365
- Effect.gen(function* () {
366
- const userService = yield* UserService
367
- const user = yield* userService.findById(input.id)
273
+ .effect(function* ({ input, errors }) {
274
+ const userService = yield* UserService
275
+ const user = yield* userService.findById(input.id)
368
276
 
369
- if (!user) {
370
- // Use oRPC's type-safe errors
371
- throw errors.NOT_FOUND({ id: input.id })
372
- }
277
+ if (!user) {
278
+ // Use oRPC's type-safe errors
279
+ yield* Effect.fail(errors.NOT_FOUND({ id: input.id }))
280
+ }
373
281
 
374
- return user
375
- })
376
- )
282
+ return user
283
+ })
284
+ ```
285
+
286
+ ## Tagged Errors
287
+
288
+ `ORPCTaggedError` lets you create Effect-native error classes that integrate seamlessly with oRPC. These errors:
289
+
290
+ - Can be yielded in Effect generators (`yield* new MyError()` or `yield* Effect.fail(errors.MyError)`)
291
+ - Have all ORPCError properties (code, status, data, defined)
292
+ - Can be used in `.errors()` maps for type-safe error handling
293
+ - Automatically convert to ORPCError when thrown
294
+
295
+ ### Creating Tagged Errors
296
+
297
+ ```ts
298
+ import { ORPCTaggedError } from 'effect-orpc'
299
+
300
+ // Basic tagged error - code defaults to 'USER_NOT_FOUND' (CONSTANT_CASE of tag)
301
+ class UserNotFound extends ORPCTaggedError<UserNotFound>()('UserNotFound') {}
302
+
303
+ // With explicit code
304
+ class NotFound extends ORPCTaggedError<NotFound>()('NotFound', 'NOT_FOUND') {}
305
+
306
+ // With default options (code defaults to 'VALIDATION_ERROR') (CONSTANT_CASE of tag)
307
+ class ValidationError extends ORPCTaggedError<ValidationError>()(
308
+ 'ValidationError',
309
+ { status: 400, message: 'Validation failed' }
310
+ ) {}
311
+
312
+ // With explicit code and options
313
+ class Forbidden extends ORPCTaggedError<Forbidden>()(
314
+ 'Forbidden',
315
+ 'FORBIDDEN',
316
+ { status: 403, message: 'Access denied' }
317
+ ) {}
318
+
319
+ // With typed data
320
+ class UserNotFoundWithData extends ORPCTaggedError<
321
+ UserNotFoundWithData,
322
+ { userId: string }
323
+ >()('UserNotFoundWithData') {}
377
324
  ```
378
325
 
379
- ## Using Effect.fn vs Effect.gen
326
+ ### Using Tagged Errors in Procedures
380
327
 
381
- Both generator syntaxes are supported:
328
+ Tagged errors can be yielded directly in Effect generators:
382
329
 
383
330
  ```ts
384
- // Using Effect.fn (recommended for procedures)
385
- const procedureWithFn = effectOs
331
+ class UserNotFound extends ORPCTaggedError<
332
+ UserNotFound,
333
+ { userId: string }
334
+ >()('UserNotFound', { status: 404, message: 'User not found' })
335
+
336
+ const getUser = effectOs
386
337
  .input(z.object({ id: z.string() }))
387
- .effect(
388
- Effect.fn(function* ({ input }) {
389
- const service = yield* MyService
390
- return yield* service.doSomething(input.id)
391
- })
338
+ .effect(function* ({ input }) {
339
+ const userService = yield* UserService
340
+ const user = yield* userService.findById(input.id)
341
+
342
+ if (!user) {
343
+ // Yield the error - it will be converted to ORPCError automatically
344
+ return yield* new UserNotFound({ data: { userId: input.id } })
345
+ }
346
+
347
+ return user
348
+ })
349
+ ```
350
+
351
+ ### Using Tagged Errors in Error Maps
352
+
353
+ Tagged error classes can be passed directly to `.errors()`:
354
+
355
+ ```ts
356
+ class UserNotFound extends ORPCTaggedError<
357
+ UserNotFound,
358
+ { userId: string }
359
+ >()('UserNotFound', 'NOT_FOUND', { status: 404, message: 'User not found' })
360
+
361
+ class InvalidInput extends ORPCTaggedError<
362
+ InvalidInput,
363
+ { field: string }
364
+ >()('InvalidInput', 'BAD_REQUEST', { status: 400 })
365
+
366
+ const getUser = effectOs
367
+ .errors({
368
+ // Tagged error class - use the class directly
369
+ // The only difference is that the code is defined by the constant version of the tag
370
+ // Or when defined explicitely like in the Forbidden tagged error above
371
+ UserNotFound,
372
+ INVALID_INPUT: InvalidInput,
373
+ // Traditional format still works, and can be colocated
374
+ INTERNAL_ERROR: { status: 500, message: 'Something went wrong' },
375
+ })
376
+ .input(z.object({ id: z.string() }))
377
+ .effect(function* ({ input, errors }) {
378
+ if (!input.id) {
379
+ // errors.BAD_REQUEST is the InvalidInput class
380
+ return yield* new errors.INVALID_INPUT({ data: { field: 'id' } })
381
+ }
382
+
383
+ const userService = yield* UserService
384
+ const user = yield* userService.findById(input.id)
385
+
386
+ if (!user) {
387
+ // errors.UserNotFound is the UserNotFound class
388
+ // with the code USER_NOT_FOUND (defined at the class level)
389
+ return yield* new errors.UserNotFound({ data: { userId: input.id } })
390
+ }
391
+
392
+ return user
393
+ })
394
+ ```
395
+
396
+ ### Converting Tagged Errors
397
+
398
+ Use `toORPCError` to convert a tagged error to a plain ORPCError:
399
+
400
+ ```ts
401
+ import { toORPCError, ORPCTaggedError } from 'effect-orpc'
402
+ import { Effect } from 'effect'
403
+
404
+ class MyError extends ORPCTaggedError<MyError>()('MyError', 'BAD_REQUEST') {}
405
+
406
+ const procedure = effectOs.effect(function* () {
407
+ const result = yield* someOperation.pipe(
408
+ Effect.catchTag('MyError', (e) =>
409
+ // Convert to plain ORPCError if needed
410
+ Effect.fail(toORPCError(e))
411
+ )
392
412
  )
413
+ return result
414
+ })
415
+ ```
393
416
 
394
- // Using Effect.gen with arrow function
417
+ ### Tagged Error Properties
418
+
419
+ Tagged errors have all the properties of ORPCError plus Effect integration:
420
+
421
+ ```ts
422
+ const error = new UserNotFound({
423
+ data: { userId: '123' },
424
+ message: 'Custom message', // Override default message
425
+ cause: originalError, // Attach cause for debugging
426
+ })
427
+
428
+ error._tag // 'UserNotFound' - for Effect's catchTag
429
+ error.code // 'USER_NOT_FOUND' - ORPCError code
430
+ error.status // 404 - HTTP status
431
+ error.data // { userId: '123' } - typed data
432
+ error.message // 'Custom message'
433
+ error.defined // true - whether error is defined in error map
434
+
435
+ // Convert to plain ORPCError
436
+ const orpcError = error.toORPCError()
437
+
438
+ // Serialize to JSON
439
+ const json = error.toJSON()
440
+ // { _tag: 'UserNotFound', code: 'USER_NOT_FOUND', status: 404, ... }
441
+ ```
442
+
443
+ ## Generator Syntax
444
+
445
+ Pass a generator function directly to `.effect()` — no need to wrap it with `Effect.fn()` or `Effect.gen()`:
446
+
447
+ ```ts
448
+ // Recommended: Pass generator function directly
395
449
  const procedureWithGen = effectOs
396
450
  .input(z.object({ id: z.string() }))
397
- .effect(({ input }) =>
398
- Effect.gen(function* () {
399
- const service = yield* MyService
400
- return yield* service.doSomething(input.id)
401
- })
402
- )
451
+ .effect(function* ({ input }) {
452
+ const service = yield* MyService
453
+ return yield* service.doSomething(input.id)
454
+ })
403
455
 
404
- // Simple effects without generators
456
+ // Simple procedures without yield*
405
457
  const simpleProcedure = effectOs
406
458
  .input(z.object({ name: z.string() }))
407
- .effect(({ input }) =>
408
- Effect.succeed(`Hello, ${input.name}!`)
409
- )
459
+ .effect(function* ({ input }) {
460
+ return `Hello, ${input.name}!`
461
+ })
410
462
  ```
411
463
 
464
+ The handler receives `{ context, input, path, procedure, signal, lastEventId, errors }` as its argument, giving you full access to the oRPC procedure context.
465
+
412
466
  ## Traceable Spans
413
467
 
414
468
  All Effect procedures are automatically traced with `Effect.withSpan`. By default, the span name is the procedure path (e.g., `users.getUser`):
@@ -420,21 +474,17 @@ const router = os.router({
420
474
  // Span name: "users.get"
421
475
  get: effectOs
422
476
  .input(z.object({ id: z.string() }))
423
- .effect(
424
- Effect.fn(function* ({ input }) {
425
- const userService = yield* UserService
426
- return yield* userService.findById(input.id)
427
- })
428
- ),
477
+ .effect(function* ({ input }) {
478
+ const userService = yield* UserService
479
+ return yield* userService.findById(input.id)
480
+ }),
429
481
  // Span name: "users.create"
430
482
  create: effectOs
431
483
  .input(z.object({ name: z.string() }))
432
- .effect(
433
- Effect.fn(function* ({ input }) {
434
- const userService = yield* UserService
435
- return yield* userService.create(input.name)
436
- })
437
- ),
484
+ .effect(function* ({ input }) {
485
+ const userService = yield* UserService
486
+ return yield* userService.create(input.name)
487
+ }),
438
488
  })
439
489
  })
440
490
  ```
@@ -445,12 +495,10 @@ Use `.traced()` to override the default span name:
445
495
  const getUser = effectOs
446
496
  .input(z.object({ id: z.string() }))
447
497
  .traced('custom.span.name') // Override the default path-based name
448
- .effect(
449
- Effect.fn(function* ({ input }) {
450
- const userService = yield* UserService
451
- return yield* userService.findById(input.id)
452
- })
453
- )
498
+ .effect(function* ({ input }) {
499
+ const userService = yield* UserService
500
+ return yield* userService.findById(input.id)
501
+ })
454
502
  ```
455
503
 
456
504
  ### Enabling OpenTelemetry
@@ -533,6 +581,54 @@ The result of calling `.effect()`. Extends standard oRPC `DecoratedProcedure` wi
533
581
  | `.callable(options?)` | Make procedure directly invocable |
534
582
  | `.actionable(options?)` | Make procedure compatible with server actions |
535
583
 
584
+ ### `ORPCTaggedError<Self, TData>()(tag, codeOrOptions?, defaultOptions?)`
585
+
586
+ Factory function to create Effect-native tagged error classes.
587
+
588
+ - `Self` - The class type itself (for proper typing)
589
+ - `TData` - Optional type for the error's data payload
590
+ - `tag` - Unique tag for discriminated unions (used by Effect's `catchTag`)
591
+ - `codeOrOptions` - Either an ORPCErrorCode string or `{ status?, message? }` options
592
+ - `defaultOptions` - Default `{ status?, message? }` when code is provided explicitly
593
+
594
+ If no code is provided, it defaults to CONSTANT_CASE of the tag (e.g., `UserNotFound` → `USER_NOT_FOUND`).
595
+
596
+ ```ts
597
+ // Tag only - code defaults to 'MY_ERROR'
598
+ class MyError extends ORPCTaggedError<MyError>()('MyError') {}
599
+
600
+ // With options - code defaults to 'MY_ERROR'
601
+ class MyError extends ORPCTaggedError<MyError>()(
602
+ 'MyError',
603
+ { status: 400, message: 'Bad request' }
604
+ ) {}
605
+
606
+ // With explicit code
607
+ class MyError extends ORPCTaggedError<MyError>()(
608
+ 'MyError',
609
+ 'CUSTOM_CODE',
610
+ { status: 400 }
611
+ ) {}
612
+
613
+ // With typed data
614
+ class MyError extends ORPCTaggedError<MyError, { field: string }>()(
615
+ 'MyError',
616
+ 'BAD_REQUEST'
617
+ ) {}
618
+ ```
619
+
620
+ ### `toORPCError(taggedError)`
621
+
622
+ Converts an `ORPCTaggedError` instance to a plain `ORPCError`.
623
+
624
+ ```ts
625
+ import { toORPCError } from 'effect-orpc'
626
+
627
+ const taggedError = new UserNotFound({ data: { userId: '123' } })
628
+ const orpcError = toORPCError(taggedError)
629
+ // => ORPCError { code: 'USER_NOT_FOUND', status: 404, data: { userId: '123' } }
630
+ ```
631
+
536
632
  ## License
537
633
 
538
634
  MIT
package/dist/index.js CHANGED
@@ -117,7 +117,7 @@ function createEffectErrorConstructorMap(errors) {
117
117
  }
118
118
  const config = target[code];
119
119
  if (isORPCTaggedErrorClass(config)) {
120
- return config;
120
+ return (...opts) => new config(...opts);
121
121
  }
122
122
  return (...rest) => {
123
123
  const options = resolveMaybeOptionalOptions(rest);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/effect-builder.ts","../src/effect-procedure.ts","../src/tagged-error.ts"],"sourcesContent":["import type { ORPCErrorCode } from \"@orpc/client\";\nimport type {\n AnySchema,\n ErrorMap,\n InferSchemaOutput,\n Meta,\n Route,\n Schema,\n} from \"@orpc/contract\";\nimport type {\n AnyMiddleware,\n BuilderDef,\n Context,\n MapInputMiddleware,\n MergedCurrentContext,\n MergedInitialContext,\n Middleware,\n ORPCErrorConstructorMap,\n ProcedureHandlerOptions,\n} from \"@orpc/server\";\nimport type { IntersectPick } from \"@orpc/shared\";\nimport type { ManagedRuntime } from \"effect\";\nimport type { YieldWrap } from \"effect/Utils\";\n\nimport {\n mergeErrorMap,\n mergeMeta,\n mergeRoute,\n ORPCError,\n} from \"@orpc/contract\";\nimport {\n addMiddleware,\n Builder,\n decorateMiddleware,\n fallbackConfig,\n} from \"@orpc/server\";\nimport { Cause, Effect, Exit } from \"effect\";\n\nimport type {\n EffectErrorConstructorMap,\n EffectErrorMap,\n EffectErrorMapToUnion,\n MergedEffectErrorMap,\n} from \"./tagged-error\";\n\nimport { EffectDecoratedProcedure } from \"./effect-procedure\";\nimport {\n createEffectErrorConstructorMap,\n effectErrorMapToErrorMap,\n isORPCTaggedError,\n} from \"./tagged-error\";\n\n/**\n * Captures the stack trace at the call site for better error reporting in spans.\n * This is called at procedure definition time to capture where the procedure was defined.\n *\n * @returns A function that lazily extracts the relevant stack frame\n */\nexport function addSpanStackTrace(): () => string | undefined {\n const ErrorConstructor = Error as typeof Error & {\n stackTraceLimit?: number;\n };\n const limit = ErrorConstructor.stackTraceLimit;\n ErrorConstructor.stackTraceLimit = 3;\n const traceError = new Error();\n ErrorConstructor.stackTraceLimit = limit;\n let cache: false | string = false;\n return () => {\n if (cache !== false) {\n return cache;\n }\n if (traceError.stack !== undefined) {\n const stack = traceError.stack.split(\"\\n\");\n if (stack[3] !== undefined) {\n cache = stack[3].trim();\n return cache;\n }\n }\n };\n}\n\n/**\n * Configuration for Effect span tracing.\n */\nexport interface EffectSpanConfig {\n /**\n * The name of the span for telemetry.\n */\n name: string;\n /**\n * Function to lazily capture the stack trace at definition time.\n */\n captureStackTrace: () => string | undefined;\n}\n\n/**\n * Options passed to the Effect procedure handler.\n */\nexport interface EffectProcedureHandlerOptions<\n TCurrentContext extends Context,\n TInput,\n TEffectErrorMap extends EffectErrorMap,\n TMeta extends Meta,\n> extends Omit<\n ProcedureHandlerOptions<\n TCurrentContext,\n TInput,\n ORPCErrorConstructorMap<any>,\n TMeta\n >,\n \"errors\"\n> {\n errors: EffectErrorConstructorMap<TEffectErrorMap>;\n}\n\n/**\n * Handler type for Effect procedures.\n * The handler receives procedure options and returns an Effect.\n */\nexport type EffectProcedureHandler<\n TCurrentContext extends Context,\n TInput,\n THandlerOutput,\n TEffectErrorMap extends EffectErrorMap,\n TRequirementsProvided,\n TMeta extends Meta,\n> = (\n opt: EffectProcedureHandlerOptions<\n TCurrentContext,\n TInput,\n TEffectErrorMap,\n TMeta\n >,\n) => Generator<\n YieldWrap<\n Effect.Effect<\n any,\n | EffectErrorMapToUnion<TEffectErrorMap>\n | ORPCError<ORPCErrorCode, unknown>,\n TRequirementsProvided\n >\n >,\n THandlerOutput,\n never\n>;\n\n/**\n * Extended builder definition that includes the Effect ManagedRuntime.\n */\nexport interface EffectBuilderDef<\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TEffectErrorMap extends EffectErrorMap,\n TMeta extends Meta,\n TRequirementsProvided,\n TRuntimeError,\n> extends BuilderDef<TInputSchema, TOutputSchema, ErrorMap, TMeta> {\n runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>;\n /**\n * Optional span configuration for Effect tracing.\n */\n spanConfig?: EffectSpanConfig;\n /**\n * Effect-extended error map that supports both traditional errors and tagged errors.\n */\n effectErrorMap: TEffectErrorMap;\n}\n\n/**\n * Effect-native procedure builder that wraps an oRPC Builder instance\n * and adds Effect-specific capabilities while preserving Effect error\n * and requirements types.\n */\nexport class EffectBuilder<\n TInitialContext extends Context,\n TCurrentContext extends Context,\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TEffectErrorMap extends EffectErrorMap,\n TMeta extends Meta,\n TRequirementsProvided,\n TRuntimeError,\n> {\n \"~orpc\": EffectBuilderDef<\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >;\n\n constructor(\n def: EffectBuilderDef<\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >,\n ) {\n this[\"~orpc\"] = def;\n }\n\n /**\n * Adds type-safe custom errors.\n * Supports both traditional oRPC error definitions and ORPCTaggedError classes.\n *\n * @example\n * ```ts\n * // Traditional format\n * builder.errors({ BAD_REQUEST: { status: 400, message: 'Bad request' } })\n *\n * // Tagged error class\n * builder.errors({ USER_NOT_FOUND: UserNotFoundError })\n *\n * // Mixed\n * builder.errors({\n * BAD_REQUEST: { status: 400 },\n * USER_NOT_FOUND: UserNotFoundError,\n * })\n * ```\n *\n * @see {@link https://orpc.dev/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}\n */\n errors<U extends EffectErrorMap>(\n errors: U,\n ): EffectBuilder<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n MergedEffectErrorMap<TEffectErrorMap, U>,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectBuilder({\n ...this[\"~orpc\"],\n errorMap: mergeErrorMap(\n this[\"~orpc\"].errorMap,\n effectErrorMapToErrorMap(errors),\n ),\n effectErrorMap: {\n ...this[\"~orpc\"].effectErrorMap,\n ...errors,\n },\n });\n }\n\n /**\n * Uses a middleware to modify the context or improve the pipeline.\n *\n * @info Supports both normal middleware and inline middleware implementations.\n * @note The current context must be satisfy middleware dependent-context\n * @see {@link https://orpc.dev/docs/middleware Middleware Docs}\n */\n use<\n UOutContext extends IntersectPick<TCurrentContext, UOutContext>,\n UInContext extends Context = TCurrentContext,\n >(\n middleware: Middleware<\n UInContext | TCurrentContext,\n UOutContext,\n unknown,\n unknown,\n ORPCErrorConstructorMap<ErrorMap>,\n TMeta\n >,\n ): EffectBuilder<\n MergedInitialContext<TInitialContext, UInContext, TCurrentContext>,\n MergedCurrentContext<TCurrentContext, UOutContext>,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >;\n\n use(\n middleware: AnyMiddleware,\n mapInput?: MapInputMiddleware<any, any>,\n ): EffectBuilder<any, any, any, any, any, any, any, any> {\n const mapped = mapInput\n ? decorateMiddleware(middleware).mapInput(mapInput)\n : middleware;\n\n return new EffectBuilder({\n ...this[\"~orpc\"],\n middlewares: addMiddleware(this[\"~orpc\"].middlewares, mapped),\n });\n }\n\n /**\n * Sets or updates the metadata.\n * The provided metadata is spared-merged with any existing metadata.\n *\n * @see {@link https://orpc.dev/docs/metadata Metadata Docs}\n */\n meta(\n meta: TMeta,\n ): EffectBuilder<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectBuilder({\n ...this[\"~orpc\"],\n meta: mergeMeta(this[\"~orpc\"].meta, meta),\n });\n }\n\n /**\n * Sets or updates the route definition.\n * The provided route is spared-merged with any existing route.\n * This option is typically relevant when integrating with OpenAPI.\n *\n * @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}\n * @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}\n */\n route(\n route: Route,\n ): EffectBuilder<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectBuilder({\n ...this[\"~orpc\"],\n route: mergeRoute(this[\"~orpc\"].route, route),\n });\n }\n\n /**\n * Defines the input validation schema.\n *\n * @see {@link https://orpc.dev/docs/procedure#input-output-validation Input Validation Docs}\n */\n input<USchema extends AnySchema>(\n schema: USchema,\n ): EffectBuilder<\n TInitialContext,\n TCurrentContext,\n USchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectBuilder({\n ...this[\"~orpc\"],\n inputSchema: schema,\n inputValidationIndex:\n fallbackConfig(\n \"initialInputValidationIndex\",\n this[\"~orpc\"].config.initialInputValidationIndex,\n ) + this[\"~orpc\"].middlewares.length,\n });\n }\n\n /**\n * Defines the output validation schema.\n *\n * @see {@link https://orpc.dev/docs/procedure#input-output-validation Output Validation Docs}\n */\n output<USchema extends AnySchema>(\n schema: USchema,\n ): EffectBuilder<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n USchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectBuilder({\n ...this[\"~orpc\"],\n outputSchema: schema,\n outputValidationIndex:\n fallbackConfig(\n \"initialOutputValidationIndex\",\n this[\"~orpc\"].config.initialOutputValidationIndex,\n ) + this[\"~orpc\"].middlewares.length,\n });\n }\n\n /**\n * Adds a traceable span to the procedure for telemetry.\n * The span name is used for Effect tracing via `Effect.withSpan`.\n * Stack trace is captured at the call site for better error reporting.\n *\n * @param spanName - The name of the span for telemetry (e.g., 'users.getUser')\n * @returns An EffectBuilder with span tracing configured\n *\n * @example\n * ```ts\n * const getUser = effectOs\n * .input(z.object({ id: z.string() }))\n * .traced('users.getUser')\n * .effect(function* ({ input }) {\n * const userService = yield* UserService\n * return yield* userService.findById(input.id)\n * })\n * ```\n */\n traced(\n spanName: string,\n ): EffectBuilder<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectBuilder({\n ...this[\"~orpc\"],\n spanConfig: {\n name: spanName,\n captureStackTrace: addSpanStackTrace(),\n },\n });\n }\n\n /**\n * Defines the handler of the procedure using an Effect.\n * The Effect is executed using the ManagedRuntime provided during builder creation.\n * The effect is automatically wrapped with `Effect.withSpan`.\n *\n * @see {@link https://orpc.dev/docs/procedure Procedure Docs}\n */\n effect<UFuncOutput>(\n effectFn: EffectProcedureHandler<\n TCurrentContext,\n InferSchemaOutput<TInputSchema>,\n UFuncOutput,\n TEffectErrorMap,\n TRequirementsProvided,\n TMeta\n >,\n ): EffectDecoratedProcedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n Schema<UFuncOutput, UFuncOutput>,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n const { runtime, spanConfig } = this[\"~orpc\"];\n // Capture stack trace at definition time for default tracing\n const defaultCaptureStackTrace = addSpanStackTrace();\n return new EffectDecoratedProcedure({\n ...this[\"~orpc\"],\n handler: async (opts) => {\n const effectOpts: EffectProcedureHandlerOptions<\n TCurrentContext,\n InferSchemaOutput<TInputSchema>,\n TEffectErrorMap,\n TMeta\n > = {\n context: opts.context,\n input: opts.input,\n path: opts.path,\n procedure: opts.procedure,\n signal: opts.signal,\n lastEventId: opts.lastEventId,\n errors: createEffectErrorConstructorMap(this[\"~orpc\"].effectErrorMap),\n };\n const spanName = spanConfig?.name ?? opts.path.join(\".\");\n const captureStackTrace =\n spanConfig?.captureStackTrace ?? defaultCaptureStackTrace;\n const resolver = Effect.fnUntraced(effectFn);\n const tracedEffect = Effect.withSpan(resolver(effectOpts), spanName, {\n captureStackTrace,\n });\n const exit = await runtime.runPromiseExit(tracedEffect, {\n signal: opts.signal,\n });\n\n if (Exit.isFailure(exit)) {\n throw Cause.match(exit.cause, {\n onDie(defect) {\n return new ORPCError(\"INTERNAL_SERVER_ERROR\", {\n cause: defect,\n });\n },\n onFail(error) {\n if (isORPCTaggedError(error)) {\n return error.toORPCError();\n }\n if (error instanceof ORPCError) {\n return error;\n }\n return new ORPCError(\"INTERNAL_SERVER_ERROR\", {\n cause: error,\n });\n },\n onInterrupt(fiberId) {\n return new ORPCError(\"INTERNAL_SERVER_ERROR\", {\n cause: new Error(`${fiberId} Interrupted`),\n });\n },\n onSequential(left) {\n return left;\n },\n onEmpty: new ORPCError(\"INTERNAL_SERVER_ERROR\", {\n cause: new Error(\"Unknown error\"),\n }),\n onParallel(left) {\n return left;\n },\n });\n }\n\n return exit.value;\n },\n });\n }\n}\n\n/**\n * Any oRPC builder-like object that has the `~orpc` definition property.\n * This includes Builder, BuilderWithMiddlewares, ProcedureBuilder, etc.\n */\nexport interface AnyBuilderLike<\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TErrorMap extends ErrorMap,\n TMeta extends Meta,\n> {\n \"~orpc\": BuilderDef<TInputSchema, TOutputSchema, TErrorMap, TMeta>;\n}\n\n/**\n * Creates an Effect-aware procedure builder with the specified ManagedRuntime.\n * Uses the default `os` builder from `@orpc/server`.\n *\n * @param runtime - The ManagedRuntime that provides services for Effect procedures\n * @returns An EffectBuilder instance for creating Effect-native procedures\n *\n * @example\n * ```ts\n * import { makeEffectORPC } from '@orpc/effect'\n * import { Effect, Layer, ManagedRuntime } from 'effect'\n *\n * const runtime = ManagedRuntime.make(Layer.empty)\n * const effectOs = makeEffectORPC(runtime)\n *\n * const hello = effectOs.effect(() => Effect.succeed('Hello!'))\n * ```\n */\nexport function makeEffectORPC<TRequirementsProvided, TRuntimeError>(\n runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>,\n): EffectBuilder<\n Context,\n Context,\n Schema<unknown, unknown>,\n Schema<unknown, unknown>,\n Record<never, never>,\n Record<never, never>,\n TRequirementsProvided,\n TRuntimeError\n>;\n\n/**\n * Creates an Effect-aware procedure builder by wrapping an existing oRPC Builder\n * with the specified ManagedRuntime.\n *\n * @param runtime - The ManagedRuntime that provides services for Effect procedures\n * @param builder - The oRPC Builder instance to wrap (e.g., a customized `os`)\n * @returns An EffectBuilder instance that extends the original builder with Effect support\n *\n * @example\n * ```ts\n * import { makeEffectORPC } from '@orpc/effect'\n * import { os } from '@orpc/server'\n * import { Effect, Layer, ManagedRuntime } from 'effect'\n *\n * // Create a customized builder\n * const authedOs = os.use(authMiddleware)\n *\n * // Wrap it with Effect support\n * const runtime = ManagedRuntime.make(UserServiceLive)\n * const effectOs = makeEffectORPC(runtime, authedOs)\n *\n * const getUser = effectOs\n * .input(z.object({ id: z.string() }))\n * .effect(\n * Effect.fn(function* ({ input }) {\n * const userService = yield* UserService\n * return yield* userService.findById(input.id)\n * })\n * )\n * ```\n */\nexport function makeEffectORPC<\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TErrorMap extends ErrorMap,\n TMeta extends Meta,\n TRequirementsProvided,\n TRuntimeError,\n>(\n runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>,\n builder: AnyBuilderLike<TInputSchema, TOutputSchema, TErrorMap, TMeta>,\n): EffectBuilder<\n Context,\n Context,\n TInputSchema,\n TOutputSchema,\n TErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n>;\n\nexport function makeEffectORPC<\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TErrorMap extends ErrorMap,\n TMeta extends Meta,\n TRequirementsProvided,\n TRuntimeError,\n>(\n runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>,\n builder?: AnyBuilderLike<TInputSchema, TOutputSchema, TErrorMap, TMeta>,\n): EffectBuilder<\n Context,\n Context,\n TInputSchema,\n TOutputSchema,\n TErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n> {\n const resolvedBuilder =\n builder ?? emptyBuilder<TInputSchema, TOutputSchema, TErrorMap, TMeta>();\n return new EffectBuilder({\n ...resolvedBuilder[\"~orpc\"],\n effectErrorMap: resolvedBuilder[\"~orpc\"].errorMap,\n runtime,\n });\n}\n\nfunction emptyBuilder<\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TErrorMap extends ErrorMap,\n TMeta extends Meta,\n>() {\n return new Builder<\n Record<never, never>,\n Record<never, never>,\n TInputSchema,\n TOutputSchema,\n TErrorMap,\n TMeta\n >({\n config: {},\n route: {},\n meta: {} as TMeta,\n errorMap: {} as TErrorMap,\n inputValidationIndex: fallbackConfig(\"initialInputValidationIndex\"),\n outputValidationIndex: fallbackConfig(\"initialOutputValidationIndex\"),\n middlewares: [],\n dedupeLeadingMiddlewares: true,\n });\n}\n","import type { ClientContext } from \"@orpc/client\";\nimport type {\n AnySchema,\n ErrorMap,\n InferSchemaInput,\n InferSchemaOutput,\n Meta,\n Route,\n} from \"@orpc/contract\";\nimport type {\n AnyMiddleware,\n Context,\n CreateProcedureClientOptions,\n MapInputMiddleware,\n MergedCurrentContext,\n MergedInitialContext,\n Middleware,\n ORPCErrorConstructorMap,\n ProcedureActionableClient,\n ProcedureClient,\n ProcedureDef,\n} from \"@orpc/server\";\nimport type { IntersectPick, MaybeOptionalOptions } from \"@orpc/shared\";\nimport type { ManagedRuntime } from \"effect\";\n\nimport { mergeMeta, mergeRoute } from \"@orpc/contract\";\nimport {\n addMiddleware,\n createActionableClient,\n createProcedureClient,\n decorateMiddleware,\n Procedure,\n} from \"@orpc/server\";\n\nimport type { EffectErrorMap, MergedEffectErrorMap } from \"./tagged-error\";\n\nimport { effectErrorMapToErrorMap } from \"./tagged-error\";\n\n/**\n * Extended procedure definition that includes the Effect ManagedRuntime.\n */\nexport interface EffectProcedureDef<\n TInitialContext extends Context,\n TCurrentContext extends Context,\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TEffectErrorMap extends EffectErrorMap,\n TMeta extends Meta,\n TRequirementsProvided,\n TRuntimeError,\n> extends ProcedureDef<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n ErrorMap,\n TMeta\n> {\n runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>;\n effectErrorMap: TEffectErrorMap;\n}\n\n/**\n * An Effect-native decorated procedure that preserves Effect error and requirements types.\n *\n * This class extends Procedure with additional type parameters for Effect-specific\n * type information, allowing full type inference of Effect errors and requirements.\n */\nexport class EffectDecoratedProcedure<\n TInitialContext extends Context,\n TCurrentContext extends Context,\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TEffectErrorMap extends EffectErrorMap,\n TMeta extends Meta,\n TRequirementsProvided,\n TRuntimeError,\n> extends Procedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n ErrorMap,\n TMeta\n> {\n declare \"~orpc\": EffectProcedureDef<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >;\n\n constructor(\n def: EffectProcedureDef<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >,\n ) {\n super(def);\n }\n\n /**\n * Adds type-safe custom errors.\n * Supports both traditional oRPC error definitions and ORPCTaggedError classes.\n *\n * @see {@link https://orpc.dev/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}\n */\n errors<U extends EffectErrorMap>(\n errors: U,\n ): EffectDecoratedProcedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n MergedEffectErrorMap<TEffectErrorMap, U>,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n const newEffectErrorMap = { ...this[\"~orpc\"].effectErrorMap, ...errors };\n return new EffectDecoratedProcedure({\n ...this[\"~orpc\"],\n effectErrorMap: newEffectErrorMap,\n errorMap: effectErrorMapToErrorMap(newEffectErrorMap),\n });\n }\n\n /**\n * Sets or updates the metadata.\n * The provided metadata is spared-merged with any existing metadata.\n *\n * @see {@link https://orpc.dev/docs/metadata Metadata Docs}\n */\n meta(\n meta: TMeta,\n ): EffectDecoratedProcedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectDecoratedProcedure({\n ...this[\"~orpc\"],\n meta: mergeMeta(this[\"~orpc\"].meta, meta),\n });\n }\n\n /**\n * Sets or updates the route definition.\n * The provided route is spared-merged with any existing route.\n * This option is typically relevant when integrating with OpenAPI.\n *\n * @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}\n * @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}\n */\n route(\n route: Route,\n ): EffectDecoratedProcedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectDecoratedProcedure({\n ...this[\"~orpc\"],\n route: mergeRoute(this[\"~orpc\"].route, route),\n });\n }\n\n /**\n * Uses a middleware to modify the context or improve the pipeline.\n *\n * @info Supports both normal middleware and inline middleware implementations.\n * @info Pass second argument to map the input.\n * @note The current context must be satisfy middleware dependent-context\n * @see {@link https://orpc.dev/docs/middleware Middleware Docs}\n */\n use<\n UOutContext extends IntersectPick<TCurrentContext, UOutContext>,\n UInContext extends Context = TCurrentContext,\n >(\n middleware: Middleware<\n UInContext | TCurrentContext,\n UOutContext,\n InferSchemaOutput<TInputSchema>,\n InferSchemaInput<TOutputSchema>,\n ORPCErrorConstructorMap<ErrorMap>,\n TMeta\n >,\n ): EffectDecoratedProcedure<\n MergedInitialContext<TInitialContext, UInContext, TCurrentContext>,\n MergedCurrentContext<TCurrentContext, UOutContext>,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >;\n\n /**\n * Uses a middleware to modify the context or improve the pipeline.\n *\n * @info Supports both normal middleware and inline middleware implementations.\n * @info Pass second argument to map the input.\n * @note The current context must be satisfy middleware dependent-context\n * @see {@link https://orpc.dev/docs/middleware Middleware Docs}\n */\n use<\n UOutContext extends IntersectPick<TCurrentContext, UOutContext>,\n UInput,\n UInContext extends Context = TCurrentContext,\n >(\n middleware: Middleware<\n UInContext | TCurrentContext,\n UOutContext,\n UInput,\n InferSchemaInput<TOutputSchema>,\n ORPCErrorConstructorMap<ErrorMap>,\n TMeta\n >,\n mapInput: MapInputMiddleware<InferSchemaOutput<TInputSchema>, UInput>,\n ): EffectDecoratedProcedure<\n MergedInitialContext<TInitialContext, UInContext, TCurrentContext>,\n MergedCurrentContext<TCurrentContext, UOutContext>,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >;\n\n use(\n middleware: AnyMiddleware,\n mapInput?: MapInputMiddleware<any, any>,\n ): EffectDecoratedProcedure<any, any, any, any, any, any, any, any> {\n const mapped = mapInput\n ? decorateMiddleware(middleware).mapInput(mapInput)\n : middleware;\n\n return new EffectDecoratedProcedure({\n ...this[\"~orpc\"],\n middlewares: addMiddleware(this[\"~orpc\"].middlewares, mapped),\n });\n }\n\n /**\n * Make this procedure callable (works like a function while still being a procedure).\n *\n * @see {@link https://orpc.dev/docs/client/server-side Server-side Client Docs}\n */\n callable<TClientContext extends ClientContext>(\n ...rest: MaybeOptionalOptions<\n CreateProcedureClientOptions<\n TInitialContext,\n TOutputSchema,\n ErrorMap,\n TMeta,\n TClientContext\n >\n >\n ): EffectDecoratedProcedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > &\n ProcedureClient<TClientContext, TInputSchema, TOutputSchema, ErrorMap> {\n const client: ProcedureClient<\n TClientContext,\n TInputSchema,\n TOutputSchema,\n ErrorMap\n > = createProcedureClient(this, ...rest);\n\n return new Proxy(client, {\n get: (target, key) => {\n return Reflect.has(this, key)\n ? Reflect.get(this, key)\n : Reflect.get(target, key);\n },\n has: (target, key) => {\n return Reflect.has(this, key) || Reflect.has(target, key);\n },\n }) as any;\n }\n\n /**\n * Make this procedure compatible with server action.\n *\n * @see {@link https://orpc.dev/docs/server-action Server Action Docs}\n */\n actionable(\n ...rest: MaybeOptionalOptions<\n CreateProcedureClientOptions<\n TInitialContext,\n TOutputSchema,\n ErrorMap,\n TMeta,\n Record<never, never>\n >\n >\n ): EffectDecoratedProcedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > &\n ProcedureActionableClient<TInputSchema, TOutputSchema, ErrorMap> {\n const action: ProcedureActionableClient<\n TInputSchema,\n TOutputSchema,\n ErrorMap\n > = createActionableClient(createProcedureClient(this, ...rest));\n\n return new Proxy(action, {\n get: (target, key) => {\n return Reflect.has(this, key)\n ? Reflect.get(this, key)\n : Reflect.get(target, key);\n },\n has: (target, key) => {\n return Reflect.has(this, key) || Reflect.has(target, key);\n },\n }) as any;\n }\n}\n","import type {\n ORPCErrorCode,\n ORPCErrorJSON,\n ORPCErrorOptions,\n} from \"@orpc/client\";\nimport type { AnySchema, ErrorMap, ErrorMapItem } from \"@orpc/contract\";\nimport type { ORPCErrorConstructorMapItemOptions } from \"@orpc/server\";\nimport type { MaybeOptionalOptions } from \"@orpc/shared\";\nimport type { Pipeable, Types } from \"effect\";\nimport type * as Cause from \"effect/Cause\";\nimport type * as Effect from \"effect/Effect\";\n\nimport {\n fallbackORPCErrorMessage,\n fallbackORPCErrorStatus,\n isORPCErrorStatus,\n ORPCError,\n} from \"@orpc/client\";\nimport { resolveMaybeOptionalOptions } from \"@orpc/shared\";\nimport * as Data from \"effect/Data\";\n\n/**\n * Symbol to access the underlying ORPCError instance\n */\nexport const ORPCErrorSymbol: unique symbol = Symbol.for(\n \"@orpc/effect/ORPCTaggedError\",\n);\n\n/**\n * Instance type for ORPCTaggedError that combines YieldableError with ORPCError properties\n */\nexport interface ORPCTaggedErrorInstance<\n TTag extends string,\n TCode extends ORPCErrorCode,\n TData,\n>\n extends Cause.YieldableError, Pipeable.Pipeable {\n readonly _tag: TTag;\n readonly code: TCode;\n readonly status: number;\n readonly data: TData;\n readonly defined: boolean;\n readonly [ORPCErrorSymbol]: ORPCError<TCode, TData>;\n\n toJSON(): ORPCErrorJSON<TCode, TData> & { _tag: TTag };\n toORPCError(): ORPCError<TCode, TData>;\n commit(): Effect.Effect<never, this, never>;\n}\n\n/**\n * Options for creating an ORPCTaggedError\n */\nexport type ORPCTaggedErrorOptions<TData> = Omit<\n ORPCErrorOptions<TData>,\n \"defined\"\n> & { defined?: boolean };\n\n/**\n * Constructor type for ORPCTaggedError classes\n */\nexport interface ORPCTaggedErrorClass<\n TTag extends string,\n TCode extends ORPCErrorCode,\n TData,\n> {\n readonly _tag: TTag;\n readonly code: TCode;\n new (\n ...args: MaybeOptionalOptions<ORPCTaggedErrorOptions<TData>>\n ): ORPCTaggedErrorInstance<TTag, TCode, TData>;\n}\n\n/**\n * Type helper to infer the ORPCError type from an ORPCTaggedError\n */\nexport type InferORPCError<T> =\n T extends ORPCTaggedErrorInstance<string, infer TCode, infer TData>\n ? ORPCError<TCode, TData>\n : never;\n\n/**\n * Any ORPCTaggedErrorClass\n */\nexport type AnyORPCTaggedErrorClass = ORPCTaggedErrorClass<\n string,\n ORPCErrorCode,\n any\n>;\n\n/**\n * Check if a value is an ORPCTaggedErrorClass (constructor)\n */\nexport function isORPCTaggedErrorClass(\n value: unknown,\n): value is AnyORPCTaggedErrorClass {\n return (\n typeof value === \"function\" &&\n \"_tag\" in value &&\n \"code\" in value &&\n typeof value._tag === \"string\" &&\n typeof value.code === \"string\"\n );\n}\n\n/**\n * Check if a value is an ORPCTaggedError instance\n */\nexport function isORPCTaggedError(\n value: unknown,\n): value is ORPCTaggedErrorInstance<string, ORPCErrorCode, unknown> {\n return (\n typeof value === \"object\" && value !== null && ORPCErrorSymbol in value\n );\n}\n\n/**\n * Converts a PascalCase or camelCase string to CONSTANT_CASE.\n * e.g., \"UserNotFoundError\" -> \"USER_NOT_FOUND_ERROR\"\n */\nfunction toConstantCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, \"$1_$2\")\n .replace(/([A-Z])([A-Z][a-z])/g, \"$1_$2\")\n .toUpperCase();\n}\n\n// Type-level conversion: split on capital letters and join with underscore\ntype SplitOnCapital<\n S extends string,\n Acc extends string = \"\",\n> = S extends `${infer Head}${infer Tail}`\n ? Head extends Uppercase<Head>\n ? Head extends Lowercase<Head>\n ? SplitOnCapital<Tail, `${Acc}${Head}`>\n : Acc extends \"\"\n ? SplitOnCapital<Tail, Head>\n : `${Acc}_${SplitOnCapital<Tail, Head>}`\n : SplitOnCapital<Tail, `${Acc}${Uppercase<Head>}`>\n : Acc;\n\n/**\n * Converts a tag name to an error code in CONSTANT_CASE.\n */\nexport type TagToCode<TTag extends string> = SplitOnCapital<TTag>;\n\n/**\n * Creates a tagged error class that combines Effect's YieldableError with ORPCError.\n *\n * This allows you to create errors that:\n * - Can be yielded in Effect generators (`yield* myError`)\n * - Have all ORPCError properties (code, status, data, defined)\n * - Can be converted to a plain ORPCError for oRPC handlers\n *\n * The returned factory function takes:\n * - `tag` - The unique tag for this error type (used for discriminated unions)\n * - `codeOrOptions` - Optional ORPC error code or options. If omitted, code defaults to CONSTANT_CASE of tag\n * - `defaultOptions` - Optional default options for status and message (when code is provided)\n *\n * @example\n * ```ts\n * import { ORPCTaggedError } from '@orpc/effect'\n * import { Effect } from 'effect'\n *\n * // Define a custom error (code defaults to 'USER_NOT_FOUND_ERROR')\n * class UserNotFoundError extends ORPCTaggedError<UserNotFoundError>()('UserNotFoundError') {}\n *\n * // With explicit code\n * class NotFoundError extends ORPCTaggedError<NotFoundError>()('NotFoundError', 'NOT_FOUND') {}\n *\n * // Use in an Effect\n * const getUser = (id: string) => Effect.gen(function* () {\n * const user = yield* findUser(id)\n * if (!user) {\n * return yield* new UserNotFoundError({ data: { userId: id } })\n * }\n * return user\n * })\n *\n * // With custom data type\n * class ValidationError extends ORPCTaggedError<ValidationError, { fields: string[] }>()('ValidationError', 'BAD_REQUEST') {}\n *\n * // With options only (code defaults to 'VALIDATION_ERROR')\n * class ValidationError2 extends ORPCTaggedError<ValidationError2, { fields: string[] }>()(\n * 'ValidationError2',\n * { message: 'Validation failed' }\n * ) {}\n * ```\n */\n/**\n * Return type for the factory function with overloads\n */\ninterface ORPCTaggedErrorFactory<Self, TData> {\n // Overload 1: tag only (code defaults to CONSTANT_CASE of tag)\n <TTag extends string>(\n tag: TTag,\n ): Types.Equals<Self, unknown> extends true\n ? `Missing \\`Self\\` generic - use \\`class MyError extends ORPCTaggedError<MyError>()(tag) {}\\``\n : ORPCTaggedErrorClass<TTag, TagToCode<TTag>, TData>;\n\n // Overload 2: tag + options (code defaults to CONSTANT_CASE of tag)\n <TTag extends string>(\n tag: TTag,\n options: { status?: number; message?: string },\n ): Types.Equals<Self, unknown> extends true\n ? `Missing \\`Self\\` generic - use \\`class MyError extends ORPCTaggedError<MyError>()(tag, options) {}\\``\n : ORPCTaggedErrorClass<TTag, TagToCode<TTag>, TData>;\n\n // Overload 3: tag + explicit code\n <TTag extends string, TCode extends ORPCErrorCode>(\n tag: TTag,\n code: TCode,\n defaultOptions?: { status?: number; message?: string },\n ): Types.Equals<Self, unknown> extends true\n ? `Missing \\`Self\\` generic - use \\`class MyError extends ORPCTaggedError<MyError>()(tag, code) {}\\``\n : ORPCTaggedErrorClass<TTag, TCode, TData>;\n}\n\nexport function ORPCTaggedError<\n Self,\n TData = undefined,\n>(): ORPCTaggedErrorFactory<Self, TData> {\n const factory = <TTag extends string, TCode extends ORPCErrorCode>(\n tag: TTag,\n codeOrOptions?: TCode | { status?: number; message?: string },\n defaultOptions?: { status?: number; message?: string },\n ): ORPCTaggedErrorClass<TTag, TCode, TData> => {\n // Determine if second arg is code or options\n const isCodeProvided = typeof codeOrOptions === \"string\";\n const code = (\n isCodeProvided ? codeOrOptions : toConstantCase(tag)\n ) as TCode;\n const options = isCodeProvided ? defaultOptions : codeOrOptions;\n\n const defaultStatus = options?.status;\n const defaultMessage = options?.message;\n\n // Use Effect's TaggedError as the base - this handles all Effect internals\n // (YieldableError, type symbols, commit(), Symbol.iterator, pipe(), etc.)\n const BaseTaggedError = Data.TaggedError(tag) as unknown as new (args: {\n message?: string;\n cause?: unknown;\n code: TCode;\n status: number;\n data: TData;\n defined: boolean;\n }) => Cause.YieldableError & {\n readonly _tag: TTag;\n readonly code: TCode;\n readonly status: number;\n readonly data: TData;\n readonly defined: boolean;\n };\n\n class ORPCTaggedErrorBase extends BaseTaggedError {\n static readonly _tag = tag;\n static readonly code = code;\n\n readonly [ORPCErrorSymbol]: ORPCError<TCode, TData>;\n\n constructor(\n ...rest: MaybeOptionalOptions<ORPCTaggedErrorOptions<TData>>\n ) {\n const opts = resolveMaybeOptionalOptions(rest);\n const status = opts.status ?? defaultStatus;\n const inputMessage = opts.message ?? defaultMessage;\n\n if (status !== undefined && !isORPCErrorStatus(status)) {\n throw new globalThis.Error(\n \"[ORPCTaggedError] Invalid error status code.\",\n );\n }\n\n const finalStatus = fallbackORPCErrorStatus(code, status);\n const finalMessage = fallbackORPCErrorMessage(code, inputMessage);\n\n // Pass to Effect's TaggedError - it spreads these onto the instance\n super({\n message: finalMessage,\n cause: opts.cause,\n code,\n status: finalStatus,\n data: opts.data as TData,\n defined: opts.defined ?? true,\n });\n\n // Create the underlying ORPCError for interop\n this[ORPCErrorSymbol] = new ORPCError(code, {\n status: finalStatus,\n message: finalMessage,\n data: opts.data as TData,\n defined: this.defined,\n cause: opts.cause,\n });\n }\n\n /**\n * Converts this error to a plain ORPCError.\n * Useful when you need to return from an oRPC handler.\n */\n toORPCError(): ORPCError<TCode, TData> {\n return this[ORPCErrorSymbol];\n }\n\n override toJSON(): ORPCErrorJSON<TCode, TData> & { _tag: TTag } {\n return {\n _tag: this._tag,\n defined: this.defined,\n code: this.code,\n status: this.status,\n message: this.message,\n data: this.data,\n };\n }\n }\n\n return ORPCTaggedErrorBase as any;\n };\n\n return factory as ORPCTaggedErrorFactory<Self, TData>;\n}\n\n/**\n * Converts an ORPCTaggedError to a plain ORPCError.\n * Useful in handlers that need to throw ORPCError.\n *\n * @example\n * ```ts\n * const handler = effectOs.effect(function* () {\n * const result = yield* someOperation.pipe(\n * Effect.catchTag('UserNotFoundError', (e) =>\n * Effect.fail(toORPCError(e))\n * )\n * )\n * return result\n * })\n * ```\n */\nexport function toORPCError<TCode extends ORPCErrorCode, TData>(\n error: ORPCTaggedErrorInstance<string, TCode, TData>,\n): ORPCError<TCode, TData> {\n return error[ORPCErrorSymbol];\n}\n\n// ============================================================================\n// Extended Error Map Types for Effect\n// ============================================================================\n\n/**\n * An item in the EffectErrorMap - can be either a traditional ErrorMapItem or an ORPCTaggedErrorClass\n */\nexport type EffectErrorMapItem =\n | ErrorMapItem<AnySchema>\n | AnyORPCTaggedErrorClass;\n\n/**\n * Extended error map that supports both traditional oRPC errors and ORPCTaggedError classes.\n *\n * @example\n * ```ts\n * const errorMap = {\n * // Traditional format\n * BAD_REQUEST: { status: 400, message: 'Bad request' },\n *\n * // Tagged error class reference\n * USER_NOT_FOUND: UserNotFoundError,\n * } satisfies EffectErrorMap\n * ```\n */\nexport type EffectErrorMap = {\n [key in ORPCErrorCode]?: EffectErrorMapItem;\n};\n\n/**\n * Merges two EffectErrorMaps, with the second map taking precedence.\n */\nexport type MergedEffectErrorMap<\n T1 extends EffectErrorMap,\n T2 extends EffectErrorMap,\n> = T1 & T2;\n\n/**\n * Extracts the instance type from an EffectErrorMapItem\n */\nexport type EffectErrorMapItemToInstance<\n TCode extends ORPCErrorCode,\n T extends EffectErrorMapItem,\n> = T extends AnyORPCTaggedErrorClass\n ? InstanceType<T>\n : T extends { data?: infer TData }\n ? ORPCError<TCode, TData>\n : ORPCError<TCode, unknown>;\n\n/**\n * Converts an EffectErrorMap to a union of error instances.\n */\nexport type EffectErrorMapToUnion<T extends EffectErrorMap> = {\n [K in keyof T]: K extends ORPCErrorCode\n ? T[K] extends EffectErrorMapItem\n ? EffectErrorMapItemToInstance<K, T[K]>\n : never\n : never;\n}[keyof T];\n\n/**\n * Type for the error constructors available in Effect handlers.\n * For tagged errors, it's the class constructor itself.\n * For traditional errors, it's a function that creates ORPCError.\n */\nexport type EffectErrorConstructorMapItem<\n TCode extends ORPCErrorCode,\n T extends EffectErrorMapItem,\n> =\n T extends ORPCTaggedErrorClass<infer _TTag, TCode, infer TData>\n ? ORPCTaggedErrorClass<_TTag, TCode, TData>\n : T extends { data?: infer TData }\n ? (\n ...args: MaybeOptionalOptions<\n ORPCErrorConstructorMapItemOptions<TData>\n >\n ) => ORPCError<TCode, TData>\n : (\n ...args: MaybeOptionalOptions<\n ORPCErrorConstructorMapItemOptions<unknown>\n >\n ) => ORPCError<TCode, unknown>;\n\n/**\n * Constructor map for EffectErrorMap - provides typed error constructors for handlers.\n */\nexport type EffectErrorConstructorMap<T extends EffectErrorMap> = {\n [K in keyof T]: K extends ORPCErrorCode\n ? T[K] extends EffectErrorMapItem\n ? EffectErrorConstructorMapItem<K, T[K]>\n : never\n : never;\n};\n\n/**\n * Creates an error constructor map from an EffectErrorMap.\n * Tagged error classes are passed through directly.\n * Traditional error items become ORPCError factory functions.\n */\nexport function createEffectErrorConstructorMap<T extends EffectErrorMap>(\n errors: T | undefined,\n): EffectErrorConstructorMap<T> {\n const target = errors ?? ({} as T);\n const proxy = new Proxy(target, {\n get(proxyTarget, code) {\n if (typeof code !== \"string\") {\n return Reflect.get(proxyTarget, code);\n }\n\n const config = target[code];\n\n // If it's a tagged error class, return it directly\n if (isORPCTaggedErrorClass(config)) {\n return config;\n }\n\n // Otherwise, create a factory function for ORPCError\n return (\n ...rest: MaybeOptionalOptions<\n Omit<ORPCErrorOptions<unknown>, \"defined\" | \"status\">\n >\n ) => {\n const options = resolveMaybeOptionalOptions(rest);\n return new ORPCError(code, {\n defined: Boolean(config),\n status: config?.status,\n message: options.message ?? config?.message,\n data: options.data,\n cause: options.cause,\n });\n };\n },\n });\n\n return proxy as EffectErrorConstructorMap<T>;\n}\n\n/**\n * Converts an EffectErrorMap to a standard oRPC ErrorMap for interop.\n * Tagged error classes are converted to their equivalent ErrorMapItem format.\n */\nexport function effectErrorMapToErrorMap<T extends EffectErrorMap>(\n errorMap: T | undefined,\n): ErrorMap {\n const result: ErrorMap = {};\n\n if (!errorMap) {\n return result;\n }\n\n for (const [code, ClassOrErrorItem] of Object.entries(errorMap)) {\n if (!ClassOrErrorItem) {\n continue;\n }\n\n if (isORPCTaggedErrorClass(ClassOrErrorItem)) {\n const error = new ClassOrErrorItem().toORPCError();\n\n // For tagged errors, we create a minimal entry\n // The actual validation will be handled by the tagged error class\n result[code] = {\n status: error.status,\n message: error.message,\n data: error.data,\n };\n } else {\n result[code] = ClassOrErrorItem;\n }\n }\n\n return result;\n}\n"],"mappings":"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","names":["mergeMeta","mergeRoute","ORPCError","addMiddleware","decorateMiddleware","decorateMiddleware","addMiddleware","mergeMeta","mergeRoute","ORPCError"]}
1
+ {"version":3,"sources":["../src/effect-builder.ts","../src/effect-procedure.ts","../src/tagged-error.ts"],"sourcesContent":["import type { ORPCErrorCode } from \"@orpc/client\";\nimport type {\n AnySchema,\n ErrorMap,\n InferSchemaOutput,\n Meta,\n Route,\n Schema,\n} from \"@orpc/contract\";\nimport type {\n AnyMiddleware,\n BuilderDef,\n Context,\n MapInputMiddleware,\n MergedCurrentContext,\n MergedInitialContext,\n Middleware,\n ORPCErrorConstructorMap,\n ProcedureHandlerOptions,\n} from \"@orpc/server\";\nimport type { IntersectPick } from \"@orpc/shared\";\nimport type { ManagedRuntime } from \"effect\";\nimport type { YieldWrap } from \"effect/Utils\";\n\nimport {\n mergeErrorMap,\n mergeMeta,\n mergeRoute,\n ORPCError,\n} from \"@orpc/contract\";\nimport {\n addMiddleware,\n Builder,\n decorateMiddleware,\n fallbackConfig,\n} from \"@orpc/server\";\nimport { Cause, Effect, Exit } from \"effect\";\n\nimport type {\n EffectErrorConstructorMap,\n EffectErrorMap,\n EffectErrorMapToUnion,\n MergedEffectErrorMap,\n} from \"./tagged-error\";\n\nimport { EffectDecoratedProcedure } from \"./effect-procedure\";\nimport {\n createEffectErrorConstructorMap,\n effectErrorMapToErrorMap,\n isORPCTaggedError,\n} from \"./tagged-error\";\n\n/**\n * Captures the stack trace at the call site for better error reporting in spans.\n * This is called at procedure definition time to capture where the procedure was defined.\n *\n * @returns A function that lazily extracts the relevant stack frame\n */\nexport function addSpanStackTrace(): () => string | undefined {\n const ErrorConstructor = Error as typeof Error & {\n stackTraceLimit?: number;\n };\n const limit = ErrorConstructor.stackTraceLimit;\n ErrorConstructor.stackTraceLimit = 3;\n const traceError = new Error();\n ErrorConstructor.stackTraceLimit = limit;\n let cache: false | string = false;\n return () => {\n if (cache !== false) {\n return cache;\n }\n if (traceError.stack !== undefined) {\n const stack = traceError.stack.split(\"\\n\");\n if (stack[3] !== undefined) {\n cache = stack[3].trim();\n return cache;\n }\n }\n };\n}\n\n/**\n * Configuration for Effect span tracing.\n */\nexport interface EffectSpanConfig {\n /**\n * The name of the span for telemetry.\n */\n name: string;\n /**\n * Function to lazily capture the stack trace at definition time.\n */\n captureStackTrace: () => string | undefined;\n}\n\n/**\n * Options passed to the Effect procedure handler.\n */\nexport interface EffectProcedureHandlerOptions<\n TCurrentContext extends Context,\n TInput,\n TEffectErrorMap extends EffectErrorMap,\n TMeta extends Meta,\n> extends Omit<\n ProcedureHandlerOptions<\n TCurrentContext,\n TInput,\n ORPCErrorConstructorMap<any>,\n TMeta\n >,\n \"errors\"\n> {\n errors: EffectErrorConstructorMap<TEffectErrorMap>;\n}\n\n/**\n * Handler type for Effect procedures.\n * The handler receives procedure options and returns an Effect.\n */\nexport type EffectProcedureHandler<\n TCurrentContext extends Context,\n TInput,\n THandlerOutput,\n TEffectErrorMap extends EffectErrorMap,\n TRequirementsProvided,\n TMeta extends Meta,\n> = (\n opt: EffectProcedureHandlerOptions<\n TCurrentContext,\n TInput,\n TEffectErrorMap,\n TMeta\n >,\n) => Generator<\n YieldWrap<\n Effect.Effect<\n any,\n | EffectErrorMapToUnion<TEffectErrorMap>\n | ORPCError<ORPCErrorCode, unknown>,\n TRequirementsProvided\n >\n >,\n THandlerOutput,\n never\n>;\n\n/**\n * Extended builder definition that includes the Effect ManagedRuntime.\n */\nexport interface EffectBuilderDef<\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TEffectErrorMap extends EffectErrorMap,\n TMeta extends Meta,\n TRequirementsProvided,\n TRuntimeError,\n> extends BuilderDef<TInputSchema, TOutputSchema, ErrorMap, TMeta> {\n runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>;\n /**\n * Optional span configuration for Effect tracing.\n */\n spanConfig?: EffectSpanConfig;\n /**\n * Effect-extended error map that supports both traditional errors and tagged errors.\n */\n effectErrorMap: TEffectErrorMap;\n}\n\n/**\n * Effect-native procedure builder that wraps an oRPC Builder instance\n * and adds Effect-specific capabilities while preserving Effect error\n * and requirements types.\n */\nexport class EffectBuilder<\n TInitialContext extends Context,\n TCurrentContext extends Context,\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TEffectErrorMap extends EffectErrorMap,\n TMeta extends Meta,\n TRequirementsProvided,\n TRuntimeError,\n> {\n \"~orpc\": EffectBuilderDef<\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >;\n\n constructor(\n def: EffectBuilderDef<\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >,\n ) {\n this[\"~orpc\"] = def;\n }\n\n /**\n * Adds type-safe custom errors.\n * Supports both traditional oRPC error definitions and ORPCTaggedError classes.\n *\n * @example\n * ```ts\n * // Traditional format\n * builder.errors({ BAD_REQUEST: { status: 400, message: 'Bad request' } })\n *\n * // Tagged error class\n * builder.errors({ USER_NOT_FOUND: UserNotFoundError })\n *\n * // Mixed\n * builder.errors({\n * BAD_REQUEST: { status: 400 },\n * USER_NOT_FOUND: UserNotFoundError,\n * })\n * ```\n *\n * @see {@link https://orpc.dev/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}\n */\n errors<U extends EffectErrorMap>(\n errors: U,\n ): EffectBuilder<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n MergedEffectErrorMap<TEffectErrorMap, U>,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectBuilder({\n ...this[\"~orpc\"],\n errorMap: mergeErrorMap(\n this[\"~orpc\"].errorMap,\n effectErrorMapToErrorMap(errors),\n ),\n effectErrorMap: {\n ...this[\"~orpc\"].effectErrorMap,\n ...errors,\n },\n });\n }\n\n /**\n * Uses a middleware to modify the context or improve the pipeline.\n *\n * @info Supports both normal middleware and inline middleware implementations.\n * @note The current context must be satisfy middleware dependent-context\n * @see {@link https://orpc.dev/docs/middleware Middleware Docs}\n */\n use<\n UOutContext extends IntersectPick<TCurrentContext, UOutContext>,\n UInContext extends Context = TCurrentContext,\n >(\n middleware: Middleware<\n UInContext | TCurrentContext,\n UOutContext,\n unknown,\n unknown,\n ORPCErrorConstructorMap<ErrorMap>,\n TMeta\n >,\n ): EffectBuilder<\n MergedInitialContext<TInitialContext, UInContext, TCurrentContext>,\n MergedCurrentContext<TCurrentContext, UOutContext>,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >;\n\n use(\n middleware: AnyMiddleware,\n mapInput?: MapInputMiddleware<any, any>,\n ): EffectBuilder<any, any, any, any, any, any, any, any> {\n const mapped = mapInput\n ? decorateMiddleware(middleware).mapInput(mapInput)\n : middleware;\n\n return new EffectBuilder({\n ...this[\"~orpc\"],\n middlewares: addMiddleware(this[\"~orpc\"].middlewares, mapped),\n });\n }\n\n /**\n * Sets or updates the metadata.\n * The provided metadata is spared-merged with any existing metadata.\n *\n * @see {@link https://orpc.dev/docs/metadata Metadata Docs}\n */\n meta(\n meta: TMeta,\n ): EffectBuilder<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectBuilder({\n ...this[\"~orpc\"],\n meta: mergeMeta(this[\"~orpc\"].meta, meta),\n });\n }\n\n /**\n * Sets or updates the route definition.\n * The provided route is spared-merged with any existing route.\n * This option is typically relevant when integrating with OpenAPI.\n *\n * @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}\n * @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}\n */\n route(\n route: Route,\n ): EffectBuilder<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectBuilder({\n ...this[\"~orpc\"],\n route: mergeRoute(this[\"~orpc\"].route, route),\n });\n }\n\n /**\n * Defines the input validation schema.\n *\n * @see {@link https://orpc.dev/docs/procedure#input-output-validation Input Validation Docs}\n */\n input<USchema extends AnySchema>(\n schema: USchema,\n ): EffectBuilder<\n TInitialContext,\n TCurrentContext,\n USchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectBuilder({\n ...this[\"~orpc\"],\n inputSchema: schema,\n inputValidationIndex:\n fallbackConfig(\n \"initialInputValidationIndex\",\n this[\"~orpc\"].config.initialInputValidationIndex,\n ) + this[\"~orpc\"].middlewares.length,\n });\n }\n\n /**\n * Defines the output validation schema.\n *\n * @see {@link https://orpc.dev/docs/procedure#input-output-validation Output Validation Docs}\n */\n output<USchema extends AnySchema>(\n schema: USchema,\n ): EffectBuilder<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n USchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectBuilder({\n ...this[\"~orpc\"],\n outputSchema: schema,\n outputValidationIndex:\n fallbackConfig(\n \"initialOutputValidationIndex\",\n this[\"~orpc\"].config.initialOutputValidationIndex,\n ) + this[\"~orpc\"].middlewares.length,\n });\n }\n\n /**\n * Adds a traceable span to the procedure for telemetry.\n * The span name is used for Effect tracing via `Effect.withSpan`.\n * Stack trace is captured at the call site for better error reporting.\n *\n * @param spanName - The name of the span for telemetry (e.g., 'users.getUser')\n * @returns An EffectBuilder with span tracing configured\n *\n * @example\n * ```ts\n * const getUser = effectOs\n * .input(z.object({ id: z.string() }))\n * .traced('users.getUser')\n * .effect(function* ({ input }) {\n * const userService = yield* UserService\n * return yield* userService.findById(input.id)\n * })\n * ```\n */\n traced(\n spanName: string,\n ): EffectBuilder<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectBuilder({\n ...this[\"~orpc\"],\n spanConfig: {\n name: spanName,\n captureStackTrace: addSpanStackTrace(),\n },\n });\n }\n\n /**\n * Defines the handler of the procedure using an Effect.\n * The Effect is executed using the ManagedRuntime provided during builder creation.\n * The effect is automatically wrapped with `Effect.withSpan`.\n *\n * @see {@link https://orpc.dev/docs/procedure Procedure Docs}\n */\n effect<UFuncOutput>(\n effectFn: EffectProcedureHandler<\n TCurrentContext,\n InferSchemaOutput<TInputSchema>,\n UFuncOutput,\n TEffectErrorMap,\n TRequirementsProvided,\n TMeta\n >,\n ): EffectDecoratedProcedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n Schema<UFuncOutput, UFuncOutput>,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n const { runtime, spanConfig } = this[\"~orpc\"];\n // Capture stack trace at definition time for default tracing\n const defaultCaptureStackTrace = addSpanStackTrace();\n return new EffectDecoratedProcedure({\n ...this[\"~orpc\"],\n handler: async (opts) => {\n const effectOpts: EffectProcedureHandlerOptions<\n TCurrentContext,\n InferSchemaOutput<TInputSchema>,\n TEffectErrorMap,\n TMeta\n > = {\n context: opts.context,\n input: opts.input,\n path: opts.path,\n procedure: opts.procedure,\n signal: opts.signal,\n lastEventId: opts.lastEventId,\n errors: createEffectErrorConstructorMap(this[\"~orpc\"].effectErrorMap),\n };\n const spanName = spanConfig?.name ?? opts.path.join(\".\");\n const captureStackTrace =\n spanConfig?.captureStackTrace ?? defaultCaptureStackTrace;\n const resolver = Effect.fnUntraced(effectFn);\n const tracedEffect = Effect.withSpan(resolver(effectOpts), spanName, {\n captureStackTrace,\n });\n const exit = await runtime.runPromiseExit(tracedEffect, {\n signal: opts.signal,\n });\n\n if (Exit.isFailure(exit)) {\n throw Cause.match(exit.cause, {\n onDie(defect) {\n return new ORPCError(\"INTERNAL_SERVER_ERROR\", {\n cause: defect,\n });\n },\n onFail(error) {\n if (isORPCTaggedError(error)) {\n return error.toORPCError();\n }\n if (error instanceof ORPCError) {\n return error;\n }\n return new ORPCError(\"INTERNAL_SERVER_ERROR\", {\n cause: error,\n });\n },\n onInterrupt(fiberId) {\n return new ORPCError(\"INTERNAL_SERVER_ERROR\", {\n cause: new Error(`${fiberId} Interrupted`),\n });\n },\n onSequential(left) {\n return left;\n },\n onEmpty: new ORPCError(\"INTERNAL_SERVER_ERROR\", {\n cause: new Error(\"Unknown error\"),\n }),\n onParallel(left) {\n return left;\n },\n });\n }\n\n return exit.value;\n },\n });\n }\n}\n\n/**\n * Any oRPC builder-like object that has the `~orpc` definition property.\n * This includes Builder, BuilderWithMiddlewares, ProcedureBuilder, etc.\n */\nexport interface AnyBuilderLike<\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TErrorMap extends ErrorMap,\n TMeta extends Meta,\n> {\n \"~orpc\": BuilderDef<TInputSchema, TOutputSchema, TErrorMap, TMeta>;\n}\n\n/**\n * Creates an Effect-aware procedure builder with the specified ManagedRuntime.\n * Uses the default `os` builder from `@orpc/server`.\n *\n * @param runtime - The ManagedRuntime that provides services for Effect procedures\n * @returns An EffectBuilder instance for creating Effect-native procedures\n *\n * @example\n * ```ts\n * import { makeEffectORPC } from '@orpc/effect'\n * import { Effect, Layer, ManagedRuntime } from 'effect'\n *\n * const runtime = ManagedRuntime.make(Layer.empty)\n * const effectOs = makeEffectORPC(runtime)\n *\n * const hello = effectOs.effect(() => Effect.succeed('Hello!'))\n * ```\n */\nexport function makeEffectORPC<TRequirementsProvided, TRuntimeError>(\n runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>,\n): EffectBuilder<\n Context,\n Context,\n Schema<unknown, unknown>,\n Schema<unknown, unknown>,\n Record<never, never>,\n Record<never, never>,\n TRequirementsProvided,\n TRuntimeError\n>;\n\n/**\n * Creates an Effect-aware procedure builder by wrapping an existing oRPC Builder\n * with the specified ManagedRuntime.\n *\n * @param runtime - The ManagedRuntime that provides services for Effect procedures\n * @param builder - The oRPC Builder instance to wrap (e.g., a customized `os`)\n * @returns An EffectBuilder instance that extends the original builder with Effect support\n *\n * @example\n * ```ts\n * import { makeEffectORPC } from '@orpc/effect'\n * import { os } from '@orpc/server'\n * import { Effect, Layer, ManagedRuntime } from 'effect'\n *\n * // Create a customized builder\n * const authedOs = os.use(authMiddleware)\n *\n * // Wrap it with Effect support\n * const runtime = ManagedRuntime.make(UserServiceLive)\n * const effectOs = makeEffectORPC(runtime, authedOs)\n *\n * const getUser = effectOs\n * .input(z.object({ id: z.string() }))\n * .effect(\n * Effect.fn(function* ({ input }) {\n * const userService = yield* UserService\n * return yield* userService.findById(input.id)\n * })\n * )\n * ```\n */\nexport function makeEffectORPC<\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TErrorMap extends ErrorMap,\n TMeta extends Meta,\n TRequirementsProvided,\n TRuntimeError,\n>(\n runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>,\n builder: AnyBuilderLike<TInputSchema, TOutputSchema, TErrorMap, TMeta>,\n): EffectBuilder<\n Context,\n Context,\n TInputSchema,\n TOutputSchema,\n TErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n>;\n\nexport function makeEffectORPC<\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TErrorMap extends ErrorMap,\n TMeta extends Meta,\n TRequirementsProvided,\n TRuntimeError,\n>(\n runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>,\n builder?: AnyBuilderLike<TInputSchema, TOutputSchema, TErrorMap, TMeta>,\n): EffectBuilder<\n Context,\n Context,\n TInputSchema,\n TOutputSchema,\n TErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n> {\n const resolvedBuilder =\n builder ?? emptyBuilder<TInputSchema, TOutputSchema, TErrorMap, TMeta>();\n return new EffectBuilder({\n ...resolvedBuilder[\"~orpc\"],\n effectErrorMap: resolvedBuilder[\"~orpc\"].errorMap,\n runtime,\n });\n}\n\nfunction emptyBuilder<\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TErrorMap extends ErrorMap,\n TMeta extends Meta,\n>() {\n return new Builder<\n Record<never, never>,\n Record<never, never>,\n TInputSchema,\n TOutputSchema,\n TErrorMap,\n TMeta\n >({\n config: {},\n route: {},\n meta: {} as TMeta,\n errorMap: {} as TErrorMap,\n inputValidationIndex: fallbackConfig(\"initialInputValidationIndex\"),\n outputValidationIndex: fallbackConfig(\"initialOutputValidationIndex\"),\n middlewares: [],\n dedupeLeadingMiddlewares: true,\n });\n}\n","import type { ClientContext } from \"@orpc/client\";\nimport type {\n AnySchema,\n ErrorMap,\n InferSchemaInput,\n InferSchemaOutput,\n Meta,\n Route,\n} from \"@orpc/contract\";\nimport type {\n AnyMiddleware,\n Context,\n CreateProcedureClientOptions,\n MapInputMiddleware,\n MergedCurrentContext,\n MergedInitialContext,\n Middleware,\n ORPCErrorConstructorMap,\n ProcedureActionableClient,\n ProcedureClient,\n ProcedureDef,\n} from \"@orpc/server\";\nimport type { IntersectPick, MaybeOptionalOptions } from \"@orpc/shared\";\nimport type { ManagedRuntime } from \"effect\";\n\nimport { mergeMeta, mergeRoute } from \"@orpc/contract\";\nimport {\n addMiddleware,\n createActionableClient,\n createProcedureClient,\n decorateMiddleware,\n Procedure,\n} from \"@orpc/server\";\n\nimport type { EffectErrorMap, MergedEffectErrorMap } from \"./tagged-error\";\n\nimport { effectErrorMapToErrorMap } from \"./tagged-error\";\n\n/**\n * Extended procedure definition that includes the Effect ManagedRuntime.\n */\nexport interface EffectProcedureDef<\n TInitialContext extends Context,\n TCurrentContext extends Context,\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TEffectErrorMap extends EffectErrorMap,\n TMeta extends Meta,\n TRequirementsProvided,\n TRuntimeError,\n> extends ProcedureDef<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n ErrorMap,\n TMeta\n> {\n runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>;\n effectErrorMap: TEffectErrorMap;\n}\n\n/**\n * An Effect-native decorated procedure that preserves Effect error and requirements types.\n *\n * This class extends Procedure with additional type parameters for Effect-specific\n * type information, allowing full type inference of Effect errors and requirements.\n */\nexport class EffectDecoratedProcedure<\n TInitialContext extends Context,\n TCurrentContext extends Context,\n TInputSchema extends AnySchema,\n TOutputSchema extends AnySchema,\n TEffectErrorMap extends EffectErrorMap,\n TMeta extends Meta,\n TRequirementsProvided,\n TRuntimeError,\n> extends Procedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n ErrorMap,\n TMeta\n> {\n declare \"~orpc\": EffectProcedureDef<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >;\n\n constructor(\n def: EffectProcedureDef<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >,\n ) {\n super(def);\n }\n\n /**\n * Adds type-safe custom errors.\n * Supports both traditional oRPC error definitions and ORPCTaggedError classes.\n *\n * @see {@link https://orpc.dev/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}\n */\n errors<U extends EffectErrorMap>(\n errors: U,\n ): EffectDecoratedProcedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n MergedEffectErrorMap<TEffectErrorMap, U>,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n const newEffectErrorMap = { ...this[\"~orpc\"].effectErrorMap, ...errors };\n return new EffectDecoratedProcedure({\n ...this[\"~orpc\"],\n effectErrorMap: newEffectErrorMap,\n errorMap: effectErrorMapToErrorMap(newEffectErrorMap),\n });\n }\n\n /**\n * Sets or updates the metadata.\n * The provided metadata is spared-merged with any existing metadata.\n *\n * @see {@link https://orpc.dev/docs/metadata Metadata Docs}\n */\n meta(\n meta: TMeta,\n ): EffectDecoratedProcedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectDecoratedProcedure({\n ...this[\"~orpc\"],\n meta: mergeMeta(this[\"~orpc\"].meta, meta),\n });\n }\n\n /**\n * Sets or updates the route definition.\n * The provided route is spared-merged with any existing route.\n * This option is typically relevant when integrating with OpenAPI.\n *\n * @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}\n * @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}\n */\n route(\n route: Route,\n ): EffectDecoratedProcedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > {\n return new EffectDecoratedProcedure({\n ...this[\"~orpc\"],\n route: mergeRoute(this[\"~orpc\"].route, route),\n });\n }\n\n /**\n * Uses a middleware to modify the context or improve the pipeline.\n *\n * @info Supports both normal middleware and inline middleware implementations.\n * @info Pass second argument to map the input.\n * @note The current context must be satisfy middleware dependent-context\n * @see {@link https://orpc.dev/docs/middleware Middleware Docs}\n */\n use<\n UOutContext extends IntersectPick<TCurrentContext, UOutContext>,\n UInContext extends Context = TCurrentContext,\n >(\n middleware: Middleware<\n UInContext | TCurrentContext,\n UOutContext,\n InferSchemaOutput<TInputSchema>,\n InferSchemaInput<TOutputSchema>,\n ORPCErrorConstructorMap<ErrorMap>,\n TMeta\n >,\n ): EffectDecoratedProcedure<\n MergedInitialContext<TInitialContext, UInContext, TCurrentContext>,\n MergedCurrentContext<TCurrentContext, UOutContext>,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >;\n\n /**\n * Uses a middleware to modify the context or improve the pipeline.\n *\n * @info Supports both normal middleware and inline middleware implementations.\n * @info Pass second argument to map the input.\n * @note The current context must be satisfy middleware dependent-context\n * @see {@link https://orpc.dev/docs/middleware Middleware Docs}\n */\n use<\n UOutContext extends IntersectPick<TCurrentContext, UOutContext>,\n UInput,\n UInContext extends Context = TCurrentContext,\n >(\n middleware: Middleware<\n UInContext | TCurrentContext,\n UOutContext,\n UInput,\n InferSchemaInput<TOutputSchema>,\n ORPCErrorConstructorMap<ErrorMap>,\n TMeta\n >,\n mapInput: MapInputMiddleware<InferSchemaOutput<TInputSchema>, UInput>,\n ): EffectDecoratedProcedure<\n MergedInitialContext<TInitialContext, UInContext, TCurrentContext>,\n MergedCurrentContext<TCurrentContext, UOutContext>,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n >;\n\n use(\n middleware: AnyMiddleware,\n mapInput?: MapInputMiddleware<any, any>,\n ): EffectDecoratedProcedure<any, any, any, any, any, any, any, any> {\n const mapped = mapInput\n ? decorateMiddleware(middleware).mapInput(mapInput)\n : middleware;\n\n return new EffectDecoratedProcedure({\n ...this[\"~orpc\"],\n middlewares: addMiddleware(this[\"~orpc\"].middlewares, mapped),\n });\n }\n\n /**\n * Make this procedure callable (works like a function while still being a procedure).\n *\n * @see {@link https://orpc.dev/docs/client/server-side Server-side Client Docs}\n */\n callable<TClientContext extends ClientContext>(\n ...rest: MaybeOptionalOptions<\n CreateProcedureClientOptions<\n TInitialContext,\n TOutputSchema,\n ErrorMap,\n TMeta,\n TClientContext\n >\n >\n ): EffectDecoratedProcedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > &\n ProcedureClient<TClientContext, TInputSchema, TOutputSchema, ErrorMap> {\n const client: ProcedureClient<\n TClientContext,\n TInputSchema,\n TOutputSchema,\n ErrorMap\n > = createProcedureClient(this, ...rest);\n\n return new Proxy(client, {\n get: (target, key) => {\n return Reflect.has(this, key)\n ? Reflect.get(this, key)\n : Reflect.get(target, key);\n },\n has: (target, key) => {\n return Reflect.has(this, key) || Reflect.has(target, key);\n },\n }) as any;\n }\n\n /**\n * Make this procedure compatible with server action.\n *\n * @see {@link https://orpc.dev/docs/server-action Server Action Docs}\n */\n actionable(\n ...rest: MaybeOptionalOptions<\n CreateProcedureClientOptions<\n TInitialContext,\n TOutputSchema,\n ErrorMap,\n TMeta,\n Record<never, never>\n >\n >\n ): EffectDecoratedProcedure<\n TInitialContext,\n TCurrentContext,\n TInputSchema,\n TOutputSchema,\n TEffectErrorMap,\n TMeta,\n TRequirementsProvided,\n TRuntimeError\n > &\n ProcedureActionableClient<TInputSchema, TOutputSchema, ErrorMap> {\n const action: ProcedureActionableClient<\n TInputSchema,\n TOutputSchema,\n ErrorMap\n > = createActionableClient(createProcedureClient(this, ...rest));\n\n return new Proxy(action, {\n get: (target, key) => {\n return Reflect.has(this, key)\n ? Reflect.get(this, key)\n : Reflect.get(target, key);\n },\n has: (target, key) => {\n return Reflect.has(this, key) || Reflect.has(target, key);\n },\n }) as any;\n }\n}\n","import type {\n ORPCErrorCode,\n ORPCErrorJSON,\n ORPCErrorOptions,\n} from \"@orpc/client\";\nimport type { AnySchema, ErrorMap, ErrorMapItem } from \"@orpc/contract\";\nimport type { ORPCErrorConstructorMapItemOptions } from \"@orpc/server\";\nimport type { MaybeOptionalOptions } from \"@orpc/shared\";\nimport type { Pipeable, Types } from \"effect\";\nimport type * as Cause from \"effect/Cause\";\nimport type * as Effect from \"effect/Effect\";\n\nimport {\n fallbackORPCErrorMessage,\n fallbackORPCErrorStatus,\n isORPCErrorStatus,\n ORPCError,\n} from \"@orpc/client\";\nimport { resolveMaybeOptionalOptions } from \"@orpc/shared\";\nimport * as Data from \"effect/Data\";\n\n/**\n * Symbol to access the underlying ORPCError instance\n */\nexport const ORPCErrorSymbol: unique symbol = Symbol.for(\n \"@orpc/effect/ORPCTaggedError\",\n);\n\n/**\n * Instance type for ORPCTaggedError that combines YieldableError with ORPCError properties\n */\nexport interface ORPCTaggedErrorInstance<\n TTag extends string,\n TCode extends ORPCErrorCode,\n TData,\n>\n extends Cause.YieldableError, Pipeable.Pipeable {\n readonly _tag: TTag;\n readonly code: TCode;\n readonly status: number;\n readonly data: TData;\n readonly defined: boolean;\n readonly [ORPCErrorSymbol]: ORPCError<TCode, TData>;\n\n toJSON(): ORPCErrorJSON<TCode, TData> & { _tag: TTag };\n toORPCError(): ORPCError<TCode, TData>;\n commit(): Effect.Effect<never, this, never>;\n}\n\n/**\n * Options for creating an ORPCTaggedError\n */\nexport type ORPCTaggedErrorOptions<TData> = Omit<\n ORPCErrorOptions<TData>,\n \"defined\"\n> & { defined?: boolean };\n\n/**\n * Constructor type for ORPCTaggedError classes\n */\nexport interface ORPCTaggedErrorClass<\n TTag extends string,\n TCode extends ORPCErrorCode,\n TData,\n> {\n readonly _tag: TTag;\n readonly code: TCode;\n new (\n ...args: MaybeOptionalOptions<ORPCTaggedErrorOptions<TData>>\n ): ORPCTaggedErrorInstance<TTag, TCode, TData>;\n}\n\n/**\n * Type helper to infer the ORPCError type from an ORPCTaggedError\n */\nexport type InferORPCError<T> =\n T extends ORPCTaggedErrorInstance<string, infer TCode, infer TData>\n ? ORPCError<TCode, TData>\n : never;\n\n/**\n * Any ORPCTaggedErrorClass\n * Uses `...args: any[]` for the constructor to accept any tagged error class,\n * regardless of whether TData requires options to be provided.\n */\nexport type AnyORPCTaggedErrorClass = {\n readonly _tag: string;\n readonly code: ORPCErrorCode;\n new (...args: any[]): ORPCTaggedErrorInstance<string, ORPCErrorCode, any>;\n};\n\n/**\n * Check if a value is an ORPCTaggedErrorClass (constructor)\n */\nexport function isORPCTaggedErrorClass(\n value: unknown,\n): value is AnyORPCTaggedErrorClass {\n return (\n typeof value === \"function\" &&\n \"_tag\" in value &&\n \"code\" in value &&\n typeof value._tag === \"string\" &&\n typeof value.code === \"string\"\n );\n}\n\n/**\n * Check if a value is an ORPCTaggedError instance\n */\nexport function isORPCTaggedError(\n value: unknown,\n): value is ORPCTaggedErrorInstance<string, ORPCErrorCode, unknown> {\n return (\n typeof value === \"object\" && value !== null && ORPCErrorSymbol in value\n );\n}\n\n/**\n * Converts a PascalCase or camelCase string to CONSTANT_CASE.\n * e.g., \"UserNotFoundError\" -> \"USER_NOT_FOUND_ERROR\"\n */\nfunction toConstantCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, \"$1_$2\")\n .replace(/([A-Z])([A-Z][a-z])/g, \"$1_$2\")\n .toUpperCase();\n}\n\n// Type-level conversion: split on capital letters and join with underscore\ntype SplitOnCapital<\n S extends string,\n Acc extends string = \"\",\n> = S extends `${infer Head}${infer Tail}`\n ? Head extends Uppercase<Head>\n ? Head extends Lowercase<Head>\n ? SplitOnCapital<Tail, `${Acc}${Head}`>\n : Acc extends \"\"\n ? SplitOnCapital<Tail, Head>\n : `${Acc}_${SplitOnCapital<Tail, Head>}`\n : SplitOnCapital<Tail, `${Acc}${Uppercase<Head>}`>\n : Acc;\n\n/**\n * Converts a tag name to an error code in CONSTANT_CASE.\n */\nexport type TagToCode<TTag extends string> = SplitOnCapital<TTag>;\n\n/**\n * Creates a tagged error class that combines Effect's YieldableError with ORPCError.\n *\n * This allows you to create errors that:\n * - Can be yielded in Effect generators (`yield* myError`)\n * - Have all ORPCError properties (code, status, data, defined)\n * - Can be converted to a plain ORPCError for oRPC handlers\n *\n * The returned factory function takes:\n * - `tag` - The unique tag for this error type (used for discriminated unions)\n * - `codeOrOptions` - Optional ORPC error code or options. If omitted, code defaults to CONSTANT_CASE of tag\n * - `defaultOptions` - Optional default options for status and message (when code is provided)\n *\n * @example\n * ```ts\n * import { ORPCTaggedError } from '@orpc/effect'\n * import { Effect } from 'effect'\n *\n * // Define a custom error (code defaults to 'USER_NOT_FOUND_ERROR')\n * class UserNotFoundError extends ORPCTaggedError<UserNotFoundError>()('UserNotFoundError') {}\n *\n * // With explicit code\n * class NotFoundError extends ORPCTaggedError<NotFoundError>()('NotFoundError', 'NOT_FOUND') {}\n *\n * // Use in an Effect\n * const getUser = (id: string) => Effect.gen(function* () {\n * const user = yield* findUser(id)\n * if (!user) {\n * return yield* new UserNotFoundError({ data: { userId: id } })\n * }\n * return user\n * })\n *\n * // With custom data type\n * class ValidationError extends ORPCTaggedError<ValidationError, { fields: string[] }>()('ValidationError', 'BAD_REQUEST') {}\n *\n * // With options only (code defaults to 'VALIDATION_ERROR')\n * class ValidationError2 extends ORPCTaggedError<ValidationError2, { fields: string[] }>()(\n * 'ValidationError2',\n * { message: 'Validation failed' }\n * ) {}\n * ```\n */\n/**\n * Return type for the factory function with overloads\n */\ninterface ORPCTaggedErrorFactory<Self, TData> {\n // Overload 1: tag only (code defaults to CONSTANT_CASE of tag)\n <TTag extends string>(\n tag: TTag,\n ): Types.Equals<Self, unknown> extends true\n ? `Missing \\`Self\\` generic - use \\`class MyError extends ORPCTaggedError<MyError>()(tag) {}\\``\n : ORPCTaggedErrorClass<TTag, TagToCode<TTag>, TData>;\n\n // Overload 2: tag + options (code defaults to CONSTANT_CASE of tag)\n <TTag extends string>(\n tag: TTag,\n options: { status?: number; message?: string },\n ): Types.Equals<Self, unknown> extends true\n ? `Missing \\`Self\\` generic - use \\`class MyError extends ORPCTaggedError<MyError>()(tag, options) {}\\``\n : ORPCTaggedErrorClass<TTag, TagToCode<TTag>, TData>;\n\n // Overload 3: tag + explicit code\n <TTag extends string, TCode extends ORPCErrorCode>(\n tag: TTag,\n code: TCode,\n defaultOptions?: { status?: number; message?: string },\n ): Types.Equals<Self, unknown> extends true\n ? `Missing \\`Self\\` generic - use \\`class MyError extends ORPCTaggedError<MyError>()(tag, code) {}\\``\n : ORPCTaggedErrorClass<TTag, TCode, TData>;\n}\n\nexport function ORPCTaggedError<\n Self,\n TData = undefined,\n>(): ORPCTaggedErrorFactory<Self, TData> {\n const factory = <TTag extends string, TCode extends ORPCErrorCode>(\n tag: TTag,\n codeOrOptions?: TCode | { status?: number; message?: string },\n defaultOptions?: { status?: number; message?: string },\n ): ORPCTaggedErrorClass<TTag, TCode, TData> => {\n // Determine if second arg is code or options\n const isCodeProvided = typeof codeOrOptions === \"string\";\n const code = (\n isCodeProvided ? codeOrOptions : toConstantCase(tag)\n ) as TCode;\n const options = isCodeProvided ? defaultOptions : codeOrOptions;\n\n const defaultStatus = options?.status;\n const defaultMessage = options?.message;\n\n // Use Effect's TaggedError as the base - this handles all Effect internals\n // (YieldableError, type symbols, commit(), Symbol.iterator, pipe(), etc.)\n const BaseTaggedError = Data.TaggedError(tag) as unknown as new (args: {\n message?: string;\n cause?: unknown;\n code: TCode;\n status: number;\n data: TData;\n defined: boolean;\n }) => Cause.YieldableError & {\n readonly _tag: TTag;\n readonly code: TCode;\n readonly status: number;\n readonly data: TData;\n readonly defined: boolean;\n };\n\n class ORPCTaggedErrorBase extends BaseTaggedError {\n static readonly _tag = tag;\n static readonly code = code;\n\n readonly [ORPCErrorSymbol]: ORPCError<TCode, TData>;\n\n constructor(\n ...rest: MaybeOptionalOptions<ORPCTaggedErrorOptions<TData>>\n ) {\n const opts = resolveMaybeOptionalOptions(rest);\n const status = opts.status ?? defaultStatus;\n const inputMessage = opts.message ?? defaultMessage;\n\n if (status !== undefined && !isORPCErrorStatus(status)) {\n throw new globalThis.Error(\n \"[ORPCTaggedError] Invalid error status code.\",\n );\n }\n\n const finalStatus = fallbackORPCErrorStatus(code, status);\n const finalMessage = fallbackORPCErrorMessage(code, inputMessage);\n\n // Pass to Effect's TaggedError - it spreads these onto the instance\n super({\n message: finalMessage,\n cause: opts.cause,\n code,\n status: finalStatus,\n data: opts.data as TData,\n defined: opts.defined ?? true,\n });\n\n // Create the underlying ORPCError for interop\n this[ORPCErrorSymbol] = new ORPCError(code, {\n status: finalStatus,\n message: finalMessage,\n data: opts.data as TData,\n defined: this.defined,\n cause: opts.cause,\n });\n }\n\n /**\n * Converts this error to a plain ORPCError.\n * Useful when you need to return from an oRPC handler.\n */\n toORPCError(): ORPCError<TCode, TData> {\n return this[ORPCErrorSymbol];\n }\n\n override toJSON(): ORPCErrorJSON<TCode, TData> & { _tag: TTag } {\n return {\n _tag: this._tag,\n defined: this.defined,\n code: this.code,\n status: this.status,\n message: this.message,\n data: this.data,\n };\n }\n }\n\n return ORPCTaggedErrorBase as any;\n };\n\n return factory as ORPCTaggedErrorFactory<Self, TData>;\n}\n\n/**\n * Converts an ORPCTaggedError to a plain ORPCError.\n * Useful in handlers that need to throw ORPCError.\n *\n * @example\n * ```ts\n * const handler = effectOs.effect(function* () {\n * const result = yield* someOperation.pipe(\n * Effect.catchTag('UserNotFoundError', (e) =>\n * Effect.fail(toORPCError(e))\n * )\n * )\n * return result\n * })\n * ```\n */\nexport function toORPCError<TCode extends ORPCErrorCode, TData>(\n error: ORPCTaggedErrorInstance<string, TCode, TData>,\n): ORPCError<TCode, TData> {\n return error[ORPCErrorSymbol];\n}\n\n// ============================================================================\n// Extended Error Map Types for Effect\n// ============================================================================\n\n/**\n * An item in the EffectErrorMap - can be either a traditional ErrorMapItem or an ORPCTaggedErrorClass\n */\nexport type EffectErrorMapItem =\n | ErrorMapItem<AnySchema>\n | AnyORPCTaggedErrorClass;\n\n/**\n * Extended error map that supports both traditional oRPC errors and ORPCTaggedError classes.\n *\n * @example\n * ```ts\n * const errorMap = {\n * // Traditional format\n * BAD_REQUEST: { status: 400, message: 'Bad request' },\n *\n * // Tagged error class reference\n * USER_NOT_FOUND: UserNotFoundError,\n * } satisfies EffectErrorMap\n * ```\n */\nexport type EffectErrorMap = {\n [key in ORPCErrorCode]?: EffectErrorMapItem;\n};\n\n/**\n * Merges two EffectErrorMaps, with the second map taking precedence.\n */\nexport type MergedEffectErrorMap<\n T1 extends EffectErrorMap,\n T2 extends EffectErrorMap,\n> = T1 & T2;\n\n/**\n * Extracts the instance type from an EffectErrorMapItem\n */\nexport type EffectErrorMapItemToInstance<\n TCode extends ORPCErrorCode,\n T extends EffectErrorMapItem,\n> = T extends AnyORPCTaggedErrorClass\n ? InstanceType<T>\n : T extends { data?: infer TData }\n ? ORPCError<TCode, TData>\n : ORPCError<TCode, unknown>;\n\n/**\n * Converts an EffectErrorMap to a union of error instances.\n */\nexport type EffectErrorMapToUnion<T extends EffectErrorMap> = {\n [K in keyof T]: K extends ORPCErrorCode\n ? T[K] extends EffectErrorMapItem\n ? EffectErrorMapItemToInstance<K, T[K]>\n : never\n : never;\n}[keyof T];\n\n/**\n * Type for the error constructors available in Effect handlers.\n * For tagged errors, it's the class constructor itself.\n * For traditional errors, it's a function that creates ORPCError.\n */\nexport type EffectErrorConstructorMapItem<\n TCode extends ORPCErrorCode,\n T extends EffectErrorMapItem,\n> =\n T extends ORPCTaggedErrorClass<infer _TTag, TCode, infer TData>\n ? (\n ...args: MaybeOptionalOptions<ORPCTaggedErrorOptions<TData>>\n ) => ORPCTaggedErrorInstance<_TTag, TCode, TData>\n : T extends { data?: infer TData }\n ? (\n ...args: MaybeOptionalOptions<\n ORPCErrorConstructorMapItemOptions<TData>\n >\n ) => ORPCError<TCode, TData>\n : (\n ...args: MaybeOptionalOptions<\n ORPCErrorConstructorMapItemOptions<unknown>\n >\n ) => ORPCError<TCode, unknown>;\n\n/**\n * Constructor map for EffectErrorMap - provides typed error constructors for handlers.\n */\nexport type EffectErrorConstructorMap<T extends EffectErrorMap> = {\n [K in keyof T]: K extends ORPCErrorCode\n ? T[K] extends EffectErrorMapItem\n ? EffectErrorConstructorMapItem<K, T[K]>\n : never\n : never;\n};\n\n/**\n * Creates an error constructor map from an EffectErrorMap.\n * Tagged error classes are passed through directly.\n * Traditional error items become ORPCError factory functions.\n */\nexport function createEffectErrorConstructorMap<T extends EffectErrorMap>(\n errors: T | undefined,\n): EffectErrorConstructorMap<T> {\n const target = errors ?? ({} as T);\n const proxy = new Proxy(target, {\n get(proxyTarget, code) {\n if (typeof code !== \"string\") {\n return Reflect.get(proxyTarget, code);\n }\n\n const config = target[code];\n\n // If it's a tagged error class, create a class constructor function\n if (isORPCTaggedErrorClass(config)) {\n return (\n ...opts: MaybeOptionalOptions<ORPCTaggedErrorOptions<unknown>>\n ) => new config(...opts);\n }\n\n // Otherwise, create a factory function for ORPCError\n return (\n ...rest: MaybeOptionalOptions<\n Omit<ORPCErrorOptions<unknown>, \"defined\" | \"status\">\n >\n ) => {\n const options = resolveMaybeOptionalOptions(rest);\n return new ORPCError(code, {\n defined: Boolean(config),\n status: config?.status,\n message: options.message ?? config?.message,\n data: options.data,\n cause: options.cause,\n });\n };\n },\n });\n\n return proxy as EffectErrorConstructorMap<T>;\n}\n\n/**\n * Converts an EffectErrorMap to a standard oRPC ErrorMap for interop.\n * Tagged error classes are converted to their equivalent ErrorMapItem format.\n */\nexport function effectErrorMapToErrorMap<T extends EffectErrorMap>(\n errorMap: T | undefined,\n): ErrorMap {\n const result: ErrorMap = {};\n\n if (!errorMap) {\n return result;\n }\n\n for (const [code, ClassOrErrorItem] of Object.entries(errorMap)) {\n if (!ClassOrErrorItem) {\n continue;\n }\n\n if (isORPCTaggedErrorClass(ClassOrErrorItem)) {\n const error = new ClassOrErrorItem().toORPCError();\n\n // For tagged errors, we create a minimal entry\n // The actual validation will be handled by the tagged error class\n result[code] = {\n status: error.status,\n message: error.message,\n data: error.data,\n };\n } else {\n result[code] = ClassOrErrorItem;\n }\n }\n\n return result;\n}\n"],"mappings":";AAwBA;AAAA,EACE;AAAA,EACA,aAAAA;AAAA,EACA,cAAAC;AAAA,EACA,aAAAC;AAAA,OACK;AACP;AAAA,EACE,iBAAAC;AAAA,EACA;AAAA,EACA,sBAAAC;AAAA,EACA;AAAA,OACK;AACP,SAAS,OAAO,QAAQ,YAAY;;;ACXpC,SAAS,WAAW,kBAAkB;AACtC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACpBP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,mCAAmC;AAC5C,YAAY,UAAU;AAKf,IAAM,kBAAiC,uBAAO;AAAA,EACnD;AACF;AAoEO,SAAS,uBACd,OACkC;AAClC,SACE,OAAO,UAAU,cACjB,UAAU,SACV,UAAU,SACV,OAAO,MAAM,SAAS,YACtB,OAAO,MAAM,SAAS;AAE1B;AAKO,SAAS,kBACd,OACkE;AAClE,SACE,OAAO,UAAU,YAAY,UAAU,QAAQ,mBAAmB;AAEtE;AAMA,SAAS,eAAe,KAAqB;AAC3C,SAAO,IACJ,QAAQ,mBAAmB,OAAO,EAClC,QAAQ,wBAAwB,OAAO,EACvC,YAAY;AACjB;AA6FO,SAAS,kBAGyB;AACvC,QAAM,UAAU,CACd,KACA,eACA,mBAC6C;AAE7C,UAAM,iBAAiB,OAAO,kBAAkB;AAChD,UAAM,OACJ,iBAAiB,gBAAgB,eAAe,GAAG;AAErD,UAAM,UAAU,iBAAiB,iBAAiB;AAElD,UAAM,gBAAgB,SAAS;AAC/B,UAAM,iBAAiB,SAAS;AAIhC,UAAM,kBAAuB,iBAAY,GAAG;AAAA,IAe5C,MAAM,4BAA4B,gBAAgB;AAAA,MAChD,OAAgB,OAAO;AAAA,MACvB,OAAgB,OAAO;AAAA,MAEvB,CAAU,eAAe;AAAA,MAEzB,eACK,MACH;AACA,cAAM,OAAO,4BAA4B,IAAI;AAC7C,cAAM,SAAS,KAAK,UAAU;AAC9B,cAAM,eAAe,KAAK,WAAW;AAErC,YAAI,WAAW,UAAa,CAAC,kBAAkB,MAAM,GAAG;AACtD,gBAAM,IAAI,WAAW;AAAA,YACnB;AAAA,UACF;AAAA,QACF;AAEA,cAAM,cAAc,wBAAwB,MAAM,MAAM;AACxD,cAAM,eAAe,yBAAyB,MAAM,YAAY;AAGhE,cAAM;AAAA,UACJ,SAAS;AAAA,UACT,OAAO,KAAK;AAAA,UACZ;AAAA,UACA,QAAQ;AAAA,UACR,MAAM,KAAK;AAAA,UACX,SAAS,KAAK,WAAW;AAAA,QAC3B,CAAC;AAGD,aAAK,eAAe,IAAI,IAAI,UAAU,MAAM;AAAA,UAC1C,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,MAAM,KAAK;AAAA,UACX,SAAS,KAAK;AAAA,UACd,OAAO,KAAK;AAAA,QACd,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,cAAuC;AACrC,eAAO,KAAK,eAAe;AAAA,MAC7B;AAAA,MAES,SAAuD;AAC9D,eAAO;AAAA,UACL,MAAM,KAAK;AAAA,UACX,SAAS,KAAK;AAAA,UACd,MAAM,KAAK;AAAA,UACX,QAAQ,KAAK;AAAA,UACb,SAAS,KAAK;AAAA,UACd,MAAM,KAAK;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAkBO,SAAS,YACd,OACyB;AACzB,SAAO,MAAM,eAAe;AAC9B;AAuGO,SAAS,gCACd,QAC8B;AAC9B,QAAM,SAAS,UAAW,CAAC;AAC3B,QAAM,QAAQ,IAAI,MAAM,QAAQ;AAAA,IAC9B,IAAI,aAAa,MAAM;AACrB,UAAI,OAAO,SAAS,UAAU;AAC5B,eAAO,QAAQ,IAAI,aAAa,IAAI;AAAA,MACtC;AAEA,YAAM,SAAS,OAAO,IAAI;AAG1B,UAAI,uBAAuB,MAAM,GAAG;AAClC,eAAO,IACF,SACA,IAAI,OAAO,GAAG,IAAI;AAAA,MACzB;AAGA,aAAO,IACF,SAGA;AACH,cAAM,UAAU,4BAA4B,IAAI;AAChD,eAAO,IAAI,UAAU,MAAM;AAAA,UACzB,SAAS,QAAQ,MAAM;AAAA,UACvB,QAAQ,QAAQ;AAAA,UAChB,SAAS,QAAQ,WAAW,QAAQ;AAAA,UACpC,MAAM,QAAQ;AAAA,UACd,OAAO,QAAQ;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAMO,SAAS,yBACd,UACU;AACV,QAAM,SAAmB,CAAC;AAE1B,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,aAAW,CAAC,MAAM,gBAAgB,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAC/D,QAAI,CAAC,kBAAkB;AACrB;AAAA,IACF;AAEA,QAAI,uBAAuB,gBAAgB,GAAG;AAC5C,YAAM,QAAQ,IAAI,iBAAiB,EAAE,YAAY;AAIjD,aAAO,IAAI,IAAI;AAAA,QACb,QAAQ,MAAM;AAAA,QACd,SAAS,MAAM;AAAA,QACf,MAAM,MAAM;AAAA,MACd;AAAA,IACF,OAAO;AACL,aAAO,IAAI,IAAI;AAAA,IACjB;AAAA,EACF;AAEA,SAAO;AACT;;;ADpcO,IAAM,2BAAN,MAAM,kCASH,UAOR;AAAA,EAYA,YACE,KAUA;AACA,UAAM,GAAG;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OACE,QAUA;AACA,UAAM,oBAAoB,EAAE,GAAG,KAAK,OAAO,EAAE,gBAAgB,GAAG,OAAO;AACvE,WAAO,IAAI,0BAAyB;AAAA,MAClC,GAAG,KAAK,OAAO;AAAA,MACf,gBAAgB;AAAA,MAChB,UAAU,yBAAyB,iBAAiB;AAAA,IACtD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,KACE,MAUA;AACA,WAAO,IAAI,0BAAyB;AAAA,MAClC,GAAG,KAAK,OAAO;AAAA,MACf,MAAM,UAAU,KAAK,OAAO,EAAE,MAAM,IAAI;AAAA,IAC1C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MACE,OAUA;AACA,WAAO,IAAI,0BAAyB;AAAA,MAClC,GAAG,KAAK,OAAO;AAAA,MACf,OAAO,WAAW,KAAK,OAAO,EAAE,OAAO,KAAK;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA,EAkEA,IACE,YACA,UACkE;AAClE,UAAM,SAAS,WACX,mBAAmB,UAAU,EAAE,SAAS,QAAQ,IAChD;AAEJ,WAAO,IAAI,0BAAyB;AAAA,MAClC,GAAG,KAAK,OAAO;AAAA,MACf,aAAa,cAAc,KAAK,OAAO,EAAE,aAAa,MAAM;AAAA,IAC9D,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YACK,MAmBoE;AACvE,UAAM,SAKF,sBAAsB,MAAM,GAAG,IAAI;AAEvC,WAAO,IAAI,MAAM,QAAQ;AAAA,MACvB,KAAK,CAAC,QAAQ,QAAQ;AACpB,eAAO,QAAQ,IAAI,MAAM,GAAG,IACxB,QAAQ,IAAI,MAAM,GAAG,IACrB,QAAQ,IAAI,QAAQ,GAAG;AAAA,MAC7B;AAAA,MACA,KAAK,CAAC,QAAQ,QAAQ;AACpB,eAAO,QAAQ,IAAI,MAAM,GAAG,KAAK,QAAQ,IAAI,QAAQ,GAAG;AAAA,MAC1D;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cACK,MAmB8D;AACjE,UAAM,SAIF,uBAAuB,sBAAsB,MAAM,GAAG,IAAI,CAAC;AAE/D,WAAO,IAAI,MAAM,QAAQ;AAAA,MACvB,KAAK,CAAC,QAAQ,QAAQ;AACpB,eAAO,QAAQ,IAAI,MAAM,GAAG,IACxB,QAAQ,IAAI,MAAM,GAAG,IACrB,QAAQ,IAAI,QAAQ,GAAG;AAAA,MAC7B;AAAA,MACA,KAAK,CAAC,QAAQ,QAAQ;AACpB,eAAO,QAAQ,IAAI,MAAM,GAAG,KAAK,QAAQ,IAAI,QAAQ,GAAG;AAAA,MAC1D;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ADvSO,SAAS,oBAA8C;AAC5D,QAAM,mBAAmB;AAGzB,QAAM,QAAQ,iBAAiB;AAC/B,mBAAiB,kBAAkB;AACnC,QAAM,aAAa,IAAI,MAAM;AAC7B,mBAAiB,kBAAkB;AACnC,MAAI,QAAwB;AAC5B,SAAO,MAAM;AACX,QAAI,UAAU,OAAO;AACnB,aAAO;AAAA,IACT;AACA,QAAI,WAAW,UAAU,QAAW;AAClC,YAAM,QAAQ,WAAW,MAAM,MAAM,IAAI;AACzC,UAAI,MAAM,CAAC,MAAM,QAAW;AAC1B,gBAAQ,MAAM,CAAC,EAAE,KAAK;AACtB,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACF;AA8FO,IAAM,gBAAN,MAAM,eASX;AAAA,EACA;AAAA,EASA,YACE,KAQA;AACA,SAAK,OAAO,IAAI;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA,OACE,QAUA;AACA,WAAO,IAAI,eAAc;AAAA,MACvB,GAAG,KAAK,OAAO;AAAA,MACf,UAAU;AAAA,QACR,KAAK,OAAO,EAAE;AAAA,QACd,yBAAyB,MAAM;AAAA,MACjC;AAAA,MACA,gBAAgB;AAAA,QACd,GAAG,KAAK,OAAO,EAAE;AAAA,QACjB,GAAG;AAAA,MACL;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAgCA,IACE,YACA,UACuD;AACvD,UAAM,SAAS,WACXC,oBAAmB,UAAU,EAAE,SAAS,QAAQ,IAChD;AAEJ,WAAO,IAAI,eAAc;AAAA,MACvB,GAAG,KAAK,OAAO;AAAA,MACf,aAAaC,eAAc,KAAK,OAAO,EAAE,aAAa,MAAM;AAAA,IAC9D,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,KACE,MAUA;AACA,WAAO,IAAI,eAAc;AAAA,MACvB,GAAG,KAAK,OAAO;AAAA,MACf,MAAMC,WAAU,KAAK,OAAO,EAAE,MAAM,IAAI;AAAA,IAC1C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MACE,OAUA;AACA,WAAO,IAAI,eAAc;AAAA,MACvB,GAAG,KAAK,OAAO;AAAA,MACf,OAAOC,YAAW,KAAK,OAAO,EAAE,OAAO,KAAK;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MACE,QAUA;AACA,WAAO,IAAI,eAAc;AAAA,MACvB,GAAG,KAAK,OAAO;AAAA,MACf,aAAa;AAAA,MACb,sBACE;AAAA,QACE;AAAA,QACA,KAAK,OAAO,EAAE,OAAO;AAAA,MACvB,IAAI,KAAK,OAAO,EAAE,YAAY;AAAA,IAClC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OACE,QAUA;AACA,WAAO,IAAI,eAAc;AAAA,MACvB,GAAG,KAAK,OAAO;AAAA,MACf,cAAc;AAAA,MACd,uBACE;AAAA,QACE;AAAA,QACA,KAAK,OAAO,EAAE,OAAO;AAAA,MACvB,IAAI,KAAK,OAAO,EAAE,YAAY;AAAA,IAClC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,OACE,UAUA;AACA,WAAO,IAAI,eAAc;AAAA,MACvB,GAAG,KAAK,OAAO;AAAA,MACf,YAAY;AAAA,QACV,MAAM;AAAA,QACN,mBAAmB,kBAAkB;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OACE,UAiBA;AACA,UAAM,EAAE,SAAS,WAAW,IAAI,KAAK,OAAO;AAE5C,UAAM,2BAA2B,kBAAkB;AACnD,WAAO,IAAI,yBAAyB;AAAA,MAClC,GAAG,KAAK,OAAO;AAAA,MACf,SAAS,OAAO,SAAS;AACvB,cAAM,aAKF;AAAA,UACF,SAAS,KAAK;AAAA,UACd,OAAO,KAAK;AAAA,UACZ,MAAM,KAAK;AAAA,UACX,WAAW,KAAK;AAAA,UAChB,QAAQ,KAAK;AAAA,UACb,aAAa,KAAK;AAAA,UAClB,QAAQ,gCAAgC,KAAK,OAAO,EAAE,cAAc;AAAA,QACtE;AACA,cAAM,WAAW,YAAY,QAAQ,KAAK,KAAK,KAAK,GAAG;AACvD,cAAM,oBACJ,YAAY,qBAAqB;AACnC,cAAM,WAAW,OAAO,WAAW,QAAQ;AAC3C,cAAM,eAAe,OAAO,SAAS,SAAS,UAAU,GAAG,UAAU;AAAA,UACnE;AAAA,QACF,CAAC;AACD,cAAM,OAAO,MAAM,QAAQ,eAAe,cAAc;AAAA,UACtD,QAAQ,KAAK;AAAA,QACf,CAAC;AAED,YAAI,KAAK,UAAU,IAAI,GAAG;AACxB,gBAAM,MAAM,MAAM,KAAK,OAAO;AAAA,YAC5B,MAAM,QAAQ;AACZ,qBAAO,IAAIC,WAAU,yBAAyB;AAAA,gBAC5C,OAAO;AAAA,cACT,CAAC;AAAA,YACH;AAAA,YACA,OAAO,OAAO;AACZ,kBAAI,kBAAkB,KAAK,GAAG;AAC5B,uBAAO,MAAM,YAAY;AAAA,cAC3B;AACA,kBAAI,iBAAiBA,YAAW;AAC9B,uBAAO;AAAA,cACT;AACA,qBAAO,IAAIA,WAAU,yBAAyB;AAAA,gBAC5C,OAAO;AAAA,cACT,CAAC;AAAA,YACH;AAAA,YACA,YAAY,SAAS;AACnB,qBAAO,IAAIA,WAAU,yBAAyB;AAAA,gBAC5C,OAAO,IAAI,MAAM,GAAG,OAAO,cAAc;AAAA,cAC3C,CAAC;AAAA,YACH;AAAA,YACA,aAAa,MAAM;AACjB,qBAAO;AAAA,YACT;AAAA,YACA,SAAS,IAAIA,WAAU,yBAAyB;AAAA,cAC9C,OAAO,IAAI,MAAM,eAAe;AAAA,YAClC,CAAC;AAAA,YACD,WAAW,MAAM;AACf,qBAAO;AAAA,YACT;AAAA,UACF,CAAC;AAAA,QACH;AAEA,eAAO,KAAK;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAkGO,SAAS,eAQd,SACA,SAUA;AACA,QAAM,kBACJ,WAAW,aAA4D;AACzE,SAAO,IAAI,cAAc;AAAA,IACvB,GAAG,gBAAgB,OAAO;AAAA,IAC1B,gBAAgB,gBAAgB,OAAO,EAAE;AAAA,IACzC;AAAA,EACF,CAAC;AACH;AAEA,SAAS,eAKL;AACF,SAAO,IAAI,QAOT;AAAA,IACA,QAAQ,CAAC;AAAA,IACT,OAAO,CAAC;AAAA,IACR,MAAM,CAAC;AAAA,IACP,UAAU,CAAC;AAAA,IACX,sBAAsB,eAAe,6BAA6B;AAAA,IAClE,uBAAuB,eAAe,8BAA8B;AAAA,IACpE,aAAa,CAAC;AAAA,IACd,0BAA0B;AAAA,EAC5B,CAAC;AACH;","names":["mergeMeta","mergeRoute","ORPCError","addMiddleware","decorateMiddleware","decorateMiddleware","addMiddleware","mergeMeta","mergeRoute","ORPCError"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effect-orpc",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "keywords": [
5
5
  "effect",
6
6
  "orpc",
@@ -80,12 +80,14 @@ export type InferORPCError<T> =
80
80
 
81
81
  /**
82
82
  * Any ORPCTaggedErrorClass
83
+ * Uses `...args: any[]` for the constructor to accept any tagged error class,
84
+ * regardless of whether TData requires options to be provided.
83
85
  */
84
- export type AnyORPCTaggedErrorClass = ORPCTaggedErrorClass<
85
- string,
86
- ORPCErrorCode,
87
- any
88
- >;
86
+ export type AnyORPCTaggedErrorClass = {
87
+ readonly _tag: string;
88
+ readonly code: ORPCErrorCode;
89
+ new (...args: any[]): ORPCTaggedErrorInstance<string, ORPCErrorCode, any>;
90
+ };
89
91
 
90
92
  /**
91
93
  * Check if a value is an ORPCTaggedErrorClass (constructor)
@@ -411,7 +413,9 @@ export type EffectErrorConstructorMapItem<
411
413
  T extends EffectErrorMapItem,
412
414
  > =
413
415
  T extends ORPCTaggedErrorClass<infer _TTag, TCode, infer TData>
414
- ? ORPCTaggedErrorClass<_TTag, TCode, TData>
416
+ ? (
417
+ ...args: MaybeOptionalOptions<ORPCTaggedErrorOptions<TData>>
418
+ ) => ORPCTaggedErrorInstance<_TTag, TCode, TData>
415
419
  : T extends { data?: infer TData }
416
420
  ? (
417
421
  ...args: MaybeOptionalOptions<
@@ -452,9 +456,11 @@ export function createEffectErrorConstructorMap<T extends EffectErrorMap>(
452
456
 
453
457
  const config = target[code];
454
458
 
455
- // If it's a tagged error class, return it directly
459
+ // If it's a tagged error class, create a class constructor function
456
460
  if (isORPCTaggedErrorClass(config)) {
457
- return config;
461
+ return (
462
+ ...opts: MaybeOptionalOptions<ORPCTaggedErrorOptions<unknown>>
463
+ ) => new config(...opts);
458
464
  }
459
465
 
460
466
  // Otherwise, create a factory function for ORPCError
@@ -96,8 +96,11 @@ describe("createEffectErrorConstructorMap", () => {
96
96
 
97
97
  const constructorMap = createEffectErrorConstructorMap(errorMap);
98
98
 
99
- expect(constructorMap.USER_NOT_FOUND_ERROR).toBe(UserNotFoundError);
100
- expect(constructorMap.FORBIDDEN).toBe(PermissionDenied);
99
+ const userNotFoundError = constructorMap.USER_NOT_FOUND_ERROR();
100
+ expect(userNotFoundError).toBeInstanceOf(UserNotFoundError);
101
+
102
+ const forbiddenError = constructorMap.FORBIDDEN();
103
+ expect(forbiddenError).toBeInstanceOf(PermissionDenied);
101
104
  });
102
105
 
103
106
  it("should create ORPCError factory for traditional items", () => {
@@ -135,7 +138,7 @@ describe("createEffectErrorConstructorMap", () => {
135
138
  expect(badRequestError.message).toBe("Invalid input");
136
139
 
137
140
  // Tagged error class is passed through
138
- const userNotFoundError = new constructorMap.USER_NOT_FOUND_ERROR();
141
+ const userNotFoundError = constructorMap.USER_NOT_FOUND_ERROR();
139
142
  expect(isORPCTaggedError(userNotFoundError)).toBe(true);
140
143
  expect(userNotFoundError._tag).toBe("UserNotFoundError");
141
144
  });
@@ -253,7 +256,7 @@ describe("effectBuilder with EffectErrorMap", () => {
253
256
  // oxlint-disable-next-line require-yield
254
257
  .effect(function* ({ input, errors }) {
255
258
  if (input.id === "not-found") {
256
- return yield* Effect.fail(new errors.USER_NOT_FOUND_ERROR());
259
+ return yield* Effect.fail(errors.USER_NOT_FOUND_ERROR());
257
260
  }
258
261
  return yield* Effect.succeed({ id: input.id, name: "Test User" });
259
262
  });