npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@cepharum/indexed-db

v0.2.0

Published

browser-side wrapper for conveniently working with IndexedDBs

Downloads

8

Readme

indexed-db

a wrapper for using browsers' IndexedDB feature more conveniently

License

MIT

Usage

This package basically consists of two classes Database and Store suitable for establishing and object document management in browser.

Database

This class is representing a single IndexedDb database. Such a database can contain one or more object stores.

:::warning
Don't use constructor to gain access on a database. Work with Database.open() instead.
:::

Database.open( name, [ upgradeFn ] )

This method opens a database selected by its name and promises the manager for accessing it. In second argument a callback may be given for upgrading the existing database on establishing connection. This callback is invoked with related IDBVersionChangeEvent in first argument, the upgrading database instance in second and the covering transaction in mode "versionchange" in third argument.

First argument ist basically suitable for inspecting the change of version. The second one can be used to create new object store. The last one is required to gain access on existing object stores e.g. for upgrading the set of declared indices.

import { Database } from "@cepharum/indexed-db";

Database.open( "default", ( event, db, transaction ) => {
    let storeRef;

    if ( Database.hasObjectStore( "users", db ) ) {
        storeRef = transaction.objectStore( "users" );
    } else {
        storeRef = db.createObjectStore( "user", { keyPath: "id" } );
    }
   
    storeRef.createIndex( "name", "name", { unique: true } );
} );

Database#close()

Promises to disconnect from current database.

Usually you don't need to care for that as you can re-open same database multiple times relying on an internally managed runtime cache to re-use existing database connection.

Database.getDatabaseVersion( name )

This static method enumerates existing databases retrieving version of named one or NaN if it's missing.

As of late 2019 this method works in Chrome, only.

Database.hasObjectStore( name, database )

This static method is provided mostly for use in upgrade handlers, only. Pass database instance provided in second argument there in second argument named database here.

You should stick with the non-static version described below in other use cases. It returns true if named object store is part of given database and false otherwise.

Database#hasObjectStore( name )

This method is testing if current database includes named object store. It returns true if named object store is part of current database and false otherwise.

if ( db.hasObjectStore( "users" ) ) {
    // TODO: enable user-related features
}

You can't use approach for conditionally creating or reorganizing object stores.

Database#drop()

Promises to delete current database from browser. This will remove all contained object stores irreversibly.

db.drop()
    .then( () => {
        // TODO: e.g. re-create database
    } );

Database.api

This read-only property is exposing the browser's IndexedDb API.

Store

Object stores in IndexedDB databases are the equivalent of tables in SQL databases or collections in Non-SQL databases. This class is meant to wrap one object store each. It is exposing methods users of SQL and Non-SQL databases might be more familiar with.

:::warning
Don't use constructor to gain access on a store. Work with Store.open() instead.
:::

Store.open( dbName, storeName, schema )

This static method opens named object store in selected database of current browser. Using an internally managed runtime cache requests for same database and/or store are detected resulting in same instances used to access the resulting store.

The method is promising instance of Store prepared for accessing selected object store.

import { Store } from "@cepharum/indexed-db";

Store.open( "users", "default", {
    id: { primary: true },
    name: { unique: true },
    level: {},
    lastLogin: {}
} )
    .then( store => {
        // TODO: use `store` as demonstrated below
    } );

By intention, there is no support for closing a store manager.

Store#drop()

This method promises to remove the current object store from its database.

store.drop()
    .then( () => {
        // TODO: e.g. re-create store
    } );

Store#clear()

This method promises to remove all records from current object store. In opposition to Store#drop() it doesn't remove the store itself.

store.clear()
    .then( () => {
        // TODO: start fresh
    } );

Store#read( id, [ fallback ] )

This method promises to read record from current store selected by its ID based on defined primary key.

store.read( "USER1234" )
    .then( record => {
        console.log( record );
    } );

When there is no matching record in object store optionally provided fallback value is provided instead. When omitting second argument this fallback value is null.

Store#write( id, record )

This method promises to adjust value of named record in current object store.

store.write( "USER1234", { name: "j.doe" } )
    .then( store => {
        // TODO: keep on processing ...
    } );

Store#remove( name )

This method promises to remove named record from current object store.

store.remove( "USER1234" )
    .then( store => {
        // TODO: keep on processing ...
    } );

Store#count( [ range , [ name ] ] )

When invoked without any argument, this method promises total number of records in current store.

store.count()
    .then( total => {
        console.log( "store %s has %d record(s)", store.name, total );
    } );

When providing a range the total number of records with primary key matching that range is returned. By naming a particular property found in schema the range is applied onto that property resulting in number of records matching range with named property.

Store#list( [ options ] )

This method fetches all records in store. It returns a promise for some object containing the list of matching items in property named items. Every such item is another object containing the matching record as well as its key.

store.list()
    .then( ( { items } ) => {
        for ( let i = 0; i < items.length; i++ ) {
            const { key, record } = items[i];

            // TODO: process record ...
        }
    } );

In first argument you may provide an object providing options for customizing retrieval of records from store. These options are available:

| option | default | description | |--------|---------|-------------| | offset | 0 | Requests to skip this number of records before collecting for retrieval. | | limit | Infinity | Requests to stop collecting records for retrieval after this number of collected records. | | count | false | Set this true to get the total number of (matching) records in property total of promised result right next to items. | | indexName | null | Names property to use for searching and/or sorting records.The property must be given in schema provided in call to Store.open(). | | range | null | This instance of IDBKeyRange is used to optionally filter records. Any given range is applied to the primary key unless selecting some different property with index in option indexName. | ascending | null | This boolean controls whether records should be listed in ascending order with regards to value of primary key or selected property. | | distinct | null | This boolean controls whether result is containing every matching record or just one record per matching value of selected property. |

Store#findMatching( name, value, [ options ] )

This method is basically wrapping around Store#list() simplifying its signature for searching records with properties matching given value.

store.findMatching( "level", "guest" )
    .then( ( { items } ) => {
        // TODO: process records of store with level "guest"
    } );

FWIW, this is basically equivalent to the following:

store.list( { 
    indexName: "level", 
    range: IDBKeyRange.only( "guest" ),
} )
    .then( ( { items } ) => {
        // TODO: process records of store with level "guest"
    } );

The third arguments supports options offset, limit and count as described in context of Store#list() before.

Store#findInRange( name, lower, [ upper ], [ options ] )

Just like Store#findMatching(), this method is wrapping around Store#list() for simplifying code. It is promising all records with values of named property matching range defined by arguments lower and upper.

When providing null for either boundary the range isn't limited accordingly.

store.findInRange( "lastLogin", new Date( "2019-01-01 12:00:00Z" ) )
    .then( ( { items } ) => {
        // TODO: process records users that have logged in since 2019
    } );

FWIW, this is basically equivalent to the following:

store.list( { 
    indexName: "level", 
    range: IDBKeyRange.only( "guest" ),
} )
    .then( ( { items } ) => {
        // TODO: process records of store with level "guest"
    } );

The third arguments supports options offset, limit, count, ascending and distinct as described in context of Store#list() before.