https://github.com/1999/sklad
Promise-based API for IndexedDB
https://github.com/1999/sklad
html5 indexeddb javascript
Last synced: over 1 year ago
JSON representation
Promise-based API for IndexedDB
- Host: GitHub
- URL: https://github.com/1999/sklad
- Owner: 1999
- License: mit
- Created: 2013-04-21T15:56:04.000Z (about 13 years ago)
- Default Branch: master
- Last Pushed: 2023-03-02T06:43:32.000Z (over 3 years ago)
- Last Synced: 2024-10-14T05:32:16.185Z (over 1 year ago)
- Topics: html5, indexeddb, javascript
- Language: JavaScript
- Homepage: http://1999.github.io/sklad
- Size: 1.65 MB
- Stars: 47
- Watchers: 5
- Forks: 12
- Open Issues: 24
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Sklad: Promise-based API for IndexedDB
[](https://travis-ci.org/1999/sklad)
[](https://david-dm.org/1999/sklad#info=devDependencies)
[](https://greenkeeper.io/)
Sklad library makes work with IndexedDB less weird by providing a tiny Promise-based API on top of IndexedDB. If your browser doesn't support promises you can include [polyfill](https://www.npmjs.com/package/promise-polyfill) for this.
Starting from 4.0.0 Sklad library is working in all major browsers: Chrome, Firefox, IE11, Microsoft Edge, Safari9 and Android browser. Still there are some browser issues for IE11, Microsoft Edge and Safari9 which can't be patched inside library. Read [changelog](https://github.com/1999/sklad/blob/master/CHANGELOG.md#400) for more info.
If you're using Sklad with a bundler like Webpack or Rollup, you can either `import sklad from 'sklad/es2015'` or even import as is if your bundler supports [jsnext:main](https://github.com/rollup/rollup/wiki/jsnext:main). Otherwise UMD code will be used.
## Open database ([details](https://github.com/1999/sklad/blob/master/docs/README_sklad_open.md))
```javascript
const conn = await sklad.open(dbName, {
version: 2,
migration: {
'1': (database) => {
// This migration part starts when your code runs first time in the browser.
// This is a migration from "didn't exist" to "1" database version
const objStore = database.createObjectStore('users', {autoIncrement: true});
objStore.createIndex('fb_search', 'facebook_id', {unique: true});
},
'2': (database) => {
// This migration part starts when your database migrates from "1" to "2" version
const objStore = database.createObjectStore('users_likes', {keyPath: 'date'});
}
}
});
```
## Insert one or multiple records ([details](https://github.com/1999/sklad/blob/master/docs/README_skladConnection_insert.md))
```javascript
const conn = await sklad.open(dbName, options);
// insert one document into store
const insertedKey = await conn.insert(objStoreName, 'hello world');
// insert data into multiple stores inside one transaction
const insertedKeys = await conn.insert({
users: [
{email: 'example1@gmail.com', firstname: 'John'},
{email: 'example2@gmail.com', firstname: 'Jack'},
{email: 'example3@gmail.com', firstname: 'Peter'},
],
foo_obj_store: ['truly', 'madly', 'deeply']
});
assert.equal(insertedKeys, {
users: [id1, id2, id3],
foo_obj_store: [id4, id5, id6]
});
```
## Upsert one or multiple records ([details](https://github.com/1999/sklad/blob/master/docs/README_skladConnection_upsert.md))
```javascript
const conn = await sklad.open(dbName, options);
// upsert one document inside store
const upsertedKey = await conn.upsert(objStoreName, {id: 'BMTH', bandMembersCount: 5})
// upsert data in multiple stores inside one transaction
const upsertedKeys = await conn.upsert({
users: [
{email: 'example1@gmail.com', firstname: 'John'},
{email: 'example2@gmail.com', firstname: 'Jack'},
{email: 'example3@gmail.com', firstname: 'Peter'},
],
foo_obj_store: ['truly', 'madly', 'deeply']
});
assert.equal(insertedKeys, {
users: [id1, id2, id3],
foo_obj_store: [id4, id5, id6]
});
```
## Delete one or mutiple records ([details](https://github.com/1999/sklad/blob/master/docs/README_skladConnection_delete.md))
```javascript
const conn = await sklad.open(dbName, options);
// delete document from the object store
await conn.delete(objStoreName, 'key');
// delete multiple documents from different object stores inside one transaction
await conn.delete({
objStoreName1: ['key_1', 'key_2', 'key_3'],
objStoreName2: ['key1']
});
```
## Clear one or multiple object stores ([details](https://github.com/1999/sklad/blob/master/docs/README_skladConnection_clear.md))
```javascript
const conn = await sklad.open(dbName, options);
// clear everything in one object store
await conn.clear(objStoreName);
// clear everything in multiple object stores
await conn.clear([objStoreName1, objStoreName2]);
```
## Get records from the object store(s) ([details](https://github.com/1999/sklad/blob/master/docs/README_skladConnection_get.md))
Beware: if you use `index` or `direction` options in your request then fast `IDBObjectStore.prototype.getAll()` API is not used. This is still okay in most cases. More info [here](https://github.com/1999/sklad/releases/tag/4.1.0).
```javascript
const conn = await sklad.open(dbName, options);
// get documents from one object store
const resOneStore = await conn.get(objStoreName, {
index: 'missing_index', // index name, optional
direction: sklad.ASC_UNIQUE, // one of: ASC, ASC_UNIQUE, DESC, DESC_UNIQUE, optional
limit: 4, // optional
offset: 1, // optional
range: IDBKeyRange.only('some_key') // range, instance of IDBKeyRange, optional
});
assert.equal(resOneStore, {
[objStoreName]: [
{key: ..., value: ...},
{key: ..., value: ...},
...
]
});
// get documents from multiple stores in one transaction
const resMultipleStores = await conn.get({
objStoreName1: {},
objStoreName1: {limit: 1, offset: 1}
});
assert.equal(resMultipleStores, {
objStoreName1: [{key: ..., value: ...}, ...],
objStoreName2: [{key: ..., value: ...}, ...]
});
```
## Count objects in the object store(s) ([details](https://github.com/1999/sklad/blob/master/docs/README_skladConnection_count.md))
```javascript
const conn = await sklad.open(dbName, options);
// count documents inside one object store
const total = await conn.count(objStoreName, {
range: IDBKeyRange.bound(x, y, true, true), // range, instance of IDBKeyRange, optional
index: 'index_name' // index name, optional
});
// count documents inside multiple object stores
const res = await conn.count({
objStoreName1: null,
objStoreName2: {index: 'index_name'}
});
assert.equal(res, {
objStoreName1: NUMBER_OF_DOCUMENTS_INSIDE_objStoreName1,
objStoreName2: NUMBER_OF_DOCUMENTS_INSIDE_objStoreName2
});
```
## Close existing database connection ([details](https://github.com/1999/sklad/blob/master/docs/README_skladConnection_close.md))
```javascript
const conn = await sklad.open(dbName, options);
conn.close(); // it's sync
```
## Delete database
```javascript
await sklad.deleteDatabase(dbName)
```
# Structuring the database
You can specify `keyPath` and `autoIncrement` fields in `IDBDatabase.prototype.createObjectStore()` inside migration code. **Key path** (`keyPath`) is just a name of the field inside the objects which you store in the object store. For instance, it can be `foo` for object `{foo: 'bar'}`. **Key generator** (`autoIncrement`) is just a name for auto incrementing counter which is used as a primary key. Both of them (key path and key generator) can be used as primary keys for the records stored in the object stores.
More info on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB#Structuring_the_database).
## key path used, no key generator (objects with mandatory field)
```javascript
const objStore = database.createObjectStore('obj_store_title', {keyPath: 'field_name'});
```
In this case you **must** store **only objects** in the object store. You **can** specify `field_name` in the stored objects and its value will be used as a primary key for them. If you don't specify it, Sklad library will generate this field's value for you.
**SAMPLE USE CASE:** a database of users with unique logins and each user can be represented as an object with fields "firstname", "lastname", "login", "phone" etc.
## no key path, key generator used (any data, autoincremented primary key)
```javascript
const objStore = database.createObjectStore('obj_store_title', {autoIncrement: true});
```
In this case you **can** store any type of data in the object store. Primary key for the new created record will be generated by the auto incrementing key generator, but you also **can** specify your own primary key like this:
```javascript
const data = sklad.keyValue('your_unique_key', value);
database.insert('obj_store_title', data).then(...);
```
**SAMPLE USE CASE:** a simple set of data or even hierarchical objects which don't need a special field to be unique.
## key path used, key generator used (objects with optional primary key field)
```javascript
const objStore = database.createObjectStore('obj_store_title', {
keyPath: 'field_name',
autoIncrement: true
});
```
In this case you **must** store only objects in the object store. You **can** specify `field_name` in the stored objects and its value will be used as a primary key for them. If you don't specify it, its value will be an auto incremented value produced by the key generator.
**SAMPLE USE CASE:** set of hierarchical objects, which don't have a unique field.
## no keypath, no key generator (any data, primary key anarchy)
```javascript
const objStore = database.createObjectStore('obj_store_title');
```
In this case you **can** store **any type of data** in the object store. You **can** also specify a key to be used as a primary key for the record like this:
```javascript
var data = sklad.keyValue('your_unique_key', value);
database.insert('obj_store_title', data).then(...);
```
Otherwise Sklad library will generate this value for you.
**SAMPLE USE CASE:** non-structured data with a need for your own primary keys.
# Examples
[Detailed docs](https://github.com/1999/sklad/tree/master/docs) contain nice pieces of code using Sklad library.
# Tests
Tests are written with Jasmine testing framework and run with Karma runner. You need to have SauceLabs account to run tests in multiple browsers.
# Development/release process
* Watcher is started with `yarn watch`
* Release files are built with `yarn release`