UNPKG

@flowlab/all

Version:

A cool library focusing on handling various flows

203 lines (175 loc) 9.06 kB
// src/core/registry.ts import { IExtractor, ITransformer, ILoader, ICleaner, SourceConfig, TargetConfig, PipelineStepConfig, PipelineContext } from './interfaces'; import { ConfigurationError, ComponentError } from './errors'; import { FileExtractor } from '../extractors/fileExtractor'; import { ApiExtractor } from '../extractors/apiExtractor'; import { PrismaExtractor } from '../extractors/prismaExtractor'; import { FileLoader } from '../loaders/fileLoader'; import { ApiLoader } from '../loaders/apiLoader'; import { PrismaLoader } from '../loaders/prismaLoader'; import { MappingTransformer } from '../transformers/mappingTransformer'; import { CustomFunctionTransformer } from '../transformers/customFunctionTransformer'; import { MongoExtractor } from '../extractors/mongoExtractor'; import { RedisExtractor } from '../extractors/redisExtractor'; import { MongoLoader } from '../loaders/mongoLoader'; import { RedisLoader } from '../loaders/redisLoader'; import { DefaultValueCleaner, RequiredFieldCleaner } from '../extractors/cleaner'; import { ValidationTransformer } from '../transformers/validationTransformer'; // Define types for constructor signatures type ExtractorConstructor = new (config: SourceConfig) => IExtractor<any>; type LoaderConstructor = new (config: TargetConfig) => ILoader<any>; type TransformerConstructor = new (config: any) => ITransformer<any, any>; // Config might vary type CleanerConstructor = new (config: any) => ICleaner<any>; // Config might vary // MARK: - Registry const extractorRegistry = new Map<string, ExtractorConstructor>(); const transformerRegistry = new Map<string, TransformerConstructor>(); const loaderRegistry = new Map<string, LoaderConstructor>(); const cleanerRegistry = new Map<string, CleanerConstructor>(); // MARK: - Extractors registerExtractor('prisma', PrismaExtractor as unknown as ExtractorConstructor); // Cast needed due to generic constructor registerExtractor('postgresql', PrismaExtractor as unknown as ExtractorConstructor); registerExtractor('mysql', PrismaExtractor as unknown as ExtractorConstructor); registerExtractor('file', FileExtractor as unknown as ExtractorConstructor); registerExtractor('api', ApiExtractor as unknown as ExtractorConstructor); registerExtractor('mongodb', MongoExtractor as unknown as ExtractorConstructor); registerExtractor('redis', RedisExtractor as unknown as ExtractorConstructor); // MARK: - Loaders registerLoader('prisma', PrismaLoader as unknown as LoaderConstructor); registerLoader('postgresql', PrismaLoader as unknown as LoaderConstructor); registerLoader('mysql', PrismaLoader as unknown as LoaderConstructor); // registerLoader('file', FileLoader as LoaderConstructor); registerLoader('api', ApiLoader as LoaderConstructor); registerLoader('mongodb', MongoLoader as LoaderConstructor); registerLoader('redis', RedisLoader as LoaderConstructor); // MARK: - Transformers registerTransformer('mapping', MappingTransformer as TransformerConstructor); registerTransformer('custom-function', CustomFunctionTransformer as TransformerConstructor); registerTransformer('validator', ValidationTransformer as TransformerConstructor); // MARK: - Cleaners registerCleaner('required-fields', RequiredFieldCleaner as CleanerConstructor); registerCleaner('default-values', DefaultValueCleaner as CleanerConstructor); // --- Registration Functions --- // MARK: - + Extractor export function registerExtractor(type: string, constructor: ExtractorConstructor): void { if (extractorRegistry.has(type)) { console.warn(`[Registry] Overwriting extractor type: ${type}`); } extractorRegistry.set(type, constructor); } // MARK: - = Transformer export function registerTransformer(type: string, constructor: TransformerConstructor): void { if (transformerRegistry.has(type)) { console.warn(`[Registry] Overwriting transformer type: ${type}`); } transformerRegistry.set(type, constructor); } // MARK: - Regis Loader export function registerLoader(type: string, constructor: LoaderConstructor): void { if (loaderRegistry.has(type)) { console.warn(`[Registry] Overwriting loader type: ${type}`); } loaderRegistry.set(type, constructor); } // MARK: - Regis Cleaner export function registerCleaner(type: string, constructor: CleanerConstructor): void { if (cleanerRegistry.has(type)) { console.warn(`[Registry] Overwriting cleaner type: ${type}`); } cleanerRegistry.set(type, constructor); } // --- Instantiation Functions --- // MARK: - + Extractor export function createExtractor<T>(config: SourceConfig): IExtractor<T> { const Constructor = extractorRegistry.get(config.type); if (!Constructor) { throw new ConfigurationError(`Unsupported extractor type: ${config.type}`); } try { return new Constructor(config) as IExtractor<T>; } catch (error: any) { throw new ComponentError(`Failed to instantiate extractor type ${config.type}`, Constructor.name, error); } } // MARK: - + Loader export function createLoader<T>(config: TargetConfig): ILoader<T> { const Constructor = loaderRegistry.get(config.type); if (!Constructor) { throw new ConfigurationError(`Unsupported loader type: ${config.type}`); } try { return new Constructor(config) as ILoader<T>; } catch (error: any) { throw new ComponentError(`Failed to instantiate loader type ${config.type}`, Constructor.name, error); } } // MARK: - +Pipeline S export function createPipelineStep(stepConfig: PipelineStepConfig): ICleaner<any> | ITransformer<any, any> { let Constructor: CleanerConstructor | TransformerConstructor | undefined; let config: any = stepConfig; // Use the whole step config initially let componentType: string = ''; // For error messages // Determine constructor and config based on step type if (stepConfig.type === 'clean' && stepConfig.cleaner) { if (typeof stepConfig.cleaner === 'string') { componentType = stepConfig.cleaner; Constructor = cleanerRegistry.get(componentType); config = stepConfig; // Pass full step config to cleaner constructor potentially } else { throw new ConfigurationError(`Cleaner definition must be a string type in step config`, undefined, JSON.stringify(stepConfig)); } } else if (stepConfig.type === 'transform' && stepConfig.transformer) { if (typeof stepConfig.transformer === 'string') { componentType = stepConfig.transformer; Constructor = transformerRegistry.get(componentType); config = stepConfig; } else { throw new ConfigurationError(`Transformer definition must be a string type in step config`, undefined, JSON.stringify(stepConfig)); } } else if (stepConfig.type === 'map') { componentType = 'mapping'; // Assuming 'mapping' is the registered type for MappingTransformer Constructor = transformerRegistry.get(componentType); config = stepConfig.rules; // Pass only rules to MappingTransformer constructor usually if (!config) throw new ConfigurationError(`'map' step requires 'rules' property.`); } else if (stepConfig.type === 'custom' && stepConfig.customFunctionPath) { componentType = 'custom-function'; // Special case handled below or by a dedicated transformer Constructor = transformerRegistry.get(componentType); // Requires CustomFunctionTransformer to be registered config = stepConfig; // Pass full step config } else { throw new ConfigurationError(`Invalid or incomplete pipeline step configuration: ${JSON.stringify(stepConfig)}`); } if (!Constructor) { throw new ConfigurationError(`Unsupported pipeline step type or component not registered: ${componentType}`); } try { // We might need more specific config extraction depending on constructor needs return new Constructor(config); } catch (error: any) { throw new ComponentError(`Failed to instantiate pipeline step component ${componentType}`, Constructor.name, error); } } // --- Register Built-in Components --- // This section should be populated as components are created // Example (will add actual components later): // import { PrismaExtractor } from '../extractors/prismaExtractor'; // registerExtractor('prisma', PrismaExtractor); // Assuming PrismaExtractor takes generic config // registerExtractor('postgresql', PrismaExtractor); // Alias // registerExtractor('mysql', PrismaExtractor); // Alias // import { MappingTransformer } from '../transformers/mappingTransformer'; // registerTransformer('mapping', MappingTransformer); // import { PrismaLoader } from '../loaders/prismaLoader'; // registerLoader('prisma', PrismaLoader); // registerLoader('postgresql', PrismaLoader); // registerLoader('mysql', PrismaLoader); // import { RequiredFieldCleaner } from '../transformers/cleaner'; // registerCleaner('required-fields', RequiredFieldCleaner); // Needs config adaptation in createPipelineStep or constructor console.log('[Registry] Component registry initialized.'); // Log on load