Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion drips/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ SMTP_PASSWORD=your-app-password
SMTP_FROM=skills <noreply@hospital.com>

# Application URL
APP_URL=http://localhost:3000
APP_URL=http://localhost:3000
34 changes: 34 additions & 0 deletions drips/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,40 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
- Website - [https://nestjs.com](https://nestjs.com/)
- Twitter - [@nestframework](https://twitter.com/nestframework)

## Configuration

The application uses a centralized configuration module with environment variable validation using Joi.

### Environment Files
The application loads environment variables from `.env` files. You can use different files for different environments:
- `.env`: Default environment variables
- `.env.development`: Development-specific variables
- `.env.test`: Test-specific variables

### Required Variables
See [.env.example](.env.example) for the list of required environment variables. Key variables include:
- `PORT`: Server port (default: 3000)
- `NODE_ENV`: Environment mode (`development`, `production`, `test`)
- `DATABASE_HOST`: Database host
- `DATABASE_PORT`: Database port
- `DATABASE_USER`: Database user
- `DATABASE_PASSWORD`: Database password
- `DATABASE_NAME`: Database name

### Validation
Environment variables are validated at startup. If any required variable is missing or malformed, the application will fail to boot with a descriptive error message.

### Usage
To access configuration in other modules, inject `AppConfigService`:

```typescript
import { AppConfigService } from './config/config.service';

constructor(private configService: AppConfigService) {
const port = this.configService.port;
}
```

## License

Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE).
83 changes: 83 additions & 0 deletions drips/package-lock.json

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

2 changes: 2 additions & 0 deletions drips/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
"@nestjs/core": "^11.0.1",
"@nestjs/platform-express": "^11.0.1",
"@nestjs/typeorm": "^11.0.0",
"@types/joi": "^17.2.2",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.3",
"joi": "^18.0.2",
"pg": "^8.17.2",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
Expand Down
26 changes: 12 additions & 14 deletions drips/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AppConfigModule } from './config/config.module';
import { AppConfigService } from './config/config.service';

@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: '.env',
}),
AppConfigModule,
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
inject: [AppConfigService],
useFactory: (configService: AppConfigService) => ({
type: 'postgres',
host: configService.get('DATABASE_HOST', 'localhost'),
port: configService.get('DATABASE_PORT', 5432),
username: configService.get('DATABASE_USER', 'postgres'),
password: configService.get('DATABASE_PASSWORD', 'postgres'),
database: configService.get('DATABASE_NAME', 'drips_db'),
host: configService.databaseHost,
port: configService.databasePort,
username: configService.databaseUser,
password: configService.databasePassword,
database: configService.databaseName,
entities: ['dist/**/*.entity{.ts,.js}'],
migrations: ['dist/migrations/*{.ts,.js}'],
synchronize: configService.get('NODE_ENV') === 'development',
logging: configService.get('NODE_ENV') === 'development',
synchronize: configService.nodeEnv === 'development',
logging: configService.nodeEnv === 'development',
// namingStrategy: new (require('typeorm').SnakeNamingStrategy)(),
}),
}),
Expand Down
21 changes: 21 additions & 0 deletions drips/src/config/config.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Module, Global } from '@nestjs/common';
import { ConfigModule as NestConfigModule } from '@nestjs/config';
import { AppConfigService } from './config.service';
import { envValidationSchema } from './env.validation';

@Global()
@Module({
imports: [
NestConfigModule.forRoot({
isGlobal: true,
validationSchema: envValidationSchema,
validationOptions: {
allowUnknown: true,
abortEarly: true,
},
}),
],
providers: [AppConfigService],
exports: [AppConfigService],
})
export class AppConfigModule {}
55 changes: 55 additions & 0 deletions drips/src/config/config.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Injectable } from '@nestjs/common';
import { ConfigService as NestConfigService } from '@nestjs/config';

@Injectable()
export class AppConfigService {
constructor(private configService: NestConfigService) {}

get nodeEnv(): string {
return this.configService.get<string>('NODE_ENV')!;
}

get port(): number {
return this.configService.get<number>('PORT')!;
}

get databaseHost(): string {
return this.configService.get<string>('DATABASE_HOST')!;
}

get databasePort(): number {
return this.configService.get<number>('DATABASE_PORT')!;
}

get databaseUser(): string {
return this.configService.get<string>('DATABASE_USER')!;
}

get databasePassword(): string {
return this.configService.get<string>('DATABASE_PASSWORD')!;
}

get databaseName(): string {
return this.configService.get<string>('DATABASE_NAME')!;
}

get redisHost(): string {
return this.configService.get<string>('REDIS_HOST')!;
}

get redisPort(): number {
return this.configService.get<number>('REDIS_PORT')!;
}

get redisPassword(): string | undefined {
return this.configService.get<string>('REDIS_PASSWORD');
}

get redisDb(): number {
return this.configService.get<number>('REDIS_DB')!;
}

get(key: string): any {
return this.configService.get(key);
}
}
17 changes: 17 additions & 0 deletions drips/src/config/env.validation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as Joi from 'joi';

export const envValidationSchema = Joi.object({
NODE_ENV: Joi.string()
.valid('development', 'production', 'test', 'provision')
.default('development'),
PORT: Joi.number().default(3000),
DATABASE_HOST: Joi.string().required(),
DATABASE_PORT: Joi.number().default(5432),
DATABASE_USER: Joi.string().required(),
DATABASE_PASSWORD: Joi.string().required(),
DATABASE_NAME: Joi.string().required(),
REDIS_HOST: Joi.string().default('localhost'),
REDIS_PORT: Joi.number().default(6379),
REDIS_PASSWORD: Joi.string().allow('').optional(),
REDIS_DB: Joi.number().default(0),
});
8 changes: 6 additions & 2 deletions drips/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module';
import { AppConfigService } from './config/config.service';

async function bootstrap() {
const app = await NestFactory.create(AppModule);
Expand All @@ -14,8 +15,11 @@ async function bootstrap() {
}),
);

await app.listen(process.env.PORT ?? 3000, () => {
console.log(`Server running on http://localhost:${process.env.PORT ?? 3000}`);
const configService = app.get(AppConfigService);
const port = configService.port;

await app.listen(port, () => {
console.log(`Server running on http://localhost:${port}`);
});
}
bootstrap();
Loading