SkillAgentSearch skills...

Db.js

db.js is a wrapper for IndexedDB to make it easier to work against

Install / Use

/learn @aaronpowell/Db.js
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Build Status Selenium Test Status npm version bower version License

Selenium Test Status

db.js

db.js is a wrapper for IndexedDB to make it easier to work against, making it look more like a queryable API.

Usage

Add a reference to db.js in your application before you want to use IndexedDB:

<script src='/dist/db.js'></script>

Alternatively, db.js includes an optional define call, and can be loaded as a module using the AMD loader of your choice.

Opening/Creating a database and connection

Once you have the script included you can then open connections to each different database within your application:

var server;
db.open({
    server: 'my-app',
    version: 1,
    schema: {
        people: {
            key: {keyPath: 'id', autoIncrement: true},
            // Optionally add indexes
            indexes: {
                firstName: {},
                answer: {unique: true}
            }
        }
    }
}).then(function (s) {
    server = s;
});

Note that open() takes an options object with the following properties:

  • version - The current version of the database to open. Should be an integer. You can start with 1. You must increase the version if updating the schema or otherwise the schema property will have no effect.

  • server - The name of this server. Any subsequent attempt to open a server with this name (and with the current version) will reuse the already opened connection (unless it has been closed).

  • schema - Expects an object, or, if a function is supplied, a schema object should be returned). A schema object optionally has store names as keys (these stores will be auto-created if not yet added and modified otherwise). The values of these schema objects should be objects, optionally with the property "key" and/or "indexes". The "key" property, if present, should contain valid createObjectStore parameters (keyPath or autoIncrement). The "indexes" property should contain an object whose keys are the desired index keys and whose values are objects which can include the optional parameters and values available to createIndex (unique, multiEntry, and, for Firefox-only, locale). Note that the keyPath of the index will be set to the supplied index key, or if present, a keyPath property on the provided parameter object. Note also that when a schema is supplied for a new version, any object stores not present on the schema object will be deleted.

A connection is intended to be persisted, and you can perform multiple operations while it's kept open.

In the event a connection has already been opened for modification (whether in the same instance or in another tab/window), a blocking error will occur, for which you can listen by adding a Promise.catch statement and communicate with blocking instances still holding a connection so that they may close the connection. You can then return the resume property (a promise) to recover to continue the original open operation and proceed to the following then condition.

var server;
db.open({
    // ...
}).catch(function (err) {
    if (err.type === 'blocked') {
        oldConnection.close();
        return err.resume;
    }
    // Handle other errors here
    throw err;
}).then(function (s) {
    server = s;
    // One can add a versionchange handler here to self-close
    //   the connection upon future upgrade attempts (likely to
    //   be one made in other tabs) and thereby
    //   avoid such attempts having to face blocking errors.
});

Check out the /tests/specs folder for more examples.

General server/store methods

Note that by default the methods below (not including close, addEventListener, and removeEventListener) can be called either as server.people.xxx( arg1, arg2, ... ) or server.xxx( 'people', arg1, arg2, ... ).

To reduce some memory requirements or avoid a however unlikely potential conflict with server method names, however, one may supply noServerMethods: true as part of options supplied to db.open() and under such conditions, only the second method signature above can be used.

Store modification

Adding items

server.people.add({
    firstName: 'Aaron',
    lastName: 'Powell',
    answer: 42
}).then(function (item) {
    // item stored
});

Multiple items can be added as additional arguments to add. Another way multiple items can be added is when an array is supplied for any of the arguments in which case, its top level contents will be treated as separate items. If you want unambiguous results where the data to be added could itself be an array, be sure to wrap item supplied in your argument within an array.

Note also when add is provided with objects containing a property item (and optionally a key property), the value of item will be treated as the record to be added, while any key will be used as the key. To supply unambiguous items (where you are not sure whether item may exist on the record to be added), you may wish to consistently wrap your items within an object with an item property even if you are not supplying a key.

Updating

server.people.update({
    firstName: 'Aaron',
    lastName: 'Powell',
    answer: 42
}).then(function (item) {
    // item added or updated
});

As with add, update shares the same behaviors as far as flattening of the top level of array arguments and checking of item/key properties, so if you need unambiguous results, please see the discussion above.

Using update will cause a record to be added if it does not yet exist.

put is also available as an alias of update.

Removing

server.people.remove(1).then(function (key) {
    // item removed
});

delete is also available as an alias of remove.

Clearing

This allows removing all items in a table/collection:

server.people.clear()
    .then(function() {
        // all table data is gone.
    });

Fetching

Getting a single object by key

server.people.get(5)
    .then(function (results) {
        // do something with the results
    });

Getting a single object by key range

If more than one match, it will retrieve the first.

With a MongoDB-style range:

server.people.get({gte: 1, lt: 3})
    .then(function (results) {
        // do something with the results
    });

With an IDBKeyRange:

server.people.get(IDBKeyRange.bound(1, 3, false, true))
    .then(function (results) {
        // do something with the results
    });

Querying

Queries require one or more methods to determine the type of querying (all items, filtering, applying ranges, limits, distinct values, or custom mapping--some of which can be combined with some of the others), any methods for cursor direction, and then a subsequent call to execute() (followed by a then or catch).

Querying all objects
server.people.query()
    .all()
    .execute()
    .then(function (results) {
        // do something with the results
    });
Querying using indexes
server.people.query('specialProperty')
    .all()
    .execute()
    .then(function (results) {
        // do something with the results (items which possess `specialProperty`)
    });
Querying with filtering

Note that unlike the other methods after a query, filter can be executed multiple times.

Filter with property and value
server.people.query()
    .filter('firstName', 'Aaron')
    .execute()
    .then(function (results) {
        // do something with the results
    });
Filter with function
server.people.query()
    .filter(function(person) {return person.group === 'hipster';})
    .execute()
    .then(function (results) {
        // do something with the results
    });
Querying for distinct values

Will return only one record:

server.people
    .query('firstName')
    .only('Aaron')
    .distinct()
    .execute()
    .then(function (data) {
        //
    });
Querying with ranges

All ranges supported by IDBKeyRange can be used (only, bound, lowerBound, upperBound).

server.people.query('firstName')
    .only('Aaron')
    .then(function (results) {
        // do something with the results
    });

server.people.query('answer')
    .bound(30, 50)
    .then(function (results) {
        // do something with the results
    });

MongoDB-style ranges (as implemented in idb-range-driven libraries) are also supported:

server.people.query('firstName')
    .range({eq: 'Aaron'})
    .then(function (results) {
        // do something with the results
    });

server.people.query('answer')
    .range({gte: 30, lte: 50})
    .then(function (results) {
        // do something with the results
    });

Note that IndexedDB allows you to use array keys within ranges (and other methods where a key is accepted) as long as you have created your store with an array keyPath (and optionally with an index keyPath).


// The definition:
schema: {
    people:

Related Skills

View on GitHub
GitHub Stars824
CategoryDevelopment
Updated1mo ago
Forks140

Languages

JavaScript

Security Score

95/100

Audited on Jan 30, 2026

No findings