@muhgholy/next-drive 2.2.0 → 2.2.2

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.
Files changed (35) hide show
  1. package/README.md +222 -346
  2. package/dist/{chunk-5C6YUPCM.js → chunk-F5SLCUJ5.js} +26 -8
  3. package/dist/chunk-F5SLCUJ5.js.map +1 -0
  4. package/dist/client/components/dialog.d.ts.map +1 -1
  5. package/dist/client/components/drive/dnd-provider.d.ts +2 -2
  6. package/dist/client/components/drive/dnd-provider.d.ts.map +1 -1
  7. package/dist/client/components/drive/explorer.d.ts.map +1 -1
  8. package/dist/client/components/drive/file-grid.d.ts.map +1 -1
  9. package/dist/client/components/drive/header.d.ts +4 -1
  10. package/dist/client/components/drive/header.d.ts.map +1 -1
  11. package/dist/client/components/drive/path-bar.d.ts +3 -1
  12. package/dist/client/components/drive/path-bar.d.ts.map +1 -1
  13. package/dist/client/components/drive/sidebar.d.ts +3 -1
  14. package/dist/client/components/drive/sidebar.d.ts.map +1 -1
  15. package/dist/client/components/drive/storage/indicator.d.ts.map +1 -1
  16. package/dist/client/components/drive/upload.d.ts.map +1 -1
  17. package/dist/client/components/ui/progress.d.ts +2 -1
  18. package/dist/client/components/ui/progress.d.ts.map +1 -1
  19. package/dist/client/components/ui/sheet.d.ts.map +1 -1
  20. package/dist/client/context.d.ts +4 -0
  21. package/dist/client/context.d.ts.map +1 -1
  22. package/dist/client/file-chooser.d.ts.map +1 -1
  23. package/dist/client/index.d.ts +0 -1
  24. package/dist/client/index.d.ts.map +1 -1
  25. package/dist/client/index.js +487 -281
  26. package/dist/client/index.js.map +1 -1
  27. package/dist/client/styles.css +57 -40
  28. package/dist/server/express.js +2 -2
  29. package/dist/server/index.d.ts.map +1 -1
  30. package/dist/server/index.js +1 -1
  31. package/dist/server/providers/google.d.ts.map +1 -1
  32. package/package.json +5 -1
  33. package/dist/chunk-5C6YUPCM.js.map +0 -1
  34. package/dist/client/index.css +0 -48
  35. package/dist/client/index.css.map +0 -1
package/README.md CHANGED
@@ -1,16 +1,18 @@
1
1
  # @muhgholy/next-drive
2
2
 
3
- Robust file storage and management solution for Next.js and Express applications, featuring a responsive UI, advanced search, trash management, and secure file handling.
3
+ File storage and management for Next.js and Express apps. Includes a responsive UI, search, trash system, and secure file handling.
4
4
 
5
5
  ## Features
6
6
 
7
- - **File Management**: Upload, rename, move, and organize files and folders.
8
- - **Advanced Search**: Search both active files and the trash bin with real-time filtering.
9
- - **Trash System**: specialized trash view with soft delete, restore, and empty trash capabilities.
10
- - **Responsive UI**: optimized layouts for both desktop (single toolbar) and mobile (search-focused header).
11
- - **Video Support**: Auto-generates thumbnails for video files (requires FFmpeg).
12
- - **Security**: Signed URLs for secure file access and configurable upload limits.
13
- - **View Modes**: Toggle between Grid and List views with custom sorting and grouping.
7
+ - 📁 **File Management** Upload, rename, move, organize files and folders
8
+ - 🔍 **Search** Search active files or trash with real-time filtering
9
+ - 🗑️ **Trash System** Soft delete, restore, and empty trash
10
+ - 📱 **Responsive UI** Optimized for desktop and mobile
11
+ - 🎬 **Video Thumbnails** Auto-generated thumbnails (requires FFmpeg)
12
+ - 🔐 **Security** Signed URLs and configurable upload limits
13
+ - 📊 **View Modes** Grid/List views with sorting and grouping
14
+
15
+ ---
14
16
 
15
17
  ## Installation
16
18
 
@@ -18,59 +20,60 @@ Robust file storage and management solution for Next.js and Express applications
18
20
  npm install @muhgholy/next-drive
