dist/index.cjs.js
function pluginActions (Firebase) {
    var _this = this;
    return {
        setUserId: function (_a, userId) {
            var commit = _a.commit, getters = _a.getters;
            if (userId === undefined)
                userId = null;
            // undefined cannot be synced to firestore
            if (!userId && Firebase.auth().currentUser) {
                userId = Firebase.auth().currentUser.uid;
            }
            commit('SET_USER_ID', userId);
            if (getters.firestorePathComplete.includes('{userId}'))
                return error('user-auth');
        },
        clearUser: function (_a) {
            var commit = _a.commit;
            commit('CLEAR_USER');
        },
        setPathVars: function (_a, pathVars) {
            var commit = _a.commit;
            commit('SET_PATHVARS', pathVars);
        },
        duplicate: function (_a, id) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            return __awaiter(_this, void 0, void 0, function () {
                var _b, doc, dId, idMap;
                return __generator(this, function (_c) {
                    switch (_c.label) {
                        case 0:
                            if (!getters.collectionMode)
                                return [2 /*return*/, error('only-in-collection-mode')];
                            if (!id)
                                return [2 /*return*/, {}];
                            doc = merge(getters.storeRef[id], { id: null });
                            return [4 /*yield*/, dispatch('insert', doc)];
                        case 1:
                            dId = _c.sent();
                            idMap = (_b = {}, _b[id] = dId, _b);
                            return [2 /*return*/, idMap];
                    }
                });
            });
        },
        duplicateBatch: function (_a, ids) {
            var _this = this;
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            if (ids === void 0) { ids = []; }
            if (!getters.collectionMode)
                return error('only-in-collection-mode');
            if (!isWhat.isArray(ids) || !ids.length)
                return {};
            var idsMap = ids.reduce(function (carry, id) { return __awaiter(_this, void 0, void 0, function () {
                var idMap;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0: return [4 /*yield*/, dispatch('duplicate', id)];
                        case 1:
                            idMap = _a.sent();
                            return [4 /*yield*/, carry];
                        case 2:
                            carry = _a.sent();
                            return [2 /*return*/, Object.assign(carry, idMap)];
                    }
                });
            }); }, {});
            return idsMap;
        },
        patchDoc: function (_a, _b) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var _c = _b === void 0 ? { ids: [], doc: {} } : _b, _d = _c.id, id = _d === void 0 ? '' : _d, _e = _c.ids, ids = _e === void 0 ? [] : _e, doc = _c.doc;
            // 0. payload correction (only arrays)
            if (!isWhat.isArray(ids))
                return error("`ids` prop passed to 'patch' needs to be an array");
            if (id)
                ids.push(id);
            // EXTRA: check if doc is being inserted if so
            state._sync.syncStack.inserts.forEach(function (newDoc, newDocIndex) {
                // get the index of the id that is also in the insert stack
                var indexIdInInsert = ids.indexOf(newDoc.id);
                if (indexIdInInsert === -1)
                    return;
                // the doc trying to be synced is also in insert
                // prepare the doc as new doc:
                var patchDoc = getters.prepareForInsert([doc])[0];
                // replace insert sync stack with merged item:
                state._sync.syncStack.inserts[newDocIndex] = merge(newDoc, patchDoc);
                // empty out the id that was to be patched:
                ids.splice(indexIdInInsert, 1);
            });
            // 1. Prepare for patching
            var syncStackItems = getters.prepareForPatch(ids, doc);
            // 2. Push to syncStack
            Object.keys(syncStackItems).forEach(function (id) {
                var newVal;
                if (!state._sync.syncStack.updates[id]) {
                    // replace arrayUnion and arrayRemove
                    newVal = findAndReplaceAnything.findAndReplaceIf(syncStackItems[id], function (foundVal) {
                        if (isArrayHelper(foundVal)) {
                            return foundVal.getFirestoreFieldValue();
                        }
                        if (isIncrementHelper(foundVal)) {
                            return foundVal.getFirestoreFieldValue();
                        }
                        return foundVal;
                    });
                }
                else {
                    newVal = merge({ extensions: [
                            function (originVal, newVal) {
                                if (originVal instanceof Firebase.firestore.FieldValue &&
                                    isArrayHelper(newVal)) {
                                    originVal._elements = originVal._elements.concat(newVal.payload);
                                    newVal = originVal;
                                }
                                if (originVal instanceof Firebase.firestore.FieldValue &&
                                    isIncrementHelper(newVal)) {
                                    originVal._operand = originVal._operand + newVal.payload;
                                    newVal = originVal;
                                }
                                return newVal; // always return newVal as fallback!!
                            }
                        ] }, state._sync.syncStack.updates[id], syncStackItems[id]);
                }
                state._sync.syncStack.updates[id] = newVal;
            });
            // 3. Create or refresh debounce
            return dispatch('handleSyncStackDebounce');
        },
        deleteDoc: function (_a, ids) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            if (ids === void 0) { ids = []; }
            // 0. payload correction (only arrays)
            if (!isWhat.isArray(ids))
                ids = [ids];
            // 1. Prepare for patching
            // 2. Push to syncStack
            var deletions = state._sync.syncStack.deletions.concat(ids);
            state._sync.syncStack.deletions = deletions;
            if (!state._sync.syncStack.deletions.length)
                return;
            // 3. Create or refresh debounce
            return dispatch('handleSyncStackDebounce');
        },
        deleteProp: function (_a, path) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            // 1. Prepare for patching
            var syncStackItem = getters.prepareForPropDeletion(path);
            // 2. Push to syncStack
            Object.keys(syncStackItem).forEach(function (id) {
                var newVal = (!state._sync.syncStack.propDeletions[id])
                    ? syncStackItem[id]
                    : merge(state._sync.syncStack.propDeletions[id], syncStackItem[id]);
                state._sync.syncStack.propDeletions[id] = newVal;
            });
            // 3. Create or refresh debounce
            return dispatch('handleSyncStackDebounce');
        },
        insertDoc: function (_a, docs) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            if (docs === void 0) { docs = []; }
            // 0. payload correction (only arrays)
            if (!isWhat.isArray(docs))
                docs = [docs];
            // 1. Prepare for patching
            var syncStack = getters.prepareForInsert(docs);
            // 2. Push to syncStack
            var inserts = state._sync.syncStack.inserts.concat(syncStack);
            state._sync.syncStack.inserts = inserts;
            // 3. Create or refresh debounce
            dispatch('handleSyncStackDebounce');
            return docs.map(function (d) { return d.id; });
        },
        insertInitialDoc: function (_a) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            // 0. only docMode
            if (getters.collectionMode)
                return;
            // 1. Prepare for insert
            var initialDoc = (getters.storeRef) ? getters.storeRef : {};
            var initialDocPrepared = getters.prepareInitialDocForInsert(initialDoc);
            // 2. Create a reference to the SF doc.
            var initialDocRef = getters.dbRef;
            return Firebase.firestore().runTransaction(function (transaction) {
                // This code may get re-run multiple times if there are conflicts.
                return transaction.get(initialDocRef)
                    .then(function (foundInitialDoc) {
                    if (!foundInitialDoc.exists) {
                        transaction.set(initialDocRef, initialDocPrepared);
                    }
                });
            }).then(function (_) {
                if (state._conf.logging) {
                    console.log('[vuex-easy-firestore] Initial doc succesfully inserted.');
                }
            }).catch(function (error$1) {
                return error('initial-doc-failed', error$1);
            });
        },
        handleSyncStackDebounce: function (_a) {
            var state = _a.state, commit = _a.commit, dispatch = _a.dispatch, getters = _a.getters;
            if (!getters.signedIn)
                return false;
            if (!state._sync.syncStack.debounceTimer) {
                var ms = state._conf.sync.debounceTimerMs;
                var debounceTimer = startDebounce(ms);
                debounceTimer.done.then(function (_) { return dispatch('batchSync'); });
                state._sync.syncStack.debounceTimer = debounceTimer;
            }
            state._sync.syncStack.debounceTimer.refresh();
        },
        batchSync: function (_a) {
            var getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch, state = _a.state;
            var batch = makeBatchFromSyncstack(state, getters, Firebase);
            dispatch('_startPatching');
            state._sync.syncStack.debounceTimer = null;
            return new Promise(function (resolve, reject) {
                batch.commit().then(function (_) {
                    var remainingSyncStack = Object.keys(state._sync.syncStack.updates).length +
                        state._sync.syncStack.deletions.length +
                        state._sync.syncStack.inserts.length +
                        state._sync.syncStack.propDeletions.length;
                    if (remainingSyncStack) {
                        dispatch('batchSync');
                    }
                    dispatch('_stopPatching');
                    return resolve();
                }).catch(function (error$1) {
                    state._sync.patching = 'error';
                    state._sync.syncStack.debounceTimer = null;
                    return reject(error$1);
                });
            });
        },
        fetch: function (_a, pathVariables
        // where: [['archived', '==', true]]
        // orderBy: ['done_date', 'desc']
        ) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            if (pathVariables === void 0) { pathVariables = { where: [], whereFilters: [], orderBy: [] }; }
            dispatch('setUserId');
            var where = pathVariables.where, whereFilters = pathVariables.whereFilters, orderBy = pathVariables.orderBy;
            if (!isWhat.isArray(where))
                where = [];
            if (!isWhat.isArray(orderBy))
                orderBy = [];
            if (isWhat.isArray(whereFilters) && whereFilters.length)
                where = whereFilters; // depreciated
            if (pathVariables && isWhat.isPlainObject(pathVariables)) {
                commit('SET_PATHVARS', pathVariables);
            }
            return new Promise(function (resolve, reject) {
                // log
                if (state._conf.logging) {
                    console.log("%c fetch for Firestore PATH: " + getters.firestorePathComplete + " [" + state._conf.firestorePath + "]", 'color: lightcoral');
                }
                if (!getters.signedIn)
                    return resolve();
                var identifier = createFetchIdentifier({ where: where, orderBy: orderBy });
                var fetched = state._sync.fetched[identifier];
                // We've never fetched this before:
                if (!fetched) {
                    var ref_1 = getters.dbRef;
                    // apply where filters and orderBy
                    getters.getWhereArrays(where).forEach(function (paramsArr) {
                        ref_1 = ref_1.where.apply(ref_1, paramsArr);
                    });
                    if (orderBy.length)
                        ref_1 = ref_1.orderBy.apply(ref_1, orderBy);
                    state._sync.fetched[identifier] = {
                        ref: ref_1,
                        done: false,
                        retrievedFetchRefs: [],
                        nextFetchRef: null
                    };
                }
                var fRequest = state._sync.fetched[identifier];
                // We're already done fetching everything:
                if (fRequest.done) {
                    if (state._conf.logging)
                        console.log('[vuex-easy-firestore] done fetching');
                    return resolve({ done: true });
                }
                // attach fetch filters
                var fRef = state._sync.fetched[identifier].ref;
                if (fRequest.nextFetchRef) {
                    // get next ref if saved in state
                    fRef = state._sync.fetched[identifier].nextFetchRef;
                }
                // add doc limit
                var limit = (isWhat.isNumber(pathVariables.limit))
                    ? pathVariables.limit
                    : state._conf.fetch.docLimit;
                if (limit > 0)
                    fRef = fRef.limit(limit);
                // Stop if all records already fetched
                if (fRequest.retrievedFetchRefs.includes(fRef)) {
                    console.log('[vuex-easy-firestore] Already retrieved this part.');
                    return resolve();
                }
                // make fetch request
                fRef.get().then(function (querySnapshot) {
                    var docs = querySnapshot.docs;
                    if (docs.length === 0) {
                        state._sync.fetched[identifier].done = true;
                        querySnapshot.done = true;
                        return resolve(querySnapshot);
                    }
                    if (docs.length < limit) {
                        state._sync.fetched[identifier].done = true;
                    }
                    state._sync.fetched[identifier].retrievedFetchRefs.push(fRef);
                    // Get the last visible document
                    resolve(querySnapshot);
                    var lastVisible = docs[docs.length - 1];
                    // set the reference for the next records.
                    var next = fRef.startAfter(lastVisible);
                    state._sync.fetched[identifier].nextFetchRef = next;
                }).catch(function (error$1) {
                    return reject(error(error$1));
                });
            });
        },
        fetchAndAdd: function (_a, pathVariables
        // where: [['archived', '==', true]]
        // orderBy: ['done_date', 'desc']
        ) {
            var _this = this;
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            if (pathVariables === void 0) { pathVariables = { where: [], whereFilters: [], orderBy: [] }; }
            if (pathVariables && isWhat.isPlainObject(pathVariables)) {
                commit('SET_PATHVARS', pathVariables);
            }
            // 'doc' mode:
            if (!getters.collectionMode) {
                dispatch('setUserId');
                if (state._conf.logging) {
                    console.log("%c fetch for Firestore PATH: " + getters.firestorePathComplete + " [" + state._conf.firestorePath + "]", 'color: lightcoral');
                }
                return getters.dbRef.get().then(function (_doc) { return __awaiter(_this, void 0, void 0, function () {
                    var id, doc;
                    return __generator(this, function (_a) {
                        switch (_a.label) {
                            case 0:
                                if (!!_doc.exists) return [3 /*break*/, 2];
                                // No initial doc found in docMode
                                if (state._conf.sync.preventInitialDocInsertion)
                                    throw 'preventInitialDocInsertion';
                                if (state._conf.logging)
                                    console.log('[vuex-easy-firestore] inserting initial doc');
                                return [4 /*yield*/, dispatch('insertInitialDoc')];
                            case 1:
                                _a.sent();
                                return [2 /*return*/, _doc];
                            case 2:
                                id = getters.docModeId;
                                doc = getters.cleanUpRetrievedDoc(_doc.data(), id);
                                dispatch('applyHooksAndUpdateState', { change: 'modified', id: id, doc: doc });
                                return [2 /*return*/, doc];
                        }
                    });
                }); }).catch(function (error$1) {
                    return error(error$1);
                });
            }
            // 'collection' mode:
            return dispatch('fetch', pathVariables)
                .then(function (querySnapshot) {
                if (querySnapshot.done === true)
                    return querySnapshot;
                if (isWhat.isFunction(querySnapshot.forEach)) {
                    querySnapshot.forEach(function (_doc) {
                        var id = _doc.id;
                        var doc = getters.cleanUpRetrievedDoc(_doc.data(), id);
                        dispatch('applyHooksAndUpdateState', { change: 'added', id: id, doc: doc });
                    });
                }
                return querySnapshot;
            });
        },
        fetchById: function (_a, id) {
            var dispatch = _a.dispatch, getters = _a.getters, state = _a.state;
            return __awaiter(this, void 0, void 0, function () {
                var ref, _doc, doc, e_1;
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0:
                            _b.trys.push([0, 2, , 3]);
                            if (!id)
                                throw 'missing-id';
                            if (!getters.collectionMode)
                                throw 'only-in-collection-mode';
                            ref = getters.dbRef;
                            return [4 /*yield*/, ref.doc(id).get()];
                        case 1:
                            _doc = _b.sent();
                            if (!_doc.exists) {
                                if (state._conf.logging) {
                                    throw "Doc with id \"" + id + "\" not found!";
                                }
                            }
                            doc = getters.cleanUpRetrievedDoc(_doc.data(), id);
                            dispatch('applyHooksAndUpdateState', { change: 'added', id: id, doc: doc });
                            return [2 /*return*/, doc];
                        case 2:
                            e_1 = _b.sent();
                            return [2 /*return*/, error(e_1)];
                        case 3: return [2 /*return*/];
                    }
                });
            });
        },
        applyHooksAndUpdateState: function (// this is only on server retrievals
        _a, _b) {
            var getters = _a.getters, state = _a.state, commit = _a.commit, dispatch = _a.dispatch;
            var change = _b.change, id = _b.id, _c = _b.doc, doc = _c === void 0 ? {} : _c;
            var store = this;
            // define storeUpdateFn()
            function storeUpdateFn(_doc) {
                switch (change) {
                    case 'added':
                        commit('INSERT_DOC', _doc);
                        break;
                    case 'removed':
                        commit('DELETE_DOC', id);
                        break;
                    default:
                        dispatch('deleteMissingProps', _doc);
                        commit('PATCH_DOC', _doc);
                        break;
                }
            }
            // get user set sync hook function
            var syncHookFn = state._conf.serverChange[change + 'Hook'];
            if (isWhat.isFunction(syncHookFn)) {
                syncHookFn(storeUpdateFn, doc, id, store, 'server', change);
            }
            else {
                storeUpdateFn(doc);
            }
        },
        deleteMissingProps: function (_a, doc) {
            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
            );
            Object.keys(compareInfo.presentIn).forEach(function (prop) {
                // don't worry about props not in fillables
                if (getters.fillables.length && !getters.fillables.includes(prop)) {
                    return;
                }
                // don't worry about props in guard
                if (getters.guard.includes(prop))
                    return;
                // don't worry about props starting with _sync or _conf
                if (prop.split('.')[0] === '_sync' || prop.split('.')[0] === '_conf')
                    return;
                // where is the prop present?
                var presence = compareInfo.presentIn[prop];
                var propNotInDoc = (!presence.includes(0));
                var propNotInDefaultValues = (!presence.includes(1));
                // delete props that are not present in the doc and default values
                if (propNotInDoc && propNotInDefaultValues) {
                    var path = (getters.collectionMode)
                        ? doc.id + "." + prop
                        : prop;
                    return commit('DELETE_PROP', path);
                }
            });
        },
        openDBChannel: function (_a, pathVariables) {
            var _this = this;
            var getters = _a.getters, state = _a.state, commit = _a.commit, dispatch = _a.dispatch;
            dispatch('setUserId');
            // `first` makes sure that local changes made during offline are reflected as server changes which the app is refreshed during offline mode
            var first = true;
            // set state for pathVariables
            if (pathVariables && isWhat.isPlainObject(pathVariables)) {
                commit('SET_SYNCFILTERS', pathVariables);
                delete pathVariables.where;
                delete pathVariables.orderBy;
                commit('SET_PATHVARS', pathVariables);
            }
            var identifier = createFetchIdentifier({
                where: state._conf.sync.where,
                orderBy: state._conf.sync.orderBy,
                pathVariables: state._sync.pathVariables
            });
            if (isWhat.isFunction(state._sync.unsubscribe[identifier])) {
                var channelAlreadyOpenError_1 = "openDBChannel was already called for these filters and pathvariables. Identifier: " + identifier;
                if (state._conf.logging) {
                    console.log(channelAlreadyOpenError_1);
                }
                return new Promise(function (resolve, reject) { reject(channelAlreadyOpenError_1); });
            }
            // getters.dbRef should already have pathVariables swapped out
            var dbRef = getters.dbRef;
            // apply where filters and orderBy
            if (getters.collectionMode) {
                getters.getWhereArrays().forEach(function (whereParams) {
                    dbRef = dbRef.where.apply(dbRef, whereParams);
                });
                if (state._conf.sync.orderBy.length) {
                    dbRef = dbRef.orderBy.apply(dbRef, state._conf.sync.orderBy);
                }
            }
            // make a promise
            return new Promise(function (resolve, reject) {
                // log
                if (state._conf.logging) {
                    console.log("%c openDBChannel for Firestore PATH: " + getters.firestorePathComplete + " [" + state._conf.firestorePath + "]", 'color: lightcoral');
                }
                var unsubscribe = dbRef.onSnapshot(function (querySnapshot) { return __awaiter(_this, void 0, void 0, function () {
                    var source, id, doc;
                    return __generator(this, function (_a) {
                        switch (_a.label) {
                            case 0:
                                source = querySnapshot.metadata.hasPendingWrites ? 'local' : 'server';
                                if (!!getters.collectionMode) return [3 /*break*/, 3];
                                if (!!querySnapshot.data()) return [3 /*break*/, 2];
                                // No initial doc found in docMode
                                if (state._conf.sync.preventInitialDocInsertion)
                                    return [2 /*return*/, reject('preventInitialDocInsertion')];
                                if (state._conf.logging)
                                    console.log('[vuex-easy-firestore] inserting initial doc');
                                return [4 /*yield*/, dispatch('insertInitialDoc')];
                            case 1:
                                _a.sent();
                                return [2 /*return*/, resolve()];
                            case 2:
                                if (source === 'local' && !first)
                                    return [2 /*return*/, resolve()];
                                id = getters.docModeId;
                                doc = getters.cleanUpRetrievedDoc(querySnapshot.data(), id);
                                dispatch('applyHooksAndUpdateState', { change: 'modified', id: id, doc: doc });
                                first = false;
                                return [2 /*return*/, resolve()];
                            case 3:
                                // 'collection' mode:
                                querySnapshot.docChanges().forEach(function (change) {
                                    var changeType = change.type;
                                    // Don't do anything for local modifications & removals
                                    if (source === 'local' && !first)
                                        return resolve();
                                    var id = change.doc.id;
                                    var doc = getters.cleanUpRetrievedDoc(change.doc.data(), id);
                                    dispatch('applyHooksAndUpdateState', { change: changeType, id: id, doc: doc });
                                });
                                first = false;
                                return [2 /*return*/, resolve()];
                        }
                    });
                }); }, function (error$1) {
                    state._sync.patching = 'error';
                    return reject(error(error$1));
                });
                state._sync.unsubscribe[identifier] = unsubscribe;
            });
        },
        closeDBChannel: function (_a, _b) {
            var getters = _a.getters, state = _a.state, commit = _a.commit, dispatch = _a.dispatch;
            var _c = (_b === void 0 ? { clearModule: false } : _b).clearModule, clearModule = _c === void 0 ? false : _c;
            var identifier = createFetchIdentifier({
                where: state._conf.sync.where,
                orderBy: state._conf.sync.orderBy,
                pathVariables: state._sync.pathVariables
            });
            var unsubscribeDBChannel = state._sync.unsubscribe[identifier];
            if (isWhat.isFunction(unsubscribeDBChannel)) {
                unsubscribeDBChannel();
                state._sync.unsubscribe[identifier] = null;
            }
            if (clearModule) {
                commit('RESET_VUEX_EASY_FIRESTORE_STATE');
            }
        },
        set: function (_a, doc) {
            var commit = _a.commit, dispatch = _a.dispatch, getters = _a.getters, state = _a.state;
            if (!doc)
                return;
            if (!getters.collectionMode) {
                return dispatch('patch', doc);
            }
            var id = getId(doc);
            if (!id ||
                (!state._conf.statePropName && !state[id]) ||
                (state._conf.statePropName && !state[state._conf.statePropName][id])) {
                return dispatch('insert', doc);
            }
            return dispatch('patch', doc);
        },
        insert: function (_a, doc) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var store = this;
            // check payload
            if (!doc)
                return;
            // check userId
            dispatch('setUserId');
            var newDoc = doc;
            if (!newDoc.id)
                newDoc.id = getters.dbRef.doc().id;
            // apply default values
            var newDocWithDefaults = setDefaultValues(newDoc, state._conf.sync.defaultValues);
            // define the store update
            function storeUpdateFn(_doc) {
                commit('INSERT_DOC', _doc);
                return dispatch('insertDoc', _doc);
            }
            // check for hooks
            if (state._conf.sync.insertHook) {
                state._conf.sync.insertHook(storeUpdateFn, newDocWithDefaults, store);
                return newDocWithDefaults.id;
            }
            storeUpdateFn(newDocWithDefaults);
            return newDocWithDefaults.id;
        },
        insertBatch: function (_a, docs) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var store = this;
            // check payload
            if (!isWhat.isArray(docs) || !docs.length)
                return [];
            // check userId
            dispatch('setUserId');
            var newDocs = docs.reduce(function (carry, _doc) {
                var newDoc = getValueFromPayloadPiece(_doc);
                if (!newDoc.id)
                    newDoc.id = getters.dbRef.doc().id;
                carry.push(newDoc);
                return carry;
            }, []);
            // define the store update
            function storeUpdateFn(_docs) {
                _docs.forEach(function (_doc) {
                    commit('INSERT_DOC', _doc);
                });
                return dispatch('insertDoc', _docs);
            }
            // check for hooks
            if (state._conf.sync.insertBatchHook) {
                state._conf.sync.insertBatchHook(storeUpdateFn, newDocs, store);
                return newDocs.map(function (_doc) { return _doc.id; });
            }
            storeUpdateFn(newDocs);
            return newDocs.map(function (_doc) { return _doc.id; });
        },
        patch: function (_a, doc) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var store = this;
            // check payload
            if (!doc)
                return;
            var id = (getters.collectionMode) ? getId(doc) : getters.docModeId;
            var value = (getters.collectionMode) ? getValueFromPayloadPiece(doc) : doc;
            if (!id && getters.collectionMode)
                return error('patch-missing-id');
            // check userId
            dispatch('setUserId');
            // add id to value
            if (!value.id)
                value.id = id;
            // define the store update
            function storeUpdateFn(_val) {
                commit('PATCH_DOC', _val);
                return dispatch('patchDoc', { id: id, doc: copy(_val) });
            }
            // check for hooks
            if (state._conf.sync.patchHook) {
                state._conf.sync.patchHook(storeUpdateFn, value, store);
                return id;
            }
            storeUpdateFn(value);
            return id;
        },
        patchBatch: function (_a, _b) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var doc = _b.doc, _c = _b.ids, ids = _c === void 0 ? [] : _c;
            var store = this;
            // check payload
            if (!doc)
                return [];
            if (!isWhat.isArray(ids) || !ids.length)
                return [];
            // check userId
            dispatch('setUserId');
            // define the store update
            function storeUpdateFn(_doc, _ids) {
                _ids.forEach(function (_id) {
                    commit('PATCH_DOC', __assign({ id: _id }, _doc));
                });
                return dispatch('patchDoc', { ids: _ids, doc: _doc });
            }
            // check for hooks
            if (state._conf.sync.patchBatchHook) {
                state._conf.sync.patchBatchHook(storeUpdateFn, doc, ids, store);
                return ids;
            }
            storeUpdateFn(doc, ids);
            return ids;
        },
        delete: function (_a, id) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var store = this;
            // check payload
            if (!id)
                return;
            // check userId
            dispatch('setUserId');
            function storeUpdateFn(_id) {
                // id is a path
                var pathDelete = (_id.includes('.') || !getters.collectionMode);
                if (pathDelete) {
                    var path = _id;
                    if (!path)
                        return error('delete-missing-path');
                    commit('DELETE_PROP', path);
                    return dispatch('deleteProp', path);
                }
                if (!_id)
                    return error('delete-missing-id');
                commit('DELETE_DOC', _id);
                return dispatch('deleteDoc', _id);
            }
            // check for hooks
            if (state._conf.sync.deleteHook) {
                state._conf.sync.deleteHook(storeUpdateFn, id, store);
                return id;
            }
            storeUpdateFn(id);
            return id;
        },
        deleteBatch: function (_a, ids) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var store = this;
            // check payload
            if (!isWhat.isArray(ids) || !ids.length)
                return [];
            // check userId
            dispatch('setUserId');
            // define the store update
            function storeUpdateFn(_ids) {
                _ids.forEach(function (_id) {
                    // id is a path
                    var pathDelete = (_id.includes('.') || !getters.collectionMode);
                    if (pathDelete) {
                        var path = _id;
                        if (!path)
                            return error('delete-missing-path');
                        commit('DELETE_PROP', path);
                        return dispatch('deleteProp', path);
                    }
                    if (!_id)
                        return error('delete-missing-id');
                    commit('DELETE_DOC', _id);
                    return dispatch('deleteDoc', _id);
                });
            }
            // check for hooks
            if (state._conf.sync.deleteBatchHook) {
                state._conf.sync.deleteBatchHook(storeUpdateFn, ids, store);
                return ids;
            }
            storeUpdateFn(ids);
            return ids;
        },
        _stopPatching: function (_a) {
            var state = _a.state, commit = _a.commit;
            if (state._sync.stopPatchingTimeout) {
                clearTimeout(state._sync.stopPatchingTimeout);
            }
            state._sync.stopPatchingTimeout = setTimeout(function (_) { state._sync.patching = false; }, 300);
        },
        _startPatching: function (_a) {
            var state = _a.state, commit = _a.commit;
            if (state._sync.stopPatchingTimeout) {
                clearTimeout(state._sync.stopPatchingTimeout);
            }
            state._sync.patching = true;
        }
    };
}
function pluginActions (Firebase) {
    var _this = this;
    return {
        setUserId: function (_a, userId) {
            var commit = _a.commit, getters = _a.getters;
            if (userId === undefined)
                userId = null;
            // undefined cannot be synced to firestore
            if (!userId && Firebase.auth().currentUser) {
                userId = Firebase.auth().currentUser.uid;
            }
            commit('SET_USER_ID', userId);
            if (getters.firestorePathComplete.includes('{userId}'))
                return error('user-auth');
        },
        clearUser: function (_a) {
            var commit = _a.commit;
            commit('CLEAR_USER');
        },
        setPathVars: function (_a, pathVars) {
            var commit = _a.commit;
            commit('SET_PATHVARS', pathVars);
        },
        duplicate: function (_a, id) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            return __awaiter(_this, void 0, void 0, function () {
                var _b, doc, dId, idMap;
                return __generator(this, function (_c) {
                    switch (_c.label) {
                        case 0:
                            if (!getters.collectionMode)
                                return [2 /*return*/, error('only-in-collection-mode')];
                            if (!id)
                                return [2 /*return*/, {}];
                            doc = merge(getters.storeRef[id], { id: null });
                            return [4 /*yield*/, dispatch('insert', doc)];
                        case 1:
                            dId = _c.sent();
                            idMap = (_b = {}, _b[id] = dId, _b);
                            return [2 /*return*/, idMap];
                    }
                });
            });
        },
        duplicateBatch: function (_a, ids) {
            var _this = this;
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            if (ids === void 0) { ids = []; }
            if (!getters.collectionMode)
                return error('only-in-collection-mode');
            if (!isWhat.isArray(ids) || !ids.length)
                return {};
            var idsMap = ids.reduce(function (carry, id) { return __awaiter(_this, void 0, void 0, function () {
                var idMap;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0: return [4 /*yield*/, dispatch('duplicate', id)];
                        case 1:
                            idMap = _a.sent();
                            return [4 /*yield*/, carry];
                        case 2:
                            carry = _a.sent();
                            return [2 /*return*/, Object.assign(carry, idMap)];
                    }
                });
            }); }, {});
            return idsMap;
        },
        patchDoc: function (_a, _b) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var _c = _b === void 0 ? { ids: [], doc: {} } : _b, _d = _c.id, id = _d === void 0 ? '' : _d, _e = _c.ids, ids = _e === void 0 ? [] : _e, doc = _c.doc;
            // 0. payload correction (only arrays)
            if (!isWhat.isArray(ids))
                return error("`ids` prop passed to 'patch' needs to be an array");
            if (id)
                ids.push(id);
            // EXTRA: check if doc is being inserted if so
            state._sync.syncStack.inserts.forEach(function (newDoc, newDocIndex) {
                // get the index of the id that is also in the insert stack
                var indexIdInInsert = ids.indexOf(newDoc.id);
                if (indexIdInInsert === -1)
                    return;
                // the doc trying to be synced is also in insert
                // prepare the doc as new doc:
                var patchDoc = getters.prepareForInsert([doc])[0];
                // replace insert sync stack with merged item:
                state._sync.syncStack.inserts[newDocIndex] = merge(newDoc, patchDoc);
                // empty out the id that was to be patched:
                ids.splice(indexIdInInsert, 1);
            });
            // 1. Prepare for patching
            var syncStackItems = getters.prepareForPatch(ids, doc);
            // 2. Push to syncStack
            Object.keys(syncStackItems).forEach(function (id) {
                var newVal;
                if (!state._sync.syncStack.updates[id]) {
                    // replace arrayUnion and arrayRemove
                    newVal = findAndReplaceAnything.findAndReplaceIf(syncStackItems[id], function (foundVal) {
                        if (isArrayHelper(foundVal)) {
                            return foundVal.getFirestoreFieldValue();
                        }
                        if (isIncrementHelper(foundVal)) {
                            return foundVal.getFirestoreFieldValue();
                        }
                        return foundVal;
                    });
                }
                else {
                    newVal = merge({ extensions: [
                            function (originVal, newVal) {
                                if (originVal instanceof Firebase.firestore.FieldValue &&
                                    isArrayHelper(newVal)) {
                                    originVal._elements = originVal._elements.concat(newVal.payload);
                                    newVal = originVal;
                                }
                                if (originVal instanceof Firebase.firestore.FieldValue &&
                                    isIncrementHelper(newVal)) {
                                    originVal._operand = originVal._operand + newVal.payload;
                                    newVal = originVal;
                                }
                                return newVal; // always return newVal as fallback!!
                            }
                        ] }, state._sync.syncStack.updates[id], syncStackItems[id]);
                }
                state._sync.syncStack.updates[id] = newVal;
            });
            // 3. Create or refresh debounce
            return dispatch('handleSyncStackDebounce');
        },
        deleteDoc: function (_a, ids) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            if (ids === void 0) { ids = []; }
            // 0. payload correction (only arrays)
            if (!isWhat.isArray(ids))
                ids = [ids];
            // 1. Prepare for patching
            // 2. Push to syncStack
            var deletions = state._sync.syncStack.deletions.concat(ids);
            state._sync.syncStack.deletions = deletions;
            if (!state._sync.syncStack.deletions.length)
                return;
            // 3. Create or refresh debounce
            return dispatch('handleSyncStackDebounce');
        },
        deleteProp: function (_a, path) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            // 1. Prepare for patching
            var syncStackItem = getters.prepareForPropDeletion(path);
            // 2. Push to syncStack
            Object.keys(syncStackItem).forEach(function (id) {
                var newVal = (!state._sync.syncStack.propDeletions[id])
                    ? syncStackItem[id]
                    : merge(state._sync.syncStack.propDeletions[id], syncStackItem[id]);
                state._sync.syncStack.propDeletions[id] = newVal;
            });
            // 3. Create or refresh debounce
            return dispatch('handleSyncStackDebounce');
        },
        insertDoc: function (_a, docs) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            if (docs === void 0) { docs = []; }
            // 0. payload correction (only arrays)
            if (!isWhat.isArray(docs))
                docs = [docs];
            // 1. Prepare for patching
            var syncStack = getters.prepareForInsert(docs);
            // 2. Push to syncStack
            var inserts = state._sync.syncStack.inserts.concat(syncStack);
            state._sync.syncStack.inserts = inserts;
            // 3. Create or refresh debounce
            dispatch('handleSyncStackDebounce');
            return docs.map(function (d) { return d.id; });
        },
        insertInitialDoc: function (_a) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            // 0. only docMode
            if (getters.collectionMode)
                return;
            // 1. Prepare for insert
            var initialDoc = (getters.storeRef) ? getters.storeRef : {};
            var initialDocPrepared = getters.prepareInitialDocForInsert(initialDoc);
            // 2. Create a reference to the SF doc.
            var initialDocRef = getters.dbRef;
            return Firebase.firestore().runTransaction(function (transaction) {
                // This code may get re-run multiple times if there are conflicts.
                return transaction.get(initialDocRef)
                    .then(function (foundInitialDoc) {
                    if (!foundInitialDoc.exists) {
                        transaction.set(initialDocRef, initialDocPrepared);
                    }
                });
            }).then(function (_) {
                if (state._conf.logging) {
                    console.log('[vuex-easy-firestore] Initial doc succesfully inserted.');
                }
            }).catch(function (error$1) {
                return error('initial-doc-failed', error$1);
            });
        },
        handleSyncStackDebounce: function (_a) {
            var state = _a.state, commit = _a.commit, dispatch = _a.dispatch, getters = _a.getters;
            if (!getters.signedIn)
                return false;
            if (!state._sync.syncStack.debounceTimer) {
                var ms = state._conf.sync.debounceTimerMs;
                var debounceTimer = startDebounce(ms);
                debounceTimer.done.then(function (_) { return dispatch('batchSync'); });
                state._sync.syncStack.debounceTimer = debounceTimer;
            }
            state._sync.syncStack.debounceTimer.refresh();
        },
        batchSync: function (_a) {
            var getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch, state = _a.state;
            var batch = makeBatchFromSyncstack(state, getters, Firebase);
            dispatch('_startPatching');
            state._sync.syncStack.debounceTimer = null;
            return new Promise(function (resolve, reject) {
                batch.commit().then(function (_) {
                    var remainingSyncStack = Object.keys(state._sync.syncStack.updates).length +
                        state._sync.syncStack.deletions.length +
                        state._sync.syncStack.inserts.length +
                        state._sync.syncStack.propDeletions.length;
                    if (remainingSyncStack) {
                        dispatch('batchSync');
                    }
                    dispatch('_stopPatching');
                    return resolve();
                }).catch(function (error$1) {
                    state._sync.patching = 'error';
                    state._sync.syncStack.debounceTimer = null;
                    return reject(error$1);
                });
            });
        },
        fetch: function (_a, pathVariables
        // where: [['archived', '==', true]]
        // orderBy: ['done_date', 'desc']
        ) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            if (pathVariables === void 0) { pathVariables = { where: [], whereFilters: [], orderBy: [] }; }
            dispatch('setUserId');
            var where = pathVariables.where, whereFilters = pathVariables.whereFilters, orderBy = pathVariables.orderBy;
            if (!isWhat.isArray(where))
                where = [];
            if (!isWhat.isArray(orderBy))
                orderBy = [];
            if (isWhat.isArray(whereFilters) && whereFilters.length)
                where = whereFilters; // depreciated
            if (pathVariables && isWhat.isPlainObject(pathVariables)) {
                commit('SET_PATHVARS', pathVariables);
            }
            return new Promise(function (resolve, reject) {
                // log
                if (state._conf.logging) {
                    console.log("%c fetch for Firestore PATH: " + getters.firestorePathComplete + " [" + state._conf.firestorePath + "]", 'color: lightcoral');
                }
                if (!getters.signedIn)
                    return resolve();
                var identifier = createFetchIdentifier({ where: where, orderBy: orderBy });
                var fetched = state._sync.fetched[identifier];
                // We've never fetched this before:
                if (!fetched) {
                    var ref_1 = getters.dbRef;
                    // apply where filters and orderBy
                    getters.getWhereArrays(where).forEach(function (paramsArr) {
                        ref_1 = ref_1.where.apply(ref_1, paramsArr);
                    });
                    if (orderBy.length)
                        ref_1 = ref_1.orderBy.apply(ref_1, orderBy);
                    state._sync.fetched[identifier] = {
                        ref: ref_1,
                        done: false,
                        retrievedFetchRefs: [],
                        nextFetchRef: null
                    };
                }
                var fRequest = state._sync.fetched[identifier];
                // We're already done fetching everything:
                if (fRequest.done) {
                    if (state._conf.logging)
                        console.log('[vuex-easy-firestore] done fetching');
                    return resolve({ done: true });
                }
                // attach fetch filters
                var fRef = state._sync.fetched[identifier].ref;
                if (fRequest.nextFetchRef) {
                    // get next ref if saved in state
                    fRef = state._sync.fetched[identifier].nextFetchRef;
                }
                // add doc limit
                var limit = (isWhat.isNumber(pathVariables.limit))
                    ? pathVariables.limit
                    : state._conf.fetch.docLimit;
                if (limit > 0)
                    fRef = fRef.limit(limit);
                // Stop if all records already fetched
                if (fRequest.retrievedFetchRefs.includes(fRef)) {
                    console.log('[vuex-easy-firestore] Already retrieved this part.');
                    return resolve();
                }
                // make fetch request
                fRef.get().then(function (querySnapshot) {
                    var docs = querySnapshot.docs;
                    if (docs.length === 0) {
                        state._sync.fetched[identifier].done = true;
                        querySnapshot.done = true;
                        return resolve(querySnapshot);
                    }
                    if (docs.length < limit) {
                        state._sync.fetched[identifier].done = true;
                    }
                    state._sync.fetched[identifier].retrievedFetchRefs.push(fRef);
                    // Get the last visible document
                    resolve(querySnapshot);
                    var lastVisible = docs[docs.length - 1];
                    // set the reference for the next records.
                    var next = fRef.startAfter(lastVisible);
                    state._sync.fetched[identifier].nextFetchRef = next;
                }).catch(function (error$1) {
                    return reject(error(error$1));
                });
            });
        },
        fetchAndAdd: function (_a, pathVariables
        // where: [['archived', '==', true]]
        // orderBy: ['done_date', 'desc']
        ) {
            var _this = this;
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            if (pathVariables === void 0) { pathVariables = { where: [], whereFilters: [], orderBy: [] }; }
            if (pathVariables && isWhat.isPlainObject(pathVariables)) {
                commit('SET_PATHVARS', pathVariables);
            }
            // 'doc' mode:
            if (!getters.collectionMode) {
                dispatch('setUserId');
                if (state._conf.logging) {
                    console.log("%c fetch for Firestore PATH: " + getters.firestorePathComplete + " [" + state._conf.firestorePath + "]", 'color: lightcoral');
                }
                return getters.dbRef.get().then(function (_doc) { return __awaiter(_this, void 0, void 0, function () {
                    var id, doc;
                    return __generator(this, function (_a) {
                        switch (_a.label) {
                            case 0:
                                if (!!_doc.exists) return [3 /*break*/, 2];
                                // No initial doc found in docMode
                                if (state._conf.sync.preventInitialDocInsertion)
                                    throw 'preventInitialDocInsertion';
                                if (state._conf.logging)
                                    console.log('[vuex-easy-firestore] inserting initial doc');
                                return [4 /*yield*/, dispatch('insertInitialDoc')];
                            case 1:
                                _a.sent();
                                return [2 /*return*/, _doc];
                            case 2:
                                id = getters.docModeId;
                                doc = getters.cleanUpRetrievedDoc(_doc.data(), id);
                                dispatch('applyHooksAndUpdateState', { change: 'modified', id: id, doc: doc });
                                return [2 /*return*/, doc];
                        }
                    });
                }); }).catch(function (error$1) {
                    return error(error$1);
                });
            }
            // 'collection' mode:
            return dispatch('fetch', pathVariables)
                .then(function (querySnapshot) {
                if (querySnapshot.done === true)
                    return querySnapshot;
                if (isWhat.isFunction(querySnapshot.forEach)) {
                    querySnapshot.forEach(function (_doc) {
                        var id = _doc.id;
                        var doc = getters.cleanUpRetrievedDoc(_doc.data(), id);
                        dispatch('applyHooksAndUpdateState', { change: 'added', id: id, doc: doc });
                    });
                }
                return querySnapshot;
            });
        },
        fetchById: function (_a, id) {
            var dispatch = _a.dispatch, getters = _a.getters, state = _a.state;
            return __awaiter(this, void 0, void 0, function () {
                var ref, _doc, doc, e_1;
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0:
                            _b.trys.push([0, 2, , 3]);
                            if (!id)
                                throw 'missing-id';
                            if (!getters.collectionMode)
                                throw 'only-in-collection-mode';
                            ref = getters.dbRef;
                            return [4 /*yield*/, ref.doc(id).get()];
                        case 1:
                            _doc = _b.sent();
                            if (!_doc.exists) {
                                if (state._conf.logging) {
                                    throw "Doc with id \"" + id + "\" not found!";
                                }
                            }
                            doc = getters.cleanUpRetrievedDoc(_doc.data(), id);
                            dispatch('applyHooksAndUpdateState', { change: 'added', id: id, doc: doc });
                            return [2 /*return*/, doc];
                        case 2:
                            e_1 = _b.sent();
                            return [2 /*return*/, error(e_1)];
                        case 3: return [2 /*return*/];
                    }
                });
            });
        },
        applyHooksAndUpdateState: function (// this is only on server retrievals
        _a, _b) {
            var getters = _a.getters, state = _a.state, commit = _a.commit, dispatch = _a.dispatch;
            var change = _b.change, id = _b.id, _c = _b.doc, doc = _c === void 0 ? {} : _c;
            var store = this;
            // define storeUpdateFn()
            function storeUpdateFn(_doc) {
                switch (change) {
                    case 'added':
                        commit('INSERT_DOC', _doc);
                        break;
                    case 'removed':
                        commit('DELETE_DOC', id);
                        break;
                    default:
                        dispatch('deleteMissingProps', _doc);
                        commit('PATCH_DOC', _doc);
                        break;
                }
            }
            // get user set sync hook function
            var syncHookFn = state._conf.serverChange[change + 'Hook'];
            if (isWhat.isFunction(syncHookFn)) {
                syncHookFn(storeUpdateFn, doc, id, store, 'server', change);
            }
            else {
                storeUpdateFn(doc);
            }
        },
        deleteMissingProps: function (_a, doc) {
            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
            );
            Object.keys(compareInfo.presentIn).forEach(function (prop) {
                // don't worry about props not in fillables
                if (getters.fillables.length && !getters.fillables.includes(prop)) {
                    return;
                }
                // don't worry about props in guard
                if (getters.guard.includes(prop))
                    return;
                // don't worry about props starting with _sync or _conf
                if (prop.split('.')[0] === '_sync' || prop.split('.')[0] === '_conf')
                    return;
                // where is the prop present?
                var presence = compareInfo.presentIn[prop];
                var propNotInDoc = (!presence.includes(0));
                var propNotInDefaultValues = (!presence.includes(1));
                // delete props that are not present in the doc and default values
                if (propNotInDoc && propNotInDefaultValues) {
                    var path = (getters.collectionMode)
                        ? doc.id + "." + prop
                        : prop;
                    return commit('DELETE_PROP', path);
                }
            });
        },
        openDBChannel: function (_a, pathVariables) {
            var _this = this;
            var getters = _a.getters, state = _a.state, commit = _a.commit, dispatch = _a.dispatch;
            dispatch('setUserId');
            // `first` makes sure that local changes made during offline are reflected as server changes which the app is refreshed during offline mode
            var first = true;
            // set state for pathVariables
            if (pathVariables && isWhat.isPlainObject(pathVariables)) {
                commit('SET_SYNCFILTERS', pathVariables);
                delete pathVariables.where;
                delete pathVariables.orderBy;
                commit('SET_PATHVARS', pathVariables);
            }
            var identifier = createFetchIdentifier({
                where: state._conf.sync.where,
                orderBy: state._conf.sync.orderBy,
                pathVariables: state._sync.pathVariables
            });
            if (isWhat.isFunction(state._sync.unsubscribe[identifier])) {
                var channelAlreadyOpenError_1 = "openDBChannel was already called for these filters and pathvariables. Identifier: " + identifier;
                if (state._conf.logging) {
                    console.log(channelAlreadyOpenError_1);
                }
                return new Promise(function (resolve, reject) { reject(channelAlreadyOpenError_1); });
            }
            // getters.dbRef should already have pathVariables swapped out
            var dbRef = getters.dbRef;
            // apply where filters and orderBy
            if (getters.collectionMode) {
                getters.getWhereArrays().forEach(function (whereParams) {
                    dbRef = dbRef.where.apply(dbRef, whereParams);
                });
                if (state._conf.sync.orderBy.length) {
                    dbRef = dbRef.orderBy.apply(dbRef, state._conf.sync.orderBy);
                }
            }
            // make a promise
            return new Promise(function (resolve, reject) {
                // log
                if (state._conf.logging) {
                    console.log("%c openDBChannel for Firestore PATH: " + getters.firestorePathComplete + " [" + state._conf.firestorePath + "]", 'color: lightcoral');
                }
                var unsubscribe = dbRef.onSnapshot(function (querySnapshot) { return __awaiter(_this, void 0, void 0, function () {
                    var source, id, doc;
                    return __generator(this, function (_a) {
                        switch (_a.label) {
                            case 0:
                                source = querySnapshot.metadata.hasPendingWrites ? 'local' : 'server';
                                if (!!getters.collectionMode) return [3 /*break*/, 3];
                                if (!!querySnapshot.data()) return [3 /*break*/, 2];
                                // No initial doc found in docMode
                                if (state._conf.sync.preventInitialDocInsertion)
                                    return [2 /*return*/, reject('preventInitialDocInsertion')];
                                if (state._conf.logging)
                                    console.log('[vuex-easy-firestore] inserting initial doc');
                                return [4 /*yield*/, dispatch('insertInitialDoc')];
                            case 1:
                                _a.sent();
                                return [2 /*return*/, resolve()];
                            case 2:
                                if (source === 'local' && !first)
                                    return [2 /*return*/, resolve()];
                                id = getters.docModeId;
                                doc = getters.cleanUpRetrievedDoc(querySnapshot.data(), id);
                                dispatch('applyHooksAndUpdateState', { change: 'modified', id: id, doc: doc });
                                first = false;
                                return [2 /*return*/, resolve()];
                            case 3:
                                // 'collection' mode:
                                querySnapshot.docChanges().forEach(function (change) {
                                    var changeType = change.type;
                                    // Don't do anything for local modifications & removals
                                    if (source === 'local' && !first)
                                        return resolve();
                                    var id = change.doc.id;
                                    var doc = getters.cleanUpRetrievedDoc(change.doc.data(), id);
                                    dispatch('applyHooksAndUpdateState', { change: changeType, id: id, doc: doc });
                                });
                                first = false;
                                return [2 /*return*/, resolve()];
                        }
                    });
                }); }, function (error$1) {
                    state._sync.patching = 'error';
                    return reject(error(error$1));
                });
                state._sync.unsubscribe[identifier] = unsubscribe;
            });
        },
        closeDBChannel: function (_a, _b) {
            var getters = _a.getters, state = _a.state, commit = _a.commit, dispatch = _a.dispatch;
            var _c = (_b === void 0 ? { clearModule: false } : _b).clearModule, clearModule = _c === void 0 ? false : _c;
            var identifier = createFetchIdentifier({
                where: state._conf.sync.where,
                orderBy: state._conf.sync.orderBy,
                pathVariables: state._sync.pathVariables
            });
            var unsubscribeDBChannel = state._sync.unsubscribe[identifier];
            if (isWhat.isFunction(unsubscribeDBChannel)) {
                unsubscribeDBChannel();
                state._sync.unsubscribe[identifier] = null;
            }
            if (clearModule) {
                commit('RESET_VUEX_EASY_FIRESTORE_STATE');
            }
        },
        set: function (_a, doc) {
            var commit = _a.commit, dispatch = _a.dispatch, getters = _a.getters, state = _a.state;
            if (!doc)
                return;
            if (!getters.collectionMode) {
                return dispatch('patch', doc);
            }
            var id = getId(doc);
            if (!id ||
                (!state._conf.statePropName && !state[id]) ||
                (state._conf.statePropName && !state[state._conf.statePropName][id])) {
                return dispatch('insert', doc);
            }
            return dispatch('patch', doc);
        },
        insert: function (_a, doc) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var store = this;
            // check payload
            if (!doc)
                return;
            // check userId
            dispatch('setUserId');
            var newDoc = doc;
            if (!newDoc.id)
                newDoc.id = getters.dbRef.doc().id;
            // apply default values
            var newDocWithDefaults = setDefaultValues(newDoc, state._conf.sync.defaultValues);
            // define the store update
            function storeUpdateFn(_doc) {
                commit('INSERT_DOC', _doc);
                return dispatch('insertDoc', _doc);
            }
            // check for hooks
            if (state._conf.sync.insertHook) {
                state._conf.sync.insertHook(storeUpdateFn, newDocWithDefaults, store);
                return newDocWithDefaults.id;
            }
            storeUpdateFn(newDocWithDefaults);
            return newDocWithDefaults.id;
        },
        insertBatch: function (_a, docs) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var store = this;
            // check payload
            if (!isWhat.isArray(docs) || !docs.length)
                return [];
            // check userId
            dispatch('setUserId');
            var newDocs = docs.reduce(function (carry, _doc) {
                var newDoc = getValueFromPayloadPiece(_doc);
                if (!newDoc.id)
                    newDoc.id = getters.dbRef.doc().id;
                carry.push(newDoc);
                return carry;
            }, []);
            // define the store update
            function storeUpdateFn(_docs) {
                _docs.forEach(function (_doc) {
                    commit('INSERT_DOC', _doc);
                });
                return dispatch('insertDoc', _docs);
            }
            // check for hooks
            if (state._conf.sync.insertBatchHook) {
                state._conf.sync.insertBatchHook(storeUpdateFn, newDocs, store);
                return newDocs.map(function (_doc) { return _doc.id; });
            }
            storeUpdateFn(newDocs);
            return newDocs.map(function (_doc) { return _doc.id; });
        },
        patch: function (_a, doc) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var store = this;
            // check payload
            if (!doc)
                return;
            var id = (getters.collectionMode) ? getId(doc) : getters.docModeId;
            var value = (getters.collectionMode) ? getValueFromPayloadPiece(doc) : doc;
            if (!id && getters.collectionMode)
                return error('patch-missing-id');
            // check userId
            dispatch('setUserId');
            // add id to value
            if (!value.id)
                value.id = id;
            // define the store update
            function storeUpdateFn(_val) {
                commit('PATCH_DOC', _val);
                return dispatch('patchDoc', { id: id, doc: copy(_val) });
            }
            // check for hooks
            if (state._conf.sync.patchHook) {
                state._conf.sync.patchHook(storeUpdateFn, value, store);
                return id;
            }
            storeUpdateFn(value);
            return id;
        },
        patchBatch: function (_a, _b) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var doc = _b.doc, _c = _b.ids, ids = _c === void 0 ? [] : _c;
            var store = this;
            // check payload
            if (!doc)
                return [];
            if (!isWhat.isArray(ids) || !ids.length)
                return [];
            // check userId
            dispatch('setUserId');
            // define the store update
            function storeUpdateFn(_doc, _ids) {
                _ids.forEach(function (_id) {
                    commit('PATCH_DOC', __assign({ id: _id }, _doc));
                });
                return dispatch('patchDoc', { ids: _ids, doc: _doc });
            }
            // check for hooks
            if (state._conf.sync.patchBatchHook) {
                state._conf.sync.patchBatchHook(storeUpdateFn, doc, ids, store);
                return ids;
            }
            storeUpdateFn(doc, ids);
            return ids;
        },
        delete: function (_a, id) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var store = this;
            // check payload
            if (!id)
                return;
            // check userId
            dispatch('setUserId');
            function storeUpdateFn(_id) {
                // id is a path
                var pathDelete = (_id.includes('.') || !getters.collectionMode);
                if (pathDelete) {
                    var path = _id;
                    if (!path)
                        return error('delete-missing-path');
                    commit('DELETE_PROP', path);
                    return dispatch('deleteProp', path);
                }
                if (!_id)
                    return error('delete-missing-id');
                commit('DELETE_DOC', _id);
                return dispatch('deleteDoc', _id);
            }
            // check for hooks
            if (state._conf.sync.deleteHook) {
                state._conf.sync.deleteHook(storeUpdateFn, id, store);
                return id;
            }
            storeUpdateFn(id);
            return id;
        },
        deleteBatch: function (_a, ids) {
            var state = _a.state, getters = _a.getters, commit = _a.commit, dispatch = _a.dispatch;
            var store = this;
            // check payload
            if (!isWhat.isArray(ids) || !ids.length)
                return [];
            // check userId
            dispatch('setUserId');
            // define the store update
            function storeUpdateFn(_ids) {
                _ids.forEach(function (_id) {
                    // id is a path
                    var pathDelete = (_id.includes('.') || !getters.collectionMode);
                    if (pathDelete) {
                        var path = _id;
                        if (!path)
                            return error('delete-missing-path');
                        commit('DELETE_PROP', path);
                        return dispatch('deleteProp', path);
                    }
                    if (!_id)
                        return error('delete-missing-id');
                    commit('DELETE_DOC', _id);
                    return dispatch('deleteDoc', _id);
                });
            }
            // check for hooks
            if (state._conf.sync.deleteBatchHook) {
                state._conf.sync.deleteBatchHook(storeUpdateFn, ids, store);
                return ids;
            }
            storeUpdateFn(ids);
            return ids;
        },
        _stopPatching: function (_a) {
            var state = _a.state, commit = _a.commit;
            if (state._sync.stopPatchingTimeout) {
                clearTimeout(state._sync.stopPatchingTimeout);
            }
            state._sync.stopPatchingTimeout = setTimeout(function (_) { state._sync.patching = false; }, 300);
        },
        _startPatching: function (_a) {
            var state = _a.state, commit = _a.commit;
            if (state._sync.stopPatchingTimeout) {
                clearTimeout(state._sync.stopPatchingTimeout);
            }
            state._sync.patching = true;
        }
    };
}
function pluginActions ( Firebase ) { var _this = this ; return { setUserId : function ( _a , userId ) { var commit = _a . commit , getters = _a . getters ; if ( userId === undefined ) userId = null ; // undefined cannot be synced to firestore if ( ! userId && Firebase . auth ( ) . currentUser ) { userId = Firebase . auth ( ) . currentUser . uid ; } commit ( 'SET_USER_ID' , userId ) ; if ( getters . firestorePathComplete . includes ( '{userId}' ) ) return error ( 'user-auth' ) ; } , clearUser : function ( _a ) { var commit = _a . commit ; commit ( 'CLEAR_USER' ) ; } , setPathVars : function ( _a , pathVars ) { var commit = _a . commit ; commit ( 'SET_PATHVARS' , pathVars ) ; } , duplicate : function ( _a , id ) { var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; return __awaiter ( _this , void 0 , void 0 , function ( ) { var _b , doc , dId , idMap ; return __generator ( this , function ( _c ) { switch ( _c . label ) { case 0 : if ( ! getters . collectionMode ) return [ 2 /*return*/ , error ( 'only-in-collection-mode' ) ] ; if ( ! id ) return [ 2 /*return*/ , { } ] ; doc = merge ( getters . storeRef [ id ] , { id : null } ) ; return [ 4 /*yield*/ , dispatch ( 'insert' , doc ) ] ; case 1 : dId = _c . sent ( ) ; idMap = ( _b = { } , _b [ id ] = dId , _b ) ; return [ 2 /*return*/ , idMap ] ; } } ) ; } ) ; } , duplicateBatch : function ( _a , ids ) { var _this = this ; var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; if ( ids === void 0 ) { ids = [ ] ; } if ( ! getters . collectionMode ) return error ( 'only-in-collection-mode' ) ; if ( ! isWhat . isArray ( ids ) || ! ids . length ) return { } ; var idsMap = ids . reduce ( function ( carry , id ) { return __awaiter ( _this , void 0 , void 0 , function ( ) { var idMap ; return __generator ( this , function ( _a ) { switch ( _a . label ) { case 0 : return [ 4 /*yield*/ , dispatch ( 'duplicate' , id ) ] ; case 1 : idMap = _a . sent ( ) ; return [ 4 /*yield*/ , carry ] ; case 2 : carry = _a . sent ( ) ; return [ 2 /*return*/ , Object . assign ( carry , idMap ) ] ; } } ) ; } ) ; } , { } ) ; return idsMap ; } , patchDoc : function ( _a , _b ) { var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; var _c = _b === void 0 ? { ids : [ ] , doc : { } } : _b , _d = _c . id , id = _d === void 0 ? '' : _d , _e = _c . ids , ids = _e === void 0 ? [ ] : _e , doc = _c . doc ; // 0. payload correction (only arrays) if ( ! isWhat . isArray ( ids ) ) return error ( "`ids` prop passed to 'patch' needs to be an array" ) ; if ( id ) ids . push ( id ) ; // EXTRA: check if doc is being inserted if so state . _sync . syncStack . inserts . forEach ( function ( newDoc , newDocIndex ) { // get the index of the id that is also in the insert stack var indexIdInInsert = ids . indexOf ( newDoc . id ) ; if ( indexIdInInsert === - 1 ) return ; // the doc trying to be synced is also in insert // prepare the doc as new doc: var patchDoc = getters . prepareForInsert ( [ doc ] ) [ 0 ] ; // replace insert sync stack with merged item: state . _sync . syncStack . inserts [ newDocIndex ] = merge ( newDoc , patchDoc ) ; // empty out the id that was to be patched: ids . splice ( indexIdInInsert , 1 ) ; } ) ; // 1. Prepare for patching var syncStackItems = getters . prepareForPatch ( ids , doc ) ; // 2. Push to syncStack Object . keys ( syncStackItems ) . forEach ( function ( id ) { var newVal ; if ( ! state . _sync . syncStack . updates [ id ] ) { // replace arrayUnion and arrayRemove newVal = findAndReplaceAnything . findAndReplaceIf ( syncStackItems [ id ] , function ( foundVal ) { if ( isArrayHelper ( foundVal ) ) { return foundVal . getFirestoreFieldValue ( ) ; } if ( isIncrementHelper ( foundVal ) ) { return foundVal . getFirestoreFieldValue ( ) ; } return foundVal ; } ) ; } else { newVal = merge ( { extensions : [ function ( originVal , newVal ) { if ( originVal instanceof Firebase . firestore . FieldValue && isArrayHelper ( newVal ) ) { originVal . _elements = originVal . _elements . concat ( newVal . payload ) ; newVal = originVal ; } if ( originVal instanceof Firebase . firestore . FieldValue && isIncrementHelper ( newVal ) ) { originVal . _operand = originVal . _operand + newVal . payload ; newVal = originVal ; } return newVal ; // always return newVal as fallback!! } ] } , state . _sync . syncStack . updates [ id ] , syncStackItems [ id ] ) ; } state . _sync . syncStack . updates [ id ] = newVal ; } ) ; // 3. Create or refresh debounce return dispatch ( 'handleSyncStackDebounce' ) ; } , deleteDoc : function ( _a , ids ) { var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; if ( ids === void 0 ) { ids = [ ] ; } // 0. payload correction (only arrays) if ( ! isWhat . isArray ( ids ) ) ids = [ ids ] ; // 1. Prepare for patching // 2. Push to syncStack var deletions = state . _sync . syncStack . deletions . concat ( ids ) ; state . _sync . syncStack . deletions = deletions ; if ( ! state . _sync . syncStack . deletions . length ) return ; // 3. Create or refresh debounce return dispatch ( 'handleSyncStackDebounce' ) ; } , deleteProp : function ( _a , path ) { var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; // 1. Prepare for patching var syncStackItem = getters . prepareForPropDeletion ( path ) ; // 2. Push to syncStack Object . keys ( syncStackItem ) . forEach ( function ( id ) { var newVal = ( ! state . _sync . syncStack . propDeletions [ id ] ) ? syncStackItem [ id ] : merge ( state . _sync . syncStack . propDeletions [ id ] , syncStackItem [ id ] ) ; state . _sync . syncStack . propDeletions [ id ] = newVal ; } ) ; // 3. Create or refresh debounce return dispatch ( 'handleSyncStackDebounce' ) ; } , insertDoc : function ( _a , docs ) { var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; if ( docs === void 0 ) { docs = [ ] ; } // 0. payload correction (only arrays) if ( ! isWhat . isArray ( docs ) ) docs = [ docs ] ; // 1. Prepare for patching var syncStack = getters . prepareForInsert ( docs ) ; // 2. Push to syncStack var inserts = state . _sync . syncStack . inserts . concat ( syncStack ) ; state . _sync . syncStack . inserts = inserts ; // 3. Create or refresh debounce dispatch ( 'handleSyncStackDebounce' ) ; return docs . map ( function ( d ) { return d . id ; } ) ; } , insertInitialDoc : function ( _a ) { var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; // 0. only docMode if ( getters . collectionMode ) return ; // 1. Prepare for insert var initialDoc = ( getters . storeRef ) ? getters . storeRef : { } ; var initialDocPrepared = getters . prepareInitialDocForInsert ( initialDoc ) ; // 2. Create a reference to the SF doc. var initialDocRef = getters . dbRef ; return Firebase . firestore ( ) . runTransaction ( function ( transaction ) { // This code may get re-run multiple times if there are conflicts. return transaction . get ( initialDocRef ) . then ( function ( foundInitialDoc ) { if ( ! foundInitialDoc . exists ) { transaction . set ( initialDocRef , initialDocPrepared ) ; } } ) ; } ) . then ( function ( _ ) { if ( state . _conf . logging ) { console . log ( '[vuex-easy-firestore] Initial doc succesfully inserted.' ) ; } } ) . catch ( function ( error$1 ) { return error ( 'initial-doc-failed' , error$1 ) ; } ) ; } , handleSyncStackDebounce : function ( _a ) { var state = _a . state , commit = _a . commit , dispatch = _a . dispatch , getters = _a . getters ; if ( ! getters . signedIn ) return false ; if ( ! state . _sync . syncStack . debounceTimer ) { var ms = state . _conf . sync . debounceTimerMs ; var debounceTimer = startDebounce ( ms ) ; debounceTimer . done . then ( function ( _ ) { return dispatch ( 'batchSync' ) ; } ) ; state . _sync . syncStack . debounceTimer = debounceTimer ; } state . _sync . syncStack . debounceTimer . refresh ( ) ; } , batchSync : function ( _a ) { var getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch , state = _a . state ; var batch = makeBatchFromSyncstack ( state , getters , Firebase ) ; dispatch ( '_startPatching' ) ; state . _sync . syncStack . debounceTimer = null ; return new Promise ( function ( resolve , reject ) { batch . commit ( ) . then ( function ( _ ) { var remainingSyncStack = Object . keys ( state . _sync . syncStack . updates ) . length + state . _sync . syncStack . deletions . length + state . _sync . syncStack . inserts . length + state . _sync . syncStack . propDeletions . length ; if ( remainingSyncStack ) { dispatch ( 'batchSync' ) ; } dispatch ( '_stopPatching' ) ; return resolve ( ) ; } ) . catch ( function ( error$1 ) { state . _sync . patching = 'error' ; state . _sync . syncStack . debounceTimer = null ; return reject ( error$1 ) ; } ) ; } ) ; } , fetch : function ( _a , pathVariables // where: [['archived', '==', true]] // orderBy: ['done_date', 'desc'] ) { var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; if ( pathVariables === void 0 ) { pathVariables = { where : [ ] , whereFilters : [ ] , orderBy : [ ] } ; } dispatch ( 'setUserId' ) ; var where = pathVariables . where , whereFilters = pathVariables . whereFilters , orderBy = pathVariables . orderBy ; if ( ! isWhat . isArray ( where ) ) where = [ ] ; if ( ! isWhat . isArray ( orderBy ) ) orderBy = [ ] ; if ( isWhat . isArray ( whereFilters ) && whereFilters . length ) where = whereFilters ; // depreciated if ( pathVariables && isWhat . isPlainObject ( pathVariables ) ) { commit ( 'SET_PATHVARS' , pathVariables ) ; } return new Promise ( function ( resolve , reject ) { // log if ( state . _conf . logging ) { console . log ( "%c fetch for Firestore PATH: " + getters . firestorePathComplete + " [" + state . _conf . firestorePath + "]" , 'color: lightcoral' ) ; } if ( ! getters . signedIn ) return resolve ( ) ; var identifier = createFetchIdentifier ( { where : where , orderBy : orderBy } ) ; var fetched = state . _sync . fetched [ identifier ] ; // We've never fetched this before: if ( ! fetched ) { var ref_1 = getters . dbRef ; // apply where filters and orderBy getters . getWhereArrays ( where ) . forEach ( function ( paramsArr ) { ref_1 = ref_1 . where . apply ( ref_1 , paramsArr ) ; } ) ; if ( orderBy . length ) ref_1 = ref_1 . orderBy . apply ( ref_1 , orderBy ) ; state . _sync . fetched [ identifier ] = { ref : ref_1 , done : false , retrievedFetchRefs : [ ] , nextFetchRef : null } ; } var fRequest = state . _sync . fetched [ identifier ] ; // We're already done fetching everything: if ( fRequest . done ) { if ( state . _conf . logging ) console . log ( '[vuex-easy-firestore] done fetching' ) ; return resolve ( { done : true } ) ; } // attach fetch filters var fRef = state . _sync . fetched [ identifier ] . ref ; if ( fRequest . nextFetchRef ) { // get next ref if saved in state fRef = state . _sync . fetched [ identifier ] . nextFetchRef ; } // add doc limit var limit = ( isWhat . isNumber ( pathVariables . limit ) ) ? pathVariables . limit : state . _conf . fetch . docLimit ; if ( limit > 0 ) fRef = fRef . limit ( limit ) ; // Stop if all records already fetched if ( fRequest . retrievedFetchRefs . includes ( fRef ) ) { console . log ( '[vuex-easy-firestore] Already retrieved this part.' ) ; return resolve ( ) ; } // make fetch request fRef . get ( ) . then ( function ( querySnapshot ) { var docs = querySnapshot . docs ; if ( docs . length === 0 ) { state . _sync . fetched [ identifier ] . done = true ; querySnapshot . done = true ; return resolve ( querySnapshot ) ; } if ( docs . length < limit ) { state . _sync . fetched [ identifier ] . done = true ; } state . _sync . fetched [ identifier ] . retrievedFetchRefs . push ( fRef ) ; // Get the last visible document resolve ( querySnapshot ) ; var lastVisible = docs [ docs . length - 1 ] ; // set the reference for the next records. var next = fRef . startAfter ( lastVisible ) ; state . _sync . fetched [ identifier ] . nextFetchRef = next ; } ) . catch ( function ( error$1 ) { return reject ( error ( error$1 ) ) ; } ) ; } ) ; } , fetchAndAdd : function ( _a , pathVariables // where: [['archived', '==', true]] // orderBy: ['done_date', 'desc'] ) { var _this = this ; var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; if ( pathVariables === void 0 ) { pathVariables = { where : [ ] , whereFilters : [ ] , orderBy : [ ] } ; } if ( pathVariables && isWhat . isPlainObject ( pathVariables ) ) { commit ( 'SET_PATHVARS' , pathVariables ) ; } // 'doc' mode: if ( ! getters . collectionMode ) { dispatch ( 'setUserId' ) ; if ( state . _conf . logging ) { console . log ( "%c fetch for Firestore PATH: " + getters . firestorePathComplete + " [" + state . _conf . firestorePath + "]" , 'color: lightcoral' ) ; } return getters . dbRef . get ( ) . then ( function ( _doc ) { return __awaiter ( _this , void 0 , void 0 , function ( ) { var id , doc ; return __generator ( this , function ( _a ) { switch ( _a . label ) { case 0 : if ( ! ! _doc . exists ) return [ 3 /*break*/ , 2 ] ; // No initial doc found in docMode if ( state . _conf . sync . preventInitialDocInsertion ) throw 'preventInitialDocInsertion' ; if ( state . _conf . logging ) console . log ( '[vuex-easy-firestore] inserting initial doc' ) ; return [ 4 /*yield*/ , dispatch ( 'insertInitialDoc' ) ] ; case 1 : _a . sent ( ) ; return [ 2 /*return*/ , _doc ] ; case 2 : id = getters . docModeId ; doc = getters . cleanUpRetrievedDoc ( _doc . data ( ) , id ) ; dispatch ( 'applyHooksAndUpdateState' , { change : 'modified' , id : id , doc : doc } ) ; return [ 2 /*return*/ , doc ] ; } } ) ; } ) ; } ) . catch ( function ( error$1 ) { return error ( error$1 ) ; } ) ; } // 'collection' mode: return dispatch ( 'fetch' , pathVariables ) . then ( function ( querySnapshot ) { if ( querySnapshot . done === true ) return querySnapshot ; if ( isWhat . isFunction ( querySnapshot . forEach ) ) { querySnapshot . forEach ( function ( _doc ) { var id = _doc . id ; var doc = getters . cleanUpRetrievedDoc ( _doc . data ( ) , id ) ; dispatch ( 'applyHooksAndUpdateState' , { change : 'added' , id : id , doc : doc } ) ; } ) ; } return querySnapshot ; } ) ; } , fetchById : function ( _a , id ) { var dispatch = _a . dispatch , getters = _a . getters , state = _a . state ; return __awaiter ( this , void 0 , void 0 , function ( ) { var ref , _doc , doc , e_1 ; return __generator ( this , function ( _b ) { switch ( _b . label ) { case 0 : _b . trys . push ( [ 0 , 2 , , 3 ] ) ; if ( ! id ) throw 'missing-id' ; if ( ! getters . collectionMode ) throw 'only-in-collection-mode' ; ref = getters . dbRef ; return [ 4 /*yield*/ , ref . doc ( id ) . get ( ) ] ; case 1 : _doc = _b . sent ( ) ; if ( ! _doc . exists ) { if ( state . _conf . logging ) { throw "Doc with id \"" + id + "\" not found!" ; } } doc = getters . cleanUpRetrievedDoc ( _doc . data ( ) , id ) ; dispatch ( 'applyHooksAndUpdateState' , { change : 'added' , id : id , doc : doc } ) ; return [ 2 /*return*/ , doc ] ; case 2 : e_1 = _b . sent ( ) ; return [ 2 /*return*/ , error ( e_1 ) ] ; case 3 : return [ 2 /*return*/ ] ; } } ) ; } ) ; } , applyHooksAndUpdateState : function ( // this is only on server retrievals _a , _b ) { var getters = _a . getters , state = _a . state , commit = _a . commit , dispatch = _a . dispatch ; var change = _b . change , id = _b . id , _c = _b . doc , doc = _c === void 0 ? { } : _c ; var store = this ; // define storeUpdateFn() function storeUpdateFn ( _doc ) { switch ( change ) { case 'added' : commit ( 'INSERT_DOC' , _doc ) ; break ; case 'removed' : commit ( 'DELETE_DOC' , id ) ; break ; default : dispatch ( 'deleteMissingProps' , _doc ) ; commit ( 'PATCH_DOC' , _doc ) ; break ; } } // get user set sync hook function var syncHookFn = state . _conf . serverChange [ change + 'Hook' ] ; if ( isWhat . isFunction ( syncHookFn ) ) { syncHookFn ( storeUpdateFn , doc , id , store , 'server' , change ) ; } else { storeUpdateFn ( doc ) ; } } , deleteMissingProps : function ( _a , doc ) { 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 ) ; Object . keys ( compareInfo . presentIn ) . forEach ( function ( prop ) { // don't worry about props not in fillables if ( getters . fillables . length && ! getters . fillables . includes ( prop ) ) { return ; } // don't worry about props in guard if ( getters . guard . includes ( prop ) ) return ; // don't worry about props starting with _sync or _conf if ( prop . split ( '.' ) [ 0 ] === '_sync' || prop . split ( '.' ) [ 0 ] === '_conf' ) return ; // where is the prop present? var presence = compareInfo . presentIn [ prop ] ; var propNotInDoc = ( ! presence . includes ( 0 ) ) ; var propNotInDefaultValues = ( ! presence . includes ( 1 ) ) ; // delete props that are not present in the doc and default values if ( propNotInDoc && propNotInDefaultValues ) { var path = ( getters . collectionMode ) ? doc . id + "." + prop : prop ; return commit ( 'DELETE_PROP' , path ) ; } } ) ; } , openDBChannel : function ( _a , pathVariables ) { var _this = this ; var getters = _a . getters , state = _a . state , commit = _a . commit , dispatch = _a . dispatch ; dispatch ( 'setUserId' ) ; // `first` makes sure that local changes made during offline are reflected as server changes which the app is refreshed during offline mode var first = true ; // set state for pathVariables if ( pathVariables && isWhat . isPlainObject ( pathVariables ) ) { commit ( 'SET_SYNCFILTERS' , pathVariables ) ; delete pathVariables . where ; delete pathVariables . orderBy ; commit ( 'SET_PATHVARS' , pathVariables ) ; } var identifier = createFetchIdentifier ( { where : state . _conf . sync . where , orderBy : state . _conf . sync . orderBy , pathVariables : state . _sync . pathVariables } ) ; if ( isWhat . isFunction ( state . _sync . unsubscribe [ identifier ] ) ) { var channelAlreadyOpenError_1 = "openDBChannel was already called for these filters and pathvariables. Identifier: " + identifier ; if ( state . _conf . logging ) { console . log ( channelAlreadyOpenError_1 ) ; } return new Promise ( function ( resolve , reject ) { reject ( channelAlreadyOpenError_1 ) ; } ) ; } // getters.dbRef should already have pathVariables swapped out var dbRef = getters . dbRef ; // apply where filters and orderBy if ( getters . collectionMode ) { getters . getWhereArrays ( ) . forEach ( function ( whereParams ) { dbRef = dbRef . where . apply ( dbRef , whereParams ) ; } ) ; if ( state . _conf . sync . orderBy . length ) { dbRef = dbRef . orderBy . apply ( dbRef , state . _conf . sync . orderBy ) ; } } // make a promise return new Promise ( function ( resolve , reject ) { // log if ( state . _conf . logging ) { console . log ( "%c openDBChannel for Firestore PATH: " + getters . firestorePathComplete + " [" + state . _conf . firestorePath + "]" , 'color: lightcoral' ) ; } var unsubscribe = dbRef . onSnapshot ( function ( querySnapshot ) { return __awaiter ( _this , void 0 , void 0 , function ( ) { var source , id , doc ; return __generator ( this , function ( _a ) { switch ( _a . label ) { case 0 : source = querySnapshot . metadata . hasPendingWrites ? 'local' : 'server' ; if ( ! ! getters . collectionMode ) return [ 3 /*break*/ , 3 ] ; if ( ! ! querySnapshot . data ( ) ) return [ 3 /*break*/ , 2 ] ; // No initial doc found in docMode if ( state . _conf . sync . preventInitialDocInsertion ) return [ 2 /*return*/ , reject ( 'preventInitialDocInsertion' ) ] ; if ( state . _conf . logging ) console . log ( '[vuex-easy-firestore] inserting initial doc' ) ; return [ 4 /*yield*/ , dispatch ( 'insertInitialDoc' ) ] ; case 1 : _a . sent ( ) ; return [ 2 /*return*/ , resolve ( ) ] ; case 2 : if ( source === 'local' && ! first ) return [ 2 /*return*/ , resolve ( ) ] ; id = getters . docModeId ; doc = getters . cleanUpRetrievedDoc ( querySnapshot . data ( ) , id ) ; dispatch ( 'applyHooksAndUpdateState' , { change : 'modified' , id : id , doc : doc } ) ; first = false ; return [ 2 /*return*/ , resolve ( ) ] ; case 3 : // 'collection' mode: querySnapshot . docChanges ( ) . forEach ( function ( change ) { var changeType = change . type ; // Don't do anything for local modifications & removals if ( source === 'local' && ! first ) return resolve ( ) ; var id = change . doc . id ; var doc = getters . cleanUpRetrievedDoc ( change . doc . data ( ) , id ) ; dispatch ( 'applyHooksAndUpdateState' , { change : changeType , id : id , doc : doc } ) ; } ) ; first = false ; return [ 2 /*return*/ , resolve ( ) ] ; } } ) ; } ) ; } , function ( error$1 ) { state . _sync . patching = 'error' ; return reject ( error ( error$1 ) ) ; } ) ; state . _sync . unsubscribe [ identifier ] = unsubscribe ; } ) ; } , closeDBChannel : function ( _a , _b ) { var getters = _a . getters , state = _a . state , commit = _a . commit , dispatch = _a . dispatch ; var _c = ( _b === void 0 ? { clearModule : false } : _b ) . clearModule , clearModule = _c === void 0 ? false : _c ; var identifier = createFetchIdentifier ( { where : state . _conf . sync . where , orderBy : state . _conf . sync . orderBy , pathVariables : state . _sync . pathVariables } ) ; var unsubscribeDBChannel = state . _sync . unsubscribe [ identifier ] ; if ( isWhat . isFunction ( unsubscribeDBChannel ) ) { unsubscribeDBChannel ( ) ; state . _sync . unsubscribe [ identifier ] = null ; } if ( clearModule ) { commit ( 'RESET_VUEX_EASY_FIRESTORE_STATE' ) ; } } , set : function ( _a , doc ) { var commit = _a . commit , dispatch = _a . dispatch , getters = _a . getters , state = _a . state ; if ( ! doc ) return ; if ( ! getters . collectionMode ) { return dispatch ( 'patch' , doc ) ; } var id = getId ( doc ) ; if ( ! id || ( ! state . _conf . statePropName && ! state [ id ] ) || ( state . _conf . statePropName && ! state [ state . _conf . statePropName ] [ id ] ) ) { return dispatch ( 'insert' , doc ) ; } return dispatch ( 'patch' , doc ) ; } , insert : function ( _a , doc ) { var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; var store = this ; // check payload if ( ! doc ) return ; // check userId dispatch ( 'setUserId' ) ; var newDoc = doc ; if ( ! newDoc . id ) newDoc . id = getters . dbRef . doc ( ) . id ; // apply default values var newDocWithDefaults = setDefaultValues ( newDoc , state . _conf . sync . defaultValues ) ; // define the store update function storeUpdateFn ( _doc ) { commit ( 'INSERT_DOC' , _doc ) ; return dispatch ( 'insertDoc' , _doc ) ; } // check for hooks if ( state . _conf . sync . insertHook ) { state . _conf . sync . insertHook ( storeUpdateFn , newDocWithDefaults , store ) ; return newDocWithDefaults . id ; } storeUpdateFn ( newDocWithDefaults ) ; return newDocWithDefaults . id ; } , insertBatch : function ( _a , docs ) { var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; var store = this ; // check payload if ( ! isWhat . isArray ( docs ) || ! docs . length ) return [ ] ; // check userId dispatch ( 'setUserId' ) ; var newDocs = docs . reduce ( function ( carry , _doc ) { var newDoc = getValueFromPayloadPiece ( _doc ) ; if ( ! newDoc . id ) newDoc . id = getters . dbRef . doc ( ) . id ; carry . push ( newDoc ) ; return carry ; } , [ ] ) ; // define the store update function storeUpdateFn ( _docs ) { _docs . forEach ( function ( _doc ) { commit ( 'INSERT_DOC' , _doc ) ; } ) ; return dispatch ( 'insertDoc' , _docs ) ; } // check for hooks if ( state . _conf . sync . insertBatchHook ) { state . _conf . sync . insertBatchHook ( storeUpdateFn , newDocs , store ) ; return newDocs . map ( function ( _doc ) { return _doc . id ; } ) ; } storeUpdateFn ( newDocs ) ; return newDocs . map ( function ( _doc ) { return _doc . id ; } ) ; } , patch : function ( _a , doc ) { var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; var store = this ; // check payload if ( ! doc ) return ; var id = ( getters . collectionMode ) ? getId ( doc ) : getters . docModeId ; var value = ( getters . collectionMode ) ? getValueFromPayloadPiece ( doc ) : doc ; if ( ! id && getters . collectionMode ) return error ( 'patch-missing-id' ) ; // check userId dispatch ( 'setUserId' ) ; // add id to value if ( ! value . id ) value . id = id ; // define the store update function storeUpdateFn ( _val ) { commit ( 'PATCH_DOC' , _val ) ; return dispatch ( 'patchDoc' , { id : id , doc : copy ( _val ) } ) ; } // check for hooks if ( state . _conf . sync . patchHook ) { state . _conf . sync . patchHook ( storeUpdateFn , value , store ) ; return id ; } storeUpdateFn ( value ) ; return id ; } , patchBatch : function ( _a , _b ) { var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; var doc = _b . doc , _c = _b . ids , ids = _c === void 0 ? [ ] : _c ; var store = this ; // check payload if ( ! doc ) return [ ] ; if ( ! isWhat . isArray ( ids ) || ! ids . length ) return [ ] ; // check userId dispatch ( 'setUserId' ) ; // define the store update function storeUpdateFn ( _doc , _ids ) { _ids . forEach ( function ( _id ) { commit ( 'PATCH_DOC' , __assign ( { id : _id } , _doc ) ) ; } ) ; return dispatch ( 'patchDoc' , { ids : _ids , doc : _doc } ) ; } // check for hooks if ( state . _conf . sync . patchBatchHook ) { state . _conf . sync . patchBatchHook ( storeUpdateFn , doc , ids , store ) ; return ids ; } storeUpdateFn ( doc , ids ) ; return ids ; } , delete : function ( _a , id ) { var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; var store = this ; // check payload if ( ! id ) return ; // check userId dispatch ( 'setUserId' ) ; function storeUpdateFn ( _id ) { // id is a path var pathDelete = ( _id . includes ( '.' ) || ! getters . collectionMode ) ; if ( pathDelete ) { var path = _id ; if ( ! path ) return error ( 'delete-missing-path' ) ; commit ( 'DELETE_PROP' , path ) ; return dispatch ( 'deleteProp' , path ) ; } if ( ! _id ) return error ( 'delete-missing-id' ) ; commit ( 'DELETE_DOC' , _id ) ; return dispatch ( 'deleteDoc' , _id ) ; } // check for hooks if ( state . _conf . sync . deleteHook ) { state . _conf . sync . deleteHook ( storeUpdateFn , id , store ) ; return id ; } storeUpdateFn ( id ) ; return id ; } , deleteBatch : function ( _a , ids ) { var state = _a . state , getters = _a . getters , commit = _a . commit , dispatch = _a . dispatch ; var store = this ; // check payload if ( ! isWhat . isArray ( ids ) || ! ids . length ) return [ ] ; // check userId dispatch ( 'setUserId' ) ; // define the store update function storeUpdateFn ( _ids ) { _ids . forEach ( function ( _id ) { // id is a path var pathDelete = ( _id . includes ( '.' ) || ! getters . collectionMode ) ; if ( pathDelete ) { var path = _id ; if ( ! path ) return error ( 'delete-missing-path' ) ; commit ( 'DELETE_PROP' , path ) ; return dispatch ( 'deleteProp' , path ) ; } if ( ! _id ) return error ( 'delete-missing-id' ) ; commit ( 'DELETE_DOC' , _id ) ; return dispatch ( 'deleteDoc' , _id ) ; } ) ; } // check for hooks if ( state . _conf . sync . deleteBatchHook ) { state . _conf . sync . deleteBatchHook ( storeUpdateFn , ids , store ) ; return ids ; } storeUpdateFn ( ids ) ; return ids ; } , _stopPatching : function ( _a ) { var state = _a . state , commit = _a . commit ; if ( state . _sync . stopPatchingTimeout ) { clearTimeout ( state . _sync . stopPatchingTimeout ) ; } state . _sync . stopPatchingTimeout = setTimeout ( function ( _ ) { state . _sync . patching = false ; } , 300 ) ; } , _startPatching : function ( _a ) { var state = _a . state , commit = _a . commit ; if ( state . _sync . stopPatchingTimeout ) { clearTimeout ( state . _sync . stopPatchingTimeout ) ; } state . _sync . patching = true ; } } ; }
A function returning the actions object

@export
@param {*} Firebase The Firebase dependency
@returns {AnyObject} the actions object
A function returning the actions object