diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..91d4a0a --- /dev/null +++ b/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["@babel/env"], + "plugins": ["@babel/plugin-proposal-object-rest-spread"] + } \ No newline at end of file diff --git a/.eslistrc.js b/.eslistrc.js new file mode 100644 index 0000000..311d72f --- /dev/null +++ b/.eslistrc.js @@ -0,0 +1,36 @@ +module.exports = { + "env": { + "es6": true, + "node": true + }, + "extends": "airbnb-base", + "parserOptions": { + "ecmaVersion": 2021, + "sourceType": "module" + }, + "rules": { + "indent": [ + "error", + 2 + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "double" + ], + "semi": [ + "error", + "always" + ], + "no-unused-vars": [ + "error", { "caughtErrors": "all" } + ], + "no-param-reassign": 0, + "max-len": 0, + "strict": 0, + "no-console": 0 + } + }; \ No newline at end of file diff --git a/package.json b/package.json index 971cf2d..caaf8cc 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,11 @@ "description": "nodejs service", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "build": "npm run clean && npm run build-server", + "build-server": "./node_modules/.bin/babel src -d ./dist --copy-files --source-maps", + "clean": "./node_modules/.bin/rimraf ./dist && ./node_modules/.bin/mkdirp ./dist", + "start": "node ./dist/index.js", + "dev": "babel-watch src/index.js" }, "repository": { "type": "git", @@ -20,8 +24,24 @@ }, "homepage": "https://github.com/eatrisno/nodejs-service#readme", "dependencies": { + "body-parser": "^1.19.0", "core-js": "^3.15.2", "express": "^4.17.1", + "express-request-id": "^1.4.1", "regenerator-runtime": "^0.13.7" + }, + "devDependencies": { + "@babel/cli": "^7.14.3", + "@babel/core": "^7.14.3", + "@babel/plugin-proposal-object-rest-spread": "^7.14.2", + "@babel/preset-env": "^7.14.2", + "@babel/register": "^7.13.16", + "babel-watch": "^7.4.1", + "eslint": "^7.30.0", + "eslint-config-airbnb-base": "^14.2.1", + "eslint-plugin-import": "^2.23.4", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2", + "source-map-support": "^0.5.19" } } diff --git a/src/config.js b/src/config.js new file mode 100644 index 0000000..52356d5 --- /dev/null +++ b/src/config.js @@ -0,0 +1,19 @@ +"use strict"; + +import pack from "../package.json"; + +const env = process.env.NODE_ENV || "development"; + +export default { + env, + isDev: env === "development", + + port: "PORT" in process.env ? (Number(process.env.PORT) + ("NODE_APP_INSTANCE" in process.env ? Number(process.env.NODE_APP_INSTANCE) : 0)) : 8000, + host: process.env.HOST || (env === "development" ? "0.0.0.0" : "127.0.0.1"), + + server: { + name: process.env.SERVER_NAME || pack.name, + version: process.env.SERVER_VERSION || pack.version, + }, + +}; \ No newline at end of file diff --git a/src/controllers/system.js b/src/controllers/system.js new file mode 100644 index 0000000..f995360 --- /dev/null +++ b/src/controllers/system.js @@ -0,0 +1,26 @@ +"use strict"; + +import config from "../config"; + +function ok(req, res, next) { + res.status(200).json({ success: true }); + return next(); +} + +function getHealth(req, res, next) { + const info = { + pid: process.pid, + name: config.server.name.toUpperCase(), + version: config.server.version, + port: config.port, + uptimeSec: process.uptime(), + }; + + res.status(200).json(info); + return next(); +} + +export default { + ok, + getHealth, +}; \ No newline at end of file diff --git a/src/routes/index.js b/src/routes/index.js new file mode 100644 index 0000000..aa5d7b0 --- /dev/null +++ b/src/routes/index.js @@ -0,0 +1,11 @@ +"use strict"; + +import express from "express"; + +import systemRouter from "./system"; + +const router = express.Router(); + +router.use("", systemRouter); + +export default router; \ No newline at end of file diff --git a/src/routes/system.js b/src/routes/system.js new file mode 100644 index 0000000..e5c55d7 --- /dev/null +++ b/src/routes/system.js @@ -0,0 +1,11 @@ +"use strict"; + +import express from "express"; +import systemCtrl from "../controllers/system"; + +const router = express.Router(); + +router.route("/ok").get(systemCtrl.ok); +router.route("/health").get(systemCtrl.getHealth); + +export default router; \ No newline at end of file diff --git a/src/server.js b/src/server.js index afca6ac..41efe32 100644 --- a/src/server.js +++ b/src/server.js @@ -1,8 +1,47 @@ +"use strict"; + +import bodyParser from "body-parser"; import express from "express"; +import addRequestId from "express-request-id"; +import config from "./config"; import router from "./routes/index"; +process.title = config.server.name; + const server = express(); +server.use(addRequestId()); +server.use(bodyParser.json()); +server.use(bodyParser.urlencoded({ extended: true })); + +server.use("*", (req, res, next) => { + const data = req.method === "GET" ? req.query : req.body; + + console.log("HTTP", req.method, req.baseUrl, data); + + return next(); +}); + +server.use("", router); + +async function init() { + console.log("Launching node app"); + + const serverInstance = server.listen(config.port, config.host, () => { + console.log(`${config.server.name.toUpperCase()} v${config.server.version} listening at ${config.host}:${config.port}`); + }); + + process.on("SIGINT", () => { + console.log("Stopping server"); + serverInstance.close(() => { + console.log("Server stopped"); + process.exit(0); + }); + }); +} +export default { + init, +}; \ No newline at end of file