Skip to content

Commit

Permalink
Add boilerplate for server
Browse files Browse the repository at this point in the history
  • Loading branch information
brian-ngyn committed Feb 26, 2024
1 parent 1e4f9c6 commit b91ca02
Show file tree
Hide file tree
Showing 19 changed files with 1,257 additions and 69 deletions.
2 changes: 2 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ const config = {
"no-eval": "error",
"no-var": "error",
"no-restricted-imports": ["error", { patterns: [".*"] }],
"no-console": ["warn", { allow: ["warn", "error"] }],
"no-debugger": "error",
},
};

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ client/out/

# production
client/build
server/dist

# misc
.DS_Store
Expand Down
7 changes: 1 addition & 6 deletions amplify/backend.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
import { auth } from "@/auth/resource";
import { data } from "@/data/resource";
import { defineBackend } from "@aws-amplify/backend";

defineBackend({
auth,
data,
});
defineBackend({});
8 changes: 1 addition & 7 deletions amplify/data/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,7 @@ specify that owners, authenticated via your Auth resource can "create",
"read", "update", and "delete" their own records. Public users,
authenticated via an API key, can only "read" records.
=========================================================================*/
const schema = a.schema({
Todo: a
.model({
content: a.string(),
})
.authorization([a.allow.owner(), a.allow.public().to(["read"])]),
});
const schema = a.schema({});

export type Schema = ClientSchema<typeof schema>;

Expand Down
9 changes: 5 additions & 4 deletions client/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"type": "module",
"devDependencies": {
"husky": "^9.0.11",
"lint-staged": "^15.2.2",
"pinst": "^3.0.0"
"scripts": {
"dev": "npx next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
}
}
24 changes: 11 additions & 13 deletions client/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"paths": {
"@/*": [
"./src/*",
],
"@/amplify/*": [
"../amplify/*"
]
},
"plugins": [
{
"name": "next"
}
]
"noEmit": true,
"jsx": "preserve",
"baseUrl": "./src"
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/.next/types/**/*.ts",
],
"exclude": [
"../server"
]
}
29 changes: 23 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "concurrently --names client --prefix-colors yellow --kill-others \"cd client && npx next dev\"",
"dev:client": "cd client && npx next dev",
"build": "cd client && next build",
"start": "cd client && next start",
"lint": "cd client && next lint",
"dev": "concurrently --names client,server --prefix-colors yellow,cyan --kill-others \"yarn --cwd client dev\" \"yarn --cwd server dev\"",
"build": "concurrently --names client,server --prefix-colors yellow,cyan --kill-others \"yarn --cwd client build\" \"yarn --cwd server build\"",
"dev:client": "yarn --cwd client dev",
"dev:server": "yarn --cwd server dev",
"build:client": "yarn --cwd client build",
"build:server": "yarn --cwd server build",
"postinstall": "husky install",
"prepack": "pinst --disable",
"postpack": "pinst --enable"
Expand All @@ -16,6 +17,7 @@
"@emotion/react": "^11.11.3",
"@emotion/styled": "^11.11.0",
"@faker-js/faker": "^8.4.1",
"@godaddy/terminus": "^4.12.1",
"@googlemaps/react-wrapper": "^1.1.35",
"@mui/icons-material": "^5.15.11",
"@mui/material": "^5.15.11",
Expand All @@ -24,7 +26,12 @@
"@react-three/postprocessing": "^2.16.0",
"@types/three": "^0.161.2",
"aws-amplify": "^6.0.17",
"axios": "^1.6.7",
"axios-retry": "^4.0.0",
"dotenv": "^16.4.5",
"express": "^4.17.3",
"framer-motion": "^11.0.6",
"jwt-decode": "^4.0.0",
"mapbox-gl": "^3.1.2",
"next": "14.1.0",
"react": "^18",
Expand All @@ -33,14 +40,21 @@
"react-icons": "^5.0.1",
"react-indiana-drag-scroll": "^2.2.0",
"react-map-gl": "^7.1.7",
"three": "^0.161.0"
"three": "^0.161.0",
"uuid": "^9.0.1"
},
"devDependencies": {
"@aws-amplify/backend": "^0.12.1",
"@aws-amplify/backend-cli": "^0.11.1",
"@aws-amplify/backend-output-schemas": "^0.6.0",
"@aws-amplify/data-schema-types": "^0.7.5",
"@aws-amplify/plugin-types": "^0.8.0",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/amplify": "^1.1.28",
"@types/eslint": "^8.56.3",
"@types/express": "^4.17.21",
"@types/googlemaps": "^3.43.3",
"@types/log4js": "^2.3.5",
"@types/node": "^20.11.20",
"@types/prettier": "^3.0.0",
"@types/react": "^18.2.58",
Expand All @@ -61,10 +75,13 @@
"gltf-pipeline": "^4.1.0",
"husky": "^9.0.11",
"lint-staged": "^15.2.2",
"nodemon": "^3.0.1",
"npm-run-all": "^4.1.5",
"postcss": "^8",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.11",
"tailwindcss": "^3.3.0",
"ts-node": "^10.9.1",
"typescript": "^5.3.3"
}
}
22 changes: 22 additions & 0 deletions server/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/** @type {import("eslint").Linter.Config} */
module.exports = {
env: {
node: true,
es2021: true,
},
extends: ["eslint:recommended"],
rules: {
"no-unused-vars": ["warn", { argsIgnorePattern: "_" }],
},
overrides: [
{
env: {
node: true,
},
files: [".eslintrc.{js,cjs}"],
parserOptions: {
sourceType: "script",
},
},
],
};
11 changes: 11 additions & 0 deletions server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"main": "dist/index.js",
"scripts": {
"clean": "rm -rf dist",
"start": "node .",
"build": "npm-run-all clean tsc",
"dev:start": "npm-run-all build start",
"dev": "NODE_ENV=development nodemon --watch src -e ts,ejs --exec npm run dev:start",
"tsc": "tsc -p ./tsconfig.json"
}
}
20 changes: 20 additions & 0 deletions server/src/controllers/health.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { type Request, type Response } from "express";

