176 lines
4.5 KiB
TypeScript
176 lines
4.5 KiB
TypeScript
import * as plugins from './plugins.js';
|
|
import { Directory } from './classes.directory.js';
|
|
import { MetaData } from './classes.metadata.js';
|
|
|
|
|
|
/**
|
|
* represents a file in a directory
|
|
*/
|
|
export class File {
|
|
// STATIC
|
|
|
|
/**
|
|
* creates a file in draft mode
|
|
* you need to call .save() to store it in s3
|
|
* @param optionsArg
|
|
*/
|
|
public static async create(optionsArg: {
|
|
directory: Directory;
|
|
name: string;
|
|
contents: Buffer | string | plugins.stream.Readable;
|
|
/**
|
|
* if contents are of type string, you can specify the encoding here
|
|
*/
|
|
encoding?: 'utf8' | 'binary';
|
|
}): Promise<File> {
|
|
const contents =
|
|
typeof optionsArg.contents === 'string'
|
|
? Buffer.from(optionsArg.contents, optionsArg.encoding)
|
|
: optionsArg.contents;
|
|
const file = new File({
|
|
directoryRefArg: optionsArg.directory,
|
|
fileName: optionsArg.name,
|
|
});
|
|
if (contents instanceof plugins.stream.Readable) {} else {
|
|
await optionsArg.directory.fastPut({
|
|
path: optionsArg.name,
|
|
contents: contents,
|
|
});
|
|
}
|
|
return file;
|
|
}
|
|
|
|
// INSTANCE
|
|
public parentDirectoryRef: Directory;
|
|
public name: string;
|
|
|
|
public getBasePath(): string {
|
|
return plugins.path.join(this.parentDirectoryRef.getBasePath(), this.name);
|
|
};
|
|
|
|
constructor(optionsArg: { directoryRefArg: Directory; fileName: string }) {
|
|
this.parentDirectoryRef = optionsArg.directoryRefArg;
|
|
this.name = optionsArg.fileName;
|
|
}
|
|
|
|
public async getContentsAsString(): Promise<string> {
|
|
const fileBuffer = await this.getContents();
|
|
return fileBuffer.toString();
|
|
}
|
|
|
|
public async getContents(): Promise<Buffer> {
|
|
const resultBuffer = await this.parentDirectoryRef.bucketRef.fastGet({
|
|
path: this.getBasePath(),
|
|
});
|
|
return resultBuffer;
|
|
}
|
|
|
|
public async getReadStream() {
|
|
const readStream = this.parentDirectoryRef.bucketRef.fastGetStream({
|
|
path: this.getBasePath(),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* removes this file
|
|
* for using recycling mechanics use .delete()
|
|
*/
|
|
public async remove() {
|
|
await this.parentDirectoryRef.bucketRef.fastRemove({
|
|
path: this.getBasePath(),
|
|
});
|
|
if (!this.name.endsWith('.metadata')) {
|
|
await this.parentDirectoryRef.bucketRef.fastRemove({
|
|
path: this.getBasePath() + '.metadata',
|
|
});
|
|
}
|
|
await this.parentDirectoryRef.listFiles();
|
|
}
|
|
|
|
/**
|
|
* deletes the file with recycling mechanics
|
|
*/
|
|
public async delete() {
|
|
await this.remove();
|
|
}
|
|
|
|
/**
|
|
* allows locking the file
|
|
* @param optionsArg
|
|
*/
|
|
public async lock(optionsArg?: { timeoutMillis?: number }) {
|
|
const metadata = await this.getMetaData();
|
|
await metadata.setLock({
|
|
lock: 'locked',
|
|
expires: Date.now() + (optionsArg?.timeoutMillis || 1000),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* actively unlocks a file
|
|
*
|
|
*/
|
|
public async unlock(optionsArg?: {
|
|
/**
|
|
* unlock the file even if not locked from this instance
|
|
*/
|
|
force?: boolean;
|
|
}) {
|
|
const metadata = await this.getMetaData();
|
|
await metadata.removeLock({
|
|
force: optionsArg?.force,
|
|
});
|
|
}
|
|
|
|
public async updateWithContents(optionsArg: {
|
|
contents: Buffer | string | plugins.stream.Readable;
|
|
encoding?: 'utf8' | 'binary';
|
|
}) {
|
|
if (optionsArg.contents instanceof plugins.stream.Readable) {
|
|
await this.parentDirectoryRef.bucketRef.fastPutStream({
|
|
path: this.getBasePath(),
|
|
dataStream: optionsArg.contents,
|
|
});
|
|
} else if (Buffer.isBuffer(optionsArg.contents)) {
|
|
await this.parentDirectoryRef.bucketRef.fastPut({
|
|
path: this.getBasePath(),
|
|
contents: optionsArg.contents,
|
|
});
|
|
} else if (typeof optionsArg.contents === 'string') {
|
|
await this.parentDirectoryRef.bucketRef.fastPut({
|
|
path: this.getBasePath(),
|
|
contents: Buffer.from(optionsArg.contents, optionsArg.encoding),
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* allows updating the metadata of a file
|
|
* @param updatedMetadata
|
|
*/
|
|
public async getMetaData() {
|
|
if (this.name.endsWith('.metadata')) {
|
|
throw new Error('metadata files cannot have metadata');
|
|
}
|
|
const metadata = await MetaData.createForFile({
|
|
file: this,
|
|
});
|
|
return metadata;
|
|
}
|
|
|
|
/**
|
|
* gets the contents as json
|
|
*/
|
|
public async getJsonData() {
|
|
const json = await this.getContentsAsString();
|
|
const parsed = await JSON.parse(json);
|
|
return parsed;
|
|
}
|
|
|
|
public async writeJsonData(dataArg: any) {
|
|
await this.updateWithContents({
|
|
contents: JSON.stringify(dataArg),
|
|
});
|
|
}
|
|
}
|