diff --git a/.gitignore b/.gitignore index 3c3629e..491fc35 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +lib diff --git a/index.ts b/index.ts deleted file mode 100644 index 387fa78..0000000 --- a/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -const lines = ['Hi!', 'This', 'is', 'not', 'yet', 'a', 'server'] -lines.forEach(line => console.info(line)) diff --git a/package.json b/package.json index 86471e3..408c998 100644 --- a/package.json +++ b/package.json @@ -2,13 +2,13 @@ "name": "node-express-typescript-recipes", "version": "0.0.1", "description": "A cookbook full of recipes for developing web apps with Node.js and Express.js in TypeScript", - "main": "index.ts", + "main": "service/index.ts", "engines": { "node": ">=8.15.0", "npm": ">=6.4.1" }, "scripts": { - "start": "ts-node index.ts" + "start": "ts-node service/index.ts" }, "dependencies": { "express": "^4.16.2" diff --git a/service/Application.ts b/service/Application.ts new file mode 100644 index 0000000..da1d587 --- /dev/null +++ b/service/Application.ts @@ -0,0 +1,46 @@ +import { ExpressServer } from './ExpressServer' + +export class Application { + public static async createApplication() { + const expressServer = new ExpressServer() + await expressServer.setup(8000) + Application.handleExit(expressServer) + + return expressServer + } + + private static handleExit(express: ExpressServer) { + process.on('uncaughtException', (err: Error) => { + console.error('Uncaught exception', err) + Application.shutdownProperly(1, express) + }) + process.on('unhandledRejection', (reason: {} | null | undefined) => { + console.error('Unhandled Rejection at promise', reason) + Application.shutdownProperly(2, express) + }) + process.on('SIGINT', () => { + console.info('Caught SIGINT') + Application.shutdownProperly(128 + 2, express) + }) + process.on('SIGTERM', () => { + console.info('Caught SIGTERM') + Application.shutdownProperly(128 + 2, express) + }) + process.on('exit', () => { + console.info('Exiting') + }) + } + + private static shutdownProperly(exitCode: number, express: ExpressServer) { + Promise.resolve() + .then(() => express.kill()) + .then(() => { + console.info('Shutdown complete') + process.exit(exitCode) + }) + .catch(err => { + console.error('Error during shutdown', err) + process.exit(1) + }) + } +} \ No newline at end of file diff --git a/service/ExpressServer.ts b/service/ExpressServer.ts new file mode 100644 index 0000000..9ab2f31 --- /dev/null +++ b/service/ExpressServer.ts @@ -0,0 +1,23 @@ +import * as express from 'express' +import { Express} from 'express' +import { Server } from 'http' + +export class ExpressServer { + private server?: Express + private httpServer?: Server + + public async setup(port: number) { + const server = express() + this.httpServer = this.listen(server, port) + this.server = server + return this.server + } + + public listen(server: Express, port: number) { + return server.listen(port) + } + + public kill() { + if (this.httpServer) this.httpServer.close() + } +} \ No newline at end of file diff --git a/service/index.ts b/service/index.ts new file mode 100644 index 0000000..d6ee6ea --- /dev/null +++ b/service/index.ts @@ -0,0 +1,5 @@ +import { Application } from './Application' + +Application.createApplication().then(() => { + console.info('The application was started! Kill it using Ctrl + C') +}) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..aa04986 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "outDir": "./lib", + "allowJs": false, + "target": "es2017", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "strict": true, + "experimentalDecorators": true, + "jsx": "react", + "importHelpers": true, + "lib": [ "es2017", "dom" ] + }, + "include": [ + "./service/**/*" + ] +}