Reorganize files.

This commit is contained in:
Alan Kligman 2013-05-30 21:38:44 -04:00
parent a2ff2823dc
commit 4f5ff333fb
13 changed files with 538 additions and 976 deletions

View File

@ -15,7 +15,7 @@ require.config({
}
});
require(["src/fs2"], function(IDBFS) {
require(["src/file-system"], function(IDBFS) {
var flags = 'FORMAT';
//var flags = undefined;

36
src/constants.js Normal file
View File

@ -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',
};
});

247
src/directory.js Normal file
View File

@ -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,
};
});

View File

@ -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
};
};

160
src/file-system.js Normal file
View File

@ -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,
};
});

28
src/file.js Normal file
View File

@ -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,
};
});

View File

@ -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,
};
});

View File

@ -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;
});

View File

@ -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,
};
});

View File

@ -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();
});

42
src/object-store.js Normal file
View File

@ -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,
};
});

24
src/shared.js Normal file
View File

@ -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,
};
});