Skip to content

Commit 01723c7

Browse files
committed
2 parents acdf947 + e455a0c commit 01723c7

File tree

13 files changed

+226
-17
lines changed

13 files changed

+226
-17
lines changed

.dockerignore

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Add any directories, files, or patterns you don't want to be tracked by version control
2+
.idea
3+
4+
# ignore vs code project config files
5+
.vscode
6+
.vs
7+
8+
# ignore logs
9+
logs
10+
*.log
11+
12+
# ignore 3rd party lib
13+
node_modules
14+
15+
# Ignore built files
16+
build/
17+
dist/
18+
19+
# ignore test converage
20+
coverage/
21+
22+
# git
23+
.gitignore
24+
.git/
25+
26+
.DS_Store
27+
28+
# docker
29+
dockerfile
30+
.dockerignore
31+
32+
# Environment varibles
33+
.env
34+
35+
# Ignore local development files
36+
tmp/
37+
temp/
38+
39+
# Ignore npm debug files
40+
npm-debug.log*
41+
yarn-debug.log*
42+
yarn-error.log*
43+
44+
# Ignore output from TypeScript compiler
45+
*.tsbuildinfo
46+
47+
# Ignore eslint cache
48+
.eslintcache

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ PORT=3001
1414
CORS_URL=http://localhost:3000
1515

1616
# Database
17+
1718
# YOUR_MONGO_URI
1819
MONGO_URI=mongodb://localhost:27017/
1920

@@ -71,6 +72,9 @@ PASSWORD_RESET_TOKEN_VALIDITY_SEC=3600000
7172
TOKEN_ISSUER=api.dev.saini.com
7273
TOKEN_AUDIENCE=dev.saini.com
7374

75+
# make the value production for prod env
76+
MAILTRAP_EMAIL_ENV=testing
77+
7478
# Mailtrap(Email service) Info
7579
MAILTRAP_USERNAME=
7680
MAILTRAP_PASSWORD=

docker-compose.yaml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
services:
2+
mongodb:
3+
# To create this service, Compose will pull the mongo
4+
image: mongo:7.0.4
5+
# a custom name for the MongoDB container
6+
container_name: mongo
7+
# Configures the container to restart automatically.
8+
restart: always
9+
# Volumes to persist data and initialize MongoDB
10+
volumes:
11+
# The named volume dbdata will persist the data stored in Mongo’s default data directory, /data/db.
12+
# This will ensure that you don’t lose data in cases where you stop or remove containers.
13+
- dbdata:/data/db
14+
healthcheck:
15+
test:
16+
['CMD', 'mongosh', '--quiet', '--eval', "db.adminCommand('ping').ok"]
17+
interval: 1m
18+
timeout: 10s
19+
retries: 3
20+
start_period: 30s
21+
22+
# To build node image
23+
api:
24+
# This defines the configuration options, including the context and dockerfile,
25+
# that will be applied when Compose builds the application image.
26+
build:
27+
# This defines the build context for the image build
28+
context: ./
29+
args:
30+
NODE_ENV: production
31+
# This is the name we’ll use to refer to this image in Docker commands or to push to a Docker registry.
32+
image: sainiabhishek/nodejs_auth-api:1.1.0
33+
container_name: api
34+
env_file: .env
35+
restart: always
36+
environment:
37+
MONGO_URI: mongodb://mongo:27017/
38+
MONGO_DB_HOST: mongo
39+
TOKEN_ISSUER: api.prod.saini.com
40+
TOKEN_AUDIENCE: prod.saini.com
41+
FRONTEND_RESET_URL: http://localhost:3000/
42+
CORS_URL: http://localhost:3000
43+
MAILTRAP_EMAIL_ENV: testing
44+
ports:
45+
- ${PORT}:3001
46+
depends_on:
47+
mongodb:
48+
condition: service_healthy
49+
healthcheck:
50+
test: ['CMD', 'curl', '-f', 'http://localhost:3001/api/v1/healthcheck']
51+
interval: 1m
52+
timeout: 10s
53+
retries: 3
54+
start_period: 30s
55+
56+
# Our top-level volumes key defines the volumes dbdata.
57+
# When Docker creates volumes, the contents of the volume are stored in a part of the host filesystem, /var/lib/docker/volumes/, that’s managed by Docker.
58+
# The contents of each volume are stored in a directory under /var/lib/docker/volumes/ and get mounted to any container that uses the volume.
59+
# In this way, the data that our users will create will persist in the dbdata volume even if we remove and recreate the db container.
60+
volumes:
61+
dbdata:

dockerfile

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Stage 1: Build Stage
2+
FROM node:20.17.0-slim AS build
3+
4+
# Display build information
5+
RUN echo "!!!!!! Building node application API image !!!!!!"
6+
7+
# Set the working directory inside the build container
8+
WORKDIR /app
9+
10+
# Copy package.json and package-lock.json to the working directory
11+
COPY package*.json ./
12+
13+
# We are installing the same version that we have in the locally
14+
RUN npm ci
15+
16+
# Copy the rest of the application code to the working directory
17+
COPY . .
18+
19+
# Build the application
20+
RUN npm run build
21+
22+
# Remove unnecessary files after the build
23+
RUN rm -rf \
24+
node_modules/.bin \
25+
src \
26+
*.md \
27+
.eslintignore \
28+
.prettierignore \
29+
tsconfig.json \
30+
.prettierrc \
31+
.eslintrc.json
32+
33+
# Stage 2: Production Stage
34+
FROM node:20.17.0-slim AS production
35+
36+
# Install curl
37+
RUN apt-get update && apt-get install -y curl
38+
39+
# Argument and environment variable for production mode
40+
ARG NODE_ENV
41+
ENV NODE_ENV=${NODE_ENV}
42+
43+
# Set the working directory inside the final container
44+
WORKDIR /app
45+
46+
# Copy only the production dependencies and built application from the build stage
47+
COPY --from=build /app/package*.json ./
48+
COPY --from=build /app/node_modules ./node_modules
49+
COPY --from=build /app/build ./build
50+
COPY --from=build /app/.env.example ./.env
51+
52+
# Remove .env.example file
53+
RUN rm -rf .env.example
54+
55+
# Expose the application port
56+
EXPOSE 3001
57+
58+
# Define the command to run your application
59+
CMD [ "npm", "run", "serve" ]

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "nodejs_auth-api",
3-
"version": "1.0.0",
4-
"description": "",
3+
"version": "1.1.0",
4+
"description": "A backend authentication & authorization project to handle the scale and complexity of an application. It is design while keeping the different environments in the mind.",
55
"main": "index.js",
66
"scripts": {
77
"start": "npm run build && npm run serve",

src/config/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export const PORT = process.env.PORT;
33
export const CORS_URL = process.env.CORS_URL?.split(',') || [];
44
export const API_VERSION = process.env.API_VERSION;
55
export const FRONTEND_RESET_URL = process.env.FRONTEND_RESET_URL;
6+
export const MAILTRAP_EMAIL_ENV = process.env.MAILTRAP_EMAIL_ENV || "testing";
67

78
export const DATE_FORMAT = process.env.DATE_FORMAT || 'yyyy-MM-dd';
89
export const DATE_FULL_FORMAT =
@@ -15,6 +16,12 @@ export const MAILTRAP_EMAIL = {
1516
host: process.env.MAILTRAP_TESTING_HOST || '',
1617
port: parseInt(process.env.MAILTRAP_TESTING_PORT || ''),
1718
},
19+
prod: {
20+
username: process.env.MAILTRAP_USERNAME || '',
21+
password: process.env.MAILTRAP_PASSWORD || '',
22+
host: process.env.MAILTRAP_HOST || '',
23+
port: parseInt(process.env.MAILTRAP_PORT || ''),
24+
},
1825
};
1926

