From 329526b225af9a50123fa598022b9b199f6ce8aa Mon Sep 17 00:00:00 2001 From: 0x8890 <0x8890@airmail.cc> Date: Sun, 24 Jan 2016 16:23:30 +0100 Subject: [PATCH] show full change details --- doc/CHANGELOG.md | 5 ++ lib/core.js | 10 ++-- lib/dispatch/create.js | 15 ++---- lib/dispatch/delete.js | 11 +---- lib/dispatch/update.js | 53 ++++++++++++--------- package.json | 3 +- test/integration/methods/create.js | 6 ++- test/integration/methods/delete.js | 3 +- test/integration/methods/update.js | 75 ++++++++++++++++++++---------- 9 files changed, 105 insertions(+), 76 deletions(-) diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index 156586053..891561e9a 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog +##### 1.12.0 (2016-01-24) +- Feature: include entire payloads in change event. +- Fix: update objects should show resulting operations. + + ##### 1.11.5 (2016-01-24) - Polish: use `msgpack` to store data in IndexedDB instead of JSON, which allows use of Transferable & ArrayBuffer. - Polish: improve IndexedDB error handling. diff --git a/lib/core.js b/lib/core.js index d411e7c45..4abbd8293 100644 --- a/lib/core.js +++ b/lib/core.js @@ -1,6 +1,6 @@ 'use strict' -var EventEmitter = require('events') +var EventLite = require('event-lite') // Local modules. var memoryAdapter = require('./adapter/adapters/memory') @@ -29,8 +29,8 @@ var plainObject = {} /** * This is the default export of the `fortune` module. The Fortune class - * subclasses the built-in `EventEmitter` class, and it has a few static - * properties attached to it that may be useful to access: + * is an event emitter that implements a subset of `EventEmitter`, and it has + * a few static properties attached to it that may be useful to access: * * - `Adapter`: abstract base class for the Adapter. * - `adapters`: included adapters, defaults to memory adapter. Note that the @@ -61,8 +61,8 @@ function Fortune (options) { } -// Inherit from EventEmitter class. -Fortune.prototype = assign(Object.create(EventEmitter.prototype)) +// Inherit from EventLite class. +Fortune.prototype = assign(Object.create(EventLite.prototype)) /** diff --git a/lib/dispatch/create.js b/lib/dispatch/create.js index 16ad87927..a8bf96ce7 100644 --- a/lib/dispatch/create.js +++ b/lib/dispatch/create.js @@ -172,16 +172,12 @@ module.exports = function (context) { var eventData = {}, currentType eventData[createMethod] = {} - eventData[createMethod][type] = map(records, function (record) { - return record[primaryKey] - }) + eventData[createMethod][type] = records for (currentType in updates) { if (!updates[currentType].length) continue - if (!(updateMethod in eventData)) - eventData[updateMethod] = {} - eventData[updateMethod][currentType] = - map(updates[currentType], mapId) + if (!(updateMethod in eventData)) eventData[updateMethod] = {} + eventData[updateMethod][currentType] = updates[currentType] } // Summarize changes during the lifecycle of the request. @@ -190,8 +186,3 @@ module.exports = function (context) { return context }) } - - -function mapId (update) { - return update[primaryKey] -} diff --git a/lib/dispatch/delete.js b/lib/dispatch/delete.js index 768cc77f6..0346bd19b 100644 --- a/lib/dispatch/delete.js +++ b/lib/dispatch/delete.js @@ -137,10 +137,8 @@ module.exports = function (context) { for (currentType in updates) { if (!updates[currentType].length) continue - if (!(updateMethod in eventData)) - eventData[updateMethod] = {} - eventData[updateMethod][currentType] = - map(updates[currentType], mapId) + if (!(updateMethod in eventData)) eventData[updateMethod] = {} + eventData[updateMethod][currentType] = updates[currentType] } // Summarize changes during the lifecycle of the request. @@ -149,8 +147,3 @@ module.exports = function (context) { return context }) } - - -function mapId (update) { - return update[primaryKey] -} diff --git a/lib/dispatch/update.js b/lib/dispatch/update.js index b402db539..99d75e827 100644 --- a/lib/dispatch/update.js +++ b/lib/dispatch/update.js @@ -22,7 +22,6 @@ var BadRequestError = errors.BadRequestError var find = require('../common/array/find') var includes = require('../common/array/includes') var map = require('../common/array/map') -var unique = require('../common/array/unique') var constants = require('../common/constants') var changeEvent = constants.change @@ -247,22 +246,42 @@ module.exports = function (context) { ids = id - // Initialize array. - if (!update.push) update.push = {} - if (!update.pull) update.pull = {} - update.push[field] = [] - update.pull[field] = [] - - // Compute differences, and mutate the update. + // Compute differences for push, and mutate the update. for (k = 0, l = ids.length; k < l; k++) { id = ids[k] - if (!includes(record[field], id)) update.push[field].push(id) + if (!includes(record[field], id)) { + if (!('push' in update)) update.push = {} + if (field in update.push) { + if (Array.isArray(update.push[field])) { + update.push[field].push(id) + continue + } + update.push[field] = [ update.push[field], id ] + continue + } + update.push[field] = [ id ] + } } + // Compute differences for pull, and mutate the update. for (k = 0, l = record[field].length; k < l; k++) { id = record[field][k] - if (!includes(ids, id)) update.pull[field].push(id) + if (!includes(ids, id)) { + if (!('pull' in update)) update.pull = {} + if (field in update.pull) { + if (Array.isArray(update.pull[field])) { + update.pull[field].push(id) + continue + } + update.pull[field] = [ update.pull[field], id ] + continue + } + update.pull[field] = [ id ] + } } + + // Delete the original replace, since it is no longer valid. + delete update.replace[field] } if (update.push && update.push[field]) { @@ -333,20 +352,17 @@ module.exports = function (context) { var eventData = {}, linkedType eventData[updateMethod] = {} - eventData[updateMethod][type] = - map(transformedUpdates, mapPrimaryKey) + eventData[updateMethod][type] = transformedUpdates for (linkedType in relatedUpdates) { if (!relatedUpdates[linkedType].length) continue if (linkedType !== type) - eventData[updateMethod][linkedType] = - map(relatedUpdates[linkedType], mapPrimaryKey) + eventData[updateMethod][linkedType] = relatedUpdates[linkedType] // Get the union of update IDs. else eventData[updateMethod][type] = - unique(eventData[updateMethod][type].concat( - map(relatedUpdates[type], mapPrimaryKey))) + eventData[updateMethod][type].concat(relatedUpdates[type]) } // Summarize changes during the lifecycle of the request. @@ -387,8 +403,3 @@ function dropFields (update, fields) { for (field in update.pull) if (!(field in fields)) delete update.pull[field] } - - -function mapPrimaryKey (update) { - return update[primaryKey] -} diff --git a/package.json b/package.json index cb1a632da..8a558bda6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "fortune", "description": "Application middleware for Node.js and web browsers.", - "version": "1.11.5", + "version": "1.12.0", "license": "MIT", "author": { "email": "0x8890@airmail.cc", @@ -30,6 +30,7 @@ "chalk": "^1.1.1", "deep-equal": "^1.0.1", "error-class": "^2.0.0", + "event-lite": "^0.1.0", "msgpack-lite": "^0.1.15", "negotiator": "^0.6.0", "tapdance": "^4.1.1" diff --git a/test/integration/methods/create.js b/test/integration/methods/create.js index 37ad3faf8..21df800a5 100644 --- a/test/integration/methods/create.js +++ b/test/integration/methods/create.js @@ -46,9 +46,11 @@ run(() => { store = instance store.on(changeEvent, data => { - ok(deepEqual(data[createMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[createMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 4 ]), 'change event shows created IDs') - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 3 ]), 'change event shows updated IDs') }) diff --git a/test/integration/methods/delete.js b/test/integration/methods/delete.js index ab1a4db89..b7a7bb713 100644 --- a/test/integration/methods/delete.js +++ b/test/integration/methods/delete.js @@ -31,7 +31,8 @@ run(() => { store.on(changeEvent, data => { ok(find(data[deleteMethod].user, id => id === 3), 'change event shows deleted ID') - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2 ]), 'change event shows updated IDs') }) diff --git a/test/integration/methods/update.js b/test/integration/methods/update.js index 410869a40..dee3f5b20 100644 --- a/test/integration/methods/update.js +++ b/test/integration/methods/update.js @@ -26,7 +26,8 @@ run(() => { comment('update one to one with 2nd degree unset') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2, 3 ]), 'change event shows updated IDs') }, type: 'user', @@ -56,7 +57,8 @@ run(() => { comment('update one to one with former related record') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2, 3 ]), 'change event shows updated IDs') }, type: 'user', @@ -86,7 +88,8 @@ run(() => { comment('update one to one with same value') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2 ]), 'change event shows updated IDs') }, type: 'user', @@ -134,7 +137,8 @@ run(() => { comment('update one to one with null value') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2 ]), 'change event shows updated IDs') }, type: 'user', @@ -161,9 +165,11 @@ run(() => { comment('update one to many (set)') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].animal, + ok(deepEqual(data[updateMethod].animal + .map(x => x.id).sort((a, b) => a - b), [ 1 ]), 'change event shows updated IDs') - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2 ]), 'change event shows related update IDs') }, type: 'animal', @@ -190,9 +196,11 @@ run(() => { comment('update one to many (unset)') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].animal, + ok(deepEqual(data[updateMethod].animal + .map(x => x.id).sort((a, b) => a - b), [ 1 ]), 'change event shows updated IDs') - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1 ]), 'change event shows related update IDs') }, type: 'animal', @@ -216,9 +224,11 @@ run(() => { comment('update many to one (push)') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2 ]), 'change event shows updated IDs') - ok(deepEqual(data[updateMethod].animal, + ok(deepEqual(data[updateMethod].animal + .map(x => x.id).sort((a, b) => a - b), [ 1 ]), 'change event shows related update IDs') }, type: 'user', @@ -259,9 +269,11 @@ run(() => { comment('update many to one (push) with 2nd degree') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user, + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2 ]), 'change event shows updated IDs') - ok(deepEqual(data[updateMethod].animal, + ok(deepEqual(data[updateMethod].animal + .map(x => x.id).sort((a, b) => a - b), [ 2 ]), 'change event shows related update IDs') }, type: 'user', @@ -285,9 +297,11 @@ run(() => { comment('update many to one (pull)') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user, + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 2 ]), 'change event shows updated IDs') - ok(deepEqual(data[updateMethod].animal, + ok(deepEqual(data[updateMethod].animal + .map(x => x.id).sort((a, b) => a - b), [ 2, 3 ]), 'change event shows related update IDs') }, type: 'user', @@ -314,9 +328,11 @@ run(() => { comment('update many to one (set)') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2, 3 ]), 'change event shows updated IDs') - ok(deepEqual(data[updateMethod].animal.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].animal + .map(x => x.id).sort((a, b) => a - b), [ 1, 2, 3 ]), 'change event shows updated IDs') }, type: 'user', @@ -372,9 +388,11 @@ run(() => { comment('update many to one (set) #3') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2 ]), 'change event shows updated IDs') - ok(deepEqual(data[updateMethod].animal.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].animal + .map(x => x.id).sort((a, b) => a - b), [ 1, 3 ]), 'change event shows updated IDs') }, type: 'user', @@ -401,9 +419,11 @@ run(() => { comment('update many to one (unset)') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 2 ]), 'change event shows updated IDs') - ok(deepEqual(data[updateMethod].animal.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].animal + .map(x => x.id).sort((a, b) => a - b), [ 2, 3 ]), 'change event shows updated IDs') }, type: 'user', @@ -430,7 +450,8 @@ run(() => { comment('update many to many (push)') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2 ]), 'change event shows updated IDs') }, type: 'user', @@ -471,7 +492,8 @@ run(() => { comment('update many to many (pull)') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 2, 3 ]), 'change event shows updated IDs') }, type: 'user', @@ -495,7 +517,8 @@ run(() => { comment('update many to many (set)') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2 ]), 'change event shows updated IDs') }, type: 'user', @@ -542,7 +565,8 @@ run(() => { comment('update many to many (unset)') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2, 3 ]), 'change event shows updated IDs') }, type: 'user', @@ -572,7 +596,8 @@ run(() => { comment('update many to many (denormalized inverse)') return updateTest({ change: data => { - ok(deepEqual(data[updateMethod].user.sort((a, b) => a - b), + ok(deepEqual(data[updateMethod].user + .map(x => x.id).sort((a, b) => a - b), [ 1, 2, 3 ]), 'change event shows updated IDs') }, type: 'user',