UNPKG

next-openapi-gen

Version:

Automatically generate OpenAPI 3.0 documentation from Next.js projects, with support for TypeScript types and Zod schemas.

477 lines (378 loc) 12.4 kB
# next-openapi-gen Automatically generate OpenAPI 3.0 documentation from Next.js projects, with support for TypeScript types and Zod schemas. ## Features - ✅ Automatic OpenAPI documentation generation from Next.js code - ✅ Support for Next.js App Router (including `/api/users/[id]/route.ts` routes) - ✅ TypeScript types support - ✅ Zod schemas support - ✅ JSDoc comments support - ✅ Multiple UI interfaces: `Scalar`, `Swagger`, `Redoc`, `Stoplight` and `Rapidoc` available at `/api-docs` url - ✅ Path parameters detection (`/users/{id}`) - ✅ Intelligent parameter examples - ✅ Intuitive CLI for initialization and documentation generation ## Supported interfaces - Scalar 🆕 - Swagger - Redoc - Stoplight Elements - RapiDoc ## Installation ```bash npm install next-openapi-gen --save-dev ``` ## Quick Start ```bash # Initialize OpenAPI configuration npx next-openapi-gen init --ui scalar --docs-url api-docs # Generate OpenAPI documentation npx next-openapi-gen generate ``` ## Configuration During initialization (`npx next-openapi-gen init`), a configuration file `next.openapi.json` will be created in the project's root directory: ```json { "openapi": "3.0.0", "info": { "title": "Next.js API", "version": "1.0.0", "description": "API generated by next-openapi-gen" }, "servers": [ { "url": "http://localhost:3000", "description": "Local server" } ], "apiDir": "src/app/api", "schemaDir": "src/types", // or "src/schemas" for Zod schemas "schemaType": "typescript", // or "zod" for Zod schemas "outputFile": "openapi.json", "docsUrl": "/api-docs", "includeOpenApiRoutes": false } ``` ### Configuration Options | Option | Description | | ---------------------- | ------------------------------------------------ | | `apiDir` | Path to the API directory | | `schemaDir` | Path to the types/schemas directory | | `schemaType` | Schema type: `"typescript"` or `"zod"` | | `outputFile` | Path to the OpenAPI output file | | `docsUrl` | API documentation URL (for Swagger UI) | | `includeOpenApiRoutes` | Whether to include only routes with @openapi tag | ## Documenting Your API ### With TypeScript Types ```typescript // src/app/api/users/[id]/route.ts import { NextRequest, NextResponse } from "next/server"; type UserParams = { id: string; // User ID }; type UserResponse = { id: string; // User ID name: string; // Full name email: string; // Email address }; /** * Get user information * @description Fetches detailed user information by ID * @pathParams UserParams * @response UserResponse * @openapi */ export async function GET( request: NextRequest, { params }: { params: { id: string } } ) { // Implementation... } ``` ### With Zod Schemas ```typescript // src/app/api/products/[id]/route.ts import { NextRequest, NextResponse } from "next/server"; import { z } from "zod"; export const ProductParams = z.object({ id: z.string().describe("Product ID"), }); export const ProductResponse = z.object({ id: z.string().describe("Product ID"), name: z.string().describe("Product name"), price: z.number().positive().describe("Product price"), }); /** * Get product information * @description Fetches detailed product information by ID * @pathParams ProductParams * @response ProductResponse * @openapi */ export async function GET( request: NextRequest, { params }: { params: { id: string } } ) { // Implementation... } ``` ## JSDoc Documentation Tags | Tag | Description | | ---------------------- | ----------------------------------------------------------------------------------- | | `@description` | Endpoint description | | `@pathParams` | Path parameters type/schema | | `@params` | Query parameters type/schema | | `@body` | Request body type/schema | | `@bodyDescription` | Request body description | | `@response` | Response type/schema | | `@responseDescription` | Response description | | `@contentType` | Request body content type (`application/json`, `multipart/form-data`) | | `@auth` | Authorization type (`bearer`, `basic`, `apikey`) | | `@tag` | Custom tag | | `@deprecated` | Marks the route as deprecated | | `@openapi` | Marks the route for inclusion in documentation (if includeOpenApiRoutes is enabled) | ## CLI Usage ### 1. Initialization ```bash npx next-openapi-gen init ``` This command will generate following elements: - Generate `next.openapi.json` configuration file - Install UI interface (default `Scalar`) - Add `/api-docs` page to display OpenAPI documentation ### 2. Generate Documentation ```bash npx next-openapi-gen generate ``` This command will generate OpenAPI documentation based on your API code: - Scan API directories for routes - Analyze types/schemas - Generate OpenAPI file (`openapi.json`) in `public` folder - Create Swagger/Scalar UI endpoint and page (if enabled) ### 3. View API Documentation To see API documenation go to `http://localhost:3000/api-docs` ## Examples ### Path Parameters ```typescript // src/app/api/users/[id]/route.ts // TypeScript type UserParams = { id: string; // User ID }; // Or Zod const UserParams = z.object({ id: z.string().describe("User ID"), }); /** * @pathParams UserParams */ export async function GET() { // ... } ``` ### Query Parameters ```typescript // src/app/api/users/route.ts // TypeScript type UsersQueryParams = { page?: number; // Page number limit?: number; // Results per page search?: string; // Search phrase }; // Or Zod const UsersQueryParams = z.object({ page: z.number().optional().describe("Page number"), limit: z.number().optional().describe("Results per page"), search: z.string().optional().describe("Search phrase"), }); /** * @params UsersQueryParams */ export async function GET() { // ... } ``` ### Request Body ```typescript // src/app/api/users/route.ts // TypeScript type CreateUserBody = { name: string; // Full name email: string; // Email address password: string; // Password }; // Or Zod const CreateUserBody = z.object({ name: z.string().describe("Full name"), email: z.string().email().describe("Email address"), password: z.string().min(8).describe("Password"), }); /** * @body CreateUserBody * @bodyDescription User registration data including email and password */ export async function POST() { // ... } ``` ### Response ```typescript // src/app/api/users/route.ts // TypeScript type UserResponse = { id: string; // User ID name: string; // Full name email: string; // Email address createdAt: Date; // Creation date }; // Or Zod const UserResponse = z.object({ id: z.string().describe("User ID"), name: z.string().describe("Full name"), email: z.string().email().describe("Email address"), createdAt: z.date().describe("Creation date"), }); /** * @response UserResponse * @responseDescription Returns newly created user object */ export async function GET() { // ... } ``` ### Authorization ```typescript // src/app/api/protected/route.ts /** * @auth bearer */ export async function GET() { // ... } ``` ### Deprecated ```typescript // src/app/api/v1/route.ts // TypeScript type UserResponse = { id: string; name: string; /** @deprecated Use firstName and lastName instead */ fullName?: string; email: string; }; // Or Zod const UserSchema = z.object({ id: z.string(), name: z.string(), fullName: z.string().optional().describe("@deprecated Use name instead"), email: z.string().email(), }); /** * @body UserSchema * @response UserResponse */ export async function GET() { // ... } ``` ### File Uploads / Multipart Form Data ```typescript // src/app/api/upload/route.ts // TypeScript type FileUploadFormData = { file: File; description?: string; category: string; }; // Or Zod const FileUploadSchema = z.object({ file: z.custom<File>().describe("Image file (PNG/JPG)"), description: z.string().optional().describe("File description"), category: z.string().describe("File category"), }); /** * @body FileUploadSchema * @contentType multipart/form-data */ export async function POST() { // ... } ``` ## Advanced Usage ### Automatic Path Parameter Detection The library automatically detects path parameters and generates documentation for them: ```typescript // src/app/api/users/[id]/posts/[postId]/route.ts // Will automatically detect 'id' and 'postId' parameters export async function GET() { // ... } ``` If no type/schema is provided for path parameters, a default schema will be generated. ### Intelligent Examples The library generates intelligent examples for parameters based on their name: | Parameter name | Example | | -------------- | ---------------------------------------- | | `id`, `*Id` | `"123"` or `123` | | `slug` | `"example-slug"` | | `uuid` | `"123e4567-e89b-12d3-a456-426614174000"` | | `email` | `"user@example.com"` | | `name` | `"example-name"` | | `date` | `"2023-01-01"` | ## Advanced Zod Features The library supports advanced Zod features such as: ### Validation Chains ```typescript // Zod validation chains are properly converted to OpenAPI schemas const EmailSchema = z .string() .email() .min(5) .max(100) .describe("Email address"); // Converts to OpenAPI with email format, minLength and maxLength ``` ### Type Aliases with z.infer ```typescript // You can use TypeScript with Zod types import { z } from "zod"; const UserSchema = z.object({ id: z.string().uuid(), name: z.string().min(2), }); // Use z.infer to create a TypeScript type type User = z.infer<typeof UserSchema>; // The library will be able to recognize this schema by reference `UserSchema` or `User` type. ``` ## Available UI providers <div align="center"> <table> <thead> <th>Scalar</th> <th>Swagger</th> <th>Redoc</th> <th>Stoplight Elements</th> <th>RapiDoc</th> </thead> <tbody> <tr> <td> <img width="320" alt="scalar" src="https://raw.githubusercontent.com/tazo90/next-openapi-gen/refs/heads/main/assets/scalar.png" alt-text="scalar"> </td> <td> <img width="320" alt="swagger" src="https://raw.githubusercontent.com/tazo90/next-openapi-gen/refs/heads/main/assets/swagger.png" alt-text="swagger"> </td> <td> <img width="320" alt="redoc" src="https://raw.githubusercontent.com/tazo90/next-openapi-gen/refs/heads/main/assets/redoc.png" alt-text="redoc"> </td> <td> <img width="320" alt="stoplight" src="https://raw.githubusercontent.com/tazo90/next-openapi-gen/refs/heads/main/assets/stoplight.png" alt-text="stoplight"> </td> <td> <img width="320" alt="rapidoc" src="https://raw.githubusercontent.com/tazo90/next-openapi-gen/refs/heads/main/assets/rapidoc.png" alt-text="rapidoc"> </td> </tr> </tbody> </table> </div> ## License MIT