Feat/973 provide configuration via env vars#988
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
src/util.ts
Outdated
| group.toUpperCase().replace('-', '').replace('_', '') | ||
| ) | ||
|
|
||
| export function extractFromEnv<T>(prefix: string = 'ZX_') { |
There was a problem hiding this comment.
- I'd suggest
getZxDefaults - Let's extend signature for more convenient testing:
(defs: Options, prefix: string = 'ZX_', env = process.env) - The reduce API might be better here:
return Object.entries(env).reduce((m, [k, v]) => {
if (k.startsWith(prefix)) {
const _k = snakeToCamel(key.slice(prefix.length))
const _v = ({true: true, false: false})[v.toLowerCase()] ?? v
if (typeof _v === typeof defs[_k])
m[_k] = _v
}
return m
}, defs)// core.ts
const defaults = getZxDefaults({
[CWD]: process.cwd(),
[SYNC]: false,
verbose: false,
//..
})There was a problem hiding this comment.
Looks pretty nice. Thank you. I will rewrite it ASAP)
There is only one thing that worries me in default value type checking: mixed types. For example, shell and preferLocal. In defaults it a boolean, but we can pass a string programmatically. This condition rejects such values.
What do you think about this? @antongolub
There was a problem hiding this comment.
I updated code with some potentially improvements:
- I iterate through
defaultscause it contains less keys then env (i hope))) - I use parameter
extrato determine optional fields types and additional type forlocalPrefer
There was a problem hiding this comment.
k.startsWith(prefix) is cheap, so its fine to traverse the whole env
There was a problem hiding this comment.
We can avoid extra in arguments. Fn internal constant is fine here:
const types = {
shell: ['string', 'boolean']
}
if ([typeof defs[_k], ...types[_k]].includes(typeof _v))|
Hey, @pafik13,
|
…com:pafik13/zx into feat/973-provide-configuration-via-env-vars
src/core.ts
Outdated
|
|
||
| // prettier-ignore | ||
| export const defaults: Options = getZxDefaults( | ||
| { |
There was a problem hiding this comment.
Let's keep the original formatting here for git blame
There was a problem hiding this comment.
// prettier-ignore
export const defaults: Options = getZxDefaults({
// ... to keep git blame
})
There was a problem hiding this comment.
I restored formatting, but it didn't help (:
There was a problem hiding this comment.
prettier-ignore should go above the export const defaults declaration
There was a problem hiding this comment.
It was there and extended only to the closest expression - the function call...
JSON declaration was out of scope)
Now, JSON isn't formatted
There was a problem hiding this comment.
It was hard, but I did it.
Thank you)
src/core.ts
Outdated
|
|
||
| // prettier-ignore | ||
| export const defaults: Options = getZxDefaults( | ||
| { |
There was a problem hiding this comment.
// prettier-ignore
export const defaults: Options = getZxDefaults({
// ... to keep git blame
})
src/core.ts
Outdated
| const _k = snakeToCamel(k.slice(prefix.length)) | ||
| const _v = { true: true, false: false }[v.toLowerCase()] ?? v | ||
| if ( | ||
| [typeof defs[_k as keyof Options], ...(types[_k] ?? [])].includes( |
There was a problem hiding this comment.
{...undefined}
undefined is spreadable, afair, isnt it?
There was a problem hiding this comment.
I thought the same, but output from my Browser console
[...undefined]
VM153:1 Uncaught TypeError: undefined is not iterable
at <anonymous>:1:5
There was a problem hiding this comment.
but in your case it works)
> {...undefined}
< {}
src/core.ts
Outdated
|
|
||
| const o = Object.entries(env).reduce<Record<string, string | boolean>>( | ||
| (m, [k, v]) => { | ||
| if (k.startsWith(prefix) && v) { |
There was a problem hiding this comment.
Minor optimization: v && k.startsWith(prefix)
src/core.ts
Outdated
| shell: ['string', 'boolean'], | ||
| halt: ['boolean'], | ||
| preferLocal: ['string', 'boolean'], | ||
| input: ['string'], |
There was a problem hiding this comment.
I guess we should restrict the accepted env opts: sync, nothrow, input, halt, stdio can break the script logic, while verbose, shell, quiet, preferLocal just change its behaviour. Moreover, timeout does not belong to defaults, but it looks reasonable to set externally.
const allowed = new Set(['timeout', 'shell', ...])
// ...
if (allowed.has(_k)) {
}And if somebody is setting ZX_CWD=true, wrong typecast to bool is the least of problems. So maybe we can skip the type check at all
There was a problem hiding this comment.
Plz clarify what you suggest:
-
determine only one list of acceptable properties (
verbose, shell, quiet, preferLocal) and try it extract from env with type-checking -
determine two lists:
- acceptable - extract w/o type check
- unacceptable - extract with strict type check
There was a problem hiding this comment.
How about this?
(defs: Options, prefix = 'ZX_', env = process.env) => Object.entries(env).reduce<Options>((m, [k, v]) => {
const allowed = new Set(['preferLocal', 'detached', 'verbose', 'quiet', 'timeout', 'timeoutSignal', 'prefix', 'postfix'])
if (v && k.startsWith(prefix)) {
const _k = snakeToCamel(key.slice(prefix.length))
const _v = ({true: true, false: false})[v.toLowerCase()] ?? v
if (allowed.has(_k))
m[_k] = _v
}
return m
}, defs)There was a problem hiding this comment.
How about this?
(defs: Options, prefix = 'ZX_', env = process.env) => Object.entries(env).reduce<Options>((m, [k, v]) => { const allowed = new Set(['preferLocal', 'detached', 'verbose', 'quiet', 'timeout', 'timeoutSignal', 'prefix', 'postfix']) if (v && k.startsWith(prefix)) { const _k = snakeToCamel(key.slice(prefix.length)) const _v = ({true: true, false: false})[v.toLowerCase()] ?? v if (allowed.has(_k)) m[_k] = _v } return m }, defs)
In that case we can assign to verbose and quiet some string value. It's not good, in my opinion.
So, I combined 'allowed' and type-check together into types and use only it.
antongolub
left a comment
There was a problem hiding this comment.
Nice! Thanks for the contribution.
Thanks for the mentorship) |


Fixes #973