Commit effc66a8 authored by Tristan Cavelier's avatar Tristan Cavelier

localstorage.js amd compatible now

parent b56a8a06
/* /*
* Copyright 2013, Nexedi SA * Copyright 2013, Nexedi SA
* Released under the LGPL license. * Released under the LGPL license.
* http://www.gnu.org/licenses/lgpl.html * http://www.gnu.org/licenses/lgpl.html
*/ */
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */ /*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global jIO: true, localStorage: true, setTimeout: true, /*global jIO: true, localStorage: true, setTimeout: true,
complex_queries: true */ complex_queries, define */
/** /**
* JIO Local Storage. Type = 'local'. * JIO Local Storage. Type = 'local'.
...@@ -43,395 +43,413 @@ ...@@ -43,395 +43,413 @@
* *
* @class LocalStorage * @class LocalStorage
*/ */
jIO.addStorageType('local', function (spec, my) {
spec = spec || {};
var that, priv, localstorage;
that = my.basicStorage(spec, my);
priv = {};
/* // define([module_name], [dependencies], module);
* Wrapper for the localStorage used to simplify instion of any kind of (function (dependencies, module) {
* values "use strict";
*/ if (typeof define === 'function' && define.amd) {
localstorage = { return define(dependencies, module);
getItem: function (item) { }
var value = localStorage.getItem(item); module(jIO, complex_queries);
return value === null ? null : JSON.parse(value); }(['jio', 'complex_queries'], function (jIO, complex_queries) {
}, "use strict";
setItem: function (item, value) {
return localStorage.setItem(item, JSON.stringify(value));
},
removeItem: function (item) {
return localStorage.removeItem(item);
}
};
// attributes jIO.addStorageType('local', function (spec, my) {
priv.username = spec.username || '';
priv.application_name = spec.application_name || 'untitled';
priv.localpath = 'jio/localstorage/' + priv.username + '/' + spec = spec || {};
priv.application_name; var that, priv, localstorage;
that = my.basicStorage(spec, my);
priv = {};
// ==================== Tools ==================== /*
/** * Wrapper for the localStorage used to simplify instion of any kind of
* Generate a new uuid * values
* @method generateUuid */
* @return {string} The new uuid localstorage = {
*/ getItem: function (item) {
priv.generateUuid = function () { var value = localStorage.getItem(item);
var S4 = function () { return value === null ? null : JSON.parse(value);
/* 65536 */ },
var i, string = Math.floor( setItem: function (item, value) {
Math.random() * 0x10000 return localStorage.setItem(item, JSON.stringify(value));
).toString(16); },
for (i = string.length; i < 4; i += 1) { removeItem: function (item) {
string = '0' + string; return localStorage.removeItem(item);
} }
return string;
}; };
return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() +
S4() + S4();
};
/** // attributes
* Checks if an object has no enumerable keys priv.username = spec.username || '';
* @method objectIsEmpty priv.application_name = spec.application_name || 'untitled';
* @param {object} obj The object
* @return {boolean} true if empty, else false priv.localpath = 'jio/localstorage/' + priv.username + '/' +
*/ priv.application_name;
priv.objectIsEmpty = function (obj) {
var k;
for (k in obj) {
if (obj.hasOwnProperty(k)) {
return false;
}
}
return true;
};
// ===================== overrides ====================== // ==================== Tools ====================
that.specToStore = function () { /**
return { * Generate a new uuid
"application_name": priv.application_name, * @method generateUuid
"username": priv.username * @return {string} The new uuid
*/
priv.generateUuid = function () {
var S4 = function () {
/* 65536 */
var i, string = Math.floor(
Math.random() * 0x10000
).toString(16);
for (i = string.length; i < 4; i += 1) {
string = '0' + string;
}
return string;
};
return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() +
S4() + S4();
}; };
};
that.validateState = function () { /**
if (typeof priv.username === "string" && priv.username !== '') { * Checks if an object has no enumerable keys
return ''; * @method objectIsEmpty
} * @param {object} obj The object
return 'Need at least one parameter: "username".'; * @return {boolean} true if empty, else false
}; */
priv.objectIsEmpty = function (obj) {
var k;
for (k in obj) {
if (obj.hasOwnProperty(k)) {
return false;
}
}
return true;
};
// ===================== overrides ======================
that.specToStore = function () {
return {
"application_name": priv.application_name,
"username": priv.username
};
};
// ==================== commands ==================== that.validateState = function () {
/** if (typeof priv.username === "string" && priv.username !== '') {
* Create a document in local storage. return '';
* @method post
* @param {object} command The JIO command
*/
that.post = function (command) {
setTimeout(function () {
var doc, doc_id = command.getDocId();
if (!doc_id) {
doc_id = priv.generateUuid();
} }
doc = localstorage.getItem(priv.localpath + "/" + doc_id); return 'Need at least one parameter: "username".';
if (doc === null) { };
// the document does not exist
doc = command.cloneDoc(); // ==================== commands ====================
doc._id = doc_id; /**
delete doc._attachments; * Create a document in local storage.
localstorage.setItem(priv.localpath + "/" + doc_id, doc); * @method post
* @param {object} command The JIO command
*/
that.post = function (command) {
setTimeout(function () {
var doc, doc_id = command.getDocId();
if (!doc_id) {
doc_id = priv.generateUuid();
}
doc = localstorage.getItem(priv.localpath + "/" + doc_id);
if (doc === null) {
// the document does not exist
doc = command.cloneDoc();
doc._id = doc_id;
delete doc._attachments;
localstorage.setItem(priv.localpath + "/" + doc_id, doc);
that.success({
"ok": true,
"id": doc_id
});
} else {
// the document already exists
that.error({
"status": 409,
"statusText": "Conflicts",
"error": "conflicts",
"message": "Cannot create a new document",
"reason": "Document already exists"
});
}
});
};
/**
* Create or update a document in local storage.
* @method put
* @param {object} command The JIO command
*/
that.put = function (command) {
setTimeout(function () {
var doc, tmp;
doc = localstorage.getItem(priv.localpath + "/" + command.getDocId());
if (doc === null) {
// the document does not exist
doc = command.cloneDoc();
delete doc._attachments;
} else {
// the document already exists
tmp = command.cloneDoc();
tmp._attachments = doc._attachments;
doc = tmp;
}
// write
localstorage.setItem(priv.localpath + "/" + command.getDocId(), doc);
that.success({ that.success({
"ok": true, "ok": true,
"id": doc_id "id": command.getDocId()
});
} else {
// the document already exists
that.error({
"status": 409,
"statusText": "Conflicts",
"error": "conflicts",
"message": "Cannot create a new document",
"reason": "Document already exists"
}); });
}
});
};
/**
* Create or update a document in local storage.
* @method put
* @param {object} command The JIO command
*/
that.put = function (command) {
setTimeout(function () {
var doc, tmp;
doc = localstorage.getItem(priv.localpath + "/" + command.getDocId());
if (doc === null) {
// the document does not exist
doc = command.cloneDoc();
delete doc._attachments;
} else {
// the document already exists
tmp = command.cloneDoc();
tmp._attachments = doc._attachments;
doc = tmp;
}
// write
localstorage.setItem(priv.localpath + "/" + command.getDocId(), doc);
that.success({
"ok": true,
"id": command.getDocId()
}); });
}); };
};
/** /**
* Add an attachment to a document * Add an attachment to a document
* @method putAttachment * @method putAttachment
* @param {object} command The JIO command * @param {object} command The JIO command
*/ */
that.putAttachment = function (command) { that.putAttachment = function (command) {
setTimeout(function () { setTimeout(function () {
var doc; var doc;
doc = localstorage.getItem(priv.localpath + "/" + command.getDocId()); doc = localstorage.getItem(priv.localpath + "/" + command.getDocId());
if (doc === null) { if (doc === null) {
// the document does not exist // the document does not exist
that.error({ that.error({
"status": 404, "status": 404,
"statusText": "Not Found", "statusText": "Not Found",
"error": "not_found", "error": "not_found",
"message": "Impossible to add attachment", "message": "Impossible to add attachment",
"reason": "Document not found" "reason": "Document not found"
}); });
return; return;
} }
// the document already exists // the document already exists
doc._attachments = doc._attachments || {}; doc._attachments = doc._attachments || {};
doc._attachments[command.getAttachmentId()] = { doc._attachments[command.getAttachmentId()] = {
"content_type": command.getAttachmentMimeType(), "content_type": command.getAttachmentMimeType(),
"digest": "md5-" + command.md5SumAttachmentData(), "digest": "md5-" + command.md5SumAttachmentData(),
"length": command.getAttachmentLength() "length": command.getAttachmentLength()
}; };
// upload data // upload data
localstorage.setItem(priv.localpath + "/" + command.getDocId() + "/" + localstorage.setItem(priv.localpath + "/" + command.getDocId() + "/" +
command.getAttachmentId(), command.getAttachmentId(),
command.getAttachmentData()); command.getAttachmentData());
// write document // write document
localstorage.setItem(priv.localpath + "/" + command.getDocId(), doc); localstorage.setItem(priv.localpath + "/" + command.getDocId(), doc);
that.success({ that.success({
"ok": true, "ok": true,
"id": command.getDocId(), "id": command.getDocId(),
"attachment": command.getAttachmentId() "attachment": command.getAttachmentId()
});
}); });
}); };
};
/** /**
* Get a document * Get a document
* @method get * @method get
* @param {object} command The JIO command * @param {object} command The JIO command
*/ */
that.get = function (command) { that.get = function (command) {
setTimeout(function () { setTimeout(function () {
var doc = localstorage.getItem(priv.localpath + "/" + command.getDocId()); var doc = localstorage.getItem(
if (doc !== null) { priv.localpath + "/" + command.getDocId()
that.success(doc); );
} else { if (doc !== null) {
that.error({ that.success(doc);
"status": 404, } else {
"statusText": "Not Found", that.error({
"error": "not_found", "status": 404,
"message": "Cannot find the document", "statusText": "Not Found",
"reason": "Document does not exist" "error": "not_found",
}); "message": "Cannot find the document",
} "reason": "Document does not exist"
}); });
}; }
});
};
/** /**
* Get a attachment * Get a attachment
* @method getAttachment * @method getAttachment
* @param {object} command The JIO command * @param {object} command The JIO command
*/ */
that.getAttachment = function (command) { that.getAttachment = function (command) {
setTimeout(function () { setTimeout(function () {
var doc = localstorage.getItem(priv.localpath + "/" + command.getDocId() + var doc = localstorage.getItem(
"/" + command.getAttachmentId()); priv.localpath + "/" + command.getDocId() +
if (doc !== null) { "/" + command.getAttachmentId()
that.success(doc); );
} else { if (doc !== null) {
that.error({ that.success(doc);
"status": 404, } else {
"statusText": "Not Found", that.error({
"error": "not_found", "status": 404,
"message": "Cannot find the attachment", "statusText": "Not Found",
"reason": "Attachment does not exist" "error": "not_found",
}); "message": "Cannot find the attachment",
} "reason": "Attachment does not exist"
}); });
}; }
});
};
/** /**
* Remove a document * Remove a document
* @method remove * @method remove
* @param {object} command The JIO command * @param {object} command The JIO command
*/ */
that.remove = function (command) { that.remove = function (command) {
setTimeout(function () { setTimeout(function () {
var doc, i, attachment_list; var doc, i, attachment_list;
doc = localstorage.getItem(priv.localpath + "/" + command.getDocId()); doc = localstorage.getItem(priv.localpath + "/" + command.getDocId());
attachment_list = []; attachment_list = [];
if (doc !== null && typeof doc === "object") { if (doc !== null && typeof doc === "object") {
if (typeof doc._attachments === "object") { if (typeof doc._attachments === "object") {
// prepare list of attachments // prepare list of attachments
for (i in doc._attachments) { for (i in doc._attachments) {
if (doc._attachments.hasOwnProperty(i)) { if (doc._attachments.hasOwnProperty(i)) {
attachment_list.push(i); attachment_list.push(i);
}
} }
} }
} else {
return that.error({
"status": 404,
"statusText": "Not Found",
"error": "not_found",
"message": "Document not found",
"reason": "missing"
});
} }
} else { localstorage.removeItem(priv.localpath + "/" + command.getDocId());
return that.error({ // delete all attachments
"status": 404, for (i = 0; i < attachment_list.length; i += 1) {
"statusText": "Not Found", localstorage.removeItem(priv.localpath + "/" + command.getDocId() +
"error": "not_found", "/" + attachment_list[i]);
"message": "Document not found", }
"reason": "missing" that.success({
"ok": true,
"id": command.getDocId()
}); });
}
localstorage.removeItem(priv.localpath + "/" + command.getDocId());
// delete all attachments
for (i = 0; i < attachment_list.length; i += 1) {
localstorage.removeItem(priv.localpath + "/" + command.getDocId() +
"/" + attachment_list[i]);
}
that.success({
"ok": true,
"id": command.getDocId()
}); });
}); };
};
/** /**
* Remove an attachment * Remove an attachment
* @method removeAttachment * @method removeAttachment
* @param {object} command The JIO command * @param {object} command The JIO command
*/ */
that.removeAttachment = function (command) { that.removeAttachment = function (command) {
setTimeout(function () { setTimeout(function () {
var doc, error, i, attachment_list; var doc, error, i, attachment_list;
error = function (word) { error = function (word) {
that.error({ that.error({
"status": 404, "status": 404,
"statusText": "Not Found", "statusText": "Not Found",
"error": "not_found", "error": "not_found",
"message": word + " not found", "message": word + " not found",
"reason": "missing" "reason": "missing"
});
};
doc = localstorage.getItem(priv.localpath + "/" + command.getDocId());
// remove attachment from document
if (doc !== null && typeof doc === "object" &&
typeof doc._attachments === "object") {
if (typeof doc._attachments[command.getAttachmentId()] ===
"object") {
delete doc._attachments[command.getAttachmentId()];
if (priv.objectIsEmpty(doc._attachments)) {
delete doc._attachments;
}
localstorage.setItem(priv.localpath + "/" + command.getDocId(),
doc);
localstorage.removeItem(priv.localpath + "/" + command.getDocId() +
"/" + command.getAttachmentId());
that.success({
"ok": true,
"id": command.getDocId(),
"attachment": command.getAttachmentId()
}); });
};
doc = localstorage.getItem(priv.localpath + "/" + command.getDocId());
// remove attachment from document
if (doc !== null && typeof doc === "object" &&
typeof doc._attachments === "object") {
if (typeof doc._attachments[command.getAttachmentId()] ===
"object") {
delete doc._attachments[command.getAttachmentId()];
if (priv.objectIsEmpty(doc._attachments)) {
delete doc._attachments;
}
localstorage.setItem(priv.localpath + "/" + command.getDocId(),
doc);
localstorage.removeItem(priv.localpath + "/" + command.getDocId() +
"/" + command.getAttachmentId());
that.success({
"ok": true,
"id": command.getDocId(),
"attachment": command.getAttachmentId()
});
} else {
error("Attachment");
}
} else { } else {
error("Attachment"); error("Document");
} }
} else { });
error("Document"); };
}
});
};
/** /**
* Get all filenames belonging to a user from the document index * Get all filenames belonging to a user from the document index
* @method allDocs * @method allDocs
* @param {object} command The JIO command * @param {object} command The JIO command
*/ */
that.allDocs = function (command) { that.allDocs = function (command) {
var i, row, path_re, rows = [], document_list = [], option, document_object; var i, row, path_re, rows, document_list, option, document_object;
path_re = new RegExp(
"^" + complex_queries.stringEscapeRegexpCharacters(priv.localpath) +
"/[^/]+$"
);
option = command.cloneOption();
if (typeof complex_queries !== "object" ||
(option.query === undefined && option.sort_on === undefined &&
option.select_list === undefined &&
option.include_docs === undefined)) {
rows = []; rows = [];
for (i in localStorage) { document_list = [];
if (localStorage.hasOwnProperty(i)) { path_re = new RegExp(
// filter non-documents "^" + complex_queries.stringEscapeRegexpCharacters(priv.localpath) +
if (path_re.test(i)) { "/[^/]+$"
row = { value: {} }; );
row.id = i.split('/').slice(-1)[0]; option = command.cloneOption();
row.key = row.id; if (typeof complex_queries !== "object" ||
if (command.getOption('include_docs')) { (option.query === undefined && option.sort_on === undefined &&
row.doc = JSON.parse(localStorage.getItem(i)); option.select_list === undefined &&
option.include_docs === undefined)) {
rows = [];
for (i in localStorage) {
if (localStorage.hasOwnProperty(i)) {
// filter non-documents
if (path_re.test(i)) {
row = { value: {} };
row.id = i.split('/').slice(-1)[0];
row.key = row.id;
if (command.getOption('include_docs')) {
row.doc = JSON.parse(localStorage.getItem(i));
}
rows.push(row);
} }
rows.push(row);
} }
} }
} that.success({"rows": rows, "total_rows": rows.length});
that.success({"rows": rows, "total_rows": rows.length}); } else {
} else { // create complex query object from returned results
// create complex query object from returned results for (i in localStorage) {
for (i in localStorage) { if (localStorage.hasOwnProperty(i)) {
if (localStorage.hasOwnProperty(i)) { if (path_re.test(i)) {
if (path_re.test(i)) { document_list.push(localstorage.getItem(i));
document_list.push(localstorage.getItem(i)); }
} }
} }
} option.select_list = option.select_list || [];
option.select_list = option.select_list || []; option.select_list.push("_id");
option.select_list.push("_id");
if (option.include_docs === true) {
document_object = {};
document_list.forEach(function (meta) {
document_object[meta._id] = meta;
});
}
complex_queries.QueryFactory.create(option.query || "").
exec(document_list, option);
document_list = document_list.map(function (value) {
var o = {
"id": value._id,
"key": value._id
};
if (option.include_docs === true) { if (option.include_docs === true) {
o.doc = document_object[value._id]; document_object = {};
delete document_object[value._id]; document_list.forEach(function (meta) {
document_object[meta._id] = meta;
});
} }
delete value._id; complex_queries.QueryFactory.create(option.query || "").
o.value = value; exec(document_list, option);
return o; document_list = document_list.map(function (value) {
}); var o = {
that.success({"total_rows": document_list.length, "id": value._id,
"rows": document_list}); "key": value._id
} };
}; if (option.include_docs === true) {
o.doc = document_object[value._id];
delete document_object[value._id];
}
delete value._id;
o.value = value;
return o;
});
that.success({"total_rows": document_list.length,
"rows": document_list});
}
};
return that; return that;
}); });
}));
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment