Configuration
MiiaJS provides a ConfigModule for loading and validating environment variables with any ZodLike schema.
Setup
import { Module } from '@miiajs/core'
import { ConfigModule } from '@miiajs/config'
import { z } from 'zod'
const EnvSchema = z.object({
PORT: z.string().default('3000'),
DATABASE_URL: z.string(),
JWT_SECRET: z.string(),
DEBUG: z.string().default('false'),
})
@Module({
imports: [
ConfigModule.configure({ schema: EnvSchema }),
],
})
class AppModule {}
ConfigModule.configure() validates process.env against your schema at startup. If validation fails, the application throws with detailed error messages.
Using ConfigService
Inject ConfigService to access validated values:
import { Injectable, inject } from '@miiajs/core'
import { ConfigService } from '@miiajs/config'
@Injectable()
class DatabaseService {
private config = inject(ConfigService)
connect() {
const url = this.config.getOrThrow('DATABASE_URL')
const port = this.config.get('PORT') ?? '3000'
// ...
}
}
API
| Method | Returns | On missing key |
|---|---|---|
get(key) | T[K] | undefined | Returns undefined |
getOrThrow(key) | T[K] | Throws Error |
Factory configuration
Use a factory function to resolve config from DI:
import { DrizzleModule } from '@miiajs/drizzle'
@Module({
imports: [
ConfigModule.configure({ schema: EnvSchema }),
DrizzleModule.configure((resolve) => {
const config = resolve(ConfigService)
return {
dialect: 'postgres',
connection: { url: config.getOrThrow('DATABASE_URL') },
}
}),
],
})
class AppModule {}
The resolve function gives access to the DI container, allowing modules to depend on each other's configuration.
Custom env source
By default, ConfigModule reads from process.env. You can pass a custom source:
ConfigModule.configure({
schema: EnvSchema,
env: {
PORT: '8080',
DATABASE_URL: 'postgres://localhost:5432/test',
JWT_SECRET: 'test-secret',
},
})
This is useful for testing or when loading from a custom source.
Schema requirements
The schema must implement a safeParse() method (ZodLike interface):
interface ZodLike<T = any> {
safeParse(data: unknown):
| { success: true; data: T }
| { success: false; error: { issues: { message: string; path?: (string | number)[] }[] } }
}
This means you can use Zod, or implement a custom validation schema without any external dependency.