u
This commit is contained in:
89
src/providers/storage.js
Normal file
89
src/providers/storage.js
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Shared filesystem storage utilities for database providers.
|
||||
*/
|
||||
|
||||
import { join } from 'node:path';
|
||||
import { promises as fsPromises } from 'node:fs';
|
||||
|
||||
export async function safeWrite(filePath, buffer) {
|
||||
if (buffer == null) return;
|
||||
const buf = Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer);
|
||||
await fsPromises.writeFile(filePath, buf);
|
||||
}
|
||||
|
||||
export async function findFileByHash(dir, hash, ext = '') {
|
||||
if (!dir || !hash) return null;
|
||||
if (ext) {
|
||||
const candidate = join(dir, hash + ext);
|
||||
try {
|
||||
await fsPromises.access(candidate);
|
||||
return candidate;
|
||||
} catch {
|
||||
// fallback
|
||||
}
|
||||
}
|
||||
const candidateNoExt = join(dir, hash);
|
||||
try {
|
||||
await fsPromises.access(candidateNoExt);
|
||||
return candidateNoExt;
|
||||
} catch {
|
||||
// fallback
|
||||
}
|
||||
try {
|
||||
const files = await fsPromises.readdir(dir);
|
||||
const match = files.find((f) => f === hash || f.startsWith(hash + '.'));
|
||||
if (match) return join(dir, match);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function safeReadByHash(dir, hash, ext = '') {
|
||||
const filePath = await findFileByHash(dir, hash, ext);
|
||||
if (!filePath) return null;
|
||||
try {
|
||||
return await fsPromises.readFile(filePath);
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') return null;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export async function safeDeleteByHash(dir, hash) {
|
||||
if (!dir || !hash) return;
|
||||
try {
|
||||
const files = await fsPromises.readdir(dir);
|
||||
const matches = files.filter((f) => f === hash || f.startsWith(hash + '.'));
|
||||
await Promise.all(matches.map((f) => fsPromises.unlink(join(dir, f))));
|
||||
} catch (err) {
|
||||
if (err.code !== 'ENOENT') throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export function extFromMimetype(mimetype) {
|
||||
if (!mimetype) return '';
|
||||
const type = mimetype.trim().toLowerCase().split(';')[0];
|
||||
const map = {
|
||||
'application/pdf': '.pdf',
|
||||
'text/plain': '.txt',
|
||||
'text/csv': '.csv',
|
||||
'text/html': '.html',
|
||||
'text/markdown': '.md',
|
||||
'image/avif': '.avif',
|
||||
'image/png': '.png',
|
||||
'image/jpeg': '.jpg',
|
||||
'image/jpg': '.jpg',
|
||||
'image/webp': '.webp',
|
||||
'image/gif': '.gif',
|
||||
'image/svg+xml': '.svg',
|
||||
'application/json': '.json',
|
||||
'application/zip': '.zip',
|
||||
'application/xml': '.xml',
|
||||
'application/octet-stream': '.bin',
|
||||
};
|
||||
if (map[type]) return map[type];
|
||||
if (type.startsWith('image/')) return '.' + type.slice(6).replace('+xml', '');
|
||||
if (type.startsWith('text/')) return '.' + type.slice(5);
|
||||
return '';
|
||||
}
|
||||
Reference in New Issue
Block a user