@timothy-spaceman/multitrack-vcs
Version:
Version Control System for musicians
73 lines (64 loc) • 2.29 kB
text/typescript
import fs from "fs"
import path from "node:path"
import {FileHandle} from "fs/promises"
import {IFile} from "./types.js"
import {createHash} from "crypto"
export class File implements IFile {
path: string
name: string
extension: string = ""
fullPath: string // path + name + extension
constructor(fullPath: string) {
this.fullPath = fullPath
const parts = fullPath.split(path.sep)
const fileName = parts.pop()
if (!fileName) {
throw new Error("Unable to parse file name")
}
this.name = fileName
if (fileName.split(".").length > 1) {
this.name = fileName.split(".").slice(0, -1).join(".")
this.extension = fileName.split(".").slice(-1).join("")
}
this.path = parts.join(path.sep)
}
async readData(): Promise<Buffer> {
try {
return await fs.promises.readFile(this.fullPath)
} catch (err: any) {
throw new Error(`Failed to read file content: ${err.message}`)
}
}
async writeData(data: Buffer): Promise<void> {
try {
return await fs.promises.writeFile(this.fullPath, data)
} catch (err: any) {
throw new Error(`Failed to write file content: ${err.message}`)
}
}
async getHandle(): Promise<FileHandle> {
try {
return await fs.promises.open(this.fullPath, "r")
} catch (err: any) {
throw new Error(`Failed to open file handle: ${err.message}`)
}
}
async getDataHash(algo: string = "sha256"): Promise<string> {
const hash = createHash(algo)
const bufferSize = 64 * 1024
const buffer = Buffer.allocUnsafe(bufferSize)
const fileHandle = await this.getHandle()
try {
let position = 0
while (true) {
const {bytesRead} = await fileHandle.read(buffer, 0, bufferSize, position)
if (bytesRead === 0) break
hash.update(buffer.subarray(0, bytesRead))
position += bytesRead
}
} finally {
await fileHandle.close()
}
return hash.digest("hex")
}
}