import { createApplicationLogger } from "@/utils/logger";

export const getHealth = (request: Request, response: Response) => {
const logger = createApplicationLogger(
"health.controller.ts",
request,
response,
);
logger.info(`ENTRY - ${request.method} ${request.url}`);
const data = {
uptime: process.uptime() + " seconds",
message: "OK",
date: new Date(),
};
logger.info(`EXIT - ${request.method} ${request.url} - ${200}`);

return response.status(200).json(data);
};
71 changes: 71 additions & 0 deletions server/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import axios from "axios";
import axiosRetry from "axios-retry";
import dotenv from "dotenv";
import express from "express";
import http from "http";

import router from "@/routes/health.route";
import {
createLightweightApplicationLogger,
shutdownLoggers,
} from "@/utils/logger";
import { type TerminusOptions, createTerminus } from "@godaddy/terminus";

dotenv.config();

const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use("/", router);

const logger = createLightweightApplicationLogger("index.ts");

axiosRetry(axios, {
retries: 2,
retryDelay: (retryCount) => {
return retryCount * 1000; // time interval between retries
},
retryCondition(error) {
return error.code === "ECONNABORTED";
},

onRetry: (retryCount) => {
logger.warn(`Retrying axios call. Retry count: `, retryCount);
},
});

// eslint-disable-next-line @typescript-eslint/require-await
const onSignal = async () => {
logger.info("🚀 Server is starting cleanup");
try {
logger.info("Kafka Consumer Disconnected");
} catch (err) {
logger.error("Error disconnecting the kafka consumer", err as Error);
}
};

// eslint-disable-next-line @typescript-eslint/require-await
const onShutdown = async () => {
logger.info("Cleanup finished, 🚀 server is shutting down");
};

const gracefullyShutdown = (signal: string) => {
logger.info(`${signal} signal received: closing HTTP server.`);
server.close(() => {
logger.info("Closing remaining resources, then closing HTTP server.");
shutdownLoggers(); // Ensure any remaining async writes have finished.
});
};

const terminusOption: TerminusOptions = {
onSignal,
onShutdown,
timeout: 12 * 1000, // waits before closing the server
signals: ["SIGINT", "SIGTERM", "SIGUSR2"],
};

export const server = createTerminus(http.createServer(app), terminusOption);

process.on("SIGQUIT", gracefullyShutdown);

export default app;
9 changes: 9 additions & 0 deletions server/src/routes/health.route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import express from "express";

import * as controllers from "@/controllers/health.controller";

const router = express.Router();

router.get("/health", controllers.getHealth);

export default router;
19 changes: 19 additions & 0 deletions server/src/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import server from "@/index.js";
import { createLightweightApplicationLogger } from "@/utils/logger";

const logger = createLightweightApplicationLogger("server.ts");
const port = process.env.SERVER_PORT;

server
.listen(port, () => {
logger.info(`Server is listening on port ${port}`);

logger.info(`Process ID: ${process.pid}`);
logger.info(`Node Version: ${process.version}`);
logger.info(`Server Port: ${port}`);
logger.info(`Debug Port: ${process.debugPort}`);
})
.on("error", (error: Error) => {
logger.error(error.message);
throw error;
});
11 changes: 11 additions & 0 deletions server/src/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import dotenv from "dotenv";

dotenv.config();

// any constants go here
export const environment = {
nodeEnv: process.env.ENV || process.env.NODE_ENV,
logDir: process.env.LOG_DIR || "logs",
logLevel: process.env.LOG_LEVEL || "info",
logFile: process.env.LOG_FILE || "app.log",
};
Loading

0 comments on commit b91ca02

Please sign in to comment.