@muhgholy/next-drive 3.9.0 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,25 +15,35 @@ var driveConfiguration = (config) => {
15
15
  if (mongoose2.connection.readyState !== 1) {
16
16
  throw new Error("Database not connected. Please connect to Mongoose before initializing next-drive.");
17
17
  }
18
- const mergedConfig = {
19
- ...config,
20
- security: {
21
- maxUploadSizeInBytes: config.security?.maxUploadSizeInBytes ?? 10 * 1024 * 1024,
22
- // Default to 10MB
23
- allowedMimeTypes: config.security?.allowedMimeTypes ?? ["*/*"],
24
- signedUrls: config.security?.signedUrls,
25
- trash: config.security?.trash
26
- },
27
- information: config.information ?? (async (req) => {
28
- return {
29
- key: { id: "default-user" },
30
- storage: { quotaInBytes: 10 * 1024 * 1024 * 1024 }
31
- // Default to 10GB
32
- };
33
- })
34
- };
35
- globalConfig = mergedConfig;
36
- return mergedConfig;
18
+ const mode = config.mode || "NORMAL";
19
+ if (mode === "ROOT") {
20
+ globalConfig = {
21
+ ...config,
22
+ mode: "ROOT",
23
+ security: config.security || {
24
+ maxUploadSizeInBytes: 1024 * 1024 * 1024 * 10,
25
+ // 10GB default for ROOT
26
+ allowedMimeTypes: ["*/*"]
27
+ }
28
+ };
29
+ return globalConfig;
30
+ } else {
31
+ if (!config.information) {
32
+ throw new Error("information callback is required in NORMAL mode");
33
+ }
34
+ globalConfig = {
35
+ ...config,
36
+ mode: "NORMAL",
37
+ security: {
38
+ maxUploadSizeInBytes: config.security?.maxUploadSizeInBytes ?? 10 * 1024 * 1024,
39
+ allowedMimeTypes: config.security?.allowedMimeTypes ?? ["*/*"],
40
+ signedUrls: config.security?.signedUrls,
41
+ trash: config.security?.trash
42
+ },
43
+ information: config.information
44
+ };
45
+ return globalConfig;
46
+ }
37
47
  };
