Live Demo! |
---|
- Adds full IndexedDB support to any web browser that supports WebSql
- Does nothing if the browser already natively supports IndexedDB
- Can optionally replace native IndexedDB on browsers with buggy implementations
- Can optionally enhance native IndexedDB on browsers that are missing certain features
- Works on desktop and mobile devices
- Works on Cordova and PhoneGap via the IndexedDB plug-in
- This shim is basically an IndexedDB-to-WebSql adapter.
- Can be used in Node (courtesy of websql which sits on top of SQLite3)
- More details about the project at gh-pages
You can download the development or production (minified) script, or install it using NPM or Bower.
npm install indexeddbshim
To set up:
const setGlobalVars = require('indexeddbshim');
// This function defines `shimIndexedDB`, `indexedDB`, `IDBFactory`, etc. on
// one of the following objects in order of precedence:
// 1. A passed in object
// 2. `window` (for Node, define `GLOBAL.window = GLOBAL;`)
// 3. A new object
GLOBAL.window = GLOBAL; // We'll allow ourselves to use `window.indexedDB` or `indexedDB` as a global
setGlobalVars();
bower install IndexedDBShim
If you clone the repository to work against an unstable version, you only need to clone the repository recursively if you wish to have the W3C tests available for testing (which unfortunately loads all W3C tests into the "web-platform-tests" subdirectory rather than just the IndexedDB ones).
Add the script to your page
<script src="dist/indexeddbshim.min.js"></script>
If the browser already natively supports IndexedDB, then the script won't do anything. Otherwise, it'll add the IndexedDB API to the browser. Either way, you can use IndexedDB just like normal. Here's an example
Even if a browser natively supports IndexedDB, you may still want to use this shim. Some native IndexedDB implemenatations are very buggy. Others are missing certain features. There are also many minor inconsistencies between different browser implementations of IndexedDB, such as how errors are handled, how transaction timing works, how records are sorted, how cursors behave, etc. Using this shim will ensure consistent behavior across all browsers.
To force IndexedDBShim to shim the browser's native IndexedDB, add this line to your script:
window.shimIndexedDB.__useShim()
On browsers that support WebSQL, this line will completely replace the native IndexedDB implementation with the IndexedDBShim-to-WebSQL implementation.
On browsers that don't support WebSQL, but do support IndexedDB, this line will patch many known problems and add missing features. For example, on Internet Explorer, this will add support for compound keys.
The IndexedDB polyfill has sourcemaps enabled, so the polyfill can be debugged even if the minified file is included.
To print out detailed debug messages, add this line to your script:
window.shimIndexedDB.__debug(true);
Rather than using globals, a method has been provided to share state across IndexedDBShim modules.
Its signature for setting configuration:
shimIndexedDB.__setConfig(property, value);
...and for retrieving:
shimIndexedDB.__getConfig(property);
The available properties are:
- DEBUG - Boolean (equivalent to calling
shimIndexedDB.__debug(val)
) - cursorPreloadPackSize - Number indicating how many records to preload for
caching of (non-multiEntry)
IDBCursor.continue
calls. Defaults to 100. - win, Object on which there may be an
openDatabase
method (if any) for WebSQL; Defaults towindow
orself
in the browser and for Node, it is set by default tonode-websql
. - UnicodeIDStart and UnicodeIDContinue - Invocation of
createObjectStore
andcreateIndex
calls for validation of key paths. The specification technically allows allIdentifierName
strings, but as this requires a very large regular expression, it is replaced by default with[$A-Z_a-z]
and[$0-9A-Z_a-z]
, respectively. Note that these are and must be expressed as strings, notRegExp
objects. You can use this configuration to change the default to match the spec or as you see fit. In the future we may allow the spec behavior via optional dynamic loading of an internal module. - DEFAULT_DB_SIZE - Used as estimated size argument (in bytes) to
underlying WebSQL
openDatabase
calls. Defaults to4 * 1024 * 1024
or25 * 1024 * 1024
in Safari (apparently necessary due to Safari creating larger files and possibly also due to Safari not completing the storage of all records even after permission is given). Has no effect in Node (usingnode-websql
), and its use in WebSQL-compliant browsers is implementation dependent (the browser may use this information to suggest the use of this quota to the user rather than prompting the user regularly for say incremental 5MB permissions).
All code has bugs, and this project is no exception. If you find a bug, please let us know about it. Or better yet, send us a fix! Please make sure someone else hasn't already reported the same bug though.
Here is a summary of known issues to resolve:
- Support versionchange rollbacks
close
andblocked
event support (reconcile with existingversionchange
)eval
is currently in use (insrc/Sca.js
)- Add new Binary/ArrayBuffer/Views on buffers (TypedArray or DataView) support
- Support cyclic objects (via Structured Cloning Algorithm)
- Certain more recent APIs are missing:
IDBCursor.continuePrimaryKey
,IDBIndex
(getAll
,getAllKeys
),IDBObjectStore
(getAll
,getAllKeys
,getKey
).
There are a few bugs that are outside of our power to fix. Namely:
Due to a bug in WebKit, the
window.indexedDB
property is read-only and cannot be overridden by
IndexedDBShim. There are two possible workarounds for this:
- Use
window.shimIndexedDB
instead ofwindow.indexedDB
- Create an
indexedDB
variable in your closure
By creating a variable named indexedDB
, all the code within that closure
will use the variable instead of the window.indexedDB
property. For example:
(function() {
// This works on all browsers, and only uses IndexedDBShim as a final fallback
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;
// This code will use the native IndexedDB, if it exists, or the shim otherwise
indexedDB.open("MyDatabase", 1);
})();
IndexedDBShim works on Windows Phone via a Cordova/PhoneGap plug-in. There are two plugins available: cordova-plugin-indexedDB and cordova-plugin-indexeddb-async. Both plug-ins rely on a WebSQL-to-SQLite adapter, but there are differences in their implementations. Try them both and see which one works best for your app.
To build the project locally on your computer:
-
Clone this repo
git clone https://github.com/axemclion/IndexedDBShim.git
-
Install dev dependencies
npm install
-
Run the build script
npm start
-
Done
The output files will be generated in the dist
directory
There are currently three folders for tests, tests-qunit
,
tests-mocha
and tests-polyfill
(the latter are also Mocha-based
tests, but at present only work in Node).
They can be run through a variety of means as described below.
To properly build the files (lint, browserify, and minify), use npm start
or to also keep a web server, run npm run dev
(or grunt dev
).
The tests produce various database files. These are avoided in
.gitignore
and should be cleaned up if the tests pass, but if
you wish to delete them all manually, run npm run clean
.
All QUnit-based tests should pass in modern browsers.
All Mocha-based browser tests should pass except for one test having a problem in Firefox.
Follow all of the steps above to build the project, then run npm test
or npm run sauce-qunit
(or npm run phantom-qunit
or
grunt phantom-qunit
to avoid using Saucelabs when you have
credentials set up as environmental variables) to run the unit tests.
Note that when not running Saucelabs, the tests are run in PhantomJS, which is a headless WebKit browser.
The older PhantomJS version has problems with two tests, however:
index.openCursor(range)
and
IDBObjectStore.openKeyCursor
due apparently to
a bug with the WebKit browser used in the older PhantomJS implementation
(but the tests themselves report as having such problems).
If you want to run the tests in a normal web browser, you'll need to
spin-up a local web server and then open tests-qunit/index.html?noglobals
and/or tests-mocha/index.html
in your browser. You can also run npm run dev
and point your
browser to http://localhost:9999/tests-qunit/index.html
or
http://localhost:9999/tests-mocha/index.html
.
Note that, for the Mocha tests, you probably wish to "Switch to IndexedDBShim" when doing the testing since otherwise, it will only test the native implementation.
To run the Node tests, run the following:
npm run node-qunit
- The full test suite sometimes does not complete execution.npm run mocha
npm run tests-polyfill
(or its componentsnpm run fake
,npm run mock
). Note that none of these are currently passing in full, however. You can runnpm run good
to see the ones which ought to remain passing.npm run w3c
(you must first rungit submodule update --init --recursive
if you have not already recursively cloned the repository). Note that some of these tests may not be passing because of the test environment not being completely configured for Node. We are working on fixing this. There are some older and less complete W3C tests that can be run withnpm run w3c-old
, but the goal is to remove these once the new ones are configured properly.
To run a specific Mocha test (which includes the tests-polyfill
tests), run npm --test=... run mocha
.
If you want to run the tests in a Cordova or PhoneGap app, then you'll need
to create a new Cordova/PhoneGap project, and add the
IndexedDB plug-in.
Then copy the contents of our tests
directory into your project's www
directory. Delete our
index.html
file and rename cordova.html
to index.html
.
Pull requests or Bug reports welcome!!