Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
SAINIAbhishek committed Oct 2, 2024
2 parents acdf947 + e455a0c commit 01723c7
Show file tree
Hide file tree
Showing 13 changed files with 226 additions and 17 deletions.
48 changes: 48 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Add any directories, files, or patterns you don't want to be tracked by version control
.idea

# ignore vs code project config files
.vscode
.vs

# ignore logs
logs
*.log

# ignore 3rd party lib
node_modules

# Ignore built files
build/
dist/

# ignore test converage
coverage/

# git
.gitignore
.git/

.DS_Store

# docker
dockerfile
.dockerignore

# Environment varibles
.env

# Ignore local development files
tmp/
temp/

# Ignore npm debug files
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Ignore output from TypeScript compiler
*.tsbuildinfo

# Ignore eslint cache
.eslintcache
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ PORT=3001
CORS_URL=http://localhost:3000

# Database

# YOUR_MONGO_URI
MONGO_URI=mongodb://localhost:27017/

Expand Down Expand Up @@ -71,6 +72,9 @@ PASSWORD_RESET_TOKEN_VALIDITY_SEC=3600000
TOKEN_ISSUER=api.dev.saini.com
TOKEN_AUDIENCE=dev.saini.com

# make the value production for prod env
MAILTRAP_EMAIL_ENV=testing

# Mailtrap(Email service) Info
MAILTRAP_USERNAME=
MAILTRAP_PASSWORD=
Expand Down
61 changes: 61 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
services:
mongodb:
# To create this service, Compose will pull the mongo
image: mongo:7.0.4
# a custom name for the MongoDB container
container_name: mongo
# Configures the container to restart automatically.
restart: always
# Volumes to persist data and initialize MongoDB
volumes:
# The named volume dbdata will persist the data stored in Mongo’s default data directory, /data/db.
# This will ensure that you don’t lose data in cases where you stop or remove containers.
- dbdata:/data/db
healthcheck:
test:
['CMD', 'mongosh', '--quiet', '--eval', "db.adminCommand('ping').ok"]
interval: 1m
timeout: 10s
retries: 3
start_period: 30s

# To build node image
api:
# This defines the configuration options, including the context and dockerfile,
# that will be applied when Compose builds the application image.
build:
# This defines the build context for the image build
context: ./
args:
NODE_ENV: production
# This is the name we’ll use to refer to this image in Docker commands or to push to a Docker registry.
image: sainiabhishek/nodejs_auth-api:1.1.0
container_name: api
env_file: .env
restart: always
environment:
MONGO_URI: mongodb://mongo:27017/
MONGO_DB_HOST: mongo
TOKEN_ISSUER: api.prod.saini.com
TOKEN_AUDIENCE: prod.saini.com
FRONTEND_RESET_URL: http://localhost:3000/
CORS_URL: http://localhost:3000
MAILTRAP_EMAIL_ENV: testing
ports:
- ${PORT}:3001
depends_on:
mongodb:
condition: service_healthy
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3001/api/v1/healthcheck']
interval: 1m
timeout: 10s
retries: 3
start_period: 30s

# Our top-level volumes key defines the volumes dbdata.
# 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.
# 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.
# 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.
volumes:
dbdata:
59 changes: 59 additions & 0 deletions dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Stage 1: Build Stage
FROM node:20.17.0-slim AS build

# Display build information
RUN echo "!!!!!! Building node application API image !!!!!!"

# Set the working directory inside the build container
WORKDIR /app

# Copy package.json and package-lock.json to the working directory
COPY package*.json ./

# We are installing the same version that we have in the locally
RUN npm ci

# Copy the rest of the application code to the working directory
COPY . .

# Build the application
RUN npm run build

# Remove unnecessary files after the build
RUN rm -rf \
node_modules/.bin \
src \
*.md \
.eslintignore \
.prettierignore \
tsconfig.json \
.prettierrc \
.eslintrc.json

# Stage 2: Production Stage
FROM node:20.17.0-slim AS production

# Install curl
RUN apt-get update && apt-get install -y curl

# Argument and environment variable for production mode
ARG NODE_ENV
ENV NODE_ENV=${NODE_ENV}

# Set the working directory inside the final container
WORKDIR /app

# Copy only the production dependencies and built application from the build stage
COPY --from=build /app/package*.json ./
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/build ./build
COPY --from=build /app/.env.example ./.env

# Remove .env.example file
RUN rm -rf .env.example

# Expose the application port
EXPOSE 3001

