Skip to content

Commit

Permalink
refactor(env-vars): add validation
Browse files Browse the repository at this point in the history
  • Loading branch information
G0maa committed Oct 18, 2024
1 parent 0a26ea6 commit 5704fd3
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
run: pnpm run compose:up
- name: Running API Tests
working-directory: ./apps/api
run: pnpm run test
run: pnpm run test && pnpm run test:e2e
- name: Upload results to Codecov
uses: codecov/codecov-action@v4
with:
Expand Down
12 changes: 12 additions & 0 deletions apps/api/.env.sample
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
# Server
PORT=3000
NODE_ENV=development

# Database
DATABASE_URL=postgres://postgres:pass1234@localhost:5432/disworse
POSTGRES_DB=disworse
POSTGRES_USER=postgres
POSTGRES_PASSWORD=pass1234

# Redis
REDIS_URL=redis://localhost:6379

# Auth
SESSION_SECRET=secret
COOKIE_MAX_AGE=604800000
4 changes: 3 additions & 1 deletion apps/api/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import { AppService } from "./app.service";
import { AuthenticatedGuard } from "./common/guards/auth.guard";
import { DrizzleModule } from "./drizzle/drizzle.module";
import { AuthModule } from "./modules/auth/auth.module";
import { validate } from "./utils/env.validate";

@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: "../../../.env.backend",
envFilePath: ".env",
validate,
}),
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
Expand Down
14 changes: 8 additions & 6 deletions apps/api/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ValidationPipe } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";

Check warning on line 2 in apps/api/src/main.ts

View check run for this annotation

Codecov / codecov/patch

apps/api/src/main.ts#L2

Added line #L2 was not covered by tests
import { NestFactory } from "@nestjs/core";
import RedisStore from "connect-redis";
import * as session from "express-session";
Expand All @@ -8,7 +9,8 @@ import { AppModule } from "./app.module";

async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.setGlobalPrefix("api");
const configService = app.get(ConfigService);

Check warning on line 13 in apps/api/src/main.ts

View check run for this annotation

Codecov / codecov/patch

apps/api/src/main.ts#L12-L13

Added lines #L12 - L13 were not covered by tests
app.useGlobalPipes(
new ValidationPipe({
transform: true,
Expand All @@ -17,16 +19,16 @@ async function bootstrap() {
);

const redisClient = await createClient({
url: String(process.env.REDIS_URL),
url: String(configService.getOrThrow("REDIS_URL")),

Check warning on line 22 in apps/api/src/main.ts

View check run for this annotation

Codecov / codecov/patch

apps/api/src/main.ts#L22

Added line #L22 was not covered by tests
}).connect();

app.use(
session({
secret: String(process.env.SESSION_SECRET),
secret: configService.getOrThrow<string>("SESSION_SECRET"),

Check warning on line 27 in apps/api/src/main.ts

View check run for this annotation

Codecov / codecov/patch

apps/api/src/main.ts#L27

Added line #L27 was not covered by tests
resave: false,
saveUninitialized: false,
cookie: {
maxAge: Number(process.env.COOKIE_MAX_AGE),
maxAge: configService.getOrThrow<number>("COOKIE_MAX_AGE"),

Check warning on line 31 in apps/api/src/main.ts

View check run for this annotation

Codecov / codecov/patch

apps/api/src/main.ts#L31

Added line #L31 was not covered by tests
httpOnly: true,
},
store: new RedisStore({
Expand All @@ -37,8 +39,8 @@ async function bootstrap() {

app.use(passport.initialize());
app.use(passport.session());

app.enableCors();
await app.listen(process.env.PORT || 3333);

await app.listen(configService.get("PORT") || 3333);

Check warning on line 44 in apps/api/src/main.ts

View check run for this annotation

Codecov / codecov/patch

apps/api/src/main.ts#L43-L44

Added lines #L43 - L44 were not covered by tests
}
bootstrap();
61 changes: 61 additions & 0 deletions apps/api/src/utils/env.validate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { plainToInstance } from "class-transformer";
import {
IsBoolean,
IsEnum,
IsNumber,
IsString,
Max,
Min,
validateSync,
} from "class-validator";

enum Environment {
Development = "development",
Production = "production",
Test = "test",
}

export class EnvironmentVariables {
@IsEnum(Environment)
NODE_ENV: Environment;

@IsNumber()
@Min(0)
@Max(65535)
PORT: number;

@IsString()
DATABASE_URL: string;

@IsString()
POSTGRES_DB: string;

@IsString()
POSTGRES_USER: string;

@IsString()
POSTGRES_PASSWORD: string;

@IsString()
REDIS_URL: string;

@IsString()
SESSION_SECRET: string;

@IsNumber()
COOKIE_MAX_AGE: number;
}

export function validate(config: Record<string, unknown>) {
const validatedConfig = plainToInstance(EnvironmentVariables, config, {
enableImplicitConversion: true,
});
const errors = validateSync(validatedConfig, {
skipMissingProperties: false,
});

if (errors.length > 0) {
throw new Error(errors.toString());
}

Check warning on line 59 in apps/api/src/utils/env.validate.ts

View check run for this annotation

Codecov / codecov/patch

apps/api/src/utils/env.validate.ts#L58-L59

Added lines #L58 - L59 were not covered by tests
return validatedConfig;
}
16 changes: 16 additions & 0 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
services:
pg:
image: postgres:15-alpine
container_name: postgres-dev
restart: always
ports:
- 5432:5432
env_file:
- ./apps/api/.env

cache:
image: redis:7.2.4-alpine
container_name: cache-dev
restart: always
ports:
- 6379:6379
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"lint:fix:unsafe": "biome check . --write --unsafe",
"prepare": "husky",
"commitlint": "commitlint --edit",
"compose:up": "docker compose up -d --build",
"compose:up": "docker compose -f docker-compose.dev.yml up -d --build",
"compose:down": "docker compose down -v"
},
"lint-staged": {
Expand Down

0 comments on commit 5704fd3

Please sign in to comment.