Commit 0e69426d authored by Aurélien Vermylen's avatar Aurélien Vermylen

Merge branch 'nodejs' of https://lab.nexedi.com/aurel/jio into clearroad

Conflicts:
	Gruntfile.js
	src/jio.storage/erp5storage.js
	src/jio.storage/mappingstorage.js
	test/jio.storage/mappingstorage.tests.js
	test/tests.html
parents 63be634c bf8de85a
...@@ -30,6 +30,7 @@ module.exports = function (grunt) { ...@@ -30,6 +30,7 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-open'); grunt.loadNpmTasks('grunt-open');
grunt.loadNpmTasks('grunt-qunitnode');
// Project configuration. // Project configuration.
grunt.initConfig({ grunt.initConfig({
...@@ -68,6 +69,26 @@ module.exports = function (grunt) { ...@@ -68,6 +69,26 @@ module.exports = function (grunt) {
nomen: true nomen: true
} }
}, },
jio_nodejs: {
src: ['src/jio-nodejs.js'],
directives: {
maxlen: 80,
indent: 2,
maxerr: 3,
node: true,
nomen: true
}
},
jio_nodejs_include: {
src: ['src/nodejs/include.js'],
directives: {
maxlen: 80,
indent: 2,
maxerr: 3,
node: true,
nomen: true
}
},
jio_storages: { jio_storages: {
src: ['src/jio.storage/*.js'], src: ['src/jio.storage/*.js'],
directives: { directives: {
...@@ -93,7 +114,7 @@ module.exports = function (grunt) { ...@@ -93,7 +114,7 @@ module.exports = function (grunt) {
predef: [ predef: [
'jIO' 'jIO'
] ]
}, }
}, },
tests: { tests: {
src: ['test/**/*.js'], src: ['test/**/*.js'],
...@@ -106,7 +127,7 @@ module.exports = function (grunt) { ...@@ -106,7 +127,7 @@ module.exports = function (grunt) {
'QUnit', 'QUnit',
'jIO' 'jIO'
] ]
}, }
}, },
queries: { queries: {
src: ['src/queries/*.js'], src: ['src/queries/*.js'],
...@@ -136,8 +157,8 @@ module.exports = function (grunt) { ...@@ -136,8 +157,8 @@ module.exports = function (grunt) {
'QUnit', 'QUnit',
'jIO' 'jIO'
] ]
}, }
}, }
}, },
concat: { concat: {
options: { options: {
...@@ -187,6 +208,34 @@ module.exports = function (grunt) { ...@@ -187,6 +208,34 @@ module.exports = function (grunt) {
], ],
dest: 'dist/<%= pkg.name %>-<%= pkg.version %>.js' dest: 'dist/<%= pkg.name %>-<%= pkg.version %>.js'
// dest: 'jio.js' // dest: 'jio.js'
},
nodejs: {
// duplicate files are ignored
src: [
// all the require for nodejs
'src/nodejs/include.js',
'src/nodejs/html5.js',
// queries
'src/queries/parser-begin.js',
'src/queries/build/parser.js',
'src/queries/parser-end.js',
'src/queries/query.js',
'src/jio.date/*.js',
'src/jio-nodejs.js',
'src/jio.storage/replicatestorage.js',
'src/jio.storage/uuidstorage.js',
'src/jio.storage/memorystorage.js',
'src/jio.storage/erp5storage.js',
'src/jio.storage/documentstorage.js',
'src/jio.storage/querystorage.js',
'src/jio.storage/localstorage.js',
'src/jio.storage/mappingstorage.js'
],
dest: 'dist/nodejs/jio.js'
} }
}, },
uglify: { uglify: {
...@@ -231,6 +280,22 @@ module.exports = function (grunt) { ...@@ -231,6 +280,22 @@ module.exports = function (grunt) {
// grunt doesn't like requirejs // grunt doesn't like requirejs
files: ['test/tests.html'] files: ['test/tests.html']
}, },
// test jio with nodejs
qunitnode: {
all: [ "dist/nodejs/jio.js",
"test/jio.storage/memorystorage.tests.js",
"test/jio.storage/replicatestorage.tests.js",
"test/jio.storage/uuidstorage.tests.js",
"test/jio.storage/querystorage.tests.js",
"test/jio.storage/mappingstorage.tests.js",
"test/jio.storage/localstorage.tests.js",
"test/jio.storage/documentstorage.tests.js",
"test/jio.storage/erp5storage.tests.js"
],
options : {
force: true
}
},
watch: { watch: {
src: { src: {
...@@ -245,7 +310,9 @@ module.exports = function (grunt) { ...@@ -245,7 +310,9 @@ module.exports = function (grunt) {
'<%= concat.jio.src %>', '<%= concat.jio.src %>',
'<%= qunit.files %>', '<%= qunit.files %>',
'test/**/*.js', 'test/**/*.js',
'examples/*' 'examples/*',
'src/jio-nodejs.js',
'src/nodejs/*.js'
], ],
tasks: ['default'], tasks: ['default'],
options: { options: {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"Sven Franck <sven.franck@nexedi.com>" "Sven Franck <sven.franck@nexedi.com>"
], ],
"description": "Client-side JavaScript library to manage documents across multiple storages", "description": "Client-side JavaScript library to manage documents across multiple storages",
"main": "jio.js", "main": "dist/nodejs/jio.js",
"directories": { "directories": {
"example": "examples", "example": "examples",
"test": "test" "test": "test"
...@@ -32,7 +32,17 @@ ...@@ -32,7 +32,17 @@
"rsvp": "git+https://lab.nexedi.com/nexedi/rsvp.js.git", "rsvp": "git+https://lab.nexedi.com/nexedi/rsvp.js.git",
"uritemplate": "git+https://lab.nexedi.com/nexedi/uritemplate-js.git", "uritemplate": "git+https://lab.nexedi.com/nexedi/uritemplate-js.git",
"moment": "2.13.0", "moment": "2.13.0",
"rusha": "0.8.2" "rusha": "0.8.2",
"urijs": "^1.18.9",
"xhr2": "^0.1.4",
"navigator": "^1.0.1",
"form-data": "^2.1.2",
"atob": "^2.0.3",
"node-localstorage": "^1.3.0",
"btoa": "^1.1.2",
"stream-buffers": "^3.0.1",
"mockdoc": "^0.0.2",
"sinon": "~2.1.0"
}, },
"devDependencies": { "devDependencies": {
"renderjs": "git+https://lab.nexedi.com/nexedi/renderjs.git", "renderjs": "git+https://lab.nexedi.com/nexedi/renderjs.git",
...@@ -47,11 +57,12 @@ ...@@ -47,11 +57,12 @@
"grunt-contrib-watch": "~0.5.3", "grunt-contrib-watch": "~0.5.3",
"grunt-jslint": "~1.0.0", "grunt-jslint": "~1.0.0",
"lz-string": "^1.4.4", "lz-string": "^1.4.4",
"sinon": "~1.7.3", "sinon": "~2.1.0",
"jison": "~0.4.16", "jison": "~0.4.16",
"connect-livereload": "~0.3.0", "connect-livereload": "~0.3.0",
"grunt-open": "~0.2.2", "grunt-open": "~0.2.2",
"grunt-contrib-connect": "~0.5.0" "grunt-contrib-connect": "~0.5.0",
"grunt-qunitnode": "~1.0.0"
}, },
"engines": { "engines": {
"npm": ">=1.3" "npm": ">=1.3"
......
/*global window, RSVP, Blob, XMLHttpRequest, QueryFactory, Query, atob,
FileReader, ArrayBuffer, Uint8Array, navigator, FormData, StreamBuffers */
(function (window, RSVP, Blob, QueryFactory, Query, atob,
FileReader, ArrayBuffer, Uint8Array, navigator) {
"use strict";
if (window.openDatabase === undefined) {
window.openDatabase = function () {
throw new Error('WebSQL is not supported by ' + navigator.userAgent);
};
}
/* Safari does not define DOMError */
if (window.DOMError === undefined) {
window.DOMError = {};
}
var util = {},
jIO;
function jIOError(message, status_code) {
if ((message !== undefined) && (typeof message !== "string")) {
throw new TypeError('You must pass a string.');
}
this.message = message || "Default Message";
this.status_code = status_code || 500;
}
jIOError.prototype = new Error();
jIOError.prototype.constructor = jIOError;
util.jIOError = jIOError;
/**
* Send request with XHR and return a promise. xhr.onload: The promise is
* resolved when the status code is lower than 400 with the xhr object as
* first parameter. xhr.onerror: reject with xhr object as first
* parameter. xhr.onprogress: notifies the xhr object.
*
* @param {Object} param The parameters
* @param {String} [param.type="GET"] The request method
* @param {String} [param.dataType=""] The data type to retrieve
* @param {String} param.url The url
* @param {Any} [param.data] The data to send
* @param {Function} [param.beforeSend] A function called just before the
* send request. The first parameter of this function is the XHR object.
* @return {Promise} The promise
*/
function ajax(param) {
var xhr = new XMLHttpRequest();
return new RSVP.Promise(function (resolve, reject, notify) {
var k, buffer = new StreamBuffers.WritableStreamBuffer();
xhr.open(param.type || "GET", param.url, true);
xhr.responseType = param.dataType || "";
if (typeof param.headers === 'object' && param.headers !== null) {
for (k in param.headers) {
if (param.headers.hasOwnProperty(k)) {
xhr.setRequestHeader(k, param.headers[k]);
}
}
}
xhr.setRequestHeader("Accept", "*/*");
xhr.addEventListener("load", function (e) {
if (e.target.status >= 400) {
return reject(e);
}
resolve(e);
});
xhr.addEventListener("error", reject);
xhr.addEventListener("progress", notify);
if (typeof param.xhrFields === 'object' && param.xhrFields !== null) {
for (k in param.xhrFields) {
if (param.xhrFields.hasOwnProperty(k)) {
xhr[k] = param.xhrFields[k];
}
}
}
if (typeof param.beforeSend === 'function') {
param.beforeSend(xhr);
}
if (param.data instanceof FormData) {
xhr.setRequestHeader("Content-Type",
"multipart\/form-data; boundary=" + param.data.getBoundary());
param.data.pipe(buffer);
xhr.send(buffer.getContents());
} else {
xhr.send(param.data);
}
}, function () {
xhr.abort();
});
}
util.ajax = ajax;
function readBlobAsText(blob, encoding) {
var fr = new FileReader();
return new RSVP.Promise(function (resolve, reject, notify) {
fr.addEventListener("load", resolve);
fr.addEventListener("error", reject);
fr.addEventListener("progress", notify);
fr.readAsText(blob, encoding);
}, function () {
fr.abort();
});
}
util.readBlobAsText = readBlobAsText;
function readBlobAsArrayBuffer(blob) {
var fr = new FileReader();
return new RSVP.Promise(function (resolve, reject, notify) {
fr.addEventListener("load", resolve);
fr.addEventListener("error", reject);
fr.addEventListener("progress", notify);
fr.readAsArrayBuffer(blob);
}, function () {
fr.abort();
});
}
util.readBlobAsArrayBuffer = readBlobAsArrayBuffer;
function readBlobAsDataURL(blob) {
var fr = new FileReader();
return new RSVP.Promise(function (resolve, reject, notify) {
fr.addEventListener("load", resolve);
fr.addEventListener("error", reject);
fr.addEventListener("progress", notify);
fr.readAsDataURL(blob);
}, function () {
fr.abort();
});
}
util.readBlobAsDataURL = readBlobAsDataURL;
function stringify(obj) {
// Implement a stable JSON.stringify
// Object's keys are alphabetically ordered
var key,
key_list,
i,
value,
result_list;
if (obj === undefined) {
return undefined;
}
if (obj.constructor === Object) {
key_list = Object.keys(obj).sort();
result_list = [];
for (i = 0; i < key_list.length; i += 1) {
key = key_list[i];
value = stringify(obj[key]);
if (value !== undefined) {
result_list.push(stringify(key) + ':' + value);
}
}
return '{' + result_list.join(',') + '}';
}
if (obj.constructor === Array) {
result_list = [];
for (i = 0; i < obj.length; i += 1) {
result_list.push(stringify(obj[i]));
}
return '[' + result_list.join(',') + ']';
}
return JSON.stringify(obj);
}
util.stringify = stringify;
// https://gist.github.com/davoclavo/4424731
function dataURItoBlob(dataURI) {
if (dataURI === 'data:') {
return new Blob();
}
// convert base64 to raw binary data held in a string
var byteString = atob(dataURI.split(',')[1]),
// separate out the mime component
mimeString = dataURI.split(',')[0].split(':')[1],
// write the bytes of the string to an ArrayBuffer
arrayBuffer = new ArrayBuffer(byteString.length),
_ia = new Uint8Array(arrayBuffer),
i;
mimeString = mimeString.slice(0, mimeString.length - ";base64".length);
for (i = 0; i < byteString.length; i += 1) {
_ia[i] = byteString.charCodeAt(i);
}
return new Blob([arrayBuffer], {type: mimeString});
}
util.dataURItoBlob = dataURItoBlob;
// tools
function checkId(argument_list, storage, method_name) {
if (typeof argument_list[0] !== 'string' || argument_list[0] === '') {
throw new jIO.util.jIOError(
"Document id must be a non empty string on '" + storage.__type +
"." + method_name + "'.",
400
);
}
}
function checkAttachmentId(argument_list, storage, method_name) {
if (typeof argument_list[1] !== 'string' || argument_list[1] === '') {
throw new jIO.util.jIOError(
"Attachment id must be a non empty string on '" + storage.__type +
"." + method_name + "'.",
400
);
}
}
function declareMethod(klass, name, precondition_function, post_function) {
klass.prototype[name] = function () {
var argument_list = arguments,
context = this,
precondition_result;
return new RSVP.Queue()
.push(function () {
if (precondition_function !== undefined) {
return precondition_function.apply(
context.__storage,
[argument_list, context, name]
);
}
})
.push(function (result) {
var storage_method = context.__storage[name];
precondition_result = result;
if (storage_method === undefined) {
throw new jIO.util.jIOError(
"Capacity '" + name + "' is not implemented on '" +
context.__type + "'",
501
);
}
return storage_method.apply(
context.__storage,
argument_list
);
})
.push(function (result) {
if (post_function !== undefined) {
return post_function.call(
context,
argument_list,
result,
precondition_result
);
}
return result;
});
};
// Allow chain
return this;
}
/////////////////////////////////////////////////////////////////
// jIO Storage Proxy
/////////////////////////////////////////////////////////////////
function JioProxyStorage(type, storage) {
if (!(this instanceof JioProxyStorage)) {
return new JioProxyStorage();
}
this.__type = type;
this.__storage = storage;
}
declareMethod(JioProxyStorage, "put", checkId, function (argument_list) {
return argument_list[0];
});
declareMethod(JioProxyStorage, "get", checkId);
declareMethod(JioProxyStorage, "bulk");
declareMethod(JioProxyStorage, "remove", checkId, function (argument_list) {
return argument_list[0];
});
JioProxyStorage.prototype.post = function () {
var context = this,
argument_list = arguments;
return new RSVP.Queue()
.push(function () {
var storage_method = context.__storage.post;
if (storage_method === undefined) {
throw new jIO.util.jIOError(
"Capacity 'post' is not implemented on '" + context.__type + "'",
501
);
}
return context.__storage.post.apply(context.__storage, argument_list);
});
};
declareMethod(JioProxyStorage, 'putAttachment', function (argument_list,
storage,
method_name) {
checkId(argument_list, storage, method_name);
checkAttachmentId(argument_list, storage, method_name);
var options = argument_list[3] || {};
if (typeof argument_list[2] === 'string') {
argument_list[2] = new Blob([argument_list[2]], {
"type": options._content_type || options._mimetype ||
"text/plain;charset=utf-8"
});
} else if (!(argument_list[2] instanceof Blob)) {
throw new jIO.util.jIOError(
'Attachment content is not a blob',
400
);
}
});
declareMethod(JioProxyStorage, 'removeAttachment', function (argument_list,
storage,
method_name) {
checkId(argument_list, storage, method_name);
checkAttachmentId(argument_list, storage, method_name);
});
declareMethod(JioProxyStorage, 'getAttachment', function (argument_list,
storage,
method_name) {
var result = "blob";
// if (param.storage_spec.type !== "indexeddb" &&
// param.storage_spec.type !== "dav" &&
// (param.kwargs._start !== undefined
// || param.kwargs._end !== undefined)) {
// restCommandRejecter(param, [
// 'bad_request',
// 'unsupport',
// '_start, _end not support'
// ]);
// return false;
// }
checkId(argument_list, storage, method_name);
checkAttachmentId(argument_list, storage, method_name);
// Drop optional parameters, which are only used in postfunction
if (argument_list[2] !== undefined) {
result = argument_list[2].format || result;
delete argument_list[2].format;
}
return result;
}, function (argument_list, blob, convert) {
var result;
if (!(blob instanceof Blob)) {
throw new jIO.util.jIOError(
"'getAttachment' (" + argument_list[0] + " , " +
argument_list[1] + ") on '" + this.__type +
"' does not return a Blob.",
501
);
}
if (convert === "blob") {
result = blob;
} else if (convert === "data_url") {
result = new RSVP.Queue()
.push(function () {
return jIO.util.readBlobAsDataURL(blob);
})
.push(function (evt) {
return evt.target.result;
});
} else if (convert === "array_buffer") {
result = new RSVP.Queue()
.push(function () {
return jIO.util.readBlobAsArrayBuffer(blob);
})
.push(function (evt) {
return evt.target.result;
});
} else if (convert === "text") {
result = new RSVP.Queue()
.push(function () {
return jIO.util.readBlobAsText(blob);
})
.push(function (evt) {
return evt.target.result;
});
} else if (convert === "json") {
result = new RSVP.Queue()
.push(function () {
return jIO.util.readBlobAsText(blob);
})
.push(function (evt) {
return JSON.parse(evt.target.result);
});
} else {
throw new jIO.util.jIOError(
this.__type + ".getAttachment format: '" + convert +
"' is not supported",
400
);
}
return result;
});
JioProxyStorage.prototype.buildQuery = function () {
var storage_method = this.__storage.buildQuery,
context = this,
argument_list = arguments;
if (storage_method === undefined) {
throw new jIO.util.jIOError(
"Capacity 'buildQuery' is not implemented on '" + this.__type + "'",
501
);
}
return new RSVP.Queue()
.push(function () {
return storage_method.apply(
context.__storage,
argument_list
);
});
};
JioProxyStorage.prototype.hasCapacity = function (name) {
var storage_method = this.__storage.hasCapacity,
capacity_method = this.__storage[name];
if (capacity_method !== undefined) {
return true;
}
if ((storage_method === undefined) ||
!storage_method.apply(this.__storage, arguments)) {
throw new jIO.util.jIOError(
"Capacity '" + name + "' is not implemented on '" + this.__type + "'",
501
);
}
return true;
};
JioProxyStorage.prototype.allDocs = function (options) {
var context = this;
if (options === undefined) {
options = {};
}
return new RSVP.Queue()
.push(function () {
if (context.hasCapacity("list") &&
((options.query === undefined) || context.hasCapacity("query")) &&
((options.sort_on === undefined) || context.hasCapacity("sort")) &&
((options.select_list === undefined) ||
context.hasCapacity("select")) &&
((options.include_docs === undefined) ||
context.hasCapacity("include")) &&
((options.limit === undefined) || context.hasCapacity("limit"))) {
return context.buildQuery(options);
}
})
.push(function (result) {
return {
data: {
rows: result,
total_rows: result.length
}
};
});
};
declareMethod(JioProxyStorage, "allAttachments", checkId);
declareMethod(JioProxyStorage, "repair");
JioProxyStorage.prototype.repair = function () {
var context = this,
argument_list = arguments;
return new RSVP.Queue()
.push(function () {
var storage_method = context.__storage.repair;
if (storage_method !== undefined) {
return context.__storage.repair.apply(context.__storage,
argument_list);
}
});
};
/////////////////////////////////////////////////////////////////
// Storage builder
/////////////////////////////////////////////////////////////////
function JioBuilder() {
if (!(this instanceof JioBuilder)) {
return new JioBuilder();
}
this.__storage_types = {};
}
JioBuilder.prototype.createJIO = function (storage_spec, util) {
if (typeof storage_spec.type !== 'string') {
throw new TypeError("Invalid storage description");
}
if (!this.__storage_types[storage_spec.type]) {
throw new TypeError("Unknown storage '" + storage_spec.type + "'");
}
return new JioProxyStorage(
storage_spec.type,
new this.__storage_types[storage_spec.type](storage_spec, util)
);
};
JioBuilder.prototype.addStorage = function (type, Constructor) {
if (typeof type !== 'string') {
throw new TypeError(
"jIO.addStorage(): Argument 1 is not of type 'string'"
);
}
if (typeof Constructor !== 'function') {
throw new TypeError("jIO.addStorage(): " +
"Argument 2 is not of type 'function'");
}
if (this.__storage_types[type] !== undefined) {
throw new TypeError("jIO.addStorage(): Storage type already exists");
}
this.__storage_types[type] = Constructor;
};
JioBuilder.prototype.util = util;
JioBuilder.prototype.QueryFactory = QueryFactory;
JioBuilder.prototype.Query = Query;
/////////////////////////////////////////////////////////////////
// global
/////////////////////////////////////////////////////////////////
jIO = new JioBuilder();
window.jIO = jIO;
}(window, RSVP, Blob, QueryFactory, Query, atob,
FileReader, ArrayBuffer, Uint8Array, navigator));
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
/*jslint nomen: true, unparam: true */ /*jslint nomen: true, unparam: true */
/*global jIO, UriTemplate, FormData, RSVP, URI, Blob, /*global jIO, UriTemplate, FormData, RSVP, URI, Blob,
SimpleQuery, ComplexQuery*/ SimpleQuery, ComplexQuery, btoa*/
(function (jIO, UriTemplate, FormData, RSVP, URI, Blob, (function (jIO, UriTemplate, FormData, RSVP, URI, Blob,
SimpleQuery, ComplexQuery) { SimpleQuery, ComplexQuery) {
...@@ -24,8 +24,9 @@ ...@@ -24,8 +24,9 @@
"type": "GET", "type": "GET",
"url": storage._url, "url": storage._url,
"xhrFields": { "xhrFields": {
withCredentials: true withCredentials: storage._thisCredentials
} },
"headers": storage._headers
}); });
}) })
.push(function (event) { .push(function (event) {
...@@ -50,8 +51,9 @@ ...@@ -50,8 +51,9 @@
view: options._view view: options._view
}), }),
"xhrFields": { "xhrFields": {
withCredentials: true withCredentials: storage._thisCredentials
} },
"headers": storage._headers
}); });
}) })
.push(undefined, function (error) { .push(undefined, function (error) {
...@@ -128,8 +130,8 @@ ...@@ -128,8 +130,8 @@
}); });
} }
function extractPropertyFromForm(context, id) { function extractPropertyFromForm(storage, id) {
return context.getAttachment(id, "view") return storage.getAttachment(id, "view")
.push(function (blob) { .push(function (blob) {
return jIO.util.readBlobAsText(blob); return jIO.util.readBlobAsText(blob);
}) })
...@@ -149,20 +151,17 @@ ...@@ -149,20 +151,17 @@
} }
this._url = spec.url; this._url = spec.url;
this._default_view_reference = spec.default_view_reference; this._default_view_reference = spec.default_view_reference;
this._headers = null;
this._thisCredentials = true;
if (spec.login !== undefined && spec.password !== undefined) {
this._headers = {"Authorization": "Basic "
+ btoa(spec.login + ":" + spec.password)};
this._thisCredentials = false;
}
} }
function convertJSONToGet(json) { function convertJSONToGet(json) {
var key, return json.data;
result = json.data;
// Remove all ERP5 hateoas links / convert them into jIO ID
for (key in result) {
if (result.hasOwnProperty(key)) {
if (!result[key]) {
delete result[key];
}
}
}
return result;
} }
ERP5Storage.prototype.get = function (id) { ERP5Storage.prototype.get = function (id) {
...@@ -173,7 +172,7 @@ ...@@ -173,7 +172,7 @@
}; };
ERP5Storage.prototype.post = function (data) { ERP5Storage.prototype.post = function (data) {
var context = this, var storage = this,
new_id; new_id;
return getSiteDocument(this) return getSiteDocument(this)
...@@ -186,15 +185,16 @@ ...@@ -186,15 +185,16 @@
url: site_hal._actions.add.href, url: site_hal._actions.add.href,
data: form_data, data: form_data,
xhrFields: { xhrFields: {
withCredentials: true withCredentials: storage._thisCredentials
} },
"headers": storage._headers
}); });
}) })
.push(function (evt) { .push(function (evt) {
var location = evt.target.getResponseHeader("X-Location"), var location = evt.target.getResponseHeader("X-Location"),
uri = new URI(location); uri = new URI(location);
new_id = uri.segment(2); new_id = uri.segment(2);
return context.put(new_id, data); return storage.put(new_id, data);
}) })
.push(function () { .push(function () {
return new_id; return new_id;
...@@ -202,9 +202,9 @@ ...@@ -202,9 +202,9 @@
}; };
ERP5Storage.prototype.put = function (id, data) { ERP5Storage.prototype.put = function (id, data) {
var context = this; var storage = this;
return extractPropertyFromForm(context, id) return extractPropertyFromForm(storage, id)
.push(function (result) { .push(function (result) {
var key, var key,
json = result.form_data, json = result.form_data,
...@@ -237,7 +237,7 @@ ...@@ -237,7 +237,7 @@
403 403
); );
} }
return context.putAttachment( return storage.putAttachment(
id, id,
result.action_href, result.action_href,
new Blob([JSON.stringify(form_data)], {type: "application/json"}) new Blob([JSON.stringify(form_data)], {type: "application/json"})
...@@ -246,10 +246,10 @@ ...@@ -246,10 +246,10 @@
}; };
ERP5Storage.prototype.allAttachments = function (id) { ERP5Storage.prototype.allAttachments = function (id) {
var context = this; var storage = this;
return getDocumentAndHateoas(this, id) return getDocumentAndHateoas(this, id)
.push(function () { .push(function () {
if (context._default_view_reference === undefined) { if (storage._default_view_reference === undefined) {
return { return {
links: {} links: {}
}; };
...@@ -262,6 +262,7 @@ ...@@ -262,6 +262,7 @@
}; };
ERP5Storage.prototype.getAttachment = function (id, action, options) { ERP5Storage.prototype.getAttachment = function (id, action, options) {
var storage = this;
if (options === undefined) { if (options === undefined) {
options = {}; options = {};
} }
...@@ -308,8 +309,9 @@ ...@@ -308,8 +309,9 @@
"dataType": "blob", "dataType": "blob",
"url": action, "url": action,
"xhrFields": { "xhrFields": {
withCredentials: true withCredentials: storage._thisCredentials
} },
"headers": storage._headers
}; };
if (options.start !== undefined || options.end !== undefined) { if (options.start !== undefined || options.end !== undefined) {
start = options.start || 0; start = options.start || 0;
...@@ -329,7 +331,11 @@ ...@@ -329,7 +331,11 @@
} }
range = "bytes=" + start + "-" + end; range = "bytes=" + start + "-" + end;
} }
request_options.headers = {Range: range}; if (storage._headers === undefined) {
request_options.headers = {Range: range};
} else {
request_options.headers.Range = range;
}
} }
return jIO.util.ajax(request_options); return jIO.util.ajax(request_options);
}) })
...@@ -348,6 +354,7 @@ ...@@ -348,6 +354,7 @@
}; };
ERP5Storage.prototype.putAttachment = function (id, name, blob) { ERP5Storage.prototype.putAttachment = function (id, name, blob) {
var storage = this;
// Assert we use a callable on a document from the ERP5 site // Assert we use a callable on a document from the ERP5 site
if (name.indexOf(this._url) !== 0) { if (name.indexOf(this._url) !== 0) {
throw new jIO.util.jIOError("Can not store outside ERP5: " + throw new jIO.util.jIOError("Can not store outside ERP5: " +
...@@ -389,8 +396,9 @@ ...@@ -389,8 +396,9 @@
"data": data, "data": data,
"dataType": "blob", "dataType": "blob",
"xhrFields": { "xhrFields": {
withCredentials: true withCredentials: storage._thisCredentials
} },
"headers": storage._headers
}); });
}); });
}; };
...@@ -439,6 +447,7 @@ ...@@ -439,6 +447,7 @@
// jIO.Query.objectToSearchText(options.query) : // jIO.Query.objectToSearchText(options.query) :
// undefined); // undefined);
// } // }
var storage = this;
return getSiteDocument(this) return getSiteDocument(this)
.push(function (site_hal) { .push(function (site_hal) {
var query = options.query, var query = options.query,
...@@ -507,8 +516,9 @@ ...@@ -507,8 +516,9 @@
local_roles: local_roles local_roles: local_roles
}), }),
"xhrFields": { "xhrFields": {
withCredentials: true withCredentials: storage._thisCredentials
} },
"headers": storage._headers
}); });
}) })
.push(function (response) { .push(function (response) {
......
(function (env) {
"use strict";
var process = require("process");
env._html5_weakmap = new WeakMap();
function EventTarget() { env._html5_weakmap.set(this, Object.create(null)); }
EventTarget.prototype.addEventListener = function (type, listener) {
if (typeof listener !== "function") return;
var em = env._html5_weakmap.get(this);
type = "" + type;
if (em[type]) em[type].push(listener);
else em[type] = [listener];
};
EventTarget.prototype.removeEventListener = function (type, listener) {
if (typeof listener !== "function") return;
var em = env._html5_weakmap.get(this);
var i = 0, listeners = em[type];
type = "" + type;
if (listeners) for (; i < listeners.length; ++i) if (listeners[i] === listener) {
if (listeners.length === 1) { delete em[type]; return; }
listeners.splice(i, 1);
return;
}
};
EventTarget.prototype.dispatchEvent = function (event) {
var type = "" + event.type,
em = env._html5_weakmap.get(this),
ontype = "on" + type;
var i = 0, listeners;
if (typeof this[ontype] === "function") {
try { this[ontype](event); } catch (ignore) {}
}
if (listeners = em[type]) for (; i < listeners.length; ++i) {
try { listeners[i](event); } catch (ignore) {}
}
};
env.EventTarget = EventTarget;
function Blob(blobParts, options) {
// https://developer.mozilla.org/en-US/docs/Web/API/Blob
var i = 0; var priv = {}, buffers = [];
env._html5_weakmap.set(this, priv);
for (; i < blobParts.length; ++i) {
if (Buffer.isBuffer(blobParts[i])) {
buffers.push(blobParts[i]);
} else if (blobParts[i] instanceof Blob) {
buffers.push(env._html5_weakmap.get(blobParts[i]).data);
} else if (blobParts[i] instanceof ArrayBuffer) {
buffers.push(new Buffer(new Uint8Array(blobParts[i])));
} else {
buffers.push(new Buffer("" + blobParts[i]));
}
}
priv.data = Buffer.concat(buffers);
Object.defineProperty(this, "size", {enumerable: true, value: priv.data.length});
Object.defineProperty(this, "type", {enumerable: true, value: options ? "" + (options.type || "") : ""});
}
Blob.prototype.size = 0;
Blob.prototype.type = "";
Blob.prototype.slice = function (start, end, contentType) {
return new Blob([env._html5_weakmap.get(this).data.slice(start, end)], {type: contentType});
};
env.Blob = Blob;
function FileReader() { EventTarget.call(this); }
FileReader.prototype = Object.create(EventTarget.prototype);
Object.defineProperty(FileReader, "constructor", {value: FileReader});
FileReader.prototype.readAsText = function (blob) {
var priv = env._html5_weakmap.get(blob);
var text = priv.data.toString();
var event = Object.freeze({type: "load", target: this});
process.nextTick(() => {
this.result = text;
this.dispatchEvent(event);
});
};
FileReader.prototype.readAsArrayBuffer = function (blob) {
var priv = env._html5_weakmap.get(blob);
var arrayBuffer = new Uint8Array(priv.data).buffer;
var event = Object.freeze({type: "load", target: this});
process.nextTick(() => {
this.result = arrayBuffer;
this.dispatchEvent(event);
});
};
FileReader.prototype.readAsDataURL = function (blob) {
var priv = env._html5_weakmap.get(blob);
var dataUrl = "data:" + blob.type + ";base64," + priv.data.toString("base64");
var event = Object.freeze({type: "load", target: this});
process.nextTick(() => {
this.result = dataUrl;
this.dispatchEvent(event);
});
};
env.FileReader = FileReader;
}(global));
/*global global, require */
global.URI = require("urijs");
global.RSVP = require('rsvp');
global.UriTemplate = require("uritemplate");
global.moment = require('moment');
global.navigator = require('navigator');
global.Rusha = require('rusha');
global.FormData = require('form-data');
global.atob = require('atob');
var LocalStorage = require('node-localstorage').LocalStorage;
global.localStorage = new LocalStorage("jio");
global.btoa = require('btoa');
global.XMLHttpRequest = require('xhr2');
var Mockdoc = require("mockdoc");
global.document = new Mockdoc();
global.sinon = require('sinon');
global.StreamBuffers = require('stream-buffers');
global.window = global;
global.sessionStorage = {};
global.HTMLCanvasElement = {};
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