---
url: /unthrown/api/orpc/server.md
---
[**@unthrown/orpc**](index.md)

***

[@unthrown/orpc](index.md) / server

# server

## Server

### ResultHandler

```ts
type ResultHandler<TCurrentContext, TInput, TOutput, TError, TErrorMap> = (opts, input) => 
  | Result<TOutput, TError>
  | Promise<Result<TOutput, TError>>
  | AsyncResult<TOutput, TError>;
```

Defined in: [server.ts:40](https://github.com/btravstack/unthrown/blob/f4578e4b398ad7f3913ba2dec0343621762bbb27/packages/orpc/src/server.ts#L40)

A procedure handler that speaks `Result`: same options as a plain oRPC
handler (`input`, `context`, `errors`, …), returning a
`Result<TOutput, TError>` — synchronous, promised, or as an
`AsyncResult`.

#### Type Parameters

| Type Parameter |
| ------ |
| `TCurrentContext` *extends* `Context` |
| `TInput` |
| `TOutput` |
| `TError` *extends* `AnyORPCError` |
| `TErrorMap` *extends* `ErrorMap` |

#### Parameters

| Parameter | Type |
| ------ | ------ |
| `opts` | `ProcedureHandlerOptions`<`TCurrentContext`, `TInput`, `ORPCErrorConstructorMap`<`TErrorMap`>> |
| `input` | `TInput` |

#### Returns

| `Result`<`TOutput`, `TError`>
| `Promise`<`Result`<`TOutput`, `TError`>>
| `AsyncResult`<`TOutput`, `TError`>

***

### handlerResult()

```ts
function handlerResult<TCurrentContext, TInput, TOutput, TError, TErrorMap>(handler): ProcedureHandler<TCurrentContext, TInput, TOutput, ORPCErrorConstructorMap<TErrorMap>>;
```

Defined in: [server.ts:94](https://github.com/btravstack/unthrown/blob/f4578e4b398ad7f3913ba2dec0343621762bbb27/packages/orpc/src/server.ts#L94)

Adapt a `Result`-returning handler into a plain oRPC procedure handler.

#### Type Parameters

| Type Parameter |
| ------ |
| `TCurrentContext` *extends* `Context` |
| `TInput` |
| `TOutput` |
| `TError` *extends* `AnyORPCError` |
| `TErrorMap` *extends* `ErrorMap` |

#### Parameters

| Parameter | Type | Description |
| ------ | ------ | ------ |
| `handler` | [`ResultHandler`](#resulthandler)<`TCurrentContext`, `TInput`, `TOutput`, `TError`, `TErrorMap`> | the `Result`-speaking handler to adapt. |

#### Returns

`ProcedureHandler`<`TCurrentContext`, `TInput`, `TOutput`, `ORPCErrorConstructorMap`<`TErrorMap`>>

#### Remarks

The elimination boundary of the server half: `Ok` becomes the procedure's
output; `Err` (constrained to `ORPCError` — build one with the injected
`errors.CODE(...)` constructors, or map a domain error via `mapErrCases` first)
is thrown, so a declared code reaches the client as a defined, typed error;
a `Defect` rethrows its original cause — oRPC collapses an opaque cause to
`INTERNAL_SERVER_ERROR`, but a bug stays a defect either way, never a
typed error. A cause that is itself an `ORPCError` (a downstream oRPC call
qualified as a defect) is wrapped in a plain `Error` first, so it too
answers `INTERNAL_SERVER_ERROR` instead of its own code and status.

Like `match` handlers, the callback may be `async` (an edge elimination is
exempt from the no-thenable rule): a rejection or throw inside it cannot
skip triage, because oRPC's own boundary already treats it as the defect
path.

#### Example

```ts
import { P } from "unthrown";
import { handlerResult } from "@unthrown/orpc/server";

const find = os
  .input(z.object({ id: z.string() }))
  .errors({ NOT_FOUND: {} })
  .handler(
    handlerResult(({ input, errors }) =>
      repo
        .findPlanet(input.id)
        .mapErrCases((matcher) =>
          matcher.with(P.tag("NotFound"), () => errors.NOT_FOUND()),
        ),
    ),
  );
```
