This commit is contained in:
Mark Nadal 2019-09-10 14:40:39 -07:00
commit 78ae966813
9 changed files with 2029 additions and 1130 deletions

View File

@ -167,7 +167,7 @@ Technically, **GUN is a graph synchronization protocol** with a *lightweight emb
This would not be possible without **community contributors**, big shout out to:
**[ajmeyghani](https://github.com/ajmeyghani) ([Learn GUN Basics with Diagrams](https://medium.com/@ajmeyghani/gundb-a-graph-database-in-javascript-3860a08d873c))**; **[anywhichway](https://github.com/anywhichway) ([Block Storage](https://github.com/anywhichway/gun-block))**; **[beebase](https://github.com/beebase) ([Quasar](https://github.com/beebase/gun-vuex-quasar))**; **[BrockAtkinson](https://github.com/BrockAtkinson) ([brunch config](https://github.com/BrockAtkinson/brunch-gun))**; **[Brysgo](https://github.com/brysgo) ([GraphQL](https://github.com/brysgo/graphql-gun))**; **[d3x0r](https://github.com/d3x0r) ([SQLite](https://github.com/d3x0r/gun-db))**; **[forrestjt](https://github.com/forrestjt) ([file.js](https://github.com/amark/gun/blob/master/lib/file.js))**; **[hillct](https://github.com/hillct) (Docker)**; **[JosePedroDias](https://github.com/josepedrodias) ([graph visualizer](http://acor.sl.pt:9966))**; **[JuniperChicago](https://github.com/JuniperChicago) ([cycle.js bindings](https://github.com/JuniperChicago/cycle-gun))**; **[jveres](https://github.com/jveres) ([todoMVC](https://github.com/jveres/todomvc))**; **[kristianmandrup](https://github.com/kristianmandrup) ([edge](https://github.com/kristianmandrup/gun-edge))**; **[Lightnet](https://github.com/Lightnet)** ([Awesome Vue User Examples](https://glitch.com/edit/#!/jsvuegunui?path=README.md:1:0) & [User Kitchen Sink Playground](https://gdb-auth-vue-node.glitch.me/)); **[lmangani](https://github.com/lmangani) ([Cytoscape Visualizer](https://github.com/lmangani/gun-scape), [Cassandra](https://github.com/lmangani/gun-cassandra), [Fastify](https://github.com/lmangani/fastify-gundb), [LetsEncrypt](https://github.com/lmangani/polyGun-letsencrypt))**; **[mhelander](https://github.com/mhelander) ([SEA](https://github.com/amark/gun/blob/master/sea.js))**; [omarzion](https://github.com/omarzion) ([Sticky Note App](https://github.com/omarzion/stickies)); [PsychoLlama](https://github.com/PsychoLlama) ([LevelDB](https://github.com/PsychoLlama/gun-level)); **[RangerMauve](https://github.com/RangerMauve) ([schema](https://github.com/gundb/gun-schema))**; **[robertheessels](https://github.com/swifty) ([gun-p2p-auth](https://github.com/swifty/gun-p2p-auth))**; **[rogowski](https://github.com/rogowski) (AXE)**; [sbeleidy](https://github.com/sbeleidy); **[sbiaudet](https://github.com/sbiaudet) ([C# Port](https://github.com/sbiaudet/cs-gun))**; **[Sean Matheson](https://github.com/ctrlplusb) ([Observable/RxJS/Most.js bindings](https://github.com/ctrlplusb/gun-most))**; **[Shadyzpop](https://github.com/Shadyzpop) ([React Native example](https://github.com/amark/gun/tree/master/examples/react-native))**; **[sjones6](https://github.com/sjones6) ([Flint](https://github.com/sjones6/gun-flint))**; **[Stefdv](https://github.com/stefdv) (Polymer/web components)**; **[zrrrzzt](https://github.com/zrrrzzt) ([JWT Auth](https://gist.github.com/zrrrzzt/6f88dc3cedee4ee18588236756d2cfce))**; **[xmonader](https://github.com/xmonader) ([Python Port](https://github.com/xmonader/pygundb))**; **[88dev](https://github.com/88dev) ([Database Viewer](https://github.com/88dev/gun-show))**;
**[ajmeyghani](https://github.com/ajmeyghani) ([Learn GUN Basics with Diagrams](https://medium.com/@ajmeyghani/gundb-a-graph-database-in-javascript-3860a08d873c))**; **[anywhichway](https://github.com/anywhichway) ([Block Storage](https://github.com/anywhichway/gun-block))**; **[beebase](https://github.com/beebase) ([Quasar](https://github.com/beebase/gun-vuex-quasar))**; **[BrockAtkinson](https://github.com/BrockAtkinson) ([brunch config](https://github.com/BrockAtkinson/brunch-gun))**; **[Brysgo](https://github.com/brysgo) ([GraphQL](https://github.com/brysgo/graphql-gun))**; **[d3x0r](https://github.com/d3x0r) ([SQLite](https://github.com/d3x0r/gun-db))**; **[forrestjt](https://github.com/forrestjt) ([file.js](https://github.com/amark/gun/blob/master/lib/file.js))**; **[hillct](https://github.com/hillct) (Docker)**; **[JosePedroDias](https://github.com/josepedrodias) ([graph visualizer](http://acor.sl.pt:9966))**; **[JuniperChicago](https://github.com/JuniperChicago) ([cycle.js bindings](https://github.com/JuniperChicago/cycle-gun))**; **[jveres](https://github.com/jveres) ([todoMVC](https://github.com/jveres/todomvc))**; **[kristianmandrup](https://github.com/kristianmandrup) ([edge](https://github.com/kristianmandrup/gun-edge))**; **[Lightnet](https://github.com/Lightnet)** ([Awesome Vue User Examples](https://glitch.com/edit/#!/jsvuegunui?path=README.md:1:0) & [User Kitchen Sink Playground](https://gdb-auth-vue-node.glitch.me/)); **[lmangani](https://github.com/lmangani) ([Cytoscape Visualizer](https://github.com/lmangani/gun-scape), [Cassandra](https://github.com/lmangani/gun-cassandra), [Fastify](https://github.com/lmangani/fastify-gundb), [LetsEncrypt](https://github.com/lmangani/polyGun-letsencrypt))**; **[mhelander](https://github.com/mhelander) ([SEA](https://github.com/amark/gun/blob/master/sea.js))**; [omarzion](https://github.com/omarzion) ([Sticky Note App](https://github.com/omarzion/stickies)); [PsychoLlama](https://github.com/PsychoLlama) ([LevelDB](https://github.com/PsychoLlama/gun-level)); **[RangerMauve](https://github.com/RangerMauve) ([schema](https://github.com/gundb/gun-schema))**; **[robertheessels](https://github.com/swifty) ([gun-p2p-auth](https://github.com/swifty/gun-p2p-auth))**; **[rogowski](https://github.com/rogowski) (AXE)**; [sbeleidy](https://github.com/sbeleidy); **[sbiaudet](https://github.com/sbiaudet) ([C# Port](https://github.com/sbiaudet/cs-gun))**; **[Sean Matheson](https://github.com/ctrlplusb) ([Observable/RxJS/Most.js bindings](https://github.com/ctrlplusb/gun-most))**; **[Shadyzpop](https://github.com/Shadyzpop) ([React Native example](https://github.com/amark/gun/tree/master/examples/react-native))**; **[sjones6](https://github.com/sjones6) ([Flint](https://github.com/sjones6/gun-flint))**; **[Stefdv](https://github.com/stefdv) (Polymer/web components)**; **[zrrrzzt](https://github.com/zrrrzzt) ([JWT Auth](https://gist.github.com/zrrrzzt/6f88dc3cedee4ee18588236756d2cfce))**; **[xmonader](https://github.com/xmonader) ([Python Port](https://github.com/xmonader/pygundb))**;
I am missing many others, apologies, will be adding them soon!

View File

@ -1,156 +1,213 @@
<!DOCTYPE html>
<html>
<head>
<title>Converse</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
<link rel="stylesheet" type="text/css" href="/style.css">
<link href='https://fonts.googleapis.com/css?family=Poiret+One' rel='stylesheet' type='text/css'>
<style>
#converse {
font-size: 16pt;
}
#converse .box {
margin-bottom: 0.2em;
padding: 1em;
border-radius: 0.1em;
}
#converse b:after {
content: " ";
}
#converse li .when {
position: absolute;
top: 0;
right: -2em;
padding: 0.5em 1em;
background: rgba(100%,100%,100%,0.9);
opacity: 0;
}
#converse li:hover .when {
opacity: 1;
right: 0em;
}
.poiret {
font-family: 'Poiret One', sans-serif;
}
.large {
font-size: 200%;
}
#converse .what, #converse .who {
cursor: text;
outline: none;
display: inline;
min-width: 1em;
padding-left: 1px;
}
[contentEditable=true]:empty:not(:focus):before{
content:attr(data-text)
}
#title {
margin-bottom: 0.5em;
}
<head>
<title>Converse</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
<link rel="stylesheet" type="text/css" href="/style.css">
<link href='https://fonts.googleapis.com/css?family=Poiret+One' rel='stylesheet' type='text/css'>
<style>
.chat__heading {
position: fixed;
text-align: center;
z-index: 1;
width: 100%;
margin-top: 0;
margin-bottom: 0;
}
.say {
margin: 0 0 0.4em 0.4em;
padding: 0.2em 0.5em;
}
.chat__form-container {
display: flex;
justify-content: center;
width: 100%;
padding: 10px 20px;
position: fixed;
z-index: 1;
bottom: 0;
}
#name-input {
margin-top: 0.5em;
margin-right: 0.5em;
}
.chat__form {
display: flex;
justify-content: center;
height: 50px;
background-color: white;
border: 2px solid white;
max-width: 900px;
width: 100%;
border-radius: 5px;
}
#message-input {
margin-top: 0.5em;
}
</style>
</head>
<body>
<div id="converse" class="hue2 page">
<div class="pad">
<div id='title' class="poiret large rubric whitet">Have a Conversation...</div>
<div>
<ul>
<li class="none"></li>
</ul>
.chat__name-input {
flex: 1;
padding: 10px;
}
<form class="white huet2 box">
<div>
<div class="say hue2 right whitet box act">say</div>
<b id="name-input" class="jot left who" contenteditable="true" data-text="Name"></b>
<p id="message-input" class="jot left what" contenteditable="true" data-text="Write a message..."></p>
</div>
</form>
.chat__message-input {
flex: 5;
padding: 10px;
}
<div class="model">
<li class="white huet2 box">
<b class="who"></b>
<p class="what"></p>
<span class="sort none">0</span>
<div class="when"></div>
</li>
</div>
</div>
</div>
</div>
.chat__submit {
padding: 10px;
color: white;
border-radius: 5px;
}
<script src="/jquery.js"></script>
<script src="/gun.js"></script>
<script src="/gun/nts.js"></script>
<script>
var gun = Gun(location.origin + '/gun');
var chat = gun.get('converse/' + location.hash.slice(1));
.chat__submit:hover::after {
background-color: rgba(0,0,0,0.2);
}
$("form .say").on('click', submit);
$("form .what").on('keydown', enter);
function enter(e){
if(e.which !== 13){ return }
submit(e);
}
function submit(e){
e.preventDefault();
.chat__submit:focus::after {
background-color: rgba(0,0,0,0.2);
}
var msg = {when: Gun.time.is()};
.chat__submit::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
border-radius: 5px;
transition: background-color 0.3s;
background-color: rgba(0,0,0,0);
}
msg.who = $('form .who').text();
if(!msg.who){
msg.who = 'user' + Gun.text.random(3);
$('form .who').text(msg.who);
}
.chat__message-list {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
overflow-y: auto;
padding: 60px 20px;
width: 100%;
background-color: rgba(0, 0, 0, 0.2);
min-height: 100vh;
}
msg.what = $('form .what').text();
if(!msg.what){ return }
.chat__message {
display: flex;
flex-wrap: wrap;
margin-bottom: 10px;
padding: 10px;
border-radius: 5px;
width: 100%;
position: relative;
max-width: 900px;
}
chat.set(msg);
$('form .what').text('');
}
.chat__name {
margin-right: 20px;
}
chat.map().val(function(msg, id){
if(!msg){ return }
var ul = $('ul');
var last = sort(msg.when, ul.children('li').last());
.chat__when {
position: absolute;
top: 0;
right: 2em;
padding: 10px;
background: rgba(100%, 100%, 100%, 0.9);
opacity: 0;
border-radius: 5px;
}
var li = $("#msg-" + id)[0]; // grab if exists
if(!li){
li = $('.model li').clone(true) // else create it
.attr('id', 'msg-' + id)
.insertAfter(last);
}
.chat__message:hover .chat__when {
opacity: 1;
right: 0em;
}
// bind the message data into the UI
li = $(li);
li.find('.who').text(msg.who);
li.find('.what').text(msg.what);
li.find('.sort').text(msg.when);
@media (max-width: 567px) {
.chat__heading {
font-size: 30px;
}
}
</style>
</head>
var time = new Date(msg.when);
li.find('.when').text(time.toDateString() + ', ' + time.toLocaleTimeString());
<body>
<div class="chat hue2 page">
<h2 id='title' class="chat__heading hue2 whitet">Have a Conversation...</h2>
<ul class="chat__message-list">
<li class="none"></li>
</ul>
$('html, body').stop(true, true)
.animate({scrollTop: ul.height()});
});
<div class="chat__form-container hue2">
<form class="chat__form">
<label for="name-input" class="visually-hidden">Name</label>
<input id="name-input" class="chat__name-input" placeholder="Name"></input>
<label for="message-input" class="visually-hidden">Message</label>
<input id="message-input" class="chat__message-input" placeholder="Write a message..."></input>
<button class="chat__submit say hue2">say</button>
</form>
</div>
function sort(num, li){ return parseFloat(num) >= parseFloat($(li).find('.sort').text() || -Infinity)? li : sort(num, li.prev()) }
</script>
</body>
</html>
<div class="model">
<li class="chat__message white huet2 box">
<b class="chat__name"></b>
<p class="chat__message-text"></p>
<span class="sort none">0</span>
<div class="chat__when"></div>
</li>
</div>
</div>
<script src="/jquery.js"></script>
<script src="/gun.js"></script>
<script src="/gun/nts.js"></script>
<script>
var gun = Gun(location.origin + '/gun');
var chat = gun.get('converse/' + location.hash.slice(1));
$(".chat__submit").on('click', submit);
$(".chat_form").on('keydown', enter);
function enter(e) {
if (e.which !== 13) { return }
submit(e);
}
function submit(e) {
e.preventDefault();
var msg = { when: Gun.time.is() };
msg.who = $('.chat__name-input').val();
if (!msg.who) {
msg.who = 'user' + Gun.text.random(3);
$('.chat__name-input').val(msg.who);
}
msg.what = $('.chat__message-input').val();
if (!msg.what) { return }
chat.set(msg);
$('.chat__message-input').val('').focus();
}
chat.map().val(function (msg, id) {
if (!msg) { return }
var messageList = $('.chat__message-list');
var last = sort(msg.when, messageList.children('li').last());
var li = $("#msg-" + id)[0]; // grab if exists
if (!li) {
li = $('.model li').clone(true) // else create it
.attr('id', 'msg-' + id)
.insertAfter(last);
}
// bind the message data into the UI
li = $(li);
li.find('.chat__name').text(msg.who);
li.find('.chat__message-text').text(msg.what);
li.find('.sort').text(msg.when);
var time = new Date(msg.when);
li.find('.chat__when').text(time.toDateString() + ', ' + time.toLocaleTimeString());
$('html, body').stop(true, true)
.animate({ scrollTop: messageList.height() });
});
function sort(num, li) { return parseFloat(num) >= parseFloat($(li).find('.sort').text() || -Infinity) ? li : sort(num, li.prev()) }
</script>
</body>
</html>

