From 07b313b1f0b3b0e8078ab047a9a77f9a39482dfc Mon Sep 17 00:00:00 2001 From: Mesqueeb Date: Tue, 21 Apr 2020 15:14:24 +0900 Subject: [PATCH 1/2] WIP fix PATCH_DOC --- dist/index.cjs.js | 63 ++++++++++++++++++++++----------------- dist/index.esm.js | 54 +++++++++++++++++++-------------- package-lock.json | 7 ++++- package.json | 13 ++++++-- src/module/mutations.ts | 44 ++++++++++++++++++--------- test/helpers/index.cjs.js | 63 ++++++++++++++++++++++----------------- 6 files changed, 149 insertions(+), 95 deletions(-) diff --git a/dist/index.cjs.js b/dist/index.cjs.js index 0c6c5978..ec8a3590 100644 --- a/dist/index.cjs.js +++ b/dist/index.cjs.js @@ -11,7 +11,9 @@ var vuexEasyAccess = require('vuex-easy-access'); var isWhat = require('is-what'); var copy = _interopDefault(require('copy-anything')); var mergeAnything = require('merge-anything'); -var flatten = _interopDefault(require('flatten-anything')); +var flatten = require('flatten-anything'); +var flatten__default = _interopDefault(flatten); +var pathToProp = _interopDefault(require('path-to-prop')); var compareAnything = require('compare-anything'); var findAndReplaceAnything = require('find-and-replace-anything'); var filter = _interopDefault(require('filter-anything')); @@ -402,31 +404,40 @@ function pluginMutations (userState) { } }, PATCH_DOC: function (state, patches) { - var _this = this; // Get the state prop ref - var ref = state._conf.statePropName - ? state[state._conf.statePropName] - : state; + var ref = state._conf.statePropName ? state[state._conf.statePropName] : state; if (state._conf.firestoreRefType.toLowerCase() === 'collection') { ref = ref[patches.id]; } if (!ref) return error('patch-no-ref'); - return Object.keys(patches).forEach(function (key) { - var newVal = patches[key]; - // Merge if exists - function helpers(originVal, newVal) { - if (isWhat.isArray(originVal) && isArrayHelper(newVal)) { - newVal = newVal.executeOn(originVal); - } - if (isWhat.isNumber(originVal) && isIncrementHelper(newVal)) { - newVal = newVal.executeOn(originVal); - } - return newVal; // always return newVal as fallback!! + function convertHelpers(originVal, newVal) { + if (isWhat.isArray(originVal) && isArrayHelper(newVal)) { + newVal = newVal.executeOn(originVal); } - newVal = mergeAnything.merge({ extensions: [helpers] }, ref[key], patches[key]); - _this._vm.$set(ref, key, newVal); - }); + if (isWhat.isNumber(originVal) && isIncrementHelper(newVal)) { + newVal = newVal.executeOn(originVal); + } + return newVal; // always return newVal as fallback!! + } + // const refPropsPicked = filter(ref, Object.keys(patches)) + // const patchesSanitised = merge({ extensions: [convertHelpers] }, refPropsPicked, patches) + var patchesFlat = flatten.flattenObject(patches); + for (var _i = 0, _a = Object.entries(patchesFlat); _i < _a.length; _i++) { + var _b = _a[_i], path = _b[0], value = _b[1]; + var targetVal = pathToProp(ref, path); + var newVal = convertHelpers(targetVal, value); + // do not update anything if the values are the same + // this is technically not required, because vue takes care of this as well: + if (targetVal === newVal) + return; + // update just the nested value + var pathParts = path.split('.'); + var prop = pathParts.pop(); + var pathParent = pathParts.join(''); + var targetForNestedProp = pathToProp(ref, pathParent); + this._vm.$set(targetForNestedProp, prop, newVal); + } }, DELETE_DOC: function (state, id) { if (state._conf.firestoreRefType.toLowerCase() !== 'collection') @@ -439,9 +450,7 @@ function pluginMutations (userState) { } }, DELETE_PROP: function (state, path) { - var searchTarget = state._conf.statePropName - ? state[state._conf.statePropName] - : state; + var searchTarget = state._conf.statePropName ? state[state._conf.statePropName] : state; var propArr = path.split('.'); var target = propArr.pop(); if (!propArr.length) { @@ -449,7 +458,7 @@ function pluginMutations (userState) { } var ref = vuexEasyAccess.getDeepRef(searchTarget, propArr.join('.')); return this._vm.$delete(ref, target); - } + }, }; } @@ -1290,9 +1299,9 @@ function pluginActions (Firebase) { var getters = _a.getters, commit = _a.commit; var defaultValues = getters.defaultValues; var searchTarget = getters.collectionMode ? getters.storeRef[doc.id] : getters.storeRef; - var compareInfo = compareAnything.compareObjectProps(flatten(doc), // presentIn 0 - flatten(defaultValues), // presentIn 1 - flatten(searchTarget) // presentIn 2 + var compareInfo = compareAnything.compareObjectProps(flatten__default(doc), // presentIn 0 + flatten__default(defaultValues), // presentIn 1 + flatten__default(searchTarget) // presentIn 2 ); Object.keys(compareInfo.presentIn).forEach(function (prop) { // don't worry about props not in fillables @@ -1902,7 +1911,7 @@ function pluginGetters (Firebase) { patchData.updated_by = state._sync.userId; // clean up item var cleanedPatchData = filter(patchData, getters.fillables, getters.guard); - var itemToUpdate = flatten(cleanedPatchData); + var itemToUpdate = flatten__default(cleanedPatchData); // add id (required to get ref later at apiHelpers.ts) // @ts-ignore itemToUpdate.id = id; diff --git a/dist/index.esm.js b/dist/index.esm.js index 81bd0220..03908daf 100644 --- a/dist/index.esm.js +++ b/dist/index.esm.js @@ -5,7 +5,8 @@ import { getDeepRef, getKeysFromPath } from 'vuex-easy-access'; import { isAnyObject, isPlainObject, isArray, isFunction, isNumber, isString, isDate } from 'is-what'; import copy from 'copy-anything'; import { merge } from 'merge-anything'; -import flatten from 'flatten-anything'; +import flatten, { flattenObject } from 'flatten-anything'; +import pathToProp from 'path-to-prop'; import { compareObjectProps } from 'compare-anything'; import { findAndReplace, findAndReplaceIf } from 'find-and-replace-anything'; import filter from 'filter-anything'; @@ -396,31 +397,40 @@ function pluginMutations (userState) { } }, PATCH_DOC: function (state, patches) { - var _this = this; // Get the state prop ref - var ref = state._conf.statePropName - ? state[state._conf.statePropName] - : state; + var ref = state._conf.statePropName ? state[state._conf.statePropName] : state; if (state._conf.firestoreRefType.toLowerCase() === 'collection') { ref = ref[patches.id]; } if (!ref) return error('patch-no-ref'); - return Object.keys(patches).forEach(function (key) { - var newVal = patches[key]; - // Merge if exists - function helpers(originVal, newVal) { - if (isArray(originVal) && isArrayHelper(newVal)) { - newVal = newVal.executeOn(originVal); - } - if (isNumber(originVal) && isIncrementHelper(newVal)) { - newVal = newVal.executeOn(originVal); - } - return newVal; // always return newVal as fallback!! + function convertHelpers(originVal, newVal) { + if (isArray(originVal) && isArrayHelper(newVal)) { + newVal = newVal.executeOn(originVal); } - newVal = merge({ extensions: [helpers] }, ref[key], patches[key]); - _this._vm.$set(ref, key, newVal); - }); + if (isNumber(originVal) && isIncrementHelper(newVal)) { + newVal = newVal.executeOn(originVal); + } + return newVal; // always return newVal as fallback!! + } + // const refPropsPicked = filter(ref, Object.keys(patches)) + // const patchesSanitised = merge({ extensions: [convertHelpers] }, refPropsPicked, patches) + var patchesFlat = flattenObject(patches); + for (var _i = 0, _a = Object.entries(patchesFlat); _i < _a.length; _i++) { + var _b = _a[_i], path = _b[0], value = _b[1]; + var targetVal = pathToProp(ref, path); + var newVal = convertHelpers(targetVal, value); + // do not update anything if the values are the same + // this is technically not required, because vue takes care of this as well: + if (targetVal === newVal) + return; + // update just the nested value + var pathParts = path.split('.'); + var prop = pathParts.pop(); + var pathParent = pathParts.join(''); + var targetForNestedProp = pathToProp(ref, pathParent); + this._vm.$set(targetForNestedProp, prop, newVal); + } }, DELETE_DOC: function (state, id) { if (state._conf.firestoreRefType.toLowerCase() !== 'collection') @@ -433,9 +443,7 @@ function pluginMutations (userState) { } }, DELETE_PROP: function (state, path) { - var searchTarget = state._conf.statePropName - ? state[state._conf.statePropName] - : state; + var searchTarget = state._conf.statePropName ? state[state._conf.statePropName] : state; var propArr = path.split('.'); var target = propArr.pop(); if (!propArr.length) { @@ -443,7 +451,7 @@ function pluginMutations (userState) { } var ref = getDeepRef(searchTarget, propArr.join('.')); return this._vm.$delete(ref, target); - } + }, }; } diff --git a/package-lock.json b/package-lock.json index ca905c4e..8fdbc6d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vuex-easy-firestore", - "version": "1.35.6", + "version": "1.35.7", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -11941,6 +11941,11 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "path-to-prop": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/path-to-prop/-/path-to-prop-0.0.3.tgz", + "integrity": "sha512-HVhVwpEm4VjQADpnHxv8NCinYlsGImMZ1Bt/vEh1UY2BhBXkMgAVpr/8QnDlX0eo77fIKz8fkz2TmXWTVfDeHg==" + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", diff --git a/package.json b/package.json index e2dccd1a..ec978cbf 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "flatten-anything": "^1.4.1", "is-what": "^3.8.0", "merge-anything": "^2.4.4", + "path-to-prop": "0.0.3", "vuex-easy-access": "^3.1.8" }, "devDependencies": { @@ -71,8 +72,14 @@ }, "ava": { "compileEnhancements": false, - "extensions": ["ts"], - "require": ["ts-node/register"], - "helpers": ["**/helpers/**/*"] + "extensions": [ + "ts" + ], + "require": [ + "ts-node/register" + ], + "helpers": [ + "**/helpers/**/*" + ] } } diff --git a/src/module/mutations.ts b/src/module/mutations.ts index 0eeb385b..0f0111ea 100644 --- a/src/module/mutations.ts +++ b/src/module/mutations.ts @@ -1,5 +1,7 @@ import { isArray, isFunction, isNumber } from 'is-what' import { getDeepRef } from 'vuex-easy-access' +import { flattenObject } from 'flatten-anything' +import pathToProp from 'path-to-prop' import logError from './errors' import copy from 'copy-anything' import { merge } from 'merge-anything' @@ -79,21 +81,35 @@ export default function (userState: object): AnyObject { ref = ref[patches.id] } if (!ref) return logError('patch-no-ref') - return Object.keys(patches).forEach(key => { - let newVal = patches[key] - // Merge if exists - function helpers (originVal, newVal) { - if (isArray(originVal) && isArrayHelper(newVal)) { - newVal = newVal.executeOn(originVal) - } - if (isNumber(originVal) && isIncrementHelper(newVal)) { - newVal = newVal.executeOn(originVal) - } - return newVal // always return newVal as fallback!! + + function convertHelpers (originVal, newVal) { + if (isArray(originVal) && isArrayHelper(newVal)) { + newVal = newVal.executeOn(originVal) } - newVal = merge({ extensions: [helpers] }, ref[key], patches[key]) - this._vm.$set(ref, key, newVal) - }) + if (isNumber(originVal) && isIncrementHelper(newVal)) { + newVal = newVal.executeOn(originVal) + } + return newVal // always return newVal as fallback!! + } + + // const refPropsPicked = filter(ref, Object.keys(patches)) + // const patchesSanitised = merge({ extensions: [convertHelpers] }, refPropsPicked, patches) + + const patchesFlat = flattenObject(patches) + + for (const [path, value] of Object.entries(patchesFlat)) { + const targetVal = pathToProp(ref, path) + const newVal = convertHelpers(targetVal, value) + // do not update anything if the values are the same + // this is technically not required, because vue takes care of this as well: + if (targetVal === newVal) return + // update just the nested value + const pathParts = path.split('.') + const prop = pathParts.pop() + const pathParent = pathParts.join('') + const targetForNestedProp = pathToProp(ref, pathParent) + this._vm.$set(targetForNestedProp, prop, newVal) + } }, DELETE_DOC (state, id) { if (state._conf.firestoreRefType.toLowerCase() !== 'collection') return diff --git a/test/helpers/index.cjs.js b/test/helpers/index.cjs.js index 91eecb1a..7eca1ddf 100644 --- a/test/helpers/index.cjs.js +++ b/test/helpers/index.cjs.js @@ -12,7 +12,9 @@ require('firebase/firestore'); var isWhat = require('is-what'); var copy = _interopDefault(require('copy-anything')); var mergeAnything = require('merge-anything'); -var flatten = _interopDefault(require('flatten-anything')); +var flatten = require('flatten-anything'); +var flatten__default = _interopDefault(flatten); +var pathToProp = _interopDefault(require('path-to-prop')); var compareAnything = require('compare-anything'); var findAndReplaceAnything = require('find-and-replace-anything'); var filter = _interopDefault(require('filter-anything')); @@ -921,31 +923,40 @@ function pluginMutations (userState) { } }, PATCH_DOC: function (state, patches) { - var _this = this; // Get the state prop ref - var ref = state._conf.statePropName - ? state[state._conf.statePropName] - : state; + var ref = state._conf.statePropName ? state[state._conf.statePropName] : state; if (state._conf.firestoreRefType.toLowerCase() === 'collection') { ref = ref[patches.id]; } if (!ref) return error('patch-no-ref'); - return Object.keys(patches).forEach(function (key) { - var newVal = patches[key]; - // Merge if exists - function helpers(originVal, newVal) { - if (isWhat.isArray(originVal) && isArrayHelper(newVal)) { - newVal = newVal.executeOn(originVal); - } - if (isWhat.isNumber(originVal) && isIncrementHelper(newVal)) { - newVal = newVal.executeOn(originVal); - } - return newVal; // always return newVal as fallback!! + function convertHelpers(originVal, newVal) { + if (isWhat.isArray(originVal) && isArrayHelper(newVal)) { + newVal = newVal.executeOn(originVal); } - newVal = mergeAnything.merge({ extensions: [helpers] }, ref[key], patches[key]); - _this._vm.$set(ref, key, newVal); - }); + if (isWhat.isNumber(originVal) && isIncrementHelper(newVal)) { + newVal = newVal.executeOn(originVal); + } + return newVal; // always return newVal as fallback!! + } + // const refPropsPicked = filter(ref, Object.keys(patches)) + // const patchesSanitised = merge({ extensions: [convertHelpers] }, refPropsPicked, patches) + var patchesFlat = flatten.flattenObject(patches); + for (var _i = 0, _a = Object.entries(patchesFlat); _i < _a.length; _i++) { + var _b = _a[_i], path = _b[0], value = _b[1]; + var targetVal = pathToProp(ref, path); + var newVal = convertHelpers(targetVal, value); + // do not update anything if the values are the same + // this is technically not required, because vue takes care of this as well: + if (targetVal === newVal) + return; + // update just the nested value + var pathParts = path.split('.'); + var prop = pathParts.pop(); + var pathParent = pathParts.join(''); + var targetForNestedProp = pathToProp(ref, pathParent); + this._vm.$set(targetForNestedProp, prop, newVal); + } }, DELETE_DOC: function (state, id) { if (state._conf.firestoreRefType.toLowerCase() !== 'collection') @@ -958,9 +969,7 @@ function pluginMutations (userState) { } }, DELETE_PROP: function (state, path) { - var searchTarget = state._conf.statePropName - ? state[state._conf.statePropName] - : state; + var searchTarget = state._conf.statePropName ? state[state._conf.statePropName] : state; var propArr = path.split('.'); var target = propArr.pop(); if (!propArr.length) { @@ -968,7 +977,7 @@ function pluginMutations (userState) { } var ref = createEasyAccess.getDeepRef(searchTarget, propArr.join('.')); return this._vm.$delete(ref, target); - } + }, }; } @@ -1809,9 +1818,9 @@ function pluginActions (Firebase) { var getters = _a.getters, commit = _a.commit; var defaultValues = getters.defaultValues; var searchTarget = getters.collectionMode ? getters.storeRef[doc.id] : getters.storeRef; - var compareInfo = compareAnything.compareObjectProps(flatten(doc), // presentIn 0 - flatten(defaultValues), // presentIn 1 - flatten(searchTarget) // presentIn 2 + var compareInfo = compareAnything.compareObjectProps(flatten__default(doc), // presentIn 0 + flatten__default(defaultValues), // presentIn 1 + flatten__default(searchTarget) // presentIn 2 ); Object.keys(compareInfo.presentIn).forEach(function (prop) { // don't worry about props not in fillables @@ -2421,7 +2430,7 @@ function pluginGetters (Firebase) { patchData.updated_by = state._sync.userId; // clean up item var cleanedPatchData = filter(patchData, getters.fillables, getters.guard); - var itemToUpdate = flatten(cleanedPatchData); + var itemToUpdate = flatten__default(cleanedPatchData); // add id (required to get ref later at apiHelpers.ts) // @ts-ignore itemToUpdate.id = id; From e9390ab856524e182d0e2d354864d985dcc08867 Mon Sep 17 00:00:00 2001 From: Mesqueeb Date: Thu, 23 Apr 2020 00:06:59 +0900 Subject: [PATCH 2/2] more fixes for PATCH_DOC --- dist/index.cjs.js | 36 +++++++++++++++++++------ dist/index.esm.js | 36 +++++++++++++++++++------ src/module/mutations.ts | 55 +++++++++++++++++++++++++-------------- test/helpers/index.cjs.js | 36 +++++++++++++++++++------ 4 files changed, 119 insertions(+), 44 deletions(-) diff --git a/dist/index.cjs.js b/dist/index.cjs.js index ec8a3590..2085174c 100644 --- a/dist/index.cjs.js +++ b/dist/index.cjs.js @@ -331,6 +331,28 @@ function isIncrementHelper(payload) { payload.isIncrementHelper === true); } +/** + * Creates the params needed to $set a target based on a nested.path + * + * @param {object} target + * @param {string} path + * @param {*} value + * @returns {[object, string, any]} + */ +function getSetParams(target, path, value) { + var _a; + var pathParts = path.split('.'); + var prop = pathParts.pop(); + var pathParent = pathParts.join('.'); + var targetForNestedProp = pathToProp(target, pathParent); + if (targetForNestedProp === undefined) { + // the target doesn't have an object ready at this level to set the value to + // so we need to step down a level and try again + return getSetParams(target, pathParent, (_a = {}, _a[prop] = value, _a)); + } + var valueToSet = value; + return [targetForNestedProp, prop, valueToSet]; +} /** * a function returning the mutations object * @@ -404,6 +426,7 @@ function pluginMutations (userState) { } }, PATCH_DOC: function (state, patches) { + var _a; // Get the state prop ref var ref = state._conf.statePropName ? state[state._conf.statePropName] : state; if (state._conf.firestoreRefType.toLowerCase() === 'collection') { @@ -423,20 +446,17 @@ function pluginMutations (userState) { // const refPropsPicked = filter(ref, Object.keys(patches)) // const patchesSanitised = merge({ extensions: [convertHelpers] }, refPropsPicked, patches) var patchesFlat = flatten.flattenObject(patches); - for (var _i = 0, _a = Object.entries(patchesFlat); _i < _a.length; _i++) { - var _b = _a[_i], path = _b[0], value = _b[1]; + for (var _i = 0, _b = Object.entries(patchesFlat); _i < _b.length; _i++) { + var _c = _b[_i], path = _c[0], value = _c[1]; var targetVal = pathToProp(ref, path); var newVal = convertHelpers(targetVal, value); // do not update anything if the values are the same // this is technically not required, because vue takes care of this as well: if (targetVal === newVal) - return; + continue; // update just the nested value - var pathParts = path.split('.'); - var prop = pathParts.pop(); - var pathParent = pathParts.join(''); - var targetForNestedProp = pathToProp(ref, pathParent); - this._vm.$set(targetForNestedProp, prop, newVal); + var setParams = getSetParams(ref, path, newVal); + (_a = this._vm).$set.apply(_a, setParams); } }, DELETE_DOC: function (state, id) { diff --git a/dist/index.esm.js b/dist/index.esm.js index 03908daf..b8fc92f4 100644 --- a/dist/index.esm.js +++ b/dist/index.esm.js @@ -324,6 +324,28 @@ function isIncrementHelper(payload) { payload.isIncrementHelper === true); } +/** + * Creates the params needed to $set a target based on a nested.path + * + * @param {object} target + * @param {string} path + * @param {*} value + * @returns {[object, string, any]} + */ +function getSetParams(target, path, value) { + var _a; + var pathParts = path.split('.'); + var prop = pathParts.pop(); + var pathParent = pathParts.join('.'); + var targetForNestedProp = pathToProp(target, pathParent); + if (targetForNestedProp === undefined) { + // the target doesn't have an object ready at this level to set the value to + // so we need to step down a level and try again + return getSetParams(target, pathParent, (_a = {}, _a[prop] = value, _a)); + } + var valueToSet = value; + return [targetForNestedProp, prop, valueToSet]; +} /** * a function returning the mutations object * @@ -397,6 +419,7 @@ function pluginMutations (userState) { } }, PATCH_DOC: function (state, patches) { + var _a; // Get the state prop ref var ref = state._conf.statePropName ? state[state._conf.statePropName] : state; if (state._conf.firestoreRefType.toLowerCase() === 'collection') { @@ -416,20 +439,17 @@ function pluginMutations (userState) { // const refPropsPicked = filter(ref, Object.keys(patches)) // const patchesSanitised = merge({ extensions: [convertHelpers] }, refPropsPicked, patches) var patchesFlat = flattenObject(patches); - for (var _i = 0, _a = Object.entries(patchesFlat); _i < _a.length; _i++) { - var _b = _a[_i], path = _b[0], value = _b[1]; + for (var _i = 0, _b = Object.entries(patchesFlat); _i < _b.length; _i++) { + var _c = _b[_i], path = _c[0], value = _c[1]; var targetVal = pathToProp(ref, path); var newVal = convertHelpers(targetVal, value); // do not update anything if the values are the same // this is technically not required, because vue takes care of this as well: if (targetVal === newVal) - return; + continue; // update just the nested value - var pathParts = path.split('.'); - var prop = pathParts.pop(); - var pathParent = pathParts.join(''); - var targetForNestedProp = pathToProp(ref, pathParent); - this._vm.$set(targetForNestedProp, prop, newVal); + var setParams = getSetParams(ref, path, newVal); + (_a = this._vm).$set.apply(_a, setParams); } }, DELETE_DOC: function (state, id) { diff --git a/src/module/mutations.ts b/src/module/mutations.ts index 0f0111ea..0b2f00b2 100644 --- a/src/module/mutations.ts +++ b/src/module/mutations.ts @@ -10,6 +10,38 @@ import { isArrayHelper } from '../utils/arrayHelpers' import { isIncrementHelper } from '../utils/incrementHelper' import getStateWithSync from './state' +function convertHelpers (originVal, newVal) { + if (isArray(originVal) && isArrayHelper(newVal)) { + newVal = newVal.executeOn(originVal) + } + if (isNumber(originVal) && isIncrementHelper(newVal)) { + newVal = newVal.executeOn(originVal) + } + return newVal // always return newVal as fallback!! +} + +/** + * Creates the params needed to $set a target based on a nested.path + * + * @param {object} target + * @param {string} path + * @param {*} value + * @returns {[object, string, any]} + */ +function getSetParams (target: object, path: string, value: any): [object, string, any] { + const pathParts = path.split('.') + const prop = pathParts.pop() + const pathParent = pathParts.join('.') + const targetForNestedProp = pathToProp(target, pathParent) + if (targetForNestedProp === undefined) { + // the target doesn't have an object ready at this level to set the value to + // so we need to step down a level and try again + return getSetParams(target, pathParent, { [prop]: value }) + } + const valueToSet = value + return [targetForNestedProp, prop, valueToSet] +} + /** * a function returning the mutations object * @@ -82,33 +114,16 @@ export default function (userState: object): AnyObject { } if (!ref) return logError('patch-no-ref') - function convertHelpers (originVal, newVal) { - if (isArray(originVal) && isArrayHelper(newVal)) { - newVal = newVal.executeOn(originVal) - } - if (isNumber(originVal) && isIncrementHelper(newVal)) { - newVal = newVal.executeOn(originVal) - } - return newVal // always return newVal as fallback!! - } - - // const refPropsPicked = filter(ref, Object.keys(patches)) - // const patchesSanitised = merge({ extensions: [convertHelpers] }, refPropsPicked, patches) - const patchesFlat = flattenObject(patches) - for (const [path, value] of Object.entries(patchesFlat)) { const targetVal = pathToProp(ref, path) const newVal = convertHelpers(targetVal, value) // do not update anything if the values are the same // this is technically not required, because vue takes care of this as well: - if (targetVal === newVal) return + if (targetVal === newVal) continue // update just the nested value - const pathParts = path.split('.') - const prop = pathParts.pop() - const pathParent = pathParts.join('') - const targetForNestedProp = pathToProp(ref, pathParent) - this._vm.$set(targetForNestedProp, prop, newVal) + const setParams = getSetParams(ref, path, newVal) + this._vm.$set(...setParams) } }, DELETE_DOC (state, id) { diff --git a/test/helpers/index.cjs.js b/test/helpers/index.cjs.js index 7eca1ddf..4d3d7982 100644 --- a/test/helpers/index.cjs.js +++ b/test/helpers/index.cjs.js @@ -850,6 +850,28 @@ function isIncrementHelper(payload) { payload.isIncrementHelper === true); } +/** + * Creates the params needed to $set a target based on a nested.path + * + * @param {object} target + * @param {string} path + * @param {*} value + * @returns {[object, string, any]} + */ +function getSetParams(target, path, value) { + var _a; + var pathParts = path.split('.'); + var prop = pathParts.pop(); + var pathParent = pathParts.join('.'); + var targetForNestedProp = pathToProp(target, pathParent); + if (targetForNestedProp === undefined) { + // the target doesn't have an object ready at this level to set the value to + // so we need to step down a level and try again + return getSetParams(target, pathParent, (_a = {}, _a[prop] = value, _a)); + } + var valueToSet = value; + return [targetForNestedProp, prop, valueToSet]; +} /** * a function returning the mutations object * @@ -923,6 +945,7 @@ function pluginMutations (userState) { } }, PATCH_DOC: function (state, patches) { + var _a; // Get the state prop ref var ref = state._conf.statePropName ? state[state._conf.statePropName] : state; if (state._conf.firestoreRefType.toLowerCase() === 'collection') { @@ -942,20 +965,17 @@ function pluginMutations (userState) { // const refPropsPicked = filter(ref, Object.keys(patches)) // const patchesSanitised = merge({ extensions: [convertHelpers] }, refPropsPicked, patches) var patchesFlat = flatten.flattenObject(patches); - for (var _i = 0, _a = Object.entries(patchesFlat); _i < _a.length; _i++) { - var _b = _a[_i], path = _b[0], value = _b[1]; + for (var _i = 0, _b = Object.entries(patchesFlat); _i < _b.length; _i++) { + var _c = _b[_i], path = _c[0], value = _c[1]; var targetVal = pathToProp(ref, path); var newVal = convertHelpers(targetVal, value); // do not update anything if the values are the same // this is technically not required, because vue takes care of this as well: if (targetVal === newVal) - return; + continue; // update just the nested value - var pathParts = path.split('.'); - var prop = pathParts.pop(); - var pathParent = pathParts.join(''); - var targetForNestedProp = pathToProp(ref, pathParent); - this._vm.$set(targetForNestedProp, prop, newVal); + var setParams = getSetParams(ref, path, newVal); + (_a = this._vm).$set.apply(_a, setParams); } }, DELETE_DOC: function (state, id) {