diff --git a/services/gunDB/rpc.js b/services/gunDB/rpc.js new file mode 100644 index 00000000..3a4bf36d --- /dev/null +++ b/services/gunDB/rpc.js @@ -0,0 +1,106 @@ +/** + * @format + */ +// @ts-check +const { makePromise, Constants } = require('shock-common') + +const { getGun, getUser } = require('./Mediator') + +/** + * @param {string} rawPath + * @param {import('./contact-api/SimpleGUN').ValidDataValue} value + * @returns {Promise} + */ +const put = async (rawPath, value) => { + const [root, ...path] = rawPath.split('.') + + const node = (() => { + // eslint-disable-next-line init-declarations + let _node + + if (root === '$gun') { + _node = getGun() + } else if (root === '$user') { + const u = getUser() + + if (!u.is) { + throw new Error(Constants.ErrorCode.NOT_AUTH) + } + + _node = u + } else { + throw new TypeError( + `Unknown kind of root, expected $gun or $user but got: ${root}` + ) + } + + for (const bit of path) { + _node = _node.get(bit) + } + + return _node + })() + + await makePromise((res, rej) => { + node.put(value, ack => { + if (ack.err && typeof ack.err !== 'number') { + rej(new Error(ack.err)) + } else { + res() + } + }) + }) +} + +/** + * @param {string} rawPath + * @param {import('./contact-api/SimpleGUN').ValidDataValue} value + * @returns {Promise} + */ +const set = async (rawPath, value) => { + const [root, ...path] = rawPath.split('.') + + const node = (() => { + // eslint-disable-next-line init-declarations + let _node + + if (root === '$gun') { + _node = getGun() + } else if (root === '$user') { + const u = getUser() + + if (!u.is) { + throw new Error(Constants.ErrorCode.NOT_AUTH) + } + + _node = u + } else { + throw new TypeError( + `Unknown kind of root, expected $gun or $user but got: ${root}` + ) + } + + for (const bit of path) { + _node = _node.get(bit) + } + + return _node + })() + + const id = await makePromise((res, rej) => { + const subNode = node.set(value, ack => { + if (ack.err && typeof ack.err !== 'number') { + rej(new Error(ack.err)) + } else { + res(subNode._.get) + } + }) + }) + + return id +} + +module.exports = { + put, + set +} diff --git a/src/routes.js b/src/routes.js index 8aa1fc18..eb78f6da 100644 --- a/src/routes.js +++ b/src/routes.js @@ -36,6 +36,7 @@ const { listPayments } = require('../utils/lightningServices/v2') const { startTipStatusJob } = require('../utils/lndJobs') +const GunWriteRPC = require('../services/gunDB/rpc') const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10 const SESSION_ID = uuid() @@ -3116,4 +3117,41 @@ module.exports = async ( }) } }) + + ap.post('/api/gun/put', async (req, res) => { + try { + const { path, value } = req.body + + await GunWriteRPC.put(path, value) + + res.status(200).json({ + ok: true + }) + } catch (err) { + res + .status(err.message === Common.Constants.ErrorCode.NOT_AUTH ? 401 : 500) + .json({ + errorMessage: err.message + }) + } + }) + + ap.post('/api/gun/set', async (req, res) => { + try { + const { path, value } = req.body + + const id = await GunWriteRPC.set(path, value) + + res.status(200).json({ + ok: true, + id + }) + } catch (err) { + res + .status(err.message === Common.Constants.ErrorCode.NOT_AUTH ? 401 : 500) + .json({ + errorMessage: err.message + }) + } + }) }