Skip to content
This repository was archived by the owner on Nov 19, 2024. It is now read-only.
Merged
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
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,19 +288,20 @@ Please see [full typings here](src/types.ts).
| `protect` | `boolean` | Requires this endpoint to use an `Authorization` header credential using the `Bearer` scheme on OpenAPI document. | `false` | `false` |
| `summary` | `string` | A short summary included in the OpenAPI document. | `false` | `undefined` |
| `description` | `string` | A verbose description included in the OpenAPI document. | `false` | `undefined` |
| `tags` | `string[]` | A list of tags to group endpoints in the OpenAPI document. | `false` | `[]` |
| `tag` | `string` | A tag to group endpoints in the OpenAPI document. | `false` | `undefined` |

#### GenerateOpenApiDocumentOptions

Please see [full typings here](src/generator/index.ts).

| Property | Type | Description | Required |
| ------------- | -------- | ------------------------------------ | -------- |
| `title` | `string` | The title of the API. | `true` |
| `description` | `string` | A short description of the API. | `false` |
| `version` | `string` | The version of the OpenAPI document. | `true` |
| `baseUrl` | `string` | The base URL of the target server. | `true` |
| `docsUrl` | `string` | A URL to any external documentation. | `false` |
| Property | Type | Description | Required |
| ------------- | ---------- | -------------------------------------- | -------- |
| `title` | `string` | The title of the API. | `true` |
| `description` | `string` | A short description of the API. | `false` |
| `version` | `string` | The version of the OpenAPI document. | `true` |
| `baseUrl` | `string` | The base URL of the target server. | `true` |
| `docsUrl` | `string` | A URL to any external documentation. | `false` |
| `tags` | `string[]` | Tag list for ordering endpoint groups. | `false` |

#### CreateOpenApiNodeHttpHandlerOptions

Expand Down
1 change: 1 addition & 0 deletions examples/with-express/src/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export const openApiDocument = generateOpenApiDocument(appRouter, {
version: '1.0.0',
baseUrl: 'http://localhost:3001/api',
docsUrl: 'https://github.com/jlalmes/trpc-openapi',
tags: ['auth', 'users', 'posts'],
});
18 changes: 9 additions & 9 deletions examples/with-express/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const authRouter = createRouter()
enabled: true,
method: 'POST',
path: '/auth/register',
tags: ['auth'],
tag: 'auth',
summary: 'Register as a new user',
},
},
Expand Down Expand Up @@ -107,7 +107,7 @@ const authRouter = createRouter()
enabled: true,
method: 'POST',
path: '/auth/login',
tags: ['auth'],
tag: 'auth',
summary: 'Login as an existing user',
},
},
Expand Down Expand Up @@ -147,7 +147,7 @@ const usersRouter = createRouter()
enabled: true,
method: 'GET',
path: '/users',
tags: ['users'],
tags 'users',
summary: 'Read all users',
},
},
Expand Down Expand Up @@ -177,7 +177,7 @@ const usersRouter = createRouter()
enabled: true,
method: 'GET',
path: '/users/{id}',
tags: ['users'],
tags 'users',
summary: 'Read a user by id',
},
},
Expand Down Expand Up @@ -212,7 +212,7 @@ const postsRouter = createRouter()
enabled: true,
method: 'GET',
path: '/posts',
tags: ['posts'],
tags 'posts',
summary: 'Read all posts',
},
},
Expand Down Expand Up @@ -246,7 +246,7 @@ const postsRouter = createRouter()
enabled: true,
method: 'GET',
path: '/posts/{id}',
tags: ['posts'],
tags 'posts',
summary: 'Read a post by id',
},
},
Expand Down Expand Up @@ -281,7 +281,7 @@ const postsProtectedRouter = createProtectedRouter()
enabled: true,
method: 'POST',
path: '/posts',
tags: ['posts'],
tags 'posts',
protect: true,
summary: 'Create a new post',
},
Expand Down Expand Up @@ -314,7 +314,7 @@ const postsProtectedRouter = createProtectedRouter()
enabled: true,
method: 'PUT',
path: '/posts/{id}',
tags: ['posts'],
tags 'posts',
protect: true,
summary: 'Update an existing post',
},
Expand Down Expand Up @@ -357,7 +357,7 @@ const postsProtectedRouter = createProtectedRouter()
enabled: true,
method: 'DELETE',
path: '/posts/{id}',
tags: ['posts'],
tags 'posts',
protect: true,
summary: 'Delete a post',
},
Expand Down
1 change: 1 addition & 0 deletions examples/with-nextjs/src/server/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export const openApiDocument = generateOpenApiDocument(appRouter, {
version: '1.0.0',
baseUrl: 'http://localhost:3000/api',
docsUrl: 'https://github.com/jlalmes/trpc-openapi',
tags: ['auth', 'users', 'posts'],
});
18 changes: 9 additions & 9 deletions examples/with-nextjs/src/server/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const authRouter = createRouter()
enabled: true,
method: 'POST',
path: '/auth/register',
tags: ['auth'],
tag: 'auth',
summary: 'Register as a new user',
},
},
Expand Down Expand Up @@ -104,7 +104,7 @@ const authRouter = createRouter()
enabled: true,
method: 'POST',
path: '/auth/login',
tags: ['auth'],
tag: 'auth',
summary: 'Login as an existing user',
},
},
Expand Down Expand Up @@ -144,7 +144,7 @@ const usersRouter = createRouter()
enabled: true,
method: 'GET',
path: '/users',
tags: ['users'],
tag: 'users',
summary: 'Read all users',
},
},
Expand Down Expand Up @@ -174,7 +174,7 @@ const usersRouter = createRouter()
enabled: true,
method: 'GET',
path: '/users/{id}',
tags: ['users'],
tag: 'users',
summary: 'Read a user by id',
},
},
Expand Down Expand Up @@ -209,7 +209,7 @@ const postsRouter = createRouter()
enabled: true,
method: 'GET',
path: '/posts',
tags: ['posts'],
tag: 'posts',
summary: 'Read all posts',
},
},
Expand Down Expand Up @@ -243,7 +243,7 @@ const postsRouter = createRouter()
enabled: true,
method: 'GET',
path: '/posts/{id}',
tags: ['posts'],
tag: 'posts',
summary: 'Read a post by id',
},
},
Expand Down Expand Up @@ -278,7 +278,7 @@ const postsProtectedRouter = createProtectedRouter()
enabled: true,
method: 'POST',
path: '/posts',
tags: ['posts'],
tag: 'posts',
protect: true,
summary: 'Create a new post',
},
Expand Down Expand Up @@ -311,7 +311,7 @@ const postsProtectedRouter = createProtectedRouter()
enabled: true,
method: 'PUT',
path: '/posts/{id}',
tags: ['posts'],
tag: 'posts',
protect: true,
summary: 'Update an existing post',
},
Expand Down Expand Up @@ -354,7 +354,7 @@ const postsProtectedRouter = createProtectedRouter()
enabled: true,
method: 'DELETE',
path: '/posts/{id}',
tags: ['posts'],
tag: 'posts',
protect: true,
summary: 'Delete a post',
},
Expand Down
2 changes: 2 additions & 0 deletions src/generator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type GenerateOpenApiDocumentOptions = {
version: string;
baseUrl: string;
docsUrl?: string;
tags?: string[];
};

