File tree Expand file tree Collapse file tree 8 files changed +348
-1
lines changed Expand file tree Collapse file tree 8 files changed +348
-1
lines changed Original file line number Diff line number Diff line change 22
22
"pino-pretty" : " ^7.1.0" ,
23
23
"prom-client" : " ^14.0.0" ,
24
24
"response-time" : " ^2.3.2" ,
25
+ "swagger-jsdoc" : " ^6.1.0" ,
26
+ "swagger-ui-express" : " ^4.1.6" ,
25
27
"zod" : " ^3.9.8"
26
28
},
27
29
"devDependencies" : {
36
38
"@types/node" : " ^16.11.1" ,
37
39
"@types/pino" : " ^6.3.11" ,
38
40
"@types/response-time" : " ^2.3.5" ,
41
+ "@types/swagger-jsdoc" : " ^6.0.1" ,
42
+ "@types/swagger-ui-express" : " ^4.1.3" ,
39
43
"ts-node-dev" : " ^1.1.8" ,
40
44
"typescript" : " ^4.4.4"
41
45
}
Original file line number Diff line number Diff line change @@ -6,6 +6,7 @@ import logger from "./utils/logger";
6
6
import routes from "./routes" ;
7
7
import deserializeUser from "./middleware/deserializeUser" ;
8
8
import { restResponseTimeHistogram , startMetricsServer } from "./utils/metrics" ;
9
+ import swaggerDocs from "./utils/swagger" ;
9
10
10
11
const port = config . get < number > ( "port" ) ;
11
12
@@ -38,4 +39,6 @@ app.listen(port, async () => {
38
39
routes ( app ) ;
39
40
40
41
startMetricsServer ( ) ;
42
+
43
+ swaggerDocs ( app , port ) ;
41
44
} ) ;
Original file line number Diff line number Diff line change @@ -23,8 +23,44 @@ import { createSessionSchema } from "./schema/session.schema";
23
23
import { createUserSchema } from "./schema/user.schema" ;
24
24
25
25
function routes ( app : Express ) {
26
+ /**
27
+ * @openapi
28
+ * /healthcheck:
29
+ * get:
30
+ * tags:
31
+ * - Healthcheck
32
+ * description: Responds if the app is up and running
33
+ * responses:
34
+ * 200:
35
+ * description: App is up and running
36
+ */
26
37
app . get ( "/healthcheck" , ( req : Request , res : Response ) => res . sendStatus ( 200 ) ) ;
27
38
39
+ /**
40
+ * @openapi
41
+ * '/api/users':
42
+ * post:
43
+ * tags:
44
+ * - User
45
+ * summary: Register a user
46
+ * requestBody:
47
+ * required: true
48
+ * content:
49
+ * application/json:
50
+ * schema:
51
+ * $ref: '#/components/schemas/CreateUserInput'
52
+ * responses:
53
+ * 200:
54
+ * description: Success
55
+ * content:
56
+ * application/json:
57
+ * schema:
58
+ * $ref: '#/components/schemas/CreateUserResponse'
59
+ * 409:
60
+ * description: Conflict
61
+ * 400:
62
+ * description: Bad request
63
+ */
28
64
app . post ( "/api/users" , validateResource ( createUserSchema ) , createUserHandler ) ;
29
65
30
66
app . post (
@@ -43,6 +79,28 @@ function routes(app: Express) {
43
79
createProductHandler
44
80
) ;
45
81
82
+ /**
83
+ * @openapi
84
+ * '/api/products/{productId}':
85
+ * get:
86
+ * tags:
87
+ * - Products
88
+ * summary: Get a single product by the productId
89
+ * parameters:
90
+ * - name: productId
91
+ * in: path
92
+ * description: The id of the product
93
+ * required: true
94
+ * responses:
95
+ * 200:
96
+ * description: Success
97
+ * content:
98
+ * application/json:
99
+ * schema:
100
+ * $ref: '#/components/schema/Product'
101
+ * 404:
102
+ * description: Product not found
103
+ */
46
104
app . put (
47
105
"/api/products/:productId" ,
48
106
[ requireUser , validateResource ( updateProductSchema ) ] ,
Original file line number Diff line number Diff line change 1
1
import { object , number , string , TypeOf } from "zod" ;
2
+
3
+ /**
4
+ * @openapi
5
+ * components:
6
+ * schema:
7
+ * Product:
8
+ * type: object
9
+ * required:
10
+ * - title
11
+ * - description
12
+ * - price
13
+ * - image
14
+ * properties:
15
+ * title:
16
+ * type: string
17
+ * description:
18
+ * type: string
19
+ * price:
20
+ * type: number
21
+ * image:
22
+ * type: string
23
+ */
24
+
2
25
const payload = {
3
26
body : object ( {
4
27
title : string ( {
Original file line number Diff line number Diff line change 1
1
import { object , string , TypeOf } from "zod" ;
2
2
3
+ /**
4
+ * @openapi
5
+ * components:
6
+ * schemas:
7
+ * CreateUserInput:
8
+ * type: object
9
+ * required:
10
+ * - email
11
+ * - name
12
+ * - password
13
+ * - passwordConfirmation
14
+ * properties:
15
+ * email:
16
+ * type: string
17
+ * default: jane.doe@example.com
18
+ * name:
19
+ * type: string
20
+ * default: Jane Doe
21
+ * password:
22
+ * type: string
23
+ * default: stringPassword123
24
+ * passwordConfirmation:
25
+ * type: string
26
+ * default: stringPassword123
27
+ * CreateUserResponse:
28
+ * type: object
29
+ * properties:
30
+ * email:
31
+ * type: string
32
+ * name:
33
+ * type: string
34
+ * _id:
35
+ * type: string
36
+ * createdAt:
37
+ * type: string
38
+ * updatedAt:
39
+ * type: string
40
+ */
41
+
3
42
export const createUserSchema = object ( {
4
43
body : object ( {
5
44
name : string ( {
Original file line number Diff line number Diff line change
1
+ import { Express , Request , Response } from "express" ;
2
+ import swaggerJsdoc from "swagger-jsdoc" ;
3
+ import swaggerUi from "swagger-ui-express" ;
4
+ import { version } from "../../package.json" ;
5
+ import log from "./logger" ;
6
+
7
+ const options : swaggerJsdoc . Options = {
8
+ definition : {
9
+ openapi : "3.0.0" ,
10
+ info : {
11
+ title : "REST API Docs" ,
12
+ version,
13
+ } ,
14
+ components : {
15
+ securitySchemas : {
16
+ bearerAuth : {
17
+ type : "http" ,
18
+ scheme : "bearer" ,
19
+ bearerFormat : "JWT" ,
20
+ } ,
21
+ } ,
22
+ } ,
23
+ security : [
24
+ {
25
+ bearerAuth : [ ] ,
26
+ } ,
27
+ ] ,
28
+ } ,
29
+ apis : [ "./src/routes.ts" , "./src/schema/*.ts" ] ,
30
+ } ;
31
+
32
+ const swaggerSpec = swaggerJsdoc ( options ) ;
33
+
34
+ function swaggerDocs ( app : Express , port : number ) {
35
+ // Swagger page
36
+ app . use ( "/docs" , swaggerUi . serve , swaggerUi . setup ( swaggerSpec ) ) ;
37
+
38
+ // Docs in JSON format
39
+ app . get ( "/docs.json" , ( req : Request , res : Response ) => {
40
+ res . setHeader ( "Content-Type" , "application/json" ) ;
41
+ res . send ( swaggerSpec ) ;
42
+ } ) ;
43
+
44
+ log . info ( `Docs available at http://localhost:${ port } /docs` ) ;
45
+ }
46
+
47
+ export default swaggerDocs ;
Original file line number Diff line number Diff line change 33
33
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
34
34
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
35
35
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
36
- // "resolveJsonModule": true, /* Enable importing .json files */
36
+ "resolveJsonModule" : true /* Enable importing .json files */ ,
37
37
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
38
38
39
39
/* JavaScript Support */
You can’t perform that action at this time.
0 commit comments