hazo_files 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/config/index.ts","../src/modules/local/index.ts","../src/common/errors.ts","../src/common/utils.ts","../src/common/path-utils.ts","../src/common/base-module.ts","../src/common/mime-types.ts","../src/modules/google-drive/index.ts","../src/modules/google-drive/auth.ts","../src/modules/index.ts","../src/services/file-manager.ts","../src/common/naming-utils.ts"],"sourcesContent":["/**\n * Hazo Files - File Management Package\n * Supports local storage and Google Drive with a unified API\n */\n\n// Main service\nexport {\n FileManager,\n createFileManager,\n createInitializedFileManager,\n} from './services';\n\n// Configuration\nexport {\n loadConfig,\n loadConfigAsync,\n parseConfig,\n saveConfig,\n generateSampleConfig,\n} from './config';\n\n// Modules\nexport {\n createModule,\n createAndInitializeModule,\n getRegisteredProviders,\n isProviderRegistered,\n registerModule,\n LocalStorageModule,\n createLocalModule,\n GoogleDriveModule,\n createGoogleDriveModule,\n GoogleDriveAuth,\n createGoogleDriveAuth,\n} from './modules';\n\n// Common utilities\nexport {\n // Utils\n successResult,\n errorResult,\n generateId,\n formatBytes,\n isFile,\n isFolder,\n sortItems,\n filterItems,\n createFileItem,\n createFolderItem,\n // Path utils\n normalizePath,\n joinPath,\n getParentPath,\n getBaseName,\n getDirName,\n getPathSegments,\n isChildPath,\n getRelativePath,\n validatePath,\n sanitizeFilename,\n getExtension,\n getNameWithoutExtension,\n hasExtension,\n getBreadcrumbs,\n // MIME types\n getMimeType,\n getExtensionFromMime,\n isImage,\n isVideo,\n isAudio,\n isText,\n isDocument,\n isPreviewable,\n getFileCategory,\n // Errors\n HazoFilesError,\n FileNotFoundError,\n DirectoryNotFoundError,\n FileExistsError,\n DirectoryExistsError,\n DirectoryNotEmptyError,\n PermissionDeniedError,\n InvalidPathError,\n FileTooLargeError,\n InvalidExtensionError,\n AuthenticationError,\n ConfigurationError,\n OperationError,\n // Naming utilities\n DEFAULT_DATE_FORMATS,\n SYSTEM_DATE_VARIABLES,\n SYSTEM_FILE_VARIABLES,\n SYSTEM_COUNTER_VARIABLES,\n ALL_SYSTEM_VARIABLES,\n formatDateToken,\n isDateVariable,\n isFileMetadataVariable,\n isCounterVariable,\n formatCounter,\n getFileMetadataValues,\n hazo_files_generate_folder_name,\n hazo_files_generate_file_name,\n validateNamingRuleSchema,\n createEmptyNamingRuleSchema,\n generateSegmentId,\n createVariableSegment,\n createLiteralSegment,\n patternToString,\n parsePatternString,\n clonePattern,\n getSystemVariablePreviewValues,\n generatePreviewName,\n} from './common';\n\n// Types\nexport type {\n StorageProvider,\n StorageModule,\n FileItem,\n FolderItem,\n FileSystemItem,\n HazoFilesConfig,\n LocalStorageConfig,\n GoogleDriveConfig,\n OperationResult,\n ProgressCallback,\n UploadOptions,\n DownloadOptions,\n ListOptions,\n MoveOptions,\n RenameOptions,\n TreeNode,\n FileBrowserState,\n // Naming types\n VariableCategory,\n NamingVariable,\n PatternSegment,\n NamingRuleSchema,\n GeneratedNameResult,\n NameGenerationOptions,\n NamingRuleHistoryEntry,\n NamingRuleConfiguratorProps,\n UseNamingRuleState,\n UseNamingRuleActions,\n UseNamingRuleReturn,\n} from './types';\n\nexport type { FileManagerOptions } from './services';\nexport type { TokenData, AuthCallbacks, GoogleAuthConfig } from './modules';\n","/**\n * Configuration loader for hazo_files\n * Reads configuration from hazo_files_config.ini file\n */\n\nimport * as ini from 'ini';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { HazoFilesConfig, StorageProvider, LocalStorageConfig, GoogleDriveConfig } from '../types';\n\nconst DEFAULT_CONFIG_FILENAME = 'hazo_files_config.ini';\n\n/**\n * Parse INI configuration file and return typed config object\n */\nexport function parseConfig(configContent: string): HazoFilesConfig {\n const parsed = ini.parse(configContent);\n\n const provider = (parsed.general?.provider || 'local') as StorageProvider;\n\n const config: HazoFilesConfig = {\n provider,\n };\n\n // Parse local storage config\n if (parsed.local) {\n config.local = {\n basePath: parsed.local.base_path || './files',\n allowedExtensions: parsed.local.allowed_extensions\n ? parsed.local.allowed_extensions.split(',').map((ext: string) => ext.trim())\n : undefined,\n maxFileSize: parsed.local.max_file_size\n ? parseInt(parsed.local.max_file_size, 10)\n : undefined,\n };\n }\n\n // Parse Google Drive config\n if (parsed.google_drive) {\n config.google_drive = {\n clientId: parsed.google_drive.client_id || process.env.GOOGLE_DRIVE_CLIENT_ID || '',\n clientSecret: parsed.google_drive.client_secret || process.env.GOOGLE_DRIVE_CLIENT_SECRET || '',\n redirectUri: parsed.google_drive.redirect_uri || process.env.GOOGLE_DRIVE_REDIRECT_URI || '',\n refreshToken: parsed.google_drive.refresh_token || process.env.GOOGLE_DRIVE_REFRESH_TOKEN,\n accessToken: parsed.google_drive.access_token || process.env.GOOGLE_DRIVE_ACCESS_TOKEN,\n rootFolderId: parsed.google_drive.root_folder_id || process.env.GOOGLE_DRIVE_ROOT_FOLDER_ID,\n };\n }\n\n return config;\n}\n\n/**\n * Load configuration from file\n * @param configPath - Path to the config file, defaults to hazo_files_config.ini in current directory\n */\nexport function loadConfig(configPath?: string): HazoFilesConfig {\n const resolvedPath = configPath || path.join(process.cwd(), DEFAULT_CONFIG_FILENAME);\n\n if (!fs.existsSync(resolvedPath)) {\n // Return default config if file doesn't exist\n console.warn(`Config file not found at ${resolvedPath}, using defaults`);\n return {\n provider: 'local',\n local: {\n basePath: './files',\n },\n };\n }\n\n const content = fs.readFileSync(resolvedPath, 'utf-8');\n return parseConfig(content);\n}\n\n/**\n * Load configuration asynchronously\n */\nexport async function loadConfigAsync(configPath?: string): Promise<HazoFilesConfig> {\n const resolvedPath = configPath || path.join(process.cwd(), DEFAULT_CONFIG_FILENAME);\n\n try {\n const content = await fs.promises.readFile(resolvedPath, 'utf-8');\n return parseConfig(content);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n console.warn(`Config file not found at ${resolvedPath}, using defaults`);\n return {\n provider: 'local',\n local: {\n basePath: './files',\n },\n };\n }\n throw error;\n }\n}\n\n/**\n * Generate a sample configuration file content\n */\nexport function generateSampleConfig(): string {\n return `; Hazo Files Configuration\n; This file configures the file management system\n\n[general]\n; Available providers: local, google_drive\nprovider = local\n\n[local]\n; Base path for local file storage (relative or absolute)\nbase_path = ./files\n; Comma-separated list of allowed extensions (optional, empty = all allowed)\nallowed_extensions =\n; Maximum file size in bytes (optional, 0 = unlimited)\nmax_file_size = 0\n\n[google_drive]\n; Google Drive OAuth credentials\n; These can also be set via environment variables:\n; GOOGLE_DRIVE_CLIENT_ID, GOOGLE_DRIVE_CLIENT_SECRET, etc.\nclient_id =\nclient_secret =\nredirect_uri = http://localhost:3000/api/auth/callback/google\nrefresh_token =\naccess_token =\n; Optional: Root folder ID to use as base (empty = root of Drive)\nroot_folder_id =\n`;\n}\n\n/**\n * Save configuration to file\n */\nexport async function saveConfig(config: HazoFilesConfig, configPath?: string): Promise<void> {\n const resolvedPath = configPath || path.join(process.cwd(), DEFAULT_CONFIG_FILENAME);\n\n const iniConfig: Record<string, Record<string, string>> = {\n general: {\n provider: config.provider,\n },\n };\n\n if (config.local) {\n iniConfig.local = {\n base_path: config.local.basePath,\n allowed_extensions: config.local.allowedExtensions?.join(', ') || '',\n max_file_size: config.local.maxFileSize?.toString() || '0',\n };\n }\n\n if (config.google_drive) {\n iniConfig.google_drive = {\n client_id: config.google_drive.clientId || '',\n client_secret: config.google_drive.clientSecret || '',\n redirect_uri: config.google_drive.redirectUri || '',\n refresh_token: config.google_drive.refreshToken || '',\n access_token: config.google_drive.accessToken || '',\n root_folder_id: config.google_drive.rootFolderId || '',\n };\n }\n\n const content = ini.stringify(iniConfig);\n await fs.promises.writeFile(resolvedPath, content, 'utf-8');\n}\n\nexport type { HazoFilesConfig, LocalStorageConfig, GoogleDriveConfig };\n","/**\n * Local File System Storage Module\n * Implements file operations using Node.js fs module\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { Readable } from 'stream';\nimport { pipeline } from 'stream/promises';\n\nimport { BaseStorageModule } from '../../common/base-module';\nimport {\n FileNotFoundError,\n DirectoryNotFoundError,\n FileExistsError,\n DirectoryExistsError,\n DirectoryNotEmptyError,\n FileTooLargeError,\n InvalidExtensionError,\n} from '../../common/errors';\nimport { getMimeType } from '../../common/mime-types';\nimport { getExtension } from '../../common/path-utils';\nimport { generateId, createFileItem, createFolderItem } from '../../common/utils';\nimport type {\n StorageProvider,\n HazoFilesConfig,\n LocalStorageConfig,\n FileItem,\n FolderItem,\n FileSystemItem,\n OperationResult,\n UploadOptions,\n DownloadOptions,\n MoveOptions,\n RenameOptions,\n ListOptions,\n} from '../../types';\n\nexport class LocalStorageModule extends BaseStorageModule {\n readonly provider: StorageProvider = 'local';\n private basePath: string = '';\n private allowedExtensions: string[] = [];\n private maxFileSize: number = 0;\n\n async initialize(config: HazoFilesConfig): Promise<void> {\n await super.initialize(config);\n\n const localConfig = this.getProviderConfig<LocalStorageConfig>();\n this.basePath = path.resolve(localConfig.basePath);\n this.allowedExtensions = localConfig.allowedExtensions || [];\n this.maxFileSize = localConfig.maxFileSize || 0;\n\n // Ensure base directory exists\n await fs.promises.mkdir(this.basePath, { recursive: true });\n }\n\n /**\n * Resolve a virtual path to an absolute file system path\n */\n private resolveFullPath(virtualPath: string): string {\n const normalized = this.normalizePath(virtualPath);\n const relativePath = normalized.startsWith('/') ? normalized.slice(1) : normalized;\n return path.join(this.basePath, relativePath);\n }\n\n /**\n * Convert absolute path back to virtual path\n */\n private toVirtualPath(absolutePath: string): string {\n const relative = path.relative(this.basePath, absolutePath);\n return this.normalizePath('/' + relative.replace(/\\\\/g, '/'));\n }\n\n /**\n * Validate file extension against allowed list\n */\n private validateExtension(filename: string): void {\n if (this.allowedExtensions.length === 0) return;\n\n const ext = getExtension(filename).toLowerCase().slice(1); // Remove leading dot\n if (!this.allowedExtensions.includes(ext)) {\n throw new InvalidExtensionError(filename, ext, this.allowedExtensions);\n }\n }\n\n /**\n * Validate file size against maximum\n */\n private validateFileSize(size: number, filename: string): void {\n if (this.maxFileSize > 0 && size > this.maxFileSize) {\n throw new FileTooLargeError(filename, size, this.maxFileSize);\n }\n }\n\n /**\n * Create file/folder stats to FileSystemItem\n */\n private async statToItem(fullPath: string, stats: fs.Stats): Promise<FileSystemItem> {\n const virtualPath = this.toVirtualPath(fullPath);\n const name = path.basename(fullPath);\n const id = generateId();\n\n if (stats.isDirectory()) {\n return createFolderItem({\n id,\n name,\n path: virtualPath,\n createdAt: stats.birthtime,\n modifiedAt: stats.mtime,\n });\n }\n\n return createFileItem({\n id,\n name,\n path: virtualPath,\n size: stats.size,\n mimeType: getMimeType(name),\n createdAt: stats.birthtime,\n modifiedAt: stats.mtime,\n });\n }\n\n async createDirectory(virtualPath: string): Promise<OperationResult<FolderItem>> {\n this.ensureInitialized();\n\n try {\n const fullPath = this.resolveFullPath(virtualPath);\n\n // Check if already exists\n try {\n const stats = await fs.promises.stat(fullPath);\n if (stats.isDirectory()) {\n throw new DirectoryExistsError(virtualPath);\n }\n throw new FileExistsError(virtualPath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error;\n }\n }\n\n await fs.promises.mkdir(fullPath, { recursive: true });\n const stats = await fs.promises.stat(fullPath);\n const item = await this.statToItem(fullPath, stats) as FolderItem;\n\n return this.successResult(item);\n } catch (error) {\n if (error instanceof DirectoryExistsError || error instanceof FileExistsError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to create directory: ${(error as Error).message}`);\n }\n }\n\n async removeDirectory(virtualPath: string, recursive = false): Promise<OperationResult> {\n this.ensureInitialized();\n\n try {\n const fullPath = this.resolveFullPath(virtualPath);\n\n const stats = await fs.promises.stat(fullPath).catch(() => null);\n if (!stats) {\n throw new DirectoryNotFoundError(virtualPath);\n }\n if (!stats.isDirectory()) {\n throw new DirectoryNotFoundError(virtualPath);\n }\n\n if (!recursive) {\n const contents = await fs.promises.readdir(fullPath);\n if (contents.length > 0) {\n throw new DirectoryNotEmptyError(virtualPath);\n }\n }\n\n await fs.promises.rm(fullPath, { recursive, force: true });\n return this.successResult();\n } catch (error) {\n if (error instanceof DirectoryNotFoundError || error instanceof DirectoryNotEmptyError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to remove directory: ${(error as Error).message}`);\n }\n }\n\n async uploadFile(\n source: string | Buffer | ReadableStream,\n remotePath: string,\n options: UploadOptions = {}\n ): Promise<OperationResult<FileItem>> {\n this.ensureInitialized();\n\n try {\n const fullPath = this.resolveFullPath(remotePath);\n const filename = path.basename(fullPath);\n\n this.validateExtension(filename);\n\n // Check if file exists\n if (!options.overwrite) {\n try {\n await fs.promises.stat(fullPath);\n throw new FileExistsError(remotePath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n if (error instanceof FileExistsError) throw error;\n }\n }\n }\n\n // Ensure parent directory exists\n const parentDir = path.dirname(fullPath);\n await fs.promises.mkdir(parentDir, { recursive: true });\n\n if (typeof source === 'string') {\n // Source is a local file path\n const stats = await fs.promises.stat(source);\n this.validateFileSize(stats.size, filename);\n\n if (options.onProgress) {\n // Copy with progress\n const totalBytes = stats.size;\n let bytesTransferred = 0;\n const readStream = fs.createReadStream(source);\n const writeStream = fs.createWriteStream(fullPath);\n\n readStream.on('data', (chunk) => {\n bytesTransferred += (chunk as Buffer).length;\n const progress = (bytesTransferred / totalBytes) * 100;\n options.onProgress!(progress, bytesTransferred, totalBytes);\n });\n\n await pipeline(readStream, writeStream);\n } else {\n await fs.promises.copyFile(source, fullPath);\n }\n } else if (Buffer.isBuffer(source)) {\n // Source is a Buffer\n this.validateFileSize(source.length, filename);\n await fs.promises.writeFile(fullPath, source);\n if (options.onProgress) {\n options.onProgress(100, source.length, source.length);\n }\n } else {\n // Source is a ReadableStream\n const writeStream = fs.createWriteStream(fullPath);\n const readable = Readable.fromWeb(source as import('stream/web').ReadableStream);\n await pipeline(readable, writeStream);\n }\n\n const stats = await fs.promises.stat(fullPath);\n const item = await this.statToItem(fullPath, stats) as FileItem;\n\n return this.successResult(item);\n } catch (error) {\n if (\n error instanceof FileExistsError ||\n error instanceof FileTooLargeError ||\n error instanceof InvalidExtensionError\n ) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to upload file: ${(error as Error).message}`);\n }\n }\n\n async downloadFile(\n remotePath: string,\n localPath?: string,\n options: DownloadOptions = {}\n ): Promise<OperationResult<Buffer | string>> {\n this.ensureInitialized();\n\n try {\n const fullPath = this.resolveFullPath(remotePath);\n\n const stats = await fs.promises.stat(fullPath).catch(() => null);\n if (!stats || stats.isDirectory()) {\n throw new FileNotFoundError(remotePath);\n }\n\n if (localPath) {\n // Download to a local file\n const destDir = path.dirname(localPath);\n await fs.promises.mkdir(destDir, { recursive: true });\n\n if (options.onProgress) {\n const totalBytes = stats.size;\n let bytesTransferred = 0;\n const readStream = fs.createReadStream(fullPath);\n const writeStream = fs.createWriteStream(localPath);\n\n readStream.on('data', (chunk) => {\n bytesTransferred += (chunk as Buffer).length;\n const progress = (bytesTransferred / totalBytes) * 100;\n options.onProgress!(progress, bytesTransferred, totalBytes);\n });\n\n await pipeline(readStream, writeStream);\n } else {\n await fs.promises.copyFile(fullPath, localPath);\n }\n\n return this.successResult(localPath);\n } else {\n // Return buffer\n const buffer = await fs.promises.readFile(fullPath);\n if (options.onProgress) {\n options.onProgress(100, buffer.length, buffer.length);\n }\n return this.successResult(buffer);\n }\n } catch (error) {\n if (error instanceof FileNotFoundError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to download file: ${(error as Error).message}`);\n }\n }\n\n async moveItem(\n sourcePath: string,\n destinationPath: string,\n options: MoveOptions = {}\n ): Promise<OperationResult<FileSystemItem>> {\n this.ensureInitialized();\n\n try {\n const sourceFullPath = this.resolveFullPath(sourcePath);\n const destFullPath = this.resolveFullPath(destinationPath);\n\n const sourceStats = await fs.promises.stat(sourceFullPath).catch(() => null);\n if (!sourceStats) {\n throw new FileNotFoundError(sourcePath);\n }\n\n // Check destination\n if (!options.overwrite) {\n const destStats = await fs.promises.stat(destFullPath).catch(() => null);\n if (destStats) {\n throw new FileExistsError(destinationPath);\n }\n }\n\n // Ensure parent directory exists\n const destParent = path.dirname(destFullPath);\n await fs.promises.mkdir(destParent, { recursive: true });\n\n await fs.promises.rename(sourceFullPath, destFullPath);\n\n const newStats = await fs.promises.stat(destFullPath);\n const item = await this.statToItem(destFullPath, newStats);\n\n return this.successResult(item);\n } catch (error) {\n if (error instanceof FileNotFoundError || error instanceof FileExistsError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to move item: ${(error as Error).message}`);\n }\n }\n\n async deleteFile(virtualPath: string): Promise<OperationResult> {\n this.ensureInitialized();\n\n try {\n const fullPath = this.resolveFullPath(virtualPath);\n\n const stats = await fs.promises.stat(fullPath).catch(() => null);\n if (!stats) {\n throw new FileNotFoundError(virtualPath);\n }\n if (stats.isDirectory()) {\n throw new FileNotFoundError(virtualPath);\n }\n\n await fs.promises.unlink(fullPath);\n return this.successResult();\n } catch (error) {\n if (error instanceof FileNotFoundError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to delete file: ${(error as Error).message}`);\n }\n }\n\n async renameFile(\n virtualPath: string,\n newName: string,\n options: RenameOptions = {}\n ): Promise<OperationResult<FileItem>> {\n this.ensureInitialized();\n\n try {\n const fullPath = this.resolveFullPath(virtualPath);\n\n const stats = await fs.promises.stat(fullPath).catch(() => null);\n if (!stats || stats.isDirectory()) {\n throw new FileNotFoundError(virtualPath);\n }\n\n this.validateExtension(newName);\n\n const parentDir = path.dirname(fullPath);\n const newFullPath = path.join(parentDir, newName);\n\n // Check if destination exists\n if (!options.overwrite) {\n const destStats = await fs.promises.stat(newFullPath).catch(() => null);\n if (destStats) {\n throw new FileExistsError(newName);\n }\n }\n\n await fs.promises.rename(fullPath, newFullPath);\n\n const newStats = await fs.promises.stat(newFullPath);\n const item = await this.statToItem(newFullPath, newStats) as FileItem;\n\n return this.successResult(item);\n } catch (error) {\n if (\n error instanceof FileNotFoundError ||\n error instanceof FileExistsError ||\n error instanceof InvalidExtensionError\n ) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to rename file: ${(error as Error).message}`);\n }\n }\n\n async renameFolder(\n virtualPath: string,\n newName: string,\n options: RenameOptions = {}\n ): Promise<OperationResult<FolderItem>> {\n this.ensureInitialized();\n\n try {\n const fullPath = this.resolveFullPath(virtualPath);\n\n const stats = await fs.promises.stat(fullPath).catch(() => null);\n if (!stats || !stats.isDirectory()) {\n throw new DirectoryNotFoundError(virtualPath);\n }\n\n const parentDir = path.dirname(fullPath);\n const newFullPath = path.join(parentDir, newName);\n\n // Check if destination exists\n if (!options.overwrite) {\n const destStats = await fs.promises.stat(newFullPath).catch(() => null);\n if (destStats) {\n throw new DirectoryExistsError(newName);\n }\n }\n\n await fs.promises.rename(fullPath, newFullPath);\n\n const newStats = await fs.promises.stat(newFullPath);\n const item = await this.statToItem(newFullPath, newStats) as FolderItem;\n\n return this.successResult(item);\n } catch (error) {\n if (error instanceof DirectoryNotFoundError || error instanceof DirectoryExistsError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to rename folder: ${(error as Error).message}`);\n }\n }\n\n async listDirectory(\n virtualPath: string,\n options: ListOptions = {}\n ): Promise<OperationResult<FileSystemItem[]>> {\n this.ensureInitialized();\n\n try {\n const fullPath = this.resolveFullPath(virtualPath);\n\n const stats = await fs.promises.stat(fullPath).catch(() => null);\n if (!stats || !stats.isDirectory()) {\n throw new DirectoryNotFoundError(virtualPath);\n }\n\n const entries = await fs.promises.readdir(fullPath, { withFileTypes: true });\n const items: FileSystemItem[] = [];\n\n for (const entry of entries) {\n // Skip hidden files unless explicitly included\n if (!options.includeHidden && entry.name.startsWith('.')) {\n continue;\n }\n\n const entryPath = path.join(fullPath, entry.name);\n const entryStats = await fs.promises.stat(entryPath);\n const item = await this.statToItem(entryPath, entryStats);\n\n // Apply filter if provided\n if (options.filter && !options.filter(item)) {\n continue;\n }\n\n items.push(item);\n\n // Handle recursive listing\n if (options.recursive && entry.isDirectory()) {\n const subResult = await this.listDirectory(\n this.toVirtualPath(entryPath),\n options\n );\n if (subResult.success && subResult.data) {\n items.push(...subResult.data);\n }\n }\n }\n\n // Sort: folders first, then alphabetically\n items.sort((a, b) => {\n if (a.isDirectory && !b.isDirectory) return -1;\n if (!a.isDirectory && b.isDirectory) return 1;\n return a.name.localeCompare(b.name);\n });\n\n return this.successResult(items);\n } catch (error) {\n if (error instanceof DirectoryNotFoundError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to list directory: ${(error as Error).message}`);\n }\n }\n\n async getItem(virtualPath: string): Promise<OperationResult<FileSystemItem>> {\n this.ensureInitialized();\n\n try {\n const fullPath = this.resolveFullPath(virtualPath);\n\n const stats = await fs.promises.stat(fullPath).catch(() => null);\n if (!stats) {\n throw new FileNotFoundError(virtualPath);\n }\n\n const item = await this.statToItem(fullPath, stats);\n return this.successResult(item);\n } catch (error) {\n if (error instanceof FileNotFoundError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to get item: ${(error as Error).message}`);\n }\n }\n\n async exists(virtualPath: string): Promise<boolean> {\n this.ensureInitialized();\n\n try {\n const fullPath = this.resolveFullPath(virtualPath);\n await fs.promises.stat(fullPath);\n return true;\n } catch {\n return false;\n }\n }\n}\n\n/**\n * Factory function to create a LocalStorageModule instance\n */\nexport function createLocalModule(): LocalStorageModule {\n return new LocalStorageModule();\n}\n\nexport default LocalStorageModule;\n","/**\n * Custom error classes for hazo_files\n */\n\nexport class HazoFilesError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: Record<string, unknown>\n ) {\n super(message);\n this.name = 'HazoFilesError';\n }\n}\n\nexport class FileNotFoundError extends HazoFilesError {\n constructor(path: string) {\n super(`File not found: ${path}`, 'FILE_NOT_FOUND', { path });\n this.name = 'FileNotFoundError';\n }\n}\n\nexport class DirectoryNotFoundError extends HazoFilesError {\n constructor(path: string) {\n super(`Directory not found: ${path}`, 'DIRECTORY_NOT_FOUND', { path });\n this.name = 'DirectoryNotFoundError';\n }\n}\n\nexport class FileExistsError extends HazoFilesError {\n constructor(path: string) {\n super(`File already exists: ${path}`, 'FILE_EXISTS', { path });\n this.name = 'FileExistsError';\n }\n}\n\nexport class DirectoryExistsError extends HazoFilesError {\n constructor(path: string) {\n super(`Directory already exists: ${path}`, 'DIRECTORY_EXISTS', { path });\n this.name = 'DirectoryExistsError';\n }\n}\n\nexport class DirectoryNotEmptyError extends HazoFilesError {\n constructor(path: string) {\n super(`Directory is not empty: ${path}`, 'DIRECTORY_NOT_EMPTY', { path });\n this.name = 'DirectoryNotEmptyError';\n }\n}\n\nexport class PermissionDeniedError extends HazoFilesError {\n constructor(path: string, operation: string) {\n super(`Permission denied for ${operation} on: ${path}`, 'PERMISSION_DENIED', { path, operation });\n this.name = 'PermissionDeniedError';\n }\n}\n\nexport class InvalidPathError extends HazoFilesError {\n constructor(path: string, reason: string) {\n super(`Invalid path \"${path}\": ${reason}`, 'INVALID_PATH', { path, reason });\n this.name = 'InvalidPathError';\n }\n}\n\nexport class FileTooLargeError extends HazoFilesError {\n constructor(path: string, size: number, maxSize: number) {\n super(\n `File \"${path}\" is too large (${size} bytes). Maximum allowed: ${maxSize} bytes`,\n 'FILE_TOO_LARGE',\n { path, size, maxSize }\n );\n this.name = 'FileTooLargeError';\n }\n}\n\nexport class InvalidExtensionError extends HazoFilesError {\n constructor(path: string, extension: string, allowedExtensions: string[]) {\n super(\n `File extension \"${extension}\" is not allowed. Allowed: ${allowedExtensions.join(', ')}`,\n 'INVALID_EXTENSION',\n { path, extension, allowedExtensions }\n );\n this.name = 'InvalidExtensionError';\n }\n}\n\nexport class AuthenticationError extends HazoFilesError {\n constructor(provider: string, message: string) {\n super(`Authentication failed for ${provider}: ${message}`, 'AUTHENTICATION_ERROR', { provider });\n this.name = 'AuthenticationError';\n }\n}\n\nexport class ConfigurationError extends HazoFilesError {\n constructor(message: string) {\n super(`Configuration error: ${message}`, 'CONFIGURATION_ERROR');\n this.name = 'ConfigurationError';\n }\n}\n\nexport class OperationError extends HazoFilesError {\n constructor(operation: string, message: string, details?: Record<string, unknown>) {\n super(`${operation} failed: ${message}`, 'OPERATION_ERROR', details);\n this.name = 'OperationError';\n }\n}\n","/**\n * Common utility functions\n */\n\nimport type { OperationResult, FileItem, FolderItem, FileSystemItem } from '../types';\n\n/**\n * Create a successful operation result\n */\nexport function successResult<T>(data?: T): OperationResult<T> {\n return {\n success: true,\n data,\n };\n}\n\n/**\n * Create a failed operation result\n */\nexport function errorResult<T = void>(error: string): OperationResult<T> {\n return {\n success: false,\n error,\n };\n}\n\n/**\n * Generate a unique ID\n */\nexport function generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n}\n\n/**\n * Format bytes to human readable string\n */\nexport function formatBytes(bytes: number, decimals = 2): string {\n if (bytes === 0) return '0 Bytes';\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];\n}\n\n/**\n * Check if item is a file\n */\nexport function isFile(item: FileSystemItem): item is FileItem {\n return !item.isDirectory;\n}\n\n/**\n * Check if item is a folder\n */\nexport function isFolder(item: FileSystemItem): item is FolderItem {\n return item.isDirectory;\n}\n\n/**\n * Sort file system items (folders first, then alphabetically)\n */\nexport function sortItems(items: FileSystemItem[]): FileSystemItem[] {\n return [...items].sort((a, b) => {\n // Folders first\n if (a.isDirectory && !b.isDirectory) return -1;\n if (!a.isDirectory && b.isDirectory) return 1;\n // Then alphabetically\n return a.name.localeCompare(b.name);\n });\n}\n\n/**\n * Filter items by search term\n */\nexport function filterItems(items: FileSystemItem[], searchTerm: string): FileSystemItem[] {\n const term = searchTerm.toLowerCase();\n return items.filter(item => item.name.toLowerCase().includes(term));\n}\n\n/**\n * Create a delay (useful for rate limiting)\n */\nexport function delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Retry an operation with exponential backoff\n */\nexport async function withRetry<T>(\n operation: () => Promise<T>,\n maxRetries = 3,\n initialDelay = 1000\n): Promise<T> {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n return await operation();\n } catch (error) {\n lastError = error as Error;\n if (attempt < maxRetries - 1) {\n await delay(initialDelay * Math.pow(2, attempt));\n }\n }\n }\n\n throw lastError;\n}\n\n/**\n * Check if running in browser environment\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined';\n}\n\n/**\n * Check if running in Node.js environment\n */\nexport function isNode(): boolean {\n return typeof process !== 'undefined' && process.versions?.node !== undefined;\n}\n\n/**\n * Safe JSON parse with fallback\n */\nexport function safeJsonParse<T>(json: string, fallback: T): T {\n try {\n return JSON.parse(json);\n } catch {\n return fallback;\n }\n}\n\n/**\n * Deep clone an object\n */\nexport function deepClone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj));\n}\n\n/**\n * Create a FileItem object\n */\nexport function createFileItem(params: {\n id: string;\n name: string;\n path: string;\n size: number;\n mimeType: string;\n createdAt?: Date;\n modifiedAt?: Date;\n parentId?: string;\n metadata?: Record<string, unknown>;\n}): FileItem {\n return {\n id: params.id,\n name: params.name,\n path: params.path,\n size: params.size,\n mimeType: params.mimeType,\n createdAt: params.createdAt || new Date(),\n modifiedAt: params.modifiedAt || new Date(),\n isDirectory: false,\n parentId: params.parentId,\n metadata: params.metadata,\n };\n}\n\n/**\n * Create a FolderItem object\n */\nexport function createFolderItem(params: {\n id: string;\n name: string;\n path: string;\n createdAt?: Date;\n modifiedAt?: Date;\n parentId?: string;\n children?: (FileItem | FolderItem)[];\n metadata?: Record<string, unknown>;\n}): FolderItem {\n return {\n id: params.id,\n name: params.name,\n path: params.path,\n createdAt: params.createdAt || new Date(),\n modifiedAt: params.modifiedAt || new Date(),\n isDirectory: true,\n parentId: params.parentId,\n children: params.children,\n metadata: params.metadata,\n };\n}\n","/**\n * Path manipulation utilities\n */\n\nimport { InvalidPathError } from './errors';\n\n/**\n * Normalize a path (handle separators, remove trailing slashes, resolve . and ..)\n */\nexport function normalizePath(inputPath: string): string {\n if (!inputPath) return '/';\n\n // Replace backslashes with forward slashes\n let normalized = inputPath.replace(/\\\\/g, '/');\n\n // Handle multiple consecutive slashes\n normalized = normalized.replace(/\\/+/g, '/');\n\n // Handle . and ..\n const parts = normalized.split('/');\n const result: string[] = [];\n\n for (const part of parts) {\n if (part === '.' || part === '') continue;\n if (part === '..') {\n result.pop();\n } else {\n result.push(part);\n }\n }\n\n normalized = '/' + result.join('/');\n\n return normalized;\n}\n\n/**\n * Join path segments\n */\nexport function joinPath(...segments: string[]): string {\n const joined = segments\n .map(s => s.replace(/^\\/+|\\/+$/g, ''))\n .filter(Boolean)\n .join('/');\n return normalizePath('/' + joined);\n}\n\n/**\n * Get the parent directory of a path\n */\nexport function getParentPath(inputPath: string): string {\n const normalized = normalizePath(inputPath);\n if (normalized === '/') return '/';\n\n const lastSlash = normalized.lastIndexOf('/');\n if (lastSlash === 0) return '/';\n return normalized.slice(0, lastSlash) || '/';\n}\n\n/**\n * Get the base name (file/folder name) from a path\n */\nexport function getBaseName(inputPath: string): string {\n const normalized = normalizePath(inputPath);\n if (normalized === '/') return '';\n\n const lastSlash = normalized.lastIndexOf('/');\n return normalized.slice(lastSlash + 1);\n}\n\n/**\n * Get the directory name from a path (alias for getParentPath)\n */\nexport function getDirName(inputPath: string): string {\n return getParentPath(inputPath);\n}\n\n/**\n * Get path segments as array\n */\nexport function getPathSegments(inputPath: string): string[] {\n const normalized = normalizePath(inputPath);\n if (normalized === '/') return [];\n return normalized.slice(1).split('/');\n}\n\n/**\n * Check if a path is a child of another path\n */\nexport function isChildPath(parentPath: string, childPath: string): boolean {\n const normalizedParent = normalizePath(parentPath);\n const normalizedChild = normalizePath(childPath);\n\n if (normalizedParent === '/') {\n return normalizedChild !== '/';\n }\n\n return normalizedChild.startsWith(normalizedParent + '/');\n}\n\n/**\n * Get relative path from base to target\n */\nexport function getRelativePath(basePath: string, targetPath: string): string {\n const baseSegments = getPathSegments(basePath);\n const targetSegments = getPathSegments(targetPath);\n\n // Find common prefix\n let commonLength = 0;\n while (\n commonLength < baseSegments.length &&\n commonLength < targetSegments.length &&\n baseSegments[commonLength] === targetSegments[commonLength]\n ) {\n commonLength++;\n }\n\n // Build relative path\n const upCount = baseSegments.length - commonLength;\n const remaining = targetSegments.slice(commonLength);\n\n const parts: string[] = [];\n for (let i = 0; i < upCount; i++) {\n parts.push('..');\n }\n parts.push(...remaining);\n\n return parts.join('/') || '.';\n}\n\n/**\n * Validate a path for security issues\n */\nexport function validatePath(inputPath: string, basePath?: string): void {\n // Normalize is called for side-effect of checking path validity\n normalizePath(inputPath);\n\n // Check for null bytes\n if (inputPath.includes('\\0')) {\n throw new InvalidPathError(inputPath, 'Path contains null bytes');\n }\n\n // Check for path traversal if basePath is provided\n if (basePath) {\n const normalizedBase = normalizePath(basePath);\n const fullPath = joinPath(normalizedBase, inputPath);\n\n if (!fullPath.startsWith(normalizedBase)) {\n throw new InvalidPathError(inputPath, 'Path traversal detected');\n }\n }\n}\n\n/**\n * Create a safe filename by removing/replacing invalid characters\n */\nexport function sanitizeFilename(filename: string): string {\n // Remove or replace invalid characters\n let sanitized = filename\n .replace(/[<>:\"/\\\\|?*\\x00-\\x1F]/g, '_')\n .replace(/^\\.+/, '')\n .trim();\n\n // Ensure filename is not empty\n if (!sanitized) {\n sanitized = 'unnamed';\n }\n\n // Limit length\n if (sanitized.length > 255) {\n const ext = getExtension(sanitized);\n const name = sanitized.slice(0, 255 - ext.length);\n sanitized = name + ext;\n }\n\n return sanitized;\n}\n\n/**\n * Get file extension\n */\nexport function getExtension(filename: string): string {\n const lastDot = filename.lastIndexOf('.');\n if (lastDot === -1 || lastDot === 0) return '';\n return filename.slice(lastDot);\n}\n\n/**\n * Get filename without extension\n */\nexport function getNameWithoutExtension(filename: string): string {\n const lastDot = filename.lastIndexOf('.');\n if (lastDot === -1 || lastDot === 0) return filename;\n return filename.slice(0, lastDot);\n}\n\n/**\n * Check if filename has specific extension\n */\nexport function hasExtension(filename: string, extension: string): boolean {\n const ext = getExtension(filename).toLowerCase();\n const targetExt = extension.startsWith('.') ? extension.toLowerCase() : '.' + extension.toLowerCase();\n return ext === targetExt;\n}\n\n/**\n * Get breadcrumb segments for a path\n */\nexport function getBreadcrumbs(inputPath: string): Array<{ name: string; path: string }> {\n const segments = getPathSegments(inputPath);\n const breadcrumbs: Array<{ name: string; path: string }> = [\n { name: 'Root', path: '/' },\n ];\n\n let currentPath = '';\n for (const segment of segments) {\n currentPath += '/' + segment;\n breadcrumbs.push({\n name: segment,\n path: currentPath,\n });\n }\n\n return breadcrumbs;\n}\n","/**\n * Base module class providing common functionality for all storage modules.\n * All storage module implementations should extend this class.\n */\n\nimport type {\n StorageModule,\n StorageProvider,\n HazoFilesConfig,\n FileItem,\n FolderItem,\n FileSystemItem,\n OperationResult,\n UploadOptions,\n DownloadOptions,\n MoveOptions,\n RenameOptions,\n ListOptions,\n TreeNode,\n} from '../types';\nimport { ConfigurationError } from './errors';\nimport { successResult, errorResult } from './utils';\nimport { normalizePath, joinPath, getBaseName, getParentPath } from './path-utils';\n\n/**\n * Abstract base class for storage modules.\n * Provides common functionality and enforces the StorageModule interface.\n */\nexport abstract class BaseStorageModule implements StorageModule {\n abstract readonly provider: StorageProvider;\n protected config: HazoFilesConfig | null = null;\n protected _initialized = false;\n\n /**\n * Check if the module is initialized\n */\n get isInitialized(): boolean {\n return this._initialized;\n }\n\n /**\n * Initialize the module with configuration.\n * Subclasses should call super.initialize(config) first.\n */\n async initialize(config: HazoFilesConfig): Promise<void> {\n this.config = config;\n this._initialized = true;\n }\n\n /**\n * Ensure the module is initialized before operations\n */\n protected ensureInitialized(): void {\n if (!this._initialized || !this.config) {\n throw new ConfigurationError('Module not initialized. Call initialize() first.');\n }\n }\n\n /**\n * Get the provider-specific configuration\n */\n protected getProviderConfig<T>(): T {\n this.ensureInitialized();\n const providerConfig = this.config![this.provider as keyof HazoFilesConfig];\n if (!providerConfig) {\n throw new ConfigurationError(`No configuration found for provider: ${this.provider}`);\n }\n return providerConfig as T;\n }\n\n // Abstract methods that must be implemented by subclasses\n abstract createDirectory(path: string): Promise<OperationResult<FolderItem>>;\n abstract removeDirectory(path: string, recursive?: boolean): Promise<OperationResult>;\n abstract uploadFile(\n source: string | Buffer | ReadableStream,\n remotePath: string,\n options?: UploadOptions\n ): Promise<OperationResult<FileItem>>;\n abstract downloadFile(\n remotePath: string,\n localPath?: string,\n options?: DownloadOptions\n ): Promise<OperationResult<Buffer | string>>;\n abstract moveItem(\n sourcePath: string,\n destinationPath: string,\n options?: MoveOptions\n ): Promise<OperationResult<FileSystemItem>>;\n abstract deleteFile(path: string): Promise<OperationResult>;\n abstract renameFile(\n path: string,\n newName: string,\n options?: RenameOptions\n ): Promise<OperationResult<FileItem>>;\n abstract renameFolder(\n path: string,\n newName: string,\n options?: RenameOptions\n ): Promise<OperationResult<FolderItem>>;\n abstract listDirectory(\n path: string,\n options?: ListOptions\n ): Promise<OperationResult<FileSystemItem[]>>;\n abstract getItem(path: string): Promise<OperationResult<FileSystemItem>>;\n abstract exists(path: string): Promise<boolean>;\n\n /**\n * Get folder tree structure.\n * Default implementation that can be overridden by subclasses for optimization.\n */\n async getFolderTree(path = '/', depth = 3): Promise<OperationResult<TreeNode[]>> {\n this.ensureInitialized();\n\n try {\n const result = await this.buildTree(path, depth, 0);\n return successResult(result);\n } catch (error) {\n return errorResult(`Failed to get folder tree: ${(error as Error).message}`);\n }\n }\n\n /**\n * Recursively build folder tree\n */\n protected async buildTree(path: string, maxDepth: number, currentDepth: number): Promise<TreeNode[]> {\n if (currentDepth >= maxDepth) {\n return [];\n }\n\n const listResult = await this.listDirectory(path, { recursive: false });\n if (!listResult.success || !listResult.data) {\n return [];\n }\n\n const folders = listResult.data.filter(item => item.isDirectory);\n const nodes: TreeNode[] = [];\n\n for (const folder of folders) {\n const children = await this.buildTree(folder.path, maxDepth, currentDepth + 1);\n nodes.push({\n id: folder.id,\n name: folder.name,\n path: folder.path,\n children,\n });\n }\n\n return nodes;\n }\n\n // Utility methods available to subclasses\n protected normalizePath = normalizePath;\n protected joinPath = joinPath;\n protected getBaseName = getBaseName;\n protected getParentPath = getParentPath;\n protected successResult = successResult;\n protected errorResult = errorResult;\n}\n\n/**\n * Type guard to check if a module is initialized\n */\nexport function isModuleInitialized(module: StorageModule): boolean {\n return (module as BaseStorageModule).isInitialized ?? false;\n}\n","/**\n * MIME type utilities\n */\n\nimport { getExtension } from './path-utils';\n\nconst MIME_TYPES: Record<string, string> = {\n // Text\n '.txt': 'text/plain',\n '.html': 'text/html',\n '.htm': 'text/html',\n '.css': 'text/css',\n '.csv': 'text/csv',\n '.xml': 'text/xml',\n '.json': 'application/json',\n '.js': 'application/javascript',\n '.ts': 'application/typescript',\n '.jsx': 'text/jsx',\n '.tsx': 'text/tsx',\n '.md': 'text/markdown',\n '.yaml': 'text/yaml',\n '.yml': 'text/yaml',\n\n // Images\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.bmp': 'image/bmp',\n '.webp': 'image/webp',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n\n // Documents\n '.pdf': 'application/pdf',\n '.doc': 'application/msword',\n '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n '.xls': 'application/vnd.ms-excel',\n '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n '.ppt': 'application/vnd.ms-powerpoint',\n '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n\n // Archives\n '.zip': 'application/zip',\n '.rar': 'application/x-rar-compressed',\n '.7z': 'application/x-7z-compressed',\n '.tar': 'application/x-tar',\n '.gz': 'application/gzip',\n\n // Audio\n '.mp3': 'audio/mpeg',\n '.wav': 'audio/wav',\n '.ogg': 'audio/ogg',\n '.m4a': 'audio/mp4',\n '.flac': 'audio/flac',\n\n // Video\n '.mp4': 'video/mp4',\n '.webm': 'video/webm',\n '.avi': 'video/x-msvideo',\n '.mov': 'video/quicktime',\n '.wmv': 'video/x-ms-wmv',\n '.mkv': 'video/x-matroska',\n\n // Fonts\n '.ttf': 'font/ttf',\n '.otf': 'font/otf',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n\n // Other\n '.exe': 'application/x-msdownload',\n '.dmg': 'application/x-apple-diskimage',\n '.bin': 'application/octet-stream',\n};\n\nconst EXTENSION_BY_MIME: Record<string, string> = Object.entries(MIME_TYPES).reduce(\n (acc, [ext, mime]) => {\n if (!acc[mime]) {\n acc[mime] = ext;\n }\n return acc;\n },\n {} as Record<string, string>\n);\n\n/**\n * Get MIME type from file extension\n */\nexport function getMimeType(filename: string): string {\n const ext = getExtension(filename).toLowerCase();\n return MIME_TYPES[ext] || 'application/octet-stream';\n}\n\n/**\n * Get extension from MIME type\n */\nexport function getExtensionFromMime(mimeType: string): string {\n return EXTENSION_BY_MIME[mimeType] || '';\n}\n\n/**\n * Check if file is an image\n */\nexport function isImage(filenameOrMime: string): boolean {\n const mime = filenameOrMime.includes('/') ? filenameOrMime : getMimeType(filenameOrMime);\n return mime.startsWith('image/');\n}\n\n/**\n * Check if file is a video\n */\nexport function isVideo(filenameOrMime: string): boolean {\n const mime = filenameOrMime.includes('/') ? filenameOrMime : getMimeType(filenameOrMime);\n return mime.startsWith('video/');\n}\n\n/**\n * Check if file is audio\n */\nexport function isAudio(filenameOrMime: string): boolean {\n const mime = filenameOrMime.includes('/') ? filenameOrMime : getMimeType(filenameOrMime);\n return mime.startsWith('audio/');\n}\n\n/**\n * Check if file is a text file\n */\nexport function isText(filenameOrMime: string): boolean {\n const mime = filenameOrMime.includes('/') ? filenameOrMime : getMimeType(filenameOrMime);\n return mime.startsWith('text/') || mime === 'application/json' || mime === 'application/javascript';\n}\n\n/**\n * Check if file is a document (PDF, Word, Excel, etc.)\n */\nexport function isDocument(filenameOrMime: string): boolean {\n const mime = filenameOrMime.includes('/') ? filenameOrMime : getMimeType(filenameOrMime);\n return (\n mime === 'application/pdf' ||\n mime.includes('document') ||\n mime.includes('spreadsheet') ||\n mime.includes('presentation')\n );\n}\n\n/**\n * Check if file can be previewed in browser\n */\nexport function isPreviewable(filenameOrMime: string): boolean {\n return isImage(filenameOrMime) || isText(filenameOrMime) || isVideo(filenameOrMime) || isAudio(filenameOrMime);\n}\n\n/**\n * Get file type category\n */\nexport function getFileCategory(filenameOrMime: string): 'image' | 'video' | 'audio' | 'document' | 'text' | 'other' {\n if (isImage(filenameOrMime)) return 'image';\n if (isVideo(filenameOrMime)) return 'video';\n if (isAudio(filenameOrMime)) return 'audio';\n if (isDocument(filenameOrMime)) return 'document';\n if (isText(filenameOrMime)) return 'text';\n return 'other';\n}\n","/**\n * Google Drive Storage Module\n * Implements file operations using Google Drive API\n */\n\nimport { google, drive_v3 } from 'googleapis';\nimport { Readable } from 'stream';\n\nimport { BaseStorageModule } from '../../common/base-module';\nimport {\n FileNotFoundError,\n DirectoryNotFoundError,\n FileExistsError,\n AuthenticationError,\n} from '../../common/errors';\nimport { createFileItem, createFolderItem } from '../../common/utils';\nimport { GoogleDriveAuth, createGoogleDriveAuth, TokenData, AuthCallbacks } from './auth';\nimport type {\n StorageProvider,\n HazoFilesConfig,\n GoogleDriveConfig,\n FileItem,\n FolderItem,\n FileSystemItem,\n OperationResult,\n UploadOptions,\n DownloadOptions,\n MoveOptions,\n RenameOptions,\n ListOptions,\n TreeNode,\n} from '../../types';\n\nconst FOLDER_MIME_TYPE = 'application/vnd.google-apps.folder';\n\nexport class GoogleDriveModule extends BaseStorageModule {\n readonly provider: StorageProvider = 'google_drive';\n private auth: GoogleDriveAuth | null = null;\n private drive: drive_v3.Drive | null = null;\n private rootFolderId: string = 'root';\n private authCallbacks: AuthCallbacks = {};\n\n /**\n * Set authentication callbacks for token persistence\n */\n setAuthCallbacks(callbacks: AuthCallbacks): void {\n this.authCallbacks = callbacks;\n }\n\n async initialize(config: HazoFilesConfig): Promise<void> {\n await super.initialize(config);\n\n const driveConfig = this.getProviderConfig<GoogleDriveConfig>();\n\n if (!driveConfig.clientId || !driveConfig.clientSecret) {\n throw new AuthenticationError('google_drive', 'Missing client ID or client secret');\n }\n\n this.auth = createGoogleDriveAuth(\n {\n clientId: driveConfig.clientId,\n clientSecret: driveConfig.clientSecret,\n redirectUri: driveConfig.redirectUri,\n },\n this.authCallbacks\n );\n\n // Set tokens if provided in config\n if (driveConfig.refreshToken) {\n await this.auth.setTokens({\n accessToken: driveConfig.accessToken || '',\n refreshToken: driveConfig.refreshToken,\n });\n }\n\n this.drive = google.drive({ version: 'v3', auth: this.auth.getClient() });\n this.rootFolderId = driveConfig.rootFolderId || 'root';\n }\n\n /**\n * Get the auth instance for OAuth flow\n */\n getAuth(): GoogleDriveAuth {\n if (!this.auth) {\n throw new AuthenticationError('google_drive', 'Module not initialized');\n }\n return this.auth;\n }\n\n /**\n * Check if user is authenticated\n */\n isAuthenticated(): boolean {\n return this.auth?.isAuthenticated() ?? false;\n }\n\n /**\n * Authenticate with provided tokens\n */\n async authenticate(tokens: TokenData): Promise<void> {\n if (!this.auth) {\n throw new AuthenticationError('google_drive', 'Module not initialized');\n }\n await this.auth.setTokens(tokens);\n }\n\n /**\n * Ensure authenticated before operations\n */\n private async ensureAuthenticated(): Promise<void> {\n this.ensureInitialized();\n if (!this.isAuthenticated()) {\n throw new AuthenticationError('google_drive', 'Not authenticated. Please connect your Google Drive.');\n }\n await this.auth!.ensureValidToken();\n }\n\n /**\n * Get folder ID from path (creates folders if needed for certain operations)\n */\n private async getIdFromPath(virtualPath: string, createIfMissing = false): Promise<string | null> {\n const normalized = this.normalizePath(virtualPath);\n if (normalized === '/') {\n return this.rootFolderId;\n }\n\n const segments = normalized.split('/').filter(Boolean);\n let currentParentId = this.rootFolderId;\n\n for (const segment of segments) {\n const query = `name='${segment}' and '${currentParentId}' in parents and trashed=false`;\n\n const response = await this.drive!.files.list({\n q: query,\n fields: 'files(id, name, mimeType)',\n pageSize: 1,\n });\n\n if (response.data.files && response.data.files.length > 0) {\n currentParentId = response.data.files[0].id!;\n } else if (createIfMissing) {\n // Create the folder\n const createResponse = await this.drive!.files.create({\n requestBody: {\n name: segment,\n mimeType: FOLDER_MIME_TYPE,\n parents: [currentParentId],\n },\n fields: 'id',\n });\n currentParentId = createResponse.data.id!;\n } else {\n return null;\n }\n }\n\n return currentParentId;\n }\n\n /**\n * Convert Drive file to FileSystemItem\n */\n private driveFileToItem(file: drive_v3.Schema$File, virtualPath?: string): FileSystemItem {\n const isFolder = file.mimeType === FOLDER_MIME_TYPE;\n const path = virtualPath || '';\n\n if (isFolder) {\n return createFolderItem({\n id: file.id!,\n name: file.name!,\n path,\n createdAt: file.createdTime ? new Date(file.createdTime) : new Date(),\n modifiedAt: file.modifiedTime ? new Date(file.modifiedTime) : new Date(),\n metadata: {\n driveId: file.id,\n webViewLink: file.webViewLink,\n },\n });\n }\n\n return createFileItem({\n id: file.id!,\n name: file.name!,\n path,\n size: parseInt(file.size || '0', 10),\n mimeType: file.mimeType || 'application/octet-stream',\n createdAt: file.createdTime ? new Date(file.createdTime) : new Date(),\n modifiedAt: file.modifiedTime ? new Date(file.modifiedTime) : new Date(),\n metadata: {\n driveId: file.id,\n webViewLink: file.webViewLink,\n thumbnailLink: file.thumbnailLink,\n },\n });\n }\n\n async createDirectory(virtualPath: string): Promise<OperationResult<FolderItem>> {\n try {\n await this.ensureAuthenticated();\n\n const normalized = this.normalizePath(virtualPath);\n const parentPath = this.getParentPath(normalized);\n const folderName = this.getBaseName(normalized);\n\n // Get or create parent folder\n const parentId = await this.getIdFromPath(parentPath, true);\n if (!parentId) {\n throw new DirectoryNotFoundError(parentPath);\n }\n\n // Check if folder already exists\n const existingQuery = `name='${folderName}' and '${parentId}' in parents and mimeType='${FOLDER_MIME_TYPE}' and trashed=false`;\n const existingResponse = await this.drive!.files.list({\n q: existingQuery,\n fields: 'files(id)',\n pageSize: 1,\n });\n\n if (existingResponse.data.files && existingResponse.data.files.length > 0) {\n return this.errorResult(`Directory already exists: ${virtualPath}`);\n }\n\n // Create the folder\n const response = await this.drive!.files.create({\n requestBody: {\n name: folderName,\n mimeType: FOLDER_MIME_TYPE,\n parents: [parentId],\n },\n fields: 'id, name, mimeType, createdTime, modifiedTime, webViewLink',\n });\n\n const item = this.driveFileToItem(response.data, normalized) as FolderItem;\n return this.successResult(item);\n } catch (error) {\n if (error instanceof AuthenticationError || error instanceof DirectoryNotFoundError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to create directory: ${(error as Error).message}`);\n }\n }\n\n async removeDirectory(virtualPath: string, recursive = false): Promise<OperationResult> {\n try {\n await this.ensureAuthenticated();\n\n const folderId = await this.getIdFromPath(virtualPath);\n if (!folderId) {\n throw new DirectoryNotFoundError(virtualPath);\n }\n\n if (!recursive) {\n // Check if folder is empty\n const childrenResponse = await this.drive!.files.list({\n q: `'${folderId}' in parents and trashed=false`,\n fields: 'files(id)',\n pageSize: 1,\n });\n\n if (childrenResponse.data.files && childrenResponse.data.files.length > 0) {\n return this.errorResult(`Directory is not empty: ${virtualPath}`);\n }\n }\n\n await this.drive!.files.delete({ fileId: folderId });\n return this.successResult();\n } catch (error) {\n if (error instanceof DirectoryNotFoundError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to remove directory: ${(error as Error).message}`);\n }\n }\n\n async uploadFile(\n source: string | Buffer | ReadableStream,\n remotePath: string,\n options: UploadOptions = {}\n ): Promise<OperationResult<FileItem>> {\n try {\n await this.ensureAuthenticated();\n\n const normalized = this.normalizePath(remotePath);\n const parentPath = this.getParentPath(normalized);\n const fileName = this.getBaseName(normalized);\n\n // Get or create parent folder\n const parentId = await this.getIdFromPath(parentPath, true);\n if (!parentId) {\n throw new DirectoryNotFoundError(parentPath);\n }\n\n // Check if file already exists\n if (!options.overwrite) {\n const existingQuery = `name='${fileName}' and '${parentId}' in parents and trashed=false`;\n const existingResponse = await this.drive!.files.list({\n q: existingQuery,\n fields: 'files(id)',\n pageSize: 1,\n });\n\n if (existingResponse.data.files && existingResponse.data.files.length > 0) {\n throw new FileExistsError(remotePath);\n }\n }\n\n let media: { mimeType: string; body: Readable | Buffer };\n\n if (typeof source === 'string') {\n // Source is a file path - read it\n const fs = await import('fs');\n media = {\n mimeType: 'application/octet-stream',\n body: fs.createReadStream(source),\n };\n } else if (Buffer.isBuffer(source)) {\n media = {\n mimeType: 'application/octet-stream',\n body: source,\n };\n } else {\n media = {\n mimeType: 'application/octet-stream',\n body: Readable.fromWeb(source as import('stream/web').ReadableStream),\n };\n }\n\n const response = await this.drive!.files.create({\n requestBody: {\n name: fileName,\n parents: [parentId],\n },\n media,\n fields: 'id, name, mimeType, size, createdTime, modifiedTime, webViewLink, thumbnailLink',\n });\n\n if (options.onProgress) {\n options.onProgress(100, parseInt(response.data.size || '0', 10), parseInt(response.data.size || '0', 10));\n }\n\n const item = this.driveFileToItem(response.data, normalized) as FileItem;\n return this.successResult(item);\n } catch (error) {\n if (\n error instanceof AuthenticationError ||\n error instanceof DirectoryNotFoundError ||\n error instanceof FileExistsError\n ) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to upload file: ${(error as Error).message}`);\n }\n }\n\n async downloadFile(\n remotePath: string,\n localPath?: string,\n options: DownloadOptions = {}\n ): Promise<OperationResult<Buffer | string>> {\n try {\n await this.ensureAuthenticated();\n\n const fileId = await this.getIdFromPath(remotePath);\n if (!fileId) {\n throw new FileNotFoundError(remotePath);\n }\n\n const response = await this.drive!.files.get(\n { fileId, alt: 'media' },\n { responseType: 'arraybuffer' }\n );\n\n const buffer = Buffer.from(response.data as ArrayBuffer);\n\n if (options.onProgress) {\n options.onProgress(100, buffer.length, buffer.length);\n }\n\n if (localPath) {\n const fs = await import('fs');\n const path = await import('path');\n await fs.promises.mkdir(path.dirname(localPath), { recursive: true });\n await fs.promises.writeFile(localPath, buffer);\n return this.successResult(localPath);\n }\n\n return this.successResult(buffer);\n } catch (error) {\n if (error instanceof FileNotFoundError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to download file: ${(error as Error).message}`);\n }\n }\n\n async moveItem(\n sourcePath: string,\n destinationPath: string,\n _options: MoveOptions = {}\n ): Promise<OperationResult<FileSystemItem>> {\n try {\n await this.ensureAuthenticated();\n\n const fileId = await this.getIdFromPath(sourcePath);\n if (!fileId) {\n throw new FileNotFoundError(sourcePath);\n }\n\n // Get current parents\n const file = await this.drive!.files.get({\n fileId,\n fields: 'parents',\n });\n\n const previousParents = file.data.parents?.join(',') || '';\n\n // Get new parent\n const destParentPath = this.getParentPath(destinationPath);\n const newName = this.getBaseName(destinationPath);\n const newParentId = await this.getIdFromPath(destParentPath, true);\n\n if (!newParentId) {\n throw new DirectoryNotFoundError(destParentPath);\n }\n\n // Move the file\n const response = await this.drive!.files.update({\n fileId,\n addParents: newParentId,\n removeParents: previousParents,\n requestBody: {\n name: newName,\n },\n fields: 'id, name, mimeType, size, createdTime, modifiedTime, webViewLink, thumbnailLink',\n });\n\n const item = this.driveFileToItem(response.data, destinationPath);\n return this.successResult(item);\n } catch (error) {\n if (error instanceof FileNotFoundError || error instanceof DirectoryNotFoundError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to move item: ${(error as Error).message}`);\n }\n }\n\n async deleteFile(virtualPath: string): Promise<OperationResult> {\n try {\n await this.ensureAuthenticated();\n\n const fileId = await this.getIdFromPath(virtualPath);\n if (!fileId) {\n throw new FileNotFoundError(virtualPath);\n }\n\n await this.drive!.files.delete({ fileId });\n return this.successResult();\n } catch (error) {\n if (error instanceof FileNotFoundError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to delete file: ${(error as Error).message}`);\n }\n }\n\n async renameFile(\n virtualPath: string,\n newName: string,\n _options: RenameOptions = {}\n ): Promise<OperationResult<FileItem>> {\n try {\n await this.ensureAuthenticated();\n\n const fileId = await this.getIdFromPath(virtualPath);\n if (!fileId) {\n throw new FileNotFoundError(virtualPath);\n }\n\n const response = await this.drive!.files.update({\n fileId,\n requestBody: {\n name: newName,\n },\n fields: 'id, name, mimeType, size, createdTime, modifiedTime, webViewLink, thumbnailLink',\n });\n\n const parentPath = this.getParentPath(virtualPath);\n const newPath = this.joinPath(parentPath, newName);\n const item = this.driveFileToItem(response.data, newPath) as FileItem;\n\n return this.successResult(item);\n } catch (error) {\n if (error instanceof FileNotFoundError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to rename file: ${(error as Error).message}`);\n }\n }\n\n async renameFolder(\n virtualPath: string,\n newName: string,\n _options: RenameOptions = {}\n ): Promise<OperationResult<FolderItem>> {\n try {\n await this.ensureAuthenticated();\n\n const folderId = await this.getIdFromPath(virtualPath);\n if (!folderId) {\n throw new DirectoryNotFoundError(virtualPath);\n }\n\n const response = await this.drive!.files.update({\n fileId: folderId,\n requestBody: {\n name: newName,\n },\n fields: 'id, name, mimeType, createdTime, modifiedTime, webViewLink',\n });\n\n const parentPath = this.getParentPath(virtualPath);\n const newPath = this.joinPath(parentPath, newName);\n const item = this.driveFileToItem(response.data, newPath) as FolderItem;\n\n return this.successResult(item);\n } catch (error) {\n if (error instanceof DirectoryNotFoundError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to rename folder: ${(error as Error).message}`);\n }\n }\n\n async listDirectory(\n virtualPath: string,\n options: ListOptions = {}\n ): Promise<OperationResult<FileSystemItem[]>> {\n try {\n await this.ensureAuthenticated();\n\n const folderId = await this.getIdFromPath(virtualPath);\n if (!folderId) {\n throw new DirectoryNotFoundError(virtualPath);\n }\n\n const items: FileSystemItem[] = [];\n let pageToken: string | undefined;\n\n do {\n const response = await this.drive!.files.list({\n q: `'${folderId}' in parents and trashed=false`,\n fields: 'nextPageToken, files(id, name, mimeType, size, createdTime, modifiedTime, webViewLink, thumbnailLink)',\n pageSize: 100,\n pageToken,\n orderBy: 'folder,name',\n });\n\n if (response.data.files) {\n for (const file of response.data.files) {\n // Skip hidden files unless explicitly included\n if (!options.includeHidden && file.name?.startsWith('.')) {\n continue;\n }\n\n const itemPath = this.joinPath(virtualPath, file.name!);\n const item = this.driveFileToItem(file, itemPath);\n\n // Apply filter if provided\n if (options.filter && !options.filter(item)) {\n continue;\n }\n\n items.push(item);\n\n // Handle recursive listing\n if (options.recursive && file.mimeType === FOLDER_MIME_TYPE) {\n const subResult = await this.listDirectory(itemPath, options);\n if (subResult.success && subResult.data) {\n items.push(...subResult.data);\n }\n }\n }\n }\n\n pageToken = response.data.nextPageToken || undefined;\n } while (pageToken);\n\n return this.successResult(items);\n } catch (error) {\n if (error instanceof DirectoryNotFoundError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to list directory: ${(error as Error).message}`);\n }\n }\n\n async getItem(virtualPath: string): Promise<OperationResult<FileSystemItem>> {\n try {\n await this.ensureAuthenticated();\n\n const fileId = await this.getIdFromPath(virtualPath);\n if (!fileId) {\n throw new FileNotFoundError(virtualPath);\n }\n\n const response = await this.drive!.files.get({\n fileId,\n fields: 'id, name, mimeType, size, createdTime, modifiedTime, webViewLink, thumbnailLink',\n });\n\n const item = this.driveFileToItem(response.data, virtualPath);\n return this.successResult(item);\n } catch (error) {\n if (error instanceof FileNotFoundError) {\n return this.errorResult(error.message);\n }\n return this.errorResult(`Failed to get item: ${(error as Error).message}`);\n }\n }\n\n async exists(virtualPath: string): Promise<boolean> {\n try {\n await this.ensureAuthenticated();\n const fileId = await this.getIdFromPath(virtualPath);\n return fileId !== null;\n } catch {\n return false;\n }\n }\n\n async getFolderTree(path = '/', depth = 3): Promise<OperationResult<TreeNode[]>> {\n try {\n await this.ensureAuthenticated();\n return super.getFolderTree(path, depth);\n } catch (error) {\n return this.errorResult(`Failed to get folder tree: ${(error as Error).message}`);\n }\n }\n}\n\n/**\n * Factory function to create a GoogleDriveModule instance\n */\nexport function createGoogleDriveModule(): GoogleDriveModule {\n return new GoogleDriveModule();\n}\n\nexport { GoogleDriveAuth, createGoogleDriveAuth } from './auth';\nexport type { TokenData, AuthCallbacks, GoogleAuthConfig } from './auth';\n\nexport default GoogleDriveModule;\n","/**\n * Google Drive OAuth Authentication Handler\n * Manages OAuth flow, token storage, and token refresh\n */\n\nimport { google } from 'googleapis';\nimport type { OAuth2Client, Credentials } from 'google-auth-library';\n\nexport interface GoogleAuthConfig {\n clientId: string;\n clientSecret: string;\n redirectUri: string;\n}\n\nexport interface TokenData {\n accessToken: string;\n refreshToken: string;\n expiryDate?: number;\n scope?: string;\n}\n\nexport interface AuthCallbacks {\n onTokensUpdated?: (tokens: TokenData) => Promise<void>;\n getStoredTokens?: () => Promise<TokenData | null>;\n}\n\n/**\n * OAuth scopes required for file management\n */\nexport const GOOGLE_DRIVE_SCOPES = [\n 'https://www.googleapis.com/auth/drive.file',\n 'https://www.googleapis.com/auth/drive.metadata.readonly',\n 'https://www.googleapis.com/auth/userinfo.email',\n 'https://www.googleapis.com/auth/userinfo.profile',\n];\n\n/**\n * Google Drive Authentication Manager\n */\nexport class GoogleDriveAuth {\n private oauth2Client: OAuth2Client;\n private callbacks: AuthCallbacks;\n private tokens: TokenData | null = null;\n\n constructor(config: GoogleAuthConfig, callbacks: AuthCallbacks = {}) {\n this.oauth2Client = new google.auth.OAuth2(\n config.clientId,\n config.clientSecret,\n config.redirectUri\n );\n\n this.callbacks = callbacks;\n\n // Set up automatic token refresh\n this.oauth2Client.on('tokens', async (tokens) => {\n if (this.tokens) {\n const updatedTokens: TokenData = {\n ...this.tokens,\n accessToken: tokens.access_token || this.tokens.accessToken,\n expiryDate: tokens.expiry_date ?? this.tokens.expiryDate,\n };\n\n if (tokens.refresh_token) {\n updatedTokens.refreshToken = tokens.refresh_token;\n }\n\n this.tokens = updatedTokens;\n\n if (this.callbacks.onTokensUpdated) {\n await this.callbacks.onTokensUpdated(updatedTokens);\n }\n }\n });\n }\n\n /**\n * Get the OAuth2 client instance\n */\n getClient(): OAuth2Client {\n return this.oauth2Client;\n }\n\n /**\n * Generate the authorization URL for OAuth consent\n */\n getAuthUrl(state?: string): string {\n return this.oauth2Client.generateAuthUrl({\n access_type: 'offline',\n scope: GOOGLE_DRIVE_SCOPES,\n prompt: 'consent',\n state,\n });\n }\n\n /**\n * Exchange authorization code for tokens\n */\n async exchangeCodeForTokens(code: string): Promise<TokenData> {\n const { tokens } = await this.oauth2Client.getToken(code);\n\n this.tokens = {\n accessToken: tokens.access_token!,\n refreshToken: tokens.refresh_token!,\n expiryDate: tokens.expiry_date || undefined,\n scope: tokens.scope || undefined,\n };\n\n this.oauth2Client.setCredentials(tokens);\n\n if (this.callbacks.onTokensUpdated) {\n await this.callbacks.onTokensUpdated(this.tokens);\n }\n\n return this.tokens;\n }\n\n /**\n * Set tokens directly (e.g., from stored tokens)\n */\n async setTokens(tokens: TokenData): Promise<void> {\n this.tokens = tokens;\n\n const credentials: Credentials = {\n access_token: tokens.accessToken,\n refresh_token: tokens.refreshToken,\n expiry_date: tokens.expiryDate,\n };\n\n this.oauth2Client.setCredentials(credentials);\n }\n\n /**\n * Load tokens from storage using callback\n */\n async loadStoredTokens(): Promise<boolean> {\n if (!this.callbacks.getStoredTokens) {\n return false;\n }\n\n const tokens = await this.callbacks.getStoredTokens();\n if (tokens) {\n await this.setTokens(tokens);\n return true;\n }\n\n return false;\n }\n\n /**\n * Check if authenticated\n */\n isAuthenticated(): boolean {\n return this.tokens !== null && !!this.tokens.accessToken;\n }\n\n /**\n * Get current tokens\n */\n getTokens(): TokenData | null {\n return this.tokens;\n }\n\n /**\n * Refresh the access token\n */\n async refreshAccessToken(): Promise<TokenData> {\n if (!this.tokens?.refreshToken) {\n throw new Error('No refresh token available');\n }\n\n const { credentials } = await this.oauth2Client.refreshAccessToken();\n\n this.tokens = {\n ...this.tokens,\n accessToken: credentials.access_token!,\n expiryDate: credentials.expiry_date || undefined,\n };\n\n if (this.callbacks.onTokensUpdated) {\n await this.callbacks.onTokensUpdated(this.tokens);\n }\n\n return this.tokens;\n }\n\n /**\n * Revoke access (disconnect)\n */\n async revokeAccess(): Promise<void> {\n if (this.tokens?.accessToken) {\n await this.oauth2Client.revokeToken(this.tokens.accessToken);\n }\n this.tokens = null;\n this.oauth2Client.setCredentials({});\n }\n\n /**\n * Check if token is expired or will expire soon\n */\n isTokenExpired(bufferSeconds = 300): boolean {\n if (!this.tokens?.expiryDate) {\n return false;\n }\n\n const now = Date.now();\n const expiry = this.tokens.expiryDate;\n\n return now >= expiry - bufferSeconds * 1000;\n }\n\n /**\n * Ensure valid access token (refresh if needed)\n */\n async ensureValidToken(): Promise<void> {\n if (this.isTokenExpired()) {\n await this.refreshAccessToken();\n }\n }\n}\n\n/**\n * Create a new GoogleDriveAuth instance\n */\nexport function createGoogleDriveAuth(\n config: GoogleAuthConfig,\n callbacks?: AuthCallbacks\n): GoogleDriveAuth {\n return new GoogleDriveAuth(config, callbacks);\n}\n","/**\n * Module Registry\n * Central registry for all storage modules\n */\n\nimport type { StorageModule, StorageProvider, HazoFilesConfig } from '../types';\nimport { createLocalModule } from './local';\nimport { createGoogleDriveModule } from './google-drive';\nimport { ConfigurationError } from '../common/errors';\n\n/**\n * Factory function type for creating modules\n */\ntype ModuleFactory = () => StorageModule;\n\n/**\n * Registry of available storage modules\n */\nconst moduleRegistry: Record<StorageProvider, ModuleFactory> = {\n local: createLocalModule,\n google_drive: createGoogleDriveModule,\n};\n\n/**\n * Get a list of registered providers\n */\nexport function getRegisteredProviders(): StorageProvider[] {\n return Object.keys(moduleRegistry) as StorageProvider[];\n}\n\n/**\n * Check if a provider is registered\n */\nexport function isProviderRegistered(provider: string): provider is StorageProvider {\n return provider in moduleRegistry;\n}\n\n/**\n * Create a storage module instance for the given provider\n */\nexport function createModule(provider: StorageProvider): StorageModule {\n const factory = moduleRegistry[provider];\n if (!factory) {\n throw new ConfigurationError(`Unknown storage provider: ${provider}`);\n }\n return factory();\n}\n\n/**\n * Create and initialize a storage module with configuration\n */\nexport async function createAndInitializeModule(config: HazoFilesConfig): Promise<StorageModule> {\n const module = createModule(config.provider);\n await module.initialize(config);\n return module;\n}\n\n/**\n * Register a custom module (for extensibility)\n */\nexport function registerModule(provider: StorageProvider, factory: ModuleFactory): void {\n moduleRegistry[provider] = factory;\n}\n\n// Export module classes and factories\nexport { LocalStorageModule, createLocalModule } from './local';\nexport { GoogleDriveModule, createGoogleDriveModule, GoogleDriveAuth, createGoogleDriveAuth } from './google-drive';\nexport type { TokenData, AuthCallbacks, GoogleAuthConfig } from './google-drive';\n","/**\n * File Manager Service\n * Main service that provides a unified API for file operations\n * Delegates to the appropriate storage module based on configuration\n */\n\nimport { loadConfig, loadConfigAsync } from '../config';\nimport { createAndInitializeModule, createModule } from '../modules';\nimport type {\n StorageModule,\n StorageProvider,\n HazoFilesConfig,\n FileItem,\n FolderItem,\n FileSystemItem,\n OperationResult,\n UploadOptions,\n DownloadOptions,\n MoveOptions,\n RenameOptions,\n ListOptions,\n TreeNode,\n} from '../types';\n\nexport interface FileManagerOptions {\n /** Path to configuration file */\n configPath?: string;\n /** Configuration object (takes precedence over configPath) */\n config?: HazoFilesConfig;\n /** Auto-initialize on creation */\n autoInit?: boolean;\n}\n\n/**\n * FileManager - Main service class for file operations\n */\nexport class FileManager {\n private module: StorageModule | null = null;\n private config: HazoFilesConfig | null = null;\n private initialized = false;\n private options: FileManagerOptions;\n\n constructor(options: FileManagerOptions = {}) {\n this.options = {\n autoInit: true,\n ...options,\n };\n }\n\n /**\n * Initialize the file manager with configuration\n */\n async initialize(config?: HazoFilesConfig): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n // Determine configuration source\n if (config) {\n this.config = config;\n } else if (this.options.config) {\n this.config = this.options.config;\n } else {\n this.config = await loadConfigAsync(this.options.configPath);\n }\n\n // Create and initialize the storage module\n this.module = await createAndInitializeModule(this.config);\n this.initialized = true;\n }\n\n /**\n * Initialize synchronously (uses sync config loading)\n */\n initializeSync(config?: HazoFilesConfig): void {\n if (this.initialized) {\n return;\n }\n\n if (config) {\n this.config = config;\n } else if (this.options.config) {\n this.config = this.options.config;\n } else {\n this.config = loadConfig(this.options.configPath);\n }\n\n this.module = createModule(this.config.provider);\n // Note: Module needs async initialization, caller should call initialize() after\n }\n\n /**\n * Check if manager is initialized\n */\n isInitialized(): boolean {\n return this.initialized;\n }\n\n /**\n * Get the current configuration\n */\n getConfig(): HazoFilesConfig | null {\n return this.config;\n }\n\n /**\n * Get the current provider\n */\n getProvider(): StorageProvider | null {\n return this.config?.provider ?? null;\n }\n\n /**\n * Get the underlying storage module\n */\n getModule(): StorageModule {\n this.ensureInitialized();\n return this.module!;\n }\n\n /**\n * Ensure manager is initialized\n */\n private ensureInitialized(): void {\n if (!this.initialized || !this.module) {\n throw new Error('FileManager not initialized. Call initialize() first.');\n }\n }\n\n // ============ Directory Operations ============\n\n /**\n * Create a directory at the specified path\n */\n async createDirectory(path: string): Promise<OperationResult<FolderItem>> {\n this.ensureInitialized();\n return this.module!.createDirectory(path);\n }\n\n /**\n * Remove a directory\n * @param path - Directory path\n * @param recursive - If true, remove directory and all contents\n */\n async removeDirectory(path: string, recursive = false): Promise<OperationResult> {\n this.ensureInitialized();\n return this.module!.removeDirectory(path, recursive);\n }\n\n // ============ File Operations ============\n\n /**\n * Upload/save a file\n * @param source - File path, Buffer, or ReadableStream\n * @param remotePath - Destination path in storage\n * @param options - Upload options\n */\n async uploadFile(\n source: string | Buffer | ReadableStream,\n remotePath: string,\n options?: UploadOptions\n ): Promise<OperationResult<FileItem>> {\n this.ensureInitialized();\n return this.module!.uploadFile(source, remotePath, options);\n }\n\n /**\n * Download a file\n * @param remotePath - Path in storage\n * @param localPath - Optional local destination path\n * @param options - Download options\n */\n async downloadFile(\n remotePath: string,\n localPath?: string,\n options?: DownloadOptions\n ): Promise<OperationResult<Buffer | string>> {\n this.ensureInitialized();\n return this.module!.downloadFile(remotePath, localPath, options);\n }\n\n /**\n * Move a file or folder\n * @param sourcePath - Current path\n * @param destinationPath - New path\n * @param options - Move options\n */\n async moveItem(\n sourcePath: string,\n destinationPath: string,\n options?: MoveOptions\n ): Promise<OperationResult<FileSystemItem>> {\n this.ensureInitialized();\n return this.module!.moveItem(sourcePath, destinationPath, options);\n }\n\n /**\n * Delete a file\n */\n async deleteFile(path: string): Promise<OperationResult> {\n this.ensureInitialized();\n return this.module!.deleteFile(path);\n }\n\n /**\n * Rename a file\n * @param path - Current file path\n * @param newName - New filename (not full path)\n * @param options - Rename options\n */\n async renameFile(\n path: string,\n newName: string,\n options?: RenameOptions\n ): Promise<OperationResult<FileItem>> {\n this.ensureInitialized();\n return this.module!.renameFile(path, newName, options);\n }\n\n /**\n * Rename a folder\n * @param path - Current folder path\n * @param newName - New folder name (not full path)\n * @param options - Rename options\n */\n async renameFolder(\n path: string,\n newName: string,\n options?: RenameOptions\n ): Promise<OperationResult<FolderItem>> {\n this.ensureInitialized();\n return this.module!.renameFolder(path, newName, options);\n }\n\n // ============ Query Operations ============\n\n /**\n * List contents of a directory\n * @param path - Directory path\n * @param options - List options\n */\n async listDirectory(\n path: string,\n options?: ListOptions\n ): Promise<OperationResult<FileSystemItem[]>> {\n this.ensureInitialized();\n return this.module!.listDirectory(path, options);\n }\n\n /**\n * Get information about a file or folder\n */\n async getItem(path: string): Promise<OperationResult<FileSystemItem>> {\n this.ensureInitialized();\n return this.module!.getItem(path);\n }\n\n /**\n * Check if a file or folder exists\n */\n async exists(path: string): Promise<boolean> {\n this.ensureInitialized();\n return this.module!.exists(path);\n }\n\n /**\n * Get folder tree structure\n * @param path - Starting path (default: root)\n * @param depth - Maximum depth to traverse\n */\n async getFolderTree(path = '/', depth = 3): Promise<OperationResult<TreeNode[]>> {\n this.ensureInitialized();\n return this.module!.getFolderTree(path, depth);\n }\n\n // ============ Convenience Methods ============\n\n /**\n * Create a file with string content\n */\n async writeFile(path: string, content: string, options?: UploadOptions): Promise<OperationResult<FileItem>> {\n const buffer = Buffer.from(content, 'utf-8');\n return this.uploadFile(buffer, path, options);\n }\n\n /**\n * Read a file as string\n */\n async readFile(path: string): Promise<OperationResult<string>> {\n const result = await this.downloadFile(path);\n if (!result.success) {\n return { success: false, error: result.error };\n }\n\n if (Buffer.isBuffer(result.data)) {\n return { success: true, data: result.data.toString('utf-8') };\n }\n\n // If it's a path, read the file\n const fs = await import('fs');\n const content = await fs.promises.readFile(result.data as string, 'utf-8');\n return { success: true, data: content };\n }\n\n /**\n * Copy a file to a new location\n */\n async copyFile(\n sourcePath: string,\n destinationPath: string,\n options?: UploadOptions\n ): Promise<OperationResult<FileItem>> {\n const downloadResult = await this.downloadFile(sourcePath);\n if (!downloadResult.success) {\n return { success: false, error: downloadResult.error };\n }\n\n const buffer = Buffer.isBuffer(downloadResult.data)\n ? downloadResult.data\n : await import('fs').then(fs => fs.promises.readFile(downloadResult.data as string));\n\n return this.uploadFile(buffer, destinationPath, options);\n }\n\n /**\n * Ensure a directory exists (creates if needed)\n */\n async ensureDirectory(path: string): Promise<OperationResult<FolderItem>> {\n const exists = await this.exists(path);\n if (exists) {\n const item = await this.getItem(path);\n if (item.success && item.data?.isDirectory) {\n return { success: true, data: item.data as FolderItem };\n }\n return { success: false, error: 'Path exists but is not a directory' };\n }\n return this.createDirectory(path);\n }\n}\n\n/**\n * Create a new FileManager instance\n */\nexport function createFileManager(options?: FileManagerOptions): FileManager {\n return new FileManager(options);\n}\n\n/**\n * Create and initialize a FileManager instance\n */\nexport async function createInitializedFileManager(\n options?: FileManagerOptions\n): Promise<FileManager> {\n const manager = new FileManager(options);\n await manager.initialize();\n return manager;\n}\n\nexport default FileManager;\n","/**\n * Naming utilities for hazo_files package\n * Functions for generating file/folder names from naming rule schemas\n */\n\nimport type {\n NamingRuleSchema,\n PatternSegment,\n GeneratedNameResult,\n NamingVariable,\n NameGenerationOptions,\n} from '../types/naming';\nimport { getExtension, getNameWithoutExtension, sanitizeFilename } from './path-utils';\n\n/** Default date formats supported by the system */\nexport const DEFAULT_DATE_FORMATS = [\n 'YYYY',\n 'YY',\n 'MM',\n 'M',\n 'DD',\n 'D',\n 'MMM',\n 'MMMM',\n 'YYYY-MM-DD',\n 'YYYY-MMM-DD',\n 'DD-MM-YYYY',\n 'MM-DD-YYYY',\n] as const;\n\n/** Month names for formatting */\nconst MONTH_NAMES_SHORT = [\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',\n];\n\nconst MONTH_NAMES_FULL = [\n 'January', 'February', 'March', 'April', 'May', 'June',\n 'July', 'August', 'September', 'October', 'November', 'December',\n];\n\n/** System date variables with descriptions */\nexport const SYSTEM_DATE_VARIABLES: NamingVariable[] = [\n { variable_name: 'YYYY', description: 'Full year (4 digits)', example_value: '2024', category: 'date' },\n { variable_name: 'YY', description: 'Year (2 digits)', example_value: '24', category: 'date' },\n { variable_name: 'MM', description: 'Month (2 digits, 01-12)', example_value: '01', category: 'date' },\n { variable_name: 'M', description: 'Month (1-12)', example_value: '1', category: 'date' },\n { variable_name: 'DD', description: 'Day (2 digits, 01-31)', example_value: '15', category: 'date' },\n { variable_name: 'D', description: 'Day (1-31)', example_value: '15', category: 'date' },\n { variable_name: 'MMM', description: 'Short month name', example_value: 'Jan', category: 'date' },\n { variable_name: 'MMMM', description: 'Full month name', example_value: 'January', category: 'date' },\n { variable_name: 'YYYY-MM-DD', description: 'ISO date format', example_value: '2024-01-15', category: 'date' },\n { variable_name: 'YYYY-MMM-DD', description: 'Date with month name', example_value: '2024-Jan-15', category: 'date' },\n { variable_name: 'DD-MM-YYYY', description: 'Day-Month-Year', example_value: '15-01-2024', category: 'date' },\n { variable_name: 'MM-DD-YYYY', description: 'Month-Day-Year', example_value: '01-15-2024', category: 'date' },\n];\n\n/** System file metadata variables */\nexport const SYSTEM_FILE_VARIABLES: NamingVariable[] = [\n { variable_name: 'original_name', description: 'Original filename without extension', example_value: 'document', category: 'file' },\n { variable_name: 'extension', description: 'Original file extension with dot', example_value: '.pdf', category: 'file' },\n { variable_name: 'ext', description: 'Extension without dot', example_value: 'pdf', category: 'file' },\n];\n\n/** System counter variables */\nexport const SYSTEM_COUNTER_VARIABLES: NamingVariable[] = [\n { variable_name: 'counter', description: 'Auto-incrementing number (3 digits)', example_value: '001', category: 'counter' },\n];\n\n/** All system variables combined */\nexport const ALL_SYSTEM_VARIABLES: NamingVariable[] = [\n ...SYSTEM_DATE_VARIABLES,\n ...SYSTEM_FILE_VARIABLES,\n ...SYSTEM_COUNTER_VARIABLES,\n];\n\n/**\n * Format a date according to the format token\n */\nexport function formatDateToken(date: Date, format: string): string {\n const year = date.getFullYear();\n const month = date.getMonth();\n const day = date.getDate();\n\n switch (format) {\n case 'YYYY':\n return String(year);\n case 'YY':\n return String(year).slice(-2);\n case 'MM':\n return String(month + 1).padStart(2, '0');\n case 'M':\n return String(month + 1);\n case 'DD':\n return String(day).padStart(2, '0');\n case 'D':\n return String(day);\n case 'MMM':\n return MONTH_NAMES_SHORT[month];\n case 'MMMM':\n return MONTH_NAMES_FULL[month];\n case 'YYYY-MM-DD':\n return `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;\n case 'YYYY-MMM-DD':\n return `${year}-${MONTH_NAMES_SHORT[month]}-${String(day).padStart(2, '0')}`;\n case 'DD-MM-YYYY':\n return `${String(day).padStart(2, '0')}-${String(month + 1).padStart(2, '0')}-${year}`;\n case 'MM-DD-YYYY':\n return `${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}-${year}`;\n default:\n return format;\n }\n}\n\n/**\n * Check if a variable name is a date format\n */\nexport function isDateVariable(\n variableName: string,\n dateFormats: readonly string[] = DEFAULT_DATE_FORMATS\n): boolean {\n return dateFormats.includes(variableName);\n}\n\n/**\n * Check if a variable name is a file metadata variable\n */\nexport function isFileMetadataVariable(variableName: string): boolean {\n return ['original_name', 'extension', 'ext'].includes(variableName);\n}\n\n/**\n * Check if a variable name is the counter variable\n */\nexport function isCounterVariable(variableName: string): boolean {\n return variableName === 'counter' || variableName.startsWith('counter:');\n}\n\n/**\n * Format counter value with padding\n */\nexport function formatCounter(value: number, digits: number = 3): string {\n return String(value).padStart(digits, '0');\n}\n\n/**\n * Get file metadata values from a filename\n */\nexport function getFileMetadataValues(filename?: string): Record<string, string> {\n if (!filename) {\n return {\n original_name: '',\n extension: '',\n ext: '',\n };\n }\n\n const extension = getExtension(filename);\n const originalName = getNameWithoutExtension(filename);\n\n return {\n original_name: originalName,\n extension: extension,\n ext: extension.startsWith('.') ? extension.slice(1) : extension,\n };\n}\n\n/**\n * Generate a name from a pattern and variable values\n * Internal function used by both file and folder name generators\n */\nfunction generateNameFromPattern(\n pattern: PatternSegment[],\n variables: Record<string, string>,\n options: NameGenerationOptions = {},\n originalFileName?: string\n): GeneratedNameResult {\n if (pattern.length === 0) {\n return { success: false, error: 'Pattern is empty' };\n }\n\n const {\n dateFormats = DEFAULT_DATE_FORMATS,\n date = new Date(),\n counterValue = 1,\n counterDigits = 3,\n } = options;\n\n // Get file metadata if original filename is provided\n const fileMetadata = getFileMetadataValues(originalFileName);\n\n const parts: string[] = [];\n\n for (const segment of pattern) {\n if (segment.type === 'literal') {\n parts.push(segment.value);\n } else if (segment.type === 'variable') {\n const varName = segment.value;\n\n // Check if it's a date variable\n if (isDateVariable(varName, dateFormats)) {\n parts.push(formatDateToken(date, varName));\n }\n // Check if it's a file metadata variable\n else if (isFileMetadataVariable(varName)) {\n parts.push(fileMetadata[varName] || '');\n }\n // Check if it's a counter variable\n else if (isCounterVariable(varName)) {\n // Support counter:N format for custom digit count\n if (varName.startsWith('counter:')) {\n const customDigits = parseInt(varName.split(':')[1], 10);\n parts.push(formatCounter(counterValue, isNaN(customDigits) ? counterDigits : customDigits));\n } else {\n parts.push(formatCounter(counterValue, counterDigits));\n }\n }\n // Check user-provided variables\n else if (varName in variables) {\n parts.push(variables[varName]);\n }\n // Missing variable\n else {\n return {\n success: false,\n error: `Missing value for variable: ${varName}`,\n };\n }\n }\n }\n\n const name = parts.join('');\n\n if (!name.trim()) {\n return { success: false, error: 'Generated name is empty' };\n }\n\n return { success: true, name };\n}\n\n/**\n * Generate a folder name using the schema and variable values\n * Supports nested paths with / separators in the pattern\n */\nexport function hazo_files_generate_folder_name(\n schema: NamingRuleSchema,\n variables: Record<string, string>,\n options?: NameGenerationOptions\n): GeneratedNameResult {\n const result = generateNameFromPattern(\n schema.folderPattern,\n variables,\n options\n );\n\n if (!result.success || !result.name) {\n return result;\n }\n\n // Sanitize each path segment for nested paths\n const segments = result.name.split('/');\n const sanitizedSegments = segments\n .map(seg => seg.trim())\n .filter(seg => seg.length > 0)\n .map(seg => sanitizeFilename(seg));\n\n if (sanitizedSegments.length === 0) {\n return { success: false, error: 'Generated folder name is empty' };\n }\n\n return {\n success: true,\n name: sanitizedSegments.join('/'),\n };\n}\n\n/**\n * Generate a file name using the schema and variable values\n * Optionally preserves the original file extension\n */\nexport function hazo_files_generate_file_name(\n schema: NamingRuleSchema,\n variables: Record<string, string>,\n originalFileName?: string,\n options?: NameGenerationOptions\n): GeneratedNameResult {\n const { preserveExtension = true, ...restOptions } = options || {};\n\n const result = generateNameFromPattern(\n schema.filePattern,\n variables,\n restOptions,\n originalFileName\n );\n\n if (!result.success || !result.name) {\n return result;\n }\n\n let finalName = result.name;\n\n // Handle extension preservation\n if (originalFileName && preserveExtension) {\n const originalExtension = getExtension(originalFileName);\n if (originalExtension) {\n // Remove any extension from generated name\n const nameWithoutExt = getNameWithoutExtension(finalName);\n finalName = nameWithoutExt + originalExtension;\n }\n }\n\n return {\n success: true,\n name: sanitizeFilename(finalName),\n };\n}\n\n/**\n * Validate a naming rule schema\n */\nexport function validateNamingRuleSchema(schema: unknown): schema is NamingRuleSchema {\n if (!schema || typeof schema !== 'object') return false;\n\n const s = schema as Record<string, unknown>;\n\n if (typeof s.version !== 'number') return false;\n if (!Array.isArray(s.filePattern) || !Array.isArray(s.folderPattern)) return false;\n\n const isValidSegment = (seg: unknown): seg is PatternSegment => {\n if (!seg || typeof seg !== 'object') return false;\n const segment = seg as Record<string, unknown>;\n return (\n typeof segment.id === 'string' &&\n (segment.type === 'variable' || segment.type === 'literal') &&\n typeof segment.value === 'string'\n );\n };\n\n return (\n s.filePattern.every(isValidSegment) &&\n s.folderPattern.every(isValidSegment)\n );\n}\n\n/**\n * Create an empty naming rule schema\n */\nexport function createEmptyNamingRuleSchema(): NamingRuleSchema {\n return {\n version: 1,\n filePattern: [],\n folderPattern: [],\n metadata: {\n createdAt: new Date().toISOString(),\n },\n };\n}\n\n/**\n * Generate a unique ID for pattern segments\n */\nexport function generateSegmentId(): string {\n return `seg_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n}\n\n/**\n * Create a variable segment\n */\nexport function createVariableSegment(variableName: string): PatternSegment {\n return {\n id: generateSegmentId(),\n type: 'variable',\n value: variableName,\n };\n}\n\n/**\n * Create a literal segment\n */\nexport function createLiteralSegment(text: string): PatternSegment {\n return {\n id: generateSegmentId(),\n type: 'literal',\n value: text,\n };\n}\n\n/**\n * Convert pattern to human-readable string representation\n */\nexport function patternToString(pattern: PatternSegment[]): string {\n return pattern\n .map((seg) => (seg.type === 'variable' ? `{${seg.value}}` : seg.value))\n .join('');\n}\n\n/**\n * Parse a pattern string to segments\n * Handles {variable} syntax for variables, everything else is literal\n */\nexport function parsePatternString(patternStr: string): PatternSegment[] {\n const segments: PatternSegment[] = [];\n const regex = /\\{([^}]+)\\}|([^{]+)/g;\n let match;\n\n while ((match = regex.exec(patternStr)) !== null) {\n if (match[1]) {\n // Variable (inside braces)\n segments.push(createVariableSegment(match[1]));\n } else if (match[2]) {\n // Literal text\n segments.push(createLiteralSegment(match[2]));\n }\n }\n\n return segments;\n}\n\n/**\n * Clone a pattern with new segment IDs\n */\nexport function clonePattern(pattern: PatternSegment[]): PatternSegment[] {\n return pattern.map((seg) => ({\n ...seg,\n id: generateSegmentId(),\n }));\n}\n\n/**\n * Get preview values for all system variables\n * Uses the current date and provided options\n */\nexport function getSystemVariablePreviewValues(\n date: Date = new Date(),\n options: { counterValue?: number; counterDigits?: number; originalFileName?: string } = {}\n): Record<string, string> {\n const { counterValue = 1, counterDigits = 3, originalFileName } = options;\n const fileMetadata = getFileMetadataValues(originalFileName);\n\n const values: Record<string, string> = {};\n\n // Date variables\n for (const format of DEFAULT_DATE_FORMATS) {\n values[format] = formatDateToken(date, format);\n }\n\n // File metadata variables\n values.original_name = fileMetadata.original_name || 'document';\n values.extension = fileMetadata.extension || '.pdf';\n values.ext = fileMetadata.ext || 'pdf';\n\n // Counter\n values.counter = formatCounter(counterValue, counterDigits);\n\n return values;\n}\n\n/**\n * Generate a preview name from a pattern using example values\n */\nexport function generatePreviewName(\n pattern: PatternSegment[],\n userVariables: NamingVariable[],\n options: {\n date?: Date;\n counterValue?: number;\n counterDigits?: number;\n originalFileName?: string;\n } = {}\n): string {\n if (pattern.length === 0) {\n return '(empty pattern)';\n }\n\n const systemValues = getSystemVariablePreviewValues(\n options.date,\n options\n );\n\n // Build user variable example values\n const userValues: Record<string, string> = {};\n for (const variable of userVariables) {\n userValues[variable.variable_name] = variable.example_value;\n }\n\n // Combine all values\n const allValues = { ...userValues, ...systemValues };\n\n const parts: string[] = [];\n\n for (const segment of pattern) {\n if (segment.type === 'literal') {\n parts.push(segment.value);\n } else if (segment.type === 'variable') {\n const value = allValues[segment.value];\n if (value !== undefined) {\n parts.push(value);\n } else {\n parts.push(`{${segment.value}}`);\n }\n }\n }\n\n return parts.join('') || '(empty)';\n}\n"],"mappings":"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","names":["fs","path","path","path","relative","stats","import_googleapis","import_stream","isFolder","path","fs","module","path","fs"]}