diff --git a/examples/refactoring-test.html b/examples/refactoring-test.html index 724c7c8..3f9c0c4 100644 --- a/examples/refactoring-test.html +++ b/examples/refactoring-test.html @@ -15,7 +15,7 @@ require.config({ } }); -require(["src/fs2"], function(IDBFS) { +require(["src/file-system"], function(IDBFS) { var flags = 'FORMAT'; //var flags = undefined; diff --git a/src/fs.js b/src/_old-fs.js similarity index 100% rename from src/fs.js rename to src/_old-fs.js diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000..a2f9512 --- /dev/null +++ b/src/constants.js @@ -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', + }; + +}); \ No newline at end of file diff --git a/src/directory.js b/src/directory.js new file mode 100644 index 0000000..b7aa039 --- /dev/null +++ b/src/directory.js @@ -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, + }; + +}); \ No newline at end of file diff --git a/src/event.js b/src/event.js deleted file mode 100644 index 1c81ae8..0000000 --- a/src/event.js +++ /dev/null @@ -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 - }; - -}; \ No newline at end of file diff --git a/src/file-system.js b/src/file-system.js new file mode 100644 index 0000000..1514f47 --- /dev/null +++ b/src/file-system.js @@ -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, + }; + +}); \ No newline at end of file diff --git a/src/file.js b/src/file.js new file mode 100644 index 0000000..c6ee50c --- /dev/null +++ b/src/file.js @@ -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, + }; + +}); \ No newline at end of file diff --git a/src/fs2.js b/src/fs2.js deleted file mode 100644 index b08c535..0000000 --- a/src/fs2.js +++ /dev/null @@ -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, - }; - -}); \ No newline at end of file diff --git a/src/guid.js b/src/guid.js deleted file mode 100644 index 885cda8..0000000 --- a/src/guid.js +++ /dev/null @@ -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; - -}); diff --git a/src/indexeddb.js b/src/indexeddb.js deleted file mode 100644 index a4ac217..0000000 --- a/src/indexeddb.js +++ /dev/null @@ -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, - }; - -}); \ No newline at end of file diff --git a/src/indexeddb2.js b/src/indexeddb2.js deleted file mode 100644 index ea01ce3..0000000 --- a/src/indexeddb2.js +++ /dev/null @@ -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(); - -}); \ No newline at end of file diff --git a/src/object-store.js b/src/object-store.js new file mode 100644 index 0000000..5323e03 --- /dev/null +++ b/src/object-store.js @@ -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, + }; + +}); \ No newline at end of file diff --git a/src/shared.js b/src/shared.js new file mode 100644 index 0000000..5599bd8 --- /dev/null +++ b/src/shared.js @@ -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, + }; + +}); \ No newline at end of file