{"version":3,"file":"index.js","sources":["../../src/MockStorage.ts","../../src/SimplePromiseQueue.ts","../../src/utils.ts","../../src/index.ts"],"sourcesContent":["/**\n * Created by championswimmer on 22/07/17.\n */\nlet MockStorage: typeof Storage | undefined\n\n// @ts-ignore\nif (process.env.MODULE_FORMAT !== 'umd') {\n MockStorage = class implements Storage {\n [index: number]: string;\n [key: string]: any;\n\n public get length(): number {\n return Object.keys(this).length\n }\n\n public key(index: number): string | any {\n return Object.keys(this)[index]\n }\n\n public setItem(key: string, data: any): void {\n this[key] = data.toString()\n }\n public getItem(key: string): string {\n return this[key]\n }\n public removeItem(key: string): void {\n delete this[key]\n }\n public clear(): void {\n for (let key of Object.keys(this)) {\n delete this[key]\n }\n }\n }\n}\n\nexport { MockStorage }\n","// tslint:disable: variable-name\nexport default class SimplePromiseQueue {\n private readonly _queue: Array> = []\n private _flushing = false\n\n public enqueue(promise: Promise) {\n this._queue.push(promise)\n if (!this._flushing) { return this.flushQueue() }\n return Promise.resolve()\n }\n\n private flushQueue() {\n this._flushing = true\n\n const chain = (): Promise | void => {\n const nextTask = this._queue.shift()\n if (nextTask) {\n return nextTask.then(chain)\n } else {\n this._flushing = false\n }\n }\n return Promise.resolve(chain())\n }\n}\n","import deepmerge from 'deepmerge'\n\nexport type MergeOptionType = 'replaceArrays' | 'concatArrays'\n\nconst options: {[k in MergeOptionType]: deepmerge.Options} = {\n replaceArrays: {\n arrayMerge: (destinationArray, sourceArray, options) => sourceArray\n },\n concatArrays: {\n arrayMerge: (target, source, options) => target.concat(...source)\n }\n}\n\nconst defaultMergeOptions: deepmerge.Options = {\n // replacing arrays\n \n}\n\nexport function merge(into: Partial, from: Partial, mergeOption: MergeOptionType): I & F & {} {\n return deepmerge(into, from, options[mergeOption])\n}\n","/**\n * Created by championswimmer on 18/07/17.\n */\nimport { Mutation, MutationPayload, Payload, Plugin, Store } from 'vuex'\nimport { AsyncStorage } from './AsyncStorage'\nimport { MockStorage } from './MockStorage'\nimport { PersistOptions } from './PersistOptions'\nimport SimplePromiseQueue from './SimplePromiseQueue'\nimport { merge, MergeOptionType } from './utils'\n\nlet FlattedJSON = JSON\n\n/**\n * A class that implements the vuex persistence.\n * @type S type of the 'state' inside the store (default: any)\n */\nexport class VuexPersistence implements PersistOptions {\n public asyncStorage: boolean\n public storage: Storage | AsyncStorage | undefined\n public restoreState: (key: string, storage?: AsyncStorage | Storage) => Promise | S\n public saveState: (key: string, state: {}, storage?: AsyncStorage | Storage) => Promise | void\n public reducer: (state: S) => Partial\n public key: string\n public filter: (mutation: Payload) => boolean\n public modules: string[]\n public strictMode: boolean\n public supportCircular: boolean\n public mergeOption: MergeOptionType\n\n /**\n * The plugin function that can be used inside a vuex store.\n */\n public plugin: Plugin\n /**\n * A mutation that can be used to restore state\n * Helpful if we are running in strict mode\n */\n public RESTORE_MUTATION: Mutation\n public subscribed: boolean\n\n // tslint:disable-next-line:variable-name\n private _mutex = new SimplePromiseQueue()\n\n /**\n * Create a {@link VuexPersistence} object.\n * Use the plugin function of this class as a\n * Vuex plugin.\n * @param {PersistOptions} options\n */\n public constructor(options?: PersistOptions) {\n if (typeof options === 'undefined') options = {} as PersistOptions\n this.key = ((options.key != null) ? options.key : 'vuex')\n\n this.subscribed = false\n this.supportCircular = options.supportCircular || false\n if (this.supportCircular) {\n FlattedJSON = require('flatted')\n }\n this.mergeOption = options.mergeOption || 'replaceArrays'\n\n let localStorageLitmus = true\n\n try {\n window.localStorage.getItem('')\n } catch (err) {\n localStorageLitmus = false\n }\n\n /**\n * 1. First, prefer storage sent in optinos\n * 2. Otherwise, use window.localStorage if available\n * 3. Finally, try to use MockStorage\n * 4. None of above? Well we gotta fail.\n */\n if (options.storage) { this.storage = options.storage }\n else if (localStorageLitmus) { this.storage = window.localStorage }\n else if (MockStorage) { this.storage = new MockStorage() }\n else { throw new Error(\"Neither 'window' is defined, nor 'MockStorage' is available\") }\n\n /**\n * How this works is -\n * 1. If there is options.reducer function, we use that, if not;\n * 2. We check options.modules;\n * 1. If there is no options.modules array, we use entire state in reducer\n * 2. Otherwise, we create a reducer that merges all those state modules that are\n * defined in the options.modules[] array\n * @type {((state: S) => {}) | ((state: S) => S) | ((state: any) => {})}\n */\n this.reducer = (\n (options.reducer != null)\n ? options.reducer\n : (\n (options.modules == null)\n ? ((state: S) => state)\n : (\n (state: any) =>\n (options!.modules as string[]).reduce((a, i) =>\n merge(a, { [i]: state[i] }, this.mergeOption), {/* start empty accumulator*/ })\n )\n )\n )\n\n this.filter = options.filter || ((mutation) => true)\n\n this.strictMode = options.strictMode || false\n\n this.RESTORE_MUTATION = function RESTORE_MUTATION(state: S, savedState: any) {\n const mergedState = merge(state, savedState || {}, this.mergeOption)\n for (const propertyName of Object.keys(mergedState as {})) {\n (this as any)._vm.$set(state, propertyName, (mergedState as any)[propertyName])\n }\n }\n\n this.asyncStorage = options.asyncStorage || false\n\n if (this.asyncStorage) {\n\n /**\n * Async {@link #VuexPersistence.restoreState} implementation\n * @type {((key: string, storage?: Storage) =>\n * (Promise | S)) | ((key: string, storage: AsyncStorage) => Promise)}\n */\n this.restoreState = (\n (options.restoreState != null)\n ? options.restoreState\n : ((key: string, storage: AsyncStorage) =>\n (storage).getItem(key)\n .then((value) =>\n typeof value === 'string' // If string, parse, or else, just return\n ? (\n this.supportCircular\n ? FlattedJSON.parse(value || '{}')\n : JSON.parse(value || '{}')\n )\n : (value || {})\n )\n )\n )\n\n /**\n * Async {@link #VuexPersistence.saveState} implementation\n * @type {((key: string, state: {}, storage?: Storage) =>\n * (Promise | void)) | ((key: string, state: {}, storage?: Storage) => Promise)}\n */\n this.saveState = (\n (options.saveState != null)\n ? options.saveState\n : ((key: string, state: {}, storage: AsyncStorage) =>\n (storage).setItem(\n key, // Second argument is state _object_ if asyc storage, stringified otherwise\n // do not stringify the state if the storage type is async\n (this.asyncStorage\n ? merge({}, state || {}, this.mergeOption)\n : (\n this.supportCircular\n ? FlattedJSON.stringify(state) as any\n : JSON.stringify(state) as any\n )\n )\n )\n )\n )\n\n /**\n * Async version of plugin\n * @param {Store} store\n */\n this.plugin = (store: Store) => {\n /**\n * For async stores, we're capturing the Promise returned\n * by the `restoreState()` function in a `restored` property\n * on the store itself. This would allow app developers to\n * determine when and if the store's state has indeed been\n * refreshed. This approach was suggested by GitHub user @hotdogee.\n * See https://github.com/championswimmer/vuex-persist/pull/118#issuecomment-500914963\n * @since 2.1.0\n */\n (store as any).restored = ((this.restoreState(this.key, this.storage)) as Promise).then((savedState) => {\n /**\n * If in strict mode, do only via mutation\n */\n if (this.strictMode) {\n store.commit('RESTORE_MUTATION', savedState)\n } else {\n store.replaceState(merge(store.state, savedState || {}, this.mergeOption) as S)\n }\n this.subscriber(store)((mutation: MutationPayload, state: S) => {\n if (this.filter(mutation)) {\n this._mutex.enqueue(\n this.saveState(this.key, this.reducer(state), this.storage) as Promise\n )\n }\n })\n this.subscribed = true\n })\n }\n } else {\n\n /**\n * Sync {@link #VuexPersistence.restoreState} implementation\n * @type {((key: string, storage?: Storage) =>\n * (Promise | S)) | ((key: string, storage: Storage) => (any | string | {}))}\n */\n this.restoreState = (\n (options.restoreState != null)\n ? options.restoreState\n : ((key: string, storage: Storage) => {\n const value = (storage).getItem(key)\n if (typeof value === 'string') {// If string, parse, or else, just return\n return (\n this.supportCircular\n ? FlattedJSON.parse(value || '{}')\n : JSON.parse(value || '{}')\n )\n } else {\n return (value || {})\n }\n })\n )\n\n /**\n * Sync {@link #VuexPersistence.saveState} implementation\n * @type {((key: string, state: {}, storage?: Storage) =>\n * (Promise | void)) | ((key: string, state: {}, storage?: Storage) => Promise)}\n */\n this.saveState = (\n (options.saveState != null)\n ? options.saveState\n : ((key: string, state: {}, storage: Storage) =>\n (storage).setItem(\n key, // Second argument is state _object_ if localforage, stringified otherwise\n (\n this.supportCircular\n ? FlattedJSON.stringify(state) as any\n : JSON.stringify(state) as any\n )\n )\n )\n )\n\n /**\n * Sync version of plugin\n * @param {Store} store\n */\n this.plugin = (store: Store) => {\n const savedState = this.restoreState(this.key, this.storage) as S\n\n if (this.strictMode) {\n store.commit('RESTORE_MUTATION', savedState)\n } else {\n store.replaceState(merge(store.state, savedState || {}, this.mergeOption) as S)\n }\n\n this.subscriber(store)((mutation: MutationPayload, state: S) => {\n if (this.filter(mutation)) {\n this.saveState(this.key, this.reducer(state), this.storage)\n }\n })\n\n this.subscribed = true\n }\n }\n }\n\n /**\n * Creates a subscriber on the store. automatically is used\n * when this is used a vuex plugin. Not for manual usage.\n * @param store\n */\n private subscriber = (store: Store) =>\n (handler: (mutation: MutationPayload, state: S) => any) => store.subscribe(handler)\n}\n\nexport {\n MockStorage, AsyncStorage, PersistOptions\n}\n\nexport default VuexPersistence\n"],"names":["MockStorage"],"mappings":"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"}