constructors/browser-session.js

/* jshint -W014 */
/* jshint -W002 */
var sessionDbConnection = false;
var dbConnectionBuilder 	= false;

/**
 * browserSessionBuilder description
 * @interface BrowserSessionModule
 * @param  {string|object} objectStoreArg name or object of strategyStore
 * @param {object} [objectStoreConf]
 */
var browserSessionBuilder	= function (objectStoreArg, objectStoreConf) {
	var app	= new ApplicationPrototype();
	var loader = Application.Promise();
	if (typeof(objectStoreArg) === "string") {
		var strategyName = objectStoreArg;
		objectStoreArg	= module.require('strategy/'+strategyName).then(function (strategyStore) {
			loader.resolve(new strategyStore(objectStoreConf));
		}, function (err) {
			loader.reject(err);
		});
	} else {
		if (typeof(objectStoreArg) === "object") {
			objectStoreArg.initialization.then(function () {
				loader.resolve(objectStoreArg);
			}, function (err) {
				loader.reject(err);
			});
		} else {
			loader.resolve(sessionDbConnection);
		}
	}
	loader.then(function (objectStore) {
		var newId	= ((function () {
			var k = 0;
			return function (p) {
				return (p || '')
					+ (new Date().valueOf().toString(36))
					+ '_'
					+ (++k).toString(36)
					+ '_'
					+ Math.floor(Math.random() * 100000000).toString(36);
			};
		})());
		;((function () {
			var sid = newId('sid_');
			app.bind("id", function () {
				return sid;
			}, "");
		})());
		app.bind("getItem",
			/**
			 * @method getItem
			 * @memberof BrowserSessionModule
			 * @param {string} key 
			 * @param {boolean} returnResult 
			 * @returns {Promise<any>}
			 */
			function (key, returnResult) {
			return new Application.Promise(function (resolve, reject) {
				objectStore.getItem(key).then(function (event) {
					resolve(
						(typeof(event.target.result) === "object" && event.target.result && !returnResult)
						? event.target.result.v : event.target.result
					);
				}, function (event) {
					reject(event);
				});
			});
		}, "");
		app.bind("setItem",
			/**
			 * @method setItem
			 * @memberof BrowserSessionModule
			 * @param {string} key 
			 * @param {any} val
			 * @param {boolean} returnResult 
			 * @returns {Promise<any>}
			 */
			function (key, val, returnResult) {
			return new Application.Promise(function (resolve, reject) {
				app.getItem(key, true).then(function (result) {
					var setValue = function () {
						objectStore.setItem(key, val).then(function (event) {
							resolve(
								(typeof(event.target.result) === "object" && event.target.result && !returnResult)
								? event.target.result.v : event.target.result
							);
							app.emit("setItem::"+key, [key, val]);
						}, function (event) {
							reject(event);
						});
					};
					if (typeof(result) !== undefined) {
						app.removeItem(key).then(function () {
							setValue();
						}, function (event) {
							reject(event);
						});
					} else {
						setValue();
					}
				}, function (event) {
					reject(event);
				});
			});
		});
		app.bind("removeItem",
			/**
			 * @method removeItem
			 * @memberof BrowserSessionModule
			 * @param {string} key 
			 * @param {boolean} returnResult 
			 * @returns {Promise<any>}
			 */
			function (key, returnResult) {
			return new Application.Promise(function (resolve, reject) {
				objectStore.removeItem(key).then(function (event) {
					resolve(
						(typeof(event.target.result) === "object" && event.target.result && !returnResult)
						? event.target.result.v : event.target.result
					);
					app.emit("removeItem::"+key, [key]);
				}, function (event) {
					reject(event);
				});
			});
		});
		app.bind("getItems",
			/**
			 * @method getItems
			 * @memberof BrowserSessionModule
			 * @param {string[]} keys
			 * @returns {Promise<Object<string,any>>}
			 */
			function (keys) {
			return new Application.Promise(function (resolve, reject) {
				Application.Promise.all(keys.map(function (key) {
					return app.getItem(key);
				})).then(function (values) {
					var result = {};
					keys.forEach(function (key, index) {
						result[key]	= values[index];
					});
					resolve(result);
				}, function (event) {
					reject(event);
				});
			});
		});

		app.bind("setItems",
			/**
			 * @method setItems
			 * @memberof BrowserSessionModule
			 * @param {Object<string,any>} obj
			 * @returns {Promise<any[]>}
			 */
			function (obj) {
			var i, arr = [];
			for (i in obj) {
				arr.push((function (key, value) {
					return app.setItem(key, value);
				})(i, obj[i]));
			}
			return Application.Promise.all(arr);
		});

		app.bind("removeItems",
			/**
			 * @method removeItems
			 * @memberof BrowserSessionModule
			 * @param {string[]} keys
			 * @returns {Promise<any[]>}
			 */
			function (keys) {
			return Application.Promise.all(keys.map(function (key) {
				return app.removeItem(key);
			}));
		});

		app.bind("findItems",
			/**
			 * @method findItems
			 * @memberof BrowserSessionModule
			 * @param {function(any):boolean} filter
			 * @returns {Promise<Object<string,any>>}
			 */
			function (filter) {
			return new Application.Promise(function (resolve, reject) {
				objectStore.filter(filter).then(function (event) {
					var result = {};
					event.target.result.forEach(function (row) {
						result[row.k] = row.v;
					});
					resolve(result);
				}, function (event) {
					reject(event);
				});
			});
		});


		app.bind("clear",
			/**
			 * @method clear
			 * @memberof BrowserSessionModule
			 * @returns {Promise<any>}
			 */
			function () {
			return new Application.Promise(function (resolve, reject) {
				objectStore.filter(function (k ,v) {
					var er;
					try {
						app.removeItem(k);
						return true;
					} catch (er) {}
				}).then(function (event) {
					var result = {};
					event.target.result.forEach(function (row) {
						result[row.k] = row.v;
					});
					resolve(result);
				}, function (event) {
					reject(event);
				});
			});
		});
	}, function (err) {
		console.error(err);
		app.emit('error', [err]);
	});
	return Application.Promise(function (resolve, reject) {
		loader.then(function (store) {
			resolve(app);
		}, function (err) {
			reject(err);
		})
	});
};

module.require('strategy/indexed-db').then(function (dbConnectionBuilder) {
	var loader = new Application.Promise();
	var _sessionConnection;
	var er;
	try {
		_sessionConnection	= dbConnectionBuilder({ name: "browserDefaultSession", table: "references" });
	} catch (er) {}

	_sessionConnection.initialization.then(function () {
		loader.resolve(_sessionConnection);
	}, function (err) {
		console.error(err);
		var er;
		try {
			console.warn("IndexDB not supported, fallback to localStorage or polyfill emulation");
			module.require('strategy/local-storage').then(function (strategyStore) {
				_sessionConnection	= strategyStore();
				_sessionConnection.initialization.then(function () {
					loader.resolve(_sessionConnection);
				}, function (event) {
					loader.reject(event);
				});
			}, function (err) {
				loader.reject(err);
			});
		} catch (er) {
			loader.reject(er);
		}
	});

	loader.then(function (_sessionConnection) {
		sessionDbConnection	= _sessionConnection;
		if (typeof(module) === "object" && module) {
			module.exports	= browserSessionBuilder;
		} else if (typeof(window) === "object" && window) {
			window.browserSession	= new browserSessionBuilder();
		}
	}, function (err) {
		console.error("browserSession Error", err);
	});


	// browserSessionBuilder.dbConnectionBuilder	= dbConnectionBuilder;
}).catch(function (reason) {
 console.error(reason);
});