UNPKG

@fairdatasociety/fairdrive-opfs

Version:

Fairdrive OPFS - integrate data sources from Web 2.0 or Web 3.0

213 lines (212 loc) 6 kB
import { getOriginPrivateDirectory } from 'file-system-access'; const { GONE } = errors; import { errors } from 'file-system-access/lib/util.js'; import { Subject } from 'rxjs'; import { FileSync } from './file-sync'; /** * FdpConnectProvider is the base class for all providers. */ export class FdpConnectProvider { constructor(config) { this.config = config; this.onMount = new Subject(); } initialize(options) { Object.assign(this, options); } /** * Get the current mount point. * @returns Current mount point */ getCurrentMount() { return this.mount; } /** * getFSHandler returns a FileSystemDirectoryHandle for the given provider. * @param mount - mount point * @returns a FileSystemDirectoryHandle */ async getFSHandler(mount) { const adapter = await import('./adapter'); // FdpConnectAdapter(mount, this.filesystemDriver) this.mount = mount; this.onMount.next(mount); return getOriginPrivateDirectory(adapter, { mount, driver: this.filesystemDriver }); } /** * getTransferHandler returns a FileSync for the given provider. * @returns a FileSync */ getTransferHandler() { return new FileSync(this.filesystemDriver); } } const File = globalThis.File; class Sink { constructor(mount, driver, file) { this.mount = mount; this.driver = driver; this.file = file; } /** * Returns true if the file exists, else false * @param key * @param options * @returns */ async has(key) { try { return this.driver.exists(key, this.mount); } catch (e) { return false; } } /** * Write a chunk to the file */ async write(chunk) { this.file = chunk; } /** * Close the file */ async close() { return new Promise(async (resolve, reject) => { try { await this.driver.upload(this.file, this.mount, {}); resolve(); } catch (e) { reject(e); } }); } } // FS File Handle export class FileHandle { constructor(mount, driver, name) { this.kind = 'file'; this.writable = true; this.mount = mount; this.driver = driver; this.name = name; } /** * Get the file */ async getFile() { try { const data = await this.driver.download(`${this.mount.path}${this.name}`, this.mount, {}); return new File([data.buffer], this.name); } catch (e) { throw new DOMException(...GONE); } } /** * Create a writable stream */ async createWritable(opts) { let file; if (opts && !opts.keepExistingData) { file = new File([], this.name); } else { file = await this.getFile(); } return new Sink(this.mount, this.driver, file); } /** * Check if the file is the same as the other file */ async isSameEntry(other) { return this.name === other.name; } } // FS Folder Handle export class FolderHandle { constructor(mount, driver) { this.kind = 'directory'; this.writable = true; this.readable = true; this.mount = mount; this.driver = driver; this.name = this.mount.name; this.path = this.mount.path; } /** * Entries returns a list of files and directories */ async *entries() { const entries = await this.driver.read(this.mount); if (entries && entries.dirs && entries.dirs.length > 0) { for (const entry of entries.dirs) { yield [entry, new FolderHandle(this.mount, this.driver)]; } } if (entries && entries.files && entries.files.length > 0) { for (const entry of entries.files) { yield [entry, new FileHandle(this.mount, this.driver, entry)]; } } } /** * Check if the folder is the same as the other folder */ async isSameEntry(other) { return this.path === other.path; } /** * GetDirectoryHandle returns a directory handle */ async getDirectoryHandle(name, opts = {}) { return new Promise(async (resolve, reject) => { if (opts.create) { await this.driver.createDir(`${this.mount.path}${name}`, this.mount); resolve(new FolderHandle(this.mount, this.driver)); } else { try { const entries = await this.driver.read(this.mount); if (entries.files.length > 0 || entries.dirs.length > 0) { resolve(new FolderHandle(this.mount, this.driver)); } } catch (e) { reject(new DOMException(...GONE)); } } }); } /** * GetFileHandle returns a file handle */ async getFileHandle(name, opts = {}) { return new Promise(async (resolve, reject) => { try { if (opts.create) { resolve(new FileHandle(this.mount, this.driver, name)); } else { resolve(new FileHandle(this.mount, this.driver, name)); } } catch (e) { reject(new DOMException(...GONE)); } }); } /** * Removes a file */ async removeEntry(name, opts = {}) { return new Promise(async (resolve, reject) => { try { await this.driver.delete(`${this.mount.path}${name}`, this.mount); } catch (e) { reject(new DOMException(...GONE)); } }); } }