From 4ff2707252db5ced07740ac9d30879fc6f46e752 Mon Sep 17 00:00:00 2001 From: Ivan Kerin Date: Wed, 5 Jul 2017 16:36:54 +0300 Subject: [PATCH] Implement recursive snapshotOriginal --- package.json | 4 +- src/index.js | 30 ++++++++ test/indexTest.js | 97 +++++++++++++++++++++++- test/models/DocumentArrayNestedSchema.js | 13 ++++ test/models/DocumentArraySchema.js | 15 ++++ test/models/EmbeddedNestedSchema.js | 13 ++++ test/models/EmbeddedSchema.js | 15 ++++ test/models/Nested.js | 18 +++++ yarn.lock | 88 +++++++++++---------- 9 files changed, 252 insertions(+), 41 deletions(-) create mode 100644 test/models/DocumentArrayNestedSchema.js create mode 100644 test/models/DocumentArraySchema.js create mode 100644 test/models/EmbeddedNestedSchema.js create mode 100644 test/models/EmbeddedSchema.js create mode 100644 test/models/Nested.js diff --git a/package.json b/package.json index 805d695..4c64abf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mongoose-originals", - "version": "1.2.0", + "version": "1.3.0", "description": "Get original value of mongoose fields", "main": "src/index.js", "repository": "git@github.com:enhancv/mongoose-originals.git", @@ -17,7 +17,7 @@ "dotenv": "^4.0.0", "istanbul": "^0.4.5", "mocha": "^3.2.0", - "mongoose": "^4.8" + "mongoose": "^4.11.1" }, "dependencies": { "lodash": "^4.17.4" diff --git a/src/index.js b/src/index.js index 8f59fc5..e5ebc6b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,20 @@ const { isEqual, pick } = require("lodash/fp"); +function eachMongooseOriginalsPath(item, fn, name) { + if (item && item.schema) { + if (item.schema.mongooseOriginals) { + fn(item); + } + item.schema.eachPath((name, type) => { + if (item[name] instanceof Array) { + item[name].forEach(item => eachMongooseOriginalsPath(item, fn, name)); + } else { + eachMongooseOriginalsPath(item[name], fn, name); + } + }); + } +} + function mongooseOriginals(schema, userOptions) { var options = Object.assign({ methods: true }, userOptions); @@ -11,6 +26,18 @@ function mongooseOriginals(schema, userOptions) { return !this.original || !isEqual(this.original, pick(options.fields, this.toObject())); } + function setSnapshotOriginal() { + eachMongooseOriginalsPath(this, item => { + item.snapshotOriginal = item.original; + }); + } + + function clearSnapshotOriginal() { + eachMongooseOriginalsPath(this, item => { + delete item.snapshotOriginal; + }); + } + function saveOriginalNamed() { this.original = {}; const newValues = this.toObject(); @@ -26,6 +53,9 @@ function mongooseOriginals(schema, userOptions) { } } + schema.mongooseOriginals = true; + schema.method("setSnapshotOriginal", setSnapshotOriginal); + schema.method("clearSnapshotOriginal", clearSnapshotOriginal); schema.method("initOriginals", initOriginals); schema.method("isChanged", isChanged); schema.post("init", saveOriginalNamed); diff --git a/test/indexTest.js b/test/indexTest.js index 45b743b..2508abf 100644 --- a/test/indexTest.js +++ b/test/indexTest.js @@ -5,11 +5,12 @@ const database = require("./database"); const mongoose = require("mongoose"); const Customer = require("./models/Customer"); const Subscription = require("./models/Subscription"); +const Nested = require("./models/Nested"); const originals = require("../src"); describe( "Customer", - database([Customer], function() { + database([Customer, Nested], function() { it("Should throw an error if no fields are defined", function() { const Schema = mongoose.Schema; @@ -22,6 +23,100 @@ describe( }, /No fields specified for mongoose originals on schema/); }); + it.only("Should test nested setSnapshotOriginal and clearSnapshotOriginal", function() { + const nested = new Nested({ + name: "11", + embedded: { name: "22", children: [{ title: "33" }, { title: "44" }] }, + children: [ + { category: "55", nested: { type: "66" } }, + { category: "77", nested: { type: "88" } }, + ], + }); + + return nested + .save() + .then(nested => { + nested.setSnapshotOriginal(); + + assert.deepEqual(nested.snapshotOriginal, nested.original); + assert.deepEqual(nested.embedded.snapshotOriginal, nested.embedded.original); + assert.deepEqual( + nested.embedded.children[0].snapshotOriginal, + nested.embedded.children[0].original + ); + assert.deepEqual( + nested.embedded.children[1].snapshotOriginal, + nested.embedded.children[1].original + ); + assert.deepEqual( + nested.children[0].snapshotOriginal, + nested.children[0].original + ); + assert.deepEqual( + nested.children[0].nested.snapshotOriginal, + nested.children[0].nested.original + ); + assert.deepEqual( + nested.children[1].snapshotOriginal, + nested.children[1].original + ); + assert.deepEqual( + nested.children[1].nested.snapshotOriginal, + nested.children[1].nested.original + ); + + assert.deepEqual(nested.snapshotOriginal, { name: "11", email: undefined }); + assert.deepEqual(nested.embedded.snapshotOriginal, { name: "22" }); + assert.deepEqual(nested.embedded.children[0].snapshotOriginal, { title: "33" }); + assert.deepEqual(nested.embedded.children[1].snapshotOriginal, { title: "44" }); + assert.deepEqual(nested.children[0].snapshotOriginal, { category: "55" }); + assert.deepEqual(nested.children[0].nested.snapshotOriginal, { type: "66" }); + assert.deepEqual(nested.children[1].snapshotOriginal, { category: "77" }); + assert.deepEqual(nested.children[1].nested.snapshotOriginal, { type: "88" }); + + nested.name = "t1"; + nested.embedded.name = "t2"; + nested.embedded.children[0].title = "t3"; + nested.embedded.children[1].title = "t4"; + nested.children[0].category = "t5"; + nested.children[0].nested.type = "t6"; + nested.children[1].category = "t7"; + nested.children[1].nested.type = "t8"; + + return nested.save(); + }) + .then(nestedSaved => { + assert.deepEqual(nestedSaved.original, { name: "t1", email: undefined }); + assert.deepEqual(nestedSaved.embedded.original, { name: "t2" }); + assert.deepEqual(nestedSaved.embedded.children[0].original, { title: "t3" }); + assert.deepEqual(nestedSaved.embedded.children[1].original, { title: "t4" }); + assert.deepEqual(nestedSaved.children[0].original, { category: "t5" }); + assert.deepEqual(nestedSaved.children[0].nested.original, { type: "t6" }); + assert.deepEqual(nestedSaved.children[1].original, { category: "t7" }); + assert.deepEqual(nestedSaved.children[1].nested.original, { type: "t8" }); + + assert.deepEqual(nested.snapshotOriginal, { name: "11", email: undefined }); + assert.deepEqual(nested.embedded.snapshotOriginal, { name: "22" }); + assert.deepEqual(nested.embedded.children[0].snapshotOriginal, { title: "33" }); + assert.deepEqual(nested.embedded.children[1].snapshotOriginal, { title: "44" }); + assert.deepEqual(nested.children[0].snapshotOriginal, { category: "55" }); + assert.deepEqual(nested.children[0].nested.snapshotOriginal, { type: "66" }); + assert.deepEqual(nested.children[1].snapshotOriginal, { category: "77" }); + assert.deepEqual(nested.children[1].nested.snapshotOriginal, { type: "88" }); + + nested.clearSnapshotOriginal(); + + assert.equal(nested.snapshotOriginal, undefined); + assert.equal(nested.embedded.snapshotOriginal, undefined); + assert.equal(nested.embedded.children[0].snapshotOriginal, undefined); + assert.equal(nested.embedded.children[1].snapshotOriginal, undefined); + assert.equal(nested.children[0].snapshotOriginal, undefined); + assert.equal(nested.children[0].nested.snapshotOriginal, undefined); + assert.equal(nested.children[1].snapshotOriginal, undefined); + assert.equal(nested.children[1].nested.snapshotOriginal, undefined); + }); + }); + it("Should not add collection methods if specified", function() { const Schema = mongoose.Schema; diff --git a/test/models/DocumentArrayNestedSchema.js b/test/models/DocumentArrayNestedSchema.js new file mode 100644 index 0000000..d0a5269 --- /dev/null +++ b/test/models/DocumentArrayNestedSchema.js @@ -0,0 +1,13 @@ +const Schema = require("mongoose").Schema; +const originals = require("../../src"); + +const DocumentArrayNestedSchema = new Schema( + { + type: String, + }, + { _id: false } +); + +DocumentArrayNestedSchema.plugin(originals, { fields: ["type"] }); + +module.exports = DocumentArrayNestedSchema; diff --git a/test/models/DocumentArraySchema.js b/test/models/DocumentArraySchema.js new file mode 100644 index 0000000..a27a401 --- /dev/null +++ b/test/models/DocumentArraySchema.js @@ -0,0 +1,15 @@ +const Schema = require("mongoose").Schema; +const originals = require("../../src"); +const DocumentArrayNestedSchema = require("./DocumentArrayNestedSchema"); + +const DocumentArraySchema = new Schema( + { + category: String, + nested: DocumentArrayNestedSchema, + }, + { _id: false } +); + +DocumentArraySchema.plugin(originals, { fields: ["category"] }); + +module.exports = DocumentArraySchema; diff --git a/test/models/EmbeddedNestedSchema.js b/test/models/EmbeddedNestedSchema.js new file mode 100644 index 0000000..9a035df --- /dev/null +++ b/test/models/EmbeddedNestedSchema.js @@ -0,0 +1,13 @@ +const Schema = require("mongoose").Schema; +const originals = require("../../src"); + +const EmbeddedNestedSchema = new Schema( + { + title: String, + }, + { _id: false } +); + +EmbeddedNestedSchema.plugin(originals, { fields: ["title"] }); + +module.exports = EmbeddedNestedSchema; diff --git a/test/models/EmbeddedSchema.js b/test/models/EmbeddedSchema.js new file mode 100644 index 0000000..93df9a5 --- /dev/null +++ b/test/models/EmbeddedSchema.js @@ -0,0 +1,15 @@ +const Schema = require("mongoose").Schema; +const originals = require("../../src"); +const EmbeddedNestedSchema = require("./EmbeddedNestedSchema"); + +const EmbeddedSchema = new Schema( + { + name: String, + children: [EmbeddedNestedSchema], + }, + { _id: false } +); + +EmbeddedSchema.plugin(originals, { fields: ["name"] }); + +module.exports = EmbeddedSchema; diff --git a/test/models/Nested.js b/test/models/Nested.js new file mode 100644 index 0000000..88295a4 --- /dev/null +++ b/test/models/Nested.js @@ -0,0 +1,18 @@ +const mongoose = require("mongoose"); +const Schema = mongoose.Schema; +const originals = require("../../src"); +const DocumentArraySchema = require("./DocumentArraySchema"); +const EmbeddedSchema = require("./EmbeddedSchema"); + +const NestedSchema = new Schema({ + name: String, + email: String, + embedded: EmbeddedSchema, + children: [DocumentArraySchema], +}); + +NestedSchema.plugin(originals, { fields: ["name", "email"] }); + +const Nested = mongoose.model("Nested", NestedSchema); + +module.exports = Nested; diff --git a/yarn.lock b/yarn.lock index 21d0f53..2c78b2d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -57,7 +57,7 @@ bson@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/bson/-/bson-1.0.4.tgz#93c10d39eaa5b58415cbc4052f3e53e562b0b72c" -buffer-shims@^1.0.0: +buffer-shims@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" @@ -100,6 +100,12 @@ debug@2.2.0: dependencies: ms "0.7.1" +debug@2.6.8: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" + dependencies: + ms "2.0.0" + decamelize@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -259,9 +265,9 @@ json3@3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" -kareem@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/kareem/-/kareem-1.2.1.tgz#acdb8c8119845834abbfa58ade1cf9dea63dc752" +kareem@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/kareem/-/kareem-1.4.1.tgz#ed76200044fa041ef32b4da8261e2553f1173531" kind-of@^3.0.2: version "3.2.2" @@ -367,52 +373,52 @@ mocha@^3.2.0: mkdirp "0.5.1" supports-color "3.1.2" -mongodb-core@2.1.9: - version "2.1.9" - resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.9.tgz#85aa71ee4fb716196e06b787557bf139f801daf5" +mongodb-core@2.1.11: + version "2.1.11" + resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.11.tgz#1c38776ceb174997a99c28860eed9028da9b3e1a" dependencies: bson "~1.0.4" require_optional "~1.0.0" -mongodb@2.2.25: - version "2.2.25" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.25.tgz#d3b25dad00eda2bdfcbc996210ba082ac686a6b6" +mongodb@2.2.27: + version "2.2.27" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.27.tgz#34122034db66d983bcf6ab5adb26a24a70fef6e6" dependencies: es6-promise "3.2.1" - mongodb-core "2.1.9" - readable-stream "2.1.5" + mongodb-core "2.1.11" + readable-stream "2.2.7" -mongoose@^4.8: - version "4.9.3" - resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-4.9.3.tgz#7e3ea176ed7d3d23940368704834890595aea040" +mongoose@^4.11.1: + version "4.11.1" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-4.11.1.tgz#2560b6d89e744b05857d024cab8b316066716e3e" dependencies: async "2.1.4" bson "~1.0.4" hooks-fixed "2.0.0" - kareem "1.2.1" - mongodb "2.2.25" - mpath "0.2.1" + kareem "1.4.1" + mongodb "2.2.27" + mpath "0.3.0" mpromise "0.5.5" - mquery "2.3.0" - ms "0.7.2" + mquery "2.3.1" + ms "2.0.0" muri "1.2.1" regexp-clone "0.0.1" sliced "1.0.1" -mpath@0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.2.1.tgz#3a4e829359801de96309c27a6b2e102e89f9e96e" +mpath@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.3.0.tgz#7a58f789e9b5fd3c94520634157960f26bd5ef44" mpromise@0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mpromise/-/mpromise-0.5.5.tgz#f5b24259d763acc2257b0a0c8c6d866fd51732e6" -mquery@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/mquery/-/mquery-2.3.0.tgz#3d1717ad8958d0c99e42ea2461a109f3e5f3e458" +mquery@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/mquery/-/mquery-2.3.1.tgz#9ab36749714800ff0bb53a681ce4bc4d5f07c87b" dependencies: bluebird "2.10.2" - debug "2.2.0" + debug "2.6.8" regexp-clone "0.0.1" sliced "0.0.5" @@ -420,9 +426,9 @@ ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" -ms@0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" muri@1.2.1: version "1.2.1" @@ -470,16 +476,16 @@ process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" -readable-stream@2.1.5: - version "2.1.5" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0" +readable-stream@2.2.7: + version "2.2.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.7.tgz#07057acbe2467b22042d36f98c5ad507054e95b1" dependencies: - buffer-shims "^1.0.0" + buffer-shims "~1.0.0" core-util-is "~1.0.0" inherits "~2.0.1" isarray "~1.0.0" process-nextick-args "~1.0.6" - string_decoder "~0.10.x" + string_decoder "~1.0.0" util-deprecate "~1.0.1" regexp-clone@0.0.1: @@ -511,6 +517,10 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" +safe-buffer@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + semver@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -543,9 +553,11 @@ sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" +string_decoder@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + dependencies: + safe-buffer "~5.1.0" supports-color@3.1.2, supports-color@^3.1.0: version "3.1.2"