Got bored on some calls so I had another go now I'm a bit fresher.
Got this example working: GUN — the database for freedom fighters - Docs v2.0
[{"id":"fbf232a7.85809","type":"inject","z":"908cedac.17439","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":340,"wires":[["96a6a8fe.76a258"]]},{"id":"96a6a8fe.76a258","type":"function","z":"908cedac.17439","name":"","func":"const Gun = global.get('Gun')\nvar gun = Gun().get('thoughts') || 'No thoughts yet'\n\ngun.set(msg.payload)\n\ngun.map().on(function(thought, id){\n if(thought){\n msg.payload = [thought, id]\n } else {\n msg.payload = ['No thought']\n }\n})\n\nreturn msg;","outputs":1,"noerr":0,"x":270,"y":340,"wires":[["af790f1a.0ad64"]]},{"id":"af790f1a.0ad64","type":"debug","z":"908cedac.17439","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":470,"y":340,"wires":[]}]
Very simplistic but at least I can see that it does work even without a peering server defined.
Took a quick look at the code, looks like a quick proof of concept rather than anything else.
Not sure that Febin is active any more. All of his nodes were updated 2yrs 4m ago, none are linked to GitHub apart from the gun server node but that links to a GitHub that no longer exists (not even the user).
I found 3 Febin Joy's on GitHub but only 1 has any repos and those are all forks.
Hmm, some weird interaction going on here.
[{"id":"fbf232a7.85809","type":"inject","z":"908cedac.17439","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":340,"wires":[["96a6a8fe.76a258"]]},{"id":"96a6a8fe.76a258","type":"function","z":"908cedac.17439","name":"set","func":"const Gun = global.get('Gun')\n\n// Get the \"thoughts\" set\nvar gun = Gun().get('thoughts')\n\n// Put the latest payload into the set\ngun.set(msg.payload)\n\n// Get each item in the set\n// gun.map().on(function(thought, id){\n// if(thought){\n// msg.payload = [thought, id]\n// } else {\n// msg.payload = ['No thought']\n// }\n// })\n\nreturn msg;","outputs":1,"noerr":0,"x":270,"y":340,"wires":[["af790f1a.0ad64"]]},{"id":"af790f1a.0ad64","type":"debug","z":"908cedac.17439","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":470,"y":340,"wires":[]},{"id":"f44b41e9.2186a","type":"inject","z":"908cedac.17439","name":"","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":95,"y":380,"wires":[["abdf0b1c.ee0c88"]],"l":false},{"id":"abdf0b1c.ee0c88","type":"function","z":"908cedac.17439","name":"get","func":"const Gun = global.get('Gun')\nconst msg1 = {payload:[]}\n\n// Get the \"thoughts\" set\nconst gun = Gun().get('thoughts')\n\nmsg1.gun = JSON.stringify(gun) || 'NO GUN'\n\n// Get each item in the set\ngun.map().on(function(thought, id){\n if(thought){\n msg1.payload = [thought, id]\n } else {\n msg1.payload = ['No thought']\n }\n})\n\nreturn msg1;","outputs":1,"noerr":0,"x":270,"y":380,"wires":[["53ecdc19.9d8534"]]},{"id":"53ecdc19.9d8534","type":"debug","z":"908cedac.17439","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":450,"y":380,"wires":[]}]
First run of the 2nd flow after using the 1st flow to update the value results in an empty set, running it again gives you the correct answer.
Not quite sure what is going on there but it isn't what I expected. Probably something obvious that I've overlooked.
OK, by shifting the
const Gun = require('gun')
const thoughts = Gun().get('thoughts')
To settings.js and attaching thoughts
to the global variables there, it works as expected so clearly some odd interaction of the function node's VM.
Ah gun.map().on(...)
is actually an event processor. Of course, I understand better now.
Adding this to the start of settings.js:
const Gun = require('gun')
const thoughts = Gun().get('thoughts')
thoughts.map().on(function(thought, id){
console.log('A THOUGHT OCCURED: ', thought)
})
Gets me a list of all of the thoughts listed to the console on Node-RED startup and then a new message whenever a new thought is added.
This is nice. However, it shows that you cannot realistically use Gun.js directly in function nodes. Custom nodes are required. If I could find the time, I'd have a go a writing a custom context store.
I could see a set of custom nodes that let you create a gun peer discovery server, "souls", subscribe to data updates and update data. Could then be extended with user ids as well.