Treo is a lightweight wrapper around IndexedDB to make browser storage more enjoyable to use. Think about it as jQuery for IndexedDB. It does not add new abstractions, but simplifies the API and increases code reliability.
I think that us web developers have to stop fighting with the complex IndexedDB API, stumbling on simple tasks, and waiting for LevelDB in the browser. Current specification is stable, available in modern browsers. And the upcoming 2.0 spec will not have breaking changes. IndexedDB is powerful technology with support of indexes, stores, transactions and cursors. It allows you to build any kind of client databases. And let's be clear, it's the only real option to store data in browser, because localStorage is synchronous and WebSQL is deprecated. I spent a lot of time reading the official specification and understanding its nuances. With treo I want to save this time for other developers, and help you focus on real problems, building awesome libraries, and making the web better.
- Simple API around powerful IndexedDB features, like batch or indexes.
- Command buffering, you can start read/write right away.
- Small codebase without dependencies, ~400 LOC, 2.5Kb gziped.
- Powerful DSL to manage database schema and versions.
- Better error handling through error first node-style callbacks.
- Exposed access to low-level IndexedDB methods for cover edge cases.
- Easy to extend and create plugins.
Let's rewrite the official w3c example with treo:
var treo = require('treo'); // or window.treo
// define db schema
var schema = treo.schema()
.version(1)
.addStore('books', { key: 'isbn' })
.addIndex('byTitle', 'title', { unique: true })
.addIndex('byAuthor', 'author')
.version(2)
.getStore('books')
.addIndex('byYear', 'year')
.version(3)
.addStore('magazines')
.addIndex('byPublisher', 'publisher')
.addIndex('byFrequency', 'frequency');
// open db
var db = treo('library', schema);
db.version; // 3
// put some data in one transaction
var books = db.store('books');
books.batch([
{ isbn: 123456, title: 'Quarry Memories', author: 'Fred', year: 2012 },
{ isbn: 234567, title: 'Water Buffaloes', author: 'Fred', year: 2012 },
{ isbn: 345678, title: 'Bedrock Nights', author: 'Barney', year: 2013 },
], function(err) {
// Before this point, all actions were synchronous, and you don't need to wait
// for db.open, initialize onupgradeneeded event, create readwrite transaction,
// and handle all possible errors, blocks, aborts.
// If any error happen on one of this steps, you get it as `err`.
});
// get a single book by title using an index
books.index('byTitle').get('Bedrock Nights', function(err, book) {});
// get all books filtered by author
books.index('byAuthor').get('Fred', function(err, all) {}); // all.length == 2
For more examples check out /examples folder.
$ bower install treo
$ component install alekseykulikov/treo
$ npm install treo --save
Standalone build available as treo.js.
<script src="treo.js"></script>
<script src="indexedb-shim.js"></script> <!-- for legacy browsers -->
<script>window.treo('my-db', schema);</script>
To initialize a new db
instance, create a schema
and pass it to main function.
All methods, except multiple indexes and advanced ranges, are backward
compatible with outdated browsers through IndexedDBShim.
// define schema with one storage
var schema = treo.schema()
.version(1)
.addStore('storage');
// create db
var db = treo('key-value-storage', schema);
db.store('storage').put('foo', 'value 1', fn); // connect, create db, put value
Treo uses treo.schema()
to setup internal objects like stores and indexes for right away access.
Also, based on schema, treo generates onupgradeneeded
callback.
Change current version.
Declare store with name
.
Available options:
key
- setup keyPath for easy work with objects [default false].
Declare index with name
to one specific field
.
It can be called after store declaration or use schema.getStore(name)
to change current store.
Available options:
unique
- index is unique [default false]multi
- declare multi index for array type field [dafault false]
Change current store.
It's an interface to manage db connections, create transactions and get access to stores, where real work happen.
Get store by name
.
See Store API for more information.
Close db connection. Callback is optional when db.status == 'open'
.
Close connection and drop database.
- version - db version
- name - db name
- status - connection status: close, opening, open
Store is the primary storage mechanism for storing data. Think about it as table in SQL database.
Get value by key
.
Put val
to key
. Put means create or replace.
If it's an object store with key property, you pass the whole object.
var schema = treo.schema()
.version(1)
.addStore('books', { key: 'isbn' });
var db = treo('key-value-storage', schema);
db.get('books').put({ isbn: 123456, title: 'Quarry Memories', author: 'Fred' }, fn);
// key is isbn field and equal 123456
Delete value by key
.
Create/update/remove objects in one transaction.
opts
can be an object or an array (when key option is specified).
var db = treo('key-value-storage', schema);
var storage = db.store('storage');
storage.put('key1', 'value 1', fn);
storage.put('key2', 'value 2', fn);
storage.batch({
key1: 'update value',
key2: null, // delete value
key3: 'new value',
}, fn);
Count records in store.
Get all records.
Clear store.
Get index by name
.
Index is a way to filter your data.
Get values by key
. When index is unique it returns only one value.
key
can be string, range, or IDBKeyRange object.
books.index('byTitle').get('Bedrock Nights', fn); // get unique value
books.index('byAuthor').get('Fred', fn); // get array of matching values
books.index('byYear').get({ gte: 2012 });
books.index('byAuthor', IDBKeyRange.only('Barney'));
Count records by key
, similar to get, but returns number.
treo.range(object)
transforms javascript object to IDBKeyRange.
Values inspired by MongoDB query operators:
gt
- greater thangte
- greater or equallt
- less thanlte
- less or equal
Using then/promise:
var Promise = require('promise');
var books = db.store('books');
books.get = Promise.denodeify(books.get); // patch get method
Promise.all([
books.get('123456'),
books.get('234567'),
books.get('345678'),
]).then(function(records) {
// records.length == 3
});
Treo is designed to be a foundation for your browser storage. It gives you full power of IndexedDB through set of internal low level methods.
Create new transaction to list of stores.
Available types: readonly
and readwrite
.
Create custom cursors, see example and article for more detailed usage.
Exposed core objects.
Compare 2 values using indexeddb's internal key compassion algorithm.
Aleksey Kulikov, MIT.