@foal/storage
Version:
Storage components for FoalTS
102 lines (101 loc) • 3.58 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConcreteDisk = exports.LocalDisk = void 0;
// std
const fs_1 = require("fs");
const promises_1 = require("node:fs/promises");
const path_1 = require("path");
const stream_1 = require("stream");
const util_1 = require("util");
const node_fs_1 = require("node:fs");
// 3p
const core_1 = require("@foal/core");
// FoalTS
const disk_service_1 = require("./disk.service");
/**
* File storage to write, read and delete files in the local file system.
*
* @export
* @class LocalDisk
* @extends {Disk}
*/
class LocalDisk extends disk_service_1.Disk {
async mkdirIfNotExists(dirname) {
const dirPath = this.getPath(dirname);
if (!(0, node_fs_1.existsSync)(dirPath)) {
await (0, promises_1.mkdir)(dirPath, { recursive: true });
}
}
async write(dirname, content, options = {}) {
let name = this.hasName(options) ? options.name : await (0, core_1.generateToken)();
if (this.hasExtension(options)) {
name = `${name}.${options.extension}`;
}
const path = (0, path_1.join)(dirname, name);
if (content instanceof Buffer) {
await (0, promises_1.writeFile)(this.getPath(path), content);
}
else {
await (0, util_1.promisify)(stream_1.pipeline)(content, (0, fs_1.createWriteStream)(this.getPath(path)));
}
return { path };
}
async read(path, content) {
try {
const { size } = await (0, promises_1.stat)(this.getPath(path));
if (content === 'buffer') {
return {
file: await (0, promises_1.readFile)(this.getPath(path)),
size
};
}
return {
file: (0, fs_1.createReadStream)(this.getPath(path))
// Do not kill the process (and crash the server) if the stream emits an error.
// Note: users can still add other listeners to the stream to "catch" the error.
// Note: error streams are unlikely to occur (most "createWriteStream" errors are simply thrown).
// TODO: test this line.
.on('error', () => { }),
size
};
}
catch (error) {
if (error.code === 'ENOENT') {
throw new disk_service_1.FileDoesNotExist(path);
}
// TODO: test this line.
throw error;
}
}
async readSize(path) {
try {
const { size } = await (0, promises_1.stat)(this.getPath(path));
return size;
}
catch (error) {
if (error.code === 'ENOENT') {
throw new disk_service_1.FileDoesNotExist(path);
}
// TODO: test this line.
throw error;
}
}
async delete(path) {
try {
await (0, promises_1.unlink)(this.getPath(path));
}
catch (error) {
if (error.code === 'ENOENT') {
throw new disk_service_1.FileDoesNotExist(path);
}
// TODO: test this line.
throw error;
}
}
getPath(path) {
const directory = core_1.Config.getOrThrow('settings.disk.local.directory', 'string', 'You must provide a directory name when using local file storage (LocalDisk).');
return (0, path_1.join)(directory, path);
}
}
exports.LocalDisk = LocalDisk;
exports.ConcreteDisk = LocalDisk;