feat: added swagger for documentation

This commit is contained in:
Hackntosh 2023-10-01 14:47:41 -03:00
parent 2ad6018806
commit 2191b01a93
8 changed files with 2421 additions and 3 deletions

42
package-lock.json generated
View file

@ -26,8 +26,10 @@
"redis": "^4.6.7",
"sharp": "^0.32.3",
"socket.io": "^4.7.2",
"swagger-ui-express": "^5.0.0",
"validator": "^13.9.0",
"winston": "^3.10.0"
"winston": "^3.10.0",
"yaml": "^2.3.2"
},
"devDependencies": {
"@commitlint/cli": "^17.7.2",
@ -45,6 +47,7 @@
"@types/multer-s3": "^3.0.0",
"@types/node": "^20.3.1",
"@types/supertest": "^2.0.12",
"@types/swagger-ui-express": "^4.1.4",
"@types/validator": "^13.7.17",
"@typescript-eslint/eslint-plugin": "^6.7.3",
"@typescript-eslint/parser": "^6.7.3",
@ -3414,6 +3417,16 @@
"@types/superagent": "*"
}
},
"node_modules/@types/swagger-ui-express": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.4.tgz",
"integrity": "sha512-h6dfIPFveCJKpStDtjrB+4pig4DAf9Uu2Z51RB7Fj3s6AifexmqhZxBoG50K/k3Afz7wyXsIAY5ZIDTlC2VjrQ==",
"dev": true,
"dependencies": {
"@types/express": "*",
"@types/serve-static": "*"
}
},
"node_modules/@types/triple-beam": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.3.tgz",
@ -11671,6 +11684,25 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/swagger-ui-dist": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.9.0.tgz",
"integrity": "sha512-NUHSYoe5XRTk/Are8jPJ6phzBh3l9l33nEyXosM17QInoV95/jng8+PuSGtbD407QoPf93MH3Bkh773OgesJpA=="
},
"node_modules/swagger-ui-express": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz",
"integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==",
"dependencies": {
"swagger-ui-dist": ">=5.0.0"
},
"engines": {
"node": ">= v0.10.32"
},
"peerDependencies": {
"express": ">=4.0.0 || >=5.0.0-beta"
}
},
"node_modules/synckit": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
@ -12887,6 +12919,14 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/yaml": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz",
"integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==",
"engines": {
"node": ">= 14"
}
},
"node_modules/yamljs": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz",

View file

@ -45,6 +45,7 @@
"@types/multer-s3": "^3.0.0",
"@types/node": "^20.3.1",
"@types/supertest": "^2.0.12",
"@types/swagger-ui-express": "^4.1.4",
"@types/validator": "^13.7.17",
"@typescript-eslint/eslint-plugin": "^6.7.3",
"@typescript-eslint/parser": "^6.7.3",
@ -85,7 +86,9 @@
"redis": "^4.6.7",
"sharp": "^0.32.3",
"socket.io": "^4.7.2",
"swagger-ui-express": "^5.0.0",
"validator": "^13.9.0",
"winston": "^3.10.0"
"winston": "^3.10.0",
"yaml": "^2.3.2"
}
}

BIN
public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

1826
public/swagger-ui.css Normal file

File diff suppressed because it is too large Load diff

View file

