Skip to content

Generate RPC code from OpenAPI definition

OpenAPIの定義から、HonoRPCで、使用できるコードを自動生成させてみる。

Demo

demo

OpenAPI YAML

yaml
info:
  title: Hono API
  version: v1
openapi: 3.1.0
tags:
  - name: Hono
    description: Hono API
  - name: Post
    description: Post API
components:
  schemas: {}
  parameters: {}
paths:
  /:
    get:
      tags:
        - Hono
      responses:
        '200':
          description: Hono🔥
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Hono🔥
                required:
                  - message
  /posts:
    post:
      tags:
        - Post
      description: create a new post
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                post:
                  type: string
                  minLength: 1
                  maxLength: 140
              required:
                - post
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Created
                required:
                  - message
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Bad Request
                required:
                  - message
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Internal Server Error
                required:
                  - message
    get:
      tags:
        - Post
      description: get PostList posts with optional pagination
      parameters:
        - schema:
            type: string
          required: true
          name: page
          in: query
        - schema:
            type: string
          required: true
          name: rows
          in: query
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: string
                      format: uuid
                    post:
                      type: string
                      minLength: 1
                      maxLength: 140
                    createdAt:
                      type: string
                    updatedAt:
                      type: string
                  required:
                    - id
                    - post
                    - createdAt
                    - updatedAt
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Bad Request
                required:
                  - message
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Internal Server Error
                required:
                  - message
  /posts/{id}:
    put:
      tags:
        - Post
      description: update Post
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                post:
                  type: string
                  minLength: 1
                  maxLength: 140
              required:
                - post
      responses:
        '204':
          description: No Content
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Bad Request
                required:
                  - message
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Internal Server Error
                required:
                  - message
    delete:
      tags:
        - Post
      description: delete post
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '204':
          description: No Content
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Bad Request
                required:
                  - message
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Internal Server Error
                required:
                  - message

Generate

ts
import { createRoute, z } from '@hono/zod-openapi'

export const getRoute = createRoute({
  tags: ['Hono'],
  method: 'get',
  path: '/',
  responses: {
    200: {
      description: 'Hono🔥',
      content: {
        'application/json': { schema: z.object({ message: z.string() }) },
      },
    },
  },
})

export const postPostsRoute = createRoute({
  tags: ['Post'],
  method: 'post',
  path: '/posts',
  description: 'create a new post',
  request: {
    body: {
      required: true,
      content: {
        'application/json': {
          schema: z.object({ post: z.string().min(1).max(140) }),
        },
      },
    },
  },
  responses: {
    201: {
      description: 'Created',
      content: {
        'application/json': { schema: z.object({ message: z.string() }) },
      },
    },
    400: {
      description: 'Bad Request',
      content: {
        'application/json': { schema: z.object({ message: z.string() }) },
      },
    },
    500: {
      description: 'Internal Server Error',
      content: {
        'application/json': { schema: z.object({ message: z.string() }) },
      },
    },
  },
})

export const getPostsRoute = createRoute({
  tags: ['Post'],
  method: 'get',
  path: '/posts',
  description: 'get PostList posts with optional pagination',
  request: { query: z.object({ page: z.string(), rows: z.string() }) },
  responses: {
    200: {
      description: 'OK',
      content: {
        'application/json': {
          schema: z.array(
            z.object({
              id: z.string().uuid(),
              post: z.string().min(1).max(140),
              createdAt: z.string(),
              updatedAt: z.string(),
            }),
          ),
        },
      },
    },
    400: {
      description: 'Bad Request',
      content: {
        'application/json': { schema: z.object({ message: z.string() }) },
      },
    },
    500: {
      description: 'Internal Server Error',
      content: {
        'application/json': { schema: z.object({ message: z.string() }) },
      },
    },
  },
})

export const putPostsIdRoute = createRoute({
  tags: ['Post'],
  method: 'put',
  path: '/posts/{id}',
  description: 'update Post',
  request: {
    body: {
      required: true,
      content: {
        'application/json': {
          schema: z.object({ post: z.string().min(1).max(140) }),
        },
      },
    },
    params: z.object({ id: z.string().uuid() }),
  },
  responses: {
    204: { description: 'No Content' },
    400: {
      description: 'Bad Request',
      content: {
        'application/json': { schema: z.object({ message: z.string() }) },
      },
    },
    500: {
      description: 'Internal Server Error',
      content: {
        'application/json': { schema: z.object({ message: z.string() }) },
      },
    },
  },
})

export const deletePostsIdRoute = createRoute({
  tags: ['Post'],
  method: 'delete',
  path: '/posts/{id}',
  description: 'delete post',
  request: { params: z.object({ id: z.string().uuid() }) },
  responses: {
    204: { description: 'No Content' },
    400: {
      description: 'Bad Request',
      content: {
        'application/json': { schema: z.object({ message: z.string() }) },
      },
    },
    500: {
      description: 'Internal Server Error',
      content: {
        'application/json': { schema: z.object({ message: z.string() }) },
      },
    },
  },
})