UNPKG

@forzalabs/remora

Version:

A powerful CLI tool for seamless data translation.

171 lines (170 loc) 8.95 kB
"use strict"; 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")); const Logger_1 = __importDefault(require("../helper/Logger")); 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 from ${path_1.default.resolve(remoraPath)} 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()); if (!envSettings.has('MAX_ITEMS_IN_MEMORY')) envSettings.set('MAX_ITEMS_IN_MEMORY', Constants_1.default.defaults.MAX_ITEMS_IN_MEMORY.toString()); const debugMode = envSettings.get('DEBUG_MODE'); try { if (debugMode && debugMode.length > 0 && JSON.parse(debugMode) === true) Logger_1.default.setLevel('debug'); } catch (_a) { console.warn(`Invalid project setting "DEBUG_MODE" (${debugMode})`); } // 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.getAllConsumers = () => { (0, Affirm_1.default)(this._env, 'Environment not initialized'); return this._env.consumers || []; }; 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;