diff --git a/package-lock.json b/package-lock.json index a4611ef..41a8c63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@yasserfedsi/envfy", - "version": "0.1.0", + "version": "0.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@yasserfedsi/envfy", - "version": "0.1.0", + "version": "0.2.0", "license": "MIT", "devDependencies": { "@types/node": "^25.9.3", diff --git a/package.json b/package.json index be57f8d..2d804f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yasserfedsi/envfy", - "version": "0.1.0", + "version": "0.2.0", "description": "A simple, type-safe environment variable validator for Node.js applications", "type": "module", "main": "./dist/index.cjs", diff --git a/src/index.ts b/src/index.ts index c388107..7455c41 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,2 @@ export { validateEnv } from "./validateEnv"; -export type { Schema, PrimitiveType } from "./validateEnv"; +export type { Schema, PrimitiveType, EnumType } from "./validateEnv"; diff --git a/src/validateEnv.ts b/src/validateEnv.ts index 9675373..939c939 100644 --- a/src/validateEnv.ts +++ b/src/validateEnv.ts @@ -1,8 +1,15 @@ -import { parseBoolean, parseNumber, parseString } from "./validators"; +import { + parseBoolean, + parseNumber, + parseString, + parseEnum, +} from "./validators"; export type PrimitiveType = "string" | "number" | "boolean"; -export type Schema = Record; +export type EnumType = readonly string[]; + +export type Schema = Record; export function validateEnv(schema: Schema) { const result: Record = {}; @@ -16,6 +23,11 @@ export function validateEnv(schema: Schema) { throw new Error(`Missing environment variable: ${key}`); } + if (Array.isArray(rule)) { + result[key] = parseEnum(key, value, rule); + continue; + } + switch (rule) { case "string": result[key] = parseString(value); diff --git a/src/validators.ts b/src/validators.ts index f2a0fbd..961655e 100644 --- a/src/validators.ts +++ b/src/validators.ts @@ -18,3 +18,15 @@ export function parseBoolean(key: string, value: string): boolean { export function parseString(value: string): string { return value; } + +export function parseEnum( + key: string, + value: string, + allowedValues: readonly string[], +): string { + if (!allowedValues.includes(value)) { + throw new Error(`${key} must be one of: ${allowedValues.join(", ")}`); + } + + return value; +} diff --git a/tests/validate.test.ts b/tests/validate.test.ts index 598c79c..4139237 100644 --- a/tests/validate.test.ts +++ b/tests/validate.test.ts @@ -41,6 +41,26 @@ describe("validateEnv", () => { }); }).toThrow(); }); + + test("validates enum values", () => { + process.env.NODE_ENV = "development"; + + const env = validateEnv({ + NODE_ENV: ["development", "production", "test"], + }); + + expect(env.NODE_ENV).toBe("development"); + }); + + test("throws on invalid enum", () => { + process.env.NODE_ENV = "staging"; + + expect(() => + validateEnv({ + NODE_ENV: ["development", "production", "test"], + }), + ).toThrow("NODE_ENV must be one of"); + }); }); beforeEach(() => { @@ -48,4 +68,5 @@ beforeEach(() => { delete process.env.PORT; delete process.env.DEBUG; delete process.env.MISSING; + delete process.env.NODE_ENV; });