99 lines
1.7 KiB
TypeScript
99 lines
1.7 KiB
TypeScript
|
|
import type { OpenMode } from 'node:fs';
|
||
|
|
import * as Node from 'node:fs/promises';
|
||
|
|
|
||
|
|
|
||
|
|
export class FileHandle {
|
||
|
|
|
||
|
|
private path: string
|
||
|
|
|
||
|
|
constructor(
|
||
|
|
path: string
|
||
|
|
) {
|
||
|
|
this.path = path
|
||
|
|
}
|
||
|
|
|
||
|
|
public async text(encoding?: BufferEncoding) {
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
if (!encoding) {
|
||
|
|
encoding = "utf-8"
|
||
|
|
}
|
||
|
|
|
||
|
|
const fileContent = await Node.readFile(this.path, {encoding: encoding})
|
||
|
|
return fileContent
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public async write(text: string, append?: boolean) {
|
||
|
|
|
||
|
|
if (!append) {
|
||
|
|
append = true
|
||
|
|
}
|
||
|
|
|
||
|
|
const flag : OpenMode = append ? "a+" : "w"
|
||
|
|
|
||
|
|
await Node.writeFile(this.path, text, {flag: flag})
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Checks if the file exists
|
||
|
|
*
|
||
|
|
* @param path `string` path for the file
|
||
|
|
* @returns if the file is readable
|
||
|
|
*/
|
||
|
|
export async function doesFileExist(path: string): Promise<boolean> {
|
||
|
|
|
||
|
|
try {
|
||
|
|
await Node.access(path)
|
||
|
|
} catch {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
|
||
|
|
return true
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
export async function loadFile(path: string, create?: boolean): Promise<FileHandle> {
|
||
|
|
|
||
|
|
const DEFAULT_MODE = 0o600
|
||
|
|
|
||
|
|
// Safe to use
|
||
|
|
// worst case: create = false -> create = false
|
||
|
|
if (!create) {
|
||
|
|
create = false
|
||
|
|
}
|
||
|
|
|
||
|
|
let fd : Node.FileHandle | null = null
|
||
|
|
|
||
|
|
try {
|
||
|
|
fd = await Node.open(path, "r+", DEFAULT_MODE)
|
||
|
|
} catch {
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// We have a FD, return it
|
||
|
|
if (fd) {
|
||
|
|
await fd.close()
|
||
|
|
return new FileHandle(path)
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
if (!create) {
|
||
|
|
// UGLY: make more specific
|
||
|
|
throw new Error("The required file does not exist")
|
||
|
|
}
|
||
|
|
|
||
|
|
// We do want this to throw without catching here
|
||
|
|
fd = await Node.open(path, "w", DEFAULT_MODE)
|
||
|
|
await fd.close()
|
||
|
|
|
||
|
|
return new FileHandle(path)
|
||
|
|
|
||
|
|
}
|