38
48
  var getDriveConfig = () => {
39
49
  if (!globalConfig) throw new Error("Drive configuration not initialized");
@@ -41,6 +51,16 @@ var getDriveConfig = () => {
41
51
  };
42
52
  var getDriveInformation = async (req) => {
43
53
  const config = getDriveConfig();
54
+ if (config.mode === "ROOT") {
55
+ if (!config.information) {
56
+ return {
57
+ key: null,
58
+ storage: { quotaInBytes: Number.MAX_SAFE_INTEGER }
59
+ // Unlimited quota in ROOT mode
60
+ };
61
+ }
62
+ return config.information(req);
63
+ }
44
64
  return config.information(req);
45
65
  };
46
66
  var informationSchema = new Schema({
@@ -252,19 +272,25 @@ var LocalStorageProvider = {
252
272
  search: async (query, owner, accountId) => {
253
273
  },
254
274
  getQuota: async (owner, accountId, configuredQuotaInBytes) => {
275
+ const config = getDriveConfig();
276
+ const isRootMode = config.mode === "ROOT";
277
+ const match = {
278
+ "information.type": "FILE",
279
+ trashedAt: null,
280
+ "provider.type": "LOCAL",
281
+ storageAccountId: accountId || null
282
+ };
283
+ if (!isRootMode) {
284
+ match.owner = owner;
285
+ }
255
286
  const result = await drive_default.aggregate([
256
- {
257
- $match: {
258
- owner,
259
- "information.type": "FILE",
260
- trashedAt: null,
261
- "provider.type": "LOCAL",
262
- storageAccountId: accountId || null
263
- }
264
- },
287
+ { $match: match },
265
288
  { $group: { _id: null, total: { $sum: "$information.sizeInBytes" } } }
266
289
  ]);
267
290
  const usedInBytes = result[0]?.total || 0;
291
+ if (isRootMode) {
292
+ return { usedInBytes, quotaInBytes: Number.MAX_SAFE_INTEGER };
293
+ }
268
294
  return { usedInBytes, quotaInBytes: configuredQuotaInBytes ?? 0 };
269
295
  },
270
296
  openStream: async (item, accountId) => {
@@ -606,6 +632,23 @@ var GoogleDriveProvider = {
606
632
  }
607
633
  },
608
634
  getQuota: async (owner, accountId, _configuredQuotaInBytes) => {
635
+ const config = getDriveConfig();
636
+ const isRootMode = config.mode === "ROOT";
637
+ if (isRootMode) {
638
+ const result = await drive_default.aggregate([
639
+ {
640
+ $match: {
641
+ "information.type": "FILE",
642
+ trashedAt: null,
643
+ "provider.type": "GOOGLE",
644
+ storageAccountId: accountId || null
645
+ }
646
+ },
647
+ { $group: { _id: null, total: { $sum: "$information.sizeInBytes" } } }
648
+ ]);
649
+ const usedInBytes = result[0]?.total || 0;
650
+ return { usedInBytes, quotaInBytes: Number.MAX_SAFE_INTEGER };
651
+ }
609
652
  try {
610
653
  const { client } = await createAuthClient(owner, accountId);
611
654
  const drive = google.drive({ version: "v3", auth: client });
@@ -832,7 +875,7 @@ var getNextOrderValue = async (owner) => {
832
875
  };
833
876
  var driveGetUrl = (fileId, options) => {
834
877
  const config = getDriveConfig();
835
- if (!config.security.signedUrls?.enabled) {
878
+ if (!config.security?.signedUrls?.enabled) {
836
879
  return `/api/drive?action=serve&id=${fileId}`;
837
880
  }
838
881
  const { secret, expiresIn } = config.security.signedUrls;
@@ -1119,13 +1162,14 @@ var driveUpload = async (source, key, options) => {
1119
1162
  };
1120
1163
  mimeType = mimeTypes[ext] || "application/octet-stream";
1121
1164
  }
1122
- if (!validateMimeType(mimeType, config.security.allowedMimeTypes)) {
1165
+ if (config.security && !validateMimeType(mimeType, config.security.allowedMimeTypes)) {
1123
1166
  throw new Error(`File type ${mimeType} not allowed`);
1124
1167
  }
1125
- if (fileSize > config.security.maxUploadSizeInBytes) {
1168
+ if (config.security && fileSize > config.security.maxUploadSizeInBytes) {
1126
1169
  throw new Error(`File size ${fileSize} exceeds maximum allowed size ${config.security.maxUploadSizeInBytes}`);
1127
1170
  }
1128
- if (!options.enforce) {
1171
+ const isRootMode = config.mode === "ROOT";
1172
+ if (!options.enforce && !isRootMode) {
1129
1173
  const quota = await provider.getQuota(key, accountId, void 0);
1130
1174
  if (quota.usedInBytes + fileSize > quota.quotaInBytes) {
1131
1175
  throw new Error("Storage quota exceeded");
@@ -1251,7 +1295,7 @@ var driveAPIHandler = async (req, res) => {
1251
1295
  }
1252
1296
  const drive = await drive_default.findById(id);
1253
1297
  if (!drive) return res.status(404).json({ status: 404, message: "File not found" });
1254
- if (config.security.signedUrls?.enabled) {
1298
+ if (config.security?.signedUrls?.enabled) {
1255
1299
  if (!token || typeof token !== "string") {
1256
1300
  return res.status(401).json({ status: 401, message: "Missing or invalid token" });
1257
1301
  }
@@ -1303,9 +1347,11 @@ var driveAPIHandler = async (req, res) => {
1303
1347
  }
1304
1348
  }
1305
1349
  try {
1350
+ const mode = config.mode || "NORMAL";
1306
1351
  const information = await getDriveInformation(req);
1307
1352
  const { key: owner } = information;
1308
1353
  const STORAGE_PATH = config.storage.path;
1354
+ const isRootMode = mode === "ROOT";
1309
1355
  if (action === "information") {
1310
1356
  const { clientId, clientSecret, redirectUri } = config.storage?.google || {};
1311
1357
  const googleConfigured = !!(clientId && clientSecret && redirectUri);
@@ -1315,7 +1361,8 @@ var driveAPIHandler = async (req, res) => {
1315
1361
  data: {
1316
1362
  providers: {
1317
1363
  google: googleConfigured
1318
- }
1364
+ },
1365
+ mode
1319
1366
  }
1320
1367
  });
1321
1368
  }
@@ -1448,12 +1495,14 @@ var driveAPIHandler = async (req, res) => {
1448
1495
  console.error("Sync failed", e);
1449
1496
  }
1450
1497
  const query = {
1451
- owner,
1452
1498
  "provider.type": provider.name,
1453
1499
  storageAccountId: accountId || null,
1454
1500
  parentId: folderId === "root" || !folderId ? null : folderId,
1455
1501
  trashedAt: null
1456
1502
  };
1503
+ if (!isRootMode) {
1504
+ query.owner = owner;
1505
+ }
1457
1506
  if (afterId) query._id = { $lt: afterId };
1458
1507
  const items = await drive_default.find(query, {}, { sort: { order: 1, _id: -1 }, limit });
1459
1508
  const plainItems = await Promise.all(items.map((item) => item.toClient()));
@@ -1473,12 +1522,14 @@ var driveAPIHandler = async (req, res) => {
1473
1522
  }
1474
1523
  }
1475
1524
  const query = {
1476
- owner,
1477
1525
  "provider.type": provider.name,
1478
1526
  storageAccountId: accountId || null,
1479
1527
  trashedAt: trashed ? { $ne: null } : null,
1480
1528
  name: { $regex: q, $options: "i" }
1481
1529
  };
1530
+ if (!isRootMode) {
1531
+ query.owner = owner;
1532
+ }
1482
1533
  if (folderId && folderId !== "root") query.parentId = folderId;
1483
1534
  const items = await drive_default.find(query, {}, { limit, sort: { createdAt: -1 } });
1484
1535
  const plainItems = await Promise.all(items.map((i) => i.toClient()));
@@ -1491,7 +1542,7 @@ var driveAPIHandler = async (req, res) => {
1491
1542
  if (!fs4.existsSync(systemTmpDir)) fs4.mkdirSync(systemTmpDir, { recursive: true });
1492
1543
  const form = formidable({
1493
1544
  multiples: false,
1494
- maxFileSize: config.security.maxUploadSizeInBytes * 2,
1545
+ maxFileSize: (config.security?.maxUploadSizeInBytes ?? 1024 * 1024 * 1024) * 2,
1495
1546
  uploadDir: systemTmpDir,
1496
1547
  keepExtensions: true
1497
1548
  });
@@ -1526,14 +1577,18 @@ var driveAPIHandler = async (req, res) => {
1526
1577
  const tempBaseDir = path3.join(os2.tmpdir(), "next-drive-uploads");
1527
1578
  if (!currentUploadId) {
1528
1579
  if (chunkIndex !== 0) return res.status(400).json({ message: "Missing upload ID for non-zero chunk" });
1529
- if (fileType && !validateMimeType(fileType, config.security.allowedMimeTypes)) {
1530
- cleanupTempFiles(files);
1531
- return res.status(400).json({ status: 400, message: `File type ${fileType} not allowed` });
1580
+ if (fileType && config.security) {
1581
+ if (!validateMimeType(fileType, config.security.allowedMimeTypes)) {
1582
+ cleanupTempFiles(files);
1583
+ return res.status(400).json({ status: 400, message: `File type ${fileType} not allowed` });
1584
+ }
1532
1585
  }
1533
- const quota = await provider.getQuota(owner, accountId, information.storage.quotaInBytes);
1534
- if (quota.usedInBytes + fileSizeInBytes > quota.quotaInBytes) {
1535
- cleanupTempFiles(files);
1536
- return res.status(413).json({ status: 413, message: "Storage quota exceeded" });
1586
+ if (!isRootMode) {
1587
+ const quota = await provider.getQuota(owner, accountId, information.storage.quotaInBytes);
1588
+ if (quota.usedInBytes + fileSizeInBytes > quota.quotaInBytes) {
1589
+ cleanupTempFiles(files);
1590
+ return res.status(413).json({ status: 413, message: "Storage quota exceeded" });
1591
+ }
1537
1592
  }
1538
1593
  currentUploadId = crypto2.randomUUID();
1539
1594
  const uploadDir = path3.join(tempBaseDir, currentUploadId);
@@ -1798,5 +1853,5 @@ var driveAPIHandler = async (req, res) => {
1798
1853
  };
1799
1854
 
1800
1855
  export { driveAPIHandler, driveConfiguration, driveDelete, driveFilePath, driveFileSchemaZod, driveGetUrl, driveInfo, driveList, driveReadFile, driveUpload, getDriveConfig, getDriveInformation };
1801
- //# sourceMappingURL=chunk-WPX4ZQ4V.js.map
1802
- //# sourceMappingURL=chunk-WPX4ZQ4V.js.map
1856
+ //# sourceMappingURL=chunk-32UNO3KE.js.map
1857
+ //# sourceMappingURL=chunk-32UNO3KE.js.map