diff --git a/src/env.ts b/src/env.ts index 721f4ff..b3312f1 100644 --- a/src/env.ts +++ b/src/env.ts @@ -1,6 +1,72 @@ -const headersTimeout = Number(process.env['HEADERS_TIMEOUT']) || 10000; -const requestTimeout = Number(process.env['REQUEST_TIMEOUT']) || 30000; -const keepAliveTimeout = Number(process.env['KEEP_ALIVE_TIMEOUT']) || 5000; +import { toSafeInteger } from './utils/number.js'; + +const headersTimeoutValue = process.env['HEADERS_TIMEOUT']; +const requestTimeoutValue = process.env['REQUEST_TIMEOUT']; +const keepAliveTimeoutValue = process.env['KEEP_ALIVE_TIMEOUT']; +const maxDelayValue = process.env['MAX_DELAY']; +const portValue = process.env['PORT']; + +// Convert environment variables with error handling +const headersTimeout = + headersTimeoutValue !== undefined + ? (() => { + const parsed = toSafeInteger(headersTimeoutValue); + if (parsed === undefined) { + throw new Error( + `Invalid HEADERS_TIMEOUT value: "${headersTimeoutValue}". Must be a valid integer.` + ); + } + return parsed; + })() + : 10000; + +const requestTimeout = + requestTimeoutValue !== undefined + ? (() => { + const parsed = toSafeInteger(requestTimeoutValue); + if (parsed === undefined) { + throw new Error( + `Invalid REQUEST_TIMEOUT value: "${requestTimeoutValue}". Must be a valid integer.` + ); + } + return parsed; + })() + : 30000; + +const keepAliveTimeout = + keepAliveTimeoutValue !== undefined + ? (() => { + const parsed = toSafeInteger(keepAliveTimeoutValue); + if (parsed === undefined) { + throw new Error( + `Invalid KEEP_ALIVE_TIMEOUT value: "${keepAliveTimeoutValue}". Must be a valid integer.` + ); + } + return parsed; + })() + : 5000; + +const maxDelay = + maxDelayValue !== undefined + ? (() => { + const parsed = toSafeInteger(maxDelayValue); + if (parsed === undefined) { + throw new Error(`Invalid MAX_DELAY value: "${maxDelayValue}". Must be a valid integer.`); + } + return parsed; + })() + : 10000; + +const port = + portValue !== undefined + ? (() => { + const parsed = toSafeInteger(portValue); + if (parsed === undefined) { + throw new Error(`Invalid PORT value: "${portValue}". Must be a valid integer.`); + } + return parsed; + })() + : 8000; if (headersTimeout <= keepAliveTimeout) { throw new Error( @@ -19,9 +85,9 @@ export const environment = { headersTimeout, keepAliveTimeout, logLevel: process.env['LOG_LEVEL'] || 'info', - maxDelay: Number(process.env['MAX_DELAY']) || 10000, + maxDelay, nodeEnv: process.env['NODE_ENV'] || 'development', origin: process.env['ORIGIN'] || '*', - port: Number(process.env['PORT']) || 8000, + port, requestTimeout, }; diff --git a/tests/ut/env.test.ts b/tests/ut/env.test.ts index 80ee025..5c1f205 100644 --- a/tests/ut/env.test.ts +++ b/tests/ut/env.test.ts @@ -80,4 +80,54 @@ describe('Environment configuration', () => { requestTimeout: 40000, }); }); + + describe('Invalid environment variable values', () => { + it('should throw an error for invalid HEADERS_TIMEOUT value', async () => { + process.env.HEADERS_TIMEOUT = 'invalid'; + + await expect(loadEnv()).rejects.toThrow( + 'Invalid HEADERS_TIMEOUT value: "invalid". Must be a valid integer.' + ); + }); + + it('should throw an error for invalid REQUEST_TIMEOUT value', async () => { + process.env.REQUEST_TIMEOUT = '12.5'; + + await expect(loadEnv()).rejects.toThrow( + 'Invalid REQUEST_TIMEOUT value: "12.5". Must be a valid integer.' + ); + }); + + it('should throw an error for invalid KEEP_ALIVE_TIMEOUT value', async () => { + process.env.KEEP_ALIVE_TIMEOUT = 'abc123'; + + await expect(loadEnv()).rejects.toThrow( + 'Invalid KEEP_ALIVE_TIMEOUT value: "abc123". Must be a valid integer.' + ); + }); + + it('should throw an error for invalid MAX_DELAY value', async () => { + process.env.MAX_DELAY = '1e5'; + + await expect(loadEnv()).rejects.toThrow( + 'Invalid MAX_DELAY value: "1e5". Must be a valid integer.' + ); + }); + + it('should throw an error for invalid PORT value', async () => { + process.env.PORT = 'port8000'; + + await expect(loadEnv()).rejects.toThrow( + 'Invalid PORT value: "port8000". Must be a valid integer.' + ); + }); + + it('should throw an error for out-of-safe-range values', async () => { + process.env.PORT = '9007199254740992'; // Number.MAX_SAFE_INTEGER + 1 + + await expect(loadEnv()).rejects.toThrow( + 'Invalid PORT value: "9007199254740992". Must be a valid integer.' + ); + }); + }); });