# Define the command to run your application
CMD [ "npm", "run", "serve" ]
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "nodejs_auth-api",
"version": "1.0.0",
"description": "",
"version": "1.1.0",
"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.",
"main": "index.js",
"scripts": {
"start": "npm run build && npm run serve",
Expand Down
7 changes: 7 additions & 0 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export const PORT = process.env.PORT;
export const CORS_URL = process.env.CORS_URL?.split(',') || [];
export const API_VERSION = process.env.API_VERSION;
export const FRONTEND_RESET_URL = process.env.FRONTEND_RESET_URL;
export const MAILTRAP_EMAIL_ENV = process.env.MAILTRAP_EMAIL_ENV || "testing";

export const DATE_FORMAT = process.env.DATE_FORMAT || 'yyyy-MM-dd';
export const DATE_FULL_FORMAT =
Expand All @@ -15,6 +16,12 @@ export const MAILTRAP_EMAIL = {
host: process.env.MAILTRAP_TESTING_HOST || '',
port: parseInt(process.env.MAILTRAP_TESTING_PORT || ''),
},
prod: {
username: process.env.MAILTRAP_USERNAME || '',
password: process.env.MAILTRAP_PASSWORD || '',
host: process.env.MAILTRAP_HOST || '',
port: parseInt(process.env.MAILTRAP_PORT || ''),
},
};

export const LIMITER = {
Expand Down
4 changes: 2 additions & 2 deletions src/controllers/EmailController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class EmailController {
};

try {
await EmailHelper.testingEmailTransporter({
await EmailHelper.emailTransporter({
to: email.to,
subject: email.subject,
html: email.content,
Expand Down Expand Up @@ -79,7 +79,7 @@ class EmailController {
};

try {
await EmailHelper.testingEmailTransporter({
await EmailHelper.emailTransporter({
to: email.to,
subject: email.subject,
html: email.content,
Expand Down
13 changes: 13 additions & 0 deletions src/controllers/HealthCheckController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import asyncHandler from 'express-async-handler';
import { SuccessResponse } from '../middleware/ApiResponse';

class HealthCheckController {

checkHealth = asyncHandler(async (req, res) => {
new SuccessResponse('The API is up and running. Health check is passed.', {}).send(res);
});

}


export default new HealthCheckController();
23 changes: 13 additions & 10 deletions src/helpers/EmailHelper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import nodemailer from 'nodemailer';
import { MAILTRAP_EMAIL } from '../config';
import { MAILTRAP_EMAIL, MAILTRAP_EMAIL_ENV } from '../config';
import SMTPTransport from 'nodemailer/lib/smtp-transport';
import Mail from 'nodemailer/lib/mailer';

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

/**
* used to send test emails during development and testing phases.
* used to send emails.
*
* for sending test emails using the Nodemailer library and a service like
* Mailtrap for testing email delivery
* @param options
* Mailtrap for email delivery
* @param options
* @returns
*/
const testingEmailTransporter = async (
const emailTransporter = async (
options: Mail.Options,
): Promise<SMTPTransport.SentMessageInfo> => {
const isProdEnv = MAILTRAP_EMAIL_ENV === "production";

const transporter = nodemailer.createTransport({
host: MAILTRAP_EMAIL.testing.host,
port: MAILTRAP_EMAIL.testing.port,
host: isProdEnv ? MAILTRAP_EMAIL.prod.host : MAILTRAP_EMAIL.testing.host,
port: isProdEnv ? MAILTRAP_EMAIL.prod.port : MAILTRAP_EMAIL.testing.port,
auth: {
user: MAILTRAP_EMAIL.testing.username,
pass: MAILTRAP_EMAIL.testing.password,
user: isProdEnv ? MAILTRAP_EMAIL.prod.username : MAILTRAP_EMAIL.testing.username,
pass: isProdEnv ? MAILTRAP_EMAIL.prod.password : MAILTRAP_EMAIL.testing.password,
},
});

Expand All @@ -46,6 +49,6 @@ const testingEmailTransporter = async (
};

export default {
testingEmailTransporter,
emailFormatter,
emailTransporter
};
12 changes: 12 additions & 0 deletions src/routes/v1/HealthRoutes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import express from 'express';
import HealthCheckController from '../../controllers/HealthCheckController';

const router = express.Router();

router
.route('/')
.get(
HealthCheckController.checkHealth
);

export default router;
3 changes: 3 additions & 0 deletions src/routes/v1/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import express from 'express';
import AuthRoutes from './AuthRoutes';
import UserRoutes from './UserRoutes';
import HealthRoutes from './HealthRoutes';

const router = express.Router();

router.use('/healthcheck', HealthRoutes);

router.use('/oauth', AuthRoutes);
router.use('/users', UserRoutes);

Expand Down
1 change: 0 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
"noFallthroughCasesInSwitch": true, // Prevents fall-through cases in switch statements
"noUncheckedIndexedAccess": true, // Ensures array access is checked for undefined
"declaration": true, // Generates .d.ts files alongside .js files
"composite": true, // Enables project references
"incremental": true // Enables incremental builds for faster compilation
},
"include": ["src/**/*"],
Expand Down

0 comments on commit 01723c7

Please sign in to comment.