Dexie.js is a wrapper library for indexedDB - the standard database in the browser. http://dexie.org
Dexie solves three main issues with the native IndexedDB API:
Dexie provides a neat database API with a well thought-through API design, robust error handling, extendability, change tracking awareness and extended KeyRange support (case insensitive search, set matches and OR operations).
<!doctype html>
<html>
<head>
<script src="https://unpkg.com/dexie@latest/dist/dexie.js"></script>
<script>
//
// Declare Database
//
var db = new Dexie("FriendDatabase");
db.version(1).stores({
friends: "++id,name,age"
});
//
// Manipulate and Query Database
//
db.friends.add({name: "Josephine", age: 21}).then(function() {
return db.friends.where("age").below(25).toArray();
}).then(function (youngFriends) {
alert ("My young friends: " + JSON.stringify(youngFriends));
}).catch(function (e) {
alert ("Error: " + (e.stack || e));
});
</script>
</head>
</html>
Yes, it’s that simple.
Dexie has kick-ass performance. Its bulk methods take advantage of a lesser-known feature in IndexedDB that makes it possible to store stuff without listening to every onsuccess event. This speeds up the performance to a maximum.
above(key): Collection;
aboveOrEqual(key): Collection;
add(item, key?): Promise;
and(filter: (x) => boolean): Collection;
anyOf(keys[]): Collection;
anyOfIgnoreCase(keys: string[]): Collection;
below(key): Collection;
belowOrEqual(key): Collection;
between(lower, upper, includeLower?, includeUpper?): Collection;
bulkAdd(items: Array): Promise;
bulkDelete(keys: Array): Promise;
bulkPut(items: Array): Promise;
clear(): Promise;
count(): Promise;
delete(key): Promise;
distinct(): Collection;
each(callback: (obj) => any): Promise;
eachKey(callback: (key) => any): Promise;
eachPrimaryKey(callback: (key) => any): Promise;
eachUniqueKey(callback: (key) => any): Promise;
equals(key): Collection;
equalsIgnoreCase(key): Collection;
filter(fn: (obj) => boolean): Collection;
first(): Promise;
get(key): Promise;
inAnyRange(ranges): Collection;
keys(): Promise;
last(): Promise;
limit(n: number): Collection;
modify(changeCallback: (obj: T, ctx:{value: T}) => void): Promise;
modify(changes: { [keyPath: string]: any } ): Promise;
noneOf(keys: Array): Collection;
notEqual(key): Collection;
offset(n: number): Collection;
or(indexOrPrimayKey: string): WhereClause;
orderBy(index: string): Collection;
primaryKeys(): Promise;
put(item: T, key?: Key): Promise;
reverse(): Collection;
sortBy(keyPath: string): Promise;
startsWith(key: string): Collection;
startsWithAnyOf(prefixes: string[]): Collection;
startsWithAnyOfIgnoreCase(prefixes: string[]): Collection;
startsWithIgnoreCase(key: string): Collection;
toArray(): Promise;
toCollection(): Collection;
uniqueKeys(): Promise;
until(filter: (value) => boolean, includeStopEntry?: boolean): Collection;
update(key: Key, changes: { [keyPath: string]: any }): Promise;
This is a mix of methods from WhereClause, Table and Collection. Dive into the API reference to see the details.
import Dexie from 'dexie';
//
// Declare Database
//
const db = new Dexie("FriendDatabase");
db.version(1).stores({ friends: "++id,name,age" });
db.transaction('rw', db.friends, async() => {
// Make sure we have something in DB:
if ((await db.friends.where({name: 'Josephine'}).count()) === 0) {
const id = await db.friends.add({name: "Josephine", age: 21});
alert (`Addded friend with id ${id}`);
}
// Query:
const youngFriends = await db.friends.where("age").below(25).toArray();
// Show result:
alert ("My young friends: " + JSON.stringify(youngFriends));
}).catch(e => {
alert(e.stack || e);
});
import Dexie from 'dexie';
interface Friend {
id?: number;
name?: string;
age?: number;
}
//
// Declare Database
//
class FriendDatabase extends Dexie {
public friends: Dexie.Table<Friend, number>; // id is number in this case
public constructor() {
super("FriendDatabase");
this.version(1).stores({
friends: "++id,name,age"
});
this.friends = this.table("friends");
}
}
const db = new FriendDatabase();
db.transaction('rw', db.friends, async() => {
// Make sure we have something in DB:
if ((await db.friends.where({name: 'Josephine'}).count()) === 0) {
const id = await db.friends.add({name: "Josephine", age: 21});
alert (`Addded friend with id ${id}`);
}
// Query:
const youngFriends = await db.friends.where("age").below(25).toArray();
// Show result:
alert ("My young friends: " + JSON.stringify(youngFriends));
}).catch(e => {
alert(e.stack || e);
});
http://dexie.org/docs/Samples
https://github.com/dfahlander/Dexie.js/tree/master/samples
http://dexie.org/docs/Questions-and-Answers
npm install dexie
For those who don’t like package managers, here’s the download links:
https://unpkg.com/dexie@latest/dist/dexie.js
https://unpkg.com/dexie@latest/dist/dexie.js.map
https://unpkg.com/dexie@latest/dist/dexie.d.ts
Here is a little cheat-sheet for how to symlink your app’s node_modules/dexie to a place where you can edit the source, version control your changes and create pull requests back to Dexie. Assuming you’ve already ran npm install dexie --save for the app your are developing.
~repos/, c:\repos or whatever)Run the following commands:
git clone https://github.com/YOUR-USERNAME/Dexie.js.git dexie
cd dexie
npm install
npm run build
npm link
npm link dexie
Your app’s node_modules/dexie/ is now sym-linked to the Dexie.js clone on your hard drive so any change you do there will propagate to your app. Build dexie.js using npm run build or npm run watch. The latter will react on any source file change and rebuild the dist files.
That’s it. Now you’re up and running to test and commit changes to files under dexie/src/* or dexie/test/* and the changes will instantly affect the app you are developing.
Pull requests are more than welcome. Some advices are:
test/tests-misc.js. We use qunit. Just look at existing tests in tests-misc.js to see how they should be written. Tests are transpiled in the build script so you can use ES6 if you like.npm install
npm run build
npm test
npm run watch