diff --git a/.gitignore b/.gitignore
index b1cc390c..5a1e39c8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
node_modules/*
npm-debug.log
*data.json
+*.db
+.idea/
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 742f4ca0..c3dcb94f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,7 @@
language: node_js
node_js:
+ - 0.6
- 0.8
- 0.10
- - 0.11
\ No newline at end of file
+ - 0.11
+ - 0.12
\ No newline at end of file
diff --git a/README.md b/README.md
index 18689c14..f544a3a2 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,12 @@
-gun [](https://travis-ci.org/amark/gun)
+gun [](https://travis-ci.org/amark/gun) [](https://gitter.im/amark/gun?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
===
+GUN is a realtime, decentralized, embedded, graph database engine.
+
## Getting Started
+For the browser, try out this [tutorial](https://dl.dropboxusercontent.com/u/4374976/gun/web/think.html). This README is for GUN servers.
+
If you do not have [node](http://nodejs.org/) or [npm](https://www.npmjs.com/), read [this](https://github.com/amark/gun/blob/master/examples/install.sh) first.
Then in your terminal, run:
@@ -33,42 +37,26 @@ These are the default persistence layers, they are modular and can be replaced o
Using S3 is recommended for deployment, and using a file is recommended for local development.
-Now you can save your first object, and create a reference to it.
+## Demos
-```javascript
-gun.set({ hello: 'world' }).key('my/first/data');
-```
-
-Altogether, try it with the node hello world web server which will reply with your data.
-
-```javascript
-var Gun = require('gun');
-var gun = Gun({ file: 'data.json' });
-gun.set({ hello: 'world' }).key('my/first/data');
-
-var http = require('http');
-http.createServer(function(req, res){
- gun.load('my/first/data', function(err, data){
- res.writeHead(200, {'Content-Type': 'application/json'});
- res.end(JSON.stringify(data));
- });
-}).listen(1337, '127.0.0.1');
-console.log('Server running at http://127.0.0.1:1337/');
-```
-
-Fire up your browser and hit that URL - you'll see your data, plus some gun specific metadata.
-
-## Examples
-
-Try out some online [examples](http://gunjs.herokuapp.com/) or run them yourself with the following command:
+The examples included in this repo are online [here](http://gunjs.herokuapp.com/), you can run them locally by:
```bash
-git clone http://github.com/amark/gun
-cd gun/examples && npm install
-node express.js 8080
+sudo npm install gun
+cd node_modules/gun
+node examples/http.js 8080
```
-Then visit [http://localhost:8080](http://localhost:8080) in your browser.
+Then visit [http://localhost:8080](http://localhost:8080) in your browser. If that did not work it is probably because npm installed to a global directory, to fix this try `mkdir node_modules` in your desired directory and re-run the above commands.
+
+***
+## WARNINGS
+### v0.2.0 [](http://waffle.io/amark/gun) [](http://waffle.io/amark/gun) [](http://waffle.io/amark/gun) Status
+
+Version 0.2.0 is currently in alpha. Important changes include `.get` to `.val`, `.load` to `.get`, and `.set` to `.put`. Documentation is our current focus, and `.all` functionality will be coming soon. The latest documentation can be found at https://github.com/amark/gun/wiki/0.2.0-API-and-How-to. Please report any issues via https://github.com/amark/gun/issues.
+
+GUN is not stable, and therefore should not be trusted in a production environment.
+***
## API
@@ -85,20 +73,20 @@ In gun, it can be helpful to think of everything as field/value pairs. For examp
"email": "mark@gunDB.io"
}
```
-Now, we want to save this object to a key called `usernames/marknadal`. We can do that like this:
+Now, we want to save this object to a key called `'usernames/marknadal'`. We can do that like this:
```javascript
-gun.set({
+gun.put({
username: "marknadal",
name: "Mark Nadal",
email: "mark@gunDB.io"
}).key('usernames/marknadal');
```
-We can also pass `set` a callback that can be used to handle errors:
+We can also pass `put` a callback that can be used to handle errors:
```javascript
-gun.set({
+gun.put({
username: "marknadal",
name: "Mark Nadal",
email: "mark@gunDB.io"
@@ -112,33 +100,40 @@ gun.set({
Once we have some data stored in gun, we need a way to get them out again. Retrieving the data that we just stored would look like this:
```javascript
-gun.load('usernames/marknadal').get(function(user){
+gun.get('usernames/marknadal').val(function(user){
console.log(user.name); // Prints `Mark Nadal` to the console
});
```
-Basically, this tells gun to check `usernames/marknadal`, and then return the object it finds associated with it. For more information, including how to save relational or document based data, [check out the wiki](https://github.com/amark/gun/wiki).
+Basically, this tells gun to check `'usernames/marknadal'`, and then return the object it finds associated with it. For more information, including how to save relational or document based data, [check out the wiki](https://github.com/amark/gun/wiki).
---
-## YOU
-We're just getting started, so join us! Being lonely is never any fun, especially when programming.
-I want to help you, because my goal is for GUN to be the easiest database ever.
-That means if you ever get stuck on something for longer than 5 minutes,
-you should talk to me so I can help you solve it.
-Your input will then help me improve gun.
-We are also really open to contributions! GUN is easy to extend and customize:
+## YOU
+Being lonely is never any fun, especially when programming.
+Our goal is for GUN to be the easiest database ever,
+which means if you ever get stuck on something for longer than 5 minutes,
+let us know so we can help you. Your input is invaluable,
+as it enables us where to refine GUN. So drop us a line in the [](https://gitter.im/amark/gun?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)! Or join the [mail list](https://groups.google.com/forum/#!forum/g-u-n).
+
+Thanks to the following people who have contributed to GUN, via code, issues, or conversation:
+
+[agborkowski](https://github.com/agborkowski), [alexlafroscia](https://github.com/alexlafroscia), [anubiann00b](https://github.com/anubiann00b), [bromagosa](https://github.com/bromagosa), [coolaj86](https://github.com/coolaj86), [d-oliveros](https://github.com/d-oliveros), [danscan](https://github.com/danscan), [forrestjt](https://github.com/forrestjt), [gedw99](https://github.com/gedw99), [HelloCodeMing](https://github.com/HelloCodeMing), [JosePedroDias](https://github.com/josepedrodias), [onetom](https://github.com/onetom), [ndarilek](https://github.com/ndarilek), [phpnode](https://github.com/phpnode), [riston](https://github.com/riston), [rootsical](https://github.com/rootsical), [rrrene](https://github.com/rrrene), [ssr1ram](https://github.com/ssr1ram), [Xe](https://github.com/Xe), [zot](https://github.com/zot)
+
+This list of contributors was manually compiled, alphabetically sorted. If we missed you, please submit an issue so we can get you added!
+
+## Contribute
+
+Extending GUN or writing modules for it is as simple as:
`Gun.on('opt').event(function(gun, opt){ /* Your module here! */ })`
-It is also important to us that your database is not a magical black box.
-So often our questions get dismissed with "its complicated hard low level stuff, let the experts handle it."
-And we do not think that attitude will generate any progress for people.
-Instead, we want to make everyone an expert by actually getting really good at explaining the concepts.
-So join our community, in the quest of learning cool things and helping yourself and others build awesome technology.
+We also want our database to be comprehensible, not some magical black box.
+So often database questions get dismissed with "its complicated hard low level stuff, let the experts handle it".
+That attitude prevents progress, instead we welcome teaching people and listening to new perspectives.
+Join along side us in a quest to learn cool things and help others build awesome technology!
- - [](https://gitter.im/amark/gun?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) (all chats relating to GUN and development should be here! IRC style)
- - Google Group: https://groups.google.com/forum/#!forum/g-u-n (for slower threaded discussions)
+We need help on the following roadmap.
## Ahead
- ~~Realtime push to the browser~~
@@ -155,9 +150,7 @@ So join our community, in the quest of learning cool things and helping yourself
- LRU or some Expiry (so RAM doesn't asplode)
- Bug fixes
- Data Structures:
- - ~~Groups~~
- - Linked Lists
- - Collections (hybrid: linked-groups/paginated-lists)
+ - ~~Sets~~ (Table/Collections, Unordered Lists)
- CRDTs
- OT
- Locking / Strong Consistency (sacrifices Availability)
diff --git a/examples/admin/Procfile b/examples/admin/Procfile
deleted file mode 100644
index 207d22f8..00000000
--- a/examples/admin/Procfile
+++ /dev/null
@@ -1 +0,0 @@
-web: node app.js
\ No newline at end of file
diff --git a/examples/admin/app.js b/examples/admin/app.js
deleted file mode 100644
index 912a1bf1..00000000
--- a/examples/admin/app.js
+++ /dev/null
@@ -1,18 +0,0 @@
-console.log("If modules not found, run `npm install` in example/admin folder!"); // git subtree push -P examples/admin heroku master
-var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || 8888;
-var express = require('express');
-var bodyParser = require('body-parser');
-var app = express();
-var Gun = require('gun');
-var gun = Gun({
- s3: (process.env.NODE_ENV === 'production')? null : require('../../test/shotgun') // replace this with your own keys!
-});
-app.use(gun.server)
- .use(express.static(__dirname))
-app.listen(port);
-
-console.log('Express started on port ' + port + ' with /gun');
-gun.load('blob/data').blank(function(){ // in case there is no data on this key
- console.log("blankety blank");
- gun.set({ hello: "world", from: "Mark Nadal",_:{'#':'0DFXd0ckJ9cXGczusNf1ovrE'}}).key('blob/data'); // save some sample data
-});
\ No newline at end of file
diff --git a/examples/admin/index.html b/examples/admin/index.html
deleted file mode 100644
index 74c1316a..00000000
--- a/examples/admin/index.html
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
Admin Data Editor
- This is a live view of your JSON data, you can edit it in realtime or add new key/values.
-
-
-
-
- {{key}}:
- {{val}}
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/examples/admin/old_gun_for_slinger.js b/examples/admin/old_gun_for_slinger.js
deleted file mode 100644
index 70a662e4..00000000
--- a/examples/admin/old_gun_for_slinger.js
+++ /dev/null
@@ -1,1062 +0,0 @@
-;(function(){
- function Gun(opt){
- var gun = this;
- if(!Gun.is(gun)){
- return new Gun(opt);
- }
- gun.opt(opt);
- }
- Gun._ = {
- soul: '#'
- ,meta: '_'
- ,HAM: '>'
- }
- ;(function(Gun){
- Gun.is = function(gun){ return (gun instanceof Gun)? true : false }
- Gun.version = 0.8;
- Gun.union = function(graph, prime){
- var context = Gun.shot();
- context.nodes = {};
- context('done');context('change');
- Gun.obj.map(prime, function(node, soul){
- var vertex = graph[soul], env;
- if(!vertex){ // disjoint
- context.nodes[node._[Gun._.soul]] = graph[node._[Gun._.soul]] = node;
- context('change').fire(node);
- return;
- }
- env = Gun.HAM(vertex, node, function(current, field, deltaValue){
- if(!current){ return }
- var change = {};
- current[field] = change[field] = deltaValue; // current and vertex are the same
- current._[Gun._.HAM][field] = node._[Gun._.HAM][field];
- change._ = current._;
- context.nodes[change._[Gun._.soul]] = change;
- context('change').fire(change);
- }).upper(function(c){
- context.err = c.err;
- context.up -= 1;
- if(!context.up){
- context('done').fire(context.err, context);
- }
- });
- context.up += env.up;
- });
- if(!context.up){
- context('done').fire(context.err, context);
- }
- return context;
- }
- Gun.HAM = function(current, delta, each){ // HAM only handles primitives values, all other data structures need to be built ontop and reduce to HAM.
- function HAM(machineState, incomingState, currentState, incomingValue, currentValue){ // TODO: Lester's comments on roll backs could be vulnerable to divergence, investigate!
- if(machineState < incomingState){
- // the incoming value is outside the boundary of the machine's state, it must be reprocessed in another state.
- return {amnesiaQuarantine: true};
- }
- if(incomingState < currentState){
- // the incoming value is within the boundary of the machine's state, but not within the range.
- return {quarantineState: true};
- }
- if(currentState < incomingState){
- // the incoming value is within both the boundary and the range of the machine's state.
- return {converge: true, incoming: true};
- }
- if(incomingState === currentState){
- if(incomingValue === currentValue){ // Note: while these are practically the same, the deltas could be technically different
- return {state: true};
- }
- /*
- The following is a naive implementation, but will always work.
- Never change it unless you have specific needs that absolutely require it.
- If changed, your data will diverge unless you guarantee every peer's algorithm has also been changed to be the same.
- As a result, it is highly discouraged to modify despite the fact that it is naive,
- because convergence (data integrity) is generally more important.
- Any difference in this algorithm must be given a new and different name.
- */
- if(String(incomingValue) < String(currentValue)){ // String only works on primitive values!
- return {converge: true, current: true};
- }
- if(String(currentValue) < String(incomingValue)){ // String only works on primitive values!
- return {converge: true, incoming: true};
- }
- }
- return {err: "you have not properly handled recursion through your data or filtered it as JSON"};
- }
- var context = Gun.shot();
- context.HAM = {};
- context.states = {};
- context.states.delta = delta._[Gun._.HAM];
- context.states.current = current._[Gun._.HAM] = current._[Gun._.HAM] || {};
- context('lower');context('upper');context.up = context.up || 0;
- Gun.obj.map(delta, function update(deltaValue, field){
- if(field === Gun._.meta){ return }
- if(!Gun.obj.has(current, field)){ // does not need to be applied through HAM
- each.call({incoming: true, converge: true}, current, field, deltaValue);
- return;
- }
- var serverState = Gun.time.is();
- // add more checks?
- var state = HAM(serverState, context.states.delta[field], context.states.current[field], deltaValue, current[field]);
- //console.log("HAM:", field, deltaValue, context.states.delta[field], context.states.current[field], 'the', state, (context.states.delta[field] - serverState));
- if(state.err){
- Gun.log(".!HYPOTHETICAL AMNESIA MACHINE ERR!.", state.err);
- return;
- }
- if(state.state || state.quarantineState || state.current){
- context('lower').fire(context, state, current, field, deltaValue);
- return;
- }
- if(state.incoming){
- each.call(state, current, field, deltaValue);
- return;
- }
- if(state.amnesiaQuarantine){
- context.up += 1;
- Gun.schedule(context.states.delta[field], function(){
- update(deltaValue, field);
- context.up -= 1;
- context('upper').fire(context, state, current, field, deltaValue);
- });
- }
- });
- if(!context.up){
- context('upper').fire(context, {});
- }
- return context;
- }
- Gun.roulette = function(l, c){
- var gun = Gun.is(this)? this : {};
- if(gun._ && gun.__.opt && gun.__.opt.uuid){
- if(Gun.fns.is(gun.__.opt.uuid)){
- return gun.__.opt.uuid(l, c);
- }
- l = l || gun.__.opt.uuid.length;
- }
- return Gun.text.random(l, c);
- }
- Gun.log = function(a, b, c, d, e, f){
- //console.log(a, b, c, d, e, f);
- //console.log.apply(console, arguments);
- }
- }(Gun));
- ;(function(Chain){
- Chain.opt = function(opt, stun){ // idempotently update or set options
- var gun = this;
- gun._ = gun._ || {};
- gun.__ = gun.__ || {};
- gun.shot = Gun.shot();
- gun.shot('then');
- gun.shot('err');
- if(!opt){ return gun }
- gun.__.opt = gun.__.opt || {};
- gun.__.keys = gun.__.keys || {};
- gun.__.graph = gun.__.graph || {};
- gun.__.on = gun.__.on || Gun.on.create();
- if(Gun.text.is(opt)){ opt = {peers: opt} }
- if(Gun.list.is(opt)){ opt = {peers: opt} }
- if(Gun.text.is(opt.peers)){ opt.peers = [opt.peers] }
- if(Gun.list.is(opt.peers)){ opt.peers = Gun.obj.map(opt.peers, function(n,f,m){ m(n,{}) }) }
- gun.__.opt.peers = opt.peers || gun.__.opt.peers || {};
- gun.__.opt.uuid = opt.uuid || gun.__.opt.uuid || {};
- gun.__.opt.hooks = gun.__.opt.hooks || {};
- Gun.obj.map(opt.hooks, function(h, f){
- if(!Gun.fns.is(h)){ return }
- gun.__.opt.hooks[f] = h;
- });
- if(!stun){ Gun.on('opt').emit(gun, opt) }
- return gun;
- }
- Chain.chain = function(from){
- var gun = Gun();
- from = from || this;
- gun.back = from;
- gun.__ = from.__;
- gun._ = {};
- Gun.obj.map(from._, function(val, field){
- gun._[field] = val;
- });
- return gun;
- }
- Chain.load = function(key, cb, opt){
- var gun = this.chain();
- cb = cb || function(){};
- gun.shot.then(function(){ cb.apply(gun, arguments) });
- cb.soul = (key||{})[Gun._.soul];
- if(cb.soul){
- cb.node = gun.__.graph[cb.soul];
- } else {
- gun._.key = key;
- cb.node = gun.__.keys[key];
- }
- if(cb.node){ // set this to the current node, too!
- Gun.log("from gun"); // remember to do all the same stack stuff here also!
- var freeze = Gun.obj.copy(gun._.node = cb.node);
- gun.shot('then').fire(freeze); // freeze now even though internals use this? OK for now.
- return gun; // TODO: BUG: This needs to react the same as below!
- }
- cb.fn = function(){}
- // missing: hear shots!
- if(Gun.fns.is(gun.__.opt.hooks.load)){
- gun.__.opt.hooks.load(key, function(err, data){
- gun._.loaded = (gun._.loaded || 0) + 1; // TODO: loading should be idempotent even if we got an err or no data
- if(err){ return (gun._.dud||cb.fn)(err) }
- if(!data){ return (gun._.blank||cb.fn)() }
- var context = gun.union(data); // safely transform the data
- if(context.err){ return (gun._.dud||cb.fn)(context.err) }
- gun._.node = gun.__.graph[data._[Gun._.soul]]; // don't wait for the union to be done because we want the immediate state not the intended state.
- if(!cb.soul){ gun.__.keys[key] = gun._.node }
- var freeze = Gun.obj.copy(gun._.node);
- gun.shot('then').fire(freeze); // freeze now even though internals use this? OK for now.
- }, opt);
- } else {
- Gun.log("Warning! You have no persistence layer to load from!");
- }
- return gun;
- }
- Chain.key = function(key, cb){
- var gun = this;
- gun.shot.then(function(){
- Gun.log("make key", key);
- cb = cb || function(){};
- cb.node = gun.__.keys[key] = gun._.node;
- if(!cb.node){ return gun }
- if(Gun.fns.is(gun.__.opt.hooks.key)){
- gun.__.opt.hooks.key(key, cb.node._[Gun._.soul], function(err, data){
- Gun.log("key made", key);
- if(err){ return cb(err) }
- return cb(null);
- });
- } else {
- Gun.log("Warning! You have no key hook!");
- }
- });
- if(!gun.back){ gun.shot('then').fire() }
- return gun;
- }
- /*
- how many different ways can we get something?
- Find via a singular path
- .path('blah').get(blah);
- Find via multiple paths with the callback getting called many times
- .path('foo', 'bar').get(foorOrBar);
- Find via multiple paths with the callback getting called once with matching arguments
- .path('foo', 'bar').get(foo, bar)
- Find via multiple paths with the result aggregated into an object of pre-given fields
- .path('foo', 'bar').get({foo: foo, bar: bar}) || .path({a: 'foo', b: 'bar'}).get({a: foo, b: bar})
- Find via multiple paths where the fields and values must match
- .path({foo: val, bar: val}).get({})
- */
- Chain.path = function(path){ // The focal point follows the path
- var gun = this.chain();
- path = (path || '').split('.');
- gun.back.shot.then(function trace(node){ // should handle blank and err! Err already handled?
- //console.log("shot path", path, node);
- gun.field = null;
- gun._.node = node;
- if(!path.length){ // if the path resolves to another node, we finish here
- return gun.shot('then').fire(node); // already frozen from loaded.
- }
- var field = path.shift()
- , val = node[field];
- gun.field = field;
- if(Gun.ify.is.soul(val)){ // we might end on a link, so we must resolve
- return gun.load(val).shot.then(trace);
- } else
- if(path.length){ // we cannot go any further, despite the fact there is more path, which means the thing we wanted does not exist
- gun.shot('then').fire();
- } else { // we are done, and this should be the value we wanted.
- gun.shot('then').fire(val); // primitive values are passed as copies in JS.
- }
- });
- // if(!gun.back){ gun.shot('then').fire() } // replace below with this? maybe???
- if(gun.back && gun.back._ && gun.back._.loaded){
- gun._.node = gun.back._.node;
- gun.back.shot('then').fire(gun.back._.node);
- }
- return gun;
- }
- Chain.get = function(cb){
- var gun = this;
- gun.shot.then(function(val){
- cb.call(gun, val); // frozen from done.
- gun.__.on(gun._.node._[Gun._.soul]).event(function(delta){
- if(!delta){ return }
- if(!gun.field){
- cb.call(gun, Gun.obj.copy(gun._.node));
- return;
- }
- if(Gun.obj.has(delta, gun.field)){
- cb.call(gun, delta[gun.field]);
- }
- })
- });
- return gun;
- }
- /*
- ACID compliant, unfortunately the vocabulary is vague, as such the following is an explicit definition:
- A - Atomic, if you set a full node, or nodes of nodes, if any value is in error then nothing will be set.
- If you want sets to be independent of each other, you need to set each piece of the data individually.
- C - Consistency, if you use any reserved symbols or similar, the operation will be rejected as it could lead to an invalid read and thus an invalid state.
- I - Isolation, the conflict resolution algorithm guarantees idempotent transactions, across every peer, regardless of any partition,
- including a peer acting by itself or one having been disconnected from the network.
- D - Durability, if the acknowledgement receipt is received, then the state at which the final persistence hook was called on is guaranteed to have been written.
- The live state at point of confirmation may or may not be different than when it was called.
- If this causes any application-level concern, it can compare against the live data by immediately reading it, or accessing the logs if enabled.
- */
- Chain.set = function(val, cb, opt){ // TODO: need to turn deserializer into a trampolining function so stackoverflow doesn't happen.
- opt = opt || {};
- var gun = this, set;
- gun.shot.then(function(){
- if(gun.field){ // a field cannot be 0!
- set = {}; // in case we are doing a set on a field, not on a node
- set[gun.field] = val; // we create a blank node with the field/value to be set
- val = set;
- } // TODO: should be able to handle val being a relation or a gun context or a gun promise.
- val._ = Gun.ify.soul.call(gun, {}, gun._.node); // and then set their souls to be the same that way they will merge correctly for us during the union!
- cb = Gun.fns.is(cb)? cb : function(){};
- set = Gun.ify.call(gun, val);
- cb.root = set.root;
- if(set.err){ return cb(set.err), gun }
- set = Gun.ify.state(set.nodes, Gun.time.is()); // set time state on nodes?
- if(set.err){ return cb(set.err), gun }
- Gun.union(gun.__.graph, set.nodes); // while this maybe should return a list of the nodes that were changed, we want to send the actual delta
- gun._.node = gun.__.graph[cb.root._[Gun._.soul]] || cb.root;
- // TODO? ^ Maybe BUG! if val is a new node on a field, _.node should now be that! Or will that happen automatically?
- if(Gun.fns.is(gun.__.opt.hooks.set)){
- gun.__.opt.hooks.set(set.nodes, function(err, data){ // now iterate through those nodes to S3 and get a callback once all are saved
- //Gun.log("gun set hook callback called");
- if(err){ return cb(err) }
- return cb(null);
- });
- } else {
- Gun.log("Warning! You have no persistence layer to save to!");
- }
- });
- if(!gun.back){ gun.shot('then').fire() }
- return gun;
- }
- Chain.union = function(prime, cb){
- var tmp, gun = this, context = Gun.shot();
- context.nodes = {};
- cb = cb || function(){}
- if(!prime){
- context.err = {err: "No data to merge!"};
- } else
- if(prime._ && prime._[Gun._.soul]){
- tmp = {};
- tmp[prime._[Gun._.soul]] = prime;
- prime = tmp;
- }
- if(!gun || context.err){
- cb(context.err = context.err || {err: "No gun instance!", corrupt: true}, context);
- return context;
- }
- Gun.obj.map(prime, function(node){ // map over the prime graph, to get each node that has been modified
- var set = Gun.ify.call(gun, node);
- if(set.err){ return context.err = set.err } // check to see if the node is valid
- Gun.obj.map(set.nodes, function(node, soul){ // if so, map over it, and any other nodes that were deserialized from it
- context.nodes[soul] = node; // into a valid context we'll actually do a union on.
- });
- });
- if(context.err){ return cb(context.err, context), context } // if any errors happened in the previous steps, then fail.
- Gun.union(gun.__.graph, context.nodes).done(function(err, env){ // now merge prime into the graph
- context.err = err || env.err;
- cb(context.err, context || {});
- }).change(function(delta){
- if(!delta || !delta._ || !delta._[Gun._.soul]){ return }
- gun.__.on(delta._[Gun._.soul]).emit(Gun.obj.copy(delta)); // this is in reaction to HAM
- });
- return context;
- }
- Chain.match = function(){ // same as path, except using objects
- return this;
- }
- Chain.blank = function(blank){
- this._.blank = Gun.fns.is(blank)? blank : function(){};
- return this;
- }
- Chain.dud = function(dud){
- this._.dud = Gun.fns.is(dud)? dud : function(){};
- return this;
- }
- }(Gun.chain = Gun.prototype));
- ;(function(Util){
- Util.fns = {};
- Util.fns.is = function(fn){ return (fn instanceof Function)? true : false }
- Util.bi = {};
- Util.bi.is = function(b){ return (b instanceof Boolean || typeof b == 'boolean')? true : false }
- Util.num = {};
- Util.num.is = function(n){
- return ((n===0)? true : (!isNaN(n) && !Util.bi.is(n) && !Util.list.is(n) && !Util.text.is(n))? true : false );
- }
- Util.text = {};
- Util.text.is = function(t){ return typeof t == 'string'? true : false }
- Util.text.ify = function(t){
- if(Util.text.is(t)){ return t }
- if(JSON){ return JSON.stringify(t) }
- return (t && t.toString)? t.toString() : t;
- }
- Util.text.random = function(l, c){
- var s = '';
- l = l || 24; // you are not going to make a 0 length random number, so no need to check type
- c = c || '0123456789ABCDEFGHIJKLMNOPQRSTUVWXZabcdefghiklmnopqrstuvwxyz';
- while(l > 0){ s += c.charAt(Math.floor(Math.random() * c.length)); l-- }
- return s;
- }
- Util.list = {};
- Util.list.is = function(l){ return (l instanceof Array)? true : false }
- Util.list.slit = Array.prototype.slice;
- Util.list.sort = function(k){ // creates a new sort function based off some field
- return function(A,B){
- if(!A || !B){ return 0 } A = A[k]; B = B[k];
- if(A < B){ return -1 }else if(A > B){ return 1 }
- else { return 0 }
- }
- }
- Util.list.map = function(l, c, _){ return Util.obj.map(l, c, _) }
- Util.list.index = 1; // change this to 0 if you want non-logical, non-mathematical, non-matrix, non-convenient array notation
- Util.obj = {};
- Util.obj.is = function(o){ return (o instanceof Object && !Util.list.is(o) && !Util.fns.is(o))? true : false }
- Util.obj.del = function(o, k){
- if(!o){ return }
- o[k] = null;
- delete o[k];
- return true;
- }
- Util.obj.ify = function(o){
- if(Util.obj.is(o)){ return o }
- try{o = JSON.parse(o);
- }catch(e){o={}};
- return o;
- }
- Util.obj.copy = function(o){ // because http://web.archive.org/web/20140328224025/http://jsperf.com/cloning-an-object/2
- return !o? o : JSON.parse(JSON.stringify(o)); // is shockingly faster than anything else, and our data has to be a subset of JSON anyways!
- }
- Util.obj.has = function(o, t){ return Object.prototype.hasOwnProperty.call(o, t) }
- Util.obj.map = function(l, c, _){
- var u, i = 0, ii = 0, x, r, rr, f = Util.fns.is(c),
- t = function(k,v){
- if(v !== u){
- rr = rr || {};
- rr[k] = v;
- return;
- } rr = rr || [];
- rr.push(k);
- };
- if(Util.list.is(l)){
- x = l.length;
- for(;i < x; i++){
- ii = (i + Util.list.index);
- if(f){
- r = _? c.call(_, l[i], ii, t) : c(l[i], ii, t);
- if(r !== u){ return r }
- } else {
- //if(Util.test.is(c,l[i])){ return ii } // should implement deep equality testing!
- if(c === l[i]){ return ii } // use this for now
- }
- }
- } else {
- for(i in l){
- if(f){
- if(Util.obj.has(l,i)){
- r = _? c.call(_, l[i], i, t) : c(l[i], i, t);
- if(r !== u){ return r }
- }
- } else {
- //if(a.test.is(c,l[i])){ return i } // should implement deep equality testing!
- if(c === l[i]){ return i }
- }
- }
- }
- return f? rr : Util.list.index? 0 : -1;
- }
- Util.time = {};
- Util.time.is = function(t){ return t? t instanceof Date : (+new Date().getTime()) }
- }(Gun));
- ;Gun.shot=(function(){
- // I hate the idea of using setTimeouts in my code to do callbacks (promises and sorts)
- // as there is no way to guarantee any type of state integrity or the completion of callback.
- // However, I have fallen. HAM is suppose to assure side effect free safety of unknown states.
- var setImmediate = setImmediate || function(cb){setTimeout(cb,0)}
- function Flow(){
- var chain = new Flow.chain();
- return chain.$ = function(where){
- (chain._ = chain._ || {})[where] = chain._[where] || [];
- chain.$[where] = chain.$[where] || function(fn){
- (chain._[where]||[]).push(fn);
- return chain.$;
- }
- chain.where = where;
- return chain;
- }
- }
- Flow.is = function(flow){ return (Flow instanceof flow)? true : false }
- ;Flow.chain=(function(){
- function Chain(){
- if(!(this instanceof Chain)){
- return new Chain();
- }
- }
- Chain.chain = Chain.prototype;
- Chain.chain.pipe = function(a,s,d,f){
- var me = this
- , where = me.where
- , args = Array.prototype.slice.call(arguments);
- setImmediate(function(){
- if(!me || !me._ || !me._[where]){ return }
- while(0 < me._[where].length){
- (me._[where].shift()||function(){}).apply(me, args);
- }
- // do a done? That would be nice. :)
- });
- return me;
- }
- return Chain;
- }());
- return Flow;
- }());Gun.shot.chain.chain.fire=Gun.shot.chain.chain.pipe;
- ;Gun.on=(function(){
- function On(where){
- if(where){
- return (On.event = On.event || On.create())(where);
- }
- return On.create();
- }
- On.is = function(on){ return (On instanceof on)? true : false }
- On.create = function(){
- var chain = new On.chain();
- return chain.$ = function(where){
- chain.where = where;
- return chain;
- }
- }
- On.sort = Gun.list.sort('i');
- ;On.chain=(function(){
- function Chain(){
- if(!(this instanceof Chain)){
- return new Chain();
- }
- }
- Chain.chain = Chain.prototype;
- Chain.chain.emit = function(what){
- var me = this
- , where = me.where
- , args = arguments
- , on = (me._ = me._ || {})[where] = me._[where] || [];
- if(!(me._[where] = Gun.list.map(on, function(hear, i, map){
- if(!hear || !hear.as){ return }
- map(hear);
- hear.as.apply(hear, args);
- }))){ Gun.obj.del(on, where) }
- }
- Chain.chain.event = function(as, i){
- if(!as){ return }
- var me = this
- , where = me.where
- , args = arguments
- , on = (me._ = me._ || {})[where] = me._[where] || []
- , e = {as: as, i: i || 0, off: function(){ return !(e.as = false) }};
- return on.push(e), on.sort(On.sort), e;
- }
- Chain.chain.once = function(as, i){
- var me = this
- , once = function(){
- this.off();
- as.apply(this, arguments)
- }
- return me.event(once, i)
- }
- return Chain;
- }());
- return On;
- }());
- ;(function(schedule){ // maybe use lru-cache
- schedule.waiting = [];
- schedule.soonest = Infinity;
- schedule.sort = Gun.list.sort('when');
- schedule.set = function(future){
- var now = Gun.time.is();
- future = (future <= now)? 0 : (future - now);
- clearTimeout(schedule.id);
- schedule.id = setTimeout(schedule.check, future);
- }
- schedule.check = function(){
- var now = Gun.time.is(), soonest = Infinity;
- schedule.waiting.sort(schedule.sort);
- schedule.waiting = Gun.list.map(schedule.waiting, function(wait, i, map){
- if(!wait){ return }
- if(wait.when <= now){
- if(Gun.fns.is(wait.event)){
- wait.event();
- }
- } else {
- soonest = (soonest < wait.when)? soonest : wait.when;
- map(wait);
- }
- }) || [];
- schedule.set(soonest);
- }
- Gun.schedule = function(state, cb){
- schedule.waiting.push({when: state, event: cb});
- if(schedule.soonest < state){ return }
- schedule.set(state);
- }
- }({}));
- ;(function(Serializer){
- Gun.ify = function(data){ // TODO: BUG: Modify lists to include HAM state
- var gun = Gun.is(this)? this : {}
- , context = {
- nodes: {}
- ,seen: []
- ,_seen: []
- }, nothing;
- function ify(data, context, sub){
- sub = sub || {};
- sub.path = sub.path || '';
- context = context || {};
- context.nodes = context.nodes || {};
- if((sub.simple = Gun.ify.is(data)) && !(sub._ && Gun.text.is(sub.simple))){
- return data;
- } else
- if(Gun.obj.is(data)){
- var value = {}, symbol = {}, seen
- , err = {err: "Metadata does not support external or circular references at " + sub.path, meta: true};
- context.root = context.root || value;
- if(seen = ify.seen(context._seen, data)){
- //Gun.log("seen in _", sub._, sub.path, data);
- context.err = err;
- return;
- } else
- if(seen = ify.seen(context.seen, data)){
- //Gun.log("seen in data", sub._, sub.path, data);
- if(sub._){
- context.err = err;
- return;
- }
- symbol = Gun.ify.soul.call(gun, symbol, seen);
- return symbol;
- } else {
- //Gun.log("seen nowhere", sub._, sub.path, data);
- if(sub._){
- context.seen.push({data: data, node: value});
- } else {
- value._ = Gun.ify.soul.call(gun, {}, data);
- context.seen.push({data: data, node: value});
- context.nodes[value._[Gun._.soul]] = value;
- }
- }
- Gun.obj.map(data, function(val, field){
- var subs = {path: sub.path + field + '.', _: sub._ || (field == Gun._.meta)? true : false };
- val = ify(val, context, subs);
- //Gun.log('>>>>', sub.path + field, 'is', val);
- if(context.err){ return true }
- if(nothing === val){ return }
- // TODO: check field validity
- value[field] = val;
- });
- if(sub._){ return value }
- if(!value._ || !value._[Gun._.soul]){ return }
- symbol[Gun._.soul] = value._[Gun._.soul];
- return symbol;
- } else
- if(Gun.list.is(data)){
- var unique = {}, edges
- , err = {err: "Arrays cause data corruption at " + sub.path, array: true}
- edges = Gun.list.map(data, function(val, i, map){
- val = ify(val, context, sub);
- if(context.err){ return true }
- if(!Gun.obj.is(val)){
- context.err = err;
- return true;
- }
- return Gun.obj.map(val, function(soul, field){
- if(field !== Gun._.soul){
- context.err = err;
- return true;
- }
- if(unique[soul]){ return }
- unique[soul] = 1;
- map(val);
- });
- });
- if(context.err){ return }
- return edges;
- } else {
- context.err = {err: "Data type not supported at " + sub.path, invalid: true};
- }
- }
- ify.seen = function(seen, data){
- // unfortunately, using seen[data] = true will cause false-positives for data's children
- return Gun.list.map(seen, function(check){
- if(check.data === data){ return check.node }
- });
- }
- ify(data, context);
- return context;
- }
- Gun.ify.state = function(nodes, now){
- var context = {};
- context.nodes = nodes;
- context.now = now = (now === 0)? now : now || Gun.time.is();
- Gun.obj.map(context.nodes, function(node, soul){
- if(!node || !soul || !node._ || !node._[Gun._.soul] || node._[Gun._.soul] !== soul){
- return context.err = {err: "There is a corruption of nodes and or their souls", corrupt: true};
- }
- var states = node._[Gun._.HAM] = node._[Gun._.HAM] || {};
- Gun.obj.map(node, function(val, field){
- if(field == Gun._.meta){ return }
- val = states[field];
- states[field] = (val === 0)? val : val || now;
- });
- });
- return context;
- }
- Gun.ify.soul = function(to, from){
- var gun = this;
- to = to || {};
- if(Gun.ify.soul.is(from)){
- to[Gun._.soul] = from._[Gun._.soul];
- return to;
- }
- to[Gun._.soul] = Gun.roulette.call(gun);
- return to;
- }
- Gun.ify.soul.is = function(o){
- if(o && o._ && o._[Gun._.soul]){
- return true;
- }
- }
- Gun.ify.is = function(v){ // null, binary, number (!Infinity), text, or a rel.
- if(v === null){ return true } // deletes
- if(v === Infinity){ return false } // we want this to be, but JSON does not support it, sad face.
- if(Gun.bi.is(v)
- || Gun.num.is(v)
- || Gun.text.is(v)){
- return true; // simple values
- }
- var yes;
- if(yes = Gun.ify.is.soul(v)){
- return yes;
- }
- return false;
- }
- Gun.ify.is.soul = function(v){
- if(Gun.obj.is(v)){
- var yes;
- Gun.obj.map(v, function(soul, field){
- if(yes){ return yes = false }
- if(field === Gun._.soul && Gun.text.is(soul)){
- yes = soul;
- }
- });
- if(yes){
- return yes;
- }
- }
- return false;
- }
- }());
- if(typeof window !== "undefined"){
- window.Gun = Gun;
- } else {
- module.exports = Gun;
- }
-}({}));
-
-;(function(tab){
- if(!this.Gun){ return }
- if(!window.JSON){ Gun.log("Include JSON first: ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js") } // for old IE use
- Gun.on('opt').event(function(gun, opt){
- tab.server = tab.server || function(req, res, next){
-
- }
- window.tab = tab; // window.XMLHttpRequest = null; // for debugging purposes
- (function(){
- tab.store = {};
- var store = window.localStorage || {setItem: function(){}, removeItem: function(){}, getItem: function(){}};
- tab.store.set = function(key, val){console.log('setting', key); return store.setItem(key, Gun.text.ify(val)) }
- tab.store.get = function(key){ return Gun.obj.ify(store.getItem(key)) }
- tab.store.del = function(key){ return store.removeItem(key) }
- }());
- tab.load = tab.load || function(key, cb, opt){
- if(!key){ return }
- cb = cb || function(){};
- opt = opt || {};
- if(key[Gun._.soul]){
- key = '_' + tab.query(key);
- }
- Gun.obj.map(gun.__.opt.peers, function(peer, url){
- tab.ajax(url + '/' + key, null, function(err, reply){
- console.log('via', url, key, reply);
- if(!reply){ return } // handle reconnect?
- if(reply.body && reply.body.err){
- cb(reply.body.err);
- } else {
- cb(null, reply.body);
- }
-
- (function(){
- tab.subscribe.sub = (reply.headers || {})['gun-sub'] || tab.subscribe.sub;
- //console.log("We are sub", tab.subscribe.sub);
- var data = reply.body;
- if(!data || !data._){ return }
- tab.subscribe(data._[Gun._.soul]);
- }());
- }, {headers: {'Gun-Sub': tab.subscribe.sub || ''}, header: {'Gun-Sub': 1}});
- });
- }
- tab.url = function(nodes){
- return;
- console.log("urlify delta", nodes);
- var s = ''
- , uri = encodeURIComponent;
- Gun.obj.map(nodes, function(delta, soul){
- var ham;
- if(!delta || !delta._ || !(ham = delta._[Gun._.HAM])){ return }
- s += uri('#') + '=' + uri(soul) + '&';
- Gun.obj.map(delta, function(val, field){
- if(field === Gun._.meta){ return }
- s += uri(field) + '=' + uri(Gun.text.ify(val)) + uri('>') + uri(ham[field]) + '&';
- })
- });
- console.log(s);
- return s;
- }
- tab.set = tab.set || function(nodes, cb){
- cb = cb || function(){};
- // TODO: batch and throttle later.
- //tab.store.set(cb.id = 'send/' + Gun.text.random(), nodes);
- //tab.url(nodes);
- Gun.obj.map(gun.__.opt.peers, function(peer, url){
- tab.ajax(url, nodes, function respond(err, reply, id){
- var body = reply && reply.body;
- respond.id = respond.id || cb.id;
- Gun.obj.del(tab.set.defer, id); // handle err with a retry? Or make a system auto-do it?
- if(!body){ return }
- if(body.defer){
- //console.log("deferring post", body.defer);
- tab.set.defer[body.defer] = respond;
- }
- if(body.reply){
- respond(null, {headers: reply.headers, body: body.reply });
- }
- if(body.refed){
- console.log("-------post-reply-all--------->", 1 || reply, err);
- Gun.obj.map(body.refed, function(r, id){
- var cb;
- if(cb = tab.set.defer[id]){
- cb(null, {headers: reply.headers, body: r}, id);
- }
- });
- // TODO: should be able to do some type of "checksum" that every request cleared, and if not, figure out what is wrong/wait for finish.
- return;
- }
- if(body.reply || body.defer || body.refed){ return }
- //tab.store.del(respond.id);
- }, {headers: {'Gun-Sub': tab.subscribe.sub || ''}});
- });
- Gun.obj.map(nodes, function(node, soul){
- gun.__.on(soul).emit(node, true); // should we emit difference between local and not?
- });
- }
- tab.set.defer = {};
- tab.subscribe = function(soul){ // TODO: BUG!!! ERROR! Handle disconnection (onerror)!!!!
- tab.subscribe.to = tab.subscribe.to || {};
- if(soul){
- tab.subscribe.to[soul] = 1;
- }
- var opt = {
- header: {'Gun-Sub': 1},
- headers: {
- 'Gun-Sub': tab.subscribe.sub || ''
- }
- }, query = tab.subscribe.sub? '' : tab.query(tab.subscribe.to);
- console.log("subscribing poll", tab.subscribe.sub);
- Gun.obj.map(gun.__.opt.peers, function(peer, url){
- tab.ajax(url + query, null, function(err, reply){
- if(err || !reply || !reply.body || reply.body.err){ // not interested in any null/0/''/undefined values
- //console.log(err, reply);
- return;
- }
- console.log("poll", 1 || reply);
- tab.subscribe.poll();
- if(reply.headers){
- tab.subscribe.sub = reply.headers['gun-sub'] || tab.subscribe.sub;
- }
- if(!reply.body){ return } // do anything?
- gun.union(reply.body); // safely transform data
- }, opt);
- });
- }
- tab.subscribe.poll = function(){
- clearTimeout(tab.subscribe.poll.id);
- tab.subscribe.poll.id = setTimeout(tab.subscribe, 1); //1000 * 10); // should enable some server-side control of this.
- }
- tab.query = function(params){
- var s = '?'
- , uri = encodeURIComponent;
- Gun.obj.map(params, function(val, field){
- s += uri(field) + '=' + uri(val || '') + '&';
- });
- return s;
- }
- tab.ajax = (function(){
- function ajax(url, data, cb, opt){
- var u;
- opt = opt || {};
- opt.header = opt.header || {};
- opt.header["Content-Type"] = 1;
- opt.headers = opt.headers || {};
- if(data === u || data === null){
- data = u;
- } else {
- try{data = JSON.stringify(data);
- opt.headers["Content-Type"] = "application/json";
- }catch(e){}
- }
- opt.method = opt.method || (data? 'POST' : 'GET');
- var xhr = ajax.xhr() || ajax.jsonp() // TODO: BUG: JSONP push is working, but not post
- , clean = function(){
- if(!xhr){ return }
- xhr.onreadystatechange = xhr.onerror = null;
- try{xhr.abort();
- }catch(e){}
- xhr = null;
- }
- xhr.onerror = function(){
- if(cb){
- cb({err: err || 'Unknown error.', status: xhr.status });
- }
- clean(xhr.status === 200 ? 'network' : 'permanent');
- };
- xhr.onreadystatechange = function(){
- if(!xhr){ return }
- var reply, status;
- try{reply = xhr.responseText;
- status = xhr.status;
- }catch(e){}
- if(status === 1223){ status = 204 }
- if(xhr.readyState === 3){
- if(reply && 0 < reply.length){
- opt.ondata(status, reply);
- }
- } else
- if(xhr.readyState === 4){
- opt.ondata(status, reply, true);
- clean(status === 200? 'network' : 'permanent');
- }
- };
- opt.ondata = opt.ondata || function(status, chunk, end){
- if(status !== 200){ return }
- try{ajax.each(opt.header, function(val, i){
- (xhr.responseHeader = xhr.responseHeader||{})[i.toLowerCase()] = xhr.getResponseHeader(i);
- });
- }catch(e){}
- var data, buf, pos = 1;
- while(pos || end){ // in order to end
- if(u !== data){ // we need at least one loop
- opt.onload({
- headers: xhr.responseHeader || {}
- ,body: data
- });
- end = false; // now both pos and end will be false
- }
- if(ajax.string(chunk)){
- buf = chunk.slice(xhr.index = xhr.index || 0);
- pos = buf.indexOf('\n') + 1;
- data = pos? buf.slice(0, pos - 1) : buf;
- xhr.index += pos;
- } else {
- data = chunk;
- pos = 0;
- }
- }
- }
- opt.onload = opt.onload || function(reply){
- if(!reply){ return }
- if( reply.headers && ("application/json" === reply.headers["content-type"])){
- var body;
- try{body = JSON.parse(reply.body);
- }catch(e){body = reply.body}
- reply.body = body;
- }
- if(cb){
- cb(null, reply);
- }
- }
- if(opt.cookies || opt.credentials || opt.withCredentials){
- xhr.withCredentials = true;
- }
- opt.headers["X-Requested-With"] = xhr.transport || "XMLHttpRequest";
- try{xhr.open(opt.method, url, true);
- }catch(e){ return xhr.onerror("Open failed.") }
- if(opt.headers){
- try{ajax.each(opt.headers, function(val, i){
- xhr.setRequestHeader(i, val);
- });
- }catch(e){ return xhr.onerror("Invalid headers.") }
- }
- try{xhr.send(data);
- }catch(e){ return xhr.onerror("Failed to send request.") }
- }
- ajax.xhr = function(xhr){
- return (window.XMLHttpRequest && "withCredentials" in (xhr = new XMLHttpRequest()))? xhr : null;
- }
- ajax.jsonp = function(xhr){
- xhr = {};
- xhr.transport = "jsonp";
- xhr.open = function(method, url){
- xhr.url = url;
- }
- xhr.send = function(){
- xhr.url += ((xhr.url.indexOf('?') + 1)? '&' : '?') + 'jsonp=' + xhr.js.id;
- ajax.each(xhr.headers, function(val, i){
- xhr.url += '&' + encodeURIComponent(i) + "=" + encodeURIComponent(val);
- });
- xhr.js.src = xhr.url = xhr.url.replace(/%20/g, "+");
- document.getElementsByTagName('head')[0].appendChild(xhr.js);
- }
- xhr.setRequestHeader = function(i, val){
- (xhr.headers = xhr.headers||{})[i] = val;
- }
- xhr.getResponseHeader = function(i){ return (xhr.responseHeaders||{})[i] }
- xhr.js = document.createElement('script');
- window[xhr.js.id = 'P'+Math.floor((Math.random()*65535)+1)] = function(reply){
- xhr.status = 200;
- if(reply.chunks && reply.chunks.length){
- xhr.readyState = 3
- while(0 < reply.chunks.length){
- xhr.responseText = reply.chunks.shift();
- xhr.onreadystatechange();
- }
- }
- xhr.responseHeaders = reply.headers || {};
- xhr.readyState = 4;
- xhr.responseText = reply.body;
- xhr.onreadystatechange();
- xhr.id = xhr.js.id;
- xhr.js.parentNode.removeChild(xhr.js);
- window[xhr.id] = null;
- try{delete window[xhr.id];
- }catch(e){}
-
- }
- xhr.abort = function(){} // clean up?
- xhr.js.async = true;
- return xhr;
- }
- ajax.string = function(s){ return (typeof s == 'string') }
- ajax.each = function(obj, cb){
- if(!obj || !cb){ return }
- for(var i in obj){
- if(obj.hasOwnProperty(i)){
- cb(obj[i], i);
- }
- }
- }
- return ajax;
- }());
- gun.__.opt.hooks.load = gun.__.opt.hooks.load || tab.load;
- gun.__.opt.hooks.set = gun.__.opt.hooks.set || tab.set;
- });
-}({}));
\ No newline at end of file
diff --git a/examples/admin/package.json b/examples/admin/package.json
deleted file mode 100644
index a9f9782e..00000000
--- a/examples/admin/package.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "name": "admin",
- "main": "app.js",
- "description": "Example gun app, using Express & Angular."
-, "version": "0.0.1"
-, "engines": {
- "node": "~>0.6.6"
- }
-, "dependencies": {
- "express": "~>4.9.0",
- "body-parser": "~>1.8.1",
- "gun": "0.0.7"
- }
-, "scripts": {
- "start": "node app.js",
- "test": "mocha"
- }
-}
\ No newline at end of file
diff --git a/examples/admin/slinger-t.html b/examples/admin/slinger-t.html
deleted file mode 100644
index 9400166d..00000000
--- a/examples/admin/slinger-t.html
+++ /dev/null
@@ -1,229 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
GUN SLINGER
-
Select!
-
-
-
Next game available in 15 seconds or less...
-
Fastest draw in the west, no seconds, by nobody.
-
Previous duel won in no seconds, by no one.
-
-
-
GET READY!
-
-
-
FIRE!
-
by tapping this screen
-
-
-
STOP!
-
...waiting for the other player...
-
-
-
DISQUALIFIED!
-
-
-
YOU DIED!
-
-
-
YOU BOTH DIED!
-
-
-
-
YOU WON!
-
-
-
-
YOU WON!
-
-
-
-
-
\ No newline at end of file
diff --git a/examples/admin/slinger.html b/examples/admin/slinger.html
deleted file mode 100644
index 9fc14674..00000000
--- a/examples/admin/slinger.html
+++ /dev/null
@@ -1,229 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
GUN SLINGER
-
Select!
-
-
-
Next game available in 15 seconds or less...
-
Fastest draw in the west, no seconds, by nobody.
-
Previous duel won in no seconds, by no one.
-
-
-
GET READY!
-
-
-
FIRE!
-
by tapping this screen
-
-
-
STOP!
-
...waiting for the other player...
-
-
-
DISQUALIFIED!
-
-
-
YOU DIED!
-
-
-
YOU BOTH DIED!
-
-
-
-
YOU WON!
-
-
-
-
YOU WON!
-
-
-
-
-
\ No newline at end of file
diff --git a/examples/admin/slinger_.html b/examples/admin/slinger_.html
deleted file mode 100644
index f9fb6c83..00000000
--- a/examples/admin/slinger_.html
+++ /dev/null
@@ -1,195 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
GUN SLINGER
-
Select!
-
-
-
Next game available in 15 seconds or less...
-
-
-
GET READY!
-
-
-
FIRE!
-
by tapping this screen
-
-
-
STOP!
-
...waiting for the other player...
-
-
-
DISQUALIFIED!
-
-
-
YOU DIED!
-
-
-
YOU BOTH DIED!
-
-
-
-
YOU WON!
-
-
-
-
-
\ No newline at end of file
diff --git a/examples/angular/index.html b/examples/angular/index.html
deleted file mode 100644
index 4a32c5ea..00000000
--- a/examples/angular/index.html
+++ /dev/null
@@ -1,79 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
Admin JSON Editor
- This is a live view of your data, you can edit it in realtime or add new key/values.
-
-
-
- {{key}}:
- {{val}}
-
-
-
-
-
-
-
-
-
diff --git a/examples/cats/get.js b/examples/cats/get.js
deleted file mode 100644
index 926aa14b..00000000
--- a/examples/cats/get.js
+++ /dev/null
@@ -1,5 +0,0 @@
-var gun = require('gun')({
- s3: (process.env.NODE_ENV === 'production')? null : require('../../test/shotgun') // replace this with your own keys!
-});
-
-gun.load('kitten/hobbes').path('servant.cat.servant.name').get(function(name){ console.log(name) })
\ No newline at end of file
diff --git a/examples/cats/load.js b/examples/cats/load.js
deleted file mode 100644
index b5a9a5af..00000000
--- a/examples/cats/load.js
+++ /dev/null
@@ -1,13 +0,0 @@
-var gun = require('gun')({
- s3: (process.env.NODE_ENV === 'production')? null : require('../../test/shotgun') // replace this with your own keys!
-});
-
-gun.load('email/mark@gundb.io').get(function(Mark){
- console.log("Hello ", Mark);
- this.path('username').set('amark'); // because we hadn't saved it yet!
- this.path('cat').get(function(Hobbes){ // `this` is context of the nodes you explore via path
- console.log(Hobbes);
- this.set({ servant: Mark, coat: "tabby" }); // oh no! Hobbes has become Mark's master.
- this.key('kitten/hobbes'); // cats are taking over the internet! Better make an index for them.
- });
-});
\ No newline at end of file
diff --git a/examples/cats/set.js b/examples/cats/set.js
deleted file mode 100644
index 4ba48876..00000000
--- a/examples/cats/set.js
+++ /dev/null
@@ -1,7 +0,0 @@
-var gun = require('gun')({
- s3: (process.env.NODE_ENV === 'production')? null : require('../../test/shotgun') // replace this with your own keys!
-});
-
-gun.set({ name: "Mark Nadal", email: "mark@gunDB.io", cat: { name: "Hobbes", species: "kitty" } })
- .key('email/mark@gundb.io')
-;
\ No newline at end of file
diff --git a/examples/chat/index.html b/examples/chat/index.html
new file mode 100644
index 00000000..4ba9ff79
--- /dev/null
+++ b/examples/chat/index.html
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+ 0
+ :
+
+ 0
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/chat/spam.js b/examples/chat/spam.js
new file mode 100644
index 00000000..1adfcd18
--- /dev/null
+++ b/examples/chat/spam.js
@@ -0,0 +1,10 @@
+function spam(){
+ spam.start = true; spam.lock = false;
+ if(spam.count >= 100){ return }
+ var $f = $('form');
+ $('.what', $f).value = ++spam.count;
+ $f.onsubmit();
+ setTimeout(spam, 0);
+}; spam.count = 0; spam.lock = true;
+
+alert("ADD THIS LINE TO THE TOP OF THE MAP.VAL CALLBACK: `if(!spam.lock && !spam.start){ spam() }`");
\ No newline at end of file
diff --git a/examples/express.js b/examples/express.js
index d108ebf1..e311d5e1 100644
--- a/examples/express.js
+++ b/examples/express.js
@@ -17,4 +17,4 @@ var gun = Gun({
gun.attach(app);
app.use(express.static(__dirname)).listen(port);
-console.log('Server started on port ' + port + ' with /gun');
+console.log('Server started on port ' + port + ' with /gun');
\ No newline at end of file
diff --git a/examples/hello-world.js b/examples/hello-world.js
index 1337fff6..380c8170 100644
--- a/examples/hello-world.js
+++ b/examples/hello-world.js
@@ -6,11 +6,11 @@ var gun = Gun({
bucket: '' // The bucket you want to save into
}
});
-gun.set({ hello: 'world' }).key('my/first/data');
+gun.put({ hello: 'world' }).key('my/first/data');
var http = require('http');
http.createServer(function(req, res){
- gun.load('my/first/data', function(err, data){
+ gun.get('my/first/data', function(err, data){
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(data));
});
diff --git a/examples/http.js b/examples/http.js
index 21590548..9fabbb68 100644
--- a/examples/http.js
+++ b/examples/http.js
@@ -1,7 +1,5 @@
var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || process.argv[2] || 80;
-var http = require('http');
-
var Gun = require('gun');
var gun = Gun({
file: 'data.json',
@@ -12,10 +10,16 @@ var gun = Gun({
}
});
-var server = http.createServer(function(req, res){
- gun.server(req, res);
+var server = require('http').createServer(function(req, res){
+ if(gun.server(req, res)){
+ return; // filters gun requests!
+ }
+ require('fs').createReadStream(require('path').join(__dirname, req.url)).on('error',function(){ // static files!
+ res.writeHead(200, {'Content-Type': 'text/html'});
+ res.end(require('fs').readFileSync(require('path').join(__dirname, 'index.html'))); // or default to index
+ }).pipe(res); // stream
});
gun.attach(server);
server.listen(port);
-console.log('Server started on port ' + port + ' with /gun');
+console.log('Server started on port ' + port + ' with /gun');
\ No newline at end of file
diff --git a/examples/index.html b/examples/index.html
index 768f47ec..87268da9 100644
--- a/examples/index.html
+++ b/examples/index.html
@@ -1,6 +1,6 @@
-