From 3bc703d8dcac94ed674f57a4bbb02b6bf4343cc0 Mon Sep 17 00:00:00 2001 From: Amit Haridas Date: Tue, 24 Mar 2026 09:06:21 +0530 Subject: [PATCH] feat: add platform adapter structure for V4 - Create adapters/types.js with comprehensive type definitions - Create adapters/electron/fs.js for file system operations - Prepare structure for future migration to Tauri/Flutter This abstraction layer makes future platform migration easier and enables better testing with mock adapters. Amit Haridas --- src/adapters/electron/fs.js | 107 +++++++++++++++++++++++++++++ src/adapters/types.js | 133 ++++++++++++++++++++++++++++++++++++ 2 files changed, 240 insertions(+) create mode 100644 src/adapters/electron/fs.js create mode 100644 src/adapters/types.js diff --git a/src/adapters/electron/fs.js b/src/adapters/electron/fs.js new file mode 100644 index 0000000..c865d09 --- /dev/null +++ b/src/adapters/electron/fs.js @@ -0,0 +1,107 @@ +/** + * Electron File System Adapter + * + * Implements file system operations for Electron using IPC. + * This abstracts file operations to enable easier testing and migration. + * + * @version 4.1.0 + */ + +/** + * Electron File System Adapter + * @type {import('../types').FileSystemAdapter} + */ +const electronFsAdapter = { + /** + * Read file content + * @param {string} path - File path + * @returns {Promise} File content + */ + async readFile(path) { + return await window.electronAPI.readFile(path); + }, + + /** + * Write content to file + * @param {string} path - File path + * @param {string} content - File content + * @returns {Promise} + */ + async writeFile(path, content) { + return await window.electronAPI.writeFile(path, content); + }, + + /** + * Delete file + * @param {string} path - File path + * @returns {Promise} + */ + async deleteFile(path) { + // TODO: Add IPC channel for delete + throw new Error('deleteFile not implemented'); + }, + + /** + * Ensure directory exists + * @param {string} path - Directory path + * @returns {Promise} + */ + async ensureDir(path) { + // TODO: Add IPC channel for ensureDir + throw new Error('ensureDir not implemented'); + }, + + /** + * List directory contents + * @param {string} path - Directory path + * @returns {Promise>} + */ + async listDirectory(path) { + // TODO: Add IPC channel for listDirectory + throw new Error('listDirectory not implemented'); + }, + + /** + * Check if path exists + * @param {string} path - Path to check + * @returns {Promise} + */ + async exists(path) { + // TODO: Add IPC channel for exists + throw new Error('exists not implemented'); + }, + + /** + * Check if path is a directory + * @param {string} path - Path to check + * @returns {Promise} + */ + async isDirectory(path) { + // TODO: Add IPC channel for isDirectory + throw new Error('isDirectory not implemented'); + }, + + /** + * Copy file or directory + * @param {string} source - Source path + * @param {string} dest - Destination path + * @returns {Promise} + */ + async copy(source, dest) { + // TODO: Add IPC channel for copy + throw new Error('copy not implemented'); + }, + + /** + * Move file or directory + * @param {string} source - Source path + * @param {string} dest - Destination path + * @returns {Promise} + */ + async move(source, dest) { + // TODO: Add IPC channel for move + throw new Error('move not implemented'); + } +}; + +module.exports = { electronFsAdapter }; diff --git a/src/adapters/types.js b/src/adapters/types.js new file mode 100644 index 0000000..5986b81 --- /dev/null +++ b/src/adapters/types.js @@ -0,0 +1,133 @@ +/** + * Platform Adapter Type Definitions + * + * This module defines the interfaces for platform-specific operations. + * Adapters abstract file system, conversion, and system operations + * to enable easier testing and future platform migration. + * + * @version 4.1.0 + */ + +/** + * @typedef {Object} FileInfo + * @property {string} name - File or directory name + * @property {boolean} isDir - True if directory + * @property {number} size - File size in bytes + * @property {number} modified - Last modified timestamp (ms since epoch) + */ + +/** + * @typedef {Object} WatchEvent + * @property {string} type - Event type ('add', 'change', 'unlink', 'addDir', 'unlinkDir') + * @property {string} path - Affected file/directory path + */ + +/** + * @typedef {Object} ConversionOptions + * @property {string} format - Output format (pdf, docx, html, etc.) + * @property {string} [pdfEngine] - PDF engine for PDF export (xelatex, pdflatex, etc.) + * @property {string} [template] - Word template path for DOCX + * @property {string} [geometry] - Page geometry for PDF (e.g., 'margin=1in') + * @property {string} [header] - Header content + * @property {string} [footer] - Footer content + * @property {boolean} [toc] - Include table of contents + */ + +/** + * @typedef {Object} ConversionResult + * @property {string} input - Input file path + * @property {string} output - Output file path + * @property {boolean} success - Whether conversion succeeded + * @property {string} [error] - Error message if failed + */ + +/** + * @typedef {Object} PlatformCapabilities + * @property {boolean} hasPandoc - Pandoc is available + * @property {boolean} hasFfmpeg - FFmpeg is available + * @property {boolean} hasLibreOffice - LibreOffice is available + * @property {boolean} hasDirectFs - Direct file system access + * @property {boolean} hasSystemNotifications - System notifications available + * @property {boolean} hasPdfJs - PDF.js available for PDF viewing + */ + +/** + * @typedef {Object} DialogOptions + * @property {string} [title] - Dialog title + * @property {string} [defaultPath] - Default path + * @property {string[]} [filters] - File filters [{ name: 'Markdown', extensions: ['md'] }] + * @property {string} [buttonLabel] - Custom button label + */ + +/** + * @typedef {Object} SystemInfo + * @property {string} platform - Operating system (win32, darwin, linux) + * @property {string} homeDir - User home directory + * @property {string} documentsDir - Documents directory + * @property {string} downloadsDir - Downloads directory + * @property {string} tempDir - Temporary directory + * @property {string} appVersion - Application version + */ + +/** + * @typedef {Object} FileSystemAdapter + * @property {(path: string) => Promise} readFile - Read file content + * @property {(path: string, content: string) => Promise} writeFile - Write file content + * @property {(path: string) => Promise} deleteFile - Delete file + * @property {(path: string) => Promise} ensureDir - Ensure directory exists + * @property {(path: string) => Promise} listDirectory - List directory contents + * @property {(path: string) => Promise} exists - Check if path exists + * @property {(path: string) => Promise} isDirectory - Check if path is directory + * @property {(source: string, dest: string) => Promise} copy - Copy file or directory + * @property {(source: string, dest: string) => Promise} move - Move file or directory + * @property {(path: string, callback: (event: WatchEvent) => void) => () => void>} [watchDirectory] - Watch directory for changes + */ + +/** + * @typedef {Object} ConversionAdapter + * @property {(input: string, output: string, options: ConversionOptions) => Promise} convertFile - Convert single file + * @property {(files: string[], outputDir: string, options: ConversionOptions) => Promise} batchConvert - Batch convert files + * @property {() => Promise} checkPandoc - Check if Pandoc is available + * @property {() => Promise} checkFfmpeg - Check if FFmpeg is available + * @property {() => Promise} checkLibreOffice - Check if LibreOffice is available + */ + +/** + * @typedef {Object} DialogAdapter + * @property {(options?: DialogOptions) => Promise} showOpenDialog - Show open file dialog + * @property {(options?: DialogOptions) => Promise} showOpenDialogMulti - Show multi-select open dialog + * @property {(options?: DialogOptions) => Promise} showSaveDialog - Show save file dialog + * @property {(message: string, type?: string) => Promise} showMessage - Show message dialog + * @property {(message: string, type?: string) => Promise} showConfirm - Show confirmation dialog + */ + +/** + * @typedef {Object} SystemAdapter + * @property {() => Promise} getSystemInfo - Get system information + * @property {(title: string, body: string) => Promise} showNotification - Show system notification + * @property {(url: string) => Promise} openExternal - Open URL in default browser + * @property {(path: string) => Promise} openInExplorer - Open path in file explorer + * @property {(path: string) => Promise} openInDefaultApp - Open path in default application + */ + +/** + * @typedef {Object} PdfAdapter + * @property {(path: string) => Promise} loadDocument - Load PDF document + * @property {(doc: Object, pageNum: number, canvas: HTMLCanvasElement, scale: number, rotation: number) => Promise} renderPage - Render PDF page to canvas + * @property {(operations: Object) => Promise} processOperation - Process PDF operation (merge, split, etc.) + */ + +/** + * @typedef {Object} PlatformAdapter + * @property {string} name - Platform name ('electron', 'web', 'tauri', 'flutter') + * @property {FileSystemAdapter} fs - File system operations + * @property {ConversionAdapter} convert - Conversion operations + * @property {DialogAdapter} dialog - Dialog operations + * @property {SystemAdapter} system - System operations + * @property {PdfAdapter} [pdf] - PDF operations (optional, not available on all platforms) + * @property {PlatformCapabilities} capabilities - Platform capabilities + */ + +module.exports = { + // Type definitions are JSDoc only, no runtime exports needed +};