Add environment variable validation and parsing

Adds a validation schema for the application's environment variables using the Zod library. The parsed environment variables are then exported as constants that can be imported throughout the application, replacing the direct use of process.env.
This commit is contained in:
Aaron William Po
2023-04-06 23:38:03 -04:00
parent 6b65e09c17
commit 0d3785ad1a
21 changed files with 171 additions and 69 deletions

136
config/env/index.ts vendored Normal file
View File

@@ -0,0 +1,136 @@
/* eslint-disable prefer-destructuring */
import { z } from 'zod';
import process from 'process';
import ServerError from '../util/ServerError';
import 'dotenv/config';
const envSchema = z.object({
BASE_URL: z.string(),
CLOUDINARY_CLOUD_NAME: z.string(),
CLOUDINARY_KEY: z.string(),
CLOUDINARY_SECRET: z.string(),
CONFIRMATION_TOKEN_SECRET: z.string(),
SESSION_SECRET: z.string(),
SESSION_TOKEN_NAME: z.string(),
SESSION_MAX_AGE: z.coerce.number().positive(),
DATABASE_URL: z.string(),
NODE_ENV: z.enum(['development', 'production', 'test']),
SPARKPOST_API_KEY: z.string(),
SPARKPOST_SENDER_ADDRESS: z.string().email(),
});
const parsed = envSchema.safeParse(process.env);
if (!parsed.success) {
throw new ServerError('Invalid environment variables', 500);
}
/**
* Base URL of the application.
*
* @example
* 'https://example.com';
*/
export const BASE_URL = parsed.data.BASE_URL;
/**
* Cloudinary cloud name.
*
* @example
* 'my-cloud';
*
* @see https://cloudinary.com/documentation/cloudinary_references
* @see https://cloudinary.com/console
*/
export const CLOUDINARY_CLOUD_NAME = parsed.data.CLOUDINARY_CLOUD_NAME;
/**
* Cloudinary API key.
*
* @example
* '123456789012345';
*
* @see https://cloudinary.com/documentation/cloudinary_references
* @see https://cloudinary.com/console
*/
export const CLOUDINARY_KEY = parsed.data.CLOUDINARY_KEY;
/**
* Cloudinary API secret.
*
* @example
* 'abcdefghijklmnopqrstuvwxyz123456';
*
* @see https://cloudinary.com/documentation/cloudinary_references
* @see https://cloudinary.com/console
*/
export const CLOUDINARY_SECRET = parsed.data.CLOUDINARY_SECRET;
/**
* Fsd Fds Secret key for signing confirmation tokens.
*
* @example
* 'abcdefghijklmnopqrstuvwxyz123456';
*/
export const CONFIRMATION_TOKEN_SECRET = parsed.data.CONFIRMATION_TOKEN_SECRET;
/**
* Secret key for signing session cookies.
*
* @example
* 'abcdefghijklmnopqrstuvwxyz123456';
*/
export const SESSION_SECRET = parsed.data.SESSION_SECRET;
/**
* Name of the session cookie.
*
* @example
* 'my-app-session';
*/
export const SESSION_TOKEN_NAME = parsed.data.SESSION_TOKEN_NAME;
/**
* Maximum age of the session cookie in milliseconds.
*
* @example
* '86400000'; // 24 hours
*/
export const SESSION_MAX_AGE = parsed.data.SESSION_MAX_AGE;
/**
* URL of the CockroachDB database. CockroachDB uses the PostgreSQL wire protocol.
*
* @example
* 'postgres://username:password@localhost/my-database';
*/
export const DATABASE_URL = parsed.data.DATABASE_URL;
/**
* Node environment.
*
* @example
* 'production';
*
* @see https://nodejs.org/api/process.html#process_process_env
*/
export const NODE_ENV = parsed.data.NODE_ENV;
/**
* SparkPost API key.
*
* @example
* 'abcdefghijklmnopqrstuvwxyz123456';
*
* @see https://app.sparkpost.com/account/api-keys
*/
export const SPARKPOST_API_KEY = parsed.data.SPARKPOST_API_KEY;
/**
* Sender email address for SparkPost.
*
* @example
* 'noreply@example.com';
*/
export const SPARKPOST_SENDER_ADDRESS = parsed.data.SPARKPOST_SENDER_ADDRESS;