Comparing version 0.3.3 to 0.3.4
@@ -1,1 +0,1 @@ | ||
!function e(t,r,n){function o(i,a){if(!r[i]){if(!t[i]){var l="function"==typeof require&&require;if(!a&&l)return l(i,!0);if(u)return u(i,!0);var s=new Error("Cannot find module '"+i+"'");throw s.code="MODULE_NOT_FOUND",s}var c=r[i]={exports:{}};t[i][0].call(c.exports,function(e){var r=t[i][1][e];return o(r?r:e)},c,c.exports,e,t,r,n)}return r[i].exports}for(var u="function"==typeof require&&require,i=0;i<n.length;i++)o(n[i]);return o}({1:[function(e,t,r){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(r,"__esModule",{value:!0});var u=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),i=e("./AngularCursorObservable"),a=n(i),l="undefined"!=typeof window&&window.Mars?window.Mars.Collection:e("../Collection")["default"],s=function(){function e(t,r,n){o(this,e),this.$q=n,this._collection=new l(t,r)}return u(e,[{key:"ensureIndex",value:function(){var e;return this.$q.resolve((e=this._collection).ensureIndex.apply(e,arguments))}},{key:"insert",value:function(){var e;return this.$q.resolve((e=this._collection).insert.apply(e,arguments))}},{key:"insertAll",value:function(){var e;return this.$q.resolve((e=this._collection).insertAll.apply(e,arguments))}},{key:"update",value:function(){var e;return this.$q.resolve((e=this._collection).update.apply(e,arguments))}},{key:"remove",value:function(){var e;return this.$q.resolve((e=this._collection).remove.apply(e,arguments))}},{key:"find",value:function(e){return new a["default"](this,e)}},{key:"findOne",value:function(){var e;return this.$q.resolve((e=this._collection).findOne.apply(e,arguments))}},{key:"count",value:function(){var e;return this.$q.resolve((e=this._collection).count.apply(e,arguments))}},{key:"ids",value:function(){var e;return this.$q.resolve((e=this._collection).ids.apply(e,arguments))}},{key:"modelName",get:function(){return this._collection.modelName}}]),e}();r.AngularCollection=s,r["default"]=s},{"../Collection":void 0,"./AngularCursorObservable":2}],2:[function(e,t,r){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(r,"__esModule",{value:!0});var u=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),i=function(e,t,r){for(var n=!0;n;){var o=e,u=t,i=r;a=s=l=void 0,n=!1,null===o&&(o=Function.prototype);var a=Object.getOwnPropertyDescriptor(o,u);if(void 0!==a){if("value"in a)return a.value;var l=a.get;return void 0===l?void 0:l.call(i)}var s=Object.getPrototypeOf(o);if(null===s)return void 0;e=s,t=u,r=i,n=!0}},a="undefined"!=typeof window&&window.Mars?window.Mars.CursorObservable:e("../CursorObservable")["default"],l=function(e){function t(e,r){n(this,t),i(Object.getPrototypeOf(t.prototype),"constructor",this).call(this,e._collection,r),this.$q=e.$q}return o(t,e),u(t,[{key:"observe",value:function(e,r){var n=i(Object.getPrototypeOf(t.prototype),"observe",this).call(this,e);return r&&r.$on("$destroy",function(){n.stop()}),n}},{key:"exec",value:function(){for(var e=arguments.length,r=Array(e),n=0;e>n;n++)r[n]=arguments[n];return this.$q.resolve(i(Object.getPrototypeOf(t.prototype),"exec",this).apply(this,r))}},{key:"ids",value:function(){for(var e=arguments.length,r=Array(e),n=0;e>n;n++)r[n]=arguments[n];return this.$q.resolve(i(Object.getPrototypeOf(t.prototype),"ids",this).apply(this,r))}},{key:"update",value:function(){for(var e=arguments.length,r=Array(e),n=0;e>n;n++)r[n]=arguments[n];return this.$q.resolve(i(Object.getPrototypeOf(t.prototype),"update",this).apply(this,r))}}]),t}(a);r.AngularCursorObservable=l,r["default"]=l},{"../CursorObservable":void 0}],3:[function(e,t,r){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}var o=e("./AngularCollection"),u=n(o),i="undefined"!=typeof window&&window.angular?window.angular:e("angular"),a="undefined"!=typeof window&&window.Mars?window.Mars.Collection:e("../Collection")["default"];i.module("MarsDB",[]).provider("$collection",function(){this.defaultStorageManager=function(e){return a.defaultStorageManager(e),this},this.defaultIdGenerator=function(e){return a.defaultIdGenerator(e),this};var e={};this.$get=["$q",function(t){return function(r){var n=arguments.length<=1||void 0===arguments[1]?{}:arguments[1];if(e[r]&&!n.noCache)return e[r];var o=new u["default"](r,n,t);return n.noCache||(e[r]=o),o}}]}),t["export"]="MarsDB"},{"../Collection":void 0,"./AngularCollection":1,angular:void 0}]},{},[3]); | ||
!function e(t,r,n){function o(i,a){if(!r[i]){if(!t[i]){var l="function"==typeof require&&require;if(!a&&l)return l(i,!0);if(u)return u(i,!0);var s=new Error("Cannot find module '"+i+"'");throw s.code="MODULE_NOT_FOUND",s}var c=r[i]={exports:{}};t[i][0].call(c.exports,function(e){var r=t[i][1][e];return o(r?r:e)},c,c.exports,e,t,r,n)}return r[i].exports}for(var u="function"==typeof require&&require,i=0;i<n.length;i++)o(n[i]);return o}({1:[function(e,t,r){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(r,"__esModule",{value:!0});var u=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),i=e("./AngularCursorObservable"),a=n(i),l="undefined"!=typeof window&&window.Mars?window.Mars.Collection:e("../Collection")["default"],s=function(){function e(t,r,n){o(this,e),this.$q=n,this._collection=new l(t,r)}return u(e,[{key:"ensureIndex",value:function(){var e;return this.$q.resolve((e=this._collection).ensureIndex.apply(e,arguments))}},{key:"insert",value:function(){var e;return this.$q.resolve((e=this._collection).insert.apply(e,arguments))}},{key:"insertAll",value:function(){var e;return this.$q.resolve((e=this._collection).insertAll.apply(e,arguments))}},{key:"update",value:function(){var e;return this.$q.resolve((e=this._collection).update.apply(e,arguments))}},{key:"remove",value:function(){var e;return this.$q.resolve((e=this._collection).remove.apply(e,arguments))}},{key:"find",value:function(e){return new a["default"](this,e)}},{key:"findOne",value:function(){var e;return this.$q.resolve((e=this._collection).findOne.apply(e,arguments))}},{key:"count",value:function(){var e;return this.$q.resolve((e=this._collection).count.apply(e,arguments))}},{key:"ids",value:function(){var e;return this.$q.resolve((e=this._collection).ids.apply(e,arguments))}},{key:"modelName",get:function(){return this._collection.modelName}}]),e}();r.AngularCollection=s,r["default"]=s},{"../Collection":void 0,"./AngularCursorObservable":2}],2:[function(e,t,r){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(r,"__esModule",{value:!0});var u=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),i=function(e,t,r){for(var n=!0;n;){var o=e,u=t,i=r;a=s=l=void 0,n=!1,null===o&&(o=Function.prototype);var a=Object.getOwnPropertyDescriptor(o,u);if(void 0!==a){if("value"in a)return a.value;var l=a.get;return void 0===l?void 0:l.call(i)}var s=Object.getPrototypeOf(o);if(null===s)return void 0;e=s,t=u,r=i,n=!0}},a="undefined"!=typeof window&&window.Mars?window.Mars.CursorObservable:e("../CursorObservable")["default"],l=function(e){function t(e,r){n(this,t),i(Object.getPrototypeOf(t.prototype),"constructor",this).call(this,e._collection,r),this.$q=e.$q}return o(t,e),u(t,[{key:"destroy",value:function(e){e&&e._prevStopper&&e._prevStopper.stop()}},{key:"observe",value:function(e,r){var n=i(Object.getPrototypeOf(t.prototype),"observe",this).call(this,e);return r&&r.$on("$destroy",function(){n.stop()}),this._prevStopper=n,n}},{key:"exec",value:function(){for(var e=arguments.length,r=Array(e),n=0;e>n;n++)r[n]=arguments[n];return this.$q.resolve(i(Object.getPrototypeOf(t.prototype),"exec",this).apply(this,r))}},{key:"ids",value:function(){for(var e=arguments.length,r=Array(e),n=0;e>n;n++)r[n]=arguments[n];return this.$q.resolve(i(Object.getPrototypeOf(t.prototype),"ids",this).apply(this,r))}},{key:"update",value:function(){for(var e=arguments.length,r=Array(e),n=0;e>n;n++)r[n]=arguments[n];return this.$q.resolve(i(Object.getPrototypeOf(t.prototype),"update",this).apply(this,r))}}]),t}(a);r.AngularCursorObservable=l,r["default"]=l},{"../CursorObservable":void 0}],3:[function(e,t,r){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}var o=e("./AngularCollection"),u=n(o),i="undefined"!=typeof window&&window.angular?window.angular:e("angular"),a="undefined"!=typeof window&&window.Mars?window.Mars.Collection:e("../Collection")["default"];i.module("MarsDB",[]).provider("$collection",function(){this.defaultStorageManager=function(e){return a.defaultStorageManager(e),this},this.defaultIdGenerator=function(e){return a.defaultIdGenerator(e),this};var e={};this.$get=["$q",function(t){return function(r){var n=arguments.length<=1||void 0===arguments[1]?{}:arguments[1];if(e[r]&&!n.noCache)return e[r];var o=new u["default"](r,n,t);return n.noCache||(e[r]=o),o}}]}),t["export"]="MarsDB"},{"../Collection":void 0,"./AngularCollection":1,angular:void 0}]},{},[3]); |
@@ -27,3 +27,31 @@ 'use strict'; | ||
/** | ||
* Stop observing given cursor, if passed and | ||
* observing. | ||
* It might be useful when you need to replace | ||
* previously created request with another one | ||
* (with different query, for example). | ||
* | ||
* @param {CursorObservable} cursor | ||
*/ | ||
_createClass(AngularCursorObservable, [{ | ||
key: 'destroy', | ||
value: function destroy(cursor) { | ||
if (cursor && cursor._prevStopper) { | ||
cursor._prevStopper.stop(); | ||
} | ||
} | ||
/** | ||
* Original `observe` with one additional argument. | ||
* Second argument, if passed, a $scope for tracking | ||
* $destroy event and stopping observing when event | ||
* emited. | ||
* | ||
* @param {Function} fn | ||
* @param {Scope} $scope | ||
* @return {Stooper} | ||
*/ | ||
}, { | ||
key: 'observe', | ||
@@ -37,2 +65,4 @@ value: function observe(fn, $scope) { | ||
} | ||
this._prevStopper = stopper; | ||
return stopper; | ||
@@ -39,0 +69,0 @@ } |
@@ -54,2 +54,3 @@ 'use strict'; | ||
Map: null, | ||
Aggregate: null, | ||
Reduce: null, | ||
@@ -66,7 +67,19 @@ Join: null | ||
return docs.map(pipeObj.value); | ||
}), _defineProperty(_PIPELINE_PROCESSORS, PIPELINE_TYPE.Aggregate, function (docs, pipeObj) { | ||
return pipeObj.value(docs); | ||
}), _defineProperty(_PIPELINE_PROCESSORS, PIPELINE_TYPE.Reduce, function (docs, pipeObj) { | ||
return docs.reduce(pipeObj.value, pipeObj.args[0]); | ||
}), _defineProperty(_PIPELINE_PROCESSORS, PIPELINE_TYPE.Join, function (docs, pipeObj) { | ||
}), _defineProperty(_PIPELINE_PROCESSORS, PIPELINE_TYPE.Join, function (docs, pipeObj, cursor) { | ||
return Promise.all(docs.map(function (x) { | ||
return pipeObj.value(x); | ||
var res = pipeObj.value(x); | ||
if (cursor._observing && res && res.__onceJustUpdated) { | ||
(0, _invariant2['default'])(!res.__haveListeners, 'joins(...): for using observable joins `observe` must be called without arguments'); | ||
res.__onceJustUpdated(function () { | ||
res.stop(); | ||
cursor.update(); | ||
}); | ||
} | ||
return res; | ||
})); | ||
@@ -167,3 +180,6 @@ }), _PIPELINE_PROCESSORS); | ||
value: function aggregate(aggrFn) { | ||
return this.map(aggrFn); | ||
(0, _invariant2['default'])(typeof aggrFn === 'function', 'aggregate(...): aggregator must be a function'); | ||
this.addPipeline(PIPELINE_TYPE.Aggregate, aggrFn); | ||
return this; | ||
} | ||
@@ -206,3 +222,3 @@ }, { | ||
} else { | ||
return Promise.resolve(PIPELINE_PROCESSORS[pipeObj.type](docs, pipeObj)).then(function (result) { | ||
return Promise.resolve(PIPELINE_PROCESSORS[pipeObj.type](docs, pipeObj, this)).then(function (result) { | ||
return _this.processPipeline(result, i + 1); | ||
@@ -209,0 +225,0 @@ }); |
@@ -9,3 +9,3 @@ 'use strict'; | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
@@ -51,2 +51,12 @@ exports.debounce = debounce; | ||
/** | ||
* Change a batch size of updater. | ||
* Btach size is a number of changes must be happen | ||
* in debounce interval to force execute debounced | ||
* function (update a result, in our case) | ||
* | ||
* @param {Number} batchSize | ||
* @return {CursorObservable} | ||
*/ | ||
_createClass(CursorObservable, [{ | ||
@@ -58,2 +68,8 @@ key: 'batchSize', | ||
} | ||
/** | ||
* Change debounce wait time of the updater | ||
* @param {Number} waitTime | ||
* @return {CursorObservable} | ||
*/ | ||
}, { | ||
@@ -65,2 +81,12 @@ key: 'debounce', | ||
} | ||
/** | ||
* Observe changes of the cursor. | ||
* It returns a Stopper – Promise with `stop` function. | ||
* It is been resolved when first result of cursor is ready and | ||
* after first observe listener call. | ||
* | ||
* @param {Function} | ||
* @return {Stopper} | ||
*/ | ||
}, { | ||
@@ -72,3 +98,7 @@ key: 'observe', | ||
// Listen for changes of the cursor | ||
this.on('update', listener); | ||
this._observing = true; | ||
this._haveListeners = this._haveListeners || !!listener; | ||
if (listener) { | ||
this.on('update', listener); | ||
} | ||
@@ -84,11 +114,18 @@ // Make new wrapper for make possible to observe | ||
var firstUpdatePromise = this.update(); | ||
var firstUpdatePromise = this.update(true); | ||
var stopper = function () { | ||
_this.removeListener('update', listener); | ||
_this.db.removeListener('insert', updateWrapper); | ||
_this.db.removeListener('update', updateWrapper); | ||
_this.db.removeListener('remove', updateWrapper); | ||
if (listener) { | ||
_this.removeListener('update', listener); | ||
} | ||
}; | ||
var createStoppablePromise = function (currPromise) { | ||
// __onceUpdate is used when we do not need to know | ||
// a new result of a cursor, but just need to know | ||
// absout some changes happen. Used in observable joins. | ||
return { | ||
__haveListeners: _this._haveListeners, // must be false | ||
__onceJustUpdated: _this.once.bind(_this, 'justUpdated'), | ||
stop: stopper, | ||
@@ -103,2 +140,9 @@ then: function (successFn, failFn) { | ||
} | ||
/** | ||
* Update a cursor result. Debounced function, | ||
* return a Promise that resolved when cursor | ||
* is updated. | ||
* @return {Promise} | ||
*/ | ||
}, { | ||
@@ -109,10 +153,21 @@ key: 'update', | ||
return this.exec().then(function (result) { | ||
_this2._latestResult = result; | ||
_this2._latestIds = new Set(result.map(function (x) { | ||
return x._id; | ||
})); | ||
_this2.emit('update', result); | ||
return result; | ||
}); | ||
var firstRun = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0]; | ||
if (!this._haveListeners && !firstRun) { | ||
// Fast path for just notifying about some changes | ||
// happen when no listeners to `observe` provided | ||
// and it's not a first run (initial data). | ||
// It's used in observable joins | ||
this.emit('justUpdated', null, firstRun); | ||
return Promise.resolve(); | ||
} else { | ||
return this.exec().then(function (result) { | ||
_this2._latestResult = result; | ||
_this2._latestIds = new Set(result.map(function (x) { | ||
return x._id; | ||
})); | ||
_this2.emit('update', result, firstRun); | ||
return result; | ||
}); | ||
} | ||
} | ||
@@ -119,0 +174,0 @@ |
@@ -11,2 +11,27 @@ const CursorObservable = typeof window !== 'undefined' && window.Mars | ||
/** | ||
* Stop observing given cursor, if passed and | ||
* observing. | ||
* It might be useful when you need to replace | ||
* previously created request with another one | ||
* (with different query, for example). | ||
* | ||
* @param {CursorObservable} cursor | ||
*/ | ||
destroy(cursor) { | ||
if (cursor && cursor._prevStopper) { | ||
cursor._prevStopper.stop(); | ||
} | ||
} | ||
/** | ||
* Original `observe` with one additional argument. | ||
* Second argument, if passed, a $scope for tracking | ||
* $destroy event and stopping observing when event | ||
* emited. | ||
* | ||
* @param {Function} fn | ||
* @param {Scope} $scope | ||
* @return {Stooper} | ||
*/ | ||
observe(fn, $scope) { | ||
@@ -19,2 +44,4 @@ const stopper = super.observe(fn); | ||
} | ||
this._prevStopper = stopper; | ||
return stopper; | ||
@@ -21,0 +48,0 @@ } |
@@ -15,2 +15,3 @@ import _each from 'lodash/collection/each'; | ||
Map: null, | ||
Aggregate: null, | ||
Reduce: null, | ||
@@ -30,8 +31,24 @@ Join: null, | ||
}, | ||
[PIPELINE_TYPE.Aggregate]: (docs, pipeObj) => { | ||
return pipeObj.value(docs); | ||
}, | ||
[PIPELINE_TYPE.Reduce]: (docs, pipeObj) => { | ||
return docs.reduce(pipeObj.value, pipeObj.args[0]); | ||
}, | ||
[PIPELINE_TYPE.Join]: (docs, pipeObj) => { | ||
[PIPELINE_TYPE.Join]: (docs, pipeObj, cursor) => { | ||
return Promise.all(docs.map(x => { | ||
return pipeObj.value(x); | ||
const res = pipeObj.value(x); | ||
if (cursor._observing && res && res.__onceJustUpdated) { | ||
invariant( | ||
!res.__haveListeners, | ||
'joins(...): for using observable joins `observe` must be called without arguments' | ||
); | ||
res.__onceJustUpdated(() => { | ||
res.stop(); | ||
cursor.update(); | ||
}); | ||
} | ||
return res; | ||
})); | ||
@@ -143,3 +160,9 @@ }, | ||
aggregate(aggrFn) { | ||
return this.map(aggrFn); | ||
invariant( | ||
typeof aggrFn === 'function', | ||
'aggregate(...): aggregator must be a function' | ||
); | ||
this.addPipeline(PIPELINE_TYPE.Aggregate, aggrFn); | ||
return this; | ||
} | ||
@@ -179,3 +202,3 @@ | ||
return Promise.resolve( | ||
PIPELINE_PROCESSORS[pipeObj.type](docs, pipeObj) | ||
PIPELINE_PROCESSORS[pipeObj.type](docs, pipeObj, this) | ||
).then((result) => { | ||
@@ -182,0 +205,0 @@ return this.processPipeline(result, i + 1); |
@@ -15,2 +15,11 @@ import Cursor from './Cursor'; | ||
/** | ||
* Change a batch size of updater. | ||
* Btach size is a number of changes must be happen | ||
* in debounce interval to force execute debounced | ||
* function (update a result, in our case) | ||
* | ||
* @param {Number} batchSize | ||
* @return {CursorObservable} | ||
*/ | ||
batchSize(batchSize) { | ||
@@ -21,2 +30,7 @@ this.update.updateBatchSize(batchSize); | ||
/** | ||
* Change debounce wait time of the updater | ||
* @param {Number} waitTime | ||
* @return {CursorObservable} | ||
*/ | ||
debounce(waitTime) { | ||
@@ -27,5 +41,18 @@ this.update.updateWait(waitTime); | ||
/** | ||
* Observe changes of the cursor. | ||
* It returns a Stopper – Promise with `stop` function. | ||
* It is been resolved when first result of cursor is ready and | ||
* after first observe listener call. | ||
* | ||
* @param {Function} | ||
* @return {Stopper} | ||
*/ | ||
observe(listener) { | ||
// Listen for changes of the cursor | ||
this.on('update', listener); | ||
this._observing = true; | ||
this._haveListeners = this._haveListeners || !!listener; | ||
if (listener) { | ||
this.on('update', listener); | ||
} | ||
@@ -39,11 +66,18 @@ // Make new wrapper for make possible to observe | ||
const firstUpdatePromise = this.update(); | ||
const firstUpdatePromise = this.update(true); | ||
const stopper = () => { | ||
this.removeListener('update', listener); | ||
this.db.removeListener('insert', updateWrapper); | ||
this.db.removeListener('update', updateWrapper); | ||
this.db.removeListener('remove', updateWrapper); | ||
if (listener) { | ||
this.removeListener('update', listener); | ||
} | ||
}; | ||
const createStoppablePromise = (currPromise) => { | ||
// __onceUpdate is used when we do not need to know | ||
// a new result of a cursor, but just need to know | ||
// absout some changes happen. Used in observable joins. | ||
return { | ||
__haveListeners: this._haveListeners, // must be false | ||
__onceJustUpdated: this.once.bind(this, 'justUpdated'), | ||
stop: stopper, | ||
@@ -59,9 +93,24 @@ then: function(successFn, failFn) { | ||
update() { | ||
return this.exec().then((result) => { | ||
this._latestResult = result; | ||
this._latestIds = new Set(result.map(x => x._id)); | ||
this.emit('update', result); | ||
return result; | ||
}); | ||
/** | ||
* Update a cursor result. Debounced function, | ||
* return a Promise that resolved when cursor | ||
* is updated. | ||
* @return {Promise} | ||
*/ | ||
update(firstRun = false) { | ||
if (!this._haveListeners && !firstRun) { | ||
// Fast path for just notifying about some changes | ||
// happen when no listeners to `observe` provided | ||
// and it's not a first run (initial data). | ||
// It's used in observable joins | ||
this.emit('justUpdated', null, firstRun); | ||
return Promise.resolve(); | ||
} else { | ||
return this.exec().then((result) => { | ||
this._latestResult = result; | ||
this._latestIds = new Set(result.map(x => x._id)); | ||
this.emit('update', result, firstRun); | ||
return result; | ||
}); | ||
} | ||
} | ||
@@ -68,0 +117,0 @@ |
{ | ||
"name": "marsdb", | ||
"version": "0.3.3", | ||
"version": "0.3.4", | ||
"author": { | ||
@@ -5,0 +5,0 @@ "name": "Artem Artemev", |
@@ -24,5 +24,5 @@ <div style="text-align:center"><img src="https://static.studytime.me/marsdb.png" /></div> | ||
* **Flexible pipeline** – map, reduce, custom sorting function, filtering. All with a sexy JS interface (no ugly mongo’s aggregation language) | ||
* **Joinable cursor** – joining one object with another can’t be simplier | ||
* **Persistence API** – all collections can be stored (and restored) with any kind of storage (in-memory, LocalStorage, LevelUP, etc) | ||
* **Live queries** - just like in Meteor, but with simplier interface | ||
* **Observable queries** - live queries just like in Meteor, but with simplier interface | ||
* **Joinable cursor** – joins is simple, joins is observable (live) | ||
@@ -115,3 +115,2 @@ ## Examples | ||
### Find with joins | ||
Joined objects is not obervable yet. | ||
```javascript | ||
@@ -122,4 +121,7 @@ const users = new Collection(‘users’); | ||
.join(doc => { | ||
// Return a Promise for waiting of the result | ||
return users.findOne(doc.authorId).then(user => { | ||
// Return a Promise for waiting of the result. | ||
// Calling `observe` makes result of root query depends | ||
// on chnages of results of this query. So, when author | ||
// object changed root result is updated (yeah!) | ||
return users.findOne(doc.authorId).observe().then(user => { | ||
doc.authorObj = user; | ||
@@ -136,2 +138,5 @@ return doc; | ||
return doc; | ||
}) | ||
.observe((posts) => { | ||
// do somethin wiht posts with authors | ||
}); | ||
@@ -138,0 +143,0 @@ ``` |
@@ -266,11 +266,7 @@ import Collection from '../../lib/Collection'; | ||
const cursor = new Cursor(db); | ||
cursor.find().sort({b: 1}).aggregate(d => { | ||
return {b: d.b * 2}; | ||
cursor.find().sort({b: 1}).aggregate(docs => { | ||
return docs.length; | ||
}); | ||
return cursor.exec().then((docs) => { | ||
docs.should.have.length(7); | ||
docs[0].should.not.have.ownProperty('a'); | ||
docs[1].should.not.have.ownProperty('a'); | ||
docs[0].b.should.be.equals(2); | ||
docs[1].b.should.be.equals(4); | ||
docs.should.be.equals(7); | ||
}); | ||
@@ -277,0 +273,0 @@ }); |
@@ -101,2 +101,26 @@ import Collection from '../../lib/Collection'; | ||
}); | ||
it('should work nice with observable joins', function (done) { | ||
var calls = 0; | ||
db.find({$or: [{f: 1}, {f: 2}]}) | ||
.join((doc) => { | ||
return db.find({b: 30}).observe().then(res => { | ||
doc.joined = res; | ||
return doc; | ||
}); | ||
}).observe(res => { | ||
if (calls === 0) { | ||
expect(res).to.be.an('array'); | ||
res.should.have.length(2); | ||
expect(res[0].joined).to.have.length(0); | ||
expect(res[1].joined).to.have.length(0); | ||
db.insert({b: 30}); | ||
calls += 1; | ||
} else if (calls === 1) { | ||
expect(res[0].joined).to.have.length(1); | ||
expect(res[1].joined).to.have.length(1); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}); | ||
@@ -103,0 +127,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
24530
187
1052513
92