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

Pick from validators #199

Open
neezer opened this issue Dec 22, 2022 · 2 comments
Open

Pick from validators #199

neezer opened this issue Dec 22, 2022 · 2 comments

Comments

@neezer
Copy link
Contributor

neezer commented Dec 22, 2022

I'm working on a common library for a number of micro services that consume roughly the same environment variables. I'd like to provide definitions for all possible variables in my module, then allow each application to select the definitions they are interested in and ignore the rest.

I was thinking I could do this by wrapping the invocation of envalid.cleanEnv in my own function and pass a list of vars the application was interested in, something like this (the following code does not work FYI):

import { cleanEnv } from 'envalid';

enum Var {
  BindAddr = 'BIND_ADDR',
  BindPort = 'BIND_PORT',
  JwkFile = 'JWK_FILE'
  // ... many more
}

function pick<T, U extends keyof T>(obj: T, keys: U[]): Pick<T, U> {
  const picked = {} as Record<U, any>;

  for (const key of keys) {
    picked[key] = obj[key];
  }

  return picked as Pick<T, U>;
}

export function get<T extends Var>(varsToSelect: T[]) {
  const validators = {
    [Var.BindAddr]: str({ default: 'localhost' }),
    [Var.BindPort]: num({ default: 8000 }),
    [Var.JwkFile]: str()
  };

  return cleanEnv(
    getEnv(),
    pick<typeof validators, T>(validators, vars)
  )
}

I can't figure out how to get the resulting object typed correctly, though. This is what I'm after:

// would be awesome to get this from the argument alone, instead of effectively duplicating the list in the generic argument
const config = get<Var.BindAddr | Var.BindPort>([
  Var.BindAddr,
  Var.BindPort
]);

config.BIND_ADDR //=> should be present of type string
config.BIND_PORT //=> should be present of type number
config.JWK_FILE //=> should be absent

Does this make sense? Is this possible? How can I accomplish this?

@af
Copy link
Owner

af commented Dec 30, 2022

Have you tried the latest envalid, 8.0.0-alpha.2? Seems to be typed as desired for me when I run your example with it:

Screen Shot 2022-12-29 at 20 53 05

@neezer
Copy link
Contributor Author

neezer commented Jan 5, 2023

No, I was trying the latest stable release. I'll give 8.0.0-alpha.2 a try and let you know what I see.

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

No branches or pull requests

2 participants