valienv
Version:
A simple environment variables validator for Node.js, web browsers and React Native
1 lines • 6.15 kB
Source Map (JSON)
{"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"}