From 95955f70aa23036e623df87ad517ef9f81d7dc54 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Sun, 12 Sep 2021 16:03:06 -0400 Subject: [PATCH] Map.on() and improvements --- utils/GunSmith/GunSmith.js | 49 +++++++++++++++++++++++++++++++------- utils/GunSmith/Smith.ts | 17 +++++++++++-- utils/GunSmith/gun.js | 26 +++++++++++++++++++- 3 files changed, 80 insertions(+), 12 deletions(-) diff --git a/utils/GunSmith/GunSmith.js b/utils/GunSmith/GunSmith.js index 95213818..e2032f66 100644 --- a/utils/GunSmith/GunSmith.js +++ b/utils/GunSmith/GunSmith.js @@ -17,6 +17,12 @@ const logger = require('../../config/log') */ const pathToListeners = {} +/** + * Maps a path to `map().on()` listeners + * @type {Record|undefined>} + */ +const pathToMapListeners = {} + /** * Path to pending puts. Oldest to newest * @type {Record} @@ -38,6 +44,17 @@ const handleMsg = msg => { l(data, path.split('>')[path.split('>').length - 1]) } } + if (msg.type === 'map.on') { + const { data, key, path } = msg + + // eslint-disable-next-line no-multi-assign + const listeners = + pathToMapListeners[path] || (pathToMapListeners[path] = new Set()) + + for (const l of listeners) { + l(data, key) + } + } if (msg.type === 'put') { const { ack, id, path } = msg @@ -214,19 +231,33 @@ function createReplica(path, afterMap = false) { }, on(cb) { listenersForThisRef.push(cb) + if (afterMap) { + // eslint-disable-next-line no-multi-assign + const listeners = + pathToMapListeners[path] || (pathToMapListeners[path] = new Set()) - // eslint-disable-next-line no-multi-assign - const listeners = - pathToListeners[path] || (pathToListeners[path] = new Set()) + listeners.add(cb) - listeners.add(cb) + /** @type {Smith.SmithMsgMapOn} */ + const msg = { + path, + type: 'map.on' + } + currentGun.send(msg) + } else { + // eslint-disable-next-line no-multi-assign + const listeners = + pathToListeners[path] || (pathToListeners[path] = new Set()) - /** @type {Smith.SmithMsgOn} */ - const msg = { - path, - type: 'on' + listeners.add(cb) + + /** @type {Smith.SmithMsgOn} */ + const msg = { + path, + type: 'on' + } + currentGun.send(msg) } - currentGun.send(msg) return this }, diff --git a/utils/GunSmith/Smith.ts b/utils/GunSmith/Smith.ts index 9a54fb15..8536b4c5 100644 --- a/utils/GunSmith/Smith.ts +++ b/utils/GunSmith/Smith.ts @@ -25,6 +25,11 @@ namespace Smith { type: 'on' } + export interface SmithMsgMapOn { + path: string + type: 'map.on' + } + export interface SmithMsgPut { id: string data: GunT.ValidDataValue @@ -36,6 +41,7 @@ namespace Smith { | SmithMsgInit | SmithMsgAuth | SmithMsgOn + | SmithMsgMapOn | SmithMsgPut | BatchSmithMsg @@ -47,11 +53,18 @@ namespace Smith { } export interface GunMsgOn { - data: any + data: GunT.ListenerData path: string type: 'on' } + export interface GunMsgMapOn { + data: GunT.ListenerData + path: string + key: string + type: 'map.on' + } + export interface GunMsgPut { ack: GunT.Ack id: string @@ -59,5 +72,5 @@ namespace Smith { type: 'put' } - export type GunMsg = GunMsgAuth | GunMsgOn | GunMsgPut + export type GunMsg = GunMsgAuth | GunMsgOn | GunMsgMapOn | GunMsgPut } diff --git a/utils/GunSmith/gun.js b/utils/GunSmith/gun.js index 530dcfcb..2fb723e7 100644 --- a/utils/GunSmith/gun.js +++ b/utils/GunSmith/gun.js @@ -104,7 +104,7 @@ const handleMsg = msg => { for (const key of keys) { node = node.get(key) } - node.on((data, key) => { + node.on(data => { /** @type {Smith.GunMsgOn} */ const res = { data, @@ -114,6 +114,30 @@ const handleMsg = msg => { sendMsg(res) }) } + if (msg.type === 'map.on') { + const [root, ...keys] = msg.path.split('>') + + /** @type {GunT.GUNNode} */ + let node = + { + $root: gun, + $user: user + }[root] || gun.user(root) + + for (const key of keys) { + node = node.get(key) + } + node.map().on((data, key) => { + /** @type {Smith.GunMsgMapOn} */ + const res = { + data, + key, + path: msg.path, + type: 'map.on' + } + sendMsg(res) + }) + } if (msg.type === 'put') { const [root, ...keys] = msg.path.split('>')