You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							130 lines
						
					
					
						
							3.3 KiB
						
					
					
				
			
		
		
	
	
							130 lines
						
					
					
						
							3.3 KiB
						
					
					
				| 'use strict'
 | |
| 
 | |
| const Ajv = require('ajv')
 | |
| 
 | |
| const separator = {
 | |
|   keyword: 'separator',
 | |
|   type: 'string',
 | |
|   metaSchema: {
 | |
|     type: 'string',
 | |
|     description: 'value separator'
 | |
|   },
 | |
|   modifying: true,
 | |
|   valid: true,
 | |
|   errors: false,
 | |
|   compile: (schema) => (data, dataPath, parentData, parentDataProperty) => {
 | |
|     // In some cases parentData and parentDataProperty will be undefined.
 | |
|     // We need to fall back to the dataPath object to provide those values.
 | |
|     if (parentData && parentDataProperty) {
 | |
|       parentData[parentDataProperty] = data === '' ? [] : data.split(schema)
 | |
|     } else {
 | |
|       const {
 | |
|         parentData: pData,
 | |
|         parentDataProperty: pDataProperty
 | |
|       } = dataPath
 | |
|       pData[pDataProperty] = data === '' ? [] : data.split(schema)
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| const optsSchema = {
 | |
|   type: 'object',
 | |
|   required: ['schema'],
 | |
|   properties: {
 | |
|     schema: { type: 'object', additionalProperties: true },
 | |
|     data: {
 | |
|       oneOf: [
 | |
|         { type: 'array', items: { type: 'object' }, minItems: 1 },
 | |
|         { type: 'object' }
 | |
|       ],
 | |
|       default: {}
 | |
|     },
 | |
|     env: { type: 'boolean', default: true },
 | |
|     dotenv: { type: ['boolean', 'object'], default: false },
 | |
|     expandEnv: { type: ['boolean'], default: false },
 | |
|     ajv: { type: 'object', additionalProperties: true }
 | |
|   }
 | |
| }
 | |
| 
 | |
| const sharedAjvInstance = getDefaultInstance()
 | |
| 
 | |
| const optsSchemaValidator = sharedAjvInstance.compile(optsSchema)
 | |
| 
 | |
| function loadAndValidateEnvironment (_opts) {
 | |
|   const opts = Object.assign({}, _opts)
 | |
| 
 | |
|   if (opts.schema && opts.schema[Symbol.for('fluent-schema-object')]) {
 | |
|     opts.schema = opts.schema.valueOf()
 | |
|   }
 | |
| 
 | |
|   const isOptionValid = optsSchemaValidator(opts)
 | |
|   if (!isOptionValid) {
 | |
|     const error = new Error(sharedAjvInstance.errorsText(optsSchemaValidator.errors, { dataVar: 'opts' }))
 | |
|     error.errors = optsSchemaValidator.errors
 | |
|     throw error
 | |
|   }
 | |
| 
 | |
|   const schema = opts.schema
 | |
|   schema.additionalProperties = false
 | |
| 
 | |
|   let data = opts.data
 | |
|   if (!Array.isArray(opts.data)) {
 | |
|     data = [data]
 | |
|   }
 | |
| 
 | |
|   if (opts.dotenv) {
 | |
|     require('dotenv').config(Object.assign({}, opts.dotenv))
 | |
|   }
 | |
| 
 | |
|   if (opts.env) {
 | |
|     if (opts.expandEnv) {
 | |
|       require('dotenv-expand').expand({ parsed: process.env })
 | |
|     }
 | |
|     data.unshift(process.env)
 | |
|   }
 | |
| 
 | |
|   const merge = {}
 | |
|   data.forEach(d => Object.assign(merge, d))
 | |
| 
 | |
|   const ajv = chooseAjvInstance(sharedAjvInstance, opts.ajv)
 | |
| 
 | |
|   const valid = ajv.validate(schema, merge)
 | |
|   if (!valid) {
 | |
|     const error = new Error(ajv.errorsText(ajv.errors, { dataVar: 'env' }))
 | |
|     error.errors = ajv.errors
 | |
|     throw error
 | |
|   }
 | |
| 
 | |
|   return merge
 | |
| }
 | |
| 
 | |
| function chooseAjvInstance (defaultInstance, ajvOpts) {
 | |
|   if (!ajvOpts) {
 | |
|     return defaultInstance
 | |
|   } else if (typeof ajvOpts === 'object' && typeof ajvOpts.customOptions === 'function') {
 | |
|     const ajv = ajvOpts.customOptions(getDefaultInstance())
 | |
|     if (!(ajv instanceof Ajv)) {
 | |
|       throw new Error('customOptions function must return an instance of Ajv')
 | |
|     }
 | |
|     return ajv
 | |
|   }
 | |
|   return ajvOpts
 | |
| }
 | |
| 
 | |
| function getDefaultInstance () {
 | |
|   return new Ajv({
 | |
|     allErrors: true,
 | |
|     removeAdditional: true,
 | |
|     useDefaults: true,
 | |
|     coerceTypes: true,
 | |
|     allowUnionTypes: true,
 | |
|     addUsedSchema: false,
 | |
|     keywords: [separator]
 | |
|   })
 | |
| }
 | |
| 
 | |
| module.exports = loadAndValidateEnvironment
 | |
| module.exports.default = loadAndValidateEnvironment
 | |
| module.exports.envSchema = loadAndValidateEnvironment
 | |
| module.exports.envSchema.keywords = { separator }
 |