orbitdb/examples/browser/example.js
haad 42885b20a4 Write permissions for databases
Use latest store modules from npm
Update README
Update docs
Update examples
Update benchmarks
Update dependencies
Add Getting Started guide
Add new a screenshot
Add a new live demo
Add persistency tests for snapshot saving/loading and events
Add network stress tests (but skip them by default as they're very heavy and lengthy)
Add browser benchmarks
Add log() alias for eventlog() database
Add possibility to create database if it doesn't exist yet
Add support for orbitdb addresses
Add a test for starting replication when peers connect
Add debug build
Use IPFS nodeID as default user id
Use ipfs-pubsub-room
Handle closing of databases properly
Handle cache errors
Clean up tests, re-organize code files
Clean up code style
Support for CLI
Remove obsolete scripts
2017-11-28 09:10:51 +01:00

277 lines
8.3 KiB
JavaScript

const creatures = [
'🐙', '🐷', '🐬', '🐞',
'🐈', '🙉', '🐸', '🐓',
'🐊', '🕷', '🐠', '🐘',
'🐼', '🐰', '🐶', '🐥'
]
const elm = document.getElementById("output")
const statusElm = document.getElementById("status")
const dbnameField = document.getElementById("dbname")
const dbAddressField = document.getElementById("dbaddress")
const createButton = document.getElementById("create")
const openButton = document.getElementById("open")
const createType = document.getElementById("type")
const writerText = document.getElementById("writerText")
const publicCheckbox = document.getElementById("public")
const readonlyCheckbox = document.getElementById("readonly")
function handleError(e) {
console.error(e.stack)
statusElm.innerHTML = e.message
}
const main = (IPFS, ORBITDB) => {
let ipfsReady = false
let orbitdb, db
let count = 0
let interval = Math.floor((Math.random() * 300) + (Math.random() * 2000))
let updateInterval
// If we're building with Webpack, use the injected IPFS module.
// Otherwise use 'Ipfs' which is exposed by ipfs.min.js
if (IPFS)
Ipfs = IPFS
// If we're building with Webpack, use the injected OrbitDB module.
// Otherwise use 'OrbitDB' which is exposed by orbitdb.min.js
if (ORBITDB)
OrbitDB = ORBITDB
// Init UI
openButton.disabled = true
createButton.disabled = true
statusElm.innerHTML = "Starting IPFS..."
// Create IPFS instance
const ipfs = new Ipfs({
// repo: '/orbitdb/examples/browser/ipfs' + new Date().getTime(),
repo: '/orbitdb/examples/browser/new/ipfs',
EXPERIMENTAL: {
pubsub: true,
},
config: {
Addresses: {
Swarm: [
// Use IPFS dev signal server
'/dns4/star-signal.cloud.ipfs.team/wss/p2p-webrtc-star',
// Use local signal server
// '/ip4/0.0.0.0/tcp/9090/wss/p2p-webrtc-star',
]
},
Bootstrap: [],
Discovery: {
MDNS: {
Enabled: true,
Interval: 10
},
webRTCStar: {
Enabled: true
}
},
}
})
ipfs.on('error', (e) => handleError(e))
ipfs.on('ready', () => {
openButton.disabled = false
createButton.disabled = false
statusElm.innerHTML = "IPFS Started"
orbitdb = new OrbitDB(ipfs)
})
const load = async (db, statusText) => {
// Set the status text
statusElm.innerHTML = statusText
// When the database is ready (ie. loaded), display results
db.events.on('ready', () => queryAndRender(db))
// When database gets replicated with a peer, display results
db.events.on('replicated', () => queryAndRender(db))
// When we update the database, display result
db.events.on('write', () => queryAndRender(db))
// Hook up to the load progress event and render the progress
let maxTotal = 0, loaded = 0
db.events.on('load.progress', (address, hash, entry, progress, total) => {
loaded ++
maxTotal = Math.max.apply(null, [maxTotal, progress, 0])
statusElm.innerHTML = `Loading database... ${maxTotal} / ${total}`
})
db.events.on('ready', () => {
// Set the status text
setTimeout(() => {
statusElm.innerHTML = 'Database is ready'
}, 1000)
})
// Load locally persisted database
await db.load()
}
const startWriter = async (db, interval) => {
// Set the status text
writerText.innerHTML = `Writing to database every ${interval} milliseconds...`
// Start update/insert loop
updateInterval = setInterval(async () => {
try {
await update(db)
} catch (e) {
console.error(e.toString())
if (e.toString() === 'Error: Not allowed to write') {
writerText.innerHTML = '<span style="color: red">' + e.toString() + '</span>'
clearInterval(updateInterval)
}
}
}, interval)
}
const resetDatabase = async (db) => {
writerText.innerHTML = ""
elm.innerHTML = ""
clearInterval(updateInterval)
if (db) {
await db.close()
}
interval = Math.floor((Math.random() * 300) + (Math.random() * 2000))
}
const createDatabase = async () => {
await resetDatabase(db)
openButton.disabled = true
createButton.disabled = true
try {
const name = dbnameField.value
const type = createType.value
const publicAccess = publicCheckbox.checked
db = await orbitdb.open(name, {
// If database doesn't exist, create it
create: true,
overwrite: true,
// Load only the local version of the database,
// don't load the latest from the network yet
localOnly: false,
type: type,
// If "Public" flag is set, allow anyone to write to the database,
// otherwise only the creator of the database can write
write: publicAccess ? ['*'] : [],
})
await load(db, 'Creating database...')
startWriter(db, interval)
} catch (e) {
console.error(e)
}
openButton.disabled = false
createButton.disabled = false
}
const openDatabase = async () => {
const address = dbAddressField.value
await resetDatabase(db)
openButton.disabled = true
createButton.disabled = true
try {
statusElm.innerHTML = "Connecting to peers..."
db = await orbitdb.open(address, { sync: true })
await load(db, 'Loading database...')
if (!readonlyCheckbox.checked) {
startWriter(db, interval)
} else {
writerText.innerHTML = `Listening for updates to the database...`
}
} catch (e) {
console.error(e)
}
openButton.disabled = false
createButton.disabled = false
}
const update = async (db) => {
count ++
const time = new Date().toISOString()
const idx = Math.floor(Math.random() * creatures.length)
const creature = creatures[idx]
if (db.type === 'eventlog') {
const value = "GrEEtinGs from " + orbitdb.id + " " + creature + ": Hello #" + count + " (" + time + ")"
await db.add(value)
} else if (db.type === 'feed') {
const value = "GrEEtinGs from " + orbitdb.id + " " + creature + ": Hello #" + count + " (" + time + ")"
await db.add(value)
} else if (db.type === 'docstore') {
const value = { _id: 'peer1', avatar: creature, updated: time }
await db.put(value)
} else if (db.type === 'keyvalue') {
await db.set('mykey', creature)
} else if (db.type === 'counter') {
await db.inc(1)
} else {
throw new Error("Unknown datatbase type: ", db.type)
}
}
const query = (db) => {
if (db.type === 'eventlog')
return db.iterator({ limit: 5 }).collect()
else if (db.type === 'feed')
return db.iterator({ limit: 5 }).collect()
else if (db.type === 'docstore')
return db.get('peer1')
else if (db.type === 'keyvalue')
return db.get('mykey')
else if (db.type === 'counter')
return db.value
else
throw new Error("Unknown datatbase type: ", db.type)
}
const queryAndRender = async (db) => {
const networkPeers = await ipfs.swarm.peers()
const databasePeers = await ipfs.pubsub.peers(db.address.toString())
const result = query(db)
const output = `
<h2>${db.type.toUpperCase()}</h2>
<h3 id="remoteAddress">${db.address}</h3>
<div><i>Copy this address and use the 'Open Remote Database' in another browser to replicate this database between peers.</i></div>
<br>
<div><b>Peer ID:</b> ${orbitdb.id}</div>
<div><b>Peers (database/network):</b> ${databasePeers.length} / ${networkPeers.length}</div>
<div><b>Oplog Size:</b> ${db._oplog.length} / ${db._replicationInfo.max}</div>
<h2>Results</h2>
<div id="results">
<div>
${result && Array.isArray(result) && result.length > 0 && db.type !== 'docstore' && db.type !== 'keyvalue'
? result.slice().reverse().map((e) => e.payload.value).join('<br>\n')
: db.type === 'docstore'
? JSON.stringify(result, null, 2)
: result ? result.toString().replace('"', '').replace('"', '') : result
}
</div>
</div>
`
elm.innerHTML = output
}
openButton.addEventListener('click', openDatabase)
createButton.addEventListener('click', createDatabase)
}
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined')
module.exports = main