@codemask-labs/node-config
Version:
Node Config Module
124 lines • 5.28 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getConfigInstance = exports.registerConfigTransformTranslations = exports.registerConfigTransformOptions = exports.registerConfigDefaults = void 0;
const class_transformer_1 = require("class-transformer");
const class_validator_1 = require("class-validator");
const dotenv_1 = require("dotenv");
const ramda_1 = require("ramda");
const exceptions_1 = require("../exceptions");
const utils_1 = require("../utils");
const constants_1 = require("./constants");
const registerConfigDefaults = (base) => {
if (!constants_1.registry.has(base)) {
const dependencies = Reflect.getMetadata('design:paramtypes', base) || [];
constants_1.registry.set(base, {
base,
dependencies,
resolvedDependencies: dependencies.map(() => null),
propertyNameTranslations: {},
instance: null
});
}
};
exports.registerConfigDefaults = registerConfigDefaults;
const registerConfigTransformOptions = (base, transformOptions) => {
const current = constants_1.registry.get(base);
if (!current) {
throw new Error(`Failed to find registered config. Make sure to decorate a class with @Config()!`);
}
constants_1.registry.set(base, {
...current,
transformOptions
});
};
exports.registerConfigTransformOptions = registerConfigTransformOptions;
const registerConfigTransformTranslations = (base, propertyName, environmentPropertyName) => {
const current = constants_1.registry.get(base);
if (!current) {
throw new Error(`Failed to find registered config. Make sure to decorate a class with @Config()!`);
}
constants_1.registry.set(base, {
...current,
propertyNameTranslations: {
...current?.propertyNameTranslations,
[propertyName]: environmentPropertyName
}
});
};
exports.registerConfigTransformTranslations = registerConfigTransformTranslations;
const getConfigInstance = (base, transformOptions) => {
const registeredDependency = constants_1.registry.get(base);
if (!registeredDependency) {
throw new Error(`Failed to find registered config. Make sure to decorate a class with @Config()!`);
}
if (registeredDependency.instance) {
return registeredDependency.instance;
}
const resolvedDependencies = registeredDependency.resolvedDependencies.map((instance, index) => {
const dependency = registeredDependency.dependencies.at(index);
if (!dependency) {
throw new Error(`Failed to resolve dependency for [${base.name}] at index: ${index}`);
}
return instance ?? (0, exports.getConfigInstance)(dependency);
});
const { parsed: environmentVariables = {} } = (0, dotenv_1.configDotenv)({
override: false,
path: process.env.DOTENV_CONFIG_PATH
});
const storage = (0, class_validator_1.getMetadataStorage)();
const metadatas = storage.getTargetValidationMetadatas(base, base.name, false, false);
const transformedProperties = metadatas.reduce((acc, { propertyName, target }) => {
if (acc[propertyName]) {
return acc;
}
const prototype = typeof target === 'function' ? target.prototype : {};
const environmentPropertyName = registeredDependency.propertyNameTranslations[propertyName];
const key = environmentPropertyName || propertyName;
const value = environmentVariables[key] || process.env[key];
const type = Reflect.getMetadata('design:type', prototype, propertyName);
return {
...acc,
[propertyName]: (0, ramda_1.isNotNil)(value) ? (0, utils_1.toValueByType)(type, value) : value
};
}, {});
const descriptors = Object.getOwnPropertyDescriptors(base.prototype);
const descriptorNames = Object.keys(descriptors).filter(name => name !== 'constructor');
const unreferencedMethods = descriptorNames.reduce((result, name) => {
const descriptor = descriptors[name];
return {
...result,
[name]: (...args) => descriptor.value.apply(instance, args)
};
}, {});
class ConfigConstructorWrapper extends base {
static name = base.name;
constructor(...unusedArgs) {
super(...resolvedDependencies);
}
}
Object.assign(ConfigConstructorWrapper.prototype, unreferencedMethods);
const instance = (0, class_transformer_1.plainToInstance)(ConfigConstructorWrapper, transformedProperties, {
exposeDefaultValues: true,
enableImplicitConversion: true,
...transformOptions
});
const validationErrors = (0, class_validator_1.validateSync)(instance, {
forbidUnknownValues: false,
validationError: {
target: true,
value: true
}
});
if (validationErrors.length) {
throw new exceptions_1.ValidationException(base.name, validationErrors);
}
const config = {
...registeredDependency,
resolvedDependencies,
instance
};
constants_1.registry.set(base, config);
return config.instance;
};
exports.getConfigInstance = getConfigInstance;
//# sourceMappingURL=utils.js.map