Comments (8)
So going forward, how about this?
-
For any
Spec<T>
,devDefault
anddefault
both have typestring | T
. At runtime, during validation, if we don't have arawValue
andtypeof default === 'string'
(ordevDefault
ofc) we pass that default through the validator (same as current behaviour). However, if the default is not astring
, we assume it's an already-validated/transformed value and return it directly. -
Deprecate
Spec.choices
in favour of a new helper,choices
, which takesstring
ornumber
arguments and returns a validator, eg.cleanEnv( process.env, { RATING: choices('good', 'bad', 'ok')({ default: 'good' }), STARS: choices(1, 2, 3, 4, 5)() } )
This simplifies validator logic, fixes the case where validators that return anything other than
string
ornumber
don't work withchoices
, and the return value of the validator can be typed to exactly the values provided (which would accomplish what @SimenB wanted to achieve in #113 but without the footguns).
from envalid.
This is a good point, I don't think the type of default
/devDefault
was ever formally specified.
Looking at the implementation, rawValue
is assigned to the default
/devDefault
values so it should be safe to type them as strings. However it might be a bit counterintuitive that choices
is typed as T
instead– it doesn't look like that can be changed.
I'll try and get to this change in the next week unless anyone raises a reasonable objection. PRs welcome in the meantime
from envalid.
Huh, the behaviour of default
/devDefault
is actually kind of surprising to me here. I would have assumed that the defaults are already validated values, not ones that are substituted for rawValue
and passed into the validator.
After all, defaults are (I hope) known values -- they shouldn't require additional validation, so if rawVar
is undefined but there's a default I'd have expected to early out and just return it. That aligns with the notion of choices
, which are known values to compare to the result.
So in @novemberborn's case I'd suggest the typings aren't wrong, but that this should work:
envalid.cleanEnv({
VALUE: 'decafbad',
}, {
VALUE: hex({ default: Buffer.from('ff', 'hex') })
})
Playing around in the node repl, it looks like it actually does, but only because Buffer.from(Buffer.from('ff', 'hex'), 'hex')
happens to work.
Personally I'd be in favour of directly returning a default value if it's available and rawValue
is undefined; to me that would be the less surprising behaviour. (Technically this would comprise a breaking change in behaviour, but it's very likely there's other folks like me who have already been using defaults in this way, especially since that's how the typings work!)
We could even add an overload to allow default
/devDefault
to also be a value-returning function (ie. { default: () => Buffer.from('ff', 'hex') }
) for lazy initialization if it's expensive or side-effectful (like building a buffer or reading a file). What do folks think?
from envalid.
What's nice about specifying strings is that it's easier to see how to use those values in .env
files or Kubernetes deployments or whatever.
For example I have a validator built on top of ms
and it's nicer to be able to write '2h'
rather than 7_200_000
.
from envalid.
In your particular case with ms
, couldn't you just write { default: ms('2h') }
?
I thought about it some more and I do think you have a good point, though -- Envalid is meant to work on env vars; that is, it's mostly operating on string inputs anyway. And what I said before about validated values might be backwards -- choices
might actually be the odd one out for how it works on (potentially transformed) validated values. (choices
only makes sense for string
or number
anyway, since any non-primitive -- say, a Buffer
-- is not going to be found by choices.includes(value)
.)
Unfortunately, the other side of the coin is that for non-string primitive validators (boolean, number) it's a bit more awkward and brittle to define default
/devDefault
/choices
as strings. That is, it's maybe surprising to require users to type something like this:
{ LAUNCH_STAGE: num({ devDefault: "1", choices: ["1", "12", "36"] })
or: { IS_READY: bool({ devDefault: "true" })
rather than just letting them type the literals true
or 36
, as it currently allowed. This does mean there's technically a mistake in the typings, though -- when a user writes bool({ devDefault: true })
with the literal, that literal gets passed into the parser verbatim even though it's supposed to only take string
s.
from envalid.
@lostfictions that sounds great, I like it!
from envalid.
Hey folks! Just ran into this issue, anything I can do to help implement this?
from envalid.
Is it maybe a simpler change to have default
s always be of type string
, and parse them like any values actually read from env
?
from envalid.
Related Issues (20)
- Add parse options to str() HOT 1
- array validator HOT 1
- 7.3.0 breaking change? HOT 11
- Add option to load validator specs from .example.env file HOT 1
- Access value of env object by name HOT 1
- envalid in react-native for preview crashes without giving description of missing env HOT 2
- testOnly setting variable to Symbol instead of failing HOT 5
- Pick from validators HOT 2
- str({ devDefault: undefined }) generates an incorrect type HOT 2
- Require environment variables only if `NODE_ENV` is not set to `test` HOT 2
- Skipping env var validation in tests HOT 1
- Prevent process exit during tests HOT 1
- makeExactValidator is not exported HOT 1
- Combine envalid with Docker secrets
- Issue with envalid in test. HOT 1
- Typescript, typing the environment variables returns never HOT 1
- Waiting for an async reporter callback HOT 3
- How to see description and help for optional env? HOT 4
- Add a warn option
- devDefault does not work when NODE_ENV is undefined HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from envalid.