UNPKG

@nozbe/watermelondb

Version:

Build powerful React Native and React web apps that scale from hundreds to tens of thousands of records and remain fast

114 lines (113 loc) 5.64 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = fetchLocalChanges; exports.hasUnsyncedChanges = hasUnsyncedChanges; var _fp = require("../../utils/fp"); var _allPromisesObj = _interopRequireDefault(require("../../utils/fp/allPromisesObj")); var Q = _interopRequireWildcard(require("../../QueryDescription")); var _Schema = require("../../Schema"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } // NOTE: Two separate queries are faster than notEq(synced) on LokiJS var createdQuery = Q.where((0, _Schema.columnName)('_status'), 'created'); var updatedQuery = Q.where((0, _Schema.columnName)('_status'), 'updated'); function fetchLocalChangesForCollection(collection) { return new Promise(function ($return, $error) { var createdRecords, updatedRecords, deletedRecords, changeSet, changedRecords; return Promise.resolve(Promise.all([collection.query(createdQuery).fetch(), collection.query(updatedQuery).fetch(), collection.database.adapter.getDeletedRecords(collection.table)])).then(function ($await_1) { try { [createdRecords, updatedRecords, deletedRecords] = $await_1; changeSet = { created: [], updated: [], deleted: deletedRecords }; // TODO: It would be best to omit _status, _changed fields, since they're not necessary for the server // but this complicates markLocalChangesAsDone, since we don't have the exact copy to compare if record changed // TODO: It would probably also be good to only send to server locally changed fields, not full records // perf-critical - using mutation createdRecords.forEach(function (record) { // $FlowFixMe changeSet.created.push(Object.assign({}, record._raw)); }); updatedRecords.forEach(function (record) { // $FlowFixMe changeSet.updated.push(Object.assign({}, record._raw)); }); changedRecords = createdRecords.concat(updatedRecords); return $return([changeSet, changedRecords]); } catch ($boundEx) { return $error($boundEx); } }, $error); }); } function fetchLocalChanges(db) { return db.read(function () { return new Promise(function ($return, $error) { var changes; return Promise.resolve((0, _allPromisesObj.default)((0, _fp.mapObj)(fetchLocalChangesForCollection, db.collections.map))).then(function ($await_2) { try { changes = $await_2; // TODO: deep-freeze changes object (in dev mode only) to detect mutations (user bug) return $return({ // $FlowFixMe changes: (0, _fp.mapObj)(function ([changeSet]) { return changeSet; })(changes), affectedRecords: (0, _fp.unnest)((0, _fp.values)(changes).map(function ([, records]) { return records; })) }); } catch ($boundEx) { return $error($boundEx); } }, $error); }); }, 'sync-fetchLocalChanges'); } function hasUnsyncedChanges(db) { // action is necessary to ensure other code doesn't make changes under our nose return db.read(function () { return new Promise(function ($return, $error) { var collections, hasUnsynced, unsyncedFlags; collections = (0, _fp.values)(db.collections.map); hasUnsynced = function (collection) { return new Promise(function ($return, $error) { var created, updated, deleted; return Promise.resolve(collection.query(createdQuery).fetchCount()).then(function ($await_3) { try { created = $await_3; return Promise.resolve(collection.query(updatedQuery).fetchCount()).then(function ($await_4) { try { updated = $await_4; return Promise.resolve(db.adapter.getDeletedRecords(collection.table)).then(function ($await_5) { try { deleted = $await_5; return $return(0 < created + updated + deleted.length); } catch ($boundEx) { return $error($boundEx); } }, $error); } catch ($boundEx) { return $error($boundEx); } }, $error); } catch ($boundEx) { return $error($boundEx); } }, $error); }); }; return Promise.resolve((0, _fp.allPromises)(hasUnsynced, collections)).then(function ($await_6) { try { unsyncedFlags = $await_6; return $return(unsyncedFlags.some(_fp.identity)); } catch ($boundEx) { return $error($boundEx); } }, $error); }); }, 'sync-hasUnsyncedChanges'); }