@muhgholy/next-drive 4.6.0 → 4.8.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/server/database/mongoose/schema/drive.ts","../src/server/utils/migration.ts","../src/server/config.ts","../src/server/database/mongoose/schema/storage/account.ts","../src/server/utils.ts","../src/server/zod/schemas.ts","../src/server/security/cryptoUtils.ts","../src/server/providers/local.ts","../src/server/providers/google.ts","../src/server/controllers/drive.ts","../src/server/index.ts"],"names":["mongoose","Schema","crypto","fs","path","sharp","getNextOrderValue","owner","folderIds","os","provider","google","fields","files"],"mappings":"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","file":"chunk-AYHO6FSR.js","sourcesContent":["// ** Mongoose Drive Schema\nimport type {\n TDatabaseDrive,\n TDatabaseDriveInformation,\n TDatabaseDriveMetadata,\n TDatabaseDriveProvider,\n TDatabaseDriveStatus,\n} from '@/types/lib/database/drive';\nimport mongoose, { Schema, type Document, type Model, type Types } from 'mongoose';\n\nexport interface IDatabaseDriveDocument extends Document {\n owner: Record<string, unknown> | null;\n storageAccountId: Types.ObjectId | null;\n name: string;\n parentId: Types.ObjectId | null;\n order: number;\n provider: TDatabaseDriveProvider;\n metadata: TDatabaseDriveMetadata;\n information: TDatabaseDriveInformation;\n status: TDatabaseDriveStatus;\n trashedAt: Date | null;\n createdAt: Date;\n\n toClient: () => Promise<TDatabaseDrive>;\n}\n\n// ** Schema definition\nconst informationSchema = new Schema({\n type: { type: String, enum: ['FILE', 'FOLDER'], required: true },\n sizeInBytes: { type: Number, default: 0 },\n mime: { type: String },\n path: { type: String },\n width: { type: Number },\n height: { type: Number },\n duration: { type: Number },\n hash: { type: String },\n}, { _id: false });\n\n// Provider Sub-schema to handle 'type' field correctly without ambiguity\nconst providerSchema = new Schema({\n type: { type: String, enum: ['LOCAL', 'GOOGLE'], required: true, default: 'LOCAL' },\n google: { type: Schema.Types.Mixed }\n}, { _id: false });\n\nconst DriveSchema: Schema = new Schema<IDatabaseDriveDocument>(\n {\n owner: { type: Schema.Types.Mixed, default: null },\n storageAccountId: { type: Schema.Types.ObjectId, ref: 'StorageAccount', default: null },\n name: { type: String, required: true },\n parentId: { type: Schema.Types.ObjectId, ref: 'Drive', default: null },\n order: { type: Number, default: 0 },\n provider: { type: providerSchema, default: () => ({ type: 'LOCAL' }) },\n metadata: { type: Schema.Types.Mixed, default: {} },\n information: { type: informationSchema, required: true },\n status: { type: String, enum: ['READY', 'PROCESSING', 'UPLOADING', 'FAILED'], default: 'PROCESSING' },\n trashedAt: { type: Date, default: null },\n createdAt: { type: Date, default: Date.now },\n },\n { minimize: false },\n);\n\n// ** Indexes\nDriveSchema.index({ owner: 1, 'information.type': 1 });\nDriveSchema.index({ owner: 1, 'provider.type': 1, 'provider.google.id': 1 }); // Provider lookup updated\nDriveSchema.index({ owner: 1, storageAccountId: 1 });\nDriveSchema.index({ owner: 1, trashedAt: 1 });\nDriveSchema.index({ owner: 1, 'information.hash': 1 });\nDriveSchema.index({ owner: 1, name: 'text' });\nDriveSchema.index({ owner: 1, 'provider.type': 1 });\n\n// ** Method: toClient\nDriveSchema.method<IDatabaseDriveDocument>('toClient', async function (): Promise<TDatabaseDrive> {\n const data = this.toJSON<IDatabaseDriveDocument>();\n\n return {\n id: String(data._id),\n name: data.name,\n parentId: data.parentId ? String(data.parentId) : null,\n order: data.order,\n provider: data.provider,\n metadata: data.metadata,\n information: data.information,\n status: data.status,\n trashedAt: data.trashedAt,\n createdAt: data.createdAt,\n };\n});\n\nconst Drive: Model<IDatabaseDriveDocument> = mongoose.models.Drive || mongoose.model<IDatabaseDriveDocument>('Drive', DriveSchema);\n\nexport default Drive;\n","// ** Storage Migration Utility\n// ** Handles one-time migrations for storage structure changes\nimport fs from 'fs';\nimport path from 'path';\nimport mongoose from 'mongoose';\nimport Drive from '@/server/database/mongoose/schema/drive';\nimport type { TMigration } from '@/types/server/migration';\n\n// ** Migration version tracking\nconst MIGRATION_FILE = '.migration-version';\nconst CURRENT_VERSION = 1;\n\n// ** Check if system is ready for migration\nconst isReadyForMigration = (): boolean => {\n // ** Database must be connected\n if (mongoose.connection.readyState !== 1) {\n console.warn('[next-drive] Migration skipped: Database not connected');\n return false;\n }\n return true;\n};\n\n// ** Check if this is a new installation (no existing files to migrate)\nconst isNewInstallation = (storagePath: string): boolean => {\n // ** If storage path doesn't exist, it's a new installation\n if (!fs.existsSync(storagePath)) return true;\n\n // ** Check if there are any old-style directories to migrate\n const hasOldDriveDir = fs.existsSync(path.join(storagePath, 'drive'));\n const hasOldCacheDir = fs.existsSync(path.join(storagePath, 'cache', 'thumbnails'));\n const hasOldLibraryDir = fs.existsSync(path.join(storagePath, 'library', 'google'));\n\n // ** Check for files directly in storage root (old format: {id}/data.ext)\n const hasRootLevelFiles = fs.existsSync(storagePath) &&\n fs.readdirSync(storagePath).some(entry => {\n const entryPath = path.join(storagePath, entry);\n // ** Look for directories that look like MongoDB ObjectIds (24 hex chars)\n return fs.statSync(entryPath).isDirectory() &&\n /^[a-f0-9]{24}$/i.test(entry) &&\n entry !== 'file'; // Exclude new 'file' directory\n });\n\n // ** If none of these exist, it's effectively a new installation\n return !hasOldDriveDir && !hasOldCacheDir && !hasOldLibraryDir && !hasRootLevelFiles;\n};\n\n// ** Migration definitions (add new migrations here)\nconst migrations: TMigration[] = [\n {\n version: 1,\n name: 'restructure-file-paths',\n migrate: async (storagePath: string) => {\n // ** Migrate from old structure to new structure\n // ** Old: {storagePath}/{fileId}/data.{ext} or {storagePath}/drive/{fileId}/data.bin\n // ** New: {storagePath}/file/{fileId}/data.bin\n\n const fileDir = path.join(storagePath, 'file');\n if (!fs.existsSync(fileDir)) {\n fs.mkdirSync(fileDir, { recursive: true });\n }\n\n // ** Find all LOCAL files in database\n const files = await Drive.find({\n 'provider.type': 'LOCAL',\n 'information.type': 'FILE',\n 'information.path': { $exists: true, $ne: '' },\n }).lean();\n\n for (const file of files) {\n const info = file.information as { type: string; path?: string };\n const oldPath = info.path;\n if (!oldPath) continue;\n\n // ** Skip if already migrated (starts with 'file/')\n if (oldPath.startsWith('file/')) continue;\n\n const fileId = String(file._id);\n const newRelativePath = path.join('file', fileId, 'data.bin');\n const oldFullPath = path.join(storagePath, oldPath);\n const newFullPath = path.join(storagePath, newRelativePath);\n\n // ** Check if old file exists\n if (fs.existsSync(oldFullPath)) {\n const newDir = path.dirname(newFullPath);\n if (!fs.existsSync(newDir)) {\n fs.mkdirSync(newDir, { recursive: true });\n }\n\n // ** Move file to new location\n try {\n fs.renameSync(oldFullPath, newFullPath);\n } catch (err: unknown) {\n if (err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'EXDEV') {\n fs.copyFileSync(oldFullPath, newFullPath);\n fs.unlinkSync(oldFullPath);\n } else {\n console.error(`[next-drive] Migration failed for file ${fileId}:`, err);\n continue;\n }\n }\n\n // ** Cleanup old directory if empty\n const oldDir = path.dirname(oldFullPath);\n try {\n const remaining = fs.readdirSync(oldDir);\n if (remaining.length === 0) {\n fs.rmdirSync(oldDir);\n }\n } catch { /* ignore cleanup errors */ }\n }\n\n // ** Update database path\n await Drive.updateOne(\n { _id: file._id },\n { $set: { 'information.path': newRelativePath } }\n );\n }\n\n // ** Migrate old cache directory\n const oldCacheDir = path.join(storagePath, 'cache', 'thumbnails');\n if (fs.existsSync(oldCacheDir)) {\n const thumbnails = fs.readdirSync(oldCacheDir);\n for (const thumb of thumbnails) {\n const fileId = thumb.replace('.webp', '');\n const oldThumbPath = path.join(oldCacheDir, thumb);\n const newThumbDir = path.join(storagePath, 'file', fileId, 'cache');\n const newThumbPath = path.join(newThumbDir, 'thumbnail.webp');\n\n if (fs.existsSync(oldThumbPath) && !fs.existsSync(newThumbPath)) {\n if (!fs.existsSync(newThumbDir)) {\n fs.mkdirSync(newThumbDir, { recursive: true });\n }\n try {\n fs.renameSync(oldThumbPath, newThumbPath);\n } catch {\n // Ignore errors, thumbnail can be regenerated\n }\n }\n }\n\n // ** Cleanup old cache directory\n try {\n fs.rmSync(oldCacheDir, { recursive: true, force: true });\n const cacheParent = path.join(storagePath, 'cache');\n const remaining = fs.readdirSync(cacheParent);\n if (remaining.length === 0) {\n fs.rmdirSync(cacheParent);\n }\n } catch { /* ignore cleanup errors */ }\n }\n\n // ** Migrate old library/google directory\n const oldLibraryDir = path.join(storagePath, 'library', 'google');\n if (fs.existsSync(oldLibraryDir)) {\n const cachedFiles = fs.readdirSync(oldLibraryDir);\n for (const cached of cachedFiles) {\n // Extract fileId from filename (format: {fileId}.{ext})\n const fileId = cached.split('.')[0];\n if (!fileId) continue;\n\n const oldCachedPath = path.join(oldLibraryDir, cached);\n const newCachedDir = path.join(storagePath, 'file', fileId);\n const newCachedPath = path.join(newCachedDir, 'data.bin');\n\n if (fs.existsSync(oldCachedPath) && !fs.existsSync(newCachedPath)) {\n if (!fs.existsSync(newCachedDir)) {\n fs.mkdirSync(newCachedDir, { recursive: true });\n }\n try {\n fs.renameSync(oldCachedPath, newCachedPath);\n } catch {\n // Ignore errors, can be re-downloaded\n }\n }\n }\n\n // ** Cleanup old library directory\n try {\n fs.rmSync(path.join(storagePath, 'library'), { recursive: true, force: true });\n } catch { /* ignore cleanup errors */ }\n }\n\n // ** Cleanup old 'drive' directory if exists\n const oldDriveDir = path.join(storagePath, 'drive');\n if (fs.existsSync(oldDriveDir)) {\n try {\n fs.rmSync(oldDriveDir, { recursive: true, force: true });\n } catch { /* ignore cleanup errors */ }\n }\n\n console.log('[next-drive] Migration v1 complete: restructure-file-paths');\n },\n },\n];\n\n// ** Run pending migrations\nexport const runMigrations = async (storagePath: string): Promise<void> => {\n // ** Check readiness before attempting migration\n if (!isReadyForMigration()) {\n return;\n }\n\n // ** Ensure storage path exists\n if (!fs.existsSync(storagePath)) {\n fs.mkdirSync(storagePath, { recursive: true });\n }\n\n const versionFile = path.join(storagePath, MIGRATION_FILE);\n let currentVersion = 0;\n\n // ** Read current version\n if (fs.existsSync(versionFile)) {\n try {\n currentVersion = parseInt(fs.readFileSync(versionFile, 'utf-8').trim(), 10) || 0;\n } catch {\n currentVersion = 0;\n }\n }\n\n // ** Skip if already at current version\n if (currentVersion >= CURRENT_VERSION) return;\n\n // ** For new installations, just write the version file and skip migration\n if (isNewInstallation(storagePath)) {\n console.log('[next-drive] New installation detected, skipping migration');\n fs.writeFileSync(versionFile, String(CURRENT_VERSION));\n return;\n }\n\n // ** Run pending migrations\n const pendingMigrations = migrations.filter(m => m.version > currentVersion);\n for (const migration of pendingMigrations.sort((a, b) => a.version - b.version)) {\n console.log(`[next-drive] Running migration v${migration.version}: ${migration.name}`);\n try {\n await migration.migrate(storagePath);\n // ** Update version after each successful migration\n fs.writeFileSync(versionFile, String(migration.version));\n } catch (error) {\n console.error(`[next-drive] Migration v${migration.version} failed:`, error);\n throw error;\n }\n }\n}\n","// ** Server Config Wrapper\nimport type { NextApiRequest } from 'next';\nimport mongoose from 'mongoose';\nimport type { TDriveConfiguration, TDriveConfigInformation } from '@/types/server';\nimport { runMigrations } from '@/server/utils/migration';\n\nlet globalConfig: TDriveConfiguration | null = null;\nlet migrationPromise: Promise<void> | null = null;\nlet configInitialized = false;\n\n// ** Initialize configuration\nexport const driveConfiguration = async (config: TDriveConfiguration): Promise<TDriveConfiguration> => {\n // ** Check database connection\n if (mongoose.connection.readyState !== 1) {\n throw new Error('Database not connected. Please connect to Mongoose before initializing next-drive.');\n }\n\n // ** If already initialized, just wait for migration and return\n if (configInitialized && globalConfig) {\n if (migrationPromise) await migrationPromise;\n return globalConfig;\n }\n\n const mode = config.mode || 'NORMAL';\n\n // ** Set globalConfig FIRST (before migrations) so it's available during migration\n if (mode === 'ROOT') {\n globalConfig = {\n ...config,\n mode: 'ROOT',\n security: config.security || {\n maxUploadSizeInBytes: 1024 * 1024 * 1024 * 10, // 10GB default for ROOT\n allowedMimeTypes: ['*/*'],\n },\n };\n } else {\n if (!config.information) {\n throw new Error('information callback is required in NORMAL mode');\n }\n\n globalConfig = {\n ...config,\n mode: 'NORMAL',\n security: {\n maxUploadSizeInBytes: config.security?.maxUploadSizeInBytes ?? 10 * 1024 * 1024,\n allowedMimeTypes: config.security?.allowedMimeTypes ?? ['*/*'],\n signedUrls: config.security?.signedUrls,\n trash: config.security?.trash\n },\n information: config.information,\n };\n }\n\n // ** Mark as initialized immediately to prevent race conditions\n configInitialized = true;\n\n // ** Run migrations once (all concurrent callers share the same promise)\n if (!migrationPromise) {\n migrationPromise = runMigrations(config.storage.path);\n }\n await migrationPromise;\n\n return globalConfig;\n};\n\n// ** Get current configuration\nexport const getDriveConfig = (): TDriveConfiguration => {\n if (!globalConfig) throw new Error('Drive configuration not initialized');\n return globalConfig;\n};\n\n// ** Get drive information (quota, owner) - Returns null key in ROOT mode\nexport const getDriveInformation = async (req: NextApiRequest): Promise<TDriveConfigInformation> => {\n const config = getDriveConfig();\n\n // In ROOT mode, return null key if information callback is not provided\n if (config.mode === 'ROOT') {\n if (!config.information) {\n return {\n key: null,\n storage: { quotaInBytes: Number.MAX_SAFE_INTEGER } // Unlimited quota in ROOT mode\n };\n }\n return config.information(req);\n }\n\n // NORMAL mode - information is guaranteed to exist\n return config.information(req);\n};\n","// ** Mongoose Storage Account Schema\nimport type { TDatabaseStorageAccount, TDatabaseStorageAccountMetadata } from '@/types/lib/database/storage/account';\nimport mongoose, { Schema, type Document, type Model, type Types } from 'mongoose';\n\nexport interface IDatabaseStorageAccountDocument extends Document {\n owner: Record<string, unknown> | null;\n name: string;\n metadata: TDatabaseStorageAccountMetadata;\n createdAt: Date;\n\n toClient: () => Promise<TDatabaseStorageAccount>;\n}\n\n// ** Schema definition\nconst StorageAccountSchema: Schema = new Schema<IDatabaseStorageAccountDocument>(\n {\n owner: { type: Schema.Types.Mixed, default: null },\n name: { type: String, required: true },\n metadata: {\n provider: { type: String, enum: ['GOOGLE'], required: true },\n google: {\n email: { type: String, required: true },\n credentials: { type: Schema.Types.Mixed, required: true },\n },\n },\n createdAt: { type: Date, default: Date.now },\n },\n { minimize: false }\n);\n\n// ** Indexes\nStorageAccountSchema.index({ owner: 1, 'metadata.provider': 1 });\nStorageAccountSchema.index({ owner: 1, 'metadata.google.email': 1 });\n\n// ** Method: toClient\nStorageAccountSchema.method<IDatabaseStorageAccountDocument>('toClient', async function (): Promise<TDatabaseStorageAccount> {\n const data = this.toJSON<IDatabaseStorageAccountDocument>();\n\n return {\n id: String(data._id),\n owner: data.owner,\n name: data.name,\n metadata: data.metadata,\n createdAt: data.createdAt,\n };\n});\n\nconst StorageAccount: Model<IDatabaseStorageAccountDocument> = mongoose.models.StorageAccount || mongoose.model<IDatabaseStorageAccountDocument>('StorageAccount', StorageAccountSchema);\n\nexport default StorageAccount;\n","import fs from 'fs';\nimport crypto from 'crypto';\nimport sharp from 'sharp';\n\nexport const isImageMimeType = (mime: string): boolean => ['image/jpeg', 'image/png', 'image/webp', 'image/gif', 'image/avif'].includes(mime);\n\nexport const validateMimeType = (mime: string, allowedTypes: string[]): boolean => {\n if (allowedTypes.includes('*/*')) return true;\n return allowedTypes.some(pattern => {\n if (pattern === mime) return true;\n if (pattern.endsWith('/*')) {\n const prefix = pattern.slice(0, -2);\n return mime.startsWith(`${prefix}/`);\n }\n return false;\n });\n};\n\nexport const computeFileHash = (filePath: string): Promise<string> =>\n new Promise((resolve, reject) => {\n const hash = crypto.createHash('sha256');\n const stream = fs.createReadStream(filePath);\n stream.on('data', data => hash.update(data));\n stream.on('end', () => resolve(hash.digest('hex')));\n stream.on('error', reject);\n });\n\nexport const extractImageMetadata = async (filePath: string) => {\n try {\n const { width = 0, height = 0, exif } = await sharp(filePath).metadata();\n return { width, height, ...(exif && { exif: { raw: exif.toString('base64') } }) };\n } catch {\n return null;\n }\n};\n\nexport const formatFileSize = (bytes: number): string => {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;\n};\n\nexport const ownerMatches = (a: Record<string, unknown> | null, b: Record<string, unknown> | null): boolean => {\n if (a === null && b === null) return true;\n if (a === null || b === null) return false;\n return JSON.stringify(a) === JSON.stringify(b);\n};\n\n/**\n * Image optimization settings returned by getImageSettings\n */\nexport interface ImageSettings {\n quality: number; // 1-100, lower = more compression\n effort: number; // 0-9 for webp/avif, higher = slower but smaller\n pngCompression: number; // 0-9 for PNG, higher = more compression\n width?: number; // Max width (resize)\n height?: number; // Max height (resize)\n}\n\n/**\n * Display presets - defines aspect ratio, base dimensions, and quality factor\n */\nconst DISPLAY_PRESETS: Record<string, { ratio: [number, number]; baseWidth: number; qualityFactor: number }> = {\n 'article-header': { ratio: [16, 9], baseWidth: 1200, qualityFactor: 0.9 },\n 'article-image': { ratio: [16, 9], baseWidth: 800, qualityFactor: 0.85 },\n 'thumbnail': { ratio: [1, 1], baseWidth: 150, qualityFactor: 0.7 },\n 'avatar': { ratio: [1, 1], baseWidth: 128, qualityFactor: 0.8 },\n 'logo': { ratio: [2, 1], baseWidth: 200, qualityFactor: 0.95 },\n 'card': { ratio: [4, 3], baseWidth: 400, qualityFactor: 0.8 },\n 'gallery': { ratio: [1, 1], baseWidth: 600, qualityFactor: 0.85 },\n 'og': { ratio: [1200, 630], baseWidth: 1200, qualityFactor: 0.9 },\n 'icon': { ratio: [1, 1], baseWidth: 48, qualityFactor: 0.75 },\n 'cover': { ratio: [16, 9], baseWidth: 1920, qualityFactor: 0.9 },\n 'story': { ratio: [9, 16], baseWidth: 1080, qualityFactor: 0.85 },\n 'video': { ratio: [16, 9], baseWidth: 1280, qualityFactor: 0.85 },\n 'banner': { ratio: [3, 1], baseWidth: 1200, qualityFactor: 0.9 },\n 'portrait': { ratio: [3, 4], baseWidth: 600, qualityFactor: 0.85 },\n 'landscape': { ratio: [4, 3], baseWidth: 800, qualityFactor: 0.85 },\n};\n\n/**\n * Size scale factors - multiplies the display's baseWidth\n */\nconst SIZE_SCALES: Record<string, number> = {\n 'xs': 0.25,\n 'sm': 0.5,\n 'md': 1.0,\n 'lg': 1.5,\n 'xl': 2.0,\n '2xl': 2.5,\n};\n\n/**\n * Standalone size presets - used when no display is specified\n */\nconst STANDALONE_SIZES: Record<string, { width: number; height: number }> = {\n 'xs': { width: 64, height: 64 },\n 'sm': { width: 128, height: 128 },\n 'md': { width: 256, height: 256 },\n 'lg': { width: 512, height: 512 },\n 'xl': { width: 1024, height: 1024 },\n '2xl': { width: 1600, height: 1600 },\n 'icon': { width: 48, height: 48 },\n 'thumb': { width: 150, height: 150 },\n 'square': { width: 600, height: 600 },\n 'avatar-sm': { width: 64, height: 64 },\n 'avatar-md': { width: 128, height: 128 },\n 'avatar-lg': { width: 256, height: 256 },\n 'landscape-sm': { width: 480, height: 270 },\n 'landscape': { width: 800, height: 450 },\n 'landscape-lg': { width: 1280, height: 720 },\n 'landscape-xl': { width: 1920, height: 1080 },\n 'portrait-sm': { width: 270, height: 480 },\n 'portrait': { width: 450, height: 800 },\n 'portrait-lg': { width: 720, height: 1280 },\n 'wide': { width: 1200, height: 630 },\n 'banner': { width: 1200, height: 400 },\n 'banner-sm': { width: 800, height: 200 },\n 'photo-4x3': { width: 800, height: 600 },\n 'photo-3x2': { width: 900, height: 600 },\n 'story': { width: 1080, height: 1920 },\n 'video': { width: 1280, height: 720 },\n 'video-sm': { width: 640, height: 360 },\n 'card-sm': { width: 300, height: 200 },\n 'card': { width: 400, height: 300 },\n 'card-lg': { width: 600, height: 400 },\n};\n\n/**\n * Calculates all image optimization settings based on file size, quality, display, and size.\n * \n * @param fileSizeInBytes - Original file size in bytes\n * @param qualityPreset - Quality preset ('low', 'medium', 'high') or number (1-100)\n * @param display - Display context preset (sets aspect ratio + quality factor)\n * @param size - Size scale (xs/sm/md/lg/xl) or standalone dimension preset\n * @returns Complete image settings including quality, effort, and optional dimensions\n */\nexport const getImageSettings = (\n fileSizeInBytes: number | undefined,\n qualityPreset: string | undefined,\n display: string | undefined,\n size: string | undefined\n): ImageSettings => {\n // 1. Parse base quality from preset\n let baseQuality = 80;\n if (qualityPreset === 'low') baseQuality = 30;\n else if (qualityPreset === 'medium') baseQuality = 50;\n else if (qualityPreset === 'high') baseQuality = 75;\n else if (qualityPreset) {\n const n = parseInt(qualityPreset, 10);\n if (!isNaN(n)) baseQuality = Math.min(100, Math.max(1, n));\n }\n\n // 2. Calculate dimensions and quality factor\n let width: number | undefined;\n let height: number | undefined;\n let qualityFactor = 1.0;\n\n const displayPreset = display ? DISPLAY_PRESETS[display] : undefined;\n\n if (displayPreset) {\n // Display is specified - use its aspect ratio\n qualityFactor = displayPreset.qualityFactor;\n const [ratioW, ratioH] = displayPreset.ratio;\n\n // Apply size scale if it's a scale factor (xs/sm/md/lg/xl)\n const scale = size && SIZE_SCALES[size] ? SIZE_SCALES[size] : 1.0;\n width = Math.round(displayPreset.baseWidth * scale);\n height = Math.round(width * ratioH / ratioW);\n } else if (size) {\n // No display, check standalone sizes\n const standalone = STANDALONE_SIZES[size];\n if (standalone) {\n width = standalone.width;\n height = standalone.height;\n }\n }\n\n // Apply quality factor from display\n baseQuality = Math.round(baseQuality * qualityFactor);\n\n // 3. Apply file size dynamic adjustment\n let quality = baseQuality;\n let effort = 4;\n let pngCompression = 6;\n\n if (fileSizeInBytes) {\n const sizeInKB = fileSizeInBytes / 1024;\n\n if (sizeInKB > 500) {\n quality = Math.min(baseQuality, 25);\n effort = 9;\n pngCompression = 9;\n } else if (sizeInKB > 300) {\n quality = Math.min(baseQuality, 30);\n effort = 8;\n pngCompression = 9;\n } else if (sizeInKB > 150) {\n quality = Math.min(baseQuality, 35);\n effort = 7;\n pngCompression = 8;\n } else if (sizeInKB > 90) {\n quality = Math.min(baseQuality, 40);\n effort = 6;\n pngCompression = 8;\n } else if (sizeInKB > 50) {\n quality = Math.min(baseQuality, 50);\n effort = 5;\n pngCompression = 7;\n }\n }\n\n return {\n quality: Math.max(1, Math.min(100, quality)),\n effort,\n pngCompression,\n ...(width && height && { width, height }),\n };\n};\n\n// Legacy alias for backward compatibility\nexport const getQualitySettings = (fileSizeInBytes: number | undefined, qualityPreset: string | undefined) =>\n getImageSettings(fileSizeInBytes, qualityPreset, undefined, undefined);\n","import { z } from 'zod';\r\nimport { isValidObjectId } from 'mongoose';\r\n\r\n// ** Custom ObjectId validator\r\nconst objectIdSchema = z.string().refine(val => isValidObjectId(val), {\r\n message: 'Invalid ObjectId format',\r\n});\r\n\r\n// ** Sanitize filename - remove path traversal and dangerous characters\r\nconst sanitizeFilename = (name: string): string => {\r\n return (\r\n name\r\n .replace(/[<>:\"|?*\\x00-\\x1F]/g, '') // Remove dangerous chars\r\n .replace(/^\\.+/, '') // Remove leading dots\r\n .replace(/\\.+$/, '') // Remove trailing dots\r\n .replace(/\\\\/g, '/') // Normalize slashes\r\n .replace(/\\/+/g, '/') // Remove duplicate slashes\r\n .replace(/\\.\\.\\//g, '') // Remove path traversal\r\n .replace(/\\.\\.+/g, '') // Remove remaining ..\r\n .split('/')\r\n .pop() ||\r\n '' // Take only the filename part (remove all paths)\r\n .trim()\r\n .slice(0, 255)\r\n ); // Limit length\r\n};\r\n\r\n// ** Sanitize search query for regex\r\nconst sanitizeRegexInput = (input: string): string => {\r\n // Escape regex special characters\r\n return input.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').slice(0, 100);\r\n};\r\n\r\n// ** File/Folder name schema\r\nconst nameSchema = z\r\n .string()\r\n .min(1, 'Name is required')\r\n .max(255, 'Name too long')\r\n .transform(sanitizeFilename)\r\n .refine(val => val.length > 0, { message: 'Invalid name after sanitization' });\r\n\r\n// ** Upload chunk schema\r\nexport const uploadChunkSchema = z\r\n .object({\r\n chunkIndex: z.number().int().min(0).max(10000),\r\n totalChunks: z.number().int().min(1).max(10000),\r\n driveId: z.string().optional(),\r\n fileName: nameSchema,\r\n fileSize: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),\r\n fileType: z.string().min(1).max(255),\r\n folderId: z.string().optional(),\r\n })\r\n .refine(data => data.chunkIndex < data.totalChunks, {\r\n message: 'Chunk index must be less than total chunks',\r\n });\r\n\r\n// ** List query schema\r\nexport const listQuerySchema = z.object({\r\n folderId: z.union([z.literal('root'), objectIdSchema, z.undefined()]),\r\n limit: z\r\n .string()\r\n .optional()\r\n .transform(val => {\r\n const num = parseInt(val || '50', 10);\r\n return Math.min(Math.max(1, num), 100);\r\n }),\r\n afterId: objectIdSchema.optional(),\r\n});\r\n\r\n// ** Serve query schema\r\nexport const serveQuerySchema = z.object({\r\n id: objectIdSchema,\r\n token: z.string().optional(),\r\n});\r\n\r\n// ** Thumbnail query schema\r\nexport const thumbnailQuerySchema = z.object({\r\n id: objectIdSchema,\r\n size: z.enum(['small', 'medium', 'large']).optional().default('medium'),\r\n token: z.string().optional(),\r\n});\r\n\r\n// ** Rename body schema\r\nexport const renameBodySchema = z.object({\r\n id: objectIdSchema,\r\n newName: nameSchema,\r\n});\r\n\r\n// ** Delete query schema\r\nexport const deleteQuerySchema = z.object({\r\n id: objectIdSchema,\r\n});\r\n\r\n// ** Delete many body schema\r\nexport const deleteManyBodySchema = z.object({\r\n ids: z.array(objectIdSchema).min(1).max(1000),\r\n});\r\n\r\n// ** Create folder body schema\r\nexport const createFolderBodySchema = z.object({\r\n name: nameSchema,\r\n parentId: z.union([z.literal('root'), objectIdSchema, z.string().length(0), z.undefined()]).optional(),\r\n});\r\n\r\n// ** Move body schema\r\nexport const moveBodySchema = z.object({\r\n ids: z.array(objectIdSchema).min(1).max(1000),\r\n targetFolderId: z.union([z.literal('root'), objectIdSchema, z.undefined()]).optional(),\r\n});\r\n\r\n// ** Reorder body schema\r\nexport const reorderBodySchema = z.object({\r\n ids: z.array(objectIdSchema).min(1).max(1000),\r\n});\r\n\r\n// ** Search query schema\r\nexport const searchQuerySchema = z.object({\r\n q: z.string().min(1).max(100).transform(sanitizeRegexInput),\r\n folderId: z.union([z.literal('root'), objectIdSchema, z.undefined()]).optional(),\r\n limit: z\r\n .string()\r\n .optional()\r\n .transform(val => {\r\n const num = parseInt(val || '50', 10);\r\n return Math.min(Math.max(1, num), 100);\r\n }),\r\n trashed: z\r\n .string()\r\n .optional()\r\n .transform(val => val === 'true'),\r\n});\r\n\r\n// ** Restore query schema\r\nexport const restoreQuerySchema = z.object({\r\n id: objectIdSchema,\r\n});\r\n\r\n// ** Cancel query schema (accepts UUID since uploads use crypto.randomUUID())\r\nexport const cancelQuerySchema = z.object({\r\n id: z.string().uuid(),\r\n});\r\n\r\n// ** Purge trash query schema\r\nexport const purgeTrashQuerySchema = z.object({\r\n days: z.number().int().min(1).max(365).optional(),\r\n});\r\n\r\n// ** Drive File Schema (Public)\r\nexport const driveFileSchemaZod = z.object({\r\n id: z.string(),\r\n file: z.object({\r\n name: z.string(),\r\n mime: z.string(),\r\n size: z.number(),\r\n }),\r\n});\r\n\r\n// ** Constants\r\nexport const MAX_FOLDER_DEPTH = 50;\r\n\r\n// ** Export sanitization functions\r\nexport { sanitizeFilename, sanitizeRegexInput };\r\n","import crypto from 'crypto';\r\n\r\n/**\r\n * Constant-time string comparison to prevent timing attacks\r\n */\r\nexport function constantTimeCompare(a: string, b: string): boolean {\r\n\tif (a.length !== b.length) {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tlet result = 0;\r\n\tfor (let i = 0; i < a.length; i++) {\r\n\t\tresult |= a.charCodeAt(i) ^ b.charCodeAt(i);\r\n\t}\r\n\r\n\treturn result === 0;\r\n}\r\n\r\n/**\r\n * Safe error message that doesn't leak sensitive information\r\n */\r\nexport function getSafeErrorMessage(error: unknown): string {\r\n\tif (error instanceof Error) {\r\n\t\t// Filter out sensitive patterns (case-insensitive)\r\n\t\tconst message = error.message.toLowerCase();\r\n\r\n\t\t// Don't expose database errors\r\n\t\tif (message.includes('mongo')) {\r\n\t\t\treturn 'Database operation failed';\r\n\t\t}\r\n\r\n\t\t// Don't expose file paths\r\n\t\tif (message.includes('/') || message.includes('\\\\')) {\r\n\t\t\treturn 'File operation failed';\r\n\t\t}\r\n\r\n\t\t// Don't expose validation details from internal libraries\r\n\t\tif (message.includes('validation') || message.includes('cast')) {\r\n\t\t\treturn 'Invalid input';\r\n\t\t}\r\n\r\n\t\t// Generic safe messages\r\n\t\treturn 'Operation failed';\r\n\t}\r\n\r\n\treturn 'Internal server error';\r\n}\r\n\r\n/**\r\n * Validate and sanitize Content-Disposition filename\r\n */\r\nexport function sanitizeContentDispositionFilename(filename: string): string {\r\n\t// Remove any path components\r\n\tconst basename = filename.replace(/^.*[\\\\\\/]/, '');\r\n\r\n\t// Remove or encode dangerous characters\r\n\treturn basename\r\n\t\t.replace(/[\"\\r\\n]/g, '')\r\n\t\t.replace(/[^\\x20-\\x7E]/g, '') // Remove non-printable ASCII\r\n\t\t.slice(0, 255);\r\n}\r\n","import fs from 'fs';\nimport path from 'path';\nimport mongoose from 'mongoose';\nimport Drive from '@/server/database/mongoose/schema/drive';\nimport { getDriveConfig } from '@/server/config';\nimport { extractImageMetadata, computeFileHash } from '@/server/utils';\nimport type { TStorageProvider } from '@/types/server/storage';\nimport type { IDatabaseDriveDocument } from '@/server/database/mongoose/schema/drive';\nimport ffmpeg from 'fluent-ffmpeg';\nimport sharp from 'sharp';\n\nexport const LocalStorageProvider: TStorageProvider = {\n name: 'LOCAL',\n\n sync: async (folderId, owner, accountId) => {\n // No-op for local storage as DB is the source of truth\n },\n\n search: async (query, owner, accountId) => {\n // No-op for local storage as DB text search handles it\n },\n\n getQuota: async (owner, accountId, configuredQuotaInBytes) => {\n const config = getDriveConfig();\n const isRootMode = config.mode === 'ROOT';\n\n // In ROOT mode, return total storage used across all users\n const match: Record<string, unknown> = {\n 'information.type': 'FILE',\n trashedAt: null,\n 'provider.type': 'LOCAL',\n storageAccountId: accountId || null\n };\n\n // Only filter by owner in NORMAL mode\n if (!isRootMode) {\n match.owner = owner;\n }\n\n // Calculate storage used from DB - only count LOCAL provider files\n const result = await Drive.aggregate([\n { $match: match },\n { $group: { _id: null, total: { $sum: '$information.sizeInBytes' } } }\n ]);\n const usedInBytes = result[0]?.total || 0;\n\n // In ROOT mode, return unlimited quota\n if (isRootMode) {\n return { usedInBytes, quotaInBytes: Number.MAX_SAFE_INTEGER };\n }\n\n // Use configured quota from user's information callback (required)\n return { usedInBytes, quotaInBytes: configuredQuotaInBytes ?? 0 };\n },\n\n openStream: async (item: IDatabaseDriveDocument, accountId?: string) => {\n if (item.information.type !== 'FILE') throw new Error('Cannot stream folder');\n const storagePath = getDriveConfig().storage.path;\n const filePath = path.join(storagePath, 'file', item._id.toString(), 'data.bin');\n\n if (!fs.existsSync(filePath)) {\n throw new Error('File not found on disk');\n }\n\n const stat = fs.statSync(filePath);\n const stream = fs.createReadStream(filePath);\n\n return {\n stream,\n mime: item.information.mime,\n size: stat.size,\n };\n },\n\n getThumbnail: async (item: IDatabaseDriveDocument, accountId?: string) => {\n if (item.information.type !== 'FILE') throw new Error('No thumbnail for folder');\n\n const storagePath = getDriveConfig().storage.path;\n const fileDir = path.join(storagePath, 'file', item._id.toString());\n const originalPath = path.join(fileDir, 'data.bin');\n const thumbDir = path.join(fileDir, 'cache');\n const thumbPath = path.join(thumbDir, 'thumbnail.webp');\n\n if (!fs.existsSync(originalPath)) throw new Error('Original file not found');\n\n if (fs.existsSync(thumbPath)) {\n return fs.createReadStream(thumbPath);\n }\n\n // Generate thumbnail\n if (!fs.existsSync(thumbDir)) fs.mkdirSync(thumbDir, { recursive: true });\n\n if (item.information.mime.startsWith('image/')) {\n await sharp(originalPath).resize(300, 300, { fit: 'inside' }).toFormat('webp', { quality: 80 }).toFile(thumbPath);\n } else if (item.information.mime.startsWith('video/')) {\n await new Promise((resolve, reject) => {\n ffmpeg(originalPath)\n .screenshots({\n count: 1,\n folder: path.dirname(thumbPath),\n filename: path.basename(thumbPath),\n size: '300x?',\n })\n .on('end', resolve)\n .on('error', reject);\n });\n } else {\n throw new Error('Unsupported mime type for thumbnail');\n }\n\n return fs.createReadStream(thumbPath);\n },\n\n createFolder: async (name, parentId, owner, accountId) => {\n // Just DB operation for local folders (virtual)\n const getNextOrderValue = async (owner: Record<string, unknown> | null): Promise<number> => {\n const lastItem = await Drive.findOne({ owner }, {}, { sort: { order: -1 } });\n return lastItem ? lastItem.order + 1 : 0;\n };\n\n const folder = new Drive({\n owner,\n name,\n parentId: parentId === 'root' || !parentId ? null : parentId,\n order: await getNextOrderValue(owner),\n provider: { type: 'LOCAL' },\n information: { type: 'FOLDER' },\n status: 'READY',\n });\n await folder.save();\n return folder.toClient();\n },\n\n uploadFile: async (drive, filePath, accountId) => {\n if (drive.information.type !== 'FILE') throw new Error('Invalid drive type');\n\n const storagePath = getDriveConfig().storage.path;\n const destDir = path.join(storagePath, 'file', String(drive._id));\n const destPath = path.join(destDir, 'data.bin');\n\n // Ensure source file exists\n if (!fs.existsSync(filePath)) {\n throw new Error('Source file not found');\n }\n\n // Create destination directory if it doesn't exist\n if (!fs.existsSync(destDir)) {\n fs.mkdirSync(destDir, { recursive: true });\n }\n\n // Move file: try rename first (fast), fallback to copy+delete for cross-device\n try {\n fs.renameSync(filePath, destPath);\n } catch (err: unknown) {\n // EXDEV: cross-device link not permitted - use copy+delete instead\n if (err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'EXDEV') {\n fs.copyFileSync(filePath, destPath);\n fs.unlinkSync(filePath);\n } else {\n throw err;\n }\n }\n\n // Verify destination file exists after move/copy\n if (!fs.existsSync(destPath)) {\n throw new Error('Failed to write file to destination');\n }\n\n // Verify file size matches expected\n const destStats = fs.statSync(destPath);\n if (destStats.size !== drive.information.sizeInBytes) {\n // Cleanup corrupted file\n fs.unlinkSync(destPath);\n throw new Error(`Destination file size mismatch: expected ${drive.information.sizeInBytes}, got ${destStats.size}`);\n }\n\n drive.status = 'READY';\n drive.information.path = path.join('file', String(drive._id), 'data.bin');\n drive.information.hash = await computeFileHash(destPath);\n\n if (drive.information.mime.startsWith('image/')) {\n const meta = await extractImageMetadata(destPath);\n if (meta) {\n drive.information.width = meta.width;\n drive.information.height = meta.height;\n }\n }\n\n await drive.save();\n return drive.toClient();\n },\n\n delete: async (ids, owner, accountId) => {\n const items = await Drive.find({ _id: { $in: ids }, owner }).lean();\n\n // ** Helper to recursively get all children\n type TDriveItem = { _id: mongoose.Types.ObjectId; information: { type: string; path?: string } };\n\n const getAllChildren = async (folderIds: string[]): Promise<TDriveItem[]> => {\n const children = await Drive.find({ parentId: { $in: folderIds }, owner }).lean();\n if (children.length === 0) return [];\n\n const subFolderIds = children\n .filter(c => c.information.type === 'FOLDER')\n .map(c => c._id.toString());\n\n const subChildren = await getAllChildren(subFolderIds);\n return [...children, ...subChildren] as TDriveItem[];\n };\n\n const folderIds = items.filter(i => i.information.type === 'FOLDER').map(i => i._id.toString());\n const allChildren = await getAllChildren(folderIds);\n const allItemsToDelete = [...items, ...allChildren] as TDriveItem[];\n\n // ** Delete files from disk\n for (const item of allItemsToDelete) {\n if (item.information.type === 'FILE' && item.information.path) {\n // ** Delete entire file directory (includes cache)\n const fileDir = path.join(getDriveConfig().storage.path, 'file', item._id.toString());\n if (fs.existsSync(fileDir)) {\n fs.rmSync(fileDir, { recursive: true, force: true });\n }\n }\n }\n\n // ** Delete from DB\n await Drive.deleteMany({ _id: { $in: allItemsToDelete.map(i => i._id) } });\n },\n\n trash: async (ids, owner, accountId) => {\n // No-op for local, handled by DB update in index.ts\n },\n\n syncTrash: async (owner, accountId) => {\n // No-op for local\n },\n\n untrash: async (ids, owner, accountId) => {\n // No-op for local\n },\n\n rename: async (id, newName, owner, accountId) => {\n const item = await Drive.findOneAndUpdate({ _id: id, owner }, { name: newName }, { new: true });\n if (!item) throw new Error('Item not found');\n return item.toClient();\n },\n\n move: async (id, newParentId, owner, accountId) => {\n const item = await Drive.findOne({ _id: id, owner });\n if (!item) throw new Error('Item not found');\n\n // ** Update DB\n item.parentId = newParentId === 'root' || !newParentId ? null : new mongoose.Types.ObjectId(newParentId);\n\n // ** For LOCAL storage, physical path is ID-based: file/{ID}/data.bin\n // ** Folder hierarchy is virtual (in DB only), so move is just a DB update\n await item.save();\n return item.toClient();\n },\n\n revokeToken: async (owner, accountId) => {\n // No-op\n },\n};\n","import fs from 'fs';\nimport path from 'path';\nimport { google, type drive_v3 } from 'googleapis';\nimport { Readable } from 'stream';\nimport mongoose from 'mongoose';\nimport Drive from '@/server/database/mongoose/schema/drive';\nimport StorageAccount from '@/server/database/mongoose/schema/storage/account';\nimport { getDriveConfig } from '@/server/config';\nimport type { TStorageProvider, TDriveQuota } from '@/types/server/storage';\nimport type { IDatabaseDriveDocument } from '@/server/database/mongoose/schema/drive';\nimport type { TDatabaseDrive } from '@/types/lib/database/drive';\n\nconst createAuthClient = async (owner: Record<string, unknown> | null, accountId?: string) => {\n // ** Get credentials from StorageAccount\n const query: Record<string, unknown> = { owner, 'metadata.provider': 'GOOGLE' };\n if (accountId) query._id = accountId;\n\n // ** If multiple accounts and no accountId, pick first one\n const account = await StorageAccount.findOne(query);\n if (!account) throw new Error('Google Drive account not connected');\n\n const config = getDriveConfig();\n const { clientId, clientSecret, redirectUri } = config.storage?.google || {};\n\n if (!clientId || !clientSecret) throw new Error('Google credentials not configured on server');\n\n const oAuth2Client = new google.auth.OAuth2(clientId, clientSecret, redirectUri);\n\n // ** Verify it's a google account and metadata exists\n if (account.metadata.provider !== 'GOOGLE' || !account.metadata.google) {\n throw new Error('Invalid Google Account Metadata');\n }\n\n oAuth2Client.setCredentials(account.metadata.google.credentials as Parameters<typeof oAuth2Client.setCredentials>[0]);\n\n // ** Update tokens listener\n oAuth2Client.on('tokens', async tokens => {\n if (tokens.refresh_token) {\n account.metadata.google.credentials = { ...account.metadata.google.credentials, ...tokens };\n account.markModified('metadata');\n await account.save();\n }\n });\n\n return { client: oAuth2Client, accountId: account._id };\n};\n\nexport const GoogleDriveProvider: TStorageProvider = {\n name: 'GOOGLE',\n\n sync: async (folderId, owner, accountId) => {\n const { client, accountId: foundAccountId } = await createAuthClient(owner, accountId);\n const drive = google.drive({ version: 'v3', auth: client });\n\n // Resolve Google Folder ID\n let googleParentId = 'root';\n if (folderId && folderId !== 'root') {\n const folder = await Drive.findOne({ _id: folderId, owner });\n if (folder && folder.provider?.google?.id) {\n googleParentId = folder.provider.google.id;\n } else {\n return;\n }\n }\n\n // ** List files from Google with pagination\n let pageToken: string | undefined = undefined;\n const allSyncedGoogleIds = new Set<string>();\n\n do {\n const listParams: drive_v3.Params$Resource$Files$List = {\n q: `'${googleParentId}' in parents and trashed = false`,\n fields: 'nextPageToken, files(id, name, mimeType, size, webViewLink, iconLink, thumbnailLink, createdTime)',\n pageSize: 1000,\n pageToken,\n };\n const res = await drive.files.list(listParams);\n const responseData = res.data;\n\n pageToken = responseData.nextPageToken ?? undefined;\n const files = responseData.files ?? [];\n\n // Upsert to MongoDB\n for (const file of files) {\n if (!file.id || !file.name || !file.mimeType) continue;\n\n // Track ID\n allSyncedGoogleIds.add(file.id);\n\n // RELAXED FILTER: Allow Google Docs (application/vnd.google-apps.*)\n const isFolder = file.mimeType === 'application/vnd.google-apps.folder';\n // if (!isFolder && file.mimeType.startsWith('application/vnd.google-apps.')) continue; // REMOVED FILTER\n\n const sizeInBytes = file.size ? parseInt(file.size) : 0;\n\n // Construct update data\n const updateData = {\n name: file.name,\n storageAccountId: foundAccountId,\n parentId: folderId === 'root' ? null : folderId,\n information: {\n type: isFolder ? 'FOLDER' : 'FILE',\n sizeInBytes,\n mime: file.mimeType,\n path: '',\n },\n provider: {\n type: 'GOOGLE',\n google: {\n id: file.id,\n webViewLink: file.webViewLink,\n iconLink: file.iconLink,\n thumbnailLink: file.thumbnailLink,\n },\n },\n status: 'READY',\n trashedAt: null,\n };\n\n // Use source file's createdTime for createdAt on insert\n const insertData = file.createdTime ? { createdAt: new Date(file.createdTime) } : {};\n\n await Drive.findOneAndUpdate(\n {\n owner,\n 'provider.google.id': file.id,\n 'provider.type': 'GOOGLE',\n },\n { $set: updateData, $setOnInsert: insertData },\n { upsert: true, new: true, setDefaultsOnInsert: true },\n );\n }\n } while (pageToken);\n\n // ** Handle deletions - remove items in DB that were NOT in the gathered list\n const dbItems = await Drive.find({\n owner,\n storageAccountId: foundAccountId,\n parentId: folderId === 'root' ? null : folderId,\n 'provider.type': 'GOOGLE',\n });\n\n for (const item of dbItems) {\n // If item has a google ID and it wasn't seen in the sync list -> trash it\n if (item.provider?.google?.id && !allSyncedGoogleIds.has(item.provider.google.id)) {\n item.trashedAt = new Date();\n await item.save();\n }\n }\n },\n\n syncTrash: async (owner, accountId) => {\n const { client, accountId: foundAccountId } = await createAuthClient(owner, accountId);\n const driveApi = google.drive({ version: 'v3', auth: client });\n\n // ** Helper to fetch trashed files with pagination\n const fetchTrashedFiles = async (pageToken?: string) => {\n return driveApi.files.list({\n q: 'trashed = true',\n fields: 'nextPageToken, files(id, name, mimeType, size, webViewLink, iconLink, thumbnailLink, createdTime)',\n pageSize: 100,\n pageToken,\n });\n };\n\n // ** List trashed files from Google with pagination\n let nextToken: string | undefined = undefined;\n\n do {\n const listResult = await fetchTrashedFiles(nextToken);\n const files = listResult.data.files || [];\n\n for (const file of files) {\n if (!file.id || !file.name || !file.mimeType) continue;\n\n // ** RELAXED FILTER: Allow Google Docs (application/vnd.google-apps.*)\n const isFolder = file.mimeType === 'application/vnd.google-apps.folder';\n\n const sizeInBytes = file.size ? parseInt(file.size) : 0;\n\n // ** Use source file's createdTime for createdAt on insert\n const insertData = file.createdTime ? { createdAt: new Date(file.createdTime) } : {};\n\n await Drive.findOneAndUpdate(\n { owner, 'provider.google.id': file.id, 'provider.type': 'GOOGLE' },\n {\n $set: {\n name: file.name,\n storageAccountId: foundAccountId,\n information: {\n type: isFolder ? 'FOLDER' : 'FILE',\n sizeInBytes,\n mime: file.mimeType,\n path: '',\n },\n provider: {\n type: 'GOOGLE',\n google: {\n id: file.id,\n webViewLink: file.webViewLink,\n iconLink: file.iconLink,\n thumbnailLink: file.thumbnailLink,\n },\n },\n trashedAt: new Date(),\n },\n $setOnInsert: insertData,\n },\n { upsert: true, setDefaultsOnInsert: true },\n );\n }\n\n // ** Update pagination state\n nextToken = listResult.data.nextPageToken ?? undefined;\n } while (nextToken);\n },\n\n search: async (query, owner, accountId) => {\n const { client, accountId: foundAccountId } = await createAuthClient(owner, accountId);\n const drive = google.drive({ version: 'v3', auth: client });\n\n // Google Search Query\n // name contains 'query'\n const res = await drive.files.list({\n q: `name contains '${query}' and trashed = false`,\n fields: 'files(id, name, mimeType, size, parents, webViewLink, iconLink, thumbnailLink, createdTime)',\n pageSize: 50,\n });\n\n const files = res.data.files || [];\n\n // Upsert results\n // Note: We might not know the local parentId for these items if we haven't synced their parents.\n // This makes it tricky. If we just upsert with parentId=null (root), they show up in root, which is confusing.\n // Option: Don't change parentId if exists. If new, maybe leave parentId null/undefined but we need it.\n // Strategy: Just update existing items metadata?\n // OR: \"Search\" just returns items without persisting parent structure?\n // But our UI relies on DB.\n // If we upsert new items from search, we must assign a parent.\n // Typically we can't assign accurate local parent ID without traversing up.\n // Compromise: Update properties of existing items. Ignore new items?\n // OR: Just let `list` handle creation. Search only works on things we've synced?\n // NO, user wants to find remote files.\n // Allow creating with parentId = null (root) for now? Or keep them \"orphaned\" (parentId: undefined) if that works?\n // Drive schema requires parentId? default null.\n // Let's skip upserting NEW items from search for now to avoid mess.\n // Only update existing.\n // Wait, if I search for \"Report\", I want to see \"Report.pdf\" even if I never opened the folder.\n // This implies I need to sync it.\n // For now, I will NOT upsert in search to keep safety. search only funds synced items.\n // Re-evaluating: The prompt said \"Search... mapping user queries to Google's q syntax\".\n // This implies meaningful results.\n // Let's implement basics: Sync results to DB. Parent = null (Root) if unknown.\n // Users can then \"Go to location\" -> might fail if path unknown.\n // Just upserting with `parentId: null` puts them in root.\n // I will omit parentId in update, so it keeps existing. If new, it defaults to null (Root).\n // This is acceptable behavior for \"All files\" view or similar.\n\n for (const file of files) {\n if (!file.id || !file.name) continue;\n const isFolder = file.mimeType === 'application/vnd.google-apps.folder';\n if (!isFolder && file.mimeType?.startsWith('application/vnd.google-apps.')) continue;\n\n const sizeInBytes = file.size ? parseInt(file.size) : 0;\n\n // Use source file's createdTime for createdAt on insert\n const insertData = file.createdTime ? { createdAt: new Date(file.createdTime) } : {};\n\n await Drive.findOneAndUpdate(\n { owner, 'provider.google.id': file.id, 'metadata.type': 'GOOGLE' },\n {\n $set: {\n name: file.name,\n storageAccountId: foundAccountId,\n information: {\n type: isFolder ? 'FOLDER' : 'FILE',\n sizeInBytes,\n mime: file.mimeType,\n path: '',\n },\n metadata: {\n type: 'GOOGLE',\n },\n provider: {\n google: {\n id: file.id,\n webViewLink: file.webViewLink,\n iconLink: file.iconLink,\n thumbnailLink: file.thumbnailLink,\n },\n },\n // Don't overwrite parentId if it exists.\n // New items will default to null (Root) via schema default\n },\n $setOnInsert: insertData,\n },\n { upsert: true, setDefaultsOnInsert: true },\n );\n }\n },\n\n getQuota: async (owner, accountId, _configuredQuotaInBytes) => {\n const config = getDriveConfig();\n const isRootMode = config.mode === 'ROOT';\n\n // In ROOT mode, calculate from DB and return unlimited quota\n if (isRootMode) {\n const result = await Drive.aggregate([\n {\n $match: {\n 'information.type': 'FILE',\n trashedAt: null,\n 'provider.type': 'GOOGLE',\n storageAccountId: accountId || null,\n },\n },\n { $group: { _id: null, total: { $sum: '$information.sizeInBytes' } } },\n ]);\n const usedInBytes = result[0]?.total || 0;\n return { usedInBytes, quotaInBytes: Number.MAX_SAFE_INTEGER };\n }\n\n // Google Drive uses its own quota from the API, ignores configured quota\n try {\n const { client } = await createAuthClient(owner, accountId);\n const drive = google.drive({ version: 'v3', auth: client });\n const res = await drive.about.get({ fields: 'storageQuota' });\n return {\n usedInBytes: parseInt(res.data.storageQuota?.usage || '0'),\n quotaInBytes: parseInt(res.data.storageQuota?.limit || '0'),\n };\n } catch {\n return { usedInBytes: 0, quotaInBytes: 0 };\n }\n },\n\n openStream: async (item: IDatabaseDriveDocument, accountId?: string) => {\n const { client } = await createAuthClient(item.owner, accountId || item.storageAccountId?.toString());\n const drive = google.drive({ version: 'v3', auth: client });\n\n if (!item.provider?.google?.id) throw new Error('Missing Google File ID');\n\n // ** Check if we can stream functionality\n if (item.information.type === 'FOLDER') throw new Error('Cannot stream folder');\n\n const res = await drive.files.get(\n { fileId: item.provider.google.id, alt: 'media' },\n { responseType: 'stream' }\n );\n\n return {\n stream: res.data as Readable,\n mime: item.information.mime,\n size: item.information.sizeInBytes,\n };\n },\n\n getThumbnail: async (item: IDatabaseDriveDocument, accountId?: string) => {\n const config = getDriveConfig();\n const storagePath = config.storage.path;\n const thumbDir = path.join(storagePath, 'file', item._id.toString(), 'cache');\n const thumbPath = path.join(thumbDir, 'thumbnail.webp');\n\n // ** Return cached thumbnail if exists\n if (fs.existsSync(thumbPath)) {\n return fs.createReadStream(thumbPath);\n }\n\n // ** Fetch from Google\n const { client } = await createAuthClient(item.owner, accountId || item.storageAccountId?.toString());\n if (!item.provider?.google?.thumbnailLink) throw new Error('No thumbnail available');\n\n const res = await client.request<Readable>({ url: item.provider.google.thumbnailLink, responseType: 'stream' });\n\n // ** Cache the thumbnail\n if (!fs.existsSync(thumbDir)) {\n fs.mkdirSync(thumbDir, { recursive: true });\n }\n\n const tempPath = `${thumbPath}.tmp`;\n const writeStream = fs.createWriteStream(tempPath);\n\n await new Promise<void>((resolve, reject) => {\n (res.data as Readable).pipe(writeStream);\n writeStream.on('finish', resolve);\n writeStream.on('error', reject);\n });\n\n // ** Rename temp to final\n try {\n fs.renameSync(tempPath, thumbPath);\n } catch {\n // If rename fails, cleanup and return stream from Google\n fs.unlinkSync(tempPath);\n }\n\n // ** Return the cached file\n if (fs.existsSync(thumbPath)) {\n return fs.createReadStream(thumbPath);\n }\n\n // ** Fallback: refetch from Google\n const refetch = await client.request<Readable>({ url: item.provider.google.thumbnailLink, responseType: 'stream' });\n return refetch.data as Readable;\n },\n\n createFolder: async (name, parentId, owner, accountId) => {\n const { client, accountId: foundAccountId } = await createAuthClient(owner, accountId);\n const drive = google.drive({ version: 'v3', auth: client });\n\n let googleParentId = 'root';\n if (parentId && parentId !== 'root') {\n const parent = await Drive.findOne({ _id: parentId, owner });\n if (parent?.provider?.google?.id) googleParentId = parent.provider.google.id;\n }\n\n const res = await drive.files.create({\n requestBody: {\n name,\n mimeType: 'application/vnd.google-apps.folder',\n parents: [googleParentId],\n },\n fields: 'id, name, mimeType, webViewLink, iconLink',\n });\n\n const file = res.data;\n if (!file.id) throw new Error('Failed to create folder on Google Drive');\n\n // Create local record\n const folder = new Drive({\n owner,\n name: file.name,\n parentId: parentId === 'root' || !parentId ? null : parentId,\n provider: {\n type: 'GOOGLE',\n google: {\n id: file.id,\n webViewLink: file.webViewLink,\n iconLink: file.iconLink,\n },\n },\n storageAccountId: foundAccountId,\n information: { type: 'FOLDER' },\n status: 'READY',\n });\n await folder.save();\n return folder.toClient();\n },\n\n uploadFile: async (drive, filePath, accountId) => {\n if (drive.information.type !== 'FILE') throw new Error('Invalid drive type');\n\n const { client } = await createAuthClient(drive.owner, accountId || drive.storageAccountId?.toString());\n const googleDrive = google.drive({ version: 'v3', auth: client });\n\n let googleParentId = 'root';\n if (drive.parentId) {\n const parent = await Drive.findById(drive.parentId);\n if (parent?.provider?.google?.id) googleParentId = parent.provider.google.id;\n }\n\n try {\n const res = await googleDrive.files.create({\n requestBody: {\n name: drive.name,\n parents: [googleParentId],\n mimeType: drive.information.mime,\n },\n media: {\n mimeType: drive.information.mime,\n body: fs.createReadStream(filePath),\n },\n fields: 'id, name, mimeType, webViewLink, iconLink, thumbnailLink, size',\n });\n\n const gFile = res.data;\n if (!gFile.id) throw new Error('Upload to Google Drive failed');\n\n // ** Update Drive record\n drive.status = 'READY';\n drive.provider = {\n type: 'GOOGLE',\n google: {\n id: gFile.id,\n webViewLink: gFile.webViewLink || undefined,\n iconLink: gFile.iconLink || undefined,\n thumbnailLink: gFile.thumbnailLink || undefined,\n },\n };\n\n // ** Note: We don't delete the temp file here, index.ts handles cleanup\n } catch (error) {\n drive.status = 'FAILED';\n console.error('[next-drive] Google Upload Error:', error);\n throw error;\n }\n\n await drive.save();\n return drive.toClient();\n },\n\n delete: async (ids, owner, accountId) => {\n const { client } = await createAuthClient(owner, accountId);\n const drive = google.drive({ version: 'v3', auth: client });\n\n const items = await Drive.find({ _id: { $in: ids }, owner });\n\n for (const item of items) {\n if (item.provider?.google?.id) {\n try {\n await drive.files.delete({ fileId: item.provider.google.id });\n } catch (e) {\n console.error('Failed to delete Google file', e);\n }\n }\n }\n\n await Drive.deleteMany({ _id: { $in: ids } });\n },\n\n trash: async (ids, owner, accountId) => {\n const { client } = await createAuthClient(owner, accountId);\n const drive = google.drive({ version: 'v3', auth: client });\n\n const items = await Drive.find({ _id: { $in: ids }, owner });\n\n for (const item of items) {\n if (item.provider?.google?.id) {\n try {\n await drive.files.update({\n fileId: item.provider.google.id,\n requestBody: { trashed: true },\n });\n } catch (e) {\n console.error('Failed to trash Google file', e);\n }\n }\n }\n },\n\n untrash: async (ids, owner, accountId) => {\n const { client } = await createAuthClient(owner, accountId);\n const drive = google.drive({ version: 'v3', auth: client });\n\n const items = await Drive.find({ _id: { $in: ids }, owner });\n\n for (const item of items) {\n if (item.provider?.google?.id) {\n try {\n await drive.files.update({\n fileId: item.provider.google.id,\n requestBody: { trashed: false },\n });\n } catch (e) {\n console.error('Failed to restore Google file', e);\n }\n }\n }\n },\n\n rename: async (id, newName, owner, accountId) => {\n const { client } = await createAuthClient(owner, accountId);\n const drive = google.drive({ version: 'v3', auth: client });\n\n const item = await Drive.findOne({ _id: id, owner });\n if (!item || !item.provider?.google?.id) throw new Error('Item not found');\n\n await drive.files.update({\n fileId: item.provider.google.id,\n requestBody: { name: newName },\n });\n\n item.name = newName;\n await item.save();\n return item.toClient();\n },\n\n move: async (id, newParentId, owner, accountId) => {\n const { client, accountId: foundAccountId } = await createAuthClient(owner, accountId);\n const drive = google.drive({ version: 'v3', auth: client });\n\n // Get Item\n const item = await Drive.findOne({ _id: id, owner });\n if (!item || !item.provider?.google?.id) throw new Error('Item not found or not synced');\n\n // Resolve Old Parent Google ID\n let previousGoogleParentId: string | undefined = undefined;\n if (item.parentId) {\n const oldParent = await Drive.findOne({ _id: item.parentId, owner });\n if (oldParent && oldParent.provider?.google?.id) {\n previousGoogleParentId = oldParent.provider.google.id;\n }\n } else {\n // If parentId is null (root), finding previous parent is tricky without querying Google\n // But usually we don't need to specify removeParents if we don't care about multi-parenting?\n // Actually, in Drive API v3, moving requires removeParents if you want to 'move' and not 'add to'.\n // Let's query parents from Google to be safe\n try {\n const gFile = await drive.files.get({ fileId: item.provider.google.id, fields: 'parents' });\n if (gFile.data.parents && gFile.data.parents.length > 0) {\n previousGoogleParentId = gFile.data.parents.join(',');\n }\n } catch (e) {\n console.warn('Could not fetch parents for move', e);\n }\n }\n\n // Resolve New Parent Google ID\n let newGoogleParentId = 'root'; // User's root (maybe specific root folder if we support that?)\n // For now, assume 'root' maps to Drive root (or myDrive)\n if (newParentId && newParentId !== 'root') {\n const newParent = await Drive.findOne({ _id: newParentId, owner });\n if (!newParent || !newParent.provider?.google?.id) throw new Error('Target folder not found in Google Drive');\n newGoogleParentId = newParent.provider.google.id;\n }\n\n // Call Google API\n await drive.files.update({\n fileId: item.provider.google.id,\n addParents: newGoogleParentId,\n removeParents: previousGoogleParentId,\n fields: 'id, parents',\n });\n\n // Update DB\n item.parentId = newParentId === 'root' || !newParentId ? null : new mongoose.Types.ObjectId(newParentId);\n await item.save();\n\n return item.toClient();\n },\n\n revokeToken: async (owner, accountId) => {\n if (!accountId) return; // ** Need specific account to revoke\n const { client } = await createAuthClient(owner, accountId);\n const account = await StorageAccount.findById(accountId);\n if (account?.metadata?.provider === 'GOOGLE' && account.metadata.google?.credentials) {\n const creds = account.metadata.google.credentials as Record<string, unknown>;\n if (typeof creds === 'object' && 'access_token' in creds && typeof creds.access_token === 'string') {\n await client.revokeToken(creds.access_token);\n }\n }\n },\n};\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport crypto from 'crypto';\nimport type { Readable } from 'stream';\nimport Drive from '@/server/database/mongoose/schema/drive';\nimport { getDriveConfig } from '@/server/config';\nimport { computeFileHash, extractImageMetadata, validateMimeType } from '@/server/utils';\nimport type { IDatabaseDriveDocument } from '@/server/database/mongoose/schema/drive';\nimport type { TDatabaseDrive } from '@/types/lib/database/drive';\nimport type { TDriveFile } from '@/types/client';\nimport { LocalStorageProvider } from '@/server/providers/local';\nimport { GoogleDriveProvider } from '@/server/providers/google';\n\nexport const getNextOrderValue = async (owner: Record<string, unknown> | null): Promise<number> => {\n const lastItem = await Drive.findOne({ owner }, {}, { sort: { order: -1 } });\n return lastItem ? lastItem.order + 1 : 0;\n};\n\nexport const getStorageUsed = async (owner: Record<string, unknown> | null): Promise<number> => {\n try {\n const result = await Drive.aggregate([{ $match: { owner, 'information.type': 'FILE', trashedAt: null } }, { $group: { _id: null, total: { $sum: '$information.sizeInBytes' } } }]);\n return result[0]?.total || 0;\n } catch {\n return 0;\n }\n};\n\nexport const getAllFolderContents = async (folderId: string, owner: Record<string, unknown> | null, maxDepth = 50, currentDepth = 0): Promise<IDatabaseDriveDocument[]> => {\n if (currentDepth >= maxDepth) throw new Error('Maximum folder depth exceeded');\n\n const items = await Drive.find({ parentId: folderId, owner }).exec();\n const result: IDatabaseDriveDocument[] = [...items];\n\n for (const item of items) {\n if (item.information.type === 'FOLDER') {\n const subItems = await getAllFolderContents(String(item._id), owner, maxDepth, currentDepth + 1);\n result.push(...subItems);\n }\n }\n return result;\n};\n\nexport const driveGetUrl = (fileId: string, options?: { expiry?: number | Date }): string => {\n const config = getDriveConfig();\n if (!config.security?.signedUrls?.enabled) {\n return `/api/drive?action=serve&id=${fileId}`;\n }\n\n const { secret, expiresIn } = config.security.signedUrls;\n let expiryTimestamp: number;\n\n if (options?.expiry instanceof Date) {\n expiryTimestamp = Math.floor(options.expiry.getTime() / 1000);\n } else if (typeof options?.expiry === 'number') {\n expiryTimestamp = Math.floor(Date.now() / 1000) + options.expiry;\n } else {\n expiryTimestamp = Math.floor(Date.now() / 1000) + expiresIn;\n }\n\n const signature = crypto.createHmac('sha256', secret).update(`${fileId}:${expiryTimestamp}`).digest('hex');\n const token = Buffer.from(`${expiryTimestamp}:${signature}`).toString('base64url');\n return `/api/drive?action=serve&id=${fileId}&token=${token}`;\n};\n\n/**\n * Read a file and return a readable stream.\n * @param file - Either a file ID (string) or a TDatabaseDrive/IDatabaseDriveDocument object\n * @returns Promise with readable stream, mime type, and file size\n * @example\n * ```typescript\n * // Using file ID\n * const { stream, mime, size } = await driveReadFile('694f5013226de007be94fcc0');\n * stream.pipe(response);\n * \n * // Using database document\n * const drive = await Drive.findById(fileId);\n * const { stream, mime, size } = await driveReadFile(drive);\n * ```\n */\nexport const driveReadFile = async (\n file: string | IDatabaseDriveDocument | TDatabaseDrive\n): Promise<{ stream: Readable; mime: string; size: number }> => {\n let drive: IDatabaseDriveDocument;\n\n // If file is a string (ID), fetch from database\n if (typeof file === 'string') {\n const doc = await Drive.findById(file);\n if (!doc) throw new Error(`File not found: ${file}`);\n drive = doc;\n } else if ('toClient' in file) {\n // Already an IDatabaseDriveDocument (Mongoose document)\n drive = file;\n } else {\n throw new Error('Invalid file parameter provided');\n }\n\n if (drive.information.type !== 'FILE') {\n throw new Error('Cannot read a folder');\n }\n\n // Determine provider based on drive's provider type\n const provider = drive.provider?.type === 'GOOGLE' ? GoogleDriveProvider : LocalStorageProvider;\n const accountId = drive.storageAccountId?.toString();\n\n // Use provider's openStream method\n return await provider.openStream(drive, accountId);\n};\n\n/**\n * Get detailed information about a file or folder\n * @param source - Either a file/folder ID (string) or a TDriveFile object\n * @returns Promise with detailed file/folder information\n * @example\n * ```typescript\n * // Using file ID\n * const info = await driveInfo('694f5013226de007be94fcc0');\n * console.log(info.name, info.size, info.createdAt);\n * \n * // Using TDriveFile\n * const file = { id: '123', file: { name: 'photo.jpg', mime: 'image/jpeg', size: 1024 } };\n * const info = await driveInfo(file);\n * ```\n */\nexport const driveInfo = async (\n source: string | TDriveFile\n): Promise<import('@/types/client').TDriveInformation> => {\n const fileId = typeof source === 'string' ? source : source.id;\n\n const drive = await Drive.findById(fileId);\n if (!drive) throw new Error(`File not found: ${fileId}`);\n\n // Get parent folder name if exists\n let parentName: string | undefined;\n if (drive.parentId) {\n const parent = await Drive.findById(drive.parentId);\n if (parent) parentName = parent.name;\n }\n\n // Build the response\n const info: import('@/types/client').TDriveInformation = {\n id: String(drive._id),\n name: drive.name,\n type: drive.information.type,\n status: drive.status,\n provider: drive.provider,\n parent: {\n id: drive.parentId ? String(drive.parentId) : null,\n name: parentName,\n },\n createdAt: drive.createdAt,\n trashedAt: drive.trashedAt,\n };\n\n // Add file-specific information\n if (drive.information.type === 'FILE') {\n info.mime = drive.information.mime;\n info.size = drive.information.sizeInBytes;\n info.hash = drive.information.hash;\n\n // Add image dimensions if available\n if (drive.information.width && drive.information.height) {\n info.dimensions = {\n width: drive.information.width,\n height: drive.information.height,\n };\n }\n\n // Add video duration if available\n if (drive.information.duration) {\n info.duration = drive.information.duration;\n }\n }\n\n return info;\n};\n\n/**\n * Get the local file system path for a file. For Google Drive files, downloads them to a local cache first.\n * @param file - Either a file ID (string) or a TDatabaseDrive/IDatabaseDriveDocument object\n * @returns Promise with readonly object containing the absolute file path and metadata\n * @example\n * ```typescript\n * // Using file ID\n * const { path, mime, size } = await driveFilePath('694f5013226de007be94fcc0');\n * const data = fs.readFileSync(path);\n * \n * // Using database document\n * const drive = await Drive.findById(fileId);\n * const { path, name, provider } = await driveFilePath(drive);\n * await processFile(path);\n * ```\n */\nexport const driveFilePath = async (\n file: string | IDatabaseDriveDocument | TDatabaseDrive\n): Promise<Readonly<{ path: string; name: string; mime: string; size: number; provider: string }>> => {\n let drive: IDatabaseDriveDocument;\n\n // If file is a string (ID), fetch from database\n if (typeof file === 'string') {\n const doc = await Drive.findById(file);\n if (!doc) throw new Error(`File not found: ${file}`);\n drive = doc;\n } else if ('toClient' in file) {\n // Already an IDatabaseDriveDocument (Mongoose document)\n drive = file;\n } else {\n throw new Error('Invalid file parameter provided');\n }\n\n if (drive.information.type !== 'FILE') {\n throw new Error('Cannot get path for a folder');\n }\n\n const config = getDriveConfig();\n const STORAGE_PATH = config.storage.path;\n const providerType = drive.provider?.type || 'LOCAL';\n\n // For LOCAL files, return the existing path directly\n if (providerType === 'LOCAL') {\n const filePath = path.join(STORAGE_PATH, 'file', String(drive._id), 'data.bin');\n\n if (!fs.existsSync(filePath)) {\n throw new Error(`Local file not found on disk: ${filePath}`);\n }\n\n return Object.freeze({\n path: filePath,\n name: drive.name,\n mime: drive.information.mime,\n size: drive.information.sizeInBytes,\n provider: 'LOCAL'\n });\n }\n\n // For GOOGLE files, download to file directory\n if (providerType === 'GOOGLE') {\n const fileDir = path.join(STORAGE_PATH, 'file', String(drive._id));\n const cachedFilePath = path.join(fileDir, 'data.bin');\n\n // Check if already cached\n if (fs.existsSync(cachedFilePath)) {\n const stats = fs.statSync(cachedFilePath);\n\n // Verify cached file size matches (simple integrity check)\n if (stats.size === drive.information.sizeInBytes) {\n return Object.freeze({\n path: cachedFilePath,\n name: drive.name,\n mime: drive.information.mime,\n size: drive.information.sizeInBytes,\n provider: 'GOOGLE'\n });\n }\n\n // Size mismatch, re-download\n fs.unlinkSync(cachedFilePath);\n }\n\n // Download from Google Drive\n const accountId = drive.storageAccountId?.toString();\n const { stream } = await GoogleDriveProvider.openStream(drive, accountId);\n\n // Create file directory if it doesn't exist\n if (!fs.existsSync(fileDir)) {\n fs.mkdirSync(fileDir, { recursive: true });\n }\n\n // Download to temp file first, then move (atomic operation)\n const tempPath = `${cachedFilePath}.tmp`;\n const writeStream = fs.createWriteStream(tempPath);\n\n await new Promise<void>((resolve, reject) => {\n stream.pipe(writeStream);\n writeStream.on('finish', resolve);\n writeStream.on('error', reject);\n stream.on('error', reject);\n });\n\n // Move temp file to final path - handle cross-device case\n try {\n fs.renameSync(tempPath, cachedFilePath);\n } catch (err: unknown) {\n if (err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'EXDEV') {\n fs.copyFileSync(tempPath, cachedFilePath);\n fs.unlinkSync(tempPath);\n } else {\n throw err;\n }\n }\n\n return Object.freeze({\n path: cachedFilePath,\n name: drive.name,\n mime: drive.information.mime,\n size: drive.information.sizeInBytes,\n provider: 'GOOGLE'\n });\n }\n\n throw new Error(`Unsupported provider: ${providerType}`);\n};\n\n/**\n * List files and folders in a specific directory.\n * @param options - List options including owner key, folderId, limit, and afterId for pagination\n * @returns Promise with array of drive items\n * @example\n * ```typescript\n * // List root folder\n * const items = await driveList({ key: { userId: '123' } });\n * \n * // List specific folder with limit\n * const items = await driveList({\n * key: { userId: '123' },\n * folderId: 'folderIdHere',\n * limit: 50\n * });\n * \n * // Pagination\n * const items = await driveList({\n * key: { userId: '123' },\n * folderId: 'root',\n * limit: 20,\n * afterId: 'lastItemId'\n * });\n * ```\n */\nexport const driveList = async (\n options: {\n key: Record<string, unknown> | null;\n folderId?: string | null;\n accountId?: string;\n limit?: number;\n afterId?: string;\n }\n): Promise<TDatabaseDrive[]> => {\n const { key, folderId, accountId, limit = 100, afterId } = options;\n\n // Determine provider\n let providerName: 'LOCAL' | 'GOOGLE' = 'LOCAL';\n if (accountId && accountId !== 'LOCAL') {\n const account = await Drive.db.model('StorageAccount').findOne({ _id: accountId, owner: key });\n if (!account) {\n throw new Error('Invalid Storage Account');\n }\n if (account.metadata.provider === 'GOOGLE') {\n providerName = 'GOOGLE';\n }\n }\n\n // Build query\n const query: Record<string, unknown> = {\n owner: key,\n 'provider.type': providerName,\n storageAccountId: accountId || null,\n parentId: folderId === 'root' || !folderId ? null : folderId,\n trashedAt: null,\n };\n\n if (afterId) {\n query._id = { $lt: afterId };\n }\n\n const items = await Drive.find(query, {}, { sort: { order: 1, _id: -1 }, limit });\n return await Promise.all(items.map(item => item.toClient()));\n};\n\n/**\n * Delete a file or folder permanently from the drive system.\n * @param source - File ID (string) or a TDatabaseDrive/IDatabaseDriveDocument object\n * @param options - Delete options including recurse flag\n * @returns Promise that resolves when deletion is complete\n * @example\n * ```typescript\n * // Delete a file\n * await driveDelete('694f5013226de007be94fcc0');\n * \n * // Delete a folder recursively (default behavior)\n * await driveDelete(folderId, { recurse: true });\n * \n * // Delete only if folder is empty\n * await driveDelete(folderId, { recurse: false }); // Throws error if folder has children\n * \n * // Delete using database document\n * const drive = await Drive.findById(fileId);\n * await driveDelete(drive);\n * ```\n */\nexport const driveDelete = async (\n source: string | IDatabaseDriveDocument | TDatabaseDrive,\n options?: { recurse?: boolean }\n): Promise<void> => {\n const { recurse = true } = options || {};\n\n let drive: IDatabaseDriveDocument;\n let driveId: string;\n\n // If source is a string (ID), fetch from database\n if (typeof source === 'string') {\n const doc = await Drive.findById(source);\n if (!doc) throw new Error(`File not found: ${source}`);\n drive = doc;\n driveId = source;\n } else if ('toClient' in source) {\n // Already an IDatabaseDriveDocument (Mongoose document)\n drive = source;\n driveId = String(drive._id);\n } else {\n // TDatabaseDrive object (plain object from API)\n const doc = await Drive.findById(source.id);\n if (!doc) throw new Error(`File not found: ${source.id}`);\n drive = doc;\n driveId = source.id;\n }\n\n // If it's a folder and recurse is false, check for children\n if (drive.information.type === 'FOLDER' && !recurse) {\n const owner = drive.owner as Record<string, unknown> | null;\n const childCount = await Drive.countDocuments({\n owner,\n parentId: driveId,\n trashedAt: null,\n });\n\n if (childCount > 0) {\n throw new Error(`Cannot delete folder: it contains ${childCount} item(s). Use recurse: true to delete folder and all its contents.`);\n }\n }\n\n // Determine provider based on drive's provider type\n const provider = drive.provider?.type === 'GOOGLE' ? GoogleDriveProvider : LocalStorageProvider;\n const accountId = drive.storageAccountId?.toString();\n const owner = drive.owner as Record<string, unknown> | null;\n\n // Use provider's delete method to permanently delete the file/folder\n // Note: The provider's delete method already handles recursive deletion\n await provider.delete([driveId], owner, accountId);\n};\n\n/**\n * Resolve a folder path to a folder ID, creating folders recursively if they don't exist.\n * @param folderPath - Path like 'images/2024/january' or '/images/2024'\n * @param owner - Owner key for the folders\n * @param accountId - Storage account ID\n * @returns Promise with the resolved folder ID\n * @example\n * ```typescript\n * const folderId = await resolveFolderByPath('assets/images/avatars', { userId: '123' });\n * ```\n */\nexport const resolveFolderByPath = async (\n folderPath: string,\n owner: Record<string, unknown> | null,\n accountId?: string\n): Promise<string> => {\n // Normalize path: remove leading/trailing slashes, split by /\n const normalizedPath = folderPath.replace(/^\\/+|\\/+$/g, '');\n if (!normalizedPath) {\n throw new Error('Folder path cannot be empty');\n }\n\n const segments = normalizedPath.split('/').filter(s => s.length > 0);\n if (segments.length === 0) {\n throw new Error('Invalid folder path');\n }\n\n // Determine provider\n let providerName: 'LOCAL' | 'GOOGLE' = 'LOCAL';\n if (accountId && accountId !== 'LOCAL') {\n const account = await Drive.db.model('StorageAccount').findOne({ _id: accountId, owner });\n if (!account) {\n throw new Error('Invalid Storage Account');\n }\n if (account.metadata.provider === 'GOOGLE') {\n providerName = 'GOOGLE';\n }\n }\n\n let currentParentId: string | null = null;\n\n // Traverse/create each segment of the path\n for (const segmentName of segments) {\n // Look for existing folder with this name under current parent\n const existingFolder: IDatabaseDriveDocument | null = await Drive.findOne({\n owner,\n 'provider.type': providerName,\n storageAccountId: accountId || null,\n parentId: currentParentId,\n name: segmentName,\n 'information.type': 'FOLDER',\n trashedAt: null,\n });\n\n if (existingFolder) {\n // Folder exists, move to next level\n currentParentId = String(existingFolder._id);\n } else {\n // Create the folder\n const provider = providerName === 'GOOGLE' ? GoogleDriveProvider : LocalStorageProvider;\n const newFolder = await provider.createFolder(segmentName, currentParentId, owner, accountId);\n currentParentId = newFolder.id;\n }\n }\n\n return currentParentId!;\n};\n\n/**\n * Upload a file to the drive system from a file path or readable stream.\n * @param source - File path (string) or Readable stream\n * @param key - Owner key (must match the authenticated user's key)\n * @param options - Upload options including name, folder (id or path), accountId, mime, and enforce flag\n * @returns Promise with the created drive file object\n * @example\n * ```typescript\n * // Upload to specific folder by ID\n * const file = await driveUpload('/tmp/photo.jpg', { userId: '123' }, {\n * name: 'photo.jpg',\n * folder: { id: 'folderId' },\n * enforce: false\n * });\n * \n * // Upload to folder by path (creates folders if not exist)\n * const file = await driveUpload('/tmp/photo.jpg', { userId: '123' }, {\n * name: 'photo.jpg',\n * folder: { path: 'images/2024/january' }\n * });\n * \n * // Upload from stream with custom MIME type\n * const stream = fs.createReadStream('/tmp/video.mp4');\n * const file = await driveUpload(stream, { userId: '123' }, {\n * name: 'video.mp4',\n * mime: 'video/mp4',\n * enforce: true // Skip quota check\n * });\n * \n * // Upload from Buffer with MIME type\n * const buffer = Buffer.from('data');\n * const file = await driveUpload(buffer, { userId: '123' }, {\n * name: 'data.bin',\n * mime: 'application/octet-stream'\n * });\n * ```\n */\nexport const driveUpload = async (\n source: string | Readable | Buffer,\n key: Record<string, unknown> | null,\n options: {\n name: string;\n folder?: { id: string } | { path: string };\n /** @deprecated Use folder.id instead */\n parentId?: string | null;\n accountId?: string;\n mime?: string;\n enforce?: boolean;\n }\n): Promise<TDriveFile> => {\n const config = getDriveConfig();\n\n // Determine provider based on accountId\n let provider: typeof LocalStorageProvider | typeof GoogleDriveProvider = LocalStorageProvider;\n const accountId: string | undefined = options.accountId;\n\n if (accountId && accountId !== 'LOCAL') {\n // Validate account belongs to owner\n const account = await Drive.db.model('StorageAccount').findOne({ _id: accountId, owner: key });\n if (!account) {\n throw new Error('Invalid Storage Account');\n }\n if (account.metadata.provider === 'GOOGLE') {\n provider = GoogleDriveProvider;\n }\n }\n\n // Create temporary file if source is a stream or buffer\n let tempFilePath: string | null = null;\n let sourceFilePath: string;\n let fileSize: number;\n\n if (typeof source === 'string') {\n // Source is a file path\n if (!fs.existsSync(source)) {\n throw new Error(`Source file not found: ${source}`);\n }\n sourceFilePath = source;\n const stats = fs.statSync(source);\n fileSize = stats.size;\n } else if (Buffer.isBuffer(source)) {\n // Source is a Buffer\n const tempDir = path.join(os.tmpdir(), 'next-drive-uploads');\n if (!fs.existsSync(tempDir)) {\n fs.mkdirSync(tempDir, { recursive: true });\n }\n\n tempFilePath = path.join(tempDir, `upload-${crypto.randomUUID()}.tmp`);\n fs.writeFileSync(tempFilePath, source);\n\n sourceFilePath = tempFilePath;\n fileSize = source.length;\n } else {\n // Source is a Readable stream\n const tempDir = path.join(os.tmpdir(), 'next-drive-uploads');\n if (!fs.existsSync(tempDir)) {\n fs.mkdirSync(tempDir, { recursive: true });\n }\n\n tempFilePath = path.join(tempDir, `upload-${crypto.randomUUID()}.tmp`);\n const writeStream = fs.createWriteStream(tempFilePath);\n\n await new Promise<void>((resolve, reject) => {\n source.pipe(writeStream);\n writeStream.on('finish', resolve);\n writeStream.on('error', reject);\n source.on('error', reject);\n });\n\n sourceFilePath = tempFilePath;\n const stats = fs.statSync(tempFilePath);\n fileSize = stats.size;\n }\n\n try {\n // Detect MIME type from options or file extension\n let mimeType: string;\n\n if (options.mime) {\n // Use provided MIME type\n mimeType = options.mime;\n } else {\n // Auto-detect from file extension\n const ext = path.extname(options.name).toLowerCase();\n const mimeTypes: Record<string, string> = {\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.png': 'image/png',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.svg': 'image/svg+xml',\n '.mp4': 'video/mp4',\n '.mov': 'video/quicktime',\n '.avi': 'video/x-msvideo',\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 '.txt': 'text/plain',\n '.json': 'application/json',\n '.zip': 'application/zip',\n };\n mimeType = mimeTypes[ext] || 'application/octet-stream';\n }\n\n // Validate MIME type only if security config exists\n if (config.security && !validateMimeType(mimeType, config.security.allowedMimeTypes)) {\n throw new Error(`File type ${mimeType} not allowed`);\n }\n\n // Validate file size only if security config exists\n if (config.security && fileSize > config.security.maxUploadSizeInBytes) {\n throw new Error(`File size ${fileSize} exceeds maximum allowed size ${config.security.maxUploadSizeInBytes}`);\n }\n\n // Quota Check (skip in ROOT mode or if enforce is true)\n const isRootMode = config.mode === 'ROOT';\n if (!options.enforce && !isRootMode) {\n const quota = await provider.getQuota(key, accountId, undefined);\n if (quota.usedInBytes + fileSize > quota.quotaInBytes) {\n throw new Error('Storage quota exceeded');\n }\n }\n\n // Resolve folder ID from folder.path, folder.id, or legacy parentId\n let resolvedParentId: string | null = null;\n\n if (options.folder && 'path' in options.folder) {\n // Create folders recursively if needed\n resolvedParentId = await resolveFolderByPath(options.folder.path, key, accountId);\n } else if (options.folder && 'id' in options.folder && options.folder.id !== 'root') {\n resolvedParentId = options.folder.id;\n } else if (options.parentId && options.parentId !== 'root') {\n // Legacy support\n resolvedParentId = options.parentId;\n }\n\n // Create Drive Document\n const drive = new Drive({\n owner: key,\n storageAccountId: accountId || null,\n provider: { type: provider.name },\n name: options.name,\n parentId: resolvedParentId,\n order: await getNextOrderValue(key),\n information: { type: 'FILE', sizeInBytes: fileSize, mime: mimeType, path: '' },\n status: 'UPLOADING',\n });\n\n // Set initial path for LOCAL provider\n if (provider.name === 'LOCAL' && drive.information.type === 'FILE') {\n drive.information.path = path.join('file', String(drive._id), 'data.bin');\n }\n\n await drive.save();\n\n // Upload file through provider\n try {\n const item = await provider.uploadFile(drive, sourceFilePath, accountId);\n // Return simplified TDriveFile format for public API\n return {\n id: item.id,\n file: {\n name: item.name,\n mime: item.information.type === 'FILE' ? item.information.mime : 'application/x-folder',\n size: item.information.type === 'FILE' ? item.information.sizeInBytes : 0,\n },\n };\n } catch (err) {\n // Upload failed, cleanup DB record\n await Drive.deleteOne({ _id: drive._id });\n throw err;\n }\n } finally {\n // Cleanup temporary file if created from stream\n if (tempFilePath && fs.existsSync(tempFilePath)) {\n fs.rmSync(tempFilePath, { force: true });\n }\n }\n};\n","// ** Server Entry Point\nimport type { NextApiRequest, NextApiResponse } from 'next';\nimport formidable from 'formidable';\nimport path from 'path';\nimport fs from 'fs';\nimport os from 'os';\nimport crypto from 'crypto';\nimport { z } from 'zod';\n\nimport { getDriveConfig, getDriveInformation, driveConfiguration } from '@/server/config';\nimport Drive from '@/server/database/mongoose/schema/drive';\nimport StorageAccount from '@/server/database/mongoose/schema/storage/account';\nimport { validateMimeType, getImageSettings } from '@/server/utils';\nimport sharp from 'sharp';\nimport * as schemas from '@/server/zod/schemas';\nimport { getSafeErrorMessage, sanitizeContentDispositionFilename } from '@/server/security/cryptoUtils';\nimport type { TDatabaseDrive } from '@/types/server';\n\n// ** Providers\nimport { LocalStorageProvider } from '@/server/providers/local';\nimport { GoogleDriveProvider } from '@/server/providers/google';\nimport type { TStorageProvider } from '@/types/server/storage';\nimport { google } from 'googleapis';\n\n// ** Helper to get Provider\nconst getProvider = async (req: NextApiRequest, owner: Record<string, unknown> | null): Promise<{ provider: TStorageProvider; accountId?: string }> => {\n // Check header for account ID\n const accountId = req.headers['x-drive-account'] as string;\n\n if (!accountId || accountId === 'LOCAL') {\n return { provider: LocalStorageProvider };\n }\n\n // Validate account belongs to owner\n const account = await StorageAccount.findOne({ _id: accountId, owner });\n if (!account) {\n throw new Error('Invalid Storage Account');\n }\n\n if (account.metadata.provider === 'GOOGLE') return { provider: GoogleDriveProvider, accountId: account._id.toString() };\n\n // Fallback\n return { provider: LocalStorageProvider };\n};\n\n// ** Helper to apply CORS headers\nconst applyCorsHeaders = (req: NextApiRequest, res: NextApiResponse, config: ReturnType<typeof getDriveConfig>): boolean => {\n const cors = config.cors;\n if (!cors?.enabled) return false;\n\n const origin = req.headers.origin;\n const allowedOrigins = cors.origins ?? '*';\n const methods = cors.methods ?? ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'];\n const allowedHeaders = cors.allowedHeaders ?? ['Content-Type', 'Authorization', 'X-Drive-Account'];\n const exposedHeaders = cors.exposedHeaders ?? ['Content-Length', 'Content-Type', 'Content-Disposition'];\n const credentials = cors.credentials ?? false;\n const maxAge = cors.maxAge ?? 86400; // 24 hours default\n\n // Determine if origin is allowed\n let allowOrigin: string | null = null;\n if (origin) {\n if (allowedOrigins === '*') {\n allowOrigin = origin;\n } else if (Array.isArray(allowedOrigins)) {\n if (allowedOrigins.includes(origin)) {\n allowOrigin = origin;\n }\n } else if (allowedOrigins === origin) {\n allowOrigin = origin;\n }\n } else if (allowedOrigins === '*') {\n // No origin header (same-origin request), allow if wildcard\n allowOrigin = '*';\n }\n\n // If origin not allowed, don't set CORS headers (request will fail CORS check)\n if (!allowOrigin) {\n if (req.method === 'OPTIONS') {\n res.status(403).end();\n return true;\n }\n return false;\n }\n\n res.setHeader('Access-Control-Allow-Origin', allowOrigin);\n res.setHeader('Access-Control-Allow-Methods', methods.join(', '));\n res.setHeader('Access-Control-Allow-Headers', allowedHeaders.join(', '));\n res.setHeader('Access-Control-Expose-Headers', exposedHeaders.join(', '));\n res.setHeader('Access-Control-Max-Age', maxAge.toString());\n\n if (credentials) {\n res.setHeader('Access-Control-Allow-Credentials', 'true');\n }\n\n // Handle preflight\n if (req.method === 'OPTIONS') {\n res.status(204).end();\n return true;\n }\n\n return false;\n};\n\n// ** Main API handler for all drive operations\nexport const driveAPIHandler = async (req: NextApiRequest, res: NextApiResponse): Promise<void> => {\n // ** Auto-detect OAuth callback when code & state are present but no action\n const action = (req.query.action as string) || (req.query.code && req.query.state ? 'callback' : undefined);\n\n // ** Ensure Config\n let config: ReturnType<typeof getDriveConfig>;\n try {\n config = getDriveConfig();\n } catch (error) {\n console.error('[next-drive] Configuration error:', error);\n res.status(500).json({ status: 500, message: 'Failed to initialize drive configuration' });\n return;\n }\n\n // ** Apply CORS headers\n const isPreflightHandled = applyCorsHeaders(req, res, config);\n if (isPreflightHandled) return;\n\n if (!action) {\n res.status(400).json({ status: 400, message: 'Missing action query parameter' });\n return;\n }\n\n // ** Public Actions (No Auth Required) - Handle serve and thumbnail before authentication\n if (action === 'serve' || action === 'thumbnail') {\n try {\n const { id, token } = req.query;\n if (!id || typeof id !== 'string') {\n return res.status(400).json({ status: 400, message: 'Missing or invalid file ID' });\n }\n\n const drive = await Drive.findById(id);\n if (!drive) return res.status(404).json({ status: 404, message: 'File not found' });\n\n // Verify signed URL token if enabled\n if (config.security?.signedUrls?.enabled) {\n if (!token || typeof token !== 'string') {\n return res.status(401).json({ status: 401, message: 'Missing or invalid token' });\n }\n\n try {\n const decoded = Buffer.from(token, 'base64url').toString();\n const [expiryStr, signature] = decoded.split(':');\n const expiry = parseInt(expiryStr, 10);\n\n if (Date.now() / 1000 > expiry) {\n return res.status(401).json({ status: 401, message: 'Token expired' });\n }\n\n const { secret } = config.security.signedUrls;\n const expectedSignature = crypto.createHmac('sha256', secret)\n .update(`${id}:${expiry}`)\n .digest('hex');\n\n if (signature !== expectedSignature) {\n return res.status(401).json({ status: 401, message: 'Invalid token' });\n }\n } catch (err) {\n return res.status(401).json({ status: 401, message: 'Invalid token format' });\n }\n }\n\n // Resolve provider\n const itemProvider = drive.provider?.type === 'GOOGLE' ? GoogleDriveProvider : LocalStorageProvider;\n const itemAccountId = drive.storageAccountId ? drive.storageAccountId.toString() : undefined;\n\n if (action === 'thumbnail') {\n const stream = await itemProvider.getThumbnail(drive, itemAccountId);\n res.setHeader('Content-Type', 'image/webp');\n if (config.cors?.enabled) {\n res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');\n }\n stream.pipe(res);\n return;\n }\n\n if (action === 'serve') {\n const { stream, mime, size: fileSize } = await itemProvider.openStream(drive, itemAccountId);\n const safeFilename = sanitizeContentDispositionFilename(drive.name);\n\n // ** Image Transformation Parameters\n const format = req.query.format as string;\n const quality = req.query.quality as string;\n const display = req.query.display as string;\n const sizePreset = req.query.size as string;\n\n const isImage = mime.startsWith('image/');\n const shouldTransform = isImage && (format || quality || display || sizePreset);\n\n\n res.setHeader('Content-Disposition', `inline; filename=\"${safeFilename}\"`);\n\n if (config.cors?.enabled) {\n res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');\n }\n\n if (shouldTransform) {\n try {\n // Get all dynamic settings based on file size, quality, display, and size\n const settings = getImageSettings(fileSize, quality, display, sizePreset);\n\n // Determine target format - ensure we handle common aliases\n let targetFormat = format || mime.split('/')[1];\n if (targetFormat === 'jpg') targetFormat = 'jpeg';\n // Handle cases like 'svg+xml' -> just use jpeg/webp for output\n if (!['jpeg', 'png', 'webp', 'avif'].includes(targetFormat)) {\n targetFormat = format || 'webp'; // Default to format param or webp\n }\n\n // ** Cache Logic - Include all parameters in cache key\n const cacheDir = path.join(config.storage.path, 'file', drive._id.toString(), 'cache');\n const cacheKey = [\n 'opt',\n `q${settings.quality}`,\n `e${settings.effort}`,\n settings.width ? `${settings.width}x${settings.height}` : 'orig',\n targetFormat\n ].join('_');\n const cachePath = path.join(cacheDir, `${cacheKey}.bin`);\n\n // 1. Check Cache\n if (fs.existsSync(cachePath)) {\n const cacheStat = fs.statSync(cachePath);\n res.setHeader('Content-Type', `image/${targetFormat}`);\n res.setHeader('Content-Length', cacheStat.size);\n res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');\n if (config.cors?.enabled) {\n res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');\n }\n // Close original stream as we don't need it\n if ('destroy' in stream) (stream as any).destroy();\n\n fs.createReadStream(cachePath).pipe(res);\n return;\n }\n\n // 2. Transform & Cache\n if (!fs.existsSync(cacheDir)) fs.mkdirSync(cacheDir, { recursive: true });\n\n // Create sharp pipeline with input stream\n let pipeline = sharp();\n\n // Apply resize if dimensions specified\n if (settings.width && settings.height) {\n pipeline = pipeline.resize(settings.width, settings.height, {\n fit: 'inside',\n withoutEnlargement: true\n });\n }\n\n // Format & Quality - all settings are dynamic\n if (targetFormat === 'jpeg') {\n pipeline = pipeline.jpeg({ quality: settings.quality, mozjpeg: true });\n res.setHeader('Content-Type', 'image/jpeg');\n } else if (targetFormat === 'png') {\n pipeline = pipeline.png({ compressionLevel: settings.pngCompression, adaptiveFiltering: true });\n res.setHeader('Content-Type', 'image/png');\n } else if (targetFormat === 'webp') {\n // WebP effort is 0-6, not 0-9\n const webpEffort = Math.min(settings.effort, 6);\n pipeline = pipeline.webp({ quality: settings.quality, effort: webpEffort });\n res.setHeader('Content-Type', 'image/webp');\n } else if (targetFormat === 'avif') {\n // AVIF effort is 0-9\n pipeline = pipeline.avif({ quality: settings.quality, effort: settings.effort });\n res.setHeader('Content-Type', 'image/avif');\n }\n\n res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');\n\n // Handle pipeline errors\n pipeline.on('error', (err) => {\n console.error('[next-drive] Pipeline error:', err);\n });\n\n // Pipe stream -> pipeline\n stream.pipe(pipeline);\n\n // Fork 1: Cache (Async)\n pipeline.clone()\n .toFile(cachePath)\n .catch(e => console.error('[next-drive] Cache write failed:', e));\n\n // Fork 2: Response\n pipeline.clone().pipe(res);\n return;\n } catch (e) {\n console.error('[next-drive] Image transformation failed:', e);\n // Fallback to raw serve handled below\n }\n }\n\n // Default Raw Serve\n res.setHeader('Content-Type', mime);\n if (fileSize) res.setHeader('Content-Length', fileSize);\n stream.pipe(res);\n return;\n }\n } catch (error) {\n console.error(`[next-drive] Error in ${action}:`, error);\n return res.status(500).json({\n status: 500,\n message: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n }\n\n try {\n const mode = config.mode || 'NORMAL';\n const information = await getDriveInformation(req);\n const { key: owner } = information;\n const STORAGE_PATH = config.storage.path;\n\n // ** In ROOT mode, owner can be null and we list all files without filtering\n const isRootMode = mode === 'ROOT';\n\n // ** Information Action (No Auth Needed)\n if (action === 'information') {\n const { clientId, clientSecret, redirectUri } = config.storage?.google || {};\n const googleConfigured = !!(clientId && clientSecret && redirectUri);\n\n return res.status(200).json({\n status: 200,\n message: 'Information retrieved',\n data: {\n providers: {\n google: googleConfigured,\n },\n mode: mode,\n },\n });\n }\n\n // ** OAuth & Account Actions (No Provider Resolution Needed)\n if (['getAuthUrl', 'callback', 'listAccounts', 'removeAccount'].includes(action)) {\n switch (action) {\n case 'getAuthUrl': {\n const { provider } = req.query;\n if (provider === 'GOOGLE') {\n const { clientId, clientSecret, redirectUri } = config.storage?.google || {};\n if (!clientId || !clientSecret || !redirectUri) return res.status(500).json({ status: 500, message: 'Google not configured' });\n\n // Append action=callback to redirectUri for explicit routing\n const callbackUri = new URL(redirectUri);\n callbackUri.searchParams.set('action', 'callback');\n const oAuth2Client = new google.auth.OAuth2(clientId, clientSecret, callbackUri.toString());\n // Generate state to identify user\n // For security, should sign state. Simple base64 for now.\n const state = Buffer.from(JSON.stringify({ owner })).toString('base64');\n const url = oAuth2Client.generateAuthUrl({\n access_type: 'offline',\n scope: ['https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/userinfo.email'],\n state,\n prompt: 'consent', // force refresh token\n });\n return res.status(200).json({ status: 200, message: 'Auth URL generated', data: { url } });\n }\n return res.status(400).json({ status: 400, message: 'Unknown provider' });\n }\n case 'callback': {\n const { code, state } = req.query;\n if (!code) return res.status(400).json({ status: 400, message: 'Missing code' });\n\n // Verify state if possible, though 'owner' is derived from session/request usually.\n // Assuming 'owner' from getDriveInformation is the source of truth for current session.\n\n const { clientId, clientSecret, redirectUri } = config.storage?.google || {};\n if (!clientId || !clientSecret || !redirectUri) return res.status(500).json({ status: 500, message: 'Google not configured' });\n // Must use the same redirect URI that was used in getAuthUrl (with action=callback)\n const callbackUri = new URL(redirectUri);\n callbackUri.searchParams.set('action', 'callback');\n const oAuth2Client = new google.auth.OAuth2(clientId, clientSecret, callbackUri.toString());\n\n const { tokens } = await oAuth2Client.getToken(code as string);\n oAuth2Client.setCredentials(tokens);\n\n // Get User Info\n const oauth2 = google.oauth2({ version: 'v2', auth: oAuth2Client });\n const userInfo = await oauth2.userinfo.get();\n\n // ** Save Account\n const existing = await StorageAccount.findOne({ owner, 'metadata.google.email': userInfo.data.email, 'metadata.provider': 'GOOGLE' });\n if (existing) {\n existing.metadata.google.credentials = tokens as Record<string, unknown>;\n existing.markModified('metadata');\n await existing.save();\n } else {\n const newAccount = new StorageAccount({\n owner,\n name: userInfo.data.name || 'Google Drive',\n metadata: {\n provider: 'GOOGLE',\n google: {\n email: userInfo.data.email,\n credentials: tokens as Record<string, unknown>,\n },\n },\n });\n await newAccount.save();\n }\n\n // Helper: Return HTML that notifies parent and closes tab/popup\n // Uses both postMessage (for popups) and localStorage (for new tabs in fullscreen macOS)\n res.setHeader('Content-Type', 'text/html');\n return res.send(`<!DOCTYPE html>\n<html>\n<head><title>Authentication Complete</title></head>\n<body>\n<p>Authentication successful! This window will close automatically.</p>\n<script>\n(function() {\n\t// Method 1: postMessage for popup windows\n\tif (window.opener) {\n\t\ttry {\n\t\t\twindow.opener.postMessage('oauth-success', '*');\n\t\t} catch (e) {}\n\t}\n\t// Method 2: localStorage event for new tabs (macOS fullscreen mode)\n\ttry {\n\t\tlocalStorage.setItem('next-drive-oauth-success', Date.now().toString());\n\t\tlocalStorage.removeItem('next-drive-oauth-success');\n\t} catch (e) {}\n\t// Close the window/tab\n\twindow.close();\n\t// Fallback: If window.close() doesn't work (some browsers block it),\n\t// show a message to manually close\n\tsetTimeout(function() {\n\t\tdocument.body.innerHTML = '<p style=\"font-family: system-ui; text-align: center; margin-top: 50px;\">Authentication successful!<br>You can close this tab now.</p>';\n\t}, 500);\n})();\n</script>\n</body>\n</html>`);\n }\n case 'listAccounts': {\n const accounts = await StorageAccount.find({ owner });\n return res.status(200).json({\n status: 200,\n data: {\n accounts: accounts.map(a => ({\n id: a._id.toString(),\n name: a.name,\n email: a.metadata.google?.email || '',\n provider: a.metadata.provider,\n })),\n },\n });\n }\n case 'removeAccount': {\n const { id } = req.query;\n const account = await StorageAccount.findOne({ _id: id, owner });\n if (!account) return res.status(404).json({ status: 404, message: 'Account not found' });\n\n // Revoke Token if Google\n if (account.metadata.provider === 'GOOGLE') {\n try {\n await GoogleDriveProvider.revokeToken(owner, account._id.toString());\n } catch (e) {\n console.error('Failed to revoke Google token:', e);\n // Proceed to delete anyway\n }\n }\n\n await StorageAccount.deleteOne({ _id: id, owner });\n await Drive.deleteMany({ owner, storageAccountId: id });\n return res.status(200).json({ status: 200, message: 'Account removed' });\n }\n }\n }\n\n // ** Provider Actions\n const { provider, accountId } = await getProvider(req, owner);\n\n switch (action) {\n // ** 1. LIST **\n case 'list': {\n if (req.method !== 'GET') return res.status(405).json({ status: 405, message: 'Only GET allowed' });\n const listQuery = schemas.listQuerySchema.safeParse(req.query);\n if (!listQuery.success) return res.status(400).json({ status: 400, message: 'Invalid parameters' });\n\n const { folderId, limit, afterId } = listQuery.data;\n\n // Sync Trigger: If viewing a folder, try to sync it first if provider supports it\n // Only sync if we are browsing a specific folder or root\n try {\n await provider.sync(folderId || 'root', owner, accountId);\n } catch (e) {\n console.error('Sync failed', e);\n // Continue to list what we have in DB\n }\n\n // Query DB - In ROOT mode, don't filter by owner\n const query: Record<string, unknown> = {\n 'provider.type': provider.name,\n storageAccountId: accountId || null,\n parentId: folderId === 'root' || !folderId ? null : folderId,\n trashedAt: null,\n };\n\n // Only filter by owner in NORMAL mode\n if (!isRootMode) {\n query.owner = owner;\n }\n\n if (afterId) query._id = { $lt: afterId }; // Pagination\n\n const items = await Drive.find(query, {}, { sort: { order: 1, _id: -1 }, limit });\n const plainItems = await Promise.all(items.map(item => item.toClient()));\n\n res.status(200).json({ status: 200, message: 'Items retrieved', data: { items: plainItems, hasMore: items.length === limit } });\n return;\n }\n\n // ** 2. SEARCH **\n case 'search': {\n const searchData = schemas.searchQuerySchema.safeParse(req.query);\n if (!searchData.success) return res.status(400).json({ status: 400, message: 'Invalid params' });\n const { q, folderId, limit, trashed } = searchData.data;\n\n // Sync Search\n if (!trashed) {\n try {\n await provider.search(q, owner, accountId);\n } catch (e) {\n console.error('Search sync failed', e);\n }\n }\n\n // Query DB - In ROOT mode, don't filter by owner\n const query: Record<string, unknown> = {\n 'provider.type': provider.name,\n storageAccountId: accountId || null,\n trashedAt: trashed ? { $ne: null } : null,\n name: { $regex: q, $options: 'i' },\n };\n\n // Only filter by owner in NORMAL mode\n if (!isRootMode) {\n query.owner = owner;\n }\n\n if (folderId && folderId !== 'root') query.parentId = folderId;\n\n const items = await Drive.find(query, {}, { limit, sort: { createdAt: -1 } });\n const plainItems = await Promise.all(items.map(i => i.toClient()));\n\n return res.status(200).json({ status: 200, message: 'Results', data: { items: plainItems } });\n }\n\n // ** 3. UPLOAD **\n case 'upload': {\n if (req.method !== 'POST') return res.status(405).json({ status: 405, message: 'Only POST allowed' });\n const systemTmpDir = path.join(os.tmpdir(), 'next-drive-uploads');\n if (!fs.existsSync(systemTmpDir)) fs.mkdirSync(systemTmpDir, { recursive: true });\n const form = formidable({\n multiples: false,\n maxFileSize: (config.security?.maxUploadSizeInBytes ?? 1024 * 1024 * 1024) * 2,\n uploadDir: systemTmpDir,\n keepExtensions: true,\n });\n\n const [fields, files] = await new Promise<[formidable.Fields, formidable.Files]>((resolve, reject) => {\n form.parse(req, (err, fields, files) => {\n if (err) reject(err);\n else resolve([fields, files]);\n });\n });\n\n const cleanupTempFiles = (files: formidable.Files) => {\n Object.values(files)\n .flat()\n .forEach(file => {\n if (file && fs.existsSync(file.filepath)) fs.rmSync(file.filepath, { force: true });\n });\n };\n\n const getString = (f: string[] | string | undefined) => (Array.isArray(f) ? f[0] : f || '');\n const getInt = (f: string[] | string | undefined) => parseInt(getString(f) || '0', 10);\n\n const uploadData = schemas.uploadChunkSchema.safeParse({\n chunkIndex: getInt(fields.chunkIndex),\n totalChunks: getInt(fields.totalChunks),\n driveId: getString(fields.driveId) || undefined,\n fileName: getString(fields.fileName),\n fileSize: getInt(fields.fileSize),\n fileType: getString(fields.fileType),\n folderId: getString(fields.folderId) || undefined,\n });\n\n if (!uploadData.success) {\n cleanupTempFiles(files);\n return res.status(400).json({ status: 400, message: uploadData.error.errors[0].message });\n }\n\n const { chunkIndex, totalChunks, driveId, fileName, fileSize: fileSizeInBytes, fileType, folderId } = uploadData.data;\n\n let currentUploadId = driveId;\n\n // Ensure temp directory for this upload exists (uses system tmp for auto-cleanup)\n const tempBaseDir = path.join(os.tmpdir(), 'next-drive-uploads');\n\n if (!currentUploadId) {\n // Start of new upload (usually Chunk 0, but could be adapted)\n if (chunkIndex !== 0) return res.status(400).json({ message: 'Missing upload ID for non-zero chunk' });\n\n if (fileType && config.security) {\n if (!validateMimeType(fileType, config.security.allowedMimeTypes)) {\n cleanupTempFiles(files);\n return res.status(400).json({ status: 400, message: `File type ${fileType} not allowed` });\n }\n }\n\n // Quota Check - Skip in ROOT mode\n if (!isRootMode) {\n const quota = await provider.getQuota(owner, accountId, information.storage.quotaInBytes);\n if (quota.usedInBytes + fileSizeInBytes > quota.quotaInBytes) {\n cleanupTempFiles(files);\n return res.status(413).json({ status: 413, message: 'Storage quota exceeded' });\n }\n }\n\n // Generate Temp ID (Stateless)\n currentUploadId = crypto.randomUUID();\n const uploadDir = path.join(tempBaseDir, currentUploadId);\n fs.mkdirSync(uploadDir, { recursive: true });\n\n // Save Metadata\n const metadata = {\n owner,\n accountId,\n providerName: provider.name,\n name: fileName,\n parentId: folderId === 'root' || !folderId ? null : folderId,\n fileSize: fileSizeInBytes,\n mimeType: fileType,\n totalChunks,\n };\n fs.writeFileSync(path.join(uploadDir, 'metadata.json'), JSON.stringify(metadata));\n }\n\n // Handle Chunk Save\n if (currentUploadId) {\n const uploadDir = path.join(tempBaseDir, currentUploadId);\n\n if (!fs.existsSync(uploadDir)) {\n cleanupTempFiles(files);\n // If dir missing, maybe upload expired or finished?\n return res.status(404).json({ status: 404, message: 'Upload session not found or expired' });\n }\n\n try {\n const chunkFile = Array.isArray(files.chunk) ? files.chunk[0] : files.chunk;\n if (!chunkFile) throw new Error('No chunk file received');\n\n // Save part file: part_0, part_1...\n const partPath = path.join(uploadDir, `part_${chunkIndex}`);\n\n // Move chunk to upload dir - handle cross-device case\n try {\n fs.renameSync(chunkFile.filepath, partPath);\n } catch (err: unknown) {\n if (err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'EXDEV') {\n fs.copyFileSync(chunkFile.filepath, partPath);\n fs.unlinkSync(chunkFile.filepath);\n } else {\n throw err;\n }\n }\n\n // Check Completion\n // We count files starting with 'part_'\n const uploadedParts = fs.readdirSync(uploadDir).filter(f => f.startsWith('part_'));\n\n // Merge if all parts present\n if (uploadedParts.length === totalChunks) {\n // 1. Read Metadata\n const metaPath = path.join(uploadDir, 'metadata.json');\n const meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));\n\n // 2. Merge Parts into final file\n const finalTempPath = path.join(uploadDir, 'final.bin');\n const writeStream = fs.createWriteStream(finalTempPath);\n\n // Track stream errors immediately\n let streamError: Error | null = null;\n writeStream.on('error', (err) => {\n streamError = err;\n });\n\n // Wait for stream to be ready\n await new Promise<void>((resolve, reject) => {\n writeStream.on('open', () => resolve());\n writeStream.once('error', reject);\n });\n\n // Write chunks with proper backpressure handling\n for (let i = 0; i < totalChunks; i++) {\n if (streamError) {\n writeStream.destroy();\n throw streamError;\n }\n const pPath = path.join(uploadDir, `part_${i}`);\n if (!fs.existsSync(pPath)) {\n writeStream.destroy();\n throw new Error(`Missing chunk part: ${i}`);\n }\n const data = fs.readFileSync(pPath);\n const canContinue = writeStream.write(data);\n\n // Handle backpressure - wait for drain if buffer is full\n if (!canContinue) {\n await new Promise<void>((resolve, reject) => {\n writeStream.once('drain', resolve);\n writeStream.once('error', reject);\n });\n }\n }\n\n // Wait for write stream to finish\n await new Promise<void>((resolve, reject) => {\n if (streamError) {\n reject(streamError);\n return;\n }\n writeStream.end();\n writeStream.on('finish', resolve);\n writeStream.once('error', reject);\n });\n\n // Verify final file exists\n if (!fs.existsSync(finalTempPath)) {\n throw new Error('Failed to create merged file');\n }\n\n // Verify file size matches expected\n const finalStats = fs.statSync(finalTempPath);\n if (finalStats.size !== meta.fileSize) {\n throw new Error(`File size mismatch: expected ${meta.fileSize}, got ${finalStats.size}`);\n }\n\n // 3. Create DB Record (Delayed)\n const drive = new Drive({\n owner: meta.owner,\n storageAccountId: meta.accountId || null,\n provider: { type: meta.providerName },\n name: meta.name,\n parentId: meta.parentId,\n order: 0,\n information: { type: 'FILE', sizeInBytes: meta.fileSize, mime: meta.mimeType, path: '' }, // path set by provider\n status: 'UPLOADING',\n currentChunk: totalChunks,\n totalChunks: totalChunks,\n });\n\n // Set initial path based on ID - providers will resolve final path/ID\n if (meta.providerName === 'LOCAL' && drive.information.type === 'FILE') {\n // Path is relative to storage.path - use new structure\n drive.information.path = path.join('file', String(drive._id), 'data.bin');\n }\n\n await drive.save();\n\n // 4. Provider Upload\n try {\n const item = await provider.uploadFile(drive, finalTempPath, meta.accountId);\n\n // Cleanup\n fs.rmSync(uploadDir, { recursive: true, force: true });\n\n const newQuota = await provider.getQuota(meta.owner, meta.accountId, information.storage.quotaInBytes);\n res.status(200).json({ status: 200, message: 'Upload complete', data: { type: 'UPLOAD_COMPLETE', driveId: String(drive._id), item }, statistic: { storage: newQuota } });\n } catch (err) {\n // Upload to provider failed\n await Drive.deleteOne({ _id: drive._id });\n throw err;\n }\n } else {\n // Chunk received, wait for others\n const newQuota = await provider.getQuota(owner, accountId, information.storage.quotaInBytes);\n // If this was chunk 0, we send UPLOAD_STARTED with the new ID\n if (chunkIndex === 0) {\n res.status(200).json({ status: 200, message: 'Upload started', data: { type: 'UPLOAD_STARTED', driveId: currentUploadId }, statistic: { storage: newQuota } });\n } else {\n res.status(200).json({ status: 200, message: 'Chunk received', data: { type: 'CHUNK_RECEIVED', driveId: currentUploadId, chunkIndex }, statistic: { storage: newQuota } });\n }\n }\n } catch (e) {\n cleanupTempFiles(files);\n // Don't delete entire dir on one chunk fail, might be retryable?\n // For now, if fatal error, maybe we should?\n // Let's just throw for now.\n throw e;\n }\n return;\n }\n\n // Should not happen if logic holds\n cleanupTempFiles(files);\n return res.status(400).json({ status: 400, message: 'Invalid upload request' });\n }\n\n // ** 4. CANCEL UPLOAD **\n case 'cancel': {\n const cancelData = schemas.cancelQuerySchema.safeParse(req.query);\n if (!cancelData.success) return res.status(400).json({ status: 400, message: 'Invalid ID' });\n const { id } = cancelData.data;\n\n // Try to clean up temp upload directory (in system tmp)\n const tempUploadDir = path.join(os.tmpdir(), 'next-drive-uploads', id);\n if (fs.existsSync(tempUploadDir)) {\n try {\n fs.rmSync(tempUploadDir, { recursive: true, force: true });\n } catch (e) {\n console.error('Failed to cleanup temp upload:', e);\n }\n }\n\n return res.status(200).json({ status: 200, message: 'Upload cancelled', data: null });\n }\n\n // ** 5. CREATE FOLDER **\n case 'createFolder': {\n const folderData = schemas.createFolderBodySchema.safeParse(req.body);\n if (!folderData.success) return res.status(400).json({ status: 400, message: folderData.error.errors[0].message });\n const { name, parentId } = folderData.data;\n\n const item = await provider.createFolder(name, parentId ?? null, owner, accountId);\n return res.status(201).json({ status: 201, message: 'Folder created', data: { item } });\n }\n\n // ** 5. DELETE **\n case 'delete': {\n const deleteData = schemas.deleteQuerySchema.safeParse(req.query);\n if (!deleteData.success) return res.status(400).json({ status: 400, message: 'Invalid ID' });\n // We use generic delete (trash)\n const { id } = deleteData.data;\n const drive = await Drive.findById(id);\n if (!drive) return res.status(404).json({ status: 404, message: 'Not found' });\n\n // Call Provider Trash\n const itemProvider = drive.provider?.type === 'GOOGLE' ? GoogleDriveProvider : LocalStorageProvider;\n const itemAccountId = drive.storageAccountId ? drive.storageAccountId.toString() : undefined;\n\n try {\n await itemProvider.trash([id], owner, itemAccountId);\n } catch (e) {\n console.error('Provider trash failed:', e);\n }\n\n drive.trashedAt = new Date();\n await drive.save();\n return res.status(200).json({ status: 200, message: 'Moved to trash', data: null });\n }\n\n // ** 6. HARD DELETE **\n case 'deletePermanent': {\n const deleteData = schemas.deleteQuerySchema.safeParse(req.query);\n if (!deleteData.success) return res.status(400).json({ status: 400, message: 'Invalid ID' });\n const { id } = deleteData.data;\n // Provider Delete\n await provider.delete([id], owner, accountId);\n const quota = await provider.getQuota(owner, accountId, information.storage.quotaInBytes);\n return res.status(200).json({ status: 200, message: 'Deleted', statistic: { storage: quota } });\n }\n\n // ** 7. QUOTA **\n case 'quota': {\n const quota = await provider.getQuota(owner, accountId, information.storage.quotaInBytes);\n return res.status(200).json({\n status: 200,\n message: 'Quota retrieved',\n data: { usedInBytes: quota.usedInBytes, totalInBytes: quota.quotaInBytes, availableInBytes: Math.max(0, quota.quotaInBytes - quota.usedInBytes), percentage: quota.quotaInBytes > 0 ? Math.round((quota.usedInBytes / quota.quotaInBytes) * 100) : 0 },\n statistic: { storage: quota },\n });\n }\n\n // ** 7B. TRASH **\n case 'trash': {\n // Try to sync trash first\n try {\n const { provider: trashProvider, accountId: trashAccountId } = await getProvider(req, owner);\n await trashProvider.syncTrash(owner, trashAccountId);\n } catch (e) {\n console.error('Trash sync failed', e);\n }\n\n // Return items that are in trash\n const query: Record<string, unknown> = {\n owner,\n 'provider.type': provider.name,\n storageAccountId: accountId || null,\n trashedAt: { $ne: null },\n };\n\n const items = await Drive.find(query, {}, { sort: { trashedAt: -1 } });\n const plainItems = await Promise.all(items.map(item => item.toClient()));\n\n return res.status(200).json({\n status: 200,\n message: 'Trash items',\n data: { items: plainItems, hasMore: false },\n });\n }\n\n // ** 7C. RESTORE **\n case 'restore': {\n const restoreData = schemas.deleteQuerySchema.safeParse(req.query);\n if (!restoreData.success) return res.status(400).json({ status: 400, message: 'Invalid ID' });\n const { id } = restoreData.data;\n const drive = await Drive.findById(id);\n if (!drive) return res.status(404).json({ status: 404, message: 'Not found' });\n\n // Check if parent folder is trashed - if so, move to root\n let targetParentId = drive.parentId;\n if (targetParentId) {\n const parent = await Drive.findById(targetParentId);\n if (parent?.trashedAt) {\n targetParentId = null; // Move to root instead\n }\n }\n\n // Call Provider Untrash\n const itemProvider = drive.provider?.type === 'GOOGLE' ? GoogleDriveProvider : LocalStorageProvider;\n const itemAccountId = drive.storageAccountId ? drive.storageAccountId.toString() : undefined;\n\n try {\n await itemProvider.untrash([id], owner, itemAccountId);\n // If moving to root due to trashed parent, update location in provider\n if (targetParentId !== drive.parentId) {\n await itemProvider.move(id, targetParentId?.toString() ?? null, owner, itemAccountId);\n }\n } catch (e) {\n console.error('Provider restore failed:', e);\n }\n\n // Restore item in database\n drive.trashedAt = null;\n drive.parentId = targetParentId;\n await drive.save();\n\n return res.status(200).json({\n status: 200,\n message: targetParentId === null && drive.parentId !== null ? 'Restored to root (parent folder was trashed)' : 'Restored',\n data: null,\n });\n }\n\n // ** 7D. MOVE **\n case 'move': {\n const moveData = schemas.moveBodySchema.safeParse(req.body);\n if (!moveData.success) return res.status(400).json({ status: 400, message: 'Invalid data' });\n const { ids, targetFolderId } = moveData.data;\n\n const items: TDatabaseDrive[] = [];\n // Target folder ID for provider (null for root)\n const effectiveTargetId = targetFolderId === 'root' || !targetFolderId ? null : targetFolderId;\n\n for (const id of ids) {\n try {\n const item = await provider.move(id, effectiveTargetId, owner, accountId);\n items.push(item);\n } catch (e) {\n console.error(`Failed to move item ${id}`, e);\n // Continue moving other items\n }\n }\n\n return res.status(200).json({ status: 200, message: 'Moved', data: { items } });\n }\n\n // ** 8. RENAME **\n case 'rename': {\n const renameData = schemas.renameBodySchema.safeParse({ id: req.query.id, ...req.body });\n if (!renameData.success) return res.status(400).json({ status: 400, message: 'Invalid data' });\n const { id, newName } = renameData.data;\n const item = await provider.rename(id, newName, owner, accountId);\n return res.status(200).json({ status: 200, message: 'Renamed', data: { item } });\n }\n\n // ** 9. THUMBNAIL **\n default:\n res.status(400).json({ status: 400, message: `Unknown action: ${action}` });\n }\n } catch (error: unknown) {\n console.error(`[next-drive] Error handling action ${action}:`, error);\n // FOR DEBUGGING: Return the actual error message\n res.status(500).json({ status: 500, message: error instanceof Error ? error.message : 'Unknown error' });\n }\n};\n\n// ** Exports\nexport { driveConfiguration, getDriveConfig, getDriveInformation };\nexport { driveGetUrl, driveReadFile, driveFilePath, driveUpload, driveDelete, driveList, driveInfo } from '@/server/controllers/drive';\nexport { driveFileSchemaZod } from '@/server/zod/schemas';\nexport { driveCreateUrl } from '@/client/utils';\nexport type { TDriveFile, TDriveInformation } from '@/types/client';\nexport type * from '@/types/server';\n"]}