From b775a22d956715029326e925708442024b233f71 Mon Sep 17 00:00:00 2001 From: Peter Wong Date: Mon, 22 Jul 2024 14:11:57 +0000 Subject: [PATCH 1/2] fix: catch EnvMissingError --- src/core.ts | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/core.ts b/src/core.ts index 5c37ec4..34bf2e0 100644 --- a/src/core.ts +++ b/src/core.ts @@ -66,34 +66,35 @@ export function getSanitizedEnv( const spec = castedSpecs[k] const rawValue = readRawEnvValue(environment, k) - // If no value was given and default/devDefault were provided, return the appropriate default - // value without passing it through validation - if (rawValue === undefined) { - // Use devDefault values only if NODE_ENV was explicitly set, and isn't 'production' - const usingDevDefault = - rawNodeEnv && rawNodeEnv !== 'production' && spec.hasOwnProperty('devDefault') - if (usingDevDefault) { - cleanedEnv[k] = spec.devDefault - - if (isTestOnlySymbol(spec.devDefault) && rawNodeEnv != 'test') { - throw new EnvMissingError(formatSpecDescription(spec)) + try { + // If no value was given and default/devDefault were provided, return the appropriate default + // value without passing it through validation + if (rawValue === undefined) { + // Use devDefault values only if NODE_ENV was explicitly set, and isn't 'production' + const usingDevDefault = + rawNodeEnv && rawNodeEnv !== 'production' && spec.hasOwnProperty('devDefault') + + if (usingDevDefault) { + cleanedEnv[k] = spec.devDefault + + if (isTestOnlySymbol(spec.devDefault) && rawNodeEnv != 'test') { + throw new EnvMissingError(formatSpecDescription(spec)) + } + + continue } - continue - } - if ('default' in spec) { - cleanedEnv[k] = spec.default - continue - } - } + if ('default' in spec) { + cleanedEnv[k] = spec.default + continue + } - try { - if (rawValue === undefined) { + // Throw error when no default value is provided cleanedEnv[k] = undefined throw new EnvMissingError(formatSpecDescription(spec)) - } else { - cleanedEnv[k] = validateVar({ name: k as string, spec, rawValue }) } + + cleanedEnv[k] = validateVar({ name: k as string, spec, rawValue }) } catch (err) { if (options?.reporter === null) throw err if (err instanceof Error) errors[k] = err From b15f6b78873dd425f1f980c24782a2af49e2db2c Mon Sep 17 00:00:00 2001 From: Peter Wong Date: Mon, 22 Jul 2024 15:38:34 +0000 Subject: [PATCH 2/2] test: add tests --- tests/basics.test.ts | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/tests/basics.test.ts b/tests/basics.test.ts index 42fb684..a06c49b 100644 --- a/tests/basics.test.ts +++ b/tests/basics.test.ts @@ -1,4 +1,4 @@ -import { cleanEnv, str, num, testOnly } from '../src' +import { cleanEnv, str, num, testOnly, ReporterOptions } from '../src' import { assertPassthrough } from './utils' import { expectTypeOf } from 'expect-type' @@ -226,23 +226,46 @@ describe('NODE_ENV built-in support', () => { test('testOnly', () => { const processEnv = process.env.NODE_ENV - const makeSpec = () => ({ - FOO: str({ devDefault: testOnly('sup') }), + + const reporter = jest.fn(({ errors = {} }: ReporterOptions) => { + if (Object.keys(errors).length) { + throw new Error() + } }) // Create an env spec that has our testOnly value applied as the devDefault, // and then restore the original NODE_ENV process.env.NODE_ENV = 'test' - const testSpec = makeSpec() - process.env.NODE_ENV = processEnv - - const env = cleanEnv({ NODE_ENV: 'test' }, testSpec) + const env = cleanEnv( + { NODE_ENV: 'test' }, + { FOO: str({ devDefault: testOnly('sup') }) }, + { reporter }, + ) expect(env).toEqual({ FOO: 'sup' }) + expect(reporter).toHaveBeenCalledTimes(1) + jest.clearAllMocks() process.env.NODE_ENV = 'production' - expect(() => cleanEnv({ NODE_ENV: 'production' }, makeSpec(), makeSilent)).toThrow() + expect(() => + cleanEnv( + { NODE_ENV: 'production' }, + { FOO: str({ devDefault: testOnly('sup') }) }, + { reporter }, + ), + ).toThrow() + expect(reporter).toHaveBeenCalledTimes(1) + jest.clearAllMocks() process.env.NODE_ENV = 'development' - expect(() => cleanEnv({ NODE_ENV: 'development' }, makeSpec(), makeSilent)).toThrow() + expect(() => + cleanEnv( + { NODE_ENV: 'development' }, + { FOO: str({ devDefault: testOnly('sup') }) }, + { reporter }, + ), + ).toThrow() + expect(reporter).toHaveBeenCalledTimes(1) + jest.clearAllMocks() + process.env.NODE_ENV = processEnv })