{"version":3,"file":"index.mjs","sources":["../src/errors.ts","../src/validate.ts","../src/validators.ts"],"sourcesContent":["export class EnvValidationError extends Error {\n  variables: string[];\n\n  constructor(variables: string[]) {\n    super(\n      \"Some environment variables cannot be validated: \" + variables.join(\", \"),\n    );\n\n    Object.setPrototypeOf(this, EnvValidationError.prototype);\n    this.name = this.constructor.name;\n    this.variables = variables;\n  }\n}\n","import { EnvValidationError } from \"./errors\";\nimport { Validator } from \"./validators\";\n\nexport const validate = <\n  Validators extends Record<string, Validator<unknown>>,\n>({\n  env,\n  validators,\n  overrides = {},\n}: {\n  env: Record<string, string | undefined>;\n  validators: Validators;\n  overrides?: {\n    [Key in keyof Validators]?: ReturnType<Validators[Key]>;\n  };\n}): Readonly<{\n  [Key in keyof Validators]: Exclude<ReturnType<Validators[Key]>, undefined>;\n}> => {\n  const variables: Record<string, unknown> = {};\n  const invalidVariables: string[] = [];\n  const validatorsKeys = Object.keys(validators);\n\n  const overridesKeys = Object.keys(overrides).filter(\n    (key) => validatorsKeys.indexOf(key) !== -1, // only keep keys from validators\n  );\n\n  overridesKeys.forEach((key) => {\n    variables[key] = overrides[key];\n  });\n\n  validatorsKeys.forEach((key) => {\n    if (overridesKeys.indexOf(key) !== -1) {\n      return; // skip overridden keys\n    }\n\n    const validator = validators[key];\n    const value = env[key];\n\n    if (typeof validator !== \"undefined\") {\n      const parsed = validator(value);\n\n      if (typeof parsed !== \"undefined\") {\n        variables[key] = parsed;\n      } else {\n        invalidVariables.push(key);\n      }\n    }\n  });\n\n  if (invalidVariables.length > 0) {\n    const error = new EnvValidationError(invalidVariables);\n\n    if (typeof process === \"undefined\") {\n      throw error;\n    } else {\n      console.error(error.message);\n      process.exit(1);\n    }\n  }\n\n  // @ts-expect-error\n  return variables;\n};\n","export type Validator<T> = (value: string | undefined) => T | undefined;\n\nexport type OptionalEnvValue<T> =\n  | { defined: true; value: T }\n  | { defined: false };\n\nexport const boolean: Validator<boolean> = (value = \"\") => {\n  if (value === \"true\" || value === \"1\") {\n    return true;\n  }\n  if (value === \"false\" || value === \"0\") {\n    return false;\n  }\n};\n\nconst EMAIL_REGEX = /^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/;\n\nexport const email: Validator<string> = (value = \"\") => {\n  if (EMAIL_REGEX.test(value)) {\n    return value;\n  }\n};\n\nexport const number: Validator<number> = (value = \"\") => {\n  const number = Number.parseFloat(value);\n\n  if (!Number.isNaN(number)) {\n    return number;\n  }\n};\n\nexport const port: Validator<number> = (value = \"\") => {\n  const number = Number.parseFloat(value);\n\n  if (\n    !Number.isNaN(number) &&\n    number % 1 === 0 &&\n    number > 0 &&\n    number < 65536\n  ) {\n    return number;\n  }\n};\n\nexport const string: Validator<string> = (value = \"\") => {\n  if (value !== \"\") {\n    return value;\n  }\n};\n\nexport const url: Validator<string> = (value = \"\") => {\n  try {\n    new URL(value);\n    return value;\n  } catch {} // eslint-disable-line no-empty\n};\n\nexport const oneOf =\n  <T extends string>(...values: Readonly<T[]>): Validator<T> =>\n  (value = \"\") => {\n    const result = values.find((item) => item === value);\n\n    if (typeof result !== \"undefined\") {\n      return result;\n    }\n  };\n\nexport const optional =\n  <T>(validator: Validator<T>): Validator<OptionalEnvValue<T>> =>\n  (value) => {\n    const result = validator(value);\n\n    return typeof result !== \"undefined\"\n      ? { defined: true, value: result }\n      : { defined: false };\n  };\n"],"names":["EnvValidationError","Error","constructor","variables","super","join","this","Object","setPrototypeOf","prototype","name","validate","_ref","env","validators","overrides","invalidVariables","validatorsKeys","keys","overridesKeys","filter","key","indexOf","forEach","validator","parsed","push","length","error","process","console","message","exit","boolean","value","EMAIL_REGEX","email","test","number","Number","parseFloat","isNaN","port","string","url","URL","_unused","oneOf","_arguments","arguments","result","slice","call","find","item","optional","defined"],"mappings":"AAAM,MAAOA,UAA2BC,MAGtCC,WAAAA,CAAYC,GACVC,MACE,mDAAqDD,EAAUE,KAAK,OACpEC,KALJH,iBAOEI,OAAOC,eAAeF,KAAMN,EAAmBS,WAC/CH,KAAKI,KAAOJ,KAAKJ,YAAYQ,KAC7BJ,KAAKH,UAAYA,CACnB,ECRW,MAAAQ,EAAWC,IAcnB,IAZHC,IACAA,EAAGC,WACHA,EAAUC,UACVA,EAAY,CAAA,GAObH,EAGC,MAAMT,EAAqC,CAAA,EACrCa,EAA6B,GAC7BC,EAAiBV,OAAOW,KAAKJ,GAE7BK,EAAgBZ,OAAOW,KAAKH,GAAWK,OAC1CC,IAAyC,IAAjCJ,EAAeK,QAAQD,IA0BlC,GAvBAF,EAAcI,QAASF,IACrBlB,EAAUkB,GAAON,EAAUM,EAC7B,GAEAJ,EAAeM,QAASF,IACtB,IAAoC,IAAhCF,EAAcG,QAAQD,GACxB,OAGF,MAAMG,EAAYV,EAAWO,GAG7B,QAAyB,IAAdG,EAA2B,CACpC,MAAMC,EAASD,EAHHX,EAAIQ,SAKM,IAAXI,EACTtB,EAAUkB,GAAOI,EAEjBT,EAAiBU,KAAKL,EAE1B,IAGEL,EAAiBW,OAAS,EAAG,CAC/B,MAAMC,EAAQ,IAAI5B,EAAmBgB,GAErC,GAAuB,oBAAZa,QACT,MAAMD,EAENE,QAAQF,MAAMA,EAAMG,SACpBF,QAAQG,KAAK,EAEjB,CAGA,OAAO7B,GCvDI8B,EAA8B,SAACC,GAC1C,gBAD0CA,IAAAA,EAAQ,IACpC,SAAVA,GAA8B,MAAVA,GAGV,UAAVA,GAA+B,MAAVA,QAAzB,CAGF,EAEMC,EAAc,6BAEPC,EAA2B,SAACF,GACvC,QADuCA,IAAAA,IAAAA,EAAQ,IAC3CC,EAAYE,KAAKH,GACnB,OAAOA,CAEX,EAEaI,EAA4B,SAACJ,YAAAA,IAAAA,EAAQ,IAChD,MAAMI,EAASC,OAAOC,WAAWN,GAEjC,IAAKK,OAAOE,MAAMH,GAChB,OAAOA,CAEX,EAEaI,EAA0B,SAACR,YAAAA,IAAAA,EAAQ,IAC9C,MAAMI,EAASC,OAAOC,WAAWN,GAEjC,IACGK,OAAOE,MAAMH,IACdA,EAAS,GAAM,GACfA,EAAS,GACTA,EAAS,MAET,OAAOA,CAEX,EAEaK,EAA4B,SAACT,GACxC,QADwCA,IAAAA,IAAAA,EAAQ,IAClC,KAAVA,EACF,OAAOA,CAEX,EAEaU,EAAyB,SAACV,QAAK,IAALA,IAAAA,EAAQ,IAC7C,IAEE,OADA,IAAIW,IAAIX,GACDA,CACT,CAAE,MAAAY,IACJ,EAEaC,EACX,WAAAC,IAAAA,EAAAC,UAAA,OACCf,SAAAA,QAAAA,IAAAA,IAAAA,EAAQ,IACP,MAAMgB,EAAS,GAAAC,MAAAC,KAAAJ,GAAOK,KAAMC,GAASA,IAASpB,GAE9C,QAAsB,IAAXgB,EACT,OAAOA,CAEX,CAAC,EAEUK,EACP/B,GACHU,IACC,MAAMgB,EAAS1B,EAAUU,GAEzB,YAAyB,IAAXgB,EACV,CAAEM,SAAS,EAAMtB,MAAOgB,GACxB,CAAEM,SAAS"}