View File

@ -313,4 +313,15 @@ ul, li {
} @keyframes joy {
0% {background-position: 0 0;}
100% {background-position: -2800px 0;}
}
}
.visually-hidden {
border: 0;
clip: rect(1px, 1px, 1px, 1px);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}

View File

@ -1,83 +1,151 @@
<!DOCTYPE html>
<html>
<head>
<title>Think</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
<link rel="stylesheet" type="text/css" href="/style.css">
</head>
<body>
<div id="think" class="hue page">
<link href='https://fonts.googleapis.com/css?family=Alegreya+Sans:300italic' rel='stylesheet' type='text/css'>
<style>
#think {
font-size: 24pt;
font-size: 6vmin;
font-family: 'Alegreya Sans', sans-serif;
color: white;
}
#think li {
width: 90%;
margin-top: 0.3em;
border-bottom: 1px dashed white;
}
#think .add {
width: 1em;
height: 1em;
line-height: 1em;
padding: 0.5em;
font-family: Tahoma, arial;
text-align: center;
border-radius: 50%;
}
#think ul, #think li {
list-style-type: circle;
margin-left: 0.5em;
}
</style>
<div class="pad whitet" style="width: 75%;">
<div style="margin-top: 2%;">
<div class="rubric left center">Add a Thought...</div>
<a href="#" class="right huet white act add">+</a>
</div>
<ul>
</ul>
</div>
<script src="/jquery.js"></script>
<script src="/gun.js"></script>
<script src="/gun/nts.js"></script>
<script>
// Check out the interactive tutorial
// for how to build a simplified version
// of this example: https://scrimba.com/c/cW2Vsa
var gun = Gun(location.origin+'/gun');
var think = gun.get('think/' + location.hash.slice(1));
var typing, throttle;
$('.add').on('click', function(){
$('<li>').attr('contenteditable', true).prependTo('ul');
});
$(document).on('keyup', "[contenteditable=true]", function(){
var li = $(this), id = li.attr('id');
if(!id){
li.attr('id', id = Gun.text.random());
}
typing = id;
clearTimeout(throttle);
throttle = setTimeout(function(){
think.get(id).put(li.text());
typing = false;
},10);
});
think.map().on(function(thought, id){
var li = $('#'+id)[0] || $('<li>').attr('id', id).attr('contenteditable', true).prependTo('ul');
if(thought){
if(id === typing){ return }
$(li).text(thought);
} else {
$(li).hide();
}
});
</script>
</div>
</div>
</body>
<head>
<title>Think</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
<link rel="stylesheet" type="text/css" href="/style.css">
<link href='https://fonts.googleapis.com/css?family=Alegreya+Sans:300italic' rel='stylesheet' type='text/css'>
<style>
.thought {
font-family: 'Alegreya Sans', sans-serif;
}
.thought__heading {
text-align: center;
margin-top: 0;
margin-bottom: 0;
color: white;
}
.thought__form-container {
position: fixed;
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 10px 20px;
top: 0;
z-index: 1;
}
.thought__item {
width: 100%;
max-width: 900px;
}
.thought__input {
flex: 1;
font-family: 'Alegreya Sans', sans-serif;
font-size: 25px;
font-weight: 500;
padding: 15px;
width: 100%;
margin-bottom: 10px;
background-color: white;
border-radius: 5px;
}
.thought__add {
width: 30px;
height: 30px;
font-family: Tahoma, arial;
text-align: center;
border-radius: 50%;
background-color: white;
font-size: 25px;
font-weight: 700;
}
.thought__add:hover::after {
background-color: rgba(0,0,0,0.2);
}
.thought__add:focus::after {
background-color: rgba(0,0,0,0.2);
}
.thought__add::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
border-radius: 50%;
transition: background-color 0.3s;
background-color: rgba(0,0,0,0);
}
.thought__list {
list-style-type: circle;
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
overflow-y: auto;
padding: 90px 20px;
width: 100%;
background-color: rgba(0, 0, 0, 0.2);
min-height: 100vh;
}
@media (max-width: 567px) {
.thought__heading {
font-size: 30px;
}
}
</style>
</head>
<body>
<div class="thought hue page">
<div class="thought__form-container hue">
<h2 id='title' class="thought__heading hue">Add a thought...</h2>
<button class="thought__add say huet">
<span aria-hidden="true">+</span>
<span class="visually-hidden">Add thought</span>
</button>
</div>
<ul class="thought__list">
</ul>
</div>
<script src="/jquery.js"></script>
<script src="/gun.js"></script>
<script src="/gun/nts.js"></script>
<script>
// Check out the interactive tutorial
// for how to build a simplified version
// of this example: https://scrimba.com/c/cW2Vsa
var gun = Gun(location.origin + '/gun');
var think = gun.get('think/' + location.hash.slice(1));
var thoughtItemStr = function(id) { return '<li class="thought__item"><label class="visually-hidden" for="' + id + '">Thought</label><input id="' + id + '" class="thought__input huet"><li/>'}
var typing, throttle;
$('.thought__add').on('click', function () {
$(thoughtItemStr('')).prependTo('.thought__list').find('.thought__input').focus();
});
$(document).on('keyup', '.thought__input', function () {
var input = $(this), id = input.attr('id');
if (!id) {
input.attr('id', id = Gun.text.random());
}
typing = id;
clearTimeout(throttle);
throttle = setTimeout(function () {
think.get(id).put(input.val());
typing = false;
}, 10);
});
think.map().on(function (thought, id) {
var li = $('#' + id).parent()[0] || $(thoughtItemStr(id)).prependTo('.thought__list');
if (thought) {
if (id === typing) { return }
$(li).find('.thought__input').val(thought);
} else {
$(li).hide();
}
});
</script>
</div>
</body>

