Skip to content
This repository was archived by the owner on Nov 19, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@ name: Test
on: [push]
jobs:
test:
strategy:
matrix:
node-version: [20, 24]
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 16
node-version: ${{ matrix.node-version }}
cache: npm

- name: Install dependencies
run: npm ci --force
run: npm ci

- name: Assert Zod 4 resolution
run: node -e "const version = require('zod/package.json').version; if (!version.startsWith('4.')) throw new Error(`Expected Zod 4, got ${version}`)"

- name: Run tests
run: npm test
29 changes: 29 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"logToFile": true,
"configurations": [
{
"name": "Jest file",
"type": "node",
"request": "launch",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/jest",
"args": [
"${fileBasenameNoExtension}",
"--runInBand",
"--watch",
"--coverage=false",
"--no-cache"
],
"cwd": "${workspaceRoot}",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"sourceMaps": true,
"windows": {
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
}
}
]
}
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"editor.tabSize": 2,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
"source.fixAll.eslint": "explicit"
},
"workbench.colorCustomizations": {
"titleBar.activeBackground": "#8FCE0B",
Expand Down
49 changes: 28 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
![trpc-openapi](assets/trpc-openapi-readme.png)
![better-trpc-openapi](assets/trpc-openapi-readme.png)

<div align="center">
<h1>trpc-openapi</h1>
<a href="https://www.npmjs.com/package/trpc-openapi"><img src="https://img.shields.io/npm/v/trpc-openapi.svg?style=flat&color=brightgreen" target="_blank" /></a>
<h1>better-trpc-openapi</h1>
<a href="https://www.npmjs.com/package/better-trpc-openapi"><img src="https://img.shields.io/npm/v/better-trpc-openapi.svg?style=flat&color=brightgreen" target="_blank" /></a>
<a href="./LICENSE"><img src="https://img.shields.io/badge/license-MIT-black" /></a>
<a href="https://trpc.io/discord" target="_blank"><img src="https://img.shields.io/badge/chat-discord-blue.svg" /></a>
<br />
<hr />
</div>

#### `trpc-openapi` is maintained by ProsePilot - simple, fast and free online [writing tools](https://www.prosepilot.com/tools).
#### `better-trpc-openapi` is the Zod 4-native maintained fork of `trpc-openapi`.

---

Expand All @@ -21,20 +21,20 @@

## Usage

**1. Install `trpc-openapi`.**
**1. Install `better-trpc-openapi`, tRPC 11, and Zod 4.**

```bash
# npm
npm install trpc-openapi
npm install better-trpc-openapi @trpc/server@^11 zod@^4
# yarn
yarn add trpc-openapi
yarn add better-trpc-openapi @trpc/server@^11 zod@^4
```

**2. Add `OpenApiMeta` to your tRPC instance.**

```typescript
import { initTRPC } from '@trpc/server';
import { OpenApiMeta } from 'trpc-openapi';
import { OpenApiMeta } from 'better-trpc-openapi';

const t = initTRPC.meta<OpenApiMeta>().create(); /* 👈 */
```
Expand All @@ -56,7 +56,7 @@ export const appRouter = t.router({
**4. Generate an OpenAPI document.**

```typescript
import { generateOpenApiDocument } from 'trpc-openapi';
import { generateOpenApiDocument } from 'better-trpc-openapi';

import { appRouter } from '../appRouter';

Expand All @@ -68,15 +68,15 @@ export const openApiDocument = generateOpenApiDocument(appRouter, {
});
```

**5. Add an `trpc-openapi` handler to your app.**
**5. Add a `better-trpc-openapi` handler to your app.**

We currently support adapters for [`Express`](http://expressjs.com/), [`Next.js`](https://nextjs.org/), [`Serverless`](https://www.serverless.com/), [`Fastify`](https://www.fastify.io/), [`Nuxt`](https://nuxtjs.org/) & [`Node:HTTP`](https://nodejs.org/api/http.html).

[`Fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), [`Cloudflare Workers`](https://workers.cloudflare.com/) & more soon™, PRs are welcomed 🙌.

```typescript
import { createOpenApiHttpHandler } from 'better-trpc-openapi';
import http from 'http';
import { createOpenApiHttpHandler } from 'trpc-openapi';

import { appRouter } from '../appRouter';

Expand All @@ -97,8 +97,8 @@ const body = await res.json(); /* { greeting: 'Hello James!' } */

Peer dependencies:

- [`tRPC`](https://github.com/trpc/trpc) Server v10 (`@trpc/server`) must be installed.
- [`Zod`](https://github.com/colinhacks/zod) v3 (`zod@^3.14.4`) must be installed (recommended `^3.20.0`).
- [`tRPC`](https://github.com/trpc/trpc) Server v11 (`@trpc/server@^11`) must be installed.
- [`Zod`](https://github.com/colinhacks/zod) v4 (`zod@^4.0.0`) must be installed. Zod 3 is not supported.

For a procedure to support OpenAPI the following _must_ be true:

Expand All @@ -115,6 +115,13 @@ Please note:
- Trailing slashes are ignored.
- Routing is case-insensitive.

### Zod 4 schema behavior

- Request preprocessors are documented using their output schema, while request transforms are documented using the values they accept.
- Response transforms cannot be represented reliably and cause document generation to fail with the affected procedure name.
- Zod codecs and cyclic schemas are rejected with a contextual error because OpenAPI 3.0 cannot inline them safely.
- Zod metadata is preserved where OpenAPI 3.0 supports it. JSON Schema `examples` are represented by OpenAPI 3.0's singular `example` field.

## HTTP Requests

Procedures with a `GET`/`DELETE` method will accept inputs via URL `query parameters`. Procedures with a `POST`/`PATCH`/`PUT` method will accept inputs via the `request body` with a `application/json` or `application/x-www-form-urlencoded` content type.
Expand All @@ -125,7 +132,7 @@ A procedure can accept a set of inputs via URL path parameters. You can add a pa

### Query parameters

Query & path parameter inputs are always accepted as a `string`. This library will attempt to [coerce](https://github.com/colinhacks/zod#coercion-for-primitives) your input values to the following primitive types out of the box: `number`, `boolean`, `bigint` and `date`. If you wish to support others such as `object`, `array` etc. please use [`z.preprocess()`](https://github.com/colinhacks/zod#preprocess).
Query & path parameter inputs are always accepted as a `string`. This library will attempt to [coerce](https://github.com/colinhacks/zod#coercion-for-primitives) your input `array` and `object` values to the following primitive types out of the box: `number`, `boolean`, `bigint` and `date`. If you wish to support others (such as nested `object`, `array`) etc. please use [`z.preprocess()`](https://github.com/colinhacks/zod#preprocess).

```typescript
// Router
Expand Down Expand Up @@ -191,7 +198,7 @@ Explore a [complete example here](examples/with-nextjs/src/server/router.ts).

```typescript
import { TRPCError, initTRPC } from '@trpc/server';
import { OpenApiMeta } from 'trpc-openapi';
import { OpenApiMeta } from 'better-trpc-openapi';

type User = { id: string; name: string };

Expand Down Expand Up @@ -249,8 +256,8 @@ Please see [full example here](examples/with-express).

```typescript
import { createExpressMiddleware } from '@trpc/server/adapters/express';
import { createOpenApiExpressMiddleware } from 'better-trpc-openapi';
import express from 'express';
import { createOpenApiExpressMiddleware } from 'trpc-openapi';

import { appRouter } from '../appRouter';

Expand All @@ -268,7 +275,7 @@ Please see [full example here](examples/with-nextjs).

```typescript
// pages/api/[...trpc].ts
import { createOpenApiNextHandler } from 'trpc-openapi';
import { createOpenApiNextHandler } from 'better-trpc-openapi';

import { appRouter } from '../../server/appRouter';

Expand All @@ -280,7 +287,7 @@ export default createOpenApiNextHandler({ router: appRouter });
Please see [full example here](examples/with-serverless).

```typescript
import { createOpenApiAwsLambdaHandler } from 'trpc-openapi';
import { createOpenApiAwsLambdaHandler } from 'better-trpc-openapi';

import { appRouter } from './appRouter';

Expand All @@ -293,8 +300,8 @@ Please see [full example here](examples/with-fastify).

```typescript
import { fastifyTRPCPlugin } from '@trpc/server/adapters/fastify';
import { fastifyTRPCOpenApiPlugin } from 'better-trpc-openapi';
import Fastify from 'fastify';
import { fastifyTRPCOpenApiPlugin } from 'trpc-openapi';

import { appRouter } from './router';

Expand Down Expand Up @@ -332,7 +339,7 @@ Please see [full typings here](src/types.ts).

| Property | Type | Description | Required | Default |
| -------------- | ------------------- | ---------------------------------------------------------------------------------------------------- | -------- | ---------------------- |
| `enabled` | `boolean` | Exposes this procedure to `trpc-openapi` adapters and on the OpenAPI document. | `false` | `true` |
| `enabled` | `boolean` | Exposes this procedure to `better-trpc-openapi` adapters and on the OpenAPI document. | `false` | `true` |
| `method` | `HttpMethod` | HTTP method this endpoint is exposed on. Value can be `GET`, `POST`, `PATCH`, `PUT` or `DELETE`. | `true` | `undefined` |
| `path` | `string` | Pathname this endpoint is exposed on. Value must start with `/`, specify path parameters using `{}`. | `true` | `undefined` |
| `protect` | `boolean` | Requires this endpoint to use a security scheme. | `false` | `false` |
Expand All @@ -357,7 +364,7 @@ Please see [full typings here](src/adapters/node-http/core.ts).

---

_Still using tRPC v9? See our [`.interop()`](examples/with-interop) example._
See the [minimal tRPC 11 router](examples/with-interop) example.

## License

Expand Down
4 changes: 2 additions & 2 deletions examples/with-express/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# [**`trpc-openapi`**](../../README.md) (with-express)
# [**`better-trpc-openapi`**](../../README.md) (with-express)

### Getting started

Make sure your current working directory is at `/trpc-openapi` root.
Make sure your current working directory is at `/better-trpc-openapi` root.

```bash
npm install
Expand Down
4 changes: 2 additions & 2 deletions examples/with-express/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
"dev": "ts-node-dev --respawn --transpile-only --exit-child ./src/index.ts"
},
"dependencies": {
"@trpc/server": "^10.27.1",
"@trpc/server": "^11.7.1",
"cors": "^2.8.5",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"swagger-ui-express": "^4.6.3",
"uuid": "^9.0.0",
"zod": "^3.21.4"
"zod": "^4.4.3"
},
"devDependencies": {
"@types/cors": "^2.8.13",
Expand Down
2 changes: 1 addition & 1 deletion examples/with-express/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* eslint-disable @typescript-eslint/no-misused-promises */
import { createExpressMiddleware } from '@trpc/server/adapters/express';
import { createOpenApiExpressMiddleware } from 'better-trpc-openapi';
import cors from 'cors';
import express from 'express';
import swaggerUi from 'swagger-ui-express';
import { createOpenApiExpressMiddleware } from 'trpc-openapi';

import { openApiDocument } from './openapi';
import { appRouter, createContext } from './router';
Expand Down
4 changes: 2 additions & 2 deletions examples/with-express/src/openapi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { generateOpenApiDocument } from 'trpc-openapi';
import { generateOpenApiDocument } from 'better-trpc-openapi';

import { appRouter } from './router';

Expand All @@ -8,6 +8,6 @@ export const openApiDocument = generateOpenApiDocument(appRouter, {
description: 'OpenAPI compliant REST API built using tRPC with Express',
version: '1.0.0',
baseUrl: 'http://localhost:3000/api',
docsUrl: 'https://github.com/jlalmes/trpc-openapi',
docsUrl: 'https://github.com/deldrid1/trpc-openapi',
tags: ['auth', 'users', 'posts'],
});
2 changes: 1 addition & 1 deletion examples/with-express/src/router.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TRPCError, initTRPC } from '@trpc/server';
import { CreateExpressContextOptions } from '@trpc/server/adapters/express';
import { OpenApiMeta } from 'better-trpc-openapi';
import jwt from 'jsonwebtoken';
import { OpenApiMeta } from 'trpc-openapi';
import { v4 as uuid } from 'uuid';
import { z } from 'zod';

Expand Down
4 changes: 2 additions & 2 deletions examples/with-fastify/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# [**`trpc-openapi`**](../../README.md) (with-fastify)
# [**`better-trpc-openapi`**](../../README.md) (with-fastify)

### Getting started

Make sure your current working directory is at `/trpc-openapi` root.
Make sure your current working directory is at `/better-trpc-openapi` root.

```bash
npm install
Expand Down
4 changes: 2 additions & 2 deletions examples/with-fastify/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
"dependencies": {
"@fastify/cors": "^8.2.1",
"@fastify/swagger": "^8.5.1",
"@trpc/server": "^10.27.1",
"@trpc/server": "^11.7.1",
"fastify": "^4.17.0",
"jsonwebtoken": "^9.0.0",
"uuid": "^9.0.0",
"zod": "^3.21.4"
"zod": "^4.4.3"
},
"devDependencies": {
"@types/cors": "^2.8.13",
Expand Down
9 changes: 3 additions & 6 deletions examples/with-fastify/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import cors from '@fastify/cors';
import fastifySwagger from '@fastify/swagger';
import { fastifyTRPCPlugin } from '@trpc/server/adapters/fastify';
import { fastifyTRPCOpenApiPlugin } from 'better-trpc-openapi';
import Fastify from 'fastify';
import { fastifyTRPCOpenApiPlugin } from 'trpc-openapi';

import { openApiDocument } from './openapi';
import { appRouter, createContext } from './router';
Expand Down Expand Up @@ -37,20 +37,17 @@ async function main() {
// Serve the OpenAPI document
app.get('/openapi.json', () => openApiDocument);

// Server Swagger UI
// Register the OpenAPI document with Fastify Swagger
await app.register(fastifySwagger, {
routePrefix: '/docs',
mode: 'static',
specification: { document: openApiDocument },
uiConfig: { displayOperationId: true },
exposeRoute: true,
});

await app
.listen({ port: 3000 })
.then((address) => {
app.swagger();
console.log(`Server started on ${address}\nSwagger UI: http://localhost:3000/docs`);
console.log(`Server started on ${address}\nOpenAPI: http://localhost:3000/openapi.json`);
})
.catch((e) => {
throw e;
Expand Down
4 changes: 2 additions & 2 deletions examples/with-fastify/src/openapi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { generateOpenApiDocument } from 'trpc-openapi';
import { generateOpenApiDocument } from 'better-trpc-openapi';

import { appRouter } from './router';

Expand All @@ -8,6 +8,6 @@ export const openApiDocument = generateOpenApiDocument(appRouter, {
description: 'OpenAPI compliant REST API built using tRPC with Fastify',
version: '1.0.0',
baseUrl: 'http://localhost:3000/api',
docsUrl: 'https://github.com/jlalmes/trpc-openapi',
docsUrl: 'https://github.com/deldrid1/trpc-openapi',
tags: ['auth', 'users', 'posts'],
});
2 changes: 1 addition & 1 deletion examples/with-fastify/src/router.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* eslint-disable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-floating-promises, @typescript-eslint/ban-ts-comment */
import { TRPCError, initTRPC } from '@trpc/server';
import { CreateFastifyContextOptions } from '@trpc/server/adapters/fastify';
import { OpenApiMeta } from 'better-trpc-openapi';
import { type FastifyReply, type FastifyRequest } from 'fastify';
import jwt from 'jsonwebtoken';
import { OpenApiMeta } from 'trpc-openapi';
import { v4 as uuid } from 'uuid';
import { z } from 'zod';

Expand Down
7 changes: 3 additions & 4 deletions examples/with-interop/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# [**`trpc-openapi`**](../../README.md) (with-interop)
# [**`better-trpc-openapi`**](../../README.md) (with-interop)

### Getting started

This example shows the pattern to use a tRPC v10 `.interop()` router whilst also supporting `trpc-openapi`.
This example shows the minimal tRPC 11 router setup for `better-trpc-openapi`.

```bash
npm install @trpc/server@next
npm install trpc-openapi@0 --force
npm install better-trpc-openapi @trpc/server@^11 zod@^4
```
Loading