Skip to content

jellydn/next-swagger-doc

Repository files navigation

Welcome to next-swagger-doc πŸ‘‹

All Contributors

Version Downloads/week Prerequisite Documentation License: MIT Twitter: jellydn

Generate Swagger JSON API from NextJS Api Routes

If you enjoy working with next-swagger-doc, you will love next-validations: NextJS API Validations, support Zod, Yup, Fastest-Validator, Joi, and more

🏠 Homepage

✨ Demo

Prerequisites

  • Nextjs >= 9
  • Node >= 18

Motivation

This package reads your JSDoc-annotated source code on NextJS API route and generates an OpenAPI (Swagger) specification.

nextjs + swagger-jsdoc = next-swagger-doc

Install

yarn add next-swagger-doc

Usage #1: next-swagger-doc with Next.js 13

To incorporate next-swagger-doc with your Next.js 13 project, follow these steps. This setup will generate Swagger documentation for your API based on your code and provide a built-in Swagger UI for viewing the documentation.

1. Create Swagger Spec

Next, create a new file lib/swagger.ts. This file uses the next-swagger-doc library to create a Swagger specification based on the API routes in your Next.js project.

import { createSwaggerSpec } from "next-swagger-doc";

export const getApiDocs = async () => {
  const spec = createSwaggerSpec({
    apiFolder: "app/api", // define api folder under app folder
    definition: {
      openapi: "3.0.0",
      info: {
        title: "Next Swagger API Example",
        version: "1.0",
      },
      components: {
        securitySchemes: {
          BearerAuth: {
            type: "http",
            scheme: "bearer",
            bearerFormat: "JWT",
          },
        },
      },
      security: [],
    },
  });
  return spec;
};

2. Create Swagger UI Component

Generate a new file named app/api-doc/react-swagger.tsx. In this file, create and export a React component that utilizes the swagger-ui-react library to render the Swagger UI according to the provided specification.

For demonstration purposes, here is an example using swagger-ui-react

Feel free to employ any alternative swagger UI library, such as stoplightio/elements. I have added an example using this library in the example folder.

'use client';

import SwaggerUI from 'swagger-ui-react';
import 'swagger-ui-react/swagger-ui.css';

type Props = {
  spec: Record<string, any>,
};

function ReactSwagger({ spec }: Props) {
  return <SwaggerUI spec={spec} />;
}

export default ReactSwagger;

3. Create API Documentation Page

Create a new file app/api-doc/page.tsx. This page imports the Swagger spec and the Swagger UI component to display the Swagger documentation.

import { getApiDocs } from "@/lib/swagger";
import ReactSwagger from "./react-swagger";

export default async function IndexPage() {
  const spec = await getApiDocs();
  return (
    <section className="container">
      <ReactSwagger spec={spec} />
    </section>
  );
}

4. Add Swagger Comment to API Route

Lastly, add a Swagger comment to your API route in app/api/hello/route.ts. This comment includes metadata about the API endpoint which will be read by next-swagger-doc and included in the Swagger spec.

/**
 * @swagger
 * /api/hello:
 *   get:
 *     description: Returns the hello world
 *     responses:
 *       200:
 *         description: Hello World!
 */
export async function GET(_request: Request) {
  // Do whatever you want
  return new Response('Hello World!', {
    status: 200,
  });
}

Now, navigate to localhost:3000/api-doc (or wherever you host your Next.js application), and you should see the swagger UI.

https://gyazo.com/6bfa919c4969b000615df6bb9cabcd02.gif

Usage #2: Create an single API document

yarn add next-swagger-doc swagger-ui-react
  • Create an live swagger page, e.g: pages/api-doc.tsx
import { GetStaticProps, InferGetStaticPropsType } from 'next';
import { createSwaggerSpec } from 'next-swagger-doc';
import dynamic from 'next/dynamic';
import 'swagger-ui-react/swagger-ui.css';

const SwaggerUI = dynamic<{
  spec: any;
}>(import('swagger-ui-react'), { ssr: false });

function ApiDoc({ spec }: InferGetStaticPropsType<typeof getStaticProps>) {
  return <SwaggerUI spec={spec} />;
}

