@shons/next-configify
Version:
NestJS Config on Next Steroids
141 lines • 7 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var ConfigifyModule_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfigifyModule = void 0;
const client_secrets_manager_1 = require("@aws-sdk/client-secrets-manager");
const client_ssm_1 = require("@aws-sdk/client-ssm");
const common_1 = require("@nestjs/common");
const class_validator_1 = require("class-validator");
const fs = require("fs");
const path_1 = require("path");
const configuration_1 = require("./configuration");
const parameter_store_configuration_resolver_1 = require("./configuration/resolvers/aws/parameter-store-configuration.resolver");
const variables_1 = require("./interpolation/variables");
const _ = require("lodash");
let ConfigifyModule = ConfigifyModule_1 = class ConfigifyModule {
static async forRootAsync(options = {}) {
const settings = { ...options, ...configuration_1.DefaultConfigfyModuleOptions };
if (options.envProfile) {
settings.configFilePath = settings.configFilePath || [];
settings.configFilePath = [].concat([
(0, path_1.resolve)(process.cwd(), `application-${options.envProfile}.yml`),
(0, path_1.resolve)(process.cwd(), `application-${options.envProfile}.yaml`),
(0, path_1.resolve)(process.cwd(), `application-${options.envProfile}.json`),
(0, path_1.resolve)(process.cwd(), `.${options.envProfile}.env`),
], settings.configFilePath);
}
const files = this.resolveConfigurationFiles(settings.configFilePath);
const envVars = settings.ignoreEnvVars ? {} : process.env;
const fromFile = settings.ignoreConfigFile
? {}
: this.parseConfigurationFiles(files);
const container = { ...fromFile, ...envVars };
const secrets = await this.runSecretsResolverPipeline(container, settings);
let configuration = { ...container, ...secrets };
if (settings.expandConfig) {
const expanded = variables_1.Variables.expand(configuration);
configuration = _.merge(configuration, expanded);
}
process.env = _.merge(configuration, process.env);
const { exports, providers } = this.buildConfigurationProviders();
return {
exports,
providers,
global: true,
module: ConfigifyModule_1,
};
}
static async runSecretsResolverPipeline(config, options) {
const secrets = {};
for (const buildResolver of this.SECRETS_RESOLVER_PIPELINE) {
const resolver = buildResolver(options);
const result = await resolver.resolve(config);
Object.assign(secrets, result);
}
return secrets;
}
static buildConfigurationProviders() {
const exports = [];
const providers = [];
const registry = configuration_1.ConfigurationRegistry.getRegistry();
for (const ConfigType of registry) {
const instance = new ConfigType();
const attributes = configuration_1.ConfigurationRegistry.getValueDecoratedAttributes(instance);
for (const attribute of attributes) {
const metadata = configuration_1.ConfigurationRegistry.getValueDecoratedKey(instance, attribute);
const parse = metadata.options?.parse;
let metaKey = metadata.key.toUpperCase();
metaKey = metaKey
.split('.')
.join(ConfigifyModule_1.DEFAULT_CONFIG_KEY_SEPARATOR);
metaKey =
metaKey.indexOf('-') !== -1 ? metaKey.replaceAll('-', '_') : metaKey;
const value = parse
? parse(process.env[metaKey])
: process.env[metaKey];
instance[attribute] = value;
}
const errors = (0, class_validator_1.validateSync)(instance);
if (errors && errors.length) {
throw new Error(`validation constraints violated:\n${errors
.map((e) => JSON.stringify({ attribute: e.property, constraints: e.constraints }, null, 2))
.join('\n')}`);
}
exports.push(ConfigType);
providers.push({ provide: ConfigType, useValue: instance });
}
return { exports, providers };
}
static flattenObjectKeys(source, path = [], target = {}) {
if (typeof source === 'object') {
for (const key in source) {
this.flattenObjectKeys(source[key], [...path, key], target);
}
}
else {
path = path.map((val) => {
val = val.trim().replaceAll('-', '_').replaceAll('.', '_');
return val.toUpperCase();
});
target[path.join(ConfigifyModule_1.DEFAULT_CONFIG_KEY_SEPARATOR)] = source;
}
}
static parseConfigurationFiles(files) {
const kv = {};
let config = {};
for (const file of files) {
const parser = configuration_1.ConfigurationParserFactory.getParser(file);
const parsed = parser.parse(file);
config = _.merge(config, parsed);
}
this.flattenObjectKeys(config, [], kv);
return kv;
}
static resolveConfigurationFiles(path) {
return []
.concat(this.DEFAULT_CONFIG_FILES, path)
.filter((file) => fs.existsSync(file) && configuration_1.ConfigurationParserFactory.supports(file));
}
};
exports.ConfigifyModule = ConfigifyModule;
ConfigifyModule.DEFAULT_CONFIG_KEY_SEPARATOR = '_';
ConfigifyModule.DEFAULT_CONFIG_FILES = [
(0, path_1.resolve)(process.cwd(), 'application.yml'),
(0, path_1.resolve)(process.cwd(), 'application.yaml'),
(0, path_1.resolve)(process.cwd(), 'application.json'),
(0, path_1.resolve)(process.cwd(), '.env'),
];
ConfigifyModule.SECRETS_RESOLVER_PIPELINE = [
(options) => new configuration_1.AwsSecretsManagerConfigurationResolver(options.secretsManagerClient || new client_secrets_manager_1.SecretsManagerClient()),
(options) => new parameter_store_configuration_resolver_1.AwsParameterStoreConfigurationResolver(options.ssmClient || new client_ssm_1.SSMClient()),
];
exports.ConfigifyModule = ConfigifyModule = ConfigifyModule_1 = __decorate([
(0, common_1.Module)({})
], ConfigifyModule);
//# sourceMappingURL=configify.module.js.map