idb-wrapper
Advanced tools
Comparing version 0.2.1 to 0.3.0
174
IDBStore.js
@@ -87,10 +87,6 @@ /* | ||
_insertIdCount: 0, | ||
openDB: function () { | ||
this.newVersionAPI = typeof this.idb.setVersion == 'undefined'; | ||
if(!this.newVersionAPI){ | ||
this.onError(new Error('The IndexedDB implementation in this browser is outdated. Please upgrade your browser.')); | ||
} | ||
var features = this.features = {}; | ||
@@ -100,2 +96,3 @@ features.hasAutoIncrement = !window.mozIndexedDB; // TODO: Still, really? | ||
var openRequest = this.idb.open(this.dbName, this.dbVersion); | ||
var preventSuccessCallback = false; | ||
@@ -118,5 +115,8 @@ openRequest.onerror = function (error) { | ||
openRequest.onsuccess = function (event) { | ||
if (preventSuccessCallback) { | ||
return; | ||
} | ||
if(this.db){ | ||
@@ -129,45 +129,45 @@ this.onStoreReady(); | ||
if(this.db.objectStoreNames.contains(this.storeName)){ | ||
if(!this.store){ | ||
var emptyTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); | ||
this.store = emptyTransaction.objectStore(this.storeName); | ||
} | ||
// check indexes | ||
if(typeof this.db.version == 'string'){ | ||
this.onError(new Error('The IndexedDB implementation in this browser is outdated. Please upgrade your browser.')); | ||
return; | ||
} | ||
this.indexes.forEach(function(indexData){ | ||
var indexName = indexData.name; | ||
if(!this.db.objectStoreNames.contains(this.storeName)){ | ||
// We should never ever get here. | ||
// Lets notify the user anyway. | ||
this.onError(new Error('Something is wrong with the IndexedDB implementation in this browser. Please upgrade your browser.')); | ||
return; | ||
} | ||
// normalize and provide existing keys | ||
indexData.keyPath = indexData.keyPath || indexName; | ||
indexData.unique = !!indexData.unique; | ||
indexData.multiEntry = !!indexData.multiEntry; | ||
var emptyTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); | ||
this.store = emptyTransaction.objectStore(this.storeName); | ||
if(!indexName){ | ||
throw new Error('Cannot create index: No index name given.'); | ||
} | ||
// check indexes | ||
this.indexes.forEach(function(indexData){ | ||
var indexName = indexData.name; | ||
if(this.hasIndex(indexName)){ | ||
// check if it complies | ||
var actualIndex = this.store.index(indexName); | ||
var complies = ['keyPath', 'unique', 'multiEntry'].every(function(key){ | ||
// IE10 returns undefined for no multiEntry | ||
if (key == 'multiEntry' && actualIndex[key] === undefined && indexData[key] === false) { | ||
return true; | ||
} | ||
return indexData[key] == actualIndex[key]; | ||
}); | ||
if(!complies){ | ||
this.onError(new Error('Cannot modify index "' + indexName + '" for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); | ||
} | ||
} else { | ||
this.onError(new Error('Cannot create new index "' + indexName + '" for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); | ||
if(!indexName){ | ||
preventSuccessCallback = true; | ||
this.onError(new Error('Cannot create index: No index name given.')); | ||
return; | ||
} | ||
this.normalizeIndexData(indexData); | ||
if(this.hasIndex(indexName)){ | ||
// check if it complies | ||
var actualIndex = this.store.index(indexName); | ||
var complies = this.indexComplies(actualIndex, indexData); | ||
if(!complies){ | ||
preventSuccessCallback = true; | ||
this.onError(new Error('Cannot modify index "' + indexName + '" for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); | ||
} | ||
} else { | ||
preventSuccessCallback = true; | ||
this.onError(new Error('Cannot create new index "' + indexName + '" for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); | ||
} | ||
}, this); | ||
}, this); | ||
this.onStoreReady(); | ||
} else { | ||
// We should never get here. | ||
this.onError(new Error('Cannot create a new store for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); | ||
} | ||
preventSuccessCallback || this.onStoreReady(); | ||
}.bind(this); | ||
@@ -188,21 +188,13 @@ | ||
// normalize and provide existing keys | ||
indexData.keyPath = indexData.keyPath || indexName; | ||
indexData.unique = !!indexData.unique; | ||
indexData.multiEntry = !!indexData.multiEntry; | ||
if(!indexName){ | ||
preventSuccessCallback = true; | ||
this.onError(new Error('Cannot create index: No index name given.')); | ||
} | ||
this.normalizeIndexData(indexData); | ||
if(this.hasIndex(indexName)){ | ||
// check if it complies | ||
var actualIndex = this.store.index(indexName); | ||
var complies = ['keyPath', 'unique', 'multiEntry'].every(function(key){ | ||
// IE10 returns undefined for no multiEntry | ||
if (key == 'multiEntry' && actualIndex[key] === undefined && indexData[key] === false) { | ||
return true; | ||
} | ||
return indexData[key] == actualIndex[key]; | ||
}); | ||
var complies = this.indexComplies(actualIndex, indexData); | ||
if(!complies){ | ||
@@ -275,2 +267,55 @@ // index differs, need to delete and re-create | ||
batch: function (arr, onSuccess, onError) { | ||
onError || (onError = function (error) { | ||
console.error('Could not apply batch.', error); | ||
}); | ||
onSuccess || (onSuccess = noop); | ||
var batchTransaction = this.db.transaction([this.storeName] , this.consts.READ_WRITE); | ||
var count = arr.length; | ||
var called = false; | ||
arr.forEach(function (operation) { | ||
var type = operation.type; | ||
var key = operation.key; | ||
var value = operation.value; | ||
if (type == "remove") { | ||
var deleteRequest = batchTransaction.objectStore(this.storeName).delete(key); | ||
deleteRequest.onsuccess = function (event) { | ||
count--; | ||
if (count == 0 && !called) { | ||
called = true; | ||
onSuccess(); | ||
} | ||
}; | ||
deleteRequest.onerror = function (err) { | ||
batchTransaction.abort(); | ||
if (!called) { | ||
called = true; | ||
onError(err, type, key); | ||
} | ||
}; | ||
} else if (type == "put") { | ||
if (typeof value[this.keyPath] == 'undefined' && !this.features.hasAutoIncrement) { | ||
value[this.keyPath] = this._getUID() | ||
} | ||
var putRequest = batchTransaction.objectStore(this.storeName).put(value); | ||
putRequest.onsuccess = function (event) { | ||
count--; | ||
if (count == 0 && !called) { | ||
called = true; | ||
onSuccess(); | ||
} | ||
}; | ||
putRequest.onerror = function (err) { | ||
batchTransaction.abort(); | ||
if (!called) { | ||
called = true; | ||
onError(err, type, value); | ||
} | ||
}; | ||
} | ||
}, this); | ||
}, | ||
getAll: function (onSuccess, onError) { | ||
@@ -328,3 +373,3 @@ onError || (onError = function (error) { | ||
// worse approach now, using current time as id. Sigh. | ||
return +new Date(); | ||
return this._insertIdCount++ + Date.now(); | ||
}, | ||
@@ -345,2 +390,19 @@ | ||
normalizeIndexData: function (indexData) { | ||
indexData.keyPath = indexData.keyPath || indexData.name; | ||
indexData.unique = !!indexData.unique; | ||
indexData.multiEntry = !!indexData.multiEntry; | ||
}, | ||
indexComplies: function (actual, expected) { | ||
var complies = ['keyPath', 'unique', 'multiEntry'].every(function (key) { | ||
// IE10 returns undefined for no multiEntry | ||
if (key == 'multiEntry' && actual[key] === undefined && expected[key] === false) { | ||
return true; | ||
} | ||
return expected[key] == actual[key]; | ||
}); | ||
return complies; | ||
}, | ||
/********** | ||
@@ -347,0 +409,0 @@ * cursor * |
{ | ||
"name": "idb-wrapper", | ||
"version": "0.2.1", | ||
"version": "0.3.0", | ||
"description": "A cross-browser wrapper for IndexedDB", | ||
@@ -5,0 +5,0 @@ "keywords": [], |
@@ -6,3 +6,3 @@ About | ||
a) ease the use of indexedDB and abstract away the differences between the | ||
a) ease the use of indexedDB and abstract away the differences between the | ||
existing impls in Chrome, Firefox and IE10 (yes, it works in all three), and | ||
@@ -13,6 +13,6 @@ | ||
"Showing how it works" is the main intention of this project. IndexedDB is | ||
all the buzz, but only a few people actually know how to use it. | ||
"Showing how it works" is the main intention of this project. IndexedDB is | ||
all the buzz, but only a few people actually know how to use it. | ||
The code in IDBWrapper.js is not optimized for anything, nor minified or anything. | ||
The code in IDBWrapper.js is not optimized for anything, nor minified or anything. | ||
It is meant to be read and easy to understand. So, please, go ahead and check out | ||
@@ -89,4 +89,4 @@ the source! | ||
'keyPath' is the name of the property to be used as key index. If 'autoIncrement' is set to true, | ||
the database will automatically add a unique key to the keyPath index when storing objects missing | ||
'keyPath' is the name of the property to be used as key index. If 'autoIncrement' is set to true, | ||
the database will automatically add a unique key to the keyPath index when storing objects missing | ||
that property. 'indexes' contains objects defining indexes (see below for details on indexes). | ||
@@ -121,3 +121,3 @@ | ||
`dataObj` is the Object to store. `onSuccess` will be called when the insertion/update was successful, | ||
`dataObj` is the Object to store. `onSuccess` will be called when the insertion/update was successful, | ||
and it will receive the keyPath value (the id, so to say) of the inserted object as first and only | ||
@@ -150,3 +150,3 @@ argument. `onError` will be called if the insertion/update failed and it will receive the error event | ||
`onSuccess` will be called if the getAll operation was successful, and it will receive an Array of | ||
all objects currently stored in the store as first and only argument. `onError` will be called if | ||
all objects currently stored in the store as first and only argument. `onError` will be called if | ||
the getAll operation failed and it will receive the error event object as first and only argument. | ||
@@ -181,6 +181,45 @@ | ||
`onSuccess` will be called if the clear operation was successful. `onError` will be called if the clear | ||
`onSuccess` will be called if the clear operation was successful. `onError` will be called if the clear | ||
operation failed and it will receive the error event object as first and only argument. | ||
6) The batch method. | ||
```javascript | ||
batch: function (/*Array*/operations, /*Function?*/onSuccess, /*Function?*/onError) | ||
``` | ||
`batch` expects an array of operations that you want to apply in a single | ||
IndexedDB transaction. `operations` is an Array of objects, each containing two | ||
properties, defining the type of operation. There are two operations | ||
supported, put and remove. A put entry looks like this: | ||
```javascript | ||
{ type: "put", value: dataObj } // dataObj being the object to store | ||
``` | ||
A remove entry looks like this; | ||
```javascript | ||
{ type: "remove", key: someKey } // someKey being the keyPath value of the item to remove | ||
``` | ||
You can mix both types in the `operations` Array: | ||
```javascript | ||
db.batch([ | ||
{ type: "put", value: dataObj }, | ||
{ type: "remove", key: someKey } | ||
], onSuccess, onError) | ||
``` | ||
`onSuccess` will be called if all operations were successful and will receive no | ||
arguments. `onError` will be called if an error happens for one of the | ||
operations and will receive three arguments: the Error instance, the type of | ||
operation that caused the error and either the key or the value property | ||
(depending on the type). | ||
If an error occurs, no changes will be made to the store, even if some | ||
of the given operations would have succeeded. | ||
Index Operations | ||
@@ -187,0 +226,0 @@ ---------------- |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
163868
28
2927
359
2