Configuration Service
CruzJS provides a ConfigService for accessing environment variables with type safety and validation. It follows the same interface as NestJS’s ConfigService, making it familiar if you have worked with that framework.
How It Works
Section titled “How It Works”In Cloudflare Workers, environment variables are provided via bindings rather than process.env. CruzJS’s CloudflareContext.init() bridges these bindings to process.env so that ConfigService works consistently across local development and production.
Cloudflare env bindings │ ▼CloudflareContext.init() ──► Bridges string values to process.env │ ▼ConfigService.get() ──► Reads from validated env schemaUsing ConfigService
Section titled “Using ConfigService”Inject ConfigService into any service:
import { Injectable, Inject } from '@cruzjs/core/di';import { ConfigService } from '@cruzjs/core/shared/config/config.service';
@Injectable()export class PaymentService { private stripeKey: string; private webhookSecret: string;
constructor( @Inject(ConfigService) private readonly config: ConfigService, ) { // Required config — throws if not set this.stripeKey = this.config.getOrThrow<string>('STRIPE_SECRET_KEY'); this.webhookSecret = this.config.getOrThrow<string>('STRIPE_WEBHOOK_SECRET'); }}API Reference
Section titled “API Reference”get<T>(key, defaultValue?)
Section titled “get<T>(key, defaultValue?)”Returns the value for a configuration key, or the default value if not set. Returns undefined if no default is provided and the key is not set.
// With default valueconst port = config.get<number>('PORT', 3000);
// Without default (may be undefined)const analyticsId = config.get<string>('ANALYTICS_ID');if (analyticsId) { // analytics is configured}getOrThrow<T>(key)
Section titled “getOrThrow<T>(key)”Returns the value for a configuration key, throwing an error if the key is not set. Use this for required configuration.
// Throws: 'Configuration key "DATABASE_URL" is required but not set'const dbUrl = config.getOrThrow<string>('DATABASE_URL');getEnv()
Section titled “getEnv()”Returns the full validated environment object. Useful when you need multiple values at once:
const env = config.getEnv();// Access all validated environment variablesgetRaw(key)
Section titled “getRaw(key)”Returns a raw environment variable value from process.env, bypassing the validated schema. Use this for dynamic configuration that is not part of the validated env schema:
const customEndpoint = config.getRaw('CUSTOM_API_ENDPOINT');getRawByPrefix(prefix)
Section titled “getRawByPrefix(prefix)”Returns all environment variables matching a prefix as a Map. Useful for dynamic or plugin-based configuration:
// Get all STORAGE_DRIVER_* variablesconst storageConfig = config.getRawByPrefix('STORAGE_DRIVER_');// Map { 'S3_ENDPOINT' => 'https://...', 'S3_REGION' => 'us-east-1' }getAllRaw()
Section titled “getAllRaw()”Returns all environment variables as a Map<string, string>:
const allVars = config.getAllRaw();Common Configuration Keys
Section titled “Common Configuration Keys”| Key | Description | Example |
|---|---|---|
APP_URL | Application base URL | https://myapp.com |
EMAIL_FROM | Default sender email | noreply@myapp.com |
EMAIL_PROVIDER | Email provider | mailchannels |
EMAIL_API_KEY | Email provider API key | re_... |
STORAGE_DRIVER | Storage backend | r2 or local |
R2_BUCKET | R2 bucket name | my-app-uploads |
STRIPE_SECRET_KEY | Stripe API key | sk_live_... |
STRIPE_WEBHOOK_SECRET | Stripe webhook secret | whsec_... |
Using Config in Different Contexts
Section titled “Using Config in Different Contexts”In Services
Section titled “In Services”@Injectable()export class MyService { constructor(@Inject(ConfigService) private config: ConfigService) {}
getApiUrl(): string { return this.config.getOrThrow<string>('APP_URL'); }}In tRPC Routers
Section titled “In tRPC Routers”export const settingsRouter = router({ getAppInfo: protectedProcedure.query(async () => { const container = await getAppContainer(); const config = container.resolve(ConfigService);
return { appUrl: config.getOrThrow<string>('APP_URL'), environment: config.get<string>('NODE_ENV', 'development'), }; }),});In Modules
Section titled “In Modules”Access ConfigService from any injectable service registered in your module:
@Injectable()export class ThirdPartyIntegration { constructor(@Inject(ConfigService) private config: ConfigService) { const apiKey = this.config.get<string>('THIRD_PARTY_API_KEY'); if (apiKey) { this.initialize(apiKey); } }}Setting Configuration
Section titled “Setting Configuration”Local Development
Section titled “Local Development”Set environment variables in your .dev.vars file (Cloudflare’s local env file):
APP_URL=http://localhost:5173EMAIL_PROVIDER=consoleSTORAGE_DRIVER=localSTRIPE_SECRET_KEY=sk_test_...Production
Section titled “Production”Use the CruzJS CLI to manage secrets:
# Set a secretcruz secrets set STRIPE_SECRET_KEY sk_live_...
# List secretscruz secrets listOr set them in your wrangler.toml for non-sensitive values:
[vars]APP_URL = "https://myapp.com"EMAIL_PROVIDER = "mailchannels"STORAGE_DRIVER = "r2"Best Practices
Section titled “Best Practices”-
Use
getOrThrow()for required config. Fail fast at startup if critical configuration is missing, rather than encountering runtime errors later. -
Use
get()with defaults for optional config. Provide sensible defaults so your application works in development without extensive env setup. -
Do not access
process.envdirectly. Always useConfigServicefor consistency. The config service handles the Cloudflare-to-process.env bridge and provides type safety. -
Keep secrets in
cruz secretsor.dev.vars. Never commit secrets towrangler.tomlor source control. Use.dev.varsfor local development (it is gitignored by default) andcruz secrets setfor deployed environments. -
Group related config with prefixes. Use prefixes like
EMAIL_,STORAGE_,STRIPE_to organize configuration. UsegetRawByPrefix()to load groups of related config.