commit
5962a03efa
3 changed files with 76 additions and 21 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* @prettier
|
* @prettier
|
||||||
*/
|
*/
|
||||||
type Primitive = boolean | string | number
|
export type Primitive = boolean | string | number
|
||||||
|
|
||||||
export interface Data {
|
export interface Data {
|
||||||
[K: string]: ValidDataValue
|
[K: string]: ValidDataValue
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,25 @@
|
||||||
/**
|
/**
|
||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
/* eslint-disable no-use-before-define */
|
||||||
// @ts-check
|
// @ts-check
|
||||||
const { makePromise, Constants, Schema } = require('shock-common')
|
const { makePromise, Constants, Schema } = require('shock-common')
|
||||||
const mapValues = require('lodash/mapValues')
|
const mapValues = require('lodash/mapValues')
|
||||||
const Bluebird = require('bluebird')
|
const Bluebird = require('bluebird')
|
||||||
|
const Gun = require('gun')
|
||||||
|
|
||||||
const { pubToEpub } = require('./contact-api/utils')
|
const { pubToEpub } = require('../contact-api/utils')
|
||||||
const {
|
const {
|
||||||
getGun,
|
getGun,
|
||||||
getUser,
|
getUser,
|
||||||
mySEA: SEA,
|
mySEA: SEA,
|
||||||
getMySecret,
|
getMySecret,
|
||||||
$$__SHOCKWALLET__ENCRYPTED__
|
$$__SHOCKWALLET__ENCRYPTED__
|
||||||
} = require('./Mediator')
|
} = require('../Mediator')
|
||||||
/**
|
/**
|
||||||
* @typedef {import('./contact-api/SimpleGUN').ValidDataValue} ValidDataValue
|
* @typedef {import('../contact-api/SimpleGUN').ValidDataValue} ValidDataValue
|
||||||
|
* @typedef {import('./types').ValidRPCDataValue} ValidRPCDataValue
|
||||||
|
* @typedef {import('./types').RPCData} RPCData
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -55,10 +59,11 @@ const deepDecryptIfNeeded = async (value, publicKey) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ValidDataValue} value
|
* @param {ValidRPCDataValue} value
|
||||||
* @returns {Promise<ValidDataValue>}
|
* @returns {Promise<ValidRPCDataValue>}
|
||||||
*/
|
*/
|
||||||
const deepEncryptIfNeeded = async value => {
|
// eslint-disable-next-line func-style
|
||||||
|
async function deepEncryptIfNeeded(value) {
|
||||||
const u = getUser()
|
const u = getUser()
|
||||||
|
|
||||||
if (!u.is) {
|
if (!u.is) {
|
||||||
|
|
@ -69,6 +74,10 @@ const deepEncryptIfNeeded = async value => {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return Promise.all(value.map(v => deepEncryptIfNeeded(v)))
|
||||||
|
}
|
||||||
|
|
||||||
const pk = /** @type {string|undefined} */ (value.$$__ENCRYPT__FOR)
|
const pk = /** @type {string|undefined} */ (value.$$__ENCRYPT__FOR)
|
||||||
|
|
||||||
if (!pk) {
|
if (!pk) {
|
||||||
|
|
@ -92,7 +101,7 @@ const deepEncryptIfNeeded = async value => {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} rawPath
|
* @param {string} rawPath
|
||||||
* @param {ValidDataValue} value
|
* @param {ValidRPCDataValue} value
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
const put = async (rawPath, value) => {
|
const put = async (rawPath, value) => {
|
||||||
|
|
@ -125,25 +134,34 @@ const put = async (rawPath, value) => {
|
||||||
return _node
|
return _node
|
||||||
})()
|
})()
|
||||||
|
|
||||||
const encryptedIfNeededValue = await deepEncryptIfNeeded(value)
|
const theValue = await deepEncryptIfNeeded(value)
|
||||||
|
|
||||||
await makePromise((res, rej) => {
|
if (Array.isArray(theValue)) {
|
||||||
node.put(encryptedIfNeededValue, ack => {
|
await Promise.all(theValue.map(v => set(rawPath, v)))
|
||||||
if (ack.err && typeof ack.err !== 'number') {
|
} else if (Schema.isObj(theValue)) {
|
||||||
rej(new Error(ack.err))
|
const writes = mapValues(theValue, (v, k) => put(`${rawPath}.${k}`, v))
|
||||||
} else {
|
|
||||||
res()
|
await Bluebird.props(writes)
|
||||||
}
|
} /* is primitive */ else {
|
||||||
|
await makePromise((res, rej) => {
|
||||||
|
node.put(/** @type {ValidDataValue} */ (theValue), ack => {
|
||||||
|
if (ack.err && typeof ack.err !== 'number') {
|
||||||
|
rej(new Error(ack.err))
|
||||||
|
} else {
|
||||||
|
res()
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} rawPath
|
* @param {string} rawPath
|
||||||
* @param {ValidDataValue} value
|
* @param {ValidRPCDataValue} value
|
||||||
* @returns {Promise<string>}
|
* @returns {Promise<string>}
|
||||||
*/
|
*/
|
||||||
const set = async (rawPath, value) => {
|
// eslint-disable-next-line func-style
|
||||||
|
async function set(rawPath, value) {
|
||||||
const [root, ...path] = rawPath.split('.')
|
const [root, ...path] = rawPath.split('.')
|
||||||
|
|
||||||
const node = (() => {
|
const node = (() => {
|
||||||
|
|
@ -173,10 +191,39 @@ const set = async (rawPath, value) => {
|
||||||
return _node
|
return _node
|
||||||
})()
|
})()
|
||||||
|
|
||||||
const encryptedIfNeededValue = await deepEncryptIfNeeded(value)
|
const theValue = await deepEncryptIfNeeded(value)
|
||||||
|
|
||||||
|
if (Array.isArray(theValue)) {
|
||||||
|
// we'll create a set of sets
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
const uuid = Gun.text.random()
|
||||||
|
|
||||||
|
// here we are simulating the top-most set()
|
||||||
|
const subPath = rawPath + '.' + uuid
|
||||||
|
|
||||||
|
const writes = theValue.map(v => set(subPath, v))
|
||||||
|
|
||||||
|
await Promise.all(writes)
|
||||||
|
|
||||||
|
return uuid
|
||||||
|
} else if (Schema.isObj(theValue)) {
|
||||||
|
// @ts-expect-error
|
||||||
|
const uuid = Gun.text.random() // we'll handle UUID ourselves
|
||||||
|
|
||||||
|
// so we can use our own put()
|
||||||
|
|
||||||
|
const subPath = rawPath + '.' + uuid
|
||||||
|
|
||||||
|
await put(subPath, theValue)
|
||||||
|
|
||||||
|
return uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
/* else is primitive */
|
||||||
|
|
||||||
const id = await makePromise((res, rej) => {
|
const id = await makePromise((res, rej) => {
|
||||||
const subNode = node.set(encryptedIfNeededValue, ack => {
|
const subNode = node.set(theValue, ack => {
|
||||||
if (ack.err && typeof ack.err !== 'number') {
|
if (ack.err && typeof ack.err !== 'number') {
|
||||||
rej(new Error(ack.err))
|
rej(new Error(ack.err))
|
||||||
} else {
|
} else {
|
||||||
8
services/gunDB/rpc/types.ts
Normal file
8
services/gunDB/rpc/types.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import {Primitive} from '../contact-api/SimpleGUN'
|
||||||
|
|
||||||
|
|
||||||
|
export interface RPCData {
|
||||||
|
[K: string]: ValidRPCDataValue
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ValidRPCDataValue = Primitive | null | RPCData | Array<ValidRPCDataValue>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue