Reorganize files.
This commit is contained in:
parent
a2ff2823dc
commit
4f5ff333fb
|
@ -15,7 +15,7 @@ require.config({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
require(["src/fs2"], function(IDBFS) {
|
require(["src/file-system"], function(IDBFS) {
|
||||||
|
|
||||||
var flags = 'FORMAT';
|
var flags = 'FORMAT';
|
||||||
//var flags = undefined;
|
//var flags = undefined;
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
define(function(require) {
|
||||||
|
|
||||||
|
return {
|
||||||
|
METADATA_STORE_NAME: 'metadata',
|
||||||
|
FILE_STORE_NAME: 'files',
|
||||||
|
|
||||||
|
IDB_RO: 'readonly',
|
||||||
|
IDB_RW: 'readwrite',
|
||||||
|
|
||||||
|
MODE_FILE: 'FILE',
|
||||||
|
MODE_DIRECTORY: 'DIRECTORY',
|
||||||
|
MODE_SYMBOLIC_LINK: 'SYMLINK',
|
||||||
|
|
||||||
|
BINARY_MIME_TYPE: 'application/octet-stream',
|
||||||
|
JSON_MIME_TYPE: 'application/json',
|
||||||
|
|
||||||
|
ROOT_DIRECTORY_NAME: '/', // basename(normalize(path))
|
||||||
|
ROOT_NODE_ID: '8a5edab282632443219e051e4ade2d1d5bbc671c781051bf1437897cbdfea0f1', // sha256(ROOT_DIRECTORY_NAME)
|
||||||
|
|
||||||
|
// FileSystem flags
|
||||||
|
FS_FORMAT: 'FORMAT',
|
||||||
|
|
||||||
|
// Open flags
|
||||||
|
O_READONLY: 'READONLY',
|
||||||
|
O_READWRITE: 'READWRITE',
|
||||||
|
O_APPEND: 'APPEND',
|
||||||
|
O_CREATE: 'CREATE',
|
||||||
|
O_TRUNCATE: 'TRUNCATE',
|
||||||
|
|
||||||
|
// FileSystem readyState
|
||||||
|
FS_READY: 'READY',
|
||||||
|
FS_PENDING: 'PENDING',
|
||||||
|
FS_ERROR: 'ERROR',
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,247 @@
|
||||||
|
define(function(require) {
|
||||||
|
|
||||||
|
var read_object = require('src/object-store').read_object;
|
||||||
|
var write_object = require('src/object-store').write_object;
|
||||||
|
var delete_object = require('src/object-store').delete_object;
|
||||||
|
|
||||||
|
var ENoEntry = require('src/error').ENoEntry;
|
||||||
|
var ENotDirectory = require('src/error').ENotDirectory;
|
||||||
|
var EPathExists = require('src/error').EPathExists;
|
||||||
|
|
||||||
|
var MODE_FILE = require('src/constants').MODE_FILE;
|
||||||
|
var MODE_DIRECTORY = require('src/constants').MODE_DIRECTORY;
|
||||||
|
var ROOT_DIRECTORY_NAME = require('src/constants').ROOT_DIRECTORY_NAME;
|
||||||
|
var ROOT_NODE_ID = require('src/constants').ROOT_NODE_ID;
|
||||||
|
|
||||||
|
var Node = require('src/file').Node;
|
||||||
|
|
||||||
|
var normalize = require('src/path').normalize;
|
||||||
|
var dirname = require('src/path').dirname;
|
||||||
|
var basename = require('src/path').basename;
|
||||||
|
|
||||||
|
function DirectoryEntry(id, type) {
|
||||||
|
this.id = id;
|
||||||
|
this.type = type || MODE_FILE;
|
||||||
|
};
|
||||||
|
|
||||||
|
// in: file or directory path
|
||||||
|
// out: node structure, or error
|
||||||
|
function find_node(objectStore, path, callback) {
|
||||||
|
path = normalize(path);
|
||||||
|
var name = basename(path);
|
||||||
|
|
||||||
|
if(ROOT_DIRECTORY_NAME == name) {
|
||||||
|
function check_root_directory_node(error, rootDirectoryNode) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else if(!rootDirectoryNode) {
|
||||||
|
callback(new ENoEntry());
|
||||||
|
} else {
|
||||||
|
callback(undefined, rootDirectoryNode);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
read_object(objectStore, ROOT_NODE_ID, check_root_directory_node);
|
||||||
|
} else {
|
||||||
|
// in: parent directory node
|
||||||
|
// out: parent directory data
|
||||||
|
function read_parent_directory_data(error, parentDirectoryNode) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else if(!_(parentDirectoryNode).has('data') || !parentDirectoryNode.type == MODE_DIRECTORY) {
|
||||||
|
callback(new ENotDirectory());
|
||||||
|
} else {
|
||||||
|
read_object(objectStore, parentDirectoryNode.data, get_node_id_from_parent_directory_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// in: parent directory data
|
||||||
|
// out: searched node id
|
||||||
|
function get_node_id_from_parent_directory_data(error, parentDirectoryData) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
if(!_(parentDirectoryData).has(name)) {
|
||||||
|
callback(new ENoEntry());
|
||||||
|
} else {
|
||||||
|
var nodeId = parentDirectoryData[name].id;
|
||||||
|
read_object(objectStore, nodeId, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var parentPath = dirname(path);
|
||||||
|
find_node(objectStore, parentPath, read_parent_directory_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Note: this should only be invoked when formatting a new file system
|
||||||
|
function make_root_directory(objectStore, callback) {
|
||||||
|
var directoryNode;
|
||||||
|
var directoryData;
|
||||||
|
|
||||||
|
function write_directory_node(error, existingNode) {
|
||||||
|
if(!error && existingNode) {
|
||||||
|
callback(new EPathExists());
|
||||||
|
} else if(error && !error instanceof ENoEntry) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
directoryNode = new Node(ROOT_NODE_ID, MODE_DIRECTORY);
|
||||||
|
directoryNode.links += 1;
|
||||||
|
write_object(objectStore, directoryNode, directoryNode.id, write_directory_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function write_directory_data(error) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
directoryData = {};
|
||||||
|
write_object(objectStore, directoryData, directoryNode.data, callback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
find_node(objectStore, ROOT_DIRECTORY_NAME, write_directory_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_directory(objectStore, path, callback) {
|
||||||
|
path = normalize(path);
|
||||||
|
var name = basename(path);
|
||||||
|
var parentPath = dirname(path);
|
||||||
|
|
||||||
|
var directoryNode;
|
||||||
|
var directoryData;
|
||||||
|
var parentDirectoryNode;
|
||||||
|
var parentDirectoryData;
|
||||||
|
|
||||||
|
function check_if_directory_exists(error, result) {
|
||||||
|
if(!error && result) {
|
||||||
|
callback(new EPathExists());
|
||||||
|
} else if(error && !error instanceof ENoEntry) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
find_node(objectStore, parentPath, read_parent_directory_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function read_parent_directory_data(error, result) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
parentDirectoryNode = result;
|
||||||
|
read_object(objectStore, parentDirectoryNode.data, write_directory_node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function write_directory_node(error, result) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
parentDirectoryData = result;
|
||||||
|
directoryNode = new Node(undefined, MODE_DIRECTORY);
|
||||||
|
directoryNode.links += 1;
|
||||||
|
write_object(objectStore, directoryNode, directoryNode.id, write_directory_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function write_directory_data(error) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
directoryData = {};
|
||||||
|
write_object(objectStore, directoryData, directoryNode.data, update_parent_directory_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function update_parent_directory_data(error) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
parentDirectoryData[name] = new DirectoryEntry(directoryNode.id, MODE_DIRECTORY);
|
||||||
|
write_object(objectStore, parentDirectoryData, parentDirectoryNode.data, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
find_node(objectStore, path, check_if_directory_exists);
|
||||||
|
};
|
||||||
|
|
||||||
|
function remove_directory(objectStore, path, callback) {
|
||||||
|
path = normalize(path);
|
||||||
|
var name = basename(path);
|
||||||
|
var parentPath = dirname(path);
|
||||||
|
|
||||||
|
var directoryNode;
|
||||||
|
var directoryData;
|
||||||
|
var parentDirectoryNode;
|
||||||
|
var parentDirectoryData;
|
||||||
|
|
||||||
|
function check_if_directory_exists(error, result) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else if(!result) {
|
||||||
|
callback(new ENoEntry());
|
||||||
|
} else {
|
||||||
|
directoryNode = result;
|
||||||
|
read_object(objectStore, directoryNode.data, check_if_directory_is_empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_if_directory_is_empty(error, result) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
directoryData = result;
|
||||||
|
if(_(directoryData).size() > 0) {
|
||||||
|
callback(new ENotEmpty());
|
||||||
|
} else {
|
||||||
|
find_node(objectStore, parentPath, read_parent_directory_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function read_parent_directory_data(error, result) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
parentDirectoryNode = result;
|
||||||
|
read_object(objectStore, parentDirectoryNode.data, remove_directory_entry_from_parent_directory_node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function remove_directory_entry_from_parent_directory_node(error, result) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
parentDirectoryData = result;
|
||||||
|
delete parentDirectoryData[name];
|
||||||
|
write_object(objectStore, parentDirectoryData, parentDirectoryNode.data, remove_directory_node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function remove_directory_node(error) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
delete_object(objectStore, directoryNode.id, remove_directory_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function remove_directory_data(error) {
|
||||||
|
if(error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
delete_object(objectStore, directoryNode.data, callback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
find_node(objectStore, path, check_if_directory_exists);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
make_directory: make_directory,
|
||||||
|
make_root_directory: make_root_directory,
|
||||||
|
remove_directory: remove_directory,
|
||||||
|
find_node: find_node,
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
48
src/event.js
48
src/event.js
|
@ -1,48 +0,0 @@
|
||||||
define function(require) {
|
|
||||||
|
|
||||||
var _ = require('lodash');
|
|
||||||
|
|
||||||
function Event(type, data) {
|
|
||||||
this.type = type;
|
|
||||||
this.data = data;
|
|
||||||
};
|
|
||||||
|
|
||||||
function EventSource(types) {
|
|
||||||
var events = this.events = {};
|
|
||||||
_(types).forEach(function(type) {
|
|
||||||
events[type] = [];
|
|
||||||
});
|
|
||||||
|
|
||||||
this.on = function on(type, callback) {
|
|
||||||
if(!_(events).has(type)) {
|
|
||||||
throw new Error('unsupported event: ' + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
events[type].push(callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.off = function off(type, callback) {
|
|
||||||
if(!_(events).has(type)) {
|
|
||||||
throw new Error('unsupported event: ' + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
events[type] = _(events[type]).without(callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.emit = function emit(event) {
|
|
||||||
if(!_(events).has(type)) {
|
|
||||||
throw new Error('unsupported event: ' + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
_(events[type]).forEach(function(callack) {
|
|
||||||
callback.call(this, event);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
Event: Event,
|
|
||||||
EventSource: EventSource
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
define(function(require) {
|
||||||
|
|
||||||
|
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
|
||||||
|
|
||||||
|
var _ = require('lodash');
|
||||||
|
var when = require('when');
|
||||||
|
|
||||||
|
var guid = require('src/shared').guid;
|
||||||
|
var hash = require('src/shared').hash;
|
||||||
|
var nop = require('src/shared').nop;
|
||||||
|
|
||||||
|
var EPathExists = require('src/error').EPathExists;
|
||||||
|
var EIsDirectory = require('src/error').EIsDirectory;
|
||||||
|
var ENoEntry = require('src/error').ENoEntry;
|
||||||
|
var EBusy = require('src/error').EBusy;
|
||||||
|
var ENotEmpty = require('src/error').ENotEmpty;
|
||||||
|
var ENotDirectory = require('src/error').ENotDirectory;
|
||||||
|
var EBadFileDescriptor = require('src/error').EBadFileDescriptor;
|
||||||
|
var ENotImplemented = require('src/error').ENotImplemented;
|
||||||
|
var ENotMounted = require('src/error').ENotMounted;
|
||||||
|
var EFileExists = require('src/error').EFileExists;
|
||||||
|
|
||||||
|
var FS_FORMAT = require('src/constants').FS_FORMAT;
|
||||||
|
|
||||||
|
var IDB_RW = require('src/constants').IDB_RW;
|
||||||
|
var IDB_RO = require('src/constants').IDB_RO;
|
||||||
|
var FILE_STORE_NAME = require('src/constants').FILE_STORE_NAME;
|
||||||
|
var FS_READY = require('src/constants').READY;
|
||||||
|
var FS_PENDING = require('src/constants').FS_PENDING;
|
||||||
|
var FS_ERROR = require('src/constants').FS_ERROR;
|
||||||
|
|
||||||
|
var make_root_directory = require('src/directory').make_root_directory;
|
||||||
|
var make_directory = require('src/directory').make_directory;
|
||||||
|
var remove_directory = require('src/directory').remove_directory;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FileSystem
|
||||||
|
*/
|
||||||
|
|
||||||
|
function FileSystem(name, flags) {
|
||||||
|
var format = _(flags).contains(FS_FORMAT);
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
var deferred = when.defer();
|
||||||
|
this.promise = deferred.promise;
|
||||||
|
|
||||||
|
var openRequest = indexedDB.open(name);
|
||||||
|
openRequest.onupgradeneeded = function onupgradeneeded(event) {
|
||||||
|
var db = event.target.result;
|
||||||
|
|
||||||
|
if(db.objectStoreNames.contains(FILE_STORE_NAME)) {
|
||||||
|
db.deleteObjectStore(FILE_STORE_NAME);
|
||||||
|
}
|
||||||
|
var files = db.createObjectStore(FILE_STORE_NAME);
|
||||||
|
|
||||||
|
if(db.objectStoreNames.contains(METADATA_STORE_NAME)) {
|
||||||
|
db.deleteObjectStore(METADATA_STORE_NAME);
|
||||||
|
}
|
||||||
|
var metadata = db.createObjectStore(METADATA_STORE_NAME);
|
||||||
|
|
||||||
|
format = true;
|
||||||
|
};
|
||||||
|
openRequest.onsuccess = function onsuccess(event) {
|
||||||
|
var db = event.target.result;
|
||||||
|
|
||||||
|
function complete(error) {
|
||||||
|
if(error) {
|
||||||
|
that.readyState = FS_ERROR;
|
||||||
|
deferred.reject(error);
|
||||||
|
} else {
|
||||||
|
that.readyState = FS_READY;
|
||||||
|
that.db = db;
|
||||||
|
deferred.resolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(format) {
|
||||||
|
var transaction = db.transaction([FILE_STORE_NAME], IDB_RW);
|
||||||
|
var files = transaction.objectStore(FILE_STORE_NAME);
|
||||||
|
|
||||||
|
var clearRequest = files.clear();
|
||||||
|
clearRequest.onsuccess = function onsuccess(event) {
|
||||||
|
make_root_directory(files, complete);
|
||||||
|
};
|
||||||
|
clearRequest.onerror = function onerror(error) {
|
||||||
|
complete(error);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
openRequest.onerror = function onerror(error) {
|
||||||
|
this.readyState = FS_ERROR;
|
||||||
|
deferred.reject(error);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.readyState = FS_PENDING;
|
||||||
|
this.db = null;
|
||||||
|
};
|
||||||
|
FileSystem.prototype.open = function open(path, flags, mode) {
|
||||||
|
|
||||||
|
};
|
||||||
|
FileSystem.prototype.opendir = function opendir(path) {
|
||||||
|
|
||||||
|
};
|
||||||
|
FileSystem.prototype.mkdir = function mkdir(path) {
|
||||||
|
var deferred = when.defer();
|
||||||
|
var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW);
|
||||||
|
var files = transaction.objectStore(FILE_STORE_NAME);
|
||||||
|
|
||||||
|
function check_result(error) {
|
||||||
|
if(error) {
|
||||||
|
transaction.abort();
|
||||||
|
deferred.reject(error);
|
||||||
|
} else {
|
||||||
|
deferred.resolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
make_directory(files, path, check_result);
|
||||||
|
return deferred.promise;
|
||||||
|
};
|
||||||
|
FileSystem.prototype.rmdir = function rmdir(path) {
|
||||||
|
var deferred = when.defer();
|
||||||
|
var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW);
|
||||||
|
var files = transaction.objectStore(FILE_STORE_NAME);
|
||||||
|
|
||||||
|
function check_result(error) {
|
||||||
|
if(error) {
|
||||||
|
transaction.abort();
|
||||||
|
deferred.reject(error);
|
||||||
|
} else {
|
||||||
|
deferred.resolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
remove_directory(files, path, check_result);
|
||||||
|
return deferred.promise;
|
||||||
|
};
|
||||||
|
FileSystem.prototype.stat = function stat(path) {
|
||||||
|
|
||||||
|
};
|
||||||
|
FileSystem.prototype.link = function link(oldpath, newpath) {
|
||||||
|
|
||||||
|
};
|
||||||
|
FileSystem.prototype.unlink = function unlink(path) {
|
||||||
|
|
||||||
|
};
|
||||||
|
FileSystem.prototype.getxattr = function getxattr(path, name) {
|
||||||
|
|
||||||
|
};
|
||||||
|
FileSystem.prototype.setxattr = function setxattr(path, name, value) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
FileSystem: FileSystem,
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,28 @@
|
||||||
|
define(function(require) {
|
||||||
|
|
||||||
|
var MODE_FILE = require('src/constants').MODE_FILE;
|
||||||
|
|
||||||
|
var guid = require('src/shared').guid;
|
||||||
|
var hash = require('src/shared').hash;
|
||||||
|
|
||||||
|
function Node(id, mode, size, atime, ctime, mtime, flags, xattrs, links, version) {
|
||||||
|
var now = Date.now();
|
||||||
|
|
||||||
|
this.id = id || hash(guid()),
|
||||||
|
this.mode = mode || MODE_FILE; // node type (file, directory, etc)
|
||||||
|
this.size = size || 0; // size (bytes for files, entries for directories)
|
||||||
|
this.atime = atime || now; // access time
|
||||||
|
this.ctime = ctime || now; // creation time
|
||||||
|
this.mtime = mtime || now; // modified time
|
||||||
|
this.flags = flags || ''; // file flags
|
||||||
|
this.xattrs = xattrs || {}; // extended attributes
|
||||||
|
this.links = links || 0; // links count
|
||||||
|
this.version = version || 0; // node version
|
||||||
|
this.data = hash(id) // id for data object
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
Node: Node,
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
482
src/fs2.js
482
src/fs2.js
|
@ -1,482 +0,0 @@
|
||||||
define(function(require) {
|
|
||||||
|
|
||||||
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
|
|
||||||
|
|
||||||
var _ = require('lodash');
|
|
||||||
var when = require('when');
|
|
||||||
var Path = require('src/path');
|
|
||||||
var guid = require('src/guid');
|
|
||||||
require("crypto-js/rollups/sha256"); var Crypto = CryptoJS;
|
|
||||||
|
|
||||||
function EPathExists(){ Error.apply(this, arguments); }
|
|
||||||
EPathExists.prototype = new Error();
|
|
||||||
EPathExists.prototype.name = "EPathExists";
|
|
||||||
EPathExists.prototype.constructor = EPathExists;
|
|
||||||
|
|
||||||
function EIsDirectory(){ Error.apply(this, arguments); }
|
|
||||||
EIsDirectory.prototype = new Error();
|
|
||||||
EIsDirectory.prototype.name = "EIsDirectory";
|
|
||||||
EIsDirectory.prototype.constructor = EIsDirectory;
|
|
||||||
|
|
||||||
function ENoEntry(){ Error.apply(this, arguments); }
|
|
||||||
ENoEntry.prototype = new Error();
|
|
||||||
ENoEntry.prototype.name = "ENoEntry";
|
|
||||||
ENoEntry.prototype.constructor = ENoEntry;
|
|
||||||
|
|
||||||
function EBusy(){ Error.apply(this, arguments); }
|
|
||||||
EBusy.prototype = new Error();
|
|
||||||
EBusy.prototype.name = "EBusy";
|
|
||||||
EBusy.prototype.constructor = EBusy;
|
|
||||||
|
|
||||||
function ENotEmpty(){ Error.apply(this, arguments); }
|
|
||||||
ENotEmpty.prototype = new Error();
|
|
||||||
ENotEmpty.prototype.name = "ENotEmpty";
|
|
||||||
ENotEmpty.prototype.constructor = ENotEmpty;
|
|
||||||
|
|
||||||
function ENotDirectory(){ Error.apply(this, arguments); }
|
|
||||||
ENotDirectory.prototype = new Error();
|
|
||||||
ENotDirectory.prototype.name = "NotADirectoryError";
|
|
||||||
ENotDirectory.prototype.constructor = ENotDirectory;
|
|
||||||
|
|
||||||
function EBadFileDescriptor(){ Error.apply(this, arguments); }
|
|
||||||
EBadFileDescriptor.prototype = new Error();
|
|
||||||
EBadFileDescriptor.prototype.name = "EBadFileDescriptor";
|
|
||||||
EBadFileDescriptor.prototype.constructor = EBadFileDescriptor;
|
|
||||||
|
|
||||||
function ENotImplemented(){ Error.apply(this, arguments); }
|
|
||||||
ENotImplemented.prototype = new Error();
|
|
||||||
ENotImplemented.prototype.name = "ENotImplemented";
|
|
||||||
ENotImplemented.prototype.constructor = ENotImplemented;
|
|
||||||
|
|
||||||
function ENotMounted(){ Error.apply(this, arguments); }
|
|
||||||
ENotMounted.prototype = new Error();
|
|
||||||
ENotMounted.prototype.name = "ENotMounted";
|
|
||||||
ENotMounted.prototype.constructor = ENotMounted;
|
|
||||||
|
|
||||||
function EFileExists(){ Error.apply(this, arguments); }
|
|
||||||
EFileExists.prototype = new Error();
|
|
||||||
EFileExists.prototype.name = "EFileExists";
|
|
||||||
EFileExists.prototype.constructor = EFileExists;
|
|
||||||
|
|
||||||
var METADATA_STORE_NAME = 'metadata';
|
|
||||||
var FILE_STORE_NAME = 'files';
|
|
||||||
|
|
||||||
var IDB_RO = 'readonly';
|
|
||||||
var IDB_RW = 'readwrite';
|
|
||||||
|
|
||||||
var MODE_FILE = 'FILE';
|
|
||||||
var MODE_DIRECTORY = 'DIRECTORY';
|
|
||||||
var MODE_SYMBOLIC_LINK = 'SYMLINK';
|
|
||||||
|
|
||||||
var BINARY_MIME_TYPE = 'application/octet-stream';
|
|
||||||
var JSON_MIME_TYPE = 'application/json';
|
|
||||||
|
|
||||||
var ROOT_DIRECTORY_NAME = '/'; // basename(normalize(path))
|
|
||||||
var ROOT_NODE_ID = '8a5edab282632443219e051e4ade2d1d5bbc671c781051bf1437897cbdfea0f1'; // sha256(ROOT_DIRECTORY_NAME)
|
|
||||||
|
|
||||||
// FileSystem flags
|
|
||||||
var FS_FORMAT = 'FORMAT';
|
|
||||||
|
|
||||||
// FileSystem readyState
|
|
||||||
var FS_READY = 'READY';
|
|
||||||
var FS_PENDING = 'PENDING';
|
|
||||||
var FS_ERROR = 'ERROR';
|
|
||||||
|
|
||||||
function nop() {};
|
|
||||||
|
|
||||||
function hash(string) {
|
|
||||||
return Crypto.SHA256(string).toString(Crypto.enc.hex);
|
|
||||||
};
|
|
||||||
|
|
||||||
function Node(id, mode, size, atime, ctime, mtime, flags, xattrs, links, version) {
|
|
||||||
var now = Date.now();
|
|
||||||
|
|
||||||
this.id = id || hash(guid()),
|
|
||||||
this.mode = mode || MODE_FILE; // node type (file, directory, etc)
|
|
||||||
this.size = size || 0; // size (bytes for files, entries for directories)
|
|
||||||
this.atime = atime || now; // access time
|
|
||||||
this.ctime = ctime || now; // creation time
|
|
||||||
this.mtime = mtime || now; // modified time
|
|
||||||
this.flags = flags || ''; // file flags
|
|
||||||
this.xattrs = xattrs || {}; // extended attributes
|
|
||||||
this.links = links || 0; // links count
|
|
||||||
this.version = version || 0; // node version
|
|
||||||
this.data = hash(id) // id for data object
|
|
||||||
};
|
|
||||||
|
|
||||||
function DirectoryEntry(id, type) {
|
|
||||||
this.id = id;
|
|
||||||
this.type = type || MODE_FILE;
|
|
||||||
};
|
|
||||||
|
|
||||||
function read_object(objectStore, id, callback) {
|
|
||||||
var getRequest = objectStore.get(id);
|
|
||||||
getRequest.onsuccess = function onsuccess(event) {
|
|
||||||
var result = event.target.result;
|
|
||||||
callback(undefined, result);
|
|
||||||
};
|
|
||||||
getRequest.onerror = function onerror(error) {
|
|
||||||
callback(error);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function write_object(objectStore, object, id, callback) {
|
|
||||||
var putRequest = objectStore.put(object, id);
|
|
||||||
putRequest.onsuccess = function onsuccess(event) {
|
|
||||||
var result = event.target.result;
|
|
||||||
callback(undefined, result);
|
|
||||||
};
|
|
||||||
putRequest.onerror = function onerror(error) {
|
|
||||||
callback(error);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function delete_object(objectStore, id, callback) {
|
|
||||||
var deleteRequest = objectStore.delete(id);
|
|
||||||
deleteRequest.onsuccess = function onsuccess(event) {
|
|
||||||
var result = event.target.result;
|
|
||||||
callback(undefined, result);
|
|
||||||
};
|
|
||||||
deleteRequest.onerror = function(error) {
|
|
||||||
callback(error);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// in: file or directory path
|
|
||||||
// out: node structure, or error
|
|
||||||
function find_node(objectStore, path, callback) {
|
|
||||||
path = Path.normalize(path);
|
|
||||||
var name = Path.basename(path);
|
|
||||||
|
|
||||||
if(ROOT_DIRECTORY_NAME == name) {
|
|
||||||
function check_root_directory_node(error, rootDirectoryNode) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else if(!rootDirectoryNode) {
|
|
||||||
callback(new ENoEntry());
|
|
||||||
} else {
|
|
||||||
callback(undefined, rootDirectoryNode);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
read_object(objectStore, ROOT_NODE_ID, check_root_directory_node);
|
|
||||||
} else {
|
|
||||||
// in: parent directory node
|
|
||||||
// out: parent directory data
|
|
||||||
function read_parent_directory_data(error, parentDirectoryNode) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else if(!_(parentDirectoryNode).has('data') || !parentDirectoryNode.type == MODE_DIRECTORY) {
|
|
||||||
callback(new ENotDirectory());
|
|
||||||
} else {
|
|
||||||
read_object(objectStore, parentDirectoryNode.data, get_node_id_from_parent_directory_data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// in: parent directory data
|
|
||||||
// out: searched node id
|
|
||||||
function get_node_id_from_parent_directory_data(error, parentDirectoryData) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else {
|
|
||||||
if(!_(parentDirectoryData).has(name)) {
|
|
||||||
callback(new ENoEntry());
|
|
||||||
} else {
|
|
||||||
var nodeId = parentDirectoryData[name].id;
|
|
||||||
read_object(objectStore, nodeId, callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var parentPath = Path.dirname(path);
|
|
||||||
find_node(objectStore, parentPath, read_parent_directory_data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Note: this should only be invoked when formatting a new file system
|
|
||||||
function make_root_directory(objectStore, callback) {
|
|
||||||
var directoryNode;
|
|
||||||
var directoryData;
|
|
||||||
|
|
||||||
function write_directory_node(error, existingNode) {
|
|
||||||
if(!error && existingNode) {
|
|
||||||
callback(new EPathExists());
|
|
||||||
} else if(error && !error instanceof ENoEntry) {
|
|
||||||
callback(error);
|
|
||||||
} else {
|
|
||||||
directoryNode = new Node(ROOT_NODE_ID, MODE_DIRECTORY);
|
|
||||||
directoryNode.links += 1;
|
|
||||||
write_object(objectStore, directoryNode, directoryNode.id, write_directory_data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function write_directory_data(error) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else {
|
|
||||||
directoryData = {};
|
|
||||||
write_object(objectStore, directoryData, directoryNode.data, callback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
find_node(objectStore, ROOT_DIRECTORY_NAME, write_directory_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_directory(objectStore, path, callback) {
|
|
||||||
path = Path.normalize(path);
|
|
||||||
var name = Path.basename(path);
|
|
||||||
var parentPath = Path.dirname(path);
|
|
||||||
|
|
||||||
var directoryNode;
|
|
||||||
var directoryData;
|
|
||||||
var parentDirectoryNode;
|
|
||||||
var parentDirectoryData;
|
|
||||||
|
|
||||||
function check_if_directory_exists(error, result) {
|
|
||||||
if(!error && result) {
|
|
||||||
callback(new EPathExists());
|
|
||||||
} else if(error && !error instanceof ENoEntry) {
|
|
||||||
callback(error);
|
|
||||||
} else {
|
|
||||||
find_node(objectStore, parentPath, read_parent_directory_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function read_parent_directory_data(error, result) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else {
|
|
||||||
parentDirectoryNode = result;
|
|
||||||
read_object(objectStore, parentDirectoryNode.data, write_directory_node);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function write_directory_node(error, result) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else {
|
|
||||||
parentDirectoryData = result;
|
|
||||||
directoryNode = new Node(undefined, MODE_DIRECTORY);
|
|
||||||
directoryNode.links += 1;
|
|
||||||
write_object(objectStore, directoryNode, directoryNode.id, write_directory_data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function write_directory_data(error) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else {
|
|
||||||
directoryData = {};
|
|
||||||
write_object(objectStore, directoryData, directoryNode.data, update_parent_directory_data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function update_parent_directory_data(error) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else {
|
|
||||||
parentDirectoryData[name] = new DirectoryEntry(directoryNode.id, MODE_DIRECTORY);
|
|
||||||
write_object(objectStore, parentDirectoryData, parentDirectoryNode.data, callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
find_node(objectStore, path, check_if_directory_exists);
|
|
||||||
};
|
|
||||||
|
|
||||||
function remove_directory(objectStore, path, callback) {
|
|
||||||
path = Path.normalize(path);
|
|
||||||
var name = Path.basename(path);
|
|
||||||
var parentPath = Path.dirname(path);
|
|
||||||
|
|
||||||
var directoryNode;
|
|
||||||
var directoryData;
|
|
||||||
var parentDirectoryNode;
|
|
||||||
var parentDirectoryData;
|
|
||||||
|
|
||||||
function check_if_directory_exists(error, result) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else if(!result) {
|
|
||||||
callback(new ENoEntry());
|
|
||||||
} else {
|
|
||||||
directoryNode = result;
|
|
||||||
read_object(objectStore, directoryNode.data, check_if_directory_is_empty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function check_if_directory_is_empty(error, result) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else {
|
|
||||||
directoryData = result;
|
|
||||||
if(_(directoryData).size() > 0) {
|
|
||||||
callback(new ENotEmpty());
|
|
||||||
} else {
|
|
||||||
find_node(objectStore, parentPath, read_parent_directory_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function read_parent_directory_data(error, result) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else {
|
|
||||||
parentDirectoryNode = result;
|
|
||||||
read_object(objectStore, parentDirectoryNode.data, remove_directory_entry_from_parent_directory_node);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function remove_directory_entry_from_parent_directory_node(error, result) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else {
|
|
||||||
parentDirectoryData = result;
|
|
||||||
delete parentDirectoryData[name];
|
|
||||||
write_object(objectStore, parentDirectoryData, parentDirectoryNode.data, remove_directory_node);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function remove_directory_node(error) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else {
|
|
||||||
delete_object(objectStore, directoryNode.id, remove_directory_data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function remove_directory_data(error) {
|
|
||||||
if(error) {
|
|
||||||
callback(error);
|
|
||||||
} else {
|
|
||||||
delete_object(objectStore, directoryNode.data, callback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
find_node(objectStore, path, check_if_directory_exists);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FileSystem
|
|
||||||
*/
|
|
||||||
|
|
||||||
function FileSystem(name, flags) {
|
|
||||||
var format = _(flags).contains(FS_FORMAT);
|
|
||||||
var that = this;
|
|
||||||
|
|
||||||
var deferred = when.defer();
|
|
||||||
this.promise = deferred.promise;
|
|
||||||
|
|
||||||
var openRequest = indexedDB.open(name);
|
|
||||||
openRequest.onupgradeneeded = function onupgradeneeded(event) {
|
|
||||||
var db = event.target.result;
|
|
||||||
|
|
||||||
if(db.objectStoreNames.contains(FILE_STORE_NAME)) {
|
|
||||||
db.deleteObjectStore(FILE_STORE_NAME);
|
|
||||||
}
|
|
||||||
var files = db.createObjectStore(FILE_STORE_NAME);
|
|
||||||
|
|
||||||
if(db.objectStoreNames.contains(METADATA_STORE_NAME)) {
|
|
||||||
db.deleteObjectStore(METADATA_STORE_NAME);
|
|
||||||
}
|
|
||||||
var metadata = db.createObjectStore(METADATA_STORE_NAME);
|
|
||||||
|
|
||||||
format = true;
|
|
||||||
};
|
|
||||||
openRequest.onsuccess = function onsuccess(event) {
|
|
||||||
var db = event.target.result;
|
|
||||||
|
|
||||||
function complete(error) {
|
|
||||||
if(error) {
|
|
||||||
that.readyState = FS_ERROR;
|
|
||||||
deferred.reject(error);
|
|
||||||
} else {
|
|
||||||
that.readyState = FS_READY;
|
|
||||||
that.db = db;
|
|
||||||
deferred.resolve();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(format) {
|
|
||||||
var transaction = db.transaction([FILE_STORE_NAME], IDB_RW);
|
|
||||||
var files = transaction.objectStore(FILE_STORE_NAME);
|
|
||||||
|
|
||||||
var clearRequest = files.clear();
|
|
||||||
clearRequest.onsuccess = function onsuccess(event) {
|
|
||||||
make_root_directory(files, complete);
|
|
||||||
};
|
|
||||||
clearRequest.onerror = function onerror(error) {
|
|
||||||
complete(error);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
complete();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
openRequest.onerror = function onerror(error) {
|
|
||||||
this.readyState = FS_ERROR;
|
|
||||||
deferred.reject(error);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.readyState = FS_PENDING;
|
|
||||||
this.db = null;
|
|
||||||
};
|
|
||||||
FileSystem.prototype.open = function open(path, flags, mode) {
|
|
||||||
|
|
||||||
};
|
|
||||||
FileSystem.prototype.opendir = function opendir(path) {
|
|
||||||
|
|
||||||
};
|
|
||||||
FileSystem.prototype.mkdir = function mkdir(path) {
|
|
||||||
var deferred = when.defer();
|
|
||||||
var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW);
|
|
||||||
var files = transaction.objectStore(FILE_STORE_NAME);
|
|
||||||
|
|
||||||
function check_result(error) {
|
|
||||||
if(error) {
|
|
||||||
transaction.abort();
|
|
||||||
deferred.reject(error);
|
|
||||||
} else {
|
|
||||||
deferred.resolve();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
make_directory(files, path, check_result);
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
FileSystem.prototype.rmdir = function rmdir(path) {
|
|
||||||
var deferred = when.defer();
|
|
||||||
var transaction = this.db.transaction([FILE_STORE_NAME], IDB_RW);
|
|
||||||
var files = transaction.objectStore(FILE_STORE_NAME);
|
|
||||||
|
|
||||||
function check_result(error) {
|
|
||||||
if(error) {
|
|
||||||
transaction.abort();
|
|
||||||
deferred.reject(error);
|
|
||||||
} else {
|
|
||||||
deferred.resolve();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
remove_directory(files, path, check_result);
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
FileSystem.prototype.stat = function stat(path) {
|
|
||||||
|
|
||||||
};
|
|
||||||
FileSystem.prototype.link = function link(oldpath, newpath) {
|
|
||||||
|
|
||||||
};
|
|
||||||
FileSystem.prototype.unlink = function unlink(path) {
|
|
||||||
|
|
||||||
};
|
|
||||||
FileSystem.prototype.getxattr = function getxattr(path, name) {
|
|
||||||
|
|
||||||
};
|
|
||||||
FileSystem.prototype.setxattr = function setxattr(path, name, value) {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
FileSystem: FileSystem,
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
|
17
src/guid.js
17
src/guid.js
|
@ -1,17 +0,0 @@
|
||||||
if ( typeof define !== "function" ) {
|
|
||||||
var define = require( "amdefine" )( module );
|
|
||||||
}
|
|
||||||
|
|
||||||
define( function ( require ) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
function guid() {
|
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
|
||||||
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
|
|
||||||
return v.toString(16);
|
|
||||||
}).toUpperCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
return guid;
|
|
||||||
|
|
||||||
});
|
|
320
src/indexeddb.js
320
src/indexeddb.js
|
@ -1,320 +0,0 @@
|
||||||
define(function(require) {
|
|
||||||
|
|
||||||
var when = require('when');
|
|
||||||
|
|
||||||
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
|
|
||||||
|
|
||||||
function Event(idbEvent, target) {
|
|
||||||
this._event = idbEvent;
|
|
||||||
this.type = idbEvent.type;
|
|
||||||
this.timeStamp = idbEvent.timeStamp;
|
|
||||||
this.target = target || idbEvent.target;
|
|
||||||
};
|
|
||||||
|
|
||||||
function Target(idbTarget, result) {
|
|
||||||
this.idbTarget = idbTarget;
|
|
||||||
this.result = result || idbTarget.result;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Cursor
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Cursor(idbCursor) {
|
|
||||||
this.idbCursor = idbCursor;
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'source', {
|
|
||||||
get: function() {
|
|
||||||
return idbCursor.source;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'direction', {
|
|
||||||
get: function() {
|
|
||||||
return idbCursor.direction;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'key', {
|
|
||||||
get: function() {
|
|
||||||
return idbCursor.key;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'primaryKey', {
|
|
||||||
get: function() {
|
|
||||||
return idbCursor.primaryKey;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Cursor.prototype.update = function update(value) {
|
|
||||||
var idbCursor = this.idbCursor;
|
|
||||||
var deferred = when.defer();
|
|
||||||
|
|
||||||
var request = idbCursor.update(value);
|
|
||||||
request.onsuccess = function(event) {
|
|
||||||
deferred.resolve(event);
|
|
||||||
};
|
|
||||||
request.onerror = function(event) {
|
|
||||||
deferred.reject(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
Cursor.prototype.advance = function advance(count) {
|
|
||||||
var idbCursor = this.idbCursor;
|
|
||||||
return idbCursor.advance(count);
|
|
||||||
};
|
|
||||||
Cursor.prototype.continue = function continue(key) {
|
|
||||||
var idbCursor = this.idbCursor;
|
|
||||||
return idbCursor.continue(key);
|
|
||||||
};
|
|
||||||
Cursor.prototype.delete = function delete() {
|
|
||||||
var idbCursor = this.idbCursor;
|
|
||||||
var deferred = when.defer();
|
|
||||||
|
|
||||||
var request = idbCursor.delete();
|
|
||||||
request.onsuccess = function(event) {
|
|
||||||
deferred.resolve(event);
|
|
||||||
};
|
|
||||||
request.onerror = function(event) {
|
|
||||||
deferred.reject(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ObjectStore
|
|
||||||
*/
|
|
||||||
|
|
||||||
function ObjectStore(idbTransaction, name) {
|
|
||||||
this.idbObjectStore = idbTransaction.objectStore(name);
|
|
||||||
};
|
|
||||||
ObjectStore.prototype.add = function add(value, key) {
|
|
||||||
var idbObjectStore = this.idbObjectStore;
|
|
||||||
var deferred = when.defer();
|
|
||||||
|
|
||||||
var request = idbObjectStore.add(value, key);
|
|
||||||
request.onsuccess = function(event) {
|
|
||||||
deferred.resolve(event);
|
|
||||||
};
|
|
||||||
request.onerror = function(event) {
|
|
||||||
deferred.reject(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
ObjectStore.prototype.clear = function clear() {
|
|
||||||
var idbObjectStore = this.idbObjectStore;
|
|
||||||
var deferred = when.defer();
|
|
||||||
|
|
||||||
var request = idbObjectStore.clear();
|
|
||||||
request.onsuccess = function(event) {
|
|
||||||
deferred.resolve(event);
|
|
||||||
};
|
|
||||||
request.onerror = function(event) {
|
|
||||||
deferred.reject(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
ObjectStore.prototype.count = function count(key) {
|
|
||||||
var idbObjectStore = this.idbObjectStore;
|
|
||||||
var deferred = when.defer();
|
|
||||||
|
|
||||||
var request = idbObjectStore.count(key);
|
|
||||||
request.onsuccess = function(event) {
|
|
||||||
deferred.resolve(event);
|
|
||||||
};
|
|
||||||
request.onerror = function(event) {
|
|
||||||
deferred.reject(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
ObjectStore.prototype.createIndex = function createIndex(name, keyPath, optionalParameters) {
|
|
||||||
var idbObjectStore = this.idbObjectStore;
|
|
||||||
return idbObjectStore.createIndex(name, keyPath, optionalParameters);
|
|
||||||
};
|
|
||||||
ObjectStore.prototype.delete = function delete(key) {
|
|
||||||
var idbObjectStore = this.idbObjectStore;
|
|
||||||
var deferred = when.defer();
|
|
||||||
|
|
||||||
var request = idbObjectStore.delete(key);
|
|
||||||
request.onsuccess = function(event) {
|
|
||||||
deferred.resolve(event);
|
|
||||||
};
|
|
||||||
request.onerror = function(event) {
|
|
||||||
deferred.reject(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
ObjectStore.prototype.deleteIndex = function deleteIndex(name) {
|
|
||||||
var idbObjectStore = this.idbObjectStore;
|
|
||||||
return idbObjectStore.deleteIndex(name);
|
|
||||||
};
|
|
||||||
ObjectStore.prototype.get = function get(key) {
|
|
||||||
var idbObjectStore = this.idbObjectStore;
|
|
||||||
var deferred = when.defer();
|
|
||||||
|
|
||||||
var request = idbObjectStore.get(key);
|
|
||||||
request.onsuccess = function(event) {
|
|
||||||
deferred.resolve(event);
|
|
||||||
};
|
|
||||||
request.onerror = function(event) {
|
|
||||||
deferred.reject(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
ObjectStore.prototype.index = function index(name) {
|
|
||||||
var idbObjectStore = this.idbObjectStore;
|
|
||||||
return idbObjectStore.index(name);
|
|
||||||
};
|
|
||||||
ObjectStore.prototype.openCursor = function openCursor(range, direction) {
|
|
||||||
var idbObjectStore = this.idbObjectStore;
|
|
||||||
var deferred = when.defer();
|
|
||||||
|
|
||||||
var request = (!(range || direction)) ? idbObjectStore.openCursor() : idbObjectStore.openCursor(range, direction);
|
|
||||||
request.onsuccess = function(event) {
|
|
||||||
var wrappedEvent = new Event(event);
|
|
||||||
wrappedEvent.result = event.result;
|
|
||||||
if(!event.result) {
|
|
||||||
deferred.resolve(wrappedEvent);
|
|
||||||
} else {
|
|
||||||
deferred.notify(wrappedEvent);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
request.onerror = function(event) {
|
|
||||||
deferred.reject(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
ObjectStore.prototype.put = function put(value, key) {
|
|
||||||
var idbObjectStore = this.idbObjectStore;
|
|
||||||
var deferred = when.defer();
|
|
||||||
|
|
||||||
var request = idbObjectStore.put(value, key);
|
|
||||||
request.onsuccess = function(event) {
|
|
||||||
deferred.resolve(event);
|
|
||||||
};
|
|
||||||
request.onerror = function(event) {
|
|
||||||
deferred.reject(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Transaction
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Transaction(idbDatabase, storeNames, mode) {
|
|
||||||
this.idbTransaction = idbDatabase.transaction(storeNames, mode);
|
|
||||||
};
|
|
||||||
Transaction.prototype.objectStore = function objectStore(name) {
|
|
||||||
var idbTransaction = this.idbTransaction;
|
|
||||||
return new ObjectStore(idbTransaction, name);
|
|
||||||
};
|
|
||||||
Transaction.prototype.abort = function abort() {
|
|
||||||
var idbTransaction = this.idbTransaction;
|
|
||||||
return idbTransaction.abort();
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Database
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Database(idbDatabase) {
|
|
||||||
this.idbDatabase = idbDatabase;
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'name', {
|
|
||||||
get: function() {
|
|
||||||
return idbDatabase.name;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'version', {
|
|
||||||
get: function() {
|
|
||||||
return idbDatabase.version;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'objectStoreNames', {
|
|
||||||
get: function() {
|
|
||||||
return idbDatabase.objectStoreNames;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Database.prototype.createObjectStore = function createObjectStore(name, optionalParameters) {
|
|
||||||
var idbDatabase = this.idbDatabase;
|
|
||||||
return idbDatabase.createObjectStore(name, optionalParameters);
|
|
||||||
};
|
|
||||||
Database.prototype.deleteObjectStore = function deleteObjectStore(name) {
|
|
||||||
var idbDatabase = this.idbDatabase;
|
|
||||||
return idbDatabase.deleteObjectStore(name);
|
|
||||||
};
|
|
||||||
Database.prototype.transaction = function transaction(storeNames, mode) {
|
|
||||||
var idbDatabase = this.idbDatabase;
|
|
||||||
return new Transaction(idbDatabase, storeNames, mode);
|
|
||||||
};
|
|
||||||
Database.prototype.close = function close() {
|
|
||||||
var idbDatabase = this.idbDatabase;
|
|
||||||
return idbDatabase.close();
|
|
||||||
};
|
|
||||||
Database.prototype.objectStoreNames = function objectStoreNames() {
|
|
||||||
var idbDatabase = this.idbDatabase;
|
|
||||||
return idbDatabase.objectStoreNames;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Factory
|
|
||||||
*/
|
|
||||||
|
|
||||||
function open(name, version) {
|
|
||||||
var deferred = when.defer();
|
|
||||||
|
|
||||||
var request = indexedDB.open(name);
|
|
||||||
request.onupgradeneeded = function(event) {
|
|
||||||
var wrappedEvent = new Event(event, new Target(event.target, new Database(event.target.result)));
|
|
||||||
deferred.notify(wrappedEvent);
|
|
||||||
};
|
|
||||||
request.onsuccess = function(event) {
|
|
||||||
var wrappedEvent = new Event(event, new Target(event.target, new Database(event.target.result)));
|
|
||||||
deferred.resolve(wrappedEvent);
|
|
||||||
};
|
|
||||||
request.onerror = function(event) {
|
|
||||||
deferred.reject(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
function deleteDatabase(name) {
|
|
||||||
var deferred = when.defer();
|
|
||||||
|
|
||||||
var request = indexedDB.deleteDatabase(name);
|
|
||||||
request.onupgradeneeded = function(event) {
|
|
||||||
deferred.notify(event);
|
|
||||||
};
|
|
||||||
request.onsuccess = function(event) {
|
|
||||||
deferred.resolve(event);
|
|
||||||
};
|
|
||||||
request.onerror = function(event) {
|
|
||||||
deferred.reject(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
open: open,
|
|
||||||
deleteDatabase: deleteDatabase,
|
|
||||||
KeyRange: indexedDB.KeyRange,
|
|
||||||
when: when,
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
|
|
@ -1,108 +0,0 @@
|
||||||
define(function(require) {
|
|
||||||
|
|
||||||
var when = require('when');
|
|
||||||
|
|
||||||
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Transaction
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Transaction(idbDatabase, storeNames, mode) {
|
|
||||||
this.idbTransaction = idbDatabase.transaction(storeNames, mode);
|
|
||||||
};
|
|
||||||
Transaction.prototype.objectStore = function objectStore(name) {
|
|
||||||
var idbTransaction = this.idbTransaction;
|
|
||||||
return new ObjectStore(idbTransaction, name);
|
|
||||||
};
|
|
||||||
Transaction.prototype.abort = function abort() {
|
|
||||||
var idbTransaction = this.idbTransaction;
|
|
||||||
return idbTransaction.abort();
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Database
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Database(idbDatabase) {
|
|
||||||
this.idbDatabase = idbDatabase;
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'name', {
|
|
||||||
get: function() {
|
|
||||||
return idbDatabase.name;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'version', {
|
|
||||||
get: function() {
|
|
||||||
return idbDatabase.version;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'objectStoreNames', {
|
|
||||||
get: function() {
|
|
||||||
return idbDatabase.objectStoreNames;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Database.prototype.createObjectStore = function createObjectStore(name, optionalParameters) {
|
|
||||||
var idbDatabase = this.idbDatabase;
|
|
||||||
return idbDatabase.createObjectStore(name, optionalParameters);
|
|
||||||
};
|
|
||||||
Database.prototype.deleteObjectStore = function deleteObjectStore(name) {
|
|
||||||
var idbDatabase = this.idbDatabase;
|
|
||||||
return idbDatabase.deleteObjectStore(name);
|
|
||||||
};
|
|
||||||
Database.prototype.transaction = function transaction(storeNames, mode) {
|
|
||||||
var idbDatabase = this.idbDatabase;
|
|
||||||
return new Transaction(idbDatabase, storeNames, mode);
|
|
||||||
};
|
|
||||||
Database.prototype.close = function close() {
|
|
||||||
var idbDatabase = this.idbDatabase;
|
|
||||||
return idbDatabase.close();
|
|
||||||
};
|
|
||||||
Database.prototype.objectStoreNames = function objectStoreNames() {
|
|
||||||
var idbDatabase = this.idbDatabase;
|
|
||||||
return idbDatabase.objectStoreNames;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Factory
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Factory() {
|
|
||||||
this.when = when;
|
|
||||||
};
|
|
||||||
Factory.prototype.open = function open(name, version) {
|
|
||||||
var deferred = when.defer();
|
|
||||||
|
|
||||||
var request = indexedDB.open(name);
|
|
||||||
request.onupgradeneeded = function(idbEvent) {
|
|
||||||
var db = new Database(idbEvent.target.result);
|
|
||||||
var event = {
|
|
||||||
type: 'upgradeneeded',
|
|
||||||
db: db
|
|
||||||
};
|
|
||||||
deferred.notify(event);
|
|
||||||
};
|
|
||||||
request.onsuccess = function(idbEvent) {
|
|
||||||
var db = new Database(idbEvent.target.result);
|
|
||||||
var event = {
|
|
||||||
type: 'success',
|
|
||||||
db: db
|
|
||||||
};
|
|
||||||
deferred.resolve(event);
|
|
||||||
};
|
|
||||||
request.onerror = function(idbError) {
|
|
||||||
deferred.reject(idbError);
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
Factory.prototype.deleteDatabase = function deleteDatabase(name) {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Factory();
|
|
||||||
|
|
||||||
});
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
define(function(require) {
|
||||||
|
|
||||||
|
function read_object(objectStore, id, callback) {
|
||||||
|
var getRequest = objectStore.get(id);
|
||||||
|
getRequest.onsuccess = function onsuccess(event) {
|
||||||
|
var result = event.target.result;
|
||||||
|
callback(undefined, result);
|
||||||
|
};
|
||||||
|
getRequest.onerror = function onerror(error) {
|
||||||
|
callback(error);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function write_object(objectStore, object, id, callback) {
|
||||||
|
var putRequest = objectStore.put(object, id);
|
||||||
|
putRequest.onsuccess = function onsuccess(event) {
|
||||||
|
var result = event.target.result;
|
||||||
|
callback(undefined, result);
|
||||||
|
};
|
||||||
|
putRequest.onerror = function onerror(error) {
|
||||||
|
callback(error);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function delete_object(objectStore, id, callback) {
|
||||||
|
var deleteRequest = objectStore.delete(id);
|
||||||
|
deleteRequest.onsuccess = function onsuccess(event) {
|
||||||
|
var result = event.target.result;
|
||||||
|
callback(undefined, result);
|
||||||
|
};
|
||||||
|
deleteRequest.onerror = function(error) {
|
||||||
|
callback(error);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
read_object: read_object,
|
||||||
|
write_object: write_object,
|
||||||
|
delete_object: delete_object,
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,24 @@
|
||||||
|
define(function(require) {
|
||||||
|
|
||||||
|
require("crypto-js/rollups/sha256"); var Crypto = CryptoJS;
|
||||||
|
|
||||||
|
function guid() {
|
||||||
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||||
|
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
|
||||||
|
return v.toString(16);
|
||||||
|
}).toUpperCase();
|
||||||
|
};
|
||||||
|
|
||||||
|
function hash(string) {
|
||||||
|
return Crypto.SHA256(string).toString(Crypto.enc.hex);
|
||||||
|
};
|
||||||
|
|
||||||
|
function nop() {};
|
||||||
|
|
||||||
|
return {
|
||||||
|
guid: guid,
|
||||||
|
hash: hash,
|
||||||
|
nop: nop,
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue