@muhgholy/next-drive 1.4.2 → 1.6.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.
package/README.md CHANGED
@@ -82,6 +82,12 @@ export const drive = driveConfiguration({
82
82
  formats: ['webp', 'jpeg', 'png'],
83
83
  qualities: ['ultralow', 'low', 'medium', 'high', 'normal'],
84
84
  },
85
+ // Optional: Enable CORS for cross-origin requests
86
+ cors: {
87
+ enabled: true,
88
+ origins: ['https://example.com', 'https://app.example.com'],
89
+ credentials: true,
90
+ },
85
91
  information: async (req): Promise<TDriveConfigInformation> => {
86
92
  // Implement your auth verification here
87
93
  const auth = await verifyAuth(req);
@@ -162,6 +168,12 @@ export const drive = driveConfigurationExpress({
162
168
  expiresIn: 3600,
163
169
  },
164
170
  },
171
+ // Optional: Enable CORS for cross-origin requests
172
+ cors: {
173
+ enabled: true,
174
+ origins: ['https://example.com'],
175
+ credentials: true,
176
+ },
165
177
  apiUrl: '/api/drive',
166
178
  information: async (req): Promise<TDriveConfigInformation> => {
167
179
  // req is Express Request type
@@ -207,6 +219,22 @@ export default function RootLayout({ children }) {
207
219
  }
208
220
  ```
209
221
 
222
+ **Cross-Origin Setup:**
223
+
224
+ When your client runs on a different domain than the API, enable credentials:
225
+
226
+ ```typescript
227
+ // Enable cookies/auth headers for cross-origin requests
228
+ <DriveProvider
229
+ apiEndpoint="https://api.example.com/drive"
230
+ withCredentials={true}
231
+ >
232
+ {children}
233
+ </DriveProvider>
234
+ ```
235
+
236
+ > **Note**: Requires matching CORS configuration on the server with `credentials: true`.
237
+
210
238
  ### 4. Implement UI Components
211
239
 
212
240
  You can use the built-in `DriveExplorer` for a full file manager experience or `DriveFileChooser` for form inputs.
@@ -377,6 +405,40 @@ await ffmpeg(path).format('mp4').save('output.mp4');
377
405
  - **Search Scope**: Search automatically adapts to your current view. If you are browsing the Trash, searches will query deleted items. In the main Browser, searches query active files.
378
406
  - **Trash Management**: "Delete" moves items to Trash. From Trash, you can "Restore" items or "Delete Forever". A dedicated "Empty Trash" button is available to clear all deleted items.
379
407
 
408
+ ### CORS Configuration
409
+
410
+ When your client application runs on a different domain than your API server, you need to enable CORS (Cross-Origin Resource Sharing):
411
+
412
+ ```typescript
413
+ // lib/drive.ts
414
+ export const drive = driveConfiguration({
415
+ // ... other config
416
+ cors: {
417
+ enabled: true,
418
+ origins: ['https://app.example.com', 'https://admin.example.com'], // or '*' for all origins
419
+ methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], // default
420
+ allowedHeaders: ['Content-Type', 'Authorization', 'X-Drive-Account'], // default
421
+ exposedHeaders: ['Content-Length', 'Content-Type', 'Content-Disposition'], // default
422
+ credentials: true, // Allow cookies/auth headers
423
+ maxAge: 86400, // Preflight cache duration in seconds (default: 24 hours)
424
+ },
425
+ });
426
+ ```
427
+
428
+ **CORS Options:**
429
+
430
+ | Option | Type | Default | Description |
431
+ | ---------------- | -------------------- | ----------------------------------------------------------- | ------------------------------------------- |
432
+ | `enabled` | `boolean` | `false` | Enable/disable CORS headers |
433
+ | `origins` | `string \| string[]` | `'*'` | Allowed origins (use array for multiple) |
434
+ | `methods` | `string[]` | `['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']` | Allowed HTTP methods |
435
+ | `allowedHeaders` | `string[]` | `['Content-Type', 'Authorization', 'X-Drive-Account']` | Headers clients can send |
436
+ | `exposedHeaders` | `string[]` | `['Content-Length', 'Content-Type', 'Content-Disposition']` | Headers exposed to client |
437
+ | `credentials` | `boolean` | `false` | Allow credentials (cookies, auth headers) |
438
+ | `maxAge` | `number` | `86400` | Preflight response cache duration (seconds) |
439
+
440
+ > **Note**: When `credentials` is `true`, `origins` cannot be `'*'`. You must specify explicit origins.
441
+
380
442
  ### Responsive Design
381
443
 
382
444
  - **Desktop**: Features a unified single-row header containing Search, Group, Delete, Sort, View, and Trash controls.
@@ -1410,5 +1410,5 @@ var driveAPIHandler = async (req, res) => {
1410
1410
  };
1411
1411
 
1412
1412
  export { driveAPIHandler, driveConfiguration, driveFilePath, driveFileSchemaZod, driveGetUrl, driveReadFile, getDriveConfig, getDriveInformation };
1413
- //# sourceMappingURL=chunk-N6HIRSNO.js.map
1414
- //# sourceMappingURL=chunk-N6HIRSNO.js.map
1413
+ //# sourceMappingURL=chunk-7NT6445J.js.map
1414
+ //# sourceMappingURL=chunk-7NT6445J.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server/config.ts","../src/server/database/mongoose/schema/drive.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","owner","folderIds","provider","google","fields","files"],"mappings":"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","file":"chunk-7NT6445J.js","sourcesContent":["// ** Server Config Wrapper\nimport type { NextApiRequest } from 'next';\nimport mongoose from 'mongoose';\nimport type { TDriveConfiguration, TDriveConfigInformation } from '@/types/server';\n\nlet globalConfig: TDriveConfiguration | null = null;\n\n// ** Initialize configuration\nexport const driveConfiguration = (config: TDriveConfiguration): 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 // Apply default values if not provided in the config\n const mergedConfig: TDriveConfiguration = {\n ...config,\n security: {\n maxUploadSizeInBytes: config.security?.maxUploadSizeInBytes ?? 10 * 1024 * 1024, // Default to 10MB\n allowedMimeTypes: config.security?.allowedMimeTypes ?? ['*/*'],\n signedUrls: config.security?.signedUrls,\n trash: config.security?.trash\n },\n information: config.information ?? (async (req) => {\n return {\n key: { id: 'default-user' },\n storage: { quotaInBytes: 10 * 1024 * 1024 * 1024 } // Default to 10GB\n };\n }),\n };\n\n globalConfig = mergedConfig;\n return mergedConfig;\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)\nexport const getDriveInformation = async (req: NextApiRequest): Promise<TDriveConfigInformation> => {\n const config = getDriveConfig();\n return config.information(req);\n};\n","// ** 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","// ** 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 QUALITY_MAP: Record<string, number> = {\n\tultralow: 10,\n\tlow: 30,\n\tmedium: 60,\n\thigh: 80,\n\tnormal: 100,\n};\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\tif (allowedTypes.includes('*/*')) return true;\n\treturn allowedTypes.some(pattern => {\n\t\tif (pattern === mime) return true;\n\t\tif (pattern.endsWith('/*')) {\n\t\t\tconst prefix = pattern.slice(0, -2);\n\t\t\treturn mime.startsWith(`${prefix}/`);\n\t\t}\n\t\treturn false;\n\t});\n};\n\nexport const computeFileHash = (filePath: string): Promise<string> =>\n\tnew Promise((resolve, reject) => {\n\t\tconst hash = crypto.createHash('sha256');\n\t\tconst stream = fs.createReadStream(filePath);\n\t\tstream.on('data', data => hash.update(data));\n\t\tstream.on('end', () => resolve(hash.digest('hex')));\n\t\tstream.on('error', reject);\n\t});\n\nexport const extractImageMetadata = async (filePath: string) => {\n\ttry {\n\t\tconst { width = 0, height = 0, exif } = await sharp(filePath).metadata();\n\t\treturn { width, height, ...(exif && { exif: { raw: exif.toString('base64') } }) };\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nexport const formatFileSize = (bytes: number): string => {\n\tif (bytes === 0) return '0 B';\n\tconst k = 1024;\n\tconst sizes = ['B', 'KB', 'MB', 'GB', 'TB'];\n\tconst i = Math.floor(Math.log(bytes) / Math.log(k));\n\treturn `${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\tif (a === null && b === null) return true;\n\tif (a === null || b === null) return false;\n\treturn JSON.stringify(a) === JSON.stringify(b);\n};\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 q: z.enum(['ultralow', 'low', 'medium', 'high', 'normal']).optional(),\r\n format: z.enum(['webp', 'jpeg', 'png']).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\r\nexport const cancelQuerySchema = z.object({\r\n id: objectIdSchema,\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) => {\n // Calculate storage used from DB\n const result = await Drive.aggregate([\n { $match: { owner, 'information.type': 'FILE', trashedAt: null } },\n { $group: { _id: null, total: { $sum: '$information.sizeInBytes' } } }\n ]);\n const usedInBytes = result[0]?.total || 0;\n\n // Get quota limit from config/info\n // Since we don't have user info passed directly, we default to config or infinite\n // Note: The original implementation fetched this from `getDriveInformation` in config\n // access via config for now\n const config = getDriveConfig();\n // Assuming default quota if not found, or infinite\n return { usedInBytes, quotaInBytes: 10 * 1024 * 1024 * 1024 }; // Default 10GB for now, or fetch dynamically if needed\n },\n\n openStream: async (item: IDatabaseDriveDocument, accountId?: string) => {\n if (item.information.type !== 'FILE') throw new Error('Cannot stream folder');\n const filePath = path.join(getDriveConfig().storage.path, item.information.path);\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 originalPath = path.join(storagePath, item.information.path);\n const thumbPath = path.join(storagePath, 'cache', 'thumbnails', `${item._id.toString()}.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(path.dirname(thumbPath))) fs.mkdirSync(path.dirname(thumbPath), { recursive: true });\n\n if (item.information.mime.startsWith('image/')) {\n await sharp(originalPath)\n .resize(300, 300, { fit: 'inside' })\n .toFormat('webp', { quality: 80 })\n .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 // Move temp file to final destination\n const destPath = path.join(getDriveConfig().storage.path, drive.information.path);\n const dirPath = path.dirname(destPath);\n if (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath, { recursive: true });\n\n // Rename (move)\n fs.renameSync(filePath, destPath);\n\n drive.status = 'READY';\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 const getAllChildren = async (folderIds: string[]): Promise<any[]> => {\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];\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];\n\n // Delete files from disk\n for (const item of allItemsToDelete) {\n if (item.information.type === 'FILE' && item.information.path) {\n // Check if any other file points to this path (shouldn't happen in simple model but good hygiene)\n // Actually in this model, path is unique per file\n const fullPath = path.join(getDriveConfig().storage.path, item.information.path);\n const dirPath = path.dirname(fullPath); // .../drive/ID/\n if (fs.existsSync(dirPath)) {\n fs.rmSync(dirPath, { 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(\n { _id: id, owner },\n { name: newName },\n { new: true }\n );\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 const oldParentId = item.parentId;\n item.parentId = newParentId === 'root' || !newParentId ? null : new mongoose.Types.ObjectId(newParentId);\n\n // For LOCAL, we might store files in flat structure or hierarchical? \n // Looking at uploadFile (lines 124): path.join(STORAGE_PATH, drive.information.path)\n // And line 171: path.join(STORAGE_PATH, item.information.path)\n // And line 374 in index.ts: drive.information.path = path.join('drive', String(drive._id), 'data.bin');\n // It seems path is ID-based: drive/<ID>/data.bin.\n // So moving a file DOES NOT change its physical path on disk if path is ID-based and flat?\n // Let's verify 'createFolder'. It just creates DB entry.\n // So hierarchy is virtual in DB. Physical storage is flat-ish (by ID).\n // IF so, 'move' is just DB update!\n\n // Let's double check implementation of 'uploadFile' in local.ts\n // Line 124: destPath = path.join(STORAGE_PATH, drive.information.path);\n // And 'path' seems to be set in index.ts line 374: `path.join('drive', String(drive._id), 'data.bin')`\n // So yes, physical path is detached from folder structure.\n\n // So for Local, only DB update is needed.\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 { google } 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 // 1. Get credentials from StorageAccount\n const query: any = { owner, 'metadata.provider': 'GOOGLE' };\n if (accountId) query._id = accountId;\n\n // If multiple accounts and no accountId, we might pick a random one? \n // Ideally we should enforce accountId.\n const account = await StorageAccount.findOne(query); // Pick first one if no ID specificied\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 // Note: StorageAccount schema might still use metadata.provider or just provider?\n // Based on previous grep, context.tsx had { provider: 'GOOGLE' }. \n // Usually StorageAccount keys are consistent.\n // If we only refactored Drive schema, StorageAccount might be unchanged.\n // But `src/server/database/mongoose/schema/drive.ts` was refactored.\n // I need to be careful about StorageAccount.\n // Let's assume StorageAccount is NOT changed in this refactor unless user asked.\n // User only mentioned \"Drive Schema\".\n // But my code in createAuthClient uses account.metadata.provider.\n // Let's keep it as is if StorageAccount wasn't refactored.\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);\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\n // Implement pagination loop\n let nextPageToken: string | undefined = undefined;\n // Keep track of all synced IDs to identify deletions\n const allSyncedGoogleIds = new Set<string>();\n\n do {\n const res: any = await drive.files.list({\n q: `'${googleParentId}' in parents and trashed = false`,\n fields: 'nextPageToken, files(id, name, mimeType, size, webViewLink, iconLink, thumbnailLink)',\n pageSize: 1000,\n pageToken: nextPageToken\n });\n\n nextPageToken = res.data.nextPageToken || undefined;\n const files = res.data.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 await Drive.findOneAndUpdate(\n {\n owner,\n 'provider.google.id': file.id,\n 'provider.type': 'GOOGLE'\n },\n { $set: updateData },\n { upsert: true, new: true, setDefaultsOnInsert: true }\n );\n }\n } while (nextPageToken);\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 drive = google.drive({ version: 'v3', auth: client });\n\n // List trashed files from Google\n let nextPageToken: string | undefined = undefined;\n\n do {\n const res: any = await drive.files.list({\n q: 'trashed = true',\n fields: 'nextPageToken, files(id, name, mimeType, size, webViewLink, iconLink, thumbnailLink)',\n pageSize: 100, // Limit sync for performance\n pageToken: nextPageToken\n });\n\n nextPageToken = res.data.nextPageToken || undefined;\n const files = res.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 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 },\n { upsert: true, setDefaultsOnInsert: true }\n );\n }\n } while (nextPageToken);\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)',\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 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 },\n { upsert: true, setDefaultsOnInsert: true }\n );\n }\n },\n\n getQuota: async (owner, accountId) => {\n try {\n const { client } = await createAuthClient(owner, accountId);\n const drive = google.drive({ version: 'v3', auth: client });\n const res: any = 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: any = 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 { client } = await createAuthClient(item.owner, accountId || (item.storageAccountId?.toString()));\n\n if (!item.provider?.google?.thumbnailLink) throw new Error('No thumbnail available');\n\n const res: any = await client.request({ url: item.provider.google.thumbnailLink, responseType: 'stream' });\n return res.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: any = 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: any = 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\n } catch (error) {\n drive.status = 'FAILED';\n console.error('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;\n if (typeof creds === 'object' && 'access_token' in creds) {\n await client.revokeToken(creds.access_token);\n }\n }\n }\n};\n","import fs from 'fs';\nimport path from 'path';\nimport crypto from 'crypto';\nimport formidable from 'formidable';\nimport type { Readable } from 'stream';\nimport Drive from '@/server/database/mongoose/schema/drive';\nimport { getDriveConfig } from '@/server/config';\nimport { computeFileHash, extractImageMetadata } from '@/server/utils';\nimport type { IDatabaseDriveDocument } from '@/server/database/mongoose/schema/drive';\nimport type { TDatabaseDrive } from '@/types/lib/database/drive';\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 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, drive.information.path);\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 cache library folder\n if (providerType === 'GOOGLE') {\n const libraryDir = path.join(STORAGE_PATH, 'library', 'google');\n const fileName = `${drive._id}${path.extname(drive.name)}`;\n const cachedFilePath = path.join(libraryDir, fileName);\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 library directory if it doesn't exist\n if (!fs.existsSync(libraryDir)) {\n fs.mkdirSync(libraryDir, { recursive: true });\n }\n\n // Download to temp file first, then rename (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 // Rename temp file to final path\n fs.renameSync(tempPath, cachedFilePath);\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\nexport const processChunk = async (drive: any, chunkFile: formidable.File | formidable.File[] | undefined, chunkIndex: number, totalChunks: number, STORAGE_PATH: string) => {\n if (!chunkFile || drive.information.type !== 'FILE') return;\n\n const file = Array.isArray(chunkFile) ? chunkFile[0] : chunkFile;\n const destPath = path.join(STORAGE_PATH, drive.information.path);\n const chunkData = fs.readFileSync(file.filepath);\n\n if (chunkIndex === 0) {\n fs.writeFileSync(destPath, chunkData);\n } else {\n fs.appendFileSync(destPath, chunkData);\n }\n\n fs.rmSync(file.filepath, { force: true });\n drive.currentChunk = chunkIndex + 1;\n\n if (drive.currentChunk >= totalChunks || chunkIndex === totalChunks - 1) {\n drive.status = 'READY';\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\n await drive.save();\n};\n","// ** Server Entry Point\nimport type { NextApiRequest, NextApiResponse } from 'next';\nimport formidable from 'formidable';\nimport path from 'path';\nimport fs from 'fs';\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 } from '@/server/utils';\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';\n\n// ** Helper to get Provider\nconst getProvider = async (req: NextApiRequest, owner: Record<string, unknown> | null): Promise<{ provider: TStorageProvider; accountId?: string }> => {\n\t// Check header for account ID\n\tconst accountId = req.headers['x-drive-account'] as string;\n\n\tif (!accountId || accountId === 'LOCAL') {\n\t\treturn { provider: LocalStorageProvider };\n\t}\n\n\t// Validate account belongs to owner\n\tconst account = await StorageAccount.findOne({ _id: accountId, owner });\n\tif (!account) {\n\t\tthrow new Error('Invalid Storage Account');\n\t}\n\n\tif (account.metadata.provider === 'GOOGLE') return { provider: GoogleDriveProvider, accountId: account._id.toString() };\n\n\t// Fallback\n\treturn { provider: LocalStorageProvider };\n};\n\n// ** Helper to apply CORS headers\nconst applyCorsHeaders = (req: NextApiRequest, res: NextApiResponse, config: ReturnType<typeof getDriveConfig>): boolean => {\n\tconst cors = config.cors;\n\tif (!cors?.enabled) return false;\n\n\tconst origin = req.headers.origin;\n\tconst allowedOrigins = cors.origins ?? '*';\n\tconst methods = cors.methods ?? ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'];\n\tconst allowedHeaders = cors.allowedHeaders ?? ['Content-Type', 'Authorization', 'X-Drive-Account'];\n\tconst exposedHeaders = cors.exposedHeaders ?? ['Content-Length', 'Content-Type', 'Content-Disposition'];\n\tconst credentials = cors.credentials ?? false;\n\tconst maxAge = cors.maxAge ?? 86400; // 24 hours default\n\n\t// Determine if origin is allowed\n\tlet allowOrigin = '*';\n\tif (origin) {\n\t\tif (allowedOrigins === '*') {\n\t\t\tallowOrigin = origin;\n\t\t} else if (Array.isArray(allowedOrigins)) {\n\t\t\tif (allowedOrigins.includes(origin)) {\n\t\t\t\tallowOrigin = origin;\n\t\t\t}\n\t\t} else if (allowedOrigins === origin) {\n\t\t\tallowOrigin = origin;\n\t\t}\n\t}\n\n\tres.setHeader('Access-Control-Allow-Origin', allowOrigin);\n\tres.setHeader('Access-Control-Allow-Methods', methods.join(', '));\n\tres.setHeader('Access-Control-Allow-Headers', allowedHeaders.join(', '));\n\tres.setHeader('Access-Control-Expose-Headers', exposedHeaders.join(', '));\n\tres.setHeader('Access-Control-Max-Age', maxAge.toString());\n\n\tif (credentials) {\n\t\tres.setHeader('Access-Control-Allow-Credentials', 'true');\n\t}\n\n\t// Handle preflight\n\tif (req.method === 'OPTIONS') {\n\t\tres.status(204).end();\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\n// ** Main API handler for all drive operations\nexport const driveAPIHandler = async (req: NextApiRequest, res: NextApiResponse): Promise<void> => {\n\tconst action = req.query.action as string;\n\n\t// ** Ensure Config\n\tlet config: ReturnType<typeof getDriveConfig>;\n\ttry {\n\t\tconfig = getDriveConfig();\n\t} catch (error) {\n\t\tconsole.error('[next-drive] Configuration error:', error);\n\t\tres.status(500).json({ status: 500, message: 'Failed to initialize drive configuration' });\n\t\treturn;\n\t}\n\n\t// ** Apply CORS headers\n\tconst isPreflightHandled = applyCorsHeaders(req, res, config);\n\tif (isPreflightHandled) return;\n\n\tif (!action) {\n\t\tres.status(400).json({ status: 400, message: 'Missing action query parameter' });\n\t\treturn;\n\t}\n\n\ttry {\n\t\tconst information = await getDriveInformation(req);\n\t\tconst { key: owner } = information;\n\t\tconst STORAGE_PATH = config.storage.path;\n\n\t\t// ** OAuth & Account Actions (No Provider Resolution Needed)\n\t\tif (['getAuthUrl', 'callback', 'listAccounts', 'removeAccount'].includes(action)) {\n\t\t\tswitch (action) {\n\t\t\t\tcase 'getAuthUrl': {\n\t\t\t\t\tconst { provider } = req.query;\n\t\t\t\t\tif (provider === 'GOOGLE') {\n\t\t\t\t\t\tconst { clientId, clientSecret, redirectUri } = config.storage?.google || {};\n\t\t\t\t\t\tif (!clientId || !clientSecret) return res.status(500).json({ status: 500, message: 'Google not configured' });\n\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\t\t\t\t\tconst { google } = require('googleapis');\n\t\t\t\t\t\tconst oAuth2Client = new google.auth.OAuth2(clientId, clientSecret, redirectUri);\n\t\t\t\t\t\t// Generate state to identify user\n\t\t\t\t\t\t// For security, should sign state. Simple base64 for now.\n\t\t\t\t\t\tconst state = Buffer.from(JSON.stringify({ owner })).toString('base64');\n\t\t\t\t\t\tconst url = oAuth2Client.generateAuthUrl({\n\t\t\t\t\t\t\taccess_type: 'offline',\n\t\t\t\t\t\t\tscope: ['https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/userinfo.email'],\n\t\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\tprompt: 'consent', // force refresh token\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn res.status(200).json({ status: 200, message: 'Auth URL generated', data: { url } });\n\t\t\t\t\t}\n\t\t\t\t\treturn res.status(400).json({ status: 400, message: 'Unknown provider' });\n\t\t\t\t}\n\t\t\t\tcase 'callback': {\n\t\t\t\t\tconst { code, state } = req.query;\n\t\t\t\t\tif (!code) return res.status(400).json({ status: 400, message: 'Missing code' });\n\n\t\t\t\t\t// Verify state if possible, though 'owner' is derived from session/request usually.\n\t\t\t\t\t// Assuming 'owner' from getDriveInformation is the source of truth for current session.\n\n\t\t\t\t\tconst { clientId, clientSecret, redirectUri } = config.storage?.google || {};\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\t\t\t\tconst { google } = require('googleapis');\n\t\t\t\t\tconst oAuth2Client = new google.auth.OAuth2(clientId, clientSecret, redirectUri);\n\n\t\t\t\t\tconst { tokens } = await oAuth2Client.getToken(code as string);\n\t\t\t\t\toAuth2Client.setCredentials(tokens);\n\n\t\t\t\t\t// Get User Info\n\t\t\t\t\tconst oauth2 = google.oauth2({ version: 'v2', auth: oAuth2Client });\n\t\t\t\t\tconst userInfo = await oauth2.userinfo.get();\n\n\t\t\t\t\t// Save Account\n\t\t\t\t\tconst existing = await StorageAccount.findOne({ owner, 'metadata.google.email': userInfo.data.email, 'metadata.provider': 'GOOGLE' });\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\texisting.metadata.google.credentials = tokens;\n\t\t\t\t\t\texisting.markModified('metadata');\n\t\t\t\t\t\tawait existing.save();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait StorageAccount.create({\n\t\t\t\t\t\t\towner,\n\t\t\t\t\t\t\tname: userInfo.data.name || 'Google Drive',\n\t\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\t\tprovider: 'GOOGLE',\n\t\t\t\t\t\t\t\tgoogle: {\n\t\t\t\t\t\t\t\t\temail: userInfo.data.email,\n\t\t\t\t\t\t\t\t\tcredentials: tokens,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t// Helper: Return HTML that closes popup\n\t\t\t\t\tres.setHeader('Content-Type', 'text/html');\n\t\t\t\t\treturn res.send('<script>window.opener.postMessage(\"oauth-success\", \"*\"); window.close();</script>');\n\t\t\t\t}\n\t\t\t\tcase 'listAccounts': {\n\t\t\t\t\tconst accounts = await StorageAccount.find({ owner });\n\t\t\t\t\treturn res.status(200).json({\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\taccounts: accounts.map(a => ({\n\t\t\t\t\t\t\t\tid: a._id.toString(),\n\t\t\t\t\t\t\t\tname: a.name,\n\t\t\t\t\t\t\t\temail: a.metadata.google?.email || '',\n\t\t\t\t\t\t\t\tprovider: a.metadata.provider,\n\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tcase 'removeAccount': {\n\t\t\t\t\tconst { id } = req.query;\n\t\t\t\t\tconst account = await StorageAccount.findOne({ _id: id, owner });\n\t\t\t\t\tif (!account) return res.status(404).json({ status: 404, message: 'Account not found' });\n\n\t\t\t\t\t// Revoke Token if Google\n\t\t\t\t\tif (account.metadata.provider === 'GOOGLE') {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait GoogleDriveProvider.revokeToken(owner, account._id.toString());\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tconsole.error('Failed to revoke Google token:', e);\n\t\t\t\t\t\t\t// Proceed to delete anyway\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tawait StorageAccount.deleteOne({ _id: id, owner });\n\t\t\t\t\tawait Drive.deleteMany({ owner, storageAccountId: id });\n\t\t\t\t\treturn res.status(200).json({ status: 200, message: 'Account removed' });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// ** Provider Actions\n\t\tconst { provider, accountId } = await getProvider(req, owner);\n\n\t\tswitch (action) {\n\t\t\t// ** 1. LIST **\n\t\t\tcase 'list': {\n\t\t\t\tif (req.method !== 'GET') return res.status(405).json({ status: 405, message: 'Only GET allowed' });\n\t\t\t\tconst listQuery = schemas.listQuerySchema.safeParse(req.query);\n\t\t\t\tif (!listQuery.success) return res.status(400).json({ status: 400, message: 'Invalid parameters' });\n\n\t\t\t\tconst { folderId, limit, afterId } = listQuery.data;\n\n\t\t\t\t// Sync Trigger: If viewing a folder, try to sync it first if provider supports it\n\t\t\t\t// Only sync if we are browsing a specific folder or root\n\t\t\t\ttry {\n\t\t\t\t\tawait provider.sync(folderId || 'root', owner, accountId);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error('Sync failed', e);\n\t\t\t\t\t// Continue to list what we have in DB\n\t\t\t\t}\n\n\t\t\t\t// Query DB\n\t\t\t\tconst query: Record<string, unknown> = {\n\t\t\t\t\towner,\n\t\t\t\t\t'provider.type': provider.name,\n\t\t\t\t\tstorageAccountId: accountId || null,\n\t\t\t\t\tparentId: folderId === 'root' || !folderId ? null : folderId,\n\t\t\t\t\ttrashedAt: null,\n\t\t\t\t};\n\t\t\t\tif (afterId) query._id = { $lt: afterId }; // Pagination\n\n\t\t\t\tconst items = await Drive.find(query, {}, { sort: { order: 1, _id: -1 }, limit });\n\t\t\t\tconst plainItems = await Promise.all(items.map(item => item.toClient()));\n\n\t\t\t\tres.status(200).json({ status: 200, message: 'Items retrieved', data: { items: plainItems, hasMore: items.length === limit } });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// ** 2. SEARCH **\n\t\t\tcase 'search': {\n\t\t\t\tconst searchData = schemas.searchQuerySchema.safeParse(req.query);\n\t\t\t\tif (!searchData.success) return res.status(400).json({ status: 400, message: 'Invalid params' });\n\t\t\t\tconst { q, folderId, limit, trashed } = searchData.data;\n\n\t\t\t\t// Sync Search\n\t\t\t\tif (!trashed) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait provider.search(q, owner, accountId);\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tconsole.error('Search sync failed', e);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Query DB\n\t\t\t\tconst query: Record<string, unknown> = {\n\t\t\t\t\towner,\n\t\t\t\t\t'provider.type': provider.name,\n\t\t\t\t\tstorageAccountId: accountId || null,\n\t\t\t\t\ttrashedAt: trashed ? { $ne: null } : null,\n\t\t\t\t\tname: { $regex: q, $options: 'i' },\n\t\t\t\t};\n\t\t\t\tif (folderId && folderId !== 'root') query.parentId = folderId;\n\n\t\t\t\tconst items = await Drive.find(query, {}, { limit, sort: { createdAt: -1 } });\n\t\t\t\tconst plainItems = await Promise.all(items.map(i => i.toClient()));\n\n\t\t\t\treturn res.status(200).json({ status: 200, message: 'Results', data: { items: plainItems } });\n\t\t\t}\n\n\t\t\t// ** 3. UPLOAD **\n\t\t\tcase 'upload': {\n\t\t\t\tif (req.method !== 'POST') return res.status(405).json({ status: 405, message: 'Only POST allowed' });\n\t\t\t\tconst form = formidable({\n\t\t\t\t\tmultiples: false,\n\t\t\t\t\tmaxFileSize: config.security.maxUploadSizeInBytes * 2,\n\t\t\t\t\tuploadDir: path.join(STORAGE_PATH, 'temp'),\n\t\t\t\t\tkeepExtensions: true,\n\t\t\t\t});\n\t\t\t\tif (!fs.existsSync(path.join(STORAGE_PATH, 'temp'))) fs.mkdirSync(path.join(STORAGE_PATH, 'temp'), { recursive: true });\n\n\t\t\t\tconst [fields, files] = await new Promise<[formidable.Fields, formidable.Files]>((resolve, reject) => {\n\t\t\t\t\tform.parse(req, (err, fields, files) => {\n\t\t\t\t\t\tif (err) reject(err);\n\t\t\t\t\t\telse resolve([fields, files]);\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\tconst cleanupTempFiles = (files: formidable.Files) => {\n\t\t\t\t\tObject.values(files)\n\t\t\t\t\t\t.flat()\n\t\t\t\t\t\t.forEach(file => {\n\t\t\t\t\t\t\tif (file && fs.existsSync(file.filepath)) fs.rmSync(file.filepath, { force: true });\n\t\t\t\t\t\t});\n\t\t\t\t};\n\n\t\t\t\tconst getString = (f: string[] | string | undefined) => (Array.isArray(f) ? f[0] : f || '');\n\t\t\t\tconst getInt = (f: string[] | string | undefined) => parseInt(getString(f) || '0', 10);\n\n\t\t\t\tconst uploadData = schemas.uploadChunkSchema.safeParse({\n\t\t\t\t\tchunkIndex: getInt(fields.chunkIndex),\n\t\t\t\t\ttotalChunks: getInt(fields.totalChunks),\n\t\t\t\t\tdriveId: getString(fields.driveId) || undefined,\n\t\t\t\t\tfileName: getString(fields.fileName),\n\t\t\t\t\tfileSize: getInt(fields.fileSize),\n\t\t\t\t\tfileType: getString(fields.fileType),\n\t\t\t\t\tfolderId: getString(fields.folderId) || undefined,\n\t\t\t\t});\n\n\t\t\t\tif (!uploadData.success) {\n\t\t\t\t\tcleanupTempFiles(files);\n\t\t\t\t\treturn res.status(400).json({ status: 400, message: uploadData.error.errors[0].message });\n\t\t\t\t}\n\n\t\t\t\tconst { chunkIndex, totalChunks, driveId, fileName, fileSize: fileSizeInBytes, fileType, folderId } = uploadData.data;\n\n\t\t\t\tlet currentUploadId = driveId;\n\n\t\t\t\t// Ensure temp directory for this upload exists\n\t\t\t\tconst tempBaseDir = path.join(STORAGE_PATH, 'temp', 'uploads');\n\n\t\t\t\tif (!currentUploadId) {\n\t\t\t\t\t// Start of new upload (usually Chunk 0, but could be adapted)\n\t\t\t\t\tif (chunkIndex !== 0) return res.status(400).json({ message: 'Missing upload ID for non-zero chunk' });\n\n\t\t\t\t\tif (fileType && !validateMimeType(fileType, config.security.allowedMimeTypes)) {\n\t\t\t\t\t\tcleanupTempFiles(files);\n\t\t\t\t\t\treturn res.status(400).json({ status: 400, message: `File type ${fileType} not allowed` });\n\t\t\t\t\t}\n\n\t\t\t\t\t// Quota Check\n\t\t\t\t\tconst quota = await provider.getQuota(owner, accountId);\n\t\t\t\t\tif (quota.usedInBytes + fileSizeInBytes > quota.quotaInBytes) {\n\t\t\t\t\t\tcleanupTempFiles(files);\n\t\t\t\t\t\treturn res.status(413).json({ status: 413, message: 'Storage quota exceeded' });\n\t\t\t\t\t}\n\n\t\t\t\t\t// Generate Temp ID (Stateless)\n\t\t\t\t\tcurrentUploadId = crypto.randomUUID();\n\t\t\t\t\tconst uploadDir = path.join(tempBaseDir, currentUploadId);\n\t\t\t\t\tfs.mkdirSync(uploadDir, { recursive: true });\n\n\t\t\t\t\t// Save Metadata\n\t\t\t\t\tconst metadata = {\n\t\t\t\t\t\towner,\n\t\t\t\t\t\taccountId,\n\t\t\t\t\t\tproviderName: provider.name,\n\t\t\t\t\t\tname: fileName,\n\t\t\t\t\t\tparentId: folderId === 'root' || !folderId ? null : folderId,\n\t\t\t\t\t\tfileSize: fileSizeInBytes,\n\t\t\t\t\t\tmimeType: fileType,\n\t\t\t\t\t\ttotalChunks,\n\t\t\t\t\t};\n\t\t\t\t\tfs.writeFileSync(path.join(uploadDir, 'metadata.json'), JSON.stringify(metadata));\n\t\t\t\t}\n\n\t\t\t\t// Handle Chunk Save\n\t\t\t\tif (currentUploadId) {\n\t\t\t\t\tconst uploadDir = path.join(tempBaseDir, currentUploadId);\n\n\t\t\t\t\tif (!fs.existsSync(uploadDir)) {\n\t\t\t\t\t\tcleanupTempFiles(files);\n\t\t\t\t\t\t// If dir missing, maybe upload expired or finished?\n\t\t\t\t\t\treturn res.status(404).json({ status: 404, message: 'Upload session not found or expired' });\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst chunkFile = Array.isArray(files.chunk) ? files.chunk[0] : files.chunk;\n\t\t\t\t\t\tif (!chunkFile) throw new Error('No chunk file received');\n\n\t\t\t\t\t\t// Save part file: part_0, part_1...\n\t\t\t\t\t\tconst partPath = path.join(uploadDir, `part_${chunkIndex}`);\n\t\t\t\t\t\tfs.renameSync(chunkFile.filepath, partPath);\n\n\t\t\t\t\t\t// Check Completion\n\t\t\t\t\t\t// We count files starting with 'part_'\n\t\t\t\t\t\tconst uploadedParts = fs.readdirSync(uploadDir).filter(f => f.startsWith('part_'));\n\n\t\t\t\t\t\t// Merge if all parts present\n\t\t\t\t\t\tif (uploadedParts.length === totalChunks) {\n\t\t\t\t\t\t\t// 1. Read Metadata\n\t\t\t\t\t\t\tconst metaPath = path.join(uploadDir, 'metadata.json');\n\t\t\t\t\t\t\tconst meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));\n\n\t\t\t\t\t\t\t// 2. Merge Parts\n\t\t\t\t\t\t\tconst finalTempPath = path.join(uploadDir, 'final.bin');\n\t\t\t\t\t\t\tconst writeStream = fs.createWriteStream(finalTempPath);\n\n\t\t\t\t\t\t\tfor (let i = 0; i < totalChunks; i++) {\n\t\t\t\t\t\t\t\tconst pPath = path.join(uploadDir, `part_${i}`);\n\t\t\t\t\t\t\t\tconst data = fs.readFileSync(pPath);\n\t\t\t\t\t\t\t\twriteStream.write(data);\n\t\t\t\t\t\t\t\t// Optional: delete part immediately to save space?\n\t\t\t\t\t\t\t\t// fs.unlinkSync(pPath);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\twriteStream.end();\n\n\t\t\t\t\t\t\t// Wait for stream finish? Sync write above is blocking so it's fine.\n\n\t\t\t\t\t\t\t// 3. Create DB Record (Delayed)\n\t\t\t\t\t\t\tconst drive = new Drive({\n\t\t\t\t\t\t\t\towner: meta.owner,\n\t\t\t\t\t\t\t\tstorageAccountId: meta.accountId || null,\n\t\t\t\t\t\t\t\tprovider: { type: meta.providerName },\n\t\t\t\t\t\t\t\tname: meta.name,\n\t\t\t\t\t\t\t\tparentId: meta.parentId,\n\t\t\t\t\t\t\t\torder: 0,\n\t\t\t\t\t\t\t\tinformation: { type: 'FILE', sizeInBytes: meta.fileSize, mime: meta.mimeType, path: '' }, // path set by provider\n\t\t\t\t\t\t\t\tstatus: 'UPLOADING',\n\t\t\t\t\t\t\t\tcurrentChunk: totalChunks,\n\t\t\t\t\t\t\t\ttotalChunks: totalChunks,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t// Set initial path based on ID - providers will resolve final path/ID\n\t\t\t\t\t\t\tif (meta.providerName === 'LOCAL' && drive.information.type === 'FILE') {\n\t\t\t\t\t\t\t\tdrive.information.path = path.join('drive', String(drive._id), 'data.bin');\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tawait drive.save();\n\n\t\t\t\t\t\t\t// 4. Provider Upload\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst item = await provider.uploadFile(drive, finalTempPath, meta.accountId);\n\n\t\t\t\t\t\t\t\t// Cleanup\n\t\t\t\t\t\t\t\tfs.rmSync(uploadDir, { recursive: true, force: true });\n\n\t\t\t\t\t\t\t\tconst newQuota = await provider.getQuota(meta.owner, meta.accountId);\n\t\t\t\t\t\t\t\tres.status(200).json({ status: 200, message: 'Upload complete', data: { type: 'UPLOAD_COMPLETE', driveId: String(drive._id), item }, statistic: { storage: newQuota } });\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\t// Upload to provider failed\n\t\t\t\t\t\t\t\tawait Drive.deleteOne({ _id: drive._id });\n\t\t\t\t\t\t\t\tthrow err;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Chunk received, wait for others\n\t\t\t\t\t\t\tconst newQuota = await provider.getQuota(owner, accountId);\n\t\t\t\t\t\t\t// If this was chunk 0, we send UPLOAD_STARTED with the new ID\n\t\t\t\t\t\t\tif (chunkIndex === 0) {\n\t\t\t\t\t\t\t\tres.status(200).json({ status: 200, message: 'Upload started', data: { type: 'UPLOAD_STARTED', driveId: currentUploadId }, statistic: { storage: newQuota } });\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tres.status(200).json({ status: 200, message: 'Chunk received', data: { type: 'CHUNK_RECEIVED', driveId: currentUploadId, chunkIndex }, statistic: { storage: newQuota } });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tcleanupTempFiles(files);\n\t\t\t\t\t\t// Don't delete entire dir on one chunk fail, might be retryable?\n\t\t\t\t\t\t// For now, if fatal error, maybe we should?\n\t\t\t\t\t\t// Let's just throw for now.\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Should not happen if logic holds\n\t\t\t\tcleanupTempFiles(files);\n\t\t\t\treturn res.status(400).json({ status: 400, message: 'Invalid upload request' });\n\t\t\t}\n\n\t\t\t// ** 4. CREATE FOLDER **\n\t\t\tcase 'createFolder': {\n\t\t\t\tconst folderData = schemas.createFolderBodySchema.safeParse(req.body);\n\t\t\t\tif (!folderData.success) return res.status(400).json({ status: 400, message: folderData.error.errors[0].message });\n\t\t\t\tconst { name, parentId } = folderData.data;\n\n\t\t\t\tconst item = await provider.createFolder(name, parentId ?? null, owner, accountId);\n\t\t\t\treturn res.status(201).json({ status: 201, message: 'Folder created', data: { item } });\n\t\t\t}\n\n\t\t\t// ** 5. DELETE **\n\t\t\tcase 'delete': {\n\t\t\t\tconst deleteData = schemas.deleteQuerySchema.safeParse(req.query);\n\t\t\t\tif (!deleteData.success) return res.status(400).json({ status: 400, message: 'Invalid ID' });\n\t\t\t\t// We use generic delete (trash)\n\t\t\t\tconst { id } = deleteData.data;\n\t\t\t\tconst drive = await Drive.findById(id);\n\t\t\t\tif (!drive) return res.status(404).json({ status: 404, message: 'Not found' });\n\n\t\t\t\t// Call Provider Trash\n\t\t\t\tconst itemProvider = drive.provider?.type === 'GOOGLE' ? GoogleDriveProvider : LocalStorageProvider;\n\t\t\t\tconst itemAccountId = drive.storageAccountId ? drive.storageAccountId.toString() : undefined;\n\n\t\t\t\ttry {\n\t\t\t\t\tawait itemProvider.trash([id], owner, itemAccountId);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error('Provider trash failed:', e);\n\t\t\t\t}\n\n\t\t\t\tdrive.trashedAt = new Date();\n\t\t\t\tawait drive.save();\n\t\t\t\treturn res.status(200).json({ status: 200, message: 'Moved to trash', data: null });\n\t\t\t}\n\n\t\t\t// ** 6. HARD DELETE **\n\t\t\tcase 'deletePermanent': {\n\t\t\t\tconst deleteData = schemas.deleteQuerySchema.safeParse(req.query);\n\t\t\t\tif (!deleteData.success) return res.status(400).json({ status: 400, message: 'Invalid ID' });\n\t\t\t\tconst { id } = deleteData.data;\n\t\t\t\t// Provider Delete\n\t\t\t\tawait provider.delete([id], owner, accountId);\n\t\t\t\tconst quota = await provider.getQuota(owner, accountId);\n\t\t\t\treturn res.status(200).json({ status: 200, message: 'Deleted', statistic: { storage: quota } });\n\t\t\t}\n\n\t\t\t// ** 7. QUOTA **\n\t\t\tcase 'quota': {\n\t\t\t\tconst quota = await provider.getQuota(owner, accountId);\n\t\t\t\treturn res.status(200).json({\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\tmessage: 'Quota retrieved',\n\t\t\t\t\tdata: { 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\t\t\t\t\tstatistic: { storage: quota },\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// ** 7B. TRASH **\n\t\t\tcase 'trash': {\n\t\t\t\t// Try to sync trash first\n\t\t\t\ttry {\n\t\t\t\t\tconst { provider: trashProvider, accountId: trashAccountId } = await getProvider(req, owner);\n\t\t\t\t\tawait trashProvider.syncTrash(owner, trashAccountId);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error('Trash sync failed', e);\n\t\t\t\t}\n\n\t\t\t\t// Return items that are in trash\n\t\t\t\tconst query: Record<string, unknown> = {\n\t\t\t\t\towner,\n\t\t\t\t\t'provider.type': provider.name,\n\t\t\t\t\tstorageAccountId: accountId || null,\n\t\t\t\t\ttrashedAt: { $ne: null },\n\t\t\t\t};\n\n\t\t\t\tconst items = await Drive.find(query, {}, { sort: { trashedAt: -1 } });\n\t\t\t\tconst plainItems = await Promise.all(items.map(item => item.toClient()));\n\n\t\t\t\treturn res.status(200).json({\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\tmessage: 'Trash items',\n\t\t\t\t\tdata: { items: plainItems, hasMore: false },\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// ** 7C. RESTORE **\n\t\t\tcase 'restore': {\n\t\t\t\tconst restoreData = schemas.deleteQuerySchema.safeParse(req.query);\n\t\t\t\tif (!restoreData.success) return res.status(400).json({ status: 400, message: 'Invalid ID' });\n\t\t\t\tconst { id } = restoreData.data;\n\t\t\t\tconst drive = await Drive.findById(id);\n\t\t\t\tif (!drive) return res.status(404).json({ status: 404, message: 'Not found' });\n\n\t\t\t\t// Check if parent folder is trashed - if so, move to root\n\t\t\t\tlet targetParentId = drive.parentId;\n\t\t\t\tif (targetParentId) {\n\t\t\t\t\tconst parent = await Drive.findById(targetParentId);\n\t\t\t\t\tif (parent?.trashedAt) {\n\t\t\t\t\t\ttargetParentId = null; // Move to root instead\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Call Provider Untrash\n\t\t\t\tconst itemProvider = drive.provider?.type === 'GOOGLE' ? GoogleDriveProvider : LocalStorageProvider;\n\t\t\t\tconst itemAccountId = drive.storageAccountId ? drive.storageAccountId.toString() : undefined;\n\n\t\t\t\ttry {\n\t\t\t\t\tawait itemProvider.untrash([id], owner, itemAccountId);\n\t\t\t\t\t// If moving to root due to trashed parent, update location in provider\n\t\t\t\t\tif (targetParentId !== drive.parentId) {\n\t\t\t\t\t\tawait itemProvider.move(id, targetParentId?.toString() ?? null, owner, itemAccountId);\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error('Provider restore failed:', e);\n\t\t\t\t}\n\n\t\t\t\t// Restore item in database\n\t\t\t\tdrive.trashedAt = null;\n\t\t\t\tdrive.parentId = targetParentId;\n\t\t\t\tawait drive.save();\n\n\t\t\t\treturn res.status(200).json({\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\tmessage: targetParentId === null && drive.parentId !== null ? 'Restored to root (parent folder was trashed)' : 'Restored',\n\t\t\t\t\tdata: null,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// ** 7D. MOVE **\n\t\t\tcase 'move': {\n\t\t\t\tconst moveData = schemas.moveBodySchema.safeParse(req.body);\n\t\t\t\tif (!moveData.success) return res.status(400).json({ status: 400, message: 'Invalid data' });\n\t\t\t\tconst { ids, targetFolderId } = moveData.data;\n\n\t\t\t\tconst items: TDatabaseDrive[] = [];\n\t\t\t\t// Target folder ID for provider (null for root)\n\t\t\t\tconst effectiveTargetId = targetFolderId === 'root' || !targetFolderId ? null : targetFolderId;\n\n\t\t\t\tfor (const id of ids) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst item = await provider.move(id, effectiveTargetId, owner, accountId);\n\t\t\t\t\t\titems.push(item);\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tconsole.error(`Failed to move item ${id}`, e);\n\t\t\t\t\t\t// Continue moving other items\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn res.status(200).json({ status: 200, message: 'Moved', data: { items } });\n\t\t\t}\n\n\t\t\t// ** 8. RENAME **\n\t\t\tcase 'rename': {\n\t\t\t\tconst renameData = schemas.renameBodySchema.safeParse({ id: req.query.id, ...req.body });\n\t\t\t\tif (!renameData.success) return res.status(400).json({ status: 400, message: 'Invalid data' });\n\t\t\t\tconst { id, newName } = renameData.data;\n\t\t\t\tconst item = await provider.rename(id, newName, owner, accountId);\n\t\t\t\treturn res.status(200).json({ status: 200, message: 'Renamed', data: { item } });\n\t\t\t}\n\n\t\t\t// ** 9. THUMBNAIL **\n\t\t\tcase 'thumbnail': {\n\t\t\t\tconst thumbQuery = schemas.thumbnailQuerySchema.safeParse(req.query);\n\t\t\t\tif (!thumbQuery.success) return res.status(400).json({ status: 400, message: 'Invalid params' });\n\t\t\t\tconst { id } = thumbQuery.data;\n\t\t\t\tconst drive = await Drive.findById(id);\n\t\t\t\tif (!drive) return res.status(404).json({ status: 404, message: 'Not found' });\n\n\t\t\t\t// Resolve Correct Provider\n\t\t\t\tconst itemProvider = drive.provider?.type === 'GOOGLE' ? GoogleDriveProvider : LocalStorageProvider;\n\t\t\t\tconst itemAccountId = drive.storageAccountId ? drive.storageAccountId.toString() : undefined;\n\n\t\t\t\tconst stream = await itemProvider.getThumbnail(drive, itemAccountId);\n\t\t\t\tres.setHeader('Content-Type', 'image/webp');\n\t\t\t\t// Allow cross-origin resource sharing for images\n\t\t\t\tif (config.cors?.enabled) {\n\t\t\t\t\tres.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');\n\t\t\t\t}\n\t\t\t\tstream.pipe(res);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// ** 10. SERVE / DOWNLOAD **\n\t\t\tcase 'serve': {\n\t\t\t\tconst serveQuery = schemas.serveQuerySchema.safeParse(req.query);\n\t\t\t\tif (!serveQuery.success) return res.status(400).json({ status: 400, message: 'Invalid params' });\n\t\t\t\tconst { id } = serveQuery.data;\n\t\t\t\tconst drive = await Drive.findById(id);\n\t\t\t\tif (!drive) return res.status(404).json({ status: 404, message: 'Not found' });\n\n\t\t\t\t// Resolve Correct Provider\n\t\t\t\tconst itemProvider = drive.provider?.type === 'GOOGLE' ? GoogleDriveProvider : LocalStorageProvider;\n\t\t\t\tconst itemAccountId = drive.storageAccountId ? drive.storageAccountId.toString() : undefined;\n\n\t\t\t\tconst { stream, mime, size } = await itemProvider.openStream(drive, itemAccountId);\n\n\t\t\t\tconst safeFilename = sanitizeContentDispositionFilename(drive.name);\n\t\t\t\tres.setHeader('Content-Disposition', `inline; filename=\"${safeFilename}\"`);\n\t\t\t\tres.setHeader('Content-Type', mime);\n\t\t\t\t// Allow cross-origin resource sharing for files\n\t\t\t\tif (config.cors?.enabled) {\n\t\t\t\t\tres.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');\n\t\t\t\t}\n\t\t\t\t// Google streams might not give exact size, but we have IT in DB?\n\t\t\t\tif (size) res.setHeader('Content-Length', size);\n\n\t\t\t\tstream.pipe(res);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tres.status(400).json({ status: 400, message: `Unknown action: ${action}` });\n\t\t}\n\t} catch (error: unknown) {\n\t\tconsole.error(`[next-drive] Error handling action ${action}:`, error);\n\t\t// FOR DEBUGGING: Return the actual error message\n\t\tres.status(500).json({ status: 500, message: error instanceof Error ? error.message : 'Unknown error' });\n\t}\n};\n\n// ** Exports\nexport { driveConfiguration, getDriveConfig, getDriveInformation };\nexport { driveGetUrl, driveReadFile, driveFilePath } from '@/server/controllers/drive';\nexport { driveFileSchemaZod } from '@/server/zod/schemas';\nexport { driveCreateUrl, driveCreateSrcSet } from '@/client/utils';\nexport type { TDriveFile, TImageQuality, TImageFormat } from '@/types/client';\nexport type * from '@/types/server';\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/header.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAexC,eAAO,MAAM,WAAW,yBAgSvB,CAAC"}
1
+ {"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/header.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAexC,eAAO,MAAM,WAAW,yBAuSvB,CAAC"}
@@ -3,6 +3,7 @@ import type { TDatabaseDrive, TDriveAPIResponse } from '../types/server';
3
3
  import type { TDrivePathItem, TDriveQuota, TDriveFile, TImageQuality, TImageFormat } from '../types/client';
4
4
  export type TDriveContext = {
5
5
  apiEndpoint: string;
6
+ withCredentials: boolean;
6
7
  currentFolderId: string | null;
7
8
  path: TDrivePathItem[];
8
9
  items: TDatabaseDrive[];
@@ -82,6 +83,7 @@ export declare const DriveProvider: (props: Readonly<{
82
83
  maxFile?: number;
83
84
  };
84
85
  defaultSelectedFileIds?: string[];
86
+ withCredentials?: boolean;
85
87
  }>) => React.JSX.Element;
86
88
  export declare const useDrive: () => TDriveContext;
87
89
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/client/context.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/client/context.tsx"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { TDriveUploadState } from '../../types/client';
2
- export declare const useUpload: (apiEndpoint: string, activeAccountId: string | null, onUploadComplete?: (item: any) => void) => {
2
+ export declare const useUpload: (apiEndpoint: string, activeAccountId: string | null, withCredentials?: boolean, onUploadComplete?: (item: any) => void) => {
3
3
  uploads: TDriveUploadState[];
4
4
  uploadFiles: (files: File[], folderId: string | null) => Promise<void>;
5
5
  cancelUpload: (id: string) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"useUpload.d.ts","sourceRoot":"","sources":["../../../src/client/hooks/useUpload.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAYxD,eAAO,MAAM,SAAS,GAAI,aAAa,MAAM,EAAE,iBAAiB,MAAM,GAAG,IAAI,EAAE,mBAAmB,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI;;yBAuHnE,IAAI,EAAE,YAAY,MAAM,GAAG,IAAI;uBAqBjC,MAAM;;CA0CrD,CAAC"}
1
+ {"version":3,"file":"useUpload.d.ts","sourceRoot":"","sources":["../../../src/client/hooks/useUpload.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAYxD,eAAO,MAAM,SAAS,GAAI,aAAa,MAAM,EAAE,iBAAiB,MAAM,GAAG,IAAI,EAAE,kBAAiB,OAAe,EAAE,mBAAmB,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI;;yBA2HxG,IAAI,EAAE,YAAY,MAAM,GAAG,IAAI;uBAsBjE,MAAM;;CA+ClB,CAAC"}