UNPKG

ngx-webstorage-service

Version:
443 lines (433 loc) 19.5 kB
import * as i0 from '@angular/core'; import { InjectionToken, NgModule } from '@angular/core'; /** * A storage service implementation that is used as a proxy for another storage service. This is used to create storage services with a * different default transcoder. */ class ProxyStorageService { /** * Creates a new `ProxyStorageService` instance that uses the specified transcoder by default for read and write operations. Actual * read and writes are delegated to given storage service. * * @param defaultTranscoder Transcoder which is to be used by default for storage read and write operations. * @param subject Storage service which should handle to actual storage of data. */ constructor(defaultTranscoder, subject) { this.defaultTranscoder = defaultTranscoder; this.subject = subject; } /** * Checks whether an entry with the specified key exists in the storage. * * @param key Identifier of the entry for which its presence in the storage is to be checked. * @returns `true` if an entry with the specified key exists in the storage, `false` if not. */ has(key) { return this.subject.has(key); } /* * Retrieves the value stored for the entry that is associated with the specified key. The given decoder is used to convert the stored * value to the desired type. If no entry for the specified key exists or if the decoder is unable to decode the stored value, then * `undefined` will be returned. * * @param key Identifier of the entry whose value is to be retrieved. * @param decoder Decoder to use for converting the stored value to the desired return type. * @returns Value of the entry that is identified by the specified key. In case the entry does not exist or if it cannot be * loaded (due to a decoding issue), then `undefined` will be returned by this function. */ get(key, decoder) { return this.subject.get(key, decoder ?? this.defaultTranscoder); } /** * Creates or updates the entry identified by the specified key with the given value. The specified encoder is used to convert the given * value into a format that can be stored by the storage service's underlying storage. * * Storing a value into the storage service will ensure that an equivalent of the value can be read back, i.e. the data and structure of * the value will be the same. It, however, does not necessarily return the same reference. * * @param key Identifier of the entry which is to be created or updated. * @param value Value which is to be stored. * @param encoder Encoder used to convert the given value into a format that can be used for storage. */ set(key, value, encoder) { this.subject.set(key, value, encoder ?? this.defaultTranscoder); } /** * Removes the entry that is identified by the specified key. Attempting to remove an entry for an unknown key will have no effect. * Attempting to retrieve an entry via the `get` method after it has been removed will result in `undefined`. * * @param key Identifier of the entry which is to be removed. */ remove(key) { this.subject.remove(key); } /** * Clears the storage by removing all entries. Subsequent `get(x)` calls for a key *x* will return `undefined`, until a new value is set * for key *x*. */ clear() { this.subject.clear(); } /** * Creates a new storage service that uses the specified transcoder by default for read and write operations. The new storage service * uses the storage service on which this function is invoked as underlying storage. Both storage services will thus be able to access * the same data. * * The default transcoder will not be changed for the storage service on which this function is invoked. * * @param transcoder Transcoder that should be used by default for read and write operations by the new storage service. * @returns A new storage service that uses the specified transcoder by default. */ withDefaultTranscoder(transcoder) { return new ProxyStorageService(transcoder, this.subject); } } /** * Base implementation for storage services. */ class BaseStorageService { /** * Creates a new `BaseStorageService` that uses the specified transcoder by default for read and write operations. * * @param defaultTranscoder Transcoder which is to be used by default for storage read and write operations. */ constructor(defaultTranscoder) { this.defaultTranscoder = defaultTranscoder; } /** * Retrieves the value stored for the entry that is associated with the specified key. The given decoder is used to convert the stored * value to the desired type. If no entry for the specified key exists or if the decoder is unable to decode the stored value, then * `undefined` will be returned. * * @param key Identifier of the entry whose value is to be retrieved. * @param decoder Decoder to use for converting the stored value to the desired return type. * @returns Value of the entry that is identified by the specified key. In case the entry does not exist or if it cannot be * loaded (due to a decoding issue), then `undefined` will be returned by this function. */ get(key, decoder) { const value = this.getItem(key); return value !== undefined ? (decoder ?? this.defaultTranscoder).decode(value) : undefined; } /** * Creates or updates the entry identified by the specified key with the given value. The specified encoder is used to convert the given * value into a format that can be stored by the storage service's underlying storage. * * Storing a value into the storage service will ensure that an equivalent of the value can be read back, i.e. the data and structure of * the value will be the same. It, however, does not necessarily return the same reference. * * @param key Identifier of the entry which is to be created or updated. * @param value Value which is to be stored. * @param encoder Encoder used to convert the given value into a format that can be used for storage. */ set(key, value, encoder) { this.setItem(key, (encoder ?? this.defaultTranscoder).encode(value)); } /** * Creates a new storage service that uses the specified transcoder by default for read and write operations. The new storage service * uses the storage service on which this function is invoked as underlying storage. Both storage services will thus be able to access * the same data. * * The default transcoder will not be changed for the storage service on which this function is invoked. * * @param transcoder Transcoder that should be used by default for read and write operations by the new storage service. * @returns A new storage service that uses the specified transcoder by default. */ withDefaultTranscoder(transcoder) { return new ProxyStorageService(transcoder, this); } } /** Transcoder that encodes values as JSON strings. */ class JsonStorageTranscoder { encode(value) { return JSON.stringify(value); } decode(value) { try { return JSON.parse(value); } catch (error) { return undefined; } } } /** Transcoder that encodes/decodes strings **as is**, i.e. values are not modified in any way. */ class StringStorageTranscoder { encode(value) { return value; } decode(value) { return value; } } /** Transcoder that encodes/decodes `boolean` values. */ class BooleanStorageTranscoder { encode(value) { return value.toString(); } decode(value) { if (value === 'true') { return true; } if (value === 'false') { return false; } return undefined; } } /** Transcoder that encodes/decodes `number` values. */ class NumberStorageTranscoder { encode(value) { return value.toString(); } decode(value) { const parsedNumber = Number(value); return Number.isFinite(parsedNumber) ? parsedNumber : undefined; } } /** Transcoder that encodes/decodes `Date` values to ISO strings. */ class DateIsoStorageTranscoder { encode(value) { return value.toISOString(); } decode(value) { const timestamp = Date.parse(value); return isNaN(timestamp) ? undefined : new Date(timestamp); } } /** Transcoder that encodes/decodes `Date` values to epoch timestamps. */ class DateEpochStorageTranscoder { encode(value) { return value.valueOf().toString(); } decode(value) { const timestamp = parseInt(value, 10); return isNaN(timestamp) ? undefined : new Date(timestamp); } } /** A set of storage transcoders. */ const StorageTranscoders = { /** Transcoder that encodes values as JSON strings. */ JSON: new JsonStorageTranscoder(), /** Transcoder that encodes/decodes strings **as is**, i.e. values are not modified in any way. */ STRING: new StringStorageTranscoder(), /** Transcoder that encodes/decodes `boolean` values. */ BOOLEAN: new BooleanStorageTranscoder(), /** Transcoder that encodes/decodes `number` values. */ NUMBER: new NumberStorageTranscoder(), /** Transcoder that encodes/decodes `Date` values into ISO strings. */ DATE_ISO_STRING: new DateIsoStorageTranscoder(), /** Transcoder that encodes/decodes `Date` values into epoch timestamps. */ DATE_EPOCH_TIME: new DateEpochStorageTranscoder(), }; /** * A volatile `StorageService` implementation. This service guarantees that data stored will remain available as long as the application * instance is active. After the application is terminated all data will be lost. */ class InMemoryStorageService extends BaseStorageService { /** * Creates a new `InMemoryStorageService` instance. */ constructor() { super(StorageTranscoders.JSON); /** A map that serves as the underlying backing storage for this service. */ this.storage = new Map(); } /** * Checks whether an entry with the specified key exists in the storage. * * @param key Identifier of the entry for which its presence in the storage is to be checked. * @returns `true` if an entry with the specified key exists in the storage, `false` if not. */ has(key) { return this.storage.has(key); } /** * Removes the entry that is identified by the specified key. Attempting to remove an entry for an unknown key will have no effect. * Attempting to retrieve an entry via the `get` method after it has been removed will result in `undefined`. * * @param key Identifier of the entry which is to be removed. */ remove(key) { this.storage.delete(key); } /** * Clears the storage by removing all entries. Subsequent `get(x)` calls for a key *x* will return `undefined`, until a new value is set * for key *x*. */ clear() { this.storage.clear(); } /** * Performs the actual retrieval of a value from storage. * * @param key Identifier of the entry whose value is to be retrieved. * @returns The value that is stored for the specified entry or `undefined` if no entry exists for the specified key. */ getItem(key) { if (!this.storage.has(key)) { return undefined; } return this.storage.get(key); } /** * Stores the provided value using specified key in the storage. * * @param key Identifier of the entry for which the value is to be stored. * @param value The value that is to be stored. */ setItem(key, value) { this.storage.set(key, value); } } /** * An implementation of `StorageService` interface that uses an underlying (web) `Storage` object, such as `localStorage` and * `sessionStorage`, as backing data store. This class basically wraps the `Storage` object so it can be accessed through the * `StorageService` interface. */ class WebStorageService extends BaseStorageService { /** * Creates a new `WebStorageService` instance that uses the specified (web) storage object as underlying backing storage. * * @param storage Storage object which is to be wrapped in a class that implements the `StorageService` interface. */ constructor(storage) { super(StorageTranscoders.JSON); this.storage = storage; } /** * Checks whether an entry with the specified key exists in the storage. * * @param key Identifier of the entry for which its presence in the storage is to be checked. * @returns `true` if an entry with the specified key exists in the storage, `false` if not. */ has(key) { return this.storage.getItem(key) !== null; } /** * Removes the entry that is identified by the specified key. Attempting to remove an entry for an unknown key will have no effect. * Attempting to retrieve an entry via the `get` method after it has been removed will result in `undefined`. * * @param key Identifier of the entry which is to be removed. */ remove(key) { this.storage.removeItem(key); } /** * Clears the storage by removing all entries. Subsequent `get(x)` calls for a key *x* will return `undefined`, until a new value is set * for key *x*. */ clear() { this.storage.clear(); } /** * Performs the actual retrieval of a value from storage. * * @param key Identifier of the entry whose value is to be retrieved. * @returns The value that is stored for the specified entry or `undefined` if no entry exists for the specified key. */ getItem(key) { const value = this.storage.getItem(key); return value !== null ? value : undefined; } /** * Stores the provided value using specified key in the storage. * * @param key Identifier of the entry for which the value is to be stored. * @param value The value that is to be stored. */ setItem(key, value) { return this.storage.setItem(key, value); } } /** * Checks whether the specified (web) storage is available and functional. This might not be the case for older browsers. However even * certain browsers that do support the web storage API can, under some circumstances, have non functional storage objects. For example, * Safari is known to have `localStorage` and `sessionStorage` throw exceptions in private mode. * * @param storage Storage object which is to be tested for availability. * @returns `true` if the specified storage can be used, `false` if not. */ function isStorageAvailable(storage) { // Check if storage is available. if (!storage) { return false; } // Check if the storage can actually be accessed. try { const now = Date.now(); const testItemKey = `storage-test-entry-${now}`; const testItemValue = `storage-test-value-${now}`; storage.setItem(testItemKey, testItemValue); const retrievedItemValue = storage.getItem(testItemKey); storage.removeItem(testItemKey); return retrievedItemValue === testItemValue; } catch (error) { return false; } } /** * Checks whether session storage is available and functional. This might not be the case for older browsers. However even certain browsers * that do support the web storage API can, under some circumstances, have non functional storage objects. For example, Safari is known to * have `sessionStorage` throw exceptions in private mode. * * @returns `true` if session storage can be used, `false` if not. */ function isSessionStorageAvailable() { try { if (typeof sessionStorage !== 'undefined') { return isStorageAvailable(sessionStorage); } } catch { } return false; } /** * Checks whether local storage is available and functional. This might not be the case for older browsers. However even certain browsers * that do support the web storage API can, under some circumstances, have non functional storage objects. For example, Safari is known to * have `localStorage` throw exceptions in private mode. * * @returns `true` if local storage can be used, `false` if not. */ function isLocalStorageAvailable() { try { if (typeof localStorage !== 'undefined') { return isStorageAvailable(localStorage); } } catch { } return false; } function sessionStorageFactory() { if (isSessionStorageAvailable()) { return new WebStorageService(sessionStorage); } return new InMemoryStorageService(); } /** Injection token for the session storage service. */ const SESSION_STORAGE = new InjectionToken('SESSION_STORAGE', { providedIn: 'root', factory: sessionStorageFactory }); function localStorageFactory() { if (isLocalStorageAvailable()) { return new WebStorageService(localStorage); } return new InMemoryStorageService(); } /** Injection token for the local storage service. */ const LOCAL_STORAGE = new InjectionToken('LOCAL_STORAGE', { providedIn: 'root', factory: localStorageFactory }); /** * @deprecated You no longer need to import the `StorageServiceModule`, since the `SESSION_STORAGE` and `LOCAL_STORAGE` injection tokens are * now 'self providing' in the root injector. */ class StorageServiceModule { } StorageServiceModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: StorageServiceModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); StorageServiceModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: StorageServiceModule }); StorageServiceModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: StorageServiceModule }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: StorageServiceModule, decorators: [{ type: NgModule }] }); /** * Generated bundle index. Do not edit. */ export { BaseStorageService, BooleanStorageTranscoder, DateEpochStorageTranscoder, DateIsoStorageTranscoder, InMemoryStorageService, JsonStorageTranscoder, LOCAL_STORAGE, NumberStorageTranscoder, ProxyStorageService, SESSION_STORAGE, StorageServiceModule, StorageTranscoders, StringStorageTranscoder, WebStorageService, isLocalStorageAvailable, isSessionStorageAvailable, isStorageAvailable, localStorageFactory, sessionStorageFactory }; //# sourceMappingURL=ngx-webstorage-service.mjs.map