feat(zero-cache): valitas-based flag/env configuration#2894
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
before digging into this... See comments regarding pitfalls with |
arv
left a comment
There was a problem hiding this comment.
LGTM
NIH :-)
But I understand the need.
A few things.
- How do we deal with things like
fooJSONvsfooJson? - It is common to support short flags like
-pfor--port. In git one can dogit commit -am "Hello world"which is the same asgit commit --add --message "Hello world".
| '--litestream', | ||
| 'true', | ||
| '--logFormat=json', | ||
| '--shardId', |
There was a problem hiding this comment.
What happens with shardID for example?
Very nice, thanks for the tip. I added an instance of that use case in the test (particularly, for the array). |
I am of the same mind. My first attempt was actually completely based on the https://github.com/Roaders/ts-command-line-args library, which is a similar type-safe wrapper around command-line-args (but doesn't use valitas). I even implemented a feature request and added env vars to it: Roaders/ts-command-line-args#48 But as I went down that path, I found a few things lacking:
I like how it turned out. But just so you know, I explored quite a few options before deciding they were all NIH. 🤣
It looks like lodash.camelcase handles things that are already like that, like
wdyt?
|
darkgnotic
left a comment
There was a problem hiding this comment.
Thank you for the thoughtful review!
On second thought, the Or, we could capitalize the filed itself, but that's kind of weird too. shard: {
ID: ...
} |
Looks like the combining of short aliases is supported by |
I went for an Accidentally committed directly into main: 79c6aca |
All your config are belong to valitas
valitas-based library for automatically deriving command line flags + environment variables from a valitas-style configuration object schema.
The
Optionstype is structured similarly to the familiar valitasv.object()specification.e.g.
with the two important differences being:
v.object()instancesv.Typeor a{type: v.Type, desc: string[]}wrapper that allows documenting the configuration value in the same place that the value is defined.The resulting configuration object type is derived from the
Optionsinstance:And, most importantly, flag and environment variable parsing is dynamically configured from the
Optionsobject:The library includes support for:
number,string,booleanv.array()types thereofv.union().optional()semantics.default()semanticsThe precedence for determining the values of the final configuration object are, from low to high:
.default(...)in theOptionsobject.Implementation Notes
The general approach leverages the
command-line-argslibrary for command line parsing andvalitasfor validation. (command-line-argsexplicitly focuses on command line parsing and delegates validation).valitas is similarly laser-focused on JSON messages and doesn't always provide convenient APIs for using it in other contexts. However, we already use valitas everywhere, it is good at what it does, and it packages pretty much all of the semantic information that we need for flags parsing (with the exception being description / documentation).
On balance, the convenience of being able to stick to valitas, and automatically derive our flags and environment variables from it, seems to justify the sometimes obtuse implementation necessary to make it work (e.g. you have to figure out what
Type.func()andType.toTerminals()do).Luckily, the valitas package is small and simple enough that it's not too bad.