124
lib/promise.js Normal file
View File

@ -0,0 +1,124 @@
/* Promise Library v1.0 for GUN DB
* Turn any part of a gun chain into a promise, that you can then use
* .then().catch() pattern.
* In normal gun doing var item = gun.get('someKey'), gun returns a reference
* to the someKey synchroneously. Using a reference is quite helpful in making
* graph structures, so I have chosen to follow the following paradigm.
* Whenever a promise is resolved, gun will return an object of data, I will
* wrap that data in an object together with the reference like so:
* {ref: gunRef, data: data}.
* This code is freely given in the spirit of open source MIT license.
* Author: Jachen Duschletta / 2019
*/
/*
* Function promOnce
* @param limit - due to promises resolving too fast if we do not set a timer
* we will not be able receive any data back from gun before returning the promise
* works both following a Chain.get and a Chain.map (limit only applies to map)
* If no limit is chosen, defaults to 100 ms (quite sufficient to fetch about 2000 nodes or more)
* @param opt - option object
* @return {ref: gunReference, data: object / string (data), key: string (soulOfData)}
*/
Gun.chain.promOnce = async function (limit, opt) {
var gun = this, cat = gun._;
if(!limit){limit = 100}
if(cat.subs){
var array = [];
gun.map().once((data, key)=>{
var gun = this;
array.push(new Promise((res, rej)=>{
res({ref: gun, data:data, key:key});
})
)
}, opt);
await sleep(limit);
return Promise.all(array)
} else {
return (new Promise((res, rej)=>{
gun.once(function (data, key) {
var gun = this;
res({ref:gun,data:data,key:key});
}, opt);
}))
}
var chain = gun.chain();
return chain;
}
function sleep (limit) {
return (new Promise((res, rej)=>{
setTimeout(res, limit);
}))
}
/*
* Function promPut
* @param item (string / object) - item to be put to that key in the chain
* @param opt - option object
* @return object - Returns an object with the ref to that node that was just
* created as well as the 'ack' which acknowledges the put was succesful
* object {ref: gunReference, ack: acknowledgmentObject}
* If put had an error we can catch the return via .catch
*/
Gun.chain.promPut = async function (item, opt) {
var gun = this;
return (new Promise((res, rej)=>{
gun.put(item, function(ack) {
if(ack.err){rej(ack.err)}
res({ref:gun, ack:ack});
}, opt);
}))
}
/*
* Function promSet
* @param item (string / object) - item to be set into a list at this key
* @param opt - option object
* @return object - Returns object with the ref to that node that was just
* created as well as the 'ack' which acknowledges the set was succesful
* object {ref: gunReference, ack: acknowledgmentObject}
* If set had an error we can catch the return via .catch
*/
Gun.chain.promSet = async function(item, opt){
var gun = this, soul;
var cb = cb || function(){};
opt = opt || {}; opt.item = opt.item || item;
return (new Promise(async function (res,rej) {
if(soul = Gun.node.soul(item)){ item = Gun.obj.put({}, soul, Gun.val.link.ify(soul)) }
if(!Gun.is(item)){
if(Gun.obj.is(item)){;
item = await gun.back(-1).get(soul = soul || Gun.node.soul(item) || gun.back('opt.uuid')()).promPut(item);
item = item.ref;
}
res(gun.get(soul || (Gun.state.lex() + Gun.text.random(7))).promPut(item));
}
item.get(function(soul, o, msg){
var ack = {};
if(!soul){ rej({ack:{err: Gun.log('Only a node can be linked! Not "' + msg.put + '"!')}} ) }
gun.put(Gun.obj.put({}, soul, Gun.val.link.ify(soul)), cb, opt);
},true);
res({ref:item, ack:{ok:0}});
}))
}
/*
* Function promOn
* @param callback (function) - function to be called upon changes to data
* @param option (object) - {change: true} only allow changes to trigger the callback
* @return - data and key
* subscribes callback to data
*/
Gun.chain.promOn = async function (callback, option) {
var gun = this;
return (new Promise((res, rej)=>{
gun.on(function (data, key){
callback(data, key);
res(data, key);
}, option);
}));
}

