UNPKG

@push.rocks/smartbucket

Version:

A TypeScript library providing a cloud-agnostic interface for managing object storage with functionalities like bucket management, file and directory operations, and advanced features such as metadata handling and file locking.

252 lines 17.5 kB
import * as plugins from './plugins.js'; import * as helpers from './helpers.js'; import * as interfaces from './interfaces.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 object storage * @param optionsArg */ static async create(optionsArg) { 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) { await optionsArg.directory.fastPutStream({ path: optionsArg.name, stream: contents, }); } else { await optionsArg.directory.fastPut({ path: optionsArg.name, contents: contents, }); } return file; } /** * get the full path to the file * @returns the full path to the file */ getBasePath() { return plugins.path.join(this.parentDirectoryRef.getBasePath(), this.name); } constructor(optionsArg) { this.parentDirectoryRef = optionsArg.directoryRefArg; this.name = optionsArg.fileName; } async getContentsAsString() { const fileBuffer = await this.getContents(); return fileBuffer.toString(); } async getContents() { const resultBuffer = await this.parentDirectoryRef.bucketRef.fastGet({ path: this.getBasePath(), }); return resultBuffer; } async getReadStream(typeArg) { const readStream = this.parentDirectoryRef.bucketRef.fastGetStream({ path: this.getBasePath(), }, typeArg); return readStream; } /** * deletes this file */ async delete(optionsArg) { optionsArg = { ...{ mode: 'permanent', }, ...optionsArg, }; if (optionsArg.mode === 'permanent') { await this.parentDirectoryRef.bucketRef.fastRemove({ path: this.getBasePath(), }); if (!this.name.endsWith('.metadata')) { if (await this.hasMetaData()) { const metadata = await this.getMetaData(); await metadata.metadataFile.delete(optionsArg); } } } else if (optionsArg.mode === 'trash') { const metadata = await this.getMetaData(); await metadata.storeCustomMetaData({ key: 'recycle', value: { deletedAt: Date.now(), originalPath: this.getBasePath(), }, }); const trash = await this.parentDirectoryRef.bucketRef.getTrash(); const trashDir = await trash.getTrashDir(); await this.move({ directory: trashDir, path: await trash.getTrashKeyByOriginalBasePath(this.getBasePath()), }); } await this.parentDirectoryRef.listFiles(); } /** * restores */ async restore(optionsArg = {}) { optionsArg = { useOriginalPath: (() => { return optionsArg.toPath ? false : true; })(), overwrite: false, ...optionsArg, }; const metadata = await this.getMetaData(); const moveToPath = optionsArg.toPath || (await metadata.getCustomMetaData({ key: 'recycle' })).originalPath; await metadata.deleteCustomMetaData({ key: 'recycle' }); await this.move({ path: moveToPath, }); } /** * allows locking the file * @param optionsArg */ async lock(optionsArg) { const metadata = await this.getMetaData(); await metadata.setLock({ lock: 'locked', expires: Date.now() + (optionsArg?.timeoutMillis || 1000), }); } /** * actively unlocks a file * */ async unlock(optionsArg) { const metadata = await this.getMetaData(); await metadata.removeLock({ force: optionsArg?.force || false, }); } async updateWithContents(optionsArg) { if (optionsArg.contents instanceof plugins.stream.Readable || optionsArg.contents instanceof ReadableStream) { await this.parentDirectoryRef.bucketRef.fastPutStream({ path: this.getBasePath(), readableStream: optionsArg.contents, overwrite: true, }); } else if (Buffer.isBuffer(optionsArg.contents)) { await this.parentDirectoryRef.bucketRef.fastPut({ path: this.getBasePath(), contents: optionsArg.contents, overwrite: true, }); } else if (typeof optionsArg.contents === 'string') { await this.parentDirectoryRef.bucketRef.fastPut({ path: this.getBasePath(), contents: Buffer.from(optionsArg.contents, optionsArg.encoding), overwrite: true, }); } } /** * moves the file to another directory */ async move(pathDescriptorArg) { let moveToPath = ''; const isDirectory = await this.parentDirectoryRef.bucketRef.isDirectory(pathDescriptorArg); if (isDirectory) { moveToPath = await helpers.reducePathDescriptorToPath({ ...pathDescriptorArg, path: plugins.path.join(pathDescriptorArg.path, this.name), }); } else { moveToPath = await helpers.reducePathDescriptorToPath(pathDescriptorArg); } // lets move the file await this.parentDirectoryRef.bucketRef.fastMove({ sourcePath: this.getBasePath(), destinationPath: moveToPath, overwrite: true, }); // lets move the metadatafile if (!this.name.endsWith('.metadata')) { const metadata = await this.getMetaData(); await this.parentDirectoryRef.bucketRef.fastMove({ sourcePath: metadata.metadataFile.getBasePath(), destinationPath: moveToPath + '.metadata', overwrite: true, }); } // lets update references of this const baseDirectory = await this.parentDirectoryRef.bucketRef.getBaseDirectory(); this.parentDirectoryRef = await baseDirectory.getSubDirectoryByName(await helpers.reducePathDescriptorToPath(pathDescriptorArg), { couldBeFilePath: true, }); this.name = pathDescriptorArg.path; } async hasMetaData() { if (!this.name.endsWith('.metadata')) { const hasMetadataBool = MetaData.hasMetaData({ file: this, }); return hasMetadataBool; } else { return false; } } /** * allows updating the metadata of a file * @param updatedMetadata */ 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 */ async getJsonData() { const json = await this.getContentsAsString(); const parsed = await JSON.parse(json); return parsed; } async writeJsonData(dataArg) { await this.updateWithContents({ contents: JSON.stringify(dataArg), }); } async getMagicBytes(optionsArg) { return this.parentDirectoryRef.bucketRef.getMagicBytes({ path: this.getBasePath(), length: optionsArg.length, }); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5maWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5maWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sS0FBSyxVQUFVLE1BQU0saUJBQWlCLENBQUM7QUFDOUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUVqRDs7R0FFRztBQUNILE1BQU0sT0FBTyxJQUFJO0lBQ2YsU0FBUztJQUVUOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxVQVExQjtRQUNDLE1BQU0sUUFBUSxHQUNaLE9BQU8sVUFBVSxDQUFDLFFBQVEsS0FBSyxRQUFRO1lBQ3JDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLFFBQVEsQ0FBQztZQUN2RCxDQUFDLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQztRQUMxQixNQUFNLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQztZQUNwQixlQUFlLEVBQUUsVUFBVSxDQUFDLFNBQVM7WUFDckMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxJQUFJO1NBQzFCLENBQUMsQ0FBQztRQUNILElBQUksUUFBUSxZQUFZLE9BQU8sQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDaEQsTUFBTSxVQUFVLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQztnQkFDdkMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxJQUFJO2dCQUNyQixNQUFNLEVBQUUsUUFBUTthQUNqQixDQUFDLENBQUM7UUFDTCxDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sVUFBVSxDQUFDLFNBQVMsQ0FBQyxPQUFP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