UNPKG

browserfs

Version:

A filesystem in your browser!

103 lines (92 loc) 3.33 kB
import {BFSCallback, FileSystemOptions} from '../core/file_system'; import {SyncKeyValueStore, SimpleSyncStore, SyncKeyValueFileSystem, SimpleSyncRWTransaction, SyncKeyValueRWTransaction} from '../generic/key_value_filesystem'; import {ApiError, ErrorCode} from '../core/api_error'; import global from '../core/global'; /** * Some versions of FF and all versions of IE do not support the full range of * 16-bit numbers encoded as characters, as they enforce UTF-16 restrictions. * @url http://stackoverflow.com/questions/11170716/are-there-any-characters-that-are-not-allowed-in-localstorage/11173673#11173673 * @hidden */ let supportsBinaryString: boolean = false, binaryEncoding: string; try { global.localStorage.setItem("__test__", String.fromCharCode(0xD800)); supportsBinaryString = global.localStorage.getItem("__test__") === String.fromCharCode(0xD800); } catch (e) { // IE throws an exception. supportsBinaryString = false; } binaryEncoding = supportsBinaryString ? 'binary_string' : 'binary_string_ie'; if (!Buffer.isEncoding(binaryEncoding)) { // Fallback for non BrowserFS implementations of buffer that lack a // binary_string format. binaryEncoding = "base64"; } /** * A synchronous key-value store backed by localStorage. */ export class LocalStorageStore implements SyncKeyValueStore, SimpleSyncStore { public name(): string { return LocalStorageFileSystem.Name; } public clear(): void { global.localStorage.clear(); } public beginTransaction(type: string): SyncKeyValueRWTransaction { // No need to differentiate. return new SimpleSyncRWTransaction(this); } public get(key: string): Buffer | undefined { try { const data = global.localStorage.getItem(key); if (data !== null) { return Buffer.from(data, binaryEncoding); } } catch (e) { // Do nothing. } // Key doesn't exist, or a failure occurred. return undefined; } public put(key: string, data: Buffer, overwrite: boolean): boolean { try { if (!overwrite && global.localStorage.getItem(key) !== null) { // Don't want to overwrite the key! return false; } global.localStorage.setItem(key, data.toString(binaryEncoding)); return true; } catch (e) { throw new ApiError(ErrorCode.ENOSPC, "LocalStorage is full."); } } public del(key: string): void { try { global.localStorage.removeItem(key); } catch (e) { throw new ApiError(ErrorCode.EIO, "Unable to delete key " + key + ": " + e); } } } /** * A synchronous file system backed by localStorage. Connects our * LocalStorageStore to our SyncKeyValueFileSystem. */ export default class LocalStorageFileSystem extends SyncKeyValueFileSystem { public static readonly Name = "LocalStorage"; public static readonly Options: FileSystemOptions = {}; /** * Creates a LocalStorageFileSystem instance. */ public static Create(options: any, cb: BFSCallback<LocalStorageFileSystem>): void { cb(null, new LocalStorageFileSystem()); } public static isAvailable(): boolean { return typeof global.localStorage !== 'undefined'; } /** * Creates a new LocalStorage file system using the contents of `localStorage`. */ constructor() { super({ store: new LocalStorageStore() }); } }