Skip to content

Add Environment Variables Validation using env-var #160

@Villarley

Description

@Villarley

Description

The project currently relies on .env files (.env.example, .env.test) and runtime configuration across modules (src/config/*). However, there is no centralized validation of required environment variables. This can lead to runtime errors if variables are missing or misconfigured.

We should introduce environment validation at startup using the [env-var](https://www.npmjs.com/package/env-var) library. This ensures the app fails fast with a clear error message if required variables are absent or invalid.

What is expected

  • A centralized env.ts config file (e.g., src/config/env.ts) that validates all environment variables on load.
  • Use env-var for type-safe validation (string, int, url, etc.).
  • Replace direct process.env.* access across the codebase with imports from this validated config.
  • Keep .env.example updated and aligned with validated variables.
  • Tests remain green using .env.test.

What should be modified

1) Dependencies

  • Install env-var:
    npm install env-var

2) Create Config File

Add src/config/env.ts:

import env from "env-var";

export const ENV = {
  NODE_ENV: env.get("NODE_ENV").default("development").asString(),
  PORT: env.get("PORT").default("3000").asPortNumber(),
  
  // Database
  DATABASE_URL: env.get("DATABASE_URL").required().asUrlString(),
  
  // JWT / Security
  JWT_SECRET: env.get("JWT_SECRET").required().asString(),
  
  // Supabase
  SUPABASE_URL: env.get("SUPABASE_URL").required().asUrlString(),
  SUPABASE_ANON_KEY: env.get("SUPABASE_ANON_KEY").required().asString(),
  
  // Redis
  REDIS_URL: env.get("REDIS_URL").default("redis://localhost:6379").asString(),
  
  // Stellar / Horizon
  HORIZON_URL: env.get("HORIZON_URL").default("https://horizon-testnet.stellar.org").asUrlString(),
  STELLAR_NETWORK: env.get("STELLAR_NETWORK").default("testnet").asString(),
  
  // Email
  EMAIL_SERVICE: env.get("EMAIL_SERVICE").default("gmail").asString(),
  EMAIL_USER: env.get("EMAIL_USER").required().asString(),
  EMAIL_PASSWORD: env.get("EMAIL_PASSWORD").required().asString(),
  BASE_URL: env.get("BASE_URL").default("http://localhost:3000").asUrlString(),
};

3) Replace Direct Usage

Update config files (src/config/prisma.ts, supabase.ts, redis.ts, horizon.config.ts, winston.config.ts, etc.) to use ENV instead of process.env.

Example (prisma.ts):

import { PrismaClient } from "@prisma/client";
import { ENV } from "./env";

export const prisma = new PrismaClient({
  datasources: { db: { url: ENV.DATABASE_URL } },
});

4) Tests

  • Ensure .env.test contains all required variables with dummy/test-safe values.
  • Run full suite to validate nothing breaks.

5) Documentation

  • Update .env.example to list all required variables (with placeholders).
  • Add a section in README.md about environment validation and startup failure messages.

Acceptance criteria

  • src/config/env.ts exists and validates required env vars.
  • No direct calls to process.env.* outside of env.ts.
  • Application fails fast with descriptive errors if env vars are missing.
  • Tests and CI pipeline run successfully with .env.test.
  • .env.example reflects all required variables.

Rollback plan

  • Keep branch/tag before validation.
  • If issues arise, revert to previous config and gradually reintroduce validated variables.

Metadata

Metadata

Assignees

Labels

onlydust-waveContribute to awesome OSS repos during OnlyDust's open source week

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions