Supports all browsers that support IndexedDB.
Has TypeScript support with TS-class decorators.
$ npm install @n1md7/indexeddb-promise
$ yarn add @n1md7/indexeddb-promise
Typescript decorators are supported.
Prerequisite:
{
"experimentalDecorators": true
}
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 {}
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;
}
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;
}
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 |
Gets all the data from database.
Return type: Promise<Object[]>
Accept params: None
model.selectAll().then((data) => data);
const data = await model.selectAll();
model.selectAll().then((data) => {
// In TS {data} is inferred from the model
return data;
});
const data = await model.selectAll();
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[];
}
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',
},
};
Gets the data from database with the specified indexed property.
Return type: Promise<Object|{}>
Accept params: indexName: string, valueToMatch: string
model.selectByIndex('username', 'admin').then((data) => data);
const data = await model.selectByIndex('username', 'admin');
Gets the data from database with the specified indexed property.
Return type: Promise<Array<Object|{}>>
Accept params: indexName: string, valueToMatch: string
model.selectByIndexAll('username', 'admin').then((data) => data);
const data = await model.selectByIndexAll('username', 'admin');
Gets the data from database with the specified primary key.
Return type: Promise<Object|{}>
Accept params: primaryKey: string \ number
model.selectByPk(1).then((data) => data);
const data = await model.selectByPk('admin');
Updates the data in database with the specified primary key.
Return type: Promise<Object|{}>
Accept params: primaryKey: string \ number, Object
model.updateByPk(123, { username: 'admin' });
const data = await model.updateByPk(123, { username: 'admin' });
Deletes the data in database with the specified primary key.
Return type: Promise<String|Number>
Accept params: primaryKey: string \ number
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
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>
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>
const IndexedDB = require('@n1md7/indexeddb-promise');
const { Database } = IndexedDB;
// or
import { Database } from '@n1md7/indexeddb-promise';
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,
});
})();
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);
});
}
});
})();
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);