Unfortunately, GunDB did not prove as robust and useful as anticipated for Node-RED and so this repo will not be developed further and so is being archived. Please feel free to fork if you wish.
Collection of nodes to use Gun.js with Node-RED
Based on a suggestion from thinkbig1979 in the Node-RED Forum.
To use this Node, you will need to:
- use at least Node-RED v1
- use a recent browser (not IE)
Install production versions from Node-RED's palette manager.
Install development versions from GitHub:
cd ~/.node-red
npm install TotallyInformation/node-red-contrib-gub-db
- Use the
Gun Listen
node to listen for any changes to or beneath the given path. Uses Gun's.on()
or.open()
functions. - Use the
Gun Out
node to trigger a one-off output based on fixed settings or using themsg.topic
to set the path. Uses Gun's.once()
or.load()
functions. - Use the
Gun Update
node to add or change data. Uses Gun's.put()
or.set()
functions. - Use the
Gun Cofig
configuration node to specify a new instance of Gun.js that is used by the other nodes. Each instance creates a new physical database locally and, optionally, is able to link to a remote instance for peer-to-peer synchronisation.
-
See the To Do sections for the nodes as well.
-
Add a Gun server
So that Node-RED can be used as a Gun backend as well. In this case, you would add GunJS to your front-end (browser) code and connect it to the Node-RED server so that data is automatically synchronised.
Will also need to try to implement the
.bye()
handling. -
Find a better way at handling JavaScript Array's & functions to make the output better able to handle random JavaScript data.
-
Add more of Gun.js's features:
- Add an
unset
feature to allow removal of unordered data added viaset
. - Gun.js user handling
gun.later(cb, seconds)
- Utils:
Gun.node.is(data)
,Gun.node.soul(data)
,Gun.node.ify(json)
- Add an
-
Still more (note these will probably never be implemented unless someone really wants to ask for them or is able to help with coding and testing)
- SEA, RAD, JOY API's
- Use other data adapters rather than just the filing system
- Proper delete function (don't think this is possible with current Gun.js API's)
2 distinct use-cases here at least:
- A server that allows front-end's (whether data driven from Node-RED or otherwise) to sync/share data.
- A DB for Node-RED itself to use. Which doesn't, of course, need the server component.
Both have significant potential benefits. Especially given the ability to subscribe to changes.
Potentially also useful for a Node-RED datastore. (Maybe. The two weaknesses listed below may yet preclude this. TBD).
- Lightweight
- NoSQL, document style, eventually consistent
- Use stand-alone or in peer-to-peer sync, no central server required
- Use in browser and/or node.js
- Subscribe to data changes.
- Partial document updates
- Capable of graph data structures.
- Can handle JavaScript circular data references
-
No proper delete function - difficult to completely clean out data
To properly delete an entire hierarchy, you would have to manually walk the data and nullify each element.
To actually delete data, you would have to delete from the filing system.
-
Cannot handle all native JavaScript object types (e.g. array's)
You cannot simply throw a random JavaScript object at Gun.js's
put
orset
function. -
Inconsistent and unexpected behaviours
The Gun.js documentation has a significant number of comments about unexpected behaviours.
Here are a couple of the worst that I found during development:
-
No delete
Covered this already but the worst thing is that if you have a deep hierarchy of nodes and then set one of the nodes to
null
as suggested in the documentation, you can still access data lower in the hierarchy since that hasn't been removed. Whilst this is obviously very fast, it makes Gun.js totally unsuitable for some uses. -
Creating a deep entry does not create intermediate nodes
Using something like
Gun.get('DB/some/deep/path').put({a:1,b:2})
does NOT create the intermediate nodes!So you cannot then do
Gun.get('DB/some').once((data, key) => {console.log(key,data)})
because this will returnundefined
for the data.To get a more anticipated outcome, you have to do
Gun.get('DB').get('some').get('deep').get('path').put({a:1,b:2})
. -
SET allows you to add a string/number/true/false/null to the data but PUT does not
-
If you use SET to add a string/number/true/false/null to the data, you cannot directly query the added data
If the added data was at
DB/some/deep/path/kb5b6jxu3lnlClU
for example, you cannot doGun.get('DB/some/deep/path/kb5b6jxu3lnlClU').once((data, key) => {console.log(key,data)})
as this will return undefined as the data. Instead you have to query the parent and then reference the propertyGun.get('DB/some/deep/path').once((data, key) => {console.log(key,data.kb5b6jxu3lnlClU)})
However, if you use SET to add an Object, you CAN query it directly!
-
UNSET is inconsistent with everything else!
I still have not found a way to use it without keeping a reference to the way you created it as in the only single example code I've found. This is OK if the entry is an object because you can GET it. But if it isn't, there appears to be no way to get a reference.
Without it, there doesn't appear to be any way to remove something added via SET.
-
Install from npm using Node-RED's Palette Manager or from the command line using npm.
Uses the .once
Gun function to output data from a given path.
You can choose to output a msg for each property of the given db/path or a single message.
Note that, by default, Gun only directly returns a single level of the hierarchy and references to the next level. Should you want the whole hierarchy, you can choose the "Output the whole hierarchy" option.
Additionally, you can choose whether to include Gun's metadata (the _
property) or not. If outputting the whole hierarchy, the metadata is not available.
Listen for new or changed data on or below the given path. Uses the Gun .on
function.
Put data to the specified path. Optionally use .set
instead of .put
.
- Output a warning if anything but an object is
put
- Output a warning if an Array being
set
- Consider adding a flag that does a
once
after a put/set and returns the data in the output msg - Consider an option that, if the input is an array, offers to loop over the array doing a
put
orset
for each entry.
Configuration node primarily to give common access to the Gun()
instance. Optionally, create a Gun.js server instance.
- Ensure that every config instance uses a different physical storage location.
The Gun data is set to <userDir>/_gun/
.
All the main nodes (not the config node) require a "Db" to be set. This is a top-level Gun element. This forces all user data to be stored below the top-level of the hierarchy which Gun treats slightly differently.
- Gun.js
- Gun.js GitHub
- Gun.js questions on StackOverflow
- Couple of useful articles about Gun.js on Medium. 1, 2
Please also check out my blog, Much Ado About IT, it has information about all sorts of topics, mainly IT related, including Node-RED.