├── .gitignore ├── README.md ├── tsoa.json ├── tsconfig.json ├── src ├── controllers │ └── ping.ts ├── routes │ └── index.ts └── index.ts ├── package.json └── public └── swagger.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # super-duper-octo-couscous 2 | REST API with Express, TypeScript and Swagger 3 | -------------------------------------------------------------------------------- /tsoa.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryFile": "src/index.ts", 3 | "noImplicitAdditionalProperties": "throw-on-extras", 4 | "spec": { 5 | "outputDirectory": "public", 6 | "specVersion": 3 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "outDir": "./build", 6 | "strict": true, 7 | "esModuleInterop": true, 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/controllers/ping.ts: -------------------------------------------------------------------------------- 1 | import { Get, Route } from "tsoa"; 2 | 3 | interface PingResponse { 4 | message: string; 5 | } 6 | 7 | @Route("ping") 8 | export default class PingController { 9 | @Get("/") 10 | public async getMessage(): Promise { 11 | return { 12 | message: "hello", 13 | }; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/routes/index.ts: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import PingController from "../controllers/ping"; 3 | 4 | const router = express.Router(); 5 | 6 | router.get("/ping", async (_req, res) => { 7 | const controller = new PingController(); 8 | const response = await controller.getMessage(); 9 | return res.send(response); 10 | }); 11 | 12 | export default router; 13 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import express, { Application, Request, Response } from "express"; 2 | import morgan from "morgan"; 3 | import swaggerUi from "swagger-ui-express"; 4 | 5 | import Router from "./routes"; 6 | 7 | const PORT = process.env.PORT || 8000; 8 | 9 | const app: Application = express(); 10 | 11 | app.use(express.json()); 12 | app.use(morgan("tiny")); 13 | app.use(express.static("public")); 14 | 15 | app.use( 16 | "/docs", 17 | swaggerUi.serve, 18 | swaggerUi.setup(undefined, { 19 | swaggerOptions: { 20 | url: "/swagger.json", 21 | }, 22 | }) 23 | ); 24 | app.listen(PORT, () => { 25 | console.log("Server is running on port", PORT); 26 | }); 27 | 28 | app.use(Router); 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-typescript", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node build/index.js", 8 | "predev": "npm run swagger", 9 | "prebuild": "npm run swagger", 10 | "build": "tsc", 11 | "dev": "concurrently \"nodemon\" \"nodemon -x tsoa spec\"", 12 | "swagger": "tsoa spec", 13 | "test": "echo \"Error: no test specified\" && exit 1" 14 | }, 15 | "nodemonConfig": { 16 | "watch": [ 17 | "src" 18 | ], 19 | "ext": "ts", 20 | "exec": "ts-node src/index.ts" 21 | }, 22 | "keywords": [], 23 | "author": "", 24 | "license": "ISC", 25 | "devDependencies": { 26 | "@types/express": "^4.17.13", 27 | "@types/morgan": "^1.9.3", 28 | "@types/node": "^17.0.19", 29 | "@types/swagger-ui-express": "^4.1.3", 30 | "concurrently": "^7.0.0", 31 | "nodemon": "^2.0.15", 32 | "ts-node": "^10.5.0", 33 | "typescript": "^4.5.5" 34 | }, 35 | "dependencies": { 36 | "express": "^4.17.3", 37 | "morgan": "^1.10.0", 38 | "swagger-ui-express": "^4.3.0", 39 | "tsoa": "^3.14.1" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /public/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "components": { 3 | "examples": {}, 4 | "headers": {}, 5 | "parameters": {}, 6 | "requestBodies": {}, 7 | "responses": {}, 8 | "schemas": { 9 | "PingResponse": { 10 | "properties": { 11 | "message": { 12 | "type": "string" 13 | } 14 | }, 15 | "required": [ 16 | "message" 17 | ], 18 | "type": "object", 19 | "additionalProperties": false 20 | } 21 | }, 22 | "securitySchemes": {} 23 | }, 24 | "info": { 25 | "title": "express-typescript", 26 | "version": "1.0.0", 27 | "license": { 28 | "name": "ISC" 29 | }, 30 | "contact": {} 31 | }, 32 | "openapi": "3.0.0", 33 | "paths": { 34 | "/ping": { 35 | "get": { 36 | "operationId": "GetMessage", 37 | "responses": { 38 | "200": { 39 | "description": "Ok", 40 | "content": { 41 | "application/json": { 42 | "schema": { 43 | "$ref": "#/components/schemas/PingResponse" 44 | } 45 | } 46 | } 47 | } 48 | }, 49 | "security": [], 50 | "parameters": [] 51 | } 52 | } 53 | }, 54 | "servers": [ 55 | { 56 | "url": "/" 57 | } 58 | ] 59 | } --------------------------------------------------------------------------------