UNPKG

@slynova/flydrive

Version:

Flexible and Fluent way to manage storage in Node.js.

246 lines 7.69 kB
"use strict"; /** * @slynova/flydrive * * @license MIT * @copyright Slynova - Romain Lanz <romain.lanz@slynova.ch> */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LocalFileSystemStorage = void 0; const fse = __importStar(require("fs-extra")); const fs_1 = require("fs"); const path_1 = require("path"); const Storage_1 = __importDefault(require("./Storage")); const utils_1 = require("./utils"); const exceptions_1 = require("./exceptions"); function handleError(err, location) { switch (err.code) { case 'ENOENT': return new exceptions_1.FileNotFound(err, location); case 'EPERM': return new exceptions_1.PermissionMissing(err, location); default: return new exceptions_1.UnknownException(err, err.code, location); } } class LocalFileSystemStorage extends Storage_1.default { constructor(config) { super(); this.$root = path_1.resolve(config.root); } /** * Returns full path relative to the storage's root directory. */ _fullPath(relativePath) { return path_1.join(this.$root, path_1.join(path_1.sep, relativePath)); } /** * Appends content to a file. */ async append(location, content) { try { const result = await fse.appendFile(this._fullPath(location), content); return { raw: result }; } catch (e) { throw handleError(e, location); } } /** * Copy a file to a location. */ async copy(src, dest) { try { const result = await fse.copy(this._fullPath(src), this._fullPath(dest)); return { raw: result }; } catch (e) { throw handleError(e, `${src} -> ${dest}`); } } /** * Delete existing file. */ async delete(location) { try { const result = await fse.unlink(this._fullPath(location)); return { raw: result, wasDeleted: true }; } catch (e) { e = handleError(e, location); if (e instanceof exceptions_1.FileNotFound) { return { raw: undefined, wasDeleted: false }; } throw e; } } /** * Returns the driver. */ driver() { return fse; } /** * Determines if a file or folder already exists. */ async exists(location) { try { const result = await fse.pathExists(this._fullPath(location)); return { exists: result, raw: result }; } catch (e) { throw handleError(e, location); } } /** * Returns the file contents as string. */ async get(location, encoding = 'utf-8') { try { const result = await fse.readFile(this._fullPath(location), encoding); return { content: result, raw: result }; } catch (e) { throw handleError(e, location); } } /** * Returns the file contents as Buffer. */ async getBuffer(location) { try { const result = await fse.readFile(this._fullPath(location)); return { content: result, raw: result }; } catch (e) { throw handleError(e, location); } } /** * Returns file size in bytes. */ async getStat(location) { try { const stat = await fse.stat(this._fullPath(location)); return { size: stat.size, modified: stat.mtime, raw: stat, }; } catch (e) { throw handleError(e, location); } } /** * Returns a read stream for a file location. */ getStream(location) { return fse.createReadStream(this._fullPath(location)); } /** * Move file to a new location. */ async move(src, dest) { try { const result = await fse.move(this._fullPath(src), this._fullPath(dest)); return { raw: result }; } catch (e) { throw handleError(e, `${src} -> ${dest}`); } } /** * Prepends content to a file. */ async prepend(location, content) { try { const { content: actualContent } = await this.get(location, 'utf-8'); return this.put(location, `${content}${actualContent}`); } catch (e) { if (e instanceof exceptions_1.FileNotFound) { return this.put(location, content); } throw e; } } /** * Creates a new file. * This method will create missing directories on the fly. */ async put(location, content) { const fullPath = this._fullPath(location); try { if (utils_1.isReadableStream(content)) { const dir = path_1.dirname(fullPath); await fse.ensureDir(dir); const ws = fse.createWriteStream(fullPath); await utils_1.pipeline(content, ws); return { raw: undefined }; } const result = await fse.outputFile(fullPath, content); return { raw: result }; } catch (e) { throw handleError(e, location); } } /** * List files with a given prefix. */ flatList(prefix = '') { const fullPrefix = this._fullPath(prefix); return this._flatDirIterator(fullPrefix, prefix); } async *_flatDirIterator(prefix, originalPrefix) { const prefixDirectory = prefix[prefix.length - 1] === path_1.sep ? prefix : path_1.dirname(prefix); try { const dir = await fs_1.promises.opendir(prefixDirectory); for await (const file of dir) { const fileName = path_1.join(prefixDirectory, file.name); if (fileName.startsWith(prefix)) { if (file.isDirectory()) { yield* this._flatDirIterator(path_1.join(fileName, path_1.sep), originalPrefix); } else if (file.isFile()) { const path = path_1.relative(this.$root, fileName); yield { raw: null, path, }; } } } } catch (e) { if (e.code !== 'ENOENT') { throw handleError(e, originalPrefix); } } } } exports.LocalFileSystemStorage = LocalFileSystemStorage; //# sourceMappingURL=LocalFileSystemStorage.js.map