diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..7a167ca --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,34 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Jest All", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": ["--runInBand"], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest/bin/jest", + } + }, + { + "type": "node", + "request": "launch", + "name": "Jest Current File", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": ["${relativeFile}"], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest/bin/jest", + } + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index da06cff..8df572f 100644 --- a/README.md +++ b/README.md @@ -73,28 +73,27 @@ Installation of the Vuex Electron easy as 1-2-3. In renderer process to call actions you need to use `dispatch` or `mapActions`. Don't use `commit` because actions fired via `commit` will not be shared between processes. +### Breaking changes + +**[Deprecated]** The whitelist and blacklist features do **not** work, and have been replaced by the ignoredPaths, ignoredCommits and invertIgnored options. + ### Options Available options for `createPersistedState()` ```javascript createPersistedState({ - whitelist: ["whitelistedMutation", "anotherWhitelistedMutation"], - - // or - - whitelist: (mutation) => { - return true - }, - - // or - - blacklist: ["ignoredMutation", "anotherIgnoredMutation"], - - // or - - blacklist: (mutation) => { - return true + // Inverts the ignoredPaths and ignoredCommits settings + invertIgnored: true, + + // Ignores specific paths on the state object, when persisting. + ignoredPaths: ["a.path.on.state", "another.path"], + + // Specifies commits that will not trigger a persistance update. + ignoredCommits: ["increment"], + // or a variation using a function + ignoredCommits: (mutation) => { + return true // Return true for mutations that should not trigger an update } }) ``` diff --git a/dist/persisted-state.js b/dist/persisted-state.js index af4dc12..c09c68c 100644 --- a/dist/persisted-state.js +++ b/dist/persisted-state.js @@ -1 +1 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _deepmerge=_interopRequireDefault(require("deepmerge")),_electronStore=_interopRequireDefault(require("electron-store"));function _interopRequireDefault(a){return a&&a.__esModule?a:{default:a}}function _classCallCheck(a,b){if(!(a instanceof b))throw new TypeError("Cannot call a class as a function")}function _defineProperties(a,b){for(var c,d=0;d { + return !filter(mutation) + } + } return filter - } else { - throw new Error(`[Vuex Electron] Filter "${name}" should be Array or Function. Please, read the docs.`) } + throw new Error(`[Vuex Electron] Filter "${name}" should be Array or Function. Please, read the docs.`) } filterInArray(list) { return (mutation) => { + if (this.options.invertIgnored) { + return !list.includes(mutation.type) + } return list.includes(mutation.type) } } + // Removes ignored paths from the store object before persisting it + removeIgnoredPaths(state) { + try { + if (this.options.invertIgnored) { + var newState = {} + for (let i = 0; i < this.options.ignoredPaths.length; i++) { + const path = this.options.ignoredPaths[i] + this.setToValue(newState, this.deepFind(state, path), path) + } + return newState + } + + // Creates a copy of the store object + var stateCopy = JSON.parse(JSON.stringify(state)) + for (let i = 0; i < this.options.ignoredPaths.length; i++) { + const path = this.options.ignoredPaths[i] + this.deleteValue(stateCopy, path) + } + return stateCopy + } catch (error) { + throw new Error( + "[Vuex Electron] An error occurred while removing ignored paths from state. Please use a string array of property paths." + ) + } + } + + // Deletes, based on a given property path + deleteValue(obj, path) { + var i + path = path.split(".") + for (i = 0; i < path.length - 1; i++) { + obj = obj[path[i]] + } + + delete obj[path[i]] + } + + // Curtesy of qiao on Stack Overflow. + deepFind(obj, path) { + var paths = path.split("."), + current = obj, + i + + for (i = 0; i < paths.length; ++i) { + if (current[paths[i]] == undefined) { + return undefined + } else { + current = current[paths[i]] + } + } + return current + } + + setToValue(obj, value, path) { + var i + path = path.split(".") + for (i = 0; i < path.length - 1; i++) { + obj = obj[path[i]] + } + + obj[path[i]] = value + } + checkStorage() { try { this.options.storage.set(STORAGE_TEST_KEY, STORAGE_TEST_KEY) @@ -93,6 +168,16 @@ class PersistedState { if (this.blacklist && this.blacklist(mutation)) return if (this.whitelist && !this.whitelist(mutation)) return + // Returns if the current commit should not cause persistance. + if (this.ignoredCommits && this.ignoredCommits(mutation)) return + + // Filters the state before persisting, if ignoredPaths is set. + if (this.options.ignoredPaths) { + this.persistedStoreCopy = this.removeIgnoredPaths(state) + this.setState(this.persistedStoreCopy) + return + } + this.setState(state) }) } diff --git a/tests/helpers.js b/tests/helpers.js index 0549915..f6350e5 100644 --- a/tests/helpers.js +++ b/tests/helpers.js @@ -23,7 +23,8 @@ function createStore(options = {}) { return new Vuex.Store({ state: { - count: 0 + count: 0, + count2: 0 }, actions: { increment({ commit }) { @@ -32,6 +33,14 @@ function createStore(options = {}) { decrement({ commit }) { commit("decrement") + }, + + increment2({ commit }) { + commit("increment2") + }, + + decrement2({ commit }) { + commit("decrement2") } }, mutations: { @@ -41,6 +50,14 @@ function createStore(options = {}) { decrement(state) { state.count-- + }, + + increment2(state) { + state.count2++ + }, + + decrement2(state) { + state.count2-- } }, plugins diff --git a/tests/persisted-state.test.js b/tests/persisted-state.test.js index 3aa467f..0c0c23c 100644 --- a/tests/persisted-state.test.js +++ b/tests/persisted-state.test.js @@ -149,4 +149,134 @@ describe("createPersistedState", () => { expect(store.state.count).toEqual(0) expect(storage.get("state").count).toEqual(0) }) + + it("filters ignoredCommits (wrong type)", () => { + const storage = createStorage() + + expect(() => { + createStore({ + persistedState: { + ignoredCommits: {}, + storage + } + }) + }).toThrow() + }) + + it("filters ignoredCommits (array)", () => { + const storage = createStorage() + + const store = createStore({ + persistedState: { + ignoredCommits: ["increment"], + storage + } + }) + + store.dispatch("increment") + expect(store.state.count).toEqual(1) + expect(storage.get("state")).toBeUndefined() + + store.dispatch("decrement") + expect(store.state.count).toEqual(0) + expect(storage.get("state").count).toEqual(0) + }) + + it("filters ignoredCommits (function)", () => { + const storage = createStorage() + + const store = createStore({ + persistedState: { + ignoredCommits: (mutation) => ["increment"].includes(mutation.type), + storage + } + }) + + store.dispatch("increment") + expect(store.state.count).toEqual(1) + expect(storage.get("state")).toBeUndefined() + + store.dispatch("decrement") + expect(store.state.count).toEqual(0) + expect(storage.get("state").count).toEqual(0) + }) + + it("filters using ignoredPaths", () => { + const storage = createStorage() + + const store = createStore({ + persistedState: { + ignoredPaths: ["count"], + storage + } + }) + + store.dispatch("increment") // Modifications will NOT be allowed to be persisted. + expect(store.state.count).toEqual(1) + expect(storage.get("state").count).toBeUndefined() + + store.dispatch("decrement") // Modifications will NOT be allowed to be persisted. + expect(store.state.count).toEqual(0) + expect(storage.get("state").count).toBeUndefined() + }) + + it("filters using ignoredPaths and ignoredCommits", () => { + const storage = createStorage() + + const store = createStore({ + persistedState: { + ignoredPaths: ["count"], + ignoredCommits: (mutation) => ["increment2"].includes(mutation.type), + storage + } + }) + + store.dispatch("increment") // Modifications will NOT be allowed to be persisted, but WILL trigger a persistance. + expect(store.state.count).toEqual(1) + expect(storage.get("state").count).toBeUndefined() + + store.dispatch("decrement") // Modifications will NOT be allowed to be persisted, but WILL trigger a persistance. + expect(store.state.count).toEqual(0) + expect(storage.get("state").count).toBeUndefined() + + store.dispatch("increment2") // Modifications WILL be allowed to be persisted, but wont trigger a persistance. + expect(store.state.count2).toEqual(1) + expect(storage.get("state").count2).toEqual(0) + + store.dispatch("decrement2") // Modifications WILL be allowed to be persisted, AND WILL trigger a persistance. + expect(store.state.count2).toEqual(0) + expect(storage.get("state").count2).toEqual(0) + }) + + it("filters using ignoredPaths, ignoredCommits and invertIgnored", () => { + const storage = createStorage() + + const store = createStore({ + persistedState: { + ignoredPaths: ["count"], + ignoredCommits: (mutation) => ["increment2"].includes(mutation.type), + invertIgnored: true, + storage + } + }) + + store.dispatch("increment") // Modifications will be allowed to be persisted, but wont trigger a persistance. + expect(store.state.count).toEqual(1) + expect(storage.get("state")).toBeUndefined() + + store.dispatch("decrement") // Modifications will be allowed to be persisted, but wont trigger a persistance. + expect(store.state.count).toEqual(0) + expect(storage.get("state")).toBeUndefined() + + store.dispatch("increment2") // Modifications will NOT be allowed to be persisted, but WILL trigger a persistance. + expect(store.state.count2).toEqual(1) + expect(storage.get("state").count2).toBeUndefined() + expect(storage.get("state").count).toEqual(0) + + store.dispatch("decrement2") // Modifications will NOT be allowed to be persisted, AND will NOT trigger a persistance. + expect(store.state.count2).toEqual(0) + expect(storage.get("state").count2).toBeUndefined() + expect(store.state.count).toEqual(0) + expect(storage.get("state").count).toEqual(0) + }) })