UNPKG

@mieweb/wikigdrive

Version:

Google Drive to MarkDown synchronization

118 lines (117 loc) 3.91 kB
import fs from 'node:fs'; import path from 'node:path'; import crypto from 'node:crypto'; export function pathResolve(rootPath, ...args) { const retVal = path.resolve(path.join(rootPath, ...args)); if (!retVal.startsWith(rootPath)) { throw new Error('Access denied: ' + retVal + ' outside of ' + rootPath); } return retVal; } export class FileService { constructor(rootPath = '/') { Object.defineProperty(this, "rootPath", { enumerable: true, configurable: true, writable: true, value: rootPath }); if (!this.rootPath) { throw new Error('Empty rootPath'); } } async mkdir(dirPath) { if (!await this.exists(dirPath)) { fs.mkdirSync(pathResolve(this.rootPath, dirPath), { recursive: true }); } } async rmdir(dirPath) { if (await this.exists(dirPath)) { fs.rmSync(pathResolve(this.rootPath, dirPath), { recursive: true }); } } async remove(filePath) { if (!await this.exists(filePath)) { return; } const stat = fs.statSync(pathResolve(this.rootPath, filePath)); if (stat.isDirectory()) { await this.rmdir(filePath); } if (stat.isFile()) { fs.unlinkSync(pathResolve(this.rootPath, filePath)); } } async isDirectory(filePath) { const stat = fs.statSync(pathResolve(this.rootPath, filePath)); return stat.isDirectory(); } async exists(filePath) { return fs.existsSync(pathResolve(this.rootPath, filePath)); } async getSize(filePath) { const stats = fs.statSync(pathResolve(this.rootPath, filePath)); return stats.size; } async getMtime(filePath) { const stats = fs.statSync(pathResolve(this.rootPath, filePath)); return +stats.mtime; } readBuffer(filePath) { return new Promise((resolve, reject) => { fs.readFile(pathResolve(this.rootPath, filePath), (err, data) => { if (err) return reject(err); resolve(data); }); }); } writeBuffer(filePath, buffer) { return new Promise((resolve, reject) => { fs.writeFile(pathResolve(this.rootPath, filePath), buffer, (err) => { if (err) return reject(err); resolve(); }); }); } createWriteStream(filePath) { const stream = fs.createWriteStream(pathResolve(this.rootPath, filePath)); return stream; } createReadStream(filePath) { return fs.createReadStream(pathResolve(this.rootPath, filePath)); } md5File(filePath) { // TODO migrate to WebAPI when https://github.com/w3c/webcrypto/issues/73 is done return new Promise((resolve, reject) => { const hash = crypto.createHash('md5'); hash.setEncoding('hex'); const fullFilePath = pathResolve(this.rootPath, filePath); if (!fs.existsSync(fullFilePath)) { return resolve(null); } const fd = fs.createReadStream(fullFilePath); fd .on('error', function (err) { reject(err); }) .on('end', function () { hash.end(); resolve(hash.read()); // the desired sha1sum }); fd.pipe(hash); }); } async move(path1, path2) { fs.renameSync(pathResolve(this.rootPath, path1), pathResolve(this.rootPath, path2)); } async list(dirPath = '') { const fullPath = pathResolve(this.rootPath, dirPath); if (!await this.exists(dirPath)) { return []; } const files = fs.readdirSync(fullPath); return files; } }