import * as plugins from './plugins.js'; import type { IPreviewOptions, IPreviewResult, TSupportedInputFormat } from './interfaces.js'; import { PreviewError } from './interfaces.js'; import { PdfProcessor } from './pdfprocessor.js'; /** * Main SmartPreview class for Node.js environment * Provides unified API for generating previews from various document formats */ export class SmartPreview { private pdfProcessor: PdfProcessor | null = null; private isInitialized = false; /** * Create a new SmartPreview instance */ constructor() { // Constructor kept minimal following async initialization pattern } /** * Initialize the SmartPreview instance and all processors */ public async init(): Promise { if (this.isInitialized) { return; } try { // Initialize PDF processor this.pdfProcessor = new PdfProcessor(); await this.pdfProcessor.init(); this.isInitialized = true; } catch (error) { await this.cleanup(); // Cleanup on initialization failure throw new PreviewError( 'PROCESSING_FAILED', 'Failed to initialize SmartPreview', error instanceof Error ? error : new Error(String(error)) ); } } /** * Generate preview from buffer * @param input - Buffer containing the document data * @param options - Preview generation options * @returns Promise resolving to preview result */ public async generatePreview(input: Buffer, options: IPreviewOptions = {}): Promise { if (!this.isInitialized) { throw new PreviewError('PROCESSING_FAILED', 'SmartPreview not initialized. Call init() first.'); } if (!input || input.length === 0) { throw new PreviewError('INVALID_INPUT', 'Input buffer is empty or invalid'); } // Detect format and route to appropriate processor const format = await this.detectFormat(input); switch (format) { case 'pdf': if (!this.pdfProcessor) { throw new PreviewError('PROCESSING_FAILED', 'PDF processor not available'); } return await this.pdfProcessor.processPreview(input, options); default: throw new PreviewError('UNSUPPORTED_FORMAT', `Format '${format}' is not supported`); } } /** * Generate preview from file path * @param filePath - Path to the document file * @param options - Preview generation options * @returns Promise resolving to preview result */ public async generatePreviewFromFile(filePath: string, options: IPreviewOptions = {}): Promise { if (!plugins.fs.existsSync(filePath)) { throw new PreviewError('INVALID_INPUT', `File not found: ${filePath}`); } try { const buffer = await plugins.fs.promises.readFile(filePath); return await this.generatePreview(buffer, options); } catch (error) { if (error instanceof PreviewError) { throw error; } throw new PreviewError( 'PROCESSING_FAILED', `Failed to read file: ${filePath}`, error instanceof Error ? error : new Error(String(error)) ); } } /** * Save preview to file * @param input - Buffer containing the document data * @param outputPath - Path where the preview should be saved * @param options - Preview generation options */ public async savePreview(input: Buffer, outputPath: string, options: IPreviewOptions = {}): Promise { const result = await this.generatePreview(input, options); try { // Ensure output directory exists const outputDir = plugins.path.dirname(outputPath); await plugins.fs.promises.mkdir(outputDir, { recursive: true }); // Write preview to file await plugins.fs.promises.writeFile(outputPath, result.buffer); } catch (error) { throw new PreviewError( 'PROCESSING_FAILED', `Failed to save preview to: ${outputPath}`, error instanceof Error ? error : new Error(String(error)) ); } } /** * Get supported input formats */ public getSupportedFormats(): TSupportedInputFormat[] { return ['pdf']; } /** * Check if a format is supported */ public isFormatSupported(format: string): format is TSupportedInputFormat { return this.getSupportedFormats().includes(format as TSupportedInputFormat); } /** * Clean up resources */ public async cleanup(): Promise { if (this.pdfProcessor) { await this.pdfProcessor.cleanup(); this.pdfProcessor = null; } this.isInitialized = false; } /** * Detect document format from buffer * @private */ private async detectFormat(buffer: Buffer): Promise { // Check PDF magic bytes if (buffer.length >= 4) { const header = buffer.subarray(0, 4); if (header.equals(Buffer.from('%PDF'))) { return 'pdf'; } } // Future format detection can be added here // Example: JPEG, PNG, TIFF, etc. throw new PreviewError('UNSUPPORTED_FORMAT', 'Unable to detect supported format from input'); } /** * Static factory method for convenient instantiation */ public static async create(options: IPreviewOptions = {}): Promise { const instance = new SmartPreview(); await instance.init(); return instance; } }