export const getStaticProps: GetStaticProps = async () => {
  const spec: Record<string, any> = createSwaggerSpec({
    apiFolder: 'pages/api' // or 'src/pages/api',
    definition: {
      openapi: '3.0.0',
      info: {
        title: 'Next Swagger API Example',
        version: '1.0',
      },
    },
  });

  return {
    props: {
      spec,
    },
  };
};

export default ApiDoc;

https://gyazo.com/af250bab0d07f931c596ebc8c955ae2e.gif

Usage #3: Use NextJS API route to create Swagger JSON spec

  • Step 1: Create an api route on nextjs, e.g: pages/api/doc.ts
import { withSwagger } from "next-swagger-doc";

const swaggerHandler = withSwagger({
  definition: {
    openapi: "3.0.0",
    info: {
      title: "NextJS Swagger",
      version: "0.1.0",
    },
  },
  apiFolder: "pages/api",
});
export default swaggerHandler();
  • Step 2: Add JSdoc to any NextJS API routes, for example: pages/api/hello.ts
import { NextApiRequest, NextApiResponse } from "next";

/**
 * @swagger
 * /api/hello:
 *   get:
 *     description: Returns the hello world
 *     responses:
 *       200:
 *         description: hello world
 */
const handler = (_req: NextApiRequest, res: NextApiResponse) => {
  res.status(200).json({
    result: "hello world",
  });
};

export default handler;
  • Step 3: Access the Swagger API doc

https://gyazo.com/0bcf45f0e15778a5cb851b40526324f3.gif

Usage #4: Generate Swagger file from CLI

  • Step 1: create a JSON config file as next-swagger-doc.json
{
  "apiFolder": "pages/api",
  "schemaFolders": ["models"],
  "definition": {
    "openapi": "3.0.0",
    "info": {
      "title": "Next Swagger API Example",
      "version": "1.0"
    }
  }
}
  • Step 2: run cli for generating swagger file
yarn next-swagger-doc-cli next-swagger-doc.json

Run example app

gh repo clone jellydn/next-swagger-doc
cd examples/next14-app
pnpm install
pnm run dev

Then open http://localhost:3000/api-doc or http://localhost:3000/ on your browser ./example-screenshot.png

Linter

In order to set an eslint rule that checks that all the APIs actually have a swagger JsDoc description we can use the following settings:

Install the JsDoc eslint plugin:

yarn add -D eslint-plugin-jsdoc

Create the custom rule in your eslint configuration file:

{
    //...your configuration
    "overrides": [
        //...your overrides
        {
            // Force the setting of a swagger description on each api endpoint
            "files": ["pages/api/**/*.ts"],
            "plugins": ["jsdoc"],
            "rules": {
                "jsdoc/no-missing-syntax": [
                "error",
                {
                    "contexts": [
                    {
                        "comment": "JsdocBlock:has(JsdocTag[tag=swagger])",
                        "context": "any",
                        "message": "@swagger documentation is required on each API. Check this out for syntax info: https://github.com/jellydn/next-swagger-doc"
                    }
                    ]
                }
            ]
        }
    ]
}

Pre-commit hook

This project uses pre-commit to enforce code quality. To install pre-commit hooks, run:

pre-commit install

Author

πŸ‘€ Huynh Duc Dung

Stargazers

Stargazers repo roster for @jellydn/next-swagger-doc

Show your support

kofi paypal buymeacoffee

Give a ⭐️ if this project helped you!

Contributors ✨

Thanks goes to these wonderful people (emoji key):

Dung Duc Huynh (Kaka)
Dung Duc Huynh (Kaka)

πŸ’» πŸ“–
tmirkovic
tmirkovic

πŸ“–
Matthew Holloway
Matthew Holloway

πŸ’»
leventemihaly
leventemihaly

πŸ“–
PAHRIZAL MA'RUP
PAHRIZAL MA'RUP

πŸ’»
Aris
Aris

πŸ“–
Valerio Ageno
Valerio Ageno

πŸ“–
cachho
cachho

πŸ’»

This project follows the all-contributors specification. Contributions of any kind welcome!