Skip to content

Instantly share code, notes, and snippets.

@ortense
Created November 2, 2023 18:43
Show Gist options
  • Save ortense/949b675cd90801b368b5c52d25cf7808 to your computer and use it in GitHub Desktop.
Save ortense/949b675cd90801b368b5c52d25cf7808 to your computer and use it in GitHub Desktop.
Node app safe configuration
import { parseArgs } from 'node:util'
import { env } from 'node:process'
import { Input, Issue, Output, boolean, custom, object, safeParse, string, transform } from 'valibot'
// @infra/environment/environment-error.ts
export class EnvironmentError extends Error {
constructor(public readonly issues: Issue[]) {
super('Environment Error')
}
}
// @infra/environment/schema.ts
// could be adapted to zod, joy or your favorite schema validation lib.
const schema = object({
port: transform(string([
custom(
val => Number.isInteger(Number(val)),
'port must be a numeric strig',
),
]), Number),
debug: boolean(),
})
export type EnvironmentInput = Input<typeof schema>
export type EnvironmentConfig = Output<typeof schema>
// @infra/environment/configure.ts
// the env config setup is here
function getArguments(): Partial<EnvironmentInput> {
const args = parseArgs({
options: {
port: { type: 'string' },
debug: { type: 'boolean' },
},
})
return args.values
}
function getEnvironmentVariables(): Partial<EnvironmentInput> {
const variables = {
port: env.PORT,
debug: env.DEBUG === 'true',
}
return { ...variables }
}
const result = safeParse(schema, {
...getEnvironmentVariables(),
...getArguments(),
})
if (result.success === false) {
throw new EnvironmentError(result.issues)
}
export const config: EnvironmentConfig = result.output
/**
* @infra/environment/index.ts
*
* export { config } from './configure'
* export { EnvironmentConfig } from './schema'
*/
/**
* Usage example
* @/main.ts
* import { exit } from 'node:process'
* import { server } from '@infra/server'
* import { config } from '@infra/environment'
*
* async function main() {
* server.listen(config.port)
* }
*
* function onError(error: unknown) {
* console.error(error)
* exit(1)
* }
*
* main().catch(onError)
*/
/**
* CLI
*
* dev
* npx tsx --env-file=.env src/main.ts --port 9090 --debug
*
* prod
* PORT=3000 node build/main.js
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment