Skip to content

Commit

Permalink
Create an internal lib for configuration (#443)
Browse files Browse the repository at this point in the history
* feat: use external config as library

* deps: update nx deps

* revert

* fix: volume

* fix: some syntax

* fix: remove args from docker compose

---------

Co-authored-by: orig <[email protected]>
Co-authored-by: orig <[email protected]>
  • Loading branch information
3 people authored Sep 15, 2023
1 parent 6951e82 commit 136eeb6
Show file tree
Hide file tree
Showing 47 changed files with 8,760 additions and 9,303 deletions.
35 changes: 35 additions & 0 deletions .example.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# General
BACKEND_APP_PORT=3000
FRONTEND_APP_PORT=5000
NODE_ENV=development

# RATE LIMIT
RATE_LIMIT_TTL=60
RATE_LIMIT_COUNT=10

# LOGGER
LOGGER_CONSOLE_THRESHOLD=INFO # DEBUG, INFO, WARN, ERROR, FATAL

# FRONTEND
DOMAIN=localhost
CLIENTSIDE_API_DOMAIN=http://localhost:3000 # Use this verible, while making client side API calls
API_DOMAIN=http://localhost:3000 # If you are running with docker compose change this to http://backend:3000

# DATABASE
# If you are running with docker compose change host to postgres
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/reduced_to_db?schema=public"

# REDIS
REDIS_ENABLE=false
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=password
REDIS_TTL=604800000 # 1 week in milliseconds

# AUTH
JWT_ACCESS_SECRET=abc1234
JWT_REFRESH_SECRET=abc1234

# NOVU - You don't need this when running locally (just verify your email from the database)
NOVU_API_KEY=Get it from https://novu.co/

9 changes: 6 additions & 3 deletions apps/backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
Dockerfile
.dockerignore
node_modules
dist
npm-debug.log
dist
CONTRIBUTE.MD
README.md
.gitignore
LICENSE
.DS_Store
30 changes: 0 additions & 30 deletions apps/backend/.env.example

This file was deleted.

16 changes: 10 additions & 6 deletions apps/backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
# Dependencies Stage
# --------------------------------------------
FROM node:19.2-alpine3.15 as dependencies

WORKDIR /app
COPY package.json package-lock.json ./

COPY package*.json ./

RUN apk add --update python3 make g++\
&& rm -rf /var/cache/apk/*
Expand All @@ -24,20 +24,24 @@ COPY --from=dependencies /app/node_modules ./node_modules
# Run prisma generate & build the bundle in production mode
RUN npx nx build backend --prod --skip-nx-cache


# --------------------------------------------
# Production Stage
# --------------------------------------------
FROM node:19.2-alpine3.15 as production
WORKDIR /app

COPY --from=build /app/dist/apps/backend ./backend
COPY --from=build /app/dist/libs/prisma ./prisma
COPY --from=build /app/node_modules ./node_modules
COPY ./libs/ ./libs/
COPY ./nx.json ./nx.json
COPY --from=build /app/libs/ ./libs

EXPOSE 3000

# Start the application
CMD sh -c "npx nx migrate-deploy prisma && node backend/main.js"







3 changes: 1 addition & 2 deletions apps/backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import { APP_GUARD } from '@nestjs/core';
import { ThrottlerModule } from '@nestjs/throttler';
import { AuthModule } from './auth/auth.module';
import { AppCacheModule } from './cache/cache.module';
import { AppConfigModule } from './config/config.module';
import { AppConfigService } from './config/config.service';
import { AppConfigModule, AppConfigService } from '@reduced.to/config';
import { AppLoggerModule } from './logger/logger.module';
import { NovuModule } from './novu/novu.module';
import { PrismaService } from '@reduced.to/prisma';
Expand Down
8 changes: 4 additions & 4 deletions apps/backend/src/auth/auth.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { NovuService } from '../novu/novu.service';
import { PrismaService } from '@reduced.to/prisma';
import { AppConfigService } from '../config/config.service';
import { AppConfigService, Configuration } from '@reduced.to/config';
import { SignupDto } from './dto/signup.dto';
import { UserContext } from './interfaces/user-context';
import { LocalAuthGuard } from './guards/local.guard';
Expand Down Expand Up @@ -36,9 +36,9 @@ describe('AuthController', () => {
};

const MOCK_TOKENS = { accessToken: 'access_token', refreshToken: 'refresh_token' };
const MOCK_CONFIG = {
front: { domain: 'example.com' },
app: { env: 'production' },
const MOCK_CONFIG: Partial<Configuration> = {
front: { domain: 'example.com', apiDomain: 'http://localhost:3000', clientSideApiDomain: 'http://localhost:3000' },
general: { env: 'production', backendPort: 3000, frontendPort: 5000 },
jwt: {
accessSecret: 'secret',
refreshSecret: 'secret',
Expand Down
4 changes: 2 additions & 2 deletions apps/backend/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Body, Controller, Get, Post, Req, Res, UnauthorizedException, UseGuards } from '@nestjs/common';
import { Request, Response } from 'express';
import { AppConfigService } from '../config/config.service';
import { AppConfigService } from '@reduced.to/config';
import { NovuService } from '../novu/novu.service';
import { PrismaService } from '@reduced.to/prisma';
import { AuthService } from './auth.service';
Expand Down Expand Up @@ -44,7 +44,7 @@ export class AuthController {
const user = await this.authService.signup(signupDto);

// Send verification email to user if in production
if (this.appConfigService.getConfig().app.env === 'production') {
if (this.appConfigService.getConfig().general.env === 'production') {
await this.novuService.sendVerificationEmail(user);
}

Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/auth/auth.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { AppConfigService } from '../config/config.service';
import { AppConfigService } from '@reduced.to/config';
import { NovuModule } from '../novu/novu.module';
import { NovuService } from '../novu/novu.service';
import { PrismaModule } from '@reduced.to/prisma';
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/auth/auth.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { JwtService } from '@nestjs/jwt';
import { Test, TestingModule } from '@nestjs/testing';
import { Role, User } from '@reduced.to/prisma';
import * as bcrypt from 'bcryptjs';
import { AppConfigModule } from '../config/config.module';
import { AppConfigModule } from '@reduced.to/config';
import { PrismaService } from '@reduced.to/prisma';
import { AuthService } from './auth.service';

Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { Role } from '@reduced.to/prisma';
import * as bcrypt from 'bcryptjs';
import { AppConfigService } from '../config/config.service';
import { AppConfigService } from '@reduced.to/config';
import { PrismaService } from '@reduced.to/prisma';
import { SignupDto } from './dto/signup.dto';
import { UserContext } from './interfaces/user-context';
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/auth/strategies/jwt-refresh.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Request } from 'express';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { AppConfigService } from '../../config/config.service';
import { AppConfigService } from '@reduced.to/config';
import { AuthService } from '../auth.service';

@Injectable()
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/auth/strategies/jwt.strategy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { AppConfigService } from '../../config/config.service';
import { AppConfigService } from '@reduced.to/config';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/auth/strategies/verify.strategy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { AppConfigService } from '../../config/config.service';
import { AppConfigService } from '@reduced.to/config';

@Injectable()
export class VerifyStrategy extends PassportStrategy(Strategy, 'verify') {
Expand Down
8 changes: 1 addition & 7 deletions apps/backend/src/auth/utils/cookies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,7 @@ export const setAuthCookies = (
refreshToken: string;
}
) => {
// get the host from the domain (remove port if present)
// for example: localhost:5155 -> localhost
// for example: reduced.to -> reduced.to
const strippedDomain = rawDomain
.replace(/http(s)?(:)?(\/\/)?|(\/\/)?(www\.)?/g, '') // strip prefix
.replace(/:\d+$/g, ''); // strip port
const domain = process.env.NODE_ENV === 'production' ? `.${strippedDomain}` : strippedDomain;
const domain = process.env.NODE_ENV === 'production' ? `.${rawDomain}` : rawDomain;

res
.cookie(AUTH_COOKIE_NAME, tokens.accessToken, {
Expand Down
3 changes: 1 addition & 2 deletions apps/backend/src/cache/cache.module.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { CacheModule, CacheStore } from '@nestjs/cache-manager';
import { Global, Module } from '@nestjs/common';
import { RedisStore, redisStore } from 'cache-manager-redis-store';
import { AppConfigModule } from '../config/config.module';
import { AppConfigService } from '../config/config.service';
import { AppConfigService, AppConfigModule } from '@reduced.to/config';
import { AppCacheService } from './cache.service';

@Global()
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/logger/logger.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AppConfigModule } from '../config/config.module';
import { AppConfigModule } from '@reduced.to/config';
import { AppLoggerSerivce } from './logger.service';

describe('LoggerService', () => {
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/logger/logger.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Injectable, LoggerService, LogLevel } from '@nestjs/common';
import { ConsoleTransport, Logger } from '@origranot/ts-logger';
import { AppConfigService } from '../config/config.service';
import { AppConfigService } from '@reduced.to/config';

@Injectable()
export class AppLoggerSerivce implements LoggerService {
Expand Down
4 changes: 2 additions & 2 deletions apps/backend/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { NestExpressApplication } from '@nestjs/platform-express';
import { useContainer } from 'class-validator';
import cookieParser from 'cookie-parser';
import { AppModule } from './app.module';
import { AppConfigService } from './config/config.service';
import { AppConfigService } from '@reduced.to/config';

async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
Expand All @@ -22,7 +22,7 @@ async function bootstrap() {
// Enable DI in class-validator
useContainer(app.select(AppModule), { fallbackOnErrors: true });

const port = app.get(AppConfigService).getConfig().app.port;
const port = app.get(AppConfigService).getConfig().general.backendPort;

await app.listen(port);
}
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/novu/novu.module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Module } from '@nestjs/common';
import { AppConfigService } from '../config/config.service';
import { AppConfigService } from '@reduced.to/config';
import { Novu } from '@novu/node';

export const NOVU_INJECTION_TOKEN = 'NOVU';
Expand Down
12 changes: 10 additions & 2 deletions apps/backend/src/novu/novu.service.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import { Inject, Injectable } from '@nestjs/common';
import { Novu } from '@novu/node';
import { UserContext } from '../auth/interfaces/user-context';
import { AppConfigService } from '../config/config.service';
import { AppConfigService } from '@reduced.to/config';
import { NOVU_INJECTION_TOKEN } from './novu.module';
import { Configuration } from '@reduced.to/config';

@Injectable()
export class NovuService {
constructor(@Inject(NOVU_INJECTION_TOKEN) private readonly novu: Novu, private readonly appConfigService: AppConfigService) {}
private config: Configuration;
constructor(@Inject(NOVU_INJECTION_TOKEN) private readonly novu: Novu, private readonly appConfigService: AppConfigService) {
this.config = this.appConfigService.getConfig();
}

async sendVerificationEmail(user: UserContext) {
const domain =
process.env.NODE_ENV === 'production'
? `https://${this.config.front.domain}`
: `http://${this.config.front.domain}:${this.config.general.frontendPort}`;
const verificationUrl = `${this.appConfigService.getConfig().front.domain}/register/verify/${user.verificationToken}`;

await this.novu.trigger('new-user', {
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/shortener/shortener.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AppConfigModule } from '../config/config.module';
import { AppConfigModule } from '@reduced.to/config';
import { AppCacheModule } from '../cache/cache.module';
import { ShortenerService } from './shortener.service';
import { ShortenerController } from './shortener.controller';
Expand Down
4 changes: 2 additions & 2 deletions apps/backend/src/shortener/shortener.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { AppConfigService } from '../config/config.service';
import { AppConfigService } from '@reduced.to/config';
import { ShortenerService } from './shortener.service';
import { Test, TestingModule } from '@nestjs/testing';
import { AppCacheModule } from '../cache/cache.module';
import { AppCacheService } from '../cache/cache.service';
import { AppConfigModule } from '../config/config.module';
import { AppConfigModule } from '@reduced.to/config';
import { PrismaService } from '@reduced.to/prisma';
import { ShortenerDto } from './dto';
import { BadRequestException } from '@nestjs/common';
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/shortener/shortener.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AppCacheService } from '../cache/cache.service';
import { BadRequestException, Injectable } from '@nestjs/common';
import { AppConfigService } from '../config/config.service';
import { AppConfigService } from '@reduced.to/config';
import { PrismaService } from '@reduced.to/prisma';
import { ShortenerDto } from './dto';
import { UserContext } from '../auth/interfaces/user-context';
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/users/users.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { UsersController } from './users.controller';
import { IFindAllOptions, UsersService } from './users.service';
import { User } from '@reduced.to/prisma';
import { JwtAuthGuard } from '../auth/guards/jwt.guard';
import { AppConfigModule } from '../config/config.module';
import { AppConfigModule } from '@reduced.to/config';
import { RolesGuard } from '../auth/guards/roles.guard';
import { IPaginationResult } from '../shared/utils';
import { SortOrder } from '../shared/enums/sort-order.enum';
Expand Down
2 changes: 0 additions & 2 deletions apps/frontend/.example.env

This file was deleted.

6 changes: 2 additions & 4 deletions apps/frontend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@
# Dependencies Stage
# --------------------------------------------
FROM node:19.2-alpine3.15 as dependencies

WORKDIR /app
COPY package.json package-lock.json ./

COPY package*.json ./

RUN apk add --update python3 make g++\
&& rm -rf /var/cache/apk/*

RUN npm ci


# --------------------------------------------
# Build Stage
# --------------------------------------------
Expand All @@ -31,7 +30,6 @@ COPY --from=dependencies /app/node_modules ./node_modules
# Run prisma generate & build the bundle in production mode
RUN npx nx build frontend --prod --skip-nx-cache


# --------------------------------------------
# Production Stage
# --------------------------------------------
Expand Down
Loading

0 comments on commit 136eeb6

Please sign in to comment.