Skip to content
Open
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: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ REDIS_USERNAME=
# The password, if nay, to connect to the Redis instance.
# If there is no password, leave empty or put `nopass`.
REDIS_PASSWORD=
REDIS_HOST=


# The DB that should be used for caching.
REDIS_CACHE_DB=
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
},
"scripts": {
"format": "prettier --write \"src/**/*.ts\"",
"deploy": "bun .",
"deploy:dev": "tsc --noEmit && DEV_DEPLOYMENT=true bun ."
"deploy": "bun --env-file=.env .",
"deploy:dev": "tsc --noEmit && DEV_DEPLOYMENT=true bun --env-file=.env ."
},
"dependencies": {
"@sapphire/discord-utilities": "3.5.0",
Expand Down
116 changes: 114 additions & 2 deletions src/lib/setup/env.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,115 @@
import dotenv from 'dotenv';
import { z, type ZodTypeAny } from 'zod';

dotenv.config();
/**
* Validates and type-checks environment variables using a Zod schema.
*
* This function ensures that all required environment variables are present and correctly typed.
* If validation fails, the process will exit with an error message.
*
* @param schema - Zod schema defining the structure and types of environment variables
* @param env - Optional environment object to validate (defaults to process.env)
* @returns Validated and typed environment object
* @throws Exits process if validation fails
* @example
* ```typescript
* const schema = z.object({
* DISCORD_TOKEN: z.string(),
* PORT: z.number()
* });
*
* const env = Env(schema);
* console.log(env.DISCORD_TOKEN); // Fully typed access to env vars
* ```
*
*/
export function Env<T extends ZodTypeAny>(schema: T, env: Record<string, unknown> = process.env): z.infer<T> {
const result = schema.safeParse(env);
if (!result.success) {
console.error('❌ Invalid environment variables:', result.error.format());
process.exit(1); // Exit the process if validation fails to prevent further execution.
}

return result.data;
}

const envVariables = z.object({
/* The current deployment environment that the bot is running on.
* @default 'production' This is the default to prevent accidents.
*/
ENVIRONMENT: z.union([z.literal('production'), z.literal('development')]),

/**
* The Discord token for the bot.
*/
DISCORD_TOKEN: z.string(),

/**
* The Discord webhook url to push error information to.
*/
BOT_ERROR_WEBHOOK_URL: z.string(),

/**
* The base url for the public experience api.
*/
PUBLIC_API_URL: z.string(),

/**
* The base url for the bot's internal api.
*/
BOT_API_URL: z.string(),

/**
* The authorization for `BOT_API_URL`.
*/
BOT_ENDPOINT_API_KEY: z.string(),

/**
* The host for the Redis connection.
*/
REDIS_HOST: z.string(),

/**
* The port for the Redis connection.
*/
REDIS_PORT: z.string(),

/**
* The username to connect to the Redis instance.
*/
REDIS_USERNAME: z.string(),

/**
* The password, if nay, to connect to the Redis instance.
* If there is no password, leave empty or put `nopass`.
*/
REDIS_PASSWORD: z.string().optional(),

/**
* The DB that should be used for caching.
*/
REDIS_CACHE_DB: z.string(),

/**
* The DB that should be used for @sapphire/plugin-scheduled-tasks
*/
REDIS_TASKS_DB: z.string(),

/**
* The chrome websocket connection url.
*/
CHROME_WS_URL: z.string()
});

/**
* Currently using process.env only to maintain compatibility with existing files
*
* TODO: Consider refactoring to use the typed env object directly for better type safety and getting the jsdoc comments
* const env = Env(envVariables);
* console.log(env.DISCORD_TOKEN); // Fully typed access to env vars
*/
Env(envVariables);

// Typed proccess.env
declare module 'bun' {
interface Env extends z.infer<typeof envVariables> {}
}
64 changes: 0 additions & 64 deletions src/lib/types/env.d.ts

This file was deleted.