2027
export const LIMITER = {

src/controllers/EmailController.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class EmailController {
2929
};
3030

3131
try {
32-
await EmailHelper.testingEmailTransporter({
32+
await EmailHelper.emailTransporter({
3333
to: email.to,
3434
subject: email.subject,
3535
html: email.content,
@@ -79,7 +79,7 @@ class EmailController {
7979
};
8080

8181
try {
82-
await EmailHelper.testingEmailTransporter({
82+
await EmailHelper.emailTransporter({
8383
to: email.to,
8484
subject: email.subject,
8585
html: email.content,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import asyncHandler from 'express-async-handler';
2+
import { SuccessResponse } from '../middleware/ApiResponse';
3+
4+
class HealthCheckController {
5+
6+
checkHealth = asyncHandler(async (req, res) => {
7+
new SuccessResponse('The API is up and running. Health check is passed.', {}).send(res);
8+
});
9+
10+
}
11+
12+
13+
export default new HealthCheckController();

src/helpers/EmailHelper.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import nodemailer from 'nodemailer';
2-
import { MAILTRAP_EMAIL } from '../config';
2+
import { MAILTRAP_EMAIL, MAILTRAP_EMAIL_ENV } from '../config';
33
import SMTPTransport from 'nodemailer/lib/smtp-transport';
44
import Mail from 'nodemailer/lib/mailer';
55

@@ -19,21 +19,24 @@ const emailFormatter = (content: string, firstname = '') => {
1919
};
2020

2121
/**
22-
* used to send test emails during development and testing phases.
22+
* used to send emails.
2323
*
2424
* for sending test emails using the Nodemailer library and a service like
25-
* Mailtrap for testing email delivery
26-
* @param options
25+
* Mailtrap for email delivery
26+
* @param options
27+
* @returns
2728
*/
28-
const testingEmailTransporter = async (
29+
const emailTransporter = async (
2930
options: Mail.Options,
3031
): Promise<SMTPTransport.SentMessageInfo> => {
32+
const isProdEnv = MAILTRAP_EMAIL_ENV === "production";
33+
3134
const transporter = nodemailer.createTransport({
32-
host: MAILTRAP_EMAIL.testing.host,
33-
port: MAILTRAP_EMAIL.testing.port,
35+
host: isProdEnv ? MAILTRAP_EMAIL.prod.host : MAILTRAP_EMAIL.testing.host,
36+
port: isProdEnv ? MAILTRAP_EMAIL.prod.port : MAILTRAP_EMAIL.testing.port,
3437
auth: {
35-
user: MAILTRAP_EMAIL.testing.username,
36-
pass: MAILTRAP_EMAIL.testing.password,
38+
user: isProdEnv ? MAILTRAP_EMAIL.prod.username : MAILTRAP_EMAIL.testing.username,
39+
pass: isProdEnv ? MAILTRAP_EMAIL.prod.password : MAILTRAP_EMAIL.testing.password,
3740
},
3841
});
3942

@@ -46,6 +49,6 @@ const testingEmailTransporter = async (
4649
};
4750

4851
export default {
49-
testingEmailTransporter,
5052
emailFormatter,
53+
emailTransporter
5154
};

src/routes/v1/HealthRoutes.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import express from 'express';
2+
import HealthCheckController from '../../controllers/HealthCheckController';
3+
4+
const router = express.Router();
5+
6+
router
7+
.route('/')
8+
.get(
9+
HealthCheckController.checkHealth
10+
);
11+
12+
export default router;

src/routes/v1/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import express from 'express';
22
import AuthRoutes from './AuthRoutes';
33
import UserRoutes from './UserRoutes';
4+
import HealthRoutes from './HealthRoutes';
45

56
const router = express.Router();
67

8+
router.use('/healthcheck', HealthRoutes);
9+
710
router.use('/oauth', AuthRoutes);
811
router.use('/users', UserRoutes);
912

tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
"noFallthroughCasesInSwitch": true, // Prevents fall-through cases in switch statements
2424
"noUncheckedIndexedAccess": true, // Ensures array access is checked for undefined
2525
"declaration": true, // Generates .d.ts files alongside .js files
26-
"composite": true, // Enables project references
2726
"incremental": true // Enables incremental builds for faster compilation
2827
},
2928
"include": ["src/**/*"],

0 commit comments

Comments
 (0)