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

@n1md7/indexeddb-promise

v7.1.1

Published

Indexed DB wrapper with promises

Downloads

12

Readme

npm databaseVersion Node.js Package Node.js CI - tests GitHub codecov

Indexed DB wrapper with promises

Supports all browsers that support IndexedDB.

Has TypeScript support with TS-class decorators.

Demo

Installation

$ npm install @n1md7/indexeddb-promise
$ yarn add @n1md7/indexeddb-promise

Decorators

Typescript decorators are supported.

Prerequisite:

{
  "experimentalDecorators": true
}

@Table

Class decorator for IndexedDB table. It defines the structure of the table.

Params: options - object with following properties:

  • name? - string, name of the table, default is the class name
  • timestamps? - boolean, if true, createdAt and updatedAt columns will be added, default is false
  • initialData? - array of objects to be inserted into the table on database creation, default is empty
@Table({ name: 'Users', timestamps: true })
class User {}

@Indexed

Property decorator for IndexedDB index. It defines whether the property is indexed.

Params: options - object with following properties:

  • unique? - boolean, if true, the index will be unique, default is false
  • multiEntry? - boolean, if true, the index will be multi-entry, default is true
@Table()
class User {
  @Indexed({ unique: true, multiEntry: false })
  username: string;
}

@PrimaryKey

Property decorator for IndexedDB primary key. It defines whether the property is primary key.

Params: options - object with following properties:

  • autoIncrement? - boolean, if true, the primary key will be auto-incremented, default is true
  • unique? - boolean, if true, the primary key will be unique, default is true
@Table()
class User {
  @PrimaryKey()
  id: number;

  @Index()
  name: string;
}

Methods

| Method | Description | Params | | ------------------ | ------------------------------------------------- | ----------------------- | | selectAll | Get the data from database | None | | select | Fetch data from database with filters | Object | | insert | Add data into database | Object | | openCursor | Get database cursor to iterate on demand | None | | selectByIndex | Select database data by indexed properties (one) | String, String | | selectByIndexAll | Select database data by indexed properties (many) | String, String | | selectByPk | Select database record by primary key | String \ Number | | updateByPk | Update database record by primary key | Number \ Number, Object | | deleteByPk | Delete database record by primary key | String \ Number |

- selectAll

Params

Gets all the data from database.

Return type: Promise<Object[]>

Accept params: None

Javascript example

model.selectAll().then((data) => data);
const data = await model.selectAll();

Typescript example

model.selectAll().then((data) => {
  // In TS {data} is inferred from the model
  return data;
});
const data = await model.selectAll();

- select

Params

Gets filtered data from database.

Return type: Promise<Object[]>

Accept params: options: Object

Object properties:

{
  where?: Object | Function;
  limit?: Number;
  orderByDESC?: Boolean;
  sortBy?: String | String[];
}

JS/TS example

const options = {
  limit: 10,
  where: (dataArray) => {
    return dataArray;
  },
  orderByDESC: true,
  sortBy: 'comments', // ['comments', 'date']
};
model.select(options).then((data) => data);
const data = await model.select(options);

@where property can filter out data like

const props = {
  where: (data) => data.filter((item) => item.username === 'admin'),
};

or it can be an object, which gets data with AND(&&) comparison

const props = {
  where: {
    username: 'admin',
    password: 'admin123',
  },
};

- selectByIndex

Params

Gets the data from database with the specified indexed property.

Return type: Promise<Object|{}>

Accept params: indexName: string, valueToMatch: string

JS/TS example

model.selectByIndex('username', 'admin').then((data) => data);
const data = await model.selectByIndex('username', 'admin');

- selectByIndexAll

Params

Gets the data from database with the specified indexed property.

Return type: Promise<Array<Object|{}>>

Accept params: indexName: string, valueToMatch: string

JS/TS example

model.selectByIndexAll('username', 'admin').then((data) => data);
const data = await model.selectByIndexAll('username', 'admin');

- selectByPk

Params

Gets the data from database with the specified primary key.

Return type: Promise<Object|{}>

Accept params: primaryKey: string \ number

JS/TS example

model.selectByPk(1).then((data) => data);
const data = await model.selectByPk('admin');

- updateByPk

Params

Updates the data in database with the specified primary key.

Return type: Promise<Object|{}>

Accept params: primaryKey: string \ number, Object

JS/TS example

model.updateByPk(123, { username: 'admin' });
const data = await model.updateByPk(123, { username: 'admin' });

- deleteByPk

Params

Deletes the data in database with the specified primary key.

Return type: Promise<String|Number>

Accept params: primaryKey: string \ number

JS/TS example

model.deleteByPk(123);
const data = await model.deleteByPk(123);

note Primary key is type sensitive. If it is saved as integer then should pass as integer and vice versa

Examples

Html 01

Once you add indexed-db.min.js in your document then you will be able to access IndexedDB variable globally which contains Model. They can be extracted as following

<html>
  <head>
    <title>IndexedDB app</title>
    <script defer src="indexed-db.min.js"></script>
  </head>
  <body>
    <script>
      const Database = IndexedDB.Database;
      // Your script here
    </script>
  </body>
</html>

Html 02

