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

@vlsergey/react-indexdb-repo

v5.0.0

Published

React Components to work with IndexDB repositories

Downloads

8

Readme

@vlsergey/react-indexdb-repo

React Components to work with IndexDB repositories.

NPM version Build Status Downloads

Usage example

Data access and update

async function dbConnection( ) {
  return new Promise( ( resolve, reject ) => {
    const dbOpenRequest = window.indexedDB.open( 'TestDatabase', 1 );

    dbOpenRequest.onblocked = () => reject( 'onblocked' );
    dbOpenRequest.onerror = err => reject( err );
    dbOpenRequest.onsuccess = () => resolve( dbOpenRequest.result );
    dbOpenRequest.onupgradeneeded = event => {
      try {
        const db = event.target.result;
        try { db.deleteObjectStore( 'TestObjectStore' ); } catch ( err ) { /* NOOP */ }
        db.createObjectStore( 'TestObjectStore', { keyPath: 'id' } );
      } catch ( err ) {
        reject( err );
      }
    };
  } );
}

const db = await testDbConnection( );
const repo = new InlineKeyIndexedDbRepositoryImpl( db, 'TestObjectStore' );
await repo.saveAll( [
  { id: 1, name: 'First' },
  { id: 2, name: 'Second' },
  { id: 3, name: 'Third' },
] );
console.log( ( await repo.findById( 1 ) ).name );

Main classes

There are two main interfaces and their implementations:

  • InlineKeyIndexedDbRepositoryImpl (implemens InlineKeyIndexedDbRepository) wraps IDBObjectStore and assumes that object store uses in-line keys (i.e. keys that are part of object, some field of it)
  • OutOfLineKeyIndexedDbRepositoryImpl (implemens OutOfLineKeyIndexedDbRepository) wraps IDBObjectStore and assumes that object store uses oput-of-line keys (i.e. keys are not part of the object)

The only difference between classes / interface is in save() method. Inline key repository does not require additional argument to save object:

  • save: (item: Value) => Promise<Key>
  • saveAll: (items: Value[]) => Promise< Key[] >

Out-of-line key repository requires additional key argument:

  • save: (key: Key, item: Value) => Promise<Key>

Both of them implements the following common methods. Those methods are defined in common IndexedDbRepository interface and BaseIndexedDbRepository abstract class.

  • findAll() -- returns all elements from IDBObjectStore
  • findById( id ) -- returns element by key from IDBObjectStore.
  • findByIds( ids ) -- returns an array of elements by keys from IDBObjectStore.
  • findByPredicate( predicate ) -- returns an array of elements filtered by predicate. Semantically the same as, but with memory usage optimization compared to findAll( ).filter( predicate ).
  • getKeyToIndexValueMap( indexName ) -- returns a map where key is primary key and value is index value. Used by sorting functions (where one need to sort items by label of linked dictionary entry).
  • retain( ids ) -- deletes all elements from IDBObjectStore except with keys specified in argument (can be array, set or predicate function).

All findId() and findIds() calls are placed into single queue and optimized by using cursor over sorted ids.

Properties and settings

  • stamp -- indicates the sequence number of changes in IDBObjectStore. Can be used for memoization cache cleanup (I.e. pass it to memoize function as argument of memoization to reread data from IDBObjectStore on changes).
  • transformAfterIndexDb -- method will be called after retrivieing element from IDBObjectStore and before returning it to user code. It's a good place for custom deserialization (Date handling, for example).
  • transformBeforeIndexDb -- method will be called before placing element in IDBObjectStore. It`s a good place for custom object => string serialization.

connect()

connect -- connects data from IndexedDbRepository with component props. Automatically updates component props whenever IndexedDbRepository is updated.

Usage:

import React, { PureComponent } from 'react';
import { connect } from '@vlsergey/react-indexdb-repo';

type PropsType = {
  element: any,
}

class ElementName extends PureComponent<PropsType> {
  render() {
    const { element } = this.props;
    return !!element
      ? <div>Loading...</div>
      : <div>{element.name}</div>;
  }
}

const mapPropsToRepo = ( props ) => /* some way to obtain IndexedDbRepository */
const extractMemoArgs = ( { elementId } ) => ( { elementId } )
const mapRepoToPropsPromise = ( repo, { elementId } ) => ( {
  element: repo.findById( elementId ),
} )
const mapRepoToActions = ( repo, props ) => ( {
  doSave: ( id, value ) => repo.save( { id, value } ),
} );

export default connect( mapPropsToRepo, extractMemoArgs, mapRepoToProps, mapRepoToActions )( ElementName );
  • mapPropsToRepo -- need to obtain IndexedDbRepository from component props.
  • extractMemoArgs -- limit used props to simplify promise memoization. Promises will be recreated only if selected props changed (using shallow compare) OR data in repository changed.
  • mapRepoToPropsPromise -- build data calculation Promise's from given IndexedDbRepository and component props. Promises calculation results will be passes to wrapped component props.
  • mapRepoToActions -- build actions using IndexedDbRepository and component props. Will be passes to wrapped component props directly.

connect() can be used as annotation if you support them in your code.

import React, { PureComponent } from 'react';
import { connect } from '@vlsergey/react-indexdb-repo';

type PropsType = {
  element: any,
}

const mapPropsToRepo = ( props ) => /* some way to obtain IndexedDbRepository */
const extractMemoArgs = ( { elementId } ) => ( { elementId } )
const mapRepoToPropsPromise = ( repo, { elementId } ) => ( {
  element: repo.findById( elementId ),
} )
const mapRepoToActions = ( repo, props ) => ( {
  doSave: ( id, value ) => repo.save( { id, value } ),
} );

export default
@connect( mapPropsToRepo, extractMemoArgs, mapRepoToPropsPromise, mapRepoToActions )
class ElementName extends PureComponent<PropsType> {
  render() {
    const { element } = this.props;
    return !!element
      ? <div>Loading...</div>
      : <div>{element.name}</div>;
  }
}

Misc Classes

RepositoryListener.

RepositoryListener calls onChange() whenever repository is changed.

Usage:

  <RepositoryListener repository={repository} onChange={ () => this.forceUpdate() }>
    <!-- components that need to be rerendered when data in repository are changed -->
  </RepositoryListener>

Shall not be used directly. Used by connect() function implementation to update wrapped component props.