UNPKG

@loom-io/core

Version:

A file system wrapper for Node.js and Bun

120 lines (119 loc) 3.63 kB
import { FILE_SIZE_UNIT } from "../definitions.js"; import { Directory } from "./dir.js"; import { join as joinPath, extname, dirname, basename } from "node:path"; import { Editor } from "./editor.js"; export class LoomFile { _adapter; _dir; _name; _extension; static from(adapter, dirOrPath, name = "") { if (typeof dirOrPath === "string") { name = basename(dirOrPath); dirOrPath = new Directory(adapter, dirname(dirOrPath)); } return new LoomFile(adapter, dirOrPath, name); } constructor(_adapter, _dir, _name) { this._adapter = _adapter; this._dir = _dir; this._name = _name; } get path() { return joinPath(this.dir.path, this.name); } get name() { return this._name; } getNameWithoutExtension() { const ext = this.extension; return ext ? this.name.slice(0, -ext.length - 1) : this.name; } get extension() { if (this._extension === undefined) { const ext = extname(this.name); this._extension = ext === "" ? undefined : ext.slice(1); } return this._extension; } get dir() { return this._dir; } get parent() { return this.dir; } get adapter() { return this._adapter; } async getSizeInBytes() { const stats = await this._adapter.stat(this.path); return stats.size; } async getSize(unit = FILE_SIZE_UNIT.BYTE) { const bytes = await this.getSizeInBytes(); const index = Object.values(FILE_SIZE_UNIT).indexOf(unit); return bytes / Math.pow(1024, index); } getLastModificationTime(stats) { if (stats.ctime === undefined) { return stats.mtime; } return stats.mtime.getTime() > (stats.ctime.getTime()) ? stats.mtime : stats.ctime; } async getMeta() { const meta = await this._adapter.stat(this.path); return { size: meta.size, createdAt: meta.birthtime, updatedAt: this.getLastModificationTime(meta), }; } async getRawMeta() { return await this._adapter.stat(this.path); } async delete() { await this._adapter.deleteFile(this.path); } async copyTo(target) { if (this.adapter.isCopyable(target.adapter)) { if (target instanceof Directory) { const targetFile = target.file(this.name); await this._adapter.copyFile(this.path, targetFile.path); return targetFile; } else { await this._adapter.copyFile(this.path, target.path); return target; } } else { throw new Error("Coping between different adapters is currently not supported"); } } async exists() { const fullPath = joinPath(this.dir.path, this.name); return this._adapter.fileExists(fullPath); } async reader() { return await Editor.from(this._adapter, this); } async plain() { return await this._adapter.readFile(this.path); } async text(encoding = "utf8") { return await this._adapter.readFile(this.path, encoding); } async write(data) { await this._adapter.writeFile(this.path, data); } async create() { await this._dir.create(); await this._adapter.writeFile(this.path, Buffer.alloc(0)); } [Symbol.toPrimitive]() { return this.path; } get [Symbol.toStringTag]() { return "LoomFile"; } }