env-schema

Validate your env variable using Ajv and dotenv

README

env-schema


Utility to check environment variables using JSON schema, Ajv, and

See supporting resources section for helpful guides on getting started.

Install


  1. ```
  2. npm i env-schema
  3. ```

Usage


  1. ```js
  2. const envSchema = require('env-schema')

  3. const schema = {
  4.   type: 'object',
  5.   required: [ 'PORT' ],
  6.   properties: {
  7.     PORT: {
  8.       type: 'number',
  9.       default: 3000
  10.     }
  11.   }
  12. }

  13. const config = envSchema({
  14.   schema: schema,
  15.   data: data, // optional, default: process.env
  16.   dotenv: true // load .env if it is there, default: false
  17.   // or you can pass DotenvConfigOptions
  18.   // dotenv: {
  19.   //   path: '/custom/path/to/.env'
  20.   // }
  21. })

  22. console.log(config)
  23. // output: { PORT: 3000 }
  24. ```


Custom ajv instance


Optionally, the user can supply their own ajv instance:

  1. ```js
  2. const envSchema = require('env-schema')
  3. const Ajv = require('ajv')

  4. const schema = {
  5.   type: 'object',
  6.   required: [ 'PORT' ],
  7.   properties: {
  8.     PORT: {
  9.       type: 'number',
  10.       default: 3000
  11.     }
  12.   }
  13. }

  14. const config = envSchema({
  15.   schema: schema,
  16.   data: data,
  17.   dotenv: true,
  18.   ajv: new Ajv({
  19.     allErrors: true,
  20.     removeAdditional: true,
  21.     useDefaults: true,
  22.     coerceTypes: true,
  23.     allowUnionTypes: true
  24.   })
  25. })

  26. console.log(config)
  27. // output: { PORT: 3000 }
  28. ```

It is possible to enhance the default ajv instance providing the customOptions function parameter.
This example shows how to use the format keyword in your schemas.

  1. ```js
  2. const config = envSchema({
  3.   schema: schema,
  4.   data: data,
  5.   dotenv: true,
  6.   ajv: {
  7.     customOptions (ajvInstance) {
  8.       require('ajv-formats')(ajvInstance)
  9.       return ajvInstance
  10.     }
  11.   }
  12. })
  13. ```

Note that it is mandatory returning the ajv instance.

Order of configuration loading


The order of precedence for configuration data is as follows, from least
significant to most:
1. Data sourced from .env file (when dotenv configuration option is set)
2. Data sourced from environment variables in process.env
3. Data provided via the data configuration option

Fluent-Schema API


It is also possible to use fluent-json-schema:

  1. ```js
  2. const envSchema = require('env-schema')
  3. const S = require('fluent-json-schema')

  4. const config = envSchema({
  5.   schema: S.object().prop('PORT', S.number().default(3000).required()),
  6.   data: data, // optional, default: process.env
  7.   dotenv: true, // load .env if it is there, default: false
  8.   expandEnv: true, // use dotenv-expand, default: false
  9. })

  10. console.log(config)
  11. // output: { PORT: 3000 }
  12. ```

NB Support for additional properties in the schema is disabled for this plugin, with the additionalProperties flag set to false internally.

Custom keywords

This library supports the following Ajv custom keywords:

separator

Type: string

Applies to type: string

When present, the provided schema value will be split on this value.

Example:
  1. ```js
  2. const envSchema = require('env-schema')

  3. const schema = {
  4.   type: 'object',
  5.   required: [ 'ALLOWED_HOSTS' ],
  6.   properties: {
  7.     ALLOWED_HOSTS: {
  8.       type: 'string',
  9.       separator: ','
  10.     }
  11.   }
  12. }

  13. const data = {
  14.   ALLOWED_HOSTS: '127.0.0.1,0.0.0.0'
  15. }

  16. const config = envSchema({
  17.   schema: schema,
  18.   data: data, // optional, default: process.env
  19.   dotenv: true // load .env if it is there, default: false
  20. })

  21. // config.ALLOWED_HOSTS => ['127.0.0.1', '0.0.0.0']
  22. ```

The ajv keyword definition objects can be accessed through the property keywords on the envSchema function:

  1. ```js
  2. const envSchema = require('env-schema')
  3. const Ajv = require('ajv')

  4. const schema = {
  5.   type: 'object',
  6.   properties: {
  7.     names: {
  8.       type: 'string',
  9.       separator: ','
  10.     }
  11.   }
  12. }

  13. const config = envSchema({
  14.   schema: schema,
  15.   data: data,
  16.   dotenv: true,
  17.   ajv: new Ajv({
  18.     allErrors: true,
  19.     removeAdditional: true,
  20.     useDefaults: true,
  21.     coerceTypes: true,
  22.     allowUnionTypes: true,
  23.     keywords: [envSchema.keywords.separator]
  24.   })
  25. })

  26. console.log(config)
  27. // output: { names: ['foo', 'bar'] }
  28. ```

TypeScript


You can specify the type of your config:

  1. ```ts
  2. import { envSchema, JSONSchemaType } from 'env-schema'

  3. interface Env {
  4.   PORT: number;
  5. }

  6. const schema: JSONSchemaType<Env> = {
  7.   type: 'object',
  8.   required: [ 'PORT' ],
  9.   properties: {
  10.     PORT: {
  11.       type: 'number',
  12.       default: 3000
  13.     }
  14.   }
  15. }

  16. const config = envSchema({
  17.   schema
  18. })
  19. ```

You can also use a JSON Schema library like typebox:

  1. ```ts
  2. import { envSchema } from 'env-schema'
  3. import { Static, Type } from '@sinclair/typebox'

  4. const schema = Type.Object({
  5.   PORT: Type.Number({ default: 3000 })
  6. })

  7. type Schema = Static<typeof schema>

  8. const config = envSchema<Schema>({
  9.   schema
  10. })
  11. ```

If no type is specified the config will have the EnvSchemaData type.

  1. ```ts
  2. export type EnvSchemaData = {
  3.   [key: string]: unknown;
  4. }
  5. ```

Supporting resources


The following section lists helpful reference applications, articles, guides and other
resources that demonstrate the use of env-schema in different use-cases and scenarios:

A reference application using Fastify with env-schema and dotenv

Acknowledgements


Kindly sponsored by Mia Platform and

License


MIT