Skip to content

Instantly share code, notes, and snippets.

@hugomrdias
Created October 10, 2019 12:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hugomrdias/2027b6a065c5d71831116604bd0be8bc to your computer and use it in GitHub Desktop.
Save hugomrdias/2027b6a065c5d71831116604bd0be8bc to your computer and use it in GitHub Desktop.
Simple ipfs datastore for browsers
const { Store, set, get, del } = require('idb-keyval')
function isStrictTypedArray (arr) {
return (
arr instanceof Int8Array ||
arr instanceof Int16Array ||
arr instanceof Int32Array ||
arr instanceof Uint8Array ||
arr instanceof Uint8ClampedArray ||
arr instanceof Uint16Array ||
arr instanceof Uint32Array ||
arr instanceof Float32Array ||
arr instanceof Float64Array
)
}
function typedarrayToBuffer (arr) {
if (isStrictTypedArray(arr)) {
// To avoid a copy, use the typed array's underlying ArrayBuffer to back new Buffer
var buf = Buffer.from(arr.buffer)
if (arr.byteLength !== arr.buffer.byteLength) {
// Respect the "view", i.e. byteOffset and byteLength, without doing a copy
buf = buf.slice(arr.byteOffset, arr.byteOffset + arr.byteLength)
}
return buf
} else {
// Pass through all other types to `Buffer.from`
return Buffer.from(arr)
}
}
class IdbDatastore {
constructor (location) {
this.store = new Store(location, location)
}
open () {
}
put (key, val) {
return set(key.toBuffer(), val, this.store)
}
async get (key, callback) {
const value = await get(key.toBuffer(), this.store)
if (!value) {
return callback(new Error('No value'))
}
return typedarrayToBuffer(value)
}
async has (key) {
const v = await get(key.toBuffer(), this.store)
if (v) {
return true
}
return false
}
delete (key) {
return del(key.toBuffer(), this.store)
}
batch () {
const puts = []
const dels = []
return {
put (key, value) {
puts.push([key.toBuffer(), value])
},
delete (key) {
dels.push(key.toBuffer())
},
commit: () => {
return Promise.all(puts.map(p => this.put(p[0], p[1])))
}
}
}
query (q) {
return null
}
close () {
}
}
class IdbDatastoreBatch {
constructor (location) {
this.location = location
}
open () {
const location = this.location
return openDB(this.location, 1, {
upgrade (db) {
db.createObjectStore(location)
}
})
}
async put (key, val) {
const db = await this.open()
return db.put(this.location, val, key.toBuffer())
}
async get (key) {
const db = await this.open()
const value = await db.get(this.location, key.toBuffer())
if (!value) {
throw new Error('No value')
}
return typedarrayToBuffer(value)
}
async has (key) {
const db = await this.open()
return Boolean(await db.get(this.location, key.toBuffer()))
}
async delete (key) {
const db = await this.open()
return db.del(this.location, key.toBuffer())
}
batch () {
const puts = []
const dels = []
return {
put (key, value) {
puts.push([key.toBuffer(), value])
},
delete (key) {
dels.push(key.toBuffer())
},
commit: async () => {
const db = await this.open()
const tx = db.transaction(this.location, 'readwrite')
const store = tx.store
await Promise.all(puts.map(p => store.put(p[1], p[0])))
await Promise.all(dels.map(p => store.del(p)))
await tx.done
}
}
}
query (q) {
return null
}
close () {
this.store.close()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment