Skip to content

Commit

Permalink
Validate missing environment
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcoDaniels committed May 14, 2021
1 parent de38932 commit afd3315
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 39 deletions.
18 changes: 4 additions & 14 deletions src/debug.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
import {environmentDecoder, asString, DecodeType, asNumber, asBoolean} from "./"
import {environmentDecoder, asString, asNumber} from "./"

const env = environmentDecoder({
USER: asString,
WHAT: asString,
WHY: asNumber,
FAIL: asBoolean
WHAT: asNumber,
WHY: asString
})

type Stuff = DecodeType<typeof env>

const a: Stuff = {
USER: '',
WHAT: '123',
WHY: 123,
FAIL: false
}

console.log(a, env)
console.log(env)
40 changes: 15 additions & 25 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ export {DecodeType} from './types'

export const asString: DecodeFnType<string> = (s: JSType) => {
if (typeof s !== 'string') {
throw `Type "${typeof s}" of ${JSON.stringify(s)} is not a string`
throw `type "${typeof s}" of ${JSON.stringify(s)} is not a string`
}
return s
}

export const asNumber: DecodeFnType<number> = (n: JSType) => {
if (typeof n !== 'number') {
if (isNaN(Number(asString(n)))) {
throw `Value ${JSON.stringify(n)} cannot be cast to number`
throw `value ${JSON.stringify(n)} cannot be cast to number`
}
return Number(asString(n))
}
Expand All @@ -29,40 +29,30 @@ export const asBoolean: DecodeFnType<boolean> = (b: JSType) => {
case 'true':
return true
default:
throw `Value ${JSON.stringify(b)} cannot be cast to boolean`
throw `value ${JSON.stringify(b)} cannot be cast to boolean`
}
}
return b
}

const fieldDecoder: unique symbol = Symbol('field-decoder')
const optionalDecoder: unique symbol = Symbol('optional-decoder')
const decode = <D>(decoder: D): DecodeFnType<D> => decoder as any

export const environmentDecoder = <schema>(s: schema): DecodeType<schema> => {
const env = process.env
export const environmentDecoder = <S>(schemaType: S): DecodeType<S> => {
const environment = process.env
const schema = Object.entries(schemaType)

return Object.entries(s)
const missing = schema.filter(([key]) => !environment.hasOwnProperty(key)).map(([key]) => key)
if (missing.length) {
throw (`Missing environment variables: \n${missing.join(`\n`)}\n`)
}

return schema
.map(([key, decoder]: [string, any]) => {
if (decoder[fieldDecoder] === true) {
return [key, decode(decoder)(env)]
}
if (!env.hasOwnProperty(key)) {
if ((decoder)[optionalDecoder]) {
return [key, undefined]
}
throw `Cannot find key \`${key}\` in \`${JSON.stringify(env)}\``
}
try {
const jsonvalue = env[key]
return [key, decode(decoder)(jsonvalue)]
const value = environment[key]
return [key, decode(decoder)(value)]
} catch (message) {
throw (
message +
`\nwhen trying to decode the key \`${key}\` in \`${JSON.stringify(
env,
)}\``
)
throw (`Error for environment "${key}": ${message}\n`)
}
})
.reduce((acc, [key, value]) => ({...acc, [key]: value}), {})
Expand Down

0 comments on commit afd3315

Please sign in to comment.