@forzalabs/remora
Version:
A powerful CLI tool for seamless data translation.
156 lines (155 loc) • 8.14 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const Affirm_1 = __importDefault(require("../core/Affirm"));
const SchemaValidator_1 = __importDefault(require("./schema/SchemaValidator"));
const Validator_1 = __importDefault(require("./validation/Validator"));
const Constants_1 = __importDefault(require("../Constants"));
class EnvironmentClass {
constructor() {
this._env = null;
this.init = (env) => {
this._env = env;
};
this.load = (remoraPath) => {
const envPath = path_1.default.join(remoraPath, 'remora');
// Read and parse project.json
const projectPath = path_1.default.join(envPath, 'project.json');
if (!fs_1.default.existsSync(projectPath))
throw new Error('Project configuration file not found');
const projectConfig = JSON.parse(fs_1.default.readFileSync(projectPath, 'utf-8'));
// Validate project schema
const isValid = SchemaValidator_1.default.validate('project-schema', projectConfig);
if (!isValid)
throw new Error('Invalid project configuration');
const loadConfigurations = (basePath, paths) => {
const configs = [];
for (const configPath of paths) {
const fullPath = path_1.default.join(basePath, configPath);
try {
if (fs_1.default.statSync(fullPath).isDirectory()) {
const files = fs_1.default.readdirSync(fullPath).filter(file => file.endsWith('.json'));
for (const file of files) {
const config = JSON.parse(fs_1.default.readFileSync(path_1.default.join(fullPath, file), 'utf-8'));
configs.push(config);
}
}
else {
const config = JSON.parse(fs_1.default.readFileSync(fullPath, 'utf-8'));
configs.push(config);
}
}
catch (error) {
throw new Error(`Error loading configuration from ${configPath}: ${error.message}`);
}
}
return configs;
};
// Unload all the schemes other than the default ones, because otherwise the RW could keep loaded schemes not saved in the remora folder
SchemaValidator_1.default.unloadSchemas();
// Load all schemas first since they're needed for validation
const schemas = loadConfigurations(envPath, projectConfig.schemas);
schemas.forEach(schema => {
SchemaValidator_1.default.addSchema(schema, schema.title);
});
// Load configurations with validation
const sources = loadConfigurations(envPath, projectConfig.sources);
sources.forEach(source => {
if (!SchemaValidator_1.default.validate('source-schema', source))
throw new Error(`Invalid source configuration: ${source.name}`);
});
const producers = loadConfigurations(envPath, projectConfig.producers);
producers.forEach(producer => {
if (!SchemaValidator_1.default.validate('producer-schema', producer))
throw new Error(`Invalid producer configuration: ${producer.name}`);
});
const consumers = loadConfigurations(envPath, projectConfig.consumers);
consumers.forEach(consumer => {
if (!SchemaValidator_1.default.validate('consumer-schema', consumer))
throw new Error(`Invalid consumer configuration: ${consumer.name}`);
});
// Load the project settings
const envSettings = new Map(Object.entries(Object.assign({}, projectConfig.settings))
.map(([key, value]) => [key, String(value)]));
if (!envSettings.has('SQL_MAX_QUERY_ROWS'))
envSettings.set('SQL_MAX_QUERY_ROWS', Constants_1.default.defaults.SQL_MAX_QUERY_ROWS.toString());
if (!envSettings.has('STRING_MAX_CHARACTERS_LENGTH'))
envSettings.set('STRING_MAX_CHARACTERS_LENGTH', Constants_1.default.defaults.STRING_MAX_CHARACTERS_LENGTH.toString());
// Initialize environment
this.init({
settings: envSettings,
sources,
producers,
consumers,
schemas,
sqlLibrary: [] // TODO: Add SQL library loading if needed
});
};
this.get = (setting) => {
return this._env.settings.get(setting);
};
this.getSource = (sourceName) => {
(0, Affirm_1.default)(sourceName, 'Invalid source name');
return this._env.sources.find(x => x.name === sourceName);
};
/**
* A consumer can reference another consumer, in this case I need to keep digging to find the real producer
*/
this.getFirstProducer = (producerName) => {
(0, Affirm_1.default)(producerName, `Invalid producer name`);
const prod = this._env.producers.find(x => x.name.toLocaleLowerCase() === producerName.toLowerCase());
if (!prod) {
const consumer = this.getConsumer(producerName);
(0, Affirm_1.default)(consumer, `Invalid producer name`);
return this.getFirstProducer(consumer.producers[0].name);
}
return prod;
};
this.getProducer = (producerName) => {
(0, Affirm_1.default)(producerName, `Invalid producer name`);
return this._env.producers.find(x => x.name.toLowerCase() === producerName.toLowerCase());
};
this.getConsumer = (consumerName) => {
(0, Affirm_1.default)(consumerName, `Invalid consumer name`);
return this._env.consumers.find(x => x.name.toLowerCase() === consumerName.toLowerCase());
};
this.getSchema = (schemaName) => {
(0, Affirm_1.default)(schemaName, 'Invalid schema name');
return this._env.schemas.find(x => x.title === schemaName);
};
this.getSqlInLibrary = (name) => {
(0, Affirm_1.default)(name, `Invalid sql library item name`);
return this._env.sqlLibrary.find(x => x.name === name);
};
this.validate = () => {
(0, Affirm_1.default)(this._env, 'Invalid environment');
let errors = [];
try {
errors = [...errors, ...Validator_1.default.validateSources(this._env.sources)];
errors = [...errors, ...Validator_1.default.validateProducers(this._env.producers)];
this._env.producers.forEach(prod => {
const ce = Validator_1.default.validateProducer(prod);
if (ce.length > 0)
errors.push(`Producer "${prod.name}" errors:\n${ce.map(x => `\t-${x}\n`)}`);
});
errors = [...errors, ...Validator_1.default.validateConsumers(this._env.consumers)];
this._env.consumers.forEach(cons => {
const ce = Validator_1.default.validateConsumer(cons);
if (ce.length > 0)
errors.push(`Consumer "${cons.name}" errors:\n${ce.map(x => `\t-${x}\n`)}`);
});
}
catch (e) {
if (errors.length === 0)
errors.push(`There was an error in the validation Environment. (error: ${e})`);
}
return errors;
};
}
}
const Environment = new EnvironmentClass();
exports.default = Environment;