@loom-io/core
Version:
A file system wrapper for Node.js and Bun
120 lines (119 loc) • 3.63 kB
JavaScript
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";
}
}