79 lines
2.1 KiB
JavaScript
79 lines
2.1 KiB
JavaScript
import express from 'express';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
import dotenv from 'dotenv';
|
|
import cors from "cors";
|
|
import { S3Client, ListObjectsV2Command } from "@aws-sdk/client-s3";
|
|
|
|
// Load environment variables
|
|
dotenv.config();
|
|
|
|
// Set up __dirname in ESM
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
const app = express();
|
|
const port = process.env.PORT || 3000;
|
|
|
|
app.use(cors());
|
|
|
|
const s3 = new S3Client({
|
|
region: "auto",
|
|
endpoint: process.env.R2_ENDPOINT,
|
|
credentials: {
|
|
accessKeyId: process.env.R2_ACCESS_KEY,
|
|
secretAccessKey: process.env.R2_SECRET_KEY,
|
|
},
|
|
});
|
|
|
|
app.get("/api/list", async (req, res) => {
|
|
const prefix = req.query.prefix || "";
|
|
const token = req.query.token;
|
|
const search = req.query.search?.toLowerCase();
|
|
|
|
try {
|
|
const response = await s3.send(
|
|
new ListObjectsV2Command({
|
|
Bucket: process.env.R2_BUCKET,
|
|
Prefix: prefix,
|
|
ContinuationToken: token,
|
|
Delimiter: "/",
|
|
})
|
|
);
|
|
|
|
const filteredFolders = (response.CommonPrefixes || []).filter(
|
|
(p) => !search || p.Prefix.toLowerCase().includes(search)
|
|
);
|
|
|
|
const filteredFiles = (response.Contents || [])
|
|
.filter((obj) => obj.Size > 0)
|
|
.filter((obj) => !search || obj.Key.toLowerCase().includes(search));
|
|
|
|
res.json({
|
|
folders: filteredFolders.map((p) => p.Prefix),
|
|
files: filteredFiles.map((obj) => ({
|
|
key: obj.Key,
|
|
size: obj.Size,
|
|
lastModified: obj.LastModified,
|
|
})),
|
|
nextToken: response.NextContinuationToken || null,
|
|
isTruncated: response.IsTruncated || false,
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).json({ error: "Failed to list objects" });
|
|
}
|
|
});
|
|
|
|
// === STATIC FRONTEND ===
|
|
app.use(express.static(path.join(__dirname, 'dist')));
|
|
|
|
// === Fallback to index.html for client-side routing ===
|
|
app.get('/{*splat}', (req, res) => {
|
|
res.sendFile(path.join(__dirname, 'dist', 'index.html'));
|
|
});
|
|
|
|
// === START SERVER ===
|
|
app.listen(port, () => {
|
|
console.log(`Server running on http://localhost:${port}`);
|
|
}); |