Basic usage of Model

<html>
  <head>
    <title>IndexedDB app</title>
    <script src="indexed-db.min.js"></script>
  </head>
  <body>
    <script>
      const db = new IndexedDB.Database({
        databaseVersion: 1,
        databaseName: 'MyNewDatabase',
        tables: [
          {
            name: 'MyNewTable',
            primaryKey: {
              name: 'id',
              autoIncrement: false,
              unique: true,
            },
            initData: [],
            indexes: {
              username: { unique: false, autoIncrement: false },
              password: { unique: false, autoIncrement: false },
            },
          },
        ],
      });
      await db.connect();
      // Add a new record
      const model = db.useModel('MyNewTable');
      model
        .insert({
          id: Math.random() * 10,
          username: 'admin',
          password: 'nimda',
          createdAt: new Date(),
          updatedAt: new Date(),
        })
        .then(function() {
          console.info('Yay, you have saved the data.');
        })
        .catch(function(error) {
          console.error(error);
        });

      // Get all results from the database
      model.selectAll().then(function(results) {
        console.log(...results);
      });
    </script>
  </body>
</html>

Javascript

const IndexedDB = require('@n1md7/indexeddb-promise');
const { Database } = IndexedDB;
// or
import { Database } from '@n1md7/indexeddb-promise';

TypeScript 01

import { Database } from '@n1md7/indexeddb-promise';

interface Users {
  id?: number;
  username: string;
  password: string;
}

enum Priority {
  LOW = 'LOW',
  MEDIUM = 'MEDIUM',
  HIGH = 'HIGH',
}

interface ToDos {
  id?: number;
  userId: number;
  title: string;
  description: string;
  done: boolean;
  priority: Priority;
}

const database = new Database({
  version: 1,
  name: 'Todo-list',
  tables: [
    {
      name: 'users',
      primaryKey: {
        name: 'id',
        autoIncrement: true,
        unique: true,
      },
      indexes: {
        username: {
          unique: false,
        },
      },
      timestamps: true,
    },
    {
      name: 'todos',
      primaryKey: {
        name: 'id',
        autoIncrement: true,
        unique: true,
      },
      indexes: {
        userId: {
          unique: true,
        },
      },
      timestamps: true,
    },
  ],
});

(async () => {
  await database.connect();
  const users = database.useModel<Users>('users');
  const user = await users.insert({
    username: 'admin',
    password: 'admin',
  });
  const todos = database.useModel<ToDos>('todos');
  await todos.insert({
    userId: user.id,
    title: 'Todo 1',
    description: 'Description 1',
    done: false,
    priority: Priority.LOW,
  });
})();

TypeScript decorators 02

import { Table, PrimaryKey, Indexed, Database } from '@n1md7/indexeddb-promise';

@Table({ name: '__Name__', timestamps: true })
class SomeTable {
  @PrimaryKey({ autoIncrement: true, unique: true })
  id: number;

  @Indexed({ unique: true, multiEntry: false })
  username: string;

  @Indexed({ unique: false })
  age: number;

  otherData: string;
}

const anotherDb = new Database({
  version: 1,
  name: 'Other-DB',
  tables: [SomeTable],
});
await anotherDb.connect();
const model = anotherDb.useModel(SomeTable);

(async () => {
  await model
    .insert({
      username: 'John',
      age: 20,
      otherData: 'Some data',
    })
    .catch((error) => console.error(error));

  model.selectAll().then((results) => {
    if (results) {
      results.forEach((result) => {
        // result is inferred to be SomeTable
        console.log(result.username);
      });
    }
  });
})();

TypeScript decorators 02

import { Database, Indexed, PrimaryKey, Table } from '@n1md7/indexeddb-promise';

@Table({ timestamps: true })
class User {
  @PrimaryKey({ autoIncrement: true, unique: true })
  id: number;

  @Indexed({ unique: true, multiEntry: false })
  username: string;

  @Indexed()
  password: string;

  toString() {
    return `#${this.id} ${this.username}`;
  }
}

@Table()
class Info {
  @PrimaryKey({ autoIncrement: true, unique: true })
  id: number;

  @Indexed()
  userId: number;

  name: {
    first: string,
    last: string,
  };

  age: number;

  occupation: string;

  toString() {
    return `${this.name.first} ${this.name.last} ${this.age} years old - ${this.occupation}`;
  }
}

const store = new Database({
  version: 1,
  name: 'Store',
  tables: [User, Info],
});

await store.connect();

const userModel = store.useModel(User);
const infoModel = store.useModel(Info);

(async () => {
  const savedUser = await userModel.insert({
    username: 'admin',
    password: 'admin',
  });

  await infoModel.insert({
    userId: savedUser.id,
    name: {
      first: 'John',
      last: 'Doe',
    },
    age: 27,
    occupation: 'Web Developer',
  });
})().catch(console.log);

(async () => {
  const user = await userModel.selectByIndex('username', 'admin');
  if (!user) throw new Error('User not found');

  const info = await infoModel.select({ where: { userId: user.id } });
  if (!info) throw new Error('Info not found');

  console.log(user.toString() + ' - ' + info.toString());
})().catch(console.log);