Skip to content

Commit 4447e48

Browse files
feat: add express-openapi-ui middleware
1 parent 726144f commit 4447e48

File tree

19 files changed

+583
-41
lines changed

19 files changed

+583
-41
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "@openapi-ui-examples/express-openapi-ui",
3+
"type": "module",
4+
"version": "0.1.0",
5+
"author": "rookie-luochao",
6+
"private": true,
7+
"engines": {
8+
"node": ">=18"
9+
},
10+
"scripts": {
11+
"build": "tsc --p tsconfig.json && tsc-alias -p tsconfig.json",
12+
"dev": "nodemon --exec \"vite-node src/index.ts\" --ext ts --quiet --watch ../../packages/express-api-reference --watch ./"
13+
},
14+
"dependencies": {
15+
"@openapi-ui/express-openapi-ui": "workspace:*",
16+
"express": "^4.19.2",
17+
"swagger-jsdoc": "^6.2.8"
18+
},
19+
"devDependencies": {
20+
"@types/express": "^4.17.21",
21+
"@types/swagger-jsdoc": "^6.0.3",
22+
"nodemon": "^3.0.1",
23+
"tsc-alias": "^1.8.8",
24+
"vite": "^5.2.10",
25+
"vite-node": "^1.3.1"
26+
}
27+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { openApiUIReference } from "@openapi-ui/express-openapi-ui";
2+
import Express from "express";
3+
import swaggerJsdoc from "swagger-jsdoc";
4+
5+
const app = Express();
6+
const docsPath = "/openapi";
7+
const specPath = "/openapi.json";
8+
9+
/**
10+
* @openapi
11+
* components:
12+
* schemas:
13+
* HelloWorldResModel:
14+
* type: object
15+
* required:
16+
* - data
17+
* properties:
18+
* data:
19+
* type: string
20+
*/
21+
22+
/**
23+
* @openapi
24+
* /helloword:
25+
* get:
26+
* operationId: "HelloWordGet"
27+
* description: Get a mysterious map
28+
* responses:
29+
* 200:
30+
* description: Returns a mysterious map
31+
* content:
32+
* application/json:
33+
* schema:
34+
* $ref: '#/components/schemas/HelloWorldResModel'
35+
* 400:
36+
* description: Returns failed
37+
*/
38+
app.get("/helloword", (req, res) => {
39+
res.send({ data: "Hello World!" });
40+
});
41+
42+
const openApiSpec = swaggerJsdoc({
43+
definition: {
44+
openapi: "3.0.0",
45+
info: {
46+
title: "Hello World",
47+
version: "1.0.0",
48+
},
49+
},
50+
apis: ["./src/*.ts"], // files containing annotations as above
51+
});
52+
53+
// Serve the OpenAPI specification
54+
app.get(specPath, (req, res) => {
55+
res.json(openApiSpec);
56+
});
57+
58+
// Serve the OpenAPI UI
59+
app.use(
60+
docsPath,
61+
openApiUIReference({
62+
title: "openapi docs",
63+
description: "openapi docs description",
64+
specPath: specPath,
65+
}),
66+
);
67+
68+
const PORT = Number(process.env.PORT) || 8003;
69+
const HOST = process.env.HOST || "0.0.0.0";
70+
app.listen(PORT, HOST, () => {
71+
console.log(`✅ Express listening at http://127.0.0.1:${PORT}${docsPath}`);
72+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"include": ["src"],
4+
"exclude": ["dist", "test", "vite.config.ts", "**/*.test.ts"],
5+
"compilerOptions": {
6+
"types": ["vite/client"],
7+
"paths": {
8+
"@/*": ["./src/*"]
9+
},
10+
"outDir": "dist/"
11+
}
12+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { defineConfig } from "vite";
2+
3+
export default defineConfig({
4+
resolve: {
5+
alias: [],
6+
},
7+
});

examples/nestjs-openapi-ui-express/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "@openapi-ui/nestjs-openapi-ui-express",
2+
"name": "@openapi-ui-examples/nestjs-openapi-ui-express",
33
"description": "Nest with express as http adapter",
44
"version": "0.1.0",
55
"author": "rookie-luochao",

examples/nestjs-openapi-ui-fastify/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "@openapi-ui/nestjs-openapi-ui-fastify",
2+
"name": "@openapi-ui-examples/nestjs-openapi-ui-fastify",
33
"description": "Nest with fastify as http adapter",
44
"version": "0.1.0",
55
"author": "rookie-luochao",

examples/nestjs-openapi-ui-fastify/src/main.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ async function bootstrap() {
3737
specPath: specPath,
3838
withFastify: true,
3939
theme: 'dark',
40+
cdn: 'https://registry.npmmirror.com/openapi-ui-dist/latest/files',
4041
}),
4142
);
4243

