@dword-design/dotenv-json-extended
Version:
Custom dotenv wrapper with support for parent folders and schema validation.
56 lines • 1.61 kB
JavaScript
import Ajv from 'ajv';
import { constantCase } from 'change-case';
import { findUpSync } from 'find-up';
import fs from 'fs-extra';
import mapObj from 'map-obj';
import parseValue from "./parse-value.js";
const ajv = new Ajv({
useDefaults: true
});
const parse = ({
cwd = '.'
} = {}) => {
const schemaPath = findUpSync('.env.schema.json', {
cwd
});
const filePath = findUpSync(process.env.NODE_ENV === 'test' ? '.test.env.json' : '.env.json', {
cwd
});
const fromFile = filePath ? fs.readJsonSync(filePath) : {};
const properties = schemaPath ? fs.readJsonSync(schemaPath) : {};
const fromEnv = mapObj(properties, (name, property) => {
const nodeEnvPrefix = process.env.NODE_ENV === 'test' ? 'TEST_' : '';
const envVariableName = `${nodeEnvPrefix}${constantCase(name)}`;
const valueString = process.env[envVariableName];
let value;
try {
value = parseValue(valueString, property.type);
} catch (error) {
throw new Error(`Error at data.${name}: ${error.message}`);
}
return [name, value];
});
const fromAll = {
...fromEnv,
...fromFile
};
const schema = {
additionalProperties: false,
properties,
required: Object.keys(properties),
type: 'object'
};
const valid = ajv.validate(schema, fromAll);
if (!valid) {
throw new Error(`dotenv: ${ajv.errorsText()}`);
}
return mapObj(fromAll, (name, value) => [constantCase(name), typeof value === 'object' ? JSON.stringify(value) : value]);
};
export default {
config: ({
cwd = '.'
} = {}) => Object.assign(process.env, parse({
cwd
})),
parse
};