oRPC
background

OpenAPI Generator

Generate OpenAPI from your oRPC router

Installation

npm i @orpc/openapi

Define the Route

import { ,  } from '@orpc/server'
import {  } from '@orpc/zod'
import {  } from 'zod'
 
export type  = { ?: { : string } }
 
// global pub, authed completely optional
export const  /** public access */ = .<>()
export const  /** require authed */ = .((, , ) => /** put auth logic here */ .({}))
 
export const  = .({
  : 
    .(
      .({
        : .(),
      }),
    )
    .(async (, , ) => {
      return {
        : `Hello, ${.}!`,
      }
    }),
 
  : .('/posts').({
    : 
      .({
        : '/{id}', // custom your OpenAPI
        : 'GET',
      })
      .(
        .({
          : .({}),
        }),
      )
      .(
        .({
          : .(),
          : .(),
          : .(),
        }),
      )
      .((, , ) => {
        return {
          : 'example',
          : 'example',
          : 'example',
        }
      }),
 
    : 
      .(
        .({
          : .(),
          : .(),
          : .().('image/*'),
        }),
      )
      .(async (, , ) => {
        . // file upload out of the box
 
        return {
          : 'example',
          : .,
          : .,
        }
      }),
  }),
})

Generate the OpenAPI Specification

To generate an OpenAPI specification, you need either the type of the router you intend to use or the contract.

import {  } from '@orpc/openapi'
import {  } from 'examples/server'
import {  } from 'examples/contract'
 
const  = ({
    : , // both router and contract are supported
    : {
        : 'My App',
        : '0.0.0',
    },
})
 
.(.(, null, 2))

Here is the result:

{
  info: {
    title: 'My App',
    version: '0.0.0',
  },
  openapi: '3.1.0',
  paths: {
    '/getting': {
      post: {
        operationId: 'getting',
        requestBody: {
          required: false,
          content: {
            'application/json': {
              schema: {
                type: 'object',
                properties: {
                  name: {
                    type: 'string',
                  },
                },
                required: ['name'],
              },
            },
          },
        },
        responses: {
          '200': {
            description: 'OK',
            content: {
              'application/json': {
                schema: {
                  type: 'object',
                  properties: {
                    message: {
                      type: 'string',
                    },
                  },
                  required: ['message'],
                },
              },
            },
          },
        },
      },
    },
    '/posts/{id}': {
      get: {
        operationId: 'post.find',
        parameters: [
          {
            name: 'id',
            in: 'path',
            required: true,
            schema: {
              type: 'string',
            },
          },
        ],
        responses: {
          '200': {
            description: 'OK',
            content: {
              'application/json': {
                schema: {
                  type: 'object',
                  properties: {
                    id: {
                      type: 'string',
                    },
                    title: {
                      type: 'string',
                    },
                    description: {
                      type: 'string',
                    },
                  },
                  required: ['id', 'title', 'description'],
                },
              },
            },
          },
        },
      },
    },
    '/post/create': {
      post: {
        operationId: 'post.create',
        requestBody: {
          required: false,
          content: {
            'multipart/form-data': {
              schema: {
                type: 'object',
                properties: {
                  title: {
                    type: 'string',
                  },
                  description: {
                    type: 'string',
                  },
                  thumb: {
                    type: 'string',
                    contentMediaType: 'image/*',
                  },
                },
                required: ['title', 'description', 'thumb'],
              },
            },
          },
        },
        responses: {
          '200': {
            description: 'OK',
            content: {
              'application/json': {
                schema: {
                  type: 'object',
                  properties: {
                    id: {
                      type: 'string',
                    },
                    title: {
                      type: 'string',
                    },
                    description: {
                      type: 'string',
                    },
                  },
                  required: ['id', 'title', 'description'],
                },
              },
            },
          },
        },
      },
    },
  },
}

On this page