packages/express-openapi-ui/README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Express-OpenAPI-UI Middleware
2+
3+
[![Version](https://img.shields.io/npm/v/%40openapi-ui/express-openapi-ui)](https://www.npmjs.com/package/@openapi-ui/express-openapi-ui)
4+
[![Downloads](https://img.shields.io/npm/dm/%40openapi-ui/express-openapi-ui)](https://www.npmjs.com/package/@openapi-ui/express-openapi-ui)
5+
[![License](https://img.shields.io/npm/l/%40openapi-ui/express-openapi-ui)](https://www.npmjs.com/package/@openapi-ui/express-openapi-ui)
6+
7+
## Install
8+
9+
```bash
10+
npm install @openapi-ui/express-openapi-ui
11+
```
12+
13+
## Usage
14+
15+
[Set up Express](https://expressjs.com/en/starter/hello-world.html) and pass an OpenAPI/Swagger spec to the `openApiUIReference` middleware:
16+
17+
> The most popular way is use [`swagger-jsdoc`](https://github.com/Surnet/swagger-jsdoc) to generate an OpenAPI/Swagger file.
18+
19+
20+
```ts
21+
import { openApiUIReference } from '@openapi-ui/express-openapi-ui'
22+
23+
app.get('/openapi.json', (req, res) => {
24+
res.json(openApiSpec)
25+
})
26+
27+
app.use(
28+
'/openapi',
29+
openApiUIReference({
30+
specPath: '/openapi.json',
31+
}),
32+
)
33+
```
34+
35+
[try example](https://github.com/openapi-ui/nodejs-openapi-ui/tree/main/examples/express-openapi-ui)
36+
37+
### Themes
38+
39+
```ts
40+
import { openApiUIReference } from '@openapi-ui/nestjs-openapi-ui'
41+
42+
app.use(
43+
"/openapi",
44+
openApiUIReference({
45+
specPath: "/openapi.json",
46+
theme: 'light', // light or dark
47+
}),
48+
)
49+
```
50+
51+
### Custom CDN
52+
53+
You can use a custom CDN ,default is `https://unpkg.com/openapi-ui-dist`.
54+
55+
```ts
56+
import { openApiUIReference } from '@openapi-ui/nestjs-openapi-ui'
57+
58+
app.use(
59+
"/openapi",
60+
openApiUIReference({
61+
specPath: "/openapi.json",
62+
cdn: 'https://registry.npmmirror.com/openapi-ui-dist/latest/files',
63+
}),
64+
)
65+
```
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"name": "@openapi-ui/express-openapi-ui",
3+
"description": "A middleware for using the OpenAPI-UI with Express",
4+
"version": "0.1.0",
5+
"author": "rookie-luochao",
6+
"homepage": "https://github.com/openapi-ui/nodejs-openapi-ui",
7+
"bugs": "https://github.com/openapi-ui/nodejs-openapi-ui/issues",
8+
"repository": {
9+
"type": "git",
10+
"url": "https://github.com/openapi-ui/nodejs-openapi-ui.git",
11+
"directory": "packages/express-openapi-ui"
12+
},
13+
"engines": {
14+
"node": ">=18"
15+
},
16+
"scripts": {
17+
"build": "tsup ./src/index.ts --format esm,cjs --dts",
18+
"test": "vitest run"
19+
},
20+
"type": "module",
21+
"main": "dist/index.cjs",
22+
"module": "dist/index.js",
23+
"types": "dist/index.d.ts",
24+
"exports": {
25+
".": {
26+
"import": {
27+
"types": "./dist/index.d.ts",
28+
"default": "./dist/index.js"
29+
},
30+
"require": {
31+
"types": "./dist/index.d.cts",
32+
"default": "./dist/index.cjs"
33+
}
34+
}
35+
},
36+
"files": [
37+
"dist"
38+
],
39+
"dependencies": {
40+
"express": "^4.19.2",
41+
"openapi-ui-dist": "^2.2.1"
42+
},
43+
"devDependencies": {
44+
"@types/express": "^4.17.21",
45+
"tsup": "^7.2.0",
46+
"vite": "^5.2.10",
47+
"vitest": "^1.6.0"
48+
},
49+
"peerDependencies": {
50+
"express": "^4.0.0"
51+
}
52+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./middleware";

0 commit comments

Comments
 (0)