@muhgholy/next-drive 2.2.0 → 2.2.1
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/dist/{chunk-5C6YUPCM.js → chunk-F5SLCUJ5.js} +26 -8
- package/dist/chunk-F5SLCUJ5.js.map +1 -0
- package/dist/client/components/dialog.d.ts.map +1 -1
- package/dist/client/components/drive/dnd-provider.d.ts +2 -2
- package/dist/client/components/drive/dnd-provider.d.ts.map +1 -1
- package/dist/client/components/drive/explorer.d.ts.map +1 -1
- package/dist/client/components/drive/file-grid.d.ts.map +1 -1
- package/dist/client/components/drive/header.d.ts +4 -1
- package/dist/client/components/drive/header.d.ts.map +1 -1
- package/dist/client/components/drive/path-bar.d.ts +3 -1
- package/dist/client/components/drive/path-bar.d.ts.map +1 -1
- package/dist/client/components/drive/sidebar.d.ts +3 -1
- package/dist/client/components/drive/sidebar.d.ts.map +1 -1
- package/dist/client/components/drive/storage/indicator.d.ts.map +1 -1
- package/dist/client/components/drive/upload.d.ts.map +1 -1
- package/dist/client/components/ui/progress.d.ts +2 -1
- package/dist/client/components/ui/progress.d.ts.map +1 -1
- package/dist/client/components/ui/sheet.d.ts.map +1 -1
- package/dist/client/context.d.ts +4 -0
- package/dist/client/context.d.ts.map +1 -1
- package/dist/client/file-chooser.d.ts.map +1 -1
- package/dist/client/index.css +11 -0
- package/dist/client/index.css.map +1 -1
- package/dist/client/index.js +467 -281
- package/dist/client/index.js.map +1 -1
- package/dist/client/styles.css +53 -40
- package/dist/server/express.js +2 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/providers/google.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-5C6YUPCM.js.map +0 -1
|
@@ -417,7 +417,7 @@ var GoogleDriveProvider = {
|
|
|
417
417
|
do {
|
|
418
418
|
const res = await drive.files.list({
|
|
419
419
|
q: `'${googleParentId}' in parents and trashed = false`,
|
|
420
|
-
fields: "nextPageToken, files(id, name, mimeType, size, webViewLink, iconLink, thumbnailLink)",
|
|
420
|
+
fields: "nextPageToken, files(id, name, mimeType, size, webViewLink, iconLink, thumbnailLink, createdTime)",
|
|
421
421
|
pageSize: 1e3,
|
|
422
422
|
pageToken: nextPageToken
|
|
423
423
|
});
|
|
@@ -450,13 +450,14 @@ var GoogleDriveProvider = {
|
|
|
450
450
|
status: "READY",
|
|
451
451
|
trashedAt: null
|
|
452
452
|
};
|
|
453
|
+
const insertData = file.createdTime ? { createdAt: new Date(file.createdTime) } : {};
|
|
453
454
|
await drive_default.findOneAndUpdate(
|
|
454
455
|
{
|
|
455
456
|
owner,
|
|
456
457
|
"provider.google.id": file.id,
|
|
457
458
|
"provider.type": "GOOGLE"
|
|
458
459
|
},
|
|
459
|
-
{ $set: updateData },
|
|
460
|
+
{ $set: updateData, $setOnInsert: insertData },
|
|
460
461
|
{ upsert: true, new: true, setDefaultsOnInsert: true }
|
|
461
462
|
);
|
|
462
463
|
}
|
|
@@ -481,7 +482,7 @@ var GoogleDriveProvider = {
|
|
|
481
482
|
do {
|
|
482
483
|
const res = await drive.files.list({
|
|
483
484
|
q: "trashed = true",
|
|
484
|
-
fields: "nextPageToken, files(id, name, mimeType, size, webViewLink, iconLink, thumbnailLink)",
|
|
485
|
+
fields: "nextPageToken, files(id, name, mimeType, size, webViewLink, iconLink, thumbnailLink, createdTime)",
|
|
485
486
|
pageSize: 100,
|
|
486
487
|
// Limit sync for performance
|
|
487
488
|
pageToken: nextPageToken
|
|
@@ -492,6 +493,7 @@ var GoogleDriveProvider = {
|
|
|
492
493
|
if (!file.id || !file.name || !file.mimeType) continue;
|
|
493
494
|
const isFolder = file.mimeType === "application/vnd.google-apps.folder";
|
|
494
495
|
const sizeInBytes = file.size ? parseInt(file.size) : 0;
|
|
496
|
+
const insertData = file.createdTime ? { createdAt: new Date(file.createdTime) } : {};
|
|
495
497
|
await drive_default.findOneAndUpdate(
|
|
496
498
|
{ owner, "provider.google.id": file.id, "provider.type": "GOOGLE" },
|
|
497
499
|
{
|
|
@@ -514,7 +516,8 @@ var GoogleDriveProvider = {
|
|
|
514
516
|
}
|
|
515
517
|
},
|
|
516
518
|
trashedAt: /* @__PURE__ */ new Date()
|
|
517
|
-
}
|
|
519
|
+
},
|
|
520
|
+
$setOnInsert: insertData
|
|
518
521
|
},
|
|
519
522
|
{ upsert: true, setDefaultsOnInsert: true }
|
|
520
523
|
);
|
|
@@ -526,7 +529,7 @@ var GoogleDriveProvider = {
|
|
|
526
529
|
const drive = google.drive({ version: "v3", auth: client });
|
|
527
530
|
const res = await drive.files.list({
|
|
528
531
|
q: `name contains '${query}' and trashed = false`,
|
|
529
|
-
fields: "files(id, name, mimeType, size, parents, webViewLink, iconLink, thumbnailLink)",
|
|
532
|
+
fields: "files(id, name, mimeType, size, parents, webViewLink, iconLink, thumbnailLink, createdTime)",
|
|
530
533
|
pageSize: 50
|
|
531
534
|
});
|
|
532
535
|
const files = res.data.files || [];
|
|
@@ -535,6 +538,7 @@ var GoogleDriveProvider = {
|
|
|
535
538
|
const isFolder = file.mimeType === "application/vnd.google-apps.folder";
|
|
536
539
|
if (!isFolder && file.mimeType?.startsWith("application/vnd.google-apps.")) continue;
|
|
537
540
|
const sizeInBytes = file.size ? parseInt(file.size) : 0;
|
|
541
|
+
const insertData = file.createdTime ? { createdAt: new Date(file.createdTime) } : {};
|
|
538
542
|
await drive_default.findOneAndUpdate(
|
|
539
543
|
{ owner, "provider.google.id": file.id, "metadata.type": "GOOGLE" },
|
|
540
544
|
{
|
|
@@ -560,7 +564,8 @@ var GoogleDriveProvider = {
|
|
|
560
564
|
}
|
|
561
565
|
// Don't overwrite parentId if it exists.
|
|
562
566
|
// New items will default to null (Root) via schema default
|
|
563
|
-
}
|
|
567
|
+
},
|
|
568
|
+
$setOnInsert: insertData
|
|
564
569
|
},
|
|
565
570
|
{ upsert: true, setDefaultsOnInsert: true }
|
|
566
571
|
);
|
|
@@ -973,6 +978,19 @@ var driveAPIHandler = async (req, res) => {
|
|
|
973
978
|
const information = await getDriveInformation(req);
|
|
974
979
|
const { key: owner } = information;
|
|
975
980
|
const STORAGE_PATH = config.storage.path;
|
|
981
|
+
if (action === "information") {
|
|
982
|
+
const { clientId, clientSecret, redirectUri } = config.storage?.google || {};
|
|
983
|
+
const googleConfigured = !!(clientId && clientSecret && redirectUri);
|
|
984
|
+
return res.status(200).json({
|
|
985
|
+
status: 200,
|
|
986
|
+
message: "Information retrieved",
|
|
987
|
+
data: {
|
|
988
|
+
providers: {
|
|
989
|
+
google: googleConfigured
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
}
|
|
976
994
|
if (["getAuthUrl", "callback", "listAccounts", "removeAccount"].includes(action)) {
|
|
977
995
|
switch (action) {
|
|
978
996
|
case "getAuthUrl": {
|
|
@@ -1461,5 +1479,5 @@ var driveAPIHandler = async (req, res) => {
|
|
|
1461
1479
|
};
|
|
1462
1480
|
|
|
1463
1481
|
export { driveAPIHandler, driveConfiguration, driveFilePath, driveFileSchemaZod, driveGetUrl, driveReadFile, getDriveConfig, getDriveInformation };
|
|
1464
|
-
//# sourceMappingURL=chunk-
|
|
1465
|
-
//# sourceMappingURL=chunk-
|
|
1482
|
+
//# sourceMappingURL=chunk-F5SLCUJ5.js.map
|
|
1483
|
+
//# sourceMappingURL=chunk-F5SLCUJ5.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-F5SLCUJ5.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\tmessage: '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\treturn (\r\n\t\tname\r\n\t\t\t.replace(/[<>:\"|?*\\x00-\\x1F]/g, '') // Remove dangerous chars\r\n\t\t\t.replace(/^\\.+/, '') // Remove leading dots\r\n\t\t\t.replace(/\\.+$/, '') // Remove trailing dots\r\n\t\t\t.replace(/\\\\/g, '/') // Normalize slashes\r\n\t\t\t.replace(/\\/+/g, '/') // Remove duplicate slashes\r\n\t\t\t.replace(/\\.\\.\\//g, '') // Remove path traversal\r\n\t\t\t.replace(/\\.\\.+/g, '') // Remove remaining ..\r\n\t\t\t.split('/')\r\n\t\t\t.pop() ||\r\n\t\t'' // Take only the filename part (remove all paths)\r\n\t\t\t.trim()\r\n\t\t\t.slice(0, 255)\r\n\t); // Limit length\r\n};\r\n\r\n// ** Sanitize search query for regex\r\nconst sanitizeRegexInput = (input: string): string => {\r\n\t// Escape regex special characters\r\n\treturn input.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').slice(0, 100);\r\n};\r\n\r\n// ** File/Folder name schema\r\nconst nameSchema = z\r\n\t.string()\r\n\t.min(1, 'Name is required')\r\n\t.max(255, 'Name too long')\r\n\t.transform(sanitizeFilename)\r\n\t.refine(val => val.length > 0, { message: 'Invalid name after sanitization' });\r\n\r\n// ** Upload chunk schema\r\nexport const uploadChunkSchema = z\r\n\t.object({\r\n\t\tchunkIndex: z.number().int().min(0).max(10000),\r\n\t\ttotalChunks: z.number().int().min(1).max(10000),\r\n\t\tdriveId: z.string().optional(),\r\n\t\tfileName: nameSchema,\r\n\t\tfileSize: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),\r\n\t\tfileType: z.string().min(1).max(255),\r\n\t\tfolderId: z.string().optional(),\r\n\t})\r\n\t.refine(data => data.chunkIndex < data.totalChunks, {\r\n\t\tmessage: 'Chunk index must be less than total chunks',\r\n\t});\r\n\r\n// ** List query schema\r\nexport const listQuerySchema = z.object({\r\n\tfolderId: z.union([z.literal('root'), objectIdSchema, z.undefined()]),\r\n\tlimit: z\r\n\t\t.string()\r\n\t\t.optional()\r\n\t\t.transform(val => {\r\n\t\t\tconst num = parseInt(val || '50', 10);\r\n\t\t\treturn Math.min(Math.max(1, num), 100);\r\n\t\t}),\r\n\tafterId: objectIdSchema.optional(),\r\n});\r\n\r\n// ** Serve query schema\r\nexport const serveQuerySchema = z.object({\r\n\tid: objectIdSchema,\r\n\ttoken: z.string().optional(),\r\n\tq: z.enum(['ultralow', 'low', 'medium', 'high', 'normal']).optional(),\r\n\tformat: z.enum(['webp', 'jpeg', 'png']).optional(),\r\n});\r\n\r\n// ** Thumbnail query schema\r\nexport const thumbnailQuerySchema = z.object({\r\n\tid: objectIdSchema,\r\n\tsize: z.enum(['small', 'medium', 'large']).optional().default('medium'),\r\n\ttoken: z.string().optional(),\r\n});\r\n\r\n// ** Rename body schema\r\nexport const renameBodySchema = z.object({\r\n\tid: objectIdSchema,\r\n\tnewName: nameSchema,\r\n});\r\n\r\n// ** Delete query schema\r\nexport const deleteQuerySchema = z.object({\r\n\tid: objectIdSchema,\r\n});\r\n\r\n// ** Delete many body schema\r\nexport const deleteManyBodySchema = z.object({\r\n\tids: 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\tname: nameSchema,\r\n\tparentId: 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\tids: z.array(objectIdSchema).min(1).max(1000),\r\n\ttargetFolderId: 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\tids: z.array(objectIdSchema).min(1).max(1000),\r\n});\r\n\r\n// ** Search query schema\r\nexport const searchQuerySchema = z.object({\r\n\tq: z.string().min(1).max(100).transform(sanitizeRegexInput),\r\n\tfolderId: z.union([z.literal('root'), objectIdSchema, z.undefined()]).optional(),\r\n\tlimit: z\r\n\t\t.string()\r\n\t\t.optional()\r\n\t\t.transform(val => {\r\n\t\t\tconst num = parseInt(val || '50', 10);\r\n\t\t\treturn Math.min(Math.max(1, num), 100);\r\n\t\t}),\r\n\ttrashed: z\r\n\t\t.string()\r\n\t\t.optional()\r\n\t\t.transform(val => val === 'true'),\r\n});\r\n\r\n// ** Restore query schema\r\nexport const restoreQuerySchema = z.object({\r\n\tid: 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\tid: z.string().uuid(),\r\n});\r\n\r\n// ** Purge trash query schema\r\nexport const purgeTrashQuerySchema = z.object({\r\n\tdays: 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\tid: z.string(),\r\n\tfile: z.object({\r\n\t\tname: z.string(),\r\n\t\tmime: z.string(),\r\n\t\tsize: z.number(),\r\n\t}),\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\tname: 'LOCAL',\n\n\tsync: async (folderId, owner, accountId) => {\n\t\t// No-op for local storage as DB is the source of truth\n\t},\n\n\tsearch: async (query, owner, accountId) => {\n\t\t// No-op for local storage as DB text search handles it\n\t},\n\n\tgetQuota: async (owner, accountId, configuredQuotaInBytes) => {\n\t\t// Calculate storage used from DB\n\t\tconst result = await Drive.aggregate([{ $match: { owner, 'information.type': 'FILE', trashedAt: null } }, { $group: { _id: null, total: { $sum: '$information.sizeInBytes' } } }]);\n\t\tconst usedInBytes = result[0]?.total || 0;\n\n\t\t// Use configured quota from user's information callback (required)\n\t\treturn { usedInBytes, quotaInBytes: configuredQuotaInBytes ?? 0 };\n\t},\n\n\topenStream: async (item: IDatabaseDriveDocument, accountId?: string) => {\n\t\tif (item.information.type !== 'FILE') throw new Error('Cannot stream folder');\n\t\tconst filePath = path.join(getDriveConfig().storage.path, item.information.path);\n\n\t\tif (!fs.existsSync(filePath)) {\n\t\t\tthrow new Error('File not found on disk');\n\t\t}\n\n\t\tconst stat = fs.statSync(filePath);\n\t\tconst stream = fs.createReadStream(filePath);\n\n\t\treturn {\n\t\t\tstream,\n\t\t\tmime: item.information.mime,\n\t\t\tsize: stat.size,\n\t\t};\n\t},\n\n\tgetThumbnail: async (item: IDatabaseDriveDocument, accountId?: string) => {\n\t\tif (item.information.type !== 'FILE') throw new Error('No thumbnail for folder');\n\n\t\tconst storagePath = getDriveConfig().storage.path;\n\t\tconst originalPath = path.join(storagePath, item.information.path);\n\t\tconst thumbPath = path.join(storagePath, 'cache', 'thumbnails', `${item._id.toString()}.webp`);\n\n\t\tif (!fs.existsSync(originalPath)) throw new Error('Original file not found');\n\n\t\tif (fs.existsSync(thumbPath)) {\n\t\t\treturn fs.createReadStream(thumbPath);\n\t\t}\n\n\t\t// Generate thumbnail\n\t\tif (!fs.existsSync(path.dirname(thumbPath))) fs.mkdirSync(path.dirname(thumbPath), { recursive: true });\n\n\t\tif (item.information.mime.startsWith('image/')) {\n\t\t\tawait sharp(originalPath).resize(300, 300, { fit: 'inside' }).toFormat('webp', { quality: 80 }).toFile(thumbPath);\n\t\t} else if (item.information.mime.startsWith('video/')) {\n\t\t\tawait new Promise((resolve, reject) => {\n\t\t\t\tffmpeg(originalPath)\n\t\t\t\t\t.screenshots({\n\t\t\t\t\t\tcount: 1,\n\t\t\t\t\t\tfolder: path.dirname(thumbPath),\n\t\t\t\t\t\tfilename: path.basename(thumbPath),\n\t\t\t\t\t\tsize: '300x?',\n\t\t\t\t\t})\n\t\t\t\t\t.on('end', resolve)\n\t\t\t\t\t.on('error', reject);\n\t\t\t});\n\t\t} else {\n\t\t\tthrow new Error('Unsupported mime type for thumbnail');\n\t\t}\n\n\t\treturn fs.createReadStream(thumbPath);\n\t},\n\n\tcreateFolder: async (name, parentId, owner, accountId) => {\n\t\t// Just DB operation for local folders (virtual)\n\t\tconst getNextOrderValue = async (owner: Record<string, unknown> | null): Promise<number> => {\n\t\t\tconst lastItem = await Drive.findOne({ owner }, {}, { sort: { order: -1 } });\n\t\t\treturn lastItem ? lastItem.order + 1 : 0;\n\t\t};\n\n\t\tconst folder = new Drive({\n\t\t\towner,\n\t\t\tname,\n\t\t\tparentId: parentId === 'root' || !parentId ? null : parentId,\n\t\t\torder: await getNextOrderValue(owner),\n\t\t\tprovider: { type: 'LOCAL' },\n\t\t\tinformation: { type: 'FOLDER' },\n\t\t\tstatus: 'READY',\n\t\t});\n\t\tawait folder.save();\n\t\treturn folder.toClient();\n\t},\n\n\tuploadFile: async (drive, filePath, accountId) => {\n\t\tif (drive.information.type !== 'FILE') throw new Error('Invalid drive type');\n\n\t\t// Move temp file to final destination\n\t\tconst destPath = path.join(getDriveConfig().storage.path, drive.information.path);\n\t\tconst dirPath = path.dirname(destPath);\n\t\tif (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath, { recursive: true });\n\n\t\t// Rename (move)\n\t\tfs.renameSync(filePath, destPath);\n\n\t\tdrive.status = 'READY';\n\t\tdrive.information.hash = await computeFileHash(destPath);\n\n\t\tif (drive.information.mime.startsWith('image/')) {\n\t\t\tconst meta = await extractImageMetadata(destPath);\n\t\t\tif (meta) {\n\t\t\t\tdrive.information.width = meta.width;\n\t\t\t\tdrive.information.height = meta.height;\n\t\t\t}\n\t\t}\n\n\t\tawait drive.save();\n\t\treturn drive.toClient();\n\t},\n\n\tdelete: async (ids, owner, accountId) => {\n\t\tconst items = await Drive.find({ _id: { $in: ids }, owner }).lean();\n\n\t\t// Helper to recursively get all children\n\t\tconst getAllChildren = async (folderIds: string[]): Promise<any[]> => {\n\t\t\tconst children = await Drive.find({ parentId: { $in: folderIds }, owner }).lean();\n\t\t\tif (children.length === 0) return [];\n\n\t\t\tconst subFolderIds = children.filter(c => c.information.type === 'FOLDER').map(c => c._id.toString());\n\n\t\t\tconst subChildren = await getAllChildren(subFolderIds);\n\t\t\treturn [...children, ...subChildren];\n\t\t};\n\n\t\tconst folderIds = items.filter(i => i.information.type === 'FOLDER').map(i => i._id.toString());\n\t\tconst allChildren = await getAllChildren(folderIds);\n\t\tconst allItemsToDelete = [...items, ...allChildren];\n\n\t\t// Delete files from disk\n\t\tfor (const item of allItemsToDelete) {\n\t\t\tif (item.information.type === 'FILE' && item.information.path) {\n\t\t\t\t// Check if any other file points to this path (shouldn't happen in simple model but good hygiene)\n\t\t\t\t// Actually in this model, path is unique per file\n\t\t\t\tconst fullPath = path.join(getDriveConfig().storage.path, item.information.path);\n\t\t\t\tconst dirPath = path.dirname(fullPath); // .../drive/ID/\n\t\t\t\tif (fs.existsSync(dirPath)) {\n\t\t\t\t\tfs.rmSync(dirPath, { recursive: true, force: true });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Delete from DB\n\t\tawait Drive.deleteMany({ _id: { $in: allItemsToDelete.map(i => i._id) } });\n\t},\n\n\ttrash: async (ids, owner, accountId) => {\n\t\t// No-op for local, handled by DB update in index.ts\n\t},\n\n\tsyncTrash: async (owner, accountId) => {\n\t\t// No-op for local\n\t},\n\n\tuntrash: async (ids, owner, accountId) => {\n\t\t// No-op for local\n\t},\n\n\trename: async (id, newName, owner, accountId) => {\n\t\tconst item = await Drive.findOneAndUpdate({ _id: id, owner }, { name: newName }, { new: true });\n\t\tif (!item) throw new Error('Item not found');\n\t\treturn item.toClient();\n\t},\n\n\tmove: async (id, newParentId, owner, accountId) => {\n\t\tconst item = await Drive.findOne({ _id: id, owner });\n\t\tif (!item) throw new Error('Item not found');\n\n\t\t// Update DB\n\t\tconst oldParentId = item.parentId;\n\t\titem.parentId = newParentId === 'root' || !newParentId ? null : new mongoose.Types.ObjectId(newParentId);\n\n\t\t// For LOCAL, we might store files in flat structure or hierarchical?\n\t\t// Looking at uploadFile (lines 124): path.join(STORAGE_PATH, drive.information.path)\n\t\t// And line 171: path.join(STORAGE_PATH, item.information.path)\n\t\t// And line 374 in index.ts: drive.information.path = path.join('drive', String(drive._id), 'data.bin');\n\t\t// It seems path is ID-based: drive/<ID>/data.bin.\n\t\t// So moving a file DOES NOT change its physical path on disk if path is ID-based and flat?\n\t\t// Let's verify 'createFolder'. It just creates DB entry.\n\t\t// So hierarchy is virtual in DB. Physical storage is flat-ish (by ID).\n\t\t// IF so, 'move' is just DB update!\n\n\t\t// Let's double check implementation of 'uploadFile' in local.ts\n\t\t// Line 124: destPath = path.join(STORAGE_PATH, drive.information.path);\n\t\t// And 'path' seems to be set in index.ts line 374: `path.join('drive', String(drive._id), 'data.bin')`\n\t\t// So yes, physical path is detached from folder structure.\n\n\t\t// So for Local, only DB update is needed.\n\t\tawait item.save();\n\t\treturn item.toClient();\n\t},\n\n\trevokeToken: async (owner, accountId) => {\n\t\t// No-op\n\t},\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\t// 1. Get credentials from StorageAccount\n\tconst query: any = { owner, 'metadata.provider': 'GOOGLE' };\n\tif (accountId) query._id = accountId;\n\n\t// If multiple accounts and no accountId, we might pick a random one?\n\t// Ideally we should enforce accountId.\n\tconst account = await StorageAccount.findOne(query); // Pick first one if no ID specificied\n\tif (!account) throw new Error('Google Drive account not connected');\n\n\tconst config = getDriveConfig();\n\tconst { clientId, clientSecret, redirectUri } = config.storage?.google || {};\n\n\tif (!clientId || !clientSecret) throw new Error('Google credentials not configured on server');\n\n\tconst oAuth2Client = new google.auth.OAuth2(clientId, clientSecret, redirectUri);\n\n\t// Verify it's a google account and metadata exists\n\t// Note: StorageAccount schema might still use metadata.provider or just provider?\n\t// Based on previous grep, context.tsx had { provider: 'GOOGLE' }.\n\t// Usually StorageAccount keys are consistent.\n\t// If we only refactored Drive schema, StorageAccount might be unchanged.\n\t// But `src/server/database/mongoose/schema/drive.ts` was refactored.\n\t// I need to be careful about StorageAccount.\n\t// Let's assume StorageAccount is NOT changed in this refactor unless user asked.\n\t// User only mentioned \"Drive Schema\".\n\t// But my code in createAuthClient uses account.metadata.provider.\n\t// Let's keep it as is if StorageAccount wasn't refactored.\n\tif (account.metadata.provider !== 'GOOGLE' || !account.metadata.google) {\n\t\tthrow new Error('Invalid Google Account Metadata');\n\t}\n\n\toAuth2Client.setCredentials(account.metadata.google.credentials);\n\n\t// Update tokens listener\n\toAuth2Client.on('tokens', async tokens => {\n\t\tif (tokens.refresh_token) {\n\t\t\taccount.metadata.google.credentials = { ...account.metadata.google.credentials, ...tokens };\n\t\t\taccount.markModified('metadata');\n\t\t\tawait account.save();\n\t\t}\n\t});\n\n\treturn { client: oAuth2Client, accountId: account._id };\n};\n\nexport const GoogleDriveProvider: TStorageProvider = {\n\tname: 'GOOGLE',\n\n\tsync: async (folderId, owner, accountId) => {\n\t\tconst { client, accountId: foundAccountId } = await createAuthClient(owner, accountId);\n\t\tconst drive = google.drive({ version: 'v3', auth: client });\n\n\t\t// Resolve Google Folder ID\n\t\tlet googleParentId = 'root';\n\t\tif (folderId && folderId !== 'root') {\n\t\t\tconst folder = await Drive.findOne({ _id: folderId, owner });\n\t\t\tif (folder && folder.provider?.google?.id) {\n\t\t\t\tgoogleParentId = folder.provider.google.id;\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// List files from Google\n\t\t// Implement pagination loop\n\t\tlet nextPageToken: string | undefined = undefined;\n\t\t// Keep track of all synced IDs to identify deletions\n\t\tconst allSyncedGoogleIds = new Set<string>();\n\n\t\tdo {\n\t\t\tconst res: any = await drive.files.list({\n\t\t\t\tq: `'${googleParentId}' in parents and trashed = false`,\n\t\t\t\tfields: 'nextPageToken, files(id, name, mimeType, size, webViewLink, iconLink, thumbnailLink, createdTime)',\n\t\t\t\tpageSize: 1000,\n\t\t\t\tpageToken: nextPageToken,\n\t\t\t});\n\n\t\t\tnextPageToken = res.data.nextPageToken || undefined;\n\t\t\tconst files = res.data.files || [];\n\n\t\t\t// Upsert to MongoDB\n\t\t\tfor (const file of files) {\n\t\t\t\tif (!file.id || !file.name || !file.mimeType) continue;\n\n\t\t\t\t// Track ID\n\t\t\t\tallSyncedGoogleIds.add(file.id);\n\n\t\t\t\t// RELAXED FILTER: Allow Google Docs (application/vnd.google-apps.*)\n\t\t\t\tconst isFolder = file.mimeType === 'application/vnd.google-apps.folder';\n\t\t\t\t// if (!isFolder && file.mimeType.startsWith('application/vnd.google-apps.')) continue; // REMOVED FILTER\n\n\t\t\t\tconst sizeInBytes = file.size ? parseInt(file.size) : 0;\n\n\t\t\t\t// Construct update data\n\t\t\t\tconst updateData = {\n\t\t\t\t\tname: file.name,\n\t\t\t\t\tstorageAccountId: foundAccountId,\n\t\t\t\t\tparentId: folderId === 'root' ? null : folderId,\n\t\t\t\t\tinformation: {\n\t\t\t\t\t\ttype: isFolder ? 'FOLDER' : 'FILE',\n\t\t\t\t\t\tsizeInBytes,\n\t\t\t\t\t\tmime: file.mimeType,\n\t\t\t\t\t\tpath: '',\n\t\t\t\t\t},\n\t\t\t\t\tprovider: {\n\t\t\t\t\t\ttype: 'GOOGLE',\n\t\t\t\t\t\tgoogle: {\n\t\t\t\t\t\t\tid: file.id,\n\t\t\t\t\t\t\twebViewLink: file.webViewLink,\n\t\t\t\t\t\t\ticonLink: file.iconLink,\n\t\t\t\t\t\t\tthumbnailLink: file.thumbnailLink,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tstatus: 'READY',\n\t\t\t\t\ttrashedAt: null,\n\t\t\t\t};\n\n\t\t\t\t// Use source file's createdTime for createdAt on insert\n\t\t\t\tconst insertData = file.createdTime ? { createdAt: new Date(file.createdTime) } : {};\n\n\t\t\t\tawait Drive.findOneAndUpdate(\n\t\t\t\t\t{\n\t\t\t\t\t\towner,\n\t\t\t\t\t\t'provider.google.id': file.id,\n\t\t\t\t\t\t'provider.type': 'GOOGLE',\n\t\t\t\t\t},\n\t\t\t\t\t{ $set: updateData, $setOnInsert: insertData },\n\t\t\t\t\t{ upsert: true, new: true, setDefaultsOnInsert: true },\n\t\t\t\t);\n\t\t\t}\n\t\t} while (nextPageToken);\n\n\t\t// Handle deletions - remove items in DB that were NOT in the gathered list\n\t\tconst dbItems = await Drive.find({\n\t\t\towner,\n\t\t\tstorageAccountId: foundAccountId,\n\t\t\tparentId: folderId === 'root' ? null : folderId,\n\t\t\t'provider.type': 'GOOGLE',\n\t\t});\n\n\t\tfor (const item of dbItems) {\n\t\t\t// If item has a google ID and it wasn't seen in the sync list -> trash it\n\t\t\tif (item.provider?.google?.id && !allSyncedGoogleIds.has(item.provider.google.id)) {\n\t\t\t\titem.trashedAt = new Date();\n\t\t\t\tawait item.save();\n\t\t\t}\n\t\t}\n\t},\n\n\tsyncTrash: async (owner, accountId) => {\n\t\tconst { client, accountId: foundAccountId } = await createAuthClient(owner, accountId);\n\t\tconst drive = google.drive({ version: 'v3', auth: client });\n\n\t\t// List trashed files from Google\n\t\tlet nextPageToken: string | undefined = undefined;\n\n\t\tdo {\n\t\t\tconst res: any = await drive.files.list({\n\t\t\t\tq: 'trashed = true',\n\t\t\t\tfields: 'nextPageToken, files(id, name, mimeType, size, webViewLink, iconLink, thumbnailLink, createdTime)',\n\t\t\t\tpageSize: 100, // Limit sync for performance\n\t\t\t\tpageToken: nextPageToken,\n\t\t\t});\n\n\t\t\tnextPageToken = res.data.nextPageToken || undefined;\n\t\t\tconst files = res.data.files || [];\n\n\t\t\tfor (const file of files) {\n\t\t\t\tif (!file.id || !file.name || !file.mimeType) continue;\n\n\t\t\t\t// RELAXED FILTER: Allow Google Docs (application/vnd.google-apps.*)\n\t\t\t\tconst isFolder = file.mimeType === 'application/vnd.google-apps.folder';\n\n\t\t\t\tconst sizeInBytes = file.size ? parseInt(file.size) : 0;\n\n\t\t\t\t// Use source file's createdTime for createdAt on insert\n\t\t\t\tconst insertData = file.createdTime ? { createdAt: new Date(file.createdTime) } : {};\n\n\t\t\t\tawait Drive.findOneAndUpdate(\n\t\t\t\t\t{ owner, 'provider.google.id': file.id, 'provider.type': 'GOOGLE' },\n\t\t\t\t\t{\n\t\t\t\t\t\t$set: {\n\t\t\t\t\t\t\tname: file.name,\n\t\t\t\t\t\t\tstorageAccountId: foundAccountId,\n\t\t\t\t\t\t\tinformation: {\n\t\t\t\t\t\t\t\ttype: isFolder ? 'FOLDER' : 'FILE',\n\t\t\t\t\t\t\t\tsizeInBytes,\n\t\t\t\t\t\t\t\tmime: file.mimeType,\n\t\t\t\t\t\t\t\tpath: '',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tprovider: {\n\t\t\t\t\t\t\t\ttype: 'GOOGLE',\n\t\t\t\t\t\t\t\tgoogle: {\n\t\t\t\t\t\t\t\t\tid: file.id,\n\t\t\t\t\t\t\t\t\twebViewLink: file.webViewLink,\n\t\t\t\t\t\t\t\t\ticonLink: file.iconLink,\n\t\t\t\t\t\t\t\t\tthumbnailLink: file.thumbnailLink,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttrashedAt: new Date(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t$setOnInsert: insertData,\n\t\t\t\t\t},\n\t\t\t\t\t{ upsert: true, setDefaultsOnInsert: true },\n\t\t\t\t);\n\t\t\t}\n\t\t} while (nextPageToken);\n\t},\n\n\tsearch: async (query, owner, accountId) => {\n\t\tconst { client, accountId: foundAccountId } = await createAuthClient(owner, accountId);\n\t\tconst drive = google.drive({ version: 'v3', auth: client });\n\n\t\t// Google Search Query\n\t\t// name contains 'query'\n\t\tconst res = await drive.files.list({\n\t\t\tq: `name contains '${query}' and trashed = false`,\n\t\t\tfields: 'files(id, name, mimeType, size, parents, webViewLink, iconLink, thumbnailLink, createdTime)',\n\t\t\tpageSize: 50,\n\t\t});\n\n\t\tconst files = res.data.files || [];\n\n\t\t// Upsert results\n\t\t// Note: We might not know the local parentId for these items if we haven't synced their parents.\n\t\t// This makes it tricky. If we just upsert with parentId=null (root), they show up in root, which is confusing.\n\t\t// Option: Don't change parentId if exists. If new, maybe leave parentId null/undefined but we need it.\n\t\t// Strategy: Just update existing items metadata?\n\t\t// OR: \"Search\" just returns items without persisting parent structure?\n\t\t// But our UI relies on DB.\n\t\t// If we upsert new items from search, we must assign a parent.\n\t\t// Typically we can't assign accurate local parent ID without traversing up.\n\t\t// Compromise: Update properties of existing items. Ignore new items?\n\t\t// OR: Just let `list` handle creation. Search only works on things we've synced?\n\t\t// NO, user wants to find remote files.\n\t\t// Allow creating with parentId = null (root) for now? Or keep them \"orphaned\" (parentId: undefined) if that works?\n\t\t// Drive schema requires parentId? default null.\n\t\t// Let's skip upserting NEW items from search for now to avoid mess.\n\t\t// Only update existing.\n\t\t// Wait, if I search for \"Report\", I want to see \"Report.pdf\" even if I never opened the folder.\n\t\t// This implies I need to sync it.\n\t\t// For now, I will NOT upsert in search to keep safety. search only funds synced items.\n\t\t// Re-evaluating: The prompt said \"Search... mapping user queries to Google's q syntax\".\n\t\t// This implies meaningful results.\n\t\t// Let's implement basics: Sync results to DB. Parent = null (Root) if unknown.\n\t\t// Users can then \"Go to location\" -> might fail if path unknown.\n\t\t// Just upserting with `parentId: null` puts them in root.\n\t\t// I will omit parentId in update, so it keeps existing. If new, it defaults to null (Root).\n\t\t// This is acceptable behavior for \"All files\" view or similar.\n\n\t\tfor (const file of files) {\n\t\t\tif (!file.id || !file.name) continue;\n\t\t\tconst isFolder = file.mimeType === 'application/vnd.google-apps.folder';\n\t\t\tif (!isFolder && file.mimeType?.startsWith('application/vnd.google-apps.')) continue;\n\n\t\t\tconst sizeInBytes = file.size ? parseInt(file.size) : 0;\n\n\t\t\t// Use source file's createdTime for createdAt on insert\n\t\t\tconst insertData = file.createdTime ? { createdAt: new Date(file.createdTime) } : {};\n\n\t\t\tawait Drive.findOneAndUpdate(\n\t\t\t\t{ owner, 'provider.google.id': file.id, 'metadata.type': 'GOOGLE' },\n\t\t\t\t{\n\t\t\t\t\t$set: {\n\t\t\t\t\t\tname: file.name,\n\t\t\t\t\t\tstorageAccountId: foundAccountId,\n\t\t\t\t\t\tinformation: {\n\t\t\t\t\t\t\ttype: isFolder ? 'FOLDER' : 'FILE',\n\t\t\t\t\t\t\tsizeInBytes,\n\t\t\t\t\t\t\tmime: file.mimeType,\n\t\t\t\t\t\t\tpath: '',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\ttype: 'GOOGLE',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tprovider: {\n\t\t\t\t\t\t\tgoogle: {\n\t\t\t\t\t\t\t\tid: file.id,\n\t\t\t\t\t\t\t\twebViewLink: file.webViewLink,\n\t\t\t\t\t\t\t\ticonLink: file.iconLink,\n\t\t\t\t\t\t\t\tthumbnailLink: file.thumbnailLink,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// Don't overwrite parentId if it exists.\n\t\t\t\t\t\t// New items will default to null (Root) via schema default\n\t\t\t\t\t},\n\t\t\t\t\t$setOnInsert: insertData,\n\t\t\t\t},\n\t\t\t\t{ upsert: true, setDefaultsOnInsert: true },\n\t\t\t);\n\t\t}\n\t},\n\n\tgetQuota: async (owner, accountId, _configuredQuotaInBytes) => {\n\t\t// Google Drive uses its own quota from the API, ignores configured quota\n\t\ttry {\n\t\t\tconst { client } = await createAuthClient(owner, accountId);\n\t\t\tconst drive = google.drive({ version: 'v3', auth: client });\n\t\t\tconst res: any = await drive.about.get({ fields: 'storageQuota' });\n\t\t\treturn {\n\t\t\t\tusedInBytes: parseInt(res.data.storageQuota?.usage || '0'),\n\t\t\t\tquotaInBytes: parseInt(res.data.storageQuota?.limit || '0'),\n\t\t\t};\n\t\t} catch {\n\t\t\treturn { usedInBytes: 0, quotaInBytes: 0 };\n\t\t}\n\t},\n\n\topenStream: async (item: IDatabaseDriveDocument, accountId?: string) => {\n\t\tconst { client } = await createAuthClient(item.owner, accountId || item.storageAccountId?.toString());\n\t\tconst drive = google.drive({ version: 'v3', auth: client });\n\n\t\tif (!item.provider?.google?.id) throw new Error('Missing Google File ID');\n\n\t\t// Check if we can stream functionality\n\t\tif (item.information.type === 'FOLDER') throw new Error('Cannot stream folder');\n\n\t\tconst res: any = await drive.files.get({ fileId: item.provider.google.id, alt: 'media' }, { responseType: 'stream' });\n\n\t\treturn {\n\t\t\tstream: res.data as Readable,\n\t\t\tmime: item.information.mime,\n\t\t\tsize: item.information.sizeInBytes,\n\t\t};\n\t},\n\n\tgetThumbnail: async (item: IDatabaseDriveDocument, accountId?: string) => {\n\t\tconst { client } = await createAuthClient(item.owner, accountId || item.storageAccountId?.toString());\n\n\t\tif (!item.provider?.google?.thumbnailLink) throw new Error('No thumbnail available');\n\n\t\tconst res: any = await client.request({ url: item.provider.google.thumbnailLink, responseType: 'stream' });\n\t\treturn res.data as Readable;\n\t},\n\n\tcreateFolder: async (name, parentId, owner, accountId) => {\n\t\tconst { client, accountId: foundAccountId } = await createAuthClient(owner, accountId);\n\t\tconst drive = google.drive({ version: 'v3', auth: client });\n\n\t\tlet googleParentId = 'root';\n\t\tif (parentId && parentId !== 'root') {\n\t\t\tconst parent = await Drive.findOne({ _id: parentId, owner });\n\t\t\tif (parent?.provider?.google?.id) googleParentId = parent.provider.google.id;\n\t\t}\n\n\t\tconst res: any = await drive.files.create({\n\t\t\trequestBody: {\n\t\t\t\tname,\n\t\t\t\tmimeType: 'application/vnd.google-apps.folder',\n\t\t\t\tparents: [googleParentId],\n\t\t\t},\n\t\t\tfields: 'id, name, mimeType, webViewLink, iconLink',\n\t\t});\n\n\t\tconst file = res.data;\n\t\tif (!file.id) throw new Error('Failed to create folder on Google Drive');\n\n\t\t// Create local record\n\t\tconst folder = new Drive({\n\t\t\towner,\n\t\t\tname: file.name,\n\t\t\tparentId: parentId === 'root' || !parentId ? null : parentId,\n\t\t\tprovider: {\n\t\t\t\ttype: 'GOOGLE',\n\t\t\t\tgoogle: {\n\t\t\t\t\tid: file.id,\n\t\t\t\t\twebViewLink: file.webViewLink,\n\t\t\t\t\ticonLink: file.iconLink,\n\t\t\t\t},\n\t\t\t},\n\t\t\tstorageAccountId: foundAccountId,\n\t\t\tinformation: { type: 'FOLDER' },\n\t\t\tstatus: 'READY',\n\t\t});\n\t\tawait folder.save();\n\t\treturn folder.toClient();\n\t},\n\n\tuploadFile: async (drive, filePath, accountId) => {\n\t\tif (drive.information.type !== 'FILE') throw new Error('Invalid drive type');\n\n\t\tconst { client } = await createAuthClient(drive.owner, accountId || drive.storageAccountId?.toString());\n\t\tconst googleDrive = google.drive({ version: 'v3', auth: client });\n\n\t\tlet googleParentId = 'root';\n\t\tif (drive.parentId) {\n\t\t\tconst parent = await Drive.findById(drive.parentId);\n\t\t\tif (parent?.provider?.google?.id) googleParentId = parent.provider.google.id;\n\t\t}\n\n\t\ttry {\n\t\t\tconst res: any = await googleDrive.files.create({\n\t\t\t\trequestBody: {\n\t\t\t\t\tname: drive.name,\n\t\t\t\t\tparents: [googleParentId],\n\t\t\t\t\tmimeType: drive.information.mime,\n\t\t\t\t},\n\t\t\t\tmedia: {\n\t\t\t\t\tmimeType: drive.information.mime,\n\t\t\t\t\tbody: fs.createReadStream(filePath),\n\t\t\t\t},\n\t\t\t\tfields: 'id, name, mimeType, webViewLink, iconLink, thumbnailLink, size',\n\t\t\t});\n\n\t\t\tconst gFile = res.data;\n\t\t\tif (!gFile.id) throw new Error('Upload to Google Drive failed');\n\n\t\t\t// Update Drive record\n\t\t\tdrive.status = 'READY';\n\t\t\tdrive.provider = {\n\t\t\t\ttype: 'GOOGLE',\n\t\t\t\tgoogle: {\n\t\t\t\t\tid: gFile.id,\n\t\t\t\t\twebViewLink: gFile.webViewLink || undefined,\n\t\t\t\t\ticonLink: gFile.iconLink || undefined,\n\t\t\t\t\tthumbnailLink: gFile.thumbnailLink || undefined,\n\t\t\t\t},\n\t\t\t};\n\n\t\t\t// Note: We don't delete the temp file here, index.ts handles cleanup\n\t\t} catch (error) {\n\t\t\tdrive.status = 'FAILED';\n\t\t\tconsole.error('Google Upload Error:', error);\n\t\t\tthrow error;\n\t\t}\n\n\t\tawait drive.save();\n\t\treturn drive.toClient();\n\t},\n\n\tdelete: async (ids, owner, accountId) => {\n\t\tconst { client } = await createAuthClient(owner, accountId);\n\t\tconst drive = google.drive({ version: 'v3', auth: client });\n\n\t\tconst items = await Drive.find({ _id: { $in: ids }, owner });\n\n\t\tfor (const item of items) {\n\t\t\tif (item.provider?.google?.id) {\n\t\t\t\ttry {\n\t\t\t\t\tawait drive.files.delete({ fileId: item.provider.google.id });\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error('Failed to delete Google file', e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tawait Drive.deleteMany({ _id: { $in: ids } });\n\t},\n\n\ttrash: async (ids, owner, accountId) => {\n\t\tconst { client } = await createAuthClient(owner, accountId);\n\t\tconst drive = google.drive({ version: 'v3', auth: client });\n\n\t\tconst items = await Drive.find({ _id: { $in: ids }, owner });\n\n\t\tfor (const item of items) {\n\t\t\tif (item.provider?.google?.id) {\n\t\t\t\ttry {\n\t\t\t\t\tawait drive.files.update({\n\t\t\t\t\t\tfileId: item.provider.google.id,\n\t\t\t\t\t\trequestBody: { trashed: true },\n\t\t\t\t\t});\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error('Failed to trash Google file', e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tuntrash: async (ids, owner, accountId) => {\n\t\tconst { client } = await createAuthClient(owner, accountId);\n\t\tconst drive = google.drive({ version: 'v3', auth: client });\n\n\t\tconst items = await Drive.find({ _id: { $in: ids }, owner });\n\n\t\tfor (const item of items) {\n\t\t\tif (item.provider?.google?.id) {\n\t\t\t\ttry {\n\t\t\t\t\tawait drive.files.update({\n\t\t\t\t\t\tfileId: item.provider.google.id,\n\t\t\t\t\t\trequestBody: { trashed: false },\n\t\t\t\t\t});\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error('Failed to restore Google file', e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\trename: async (id, newName, owner, accountId) => {\n\t\tconst { client } = await createAuthClient(owner, accountId);\n\t\tconst drive = google.drive({ version: 'v3', auth: client });\n\n\t\tconst item = await Drive.findOne({ _id: id, owner });\n\t\tif (!item || !item.provider?.google?.id) throw new Error('Item not found');\n\n\t\tawait drive.files.update({\n\t\t\tfileId: item.provider.google.id,\n\t\t\trequestBody: { name: newName },\n\t\t});\n\n\t\titem.name = newName;\n\t\tawait item.save();\n\t\treturn item.toClient();\n\t},\n\n\tmove: async (id, newParentId, owner, accountId) => {\n\t\tconst { client, accountId: foundAccountId } = await createAuthClient(owner, accountId);\n\t\tconst drive = google.drive({ version: 'v3', auth: client });\n\n\t\t// Get Item\n\t\tconst item = await Drive.findOne({ _id: id, owner });\n\t\tif (!item || !item.provider?.google?.id) throw new Error('Item not found or not synced');\n\n\t\t// Resolve Old Parent Google ID\n\t\tlet previousGoogleParentId: string | undefined = undefined;\n\t\tif (item.parentId) {\n\t\t\tconst oldParent = await Drive.findOne({ _id: item.parentId, owner });\n\t\t\tif (oldParent && oldParent.provider?.google?.id) {\n\t\t\t\tpreviousGoogleParentId = oldParent.provider.google.id;\n\t\t\t}\n\t\t} else {\n\t\t\t// If parentId is null (root), finding previous parent is tricky without querying Google\n\t\t\t// But usually we don't need to specify removeParents if we don't care about multi-parenting?\n\t\t\t// Actually, in Drive API v3, moving requires removeParents if you want to 'move' and not 'add to'.\n\t\t\t// Let's query parents from Google to be safe\n\t\t\ttry {\n\t\t\t\tconst gFile = await drive.files.get({ fileId: item.provider.google.id, fields: 'parents' });\n\t\t\t\tif (gFile.data.parents && gFile.data.parents.length > 0) {\n\t\t\t\t\tpreviousGoogleParentId = gFile.data.parents.join(',');\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tconsole.warn('Could not fetch parents for move', e);\n\t\t\t}\n\t\t}\n\n\t\t// Resolve New Parent Google ID\n\t\tlet newGoogleParentId = 'root'; // User's root (maybe specific root folder if we support that?)\n\t\t// For now, assume 'root' maps to Drive root (or myDrive)\n\t\tif (newParentId && newParentId !== 'root') {\n\t\t\tconst newParent = await Drive.findOne({ _id: newParentId, owner });\n\t\t\tif (!newParent || !newParent.provider?.google?.id) throw new Error('Target folder not found in Google Drive');\n\t\t\tnewGoogleParentId = newParent.provider.google.id;\n\t\t}\n\n\t\t// Call Google API\n\t\tawait drive.files.update({\n\t\t\tfileId: item.provider.google.id,\n\t\t\taddParents: newGoogleParentId,\n\t\t\tremoveParents: previousGoogleParentId,\n\t\t\tfields: 'id, parents',\n\t\t});\n\n\t\t// Update DB\n\t\titem.parentId = newParentId === 'root' || !newParentId ? null : new mongoose.Types.ObjectId(newParentId);\n\t\tawait item.save();\n\n\t\treturn item.toClient();\n\t},\n\n\trevokeToken: async (owner, accountId) => {\n\t\tif (!accountId) return; // Need specific account to revoke\n\t\tconst { client } = await createAuthClient(owner, accountId);\n\t\tconst account = await StorageAccount.findById(accountId);\n\t\tif (account?.metadata?.provider === 'GOOGLE' && account.metadata.google?.credentials) {\n\t\t\tconst creds = account.metadata.google.credentials;\n\t\t\tif (typeof creds === 'object' && 'access_token' in creds) {\n\t\t\t\tawait client.revokeToken(creds.access_token);\n\t\t\t}\n\t\t}\n\t},\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 os from 'os';\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: string | null = null;\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} else if (allowedOrigins === '*') {\n\t\t// No origin header (same-origin request), allow if wildcard\n\t\tallowOrigin = '*';\n\t}\n\n\t// If origin not allowed, don't set CORS headers (request will fail CORS check)\n\tif (!allowOrigin) {\n\t\tif (req.method === 'OPTIONS') {\n\t\t\tres.status(403).end();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\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\t// ** Auto-detect OAuth callback when code & state are present but no action\n\tconst action = (req.query.action as string) || (req.query.code && req.query.state ? 'callback' : undefined);\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// ** Information Action (No Auth Needed)\n\t\tif (action === 'information') {\n\t\t\tconst { clientId, clientSecret, redirectUri } = config.storage?.google || {};\n\t\t\tconst googleConfigured = !!(clientId && clientSecret && redirectUri);\n\n\t\t\treturn res.status(200).json({\n\t\t\t\tstatus: 200,\n\t\t\t\tmessage: 'Information retrieved',\n\t\t\t\tdata: {\n\t\t\t\t\tproviders: {\n\t\t\t\t\t\tgoogle: googleConfigured,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\t\t}\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 || !redirectUri) 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\t// Append action=callback to redirectUri for explicit routing\n\t\t\t\t\t\tconst callbackUri = new URL(redirectUri);\n\t\t\t\t\t\tcallbackUri.searchParams.set('action', 'callback');\n\t\t\t\t\t\tconst oAuth2Client = new google.auth.OAuth2(clientId, clientSecret, callbackUri.toString());\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\tif (!clientId || !clientSecret || !redirectUri) return res.status(500).json({ status: 500, message: 'Google not configured' });\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\t// Must use the same redirect URI that was used in getAuthUrl (with action=callback)\n\t\t\t\t\tconst callbackUri = new URL(redirectUri);\n\t\t\t\t\tcallbackUri.searchParams.set('action', 'callback');\n\t\t\t\t\tconst oAuth2Client = new google.auth.OAuth2(clientId, clientSecret, callbackUri.toString());\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 notifies parent and closes tab/popup\n\t\t\t\t\t// Uses both postMessage (for popups) and localStorage (for new tabs in fullscreen macOS)\n\t\t\t\t\tres.setHeader('Content-Type', 'text/html');\n\t\t\t\t\treturn 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\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 systemTmpDir = path.join(os.tmpdir(), 'next-drive-uploads');\n\t\t\t\tif (!fs.existsSync(systemTmpDir)) fs.mkdirSync(systemTmpDir, { recursive: true });\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: systemTmpDir,\n\t\t\t\t\tkeepExtensions: true,\n\t\t\t\t});\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 (uses system tmp for auto-cleanup)\n\t\t\t\tconst tempBaseDir = path.join(os.tmpdir(), 'next-drive-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, information.storage.quotaInBytes);\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\t// Preserve original file extension (sanitized)\n\t\t\t\t\t\t\t\tlet ext = path.extname(meta.name) || '.bin';\n\t\t\t\t\t\t\t\t// Sanitize: only allow alphanumeric and common safe characters, max 10 chars\n\t\t\t\t\t\t\t\text = ext.replace(/[^a-zA-Z0-9.]/g, '').slice(0, 11);\n\t\t\t\t\t\t\t\tif (!ext.startsWith('.')) ext = '.bin';\n\t\t\t\t\t\t\t\tdrive.information.path = path.join('drive', String(drive._id), `data${ext}`);\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, information.storage.quotaInBytes);\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, information.storage.quotaInBytes);\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. CANCEL UPLOAD **\n\t\t\tcase 'cancel': {\n\t\t\t\tconst cancelData = schemas.cancelQuerySchema.safeParse(req.query);\n\t\t\t\tif (!cancelData.success) return res.status(400).json({ status: 400, message: 'Invalid ID' });\n\t\t\t\tconst { id } = cancelData.data;\n\n\t\t\t\t// Try to clean up temp upload directory (in system tmp)\n\t\t\t\tconst tempUploadDir = path.join(os.tmpdir(), 'next-drive-uploads', id);\n\t\t\t\tif (fs.existsSync(tempUploadDir)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfs.rmSync(tempUploadDir, { recursive: true, force: true });\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tconsole.error('Failed to cleanup temp upload:', e);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn res.status(200).json({ status: 200, message: 'Upload cancelled', data: null });\n\t\t\t}\n\n\t\t\t// ** 5. 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, information.storage.quotaInBytes);\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, information.storage.quotaInBytes);\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":"dialog.d.ts","sourceRoot":"","sources":["../../../src/client/components/dialog.tsx"],"names":[],"mappings":"AAgBA,KAAK,gBAAgB,GAAG;
|
|
1
|
+
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../src/client/components/dialog.tsx"],"names":[],"mappings":"AAgBA,KAAK,gBAAgB,GAAG;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACtB,CAAC;AAGF,KAAK,YAAY,CAAC,CAAC,SAAS,SAAS,gBAAgB,EAAE,IAAI;KAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM;CAAE,CAAC;AAE9F,eAAO,MAAM,kBAAkB,GAAI,CAAC,SAAS,SAAS,gBAAgB,EAAE,GAAG,SAAS,GAAG,SAAS,EAC3F,OAAO,QAAQ,CAAC;IACX,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,MAAM,CAAC,EAAE,CAAC,CAAA;IACV,SAAS,EAAE,CAAC,SAAS,SAAS,gBAAgB,EAAE,GAC9C,CAAC,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,GACxE,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IACzC,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAClC,CAAC,gCAoIN,CAAA"}
|
|
@@ -4,8 +4,8 @@ type DriveDndContextType = {
|
|
|
4
4
|
draggingItemId: string | null;
|
|
5
5
|
};
|
|
6
6
|
export declare const useDriveDnd: () => DriveDndContextType;
|
|
7
|
-
export declare const DriveDndProvider: (
|
|
7
|
+
export declare const DriveDndProvider: (props: Readonly<{
|
|
8
8
|
children: React.ReactNode;
|
|
9
|
-
}) => React.JSX.Element;
|
|
9
|
+
}>) => React.JSX.Element;
|
|
10
10
|
export {};
|
|
11
11
|
//# sourceMappingURL=dnd-provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dnd-provider.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/dnd-provider.tsx"],"names":[],"mappings":"AAGA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAgBhF,KAAK,mBAAmB,GAAG;
|
|
1
|
+
{"version":3,"file":"dnd-provider.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/dnd-provider.tsx"],"names":[],"mappings":"AAGA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAgBhF,KAAK,mBAAmB,GAAG;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAOF,eAAO,MAAM,WAAW,2BAAoC,CAAC;AAG7D,eAAO,MAAM,gBAAgB,GAAI,OAAO,QAAQ,CAAC;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAAC,sBAuG9E,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explorer.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/explorer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"explorer.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/explorer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAmErD,eAAO,MAAM,aAAa,GAAI,OAAO,QAAQ,CAAC;IACzC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC,sBAmfD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-grid.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/file-grid.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"file-grid.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/file-grid.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AA4KrD,eAAO,MAAM,aAAa,GAAI,OAAO,QAAQ,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;CACvD,CAAC,sBA+QD,CAAC"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
export declare const DriveHeader: (
|
|
2
|
+
export declare const DriveHeader: ({ className }: {
|
|
3
|
+
className?: string;
|
|
4
|
+
}) => React.JSX.Element;
|
|
5
|
+
export declare const DriveContentProgress: () => React.JSX.Element | null;
|
|
3
6
|
//# sourceMappingURL=header.d.ts.map
|
|
@@ -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,
|
|
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,GAAI,eAAe;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,sBAkShE,CAAC;AAKF,eAAO,MAAM,oBAAoB,gCAchC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-bar.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/path-bar.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AA4D1B,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"path-bar.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/path-bar.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AA4D1B,eAAO,MAAM,YAAY,GAAI,eAAe;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,sBAqBjE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/sidebar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/sidebar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAC;AA6XxC,eAAO,MAAM,YAAY,GAAI,eAAe;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,sBAmBjE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indicator.d.ts","sourceRoot":"","sources":["../../../../../src/client/components/drive/storage/indicator.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAMzC,eAAO,MAAM,qBAAqB,GAAI,OAAO,QAAQ,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"indicator.d.ts","sourceRoot":"","sources":["../../../../../src/client/components/drive/storage/indicator.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAMzC,eAAO,MAAM,qBAAqB,GAAI,OAAO,QAAQ,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,6BAuE/F,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/upload.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAwC,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../../../src/client/components/drive/upload.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAwC,MAAM,OAAO,CAAC;AA4B7D,eAAO,MAAM,WAAW,GAAI,OAAO,QAAQ,CAAC;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,sBAkOD,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as ProgressPrimitive from "@radix-ui/react-progress";
|
|
3
|
-
declare function Progress({ className, value, indicatorClassName, ...props }: React.ComponentProps<typeof ProgressPrimitive.Root> & {
|
|
3
|
+
declare function Progress({ className, value, indicatorClassName, indeterminate, ...props }: React.ComponentProps<typeof ProgressPrimitive.Root> & {
|
|
4
4
|
indicatorClassName?: string;
|
|
5
|
+
indeterminate?: boolean;
|
|
5
6
|
}): React.JSX.Element;
|
|
6
7
|
export { Progress };
|
|
7
8
|
//# sourceMappingURL=progress.d.ts.map
|