diff --git a/src/Model/mutators.ts b/src/Model/mutators.ts index b9029ade..55b4789e 100644 --- a/src/Model/mutators.ts +++ b/src/Model/mutators.ts @@ -10,6 +10,8 @@ var RemoveEvent = mutationEvents.RemoveEvent; var MoveEvent = mutationEvents.MoveEvent; var promisify = util.promisify; +type ValueCallback = ((error: Error | null | undefined, value: T) => void); + declare module './Model' { interface Model { _mutate(segments, fn, cb): void; @@ -43,11 +45,11 @@ declare module './Model' { createNullPromised(subpath: Path, value: any): Promise; _createNull(segments: Segments, value: any, cb?: ErrorCallback): void; - add(value: any, cb?: ErrorCallback): string; - add(subpath: Path, value: any, cb?: ErrorCallback): string; + add(value: any, cb?: ValueCallback): string; + add(subpath: Path, value: any, cb?: ValueCallback): string; addPromised(value: any): Promise; addPromised(subpath: Path, value: any): Promise; - _add(segments: Segments, value: any, cb?: ErrorCallback): string; + _add(segments: Segments, value: any, cb?: ValueCallback): string; /** * Deletes the value at this model's path or a relative subpath. @@ -404,20 +406,23 @@ Model.prototype.add = function() { var segments = this._splitPath(subpath); return this._add(segments, value, cb); }; -Model.prototype.addPromised = promisify(Model.prototype.add); +Model.prototype.addPromised = promisify(Model.prototype.add); Model.prototype._add = function(segments, value, cb) { if (typeof value !== 'object') { - var message = 'add requires an object value. Invalid value: ' + value; - cb = this.wrapCallback(cb); - return cb(new Error(message)); + let message = 'add requires an object value. Invalid value: ' + value; + const errorCallback = this.wrapCallback(cb); + errorCallback(new Error(message)); + return; } - var id = value.id || this.id(); + + const id = value.id || this.id(); value.id = id; segments = this._dereference(segments.concat(id)); - var model = this; + const model = this; + function add(doc, docSegments, fnCb) { - var previous; + let previous; if (docSegments.length) { previous = doc.set(docSegments, value, fnCb); } else { @@ -426,10 +431,15 @@ Model.prototype._add = function(segments, value, cb) { // it being stored in the database by ShareJS value = doc.get(); } - var event = new ChangeEvent(value, previous, model._pass); + const event = new ChangeEvent(value, previous, model._pass); model._emitMutation(segments, event); } - this._mutate(segments, add, cb); + + const callbackWithId = (cb != null) + ? (err: Error) => { cb(err, id); } + : null; + + this._mutate(segments, add, callbackWithId); return id; }; diff --git a/test/Model/mutators.js b/test/Model/mutators.js new file mode 100644 index 00000000..589ba3d9 --- /dev/null +++ b/test/Model/mutators.js @@ -0,0 +1,23 @@ +const {expect} = require('chai'); +const {RootModel} = require('../../lib/Model'); + +describe('mutators', () => { + describe('add', () => { + const guidRegExp = new RegExp(/[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}/); + it('returns created id in callback', () => { + const model = new RootModel(); + model.add('_test_doc', {name: 'foo'}, (error, id) => { + expect(error).to.not.exist; + expect(id).not.to.be.undefined; + expect(id).to.match(guidRegExp, 'Expected a GUID-like Id'); + }); + }); + + it('resolves promised add with id', async () => { + const model = new RootModel(); + const id = await model.addPromised('_test_doc', {name: 'bar'}); + expect(id).not.to.be.undefined; + expect(id).to.match(guidRegExp, 'Expected a GUID-like Id'); + }); + }); +});