Skip to content

Instantly share code, notes, and snippets.

@AcidLeroy
Created January 22, 2019 01:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AcidLeroy/77d2b28ebfd963589503df2a36fe0e64 to your computer and use it in GitHub Desktop.
Save AcidLeroy/77d2b28ebfd963589503df2a36fe0e64 to your computer and use it in GitHub Desktop.
An incomplete example of syncing lenses
const PouchDB = require('pouchdb')
const tmp = require('tmp');
const assert = require('assert');
const R = require('ramda')
PouchDB.plugin(require('crypto-pouch'));
// Create a temporary directory
var tmpobj = tmp.dirSync();
let dbLoc = `${tmpobj.name + '/mydb'}`
console.log(`dbLoc = ${dbLoc}`)
let myProfile = {
_id: 'profile',
firstName: 'Homer',
lastName: 'Simpson',
Addresses: [{
label: 'home',
street: '1234 Fake St.',
state: 'Unknown',
city: 'Springfield'
}],
phones: [{
label: 'home',
number: '15051234567'
},
{
label: 'cell',
number: '15057654321'
}
],
emails: [{
label: 'personal',
email: 'maxpower@hotmail.com'
},
{
label: 'work',
email: 'hjsimp@nuclear.com'
}
]
}
async function createData(db, data) {
let newData = Object.assign({}, data)
newData['lensRefs'] = [] // What lenses reference this data
newData['dateCreated'] = new Date().getTime()
newData['lastModified'] = new Date().getTime()
let result = await db.put(newData)
console.log('create Data = ', result)
return result
}
async function updateData(db, id, newData, updateLensFunc) {
newData['lastModified'] = new Date().getTime()
await db.put(newData)
newData.lensRefs.map(ref => {
updateLens(db, ref, updateLensFunc)
})
}
async function updateLens(db, lensId, updateLensFunc) {
try {
let lensRef = await db.get(lensId)
let lens = {}
let a = lensRef.dataRefs.map(async ref => {
let result = await getData(db, ref.id)
console.log('result = ', result)
if (ref.srcPaths.length !== ref.destPaths.length) {
throw (new Error('Src path length must match destination path length'))
}
R.zip(ref.srcPaths, ref.destPaths).map(([src, dest]) => {
console.log(`src = '${src}, dest = ${dest}'`)
try {
let val = R.path(src, result)
lens[dest] = val
} catch (e) {
console.log('Could not retrieve path for src data, skipping for output data')
}
})
})
await Promise.all(a).catch(e => {
console.log('e = ', e)
})
// update the Lens with the new data.
await updateLensFunc(lensRef.lensPath, lens)
lensRef.lastModified = new Date().getTime()
} catch (e) {
console.log('e = ', e)
}
}
async function getData(db, id) {
let result = await db.get(id)
return result
}
async function createLens(db, lensLabel, lensDescription, dataRefs, createLensFunc) {
let lens = {}
let lensId = `lenses/${lensLabel}`
let a = dataRefs.map(async ref => {
let result = await getData(db, ref.id)
if (ref.srcPaths.length !== ref.destPaths.length) {
throw (new Error('Src path length must match destination path'))
}
R.zip(ref.srcPaths, ref.destPaths).map(([src, dest]) => {
console.log(`src = '${src}, dest = ${dest}'`)
let val = R.path(src, result)
if (!val) throw (new Error(`Source path "${src}" does not have a value associated with it`))
lens[dest] = val
})
// Reference this lens in the original data set
result.lensRefs.push(lensId)
let newData = await db.put(result)
console.log('updated new data: ', newData)
})
await Promise.all(a)
// Use the createLensFunc to create a lens
console.log('lens = ', lens)
let newLens = await createLensFunc(lens)
let lensData = {
_id: lensId,
lensDescription: lensDescription,
lensPath: newLens.lensPath, // Location to new lens locally, i.e. /lumen
lensUrl: newLens.lensUrl, // URL of where the lens can be found, i.e. dat://1234...
dataRefs: dataRefs, // could be more than on data ref
dateCreated: new Date().getTime(),
lastModified: new Date().getTime()
}
await db.put(lensData)
return lensData
}
async function test() {
try {
let pouch = new PouchDB(dbLoc);
pouch.crypto('passwords');
let created = await createData(pouch, myProfile)
let result = await getData(pouch, created.id)
// attempt to get DB with bad password
try {
pouch.crypto('bad password')
assert(false, 'Bad password should fail here!')
// let badResult = getData(pouch, created.id)
} catch (e) {
pouch.crypto('passwords');
assert(true, 'Could not get data because bad password!')
}
// Test Create a lens
// These are the desired paths to share. The source paths
let srcPaths = [
['firstName'],
['phones', 0, 'number'],
['emails', 1, 'email']
]
// The destination paths
let destPaths = [
['name'],
['preferredPhoneNumber'],
['preferredEmail']
]
let dataRef = {
id: created.id,
srcPaths: srcPaths,
destPaths: destPaths
}
// A lens can be composed of references to multiple data sources
let dataRefs = [dataRef]
// This function would create the dat url and host it.
function createLensFunc(data) {
return {
lensPath: '/some/path/lens.obj',
lensUrl: 'dat://1234....'
}
}
// This would update the lens DB and also generate the dat url and
// local lens location
let lensInfo = await createLens(pouch, 'Lowes Data',
'Some information needed by Lowes', dataRefs, createLensFunc)
let orig = await pouch.get(created.id)
orig.firstName = 'Max'
orig.lastName = 'Power'
function updateLensFunc(lensPath, data) {
console.log('updating lens at location', lensPath)
console.log('with data ', data)
}
console.log('the orig = ', orig)
// Make sure that if we update data, that the lens is updated as well.
await updateData(pouch, created.id, orig, updateLensFunc)
console.log('lensInfo =', lensInfo)
} catch (e) {
assert(false, 'Received an error in test: ' + e)
}
}
test().catch(e => {
console.log('There was an issue: ', e)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment