Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: catch EnvMissingError and send error to reporter when no default value is provided in dev #225

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

petercpwong
Copy link

envalid/src/core.ts

Lines 78 to 80 in 292fb13

if (isTestOnlySymbol(spec.devDefault) && rawNodeEnv != 'test') {
throw new EnvMissingError(formatSpecDescription(spec))
}

When no default value is provided in dev mode, the EnvMissingError that is thrown is not subsequently handled and passed to the reporter. As a consequence, a cryptic error is thrown instead of having the reporter output a formatted error.

To reproduce:

import { cleanEnv, testOnly } from 'envalid';

cleanEnv({ NODE_ENV: 'development' }, { FOO: str({ devDefault: testOnly('sup') }) });

This PR fixes the aforementioned bug and also adds the necessary tests.

@af
Copy link
Owner

af commented Jul 25, 2024

Thanks for the PR, especially the tests and repro case 💯

I verified that this is a bug and your PR fixes it 👍 I'm just wondering if you can think of a way to handle this case without expanding the try block so widely though?

@petercpwong
Copy link
Author

I'm just wondering if you can think of a way to handle this case without expanding the try block so widely though?

Perhaps, we could append to the errors array instead of throwing an error? But that makes the code a tad less readable.

@af
Copy link
Owner

af commented Aug 9, 2024

Hi, I finally got a chance to look in a bit more depth, I think there's a simpler solution. Rather than the big try/catch, just assigning to the errors object when we hit this case does the trick:

      if (usingDevDefault) {
        cleanedEnv[k] = spec.devDefault

        if (isTestOnlySymbol(spec.devDefault) && rawNodeEnv != 'test') {
          // this is the new line:
          errors[k] = new EnvMissingError(formatSpecDescription(spec))
        }

        continue
      }

The testOnly tests in basics.test.ts might need an update, since they currently fall back to the default reporter that calls process.exit– but creating a new reporter in the tests that just throws any provided errors does the trick.

@petercpwong
Copy link
Author

petercpwong commented Aug 9, 2024

If we just simply assign to the errors object instead of throwing an error, then we will have to duplicate the error handling code inside the catch block:

    } catch (err) {
      if (options?.reporter === null) throw err
      if (err instanceof Error) errors[k] = err
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants