Comparing version 0.4.0 to 0.5.0
218
db64.js
@@ -1,126 +0,152 @@ | ||
let dbName = 'default' | ||
const { isArray } = Array | ||
const err = console.error | ||
const openDBErrMessage = e => err(`Error creating database: ${e}`) | ||
const setDataError = e => err('Error setting data', e) | ||
const getDataError = e => err('Error retrieving data', e) | ||
let lastDBName | ||
let lastStoreName | ||
const openDB = (name = 'default', storeNames) => new Promise((resolve, reject) => { | ||
let db | ||
try { | ||
db = window.indexedDB.open(name, 1) | ||
} catch (e) { | ||
reject(openDBErrMessage) | ||
} | ||
const openDBErrMessage = err => console.error(`Error creating database: ${err}`) | ||
const setDataError = e => console.error('Error setting data', e) | ||
const getDataError = e => console.error('Error retrieving data', e) | ||
const openDB = (storeName) => new Promise((resolve, reject) => { | ||
let db | ||
try { | ||
db = window.indexedDB.open(dbName, 1) | ||
} catch (e) { | ||
reject(openDBErrMessage) | ||
} | ||
db.onupgradeneeded = e => (e.target.result).createObjectStore(storeName) | ||
db.onsuccess = e => resolve(e.target.result) | ||
db.onerror = e => reject(e.target.result) | ||
return db | ||
db.onupgradeneeded = e => { | ||
const { result } = e.target | ||
storeNames.forEach(storeName => { | ||
if (!result.objectStoreNames.contains(storeName)) { | ||
const storeCreation = result.createObjectStore(storeName) | ||
storeCreation.onerror = err => reject(err.target.error) | ||
} | ||
}) | ||
} | ||
db.onsuccess = e => (hasDBandStores = true, resolve(e.target.result)) //eslint-disable-line | ||
db.onerror = e => reject(e.target.result) | ||
return db | ||
}) | ||
const setData = async (db, storeName, key, dataValue, entries) => { | ||
try { | ||
const transaction = db.transaction([storeName], 'readwrite') | ||
const obStore = transaction.objectStore(storeName) | ||
const obStore = (db.transaction([storeName], 'readwrite')).objectStore(storeName) | ||
try { | ||
const obStore = (db.transaction([storeName], 'readwrite')).objectStore(storeName) | ||
if (entries) { | ||
const dataEntries = isArray(dataValue) | ||
? () => dataValue.map((fruitName, index) => obStore.put(fruitName, index)) | ||
: () => Object.entries(dataValue).map(([key, value]) => obStore.put(value, key)) | ||
await Promise.all(dataEntries()) | ||
} else { | ||
await obStore.put(dataValue, key) | ||
if (entries) { | ||
const dataEntries = isArray(dataValue) | ||
? () => dataValue.map((fruitName, index) => obStore.put(fruitName, index)) | ||
: () => Object.entries(dataValue).map(([key, value]) => obStore.put(value, key)) | ||
await Promise.all(dataEntries()) | ||
} else { | ||
await obStore.put(dataValue, key) | ||
} | ||
} catch (e) { | ||
console.error(e) | ||
} | ||
} catch (e) { | ||
setDataError(e) | ||
} | ||
return await db64 | ||
return db64 | ||
} | ||
const getData = async (db, storeName, key, entries) => { | ||
console.log('getData') | ||
return new Promise((resolve) => { | ||
const transaction = db.transaction([storeName]) | ||
const objectStore = transaction.objectStore(storeName) | ||
let dataRequest | ||
if (entries) { | ||
const results = {} | ||
const cursorRequest = objectStore.openCursor() | ||
cursorRequest.onsuccess = e => { | ||
const cursor = e.target.result | ||
return new Promise((resolve) => { | ||
const objectStore = (db.transaction([storeName])).objectStore(storeName) | ||
let dataRequest | ||
if (entries) { | ||
const results = {} | ||
const cursorRequest = objectStore.openCursor() | ||
if (cursor) { | ||
if (key.includes(cursor.key)) { | ||
const value = cursor.value | ||
results[cursor.key] = value | ||
} | ||
cursor.continue() | ||
cursorRequest.onsuccess = e => { | ||
const cursor = e.target.result | ||
if (cursor) { | ||
if (key.includes(cursor.key)) results[cursor.key] = cursor.value | ||
cursor.continue() | ||
} else { | ||
resolve(results) | ||
} | ||
} | ||
} else { | ||
resolve(results) | ||
dataRequest = objectStore.get(key) | ||
dataRequest.onsuccess = () => resolve(dataRequest.result) | ||
} | ||
} | ||
} else { | ||
dataRequest = objectStore.get(key) | ||
dataRequest.onsuccess = () => resolve(dataRequest.result) | ||
} | ||
}) | ||
}) | ||
} | ||
const deleteData = async (db, storeName, key) => { | ||
try { | ||
const objectStore = (db.transaction([storeName], 'readwrite')).objectStore(storeName) | ||
const cursorRequest = objectStore.openCursor() | ||
try { | ||
const objectStore = (db.transaction([storeName], 'readwrite')).objectStore(storeName) | ||
const cursorRequest = objectStore.openCursor() | ||
cursorRequest.onsuccess = e => { | ||
const cursor = e.target.result | ||
cursorRequest.onsuccess = e => { | ||
const cursor = e.target.result | ||
if (cursor) { | ||
if ((isArray(key) ? key : [key]).includes(cursor.key)) cursor.delete() | ||
cursor.continue() | ||
} | ||
if (cursor) { | ||
if ((isArray(key) ? key : [key]).includes(cursor.key)) cursor.delete() | ||
cursor.continue() | ||
} | ||
} | ||
} catch (e) { | ||
console.error(e) | ||
} | ||
} catch (e) { | ||
console.error(e) | ||
} | ||
return await db64 | ||
return db64 | ||
} | ||
const clearStore = (db, storeName) => { | ||
return new Promise((resolve, reject) => { | ||
const objectStore = (db.transaction([storeName], 'readwrite')).objectStore(storeName) | ||
const objectStoreRequest = objectStore.clear() | ||
return new Promise((resolve, reject) => { | ||
const objectStore = (db.transaction([storeName], 'readwrite')).objectStore(storeName) | ||
const objectStoreRequest = objectStore.clear() | ||
objectStoreRequest.onsuccess = resolve | ||
objectStoreRequest.onerror = e => reject(e.target.error) | ||
}) | ||
objectStoreRequest.onsuccess = resolve(db64) | ||
objectStoreRequest.onerror = e => reject(e.target.error) | ||
}) | ||
} | ||
let hasDBandStores = false | ||
const db64 = { | ||
store: storeName => { | ||
return { | ||
set: async (key, value) => openDB(storeName) | ||
.then(db => setData(db, storeName, key, value)) | ||
.catch(setDataError), | ||
setEntries: async (value) => openDB(storeName) | ||
.then(db => setData(db, storeName, null, value, 'entries')) | ||
.catch(setDataError), | ||
get: async key => openDB(storeName) | ||
.then(db => getData(db, storeName, key)) | ||
.catch(getDataError), | ||
getEntries: async (keys) => openDB(storeName) | ||
.then(db => getData(db, storeName, keys, 'entries')) | ||
.catch(getDataError), | ||
delete: async (keys) => openDB(storeName) | ||
.then(db => deleteData(db, storeName, keys)) | ||
create: async (name, storeNames) => { | ||
if(!isArray(storeNames)) return console.error('storeNames should be an array') | ||
lastDBName = name | ||
lastStoreName = storeNames[0] | ||
await openDB(name, storeNames, hasDBandStores) | ||
return db64 | ||
}, | ||
use: (name, storeName) => { | ||
if(!hasDBandStores) return console.error('A database and store needs to be created first') | ||
lastDBName = name | ||
lastStoreName = storeName | ||
return { | ||
set: async (key, value) => openDB(name, storeName) | ||
.then(db => setData(db, storeName, key, value)) | ||
.catch(console.error) | ||
, | ||
setEntries: async (value) => openDB(name, storeName) | ||
.then(db => setData(db, storeName, null, value, 'entries')) | ||
.catch(setDataError) | ||
, | ||
get: async key => openDB(name, storeName) | ||
.then(db => getData(db, storeName, key)) | ||
.catch(getDataError) | ||
, | ||
getEntries: async (keys) => openDB(name, storeName) | ||
.then(db => getData(db, storeName, keys, 'entries')) | ||
.catch(getDataError) | ||
, | ||
delete: async (keys) => openDB(name, storeName) | ||
.then(db => deleteData(db, storeName, keys)) | ||
.catch(console.error) | ||
} | ||
}, | ||
clear: async (name, storeName) => openDB(name, storeName) | ||
.then(db => clearStore(db, storeName)) | ||
.catch(console.error) | ||
} | ||
}, | ||
clear: async storeName => { | ||
return openDB(storeName).then(db => clearStore(db, storeName)) | ||
.catch(console.error) | ||
}, | ||
use: name => (dbName = name, db64) // eslint-disable-line | ||
} | ||
// const getLastDBandStore = () => db64.use(lastDBName,lastStoreName) | ||
// db64.set = (key, value) => getLastDBandStore().set(key, value) | ||
// db64.setEntries = entries => getLastDBandStore().setEntries(entries) | ||
// db64.get = key => getLastDBandStore().get(key) | ||
// db64.getEntries = entries => getLastDBandStore().getEntries(entries) | ||
// db64.delete = keys => getLastDBandStore().delete(keys) | ||
export default db64 |
{ | ||
"name": "db64", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "A Practical IndexedDB API", | ||
@@ -5,0 +5,0 @@ "main": "db64.js", |
@@ -14,3 +14,3 @@ # db64 | ||
- No versioning | ||
- 2.1kB minified | ||
- Around 2kB minified | ||
@@ -20,11 +20,15 @@ ```javascript | ||
db64.use('animals') // - Create or use an existing database | ||
.store('birds') // - create or use an existubg store | ||
.setEntries({warbler: 4, cuckoo: 3, emu: 2}) // - Set multiple entries via an array or object | ||
try { | ||
// First create a database with stores. | ||
await db64.create('Games', 'Super Nintendo', 'Gameboy') | ||
db64.store('birds').getEntries(['emu', 'warbler']) // Get multiple entries | ||
// Assing a variable for modifying a store. | ||
const snes = db64.use('Games', 'Super Nintendo') | ||
db64.store('birds').delete(['cuckoo', 'emu']) // Delete a single or array of entries | ||
// Set multiple entries | ||
await snes.setEntries({ adventure: 'Mario Wrold', rpg: 'Zelda', fighting: 'Street Fighter II' }) | ||
db64.clear('birds') // Delete all entries in birds | ||
// Get multiple entries | ||
await snes.getEntries(['adventure', 'fighting']) | ||
... | ||
``` | ||
@@ -43,4 +47,4 @@ | ||
- It was designed to encourage versioning, which is not necessary for the majority of projects | ||
- The API is considered as (low level) and is not a drop in replacement for localStorage | ||
- Removing databases and stores is not straight forward and usually requires versioning | ||
- The API is considered as (low level) and can be challenging as a replacement for localStorage | ||
- Removing databases and stores is not straight forward nor necessary, and usually requires versioning | ||
@@ -53,44 +57,47 @@ | ||
**Create or use an existing database** _[string]_ (the default DB name is "default") | ||
**Create a database with stores** _(string, array)_ | ||
```javascript | ||
db64.use('localDB') // Returns db64 | ||
await db64.create('game-consoles', ['n64', 'ps5', 'dreamcast', 'xbox-360']) | ||
``` | ||
**Create a store** and **set data**. See [structured clone algorithm](https://developer.mozilla.org/en/US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) for supported types. | ||
```javascript | ||
db64.store('fruits').set('some-key', 'some-value') // [Promise] | ||
**Use a store** _(string, string)_ | ||
```javascript | ||
const n64 = db64.use('game-consoles', 'n64') | ||
``` | ||
**Get data** _[string]_ | ||
**Set an entry** _(IDB type, IDB type)_ _See [structured clone algorithm](https://developer.mozilla.org/en/US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) for supported types_ | ||
```javascript | ||
const someKey = await db64.store('fruits').get('some-key') // [Promise] | ||
await n64.set(5, 'Super Mario 64') | ||
``` | ||
**Set multiple entries** _[Object] | [Array]_ | ||
**Set multiple entries** _(object | array)_ | ||
```javascript | ||
db64.store('fruits').setEntries({ bananas: 5, pears: 4, mangoes: 7, apples: 2 }) // [Promise] | ||
// or | ||
db64.store('fruits').setEntries([ 'bananas', 'pears', 'mangoes', 'apples' ]) // [Promise] | ||
await n64.setEntries({fps: 'GoldenEye 007', space: 'Star Fox 64', adventure: 'Banjo-Kazooie'}) | ||
await n64.setEntries(['Wave Race 64', 'The Legend of Zelda']) | ||
``` | ||
**Get multiple entries** _[Array]_ | ||
**Get an entry** _(IDB type)_ | ||
```javascript | ||
const rosaceaeFruits = await db64.store('fruits').setEntries([ 'pears', 'apples' ]) // [Promise] | ||
const fps = await n64.get('fps') // GoldenEye 007 | ||
``` | ||
**Delete a single or multiple entries** _[String] | [Array]_ | ||
**Get multiple entries** _(object | array)_ | ||
```javascript | ||
db64.store('fruits').delete('mangoes') // [Promise] | ||
// or | ||
db64.store('fruits').delete([ 'bananas', 'mangoes' ]) // [Promise] | ||
const rareware = await n64.getEntries(['fps', 'adventure', 5]) // {fps: 'GoldenEye 007', adventure: 'Banjo-Kazooie', 0: 'Super Mario 64'} | ||
``` | ||
**Delete an entry** _(IDB type | array)_ | ||
```javascript | ||
await n64.delete(1) // Deletes 'The Legend of Zelda' | ||
``` | ||
**Empty an object store** _[String]_ | ||
**Delete multiple entries** | ||
```javascript | ||
db64.clear('fruits') // [Promise] | ||
await n64.delete(['adventure', 0]) // Deletes 'Banjo-Kazooie' and 'Super Mario 64' | ||
``` | ||
**Clear a store** _(string, string)_ | ||
```javascirpt | ||
await db64.clear('game-consoles', 'n64') // All data in n64 is deleted | ||
``` | ||
### Why bd64 opts out of deleting databases and object stores | ||
@@ -97,0 +104,0 @@ |
10336
148
109