View File

@ -55,4 +55,4 @@ Gun.on('opt', function(root){
stats.gap = {};
}, 1000 * 15);
Object.keys = Object.keys || function(o){ return Gun.obj.map(o, function(v,k,t){t(k)}) }
});
});

View File

@ -1,16 +1,21 @@
var Gun = (typeof window !== "undefined")? window.Gun : require('../gun');
// Returns a gun reference in a promise and then calls a callback if specified
Gun.chain.promise = function(cb) {
var gun = this, cb = cb || function(ctx) { return ctx };
return (new Promise(function(res, rej) {
gun.once(function(data, key){
res({put: data, get: key, gun: this});
res({put: data, get: key, gun: this}); // gun reference is returned by promise
});
})).then(cb);
})).then(cb); //calling callback with resolved data
};
Gun.chain.then = function(cb) {
return this.promise(function(res){
return cb? cb(res.put) : res.put;
});
};
// Returns a promise for the data, key of the gun call
Gun.chain.then = function() {
var gun = this;
return (new Promise((res, rej)=>{
gun.once(function (data, key) {
res(data, key); //call resolve when data is returned
})
}))
};

2436
sea.js

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@
var epriv = pair.epriv;
var ecdhSubtle = shim.ossl || shim.subtle;
var pubKeyData = keysToEcdhJwk(pub);
var props = Object.assign(S.ecdh, { public: await ecdhSubtle.importKey(...pubKeyData, true, []) });
var props = Object.assign({ public: await ecdhSubtle.importKey(...pubKeyData, true, []) },S.ecdh);
var privKeyData = keysToEcdhJwk(epub, epriv);
var derived = await ecdhSubtle.importKey(...privKeyData, false, ['deriveKey']).then(async (privKey) => {
// privateKey scope doesn't leak out from here!
@ -47,4 +47,4 @@
}
module.exports = SEA.secret;