UNPKG

sync-server

Version:

A simple server which can be used to synchronize data from Dexie.Syncable and an ISyncProtocol implementation and write them into files

77 lines (69 loc) 2.86 kB
'use strict'; /* * License: * The contents of this file were copied from * https://github.com/dfahlander/Dexie.js/blob/master/samples/remote-sync/websocket/WebSocketSyncServer.js * and are under the Apache 2 License. * * The code was modified to improve readability. */ const { CREATE, UPDATE, DELETE } = require('./types'); const combineCreateAndUpdate = require('./combine_create_and_update'); const combineUpdateAndUpdate = require('./combine_update_and_update'); function reduceCreateChange(prevChange, nextChange) { switch (nextChange.type) { case CREATE: return nextChange; // Another CREATE replaces previous CREATE. case UPDATE: return combineCreateAndUpdate(prevChange, nextChange); // Apply nextChange.mods into prevChange.obj case DELETE: // Object created and then deleted. If it wasn't for that we MUST handle resent changes, // we would skip the entire change here. But what if the CREATE was sent earlier, // and then CREATE/DELETE at a later stage? // It would become a ghost object in the DB. Therefore, we MUST keep the delete change! // If object doesn't exist, it wont harm! return nextChange; } } function reduceUpdateChange(prevChange, nextChange) { switch (nextChange.type) { case CREATE: return nextChange; // Another CREATE replaces previous update. case UPDATE: // Add the additional modifications to existing modification map. return combineUpdateAndUpdate(prevChange, nextChange); case DELETE: return nextChange; // Only send the delete change. What was updated earlier is no longer of interest. } } function reduceDeleteChange(prevChange, nextChange) { switch (nextChange.type) { case CREATE: return nextChange; // A resurrection occurred. Only create change is of interest. case UPDATE: return prevChange; // Nothing to do. We cannot update an object that doesn't exist. Leave the delete change there. case DELETE: return prevChange; // Still a delete change. Leave as is. } } const actions = { [CREATE]: reduceCreateChange, [UPDATE]: reduceUpdateChange, [DELETE]: reduceDeleteChange, }; module.exports = function reduceChanges(changes) { // Converts an Array of change objects to a set of change objects based on its unique combination of (table ":" key). // If several changes were applied to the same object, the resulting set will only contain one change for that object. return changes.reduce((map, nextChange) => { const id = `${nextChange.table}:${nextChange.key}`; const prevChange = map[id]; if (!prevChange) { // This is the first change on this key. map[id] = nextChange; } else { // Merge the oldchange with the new change map[id] = actions[prevChange.type](prevChange, nextChange); } return map; }, {}); };