From d213dda7797d9b71006ff658d0abcd7e7f0906e9 Mon Sep 17 00:00:00 2001 From: Benjamin Pannell Date: Mon, 15 Jun 2015 15:51:57 +0200 Subject: [PATCH] Fixes for a number of weird fringe cases after calling instance.save --- dist/lib/Instance.js | 17 ++++++++------- dist/lib/Instance.js.map | 2 +- lib/Instance.ts | 22 +++++++++++--------- test/Instance.ts | 45 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 18 deletions(-) diff --git a/dist/lib/Instance.js b/dist/lib/Instance.js index 91dd02a..be67e3f 100644 --- a/dist/lib/Instance.js +++ b/dist/lib/Instance.js @@ -61,7 +61,6 @@ var Instance = (function () { return Bluebird.resolve().then(function () { conditions = _.cloneDeep(conditions); _.merge(conditions, { _id: _this._modified._id }); - conditions = _this._model.helpers.transformToDB(conditions); if (!changes) { var validation = _this._model.helpers.validate(_this._modified); if (validation.failed) @@ -99,10 +98,9 @@ var Instance = (function () { }); } }).then(function (changed) { - conditions = _this._model.helpers.convertToDB({ _id: _this._modified._id }); - if (!changed) { - return _.cloneDeep(_this._modified); - } + conditions = { _id: _this._modified._id }; + if (!changed) + return _this._modified; return new Bluebird(function (resolve, reject) { _this._model.collection.findOne(conditions, function (err, latest) { if (err) @@ -111,11 +109,16 @@ var Instance = (function () { }); }); }).then(function (latest) { + if (!latest) { + _this._isNew = true; + _this._original = _.cloneDeep(_this._modified); + return Bluebird.resolve(_this); + } return _this._model.handlers.documentReceived(conditions, latest, function (value) { _this._isPartial = false; _this._isNew = false; - _this._original = value; - _this._modified = _.clone(value); + _this._modified = value; + _this._original = _.cloneDeep(value); return _this; }); }).nodeify(callback); diff --git a/dist/lib/Instance.js.map b/dist/lib/Instance.js.map index f29897d..d199e29 100644 --- a/dist/lib/Instance.js.map +++ b/dist/lib/Instance.js.map @@ -1 +1 @@ -{"version":3,"sources":["lib/Instance.ts"],"names":["Instance","Instance.constructor","Instance.document","Instance.save","Instance.update","Instance.refresh","Instance.delete","Instance.remove","Instance.first","Instance.select","Instance.toJSON","Instance.toString"],"mappings":"AAUA,IAAO,CAAC,WAAW,QAAQ,CAAC,CAAC;AAC7B,IAAO,OAAO,WAAW,SAAS,CAAC,CAAC;AACpC,IAAO,QAAQ,WAAW,UAAU,CAAC,CAAC;AACtC,IAAO,MAAM,WAAW,QAAQ,CAAC,CAAC;AAElC;IACIA;;;;;;;;;;;OAWGA;IACHA,kBAAYA,KAAkCA,EAAEA,QAAmBA,EAAEA,KAAqBA,EAAEA,SAA0BA;QAb1HC,iBA4TCA;QA/SwEA,qBAAqBA,GAArBA,YAAqBA;QAAEA,yBAA0BA,GAA1BA,iBAA0BA;QAClHA,IAAIA,CAACA,MAAMA,GAAGA,KAAKA,CAACA;QAEpBA,IAAIA,CAACA,MAAMA,GAAGA,CAACA,CAACA,KAAKA,CAACA;QACtBA,IAAIA,CAACA,UAAUA,GAAGA,SAASA,CAACA;QAC5BA,IAAIA,CAACA,SAASA,GAAGA,QAAQA,CAACA;QAC1BA,IAAIA,CAACA,SAASA,GAAGA,CAACA,CAACA,SAASA,CAAYA,QAAQA,CAACA,CAACA;QAElDA,CAACA,CAACA,IAAIA,CAACA,KAAKA,CAACA,IAAIA,CAACA,OAAOA,EAACA,UAACA,MAAcA;YACrCA,EAAEA,CAACA,CAACA,MAAMA,CAACA,WAAWA,CAACA;gBAACA,MAAMA,CAACA,WAAWA,CAACA,KAAIA,EAAEA,KAAKA,CAACA,CAACA;QAC5DA,CAACA,CAACA,CAACA;IACPA,CAACA;IAWDD,sBAAIA,8BAAQA;QAHZA;;WAEGA;aACHA;YACIE,MAAMA,CAACA,IAAIA,CAACA,SAASA,CAACA;QAC1BA,CAACA;;;OAAAF;IAwDDA,uBAAIA,GAAJA;QAAAG,iBA0ECA;QA1EIA,cAAcA;aAAdA,WAAcA,CAAdA,sBAAcA,CAAdA,IAAcA;YAAdA,6BAAcA;;QACfA,IAAIA,QAAQA,GAA0BA,IAAIA,CAACA;QAC3CA,IAAIA,OAAOA,GAAQA,IAAIA,CAACA;QACxBA,IAAIA,UAAUA,GAAQA,EAAEA,CAACA;QAEzBA,KAAKA,CAACA,SAASA,CAACA,KAAKA,CAACA,IAAIA,CAACA,IAAIA,EAAEA,CAACA,CAACA,CAACA,OAAOA,EAAEA,CAACA,OAAOA,CAACA,UAACA,GAAGA;YACtDA,EAAEA,CAACA,CAACA,OAAOA,GAAGA,IAAIA,UAAUA,CAACA;gBAACA,QAAQA,GAAGA,GAAGA,CAACA;YAC7CA,IAAIA,CAACA,EAAEA,CAACA,CAACA,OAAOA,GAAGA,IAAIA,QAAQA,CAACA,CAACA,CAACA;gBAC9BA,EAAEA,CAACA,CAACA,CAACA,OAAOA,CAACA;oBAACA,OAAOA,GAAGA,GAAGA,CAACA;gBAC5BA,IAAIA;oBAACA,UAAUA,GAAGA,GAAGA,CAACA;YAC1BA,CAACA;QACLA,CAACA,CAACA,CAACA;QAEHA,MAAMA,CAACA,QAAQA,CAACA,OAAOA,EAAEA,CAACA,IAAIA,CAACA;YAC3BA,UAAUA,GAAGA,CAACA,CAACA,SAASA,CAACA,UAAUA,CAACA,CAACA;YACrCA,CAACA,CAACA,KAAKA,CAACA,UAAUA,EAAEA,EAAEA,GAAGA,EAAEA,KAAIA,CAACA,SAASA,CAACA,GAAGA,EAAEA,CAACA,CAACA;YAEjDA,UAAUA,GAAGA,KAAIA,CAACA,MAAMA,CAACA,OAAOA,CAACA,aAAaA,CAACA,UAAUA,CAACA,CAACA;YAE3DA,EAAEA,CAACA,CAACA,CAACA,OAAOA,CAACA,CAACA,CAACA;gBACXA,IAAIA,UAAUA,GAAGA,KAAIA,CAACA,MAAMA,CAACA,OAAOA,CAACA,QAAQA,CAACA,KAAIA,CAACA,SAASA,CAACA,CAACA;gBAC9DA,EAAEA,CAACA,CAACA,UAAUA,CAACA,MAAMA,CAACA;oBAACA,MAAMA,CAACA,QAAQA,CAACA,MAAMA,CAACA,UAAUA,CAACA,KAAKA,CAACA,CAACA,IAAIA,CAACA,KAAIA,CAACA,CAACA,OAAOA,CAACA,QAAQA,CAACA,CAACA;gBAE7FA,IAAIA,QAAQA,GAAGA,CAACA,CAACA,SAASA,CAACA,KAAIA,CAACA,SAASA,CAACA,CAACA;gBAC3CA,IAAIA,QAAQA,GAAGA,CAACA,CAACA,SAASA,CAACA,KAAIA,CAACA,SAASA,CAACA,CAACA;gBAE3CA,OAAOA,GAAGA,KAAIA,CAACA,MAAMA,CAACA,OAAOA,CAACA,IAAIA,CAACA,QAAQA,EAAEA,QAAQA,CAACA,CAACA;YAC3DA,CAACA;YAEDA,EAAEA,CAACA,CAACA,CAACA,CAACA,CAACA,IAAIA,CAACA,OAAOA,CAACA,CAACA,MAAMA,CAACA;gBAACA,MAAMA,CAACA,IAAIA,CAACA;YAEzCA,MAAMA,CAACA,OAAOA,CAACA;QACnBA,CAACA,CAACA,CAACA,IAAIA,CAACA,UAACA,OAAOA;YACZA,EAAEA,CAACA,CAACA,CAACA,OAAOA,IAAIA,CAACA,KAAIA,CAACA,MAAMA,CAACA;gBAACA,MAAMA,CAACA,OAAOA,CAACA;YAC7CA,MAAMA,CAACA,KAAIA,CAACA,MAAMA,CAACA,QAAQA,CAACA,cAAcA,CAAiBA,KAAIA,EAAEA,OAAOA,CAACA,CAACA,IAAIA,CAACA,cAAMA,OAAAA,OAAOA,EAAPA,CAAOA,CAACA,CAACA;QAClGA,CAACA,CAACA,CAACA,IAAIA,CAACA,UAACA,OAAOA;YACZA,EAAEA,CAACA,CAACA,CAACA,OAAOA,IAAIA,CAACA,KAAIA,CAACA,MAAMA,CAACA;gBAACA,MAAMA,CAACA,KAAKA,CAACA;YAE3CA,EAAEA,CAACA,CAACA,KAAIA,CAACA,MAAMA,CAACA,CAACA,CAACA;gBACdA,MAAMA,CAACA,IAAIA,QAAQA,CAAUA,UAACA,OAAOA,EAAEA,MAAMA;oBACzCA,KAAIA,CAACA,MAAMA,CAACA,UAAUA,CAACA,SAASA,CAACA,KAAIA,CAACA,SAASA,EAAEA,EAAEA,CAACA,EAAEA,UAAUA,EAAEA,EAAEA,UAACA,GAAGA,EAAEA,GAAGA;wBACzEA,EAAEA,CAACA,CAACA,GAAGA,CAACA;4BAACA,MAAMA,CAACA,MAAMA,CAACA,GAAGA,CAACA,CAACA;wBAC5BA,MAAMA,CAACA,OAAOA,CAAMA,CAACA,CAACA,GAAGA,CAACA,CAACA;oBAC/BA,CAACA,CAACA,CAACA;gBACPA,CAACA,CAACA,CAACA;YACPA,CAACA;YAACA,IAAIA,CAACA,CAACA;gBACJA,MAAMA,CAACA,IAAIA,QAAQA,CAAUA,UAACA,OAAmCA,EAAEA,MAAMA;oBACrEA,KAAIA,CAACA,MAAMA,CAACA,UAAUA,CAACA,SAASA,CAACA,UAAUA,EAAEA,OAAOA,EAAEA,EAAEA,CAACA,EAAEA,UAAUA,EAAEA,EAAEA,UAACA,GAAUA,EAAEA,OAAgBA;wBAClGA,EAAEA,CAACA,CAACA,GAAGA,CAACA;4BAACA,MAAMA,CAACA,MAAMA,CAACA,GAAGA,CAACA,CAACA;wBAC5BA,MAAMA,CAACA,OAAOA,CAACA,OAAOA,CAACA,CAACA;oBAC5BA,CAACA,CAACA,CAACA;gBACPA,CAACA,CAACA,CAACA;YACPA,CAACA;QACLA,CAACA,CAACA,CAACA,IAAIA,CAACA,UAACA,OAAgBA;YACrBA,UAAUA,GAAGA,KAAIA,CAACA,MAAMA,CAACA,OAAOA,CAACA,WAAWA,CAACA,EAAEA,GAAGA,EAAEA,KAAIA,CAACA,SAASA,CAACA,GAAGA,EAAEA,CAACA,CAACA;YAC1EA,EAAEA,CAACA,CAACA,CAACA,OAAOA,CAACA,CAACA,CAACA;gBACXA,MAAMA,CAACA,CAACA,CAACA,SAASA,CAACA,KAAIA,CAACA,SAASA,CAACA,CAACA;YACvCA,CAACA;YAEDA,MAAMA,CAACA,IAAIA,QAAQA,CAAYA,UAACA,OAAOA,EAAEA,MAAMA;gBAC3CA,KAAIA,CAACA,MAAMA,CAACA,UAAUA,CAACA,OAAOA,CAACA,UAAUA,EAACA,UAACA,GAAUA,EAAEA,MAAMA;oBACzDA,EAAEA,CAACA,CAACA,GAAGA,CAACA;wBAACA,MAAMA,CAACA,MAAMA,CAACA,GAAGA,CAACA,CAACA;oBAC5BA,MAAMA,CAACA,OAAOA,CAACA,MAAMA,CAACA,CAACA;gBAC3BA,CAACA,CAACA,CAACA;YACPA,CAACA,CAACA,CAACA;QACPA,CAACA,CAACA,CAACA,IAAIA,CAACA,UAACA,MAAiBA;YACtBA,MAAMA,CAACA,KAAIA,CAACA,MAAMA,CAACA,QAAQA,CAACA,gBAAgBA,CAACA,UAAUA,EAAEA,MAAMA,EAACA,UAACA,KAAKA;gBAClEA,KAAIA,CAACA,UAAUA,GAAGA,KAAKA,CAACA;gBACxBA,KAAIA,CAACA,MAAMA,GAAGA,KAAKA,CAACA;gBACpBA,KAAIA,CAACA,SAASA,GAAGA,KAAKA,CAACA;gBACvBA,KAAIA,CAACA,SAASA,GAAGA,CAACA,CAACA,KAAKA,CAAYA,KAAKA,CAACA,CAACA;gBAC3CA,MAAMA,CAAiBA,KAAIA,CAACA;YAChCA,CAACA,CAACA,CAACA;QACPA,CAACA,CAACA,CAACA,OAAOA,CAACA,QAAQA,CAACA,CAACA;IACzBA,CAACA;IAEDH;;;;OAIGA;IACHA,yBAAMA,GAANA,UAAOA,QAAsCA;QACzCI,MAAMA,CAACA,IAAIA,CAACA,OAAOA,CAACA,QAAQA,CAACA,CAACA;IAClCA,CAACA;IAEDJ;;;;OAIGA;IACHA,0BAAOA,GAAPA,UAAQA,QAAsCA;QAA9CK,iBA2BCA;QA1BGA,IAAIA,UAAUA,GAAGA,EAAEA,GAAGA,EAAEA,IAAIA,CAACA,SAASA,CAACA,GAAGA,EAAEA,CAACA;QAE7CA,MAAMA,CAACA,QAAQA,CAACA,OAAOA,EAAEA,CAACA,IAAIA,CAACA;YAC3BA,MAAMA,CAACA,IAAIA,QAAQA,CAAYA,UAACA,OAAOA,EAAEA,MAAMA;gBAC3CA,KAAIA,CAACA,MAAMA,CAACA,UAAUA,CAACA,OAAOA,CAACA,UAAUA,EAACA,UAACA,GAAUA,EAAEA,GAAQA;oBAC3DA,EAAEA,CAACA,CAACA,GAAGA,CAACA;wBAACA,MAAMA,CAACA,MAAMA,CAACA,GAAGA,CAACA,CAACA;oBAC5BA,MAAMA,CAACA,OAAOA,CAACA,GAAGA,CAACA,CAACA;gBACxBA,CAACA,CAACA,CAACA;YACPA,CAACA,CAACA,CAACA;QACPA,CAACA,CAACA,CAACA,IAAIA,CAACA,UAACA,WAAWA;YAChBA,EAAEA,CAACA,CAACA,CAACA,WAAWA,CAACA,CAACA,CAACA;gBACfA,KAAIA,CAACA,UAAUA,GAAGA,IAAIA,CAACA;gBACvBA,KAAIA,CAACA,MAAMA,GAAGA,IAAIA,CAACA;gBACnBA,KAAIA,CAACA,SAASA,GAAGA,CAACA,CAACA,SAASA,CAAYA,KAAIA,CAACA,SAASA,CAACA,CAACA;gBACxDA,MAAMA,CAA2BA,KAAIA,CAACA;YAC1CA,CAACA;YAEDA,MAAMA,CAACA,KAAIA,CAACA,MAAMA,CAACA,QAAQA,CAACA,gBAAgBA,CAACA,UAAUA,EAAEA,WAAWA,EAAEA,UAACA,GAAGA;gBACtEA,KAAIA,CAACA,MAAMA,GAAGA,KAAKA,CAACA;gBACpBA,KAAIA,CAACA,UAAUA,GAAGA,KAAKA,CAACA;gBACxBA,KAAIA,CAACA,SAASA,GAAGA,GAAGA,CAACA;gBACrBA,KAAIA,CAACA,SAASA,GAAGA,CAACA,CAACA,SAASA,CAAYA,GAAGA,CAACA,CAACA;gBAE7CA,MAAMA,CAAiBA,KAAIA,CAACA;YAChCA,CAACA,CAACA,CAACA;QACPA,CAACA,CAACA,CAACA,OAAOA,CAACA,QAAQA,CAACA,CAACA;IACzBA,CAACA;IAEDL;;;;OAIGA;IACHA,yBAAMA,GAANA,UAAOA,QAAsCA;QACzCM,MAAMA,CAACA,IAAIA,CAACA,MAAMA,CAACA,QAAQA,CAACA,CAACA;IACjCA,CAACA;IAEDN;;;;OAIGA;IACHA,yBAAMA,GAANA,UAAOA,QAAsCA;QAA7CO,iBAkBCA;QAjBGA,IAAIA,UAAUA,GAAGA,EAAEA,GAAGA,EAAEA,IAAIA,CAACA,SAASA,CAACA,GAAGA,EAAEA,CAACA;QAE7CA,MAAMA,CAACA,QAAQA,CAACA,OAAOA,EAAEA,CAACA,IAAIA,CAACA;YAC3BA,EAAEA,CAACA,CAACA,KAAIA,CAACA,MAAMA,CAACA;gBAACA,MAAMA,CAACA,CAACA,CAACA;YAC1BA,MAAMA,CAACA,IAAIA,QAAQA,CAASA,UAACA,OAAOA,EAAEA,MAAMA;gBACxCA,KAAIA,CAACA,MAAMA,CAACA,UAAUA,CAACA,MAAMA,CAACA,UAAUA,EAAEA,EAAEA,CAACA,EAAEA,UAAUA,EAAEA,EAACA,UAACA,GAAUA,EAAEA,OAAaA;oBAClFA,EAAEA,CAACA,CAACA,GAAGA,CAACA;wBAACA,MAAMA,CAACA,MAAMA,CAACA,GAAGA,CAACA,CAACA;oBAC5BA,MAAMA,CAACA,OAAOA,CAACA,OAAOA,CAACA,CAACA;gBAC5BA,CAACA,CAACA,CAACA;YACPA,CAACA,CAACA,CAACA;QACPA,CAACA,CAACA,CAACA,IAAIA,CAACA,UAACA,OAAOA;YACZA,EAAEA,CAACA,CAACA,OAAOA,CAACA;gBAACA,MAAMA,CAACA,KAAIA,CAACA,MAAMA,CAACA,KAAKA,CAACA,KAAKA,CAACA,UAAUA,CAACA,CAACA;YACxDA,MAAMA,CAACA,KAAKA,CAACA;QACjBA,CAACA,CAACA,CAACA,IAAIA,CAACA;YACJA,KAAIA,CAACA,MAAMA,GAAGA,IAAIA,CAACA;YACnBA,MAAMA,CAAiBA,KAAIA,CAACA;QAChCA,CAACA,CAACA,CAACA,OAAOA,CAACA,QAAQA,CAACA,CAACA;IACzBA,CAACA;IAgBDP,wBAAKA,GAALA,UAASA,UAAqCA,EAAEA,SAA+BA;QAA/EQ,iBAWCA;QAVGA,IAAIA,MAAMA,GAAGA,IAAIA,CAACA;QAElBA,CAACA,CAACA,IAAIA,CAACA,UAAUA,EAACA,UAACA,KAAQA,EAAEA,GAAGA;YAC5BA,EAAEA,CAACA,CAACA,SAASA,CAACA,IAAIA,CAACA,KAAIA,EAAEA,KAAKA,EAAEA,GAAGA,CAACA,CAACA,CAACA,CAACA;gBACnCA,MAAMA,GAAGA,KAAKA,CAACA;gBACfA,MAAMA,CAACA,KAAKA,CAACA;YACjBA,CAACA;QACLA,CAACA,CAACA,CAACA;QAEHA,MAAMA,CAACA,MAAMA,CAACA;IAClBA,CAACA;IAgBDR,yBAAMA,GAANA,UAAUA,UAAqCA,EAAEA,SAA+BA;QAAhFS,iBAYCA;QAXGA,IAAIA,OAAOA,GAAGA,KAAKA,CAACA,OAAOA,CAACA,UAAUA,CAACA,CAACA;QACxCA,IAAIA,OAAOA,GAAQA,OAAOA,GAAGA,EAAEA,GAAGA,EAAEA,CAACA;QAErCA,CAACA,CAACA,IAAIA,CAACA,UAAUA,EAACA,UAACA,KAAQA,EAAEA,GAAGA;YAC5BA,EAAEA,CAACA,CAACA,SAASA,CAACA,IAAIA,CAACA,KAAIA,EAAEA,KAAKA,EAAEA,GAAGA,CAACA,CAACA,CAACA,CAACA;gBACnCA,EAAEA,CAACA,CAACA,OAAOA,CAACA;oBAACA,OAAOA,CAACA,IAAIA,CAACA,KAAKA,CAACA,CAACA;gBACjCA,IAAIA;oBAACA,OAAOA,CAACA,GAAGA,CAACA,GAAGA,KAAKA,CAACA;YAC9BA,CAACA;QACLA,CAACA,CAACA,CAACA;QAEHA,MAAMA,CAACA,OAAOA,CAACA;IACnBA,CAACA;IAEDT;;;OAGGA;IACHA,yBAAMA,GAANA;QACIU,MAAMA,CAACA,IAAIA,CAACA,QAAQA,CAACA;IACzBA,CAACA;IAEDV;;;OAGGA;IACHA,2BAAQA,GAARA;QACIW,MAAMA,CAACA,IAAIA,CAACA,SAASA,CAACA,IAAIA,CAACA,QAAQA,EAAEA,IAAIA,EAAEA,CAACA,CAACA,CAACA;IAClDA,CAACA;IA3QMX,eAAMA,GAAWA;QACpBA,GAAGA,EAAEA,OAAOA,CAACA,QAAQA;KACxBA,CAACA;IAEKA,mBAAUA,GAAuBA;QACpCA,MAAMA,CAACA,MAAMA,CAACA,UAAAA,MAAMA,IAAIA,OAAAA,MAAMA,KAAKA,OAAOA,CAACA,QAAQA,EAA3BA,CAA2BA,EAAEA,UAASA,MAAMA,EAAEA,IAAIA;YACtE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,IAAI,IAAI,YAAY,OAAO,CAAC,QAAQ,CAAC,CAAC;QAClE,CAAC,EAAEA,EAAEA,IAAIA,EAAEA,qBAAqBA,EAAEA,CAACA;KACtCA,CAACA;IAEKA,mBAAUA,GAAwFA;QACrGA,GAAGA,EAAEA;YACDA,MAAMA,EAAEA,UAAAA,KAAKA,IAAIA,OAAAA,KAAKA,CAACA,SAASA,IAAIA,UAAUA,GAAGA,IAAIA,OAAOA,CAACA,QAAQA,CAACA,KAAKA,CAACA,EAAEA,CAACA,CAACA,WAAWA,EAAEA,GAAGA,KAAKA,EAApFA,CAAoFA;YACrGA,IAAIA,EAAEA,UAAAA,KAAKA,IAAIA,OAAAA,KAAKA,IAAIA,OAAOA,KAAKA,KAAKA,QAAQA,GAAGA,IAAIA,OAAOA,CAACA,QAAQA,CAACA,KAAKA,CAACA,GAAGA,KAAKA,EAAxEA,CAAwEA;SAC1FA;KACJA,CAACA;IAGKA,gBAAOA,GAA+CA,EAAEA,CAACA;IA0PpEA,eAACA;AAADA,CA5TA,AA4TCA,IAAA;AA5TD,0BA4TC,CAAA","file":"lib/Instance.js","sourcesContent":["/// \r\nimport Core from './Core';\r\nimport Model from './Model';\r\nimport {Plugin} from './Plugins';\r\nimport {CacheDirector} from './CacheDirector';\r\nimport * as General from './General';\r\nimport * as ModelInterfaces from './ModelInterfaces';\r\nimport * as Index from './Index';\r\nimport {Schema} from './Schema';\r\n\r\nimport _ = require('lodash');\r\nimport MongoDB = require('mongodb');\r\nimport Bluebird = require('bluebird');\r\nimport skmatc = require('skmatc');\r\n\r\nexport default class Instance {\r\n /**\r\n * Creates a new instance which represents the given document as a type of model\r\n * @param {model.Model} model The model that the document represents\r\n * @param {TSchema} document The document which should be wrapped by this instance\r\n * @param {Boolean} isNew Whether the document is new (doesn't exist in the database) or not\r\n * @param {Boolean} isPartial Whether the document has only a subset of its fields populated\r\n * @description\r\n * This class will be subclassed automatically by Iridium to create a model specific instance\r\n * which takes advantage of some of v8's optimizations to boost performance significantly.\r\n * The instance returned by the model, and all of this instance's methods, will be of type\r\n * TInstance - which should represent the merger of TSchema and IInstance for best results.\r\n */\r\n constructor(model: Model, document: TDocument, isNew: boolean = true, isPartial: boolean = false) {\r\n this._model = model;\r\n\r\n this._isNew = !!isNew;\r\n this._isPartial = isPartial;\r\n this._original = document;\r\n this._modified = _.cloneDeep(document);\r\n\r\n _.each(model.core.plugins,(plugin: Plugin) => {\r\n if (plugin.newInstance) plugin.newInstance(this, model);\r\n });\r\n }\r\n\r\n private _isNew: boolean;\r\n private _isPartial: boolean;\r\n private _model: Model;\r\n private _original: TDocument;\r\n private _modified: TDocument;\r\n\r\n /**\r\n * Gets the underlying document representation of this instance\r\n */\r\n get document(): TDocument {\r\n return this._modified;\r\n }\r\n\r\n [name: string]: any;\r\n\r\n static onCreating: (document: { _id?: any }) => void;\r\n static onRetrieved: (document: { _id?: any }) => void;\r\n static onReady: (instance: Instance<{ _id?: any }, Instance<{ _id?: any }, any>>) => void;\r\n static onSaving: (instance: Instance<{ _id?: any }, Instance<{ _id?: any }, any>>, changes: any) => void;\r\n \r\n static collection: string;\r\n \r\n static schema: Schema = {\r\n _id: MongoDB.ObjectID\r\n };\r\n \r\n static validators: Skmatc.Validator[] = [\r\n skmatc.create(schema => schema === MongoDB.ObjectID, function(schema, data) {\r\n return this.assert(!data || data instanceof MongoDB.ObjectID);\r\n }, { name: 'ObjectID validation' })\r\n ];\r\n \r\n static transforms: { [property: string]: { fromDB: (value: any) => any; toDB: (value: any) => any; } } = {\r\n _id: {\r\n fromDB: value => value._bsontype == 'ObjectID' ? new MongoDB.ObjectID(value.id).toHexString() : value,\r\n toDB: value => value && typeof value === 'string' ? new MongoDB.ObjectID(value) : value\r\n }\r\n };\r\n \r\n static cache: CacheDirector;\r\n static indexes: (Index.Index | Index.IndexSpecification)[] = [];\r\n static identifier: {\r\n apply(fromSource: any): any;\r\n reverse(toSource: any): any;\r\n };\r\n \r\n /**\r\n * Saves any changes to this instance, using the built in diff algorithm to write the update query.\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the save operation completes\r\n * @returns {Promise}\r\n */\r\n save(callback?: General.Callback): Bluebird;\r\n /**\r\n * Saves the given changes to this instance and updates the instance to match the latest database document.\r\n * @param {Object} changes The MongoDB changes object to be used when updating this instance\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the save operation completes\r\n * @returns {Promise}\r\n */\r\n save(changes: Object, callback?: General.Callback): Bluebird;\r\n /**\r\n * Saves the given changes to this instance and updates the instance to match the latest database document.\r\n * @param {Object} conditions The conditions under which the update will take place - these will be merged with an _id query\r\n * @param {Object} changes The MongoDB changes object to be used when updating this instance\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the save operation completes\r\n * @returns {Promise}\r\n */\r\n save(conditions: Object, changes: Object, callback?: General.Callback): Bluebird;\r\n save(...args: any[]): Bluebird {\r\n var callback: General.Callback = null;\r\n var changes: any = null;\r\n var conditions: any = {};\r\n\r\n Array.prototype.slice.call(args, 0).reverse().forEach((arg) => {\r\n if (typeof arg == 'function') callback = arg;\r\n else if (typeof arg == 'object') {\r\n if (!changes) changes = arg;\r\n else conditions = arg;\r\n }\r\n });\r\n\r\n return Bluebird.resolve().then(() => {\r\n conditions = _.cloneDeep(conditions);\r\n _.merge(conditions, { _id: this._modified._id });\r\n \r\n conditions = this._model.helpers.transformToDB(conditions);\r\n \r\n if (!changes) {\r\n var validation = this._model.helpers.validate(this._modified);\r\n if (validation.failed) return Bluebird.reject(validation.error).bind(this).nodeify(callback);\r\n\r\n var original = _.cloneDeep(this._original);\r\n var modified = _.cloneDeep(this._modified);\r\n\r\n changes = this._model.helpers.diff(original, modified);\r\n }\r\n\r\n if (!_.keys(changes).length) return null;\r\n\r\n return changes;\r\n }).then((changes) => {\r\n if (!changes && !this._isNew) return changes;\r\n return this._model.handlers.savingDocument(this, changes).then(() => changes);\r\n }).then((changes) => {\r\n if (!changes && !this._isNew) return false;\r\n\r\n if (this._isNew) {\r\n return new Bluebird((resolve, reject) => {\r\n this._model.collection.insertOne(this._modified, { w: 'majority' }, (err, doc) => {\r\n if (err) return reject(err);\r\n return resolve(!!doc);\r\n });\r\n });\r\n } else {\r\n return new Bluebird((resolve: (changed: boolean) => void, reject) => {\r\n this._model.collection.updateOne(conditions, changes, { w: 'majority' }, (err: Error, changed: boolean) => {\r\n if (err) return reject(err);\r\n return resolve(changed);\r\n });\r\n });\r\n }\r\n }).then((changed: boolean) => {\r\n conditions = this._model.helpers.convertToDB({ _id: this._modified._id });\r\n if (!changed) {\r\n return _.cloneDeep(this._modified);\r\n }\r\n\r\n return new Bluebird((resolve, reject) => {\r\n this._model.collection.findOne(conditions,(err: Error, latest) => {\r\n if (err) return reject(err);\r\n return resolve(latest);\r\n });\r\n });\r\n }).then((latest: TDocument) => {\r\n return this._model.handlers.documentReceived(conditions, latest,(value) => {\r\n this._isPartial = false;\r\n this._isNew = false;\r\n this._original = value;\r\n this._modified = _.clone(value);\r\n return this;\r\n });\r\n }).nodeify(callback);\r\n }\r\n\r\n /**\r\n * Updates this instance to match the latest document available in the backing collection\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the update completes\r\n * @returns {Promise}\r\n */\r\n update(callback?: General.Callback): Bluebird {\r\n return this.refresh(callback);\r\n }\r\n\r\n /**\r\n * Updates this instance to match the latest document available in the backing collection\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the update completes\r\n * @returns {Promise}\r\n */\r\n refresh(callback?: General.Callback): Bluebird {\r\n var conditions = { _id: this._original._id };\r\n\r\n return Bluebird.resolve().then(() => {\r\n return new Bluebird((resolve, reject) => {\r\n this._model.collection.findOne(conditions,(err: Error, doc: any) => {\r\n if (err) return reject(err);\r\n return resolve(doc);\r\n });\r\n });\r\n }).then((newDocument) => {\r\n if (!newDocument) {\r\n this._isPartial = true;\r\n this._isNew = true;\r\n this._original = _.cloneDeep(this._modified);\r\n return >this;\r\n }\r\n\r\n return this._model.handlers.documentReceived(conditions, newDocument, (doc) => {\r\n this._isNew = false;\r\n this._isPartial = false;\r\n this._original = doc;\r\n this._modified = _.cloneDeep(doc);\r\n\r\n return this;\r\n });\r\n }).nodeify(callback);\r\n }\r\n\r\n /**\r\n * Removes this instance's document from the backing collection\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the operation completes\r\n * @returns {Promise}\r\n */\r\n delete(callback?: General.Callback): Bluebird {\r\n return this.remove(callback);\r\n }\r\n\r\n /**\r\n * Removes this instance's document from the backing collection\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the operation completes\r\n * @returns {Promise}\r\n */\r\n remove(callback?: General.Callback): Bluebird {\r\n var conditions = { _id: this._original._id };\r\n\r\n return Bluebird.resolve().then(() => {\r\n if (this._isNew) return 0;\r\n return new Bluebird((resolve, reject) => {\r\n this._model.collection.remove(conditions, { w: 'majority' },(err: Error, removed?: any) => {\r\n if (err) return reject(err);\r\n return resolve(removed);\r\n });\r\n });\r\n }).then((removed) => {\r\n if (removed) return this._model.cache.clear(conditions);\r\n return false;\r\n }).then(() => {\r\n this._isNew = true;\r\n return this;\r\n }).nodeify(callback);\r\n }\r\n\r\n /**\r\n * Retrieves the first element in an enumerable collection which matches the predicate\r\n * @param {any[]} collection The collection from which to retrieve the element\r\n * @param {function(any, Number): Boolean} predicate The function which determines whether to select an element\r\n * @returns {any}\r\n */\r\n first(collection: T[], predicate: General.Predicate): T;\r\n /**\r\n * Retrieves the first element in an enumerable collection which matches the predicate\r\n * @param {Object} collection The collection from which to retrieve the element\r\n * @param {function(any, String): Boolean} predicate The function which determines whether to select an element\r\n * @returns {any}\r\n */\r\n first(collection: { [key: string]: T }, predicate: General.Predicate): T;\r\n first(collection: T[]| { [key: string]: T }, predicate: General.Predicate): T {\r\n var result = null;\r\n\r\n _.each(collection,(value: T, key) => {\r\n if (predicate.call(this, value, key)) {\r\n result = value;\r\n return false;\r\n }\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Retrieves a number of elements from an enumerable collection which match the predicate\r\n * @param {any[]} collection The collection from which elements will be plucked\r\n * @param {function(any, Number): Boolean} predicate The function which determines the elements to be plucked\r\n * @returns {any[]}\r\n */\r\n select(collection: T[], predicate: General.Predicate): T[];\r\n /**\r\n * Retrieves a number of elements from an enumerable collection which match the predicate\r\n * @param {Object} collection The collection from which elements will be plucked\r\n * @param {function(any, String): Boolean} predicate The function which determines the elements to be plucked\r\n * @returns {Object}\r\n */\r\n select(collection: { [key: string]: T }, predicate: General.Predicate): { [key: string]: T };\r\n select(collection: T[]| { [key: string]: T }, predicate: General.Predicate): any {\r\n var isArray = Array.isArray(collection);\r\n var results: any = isArray ? [] : {};\r\n\r\n _.each(collection,(value: T, key) => {\r\n if (predicate.call(this, value, key)) {\r\n if (isArray) results.push(value);\r\n else results[key] = value;\r\n }\r\n });\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * Gets the JSON representation of this instance\r\n * @returns {TDocument}\r\n */\r\n toJSON(): any {\r\n return this.document;\r\n }\r\n\r\n /**\r\n * Gets a string representation of this instance\r\n * @returns {String}\r\n */\r\n toString(): string {\r\n return JSON.stringify(this.document, null, 2);\r\n }\r\n}"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["lib/Instance.ts"],"names":["Instance","Instance.constructor","Instance.document","Instance.save","Instance.update","Instance.refresh","Instance.delete","Instance.remove","Instance.first","Instance.select","Instance.toJSON","Instance.toString"],"mappings":"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","file":"lib/Instance.js","sourcesContent":["/// \r\nimport Core from './Core';\r\nimport Model from './Model';\r\nimport {Plugin} from './Plugins';\r\nimport {CacheDirector} from './CacheDirector';\r\nimport * as General from './General';\r\nimport * as ModelInterfaces from './ModelInterfaces';\r\nimport * as Index from './Index';\r\nimport {Schema} from './Schema';\r\n\r\nimport _ = require('lodash');\r\nimport MongoDB = require('mongodb');\r\nimport Bluebird = require('bluebird');\r\nimport skmatc = require('skmatc');\r\n\r\nexport default class Instance {\r\n /**\r\n * Creates a new instance which represents the given document as a type of model\r\n * @param {model.Model} model The model that the document represents\r\n * @param {TSchema} document The document which should be wrapped by this instance\r\n * @param {Boolean} isNew Whether the document is new (doesn't exist in the database) or not\r\n * @param {Boolean} isPartial Whether the document has only a subset of its fields populated\r\n * @description\r\n * This class will be subclassed automatically by Iridium to create a model specific instance\r\n * which takes advantage of some of v8's optimizations to boost performance significantly.\r\n * The instance returned by the model, and all of this instance's methods, will be of type\r\n * TInstance - which should represent the merger of TSchema and IInstance for best results.\r\n */\r\n constructor(model: Model, document: TDocument, isNew: boolean = true, isPartial: boolean = false) {\r\n this._model = model;\r\n\r\n this._isNew = !!isNew;\r\n this._isPartial = isPartial;\r\n this._original = document;\r\n this._modified = _.cloneDeep(document);\r\n\r\n _.each(model.core.plugins,(plugin: Plugin) => {\r\n if (plugin.newInstance) plugin.newInstance(this, model);\r\n });\r\n }\r\n\r\n private _isNew: boolean;\r\n private _isPartial: boolean;\r\n private _model: Model;\r\n private _original: TDocument;\r\n private _modified: TDocument;\r\n\r\n /**\r\n * Gets the underlying document representation of this instance\r\n */\r\n get document(): TDocument {\r\n return this._modified;\r\n }\r\n\r\n [name: string]: any;\r\n\r\n static onCreating: (document: { _id?: any }) => void;\r\n static onRetrieved: (document: { _id?: any }) => void;\r\n static onReady: (instance: Instance<{ _id?: any }, Instance<{ _id?: any }, any>>) => void;\r\n static onSaving: (instance: Instance<{ _id?: any }, Instance<{ _id?: any }, any>>, changes: any) => void;\r\n \r\n static collection: string;\r\n \r\n static schema: Schema = {\r\n _id: MongoDB.ObjectID\r\n };\r\n \r\n static validators: Skmatc.Validator[] = [\r\n skmatc.create(schema => schema === MongoDB.ObjectID, function(schema, data) {\r\n return this.assert(!data || data instanceof MongoDB.ObjectID);\r\n }, { name: 'ObjectID validation' })\r\n ];\r\n \r\n static transforms: { [property: string]: { fromDB: (value: any) => any; toDB: (value: any) => any; } } = {\r\n _id: {\r\n fromDB: value => value._bsontype == 'ObjectID' ? new MongoDB.ObjectID(value.id).toHexString() : value,\r\n toDB: value => value && typeof value === 'string' ? new MongoDB.ObjectID(value) : value\r\n }\r\n };\r\n \r\n static cache: CacheDirector;\r\n static indexes: (Index.Index | Index.IndexSpecification)[] = [];\r\n static identifier: {\r\n apply(fromSource: any): any;\r\n reverse(toSource: any): any;\r\n };\r\n \r\n /**\r\n * Saves any changes to this instance, using the built in diff algorithm to write the update query.\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the save operation completes\r\n * @returns {Promise}\r\n */\r\n save(callback?: General.Callback): Bluebird;\r\n /**\r\n * Saves the given changes to this instance and updates the instance to match the latest database document.\r\n * @param {Object} changes The MongoDB changes object to be used when updating this instance\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the save operation completes\r\n * @returns {Promise}\r\n */\r\n save(changes: Object, callback?: General.Callback): Bluebird;\r\n /**\r\n * Saves the given changes to this instance and updates the instance to match the latest database document.\r\n * @param {Object} conditions The conditions under which the update will take place - these will be merged with an _id query\r\n * @param {Object} changes The MongoDB changes object to be used when updating this instance\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the save operation completes\r\n * @returns {Promise}\r\n */\r\n save(conditions: Object, changes: Object, callback?: General.Callback): Bluebird;\r\n save(...args: any[]): Bluebird {\r\n var callback: General.Callback = null;\r\n var changes: any = null;\r\n var conditions: any = {};\r\n\r\n Array.prototype.slice.call(args, 0).reverse().forEach((arg) => {\r\n if (typeof arg == 'function') callback = arg;\r\n else if (typeof arg == 'object') {\r\n if (!changes) changes = arg;\r\n else conditions = arg;\r\n }\r\n });\r\n\r\n return Bluebird.resolve().then(() => {\r\n conditions = _.cloneDeep(conditions);\r\n _.merge(conditions, { _id: this._modified._id });\r\n \r\n if (!changes) {\r\n var validation = this._model.helpers.validate(this._modified);\r\n if (validation.failed) return Bluebird.reject(validation.error).bind(this).nodeify(callback);\r\n\r\n var original = _.cloneDeep(this._original);\r\n var modified = _.cloneDeep(this._modified);\r\n\r\n changes = this._model.helpers.diff(original, modified);\r\n }\r\n\r\n if (!_.keys(changes).length) return null;\r\n\r\n return changes;\r\n }).then((changes) => {\r\n if (!changes && !this._isNew) return changes;\r\n return this._model.handlers.savingDocument(this, changes).then(() => changes);\r\n }).then((changes) => {\r\n if (!changes && !this._isNew) return false;\r\n\r\n if (this._isNew) {\r\n return new Bluebird((resolve, reject) => {\r\n this._model.collection.insertOne(this._modified, { w: 'majority' }, (err, doc) => {\r\n if (err) return reject(err);\r\n return resolve(!!doc);\r\n });\r\n });\r\n } else {\r\n return new Bluebird((resolve: (changed: boolean) => void, reject) => {\r\n this._model.collection.updateOne(conditions, changes, { w: 'majority' }, (err: Error, changed: boolean) => {\r\n if (err) return reject(err);\r\n return resolve(changed);\r\n });\r\n });\r\n }\r\n }).then((changed: boolean) => {\r\n conditions = { _id: this._modified._id };\r\n if (!changed) return this._modified;\r\n\r\n return new Bluebird((resolve, reject) => {\r\n this._model.collection.findOne(conditions, (err: Error, latest) => {\r\n if (err) return reject(err);\r\n return resolve(latest);\r\n });\r\n });\r\n }).then((latest: TDocument) => {\r\n if(!latest) {\r\n this._isNew = true;\r\n this._original = _.cloneDeep(this._modified);\r\n return Bluebird.resolve(this);\r\n }\r\n \r\n return this._model.handlers.documentReceived(conditions, latest, (value) => {\r\n this._isPartial = false;\r\n this._isNew = false;\r\n this._modified = value;\r\n this._original = _.cloneDeep(value);\r\n return this;\r\n });\r\n }).nodeify(callback);\r\n }\r\n\r\n /**\r\n * Updates this instance to match the latest document available in the backing collection\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the update completes\r\n * @returns {Promise}\r\n */\r\n update(callback?: General.Callback): Bluebird {\r\n return this.refresh(callback);\r\n }\r\n\r\n /**\r\n * Updates this instance to match the latest document available in the backing collection\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the update completes\r\n * @returns {Promise}\r\n */\r\n refresh(callback?: General.Callback): Bluebird {\r\n var conditions = { _id: this._original._id };\r\n\r\n return Bluebird.resolve().then(() => {\r\n return new Bluebird((resolve, reject) => {\r\n this._model.collection.findOne(conditions,(err: Error, doc: any) => {\r\n if (err) return reject(err);\r\n return resolve(doc);\r\n });\r\n });\r\n }).then((newDocument) => {\r\n if (!newDocument) {\r\n this._isPartial = true;\r\n this._isNew = true;\r\n this._original = _.cloneDeep(this._modified);\r\n return >this;\r\n }\r\n\r\n return this._model.handlers.documentReceived(conditions, newDocument, (doc) => {\r\n this._isNew = false;\r\n this._isPartial = false;\r\n this._original = doc;\r\n this._modified = _.cloneDeep(doc);\r\n\r\n return this;\r\n });\r\n }).nodeify(callback);\r\n }\r\n\r\n /**\r\n * Removes this instance's document from the backing collection\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the operation completes\r\n * @returns {Promise}\r\n */\r\n delete(callback?: General.Callback): Bluebird {\r\n return this.remove(callback);\r\n }\r\n\r\n /**\r\n * Removes this instance's document from the backing collection\r\n * @param {function(Error, IInstance)} callback A callback which is triggered when the operation completes\r\n * @returns {Promise}\r\n */\r\n remove(callback?: General.Callback): Bluebird {\r\n var conditions = { _id: this._original._id };\r\n\r\n return Bluebird.resolve().then(() => {\r\n if (this._isNew) return 0;\r\n return new Bluebird((resolve, reject) => {\r\n this._model.collection.remove(conditions, { w: 'majority' },(err: Error, removed?: any) => {\r\n if (err) return reject(err);\r\n return resolve(removed);\r\n });\r\n });\r\n }).then((removed) => {\r\n if (removed) return this._model.cache.clear(conditions);\r\n return false;\r\n }).then(() => {\r\n this._isNew = true;\r\n return this;\r\n }).nodeify(callback);\r\n }\r\n\r\n /**\r\n * Retrieves the first element in an enumerable collection which matches the predicate\r\n * @param {any[]} collection The collection from which to retrieve the element\r\n * @param {function(any, Number): Boolean} predicate The function which determines whether to select an element\r\n * @returns {any}\r\n */\r\n first(collection: T[], predicate: General.Predicate): T;\r\n /**\r\n * Retrieves the first element in an enumerable collection which matches the predicate\r\n * @param {Object} collection The collection from which to retrieve the element\r\n * @param {function(any, String): Boolean} predicate The function which determines whether to select an element\r\n * @returns {any}\r\n */\r\n first(collection: { [key: string]: T }, predicate: General.Predicate): T;\r\n first(collection: T[]| { [key: string]: T }, predicate: General.Predicate): T {\r\n var result = null;\r\n\r\n _.each(collection,(value: T, key) => {\r\n if (predicate.call(this, value, key)) {\r\n result = value;\r\n return false;\r\n }\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Retrieves a number of elements from an enumerable collection which match the predicate\r\n * @param {any[]} collection The collection from which elements will be plucked\r\n * @param {function(any, Number): Boolean} predicate The function which determines the elements to be plucked\r\n * @returns {any[]}\r\n */\r\n select(collection: T[], predicate: General.Predicate): T[];\r\n /**\r\n * Retrieves a number of elements from an enumerable collection which match the predicate\r\n * @param {Object} collection The collection from which elements will be plucked\r\n * @param {function(any, String): Boolean} predicate The function which determines the elements to be plucked\r\n * @returns {Object}\r\n */\r\n select(collection: { [key: string]: T }, predicate: General.Predicate): { [key: string]: T };\r\n select(collection: T[]| { [key: string]: T }, predicate: General.Predicate): any {\r\n var isArray = Array.isArray(collection);\r\n var results: any = isArray ? [] : {};\r\n\r\n _.each(collection,(value: T, key) => {\r\n if (predicate.call(this, value, key)) {\r\n if (isArray) results.push(value);\r\n else results[key] = value;\r\n }\r\n });\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * Gets the JSON representation of this instance\r\n * @returns {TDocument}\r\n */\r\n toJSON(): any {\r\n return this.document;\r\n }\r\n\r\n /**\r\n * Gets a string representation of this instance\r\n * @returns {String}\r\n */\r\n toString(): string {\r\n return JSON.stringify(this.document, null, 2);\r\n }\r\n}"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/lib/Instance.ts b/lib/Instance.ts index 07a1397..545fd2d 100644 --- a/lib/Instance.ts +++ b/lib/Instance.ts @@ -123,8 +123,6 @@ export default class Instance { conditions = _.cloneDeep(conditions); _.merge(conditions, { _id: this._modified._id }); - conditions = this._model.helpers.transformToDB(conditions); - if (!changes) { var validation = this._model.helpers.validate(this._modified); if (validation.failed) return Bluebird.reject(validation.error).bind(this).nodeify(callback); @@ -160,23 +158,27 @@ export default class Instance { }); } }).then((changed: boolean) => { - conditions = this._model.helpers.convertToDB({ _id: this._modified._id }); - if (!changed) { - return _.cloneDeep(this._modified); - } + conditions = { _id: this._modified._id }; + if (!changed) return this._modified; return new Bluebird((resolve, reject) => { - this._model.collection.findOne(conditions,(err: Error, latest) => { + this._model.collection.findOne(conditions, (err: Error, latest) => { if (err) return reject(err); return resolve(latest); }); }); }).then((latest: TDocument) => { - return this._model.handlers.documentReceived(conditions, latest,(value) => { + if(!latest) { + this._isNew = true; + this._original = _.cloneDeep(this._modified); + return Bluebird.resolve(this); + } + + return this._model.handlers.documentReceived(conditions, latest, (value) => { this._isPartial = false; this._isNew = false; - this._original = value; - this._modified = _.clone(value); + this._modified = value; + this._original = _.cloneDeep(value); return this; }); }).nodeify(callback); diff --git a/test/Instance.ts b/test/Instance.ts index c09e31b..854306d 100644 --- a/test/Instance.ts +++ b/test/Instance.ts @@ -1,6 +1,7 @@ /// import * as Iridium from '../index'; import MongoDB = require('mongodb'); +import Bluebird = require('bluebird'); interface TestDocument { _id?: string; @@ -450,4 +451,48 @@ describe("Instance",() => { }); }); }); + + describe("after a save", () => { + var instance: Test; + + before(() => core.Test.remove().then(() => core.Test.insert({ answer: 1, lots: [1, 2, 3, 4], less: { 'a': 1, 'b': 2 } })).then(i => { + i.answer = 3; + return i.save(); + }).then(i => instance = i)); + + it("should return the instance", () => { + chai.expect(instance).to.exist; + }); + + it("should correctly diff simple property changes", () => { + return Bluebird.resolve(instance).then(i => { + i.answer = 2; + return i.save(); + }).then(i => { + chai.expect(i).to.exist; + chai.expect(i).to.have.property('answer', 2); + }); + }); + + it("should correctly diff deep property changes", () => { + return Bluebird.resolve(instance).then(i => { + i.less['a'] = 2; + return i.save(); + }).then(i => { + chai.expect(i).to.exist; + chai.expect(i).to.have.property('less').eql({ a: 2, b: 2 }); + }); + }); + + it("should correctly diff array operations", () => { + return Bluebird.resolve(instance).then(i => { + i.lots.push(5); + return i.save(); + }).then(i => { + chai.expect(i).to.exist; + chai.expect(i).to.have.property('lots').eql([1,2,3,4,5]); + }); + }); + + }); }); \ No newline at end of file