dotenv-types-generator
Version:
Generates type declarations for your .env file
171 lines (150 loc) • 4.83 kB
JavaScript
;
var yargs = require('yargs');
var process$1 = require('process');
var fs = require('fs');
/**
* Merges mapped types with already defined types from the given file
* @param {Array} mappedTypes Mapped type definitions
* @param {String} path The env.d.ts file to merge
*/
var mergeTypes = function mergeTypes(mappedTypes, path) {
var mergedArray;
var file;
try {
file = fs.readFileSync(path);
} catch (_unused) {
return mappedTypes;
}
var fileContent = file.toString();
var isValidFile = /(?<=ProcessEnv[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*\{)([\s\S]+?)(?=\})/g.test(fileContent);
if (isValidFile) {
var typeDefinitions = fileContent.match(/(?<=\s*)\w+\??: string/gim);
var diff = mappedTypes.filter(function (item) {
// we split the item and strip ? character to check if it exists in the file
var val = item.split(':')[0].replace('?', '');
return typeDefinitions.findIndex(function (el) {
return el.includes(val);
}) === -1;
});
mergedArray = typeDefinitions.concat(diff);
} else mergedArray = mappedTypes;
return mergedArray;
};
var placeholderText = 'types-placeholder';
var template = [{
indentation: 0,
value: 'declare global {\n'
}, {
indentation: 1,
value: 'namespace NodeJS {\n'
}, {
indentation: 2,
value: 'interface ProcessEnv {\n'
}, {
indentation: 3,
value: placeholderText
}, {
indentation: 2,
value: '}\n'
}, {
indentation: 1,
value: '}\n'
}, {
indentation: 0,
value: '}\n'
}, {
indentation: 0,
value: '\n'
}, {
indentation: 0,
value: 'export {};\n'
}];
/**
* Creates a type definition file template depending on the given indentation size.
* @param {Number} indentationSize Defines how the template should be indented
* @param {Array} mappedTypes Mapped type definitions
*/
var printTypes = function printTypes(indentationSize, mappedTypes) {
var output = '';
var indentationText = ' '.repeat(indentationSize);
template.forEach(function (element) {
var indentation = indentationText.repeat(element.indentation);
if (element.value === placeholderText) {
mappedTypes.forEach(function (mappedType) {
output += "".concat(indentation).concat(mappedType, ";\n");
});
} else output += "".concat(indentation).concat(element.value);
});
return output;
};
var generate = function generate(cwd, path) {
var shouldOutputOptionalTypes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var indentationSize = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 2;
var shouldMerge = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
var defaults = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : [];
var file;
try {
file = fs.readFileSync("".concat(cwd, "/").concat(path));
} catch (_unused) {
console.error('invalid path to .env file');
process.exit(1);
}
var variables = file.toString().match(/(?<=\s*)\w+(?==)/gm);
try {
if (!variables) throw new Error();
} catch (_unused2) {
console.error('Empty .env file');
process.exit(1);
} // merge defaults
variables = variables.concat(defaults);
variables = variables.filter(function (item, pos) {
return variables.indexOf(item) === pos;
});
var outPath = path.match(/[.\w\-/]*\/(?=\.env)/);
outPath = outPath ? "".concat(outPath, "/") : '';
var mappedTypes = variables.map(function (v) {
return "".concat(v).concat(shouldOutputOptionalTypes ? '?' : '', ": string");
});
if (shouldMerge) {
mappedTypes = mergeTypes(mappedTypes, "".concat(cwd, "/").concat(outPath, "env.d.ts"));
}
var typeDeclaration = printTypes(indentationSize, mappedTypes);
fs.writeFileSync("".concat(cwd, "/").concat(outPath, "env.d.ts"), typeDeclaration);
return Buffer.from(typeDeclaration);
};
var _options$help$alias = yargs.options({
file: {
type: 'string',
"default": '.env',
alias: 'f'
},
version: {
alias: 'v'
},
optionalTypes: {
type: 'boolean',
"default": false,
alias: 'o',
description: 'Makes all types optional (nullable)'
},
indentationSize: {
type: 'number',
"default": 2,
alias: 'i',
description: 'Defines how the template should be indented'
},
mergeTypes: {
type: 'boolean',
"default": false,
alias: 'm',
description: 'Merges existing types from env.d.ts file with the types from .env file'
},
defaults: {
type: 'array',
alias: 'd',
description: 'Adds default process.env properties to template'
}
}).help().alias('help', 'h'),
argv = _options$help$alias.argv;
generate(process$1.cwd(), argv.file, argv.optionalTypes, argv.indentationSize, argv.mergeTypes, argv.defaults);