export const generateOpenApiDocument = (
Expand Down Expand Up @@ -42,6 +43,7 @@ export const generateOpenApiDocument = (
error: errorResponseObject,
},
},
tags: opts.tags?.map((tag) => ({ name: tag })),
externalDocs: opts.docsUrl ? { url: opts.docsUrl } : undefined,
};
};
8 changes: 4 additions & 4 deletions src/generator/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const getOpenApiPathsObject = (
continue;
}

const { method, protect, summary, description, tags } = openapi;
const { method, protect, summary, description, tag } = openapi;
if (method !== 'GET' && method !== 'DELETE') {
throw new TRPCError({
message: 'Query method must be GET or DELETE',
Expand All @@ -44,7 +44,7 @@ export const getOpenApiPathsObject = (
[httpMethod]: {
summary,
description,
tags,
tags: tag ? [tag] : undefined,
security: protect ? [{ Authorization: [] }] : undefined,
parameters: getParameterObjects(inputParser, pathParameters, 'all'),
responses: getResponsesObject(outputParser),
Expand All @@ -65,7 +65,7 @@ export const getOpenApiPathsObject = (
continue;
}

const { method, protect, summary, description, tags } = openapi;
const { method, protect, summary, description, tag } = openapi;
if (method !== 'POST' && method !== 'PATCH' && method !== 'PUT') {
throw new TRPCError({
message: 'Mutation method must be POST, PATCH or PUT',
Expand All @@ -90,7 +90,7 @@ export const getOpenApiPathsObject = (
[httpMethod]: {
summary,
description,
tags,
tags: tag ? [tag] : undefined,
security: protect ? [{ Authorization: [] }] : undefined,
requestBody: getRequestBodyObject(inputParser, pathParameters),
parameters: getParameterObjects(inputParser, pathParameters, 'path'),
Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export type OpenApiMeta<TMeta = Record<string, any>> = TMeta & {
summary?: string;
description?: string;
protect?: boolean;
tags?: string[];
tag?: string;
};
};

Expand Down
8 changes: 5 additions & 3 deletions test/generator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { z } from 'zod';
import { OpenApiMeta, generateOpenApiDocument, openApiVersion } from '../src';

// TODO: test for duplicate paths (using getPathRegExp)
// TODO: tags ordering

const openApiSchemaValidator = new openAPISchemaValidator({ version: openApiVersion });

Expand All @@ -25,6 +24,7 @@ describe('generator', () => {
description: 'API documentation',
baseUrl: 'http://localhost:3000/api',
docsUrl: 'http://localhost:3000/docs',
tags: [],
});

expect(openApiSchemaValidator.validate(openApiDocument).errors).toEqual([]);
Expand Down Expand Up @@ -109,6 +109,7 @@ describe('generator', () => {
"url": "http://localhost:3000/api",
},
],
"tags": Array [],
}
`);
});
Expand Down Expand Up @@ -958,6 +959,7 @@ describe('generator', () => {
"url": "http://localhost:3000/api",
},
],
"tags": undefined,
}
`);
});
Expand Down Expand Up @@ -1217,7 +1219,7 @@ describe('generator', () => {
`);
});

test('with summary, description & tags', () => {
test('with summary, description & tag', () => {
const appRouter = trpc.router<any, OpenApiMeta>().query('all.metadata', {
meta: {
openapi: {
Expand All @@ -1226,7 +1228,7 @@ describe('generator', () => {
method: 'GET',
summary: 'Short summary',
description: 'Verbose description',
tags: ['tag'],
tag: 'tag',
},
},
input: z.object({ name: z.string() }),
Expand Down