@muhgholy/next-drive 4.23.1 → 4.23.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.
- package/README.md +14 -0
- package/dist/{chunk-MZFX6M44.js → chunk-R43JCXQB.js} +85 -10
- package/dist/chunk-R43JCXQB.js.map +1 -0
- package/dist/{chunk-BGCV4Y2V.cjs → chunk-RBLDH7CP.cjs} +86 -10
- package/dist/chunk-RBLDH7CP.cjs.map +1 -0
- package/dist/server/controllers/drive.d.ts +16 -0
- package/dist/server/controllers/drive.d.ts.map +1 -1
- package/dist/server/express.cjs +11 -11
- package/dist/server/express.js +2 -2
- package/dist/server/hono.cjs +11 -11
- package/dist/server/hono.js +2 -2
- package/dist/server/index.cjs +19 -15
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-BGCV4Y2V.cjs.map +0 -1
- package/dist/chunk-MZFX6M44.js.map +0 -1
package/README.md
CHANGED
|
@@ -521,6 +521,20 @@ const stats = await DatabaseMongoDrive.aggregate([
|
|
|
521
521
|
]);
|
|
522
522
|
```
|
|
523
523
|
|
|
524
|
+
### Cleanup Orphaned Files
|
|
525
|
+
|
|
526
|
+
Remove orphaned file folders from storage that no longer exist in the database, and clean up leftover temp directories:
|
|
527
|
+
|
|
528
|
+
```typescript
|
|
529
|
+
import { driveCleanup } from "@muhgholy/next-drive/server";
|
|
530
|
+
|
|
531
|
+
const result = await driveCleanup();
|
|
532
|
+
console.log(`Removed ${result.removed.length} orphaned folders`);
|
|
533
|
+
console.log(`Freed ${result.totalFreedInBytes} bytes`);
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
**Returns:** `{ removed: string[], totalFreedInBytes: number }`
|
|
537
|
+
|
|
524
538
|
### Delete File or Folder
|
|
525
539
|
|
|
526
540
|
Permanently delete a file or folder from the drive system:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import formidable from 'formidable';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import fs from 'fs';
|
|
4
|
-
import
|
|
4
|
+
import os2 from 'os';
|
|
5
5
|
import crypto2 from 'crypto';
|
|
6
6
|
import mongoose, { Schema, isValidObjectId } from 'mongoose';
|
|
7
7
|
import sharp2 from 'sharp';
|
|
@@ -260,7 +260,7 @@ var driveConfiguration = async (config) => {
|
|
|
260
260
|
if (g.migrationPromise) await g.migrationPromise;
|
|
261
261
|
return g.config;
|
|
262
262
|
}
|
|
263
|
-
const resolvedPath = config.storage?.path || path.join(
|
|
263
|
+
const resolvedPath = config.storage?.path || path.join(os2.tmpdir(), "next-drive-data");
|
|
264
264
|
const mode = config.mode || "NORMAL";
|
|
265
265
|
if (mode === "ROOT") {
|
|
266
266
|
g.config = {
|
|
@@ -1594,7 +1594,7 @@ var driveUpload = async (source, key, options) => {
|
|
|
1594
1594
|
const stats = fs.statSync(source);
|
|
1595
1595
|
fileSize = stats.size;
|
|
1596
1596
|
} else if (Buffer.isBuffer(source)) {
|
|
1597
|
-
const tempDir = path.join(
|
|
1597
|
+
const tempDir = path.join(os2.tmpdir(), "next-drive-uploads");
|
|
1598
1598
|
if (!fs.existsSync(tempDir)) {
|
|
1599
1599
|
fs.mkdirSync(tempDir, { recursive: true });
|
|
1600
1600
|
}
|
|
@@ -1603,7 +1603,7 @@ var driveUpload = async (source, key, options) => {
|
|
|
1603
1603
|
sourceFilePath = tempFilePath;
|
|
1604
1604
|
fileSize = source.length;
|
|
1605
1605
|
} else {
|
|
1606
|
-
const tempDir = path.join(
|
|
1606
|
+
const tempDir = path.join(os2.tmpdir(), "next-drive-uploads");
|
|
1607
1607
|
if (!fs.existsSync(tempDir)) {
|
|
1608
1608
|
fs.mkdirSync(tempDir, { recursive: true });
|
|
1609
1609
|
}
|
|
@@ -1703,6 +1703,81 @@ var driveUpload = async (source, key, options) => {
|
|
|
1703
1703
|
}
|
|
1704
1704
|
}
|
|
1705
1705
|
};
|
|
1706
|
+
var driveCleanup = async () => {
|
|
1707
|
+
const config = getDriveConfig();
|
|
1708
|
+
const fileDir = path.join(config.storage.path, "file");
|
|
1709
|
+
if (!fs.existsSync(fileDir)) {
|
|
1710
|
+
return { removed: [], totalFreedInBytes: 0 };
|
|
1711
|
+
}
|
|
1712
|
+
const folderNames = fs.readdirSync(fileDir).filter((name) => {
|
|
1713
|
+
const fullPath = path.join(fileDir, name);
|
|
1714
|
+
return fs.statSync(fullPath).isDirectory();
|
|
1715
|
+
});
|
|
1716
|
+
if (folderNames.length === 0) {
|
|
1717
|
+
return { removed: [], totalFreedInBytes: 0 };
|
|
1718
|
+
}
|
|
1719
|
+
const getDirSize = (dirPath) => {
|
|
1720
|
+
let size = 0;
|
|
1721
|
+
try {
|
|
1722
|
+
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
1723
|
+
for (const entry of entries) {
|
|
1724
|
+
const entryPath = path.join(dirPath, entry.name);
|
|
1725
|
+
if (entry.isFile()) {
|
|
1726
|
+
size += fs.statSync(entryPath).size;
|
|
1727
|
+
} else if (entry.isDirectory()) {
|
|
1728
|
+
size += getDirSize(entryPath);
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
} catch {
|
|
1732
|
+
}
|
|
1733
|
+
return size;
|
|
1734
|
+
};
|
|
1735
|
+
const BATCH_SIZE = 500;
|
|
1736
|
+
const existingIds = /* @__PURE__ */ new Set();
|
|
1737
|
+
for (let i = 0; i < folderNames.length; i += BATCH_SIZE) {
|
|
1738
|
+
const batch = folderNames.slice(i, i + BATCH_SIZE);
|
|
1739
|
+
const docs = await drive_default.find(
|
|
1740
|
+
{ _id: { $in: batch } },
|
|
1741
|
+
{ _id: 1 }
|
|
1742
|
+
).lean();
|
|
1743
|
+
for (const doc of docs) {
|
|
1744
|
+
existingIds.add(doc._id.toString());
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
const removed = [];
|
|
1748
|
+
let totalFreedInBytes = 0;
|
|
1749
|
+
for (const name of folderNames) {
|
|
1750
|
+
if (!existingIds.has(name)) {
|
|
1751
|
+
const dirPath = path.join(fileDir, name);
|
|
1752
|
+
try {
|
|
1753
|
+
totalFreedInBytes += getDirSize(dirPath);
|
|
1754
|
+
fs.rmSync(dirPath, { recursive: true, force: true });
|
|
1755
|
+
removed.push(name);
|
|
1756
|
+
} catch (e) {
|
|
1757
|
+
console.error(`[next-drive] Failed to remove orphaned folder ${name}:`, e);
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
const tempDir = path.join(config.storage.path, "temp");
|
|
1762
|
+
if (fs.existsSync(tempDir)) {
|
|
1763
|
+
try {
|
|
1764
|
+
totalFreedInBytes += getDirSize(tempDir);
|
|
1765
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
1766
|
+
} catch (e) {
|
|
1767
|
+
console.error("[next-drive] Failed to remove temp directory:", e);
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
const systemTmpDir = path.join(os2.tmpdir(), "next-drive-uploads");
|
|
1771
|
+
if (fs.existsSync(systemTmpDir)) {
|
|
1772
|
+
try {
|
|
1773
|
+
totalFreedInBytes += getDirSize(systemTmpDir);
|
|
1774
|
+
fs.rmSync(systemTmpDir, { recursive: true, force: true });
|
|
1775
|
+
} catch (e) {
|
|
1776
|
+
console.error("[next-drive] Failed to remove system temp directory:", e);
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
return { removed, totalFreedInBytes };
|
|
1780
|
+
};
|
|
1706
1781
|
|
|
1707
1782
|
// src/server/index.ts
|
|
1708
1783
|
var getProvider = async (req, owner) => {
|
|
@@ -2120,7 +2195,7 @@ var driveAPIHandler = async (req, res) => {
|
|
|
2120
2195
|
// ** 3. UPLOAD **
|
|
2121
2196
|
case "upload": {
|
|
2122
2197
|
if (req.method !== "POST") return res.status(405).json({ status: 405, message: "Only POST allowed" });
|
|
2123
|
-
const systemTmpDir = path.join(
|
|
2198
|
+
const systemTmpDir = path.join(os2.tmpdir(), "next-drive-uploads");
|
|
2124
2199
|
if (!fs.existsSync(systemTmpDir)) fs.mkdirSync(systemTmpDir, { recursive: true });
|
|
2125
2200
|
const form = formidable({
|
|
2126
2201
|
multiples: false,
|
|
@@ -2156,7 +2231,7 @@ var driveAPIHandler = async (req, res) => {
|
|
|
2156
2231
|
}
|
|
2157
2232
|
const { chunkIndex, totalChunks, driveId, fileName, fileSize: fileSizeInBytes, fileType, folderId } = uploadData.data;
|
|
2158
2233
|
let currentUploadId = driveId;
|
|
2159
|
-
const tempBaseDir = path.join(
|
|
2234
|
+
const tempBaseDir = path.join(os2.tmpdir(), "next-drive-uploads");
|
|
2160
2235
|
if (!currentUploadId) {
|
|
2161
2236
|
if (chunkIndex !== 0) return res.status(400).json({ message: "Missing upload ID for non-zero chunk" });
|
|
2162
2237
|
if (fileType && config.security) {
|
|
@@ -2304,7 +2379,7 @@ var driveAPIHandler = async (req, res) => {
|
|
|
2304
2379
|
const cancelData = cancelQuerySchema.safeParse(req.query);
|
|
2305
2380
|
if (!cancelData.success) return res.status(400).json({ status: 400, message: "Invalid ID" });
|
|
2306
2381
|
const { id } = cancelData.data;
|
|
2307
|
-
const tempUploadDir = path.join(
|
|
2382
|
+
const tempUploadDir = path.join(os2.tmpdir(), "next-drive-uploads", id);
|
|
2308
2383
|
if (fs.existsSync(tempUploadDir)) {
|
|
2309
2384
|
try {
|
|
2310
2385
|
fs.rmSync(tempUploadDir, { recursive: true, force: true });
|
|
@@ -2449,6 +2524,6 @@ var driveAPIHandler = async (req, res) => {
|
|
|
2449
2524
|
}
|
|
2450
2525
|
};
|
|
2451
2526
|
|
|
2452
|
-
export { driveAPIHandler, driveConfiguration, driveDelete, driveFilePath, driveFileSchemaZod, driveGetUrl, driveInfo, driveList, driveListFiles, driveReadFile, driveUpload, drive_default, getDriveConfig, getDriveInformation };
|
|
2453
|
-
//# sourceMappingURL=chunk-
|
|
2454
|
-
//# sourceMappingURL=chunk-
|
|
2527
|
+
export { driveAPIHandler, driveCleanup, driveConfiguration, driveDelete, driveFilePath, driveFileSchemaZod, driveGetUrl, driveInfo, driveList, driveListFiles, driveReadFile, driveUpload, drive_default, getDriveConfig, getDriveInformation };
|
|
2528
|
+
//# sourceMappingURL=chunk-R43JCXQB.js.map
|
|
2529
|
+
//# sourceMappingURL=chunk-R43JCXQB.js.map
|