19
21
  ```
20
22
 
21
- **Peer Dependencies:**
23
+ ### Requirements
24
+
25
+ | Dependency | Version |
26
+ | ------------ | ------- |
27
+ | Next.js | >= 14 |
28
+ | React | >= 18 |
29
+ | Mongoose | >= 7 |
30
+ | Tailwind CSS | >= 3 |
22
31
 
23
- - Next.js >= 14
24
- - React >= 18
25
- - Mongoose >= 7
26
- - Tailwind CSS >= 3
32
+ **FFmpeg** (for video thumbnails):
27
33
 
28
- **System Requirements:**
34
+ ```bash
35
+ # macOS
36
+ brew install ffmpeg
29
37
 
30
- - **FFmpeg**: Required for generating thumbnails from video files.
31
- - MacOS: `brew install ffmpeg`
32
- - Ubuntu: `sudo apt install ffmpeg`
33
- - Windows: Download from official site and add to PATH.
38
+ # Ubuntu
39
+ sudo apt install ffmpeg
40
+
41
+ # Windows
42
+ # Download from https://ffmpeg.org and add to PATH
43
+ ```
34
44
 
35
- ### Tailwind CSS Configuration
45
+ ### Tailwind Setup
36
46
 
37
- Since this package uses Tailwind CSS for styling, you **must** configure Tailwind to scan the package's files:
47
+ Add the package to your Tailwind content config:
38
48
 
39
49
  ```js
40
50
  // tailwind.config.js
41
51
  export default {
42
- content: [
43
- './app/**/*.{js,ts,jsx,tsx,mdx}',
44
- './pages/**/*.{js,ts,jsx,tsx,mdx}',
45
- './components/**/*.{js,ts,jsx,tsx,mdx}',
46
- // Add the next-drive package
47
- './node_modules/@muhgholy/next-drive/dist/**/*.{js,mjs}',
48
- ],
49
- theme: {
50
- extend: {},
51
- },
52
- plugins: [],
52
+ content: ['./app/**/*.{js,ts,jsx,tsx,mdx}', './pages/**/*.{js,ts,jsx,tsx,mdx}', './components/**/*.{js,ts,jsx,tsx,mdx}', './node_modules/@muhgholy/next-drive/dist/**/*.{js,mjs}'],
53
53
  };
54
54
  ```
55
55
 
56
- > **Note**: The CSS is automatically injected when you import from `@muhgholy/next-drive/client` - no need to manually import stylesheets.
56
+ > CSS is auto-injected when importing from `@muhgholy/next-drive/client`.
57
+
58
+ ---
57
59
 
58
60
  ## Quick Start
59
61
 
60
- ### 1. Configure Server
62
+ ### 1. Server Configuration
61
63
 
62
- Create a configuration file (e.g., `lib/drive.ts`) to set up storage paths, database connection, and security rules.
64
+ Create `lib/drive.ts` to configure storage, security, and authentication:
63
65
 
64
66
  ```typescript
65
67
  // lib/drive.ts
66
68
  import { driveConfiguration } from '@muhgholy/next-drive/server';
67
69
  import type { TDriveConfigInformation } from '@muhgholy/next-drive/server';
68
70
 
