UNPKG

gun-flint

Version:

Micro-framework for building Gun adapters

122 lines (78 loc) 5.04 kB
# Gun-Flint: Easy Gun Adapters Gun-Flint is a package that makes it easy to write adapters to connect your Gun database to various services (like databases, Pusher, etc.). Gun-Flint is not itself an adapter. # Installation `npm install gun-flint` or `yarn add gun-flint` # A Key Decision: Node, Key:Value, Delta Since Gun is a graph database, its data structure requires some special consideration. Gun-Flint attempts to provide as much flexibility for the adapter developer to store data in a format that makes sense for the storage system you are using. Building your Gun-Flint gives you an advantage of allowing Flint to ensure that the data coming from Gun reaches your adapter in a consistent format and returns data to Gun in a format that it recognizes. ### [Node Storage](https://github.com/sjones6/gun-flint/blob/master/docs/NODE_ADAPTER.MD) `get` request expect to read an entire Gun node; `put` requests write an entire node. Pros: * Easiest to implement * Flint handles merging of existing nodes with a delta on write so little chance of data corruption during conflict resolution. Cons: * Slower performance (requires a read > merge for every write); this is especially problematic if your data requires large nodes (e.g., a `users` node with millions of `user`s) * Large nodes could overwhelm memory and cause crashes; if you anticipate this, consider [Key:Value](https://github.com/sjones6/gun-flint/blob/master/docs/KEY_VAL_ADAPTER.MD) storage with streaming. **When to Use:** Most/all nodes are small; nodes are frequently created; optimal for document-based databases (e.g., MongoDB; Postgres) Example: [gun-mongo](https://github.com/sjones6/gun-mongo) ### [Key:Value](https://github.com/sjones6/gun-flint/blob/master/docs/KEY_VAL_ADAPTER.MD) `get` request returns an array/list of nodes properties; `put` requests write batch updates to specific node's key:value pairs. Pros: * Easy to implement * Faster than full-node storage * Doesn't require any additional concerns for conflict resolution Cons: * Every key:value pair (node property) would presumably require a separate record in storage (although not necessarily) * Read requests require retrieval of multiple records **When to Use:** Nodes are small/medium in size; some large nodes; nodes are frequently updated Example: [gun-mongo-key](https://github.com/sjones6/gun-mongo-key) ### [Delta Storage](https://github.com/sjones6/gun-flint/blob/master/docs/DELTA_ADAPTER.MD) `get` request return an entire node, formatted in a way Gun recognizes; `put` requests receive a delta (diff) of node properties as well as conflict-resolution state indicators. Pros: * Most flexibility for how you store a delta * High performance possibility, depending on how you implement storage. Cons: * Most difficult to implement, and incorrect implementation can lead to data corruption during conflict resolution. **When to Use:** You need total control of storage format and one of the above formats is not sufficient. # Usage Whichever storage method you decide, your adapter needs to only implement three methods: opt, get, put. See the documentation for each storage method as the exact API depends on the method selected. Stripped down, the API looks like this: ```javascript const {Flint, NodeAdapter} = require('gun-flint'); const myGunAdapter = new NodeAdapter({ opt: function(context, options) { // etc }, get: function(key, field, done) { // handle read }, put: function(node, done) { // handle write } }); Flint.register(myGunAdapter); ``` # Using Your Adapter In the end, the good users of your adapter should install it like this: ```javascript var Gun = require('gun'); // Adapter must come after requiring Gun but before `new Gun` require('your-awesome-adapter'); // Adapters all set up? Instantiate Gun. var gun = new Gun({ myAwesomeAdapter: { key: "This gets passed into the `opt` call when gun is initialized. Useful for allowing those who use your adapter to pass in DB drivers of the like." } }); ``` # Testing Your Adapter Flint comes packaged with an integration testing suite. See [full documentation here](https://github.com/sjones6/gun-flint/blob/master/docs/INTEGRATION_TESTING.MD). # Performance Profiling Flint comes packaged with an performance suite that will run against your adapter. See [full documentation here](https://github.com/sjones6/gun-flint/blob/master/docs/PERFORMANCE_TESTING.MD). # Troubleshooting If your adapter's `opt` function is never called, or when it is called, it doesn't have options that you passed to the constructor, here are some steps: 1. Do NOT list Gun in your list of dependencies. You can list it in `peerDependencies` or `devDependencies`, especially the later if you need it for testing your adapter. 2. Make sure Gun is not installed globally (run `npm list -g --depth=0` to check), and `npm uninstall -g gun` if it is. 3. Delete your `node_modules` and install a fresh set (preferably from a lockfile)