@n1md7/indexeddb-promise
v7.1.1
Published
Indexed DB wrapper with promises
Downloads
12
Maintainers
Readme
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);