69
- export const drive = driveConfiguration({
71
+ driveConfiguration({
70
72
  database: 'MONGOOSE',
73
+ apiUrl: '/api/drive',
71
74
  storage: { path: '/var/data/drive' },
72
75
  security: {
73
- maxUploadSize: 50 * 1024 * 1024, // 50MB
76
+ maxUploadSizeInBytes: 50 * 1024 * 1024, // 50MB
74
77
  allowedMimeTypes: ['image/*', 'video/*', 'application/pdf'],
75
78
  signedUrls: {
76
79
  enabled: true,
@@ -78,36 +81,20 @@ export const drive = driveConfiguration({
78
81
  expiresIn: 3600, // 1 hour
79
82
  },
80
83
  },
81
- image: {
82
- formats: ['webp', 'jpeg', 'png'],
83
- qualities: ['ultralow', 'low', 'medium', 'high', 'normal'],
84
- },
85
- // Optional: Enable CORS for cross-origin requests
86
- cors: {
87
- enabled: true,
88
- origins: ['https://example.com', 'https://app.example.com'],
89
- credentials: true,
90
- },
91
84
  information: async (req): Promise<TDriveConfigInformation> => {
92
- // Implement your auth verification here
93
85
  const auth = await verifyAuth(req);
94
86
  if (!auth) throw new Error('Unauthenticated');
95
87
  return {
96
88
  key: { userId: auth.userId },
97
- storage: { quotaInBytes: 1024 * 1024 * 1024 }, // 1GB limit
89
+ storage: { quotaInBytes: 1024 * 1024 * 1024 }, // 1GB
98
90
  };
99
91
  },
100
92
  });
101
93
  ```
102
94
 
103
- ### 2. Create API Route
104
-
105
- Set up the API route handler that `next-drive` will use to communicate with the client.
106
-
107
- **Important:**
95
+ ### 2. API Route (Pages Router)
108
96
 
109
- - The API route must be in the `pages` folder (Pages Router)
110
- - **You MUST disable Next.js body parser** for uploads to work properly
97
+ > ⚠️ **Important**: Must be in `pages/` folder with body parser disabled.
111
98
 
112
99
  ```typescript
113
100
  // pages/api/drive.ts
@@ -116,67 +103,82 @@ import { driveAPIHandler } from '@muhgholy/next-drive/server';
116
103
  import type { NextApiRequest, NextApiResponse } from 'next';
117
104
 
118
105
  export default async function handler(req: NextApiRequest, res: NextApiResponse) {
119
- // Manually parse JSON body for non-upload requests
120
- if (!req.body) req.body = {};
121
-
106
+ // Parse JSON body manually (body parser is disabled)
122
107
  if (req.headers['content-type']?.includes('application/json')) {
123
- try {
124
- const buffer = await new Promise<Buffer>((resolve, reject) => {
125
- const chunks: Buffer[] = [];
126
- req.on('data', chunk => chunks.push(chunk));
127
- req.on('end', () => resolve(Buffer.concat(chunks)));
128
- req.on('error', reject);
129
- });
130
-
131
- if (buffer.length > 0) {
132
- req.body = JSON.parse(buffer.toString());
133
- }
134
- } catch (e) {
135
- console.error('Failed to parse JSON body', e);
136
- }
108
+ const chunks: Buffer[] = [];
109
+ for await (const chunk of req) chunks.push(chunk);
110
+ const buffer = Buffer.concat(chunks);
111
+ req.body = buffer.length > 0 ? JSON.parse(buffer.toString()) : {};
112
+ } else {
113
+ req.body = req.body || {};
137
114
  }
138
115
 
139
116
  return driveAPIHandler(req, res);
140
117
  }
141
118
 
142
- // ⚠️ CRITICAL: Disable body parser for file uploads
143
119
  export const config = {
144
- api: {
145
- bodyParser: false,
146
- },
120
+ api: { bodyParser: false },
147
121
  };
148
122
  ```
149
123
 
150
- ### 2b. Express Integration (Alternative)
124
+ ### 3. Client Provider
125
+
126
+ Wrap your app with `DriveProvider`:
127
+
128
+ ```tsx
129
+ // app/layout.tsx
130
+ import { DriveProvider } from '@muhgholy/next-drive/client';
131
+
132
+ export default function RootLayout({ children }) {
133
+ return <DriveProvider apiEndpoint='/api/drive'>{children}</DriveProvider>;
134
+ }
135
+ ```
136
+
137
+ ### 4. UI Components
138
+
139
+ **File Explorer:**
140
+
141
+ ```tsx
142
+ import { DriveExplorer } from '@muhgholy/next-drive/client';
143
+
144
+ export default function DrivePage() {
145
+ return <DriveExplorer />;
146
+ }
147
+ ```
148
+
149
+ **File Picker (for forms):**
150
+
151
+ ```tsx
152
+ import { useState } from 'react';
153
+ import { DriveFileChooser } from '@muhgholy/next-drive/client';
154
+ import type { TDriveFile } from '@muhgholy/next-drive/client';
155
+
156
+ function MyForm() {
157
+ const [file, setFile] = useState<TDriveFile | null>(null);
158
+ return <DriveFileChooser value={file} onChange={setFile} accept='image/*' />;
159
+ }
160
+ ```
161
+
162
+ ---
163
+
164
+ ## Express Integration
151
165
 
152
- If you're using Express instead of Next.js API Routes, use the Express adapter:
166
+ Use the Express adapter instead of Next.js API routes:
153
167
 
154
168
  ```typescript
155
169
  // lib/drive.ts
156
170
  import { driveConfigurationExpress } from '@muhgholy/next-drive/server/express';
157
171
  import type { TDriveConfigInformation } from '@muhgholy/next-drive/server/express';
158
172
 
159
- export const drive = driveConfigurationExpress({
173
+ driveConfigurationExpress({
160
174
  database: 'MONGOOSE',
175
+ apiUrl: '/api/drive',
161
176
  storage: { path: '/var/data/drive' },
162
177
  security: {
163
- maxUploadSizeInBytes: 50 * 1024 * 1024, // 50MB
178
+ maxUploadSizeInBytes: 50 * 1024 * 1024,
164
179
  allowedMimeTypes: ['image/*', 'video/*', 'application/pdf'],
165
- signedUrls: {
166
- enabled: true,
167
- secret: process.env.DRIVE_SECRET!,
168
- expiresIn: 3600,
169
- },
170
180
  },
171
- // Optional: Enable CORS for cross-origin requests
172
- cors: {
173
- enabled: true,
174
- origins: ['https://example.com'],
175
- credentials: true,
176
- },
177
- apiUrl: '/api/drive',
178
181
  information: async (req): Promise<TDriveConfigInformation> => {
179
- // req is Express Request type
180
182
  const auth = await verifyAuth(req);
181
183
  if (!auth) throw new Error('Unauthenticated');
182
184
  return {
@@ -189,168 +191,82 @@ export const drive = driveConfigurationExpress({
189
191
 
190
192
  ```typescript
191
193
  // routes/drive.ts
192
- import './lib/drive'; // Initialize configuration
194
+ import './lib/drive';
193
195
  import express from 'express';
194
196
  import { driveAPIHandlerExpress } from '@muhgholy/next-drive/server/express';
195
197
 
196
198
  const router = express.Router();
197
-
198
- // Handle all drive API requests
199
199
  router.all('/drive', driveAPIHandlerExpress);
200
200
 
201
201
  export default router;
202
202
  ```
203
203
 
204
- **Important for Express:**
205
-
206
- - Do NOT use `express.json()` middleware on the drive route (file uploads need raw body)
207
- - The handler supports all HTTP methods (GET, POST, PATCH, DELETE)
208
-
209
- ### 3. Add Provider
210
-
211
- Wrap your application or the specific route with `DriveProvider`.
212
-
213
- ```typescript
214
- // app/layout.tsx
215
- import { DriveProvider } from "@muhgholy/next-drive/client";
216
-
217
- export default function RootLayout({ children }) {
218
- return <DriveProvider apiEndpoint="/api/drive">{children}</DriveProvider>;
219
- }
220
- ```
221
-
222
- **Cross-Origin Setup:**
223
-
224
- When your client runs on a different domain than the API, enable credentials:
225
-
226
- ```typescript
227
- // Enable cookies/auth headers for cross-origin requests
228
- <DriveProvider
229
- apiEndpoint="https://api.example.com/drive"
230
- withCredentials={true}
231
- >
232
- {children}
233
- </DriveProvider>
234
- ```
235
-
236
- > **Note**: Requires matching CORS configuration on the server with `credentials: true`.
237
-
238
- ### 4. Implement UI Components
239
-
240
- You can use the built-in `DriveExplorer` for a full file manager experience or `DriveFileChooser` for form inputs.
241
-
242
- **Full File Explorer:**
243
-
244
- ```typescript
245
- import { DriveExplorer } from "@muhgholy/next-drive/client";
246
-
247
- export default function DrivePage() {
248
- return <DriveExplorer />;
249
- }
250
- ```
251
-
252
- **File Picker:**
253
-
254
- ```typescript
255
- import { DriveFileChooser } from "@muhgholy/next-drive/client";
256
- import type { TDriveFile } from "@muhgholy/next-drive/client";
204
+ > ⚠️ Don't use `express.json()` middleware on this route.
257
205
 
258
- function MyForm() {
259
- const [file, setFile] = useState<TDriveFile | null>(null);
206
+ ---
260
207
 
261
- return <DriveFileChooser value={file} onChange={setFile} accept="image/*" />;
262
- }
263
- ```
208
+ ## Zod Validation
264
209
 
265
- **Zod Validation:**
266
-
267
- You can use the exported `driveFileSchemaZod` to validate file data in your forms or API routes.
210
+ Validate file data in forms or API routes:
268
211
 
269
212
  ```typescript
270
213
  import { z } from 'zod';
271
214
  import { driveFileSchemaZod } from '@muhgholy/next-drive/schemas';
272
215
 
273
- // Use in your form schema (works in both client and server)
274
- const myFormSchema = z.object({
216
+ const formSchema = z.object({
275
217
  asset: driveFileSchemaZod,
276
218
  title: z.string(),
277
- description: z.string().optional(),
278
219
  });
279
-
280
- type MyFormData = z.infer<typeof myFormSchema>;
281
220
  ```
282
221
 
283
- > **Note**: The schema is also available from `/client` and `/server` exports for convenience, but `/schemas` is the recommended universal import.
222
+ > Schema also available from `/client` and `/server` exports.
284
223
 
285
- // Use in your form schema
286
- const myFormSchema = z.object({
224
+ ---
287
225
 
288
- ````
226
+ ## Client-Side File URLs
289
227
 
290
- ## Key Capabilities
228
+ Generate URLs for displaying files:
291
229
 
292
- ### Client-Side File URLs
230
+ ```tsx
231
+ import { useDrive } from '@muhgholy/next-drive/client';
232
+ import type { TDriveFile } from '@muhgholy/next-drive/client';
293
233
 
294
- **Generate File URL:**
295
-
296
- ```typescript
297
- import { useDrive } from "@muhgholy/next-drive/client";
298
- import type { TDriveFile } from "@muhgholy/next-drive/client";
299
-
300
- function MyComponent() {
301
- const { createUrl } = useDrive();
234
+ function MyComponent({ driveFile }: { driveFile: TDriveFile }) {
235
+ const { createUrl, createSrcSet } = useDrive();
302
236
 
303
- // Basic URL generation
237
+ // Basic URL
304
238
  const url = createUrl(driveFile);
305
- // Returns: /api/drive?action=serve&id={fileId}
306
-
307
- // With image quality and format
308
- const url = createUrl(driveFile, {
309
- quality: "medium",
310
- format: "webp",
311
- });
312
- // Returns: /api/drive?action=serve&id={fileId}&q=medium&format=webp
313
-
314
- // Use in Next.js Image component
315
- return <Image src={createUrl(driveFile)} alt={driveFile.file.name} />;
316
- }
317
- ````
318
239
 
319
- **Responsive Image SrcSet:**
320
-
321
- ```typescript
322
- import { useDrive } from "@muhgholy/next-drive/client";
323
-
324
- function ResponsiveImage({ driveFile }: { driveFile: TDriveFile }) {
325
- const { createUrl, createSrcSet } = useDrive();
240
+ // With quality and format
241
+ const optimizedUrl = createUrl(driveFile, { quality: 'medium', format: 'webp' });
326
242
 
327
- // Generate responsive srcSet for optimal image loading
328
- const { srcSet, sizes } = createSrcSet(driveFile, "webp");
243
+ // Responsive srcSet for images
244
+ const { srcSet, sizes } = createSrcSet(driveFile, 'webp');
329
245
 
330
- // Use in img tag
331
- return <img src={createUrl(driveFile, { quality: "medium" })} srcSet={srcSet} sizes={sizes} alt={driveFile.file.name} />;
246
+ return <img src={optimizedUrl} srcSet={srcSet} sizes={sizes} alt={driveFile.file.name} />;
332
247
  }
333
248
  ```
334
249
 
335
- ### Server-Side File Access
250
+ ---
336
251
 
337
- **Get File URL:**
252
+ ## Server-Side File Access
253
+
254
+ ### Get Signed URL
338
255
 
339
256
  ```typescript
340
257
  import { driveGetUrl } from '@muhgholy/next-drive/server';
341
258
 
342
- // Generate a secure URL
259
+ // Default expiry (from config)
343
260
  const url = driveGetUrl(fileId);
344
- // Returns: /api/drive?action=serve&id={fileId}&token={signedToken}
345
261
 
346
- // With custom expiry (in seconds)
262
+ // Custom expiry in seconds
347
263
  const url = driveGetUrl(fileId, { expiry: 7200 }); // 2 hours
348
264
 
349
- // With specific expiry date
350
- const url = driveGetUrl(fileId, { expiry: new Date('2025-12-31') });
265
+ // Specific date
266
+ const url = driveGetUrl(fileId, { expiry: new Date('2026-12-31') });
351
267
  ```
352
268
 
353
- **Read File Stream:**
269
+ ### Read File Stream
354
270
 
355
271
  ```typescript
356
272
  import { driveReadFile } from '@muhgholy/next-drive/server';
@@ -362,191 +278,151 @@ stream.pipe(response);
362
278
  // Using database document
363
279
  const drive = await Drive.findById(fileId);
364
280
  const { stream, mime, size } = await driveReadFile(drive);
365
-
366
- // Example: Send file via email
367
- const { stream } = await driveReadFile(fileId);
368
- await sendEmail({
369
- attachments: [{ filename: 'report.pdf', content: stream }],
370
- });
371
-
372
- // Example: Process file contents
373
- const { stream } = await driveReadFile(fileId);
374
- const chunks = [];
375
- for await (const chunk of stream) {
376
- chunks.push(chunk);
377
- }
378
- const buffer = Buffer.concat(chunks);
379
281
  ```
380
282
 
381
- **Get Local File Path:**
283
+ ### Get Local File Path
382
284
 
383
- For scenarios requiring direct file system access, `driveFilePath()` provides the absolute path. Google Drive files are automatically downloaded to a local cache.
285
+ For libraries requiring file paths (Sharp, FFmpeg, etc.):
384
286
 
385
287
  ```typescript
386
288
  import { driveFilePath } from '@muhgholy/next-drive/server';
387
- import fs from 'fs';
388
289
 
389
- // Get local path (downloads Google Drive files automatically)
390
290
  const { path, mime, size, provider } = await driveFilePath(fileId);
391
291
 
392
- // Use with synchronous file operations
393
- const buffer = fs.readFileSync(path);
394
-
395
- // Use with libraries requiring file paths
292
+ // Use with Sharp
396
293
  await sharp(path).resize(800, 600).toFile('output.jpg');
397
- await ffmpeg(path).format('mp4').save('output.mp4');
398
294
 
399
- // Google Drive files are cached at: storage/library/google/{fileId}.ext
400
- // Local files use their original location
295
+ // Use with FFmpeg
296
+ await ffmpeg(path).format('mp4').save('output.mp4');
401
297
  ```
402
298
 
403
- ### Search & Trash
299
+ > Google Drive files are automatically downloaded to local cache.
404
300
 
405
- - **Search Scope**: Search automatically adapts to your current view. If you are browsing the Trash, searches will query deleted items. In the main Browser, searches query active files.
406
- - **Trash Management**: "Delete" moves items to Trash. From Trash, you can "Restore" items or "Delete Forever". A dedicated "Empty Trash" button is available to clear all deleted items.
301
+ ---
407
302
 
408
- ### CORS Configuration
303
+ ## Configuration Options
409
304
 
410
- When your client application runs on a different domain than your API server, you need to enable CORS (Cross-Origin Resource Sharing):
305
+ ### Security
411
306
 
412
307
  ```typescript
413
- // lib/drive.ts
414
- export const drive = driveConfiguration({
415
- // ... other config
416
- cors: {
308
+ security: {
309
+ maxUploadSizeInBytes: 50 * 1024 * 1024, // 50MB
310
+ allowedMimeTypes: ['image/*', 'video/*', 'application/pdf'],
311
+ signedUrls: {
417
312
  enabled: true,
418
- origins: ['https://app.example.com', 'https://admin.example.com'], // or '*' for all origins
419
- methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], // default
420
- allowedHeaders: ['Content-Type', 'Authorization', 'X-Drive-Account'], // default
421
- exposedHeaders: ['Content-Length', 'Content-Type', 'Content-Disposition'], // default
422
- credentials: true, // Allow cookies/auth headers
423
- maxAge: 86400, // Preflight cache duration in seconds (default: 24 hours)
313
+ secret: process.env.DRIVE_SECRET!,
314
+ expiresIn: 3600, // seconds
424
315
  },
425
- });
316
+ trash: { retentionDays: 30 },
317
+ }
426
318
  ```
427
319
 
428
- **CORS Options:**
429
-
430
- | Option | Type | Default | Description |
431
- | ---------------- | -------------------- | ----------------------------------------------------------- | ------------------------------------------- |
432
- | `enabled` | `boolean` | `false` | Enable/disable CORS headers |
433
- | `origins` | `string \| string[]` | `'*'` | Allowed origins (use array for multiple) |
434
- | `methods` | `string[]` | `['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']` | Allowed HTTP methods |
435
- | `allowedHeaders` | `string[]` | `['Content-Type', 'Authorization', 'X-Drive-Account']` | Headers clients can send |
436
- | `exposedHeaders` | `string[]` | `['Content-Length', 'Content-Type', 'Content-Disposition']` | Headers exposed to client |
437
- | `credentials` | `boolean` | `false` | Allow credentials (cookies, auth headers) |
438
- | `maxAge` | `number` | `86400` | Preflight response cache duration (seconds) |
439
-
440
- > **Note**: When `credentials` is `true`, `origins` cannot be `'*'`. You must specify explicit origins.
320
+ ### Image Processing
441
321
 
442
- ### Google Drive Integration
443
-
444
- To enable Google Drive as a storage provider, you need to set up OAuth 2.0 credentials.
445
-
446
- #### 1. Google Cloud Console Setup
447
-
448
- 1. Go to [Google Cloud Console](https://console.cloud.google.com/)
449
- 2. Create a new project or select an existing one
450
- 3. Enable the **Google Drive API** from the API Library
451
- 4. Go to **Credentials** → **Create Credentials** → **OAuth 2.0 Client ID**
452
- 5. Select **Web application** as the application type
453
- 6. Add your redirect URI (e.g., `http://localhost:3000/api/auth/google/callback`)
454
- 7. Copy the **Client ID** and **Client Secret**
322
+ ```typescript
323
+ image: {
324
+ formats: ['webp', 'jpeg', 'png'],
325
+ qualities: ['ultralow', 'low', 'medium', 'high', 'normal'],
326
+ }
327
+ ```
455
328
 
456
- #### 2. Configuration
329
+ ### CORS (Cross-Origin)
457
330
 
458
- Add Google credentials to your drive configuration:
331
+ Required when client and API are on different domains:
459
332
 
460
333
  ```typescript
461
- // lib/drive.ts
462
- import { driveConfiguration } from '@muhgholy/next-drive/server';
463
-
464
- export const drive = driveConfiguration({
465
- database: 'MONGOOSE',
466
- storage: {
467
- path: '/var/data/drive',
468
- google: {
469
- clientId: process.env.GOOGLE_CLIENT_ID!,
470
- clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
471
- redirectUri: process.env.GOOGLE_REDIRECT_URI!,
472
- },
473
- },
474
- // ... other config options
475
- });
334
+ cors: {
335
+ enabled: true,
336
+ origins: ['https://app.example.com'],
337
+ credentials: true, // Allow cookies/auth headers
338
+ maxAge: 86400, // Preflight cache (24 hours)
339
+ }
476
340
  ```
477
341
 
478
- #### 3. Environment Variables
479
-
480
- Add to your `.env` file:
342
+ **Client setup for CORS:**
481
343
 
482
- ```env
483
- GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
484
- GOOGLE_CLIENT_SECRET=your-client-secret
485
- GOOGLE_REDIRECT_URI=http://localhost:3000/api/auth/google/callback
344
+ ```tsx
345
+ <DriveProvider apiEndpoint='https://api.example.com/drive' withCredentials={true}>
346
+ {children}
347
+ </DriveProvider>
486
348
  ```
487
349
 
488
- #### 4. OAuth Scopes
350
+ | Option | Type | Default | Description |
351
+ | ---------------- | -------------------- | ----------------------------------------------------------- | ------------------------------- |
352
+ | `enabled` | `boolean` | `false` | Enable CORS |
353
+ | `origins` | `string \| string[]` | `'*'` | Allowed origins |
354
+ | `methods` | `string[]` | `['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']` | Allowed HTTP methods |
355
+ | `allowedHeaders` | `string[]` | `['Content-Type', 'Authorization', 'X-Drive-Account']` | Headers clients can send |
356
+ | `exposedHeaders` | `string[]` | `['Content-Length', 'Content-Type', 'Content-Disposition']` | Headers exposed to client |
357
+ | `credentials` | `boolean` | `false` | Allow credentials |
358
+ | `maxAge` | `number` | `86400` | Preflight cache duration (secs) |
489
359
 
490
- The following scopes are used depending on your needs:
360
+ > When `credentials: true`, you must specify explicit origins (not `'*'`).
491
361
 
492
- | Scope | Description |
493
- | ------------------------------------------------ | ---------------------------------------------------------------- |
494
- | `https://www.googleapis.com/auth/drive` | Full access to all Drive files (recommended for file management) |
495
- | `https://www.googleapis.com/auth/drive.file` | Access only to files created/opened by your app |
496
- | `https://www.googleapis.com/auth/drive.readonly` | Read-only access to all Drive files |
362
+ ---
497
363
 
498
- For full file management features (list, upload, download, delete), use:
364
+ ## Google Drive Integration
499
365
 
500
- ```typescript
501
- const SCOPES = ['https://www.googleapis.com/auth/drive'];
502
- ```
366
+ ### 1. Google Cloud Setup
503
367
 
504
- #### 5. User Authentication Flow
368
+ 1. Go to [Google Cloud Console](https://console.cloud.google.com/)
369
+ 2. Create/select a project
370
+ 3. Enable **Google Drive API**
371
+ 4. Create OAuth 2.0 credentials (Web application)
372
+ 5. Add redirect URI (e.g., `http://localhost:3000/api/drive?action=callback`)
505
373
 
506
- After OAuth authentication, user credentials are stored in the `StorageAccount` collection:
374
+ ### 2. Configuration
507
375
 
508
376
  ```typescript
509
- {
510
- owner: { userId: 'user-id' },
511
- metadata: {
512
- provider: 'GOOGLE',
513
- google: {
514
- credentials: {
515
- access_token: '...',
516
- refresh_token: '...',
517
- expiry_date: 1234567890
518
- }
519
- }
520
- }
377
+ storage: {
378
+ path: '/var/data/drive',
379
+ google: {
380
+ clientId: process.env.GOOGLE_CLIENT_ID!,
381
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
382
+ redirectUri: process.env.GOOGLE_REDIRECT_URI!,
383
+ },
521
384
  }
522
385
  ```
523
386
 
524
- The library automatically handles token refresh when tokens expire.
387
+ ### 3. Environment Variables
388
+
389
+ ```env
390
+ GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
391
+ GOOGLE_CLIENT_SECRET=your-client-secret
392
+ GOOGLE_REDIRECT_URI=http://localhost:3000/api/drive?action=callback
393
+ ```
394
+
395
+ ### OAuth Scopes
525
396
 
526
- ### Responsive Design
397
+ | Scope | Description |
398
+ | ------------------------------------------------ | ---------------------- |
399
+ | `https://www.googleapis.com/auth/drive` | Full Drive access |
400
+ | `https://www.googleapis.com/auth/drive.file` | App-created files only |
401
+ | `https://www.googleapis.com/auth/drive.readonly` | Read-only access |
527
402
 
528
- - **Desktop**: Features a unified single-row header containing Search, Group, Delete, Sort, View, and Trash controls.
529
- - **Mobile**: Optimizes for small screens by separating the Search bar into a full-width top row and grouping action buttons in a scrollable toolbar below.
403
+ ---
530
404
 
531
405
  ## API Endpoints
532
406
 
533
- All operations use the `?action=` query parameter on your configured API endpoint:
534
-
535
- | Action | Method | Description |
536
- | ----------------- | ------ | -------------------------------------------------------- |
537
- | `upload` | POST | Chunked file upload handling |
538
- | `list` | GET | List files in a folder (supports `trashed` param) |
539
- | `serve` | GET | Serve file content (supports resizing/format conversion) |
540
- | `thumbnail` | GET | specific endpoint for file thumbnails |
541
- | `rename` | PATCH | Rename a file or folder |
542
- | `trash` | POST | Move items to trash (soft delete) |
543
- | `deletePermanent` | DELETE | Permanently remove items |
544
- | `restore` | POST | Restore items from trash |
545
- | `emptyTrash` | DELETE | Permanently remove all trashed items |
546
- | `createFolder` | POST | Create a new directory |
547
- | `move` | POST | Move files/folders to a new parent |
548
- | `search` | GET | Search by name (supports `trashed=true`) |
549
- | `quota` | GET | Get current storage usage |
407
+ All operations use `?action=` query parameter:
408
+
409
+ | Action | Method | Description |
410
+ | ----------------- | ------ | -------------------------------- |
411
+ | `upload` | POST | Chunked file upload |
412
+ | `list` | GET | List folder contents |
413
+ | `serve` | GET | Serve file (with resize/convert) |
414
+ | `thumbnail` | GET | Get file thumbnail |
415
+ | `rename` | PATCH | Rename file/folder |
416
+ | `trash` | POST | Move to trash |
417
+ | `deletePermanent` | DELETE | Delete permanently |
418
+ | `restore` | POST | Restore from trash |
419
+ | `emptyTrash` | DELETE | Empty all trash |
420
+ | `createFolder` | POST | Create folder |
421
+ | `move` | POST | Move to new parent |
422
+ | `search` | GET | Search by name |
423
+ | `quota` | GET | Get storage usage |
424
+
425
+ ---
550
426
 
551
427
  ## License
552
428