Skip to content

Commit

Permalink
feat: ✨ adding openapi-typescript lib and configuring it
Browse files Browse the repository at this point in the history
  • Loading branch information
louiscavalcante committed Jan 20, 2024
1 parent e8985a2 commit 7af7bf7
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 16 deletions.
10 changes: 9 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,13 @@
"alphabetize": { "order": "asc", "ignoreCase": true }
}
]
}
},
"overrides": [
{
"files": ["./src/docs/openapi-schema.d.ts"],
"rules": {
"@typescript-eslint/naming-convention": "off"
}
}
]
}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ $ npm run dev:requirements
This will fix everything and let you know if you forgot about any error.<br>
It will also run tests that were created or modified.

- Every time you update the `openapi.yaml` file, you need to run the `npm run update:openapi` script, to keep `openapi-schema.d.ts` updated, so you can use the openapi's schemas as types for this application.

- The `error-handler.middleware` will handle all errors, this also includes any unknown routes by the `openapi.yaml` and the errors thrown by the classes `DomainError` and `AxiosRequestError`.<br>
When `NODE_ENV` is set to `production`. It will NOT interfere with the logs, but will change the error response to:<br>
`http status 500` and the body response to: `Something bad happened`<br>
Expand Down
60 changes: 60 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"scripts": {
"build": "babel src --extensions \".js,.ts\" --out-dir dist --copy-files --no-copy-ignored",
"start": "node dist/app.js",
"update:openapi": "npx openapi-typescript ./src/docs/openapi.yaml -o ./src/docs/openapi-schema.d.ts",
"dev:requirements": "rm -rf ./.husky && npx mrm lint-staged && npm pkg delete scripts.prepare && npm pkg delete 'lint-staged[*.js]' && npm pkg delete 'lint-staged[*.{js,css,md}]'",
"dev": "ts-node-dev --env-file=./environments/.env -r tsconfig-paths/register --respawn --transpile-only --cls src/app.ts",
"test": "jest --config ./jest/jest.run-all-config.js --detectOpenHandles --runInBand --forceExit",
Expand Down Expand Up @@ -60,6 +61,7 @@
"husky": "^8.0.0",
"jest": "^29.7.0",
"lint-staged": "^15.2.0",
"openapi-typescript": "^6.7.4",
"prettier": "^3.1.1",
"supertest": "^6.3.3",
"ts-jest": "^29.1.1",
Expand Down
2 changes: 1 addition & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default class App {
OpenApiValidator.middleware({
apiSpec: path.join(__dirname, 'docs/openapi.yaml'),
validateRequests: true,
validateResponses: false,
validateResponses: true,
validateSecurity: false,
})
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { paths } from '@docs/openapi-schema'

export type GetUsersSuccessResponse = paths['/users']['get']['responses'][200]['content']['application/json']
7 changes: 4 additions & 3 deletions src/application/controllers/users.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import express, { Router, Request, Response, NextFunction } from 'express'

import { IControllers } from '@application/controllers/interfaces/controllers.interface'
import { GetUsersSuccessResponse } from '@application/controllers/interfaces/users.controller.interface'
import { IUsersService } from '@domain/services/interfaces/users.service.interface'

export default class UsersController implements IControllers {
Expand All @@ -18,11 +19,11 @@ export default class UsersController implements IControllers {
return this.router.get('/users', this.getUsers)
}

private getUsers = async (req: Request, res: Response, next: NextFunction): Promise<Response | void> => {
private getUsers = async (_req: Request, res: Response, next: NextFunction): Promise<void> => {
try {
const results = await this.service.getUsers()
const users: GetUsersSuccessResponse = await this.service.getUsers()

return res.status(200).send(results)
res.status(200).send(users)
} catch (error) {
next(error)
}
Expand Down
59 changes: 59 additions & 0 deletions src/docs/openapi-schema.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* This file was auto-generated by openapi-typescript.
* Do not make direct changes to the file.
*/

export interface paths {
'/users': {
/** @description Get users */
get: {
responses: {
/** @description OK */
200: {
content: {
'application/json': components['schemas']['User'][]
}
}
/** @description Unexpected error */
default: {
content: {
'application/json': components['schemas']['Error']
}
}
}
}
}
}

export type webhooks = Record<string, never>

export interface components {
schemas: {
Error: {
message: string
stack?: string
axiosError?: string
}
User: {
name?: string
}
}
responses: {
/** @description Unauthorized */
Unauthorized: {
content: {
'application/json': components['schemas']['Error']
}
}
}
parameters: never
requestBodies: never
headers: never
pathItems: never
}

export type $defs = Record<string, never>

export type external = Record<string, never>

export type operations = Record<string, never>
27 changes: 17 additions & 10 deletions src/docs/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ info:
title: microservice-name
description: microservice
version: '1.0'
security:
- basicAuth: []

servers:
- url: 'http://localhost/api'
description: development
Expand All @@ -22,25 +21,24 @@ paths:
Get users
responses:
'200':
description: Successful request
description: OK
content:
application/json:
schema:
type: array
items:
type: object
additionalProperties: false
properties:
name:
type: string
$ref: '#/components/schemas/User'

default:
description: Invalid request
description: Errors
content:
application/json:
schema:
$ref: '#/components/schemas/Error'

security:
- basicAuth: []

components:
securitySchemes:
basicAuth:
Expand All @@ -52,7 +50,16 @@ components:
properties:
message:
type: string
error:
stack:
type: string
axiosError:
type: string
required:
- message

User:
type: object
additionalProperties: false
properties:
name:
type: string
2 changes: 1 addition & 1 deletion src/domain/services/users.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ import { IUsersService } from '@domain/services/interfaces/users.service.interfa

export default class UsersService implements IUsersService {
public async getUsers(): Promise<any> {
return ['Luiz', 'Jose']
return [{ name: 'Luiz' }, { name: 'Jose' }]
}
}

0 comments on commit 7af7bf7

Please sign in to comment.