Created
January 22, 2019 01:49
-
-
Save AcidLeroy/77d2b28ebfd963589503df2a36fe0e64 to your computer and use it in GitHub Desktop.
An incomplete example of syncing lenses
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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: '[email protected]' | |
}, | |
{ | |
label: 'work', | |
email: '[email protected]' | |
} | |
] | |
} | |
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