> ## Documentation Index
> Fetch the complete documentation index at: https://www.orionjs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Introduction

> Creating type-safe APIs with tRPC in Orionjs

Orionjs provides seamless integration with [tRPC](https://trpc.io/) for building end-to-end type-safe APIs. The `@orion-js/trpc` package offers decorators and utilities that work with Orionjs schemas and the service injection system.

## Installation

```bash theme={null}
pnpm add @orion-js/trpc @trpc/server superjson
```

## Key Features

* Full TypeScript type inference
* Integration with Orionjs schema validation
* Service injection support via `@Inject()`
* Compatible with the Orionjs component system

## Basic Setup

### 1. Create Procedures

Create a procedures class using the `@Procedures()` decorator:

```typescript theme={null}
// app/exampleComponent/controllers/trpc/ExampleProcedures/index.ts
import {Procedures, TQuery, TMutation, createTQuery, createTMutation} from '@orion-js/trpc'
import {Inject} from '@orion-js/services'
import {ExampleSchema} from 'app/exampleComponent/schemas/ExampleSchema'
import {ExampleService} from 'app/exampleComponent/services/ExampleService'

@Procedures()
export class ExampleProcedures {
  @Inject(() => ExampleService)
  private exampleService: ExampleService

  @TQuery()
  getExample = createTQuery({
    params: {exampleId: {type: String}},
    returns: ExampleSchema,
    resolve: async ({exampleId}) => {
      return await this.exampleService.getExample(exampleId)
    },
  })

  @TQuery()
  listExamples = createTQuery({
    returns: [ExampleSchema],
    resolve: async () => {
      return await this.exampleService.getExamples()
    },
  })

  @TMutation()
  createExample = createTMutation({
    params: {name: {type: String}},
    returns: {message: {type: String}},
    resolve: async ({name}) => {
      await this.exampleService.createExample(name)
      return {message: 'Created successfully'}
    },
  })
}
```

### 2. Register in a Component

Add your procedure classes to a component's `trpc` controllers:

```typescript theme={null}
// app/exampleComponent/index.ts
import {component} from '@orion-js/components'
import trpc from './controllers/trpc'

export default component({
  trpc,
  // ...other controllers
})
```

### 3. Set Up the tRPC Server

Create a local `t` config and mount routes with `registerTRPCRoute`:

```typescript theme={null}
// app/config/trpc/index.ts
import {initTRPC} from '@trpc/server'
import {
  defaultErrorFormatter,
  registerTRPCRoute,
  type TRPCContext,
} from '@orion-js/trpc'
import {logger} from '@orion-js/logger'
import type {TRPCRouterRecord} from '@trpc/server'
import {deserialize as superjsonDeserialize, serialize as superjsonSerialize} from 'superjson'

export const transformer = {
  serialize: superjsonSerialize,
  deserialize: superjsonDeserialize,
}

export const t = initTRPC.context<TRPCContext>().create({
  transformer,
  errorFormatter: defaultErrorFormatter,
})

export function startTrpc<T extends TRPCRouterRecord>(procedures: T) {
  const appRouter = t.router(procedures)
  registerTRPCRoute({appRouter, path: '/trpc'})

  logger.info('tRPC started at /trpc')
  return appRouter
}
```

Because you call `initTRPC.create()` directly, the router type reflects your configuration.

### 4. Wire Everything Together

The `component()` and `mergeComponents()` functions are generic, so tRPC procedure types flow through automatically:

```typescript theme={null}
// app/config/index.ts
import {type Component, mergeComponents} from '@orion-js/components'

export async function startApp<T extends Component<any>[]>(components: [...T]) {
  const controllers = mergeComponents(components)
  return {procedures: controllers.trpc}
}
```

```typescript theme={null}
// app/index.ts
import {registerTRPCRoute} from '@orion-js/trpc'
import {startApp} from './config'
import {t} from './config/trpc'
import exampleComponent from './exampleComponent'

const {procedures} = await startApp([exampleComponent])
const appRouter = t.router(procedures)
registerTRPCRoute({appRouter})

// Export the router type for client usage — transformer types flow through!
export type AppRouter = typeof appRouter
```

### Type Inference Requirement

Enable `strictNullChecks` in both backend and frontend tsconfig for native transformer type inference:

```json theme={null}
{
  "compilerOptions": {
    "strictNullChecks": true
  }
}
```

## File Organization

Recommended structure for tRPC procedures:

```
app/
└── exampleComponent/
    └── controllers/
        └── trpc/
            ├── ExampleProcedures/
            │   └── index.ts
            └── index.ts  # Exports procedure classes as array
```

The `controllers/trpc/index.ts`:

```typescript theme={null}
import {ExampleProcedures} from './ExampleProcedures'

export default [ExampleProcedures]
```
