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.
Orionjs provides seamless integration with tRPC 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
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:
// 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:
// 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:
// 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:
// 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}
}
// 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:
{
"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:
import {ExampleProcedures} from './ExampleProcedures'
export default [ExampleProcedures]