@ -6,11 +6,13 @@ import express from 'express'
import limiter from 'middlewares/rate-limit'
import morganMiddleware from 'middlewares/morgan'
import router from './routes'
import swaggerUI from 'swagger-ui-express'
import swaggerDocument from 'helpers/parse-swagger'
import swaggerConfig from 'config/swagger'
const app = express()
// TODO: test socket io, emit notifications when create one.
// TODO: start to create the client, or a barebone to test socket io
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
@ -24,10 +26,20 @@ app.use(
optionsSuccessStatus: 200,
}),
)
app.use(express.static('public'))
app.use(limiter)
app.use(router)
app.use(
'/docs',
swaggerUI.serve,
swaggerUI.setup(swaggerDocument, swaggerConfig),
)
app.use(compression({ level: 9 }))
app.get('/', function (_req, res) {
res.redirect('/docs')
})
app.use((_req, res) => {
res.status(404).json({
error: 'Endpoint not found',

9
src/config/swagger.ts Normal file
View file

@ -0,0 +1,9 @@
import type { SwaggerUiOptions } from 'swagger-ui-express'
const swaggerConfig: SwaggerUiOptions = {
customCssUrl: '/swagger-ui.css',
customSiteTitle: 'Project Knedita Docs',
customfavIcon: '/favicon.png',
}
export default swaggerConfig

View file

@ -0,0 +1,7 @@
import { parse } from 'yaml'
import { readFileSync } from 'fs'
const swaggerConfigFile = readFileSync('./swagger.yaml', 'utf-8')
const swaggerDocument = parse(swaggerConfigFile)
export default swaggerDocument

521
swagger.yaml Normal file
View file

@ -0,0 +1,521 @@
openapi: 3.0.0
info:
version: 0.0.1
title: Project Knedita - Documentation
description: An open source social media project.
license:
name: MIT
url: https://opensource.org/licenses/MIT
tags:
- name: Users
description: User related endpoints
- name: Posts
description: Post related endpoints
- name: Comments
description: Comment related endpoints
paths:
# Users - GET paths
/user/info:
get:
summary: Returns information about a specific user.
description: Returns information about a specific user (profile picture, display name, etc).
tags:
- Users
parameters:
- name: u
in: query
required: true
schema:
type: string
example: 'cookie'
responses:
'200':
description: An object containing all user information.
content:
application/json:
schema:
type: object
properties:
id:
type: string
profileImage:
type: string
displayName:
type: string
username:
type: string
createdAt:
type: string
followers:
type: integer
example: 0
following:
type: integer
example: 0
posts:
type: array
items:
type: object
properties:
id:
type: string
content:
type: string
createdAt:
type: string
updatedAt:
type: string
likedPosts:
type: array
items:
type: object
properties:
postId:
type: string
'400':
$ref: '#/components/responses/BadRequest'
/user/fetch-posts:
get:
summary: Returns all posts made by specific user.
description: Returns all posts made by specific user.
tags:
- Users
parameters:
- name: u
in: query
required: true
schema:
type: string
example: 'cookie'
responses:
'200':
description: An array of objects containing post information (returns an empty array if no posts were found).
content:
application/json:
schema:
type: array
items:
type: object
properties:
id:
type: string
content:
type: string
createdAt:
type: string
updatedAt:
type: string
author:
type: object
properties:
displayName:
type: string
username:
type: string
profileImage:
type: string
_count:
type: object
properties:
likes:
type: integer
comments:
type: integer
/user/search:
get:
summary: Returns user with the provided username.
description: Returns up to 10 users with the provided username.
tags:
- Users
parameters:
- name: u
in: query
required: true
schema:
type: string
example: 'cookie'
responses:
'200':
description: An array of objects containing basic user information (returns an empty array if no users were found).
content:
application/json:
schema:
type: array
items:
type: object
properties:
displayName:
type: string
username:
type: string
profileImage:
type: string
/user/auth:
post:
summary: Authenticate user
description: Authenticate the provided user
tags:
- Users
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
email:
type: string
password:
type: string
responses:
'200':
description: Returns authentication token and user's username
content:
application/json:
schema:
type: object
properties:
token:
type: string
user:
type: string
example: 'cookie'
'400':
$ref: '#/components/responses/BadRequest'
/user/signup:
post:
summary: Creates a new user
description: Creates a new user
tags:
- Users
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
username:
type: string
email:
type: string
password:
type: string
responses:
'200':
description: An object containing basic user information
content:
application/json:
schema:
type: object
properties:
displayName:
type: string
username:
type: string
createdAt:
type: string
'400':
$ref: '#/components/responses/BadRequest'
# Users - POST paths
/user/delete:
post:
summary: Deletes an authenticated user
description: Deletes an authenticated user
tags:
- Users
security:
- JWTAuth: []
responses:
'200':
$ref: '#/components/responses/EmptyResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/user/follow-user:
post:
summary: Follows a user
description: Follows a user
security:
- JWTAuth: []
tags:
- Users
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
userToFollow:
type: string
example: 'cookie1'
responses:
'200':
$ref: '#/components/responses/EmptyResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/user/like-comment:
post:
summary: Likes a post comment
description: Likes a post comment
security:
- JWTAuth: []
tags:
- Users
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
commentId:
type: string
example: '7fb6e6e7-8e37-4814-bab6-36e5aa35796c'
responses:
'200':
$ref: '#/components/responses/EmptyResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/user/like-post:
post:
summary: Likes a post
description: Likes a post
security:
- JWTAuth: []
tags:
- Users
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
postId:
type: string
example: f4e2b724-f226-4674-8e3b-0c0c512b09d4
responses:
'200':
$ref: '#/components/responses/EmptyResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/user/me:
post:
summary: Returns basic information about the authenticated user
description: Returns basic information about the authenticated user
security:
- JWTAuth: []
tags:
- Users
responses:
'200':
description: Authenticated user information
content:
application/json:
schema:
type: object
properties:
id:
type: string
profileImage:
type: string
displayName:
type: string
username:
type: string
createdAt:
type: string
followers:
type: integer
example: 0
following:
type: integer
example: 0
posts:
type: array
items:
type: object
properties:
id:
type: string
content:
type: string
createdAt:
type: string
updatedAt:
type: string
likedPosts:
type: array
items:
type: object
properties:
postId:
type: string
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
# Users - PUT paths
/user/profile-picture/upload:
put:
summary: Uploads a profile picture for the authenticated user
description: Uploads a profile picture for the authenticated user
security:
- JWTAuth: []
tags:
- Users
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
image:
type: string
format: binary
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
profileImage:
type: string
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/user/update-name:
put:
security:
- JWTAuth: []
tags:
- Users
/user/update-email:
put:
security:
- JWTAuth: []
tags:
- Users
/user/update-password:
put:
security:
- JWTAuth: []
tags:
- Users
# Posts - GET paths
/post/info:
get:
tags:
- Posts
/post/fetch-likes:
get:
tags:
- Posts
# Posts - POST paths
/post/create:
post:
tags:
- Posts
/post/delete:
post:
tags:
- Posts
# Posts - PUT paths
/post/update:
put:
tags:
- Posts
# Comments - GET paths
/comment/info:
get:
tags:
- Comments
/comment/fetch-likes:
get:
tags:
- Comments
# Comments - POST paths
/comment/create:
post:
tags:
- Comments
/comment/delete:
post:
tags:
- Comments
# Comments - PUT paths
/comment/update:
put:
tags:
- Comments
components:
securitySchemes:
JWTAuth:
type: http
scheme: bearer
description: JWT Authentication via Authorization header
responses:
BadRequest:
description: Bad Request
content:
application/json:
schema:
type: object
properties:
error:
type: string
EmptyResponse:
description: Successful Response (empty response)
content:
application/json:
schema:
type: object
Unauthorized:
description: Unauthorized
content:
application/json:
schema:
type: object
properties:
error:
type: string