Compare commits

...

892 Commits

Author SHA1 Message Date
leo
ff4bf9293c
docs: remove repetitive words (#1392)
Signed-off-by: RiceChuan <lc582041246@gmail.com>
2025-03-08 11:15:39 -08:00
brad winter
0c423c999c
remove redundant return statement (#1394)
* comment out redundant return;

* remove redundant return
2025-03-08 11:13:14 -08:00
Mark Nadal
e3a5a52506
Update README.md 2024-11-29 15:52:33 -08:00
Mark Nadal
9a0e259a9b
Merge branch 'deploys' into master 2024-11-23 17:51:50 -08:00
Mark Nadal
5305f01011 Merge branch 'master' of http://github.com/amark/gun 2024-11-23 17:47:30 -08:00
Mark Nadal
90b88959d0 universal notification system 2024-11-23 17:47:13 -08:00
carlin978
7cc4cce1a3
Update STUN servers (#1381)
Commented out sipgate.net STUN server.
Added Cloudflare STUN server.
2024-07-23 05:56:40 -07:00
Andreas Heissenberger
03735dc09c
fix: ERROR: Radisk needs store.put interface (#1374) 2024-04-15 12:42:03 -07:00
Malcolm Blaney
1c095b13e9
Check atom exists in graph when deciding to read from disk (#1371) 2024-04-04 11:01:15 -07:00
Mark Nadal
faff9efaca Merge branch 'master' of http://github.com/amark/gun 2024-03-11 13:55:50 -07:00
Mark Nadal
7a2767a763 webrtc accept getUserMedia streams as peer 2024-03-11 13:50:17 -07:00
Simardeep Singh
c47800f4d8
update SECURITY.md file and change the versions to 0.2020.x (#1365) 2024-02-06 20:21:18 -08:00
Bradley Matusiak
e584906a65
Loading fix (#1356)
* does this load better

* check window.Gun too in rfs
2024-02-05 03:10:35 -08:00
Bradley Matusiak
3070627c83
... works (#1357) 2024-02-05 03:06:38 -08:00
Simardeep Singh
3bd809818f
Create SECURITY.md (#1364) 2024-02-05 03:05:11 -08:00
mimiza
61df63c96e
Fix SEA certificate verification, allow multiple pubs (#1358) 2024-02-05 03:01:31 -08:00
Bradley Matusiak
7eb6d38cfc
quick-fix (#1355) 2024-01-17 10:47:07 -08:00
Mark Nadal
638c2c3c23 have unbuild function wrap to prevent scope leaks & allow RETURN hehehe so I can reject @bmatusiak 's lS change O:) O:) I love you you're a hero!
later with @bmatusiak check sea.then for '../gun.js' vs '../' vs ...
note: src/index -> core.js
TODO: something about WebRTC candidates hitting ack decrement limits?
2024-01-17 10:13:00 -08:00
Bradley Matusiak
5c52df2eee
react-native detection, and load needed shims (#1349)
* react-native detection

* added lib mobile

* changed back to gun. for another solution
2024-01-17 09:49:52 -08:00
Bradley Matusiak
7cb337c158
add a way to select stats file from url (#1351) 2024-01-17 09:46:48 -08:00
Bradley Matusiak
e07c9b21ec
sea blobs! (#1353)
* sea blobs!

* and null origins

* null fix

* null check is last
2024-01-17 09:45:09 -08:00
Mark Nadal
203bd40932 cleaned up Book results & sorting & caching 2024-01-16 21:08:14 -08:00
Mark Nadal
3688ba1cc6 bump path 2024-01-16 03:40:40 -08:00
Mark Nadal
78a40daf46 RAD & Book promoted! + buggy example: test/rad/book.html 2024-01-16 02:54:07 -08:00
Mark Nadal
d7f19473a4 book & rad APIs stabilizing 2024-01-15 16:46:18 -08:00
Mark Nadal
dc5f90ad61 Merge branch 'master' of http://github.com/amark/gun 2023-12-28 16:07:56 -08:00
Mark Nadal
2b4f750392 is ??? this a MVP of book & rad ???? thanks to @rogowski 2023-12-28 16:07:51 -08:00
Bradley Matusiak
c440a7cc88
update src/index (#1254)
* update src/index

* update

* src/index fix

* added src/core
2023-12-14 18:11:32 -08:00
Jay Byoun
6dfaaf229b
add one click deploy to readme (#1342) 2023-11-25 15:59:35 -08:00
Bradley Matusiak
5ff33b7ac3
WS ws.path fix (#1343)
* Update wire.js

* Update wire.js

* Update wire.js
2023-11-25 15:54:46 -08:00
Mark Nadal
efb2552997 encode objects 2023-11-17 03:44:20 -08:00
Mark Nadal
5d3cbaca19 Merge branch 'master' of http://github.com/amark/gun 2023-11-10 04:37:57 -08:00
Mark Nadal
96b1402a65 yay format change 2023-11-10 04:24:26 -08:00
Mark Nadal
0251de11ec
Update README.md 2023-10-19 11:43:47 -07:00
Anton
1862fb69fd
Remove unused imports (#1337) 2023-10-17 17:53:51 -07:00
Mark Nadal
f882b86889
Thanks Jason Stallings @octalmage !!! 2023-05-26 19:23:47 -07:00
ritchia1
7f6a0b27c3
Support variable number of auth retry attempts through opt.retries (#1325)
Maintain default to 9 to ensure backwards compatibility
2023-05-20 20:47:39 -07:00
ritchia1
0cb9706393
Fix opt.s3.fakes3 parsing issue (#1318)
* Fix opt.s3.fakes3 parsing issue

* Fix second typo within if block
2023-05-12 11:33:40 -07:00
Mark Nadal
4c01db9a67 up mob 2023-04-29 12:19:21 -07:00
Mark Nadal
1304ef90e8 reuse 2023-04-28 15:24:40 -07:00
Mark Nadal
8c4d38e30e oops 2023-04-28 04:13:56 -07:00
Mark Nadal
30eff267ea nope need curl lol 2023-04-28 04:08:51 -07:00
Mark Nadal
580058056f reduce? 2023-04-28 03:35:51 -07:00
Mark Nadal
bfedfc027c sleepy ugh 2023-04-28 02:57:08 -07:00
Mark Nadal
bf1565398b ugh 2023-04-28 02:53:07 -07:00
Mark Nadal
8b1f055cd1 auto update 2023-04-28 02:26:16 -07:00
Mark Nadal
ca0e7e35ae trim 2023-04-26 02:03:32 -07:00
Mark Nadal
e15416ff2d longer 2023-04-26 01:27:48 -07:00
Mark Nadal
0e7121b8f4 finally! 2023-04-26 01:13:17 -07:00
Mark Nadal
2183e6acdf log 2023-04-25 20:02:28 -07:00
Mark Nadal
48b5a0e765 what about now? 2023-04-25 19:41:34 -07:00
Mark Nadal
1ddf797fff reverse? 2023-04-25 15:42:34 -07:00
Mark Nadal
2afde8db4a hmm 2023-04-25 04:18:46 -07:00
Mark Nadal
c6b9fa8d13 back? 2023-04-25 03:44:38 -07:00
Mark Nadal
c9283d8fa6 bump 2023-04-25 03:16:21 -07:00
Mark Nadal
58f9135f6b again 2023-04-25 03:06:35 -07:00
Mark Nadal
b79e5bbad7 test install 2023-04-25 02:29:52 -07:00
Mark Nadal
b14d5da558
Thank you Murage Martin @murageyun for donating!!! 2023-04-07 00:16:19 -07:00
Sharlon Balbalosa
9433e5ca06
fix: change type to string instead of literal newPassword (#1309) 2023-03-13 00:00:21 -07:00
Adriano Rogowski
73b661a6a5 Book passing encode/decode test. 2023-03-02 19:54:30 -03:00
Dimitris Apostolou
9e616ea3a9
Fix typos (#1299) 2023-02-25 17:09:54 -08:00
Mark Nadal
1bdab7394a Book formatting + more tests 2023-02-23 19:07:43 -08:00
Mark Nadal
d732a9e48b fix page size transfer 2023-02-17 19:36:15 -08:00
Mark Nadal
c274977eb6 Merge branch 'master' of http://github.com/amark/gun
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
2023-02-17 18:28:04 -08:00
Mark Nadal
81a29cdd60 fix book mismatch between parse & parseless 2023-02-17 18:26:25 -08:00
Mark Nadal
713380ccd2
opt.env = process.env 2023-02-14 02:03:43 -08:00
Mark Nadal
6f6d8b533d Merge branch 'master' of http://github.com/amark/gun 2023-01-30 15:29:43 -08:00
Mark Nadal
0665787e2b thanks @rogowski book test read/memory/disk variations 2023-01-30 15:29:30 -08:00
Anton
2ee0bed0c1
Allow Dockerfile to auto-update Node version (#1303) 2023-01-24 15:53:52 -08:00
Mark Nadal
9abebd7673 rad fixed dup text, perf, read + tests. 2023-01-24 15:51:26 -08:00
Mark Nadal
8778ca4138 basic book test + some failing ones (cause its so early) 2023-01-19 15:04:56 -08:00
Mark Nadal
eca0451c4e wrapper for browser tests of book @rogowski 2023-01-19 14:35:24 -08:00
Mark Nadal
9ceb86b208 revert tower tying while publishing AXE fix 2022-12-23 01:11:13 -08:00
Mark Nadal
47c070932a revert & make axe not skip if other props 2022-12-21 06:28:20 -08:00
Mark Nadal
73d54b6271 toString must be stringy! 2022-11-30 23:27:51 -08:00
Adriano Rogowski
2d3993125d fix .off() 2022-10-27 20:14:14 -03:00
Martti Malmi
ad8e67e3c3
make SEA work in service worker (no window obj) (#1282) 2022-10-18 22:45:39 -07:00
Mark Nadal
6d7e980b5f silly book. Is this correct? 2022-08-25 14:07:35 -07:00
Mark Nadal
e9439daa51 THANK YOU NORMAN! @nsreed 2022-08-25 14:06:25 -07:00
Norman Reed
94c6a97ae7
Rad book tests (#1274)
* allow unset to unset user nodes

* add options to type declarations for put and set

* roll back unset.js changes

* work toward radisk3/book unit testing

Co-authored-by: Norman Reed <norman.s.reed@gmail.com>
2022-08-25 12:05:54 -07:00
Mark Nadal
f25747443e fix gun <-> axe mismatch on uninit data 2022-08-21 14:06:57 -07:00
Mark Nadal
680f871aa3 PANIC 4: AXE get subscriptions 2022-08-13 14:01:54 -07:00
Mark Nadal
b125d8d150 Merge branch 'master' of http://github.com/amark/gun
chill!
2022-08-13 12:01:32 -07:00
Martti Malmi
7123207c66
Panic tests for rod & radix.js try / catch (#1269)
* try/catch radix.js

* rod test/panic/chat.js

rod test/panic/holy-grail.js

rod panic tests
2022-08-13 11:58:00 -07:00
Mark Nadal
89b24d3862 subscribe only on backpropagation 2022-08-12 18:17:01 -07:00
Mark Nadal
d5c8a02980 test undo tmp 2022-08-10 16:56:05 -07:00
Mark Nadal
451c33a69a reduce not-found acks if via/relay has found ## 2022-08-10 16:21:06 -07:00
Mark Nadal
07b30ed602 unbuild - PUBLISHED! 1238 2022-08-09 15:33:22 -07:00
I001962
d06359f45c
SEA - Update sea.work to support hex (#1266)
This was would encode to hex:
```var data = "hello world";
var hash1 = await SEA.work(data, null, null, {name: "SHA-256",encode:
"hex"});
```
but this would not verify correctly:
gun.get('#').get(hash1).put(data);

This PR will first check base64 (current functionality) and if it fails now it will fall back and check hex.
2022-08-09 15:24:29 -07:00
Mark Nadal
cedf9b8809 stupid cache miss kills me all + update examples 2022-08-09 15:16:58 -07:00
Mark Nadal
e840df43af note/fix 2022-08-03 16:33:16 -07:00
Mark Nadal
ef59ea185c mark fails at JSON again 2022-08-03 14:52:44 -07:00
Mark Nadal
233d2612d1 fix login maybe? AGAIN? 2022-08-03 14:13:17 -07:00
Mark Nadal
cfad98b0c6 it's alive!!!! 2022-08-03 13:59:12 -07:00
Mark Nadal
3dbdd4e43c is this good enough? 2022-08-02 16:45:03 -07:00
Mark Nadal
db99ad65fb argh, axe needed skip reset. + always relay up for now 2022-08-02 16:42:16 -07:00
Mark Nadal
5efedd7308 fix peer sharing 2022-07-31 20:22:20 -07:00
Mark Nadal
8f6322efc0 browser axe remember, random, fallback. 2022-07-31 17:26:14 -07:00
Mark Nadal
7ec5805d8d fix log 2022-07-31 17:14:41 -07:00
Mark Nadal
faff04ff63 floor >> 2022-07-31 15:54:26 -07:00
Mark Nadal
3749bf74cf perf seemed worth it to add MC as sI 2022-07-31 15:53:45 -07:00
Mark Nadal
027edcb54e requery - oye, hopefully safer 2022-07-31 15:51:01 -07:00
Mark Nadal
cdfe87c2b6 fix ws error/reconnect ordering 2022-07-31 15:44:25 -07:00
Joe Thielen
9ca6e59d32
Removed bad dir references (#1263) 2022-07-19 00:26:54 -07:00
Mark Nadal
8b52cbb2cb
oh, try export 2022-07-14 17:27:31 -07:00
Mark Nadal
e4e703c957
Create radisk3.js 2022-07-14 16:54:01 -07:00
Mark Nadal
d6d50040dc
Create book.js 2022-07-14 16:42:17 -07:00
Bradley Matusiak
809eae4f98
dont block stop chain because of deprecated nts (#1252) 2022-07-12 20:57:27 -07:00
Mark Nadal
081931a6d4
Thanks @gabriellemon Gabriel for donating! :) 2022-06-26 04:02:39 -07:00
Mark Nadal
5687bddc90
Thank you @b-lack Gerrit Balindt for sponsoring! 2022-06-18 17:05:06 -07:00
Mark Nadal
ac52811880 put sampling, mob, tests. 2022-06-06 18:20:18 -07:00
Mark Nadal
19cb91ee4e Merge branch 'master' of http://github.com/amark/gun
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
2022-06-06 18:14:10 -07:00
Mark Nadal
46d926e831 put sampling, mob, tests 2022-06-06 18:08:43 -07:00
Bradley Matusiak
9c9a5fd293
Lex builder (#1249)
* lex builder

* updated lex builder

* added args to map

* added match to lex-builder

* update match

* moved matach and gave Lex to Global Gun

* fix match in lex
2022-06-06 15:04:29 -07:00
Bradley Matusiak
87652467b5
chain fork (#1247)
* chain fork

* removed test

* removed unbuild

* moved chain fork to libs folder
2022-06-06 15:02:36 -07:00
Bradley Matusiak
de46cccc1e
Unbuild update (#1248)
* unbuild gun

* unbuild sea
2022-06-03 12:27:38 -07:00
abenezermario
fa1e1578f7
fixed s3 (#1245) 2022-05-30 20:06:43 -07:00
Bradley Matusiak
42720c57ea
unbuild is no longer silent (#1239)
* prepare to sync gun lib unbuild on npm install

* Update unbuild.js

* Update package.json

* Update package.json
2022-05-30 20:02:25 -07:00
Daniel Raeder
8facbcc095
Adds Heroku deploy unit testing thanks to @bmatusiak (#1244)
* Add Heroku deploy unit testing thanks to @bmatusiak

1243.js is a reference to PR #1243

* Update 1243.js

Corrected some indentation, removed unnecessary require
2022-05-30 20:00:14 -07:00
Daniel Raeder
a634b37b1a
Heroku fixes (#1243)
* Update app.json

Removed 'stack' parameter to enable using the latest Heroku stack

* Update package.json

Remove prepare parameter to fix Heroku deploys
2022-05-29 20:00:52 -07:00
Mark Nadal
525d834784 Merge branch 'master' of http://github.com/amark/gun 2022-05-29 19:43:31 -07:00
Mark Nadal
2beb258b4c OK start 2022-05-29 19:43:24 -07:00
Shaun Hamilton
39337338bd
fix(npm): change glob preventing GunDataNode.d.ts (#1241) 2022-05-25 10:25:33 -07:00
Bradley Matusiak
c85cb4365d
webpack example (#1240) 2022-05-24 14:08:18 -07:00
Bradley Matusiak
210a5834c6
prepare to sync gun lib unbuild on npm install (#1237) 2022-05-23 17:14:25 -07:00
Mark Nadal
55682b6f4b bump (ok ack + webrtc) @Draeder yay thanks! 2022-05-18 18:36:35 -07:00
Mark Nadal
7335f8c866 Merge branch 'master' of http://github.com/amark/gun 2022-05-18 18:10:39 -07:00
Mark Nadal
904b2f8e7f ok ack + webrtc 2022-05-18 18:10:36 -07:00
Bradley Matusiak
ced9cde41b
websocket ../index to ./index (#1235)
* Update sea.js

* Update auth.js

* Update sea.js

* Update auth.js

* Update rs3.js

* added test for login via {pub}

* gh page build

* fix index path in websocket plugin
2022-05-15 18:07:35 -07:00
Mark Nadal
94ab05b032 Merge branch 'master' of http://github.com/amark/gun 2022-05-08 20:34:16 -07:00
Mark Nadal
589a7784dc PANIC tests + AXE get dedup + fix DAM add by id 2022-05-08 20:34:06 -07:00
George Shammas
440bbffb73
lib/ison: Use setTimeout instead of setImmediate. Allows the use of indexDB in browsers (#1226) 2022-05-05 13:13:18 -07:00
Bradley Matusiak
e3eaf5e268
Allow {pair.pub} to login with pass (#1233)
* Update sea.js

* Update auth.js

* Update sea.js

* Update auth.js

* Update rs3.js

* added test for login via {pub}

* gh page build
2022-04-29 16:26:26 -07:00
Mark Nadal
a092f5a725 @rococtz fix + @draeder AXE tests. Force. 2022-04-26 23:20:34 -07:00
Mark Nadal
8f79ff7bb0 Merge branch 'master' of http://github.com/amark/gun 2022-04-26 23:18:54 -07:00
Mark Nadal
ebe6f0cf3b @rococtz fix + @dreader AXE tests 2022-04-26 23:12:52 -07:00
George Shammas
9d94b433d0
export SEA type information (#1224) 2022-04-02 16:26:08 -07:00
Mark Nadal
ff3c4f6e69
Thank you @JacobMillner for donating!!! 2022-04-02 10:07:23 -07:00
Mark Nadal
f062fc330b
Thanks Hunter Owens @howens for backing! 2022-03-23 00:28:37 -07:00
Mark Nadal
4f19440262 axe tweaks 2022-03-23 00:10:57 -07:00
Mark Nadal
e4bb977d5d
Thanks @wayjake for https://wallie.io/ supporting GUN! 2022-03-17 21:49:30 -07:00
Thorsten Zoerner
0e8b4549df
Update axe.js (#1222)
Should solve uncaught exception:
```
error] TypeError: Cannot read properties of undefined (reading 'lack')
    at Function.GET.turn (/root/.node-red/node_modules/gun/lib/axe.js:42:20)
    at Timeout._onTimeout (/root/.node-red/node_modules/gun/lib/axe.js:57:42)
    at listOnTimeout (node:internal/timers:559:17)
    at processTimers (node:internal/timers:502:7)
```

That happens in some node environments from time to time.
2022-03-17 19:00:10 -07:00
Mark Nadal
f6b65c8e7e Merge branch 'master' of http://github.com/amark/gun 2022-03-16 17:04:21 -07:00
Mark Nadal
5ea98f48e3 fix open, warn if too fast 2022-03-16 17:02:38 -07:00
Mark Nadal
41c2f64ef2
github debug stats 2022-03-13 13:39:13 -07:00
Mark Nadal
2ff35aa316 Merge branch 'master' of http://github.com/amark/gun 2022-03-11 05:17:06 -08:00
Mark Nadal
c4a613a971 json is lame 2022-03-11 05:17:01 -08:00
Mark Nadal
2bbbe36e13 prep for stash 2022-03-06 04:53:15 -08:00
Malted
532b59b098
Remove erroneous apostrophe (#1213) 2022-02-27 04:16:37 -08:00
Orimay
d53d157f19
New GUN typings (#1205)
* New GUN typings

* Fixing comments

* Gun schema is now supported

Co-authored-by: dbaranov <dbaranov@bellintegrator.com>
2022-02-18 23:17:41 -08:00
Anton W
1051e477ba
Fix offer payload (#1210) 2022-02-18 23:03:44 -08:00
bbayazit16
2c3e7d55fd
Remove val from comment (#1207)
Line 78 uses ".once", but "val" is used in comment at line 79.
2022-02-18 22:59:38 -08:00
Orimay
ba7c3e8bda
NaN -> false (#1200) 2022-02-04 03:00:10 -08:00
Orimay
ddaf523a98
NaN -> false (#1202) 2022-02-04 02:59:53 -08:00
Orimay
666569f1d7
NaN -> false (#1201) 2022-02-04 02:58:40 -08:00
Orimay
05f497778a
@Orimay put validation: adding '-Infinity' as an invalid case; speeding validation up (#1189)
* Adding '-Infinity' as an invalid case

Adding '-Infinity' as an invalid case, not handled before
Skipping extra checks until needed (like NaN, Infinity)
Checking for 'null' first as for more common case than invalid 'undefined'

* Adding '-Infinity' as an invalid case

Adding '-Infinity' as an invalid case, not handled before
Skipping extra checks until needed (like NaN, Infinity)
Checking for 'null' first as for more common case than invalid 'undefined'

* Adding '-Infinity' as an invalid case

Adding '-Infinity' as an invalid case, not handled before
Skipping extra checks until needed (like NaN, Infinity)
Checking for 'null' first as for more common case than invalid 'undefined'

* Fixing tests to handle -Infinity

* Removing useless shim import

* Removing useless shim import

* Removing redundant undefined check

* Removing redundant undefined check

* Removing redundant undefined check

* ES5 compatibility

Co-authored-by: dbaranov <dbaranov@bellintegrator.com>
Co-authored-by: Mark Nadal <mark@gun.eco>
2022-02-04 02:41:22 -08:00
Promaethius
f85f55c5a1
test escaped backslash (#1156) 2022-02-02 22:45:55 -08:00
david smooke
ce20e0787d
Update README.md (#1181) 2022-01-15 21:22:57 -08:00
Mark Nadal
852b77f49a Merge branch 'master' of http://github.com/amark/gun 2021-12-16 01:21:04 -08:00
Mark Nadal
6780cb4334 better error + fix nested .once hanging on non-existent node when link does exist 2021-12-16 00:05:43 -08:00
Emad Kheir
77162fcb68
YSON Fixes (#1170)
* Rewrite YSON, fixes #1155

* Modify test file so it now includes a backslash to test YSON's escaping functionality

* Moved new yson implementation to ison.js

* Update YSON imports to ison.js on radisk, server and stats

* Update test to use ison.js and added emojis to test strings with unicode characters
2021-12-07 22:47:48 -08:00
tedd pasta
d1f13c86c6
make change to lib/unset.js (#1167)
* change stats.radata

* remove stats.radata file creation since fs.writeFil will do it any way

* require path and use last directory of opt file path or use radata

* make unset change
2021-12-02 18:39:37 -08:00
Natnael Teferi
9413142c80
ReactNative/Expo fix for SEA (#1169) 2021-11-28 20:05:15 -08:00
Mark Nadal
6d3ea2ecc5
Thanks to @DimensionDev https://mask.io/ for supporting! 2021-11-24 17:36:53 -08:00
Jairus Joer
3c5de47c42
Change Dockerfile python package to python3 (#1166)
As of version 3.12, the python package will no longer be supported in favor of explicitly chosen packages python2 or python3.
2021-11-23 13:52:01 -08:00
tedd pasta
396b367e4e
change stats.radata file (#1161)
* change stats.radata

* remove stats.radata file creation since fs.writeFil will do it any way

* require path and use last directory of opt file path or use radata
2021-11-23 13:51:25 -08:00
Mark Nadal
1969d48e0f
Thanks @mikestaub for donating!!! :) <3 2021-11-21 17:49:23 -08:00
Mark Nadal
0441aa332d
Update axe.js 2021-11-15 02:03:41 -08:00
Mark Nadal
009be7e534
Thanks https://ghostdrive.com (Roman Tykhovsky) for donating!!! :) 2021-11-13 18:32:14 -08:00
Mark Nadal
74d2b077cd
Thank you Fabian Stamm @hibas123 for donating!!! 2021-11-10 17:10:33 -08:00
Emad Kheir
50af2d52ad
Halt rap function on undefined key (#1157) 2021-11-05 23:52:08 -07:00
Hector
3b8eb16960
✂️ Path shortened ! (#1141)
* Fix the "/" bug.

* Update the "hub-test" to make them work everywhere!

* 🤛Fix the "/" bug !

* Fix indentation

* ✂️ My new quest shall be to shorten the file paths !

* 👽 Remove Chokidar from dependencies

* 👽 Remove chokidar from dependencies!
2021-10-29 23:20:16 -07:00
MaciejDot
395c2b8f98
partly repair gun types (#1154)
* partly repair gun types

* added types tests
2021-10-29 23:15:02 -07:00
Jeff Hykin
17af355ac1
4 lines, improve logging slightly (#1153)
* use gun.log.once for logging consistency

* -
2021-10-29 23:09:37 -07:00
Mark Nadal
49973ac522
Update README.md 2021-10-15 02:03:21 -07:00
Mark Nadal
90c7fb813e
it did not, so undo 2021-10-13 22:34:24 -07:00
Mark Nadal
34f53a20fb
let's see if this works? 2021-10-13 22:23:50 -07:00
Hector
0b158667a7
Update hub ! (#1134)
* Fix the "/" bug.

* Update the "hub-test" to make them work everywhere!
2021-09-16 08:54:01 -07:00
Mark Nadal
edf6c5f38d fix @yokowasis bug found + house keeping. 2021-09-13 23:02:45 -07:00
Gál Péter
c97ac0002c
Fix: type error shown when using generated keypair (#1131)
* fix errors shown when trying to use correct keypairs

* mark only (really) used parameters as required

- a callback is optional, because we could just use the async/await methodology to recieve the keypair
- when signing only `priv` is used
- when verifying only `pub` is used
- both when encrypting/decrypting only `epriv` is used
2021-09-11 10:02:08 -07:00
Mark Nadal
d7282be14b
yaml y u no multi line comment? 2021-09-06 04:43:31 -07:00
Mark Nadal
f8f2fc502d
@tcurdt docker no login so it fails, disabling till fix 2021-09-06 04:21:36 -07:00
mimiza
63b0043076
Improve SEA: .auth, .certify, check.pub (#1130)
* Improve SEA.certify

- Improve certify() logic
- "Blacklist" renamed to "block". BLACK LIVES MATTER!
- Fix user.is.alias, now it doesn't contain full pair any more.

* SEA.certify wire logic tests

The "block" (former "blacklist") feature is not working yet (due to a bug in gun)

* skip certify block feature unit test
2021-09-05 22:40:36 -07:00
Luca Guzzon
89c5286a52
A silly typo ... (#1127)
I think that "process.AWS_REGION" should be "process.env.AWS_REGION", right?
2021-09-05 22:38:45 -07:00
Torsten Curdt
31971c0c51
publish master and releases (#1126)
* no artifacts, not required

* renamed

* cleanup and comments

* pass build args

* two-step docker build

* renamed to as we might push to any docker repo

* rename and cleanup

* added some docs and expectation about the CI/CD and release information

* combined all workflows into steps
2021-09-05 22:34:13 -07:00
Mark Nadal
7dedd0797c
yummier quickstart! 2021-09-02 04:48:45 -07:00
Mark Nadal
e52e5821c1
add intro video! 2021-09-02 04:11:10 -07:00
Mark Nadal
eafab334a9
clean, update, housekeep :) 2021-09-02 03:56:50 -07:00
Mark Nadal
d1a59e5d6f
Update install.sh 2021-09-02 03:22:08 -07:00
Mark Nadal
d178d4a095 what about this new peer? 2021-08-31 10:59:47 -07:00
Mark Nadal
8cd8c4f6fb Merge branch 'master' of http://github.com/amark/gun 2021-08-31 09:38:26 -07:00
Mark Nadal
e63504a8df what about this volunteer peer? 2021-08-31 09:38:22 -07:00
Mark Nadal
ae0ffadc29
Update README.md 2021-08-30 23:54:15 -07:00
Mark Nadal
bdf4717d2d
Thanks @timjrobinson ! :) 2021-08-30 21:05:29 -07:00
Hector
084e2907da
🎉 Introducing a new feature ! (#1121)
* 🎉 .hubignore is ready !

* 🧪 Add tests for hub.js !
2021-08-30 14:29:55 -07:00
Torsten Curdt
0eec835c31
cleaning up and improving the CI/CD pipeline (#1122)
* no artifacts, not required

* renamed

* cleanup and comments

* pass build args

* two-step docker build
2021-08-30 14:26:44 -07:00
Mark Nadal
8e2f12542d ENV vars to disable RAD 2021-08-29 10:17:38 -07:00
Mark Nadal
5df08f91cb Merge branch 'master' of http://github.com/amark/gun 2021-08-25 21:27:29 -07:00
Mark Nadal
b8450ceab9 Cleaner installs, more compatible environments 2021-08-25 21:27:25 -07:00
Hector
1be6c5ed62
📦 You can now disable messages from hub & more... (#1120) 2021-08-24 22:25:09 -07:00
Hector
4db88079b5
👺 Add a .replace() to delete all the “\n’ (#1118) 2021-08-24 02:18:06 -07:00
Mark Nadal
6cb7261ac2 unbuild fixes & shim temporary deprecations for publication 2021-08-23 00:59:58 -07:00
Mark Nadal
dac9e8d059 fix synchronous runs, don't skip wait, fire first, aggregate but error if need fire, 2021-08-23 00:49:22 -07:00
Mark Nadal
6336cc66ae starting documentation etc. refinements piece by piece 2021-08-21 23:26:37 -07:00
Mark Nadal
8e4128b474 unbuild gun - after 1 year of merges! 2021-08-21 21:27:55 -07:00
Mark Nadal
cd45008433 unbuild sea 2021-08-21 21:27:00 -07:00
Mark Nadal
087704ec6b
Begin 1 Years worth of Merges... (#1116)
* tmp for hn issue

* log top to stats

* test for guntest peer

* try big messages

* parse time?

* what bin/node is 11ms?

* be normal for hnoon

* tolerate 0.5s

* try 3s for hnoon?

* stop empty gets

* tmp for guntest

* back to normal

* check hash time

* back to normal in hear

* screen / upload / play / pause

* merge latest npm release into manhattan

* merge master 0.2020.421 into manhattan manually

* WIP

* manually merge from master

* gatling

* Update upload.html

* work in progress...

* yson panic chat basic

* after `.put(` walk

* restructure acks

* messy but 2 units passing!

* put recursive once on map

* basics

* have NTS use DAM + fix other utils

* Rewrote nts

* Allow passing test cli args.

Before, no CLI args would be passed when running `npm test`. Keeping the `mocha` at the end of the test script allows passing CLI args to Mocha.

* put back scan & once tweak

* PANIC user paste OK

* manhattan sea

* stub out nts for now

* AXE tweak

* tweak for quick first prod testing

* tweak for first in-prod testing

* tweak

* tweak

* sketchy in-prod debug attempt

* caught it? maybe? now restore

* Create download-log.html

* stub out yson test prod?

* ugh, gotta see what is going on

* move dl

* gonna stop doing commit messages for in-prod test/tweaks/debugging

* a

* p

* squelch

* console stats

* stats

* stop travis

* restore yson

* ahhh no file access without sudo

* mem

* no stub

* fix axe

* bump

* back to in-prod testing, isolate/stub out code

* stub all out for 17K ? CPU ? test

* stub dup gc

* ugh main stub

* does this stop url format blocking?

* re-add dup

* no top :(

* will this work?

* get ack stats?

* a map chain may ask for data not a root soul chain

* move proper logic into .get(

* how 2019 compat?

* a couple more!

* more tests passing! :D :)

* even more! SO EXCITING :D

* Am I alive?

* wow I can't believe it works like this

* THANK YOU @rogowski !!!!!!

* Create trace.html

Adding tracing to debuging.

* @rogowski is a super star :) :) :)

* Update trace.js

Change `Gun.logs` to `Gun.traces` and `Gun._log` to `Gun._trace`.

* Update trace.html

Change `Gun.logs` to `Gun.traces` and `Gun._log` to `Gun._trace`.
Overload get,put,on,map

* @rogowski approved of these trace changes :)

* Update trace.html

More decoupled.

* Update trace.js

More decoupled

* 2 steps backwards, 1 step forward?

* back where we ( @rogowski ) started :P

* YAYAYAYAYAYAYAY past where we started at!

* safer to have it here

* slight tweak? Let's see how long it lasts.

* merge checks we left out during consolidation

* ugly common.js for @rogowski

* slightly better

* amazing map discovery + don't clear on not found if data exists

* onto next test...

* all caught up!!! Now update tests from graphify to statedisk

* Update common.js

Tests updated from graphify to statedisk.

* easy to debug & fix thanks to @rogowski 's test upgrades & trace!

* hmm, IDK if we should support this anymore?

* support once chaining?

* check if listener order is earlier than write

* in-process message passing needs to clean itself of flags for now

* ack to chains that can't be reached

* call sub chains on clear/empty WIP

* call sub chains clear/empty OK!

* into unlink. Clean/refactor later.

* oh that was nice

* self check not needed?

* test was poorly constructed?

* refactor unlink to cleaner logic

* Will you blame me for this? Special case, maybe later move to cleaner place?

* use stun's run id instead.

* cleaner unlink logic

* better map, link, and unlink logic.

* unstub relay

* refactor unlink

* invert

* if prev value would have caused unlink, do not unlink again.

* w000h00! Best unlink so far.

* woops, fix unlinking nested

* unsubscribe nested maps (working, tho possible perf regression? check)

* put check soul

* add default uuid

* improved browser peer retry logic, let devices sleep, etc.

* Chaining API unit tests passing!

* merge new panic tests into here to test

* add panic utils

* fix long streaming timeout/expiry issue, update examples

* yield generating test data

* yeah, adapter errors (like out of storage) should not affect sync/networking logic, that was a bad experiment

* git glitch?

* some mid debugging fixes but maybe scary changes, hopefully safe to revert here except dub

* SEA unit tests passing!!! Needed quite a few fixes on async write queue stuff.

* optionally make auth async

* revise/correct set

* Fix reverse boundary check

* Add extra tests, catch bad guy, obliterate bug.

* chat app with emoji examples

* handle empty string keyed objects

* starting lex support

* tweak for lex

* woops! lexical alphabetical oopsies. That was bad.

* upload either way

* debug

* start

* fix

* fix

* clean + feature

* update dependencies in package.json (#1086)

* rad lex once map once

* axe polyfill for now

* oops log

* oops maybe without this it crashed the peer

* what on earth happened to my browser/OS? "unplug & plug it back in" restart seemed to fix it.

* oh, don't memory leak req/res asks. :/ duh!

* no accidental #soul.""

* ugh, still have to sort :(, really should polyfill weakmap then

* oops, pluck needs new object to go into

* oops, make sure soul is passed

* updating deprecated functions

* begin AXE. Next: load balance!

* Update sea.js

* keys are dangerous!

* AXE round robin load balance

* better ash hash checking

* lS reuse in-mem reply chunking

* state machine!!!

* RAD needs to pass cache misses.

* updating deprecated functions (#1088)

* update dependencies in package.json

* updating deprecated functions

* remove where.gundb.io

* Bring SEA.certify into manhattan branch (#1092)

Co-authored-by: Radu Cioienaru <radu@projectmanager.com>

* fix rad, make get() hookable

* rad browser tests seem to be passing!

* reverse user random side, add err, update styles, + more

* fix pack/max, update dom

* paste!

* of course it'll dedup cause it just called track on hear, fix

* 📦 Adding the hub feature to this branch & improvements. (#1102)

* 📦 Adding the hub feature to this branch.

* 🗑 Removed the container for speed improvement !

* 📝 I added some comments to the code.

Co-authored-by: Hector <fairfairytotor@gmail.com>
Co-authored-by: Hector <pro.hector.kub@gmail.com>

* Update axe.js

* 🦅 Wrap everything in a try & catch for error handling…  (#1105)

* 🦅 Wrap everything in a try & catch for error handling & speed improvement.

* 📦 Finally here : opt.file for the hub feature !

* 📦 Finally here : opt.file for the hub feature !

And also : fixed indentation 😋

Co-authored-by: noctisatrae <pro.hector.kub@gmail.com>

* probs better this way, safer

* moved test/axe tests to test/panic/axe.

* New test: axe load balance.

* axe test: webrtc data balance(fix paths and file renamed).

* test axe: renaming webrtc file.

* axe test: separating webrtc test for data_balance.

* axe test: test only with the relay(without webrtc).

* Update sea.js

Same as https://github.com/amark/gun/pull/1062

* Update gun.js

var tmp

* Update upload.js

* merge, update stun

* SEA.certify wire logic + unit tests (#1110)

* SEA.certify wire logic + unit tests

* picking white hair

* ack err

* axe tests using puppeteer.

* change stun system

* ~20lines

* put use parent soul link if need

* handle errors

* finally seems fixed

* cb not to

* relay

* nasty bug! Don't crash, tho need to find what causes it

* undo local changes/notes to self

* deprecation warnings

* "old" data to test against

* oops, forgot I played with ascii

* debug

* in-prod check: sites

* in-prod isolate

* gotta find this, by stubbing out

* where?

* will this work?

* clearly not, lol what's the point then? maybe like this

* and again

* must we?

* USE THIS MANHATTAN VERSION

* clean

* better panic hints

Co-authored-by: Robin Bron <finwo@pm.me>
Co-authored-by: Pavel Diatchenko <diatche@users.noreply.github.com>
Co-authored-by: rogowski <163828+rogowski@users.noreply.github.com>
Co-authored-by: I001962 <i001962@gmail.com>
Co-authored-by: Adriano Rogowski <rogowski.adriano@gmail.com>
Co-authored-by: Radu <cetatuie@gmail.com>
Co-authored-by: Radu Cioienaru <radu@projectmanager.com>
Co-authored-by: Hector <46224745+noctisatrae@users.noreply.github.com>
Co-authored-by: Hector <fairfairytotor@gmail.com>
Co-authored-by: Hector <pro.hector.kub@gmail.com>
Co-authored-by: Martti Malmi <sirius@iki.fi>
Co-authored-by: mimiza <dev@mimiza.com>
2021-08-21 21:19:29 -07:00
mads
e7afd231eb
update some things to make docker work again (#1095) 2021-08-08 10:32:54 -07:00
chance
da573640b3
Fixes a few typos and small grammatical errors in the type definitions located at types/chain.d.ts (#1106)
* Adds a note about deploying web apps where an environment variable should be changed to avoid GUN warnings being treated as errors during CI

* Fixes a few typos and small grammatical errors in the type definitions types/chain.d.ts
2021-08-05 20:28:35 -07:00
chance
44fd7bee89
Adds a note about deploying web apps where an environment variable should be changed to avoid GUN warnings being treated as errors during CI (#1101) 2021-08-03 21:40:46 -07:00
Hector
5ba2d9b44f
📦 Adding the new hub feature ! (#1099)
Co-authored-by: Hector <fairfairytotor@gmail.com>
2021-08-03 13:05:51 -07:00
Bernie Telles
5d5432a9b5
Fix set/get parameters to use Record<string,*>. (#1094)
* Add TypeScript test file & tsd as devDep to run it

This helps those who want to contribute to the TypeScript definitions
by adding:
 * a tool called `tsd,`
 * its corresponding configuration in package.json
 * a teste file index.test-d.ts

Also add a extra line between type definitions to improve readability.

* Fix set/get parameters to use Record<string,*>.

The previous implementation did not allow users to
retrieve items that were inserted using "set," and
it incorrectly used ArrayOf to extract record types.

The previous implementation also prevented users
from ever inserting an array. Although it the database
does not handle arrays elegantly, it allows the user
to insert them. Typing should not prohibit use of
arrays.
2021-07-30 00:20:32 -07:00
Bernie Telles
70eb769209
Add TypeScript test file & tsd as devDep to run it (#1091)
This helps those who want to contribute to the TypeScript definitions
by adding:
 * a tool called `tsd,`
 * its corresponding configuration in package.json
 * a teste file index.test-d.ts

Also add a extra line between type definitions to improve readability.
2021-07-27 13:02:47 -07:00
Mark Nadal
8c8b513716
Update rs3.js 2021-07-15 23:03:56 -07:00
Mark Nadal
5bafcea9f3
thanks @ajartille 's http://ajar.org/ foundation! 2021-07-14 06:16:50 -07:00
Mark Nadal
a362460b0f
Thank you @nmauersberg !!! 2021-07-10 00:06:24 -07:00
Mark Nadal
617c7ac2f1
Thanks @sjuxax ! 2021-07-08 15:52:31 -07:00
Egi Hasdi
fdedf8e59d
[type definition] use keypair for user.auth (#1085) 2021-06-30 17:27:49 -07:00
Johnny Dallas
b1b0432983
Add zeet.co deploy button (#1075) 2021-06-22 15:23:54 -07:00
marcomow
fe9ea62f61
Fix wrong element's dynamic identifier, semicols (#1080) 2021-06-16 22:23:37 -07:00
nsreed
10b42525ad
update on-recovery PANIC test to run default & radisk configurations (#1078) 2021-06-16 11:56:34 -07:00
nsreed
fc10c250c9
add load-browser-scripts utility (#1077) 2021-06-02 16:23:47 -07:00
Martti Malmi
0f9ebfc454 update iris-lib in package-lock.json 2021-05-31 16:07:22 +03:00
Martti Malmi
7925598cd8 update iris 2021-05-31 13:52:35 +03:00
Mark Nadal
8b9f8915f2
Update README.md 2021-05-10 12:36:07 -07:00
Mark Nadal
804bf04e50 version bump 2021-05-06 00:37:48 -07:00
nsreed
2168e3e2d7
add options argument to set/put method signatures (#1067)
* chain.d.ts: add options argument to put & set

* chain.d.ts: set cb may be null when providing opts

Co-authored-by: Norman Reed <norman.s.reed@gmail.com>
2021-04-11 22:58:38 -07:00
Mike
5ca97d88a3
Add git to Dockerfile apks (#1061)
Git needs to be added to the docker image or the build fails at the npm install stage.

_Looks at iris_
...
npm ERR! path git
npm ERR! errno -2
npm ERR! enoent undefined ls-remote -h -t ssh://git@github.com/irislib/iris-messenger.git
...
2021-04-11 22:57:45 -07:00
RICHΛRD ΛNΛYΛ
429b011955
Fixing non-existent err variable in localStorage (#1044)
* Fixing non-existant err variable in localStorage

* Update localStorage.js
2021-04-11 22:55:44 -07:00
RICHΛRD ΛNΛYΛ
e9ed2e5a02
Improving websocket retry logic to support no retries (#1045)
* improving retry logic

* Trigger Build
2021-04-11 22:51:40 -07:00
Mark Nadal
331ea85c86
Rename emoji to emoji.html 2021-04-11 21:52:20 -07:00
Mark Nadal
183555d793
Create emoji 2021-04-11 21:51:59 -07:00
Mark Nadal
655bec7b16
Rest In Peace Sergeant Major de Vries 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 🔫 2021-04-06 04:34:06 -07:00
damian-tripbuddi
4a84984699
Correctly referring to process.env.AWS_REGION and initializing Store with s3 if opts.s3 has been configured. (#1064) 2021-04-02 14:49:01 -07:00
I001962
4dc672eeb4
Fix safari sea issues (#1062) 2021-03-19 13:24:40 -07:00
Mark Nadal
508d38cd1b
Update rad.js 2021-03-04 14:37:31 -08:00
Carlos Vega
45dd008cb7
(WIP) Bug rad reverse sorting (#1021)
* bug: fixes issue with reverse sorting

* chore: updates unit test

* bug: new array not needed as filter already return a new one
2021-03-04 14:35:52 -08:00
jojobyte
1c25266935
Keep devDependencies installed in docker image (#1047) 2021-03-04 14:32:14 -08:00
Yang Hanlin
ae6d5cb6bf
Improvements to automatic redirect on loading SEA module (#1055)
* Warn on automatic redirect to HTTPS

* Don't redirect to HTTPS on loopback IP addresses

* Check if current location is a local loopback IP address (127.0.0.0/8) and do not redirect
2021-03-04 14:30:41 -08:00
davay
5be57c3fb1
Fix: certificants' pub strings now pass to cert (#1058)
`certificants.indexOf('*') !== -1` appears to be correct way of using this function. `certificants.includes` may be another option, but it may be too modern for compatibility concern
2021-03-04 14:21:47 -08:00
Martti Malmi
4ded14186f
Update app.json 2021-01-23 00:11:46 +02:00
Martti Malmi
88cfae52b4
Add PEERS env variable to app.json for Heroku 2021-01-23 00:07:03 +02:00
Martti Malmi
8de6ce5ca2
Don't prune devDependencies on Heroku (#1046)
* NODE_ENV=development for heroku deployment

* Use NPM_CONFIG_PRODUCTION=false instead

* Update app.json

* Update app.json
2021-01-19 11:51:34 -08:00
Mark Nadal
60d94180e2
Merge pull request #1043 from mmalmi/startpage
New landing page
2021-01-18 01:21:50 -08:00
Martti Malmi
43eae41c35 move images to iris, move iris to devDependencies 2021-01-16 16:21:25 +02:00
Martti Malmi
d141c6e403 togglable sidebar on mobile 2021-01-14 16:50:12 +02:00
Martti Malmi
edccff60a7 redo landing page using iris components 2021-01-14 12:48:11 +02:00
Mark Nadal
cb3f8600d9
Merge pull request #1029 from jussiry/master
Wave.js comments and spaces to structure code
2020-12-23 02:18:55 -08:00
Mark Nadal
00f75aff9a
Merge pull request #1036 from mimiza/master
SEA.certify(): Urgent bug fix for blacklist
2020-12-18 12:29:33 -08:00
MIMIZA
1bbc308ceb fix bug 2020-12-19 01:14:26 +07:00
MIMIZA
6e0a6fe225 SEA.certify: fix bug 2020-12-19 00:24:03 +07:00
Mark Nadal
a6b6b7f2ee
Merge pull request #1035 from mimiza/master
SEA.certify() small bug fix + more unit test
2020-12-16 01:20:45 -08:00
MIMIZA
49b2937421 SEA.certify() small bug fix + more unit test
There is a small bug and this is a fix for it. More unit tests added.
2020-12-16 15:51:37 +07:00
Mark Nadal
be0b1cefb2
Merge pull request #1034 from mimiza/master
change SEA.certify() && check.pub()
2020-12-14 23:09:07 -08:00
MIMIZA
0a91b8079b change SEA.certify() && check.pub() 2020-12-14 15:27:46 +07:00
Mark Nadal
c17a14b53a
Merge pull request #1033 from mimiza/master
SEA.certify: replace RegEx with RAD/LEX, force path to contain Certificant Pub
2020-12-13 12:33:05 -08:00
MIMIZA
e2a92bd61e small fix 2020-12-14 02:36:50 +07:00
MIMIZA
34d7f6fc70 small fix 2020-12-14 02:28:46 +07:00
MIMIZA
d8d037fc81 SEA.certify: replace RegEx with RAD/LEX. New feature: Path must contain Certificant Pub
- RegEx replaced with RAD/LEX
- NEW FEATURE: If LEX has key "?" and lex['?'] contains '*': check if Certificant Pub is in Path
- Unit tests updated
Official doc will be written after this PR is merged.
2020-12-14 02:23:26 +07:00
Mark Nadal
7d12a82458
Merge pull request #1028 from mimiza/master
Add Blacklist feature to SEA.certify
2020-11-29 15:01:31 -08:00
Jussi Rytkönen
227685cedf Merge branch 'master' of github.com:amark/gun 2020-11-23 13:10:16 +02:00
Jussi Rytkönen
1e1cad8bbd wave.js comments and structured spaces 2020-11-23 13:09:21 +02:00
MIMIZA
4d0bcab3b8 Add Blacklist feature to SEA.certify
Now SEA.certify supports Blacklist. For more details, please read doc here: https://gun.eco/docs/SEA#certify
2020-11-23 12:21:48 +07:00
Mark Nadal
b3e5b21f86
Merge pull request #1020 from mimiza/master
Add SEA.certify(), upgrade SEA check.pub(). Tests passed. Bugs free.
2020-11-18 22:59:40 -08:00
Mark Nadal
deeb87e31b
Merge pull request #1026 from tcurdt/master
CI/CD setup
2020-11-18 22:57:32 -08:00
Torsten Curdt
0770648219 switch version back to master 2020-11-15 01:10:20 +01:00
MIMIZA
5ee816191a Improve SEA check.pub() 2020-11-14 13:44:20 +07:00
Torsten Curdt
ab5e38b367 not sure how it happend - but fixed the tab mixup 2020-11-13 20:56:00 +01:00
Torsten Curdt
002680ede4 removed debug 2020-11-13 20:09:00 +01:00
Torsten Curdt
e1de0c875e unbuild needs uglifyjs 2020-11-13 20:09:00 +01:00
Torsten Curdt
d7dd65babf debug publish 2020-11-13 20:09:00 +01:00
Torsten Curdt
fece267263 reduce the test matrix because of flaky test 2020-11-13 20:09:00 +01:00
Torsten Curdt
bff7804b5b disable windows builds for now 2020-11-13 20:09:00 +01:00
Torsten Curdt
1eed73af48 proper directory 2020-11-13 20:09:00 +01:00
Torsten Curdt
afa7abc646 Create main.yml
wtf, github
2020-11-13 20:09:00 +01:00
Torsten Curdt
8a7d1ce2fc added ci, artifact cleanup, and pushing releases to dockerhub and npm 2020-11-13 20:09:00 +01:00
Torsten Curdt
52590d96b9 personal package space for testing 2020-11-13 20:09:00 +01:00
Torsten Curdt
4f3c5f0f3d re-add peer dep (was a npm problem) 2020-11-13 20:09:00 +01:00
Mark Nadal
57d1919c68
Update meta.js 2020-11-13 05:28:40 -08:00
Mark Nadal
1703e6003c
Merge pull request #1025 from jussiry/master
meta lib update: open/close on hover and back button fixes
2020-11-13 05:11:55 -08:00
Jussi Rytkönen
4a66bface6 meta lib: removes extra indentation 2020-11-13 15:02:14 +02:00
Jussi Rytkönen
badb490d50 Merge branch 'master' of github.com:amark/gun 2020-11-13 14:31:26 +02:00
Jussi Rytkönen
807ec9ef25 meta lib update: open/close on hover and back button fixes 2020-11-13 14:30:01 +02:00
Mark Nadal
bafb25dcfa
Merge pull request #1023 from jussiry/master
Wave update
2020-11-11 12:48:07 -08:00
Jussi Rytkönen
cf5c00d82c Merge branch 'master' of github.com:amark/gun 2020-11-10 13:14:11 +02:00
Jussi Rytkönen
77c39a2035 wave example and library update 2020-11-10 13:13:39 +02:00
Mark Nadal
564c6f3100
Merge pull request #1022 from mmalmi/peers-env-variable
Peers env variable
2020-11-09 13:18:34 -08:00
Martti Malmi
c254f4c699
remove console.log 2020-11-09 16:09:34 +02:00
Mark Nadal
0875201558
Merge pull request #1013 from rogowski/test-panic-lexical
Test RAD lexical queries.
2020-11-08 23:04:18 -08:00
Mark Nadal
803e1d4938
Merge pull request #1014 from finwo/adapter/leveldb-radless
RAD-less leveldb adapter
2020-11-08 23:00:57 -08:00
MIMIZA
5701b8b581 SEA.certify unit tests 2020-11-07 16:27:08 +07:00
Martti Malmi
2777d87c4d remove react-native-webiew-crypto dependency which breaks the build 2020-11-04 11:07:23 +02:00
Martti Malmi
ca003747b7 use PEERS env variable in http.js 2020-11-03 17:05:40 +02:00
mimiza
c95b99d376
Added a warning console.log to SEA.certify() 2020-10-28 19:38:14 +07:00
mimiza
c686a15980
Small fix 2020-10-27 16:55:22 +07:00
mimiza
04bbfdd2eb
Small fix 2020-10-27 15:44:45 +07:00
MIMIZA
5d755af301 Merge branch 'master' of https://github.com/amark/gun 2020-10-27 14:35:36 +07:00
MIMIZA
bac237fa89 SEA.certify() completed. SEA check.pub() upgrade completed. Tests passed. Bugs free. 2020-10-27 14:26:11 +07:00
MIMIZA
37da3cc8ea improve SEA Cert security, still need much improvement in check.pub, unfinished 2020-10-26 23:53:04 +07:00
MIMIZA
be6dcf0f99 improve SEA Cert security, still need much improvement in check.pub, unfinished 2020-10-26 23:48:20 +07:00
MIMIZA
ebe8345090 finished prototyping, but need much refactoring 2020-10-26 15:56:04 +07:00
Mark Nadal
4dc88e9ea8
Merge pull request #1019 from bioshazard/bug/GUN-935
Fixed issue 935. Detects zero length key
2020-10-25 15:09:52 -07:00
MIMIZA
80c74d254b refactoring cert prototype & check.pub, unfinished. 2020-10-24 23:27:53 +07:00
MIMIZA
97bbdd9b74 cert injection && validation done 2020-10-21 01:36:57 +07:00
mimiza
622a252722
prototyping SEA.certify() 2020-10-19 22:53:57 +07:00
Joe Still
37726f6e68 Fixed issue 935. Detects zero length key 2020-10-18 17:03:48 -05:00
Robin Bron
84097d7e68 Added radless leveldb adapter 2020-09-27 01:55:12 +02:00
Adriano Rogowski
69165f69f5 Test RAD lexical queries. 2020-09-24 21:46:29 -03:00
Mark Nadal
05349a5c68
Merge pull request #1010 from mmalmi/infinite-scroll-test
infinite scrolling example
2020-09-21 13:26:03 -07:00
Martti Malmi
fe57813721 simple panic test that scrolls through 1500 entries 2020-09-18 15:05:23 +03:00
Martti Malmi
773d5cba25 cleanup 2020-09-18 11:25:08 +03:00
Mark Nadal
7e9ec5d93a
Merge pull request #1007 from diatche/feature/panic2
PANIC test semi-automation using Puppeteer
2020-09-17 22:30:56 -07:00
Martti Malmi
866e8594d6 scrolling up from bottom 2020-09-17 23:28:33 +03:00
Martti Malmi
11bdf2211e empty img src in between 2020-09-17 22:03:58 +03:00
Martti Malmi
811a1b8963 infinite scrolling example, panic test wip 2020-09-17 17:16:14 +03:00
Pavel Diatchenko
a607bdd004 Cleanup puppeteer on exit. 2020-09-17 12:37:47 +12:00
Pavel Diatchenko
33b29f4ee6 Added puppeteer cleanup method. 2020-09-17 12:33:04 +12:00
Pavel Diatchenko
fee7473ccb Use puppeteer if available. 2020-09-14 16:12:50 +12:00
Pavel Diatchenko
fd6752cbd6 Added browser open utility method. 2020-09-14 16:06:49 +12:00
Mark Nadal
a89ca678bb
Merge pull request #1001 from shocknet/shocknet-tests
Shocknet tests
2020-09-11 14:05:18 -07:00
Mark Nadal
c82e0da589
Update README.md 2020-09-04 17:35:18 -07:00
Mark Nadal
b78bbc322b
Update .dockerignore 2020-08-26 13:46:02 -07:00
Mark Nadal
35c8a75a00
Merge pull request #1000 from estebanrfp/master
added vanilla js version of video.html
2020-08-19 03:50:59 -07:00
estebanrfp
bf68704063 added vanilla js version of video.html 2020-08-16 22:59:09 +02:00
Mark Nadal
5cbd5e3943
Merge pull request #990 from amark/node-client-auth
add: test node as client SEA auth
2020-07-24 01:35:18 -07:00
Mark Nadal
bd417b9f04
Merge pull request #991 from Joncom/on-recovery
Test if gun.on() callback fires after relay peer crashes
2020-07-24 01:08:52 -07:00
sirpy
f723c69d7c
add: test node as client SEA auth 2020-07-19 00:07:06 +03:00
Daniel Lugo
a394a23aa1 saner name 2020-07-10 20:09:56 -04:00
boufni95
8161f14553 once -> then 2020-07-08 17:39:43 +02:00
boufni95
87b2dbe03d 6 -> 4 servers 2020-07-08 16:46:12 +02:00
boufni95
85191e8042 alice -> peer1 -> peer2 -> bob 2020-07-08 16:34:10 +02:00
boufni95
18aebaa4a1 handshake tests 2020-07-08 15:55:24 +02:00
boufni95
34f1be198e shocknet tests 2020-07-06 14:55:28 +02:00
Mark Nadal
97aa976c97
Merge pull request #970 from mimiza/fix-sea-sessionStorage
Fix user.create() callback not firing and user.create(pair)
2020-07-05 20:14:54 -07:00
Jonathan Commins
2ddb526323 Test if gun.on() callback fires after relay peer crashes 2020-06-24 22:08:57 -07:00
MIMIZA
a7bb4a840f Update sea.js 2020-06-24 10:55:27 +07:00
MIMIZA
feb54f024b Update sea.js 2020-06-24 10:42:03 +07:00
MIMIZA
e74f4a00e2 Update sea.js 2020-06-24 10:35:21 +07:00
MIMIZA
ef837a1018 alias = alias || pair.pub 2020-06-24 10:26:46 +07:00
MIMIZA
6d8f776200 Fix user.create()
BEFORE:
- user.create(pair) --> ~@[object Object]
- (noop == cb) --> callback will never fire because functions can't be compared like this. For example:
```
const a = b = function(){};
a == b // FALSE
```

AFTER:
- user.create(pair) --> ~@pair.pub
- callback is fired
2020-06-22 21:18:24 +07:00
MIMIZA
01cd2050d2 improve sea.js
Removed the small try/catch in recall() because there is already a bigger try/catch.
2020-06-22 08:59:39 +07:00
MIMIZA
edc122f63c Improve user.recall()
Wrap JSON.parse() in a try{}catch{}
2020-06-19 12:38:52 +07:00
Mark Nadal
3e678b8568
Merge pull request #964 from mimiza/fix-sea-sessionStorage
Fix sea.js issues #962, #957, #956
2020-06-17 10:43:41 -07:00
Mark Nadal
7c45ddb558
Merge pull request #961 from diatche/log-once-fix
Fixed missing Gun.log.once function
2020-06-14 20:34:44 -07:00
MIMIZA
e88a120a4e remove console.log 2020-06-15 08:40:00 +07:00
MIMIZA
486184e767 Switch to ancient technique
ES6 might not be reliable, so I decided to switch back to ancient JS. Removed spread operator (...args), replaced with "arguments"
2020-06-15 08:32:22 +07:00
MIMIZA
823df19593 Fix sea.js issues #962, #957, #956
BEFORE:
- user.recall() uses alias/pass -> not reliable, only works with auth(alias,pass), doesn't work with auth(pair)
- user.auth(pair, cb) -> cb is not a function

AFTER:
- user.recall() uses pair -> more reliable, works with auth(pair)
- user.auth(pair, cb) -> works
2020-06-13 11:55:19 +07:00
Pavel Diatchenko
0d53db7877 Fixed error "Gun.log.once is not a function". 2020-06-10 14:45:18 +12:00
Mark Nadal
f759ab1394 rfs should be after rs3 but both defer so rfs be before 2020-06-07 17:44:48 -07:00
Mark Nadal
9bc25e3647 do not axe up peers on puts 2020-06-07 15:55:53 -07:00
Mark Nadal
461bb7990a Merge branch 'master' of http://github.com/amark/gun 2020-06-07 15:17:58 -07:00
Mark Nadal
bfb43bf7a9 make sure to call next middleware 2020-06-07 15:17:52 -07:00
Mark Nadal
5706f46b00
Update README.md 2020-06-05 23:59:01 -07:00
Mark Nadal
6d02684036
Merge pull request #929 from DimensionDev/feature/reduce-docker-image
chore: reduce docker image
2020-06-03 13:34:56 -07:00
Septs
16d286538f fix dockerfile 2020-06-03 11:35:05 +08:00
Septs
4a74c65019 Merge remote-tracking branch 'upstream/master' into feature/reduce-docker-image 2020-06-03 11:34:40 +08:00
Mark Nadal
b356877a23 clean uploadS! 2020-05-23 23:47:43 -07:00
Mark Nadal
113fd7727d uploadS 2020-05-23 23:35:18 -07:00
Mark Nadal
bcad8f7ef3 uploads 2020-05-23 23:30:26 -07:00
Mark Nadal
47a841fbcd cleaner & smaller video & upload 2020-05-23 22:35:47 -07:00
Mark Nadal
c45950a771 Create upload.html 2020-05-23 21:40:34 -07:00
Mark Nadal
d56e06fec7 video example in ~90 lines 2020-05-23 20:08:30 -07:00
Mark Nadal
fcf105aaab #948 2020-05-22 21:34:47 -07:00
Mark Nadal
a48fd8c0a3 help robots 2020-05-21 17:42:39 -07:00
Mark Nadal
e4333397e4 clean package 2020-05-21 17:27:43 -07:00
Mark Nadal
022741dd90
Update README.md 2020-05-21 16:27:29 -07:00
Mark Nadal
98e0554944
Update README.md 2020-05-21 15:45:32 -07:00
Mark Nadal
d333738b0a
Merge pull request #949 from GoodDollar/minor-rn-changes
Minor rn changes
2020-05-21 14:51:20 -07:00
Mark Nadal
00c48f172b deprecate unofficial opt 2020-05-21 14:48:07 -07:00
Mark Nadal
4eb7d0d383 stupid lock file ugh travis 2020-05-21 14:44:35 -07:00
Mark Nadal
9e811e882c tell Travis to use module :P 2020-05-21 14:40:19 -07:00
Mark Nadal
125e1384c1 fix RN by moving require 2020-05-21 14:20:30 -07:00
Hadar Rottenberg
55b9231d47 add: info about RN v8 2020-05-21 23:37:07 +03:00
Hadar Rottenberg
213a14b0c8 add: better RN docs 2020-05-21 23:26:20 +03:00
Hadar Rottenberg
d69e6d43fe fix: make import isomorphic (this breaks EXPO) 2020-05-21 23:26:10 +03:00
Hadar Rottenberg
99cb0e92df add: lates ras.js 2020-05-21 22:10:07 +03:00
Hadar Rottenberg
d681c5ca91 Merge remote-tracking branch 'origin/master' into pr/sirpy/12 2020-05-21 22:05:19 +03:00
Hadar Rottenberg
5372279fb2 add: asyncstorage for rad 2020-05-16 23:21:29 +03:00
Mark Nadal
2501b5cdea
Update CHANGELOG.md 2020-05-16 04:18:23 -07:00
Mark Nadal
116d485379
Merge pull request #878 from rogowski/bug-121
Test file for bug-121
2020-05-16 03:19:45 -07:00
Mark Nadal
c7f017191e
Merge pull request #934 from estebanrfp/master
added vanilla js version of user.html
2020-05-16 01:57:16 -07:00
Mark Nadal
0af7379ed6
Merge pull request #939 from revolunet/patch-1
fix: fix #918
2020-05-16 01:56:12 -07:00
Mark Nadal
9f92b014f4
Merge pull request #946 from amark/dev
Fix 2020 "sync" issue for @JamieRez
2020-05-16 01:42:28 -07:00
Mark Nadal
eb8985b2fd vbump 2020-05-16 01:39:18 -07:00
Mark Nadal
49bc20ee95 nodejs fixes, some tmp 2020-05-16 01:33:41 -07:00
Mark Nadal
880947afe8 fix cache miss of cache hit 2020-05-16 01:23:40 -07:00
Mark Nadal
9d03ce83d0
Update README.md 2020-05-10 21:24:48 -07:00
Julien Bouquillon
284a028e1c
fix: fix #918
only replace http if at the start of the url
2020-05-04 01:22:18 +02:00
Mark Nadal
5a430bc812 stats should not swallow errors 2020-05-02 18:05:51 -07:00
Mark Nadal
985cfa2b4d build/unbuild 2020-05-01 19:13:13 -07:00
Mark Nadal
51be588a74 nomem for Meething! 2020-05-01 19:08:25 -07:00
Mark Nadal
c93305ae11 fix ws noServer 2020-05-01 18:54:16 -07:00
Mark Nadal
ff99a4639d
Merge pull request #936 from joedakroub/master
Fix for ES Modules when using a peer
2020-04-24 11:50:36 -07:00
rogowski
06a4a0bfeb
Merge pull request #868 from rogowski/bug-850
Test for bug-850 - Saving a deep object under a user node seems to lose public key at some depth. Add test.
2020-04-23 21:45:06 -03:00
Mark Nadal
29d596baf7 Merge branch 'master' of http://github.com/amark/gun 2020-04-22 14:31:54 -07:00
Mark Nadal
018fa8cc1e FIX user.set({obj not secure, + try fix hash & predictable souls + beta forgetfulness 2020-04-22 14:31:27 -07:00
estebanrfp
1d85346770 replaced gun peers url to location.origin 2020-04-20 21:15:36 +02:00
estebanrfp
f8e2230b04 added vanilla js version of user.html 2020-04-20 20:30:30 +02:00
estebanrfp
550b0633b0 Merge branch 'master' of github.com:amark/gun 2020-04-19 21:15:13 +02:00
Mark Nadal
5bedffc864
Merge pull request #930 from lmangani/patch-1
Allow externally provided websockets in constructor
2020-04-19 06:46:58 -07:00
Lorenzo Mangani
4124a2db50
Allow externally provided websockets in constructor
For consideration (this can also be overloaded in stock gun)
The current ws.js code does not allow providing an external websocket while initializing Gun. This one line patch makes it possible:

```
        var myWS= new WebSocket.Server({ noServer: true, path: pathname});
        var myGun = new Gun({ 
            ws: { noServer: true, path: '/mygun', web: myWS }, 
            web: myWS 
        });
```
2020-04-16 21:54:02 +02:00
Septs
47b29768c7 chore: reduce docker image 2020-04-14 17:21:34 +08:00
Joe Dakroub
1a71145b4d
Merge pull request #1 from joedakroub/jd/gun-mesh-this-error-esm-fix
Test fix - Loading gun via ES Modules throws error when setting a peer
2020-04-10 11:03:25 -04:00
joedakroub
46b0fb6dc5 Added this check on ine 2151 to prevent an error when using ESM 2020-04-10 10:48:01 -04:00
Mark Nadal
17f90d6d10
Merge pull request #927 from genderev/master
Explains Unubo issue
2020-04-10 02:17:59 -07:00
genderev
b0de4027e3
Update README.md 2020-04-10 01:44:09 +00:00
estebanrfp
f0b041cdb1 improve indentation code - vanilla folder examples 2020-04-08 18:13:33 +02:00
estebanrfp
964b1c9fcf +indentation 2020-04-07 19:17:00 +02:00
estebanrfp
60a62d867c update todo.html - keep it simple 2020-04-07 18:55:57 +02:00
Mark Nadal
ce78d7a4c9
Merge pull request #924 from estebanrfp/patch-1
Create screen.html - vanilla javascript version
2020-04-06 21:36:36 -07:00
Mark Nadal
2f34d8cb4e
Merge pull request #906 from jussiry/patch-1
react todo example: fixes input clear on submit
2020-04-06 21:35:06 -07:00
Mark Nadal
e2f4f11e6a
Merge pull request #923 from smpsnr/fix-private-example
update private.html to fix #808
2020-04-06 21:29:21 -07:00
Esteban Fuster Pozzi
31abc3eaa0
Create screen.html
Vanilla javascript version, video streaming using Gun
2020-04-06 23:33:09 +02:00
sam
6a3c55cc69 update private.html to fix #808 2020-04-06 15:07:46 -04:00
Mark Nadal
47e7c495d7 up not found ack count before new soul + use more predictable offline souls + content address hash fix 2020-04-06 01:34:41 -07:00
Mark Nadal
87955288a0
Merge pull request #921 from amark/dev
Dev
2020-04-06 00:30:34 -07:00
Mark Nadal
fc58d3552a important offline fixes & assumption/default changes 2020-04-05 17:41:51 -07:00
Mark Nadal
ce865da613
Merge pull request #916 from rayros/master
Fix: Angular - Cannot find module 'ts-type'
2020-04-05 17:19:16 -07:00
Mark Nadal
879cd84ccc
Merge pull request #920 from brysgo/patch-1
clean up subscription when component unmounts
2020-04-05 17:17:23 -07:00
Bryan Goldstein
8ec8e394b8
clean up subscription when component unmounts 2020-04-04 19:45:47 -04:00
Mark Nadal
156b84acee
Create FUNDING.yml 2020-04-04 16:15:49 -07:00
Mark Nadal
ec8808735b Merge branch 'master' into dev 2020-04-02 13:10:48 -07:00
Mark Nadal
7857c70b6e
Create yson.js 2020-03-31 23:19:36 -07:00
Hadar Rottenberg
22a76f489d Merge branch 'amark-master' 2020-03-30 15:59:55 +03:00
Hadar Rottenberg
3520f04b36 Merge branch 'master' of https://github.com/amark/gun into amark-master 2020-03-30 15:57:08 +03:00
rayros
7ba9aa1c3d remove ts-type devdeps 2020-03-29 20:46:14 +02:00
rayros
cba32c1040 remove ts-type import 2020-03-29 20:45:57 +02:00
Mark Nadal
12ff85aa2f
Merge pull request #914 from jussiry/dev
meta cmd hold, backspace etc.
2020-03-22 13:09:14 -07:00
Jussi Rytkönen
28205fe69e
Merge branch 'dev' into dev 2020-03-22 22:01:37 +02:00
Jussi Rytkönen
ee7a01675f meta cmd hold, backspace etc. 2020-03-22 21:38:12 +02:00
Mark Nadal
54a50d62ff
Merge pull request #879 from rogowski/bug-783
Test file for bug-783
2020-03-18 12:06:58 -07:00
Mark Nadal
dec75be45e
Merge pull request #888 from rogowski/bug-686
Test for bug-686: Cannot put string 'null' as value in put. SEA error…
2020-03-18 12:05:50 -07:00
Mark Nadal
1b002bd49d
Merge pull request #884 from rogowski/bug-322
Test for bug-322: modify returned node in callback leaks thru
2020-03-18 12:04:31 -07:00
sirpy
6d05150ae8
fix: remove undefined/unused variable 2020-03-18 09:23:48 +02:00
Mark Nadal
fbcb369aa8
Merge pull request #908 from amark/manhattan
Manhattan
2020-03-06 02:03:41 -08:00
Mark Nadal
6bdc99da1a Merge branch 'master' into manhattan 2020-03-06 01:49:31 -08:00
Mark Nadal
4163687acb check if migration needed 2020-03-06 01:35:14 -08:00
Mark Nadal
9de7d0f38d fix chain emit & faith 2020-03-04 22:58:25 -08:00
Mark Nadal
da7c243fb0 rad check node read, important puffs 2020-03-04 02:18:49 -08:00
Mark Nadal
97065b70fa in s not ms 2020-03-03 11:27:45 -08:00
Mark Nadal
b4568e52c3 prof back in 2020-03-03 11:25:23 -08:00
Mark Nadal
c58e412208 puff it 2020-03-03 04:24:54 -08:00
Mark Nadal
2540818665 don't lose ref 2020-03-02 15:26:26 -08:00
Mark Nadal
ccf2c303b9 puff say loop? see how it goes. 2020-03-02 15:03:18 -08:00
Mark Nadal
3733473115 perf notes 2020-03-02 13:14:04 -08:00
Mark Nadal
6f053b6327 restore 2020-02-27 19:45:32 -08:00
Mark Nadal
5a70f506d3 TEMPORARILY disable RAD 2020-02-27 19:40:21 -08:00
Mark Nadal
8f78669997 must be defined undefined 2020-02-25 12:34:47 -08:00
Mark Nadal
e5c06e7491 put debug (dbg) 2020-02-25 12:29:28 -08:00
Mark Nadal
74f6638227 DO NOT PUBLISH! ECHO TEST. 2020-02-25 03:32:42 -08:00
Mark Nadal
9a3225e387 file serve stats 2020-02-25 02:31:34 -08:00
Mark Nadal
105d81f7a6 undo temporary test 2020-02-21 23:53:02 -08:00
Mark Nadal
5bf425d2c4 TEMPORARY test 2020-02-21 23:32:37 -08:00
Mark Nadal
79fac4cb45 fix large records saving to RAD 2020-02-21 22:39:06 -08:00
Mark Nadal
50a7373d00 woops, what? 2020-02-21 19:46:25 -08:00
Mark Nadal
1c29092af8 -log +stat, not gets or dbg yet tho 2020-02-21 16:38:26 -08:00
Mark Nadal
ff04e23b64 fix .pub on account check 2020-02-19 11:47:26 -08:00
Jussi Rytkönen
c7f0acb0df
react todo example: fixes input clear on submit 2020-02-19 14:37:44 +02:00
Mark Nadal
3ab14ffc42 3rd rewrite, have batched acks. 2020-02-17 12:38:46 -08:00
Mark Nadal
699823d578 if emitting chain perf fault, then redo _rad 2020-02-13 00:53:42 -08:00
Mark Nadal
c785a184c1 yet again 2020-02-12 14:32:45 -08:00
Mark Nadal
63d8114791 I want the count 2020-02-12 14:07:27 -08:00
Mark Nadal
f84af3fcd7 more info 2020-02-12 13:56:48 -08:00
Mark Nadal
cac59fbc12 ugh lol finally get this right? 2020-02-12 13:18:06 -08:00
Mark Nadal
fb0e44f4a6 Update gun.js 2020-02-12 13:00:55 -08:00
Hadar Rottenberg
947ee8455c add: update readme with example 2020-02-12 21:25:58 +02:00
Hadar Rottenberg
5016298b45 fix: typo 2020-02-12 21:17:15 +02:00
Hadar Rottenberg
72c699f20b add: restore old crypto package, isomorphic changes things in react-native 2020-02-12 21:07:24 +02:00
Mark Nadal
77263e40b7 allow sort / dynamic prefix on hash? 2020-02-12 11:06:02 -08:00
Mark Nadal
3085579915 check mix time 2020-02-12 09:46:37 -08:00
Mark Nadal
35414daa20 better diagnostics 2020-02-12 09:19:18 -08:00
Mark Nadal
4aadd43248 woops put was too big for email 2020-02-12 07:06:08 -08:00
Mark Nadal
a3383e5617 FIX CHAIN EMIT / ON, add more stats 2020-02-12 06:35:17 -08:00
sirpy
40b47a2621
Update README.md 2020-02-12 10:32:35 +02:00
sirpy
d15721c46d
Update README.md 2020-02-12 10:30:26 +02:00
Hadar Rottenberg
5a1f8350cb fix: match amark master 2020-02-12 10:27:00 +02:00
Hadar Rottenberg
e355d41f60 refactor: remove duplicate 2020-02-12 10:22:36 +02:00
Hadar Rottenberg
ca4b5ae016 Merge remote-tracking branch 'amark/master' 2020-02-12 10:03:51 +02:00
Hadar Rottenberg
a72342431f add: update to use webview-crypto 2020-02-12 09:54:04 +02:00
Mark Nadal
82d8192700 woops that was crashing stuff 2020-02-11 20:38:59 -08:00
Mark Nadal
5253e2084a only check once per disk, not each cb of it 2020-02-11 16:01:42 -08:00
Mark Nadal
c4fc859789
Merge pull request #898 from bluelovers/master
refactor: update types for better extendable
2020-02-11 15:05:08 -08:00
Mark Nadal
4137c52598
Merge pull request #902 from bluelovers/pr/003
fix: bug when import 'lib/then'
2020-02-11 14:52:55 -08:00
Mark Nadal
2801198691
Merge pull request #899 from bluelovers/pr/002
chore: fix log
2020-02-11 14:51:36 -08:00
Mark Nadal
3668f5099f uptime decimal 2020-02-11 14:32:25 -08:00
Hadar Rottenberg
1f3b090f81 add: update dependencies 2020-02-11 10:28:37 +02:00
Mark Nadal
77fda9d42c Update radisk.js 2020-02-10 23:17:15 -08:00
Mark Nadal
ed82e28109 Update rs3.js 2020-02-10 18:50:01 -08:00
Mark Nadal
3c30c52f01 work! 2020-02-10 18:34:29 -08:00
Mark Nadal
d075423ffb crash it 2020-02-10 18:32:15 -08:00
Mark Nadal
48b288280d Update sea.js 2020-02-10 18:25:01 -08:00
Mark Nadal
b45be18ad3 Update sea.js 2020-02-10 18:11:23 -08:00
Mark Nadal
58f8cd0e03 find ugh 2020-02-10 18:07:48 -08:00
Mark Nadal
b101b492d4 duh 2020-02-10 17:58:32 -08:00
Mark Nadal
bc40109e61 fixup 2020-02-10 17:48:39 -08:00
Mark Nadal
d6dae4871e p v b 2020-02-10 15:22:07 -08:00
Mark Nadal
0936c326f8 unit tests passing 2020-02-10 15:13:37 -08:00
Hadar Rottenberg
6f65c6ef26 Merge branch 'amark-master' 2020-02-09 22:28:58 +02:00
Hadar Rottenberg
fd26e39acc Merge branch 'master' of https://github.com/amark/gun into amark-master 2020-02-09 22:28:42 +02:00
Mark Nadal
3127b41f38 full circuit 2020-02-08 02:02:36 -08:00
Mark Nadal
9b188dea72 Update .gitignore 2020-02-06 14:11:47 -08:00
Mark Nadal
e614100c47 Merge branch 'dev' into manhattan 2020-02-06 14:11:39 -08:00
Mark Nadal
e98e51a0ea Merge branch 'master' into manhattan 2020-02-06 14:09:37 -08:00
Mark Nadal
7cf2d42dcd yet another day. 2020-02-06 14:05:27 -08:00
bluelovers
c59e0e95f9 fix: type CryptoKeyPair and rename to IGunCryptoKeyPair 2020-02-06 21:41:12 +08:00
bluelovers
273f7fce8d chore: update type Gun.log 2020-02-06 21:41:11 +08:00
bluelovers
16f911e126 fix: bug when import 'lib/then' 2020-02-06 20:54:42 +08:00
Mark Nadal
89b8f01cda because yeah! 2020-02-05 01:57:11 -08:00
bluelovers
d2512f2842 chore: fix log 2020-02-05 11:00:16 +08:00
bluelovers
90ca38ee7e chore: yarn-tool lockfile --npm --overwrite 2020-02-05 09:32:00 +08:00
bluelovers
4a42a4f1ce refactor: split types node , SEA 2020-02-05 09:24:50 +08:00
bluelovers
4d252a96f7 fix: types chain.then 2020-02-05 09:02:32 +08:00
bluelovers
4e94d7f04e chore: .npmignore 2020-02-05 08:38:51 +08:00
bluelovers
c93149a3a0 refactor: update types for better extendable 2020-02-05 08:37:00 +08:00
bluelovers
248e09c573 split @types/gun 2020-02-05 08:06:20 +08:00
bluelovers
82d7bfad61 copy @types/gun 2020-02-05 07:43:31 +08:00
Mark Nadal
60c98a5ba0
Update install.sh 2020-02-04 02:45:18 -08:00
Mark Nadal
fa8a63606c TODO SPAM, REMEMBER TO UNCOMMIT 2020-02-03 14:26:01 -08:00
Mark Nadal
efd055c2b0 notes & tests 2020-02-03 14:25:41 -08:00
Mark Nadal
827197dbb7 only flamegraph emails 2020-02-03 10:27:49 -08:00
Mark Nadal
a5a0eab24c Update trace.js 2020-02-02 22:59:48 -08:00
Mark Nadal
782750d728 Update trace.js 2020-02-02 22:57:06 -08:00
Mark Nadal
a980f4efc1 ? trace ? tmp 2020-02-02 22:30:13 -08:00
Mark Nadal
75148ec540 Update Procfile 2020-02-02 10:33:37 -08:00
Mark Nadal
d8f3ed7edb Update Procfile 2020-02-02 10:05:10 -08:00
Mark Nadal
c97526a36c Update Procfile 2020-02-02 09:40:59 -08:00
Mark Nadal
cae8264832 Update Procfile 2020-02-02 09:40:49 -08:00
Mark Nadal
6281fed309 Update Aptfile 2020-02-02 09:31:26 -08:00
Mark Nadal
ebfd82eac6 Update Aptfile 2020-02-02 09:27:51 -08:00
Mark Nadal
cc6415fa44 Update Aptfile 2020-02-02 09:24:37 -08:00
Mark Nadal
c5d3ef47e7 try live debug (chrome inspector) 2020-02-02 09:17:43 -08:00
Mark Nadal
d3e89c2adc live debug ? 2020-02-02 01:13:47 -08:00
Mark Nadal
328ae52c2c begin 2020-02-02 01:09:48 -08:00
Mark Nadal
9dfdf608dc skip saving in-mem acks? thrash socket 0? 2020-01-31 05:41:26 -08:00
Mark Nadal
e6b61f667e how long is 1ms in actuality? 2020-01-30 20:36:22 -08:00
Mark Nadal
56488b567e
Merge pull request #897 from jabis/master
webrtc defaults messing at least firefox
2020-01-30 12:44:26 -08:00
Jabis Sevon
bf907d5f87
Merge pull request #1 from jabis/jabis-patch-1
Update webrtc.js
2020-01-31 03:34:18 +07:00
Jabis Sevon
b3f87b180e
Update webrtc.js
The above change corrects at least firefox RTC Peer handler where it **throws** on over 6 ice servers, and updates url: to urls: removing spec deprecation warnings

Left todo: when ICE Fails it throws, and all `.on` and `.open` listeners will fail
2020-01-31 03:32:56 +07:00
Mark Nadal
9dbbf856d3
Declare CDN 2020-01-29 21:42:24 -08:00
Mark Nadal
66361cb6f3
Update README.md 2020-01-29 20:33:27 -08:00
Mark Nadal
fa5fe8a325 refine health 2020-01-29 19:05:52 -08:00
Mark Nadal
6593844ed0 IF email ENV CONFIG set, report slows 2020-01-28 21:36:39 -08:00
Mark Nadal
958d736e0c IF email ENV CONFIG set, report slow parse 2020-01-28 17:15:50 -08:00
Mark Nadal
faa776a8e5 cache remote files, quick ugly test experiment? 2020-01-24 12:02:17 -08:00
Mark Nadal
39d467314a skip lex cursors until fixed 2020-01-24 10:37:52 -08:00
Martti Malmi
9890fb88aa tests for cursor and descending ordering 2020-01-24 15:33:45 +02:00
Martti Malmi
ff9ff71cb2 multicast fix 2020-01-24 15:29:30 +02:00
Mark Nadal
fe3a25682a
Merge pull request #889 from amark/dev
woops THIS is CLOSER to the BIG 2020 RELEASE, don't use old one :P
2020-01-22 23:21:09 -08:00
Mark Nadal
8f874d6f32 try relocate mislocated data on reads 2020-01-22 22:39:02 -08:00
Mark Nadal
ba2b207dd6 hopefully increases limits? 2020-01-22 06:56:57 -08:00
Adriano Rogowski
9f446a08d4 Test for bug-686: Cannot put string 'null' as value in put. SEA error thrown 2020-01-21 20:46:13 -03:00
Mark Nadal
b5fd757db4 dev -> master, master -> 2020-01-21 15:38:31 -08:00
Adriano Rogowski
de85106c42 Test for bug-322: modify returned node in callback leaks thru 2020-01-21 20:37:36 -03:00
Mark Nadal
f8f9cddafe
Merge pull request #882 from amark/dev
THE 2020 MAJOR RELEASE!
2020-01-21 14:55:38 -08:00
Mark Nadal
5c4126bc0a done 2020-01-21 09:34:02 -08:00
Mark Nadal
dc94252f20 crash while deleting s3 2020-01-21 09:32:00 -08:00
Mark Nadal
08fc562eac don't rebuild file index (?) 2020-01-21 00:37:00 -08:00
Mark Nadal
80159888fb max defer timeout, + tmps 2020-01-20 23:43:44 -08:00
Mark Nadal
3d8c8a2f47 don't delete message tracking too soon 2020-01-20 14:20:25 -08:00
Mark Nadal
23420c9f60
Retiring this example due to old security leak of mine that got copy&pasted
Please see https://github.com/amark/gun/issues/880
2020-01-20 09:39:12 -08:00
Mark Nadal
ecf4fda285 Only track msg meta data, renew original request on @, fix faith/raw/rad unique, better GC, GC tracker too. 2020-01-18 17:49:44 -08:00
Mark Nadal
06099bf881 faith must be unique, store glue graph must be reset, try evict on v8 heap limit 2020-01-18 00:30:16 -08:00
Adriano Rogowski
277147acc0 Test file for bug-783 2020-01-14 22:03:54 -03:00
Adriano Rogowski
86c74737f5 Test file for bug-121 2020-01-14 21:59:57 -03:00
Mark Nadal
50ee5c766f
Update README.md 2020-01-14 11:09:47 -08:00
Mark Nadal
db868d0e3a security sticky note ALWAYS has to be unique, CRITICAL 7 letter fix 2020-01-13 13:08:37 -08:00
Hadar Rottenberg
dab91974c1 add: decrypt opposite of secret 2020-01-13 13:00:51 +02:00
Hadar Rottenberg
761030d721 Merge branch 'pr/sirpy/9' 2020-01-13 12:52:39 +02:00
Hadar Rottenberg
af43b394c3 Merge branch 'master' into pr/sirpy/9 2020-01-13 12:49:57 +02:00
Mark Nadal
77be32167f moving forward 2020-01-11 04:39:19 -08:00
Mark Nadal
3547039cba tmp then revert: force s3 list command 2020-01-11 04:25:06 -08:00
Mark Nadal
8d5d6a3ee6 make rad great again, replace file after 2nd half saved already, check for no files, thanks @mhelander 2020-01-11 04:23:33 -08:00
Mark Nadal
08c45c08d4 delete logs 2020-01-10 06:15:05 -08:00
Mark Nadal
e8b5587b99 HNPERF performance tests 2020-01-10 06:07:31 -08:00
Mark Nadal
bbf7791893
Merge pull request #874 from GoodDollar/rnsupport
Rnsupport
2020-01-09 11:58:09 -08:00
Mark Nadal
47b0519117 tmp 2020-01-08 14:31:17 -08:00
Mark Nadal
787ea543b4 tmp 2020-01-07 20:13:51 -08:00
Mark Nadal
ccea6a030c change DAM configs, don't send @ ACK if can't find via trace. 2020-01-07 20:07:34 -08:00
Mark Nadal
5d7e1dd226 tmp 2020-01-07 18:57:59 -08:00
Mark Nadal
a3784d7930 tmp 2020-01-07 18:41:38 -08:00
Mark Nadal
05ba89888f tmp 2020-01-07 18:18:35 -08:00
Mark Nadal
2a450bf3cc tmp 2020-01-07 18:16:32 -08:00
Mark Nadal
e4b4611856 tmp 2020-01-07 17:57:30 -08:00
Mark Nadal
6eab251438 tmp 2020-01-07 17:35:45 -08:00
Hadar Rottenberg
0c27b81993 Merge branch 'rnsupport' of https://github.com/gooddollar/gun into rnsupport 2020-01-07 15:32:30 +02:00
Hadar Rottenberg
f287887e87 fix: force use of isomorphiccrypto on react-native 2020-01-07 15:32:22 +02:00
sirpy
7a08fc400a
Merge branch 'master' into rnsupport 2020-01-07 15:29:51 +02:00
Nicolas Castellanos
de43978382
Merge pull request #8 from GoodDollar/rnsupport-no-scolons
Remove invalid semicolons
2020-01-06 15:48:01 -03:00
sirpy
4b14e7c645
remove semicolons (#7)
Co-authored-by: Nicolas Castellanos <imnicastelo@gmail.com>
2020-01-06 18:08:47 +02:00
Nicolás Castellanos
fcce25df48 remove semicolons 2020-01-06 12:16:17 -03:00
Hadar Rottenberg
4619e57968 fix: unknown issue where global S object is modified, then sign doesnt work 2020-01-06 15:34:58 +02:00
Adriano Rogowski
c7dcbfbd7e test sea - User\'s nodes must be signed when on user scope! issue #850 issue #616 2020-01-05 21:13:44 -03:00
Adriano Rogowski
d9d9e5c5d0 sea - correct path to sea test. 2020-01-05 21:13:28 -03:00
Mark Nadal
4bb9d2dd51 re-enable all stats for demo/testing peers 2019-12-30 12:26:22 -08:00
Mark Nadal
14ebd73d80 bump version 2019-12-30 12:16:45 -08:00
Mark Nadal
8f5ab18fa3
Merge pull request #860 from amark/dev
Dev
2019-12-30 12:06:05 -08:00
Mark Nadal
88a5c8fea0 .open / .load opt meta , axe mob , music -> wave 2019-12-30 11:57:28 -08:00
Mark Nadal
9db8adea2a disconnect duplicate connections thanks to @malsaeed 2019-12-20 15:08:36 -08:00
Mark Nadal
46066fee0d https://gun.eco/docs/DAM#self 2019-12-19 16:08:37 -08:00
Mark Nadal
9caf77dd0c
Update todo.html 2019-12-16 16:32:16 -08:00
Mark Nadal
fc00ed0239
Merge pull request #853 from amark/dev
Dev
2019-12-12 16:28:22 -08:00
Mark Nadal
dedab599d6 micro adjustment for calling a 2nd .once( with undefined 2019-12-12 16:19:34 -08:00
Mark Nadal
8dbd9db17b testing 2019-12-11 11:19:21 -08:00
Mark Nadal
bc87faa8d9 tweak doc 2019-12-10 03:42:09 -08:00
sirpy
512d2c8c32
add: wait for once, so data is returned on first get (#6)
* add: wait for once, so data is returned on first get

* Update then.js
2019-12-08 17:49:48 +02:00
sirpy
29ed57e955
react native support (#5)
* WIP: use isomorphic-webcrypto for RN

* WIP: expo friendly exports

* WIP: buffer for RN

* WIP: textencoder for RN

* WIP: aeskey from jwk instead of raw for RN

* fix: missing taglength for msrcrypto

* add: update isomorphic-webcrypto

* add: match isocrypto api

* add: failing test for 4e2 as 400

* fix: remove extra atob btoa

* add: sea unbuild

* refactor: according to mhelander review

* refactor: shorter require

* fix: make bug test pass, capitlize bug test.

* fix: npm ci + sea test

* add: restore old browser export and add react-native friendly exports

* fix: import buffer into correct global/window

* fix: bad comparison

* fix: only include buffer if no btoa/atob
2019-12-08 17:41:26 +02:00
sirpy
af1590cf60
Merge pull request #4 from amark/master
update to amark/gun master
2019-12-08 17:40:24 +02:00
Mark Nadal
1cd0c08ab0 axe doc music dht :) 2019-12-06 16:24:12 -08:00
Hadar Rottenberg
b2709e2eb7 fix: only include buffer if no btoa/atob 2019-11-29 11:42:47 +02:00
Mark Nadal
d2c4e7c8e8 if wifi off don't crash due to multicast membership 2019-11-23 12:09:02 -08:00
Mark Nadal
1a4a621fd1
Delete tmp.test.sql.js 2019-11-22 23:16:56 -08:00
Mark Nadal
14b1ea1896 Update 4dht.js 2019-11-22 17:59:47 -08:00
Mark Nadal
c1c7c9ec74
Update README.md 2019-11-22 16:15:26 -08:00
Mark Nadal
eece7f91ac merge with @jussiry + correct HUD display 2019-11-22 14:20:09 -08:00
Mark Nadal
3a0b084449
Merge pull request #846 from jussiry/dev
click open, mouse button drag, open cancel disabled
2019-11-22 13:58:39 -08:00
Jussi Rytkönen
b41022ca91 click open, mouse button drag, open canceld disabled 2019-11-22 17:09:29 +02:00
Mark Nadal
79216341e3 docs tweaks 2019-11-22 03:13:40 -08:00
Mark Nadal
b57a7a8013 Update meta.js 2019-11-22 03:10:54 -08:00
Mark Nadal
22547099bd don't cancel user input on meta HUD inputs 2019-11-21 20:49:51 -08:00
Mark Nadal
24aec9f466
Update README.md 2019-11-21 15:23:23 -08:00
Mark Nadal
5a12e30996 clean up 2019-11-21 15:20:39 -08:00
Mark Nadal
48ebe38e08 Create todo.html 2019-11-21 15:17:19 -08:00
Mark Nadal
3f3e973f39
Merge pull request #845 from amark/dev
fix for @capitalistdog @danlugo92
2019-11-21 00:37:31 -08:00
Mark Nadal
5aafbbbff0 version bump to publish fix for fix for @capitalistdog @danlugo92 2019-11-21 00:28:48 -08:00
Mark Nadal
7ac8e29f67 fix for @capitalistdog @danlugo92 + docs & game proto alpha 2019-11-21 00:09:59 -08:00
Hadar Rottenberg
ef49a73e4a fix: bad comparison 2019-11-21 09:12:56 +02:00
Hadar Rottenberg
5172c38913 fix: import buffer into correct global/window 2019-11-21 08:29:40 +02:00
Mark Nadal
21fcdf8693 Merge branch 'dev' of http://github.com/amark/gun into dev 2019-11-20 03:50:09 -08:00
Mark Nadal
79bd5b9827
Merge pull request #843 from jussiry/dev
meta.js alpha version of tap only
2019-11-20 02:44:49 -08:00
Jussi Rytkönen
8dbe77f4d0 meta.js alpha version of tap only 2019-11-20 12:31:51 +02:00
Mark Nadal
56678aa7f5 Merge branch 'dev' of http://github.com/amark/gun into dev 2019-11-17 03:35:25 -08:00
Mark Nadal
e048b897da stuff 2019-11-17 03:35:12 -08:00
Mark Nadal
875de844fb
Merge pull request #838 from Dletta/patch-1
Added missing reference for global obj
2019-11-13 05:46:15 -08:00
Mark Nadal
1895010188
Merge pull request #840 from jussiry/dev
Dev
2019-11-13 01:32:59 -08:00
Jussi Rytkönen
5a58f77a32 meta.js update from edide 2019-11-11 17:38:56 +02:00
Jussi Rytkönen
301f8910fb meta.js update from edide 2019-11-11 17:33:22 +02:00
Mark Nadal
c99ad39c56 Update README.md 2019-11-11 15:27:10 +02:00
Mark Nadal
0a02e7bfaa Update README.md 2019-11-11 15:27:10 +02:00
Mark Nadal
1c3ea91011
Update README.md 2019-11-09 15:25:23 -08:00
Mark Nadal
8dc8b27cd0
Update README.md 2019-11-09 15:22:06 -08:00
Mark Nadal
8da4689fea paste.html ! 2019-11-09 15:02:47 -08:00
Mark Nadal
1ba73dd47b update basics 2019-11-09 14:56:16 -08:00
Mark Nadal
f8bb17e27f paste example 2019-11-09 14:38:02 -08:00
Mark Nadal
b5b4357a5d screen recorder thanks to @JamieRez 2019-11-08 14:58:59 -08:00
Mark Nadal
fa724b5abb test 2019-11-08 08:51:17 -08:00
Jachen Duschletta
ef4b4ff795
Added missing reference for global obj 2019-11-07 13:45:32 -08:00
Mark Nadal
8dc043c44f
Merge pull request #837 from jussiry/master
meta.js ununbound
2019-11-04 15:50:42 -08:00
Jussi Rytkönen
c0224c4d28
meta.js ununbound 2019-11-05 01:02:09 +02:00
Mark Nadal
7c6886857c
Merge pull request #836 from jussiry/master
meta.js modularization
2019-11-04 12:31:58 -08:00
Jussi Rytkönen
42926ec09d meta/edit removed from gitignore 2019-11-04 22:28:23 +02:00
Hadar Rottenberg
325c7b48ed add: restore old browser export and add react-native friendly exports 2019-11-04 13:02:11 +02:00
Hadar Rottenberg
92a4f7ad24 Merge branch 'master' into rnsupport 2019-11-04 12:49:25 +02:00
sirpy
f15281dcd0
Merge pull request #3 from amark/master
update to master
2019-11-04 12:49:00 +02:00
Hadar Rottenberg
209fe60c76 fix: npm ci + sea test 2019-11-04 12:41:43 +02:00
sirpy
e8f15b27e3
fix: make bug test pass, capitlize bug test. 2019-11-04 12:34:03 +02:00
Mark Nadal
1c6d519162
Merge pull request #832 from Dletta/dev
Overview Stats
2019-10-29 11:40:09 -07:00
Jussi Rytkönen
e92bf7b940 modularizes meta.js 2019-10-29 18:06:39 +02:00
Dletta
b916aea3c1 removed neon tube font and made the next best thing, green stuff 2019-10-28 19:57:32 -07:00
Mark Nadal
d69c315023
Merge pull request #833 from BillyNate/readmedeployunebo
Add Unebo as a deploy option
2019-10-28 14:24:10 -07:00
Dletta
d193a332bf Second Iteration
dynamic keys and lines
2019-10-26 16:30:50 -07:00
Dletta
528db20161 Overview Stats
First Draft, non-auto loop version
2019-10-25 23:10:14 -07:00
Mark Nadal
026b278311 temporary push for @Dletta to update stats 2019-10-25 15:44:07 -07:00
Nate
0050eeb89a
Added Unebo to the 'deploy' section of the readme 2019-10-25 23:11:09 +02:00
Martti Malmi
2b82d6211f
Merge pull request #830 from BillyNate/fixw10multicast
Multicast fix for Windows 10
2019-10-24 12:47:05 +03:00
BillyNate
76a5231498 Fixed an error on Windows 10 in multicasting
Fixes #787
2019-10-22 23:25:48 +02:00
Mark Nadal
418b0b22b6
Update README.md 2019-10-22 11:41:23 -07:00
Mark Nadal
d387a4f790 drop chat example until DOM bug fixed 2019-09-30 14:26:55 -07:00
Mark Nadal
e997b4d2d1 unbuild & delete plugins changing defaults 2019-09-30 14:06:29 -07:00
Mark Nadal
4ffcc5b17a Merge branch 'master' of http://github.com/amark/gun 2019-09-30 13:36:47 -07:00
Mark Nadal
df272501c0 update panic test 2019-09-30 13:36:43 -07:00
Mark Nadal
d7de5e7a67
Merge pull request #825 from Dletta/patch-1
Added better error handling into put
2019-09-30 11:29:48 -07:00
Mark Nadal
b40a6a50fc Create 3puts.js 2019-09-30 01:13:13 -07:00
Mark Nadal
247ddee578 temporary fix for logs 2019-09-30 01:12:57 -07:00
Mark Nadal
b3399a4c01
Merge pull request #826 from amark/dev
Dev
2019-09-30 00:53:38 -07:00
Jachen Duschletta
6f2c246146
Added better error handling into put 2019-09-28 20:59:35 -07:00
Mark Nadal
4de57d4014 reduce RAD chunk and try JSON serializing 2019-09-27 02:22:20 -07:00
Mark Nadal
382cbc4798 does this work? don't read if already read? 2019-09-27 01:52:35 -07:00
Hadar
a2086cd09c refactor: shorter require 2019-09-22 00:25:15 +03:00
Hadar
8e7a5369cc refactor: according to mhelander review 2019-09-21 23:09:32 +03:00
Mark Nadal
814d330b8a more logs 2019-09-20 00:55:09 -07:00
Mark Nadal
7cd19b3d67 debug info 2019-09-19 17:00:16 -07:00
Mark Nadal
93cd24caa7
Update bye.js 2019-09-19 05:00:28 -07:00
Hadar
a6fc7fd5c5 add: sea unbuild 2019-09-18 00:22:10 +03:00
Hadar
0804c5ef24 fix: remove extra atob btoa 2019-09-18 00:19:34 +03:00
Hadar
6d798a136f Merge branch 'master' into rnsupport 2019-09-17 23:41:30 +03:00
sirpy
87f69aebc9
Merge pull request #2 from amark/master
update to gun master
2019-09-17 23:37:16 +03:00
Mark Nadal
14f6ba098a
Update README.md 2019-09-17 08:26:42 -07:00
Mark Nadal
ef29f181fe Merge branch 'master' into dev 2019-09-17 03:16:33 -07:00
Mark Nadal
1f0d0d62b0 does puff help? 2019-09-17 03:15:13 -07:00
Mark Nadal
68f4308664 loopit 2019-09-17 01:53:56 -07:00
Mark Nadal
f4526238f3 add more stats 2019-09-17 00:27:39 -07:00
Mark Nadal
3953c17130
Merge pull request #818 from amark/master
merge master INTO dev
2019-09-16 18:12:55 -07:00
Mark Nadal
99ed43f5c4 console.debug -> console.only & unbuild 2019-09-16 13:59:44 -07:00
Mark Nadal
4fb04b8f53 base64 shim 2019-09-16 12:36:18 -07:00
Mark Nadal
89578efd68
Merge pull request #814 from mboperator/sea-switch-to-webcrypto
[SEA] Migrate from `node-webcrypto-ossl` to `@peculiar/webcrypto`
2019-09-16 10:09:04 -07:00
Mark Nadal
12d61ace2c
DROPPING NODEJS 8 SUPPORT!!!! 2019-09-16 10:04:38 -07:00
Hadar
932ff99c58 add: failing test for 4e2 as 400 2019-09-15 01:14:18 +03:00
Hadar
a0ab6931d1 add: match isocrypto api 2019-09-15 01:14:01 +03:00
Marcus Bernales
cf642b75d1 Brought back new changes 2019-09-14 13:20:21 -07:00
Marcus Bernales
7d7b11f9b8 Reset unnecessary prettier changes 2019-09-14 13:19:27 -07:00
Marcus Bernales
7b583f3b41 Remove unnecessary console.log 2019-09-14 13:13:40 -07:00
Marcus Bernales
0b03702152 Update package-lock for travis 2019-09-14 13:08:40 -07:00
Marcus Bernales
71e0be33f7 Switched to webcrypto 2019-09-14 12:56:48 -07:00
Hadar
2027012379 add: update isomorphic-webcrypto 2019-09-14 22:33:19 +03:00
Hadar
502dd9a3db fix: missing taglength for msrcrypto 2019-09-11 16:36:47 +03:00
Hadar
0b31971678 WIP: aeskey from jwk instead of raw for RN 2019-09-11 09:46:08 +03:00
Mark Nadal
2f0d2e3ade version bump for upcoming RAD fixes (currently not all done) 2019-09-10 14:48:10 -07:00
Mark Nadal
ab69258633 adjust format after merge 2019-09-10 14:45:47 -07:00
Mark Nadal
78ae966813 Merge branch 'master' of http://github.com/amark/gun 2019-09-10 14:40:39 -07:00
Mark Nadal
6af5b6c2ac fix SOME of RAD due to GUN queue growing too deep 2019-09-10 14:40:34 -07:00
Hadar
0311969060 WIP: textencoder for RN 2019-09-11 00:21:21 +03:00
Hadar
a2a7ef91bb WIP: buffer for RN 2019-09-11 00:10:59 +03:00
Hadar
5d352d90c9 WIP: expo friendly exports 2019-09-10 23:47:19 +03:00
Hadar
209909ce94 WIP: use isomorphic-webcrypto for RN 2019-09-10 23:30:00 +03:00
Mark Nadal
8a44eb7f62
Merge pull request #810 from GoodDollar/SEA-concurrent-possible-fix
SEA concurrent possible fix
2019-09-06 01:29:10 -07:00
Hadar
0725190a94 Merge remote-tracking branch 'origin/master' into SEA-concurrent-possible-fix 2019-09-05 14:54:13 +03:00
sirpy
fc4a23e148
Merge pull request #1 from amark/master
update to latest gun
2019-09-05 14:53:31 +03:00
Hadar
9fc0adbbe6 add: reflect change in sea.js 2019-09-05 14:40:24 +03:00
Mark Nadal
0a4af74ea9
Merge pull request #809 from Dletta/promise
added promise wrappers to core API
2019-09-04 09:35:12 -07:00
Dletta
d299a99a57 added promise wrappers to core API 2019-09-03 21:37:02 -07:00
Mark Nadal
a34e90e868 for testing @rogowski 's awesome work 2019-08-29 14:43:47 -07:00
Mark Nadal
aa558f0706 don't crash if multicast offline 2019-08-29 14:29:08 -07:00
Mark Nadal
0515403716 use @Artoria2e5 's gold 2019-08-29 14:28:43 -07:00
Mark Nadal
1101c06130 this screwed up RAD folders, undo 2019-08-29 14:28:08 -07:00
Mark Nadal
d148f46d30
Merge pull request #803 from Dletta/then
proposed lib/then
2019-08-29 13:43:58 -07:00
Mark Nadal
a52f9ef3f4
Merge branch 'master' into then 2019-08-29 13:43:47 -07:00
sirpy
597bb77a98
fix: Object.assign modiifies S.ecdh which should be static 2019-08-29 10:54:02 +03:00
Dletta
e0c93228ee proposed lib/then 2019-08-26 21:00:22 -07:00
sirpy
203a80a430
revert argv2 2019-08-20 15:26:11 +03:00
Mark Nadal
9ac94db8b3
Merge pull request #798 from shamsartem/feature-css-fix
Feature css fix
2019-08-19 10:43:28 -07:00
Artsiom Shamsutdzinau
b1aab8cd0f Fix css for chat and todo apps 2019-08-19 13:48:24 +03:00
Mark Nadal
44f5e22bdc
Merge pull request #793 from Tedko/patch-1
Seems like gun-show no longer exist anymore?
2019-08-15 01:27:44 -07:00
Suji Yan
a7083105b6
Seems like gun-show no longer exist anymore?
Trying to find a community solution for GunDB Viewer, seems like gun-show no longer exist. Any idea of any alternative one?

Also @amark  pls double check the status of gun-show. Thanks.
2019-08-14 13:04:12 +08:00
Mark Nadal
37d6d47462
Merge pull request #785 from rogowski/master
RADISK - better performance.
2019-08-05 14:44:44 -07:00
Adriano Rogowski
b4d5f3becc RADISK - better performance. 2019-08-03 01:39:27 -03:00
Mark Nadal
3a7975a235 array options shouldn't be ignored 2019-07-29 15:10:55 -07:00
Mark Nadal
9839f65a69 Merge branch 'master' of http://github.com/amark/gun 2019-07-29 14:43:30 -07:00
Mark Nadal
8dee34d6dc fix #769 for @TensorTom @go1dfish 2019-07-29 14:43:09 -07:00
Mark Nadal
d729ab940f
Merge pull request #782 from skzap/patch-1
Update README.md
2019-07-28 08:14:39 -07:00
heimindanger
f3c925a857
Update README.md
```
npm ERR! code E404
npm ERR! 404 Not Found: @trust/crypto@latest
```

npm module @trust/crypto does not exist anymore
2019-07-28 15:40:03 +02:00
Mark Nadal
cc276a6862 uuid fix (?) for @go1dfish 2019-07-27 19:43:19 -07:00
Mark Nadal
e1ae0158a4 mix node 2019-07-26 15:11:40 -07:00
Mark Nadal
e5589d435c Merge branch 'master' of http://github.com/amark/gun 2019-07-24 15:03:56 -07:00
Mark Nadal
c4864c214b afore! test? 2019-07-24 15:03:54 -07:00
Mark Nadal
8431dce0b9
Merge pull request #772 from negue/fix/lib/open
fix null doc
2019-07-17 11:05:51 -07:00
negue
959e8e36bb
fix null doc 2019-07-17 18:51:47 +02:00
Mark Nadal
68ba4dcc65 need to fix opt more, but hopefully quick fix on axe reconfig that @SunriseFox pointed out 2019-07-17 05:57:31 -07:00
Mark Nadal
3277ba4127 unbuild fixes/updates 2019-07-15 17:03:14 -07:00
Mark Nadal
ced1e20ecc improve .once, but need to review it more/again later 2019-07-15 16:56:06 -07:00
Mark Nadal
9a6495dc21 fix webrtc 2019-07-14 23:38:57 -07:00
Mark Nadal
eb313d6f65 don't make another websocket server when options/config live update 2019-07-14 02:09:25 -07:00
Mark Nadal
ab36283b2e GUN: -peer, once fix, +multicast; AXE +peer +email 2019-07-12 12:17:08 -07:00
Mark Nadal
0c718c8658 hot as a meta doll 2019-07-04 16:40:22 -07:00
Mark Nadal
e52496ae76 allow for COR(B) stats 2019-06-28 13:23:38 -07:00
Mark Nadal
7ce2dc9056 tweak? 2019-06-28 12:45:18 -07:00
Mark Nadal
b2db5f6b43
Merge pull request #761 from amark/debug
axe -> debug -> master -> npm
2019-06-14 04:38:07 -07:00
Mark Nadal
2741996002 bump ossl & ws 2019-06-14 04:32:54 -07:00
Mark Nadal
5b38d06bcb bump ossl 2019-06-14 04:27:02 -07:00
Mark
6033abbdd9 reduce ? 2019-06-14 03:22:12 -07:00
Mark
7bec7ce5a0 go back to routing put 2019-06-13 15:15:59 -07:00
Mark
162061259a test no put route for peer = out count (?) 2019-06-13 15:04:46 -07:00
Mark
6eaa0f5fa6 rad stats 2019-06-13 12:55:47 -07:00
Mark
48f9d10e2a un-indent, woah git diff :/ 2019-06-12 15:01:56 -07:00
Mark
dc42f63204 axe put routes 2019-06-12 01:18:54 -07:00
Mark Nadal
86043aa89e heartbeat is needed? 2019-05-28 02:02:42 -07:00
Mark Nadal
c4ba41c4b8 try axe 2019-05-28 00:36:28 -07:00
Mark Nadal
866593343d
Merge pull request #756 from amark/master
master into debug
2019-05-28 00:31:09 -07:00
Mark Nadal
9f7c530922
Merge branch 'debug' into master 2019-05-28 00:24:31 -07:00
Mark Nadal
cfd7d1042d "fix" holy grail, unbuild. 2019-05-28 00:14:23 -07:00
Mark Nadal
4aac986e94 distribute & cap load 2019-05-27 22:06:38 -07:00
Mark Nadal
209bdf2b06 refactor DAM & add PANIC tests 2019-05-26 04:33:00 -07:00
Mark Nadal
a786944ed6 finally fix pid , I'm sure @rogowski will be delighted! 2019-05-21 00:21:02 -07:00
Mark Nadal
a6a5aec76f have AXE use DAM. 2019-05-20 20:46:55 -07:00
Mark Nadal
5b1a2d1b28 peer duration time 2019-05-20 04:40:26 -07:00
Mark Nadal
c9b0a05ee7 force stop test 2019-05-16 16:25:33 -07:00
Mark Nadal
2945c42ba2 Merge remote-tracking branch 'origin/debug' into debug 2019-05-16 16:23:27 -07:00
Mark Nadal
f82cb32a54
Merge pull request #750 from amark/master
master into debug
2019-05-16 16:22:59 -07:00
Mark Nadal
455e9f9c91 more stats to debug perf 2019-05-16 03:14:26 -07:00
Mark Nadal
ed30911ba7 fix peer leak + more stats 2019-05-15 10:27:57 -07:00
Mark Nadal
9b820287d6 :( make sure test wasn't false not false positive :( for @go1dfish 2019-05-14 11:01:27 -07:00
Mark Nadal
abac11d959 version bump, maybe peer leak fix, @go1dfish feature ++ 2019-05-14 00:51:06 -07:00
Mark Nadal
124d0146c8 fix possible peer leak & add feature for @go1dfish 2019-05-14 00:45:04 -07:00
Mark Nadal
083c1c59f8 visualize memory 2019-05-10 12:47:04 -07:00
Mark Nadal
2b899aeb93
Merge pull request #738 from eugenioclrc/master
Missing condition in rs3
2019-05-07 19:58:45 -07:00
Mark Nadal
3bee20dd8a
Merge branch 'master' into master 2019-05-07 19:57:40 -07:00
Mark Nadal
86e78f1e5d
Merge pull request #746 from sirpy/patch-1
fix: settings can be from opts or from process.env
2019-05-07 19:56:25 -07:00
sirpy
ed9b234c21
fix: settings can be from opts or from process.env 2019-05-06 23:46:35 +03:00
Mark Nadal
1c44bf900e
Merge pull request #744 from nuragic/patch-1
Update nts.html
2019-05-06 11:33:11 -07:00
Andrea Puddu
4c8eb2c112
Update nts.html
Change font family to monospace to prevent the text moving
2019-05-03 12:21:27 +02:00
Mark Nadal
a111e20f27 fix Lex lookups 2019-04-27 15:06:00 -07:00
Mark Nadal
b78e73a32b stats! version bump 2019-04-27 11:55:08 -07:00
Mark Nadal
bf40e7e152 tomap + stats 2019-04-27 11:54:25 -07:00
Mark Nadal
2071512b20 add health stats 2019-04-27 00:16:12 -07:00
Mark Nadal
e9fc38ddd1 disable multicast by default :( 2019-04-26 16:10:56 -07:00
Mark Nadal
16634cf023 bump version 2019-04-26 16:03:57 -07:00
Mark Nadal
2d541f9529 fix queue issue 2019-04-26 16:03:33 -07:00
Mark Nadal
da431c06bc fix tests to not delete folder while running 2019-04-25 20:10:08 -07:00
Mark Nadal
ecffdce786 same process instances should share RAD plugins for same file options to prevent corruption 2019-04-25 20:10:08 -07:00
Mark Nadal
782f66cd49
Merge pull request #741 from go1dfish/patch-4
Fix for gc_info_enable
2019-04-25 13:51:45 -07:00
go1dfish
33893e40b8
Fix for gc_info_enable 2019-04-25 13:48:50 -07:00
Mark Nadal
2c8abba79c
call next in put 2019-04-25 13:22:23 -07:00
Mark Nadal
32a68c2d4d fix Reverse RAD! 2019-04-23 13:28:05 -07:00
Mark Nadal
1abcfe0c83 radix empty end should be infinite 2019-04-22 18:14:02 -07:00
Mark Nadal
4b247628e7 fix / merge. REVERSE RAD! 2019-04-22 17:46:26 -07:00
Mark Nadal
4085a4053c Reverse RAD! 2019-04-22 17:44:38 -07:00
Mark Nadal
98a1290cbc
Merge pull request #739 from toyoko-we/fix
bye.js fix (support new mesh)
2019-04-22 14:13:42 -07:00
Yusuke Sano
f7d9089ba7 bye.js fix (support new mesh)
I am using gundb 0.8.1 0.2019.331 and noticed not working bye method when programming web application on this version.
Maybe this is happened because bye() access to outdated mesh structure.
2019-04-21 17:45:39 +09:00
Mark Nadal
e7e9c35d69
Merge pull request #737 from rogowski/master
AXE - change necessary to work webrtc.
2019-04-20 18:39:23 -07:00
eugenioclrc
29519b0ebd missing condition in rs3
The condition if(!process.env.AWS_S3_BUCKET){ return } force you tu have
env variables, if you config s3 via Gun constructor you could never use
s3
2019-04-20 22:05:23 -03:00
Adriano Rogowski
b99202f0ec AXE - change necessary to work webrtc. 2019-04-20 21:28:04 -03:00
Mark Nadal
9cb1a52fc0 RAD lexical cursors! 2019-04-19 16:57:33 -07:00
Mark Nadal
0bdaf053f0 initial RAD > < but need to decide default behavior 2019-04-19 00:29:38 -07:00
Mark Nadal
d8ce093e9f merge updates with @JK0N 's 2019-04-16 18:27:16 -07:00
Mark Nadal
8bc815e827
Merge pull request #527 from JK0N/master
Fix serve.js module, prevent access to files in parent directories.
2019-04-16 18:24:49 -07:00
Mark Nadal
2e41cef16b
Merge branch 'master' into master 2019-04-16 18:24:42 -07:00
Mark Nadal
7ae2f3d1ec
Merge pull request #733 from rogowski/master
Small change, but necessary.
2019-04-16 18:08:06 -07:00
Mark Nadal
8a36d0863a
Merge branch 'master' into master 2019-04-16 18:05:20 -07:00
Mark Nadal
d947059d5c MULTICAST!!! RAD * update, start start 2019-04-16 17:46:49 -07:00
Mark Nadal
1e20fd5761
Merge pull request #735 from amark/feature-multicast
Multicast transport
2019-04-16 16:45:42 -07:00
Martti Malmi
d11abeb781 gun multicast transport 2019-04-16 16:17:25 -07:00
Martti Malmi
fde74e1254 Merge branch 'master' into feature-multicast 2019-04-15 12:55:41 -07:00
Mark Nadal
4f2035aeb9 improve CSS, Meta Editor, & CDN. 2019-04-13 17:08:38 -07:00
Adriano Rogowski
d3f0d326b2 Testing passing.
`npm run testaxe`

Dont repeat rtc.nnounce.
2019-04-10 21:15:27 -03:00
Adriano Rogowski
ed509d0ae3 Merge branch 'master' of https://github.com/amark/gun 2019-04-08 19:16:53 -03:00
Mark Nadal
6b1af72038 quick fix 2019-03-31 12:28:27 -07:00
Mark Nadal
11c5087a83 less 2019-03-25 02:48:00 -07:00
Mark Nadal
4cada84ed5
1M rindex !!!
Rad
2019-03-23 18:29:42 -07:00
Mark Nadal
c071c6ff3e user refresh wait for storage? 2019-03-23 18:18:58 -07:00
Mark Nadal
d3b048085d rindex 1M !!! 2019-03-23 18:07:07 -07:00
Mark Nadal
bc742aab0d RAD rindexed radisk! 2019-03-23 15:21:58 -07:00
Mark Nadal
116a2521df tweaks 2019-03-21 14:39:23 -07:00
Adriano Rogowski
f7a5937ed5 AXE - chancher lib/super.js to use Rad instead of json plain object. 2019-03-10 17:31:13 -03:00
Adriano Rogowski
f92da9b14d AXE - merge with amark's gun master. 2019-03-10 17:29:45 -03:00
Adriano Rogowski
16a34c1d0c Change mesh to _. 2019-03-10 16:40:56 -03:00
Adriano Rogowski
b4f760f1b5 Pull with amark master 2019-03-10 16:40:06 -03:00
Mark Nadal
2baa85c082 break RAD 2019-02-22 10:58:30 -08:00
Martti Malmi
be4574840a add /gun to peer url 2019-02-12 13:49:24 +02:00
Martti Malmi
6795ef04a8 better env detection 2019-02-12 11:20:54 +02:00
Martti Malmi
5f153a4912 lib/multicast.js module for finding local peers 2019-02-12 11:20:54 +02:00
Mark Nadal
848a244c39 RAD * limit 2019-02-10 20:44:12 -08:00
Mark Nadal
c32a8f39ee RAD * demo! 2019-02-10 03:04:10 -08:00
Mark Nadal
85d6fc9e57 RAD * 2019-02-10 02:55:51 -08:00
Mark Nadal
de3a2f4b33
Merge pull request #702 from amark/master
Master into RAD
2019-02-05 16:42:48 -08:00
Mark Nadal
1fe9daafde
Merge pull request #701 from amark/dev
Dev
2019-02-05 16:24:38 -08:00
Mark Nadal
64e8b03f37 Merge branch 'master' into dev 2019-01-31 05:37:53 -08:00
Mark Nadal
c243d71e71 link and normalize 2019-01-31 05:37:49 -08:00
Mark Nadal
c5b1906c47
Merge pull request #700 from amark/dev
fix sea set
2019-01-31 05:05:14 -08:00
Mark Nadal
2aae735960 bump 2019-01-31 04:57:44 -08:00
Mark Nadal
b9edb1de15 party 2019-01-31 04:46:34 -08:00
Mark Nadal
a96a80ce66 set gun ref with SEA causes race condition while crypto op happen, cache dub 2019-01-30 23:41:30 -08:00
Mark Nadal
7f4bfd4a60 Merge branch 'master' into dev 2019-01-28 00:43:46 -08:00
Mark Nadal
ff28c1657e meta not metae 2019-01-27 18:30:54 -08:00
Mark Nadal
18408f6ab3
Merge pull request #699 from amark/dev
Dev
2019-01-27 18:28:52 -08:00
Mark Nadal
858b5d1cf7 unbuild peer not founds fix 2019-01-27 18:25:01 -08:00
Mark Nadal
ebb7fe8ca8 fix peer not founds 2019-01-27 18:22:21 -08:00
Mark Nadal
4d40ec72ad Merge branch 'master' into dev 2019-01-27 15:06:20 -08:00
Mark Nadal
c5cd72a631 unbuild 2019-01-27 15:03:43 -08:00
Mark Nadal
428f7e9d1c Merge branch 'master' into dev 2019-01-26 02:13:21 -08:00
Adriano Rogowski
7bc146bcce AXE - new test and example for webrtc. 2019-01-22 22:55:36 -02:00
Adriano Rogowski
803c5b6ee0 AXE - changes for radix DHT. 2019-01-22 22:54:22 -02:00
Adriano Rogowski
259857453a GUN - changes to AXE with radix. 2019-01-22 22:53:49 -02:00
Mark Nadal
6c08ebaea3 unbuild 2019-01-16 10:28:16 -08:00
Mark Nadal
a07cfaaeac
Merge pull request #689 from 71/patch-1
Make node-webcrypto-ossl an optional dependency.
2019-01-15 16:47:33 -08:00
Grégoire Geis
6b54932427
Make node-webcrypto-ossl an optional dependency.
`node-webcrypto-ossl` is a native Node package, and will only be used in a very specific instance (using SEA from Node).

In my case, and I suppose in many others', SEA in Node will never be used.

I'd like to have that dependency made optional, since a failure to require it [is already handled](535d6569fc/sea.js (L183)). Furthermore on Windows it requires the entire native build toolchain to be installed, which is not ideal for such a small feature.
2019-01-16 01:14:59 +01:00
Mark Nadal
08b375df48
Merge pull request #678 from go1dfish/patch-3
Fix apparent copy/paste error in rindexed.js
2019-01-15 16:08:29 -08:00
Mark Nadal
b51acbf615
Merge pull request #679 from masterex1000/master
Add options to les.js
2019-01-15 16:07:29 -08:00
Mark Nadal
535d6569fc
Merge pull request #688 from amark/sea
Sea
2019-01-15 11:24:30 -08:00
Mark Nadal
93e14d8f74 Merge branch 'master' into sea 2019-01-15 10:51:51 -08:00
Mark Nadal
111953a1bf patch + update .mesh to _ 2019-01-15 10:51:48 -08:00
Adriano Rogowski
7bb3aa250e AXE - First PANIC test. 2019-01-10 20:44:20 -02:00
Adriano Rogowski
1869f09a4c Turning on AXE. 2019-01-10 20:38:10 -02:00
Adriano Rogowski
25db64527c Only remove log in axe. 2019-01-10 20:18:03 -02:00
Adriano Rogowski
a6f12af8da Revert changes in gun to solve peer.id undefined. Don't need this change now because we are not using the peer.id in the subscriptions. Maybe will add this in the future. 2019-01-10 20:16:35 -02:00
masterex1000
2462e4f33d Fix USELOCALGUN setting from last commit 2019-01-10 08:38:08 -07:00
masterex1000
cb9b4b8013 More Changes To Les! 2019-01-10 08:20:52 -07:00
masterex1000
810692e2c1 add options to les.js 2019-01-07 08:12:35 -07:00
masterex1000
38b65ff9ea add a bunch options for les.js 2019-01-07 08:09:01 -07:00
go1dfish
91bd68e1f3
Fix apparent copy/paste error in rindexed.js
Looks like this should be doPut instead of doGet since doGet is not defined in this scope.
2019-01-07 04:03:26 -08:00
=
88316e78fb Merge branch 'master' of https://github.com/amark/gun 2019-01-04 22:46:21 -07:00
Mark Nadal
b08eac1a7d dabbles 2019-01-02 21:23:04 -08:00
Adriano Rogowski
dd3d4c3066 Gun Mesh - remove queue from mesh.hi. 2019-01-01 18:30:52 -02:00
Adriano Rogowski
fe7576ee66 GUN - changes to fix peer.id undefined. @amark please validate this change. 2019-01-01 10:40:11 -02:00
Mark Nadal
2130460ef7 Merge branch 'master' into dev 2018-12-24 15:33:56 -08:00
Adriano Rogowski
6d12b3d5a9 Gun - mesh. Putting the dam message first solve the problem of the first gun 'in' event come without peer.id. 2018-12-20 21:10:02 -02:00
Adriano Rogowski
51b98ba370 Merge https://github.com/amark/gun 2018-12-20 09:09:26 -02:00
Adriano Rogowski
83f2aec1e3 Log for when peer.id is undefined. 2018-12-02 17:18:42 -02:00
Adriano Rogowski
6fd0e88dd5 Merge https://github.com/amark/gun 2018-11-30 22:43:00 -02:00
Adriano Rogowski
e2a7dba29f AXE - using a garbage collector to remove subscribes from superpeer and resubscribe from peers (browser). 2018-11-30 21:50:40 -02:00
Adriano Rogowski
1e8bece479 Solve: require Gun in Mesh. 2018-11-28 07:31:38 -02:00
masterex1000
5cfa492d7d Add les.js (Memory Evict) 2018-09-26 17:32:22 -06:00
Mark Nadal
fc4f3c5157 Merge branch 'master' into debug 2018-05-23 23:18:33 -07:00
Jouni
960031ca4f Fix serve.js module, prevent access to files in parent directories. It's a bad idea to have your code serve your source code but if it needs to be done, this will prevent the most obvious leaks (curl -v --path-as-is 'http://localhost:8080/gun/../../.env') 2018-04-10 18:56:41 +03:00
376 changed files with 88494 additions and 34086 deletions

View File

@ -1,4 +1,6 @@
node_modules
radata
stats.radata
.git
.gitignore
*.md

12
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: amark
patreon: gunDB
open_collective: gun
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

114
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,114 @@
name: ci
on:
- push
- pull_request
jobs:
test:
strategy:
matrix:
node-version: [ 14.x ]
os: [ ubuntu-latest ]
runs-on: ${{ matrix.os }}
steps:
# checkout the code
- name: Checkout
uses: actions/checkout@v2
# verify the version in package.json matches the release tag
- name: Version
uses: tcurdt/action-verify-version-npm@master
# setup the node version
- name: Setup Node ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
# cache node_modules if we can
- name: Cache
id: cache-modules
uses: actions/cache@v2
with:
path: node_modules
key: ${{ matrix.node-version }}-${{ runner.OS }}-build-${{ hashFiles('package.json') }}
# ottherweise run install
- name: Install
if: steps.cache-modules.outputs.cache-hit != 'true'
run: npm install
# run tests
- name: Test
run: npm test
# create github release
release:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
needs: [ test ]
runs-on: ubuntu-latest
steps:
# create github release (which triggers the release workflows)
- name: Release
uses: softprops/action-gh-release@v1
# env:
# GITHUB_TOKEN: ${{ secrets.PAT }}
# # publish latest master or release to dockerhub
# dockerhub:
# if: github.event_name == 'push'
# needs: [ test ]
# runs-on: ubuntu-latest
# env:
# image: ${{ secrets.DOCKERHUB_USERNAME }}/gun
# steps:
# - name: Checkout
# uses: actions/checkout@v2
# - name: Login
# env:
# DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
# DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
# run: echo -n ${{ secrets.DOCKERHUB_TOKEN }} | docker login -u ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin
# - name: Build
# run: |
# echo "SHA=$GITHUB_SHA"
# docker build --build-arg SHA=$GITHUB_SHA \
# BUILD_DATE=$(date +'%Y-%m-%dT%H:%M:%S') \
# VCS_REF=${GITHUB_REF} \
# VCS_URL=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY} \
# VERSION=${GITHUB_REF##*/} \
# SHA=$GITHUB_SHA \
# --label "SHA=$GITHUB_SHA" \
# --tag ${{ env.image }}:${GITHUB_REF##*/} \
# --tag ${{ env.image }}:latest \
# .
# - name: Push
# run: docker push ${{ env.image }}
# publish release to npm
npm:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
needs: [ test ]
# needs: [ release ]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Publish
env:
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
run: |
npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN
npm install
npm publish --access=public

8
.gitignore vendored
View File

@ -7,7 +7,15 @@ yarn.lock
.idea/
*.bak
*.new
*.log
v8.json
*.DS_store
isolate*.log
.esm-cache
.sessionStorage
.localStorage
/types/**/*.ts
!/types/**/*.d.ts
!/types/**/*.test-d.ts
/gun.ts
/temp/

5
.npmignore Normal file
View File

@ -0,0 +1,5 @@
*.ts
/temp/
!*.d.ts
*.radata
isolate-*

1
.prettierignore Normal file
View File

@ -0,0 +1 @@
*

View File

@ -2,9 +2,9 @@ language: node_js
branches:
except:
- debug
- manhattan
node_js:
- 8
- 10
cache:
directories:
- node_modules
- node_modules

View File

@ -1,20 +1,26 @@
# CHANGELOG
## 0.2020.x
`>0.2020.520` may break in-process `gun1` `gun2` message passing. Check `test/common.js` "Check multi instance message passing" for a hint and/or complain on community chat.
- No breaking changes to core API.
- Storage adapter `put` event breaking change (temporary?), RAD is official now and storage adapters should be RAD plugins instead of GUN adapters.
- GUN soul format changed from being a random UUID to being a more predictable graph path (of where initially created) to support even better offline behavior. This means `null`ing & replacing an object will not create a new but re-merge.
- Pretty much all internal GUN utility will be deleted, these are mostly undocumented but will affect some people - they will still be available as a separate file but deprecated.
- As the DHT gets implemented, your relay peers may automatically connect to it, so do not assume your peer is standalone. `Gun({axe: false` should help prevent this but loses you most scaling properties.
- The 2019 -> 2020 "changes" are happening gradually, based on experimental in-production tests.
- As always, **most important** is to ask in the [community chat](http://chat.gun.eco) if you have any issues, and to keep up to date with changes.
## 0.2019.x
Some RAD & SEA data format changes, but with as much backward compatibility as possible, tho ideally should be dropped.
## 0.9.x
No breaking changes, but the new Radix Storage Engine (RSE) has been finally integrated and works with S3 as a backup. Expect an order of magnitude or more in cost savings, we'll report our December bill compared to November when we get it.
No breaking changes, but the new Radix Storage Engine (RSE) has been finally integrated and works with S3 as a backup.
We have successfully benchmarked it against **1,000,000 records** doing end-to-end triple verification using our Jepsen-inspired [PANIC](https://github.com/gundb/panic-server) distritubed testing framework, doing **~4K acked writes/second** on a Macbook Air dev machine. For more information on PANIC, check out this [5 minute presentation](https://youtu.be/nTbUCTgLmkY) we did in Sweden (and the prior talk, for those interested in [porting GUN](https://github.com/amark/gun/wiki/porting-gun) out of its reference implementation of JS).
> Warning: There is a known rare edge case in RSE currently, if data is split between two chunked files, a GET will only return from the first chunk. This will be fixed soon, but we still encourage developers to run and test against it, please report any problems.
To use RSE, initialize a gun server peer with the default storage disabled, like `Gun({localStorage: false})`. Want to use it with S3? All you need to do is make sure that your environment variables are configured and it will automatically use S3, here is a [template](https://github.com/amark/gun/wiki/Using-Amazon-S3-for-Storage). This works especially well for our 1-click-deploy Heroku [demo server](http://gunjs.herokuapp.com/) with the example apps.
Finally, with **end-to-end encryption** being enabled with our Security, Encryption, Authorization (SEA) framework (check out our [P2P/decentralized crypto-identity blockchain](https://github.com/amark/gun/wiki/auth)), gun is marching towards a stable v1.0 production-ready system (it is already being used in production by a Northern European government's Navy). So if you are able to [work around the remaining bugs](https://github.com/amark/gun/issues), we would appreciate everybody efforts in experimenting and testing out gun and reporting any last hiccups **in our lead up to the v1.0**!
We will be **overhauling documentation in this v0.9.x series**, please make complaints about what is missing, and how we can make it better, so it will be polished for the v1.0! The [chatroom is actively and friendly for help](https://gitter.im/amark/gun), [StackOverflow](https://stackoverflow.com/questions/tagged/gun) for questions. And we're looking for [sponsors](https://www.patreon.com/gunDB), we **regularly get 1,200+ uniques every 2 weeks** on this repo, we've had **53% monthly growth** on our installs, and GUN is ranked in the top quarter of the top 1% of the top 1% fastest growing projects across all GitHub! If you are an Enterprise, this would be a great time to chat with us about our IoT, AI/ML, edge computing, graph, and cybersecurity solutions.
Here is towards a v1.0! Cheers.
// Edit: commentary removed.
## 0.8.x

View File

@ -1,5 +1,15 @@
FROM alpine:latest
# Build-time metadata as defined at http://label-schema.org
# install packages
FROM node:lts-alpine as builder
RUN mkdir /work
WORKDIR /work
RUN apk add --no-cache alpine-sdk python3
COPY package*.json ./
RUN mkdir -p node_modules
RUN npm ci --only=production
# fresh image without dev packages
FROM node:lts-alpine
# build-time metadata as defined at http://label-schema.org
ARG BUILD_DATE
ARG VCS_REF
ARG VCS_URL
@ -12,15 +22,14 @@ LABEL org.label-schema.build-date=$BUILD_DATE \
org.label-schema.vendor="The Gun Database Team" \
org.label-schema.version=$VERSION \
org.label-schema.schema-version="1.0"
# org.label-schema.description="Let it be pulled from Readme.md..." \
WORKDIR /app
ARG SHA
RUN mkdir /work
WORKDIR /work
COPY --from=builder /work/node_modules ./node_modules
RUN npm rebuild -q
ADD . .
ENV NPM_CONFIG_LOGLEVEL warn
RUN apk update && apk upgrade \
&& apk add --no-cache ca-certificates nodejs-npm \
&& apk add --no-cache --virtual .build-dependencies python make g++ \
&& npm install \
&& apk del .build-dependencies && rm -rf /var/cache/* /tmp/npm*
RUN echo "{ \"sha\": \"$SHA\" }" > version.json
RUN cat version.json
EXPOSE 8080
EXPOSE 8765
CMD ["npm","start"]

View File

@ -1 +1 @@
web: node --optimize_for_size --gc_interval=100 examples/http.js
web: node --inspect examples/http.js

207
README.md
View File

@ -1,64 +1,73 @@
<p><a href="https://gun.eco/"><img width="40%" src="https://cldup.com/TEy9yGh45l.svg"/></a><img width="50%" align="right" vspace="25" src="https://gun.eco/see/demo.gif"/></p>
<p id="readme"><a href="https://gun.eco/"><img width="40%" src="https://cldup.com/TEy9yGh45l.svg"/></a><img width="50%" align="right" vspace="25" src="https://gun.eco/see/demo.gif"/></p>
[![npm](https://img.shields.io/npm/dm/gun.svg)](https://www.npmjs.com/package/gun)
[![Travis](https://img.shields.io/travis/amark/gun/master.svg)](https://travis-ci.org/amark/gun)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Famark%2Fgun.svg?size=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Famark%2Fgun?ref=badge_shield)
[![Gitter](https://img.shields.io/gitter/room/amark/gun.js.svg)](https://gitter.im/amark/gun)
[![](https://data.jsdelivr.com/v1/package/npm/gun/badge?style=rounded)](https://www.jsdelivr.com/package/npm/gun)
[![](https://data.jsdelivr.com/v1/package/npm/gun/badge)](https://www.jsdelivr.com/package/npm/gun)
![Build](https://github.com/amark/gun/actions/workflows/ci.yml/badge.svg)
[![Gitter](https://img.shields.io/gitter/room/amark/gun.js.svg)](http://chat.gun.eco)
**GUN** is an _ecosystem_ of tools that let you <u>build tomorrow's dApps, today</u>.
**GUN** is an [ecosystem](https://gun.eco/docs/Ecosystem) of **tools** that let you build [community run](https://www.nbcnews.com/tech/tech-news/these-technologists-think-internet-broken-so-they-re-building-another-n1030136) and [encrypted applications](https://gun.eco/docs/Cartoon-Cryptography) - like an Open Source Firebase or a Decentralized Dropbox.
Decentralized alternatives to [Reddit](https://notabug.io/t/whatever/comments/36588a16b9008da4e3f15663c2225e949eca4a15/gpu-bot-test), [YouTube](https://d.tube/), [Wikipedia](https://news.ycombinator.com/item?id=17685682), etc. are already pushing terabytes of daily P2P traffic on GUN. We are a [friendly community](https://gitter.im/amark/gun) creating a free fun future for freedom:
The [Internet Archive](https://news.ycombinator.com/item?id=17685682) and [100s of other apps](https://github.com/amark/gun/wiki/awesome-gun) run GUN in-production.
+ Multiplayer by default with realtime p2p state synchronization!
+ Graph data lets you use key/value, tables, documents, videos, & more!
+ Local-first, offline, and decentralized with end-to-end encryption.
Decentralized alternatives to [Zoom](https://www.zdnet.com/article/era-hatches-meething-an-open-source-browser-based-video-conferencing-system/), [Reddit](https://notabug.io/t/whatever/comments/36588a16b9008da4e3f15663c2225e949eca4a15/gpu-bot-test), [Instagram](https://iris.to/), [Slack](https://iris.to/), [YouTube](https://d.tube/), [Stripe](https://twitter.com/marknadal/status/1422717427427647489), [Wikipedia](https://news.ycombinator.com/item?id=17685682), Facebook [Horizon](https://twitter.com/marknadal/status/1424476179189305347) and more have already pushed terabytes of daily P2P traffic on GUN. We are a [friendly community](http://chat.gun.eco/) creating a [free fun future for freedom](https://youtu.be/1HJdrBk3BlE):
<table>
<tr>
<a href=""><img width="31%" align="left" src="https://gun.eco/see/3dvr.gif" title="3D VR"/></a>
<a href="https://github.com/cstefanache/cstefanache.github.io/blob/master/_posts/2016-08-02-gun-db-artificial-knowledge-sharing.md#gundb"><img width="31%" align="left" src="https://gun.eco/see/aiml.gif" title="AI/ML"/></a>
<a href="http://gps.gunDB.io/"><img width="31%" align="left" src="https://gun.eco/see/gps.gif" title="GPS"/></a>
<a href="https://github.com/lmangani/gun-scape#gun-scape"><img width="31%" align="left" src="https://gun.eco/see/dataviz.gif" title="Data Viz"/></a>
<a href="https://github.com/amark/gun/wiki/Auth"><img width="31%" align="left" src="https://gun.eco/see/p2p.gif" title="P2P"/></a>
<a href="https://github.com/Stefdv/gun-ui-lcd#okay-what-about-gundb-"><img width="31%" align="left" src="https://gun.eco/see/iot.gif" title="IoT"/></a>
<a href="https://youtu.be/s_m16-w6bBI"><img width="31%" src="https://gun.eco/see/3dvr.gif" title="3D VR"/></a>
<a href="https://github.com/cstefanache/cstefanache.github.io/blob/06697003449e4fc531fd32ee068bab532976f47b/_posts/2016-08-02-gun-db-artificial-knowledge-sharing.md"><img width="31%" src="https://gun.eco/see/aiml.gif" title="AI/ML"/></a>
<a href="http://gps.gunDB.io/"><img width="31%" src="https://gun.eco/see/gps.gif" title="GPS"/></a>
</tr>
<tr>
<a href="https://github.com/lmangani/gun-scape#gun-scape"><img width="31%" src="https://gun.eco/see/dataviz.gif" title="Data Viz"/></a>
<a href="https://github.com/amark/gun/wiki/Auth"><img width="31%" src="https://gun.eco/see/p2p.gif" title="P2P"/></a>
<a href="https://github.com/Stefdv/gun-ui-lcd#okay-what-about-gundb-"><img width="31%" src="https://gun.eco/see/iot.gif" title="IoT"/></a>
</tr>
<tr>
<a href="http://chat.gun.eco"><img width="31%" src="https://gun.eco/see/vr-world.gif" title="VR World"/></a>
<a href="https://youtu.be/1ASrmQ-CwX4"><img width="31%" src="https://gun.eco/see/ar.gif" title="AR"/></a>
<a href="https://meething.space/"><img width="31%" src="https://gun.eco/see/video-conf.gif" title="Video Confernece"/></a>
</tr>
</table>
The ecosystem is one nice stack of technologies that looks like this:
<div><img width="48%" src="https://gun.eco/see/stack.png"/>
<img width="48%" align="right" src="https://gun.eco/see/layers.png"/></div>
For now, it is best to start with GUN and _just use it_ to learn the basics, since it is _**so easy**_: (**or** want to read more? Skip ahead to the "[What is GUN?](#what-is-gun)" section.)
## Quickstart
GUN is *super easy* to get started with:
- Try the [interactive tutorial](https://gun.eco/docs/Todo-Dapp) in the browser (**5min** ~ average developer).
- Or `npm install gun` and run the examples with `cd node_modules/gun && npm start` (**5min** ~ average developer).
> **Note:** If you don't have [node](http://nodejs.org/) or [npm](https://www.npmjs.com/), read [this](https://github.com/amark/gun/blob/master/examples/install.sh) first.
> If the `npm` command line didn't work, you may need to `mkdir node_modules` first or use `sudo`.
- An online demo of the examples are available here: http://gunjs.herokuapp.com/
- Or write a quick app: ([try now in jsbin](http://jsbin.com/sovihaveso/edit?js,console))
- An online demo of the examples are available here: http://try.axe.eco/
- Or write a quick app: ([try now in a playground](https://jsbin.com/kadobamevo/edit?js,console))
```html
<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>
<script>
// var Gun = require('gun'); // in NodeJS
// var Gun = require('gun/gun'); // in React
var gun = Gun();
// import GUN from 'gun'; // in ESM
// GUN = require('gun'); // in NodeJS
// GUN = require('gun/gun'); // in React
gun = GUN();
gun.get('mark').put({
name: "Mark",
email: "mark@gunDB.io",
email: "mark@gun.eco",
});
gun.get('mark').on(function(data, key){
console.log("update:", data);
gun.get('mark').on((data, key) => {
console.log("realtime updates:", data);
});
setInterval(() => { gun.get('mark').get('live').put(Math.random()) }, 9);
</script>
```
- Or try something **mind blowing**, like saving circular references to a table of documents! ([play](http://jsbin.com/wefozepume/edit?js,console))
```javascript
var cat = {name: "Fluffy", species: "kitty"};
var mark = {boss: cat};
cat = {name: "Fluffy", species: "kitty"};
mark = {boss: cat};
cat.slave = mark;
// partial updates merge with existing data!
@ -66,13 +75,13 @@ gun.get('mark').put(mark);
// access the data as if it is a document.
gun.get('mark').get('boss').get('name').once(function(data, key){
// `val` grabs the data once, no subscriptions.
// `once` grabs the data once, no subscriptions.
console.log("Mark's boss is", data);
});
// traverse a graph of circular references!
gun.get('mark').get('boss').get('slave').once(function(data, key){
console.log("Mark is the slave!", data);
console.log("Mark is the cat's slave!", data);
});
// add both of them to a table!
@ -85,21 +94,41 @@ gun.get('list').map().once(function(data, key){
});
// live update the table!
gun.get('list').set({type: "cucumber", goal: "scare cat"});
gun.get('list').set({type: "cucumber", goal: "jumping cat"});
```
Want to keep building more? **Jump to [THE DOCUMENTATION](#documentation)!**
# What is GUN?
# About
First & foremost, GUN is **a community of the nicest and most helpful people** out there. So [I want to invite you](http://chat.gun.eco) to come tell us about what **you** are working on & wanting to build (new or old school alike! Just be nice as well.) and ask us your questions directly. :)
First & foremost, GUN is **a community of the nicest and most helpful people** out there. So [I want to invite you](https://gitter.im/amark/gun) to come tell us about what **you** are working on & wanting to build (new or old school alike! Just be nice as well.) and ask us your questions directly. :)
<p align="center"><a href="https://www.youtube.com/watch?v=oTQXzhm8w_8"><img width="250" src="https://img.youtube.com/vi/oTQXzhm8w_8/0.jpg"><br/>Watch the 100 second intro!</a></p>
The GUN ecosystem stack is a collection of independent and modular tools covering everything from [CRDT](https://crdt.tech/) [conflict resolution](https://gun.eco/distributed/matters.html), [cryptographic security](https://gun.eco/docs/Cartoon-Cryptography) & [encryption](https://gun.eco/docs/SEA), [radix storage serialization](https://gun.eco/docs/RAD), [mesh networking](https://gun.eco/docs/DAM) & [routing algorithms](https://gun.eco/docs/Routing), to distributed systems [correctness & load testing](https://github.com/gundb/panic-server), CPU scheduled [JSON parser](https://github.com/amark/gun/blob/master/lib/yson.js) to prevent UI lag, and more!
<div><img width="48%" src="https://gun.eco/see/stack.png"/>
<img width="48%" align="right" src="https://gun.eco/see/layers.png"/></div>
On that note, let's get some official shout outs covered first:
### Support
<p align="center">
Thanks to:<br/>
Thanks to:
<table>
<tr>
<td vlign="center"><a href="https://mozilla.org/builders"><img height="100" src="https://user-images.githubusercontent.com/1423657/81992335-85346480-9643-11ea-8754-8275e98e06bc.png"></a></td>
<td vlign="center"><a href="http://unstoppabledomains.com/"><img src="https://gun.eco/img/unstoppable.png"></a></td>
<td vlign="center"><a href="https://mask.io/"><img src="https://dimensiondev.github.io/Mask-VI/assets/Logo/MB--Logo--CombH-Circle--Blue.svg" width="250"></a></td>
</tr>
<tr>
<td vlign="center">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://www.ajar.org/"><img src="https://www.ajar.org/logo.png" height="120"></a></td>
<td vlign="center"><a href="https://wallie.io/"><img src="https://raw.githubusercontent.com/gundb/gun-site/master/img/wallie.png" width="250"></a></td>
<td vlign="center">&nbsp;&nbsp;<a href="https://ghostdrive.com/"><img src="https://gun.eco/img/ghostdrive.png" height="120"></a></td>
</tr>
</table>
<a href="https://github.com/robertheessels">Robert Heessels</a>,
<a href="http://qxip.net/">Lorenzo Mangani</a>,
<a href="https://nlnet.nl/">NLnet Foundation</a>,
@ -113,13 +142,28 @@ Thanks to:<br/>
<a href="http://github.com/alanmimms">Alan Mimms</a>,
<a href="https://github.com/dfreire">Dário Freire</a>,
<a href="http://github.com/velua">John Williamson</a>,
<a href="http://github.com/finwo">Robin Bron</a>
<a href="http://github.com/finwo">Robin Bron</a>,
<a href="http://github.com/ElieMakhoul">Elie Makhoul</a>,
<a href="http://github.com/mikestaub">Mike Staub</a>,
<a href="http://github.com/bmatusiak">Bradley Matusiak</a>,
<a href="https://github.com/sjuxax">Jeff Cook</a>,
<a href="https://github.com/nmauersberg">Nico</a>,
<a href="https://github.com/ajartille">Aaron Artille</a>,
<a href="https://github.com/timjrobinson">Tim Robinson</a>,
<a href="https://github.com/hibas123">Fabian Stamm</a>,
<a href="https://twitter.com/mikestaub">Mike Staub</a>,
<a href="https://hunterowens.com/">Hunter Owens</a>,
<a href="https://github.com/JacobMillner">Jacob Millner</a>,
<a href="https://github.com/b-lack">Gerrit Balindt</a>,
<a href="https://github.com/gabriellemon">Gabriel Lemon</a>,
<a href="https://github.com/murageyun">Murage Martin</a>,
<a href="https://github.com/octalmage">Jason Stallings</a>
</p>
- Join others in sponsoring code: https://www.patreon.com/gunDB !
- Ask questions: http://stackoverflow.com/questions/tagged/gun ?
- Found a bug? Report at: https://github.com/amark/gun/issues ;
- **Need help**? Chat with us: https://gitter.im/amark/gun .
- **Need help**? Chat with us: http://chat.gun.eco .
### History
@ -146,11 +190,11 @@ Technically, **GUN is a graph synchronization protocol** with a *lightweight emb
<tr>
<td style="border: 0;"><h3><a href="https://github.com/brysgo/graphql-gun">GraphQL</a></h3></td>
<td style="border: 0;"><h3><a href="https://github.com/PenguinMan98/electrontest">Electron</a></h3></td>
<td style="border: 0;"><h3><a href="https://gun.eco/docs/React-Native">React Native</a></h3></td>
<td style="border: 0;"><h3><a href="https://gun.eco/docs/React-Native">React & Native</a></h3></td>
</tr>
<tr>
<td style="border: 0;"><h3><a href="https://github.com/sjones6/vue-gun">Vue</a></h3></td>
<td style="border: 0;"><h3><a href="https://github.com/amark/gun/wiki/React-Tutorial">React</a></h3></td>
<td style="border: 0;"><h3><a href="https://gun.eco/docs/Svelte">Svelte</a></h3></td>
<td style="border: 0;"><h3><a href="https://github.com/Stefdv/gun-ui-lcd#syncing">Webcomponents</a></h3></td>
</tr>
<tr>
@ -160,54 +204,74 @@ Technically, **GUN is a graph synchronization protocol** with a *lightweight emb
</tr>
<tr>
<td style="border: 0;"><h3><a href="https://gun.eco/docs/Auth">Crypto Auth</a></h3></td>
<td style="border: 0;"><h3><a href="https://gun.eco/docs/Awesome-GUN">Modules</a></h3></td>
<td style="border: 0;"><h3><a href="https://github.com/amark/gun/wiki/Awesome-GUN">Modules</a></h3></td>
<td style="border: 0;"><h3><a href="https://gun.eco/docs/Roadmap">Roadmap</a></h3></td>
</tr>
</table>
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))**; RIP **[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!
I am missing many others, apologies, will be adding them soon! This list is infinitely old & way out of date, if you want to be listed in it please make a PR! :)
## Testing
Tests may be run with `npm test`. Tests will trigger persistent writes to the DB, so subsequent runs of the test will fail. You must clear the DB before running the tests again. This can be done by running the following command in the project directory.
You will need to `npm install -g mocha` first. Then in the gun root folder run `npm test`. Tests will trigger persistent writes to the DB, so subsequent runs of the test will fail. You must clear the DB before running the tests again. This can be done by running `rm -rf *data*` command in the project directory.
```bash
rm -rf *data*
```
## Shims
### Additional Cryptography Libraries
> These are only needed for NodeJS & React Native, they shim the native Browser WebCrypto API.
To install with npm, first install `npm install gun -S`.
For just the networking layer, import Gun:
If you want to use [SEA](https://gun.eco/docs/SEA) for `User` auth and security, you will need to install:
`npm install @peculiar/webcrypto --save`
Please see [our React Native docs](https://gun.eco/docs/React-Native) for installation instructions!
Then you can require [SEA](https://gun.eco/docs/SEA) without an error:
```javascript
var Gun = require('gun/gun');
GUN = require('gun/gun');
SEA = require('gun/sea');
```
If you also need to install SEA for user auth and crypto, also install some of its dependencies like this:
`npm install @trust/crypto text-encoding node-webcrypto-ossl --save`
You will need to require it too (it will be automatically added to the Gun object):
```javascript
var Gun = require('gun/gun');
var Sea = require('gun/sea');
```
## Deploy
To quickly spin up a Gun test server for your development team, utilize either [Heroku](http://heroku.com) or [Docker](http://docker.com) or any variant thereof [Dokku](http://dokku.viewdocs.io/dokku/), [Flynn.io](http://flynn.io), [now.sh](https://zeit.co/now), etc. !
> Note: The default examples that get auto-deployed on `npm start` CDN-ify all GUN files, modules, & storage.
> Note: Moving forward, AXE will start to automatically cluster your peer into a shared DHT. You may want to disable this to run an isolated network.
> Note: When deploying a web application using GUN on a cloud provider, you may have to set `CI=false` in your `.env`. This prevents GUN-specific warnings from being treated as errors when deploying your app. You may also resolve this by modifying your webpack config to not try to build the GUN dependencies.
To quickly spin up a GUN relay peer for your development team, utilize [Heroku](http://heroku.com), [Docker](http://docker.com), or any others listed below. Or some variant thereof [Dokku](http://dokku.viewdocs.io/dokku/), K8s, etc. ! Or use all of them so your relays are decentralized too!
### Linux
`SSH` into the home directory of a clean OS install with `sudo` ability. Set any environment variables you need (see below), then do:
```bash
curl -o- https://raw.githubusercontent.com/amark/gun/master/examples/install.sh | bash
```
> Read [install.sh](https://github.com/amark/gun/blob/master/examples/install.sh) first!
> If `curl` is not found, *copy&paste* the contents of install.sh into your ssh.
You can now safely `CTRL+A+D` to escape without stopping the peer. To stop everything `killall screen` or `killall node`.
Environment variables may need to be set like `export HTTPS_CERT=~/cert.pem HTTPS_KEY=~/key.pem PORT=443`. You can also look at a sample [nginx](https://gun.eco/docs/nginx) config. For production deployments, you probably will want to use something like `pm2` or better to keep the peer alive after machine reboots.
### [Dome](https://www.trydome.io/)
[Deploy GUN in one-click](https://app.trydome.io/signup?package=gun) with [Dome](https://trydome.io) and receive a free trial:
[![Deploy to Dome](https://trydome.io/button.svg)](https://app.trydome.io/signup?package=gun)
### [Heroku](https://www.heroku.com/)
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/amark/gun)
> Heroku deletes your data every 15 minutes, one way to fix this is by adding [cheap storage](https://gun.eco/docs/Using-Amazon-S3-for-Storage).
Or:
```bash
@ -217,20 +281,19 @@ heroku create
git push -f heroku HEAD:master
```
Then visit the URL in the output of the 'heroku create' step, in a browser.
Then visit the URL in the output of the 'heroku create' step, in a browser. Make sure to set any environment config vars in the settings tab.
### [Now.sh](https://zeit.co/now/)
### [Zeet.co](https://www.zeet.co/)
```bash
npm install -g now
now --npm amark/gun
```
[![Deploy](https://deploy.zeet.co/gun.svg)](https://deploy.zeet.co/?url=https://github.com/amark/gun)
Then visit the URL in the output of the 'now --npm' step, in your browser.
### [Docker](https://www.docker.com/)
[![Docker Automated buil](https://img.shields.io/docker/automated/gundb/gun.svg)](https://hub.docker.com/r/gundb/gun/) [![](https://images.microbadger.com/badges/image/gundb/gun.svg)](https://microbadger.com/images/gundb/gun "Get your own image badge on microbadger.com") [![Docker Pulls](https://img.shields.io/docker/pulls/gundb/gun.svg)](https://hub.docker.com/r/gundb/gun/) [![Docker Stars](https://img.shields.io/docker/stars/gundb/gun.svg)](https://hub.docker.com/r/gundb/gun/)
> Warning: Docker image is community contributed and may be old with missing security updates, please check version numbers to compare.
[![Docker Automated build](https://img.shields.io/docker/automated/gundb/gun.svg)](https://hub.docker.com/r/gundb/gun/) [![](https://images.microbadger.com/badges/image/gundb/gun.svg)](https://microbadger.com/images/gundb/gun "Get your own image badge on microbadger.com") [![Docker Pulls](https://img.shields.io/docker/pulls/gundb/gun.svg)](https://hub.docker.com/r/gundb/gun/) [![Docker Stars](https://img.shields.io/docker/stars/gundb/gun.svg)](https://hub.docker.com/r/gundb/gun/)
Pull from the [Docker Hub](https://hub.docker.com/r/gundb/gun/) [![](https://images.microbadger.com/badges/commit/gundb/gun.svg)](https://microbadger.com/images/gundb/gun). Or:

25
RELEASE.md Normal file
View File

@ -0,0 +1,25 @@
Every push or pull request will
- run the tests
Every push to master will
- run the tests
- publish the latest docker image to dockerhub
Creating a tag that starts with `v` will
- create a new github release
- publish the release to npm
- publish the release to dockerhub
Creating a release from the github web interface will
- publish the release to npm
- publish the release to dockerhub
Creating the release for version `0.2021.001` from the command line works as follows
git tag v0.2021.001
git push --tags

47
SECURITY.md Normal file
View File

@ -0,0 +1,47 @@
# Security Policy
## Introduction
Security is our top priority. We are committed to ensuring that our project is as secure as possible for everyone who uses it. This document outlines our security policy and procedures for dealing with security issues.
## Supported Versions
We provide security updates for the following versions of our project:
| Version | Supported |
| ------- | ------------------ |
| 0.2020.x| :white_check_mark: |
| < 0.2020| :x: |
## Reporting a Vulnerability
If you discover a vulnerability, we would like to know about it so we can take steps to address it as quickly as possible.
### Report Format
When reporting vulnerabilities, please include the following details:
- Description of the vulnerability
- Steps to reproduce the issue
- Potential impact if left unaddressed
- Suggested mitigation or resolution if any
### Response Time
We aim to confirm the receipt of your vulnerability report within 48 hours. Depending on the severity and complexity of the issue, we strive to investigate the issue and provide an initial response within a week.
### Disclosure Policy
If the vulnerability is confirmed, we will work on a fix and plan a release. We ask that you do not publicly disclose the issue until it has been addressed by us.
## Security Practices
We follow industry-standard security practices, including regular audits of the services and features we provide, to maintain the trust of our users.
## Security Updates
We will communicate any security updates through our standard communication channels, including our project's release notes and official website.
## Conclusion
We greatly value the work of security researchers and believe that responsible disclosure of vulnerabilities is a valuable contribution to the security of the Internet. We encourage users to contribute to the security of our project by reporting any security-related issues to us.

View File

@ -1,8 +1,18 @@
{
"name": "gun-server",
"website": "http://gun.js.org",
"website": "http://gun.eco/",
"repository": "https://github.com/amark/gun",
"logo": "https://avatars3.githubusercontent.com/u/8811914",
"keywords": ["node", "gun", "gunDB", "database","graph","offline-first"],
"description": "Javascript, Offline-First Javascript Graph Database Server Peer"
"description": "Javascript, Offline-First Javascript Graph Database Server Peer",
"env": {
"NPM_CONFIG_PRODUCTION": {
"description": "If you do not want default features, set to \"true\".",
"value": "false"
},
"PEERS": {
"description": "Comma-separated list of peer urls to connect to",
"required": false
}
}
}

110
as.js
View File

@ -1,7 +1,73 @@
;(function(){
function as(el, gun, cb){
function as(el, gun, cb, opt){
el = $(el);
if(gun === as.gui && as.el && as.el.is(el)){ return }
opt = opt || {};
opt.match = opt.match || '{{ ';
opt.end = opt.end || ' }}';
;(function(){ // experimental
function nest(t, s,e, r, i,tmp,u){
if(r && !r.length){ return t||'' }
if(!t){ return [] }
e = e || s;
i = t.indexOf(s, i||0);
if(0 > i){ return [] }
tmp = t.indexOf(e, i+1);
if(!r){ return [t.slice(i+s.length, tmp)].concat(nest(t, s,e, r, tmp,tmp,u)) }
return t.slice(0,i)+r[0]+nest(t.slice(tmp+e.length), s,e, r.slice(1), 0,tmp,u);
}
/* experimental */
function template(tag, attr){
var html = (tag = $(tag))[0].outerHTML, sub, tmp;
if(html && (0 > html.indexOf(opt.match))){ return }
if(!attr){
$.each(tag[0].attributes, function(i,v){
if(!v){ return }
if(!nest(v.value, opt.match, opt.end).length){ return }
template(tag, v.name)
});
if((sub = tag.children()).length){
return sub.each(function(){ template(this) });
}
}
var data = [], plate = attr? tag.attr(attr) : tag.html();
tmp = nest(plate, opt.match, opt.end);
if(!tmp.length){ return }
$.each(tmp, function(pos, match){
var expr = match.split(' ');
var path = (expr[0]).split('.');
if(expr = expr.slice(1).join(' ')){
expr = new Function("_", "b", "return (_)" + expr);
}
var val = (expr && expr('')) || '';
data.push(val);
if(!attr){ tag.text(val) }
var ref = gun, sup = [], tmp;
if(tmp = tag.attr('name')){ sup.push(tmp) }
tag.parents("[name]").each(function(){
sup.push($(this).attr('name'));
});
$.each(path = sup.reverse().concat(path), function(i,v){
ref = ref.get(v);
});
ref.on(function(v){
v = data[pos] = expr? expr(v) : v;
var tmp = nest(plate, opt.match, opt.end, data);
if(attr){
tag.attr(attr, tmp);
} else {
tag.text(tmp);
}
});
});
}
template(el);
}());
as.gui = gun;
as.el = el;
if(el.data('as')){
@ -59,10 +125,12 @@
if(many && ui.is('.sort')){
var up = ui.closest("[name='#']");
var tmp = as.sort(data, up.parent().children().last());
up.insertAfter(tmp);
tmp? up.insertAfter(tmp) : up.prependTo(up.parent());
}
if(as.lock === gui){ return }
(ui[0] && u === ui[0].value)? ui.text(data) : ui.val(data);
if(!(data && data instanceof Object)){
(ui[0] && u === ui[0].value)? ui.text(data) : ui.val(data);
}
ui.data('was', data);
if(cb){
cb(data, key, ui);
@ -80,12 +148,7 @@
}, wait || 200);
}
}
as.sort = function sort(id, li){
var num = parseFloat(id);
var id = $(li).find('.sort').text() || -Infinity;
var at = num >= parseFloat(id);
return at ? li : sort(id, li.prev());
}
as.sort = function sort(num, li){ return parseFloat(num) >= parseFloat($(li).find('.sort').text() || -Infinity)? li : sort(num, li.prev()) }
$(document).on('keyup', 'input, textarea, [contenteditable]', as.wait(function(){
var el = $(this);
var data = (el[0] && u === el[0].value)? el.text() : el.val();
@ -94,7 +157,7 @@
as.lock = g;
g.put(data);
}, 99));
$(document).on('submit', 'form', function(e){ e.preventDefault() });
//$(document).on('submit', 'form', function(e){ e.preventDefault() });
var u;
window.as = as;
$.as = as;
@ -146,4 +209,31 @@
;$(function(){
$('.page').not(':first').hide();
$.as.route(location.hash.slice(1));
$(JOY.start = JOY.start || function(){ $.as(document, gun, null, JOY.opt) });
if($('body').attr('peers')){ (console.warn || console.log)('Warning: Please upgrade <body peers=""> to https://github.com/eraeco/joydb#peers !') }
});
;(function(){ // need to isolate into separate module!
var joy = window.JOY = function(){};
joy.auth = function(a,b,cb,o){
if(!o){ o = cb ; cb = 0 }
if(o === true){
gun.user().create(a, b);
return;
}
gun.user().auth(a,b, cb,o);
}
var opt = joy.opt = window.CONFIG || {}, peers;
$('link[type=peer]').each(function(){ (peers || (peers = [])).push($(this).attr('href')) });
!window.gun && (opt.peers = opt.peers || peers || (function(){
(console.warn || console.log)('Warning: No peer provided, defaulting to DEMO peer. Do not run in production, or your data will be regularly wiped, reset, or deleted. For more info, check https://github.com/eraeco/joydb#peers !');
return ['https://gunjs.herokuapp.com/gun'];
}()));
window.gun = window.gun || Gun(opt);
gun.on('auth', function(ack){
console.log("Your namespace is publicly available at", ack.soul);
});
}());

188
axe.js
View File

@ -1,99 +1,109 @@
;(function(){
/* UNBUILD */
var root;
if(typeof window !== "undefined"){ root = window }
if(typeof global !== "undefined"){ root = global }
root = root || {};
var console = root.console || {log: function(){}};
function USE(arg, req){
return req? require(arg) : arg.slice? USE[R(arg)] : function(mod, path){
arg(mod = {exports: {}});
USE[R(path)] = mod.exports;
}
function R(p){
return p.split('/').slice(-1).toString().replace('.js','');
}
}
if(typeof module !== "undefined"){ var common = module }
/* UNBUILD */
var sT = setTimeout || {}, u;
if(typeof window !== ''+u){ sT.window = window }
var AXE = (sT.window||'').AXE || function(){};
if(AXE.window = sT.window){ AXE.window.AXE = AXE }
;USE(function(module){
if(typeof window !== "undefined"){ module.window = window }
var tmp = module.window || module;
var AXE = tmp.AXE || function(){};
var Gun = (AXE.window||'').GUN || require('./gun');
(Gun.AXE = AXE).GUN = AXE.Gun = Gun;
if(AXE.window = module.window){ try{
AXE.window.AXE = AXE;
tmp = document.createEvent('CustomEvent');
tmp.initCustomEvent('extension', false, false, {type: "AXE"});
(window.dispatchEvent || window.fireEvent)(tmp);
window.postMessage({type: "AXE"}, '*');
} catch(e){} }
//if(!Gun.window){ try{ require('./lib/axe') }catch(e){} }
if(!Gun.window){ require('./lib/axe') }
try{ if(typeof common !== "undefined"){ common.exports = AXE } }catch(e){}
module.exports = AXE;
})(USE, './root');
;USE(function(module){
Gun.on('opt', function(at){ start(at) ; this.to.next(at) }); // make sure to call the "next" middleware adapter.
var AXE = USE('./root'), Gun = (AXE.window||{}).Gun || USE('./gun', 1);
(Gun.AXE = AXE).GUN = AXE.Gun = Gun;
function start(root){
if(root.axe){ return }
var opt = root.opt, peers = opt.peers;
if(false === opt.axe){ return }
if(!Gun.window){ return } // handled by ^ lib/axe.js
var w = Gun.window, lS = w.localStorage || opt.localStorage || {}, loc = w.location || opt.location || {}, nav = w.navigator || opt.navigator || {};
var axe = root.axe = {}, tmp, id;
var mesh = opt.mesh = opt.mesh || Gun.Mesh(root); // DAM!
Gun.on('opt', function(at){
if(!at.axe){
at.axe = {};
var p = at.opt.peers, tmp;
// 1. If any remembered peers or from last cache or extension
// 2. Fallback to use hard coded peers from dApp
// 3. Or any offered peers.
//if(Gun.obj.empty(p)){
// Gun.obj.map(['http://localhost:8765/gun'/*, 'https://guntest.herokuapp.com/gun'*/], function(url){
// p[url] = {url: url, axe: {}};
// });
//}
// Our current hypothesis is that it is most optimal
// to take peers in a common network, and align
// them in a line, where you only have left and right
// peers, so messages propagate left and right in
// a linear manner with reduced overlap, and
// with one common superpeer (with ready failovers)
// in case the p2p linear latency is high.
// Or there could be plenty of other better options.
console.log("axe", at.opt);
if(at.opt.super){
function verify(msg, send, at) {
var peers = Object.keys(p), puts = Object.keys(msg.put), i, j, peer;
var soul = puts[0]; /// TODO: verify all souls in puts. Copy the msg only with subscribed souls?
for (i=0; i < peers.length; ++i) {
peer = p[peers[i]];
//if (peer.url) {console.log('AXE do not reject superpeers'); send(msg, peer); continue;} /// always send to superpeers?
if (!peer.id) {console.log('AXE peer without id: ', peer); continue;}
if (!Gun.subscribe[soul] || !Gun.subscribe[soul][peer.id]) { console.log('AXE SAY reject msg to peer: %s, soul: %s', peer.id, soul); continue; }
send(msg, peer);
}
}
AXE.say = function(msg, send, at) {
if (!msg.put) { send(msg); return; }
console.log('AXE HOOK!! ', msg);
verify(msg, send, at);
};
/// TODO: remove peer from all Gun.subscribe. On `mesh.bye` event?
}
if(at.opt.super){
at.on('in', USE('./lib/super', 1), at);
} else {
//at.on('in', input, at);
}
}
this.to.next(at); // make sure to call the "next" middleware adapter.
});
tmp = peers[id = loc.origin + '/gun'] = peers[id] || {};
tmp.id = tmp.url = id; tmp.retry = tmp.retry || 0;
tmp = peers[id = 'http://localhost:8765/gun'] = peers[id] || {};
tmp.id = tmp.url = id; tmp.retry = tmp.retry || 0;
Gun.log.once("AXE", "AXE enabled: Trying to find network via (1) local peer (2) last used peers (3) a URL parameter, and last (4) hard coded peers.");
Gun.log.once("AXEWarn", "Warning: AXE is in alpha, use only for testing!");
var last = lS.peers || ''; if(last){ last += ' ' }
last += ((loc.search||'').split('peers=')[1]||'').split('&')[0];
function input(msg){
var at = this.as, to = this.to;
}
root.on('bye', function(peer){
this.to.next(peer);
if(!peer.url){ return } // ignore WebRTC disconnects for now.
if(!nav.onLine){ peer.retry = 1 }
if(peer.retry){ return }
if(axe.fall){ delete axe.fall[peer.url || peer.id] }
(function next(){
if(!axe.fall){ setTimeout(next, 9); return } // not found yet
var fall = Object.keys(axe.fall||''), one = fall[(Math.random()*fall.length) >> 0];
if(!fall.length){ lS.peers = ''; one = 'https://gunjs.herokuapp.com/gun' } // out of peers
if(peers[one]){ next(); return } // already choose
mesh.hi(one);
}());
});
module.exports = AXE;
})(USE, './axe');
root.on('hi', function(peer){ // TEMPORARY! Try to connect all peers.
this.to.next(peer);
if(!peer.url){ return } // ignore WebRTC disconnects for now.
return; // DO NOT COMMIT THIS FEATURE YET! KEEP TESTING NETWORK PERFORMANCE FIRST!
(function next(){
if(!peer.wire){ return }
if(!axe.fall){ setTimeout(next, 9); return } // not found yet
var one = (next.fall = next.fall || Object.keys(axe.fall||'')).pop();
if(!one){ return }
setTimeout(next, 99);
mesh.say({dam: 'opt', opt: {peers: one}}, peer);
}());
});
}());
function found(text){
axe.fall = {};
((text||'').match(/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/ig)||[]).forEach(function(url){
axe.fall[url] = {url: url, id: url, retry: 0}; // RETRY
});
return;
// TODO: Finish porting below? Maybe not.
Object.keys(last.peers||'').forEach(function(key){
tmp = peers[id = key] = peers[id] || {};
tmp.id = tmp.url = id;
});
tmp = peers[id = 'https://guntest.herokuapp.com/gun'] = peers[id] || {};
tmp.id = tmp.url = id;
var mesh = opt.mesh = opt.mesh || Gun.Mesh(root); // DAM!
mesh.way = function(msg){
if(root.$ === msg.$ || (msg._||'').via){
mesh.say(msg, opt.peers);
return;
}
var at = (msg.$||'')._;
if(!at){ mesh.say(msg, opt.peers); return }
if(msg.get){
if(at.axe){ return } // don't ask for it again!
at.axe = {};
}
mesh.say(msg, opt.peers);
}
}
if(last){ found(last); return }
try{ fetch(((loc.search||'').split('axe=')[1]||'').split('&')[0] || loc.axe || 'https://raw.githubusercontent.com/wiki/amark/gun/volunteer.dht.md').then(function(res){
return res.text()
}).then(function(text){
found(lS.peers = text);
}).catch(function(){
found(); // nothing
})}catch(e){found()}
}
var empty = {}, yes = true;
try{ if(typeof module != ''+u){ module.exports = AXE } }catch(e){}
}());

4
browser.js Normal file
View File

@ -0,0 +1,4 @@
// if(!(typeof navigator == "undefined") && navigator.product == "ReactNative"){
// require("./lib/mobile.js");
// }
module.exports = require('./gun.js');

217
examples/Main.js Normal file
View File

@ -0,0 +1,217 @@
import { render } from './iris/js/lib/preact.js';
import { Router, route } from './iris/js/lib/preact-router.es.js';
import { createHashHistory } from './iris/js/lib/history.production.min.js';
import { Component } from './iris/js/lib/preact.js';
import { Link } from './iris/js/lib/preact.match.js';
import Helpers from './iris/js/Helpers.js';
import { html } from './iris/js/Helpers.js';
import QRScanner from './iris/js/QRScanner.js';
import PeerManager from './iris/js/PeerManager.js';
import Session from './iris/js/Session.js';
import { translate as t } from './iris/js/Translation.js';
import Settings from './iris/js/views/Settings.js';
import LogoutConfirmation from './iris/js/views/LogoutConfirmation.js';
import Chat from './iris/js/views/Chat.js';
import Store from './iris/js/views/Store.js';
import Checkout from './iris/js/views/Checkout.js';
import Product from './iris/js/views/Product.js';
import Login from './iris/js/views/Login.js';
import Profile from './iris/js/views/Profile.js';
import Group from './iris/js/views/Group.js';
import Message from './iris/js/views/Message.js';
import Follows from './iris/js/views/Follows.js';
import Feed from './iris/js/views/Feed.js';
import About from './iris/js/views/About.js';
import Explorer from './iris/js/views/Explorer.js';
import Contacts from './iris/js/views/Contacts.js';
import Torrent from './iris/js/views/Torrent.js';
import VideoCall from './iris/js/components/VideoCall.js';
import Identicon from './iris/js/components/Identicon.js';
import MediaPlayer from './iris/js/components/MediaPlayer.js';
import Footer from './iris/js/components/Footer.js';
import State from './iris/js/State.js';
import Icons from './iris/js/Icons.js';
const userAgent = navigator.userAgent.toLowerCase();
const isElectron = (userAgent.indexOf(' electron/') > -1);
if (!isElectron && ('serviceWorker' in navigator)) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('iris/serviceworker.js')
.catch(function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
});
}
State.init();
Session.init({autologin: true});
PeerManager.init();
Helpers.checkColorScheme();
const APPLICATIONS = [ // TODO: move editable shortcuts to State.local gun
{url: '/', text: t('home'), icon: Icons.home},
{url: '/feed', text: t('feed'), icon: Icons.feed},
{url: '/media', text: t('media'), icon: Icons.play},
{url: '/settings', text: t('settings'), icon: Icons.settings},
{url: '/store', text: t('store'), icon: Icons.store},
{url: '/explorer', text: t('explorer'), icon: Icons.folder},
{url: '/chat', text: t('messages'), icon: Icons.chat},
// {url: '/store', text: t('store'), icon: Icons.store}, // restore when it works!
{},
{url: '../stats.html', text: 'Gun node stats'},
{url: '../iris/index.html', text: 'Iris', icon: html`<img src="iris/img/icon128.png" width=24/>`},
{url: '../infinite-scroll/index.html', text: 'Infinite scroll'},
{url: '../chat/index.html', text: 'Chat'},
{url: '../game/space.html', text: 'Space'},
{},
{url: 'https://gun.eco/docs/', text: 'Gun documentation'},
{url: 'https://examples.iris.to/components/', text: 'Iris web components'}
];
const HomeView = () => {
return html`
<div class="main-view">
<div class="centered-container public-messages-view">
<h1>Hello, world!</h1>
<p>Here you can find sample applications and utilities for <a href="https://github.com/amark/gun">GUN</a>.</p>
<p>If you need any help, please feel free to join the GUN community chat: <a href="http://chat.gun.eco">http://chat.gun.eco</a></p>
<a href="/explorer" class="msg"><div class="msg-content">
<b>Explorer</b>
<p>Explore the data saved on the GUN database. Open to the side while using an application and see the data change in real-time.</p>
</div></a>
<a class="msg" href="game/space.html"><div class="msg-content">
<div class="img-container"><img src="iris/img/space-game.jpg"/></div>
<b>Space</b>
<p>Spaceflight game. Open in 2 or more browser windows.</p>
</div></a>
<a class="msg" href="/iris/index.html"><div class="msg-content">
<div class="img-container"><img src="iris/img/screenshot.png"/></div>
<b>Iris</b>
<p>Decentralized Twitter/Instagram. Provides modular components that can be reused in other applications (including this one).</p>
</div></a>
<a native class="msg" href="/chat/index.html"><div class="msg-content">
<div class="img-container"><img src="iris/img/gun-chat.jpg"/></div>
<b>Chat</b>
<p>Shoutbox!</p>
</div></a>
</div>
</div>
`;
};
class MenuView extends Component {
componentDidMount() {
State.local.get('showMenu').on(showMenu => this.setState({showMenu}));
}
render() {
const pub = Session.getPubKey();
return html`
<div class="application-list ${this.state.showMenu ? 'menu-visible-xs' : ''}">
<a href="/profile/${pub}">
<span class="icon"><${Identicon} str=${pub} width=40/></span>
<span class="text" style="font-size: 1.2em;border:0;margin-left: 7px;"><iris-text user="${pub}" path="profile/name" editable="false"/></span>
</a>
<br/><br/>
${APPLICATIONS.map(a => {
if (a.url) {
return html`
<a href=${a.url}>
<span class="icon">${a.icon || Icons.circle}</span>
<span class="text">${a.text}</span>
</a>`;
} else {
return html`<br/><br/>`;
}
})}
</div>
`;
}
};
class Main extends Component {
constructor() {
super();
this.showMenu = false;
}
componentDidMount() {
State.local.get('loggedIn').on(loggedIn => this.setState({loggedIn}));
}
handleRoute(e) {
let activeRoute = e.url;
if (!activeRoute && window.location.hash) {
return route(window.location.hash.replace('#', '')); // bubblegum fix back navigation
}
document.title = 'Iris';
if (activeRoute && activeRoute.length > 1) { document.title += ' - ' + Helpers.capitalize(activeRoute.replace('/', '')); }
State.local.get('activeRoute').put(activeRoute);
QRScanner.cleanupScanner();
}
onClickOverlay() {
if (this.state.showMenu) {
this.setState({showMenu: false});
}
}
toggleMenu(show) {
this.setState({showMenu: typeof show === 'undefined' ? !this.state.showMenu : show});
}
render() {
const content = this.state.loggedIn ? html`
<div class="visible-xs-flex" style="border-bottom:var(--sidebar-border-right)">
<svg onClick=${() => State.local.get('showMenu').put(this.showMenu = !this.showMenu)} style="padding: 5px;cursor:pointer;" viewBox="0 -53 384 384" width="40px"><path d="m368 154.667969h-352c-8.832031 0-16-7.167969-16-16s7.167969-16 16-16h352c8.832031 0 16 7.167969 16 16s-7.167969 16-16 16zm0 0"/><path d="m368 32h-352c-8.832031 0-16-7.167969-16-16s7.167969-16 16-16h352c8.832031 0 16 7.167969 16 16s-7.167969 16-16 16zm0 0"/><path d="m368 277.332031h-352c-8.832031 0-16-7.167969-16-16s7.167969-16 16-16h352c8.832031 0 16 7.167969 16 16s-7.167969 16-16 16zm0 0"/></svg>
</div>
<section class="main" style="flex-direction: row;">
<${MenuView}/>
<div style="flex: 3; display: flex">
<${Router} history=${createHashHistory()} onChange=${e => this.handleRoute(e)}>
<${HomeView} path="/"/>
<${Feed} path="/feed"/>
<${Feed} path="/search/:term?/:type?"/>
<${Feed} path="/media" index="media"/>
<${Login} path="/login"/>
<${Chat} path="/chat/:id?"/>
<${Message} path="/post/:hash"/>
<${Torrent} path="/torrent/:id"/>
<${About} path="/about"/>
<${Settings} path="/settings"/>
<${LogoutConfirmation} path="/logout"/>
<${Profile} path="/profile/:id?" tab="profile"/>
<${Profile} path="/replies/:id?" tab="replies"/>
<${Profile} path="/likes/:id?" tab="likes"/>
<${Profile} path="/media/:id" tab="media"/>
<${Group} path="/group/:id?"/>
<${Store} path="/store/:store?"/>
<${Checkout} path="/checkout/:store?"/>
<${Product} path="/product/:product/:store"/>
<${Product} path="/product/new" store=Session.getPubKey()/>
<${Explorer} path="/explorer/:node"/>
<${Explorer} path="/explorer"/>
<${Follows} path="/follows/:id"/>
<${Follows} followers=${true} path="/followers/:id"/>
<${Contacts} path="/contacts"/>
</${Router}>
</div>
</section>
<${VideoCall}/>
` : '';
return html`
<div id="main-content">
${content}
</div>
`;
}
}
render(html`<${Main}/>`, document.body);
$('body').css('opacity', 1); // use opacity because setting focus on display: none elements fails

View File

@ -22,7 +22,7 @@
"@angular/router": "^4.1.0",
"core-js": "^2.4.1",
"express-http-proxy": "^1.0.1",
"gun": "^0.7.4",
"gun": "https://github.com/amark/gun.git#master",
"ngx-pipes": "^2.0.5",
"rxjs": "^5.3.0",
"underscore": "^1.8.3",

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@ import { pick } from 'underscore';
export function on$(node, cleanup = true): Observable<any> {
return Observable.fromEventPattern(
h => {
// there is no way to off() an on() until at least one value is trigerred
// there is no way to off() an on() until at least one value is triggered
// so that we can access the event listener to off() it
const signal = { stop: false };
node.on((data, key, at, ev) => {

File diff suppressed because it is too large Load Diff

View File

@ -8,8 +8,11 @@
</head>
<body>
<h3 id="pid"></h3>
<script src="../gun.js"></script>
<!-- <script src="../axe.js"></script> -->
<script src="../axe.js"></script>
<script src="../lib/radix.js"></script>
<script src="../lib/webrtc.js"></script>
<!-- <script src="../sea.js"></script> -->
<script>
var pid = location.hash.slice(1);
@ -23,14 +26,17 @@
Gun.on('opt', function(ctx) {
this.to.next(ctx);
ctx.on('hi', function(opt) {
console.log('HI!! PEER', new Date(), opt.pid);
// console.log('HI!! PEER', new Date(), opt.pid);
setTimeout(function() {
document.getElementById('pid').innerHTML = gun._.opt.pid;
});
});
if (pid) {
ctx.on('out', function(msg) {
msg.pid = pid;
this.to.next(msg);
});
}
// if (pid) {
// ctx.on('out', function(msg) {
// msg.pid = pid;
// this.to.next(msg);
// });
// }
});
var gun = Gun(opt);

21
examples/basic/chat.html Normal file
View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<ul id='list'></ul>
<form id='form'>
<input id='who' placeholder='name'>
<input id='what' placeholder='say'>
<input type='submit' value='send'>
</form>
<script src="../../../gun/gun.js"></script>
<script src="../../../gun/axe.js"></script>
<script src="https://cdn.jsdelivr.net/npm/emojione@4.0.0/lib/js/emojione.min.js"></script>
<script>
gun = GUN(), chat = gun.get("note" + location.hash.replace('#','/')), view = document;
form.onsubmit = (eve) => { chat.set(who.value+': '+what.value), eve.preventDefault(what.value = "") }
chat.map().on(function show(data, id){
(view.line = view.getElementById(id) || view.createElement("li")).id = id;
list.appendChild(view.line).innerText = emojione.shortnameToUnicode(data);
window.scroll(0, list.offsetHeight);
(list.beep = new SpeechSynthesisUtterance()).text = "new";
list.beep.rate = 10, list.beep.pitch = 2, window.speechSynthesis.speak(list.beep);
});
</script>

View File

@ -0,0 +1,2 @@
<!DOCTYPE html>
<p>Moved to <a href="./chat.html">./chat.html</a>!</p>

38
examples/basic/meet.html Normal file
View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<center>must press play or unmute on new videos to accept meeting</center>
<center id="videos">
<video id="me" width="100%" controls autoplay playsinline muted></video>
</center>
<center>Stream <select id="select"><option id="from">from</option></select></center>
<script src="../jquery.js"></script>
<script src="../../../gun/gun.js"></script>
<script src="../../../gun/sea.js"></script>
<script src="../../../gun/lib/webrtc.js"></script>
<script>;(async function(){
streams = {}, gun = Gun(location.origin + '/gun'); //gun = GUN();
mesh = gun.back('opt.mesh');
(await (me.stream = navigator.mediaDevices).enumerateDevices()).forEach((device,i) => {
if('videoinput' !== device.kind){ return }
var opt = $(from).clone().prependTo('select').get(0);
$(opt).text(opt.id = device.label || 'Camera '+i);
opt.value = device.deviceId;
});
$('select').on('change', async eve => { $(from).text('Off'); // update label
if('Off' == select.value){ return me.srcObject.getTracks()[0].stop() }
mesh.hi(me.srcObject = await me.stream.getUserMedia({ audio: true,
video: (select.value && {deviceId: {exact: select.value}}) || {facingMode: "environment"}
}));
});
gun.on('rtc', async function(eve){ var ui, src;
console.log("?RTC?", eve.peer && eve.peer.connectionState, eve);
if(!(src = eve.streams)){ return }
ui = $('#v'+(src=src[0]).id).get(0) || $(me).clone().attr('id', 'v'+src.id).prependTo('#videos').get(0); // reuse or create video element
ui.srcObject = src;
});
}());</script>

9
examples/basic/note.html Normal file
View File

@ -0,0 +1,9 @@
<!DOCTYPE html>
<style>html, body, textarea { width: 100%; height: 100%; padding: 0; margin: 0; }</style>
<textarea id="view" placeholder="write here..."></textarea>
<script src="../../../gun/gun.js"></script><script>
gun = GUN(location.origin + '/gun');
note = gun.get('note').get(location.hash.replace('#','')||1);
view.oninput = () => { note.put(view.value) };
note.on((data) => { view.value = data });
</script>

View File

@ -0,0 +1,2 @@
<!DOCTYPE html>
<p>Moved to <a href="./note.html">./note.html</a>!</p>

148
examples/basic/poll.html Normal file
View File

@ -0,0 +1,148 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="../jquery.js"></script>
<script src="../../../gun/gun.js"></script>
<script src="../../../gun/sea.js"></script>
<!-- script src="../../../gun/axe.js"></script -->
<script> // main init!
var app = {
view: $, // replace with not jquery!
data: GUN('http://localhost:8765/gun'), // peer-to-peer database!
};
app.user = app.data.user().recall({sessionStorage: true});
</script>
</head>
<body>
<div id="login" class="center pad">
<style>
#login input {
max-width: 6em;
}
</style>
<form id="sign" onsubmit="app.login(event)">
<input id="alias" placeholder="username" class="jot rim">
<input id="pass" type="password" placeholder="passphrase" class="jot rim">
<input id="in" type="submit" value="sign in" class="green whitet act gap sap rim">
<input id="up" type="button" value="sign up" onclick="app.register()" class="act gap sap rim">
</form>
<script>
app.login = function(eve){
if(app.error(eve)){ return }
app.data.user().auth(
app.view('#alias').val(),
app.view('#pass').val(),
app.error
);
};
app.register = function(eve){
app.data.user().create(
app.view('#alias').val(),
app.view('#pass').val(),
app.login
);
};
app.data.on('auth', function(eve){
app.view('#sign').hide(); // hide login form upon logging in.
});
</script>
</div>
<div id="poll" class="pad">
<style>
#poll {
display: flex;
flex-wrap: wrap;
}
#poll div {
margin: 1%;
width: 100%;
}
</style>
<script>
(window.onhashchange = async function(){
app.poll = app.data.get(location.hash.slice(1));
app.poll.map().on(function(data, id){
app.render(id = 'p'+String.hash(id), '.q', '#poll', data).css({order: data.how}).data('as',{$:this});
console.log("poll?", id, data);
});
})();
app.render = function(id, model, onto, data){
var ui = $(
$('#'+id).get(0) ||
$('.model').find(model).clone(true).attr('id', id).appendTo(onto)
);
$.each(data, function(field, val){
if($.isPlainObject(val)){ return }
ui.find("[name='" + field + "']").val(val).text(val);
});
return ui;
}
</script>
<div class="model">
<div class="q">
<span name="what"></span>
</div>
</div>
</div>
<div id="make" class="pad">
<style>
#make #add {
border-radius: 100%;
width: 2em;
height: 2em;
line-height: 0em;
padding: 0;
margin: 0;
text-align: center;
}
</style>
<button id="add" onclick="app.add()" class="green whitet act">+</button>
<span class="hint">add new title, text, question...</span>
<script>
app.add = async function(){
if(app.error(app.user)){ return }
var tmp = await (app.poll = app.poll || app.data.get(location.hash.slice(1)));
if(!tmp){ app.poll = app.user.get('poll').set({}) }
app.poll.set({how: tmp = Object.keys(tmp||'').length || 1, what: "Question " + tmp });
if(!location.hash){ location.hash = (await app.poll)._['#'] }
}
</script>
</div>
<span id="error">
<span id="err"></span>
<script>
app.error = function(eve){
app.view('#err').text('').hide();
if(!eve){ return }
if(eve.preventDefault){
eve.preventDefault();
return;
}
if(eve._ && !eve.is){ eve = {err: "Not signed in!"} }
if(!eve.err){ return }
app.view('#err').text(eve.err).show();
return true;
}
</script>
</span>
<style>
#error { position: fixed; top: 0; width: 100%; text-align: center; background: white; }
</style>
<link rel="stylesheet" href="../style.css"/>
<style>
@import url('https://fonts.googleapis.com/css?family=Oxygen');
html, body { font-family: "Oxygen", sans-serif; }
</style>
</body>
</html>

45
examples/basic/post.html Normal file
View File

@ -0,0 +1,45 @@
<!DOCTYPE html>
<h1>Posts</h1>
<form id="sign">
<input id="alias" placeholder="username">
<input id="pass" type="password" placeholder="passphrase">
<input id="in" type="submit" value="sign in">
<input id="up" type="button" value="sign up">
</form>
<form id="said">
<input id="say" placeholder="write here...">
<input id="speak" type="submit" value="say">
</form>
<ul></ul>
<script src="../jquery.js"></script>
<script src="../../../gun/gun.js"></script>
<script src="../../../gun/sea.js"></script>
<script src="../../../gun/axe.js"></script>
<script>
gun = GUN(), user = gun.user().recall({sessionStorage: true});
$('#sign').on('submit', login);
$('#up').on('click', () => { user.create($('#alias').val(), $('#pass').val(), login) });
function login(eve){
eve.preventDefault();
user.auth($('#alias').val(), $('#pass').val());
};
gun.on('auth', () => { $('#sign').hide(), user.get('said').map().on(show) });
function show(data, id){
return ($('#' + id).get(0) || $('<li>').attr('id', id).prependTo('ul')).text(data);
};
$('#said').on('submit', (eve) => {
eve.preventDefault();
if(!user.is){ return }
user.get('said').set($('#say').val());
$('#say').val("");
});
</script>

View File

@ -1,4 +1,4 @@
<html><body>
<!DOCTYPE html>
<style>
html, body {
background: rgb(245, 245, 245);
@ -70,13 +70,98 @@
Public Key: <input id="pub">
</div></div>
<script src="https://cdn.jsdelivr.net/npm/gun/examples/jquery.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gun/sea.js"></script>
<script src="../jquery.js"></script>
<script src="../../../gun/gun.js"></script>
<script src="../../../gun/sea.js"></script>
<script>
//var gun = Gun();
var gun = Gun('http://localhost:8080/gun');
// extend SEA functions to base64 encode encrypted data
// workaround for https://github.com/amark/gun/issues/783
(() => {
const _encrypt = SEA.encrypt;
SEA.encrypt = function(...args) {
return _encrypt.apply(this, args).then(enc => btoa(JSON.stringify(enc)));
}
const _decrypt = SEA.decrypt;
SEA.decrypt = function(data, ...args) {
try { data = JSON.parse(atob(data)); }
finally { return _decrypt.apply(this, [data, ...args]); }
}
})();
// override User functions to fix several issues
// see https://github.com/amark/gun/issues/808
SEA.Gun.User.prototype.grant = function grant(to, cb) {
const gun = this; const user = gun.back(-1).user();
const pair = user._.sea; let path = '';
gun.back(at => { if (at.has) { path += at.get; } });
(async () => {
let enc, sec;
if (sec = await user.get('trust').get(pair.pub).get(path).then()) {
sec = await SEA.decrypt(sec, pair);
} else {
sec = SEA.random(24).toString();
enc = await SEA.encrypt(sec, pair);
user.get('trust').get(pair.pub).get(path).put(enc);
}
let pub = to.get('pub') .then();
let epub = to.get('epub').then();
pub = await pub; epub = await epub;
const dh = await SEA.secret (epub, pair);
enc = await SEA.encrypt(sec, dh);
// if pub is not already in trust, first put an empty node
// workaround for https://github.com/amark/gun/issues/844
if (!await user.get('trust').get(pub).then()) {
await user.get('trust').get(pub).get(path).put({}).then();
}
user.get('trust').get(pub).get(path).put(enc, cb);
})();
return gun;
}
SEA.Gun.User.prototype.secret = function(data, cb) {
const gun = this; const user = gun.back(-1).user();
const pair = user._.sea; let path = '';
gun.back(at => { if (at.has) { path += at.get; } });
(async () => {
let enc, sec;
if (sec = await user.get('trust').get(pair.pub).get(path).then()) {
sec = await SEA.decrypt(sec, pair);
} else {
sec = SEA.random(24).toString();
enc = await SEA.encrypt(sec, pair);
user.get('trust').get(pair.pub).get(path).put(enc);
}
enc = await SEA.encrypt(data, sec);
gun.put(enc, cb);
})();
return gun;
}
var gun = Gun('http://localhost:8765/gun');
var user = gun.user();
var LI = {};
@ -94,7 +179,7 @@ $('#sign').on('submit', function(e){
gun.on('auth', function(){
$('#sign').hide();
$('#profile').show();
var pub = user.pair().pub;
var pub = user._.sea.pub;
$('#pub').val(pub);
return;
$("#search").val(pub).trigger('blur');
@ -126,15 +211,25 @@ $('#search').on('blur', function(e){
ev.off();
return;
}
Gun.node.is(data, async function(v, k){
if(k === LI.busy){ return }
var key = await find.get('trust').get(user.pair().pub).get(k+'profile').then();
var mix = await Gun.SEA.secret(await find.get('epub').then(), user.pair());
key = await Gun.SEA.decrypt(key, mix);
var val = await Gun.SEA.decrypt(v, key);
$('#'+k).val(val || v);
Gun.node.is(data, async (enc, id) => {
if (id === LI.busy) { return; }
const pair = user._.sea;
let key, val;
if (key =
await find.get('trust').get(pair.pub).get(id + 'profile').then()) {
const mix = await Gun.SEA.secret(await find.get('epub').then(), pair);
key = await Gun.SEA.decrypt(key, mix);
val = await Gun.SEA.decrypt(enc, key);
// decode encrypted data to show 'SEA{...}'
} else { val = JSON.parse(atob(enc)); }
$('#' + id).val(val);
});
});
});
</script>
</body></html>
</script>

View File

@ -0,0 +1,121 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
<link href='https://fonts.googleapis.com/css?family=Poiret+One' rel='stylesheet' type='text/css'>
</head>
<body>
<h1><button id="left">&larr;</button> <span id="date"></span> Schedule <button id="right">&rarr;</button></h1>
<form id="add">
<style>input[type="number"]{ width: 4em; }</style>
<input id="what" placeholder="What?">
<input id="where" placeholder="Where?">
<input type="number" id="hour"><script>hour.value = new Date().getHours() % 12 || 12</script> :
<input type="number" id="min" value="0">
<select id="ampm">
<option value="">am</option>
<option value="1">pm</option>
<script>ampm.children[new Date().getHours() < 12? 0 : 1].selected='selected'</script>
</select>
<input id="id" type="hidden">
<input id="go" type="submit" value="add">
<div id="err"></div>
</form>
<style>
.none { display: none; }
p, ul, li { list-style-type: none; margin: 0; padding: 0; }
</style>
<ul></ul>
<div class="model none">
<li>
<b class="when"></b>
<span class="what"></span>
<u class="where"></u>
<span class="sort none">0</span>
<button class="edit"><</button>
</li>
</div>
<script src="../jquery.js"></script>
<script src="../../../gun/gun.js"></script>
<script src="../../../gun/nts.js"></script>
<script src="../../../gun/lib/webrtc.js"></script>
<script>
var name = 'schedule/' + location.hash.slice(1);
var gun = Gun(location.origin + '/gun');
//var gun = Gun('http://localhost:8765/gun');
//var gun = Gun();
$('#add').on('submit', function(event){
event.preventDefault();
event = {};
if(!schedule.on){ return err.innerText = "No date!" }
event.when = new Date(schedule.on.getFullYear(), schedule.on.getMonth(), schedule.on.getDate(), hour.value % 12 + (ampm.value? 12 : 0), min.value).getTime();
if(!(event.what = what.value)){ return err.innerText = "No description!" }
if(!(event.where = where.value)){ return err.innerText = "No location!" }
var day = gun.get(name+now(event.when));
day.get(id.value || String.random(9)).put(event);
what.value = where.value = id.value = err.innerText = '';
go.value = 'add';
schedule(event.when);
});
function schedule(ms){
var day = new Date(ms);
if(schedule.on && schedule.on.toLocaleDateString() === day.toLocaleDateString()){ return } schedule.on = day;
$('#date').text(day.getFullYear()+' '+ day.toString().split(' ')[1] +' '+day.getDate());
day = gun.get(name+now(ms));
$('ul').empty();
day.map().on(UI);
}
schedule(+new Date());
$('#left').on('click', function(){ schedule(+new Date(schedule.on.getFullYear(), schedule.on.getMonth(), schedule.on.getDate() - 1)) });
$('#right').on('click', function(){ schedule(+new Date(schedule.on.getFullYear(), schedule.on.getMonth(), schedule.on.getDate() + 1)) });
function UI(event, id){
if(!event){ return }
var when = new Date(event.when);
if(schedule.on && when.toLocaleDateString() !== schedule.on.toLocaleDateString()){ return }
var ul = $('ul')
var li = $("#cal-" + id)[0]; // grab if exists
if(!li){
li = $('.model li').clone(true) // else create it
.attr('id', 'cal-' + id);
}
li = (UI.last = sort(event.when, ul.children('li').last())[0])? $(li).insertAfter(UI.last) : $(li).prependTo(ul);
li.find('.what').text(event.what);
li.find('.where').text(event.where);
li.find('.sort').text(event.when);
li.find('.edit').val(id);
var time = when.toLocaleTimeString();
li.find('.when').text(time.split(':').slice(0,2).join(':') + time.slice(-2));
};
$(document).on('click', '.edit', function(){
go.value = 'update';
id.value = this.value;
what.value = $(this).parent().find('.what').text();
where.value = $(this).parent().find('.where').text();
var when = new Date(parseFloat($(this).parent().find('.sort').text()));
hour.value = when.getHours() % 12 || 12;
min.value = when.getMinutes();
ampm.value = when.getHours() < 12? '' : 1;
what.focus();
});
function now(t){
return new Date(t || Gun.state()).toLocaleDateString().split('/').reverse().join('/')
}
function sort(num, li){ return parseFloat(num) >= parseFloat($(li).find('.sort').text() || -Infinity)? li : sort(num, li.prev()) }
</script>
</body>
</html>

View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<video id="video" width="100%"></video>
<center>
<button id="record">Record</button>
<button id="play">Play</button>
</center>
<script src="../jquery.js"></script>
<script src="../../../gun/gun.js"></script>
<script>
var gun = Gun(location.origin + '/gun');
var record = {recorder: null, recording: false};
$('#record').on('click', ()=>{
if(!record.ing){ return record.stream() }
$('#record').text("Record");
if(record.ing.stop){ record.ing.stop() }
record.ing = false;
})
record.stream = function(){
navigator.mediaDevices.getDisplayMedia({ video: true }).then(stream => {
var chunks = []; // we have a stream, we can record it
record.ing = new MediaRecorder(stream);
record.ing.ondataavailable = eve => chunks.push(eve.data);
record.ing.onstop = eve => record.save(new Blob(chunks));
record.ing.start()
$('#record').text("End");
}, err => { console.log(err) });
}
record.save = function(data){
record.file = record.file || new FileReader();
record.file.readAsDataURL(data);
record.file.onloadend = function(){
var b64 = record.file.result;
b64 = "data:video/webm" + b64.slice(b64.indexOf(';'));
gun.get('test').get('screen').put(b64);
}
}
$('#play').on('click', ()=>{
if(record.playing){
$('#play').text("Play")
$('#video').get(0).stop();
record.playing = false;
return;
}
$('#play').text("Stop");
record.playing = true;
gun.get('test').get('screen').once((data)=>{
if(!data){ return }
$('#video').get(0).src = data;
$('#video').get(0).play()
})
})
</script>

View File

@ -1,50 +0,0 @@
<h1>Search</h1>
<form id="ask">
<input id="search" placeholder="search..." autocomplete="off">
</form>
<div id="answer"></div>
<ul></ul>
<small>Note: No data is indexed by default, you need to add some!</small>
<script src="../../examples/jquery.js"></script>
<script src="../../gun.js"></script>
<script src="../../sea.js"></script>
<script src="../../lib/space.js"></script>
<script>
var gun = Gun();
var ask = {};
$('#search').on('keyup', function(e){
ask.now = (this.value||'').toLowerCase().replace(/[\W_]+/g,"");
if(ask.last === ask.now){ return }
ask.last = ask.now;
clearTimeout(ask.to);
ask.to = setTimeout(search, 20);
});
function search(){
var key = ask.now;
gun.get('Q').space(key, function(ack){
if(!ack || key !== ask.now){ return }
UI(ack)
});
}
function UI(ack){
$('#answer').text(ack.data || '');
var $ul = $('ul').empty(), tree = ack.tree;
Gun.obj.map(tree, function(v,k){
$('<li>').text(k +' - ' + v).appendTo($ul);
});
};
function load(DATA){
Gun.obj.map(DATA, function(v,k){
gun.get('Q').space(k, v);
});
}
</script>

View File

@ -0,0 +1,55 @@
<!DOCTYPE html>
<center>
<img id="img" width="100%"><br/>
Stream <select id="select"><option id="from">from</option></select>
add <input id="pass" placeholder="password" type="password">
resolution <input id="res" value="240" step="32" max="1080" type="number" style="width:3em;">
or <input id="upload" type="file">
</center>
<video id="video" width="100%" controls autoplay style="display: none;"></video>
<canvas id="canvas" width="0" style="display: none;"></canvas>
<script src="../jquery.js"></script>
<script src="../../../gun/gun.js"></script>
<script src="../../../gun/sea.js"></script>
<script src="../../../gun/lib/webrtc.js"></script>
<script>;(async function(){
gun = Gun(location.origin + '/gun'); //gun = GUN();
stream = canvas.getContext('2d'), stream.from = navigator.mediaDevices;
(await stream.from.enumerateDevices()).forEach((device,i) => {
if('videoinput' !== device.kind){ return }
var opt = $(from).clone().prependTo('select').get(0);
$(opt).text(opt.id = device.label || 'Camera '+i);
opt.value = device.deviceId;
});
$('select').on('change', async eve => { $(from).text('Off'); // update label
if('Off' == select.value){ return video.srcObject.getTracks()[0].stop() }
video.srcObject = await stream.from.getUserMedia({ audio: false,
video: (select.value && {deviceId: {exact: select.value}}) || {facingMode: "environment"}
});
});
$('#upload').on('change', async eve => { console.log("Check ./upload.html") })
setInterval(async tmp => {
if(!(video.srcObject||'').active){ return }
var size = parseInt(res.value);
stream.drawImage(video, 0,0,
canvas.width = size || video.videoWidth * 0.1,
canvas.height = (size * (video.videoHeight/video.videoWidth)) || video.videoHeight * 0.1
);
var b64 = canvas.toDataURL('image/jpeg');
if(pass.value){ b64 = await SEA.encrypt(b64, pass.value) }
gun.get('test').get('video').put(b64);
}, 99);
gun.get('test').get('video').on(async data => {
if(pass.value){ data = await SEA.decrypt(data, pass.value) }
img.src = data; // Beware: Some browsers memory leak fast src updates.
});
}());</script>

View File

@ -1,3 +1,5 @@
<!DOCTYPE html>
<h1>Tables</h1>
<form id="sign">

View File

@ -0,0 +1,35 @@
<!DOCTYPE html>
<div class="model" style="display: none;">
<video width="100%" controls autoplay></video>
<audio width="100%" controls autoplay></audio>
<img style="max-width: 100%;">
</div>
<center>
<p>Drag & drop videos, songs, or images! <input id="upload" type="file" multiple></p>
</center>
<script src="../../../gun/lib/yson.js"></script>
<script src="../../../gun/gun.js"></script>
<script src="../../../gun/lib/dom.js"></script>
<script src="../../../gun/lib/upload.js"></script>
<script>
gun = GUN(location.origin + '/gun');
$('html, #upload').upload(function resize(eve, up){
if(up){ return up.shrink(eve, resize, 1024) }
var b64 = (eve.base64 || ((eve.event || eve).target || eve).result || eve); // which one? try all!
gun.get('test').get((eve.id+(new Date).getUTCSeconds()) % 60).put(b64); // limit uploads to 1 of 60 slots.
});
gun.get('test').map().once(function(data){
if("string" != typeof data){ return }
var type = data.split(';')[0], ui;
if(type.indexOf('image') + 1){ ui = $("img").get(0) }
if(type.indexOf('video') + 1){ ui = $('video').get(0) }
if(type.indexOf('audio') + 1){ ui = $('audio').get(0) }
if(!ui){ return }
$(ui).clone().prependTo('center').get(0).src = data;
});
</script>

View File

@ -1,52 +1,2 @@
<h1>User</h1>
<form id="sign">
<input id="alias" placeholder="username">
<input id="pass" type="password" placeholder="passphrase">
<input id="in" type="submit" value="sign in">
<input id="up" type="button" value="sign up">
<input id="mask" type="button" value="MetaMask Login">
</form>
<ul></ul>
<form id="said">
<input id="say">
<input id="speak" type="submit" value="speak">
</form>
<script src="../jquery.js"></script>
<script src="../../../gun/gun.js"></script>
<script src="../../../gun/sea.js"></script>
<script>
var gun = Gun(); //Gun(['http://localhost:8765/gun', 'https://guntest.herokuapp.com/gun']);
var user = gun.user().recall({sessionStorage: true});
$('#up').on('click', function(e){
user.create($('#alias').val(), $('#pass').val(), login);
});
function login(e){
user.auth($('#alias').val(), $('#pass').val());
return false; // e.preventDefault();
};
$('#sign').on('submit', login);
$('#mask').on('click', login);
gun.on('auth', function(){
$('#sign').hide();
user.get('said').map().on(UI);
});
$('#said').on('submit', function(e){
e.preventDefault();
//if(!user.is){ return }
user.get('said').set($('#say').val());
$('#say').val("");
});
function UI(say, id){
var li = $('#' + id).get(0) || $('<li>').attr('id', id).appendTo('ul');
$(li).text(say);
};
</script>
<!DOCTYPE html>
<p>Moved to <a href="./post.html">./post.html</a>!</p>

62
examples/basic/video.html Normal file
View File

@ -0,0 +1,62 @@
<!DOCTYPE html>
<video id="video" width="100%" controls autoplay></video>
<center>
<input id="pass" placeholder="password">
Record <button class="record">Camera</button> or <button class="record">Screen</button>
</center>
<script src="../jquery.js"></script>
<script src="../../../gun/gun.js"></script>
<script src="../../../gun/sea.js"></script>
<script>
var gun = Gun(location.origin + '/gun');
gun.get('test').get('video').on(async function(data){
if($('#pass').val()){ data = await SEA.decrypt(data, $('#pass').val()) }
$('#video').get(0).src = data;
})
$('.record').on('click', function(){
if(record.ing){
if(record.ing.stop){ record.ing.stop() }
$(this).text(record.type);
record.ing = false;
return;
}
record(record.type = $(this).text());
$(this).text("End");
})
function record(type){
if('Camera' === type){
navigator.getMedia({ video: true, audio: true }, load, error);
}
if('Screen' === type){
navigator.mediaDevices.getDisplayMedia({ video: true, audio: true }).then(load, error);
}
function load(media){
var chunks = [];
record.ing = new MediaRecorder(media);
record.ing.ondataavailable = function(eve){ chunks.push(eve.data) }
record.ing.onstop = function(eve){record.save(new Blob(chunks)) }
record.ing.start();
}
function error(err){ console.log(err) }
}
record.save = function(data){
record.file = record.file || new FileReader();
record.file.readAsDataURL(data);
record.file.onloadend = async function(){
var b64 = record.file.result, pass;
b64 = $('#video').get(0).src = "data:video/webm" + b64.slice(b64.indexOf(';'));
if($('#pass').val()){ b64 = await SEA.encrypt(b64, $('#pass').val()) }
gun.get('test').get('video').put(b64);
}
}
navigator.getMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia
|| navigator.mozGetUserMedia || navigator.msGetUserMedia);
</script>

View File

@ -1,161 +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(id, li){
var num = parseFloat(id);
var id = $(li).find('.sort').text() || -Infinity;
var at = num >= parseFloat(id);
return at ? li : sort(id, 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.state() };
msg.who = $('.chat__name-input').val();
if (!msg.who) {
msg.who = 'user' + String.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().once(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>

379
examples/docs.html Normal file
View File

@ -0,0 +1,379 @@
<!DOCTYPE html>
<html>
<head>
<!-- always start with these two lines to set a clean baseline for different devices -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="jquery.js"></script>
<title>Docs</title>
</head>
<body class="black whitet">
<style>
/*
Choose white text on a black background so you can add color in.
Pick your favorite font and choose a font size.
*/
@import url('https://fonts.googleapis.com/css?family=Oxygen');
html, body {
font-family: "Oxygen", sans-serif;
}
[contenteditable]:focus {
outline: none;
}
.meta-on, div:hover, ul:hover, ol:hover, li:hover, p:hover, span:hover, form:hover, button:hover, input:hover, textarea:hover, img:hover {
outline: 1px solid;
animation: meta-on 3s infinite;
transition: none !important;
} @keyframes meta-on {
0% {outline-color: magenta;}
33% {outline-color: cyan;}
66% {outline-color: yellow;}
100% {outline-color: magenta;}
}
</style>
<div class="hold full hue2">
<div id="page" class="max focus gap" style="margin-top: 9%;"></div>
</div>
<script src="../../gun/gun.js"></script>
<script src="../../gun/lib/monotype.js"></script>
<script src="../../gun/lib/meta.js"></script>
<script src="../../gun/lib/normalize.js"></script>
<script async src="../../gun/lib/fun.js"></script>
<script async src="../../gun/lib/wave.js"></script>
<!-- script async src="https://edide.io/music.lib"></script -->
<script>
var gun = Gun();
var page = {};
//var gun = Gun(['https://guntest.herokuapp.com/gun', 'http://localhost:8765/gun']);
;(window.onhashchange = function(){
var file = (location.hash||'').slice(1);
var S = +new Date;
$('#page').empty().attr('contenteditable', 'false');
gun.get('test/gun/docs/'+file).get('what').map().on(function render(data, i, msg, eve){
var tmp = page[i] || '';
var last = Gun.state.is(gun._.root.graph[msg.put['#']], i);
if(last < tmp.last){ return }
//});
//if(window.LOCK){ return }
var p = $('#page').children().get(i);
if(!p){
$('#page').append('<p>');
setTimeout(function(){ render(data, i, msg, eve) },0);
return;
}
var DBG = {s: +new Date};
var r = monotype(p);
DBG.mono = +new Date;
var safe = $.normalize(data);
DBG.norm = +new Date;
p.outerHTML = data;
DBG.html = +new Date;
r.restore();
DBG.rest = +new Date;
//console.log("mono:", DBG.mono - DBG.s, "norm:", DBG.norm - DBG.mono, 'html:', DBG.html - DBG.norm, 'rest:', DBG.rest - DBG.html, ':::', msg, eve);
});
})();
window.requestAnimationFrame = window.requestAnimationFrame || setTimeout;
window.requestAnimationFrame(function frame(){
window.requestAnimationFrame(frame, 16);
}, 16);
document.execCommand('defaultParagraphSeparator', false, 'p');
meta.edit({
name: "Edit",
combo: ['E'],
use: function(eve){
console.log('on');
}, on: function(eve){
if($(eve.target).closest('p').length){ return }
var edit = this;
setTimeout(function(){ meta.flip(false) },1);
edit.init();
$(document).on('keydown.tmp', '[contenteditable]', function(eve){
if(eve.which != 13){ return }
eve.preventDefault();
var r = window.getSelection().getRangeAt(0);
var c = r.commonAncestorContainer, p;
r.deleteContents();
var p = c.splitText? $(c.splitText(r.startOffset)).parent() : $(c);
var n = $("<"+p.get(0).tagName+">"), f;
p.contents().each(function(){
if(this === c){ return f = true }
if(!f){ return }
n.append(this);
});
p.after(n);
edit.select(n.get(0));
// make sure we re-save & sync each changed paragraph.
edit.save(p);
p.nextAll().each(function(){
edit.save(this);
});
}).on('keyup.tmp', '[contenteditable]', function(eve){
//$('#debug').val(doc.html());
var p = $(window.getSelection().anchorNode).closest('p'), tmp;
(tmp = page[p.index()] || (page[p.index()] = {})).last = (+new Date) + 99;
clearTimeout(tmp.to); tmp.to = setTimeout(function(){
var DBG = {s: +new Date};
var r = monotype(p);
DBG.m = +new Date;
var html = p.html() || '';
DBG.g = +new Date;
if(!html && !p.prev().length && !p.next().length && !$('#page').html()){
edit.init();
}
DBG.i = +new Date;
var safe = $.normalize(html);
DBG.n = +new Date;
p.html(safe);
DBG.h = +new Date;
r.restore();
DBG.r = +new Date;
edit.save(p);
DBG.p = +new Date;
//console.log("save:", DBG.p - DBG.r, "rest:", DBG.r - DBG.h, "html:", DBG.h - DBG.n, "norm:", DBG.n - DBG.i, 'init:', DBG.i - DBG.g, 'grab:', DBG.g - DBG.m, 'mono:', DBG.m - DBG.s);
},50)});
},
up: function(){
console.log("UP");
$('[contenteditable=true]').off('.tmp');
},
init: function(){
var edit = this;
var doc = $('#page').attr('contenteditable', 'true');
if(!doc.text()){
doc.html('<p class="loud crack"></p>');
}
edit.select(doc.children().first().get(0));
},
save: function(p){
p = $(p);
var i = p.index();// = Array.prototype.indexOf.call(parent.children, child);
var file = (location.hash||'').slice(1);
var data = (p.get(0)||{}).outerHTML||'';
//data = $.normalize(data); // GOOD TO DO SECURITY ON SENDING SIDE TOO!!!
window.LOCK = true;
gun.get('test/gun/docs/'+file).get('what').get(i).put(data);
window.LOCK = false;
},
select: function(p){
var s = window.getSelection(),
r = document.createRange();
if(p.innerHTML){
r.setStart(p, 0);
r.collapse(true);
s.removeAllRanges();
s.addRange(r);
return;
}
p.innerHTML = '\u00a0';
r.selectNodeContents(p);
s.removeAllRanges();
s.addRange(r);
document.execCommand('delete', false, null);
}
});
;(function(){
meta.edit({name: "Design", combo: ['D']});
meta.edit({name: "Fill", combo: ['D','F'], // TODO!
use: function(eve){},
on: function(eve){
var on = meta.tap();
meta.ask('Color name, code, or URL?', function(color){
on.css('background', color);
}, true);
},
up: function(eve){}
});
meta.edit({name: "Add", combo: ['D','A']});
meta.edit({name: "Row", combo: ['D','A', 'R'],
on: function(eve){
meta.tap().append('<div style="min-height: 9em; padding: 2%;">');
}
});
meta.edit({name: "Columns", combo: ['D','A','C'],
on: function(eve){
var on = meta.tap().addClass('center'), tmp, c;
var html = '<div class="unit col" style="min-height: 9em; padding: 2%;"></div>';
if(!on.children('.col').length){ html += html }
c = (tmp = on.append(html).children('.col')).length;
tmp.each(function(){
$(this).css('width', (100/c)+'%');
})
}
});
meta.edit({name: "Text", combo: ['D','A','T'],
on: function(eve){
var tag = $('<p>text</p>');
meta.tap().append(tag);
tag.focus();
}
});
meta.edit({name: "Delete", combo: ['D','A','D'],
on: function(eve){
meta.tap().remove();
}
});
meta.edit({name: "Turn", combo: ['D','T']});
meta.edit({name: "Size", combo: ['D','S']});
meta.edit({name: "X", combo: ['D','S','X'],
on: function(eve){
var on = this.a = meta.tap().addClass('meta-on'), was = on.width();
$(document).on('mousemove.tmp', function(eve){
var be = was + ((eve.pageX||0) - was);
on.css({'max-width': be, width: '100%'});
});
meta.ask('Width in px, %, or other unit?', function(w){
if(!w){ return }
on.css({'max-width': w, width: '100%'});
}, true);
}, up: function(){
$(document).off('mousemove.tmp');
this.a.removeClass('meta-on');
}
});
meta.edit({name: "Y", combo: ['D','S','Y'],
//on: function(eve){ console.log('on Y') },
on: function(eve){ console.log('use Y')
var on = this.a = meta.tap().addClass('meta-on'), was = on.height();
$(document).on('mousemove.tmp', function(eve){
var be = was + ((eve.pageY||0) - was);
on.css({'min-height': be});
})
}, up: function(){ console.log('up Y')
$(document).off('mousemove.tmp');
this.a.removeClass('meta-on');
}
});
}());
;(function(){
var logic = {};
meta.edit({name: "Logic", combo: ['L']});
meta.edit({name: "Symbol", combo: ['L','S'],
on: function(eve){
console.log(1);
}
});
meta.edit({name: "Action", combo: ['L','A'],
on: function(eve){
console.log(2);
}
});
meta.edit({name: "Data", combo: ['L','D'],
on: function(eve){
console.log(3);
}
});
}());
;(function(){
var song = {};
// TODO:
// 1. Manually OR automatically load music.js API, dependencies, and modules. - FINE for now
// 2. only export music API, not meta, not dom, not mouselock system, not UI/html, etc. better module isolation and export.
// 3. `var wave = Wave('a').play()` // also on `Music.now`
// defaults... instrument: pure tones, volume curve: |\_ , speed curve: 0.5
// 4. `wave.blur(0.5).itch(0.5);`
// 5. wave.long(2); // how long in seconds each note plays, optionally: wave.pace(60) is bpm
// 6. wave.loud(0.5); // 0% to 100% volume loudness of device output.
// 7. wave.vary(0.5); // slows down or speeds up wiggle per harmonic
// 8:
// wave structure, does ToneJS allow us to change the sine wave smoothness/type continuously or is it a pre-fixed type?
// wave structure: /\/\/, |_|, /|/, \|\| do some research with ToneJS whether these are dynamic or fixed
// wave.itch(); // changes the shape of the wiggle from smooth sine to square or triangle
// wave.blur(220hz); // blur may not apply/work on pure notes other than filtering them.
meta.edit({name: "Music", combo: ['M']});
meta.edit({name: "Play", combo: ['M','P'],
on: function(eve){
// TODO: We still need to add to meta API ability to change name.
if(song.play){
music.stop();
song.play = false;
return;
}
song.play = true;
music.stop();
setTimeout(function(){
song.now = wave($('#page').text()).play();
},250);
}
});
meta.edit({name: "Blur", combo: ['M','B'],
on: function(eve){
$(document).on('mousemove.tmp', function(eve){
var x = eve.pageX;
song.now.loud(x/$('body').innerWidth());
});
},
up: function(){
$(document).off('.tmp');
}
});
$(document).on('keydown', function(eve){
if(eve.which === music.which){ return }
music.play(String.fromCharCode(music.which = eve.which));
});
}());
;(function(){
/*
Edit
Bold
Italic
Link
?
Left
Middle
Right
Justify
?
Small
Normal
Header
Title
Design
Add
Row
Column
Text
Delete
Turn
Grab
Size
X
Y
Fill
Logic
Symbol
Action
Data
*/
/*
*/
}());
</script>
</body>
</html>

439
examples/game/furball.html Normal file
View File

@ -0,0 +1,439 @@
<!DOCTYPE html>
<html>
<head>
<!-- always start with these two lines to set a clean baseline for different devices -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="../style.css">
<!-- link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/gun/examples/style.css" -->
<script src="https://cdn.jsdelivr.net/npm/gun/examples/jquery.js"></script>
<title>Furball</title>
</head>
<body class="black whitet">
<style>
/*
Choose white text on a black background so you can add color in.
Pick your favorite font and choose a font size.
*/
@import url('https://fonts.googleapis.com/css?family=Mali');
html, body {
font-family: "Mali", sans-serif;
}
.huef {
background: #4D79D8;
-webkit-animation: huef 9s infinite;
animation: huef 9s infinite;
} @keyframes huef {
0% {background-color: #4D79D8;}
25% {background-color: #33cc33;}
50% {background-color: #f2b919;}
75% {background-color: #ea3224;}
100% {background-color: #4D79D8;}
} @-webkit-keyframes huef {
0% {background-color: #4D79D8;}
25% {background-color: #33cc33;}
50% {background-color: #f2b919;}
75% {background-color: #ea3224;}
100% {background-color: #4D79D8;}
}
button, input {
padding: 1em;
background: transparent;
border: 1px solid white;
border-radius: 1.5em;
color: white;
margin: 0.5em;
margin-bottom: 0;
cursor: pointer;
}
button:hover, input:hover {
background: white;
color: black;
transform: scale(1.1);
}
.air { padding-top: 9%; }
.yak button { font-size: 80%; }
.wag {
-webkit-animation: wag 3s infinite;
animation: wag 3s infinite;
} @keyframes wag {
0% {transform: rotate(0deg);}
50% {transform: rotate(-1deg);}
100% {transform: rotate(0deg);}
}
@keyframes print {
0% { overflow: hidden; height: 0vh; }
99% { overflow: hidden; height: 100vh; }
100% { overflow: visible; height: auto; }
}
input {
outline: none;
}
</style>
</style>
<!-- for educational sites, consider starting with a nice full screen welcome message -->
<div class="home hold full huef center air">
<div class="focus row">
<p><i>Neon ERA presents</i></p>
<p class="shout wag">Furball Forces</p>
<!-- just like in real life, say who you are and give a concise reason why you add value to someone's life and then make a call to action, if they want to learn more they can always scroll to learn more -->
<div>
<!-- a class="unit hold" href="#fullscreen"><button>WATCH TRAILER</button></a -->
<a class="unit yak" href="#choose"><button>PLAY GAME</button></a>
</div>
</div>
<div class="focus center row leak">
<!-- just like in real life, looking pretty attracts attention, so show off and look glamorous! -->
<img class="unit blink" src="file:///Users/mark/Pictures/supercatdog.png" style="min-width: 10em; width: 80%;">
</div>
<script>location.hash = ''</script>
<script src="https://cdn.jsdelivr.net/npm/gun/lib/fun.js"></script>
<script>;(function(){
// OPTIONAL MUSIC:
$('.home button').on('click', function(){
if(window.screen.height > window.screen.width){ return }
$('body').append("<div id='audio' onclick='$(this).remove();'><iframe width='0' height='0' src='https://www.youtube-nocookie.com/embed/LLPoZGX0qZk?autoplay=1' frameborder='0'></iframe></div>");
})
}());
</script>
<style>#audio { padding: 0.5em; position: fixed; bottom: 0; left: 0; } #audio:before { content: '\25BA'; } #audio:hover:before { content: '\25FC'; }</style>
</div>
<div id="choose" class="hold full hue4 center air">
<div class="focus row">
<p class="shout wag fur">Choose Team:</p>
<div>
<a class="unit yak" href="#automecha"><button style="background: white; color: black;">#AutoMecha</button></a>
<a class="unit yak" href="#cyberninjas"><button style="background: black; color: white; border-color: black;">#CyberNinjas</button></a>
</div>
</div>
<div class="focus center row leak">
<img class="unit blink" src="file:///Users/mark/Pictures/supercatdog.png" style="transform: scaleX(-1); filter: invert(1); min-width: 10em; width: 80%;">
</div>
</div>
<div id="cyberninjas" class="hold full black">
<style>
#cyberninjas:target .story {
animation: print 3s steps(50, end);
}
</style>
<div class="story pad">
<p class="loud crack">Episode 1: Waking</p>
<p>"How long until they're online?"</p>
<p>"We're copying the soul files, almost done."</p>
<p>"Monsters are on the bridge, we do not have time!"</p>
<p>"The new body is printing now, it'll be able to outrun them all, just hold on."</p>
<p>"It won't know where to run! We're risking ruining the whole resistance, I need to talk to it now."</p>
<p>"95% done." The voice behind the glass turns to the soul in the body, "My cub, can you hear me?"</p>
<p>...</p>
<a class="unit yak" href="#cyberninjas2"><button>Reply "Yes, Mom?"</button></a>
</div>
<script>
;(function(){
$('#cyberninjas a').on('click', function(){
$('#hud .life').removeClass('down');
});
}());
</script>
</div>
<div id="cyberninjas2" class="hold full red">
<style>
#cyberninjas2:target .story {
animation: print 3s steps(50, end);
}
#hud {
opacity: 0.4;
font-family: 'Audiowide', cursive;
z-index: 999999999999;
transition: all 3s;
}
#hud .life {
position: fixed;
left: 50%;
bottom: 0px;
padding: 0.25em 1em 0.1em;
border-radius: 0.5em 0.5em 0 0;
transform: translateX(-50%);
background: black;
text-shadow: 0em -0.125em 0.75em white;
}
#hud .score {
position: fixed;
left: 50%;
top: 0px;
padding: 0.1em 1em 0.25em;
border-radius: 0 0 0.5em 0.5em;
transform: translateX(-50%);
background: black;
text-shadow: 0em 0.1em 0.75em white;
}
#hud .down {
bottom: -2em !important;
}
#hud .up {
top: -2em !important;
}
</style>
<div id="hud">
<div class="score shade up">
SCORE: <span id="hudscore">0</span>%
</div>
<div class="life shade down">
LIFE: <span id="hudlife">50</span>%
</div>
</div>
<div class="story pad">
<p>A fire explodes in the room behind the glass as an AutoMecha blows the door open.</p>
<p>The floor shakes and the bed crashes through the wall, flying out of the building.</p>
<p class="center">"Mom!!!"</p>
<p>There is a total free fall from 10 levels up, water down below.</p>
<p>...</p>
<a class="unit yak" href="#cyberninjas3"><button>Dive or Die</button></a>
</div>
<script>
;(function(){
$('#cyberninjas2 a').on('click', function(){
$('#hudlife').text($('#hudlife').data().is = 50);
});
}());
</script>
</div>
<div id="cyberninjas3" class="hold full blue">
<style>
@import url('https://fonts.googleapis.com/css?family=Audiowide');
#cyberninjas3:target .story {
animation: print 3s steps(50, end);
}
</style>
<div class="story pad">
<p>The water splashes, swelling and swirling all around.</p>
<p>...</p>
<p class="center">Rapidly tap to swim up to air:</p>
<a class="unit yak"><button>Swim</button></a>
</div>
<script>
;(function(){
var go, life = $('#hudlife').data();
$('#cyberninjas3 a').on('click', function(){
$('#hudlife').text(life.is += 5);
if(100 <= life.is){
location.hash = 'cyberninjas4';
clearInterval(go);
go = false;
return;
}
if(go){ return }
go = setInterval(function(){
if(0 >= life.is){
location.hash = 'cyberninjas2';
$('#hudlife').text(life.is = 50);
clearInterval(go);
go = false;
return;
}
$('#hudlife').text(life.is -= 5);
}, 1000); // 1 second
});
}());
</script>
</div>
<div id="cyberninjas4" class="hold full black">
<style>
#cyberninjas4:target .story {
animation: print 3s steps(50, end);
}
</style>
<div class="story pad">
<p class="loud crack">Episode 2: Who Am I?</p>
<p>"Grab on!" A voice calls out from the darkness.</p>
<p>A life vest hits the water and floats within arm's distance.</p>
<p>The shivering body is pulled up onto the boat.</p>
<p>"Wow, you're heavier than you look. Are you OK? What's your name?"</p>
<p>...</p>
<p class="center">Write your reply & hit enter:</p>
<form class="center">
<input class="loud" style="width: 60%;">
</form>
</div>
<script>
;(function(){
$('form').on('submit', function(eve){ eve.preventDefault() });
$('#cyberninjas4').on('submit', function(){
var name = $(this).find('input').val();
if(!name.length){ return }
$('.story-name').text(' '+(window.NAME = name));
$('#hud .score').removeClass('up');
location.hash = 'cyberninjas5';
})
}());
</script>
</div>
<div id="cyberninjas5" class="hold full green">
<style>
#cyberninjas5:target .story {
animation: print 3s steps(50, end);
}
</style>
<div class="story pad">
<p>"Well<span class="story-name"></span>, it's a miracle you did not die in the building explosion or from that fall."</p>
<p>"What is going on? What happened?"</p>
<p>"You can't remember? Your brain must be knocked up pretty hard."</p>
<p>"No, I was mid copy into this body and now my memories are glitching."</p>
<p>"Woah, you're one of those pro elite AREION revolutionaries? All flesh & blood! Dense, too. I would've assumed they were stealing AutoMecha tech for that instead."</p>
<p>"I was about to be told vital data for the resistance, but then they blew up the build--"</p>
<p>...</p>
<p>"Hey, what's the matter?"</p>
<p>"My mom. She was in there. I need to go back. Please, help me and tell me everything you know."</p>
<p>"I'm so sorry. I can only get so close with the boat, you're gonna have to jump over a lot of broken bits. You ready?"</p>
<p>...</p>
<a class="unit yak" href="#cyberninjas6"><button>GO!</button></a>
</div>
</div>
<div id="cyberninjas6" class="hold full green">
<style>
#cyberninjas6:target .story {
animation: print 3s steps(50, end);
}
</style>
<div class="story pad">
<p class="center">... to be continued ...</p>
<div id="player" style="position: fixed; width: 1em; height: 1em; background: white; left: 50%; top: 50%; border-radius: 100%;"></div>
<!-- jumping game ? like offline dinosaur ? -->
</div>
<script src="../../../gun/lib/meta.js"></script>
<script>
;(function(){
var p = $('#player');
p.x = 50;
p.y = 50;
meta.edit({
name: "Up",
combo: ["W"],
on: function(){
console.log("up");
this.to = this.to || setInterval(this.on, 100);
$("html, body").stop().animate({ scrollTop: $(window).scrollTop()-100 }, 100);
p.css({top: --p.y +'%'});
},
use: function(){},
up: function(){ clearTimeout(this.to); this.to = 0 }
});
meta.edit({
name: "Left",
combo: ["A"],
on: function(){
console.log("left");
this.to = this.to || setInterval(this.on, 100);
p.css({left: --p.x +'%'});
},
use: function(){},
up: function(){ clearTimeout(this.to); this.to = 0 }
});
meta.edit({
name: "Down",
combo: ["S"],
on: function on(){
console.log("down");
this.to = this.to || setInterval(this.on, 100);
$("html, body").stop().animate({ scrollTop: $(window).scrollTop()+100 }, 100);
p.css({top: ++p.y +'%'});
},
use: function(){},
up: function(){ clearTimeout(this.to); this.to = 0 }
});
meta.edit({
name: "Right",
combo: ["D"],
on: function(){
console.log("right");
this.to = this.to || setInterval(this.on, 100);
p.css({left: ++p.x +'%'});
},
use: function(){},
up: function(){ clearTimeout(this.to); this.to = 0 }
});
meta.edit({
name: "Jump",
combo: [32],
on: function(){ console.log("jump") },
use: function(){},
up: function(){}
});
meta.edit({
name: "Crouch",
combo: [16],
on: function(){ console.log("crouch") },
use: function(){},
up: function(){}
});
meta.edit({
name: "Use",
combo: ["E"],
on: function(){ console.log("use") },
use: function(){},
up: function(){}
});
meta.edit({
name: "Fire",
combo: ["F"],
on: function(){ console.log("fire") },
use: function(){},
up: function(){}
});
meta.edit({
name: "Switch",
combo: [9],
on: function(){ console.log("Switch") },
use: function(){},
up: function(){}
});
window.requestAnimationFrame = window.requestAnimationFrame || setTimeout;
window.requestAnimationFrame(function frame(){
window.requestAnimationFrame(frame, 16);
}, 16);
}());
</script>
</div>
<div id="automecha" class="hold full white blackt">
<style>
#automecha:target .story {
animation: print 3s steps(50, end);
}
</style>
<div class="story pad">
<p class="loud crack">Episode 1: Training</p>
<p>...</p>
</div>
</div>
<div class="hold black center">
<div class="pad">
<div class="left">
<p class="loud">For <i>You</i>,</p>
<p>Crafted with love, <span class="redt"></span> by ERA.</p>
</div>
</div>
<div>
<img src="https://era.eco/media/world.png" class="row">
</div>
</div>
</body>
</html>

View File

@ -3,7 +3,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="text-align: center;">
<h1 id="when" style="font-size: 7vw; margin-top: 43vh;"></h1>
<h1 id="when" style="font-size: 7vw; margin-top: 43vh; font-family: monospace;"></h1>
</body>
<script src="/gun.js"></script>
<script src="/gun/nts.js"></script>
@ -16,4 +16,4 @@
when.innerHTML = print;
});
</script>
</html>
</html>

View File

@ -10,12 +10,12 @@
<p id="debug" style="position: fixed; bottom: 0px; color: white; height: 1em;"></p>
<script src="../jquery.js"></script>
<script src="../../../gun/gun.js"></script>
<script src="../../../gun/nts.js"></script>
<!-- script src="../../../gun/nts.js"></script -->
<script src="../../../gun/lib/webrtc.js"></script>
<script>
// Thanks to https://github.com/dmcinnes/HTML5-Asteroids
//var gun = Gun();
var gun = Gun(location.host? location.origin+'/gun' : 'http://localhost:8765/gun');
var gun = GUN(location.origin + '/gun');
var game = {gun: gun.get('example/game/space'), area: {}, ships: {}};
game.keys = {38: 'up', 37: 'left', 39: 'right', 40: 'down', 32: 'space'};
$(document).on('keydown', function(e){
@ -50,7 +50,7 @@
}
game.ship = function(d, el){
if(!d){ // spawn our ship
var id = Gun.text.random(1, 'abcdefghijklmno');
var id = String.random(1, 'abcdefghijklmno');
game.me = game.ships[id] = {data: d = {id: id, t: game.now}};
game.me.gun = game.gun.get('players').get(d.id).put(d);
return;
@ -101,7 +101,8 @@
s.ay = 0;
}
Gun.obj.map(game.ships, function(ship){
Object.keys(game.ships).forEach(function(key, ship){
ship = game.ships[key];
if(ship.gun){ return }
if(!ship.l){ return }
if(ship.x-50 <= s.x && s.x <= ship.x+50
@ -131,7 +132,7 @@
var d = s.data;
var dt = (now - d.t) || 0;
if(dt > 30 * 1000){
Gun.obj.del(game.ships, d.id);
delete game.ships[d.id];
s.$.remove();
return true;
}
@ -143,7 +144,7 @@
}
s.x = d.x + d.vx * dt;
s.y = d.y + d.vy * dt;
s.x = s.x % area.x;
if(s.x < 0){
s.x += area.x;
@ -159,13 +160,13 @@
}
return s;
}
localStorage.clear();
game.sync = function(shoot){
var me = game.me;
if(!me || me.boom){ return }
var keys = game.keys;
if(shoot || keys.up || keys.right || keys.left || keys.down){
var data = Gun.obj.to(me.data);
var data = {};
Object.keys(me.data).forEach(function(k){ data[k] = me.data[k] }); // 1 layer clone.
data.x = data.x / game.area.x;
data.y = data.y / game.area.y;
me.gun.put(data);
@ -182,7 +183,7 @@
game.resize();
game.ship();
game.gun.get('players').map().on(function(data, id){
data = Gun.obj.copy(data);
data = JSON.parse(JSON.stringify(data)); // clone object, this is bad perf tho.
data.x = data.x * game.area.x;
data.y = data.y * game.area.y;
data.id = data.id || id;
@ -196,7 +197,8 @@
now = game.now = Gun.state();
diff = now - last;
last = now;
Gun.obj.map(ships, function(ship){
Object.keys(ships).forEach(function(key, ship){
ship = ships[key];
if(!ship.frame){ return }
ship.frame(diff, now);
});
@ -210,7 +212,9 @@
gun.on('hi', function(peer){
console.log("hi!", peer);
if(peer.url){ return }
Gun.obj.map(gun.back('opt.peers'), function(peer){
var peers = gun.back('opt.peers');
Object.keys(peers).forEach(function(id, peer){
peer = peers[id];
if(!peer.url || !peer.wire){ return }
peer.wire._send = peer.wire.send;
peer.wire.send = send;
@ -221,7 +225,7 @@
});
function send(raw){
if(!raw){ return }
if(raw.indexOf('webrtc') >= 0){
if(raw.indexOf('rtc') >= 0){
if(!this._send){ return }
return this._send(raw);
}
@ -274,4 +278,4 @@
left: -50px;
}
</style>
</html>
</html>

331
examples/game/win.html Normal file
View File

@ -0,0 +1,331 @@
<!DOCTYPE html>
<html>
<head>
<!-- always start with these two lines to set a clean baseline for different devices -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="../style.css">
<!-- link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/gun/examples/style.css" -->
<script src="https://cdn.jsdelivr.net/npm/gun/examples/jquery.js"></script>
<title>Win</title>
</head>
<body class="black whitet">
<style>
/*
Choose white text on a black background so you can add color in.
Pick your favorite font and choose a font size.
*/
@import url('https://fonts.googleapis.com/css?family=Montserrat');
html, body {
font-family: "Montserrat", sans-serif;
}
button, input {
padding: 1em;
background: transparent;
border: 1px solid white;
border-radius: 1.5em;
color: white;
margin: 0.5em;
margin-bottom: 0;
cursor: pointer;
}
button:hover, input:hover {
background: white;
color: black;
transform: scale(1.1);
}
.air { padding-top: 9%; }
.yak button { font-size: 80%; }
.wag {
-webkit-animation: wag 3s infinite;
animation: wag 3s infinite;
} @keyframes wag {
0% {transform: rotate(0deg);}
50% {transform: rotate(-1deg);}
100% {transform: rotate(0deg);}
}
</style>
</style>
<!-- for educational sites, consider starting with a nice full screen welcome message -->
<div class="home hold full huef center air">
<div class="focus row">
<p><i>how to</i></p>
<p class="shout wag">Win at Life!</p>
<p><i>success, fame, power.</i></p>
<p><i>sex, ethics, & integrity.</i></p>
<!-- just like in real life, say who you are and give a concise reason why you add value to someone's life and then make a call to action, if they want to learn more they can always scroll to learn more -->
<div>
<!-- a class="unit hold" href="#fullscreen"><button>WATCH TRAILER</button></a -->
<a class="unit yak gap" href="#breathe"><button>PLAY GAME</button></a>
</div>
</div>
<div class="focus center row leak">
<!-- just like in real life, looking pretty attracts attention, so show off and look glamorous! -->
<img class="unit blink" src="" style="min-width: 10em; width: 80%;">
</div>
<script>location.hash = ''</script>
<script src="https://cdn.jsdelivr.net/npm/gun/lib/fun.js"></script>
</div>
<div id="breathe" class="hold full green">
<style>
</style>
<div class="story pad">
<p class="loud crack">Step 1: Breathe</p>
<a class="unit yak" href="#water"><button>Yupe</button></a>
</div>
<script>
</script>
</div>
<div id="water" class="hold full blue">
<style>
</style>
<div class="story pad">
<p class="loud crack">Step 2: Drink Water</p>
<p></p>
<a class="unit yak" href="#eat"><button>Next</button></a>
</div>
<script>
</script>
</div>
<div id="eat" class="hold full red">
<style>
</style>
<div class="story pad">
<p class="loud crack">Step 3: Eat Once a Day</p>
<p>If you do not want to be eaten, do not eat things that would not want to be eaten.</p>
<a class="unit yak" href="#babies"><button>Got It</button></a>
</div>
<script>
</script>
</div>
<div id="babies" class="hold full red">
<style>
</style>
<div class="story pad">
<p class="loud crack">Step 4: Babymaking* 😉</p>
<p>Find a willing player.</p>
<p><small> * This does not always make babies.</small></p>
<a class="unit yak" href="#make"><button>How?</button></a>
</div>
<script>
</script>
</div>
<div id="make" class="hold full hue">
<style>
</style>
<div class="story pad">
<p class="loud crack">Step 5: Make Dance</p>
<p>Moving your body is how you express your thoughts.</p>
<p>What you do with your body is what others will come to know you for. So do well.</p>
<p>You can make art, songs, or stories; You can make science, tools, or discoveries.</p>
<p>Who are you?</p>
<a class="unit yak" href="#science"><button>I am a Scientist!</button></a>
<a class="unit yak" href="#art"><button>I am an Artist!</button></a>
</div>
<script>
</script>
</div>
<div id="science" class="hold full hue">
<div class="story pad">
<p class="loud crack">Science: Knowing Games</p>
<p>If you must win one game, it should be the game of making games.</p>
<p>If you can make any game, then you will know how to win any game.</p>
<a class="unit yak" href="#games"><button>Games?</button></a>
</div>
<script>
</script>
</div>
<div id="games" class="hold full hue">
<div class="story pad">
<p>Games have goals and play.</p>
<p>Play is a safe space to try new dances.</p>
<p>Goals try to get players to do a type of dance.</p>
<a class="unit yak" href="#swim"><button>Start</button></a>
</div>
<script>
</script>
</div>
<div id="swim" class="hold full blue">
<style>
@import url('https://fonts.googleapis.com/css?family=Audiowide');
#hud {
opacity: 0.4;
font-family: 'Audiowide', cursive;
z-index: 999999999999;
transition: all 3s;
}
#hud .life {
position: fixed;
left: 50%;
bottom: 0px;
padding: 0.25em 1em 0.1em;
border-radius: 0.5em 0.5em 0 0;
transform: translateX(-50%);
background: black;
text-shadow: 0em -0.125em 0.75em white;
}
#hud .score {
position: fixed;
left: 50%;
top: 0px;
padding: 0.1em 1em 0.25em;
border-radius: 0 0 0.5em 0.5em;
transform: translateX(-50%);
background: black;
text-shadow: 0em 0.1em 0.75em white;
}
#hud .down {
bottom: -2em !important;
}
#hud .up {
top: -2em !important;
}
</style>
<div class="story pad">
<p>The simplest goal is to not "die" in the game.</p>
<p>Oh look, you've fallen into water and cannot breathe.</p>
<p>If you do not push the button to swim to the top, you'll lose the game.</p>
<a class="unit yak"><button>Swim</button></a>
</div>
<div id="hud">
<div class="score shade up">
SCORE: <span id="hudscore">0</span>%
</div>
<div class="life shade down">
LIFE: <span id="hudlife">100</span>%
</div>
</div>
<script>
;(function(){
var go, life = $('#hudlife').data();
$(window).on('hashchange', function(){
if(location.hash != '#swim'){ return }
$('#hudlife').text($('#hudlife').data().is = 100);
$('#hud .life').removeClass('down');
go = setInterval(function(){
if(0 >= life.is){
location.hash = 'die';
clearInterval(go);
go = false;
return;
}
$('#hudlife').text(life.is -= 1);
}, 100);
})
$('#swim a').on('click', function(){
$('#hudlife').text((life.is += 5) < 100? life.is : 100);
if(100 <= life.is){
location.hash = 'won';
clearInterval(go);
go = false;
return;
}
});
}());
</script>
</div>
<div id="won" class="hold full hue">
<div class="story pad">
<p>You won your first game! 🎉</p>
<p>See? I told you breathing is important.</p>
<p>You also learned the most basic dance: rapid poking.</p>
<p>The goal of the next game is to make the game you just won.</p>
<a class="unit yak" href="#won" style="z-index: 999999;"><button>Make</button></a>
</div>
<script src="https://cdn.jsdelivr.net/gh/amark/gun/lib/meta.js"></script>
<script>
meta.edit({name: "Add", combo: ['A']});
meta.edit({
name: "Timer",
combo: ['A','T'],
on: function(){
console.log("up");
this.to = this.to || setInterval(this.on, 100);
$("html, body").stop().animate({ scrollTop: $(window).scrollTop()-100 }, 100);
p.css({top: --p.y +'%'});
},
use: function(){},
up: function(){ clearTimeout(this.to); this.to = 0 }
});
meta.edit({
name: "Delete",
combo: ['A','D'],
on: function(){
$(meta.tap.on).remove();
},
use: function(){},
up: function(){}
});
meta.edit({
name: "Button",
combo: ['A','B'],
on: function(){
$(meta.tap.on).append("<a class='unit yak'><button>Button</button></a>")
},
use: function(){},
up: function(){}
});
meta.edit({
name: "Edit",
combo: ['E'],
on: function(){
$('body').attr('contenteditable', 'true' == $('body').attr('contenteditable')? false : true);
},
use: function(){},
up: function(){ }
});
</script>
<script>
window.requestAnimationFrame(function frame(){
return;
window.requestAnimationFrame(frame);
if(location.hash != '#won'){ return }
var p = $('#won a').offset();
var bx = p.left, by = p.top, mx = meta.tap.x, my = meta.tap.y;
bx = mx - bx; by = my - by;
var d = Math.sqrt(bx*bx + by*by);
console.log(bx, by, mx, my, d);
if(d > 250){ return }
$('#won a').css({position: 'fixed', left: bx + (Math.random()*100), top: by + (Math.random()*100)});
})
</script>
</div>
<div id="rules" class="hold full white blackt">
<style>
</style>
<div class="story pad">
<p class="loud crack">Bend these Rules if it is more Moral to do so</p>
<p></p>
<a class="unit yak" href="#water"><button>Next</button></a>
</div>
<script>
</script>
</div>
<div id="die" class="hold full red">
<style>
</style>
<div class="story pad">
<p class="loud crack">GAME OVER</p>
<p></p>
<a class="unit yak" href="#make"><button>Start Over</button></a>
</div>
<script>
</script>
</div>
</body>
</html>

View File

@ -1,66 +0,0 @@
var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || process.argv[2] || 8765;
var Gun = require('../');
// have to do this before instancing gun(?)
Gun.on('out', function(msg){
this.to.next( msg );
msg = JSON.stringify(msg);
gunPeers.forEach( function(peer){ peer.send( msg ) })
})
var gun = Gun({
file: 'data.json'
});
var server = require('http').createServer(function(req, res){
var insert = "";
if( req.url.endsWith( "gun.js" ) )
insert = "../";
require('fs').createReadStream(require('path').join(__dirname, insert, 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
});
// do not do this to attach server... instead pull websocket provider and use that.
// gun.wsp(server);
var ws = require( 'ws' ); // default websocket provider gun used...
var WebSocketServer = ws.Server;
var wss = new WebSocketServer( {
server: server, // 'ws' npm
autoAcceptConnections : false // want to handle the request (websocket npm?)
});
wss.on('connection',acceptConnection )
var gunPeers = []; // used as a list of connected clients.
function acceptConnection( connection ) {
// connection.upgradeReq.headers['sec-websocket-protocol'] === (if present) protocol requested by client
// connection.upgradeReq.url === url request
console.log( "connect?", connection.upgradeReq.headers, connection.upgradeReq.url )
gunPeers.push( connection );
connection.on( 'error',function(error){console.log( "WebSocket Error:", error) } );
connection.on('message', function (msg) {
msg = JSON.parse(msg)
if ("forEach" in msg) msg.forEach(m => gun.on('in', JSON.parse(m)));
else gun.on('in', msg)
})
connection.on( 'close', function(reason,desc){
// gunpeers gone.
var i = gunPeers.findIndex( function(p){return p===connection} );
if( i >= 0 )
gunPeers.splice( i, 1 );
})
}
server.listen(port);
console.log('Server started on port ' + port + ' with ');

View File

@ -1,21 +1,34 @@
;(function(){
var cluster = require('cluster');
if(cluster.isMaster){
return cluster.fork() && cluster.on('exit', function(){ cluster.fork() });
}
var fs = require('fs');
var config = { port: process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || process.argv[2] || 8765 };
var Gun = require('../'); // require('gun')
if(process.env.HTTPS_KEY){
config.key = fs.readFileSync(process.env.HTTPS_KEY);
config.cert = fs.readFileSync(process.env.HTTPS_CERT);
config.server = require('https').createServer(config, Gun.serve(__dirname));
} else {
config.server = require('http').createServer(Gun.serve(__dirname));
}
var gun = Gun({web: config.server.listen(config.port) });
console.log('Relay peer started on port ' + config.port + ' with /gun');
;(function(){
var cluster = require('cluster');
if(cluster.isMaster){
return cluster.fork() && cluster.on('exit',function(){ cluster.fork(); require('../lib/crashed') });
}
var fs = require('fs'), env = process.env;
var GUN = require('../'); // require('gun');
var opt = {
port: env.PORT || process.argv[2] || 8765,
peers: env.PEERS && env.PEERS.split(',') || []
};
if(fs.existsSync((opt.home = require('os').homedir())+'/cert.pem')){
env.HTTPS_KEY = env.HTTPS_KEY || opt.home+'/key.pem';
env.HTTPS_CERT = env.HTTPS_CERT || opt.home+'/cert.pem';
}
if(env.HTTPS_KEY){
opt.port = 443;
opt.key = fs.readFileSync(env.HTTPS_KEY);
opt.cert = fs.readFileSync(env.HTTPS_CERT);
opt.server = require('https').createServer(opt, GUN.serve(__dirname));
require('http').createServer(function(req, res){
res.writeHead(301, {"Location": "https://"+req.headers['host']+req.url });
res.end();
}).listen(80);
} else {
opt.server = require('http').createServer(GUN.serve(__dirname));
}
var gun = GUN({web: opt.server.listen(opt.port), peers: opt.peers});
console.log('Relay peer started on port ' + opt.port + ' with /gun');
module.exports = gun;
}());

8
examples/https.sh Normal file
View File

@ -0,0 +1,8 @@
#!/bin/bash
cd ~
git clone https://github.com/acmesh-official/acme.sh.git
cd ~/acme.sh
./acme.sh --install -m $EMAIL
bash ~/acme.sh/acme.sh --issue -d $DOMAIN -w $WEB
bash ~/acme.sh/acme.sh --install-cert -d $DOMAIN --key-file ~/key.pem --fullchain-file ~/cert.pem --reloadcmd "service relay force-reload"

View File

@ -1,28 +1,4 @@
<html>
<head>
<title>gun examples</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<!-- h1>Examples Directory <button style="float: right;" onclick="localStorage.clear()">Clear Local Storage</button></h1 -->
<style>
html, body {
margin: 0;
padding: 0;
}
iframe {
width: 100%;
height: 50%;
border: none;
b-order-top: ridge 2em skyblue;
border: none;
}
</style>
<a href="/todo/index.html"><iframe src="/todo/index.html"></iframe></a>
<!-- a href="/json/index.html"><iframe src="/json/index.html"></iframe></a -->
<a href="/chat/index.html"><iframe src="/chat/index.html"></iframe></a>
<!-- script src="../gun.js"></script -->
</body>
</html>
<!DOCTYPE html>
<p>This is the examples folder.
<p>The most basic example is <a href="./basic/note.html">./basic/note.html</a>!</p>
<p>Home page temporarily disabled.</p>

View File

@ -0,0 +1,116 @@
const DEFAULT_OPTIONS = {
size: 20,
stickTo: 'top',
};
class ScrollWindow {
constructor(gunNode, opts = {}) {
this.opts = Object.assign(DEFAULT_OPTIONS, opts);
this.elements = new Map();
this.node = gunNode;
this.center = this.opts.startAt;
this.updateSubscriptions();
}
updateSubscriptions() {
this.upSubscription && this.upSubscription.off();
this.downSubscription && this.downSubscription.off();
const subscribe = params => {
this.node.get({ '.': params}).map().on((val, key, a, eve) => {
if (params['-']) {
this.downSubscription = eve;
} else {
this.upSubscription = eve;
}
this._addElement(key, val);
});
};
if (this.center) {
subscribe({ '>': this.center, '<': '\uffff' });
subscribe({'<': this.center, '>' : '', '-': true});
} else {
subscribe({ '<': '\uffff', '>': '', '-': this.opts.stickTo === 'top' });
}
}
_getSortedKeys() {
this.sortedKeys = this.sortedKeys || [...this.elements.keys()].sort();
return this.sortedKeys;
}
_upOrDown(n, up) {
this.opts.stickTo = null;
const keys = this._getSortedKeys();
n = n || (keys.length / 2);
n = up ? n : -n;
const half = Math.floor(keys.length / 2);
const newMiddleIndex = Math.max(Math.min(half + n, keys.length - 1), 0);
if (this.center !== keys[newMiddleIndex]) {
this.center = keys[newMiddleIndex];
this.updateSubscriptions();
}
return this.center;
}
up(n) {
return this._upOrDown(n, true);
}
down(n) {
return this._upOrDown(n, false);
}
_topOrBottom(top) {
this.opts.stickTo = top ? 'top' : 'bottom';
this.center = null;
this.updateSubscriptions();
}
top() {
this._topOrBottom(true);
}
bottom() {
this._topOrBottom(false);
}
_addElement(key, val) {
if (!val || this.elements.has(key)) return;
const add = () => {
this.elements.set(key, val);
this.sortedKeys = [...this.elements.keys()].sort();
const sortedElements = this.sortedKeys.map(k => this.elements.get(k));
this.opts.onChange && this.opts.onChange(sortedElements);
};
const keys = this._getSortedKeys();
if (keys.length < this.opts.size) {
add();
} else {
if (this.opts.stickTo === 'top' && key > keys[0]) {
this.elements.delete(keys[0]);
add();
} else if (this.opts.stickTo === 'bottom' && key < keys[keys.length - 1]) {
this.elements.delete(keys[keys.length - 1]);
add();
} else if (this.center) {
if (keys.indexOf(this.center) < (keys.length / 2)) {
if (key < keys[keys.length - 1]) {
this.elements.delete(keys[keys.length - 1]);
add();
}
} else {
if (key > keys[0]) {
delete this.elements.delete(keys[0]);
add();
}
}
}
}
}
getElements() {
return this.elements;
}
}

View File

@ -0,0 +1,30 @@
<html>
<head>
<title>Infinite scroll example</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
<link rel="stylesheet" type="text/css" href="./style.css">
<script src="/jquery.js"></script>
<script src="/gun.js"></script>
<script src="./ScrollWindow.js"></script>
</head>
<body>
<header>
<form id="generate">
<input type="text" id="number" placeholder="Number of posts"/>
<button>Generate</button>
</form>
<div id="top-buttons">
<button id="top">Top</button>
</div>
</header>
<div id="top-sentinel" style="padding-top: 0px;"></div>
<div id="container"></div>
<div id="bottom-sentinel" style="padding-top: 0px;"></div>
<button id="bottom">Bottom</button>
<script src="./index.js"></script>
</body>
</html>

View File

@ -0,0 +1,167 @@
const gun = new Gun();
const size = 20;
const gunNode = gun.get('posts');
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
let topSentinelPreviousY = 0;
let topSentinelPreviousRatio = 0;
let bottomSentinelPreviousY = 0;
let bottomSentinelPreviousRatio = 0;
let previousUpIndex = previousDownIndex = -1;
const render = elements => {
const t = new Date();
elements.reverse().forEach((data, j) => {
var date = new Date(data.date);
$('#date' + j).text(date.toLocaleDateString() + ' ' + date.toLocaleTimeString());
$('#text' + j).text(data.text);
$('#img' + j).attr('src', '');
$('#img' + j).attr('src', _getCatImg(date.getTime()));
$('#post' + j).css({visibility: 'visible'});
});
console.log('rendering took', new Date().getTime() - t.getTime(), 'ms');
window.onRender && window.onRender(elements);
};
const onChange = debounce(render, 20);
const scroller = new ScrollWindow(gunNode, {size, stickTo: 'top', onChange});
const initList = () => {
for (var n = 0; n < size; n++) {
var el = $("<div>").addClass('post').attr('id', 'post' + n).css({visibility: 'hidden'});
el.append($('<b>').attr('id', 'date' + n));
el.append($('<span>').attr('id', 'text' + n));
el.append($('<img>').attr('id', 'img' + n).attr('height', 100).attr('width', 100));
$('#container').append(el);
}
}
const _getCatImg = (n) => {
const url = "https://source.unsplash.com/collection/139386/100x100/?sig=";
return url + n % 999999;
};
const getNumFromStyle = numStr => Number(numStr.substring(0, numStr.length - 2));
const adjustPaddings = isScrollDown => {
const container = document.getElementById("container");
const currentPaddingTop = getNumFromStyle(container.style.paddingTop);
const currentPaddingBottom = getNumFromStyle(container.style.paddingBottom);
const remPaddingsVal = 198 * (size / 2); // TODO: calculate actual element heights
if (isScrollDown) {
container.style.paddingTop = currentPaddingTop + remPaddingsVal + "px";
container.style.paddingBottom = currentPaddingBottom === 0 ? "0px" : currentPaddingBottom - remPaddingsVal + "px";
} else {
container.style.paddingBottom = currentPaddingBottom + remPaddingsVal + "px";
if (currentPaddingTop === 0) {
$(window).scrollTop($('#post0').offset().top + remPaddingsVal);
} else {
container.style.paddingTop = currentPaddingTop - remPaddingsVal + "px";
}
}
}
const topSentCallback = entry => {
const container = document.getElementById("container");
const currentY = entry.boundingClientRect.top;
const currentRatio = entry.intersectionRatio;
const isIntersecting = entry.isIntersecting;
// conditional check for Scrolling up
if (
currentY > topSentinelPreviousY &&
isIntersecting &&
currentRatio >= topSentinelPreviousRatio &&
scroller.center !== previousUpIndex && // stop if no new results were received
scroller.opts.stickTo !== 'top'
) {
previousUpIndex = scroller.center;
adjustPaddings(false);
scroller.up(size / 2);
}
topSentinelPreviousY = currentY;
topSentinelPreviousRatio = currentRatio;
}
const botSentCallback = entry => {
const currentY = entry.boundingClientRect.top;
const currentRatio = entry.intersectionRatio;
const isIntersecting = entry.isIntersecting;
// conditional check for Scrolling down
if (
currentY < bottomSentinelPreviousY &&
currentRatio > bottomSentinelPreviousRatio &&
isIntersecting &&
scroller.center !== previousDownIndex && // stop if no new results were received
scroller.opts.stickTo !== 'bottom'
) {
previousDownIndex = scroller.center;
adjustPaddings(true);
scroller.down(size / 2);
}
bottomSentinelPreviousY = currentY;
bottomSentinelPreviousRatio = currentRatio;
}
const initIntersectionObserver = () => {
const options = {
//rootMargin: '190px',
}
const callback = entries => {
entries.forEach(entry => {
if (entry.target.id === 'post0') {
topSentCallback(entry);
} else if (entry.target.id === `post${size - 1}`) {
botSentCallback(entry);
}
});
}
var observer = new IntersectionObserver(callback, options); // TODO: It's possible to quickly scroll past the sentinels without them firing. Top and bottom sentinels should extend to page top & bottom?
observer.observe(document.querySelector("#post0"));
observer.observe(document.querySelector(`#post${size - 1}`));
}
initList(size);
initIntersectionObserver();
$('#top').click(() => {
scroller.top();
$('#container').css({'padding-top': 0, 'padding-bottom': 0});
$(document.body).animate({ scrollTop: 0 }, 500);
});
$('#bottom').click(() => {
scroller.bottom();
$('#container').css({'padding-top': 0, 'padding-bottom': 0});
$(document.body).animate({ scrollTop: $("#container").height() }, 500);
});
$('#generate').submit(e => {
e.preventDefault();
const day = 24 * 60 * 60 * 1000;
const year = 365 * day;
const n = Number($('#number').val());
for (let i = 0; i < n; i++) {
const d = new Date(40 * year + i * day).toISOString();
gunNode.get(d).put({text: 'Hello world!', date: d});
}
});

View File

@ -0,0 +1,77 @@
html, body {
margin: 0;
padding: 0;
}
body {
padding-top: 65px;
}
header {
background: rgba(255,255,255,0.75);
padding: 15px;
}
header {
position: fixed;
top: 0; left: 0; right: 0;
}
#bottom {
position: fixed;
right: 15px;
bottom: 15px;
}
input {
border: 0;
background-color: #efefef;
padding: 15px;
border-radius: 50px;
}
button {
background-color: #4a4f9d;
border: 0;
padding: 15px;
color: white;
border-radius: 50px;
}
input, button {
outline: none;
opacity: 1;
}
input:focus, button:focus, button:hover {
opacity: 0.8;
}
button:hover {
cursor: pointer;
}
#top-buttons, form {
display: inline-block;
margin: 0;
}
#top-buttons {
float: right;
}
.post {
margin: 15px;
padding: 15px;
background-color: #9de1fe;
border-radius: 5px;
}
.post b {
margin-right: 5;
}
.post img {
display: block;
margin: 10px 0;
}

View File

@ -3,25 +3,51 @@
# README
# This will install nodejs and npm on your system,
# should work on most places other than Windows.
# For it to run on boot as a server, a recent OS is needed.
# Set any environment variables before you run this,
# like `export RAD=false` to disable storage, or
# pass file paths of `HTTPS_CERT` & `HTTPS_KEY`, etc.
# Copy paste and run each line into your terminal.
# If you are on Windows, http://nodejs.org/download/ has
# an installer that will automatically do it for you.
# curl -o- https://raw.githubusercontent.com/amark/gun/master/examples/install.sh | bash
# wget -O - https://raw.githubusercontent.com/amark/gun/master/examples/install.sh | bash
#debian/ubuntu
cd ~
apt-get install sudo -y
sudo apt-get update -y
sudo apt-get install curl git git-core -y
sudo apt-get install curl git git-core systemd -y
sudo apt-get install systemctl -y
#fedora/openSUSE
sudo yum check-update -y
sudo yum install curl git git-core -y
sudo yum install curl git git-core systemd -y
sudo yum install systemctl -y
#screen -S install # You can safely CTRL+A+D to escape without stopping the process. `screen -R install` to resume. Stop all with `killall screen`. Note: May need to `sudo apt-get install screen`
# install nodejs
git clone http://github.com/isaacs/nave.git
sudo ./nave/nave.sh usemain stable
git clone https://github.com/isaacs/nave.git
./nave/nave.sh usemain stable
# If you just want nodejs and npm but not gun, stop here.
npm install gun
# to run the gun examples:
cd ./node_modules/gun
#npm install gun@latest
#cd ./node_modules/gun
mkdir node_modules
git clone https://github.com/amark/gun.git
cd gun
git checkout .
git pull
git checkout master
git checkout $VERSION
git pull
npm install .
sudo /usr/local/bin/node ./examples/http.js 80 # change `80` to `8765` for development purposes.
cp ./examples/relay.service /lib/systemd/system/relay.service
echo $PWD >> /lib/systemd/system/relay.service
echo "fs.file-max = 999999" >> /etc/sysctl.conf
ulimit -u unlimited
sysctl -p /etc/sysctl.conf
systemctl daemon-reload
systemctl enable relay
systemctl restart relay

1
examples/iris Symbolic link
View File

@ -0,0 +1 @@
../node_modules/iris-messenger/src

View File

@ -58,7 +58,7 @@
color: skyblue;
background: transparent;
text-decoration: none;
cursor: poiner;
cursor: pointer;
}
ul, li {
list-style-type: none;

View File

@ -178,21 +178,21 @@
});
$('#share').addClass("hide");
} else {
document.cookie = 'gps=' + (gps.track = (document.cookie.match(/gps\=(.*?)(\&|$|\;)/i)||[])[1] || Gun.text.random(5)); // trick with cookies!
document.cookie = 'gps=' + (gps.track = (document.cookie.match(/gps\=(.*?)(\&|$|\;)/i)||[])[1] || String.random(5)); // trick with cookies!
gps.ref = gun.get('gps/' + gps.track);
gps.opt.track = function(pos){
pos = pos.latlng;
if(gps.follow
|| Gun.time.is() - gps.when < 1000
|| Gun.state() - gps.when < 1000
|| gps.last && gps.last.lat == pos.lat && gps.last.lng == pos.lng){
return; // throttle!
}
gps.when = Gun.time.is();
gps.when = Gun.state();
gps.ref.put(gps.last = pos);
//$('#debug').value = JSON.stringify(gps.last);
}
gps.where = gps.where || Where(gps.opt);
$('#follow').text(("where.gunDB.io/" || (location.origin + location.pathname)) + '#' + gps.track);
$('#follow').text((location.origin + location.pathname) + '#' + gps.track);
$('#share').removeClass("hide");
$('#share').on('click', function(){
$('#link').toggleClass("hide");

View File

@ -4,7 +4,7 @@
<title>Party by Neon ERA</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<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">
<link href="https://fonts.googleapis.com/css?family=Raleway:100" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Caveat" rel="stylesheet">
<style>
.write {
@ -38,10 +38,12 @@
;(() => {
function S(){};
window.S = S;
try{localStorage.clear();//sessionStorage.clear();
}catch(e){}
S.gun = Gun(location.host? location.origin+'/gun' : 'http://localhost:8765/gun');
//S.gun = Gun('http://localhost:8765/gun');
//S.gun = Gun();
S.app = S.gun.get('examples/social/1');
S.app = S.gun.get('examples/social/2');
S.user = S.gun.user();
S.tell = (what, n) => {
var e = $('#tell').find('p');
@ -67,13 +69,30 @@
#hi .faces img {
w-idth: 5%;
width: 3em;
width: 7vh;
}
#hi .ton {
border-radius: 1em;
font-size: 150%;
font-size: 2.25vmax;
margin: 0 0.5em 0 0.5em;
background: transparent;
border: 1px solid white;
color: white;
font-family: 'Raleway', sans-serif;
}
#hi .ton:hover {
background: white;
color: black;
}
</style>
<div class="loud write shout rim">Party by NEON ERA.</div>
<div class="loud write shout rim">Join the Private Party!</div>
<div id="faces" class="flush faces">
<div class="right" style="max-width: 20em;">
<input id="halias" class="write jot sap" placeholder="username">
<input id="hpass" type="password" class="write jot sap" placeholder="passphrase">
<div class="right" style="max-width: 30em;">
<a href="chrome://extensions" target="_blank"><button class="ton">Install Now</button></a>
<a href="#"><button class="ton">How It Works</button></a>
<!-- input id="halias" class="write jot sap" placeholder="username">
<input id="hpass" type="password" class="write jot sap" placeholder="passphrase" -->
<script>
$.as.route.page('hi', () => {
$('#hpass').on('focus', () => {
@ -134,6 +153,14 @@
return faces;
});
</script>
<div class="pad ditch">
<p class="loud"><i>Your friend has invited you to add a privacy extension to your browser:</i></p>
<p> - Decrypts your friends' messages across any site!</p>
<p> - Stops tech monopolies from selling your private data to advertisers.</p>
<p> - Gives you ownership and control over all your data online.</p>
<p> - Creates a searchable history of your posts, friends, and more!</p>
</div>
<div id="faces2" class="flush faces"></div>
<div class="pad ditch">
<p class="loud"><i>Express your thoughts & connect with the world around you!</i></p>
<p> - Discover new relationships.</p>
@ -141,12 +168,10 @@
<p> - Watch fun videos and photos from people who share.</p>
<p> - But this time, you own it: fully decentralized.</p>
</div>
<div id="faces2" class="flush faces">
</div>
<div class="pad ditch" style="margin-top: 1em;">
<p><span class="loud write shout">Welcome</span><span class="write loud">, you are currently connected to <b id="peers" class="huet4">2</b> peers. <b>Why not try to sign up or log in?</b></span></p>
<p><span class="loud write shout">Welcome,</span><!-- span class="write loud">, you are currently connected to <b id="peers" class="huet4">2</b> peers. <b>Why not try to sign up or log in?</b></span --></p>
<p> - Your identity is created here, by you. Not on a server.</p>
<p> - It uses secure <a href="https://gun.eco/explainers/data/security.html">cryptographic</a> methods to protect you.</p>
<p> - It uses secure <a href="https://gun.eco/docs/Cartoon-Cryptography">cryptographic</a> methods to protect you.</p>
<p> - Only you have access to it, meaning even we cannot reset your password!</p>
<p> - For added security, you can freely <a href="https://github.com/amark/gun">download</a> and run it on your own computer.</p>
</div>
@ -530,7 +555,7 @@
</ul>
<div class="model">
<li class="spoke tint sap gully">
<div class="gap"><span class="sort none"></span><img class="face act none"><b class="name"></b><span class="what"></span></div>
<div class="gap"><span class="sort none"></span><img class="face act none"><b class="name"></b><div class="what"></div></div>
</li>
</div>
<div style="height: 10%;"></div>
@ -547,23 +572,33 @@
});
window.user = S.user;
$('#speak').on('submit', (e) => {
/*var say = normalize($('#speak .draft'));
console.log(1, say.html());
return;*/
var say = $('#speak .draft').text();
var say = $('#speak .draft').text(); //.text(); // NO NO NO NO NO
if(!say){ return }
var ref = S.user.get('who').get('all').set({what: say});
ref.get('by').put(S.user.get('who'));
S.user.get('who').get('said').time(ref);
S.gun.get('@').time(ref);
console.log('save!', say);
var ref = S.user.get('who').get('all').set({what: say, when: Gun.state()});
//ref.get('by').put(S.user.get('who'));
//S.user.get('who').get('said').time(ref);
S.user.get('who').get('said').set(ref);
//S.gun.get('@').time(ref);
$('#speak .draft').text('');
});
S.gun.get('@').time(async (data, key, time) => {
var ref = S.gun.get(data), tmp;
var said = await ref.then();
//S.gun.get('@').time(async (data, key, time) => {
S.user.get('who').get('said').map().once(async (data, key, time) => {
//var ref = S.gun.get(data), tmp;
//var said = await ref.then();
key = key.replace(/[^A-Za-z]/ig,'');
var tmp, said = data, time = said.when;
var $li = $($('#'+key)[0] || $('#draft .model .spoke').clone(true,true).attr('id', key)[(tmp = $.as.sort(time, $('#draft ul').children('li').first()))[0]?'insertBefore':'appendTo'](tmp[0] || '#draft ul'));
$li.find('.what').text(said.what);
var by = ref.get('by');
tmp = said.what;
if(tmp && tmp.ct){
tmp = JSON.stringify(tmp);
setTimeout(async function(){
tmp = await SEA.decrypt(said.what, S.user._.sea);
$li.find('.what').text(tmp);
}, 750);
}
$li.find('.what').text(tmp); // NORMALIAZE!!!
var by = S.user.get('who');// ref.get('by');
by.get('face').get('small').on(data => {
$li.find('.face').attr('src', data).removeClass('none');
});
@ -579,7 +614,7 @@
if(face){
$li.find('.face').attr('src', face).removeClass('none');
}
}, 10);
});
$(document).on('click', '#speak .act.face', (eve) => {
});
@ -587,61 +622,80 @@
</script>
</div>
<div id="create" class="white center act">
<div id="contacts" class="hue2 page">
<style>
#create {
position: fixed;
bottom: 2em;
right: 2em;
font-size: 1em;
font-family: Tahoma, arial;
border-radius: 1em;
z-index: 99999;
width: 2em;
height: 2em;
opacity: 0.8;
#contacts ul .face {
float: left;
border-radius: 100%;
vertical-align: middle;
height: 2.5em;
margin-right: 5%;
}
#contacts ul, #contacts li {
overflow: visible;
transition: all 0.2s ease-in;
}
#create:hover {
opacity: 1;
}
#create span {
line-height: 2em;
}
#create .menu {
display: none;
height: 10em;
width: 10em;
bottom: 0em;
right: 0em;
overflow: visible;
position: absolute;
border-bottom-right-radius: 1em;
#contacts .who {
display: inline-block;
margin-right: 2%;
min-width: 250px;
width: 15em;
text-align: left;
padding: 2%;
vertical-align: middle;
}
#create:hover .menu {
display: block;
#contacts .what {
}
#create li {
padding: 0.3em 0.5em;
}
#create a {
color: black;
}
#create a:hover {
color: #4D79D8;
#contacts .spoke {
}
</style>
<span class="huet act">+</span>
<div class="white sap menu" style="width: 7em;">
<ul class="left blackt gap">
<a href="#out" class="act"><li>Sign Out</li></a>
<a href="#settings" class="act"><li>Settings</li></a>
<li>Profile</li>
<li>Help</li>
</ul>
<p class="pad">Contacts</p>
<ul class="mid row col center">
</ul>
<div class="model">
<li class="who tint sap gully">
<div class="gap">
<span class="sort none"></span>
<img class="face act none" crossOrigin="Anonymous">
<big class="name"></big><br/>
<i class="alias"></i><br/>
<small>FB ID:</small> <span class="fbid"></span>
</div>
</li>
</div>
<div style="height: 10%;"></div>
<script>
$.as.route.page('contacts', () => {
if(!S.user.is){ return $.as.route('sign') }
//S.gun.get('@').time(async (data, key, time) => {
// TODO: BUG!! switch from `on` to `once` to get Martti's {_} empty object bug.
var $ul = $('#contacts ul');
S.user.get('old').get('fb').map().on(async function(data){
console.log('contact:', data);
var key = data.fbid, tmp;
if(!key){ return }
var $li = $($('#fbid'+key)[0] || $('#contacts .model .who').clone(true,true).attr('id', 'fbid'+key)[(tmp = $.as.sort(data.name||1, $ul.children('li').first()))[0]?'insertBefore':'appendTo'](tmp[0] || $ul));
$li.find('.name').text(data.name);
$li.find('.alias').text(data.alias);
$li.find('.fbid').text(data.fbid);
tmp = $li.find('img').attr('src', data.face || data.tmp);
if(!data.face){
var ref = this;
$.fn.upload.shrink(data.tmp, function(b64){
ref.get('face').put(b64);
}, 100);
}
$('html, body').stop(true, true).animate({scrollTop: $ul.height()});
});
function img2b64(img, cb){
var c = document.createElement('canvas');
var ctx = c.getContext("2d");
ctx.drawImage(img, 10, 10);
cb(c.toDataURL());
}
});
</script>
</div>
<div id="tell" class="center">
@ -673,6 +727,7 @@
</style>
<p class="mid black">Hello world!</p>
</div>
<!-- textarea id='debug' class="no-ne" style="position: fixed; bottom: 0; left: 0; width: 25%; height: 30%"></textarea -->
<script>
$.as.route.page('person', () => {
@ -686,7 +741,7 @@
if(e.err){ return }
var m = $($("#d"+e.id)[0] || $('#d0').clone(true,true).attr('id', 'd'+e.id).css('backgroundImage', '').appendTo('#draft')).addClass('pulse');
if(up){ return up.shrink(e, resize, 1000) }
console.log(e.id, e.base64);
//console.log(e.id, e.base64);
m.removeClass('pulse').css({
backgroundImage: 'url(' + e.base64 + ')',
backgroundRepeat: 'no-repeat',
@ -697,5 +752,7 @@
</script>
<script async src="../../gun/lib/fun.js"></script>
<script async src="../../gun/lib/normalize.js"></script>
<script async src="../../gun/lib/monotype.js"></script>
<script async src="../../gun/lib/meta.js"></script>
</body>
</html>

View File

@ -10,7 +10,7 @@ import { fromObjects, toObjects } from './asyncSerialize';
import { subtle } from './compat';
export function parse(text) {
return __awaiter(this, void 0, void 0, function* () {
// need decodeURIComponent so binary strings are transfered properly
// need decodeURIComponent so binary strings are transferred properly
const deocodedText = unescape(text);
const objects = JSON.parse(deocodedText);
return fromObjects(serializers(true), objects);
@ -19,7 +19,7 @@ export function parse(text) {
export function stringify(value, waitForArrayBufferView = true) {
return __awaiter(this, void 0, void 0, function* () {
const serialized = yield toObjects(serializers(waitForArrayBufferView), value);
// need encodeURIComponent so binary strings are transfered properly
// need encodeURIComponent so binary strings are transferred properly
const message = JSON.stringify(serialized);
return escape(message);
});
@ -147,7 +147,7 @@ const CryptoKeySerializer = {
};
}),
fromObject: (cks) => __awaiter(this, void 0, void 0, function* () {
// if we don't have access to to a real crypto implementation, just return
// if we don't have access to a real crypto implementation, just return
// the serialized crypto key
if (crypto.fake) {
const newCks = Object.assign({}, cks);

View File

@ -1,18 +0,0 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# testing
/coverage
# production
/build
# misc
.DS_Store
.env
npm-debug.log*
yarn-debug.log*
yarn-error.log*

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +0,0 @@
{
"name": "gun-react-examples",
"version": "1.1.0",
"private": true,
"dependencies": {
"gun": "file:../..",
"react": "^15.5.4",
"react-dom": "^15.5.4"
},
"devDependencies": {
"express": "^4.15.2",
"express-http-proxy": "^0.11.0",
"react-scripts": "0.9.5"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"server": "PORT=8081 node ./server.js"
}
}

View File

@ -1,21 +0,0 @@
console.log("If modules not found, run `npm install` in /example folder!");
var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || process.argv[2] || 8765;
var host = process.env.OPENSHIFT_NODEJS_HOST || process.env.VCAP_APP_HOST || process.env.HOST || 'localhost';
var express = require('express');
var proxy = require('express-http-proxy');
var http = require('http');
var app = express();
var server = http.createServer(app);
var Gun = require('gun');
var gun = Gun({
file: 'data.json',
web: server
});
app.use(Gun.serve);
app.use(proxy(host + ':8765'));
server.listen(port);
console.log('Server started on port ' + port + ' with /gun');

39
examples/react/todo.html Normal file
View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<body>
<div id="app"></div>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>
<script type="text/babel">
const gun = Gun();
const App = () => {
const newTodo = React.useRef()
const [todos, setTodos] = React.useState({})
React.useEffect(() => {
return gun
.get("todos")
.map()
.on((todo, id) => setTodos(todos => ({...todos, [id]: todo }))).off;
}, [])
return (
<div>
<title>TODOs</title>
<ul>{Object.values(todos).map(({title}, i) => <li key={i}>{title}</li>)}</ul>
<form onSubmit={e => {
e.preventDefault();
gun.get("todos").set({ title: newTodo.current.value });
newTodo.current.value = ''
}}>
<input ref={newTodo} placeholder="new todo"/>
</form>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("app"));
</script>
</body>
</html>

19
examples/relay.service Normal file
View File

@ -0,0 +1,19 @@
[Unit]
Description=GUN relay
Documentation=https://gun.eco
After=network.target
[Install]
WantedBy=multi-user.target
[Service]
Environment=PATH=/usr/bin:/usr/local/bin
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
StartLimitBurst=999999
StartLimitIntervalSec=999999
Restart=always
ExecStart=node examples/http.js 80
# Environment=NODE_ENV=production
WorkingDirectory=

1104
examples/smoothie.js Normal file

File diff suppressed because it is too large Load Diff

22
examples/start.js.html Normal file
View File

@ -0,0 +1,22 @@
/*<!DOCTYPE html>
<html>
<head></head>
<body></body>
<script>// */
;(function(){try{
if(typeof window == "undefined"){ return }
var url = location.hash.slice(1);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(e){
if(4 != xhr.readyState){ return }
var d = document, doc = d.createElement("html");
doc.innerHTML = xhr.responseText;
var head = doc.getElementsByTagName('head')[0] || doc.appendChild(d.createElement('head'));
var base = doc.getElementsByTagName('base')[0] || head.appendChild(d.createElement('base'));
base.href = url;
document.write(doc.outerHTML);
};
xhr.open('GET', url, true);
xhr.send(null);
}catch(e){document.write(''+e)}}());
//</script></html>

153
examples/stats.html Normal file
View File

@ -0,0 +1,153 @@
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="./style.css">
</head>
<body>
<style>
body {
font-family: helvetica;
background-color: rgb(25,25,25);
color: rgb(80,135,25) !important;
text-shadow: 1px 1px 20px rgb(80,150,25);
}
.label {
position: absolute;
left: 0.5em;
top: 1.75em;
}
.input {
height: 30px;
padding:10px;
background-color: rgb(50,50,50);
color: rgb(250,50,50);
}
.tall { height: 5em; }
</style>
<div class="center"><span class="shout" id="peers">0</span> peers <span class="shout" id="time">0</span> min <span class="shout" id="nodes">0</span> nodes <span class="shout" id="hours">0</span> hours <span class="shout" id="block">0</span> block <span class="shout" id="stack">0</span> stack</div>
<input id="url" class="center input crack" placeholder="enter peer stats source url">
<div class="center row charts">
</div>
<div class="model none">
<div class="chart"><span class="label"></span><canvas class="tall row"></canvas></div>
</div>
<script src="./jquery.js"></script>
<script src="./smoothie.js" charset="utf-8"></script>
<script>
if(window.location.search){url.value = window.location.search.split("?")[1]}
var up, br = 0, bt = 0, tmp;
var fetchData = async function(){
// fetch the data from server
var S = +new Date;
var data = await (await fetch(url.value||(location.origin+'/gun/stats.radata'), {method: 'GET',mode: 'cors'})).json();
$('#block').text(((br += (+new Date - S)/1000) / ++bt).toFixed(1));
data.over = (data.over/1000) || 15;
$('#stack').text((data.cpu||'').stack);
$('#peers').text(data.peers.count);
$('#time').text((data.peers.time / 1000 / 60).toFixed(0));
$('#nodes').text(data.node.count);
$('#hours').text((data.up.time / 60 / 60).toFixed(1));
if(data.up.time === up){ console.log("up same as before") } up = data.up.time;
;(async function(){ try{
Stats('peers#').line.append(+new Date, data.peers.count);
return;
Stats('cpu%');
tmp = await (await fetch(new Request(location.origin+'/gun/stats.top.radata'), {method: 'GET',mode: 'cors'})).text();
tmp = parseFloat((tmp.split('\n').filter(l => l.indexOf('node')+1)[0]||'').split(/\s+/).slice(-4)[0]||'0');
Stats('cpu%').line.append(+new Date, tmp);
}catch(e){console.log(e)}}());
Stats('memory').line.append(+new Date, data.memory.heapTotal / 1024 / 1024);
try{ Stats('dam # in/s').line.append(+new Date, Math.round(data.dam.in.count / data.over)); }catch(e){}
try{ Stats('dam in MB/s').line.append(+new Date, data.dam.in.done / 1024 / 1024 / data.over); }catch(e){}
try{ Stats('dam # out/s').line.append(+new Date, Math.round(data.dam.out.count / data.over)); }catch(e){}
try{ Stats('dam out MB/s').line.append(+new Date, data.dam.out.done / 1024 / 1024 / data.over); }catch(e){}
console.log('data',data);
//fetch keys in all, these may be dynamically changing
//for each key, check if we already have created a time series, if not, create it and add it
// to the chart corredsponding to the unit of measure
$.each(data.all, function(key, arr){
var chart = Stats(key);
// get data and append to line
// get the arrays inside the key
//for each array append the data to the line
for(var i in arr) {
// append data [timestamp], [data]
chart.line.append(arr[i][0], arr[i][1]);
}
});
}
//setInterval(fetchData, 15 * 1000);
setInterval(fetchData, 5000);
fetchData();
function Stats(key, chart){
// if we have already created, get data to append to it.
if(chart = Stats[key]){
return chart;
}
// create a new Series for this key
// add it into the map
chart = Stats[key] = new SmoothieChart({millisPerPixel:500, limitFPS: 16, responsive: true, minValue: 0, grid:{strokeStyle:'rgba(100%,100%,100%,0.2)'},labels:{fontSize:20}, grid: {verticalSections: 0, millisPerLine: 15000 * 4 /*, strokeStyle:'rgb(125, 0, 0)'*/}});
chart.line = new TimeSeries();
chart.addTimeSeries(chart.line,{ strokeStyle:'rgb('+Math.random()*255+', '+Math.random()*255+','+Math.random()*255+')', lineWidth:5 });
chart.canvas = $('.model').find('.chart').clone(true).appendTo('.charts');
chart.canvas.find('span').text(key);
chart.streamTo(chart.canvas.find('canvas').get(0), 15 * 1000);
chart.line.append(0, 0);
// check first two characters of key to determine other charts to add this in
// tbd later
return chart;
}
;(function(){
if('https' != (''+location).slice(0,5) && "localhost" != location.hostname){
$('body').append("<button id='https'>click here to try generating https certs</button>");
if(/^(?!0)(?!.*\.$)((1?\d?\d|25[0-5]|2[0-4]\d)(\.|$)){4}$/.test(location.hostname)){
$('#https').text("Link this IP address to a Domain by adding an `A Record` to your DNS settings that point to `"+ location.hostname +"` (we recommend the `name/host` be any subdomain you want, like `relay`, but if you want the root domain itself to directly point here use `*`). Then come back here on the domain & click this button to generate HTTPS certificates.");
return;
}
$('body').append("<input id='email' placeholder='email'/>");
$('#https').on('click', function(){
$(this).text("look at console.log for errors, if none, try https");
var gun = GUN(location.origin + '/gun');
if(!$('#email').val()){
$(this).text("email necessary for certs! Type it in & click here again.");
return;
}
setTimeout(function(){
gun._.opt.mesh.say({dam: 'service', try: 'https', email: $('#email').val(), domain: location.hostname});
setTimeout(function(){
if(gun._.opt.mesh.near){ return }
$('#https').text("It might have worked! try HTTPS!");
}, 9000);
}, 999);
});
}
}());
/*
Notes to Self about Debugging:
1. Read Disks can spike up to 1min, I suspect other operations are blocking it from resolving as fast as it otherwise would.
2. JSON parsing/stringifying sometimes way slower than other times, why?
3. Looks like RAD lex read is not optimized.
4. got prep + got emit = non-RAD problems, compare against read disk & got differentials (should be same).
5. Radix map/place ops could be slow?
6. SINGLE MESSAGE PROCESS TIME occasionally is huge, should get emailed.
7. Watch out for get/put loops times, maybe indicating (5) issues?
*/
</script>
<script src="../gun.js"></script>
</body>
</html>

View File

@ -1,48 +1,57 @@
@import url(https://fonts.googleapis.com/css?family=Oxygen);
html, body {
margin: 0;
padding: 0;
font-family: 'Oxygen', 'Trebuchet MS', arial;
position: relative;
background: black;
color: white;
line-height: 1.5;
font-size: 18pt;
f-ont-size: max(18pt, 2?vw);
}
body {
font-size: 18pt;
}
div, ul, ol, li, p, span, form, button, input, textarea {
div, ul, ol, li, p, span, form, button, input, textarea, img {
margin: 0;
padding: 0;
position: relative;
overflow: hidden;
font-size: 1em;
line-height: 1.5em;
vertical-align: inherit;
-webkit-transition: all 0.3s;
transition: all 0.3s;
box-sizing: border-box;
font: inherit;
}
button, input, textarea {
background: white;
border: none;
color: black;
a, button, input, textarea {
background: inherit;
border: inherit;
color: inherit;
text-decoration: inherit;
outline: none;
}
a {
color: white;
}
input, textarea {
input:not([type=button]):not([type=submit]), textarea {
width: 100%;
}
a:focus, button:focus, input[type=button]:focus, input[type=submit]:focus {
animation: pulse 2s infinite;
}
ul, li {
list-style: none;
}
p {
padding: 0;
}
p + p {
padding-top: 0;
}
[contenteditable=true]:empty:before {
content: attr(placeholder);
}
::placeholder, .hint {
color: inherit;
opacity: 0.3;
}
.model, .none { display: none }
.hide {
opacity: 0;
@ -50,152 +59,153 @@ ul, li {
transition: all 2s;
}
.page {
.full {
width: 100%;
min-height: 100vh;
}
.max {
max-width: 48em;
}
.min {
min-width: 12em;
}
.pad {
margin: 5% auto;
min-width: 250px;
width: 95%;
max-width: 50em;
margin: 5% auto;
max-width: 48em;
min-width: 12em;
}
.row {
width: 100%;
}
.row::after {
content: "";
display: block;
clear: both;
}
.col {
max-width: 24em;
min-width: 12em;
}
.center {
text-align: center;
vertical-align: middle;
margin-left: auto;
margin-right: auto;
}
.right {
float: right;
text-align: right;
}
.left {
float: left;
}
.center {
text-align: center;
text-align: left;
}
.mid {
margin-left: auto;
margin-right: auto;
}
.flush {
line-height: 0em;
.top {
vertical-align: top;
}
.low {
vertical-align: bottom;
}
.rim {
margin: 2%;
}
.rim { margin: 1%; }
.gap {
padding: 3%;
padding: clamp(0.5em, 3%, 1.5em);
}
.gully {
margin-bottom: 1%;
.stack { line-height: 0; }
.crack { margin-bottom: 1%; }
.sit { margin-bottom: 0; }
.focus {
margin-left: auto;
margin-right: auto;
float: none;
clear: both;
}
.sit { margin-bottom: 0; }
.row { width: 100%; }
.col { max-width: 33em; }
.leak { overflow: visible; }
.hold { overflow: hidden; }
.act {
display: block;
/*display: block;*/
font-weight: normal;
text-decoration: none;
-webkit-transition: all 0.3s;
transition: all 0.3s;
cursor: pointer;
}
.symbol {
.unit, .symbol {
display: inline-block;
vertical-align: inherit;
}
.sap { border-radius: 0.1em; }
.jot { border-bottom: 1px dashed #95B2CA; }
.loud {
font-size: 150%;
}
.jot {
border-bottom: 1px dashed #95B2CA;
}
.sap {
border-radius: 0.1em;
.shout {
font-size: 36pt;
font-size: 6.5vmax;
}
.red { background: #ea3224; }
.green { background: #33cc33; }
.blue { background: #4D79D8; }
.yellow { background: #d3a438; }
.black { background: black; }
.white { background: white; }
.red {
background: #ea3224;
}
.green {
background: #33cc33;
}
.blue {
background: #4D79D8;
}
.yellow {
background: #f2b919;
}
.black {
background: black;
}
.white {
background: white;
}
.shade { background: rgba(0%, 0%, 0%, 0.1); }
.tint { background: rgba(100%, 100%, 100%, 0.1); }
.shade {
background: rgba(0%, 0%, 0%, 0.1);
}
.tint {
background: rgba(100%, 100%, 100%, 0.1);
}
.redt {
color: #ea3224;
}
.greent {
color: #33cc33;
}
.bluet {
color: #4D79D8;
}
.yellowt {
color: #f2b919;
}
.blackt {
color: black;
}
.whitet {
color: white;
}
.redt { color: #ea3224; }
.greent { color: #33cc33; }
.bluet { color: #4D79D8; }
.yellowt { color: #d3a438; }
.blackt { color: black; }
.whitet { color: white; }
.hue {
background: #4D79D8;
-webkit-animation: hue 900s infinite;
animation: hue 900s infinite;
}
@keyframes hue {
} @keyframes hue {
0% {background-color: #4D79D8;}
25% {background-color: #33cc33;}
50% {background-color: #f2b919;}
50% {background-color: #d3a438;}
75% {background-color: #ea3224;}
100% {background-color: #4D79D8;}
} @-webkit-keyframes hue {
0% {background-color: #4D79D8;}
25% {background-color: #33cc33;}
50% {background-color: #f2b919;}
50% {background-color: #d3a438;}
75% {background-color: #ea3224;}
100% {background-color: #4D79D8;}
}
.huet {
color: #4D79D8;
color: #4D79D8;
-webkit-animation: huet 900s infinite;
animation: huet 900s infinite;
}
@keyframes huet {
} @keyframes huet {
0% {color: #4D79D8;}
25% {color: #33cc33;}
50% {color: #f2b919;}
50% {color: #d3a438;}
75% {color: #ea3224;}
100% {color: #4D79D8;}
} @-webkit-keyframes huet {
0% {color: #4D79D8;}
25% {color: #33cc33;}
50% {color: #f2b919;}
50% {color: #d3a438;}
75% {color: #ea3224;}
100% {color: #4D79D8;}
}
@ -204,19 +214,17 @@ ul, li {
background: #ea3224;
-webkit-animation: hue2 900s infinite;
animation: hue2 900s infinite;
}
@keyframes hue2 {
} @keyframes hue2 {
0% {background-color: #ea3224;}
25% {background-color: #4D79D8;}
50% {background-color: #33cc33;}
75% {background-color: #f2b919;}
75% {background-color: #d3a438;}
100% {background-color: #ea3224;}
} @-webkit-keyframes hue2 {
0% {background-color: #ea3224;}
25% {background-color: #4D79D8;}
50% {background-color: #33cc33;}
75% {background-color: #f2b919;}
75% {background-color: #d3a438;}
100% {background-color: #ea3224;}
}
@ -224,19 +232,17 @@ ul, li {
color: #ea3224;
-webkit-animation: huet2 900s infinite;
animation: huet2 900s infinite;
}
@keyframes huet2 {
} @keyframes huet2 {
0% {color: #ea3224;}
25% {color: #4D79D8;}
50% {color: #33cc33;}
75% {color: #f2b919;}
75% {color: #d3a438;}
100% {color: #ea3224;}
} @-webkit-keyframes huet2 {
0% {color: #ea3224;}
25% {color: #4D79D8;}
50% {color: #33cc33;}
75% {color: #f2b919;}
75% {color: #d3a438;}
100% {color: #ea3224;}
}
@ -244,17 +250,15 @@ ul, li {
background: #33cc33;
-webkit-animation: hue3 900s infinite;
animation: hue3 900s infinite;
}
@keyframes hue3 {
} @keyframes hue3 {
0% {background-color: #33cc33;}
25% {background-color: #f2b919;}
25% {background-color: #d3a438;}
50% {background-color: #ea3224;}
75% {background-color: #4D79D8;}
100% {background-color: #33cc33;}
} @-webkit-keyframes hue3 {
0% {background-color: #33cc33;}
25% {background-color: #f2b919;}
25% {background-color: #d3a438;}
50% {background-color: #ea3224;}
75% {background-color: #4D79D8;}
100% {background-color: #33cc33;}
@ -264,74 +268,64 @@ ul, li {
color: #33cc33;
-webkit-animation: huet3 900s infinite;
animation: huet3 900s infinite;
}
@keyframes huet3 {
} @keyframes huet3 {
0% {color: #33cc33;}
25% {color: #f2b919;}
25% {color: #d3a438;}
50% {color: #ea3224;}
75% {color: #4D79D8;}
100% {color: #33cc33;}
} @-webkit-keyframes huet3 {
0% {color: #33cc33;}
25% {color: #f2b919;}
25% {color: #d3a438;}
50% {color: #ea3224;}
75% {color: #4D79D8;}
100% {color: #33cc33;}
}
.hue4 {
background: #f2b919;
background: #d3a438;
-webkit-animation: hue4 900s infinite;
animation: hue4 900s infinite;
}
@keyframes hue4 {
0% {background-color: #f2b919;}
} @keyframes hue4 {
0% {background-color: #d3a438;}
25% {background-color: #ea3224;}
50% {background-color: #4D79D8;}
75% {background-color: #33cc33;}
100% {background-color: #f2b919;}
100% {background-color: #d3a438;}
} @-webkit-keyframes hue4 {
0% {background-color: #f2b919;}
0% {background-color: #d3a438;}
25% {background-color: #ea3224;}
50% {background-color: #4D79D8;}
75% {background-color: #33cc33;}
100% {background-color: #f2b919;}
100% {background-color: #d3a438;}
}
.huet4 {
color: #f2b919;
color: #d3a438;
-webkit-animation: huet4 900s infinite;
animation: huet4 900s infinite;
}
@keyframes huet4 {
0% {color: #f2b919;}
} @keyframes huet4 {
0% {color: #d3a438;}
25% {color: #ea3224;}
50% {color: #4D79D8;}
75% {color: #33cc33;}
100% {color: #f2b919;}
100% {color: #d3a438;}
} @-webkit-keyframes huet4 {
0% {color: #f2b919;}
0% {color: #d3a438;}
25% {color: #ea3224;}
50% {color: #4D79D8;}
75% {color: #33cc33;}
100% {color: #f2b919;}
100% {color: #d3a438;}
}
.pulse {
animation: pulse 2s infinite;
}
@keyframes pulse
{
} @keyframes pulse {
0% {opacity: 1;}
50% {opacity: 0.5;}
100% {opacity: 1;}
}
.joy {
width: 100px;
height: 100px;
@ -339,13 +333,20 @@ ul, li {
background: url(https://cdn.jsdelivr.net/npm/gun/examples/pop.png) no-repeat;
background-position: -2800px 0;
pointer-events: none;
z-index: 999999999;
animation: joy 1s steps(28);
} @keyframes joy {
0% {background-position: 0 0;}
100% {background-position: -2800px 0;}
}
@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,150 @@
<!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>
// 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('think1/' + 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 = String.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>

View File

@ -0,0 +1,77 @@
<!DOCTYPE html>
<html>
<head>
<title>Think</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
</head>
<body>
<video id="video" width="100%"></video>
<center>
<button id="record">Record</button>
<button id="play">Play</button>
</center>
<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>
<script>
const gun = Gun(`${window.location.origin}/gun`)
const record = { recorder: null, recording: false }
const video = document.querySelector('#video')
const playButton = document.querySelector('#play')
const recordButton = document.querySelector('#record')
recordButton.addEventListener('click', () => {
console.log(record)
if (!record.ing) {
return record.stream()
}
recordButton.innerText = 'Record'
if (record.ing.stop) { record.ing.stop() }
record.ing = false
}, false)
record.stream = () => {
navigator.mediaDevices.getDisplayMedia({ video: true }).then(stream => {
const chunks = [] // we have a stream, we can record it
record.ing = new MediaRecorder(stream)
record.ing.ondataavailable = eve => chunks.push(eve.data)
record.ing.onstop = () => record.save(new Blob(chunks))
record.ing.start()
recordButton.innerText = 'End'
}, err => { console.log(err) })
}
record.save = data => {
record.file = record.file || new FileReader()
record.file.readAsDataURL(data)
record.file.onloadend = () => {
let b64 = record.file.result
b64 = `data:video/webm${b64.slice(b64.indexOf(';'))}`
gun.get('test').get('screen').put(b64)
}
}
playButton.addEventListener('click', () => {
if (record.playing) {
playButton.innerText = 'Play'
video.pause()
record.playing = false
return
}
playButton.innerText = 'Stop'
record.playing = true
gun.get('test').get('screen').once(data => {
if (!data) { return }
video.src = data
video.play()
})
}, false)
</script>
</body>
</html>

View File

@ -1,53 +1,65 @@
<!DOCTYPE html>
<html>
<head>
<title>Think</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
</head>
<body>
<h1>Thoughts</h1>
<h1>Thoughts</h1>
<form id="form">
<input id="input">
<button>Add</button>
</form>
<form id="form">
<input id="input">
<button>Add</button>
</form>
<ul id="parentList"></ul>
<!-- <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>
<link href="style.css" rel="stylesheet">
<script>
var gun = Gun().get('thoughts');
document.getElementById('form').addEventListener('submit', function (e) {
e.preventDefault(); // attaches event listener and prevent default form action
var data = document.getElementById('input').value;
gun.set(data);
document.getElementById('input').value = "";
});
gun.map().on(function (thought, id) {
var li = document.getElementById(id) || document.getElementById('parentList').insertAdjacentHTML('beforeend', '<li id =' + id + '> ' + thought + '</li>');
var $ = function (selector) {
return document.querySelector(selector);
};
// attach the event listener to the selected li items
var links = $('#parentList').getElementsByTagName('li');
for (var i = 0; i < links.length; i++) {
var link = links[i];
// console.log(link.innerHTML);
link.ondblclick = dynamicEvent;
if (link.innerHTML === " null" || link.innerHTML === " " || link.innerHTML === "") {
link.style.display = "none";
} else {
link.style.display = "list-item";
};
};
});
function dynamicEvent() {
gun.get(this.id).put(null);
this.innerHTML = document.getElementById(this.id.innerHTML);
if (this.innerHTML === " null" || this.innerHTML === " " || this.innerHTML === "") {
this.style.display = "none";
} else {
this.style.display = "list-item";
};
};
</script>
<ul id="parentList"></ul>
<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>
<script>
const gun = Gun(`${window.location.origin}/gun`).get('thoughts')
const parentList = document.getElementById('parentList')
const input = document.getElementById('input')
const form = document.getElementById('form')
const dynamicEvent = e => {
const target = e.target;
gun.get(target.id).put(null);
target.innerHTML = document.getElementById(target.id);
if (target.innerHTML === ' null' || target.innerHTML === ' ' || target.innerHTML === '') {
target.style.display = 'none';
} else {
target.style.display = 'list-item';
}
}
gun.map().on((thought, id) => {
parentList.insertAdjacentHTML('beforeend', `<li id =${id}> ${thought}</li>`);
const links = parentList.getElementsByTagName('li');
for (const link of links) {
if (link.innerHTML === ' null' || link.innerHTML === ' ' || link.innerHTML === '') {
link.style.display = 'none';
} else {
link.style.display = 'list-item';
}
link.ondblclick = dynamicEvent;
}
})
form.addEventListener('submit', e => {
e.preventDefault();
gun.set(input.value);
input.value = '';
})
</script>
</body>
</html>

View File

@ -0,0 +1,58 @@
<!DOCTYPE html>
<h1>User</h1>
<form id="sign">
<input id="alias" placeholder="username">
<input id="pass" type="password" placeholder="passphrase">
<input id="signup" type="button" value="sign up">
<input id="signin" type="button" value="sign in">
</form>
<ul id="list"></ul>
<form id="said">
<input id="say">
<input id="speak" type="submit" value="speak">
</form>
<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gun/sea.js"></script>
<script>
const gun = Gun(`${window.location.origin}/gun`)
const user = gun.user().recall({ sessionStorage: true })
const alias = document.querySelector('#alias')
const pass = document.querySelector('#pass')
const sign = document.querySelector('#sign')
const signup = document.querySelector('#signup')
const signin = document.querySelector('#signin')
const said = document.querySelector('#said')
const say = document.querySelector('#say')
const ul = document.querySelector('#list')
function UI (say, id) {
const li = document.createElement('li')
li.setAttribute('id', id)
li.appendChild(document.createTextNode(say))
ul.appendChild(li)
return false
}
signup.addEventListener('click', () => user.create(alias.value, pass.value, () => user.auth(alias.value, pass.value)))
signin.addEventListener('click', () => user.auth(alias.value, pass.value))
said.addEventListener('submit', e => {
e.preventDefault()
// if(!user.is){ return }
user.get('said').set(say.value)
said.value = ''
})
gun.on('auth', () => {
sign.style.display = 'none'
user.get('said').map().on(UI)
})
</script>

View File

@ -0,0 +1,83 @@
<!DOCTYPE html>
<video id="video" width="100%" controls autoplay></video>
<center>
<input id="pass" placeholder="password">
Record <button class="record">Camera</button> or <button class="screen">Screen</button>
</center>
<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gun/sea.js"></script>
<script>
const peers = [
`${window.location.origin}/gun`,
'https://gun-us.herokuapp.com/gun',
'https://gun-eu.herokuapp.com/gun'
]
const gun = Gun({ localStorage: true, peers })
const pass = document.querySelector('#pass')
const video = document.querySelector('#video')
const camera = document.querySelector('.record')
const screen = document.querySelector('.screen')
gun.get('test').get('video').on(async data => {
if (pass.value) { data = await SEA.decrypt(data, pass.value) }
video.setAttribute('src', data)
})
function record(type) {
function load(media) {
const chunks = []
record.ing = new MediaRecorder(media)
record.ing.ondataavailable = eve => { chunks.push(eve.data) }
record.ing.onstop = eve => { record.save(new Blob(chunks)) }
record.ing.start()
}
function error(err) { console.log(err) }
if (type === 'Camera') {
navigator.getMedia({ video: true, audio: true }, load, error)
}
if (type === 'Screen') {
navigator.mediaDevices.getDisplayMedia({ video: true, audio: true }).then(load, error)
}
}
function act(e) {
if (record.ing) {
if (record.ing.stop) { record.ing.stop() }
e.target.textContent = record.type
record.ing = false
return
}
record(record.type = e.target.textContent)
e.target.textContent = 'end'
}
record.save = data => {
record.file = record.file || new FileReader()
record.file.readAsDataURL(data)
record.file.onloadend = async () => {
const b64 = record.file.result
let b64formated = `data:video/webm${b64.slice(b64.indexOf(';'))}`
video.setAttribute('src', b64formated)
if (pass.value) { b64formated = await SEA.encrypt(b64formated, pass.value) }
gun.get('test').get('video').put(b64formated)
}
}
camera.addEventListener('click', e => act(e))
screen.addEventListener('click', e => act(e))
navigator.getMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia || navigator.msGetUserMedia)
</script>

View File

@ -9,7 +9,7 @@
</head>
<body>
<div id="app">
This is example of simple Vue plugin. It works exatcly same as the Vue instance data property, but the name is gunData.<br>
This is example of simple Vue plugin. It works exactly same as the Vue instance data property, but the name is gunData.<br>
The cool part is that every property in the gunData is realtime synced via gunDB to every other page viewer!<br>
<table>
<tr>

40
examples/wave.html Normal file
View File

@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Wave example</title>
</head>
<body>
<button id="bPiano">Piano left</button>
<button id="bGuitar">Guitar itched</button>
<button id="bXylo">Xylophone slow</button>
<button id="bAll">All in one</button>
<script src="../lib/wave.js"></script>
<script>
function piano() {
wave(':piano:zxcvbn').balance(-1).play()
}
function guitar() {
wave(':guitar:zxcvbn').itch(0.5).play()
}
function xylo() {
wave(':xylophone:zxcvbn').pace(100).play()
}
function all() {
wave(`
:pace 400: :itch 0: :balance 0:
:piano: :balance -1: zxcvbn
:guitar: :balance 0: :itch 0.5: zxcvbn
:xylophone: :itch 0: :pace 100: zxcvbn
`).play()
}
document.querySelector('#bPiano').addEventListener("click", piano)
document.querySelector('#bGuitar').addEventListener("click", guitar)
document.querySelector('#bXylo').addEventListener("click", xylo)
document.querySelector('#bAll').addEventListener("click", all)
</script>
</body>
</html>

3
examples/webpack/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
package-lock.json
node_modules
public

View File

@ -0,0 +1,17 @@
{
"name": "webpack",
"version": "1.0.0",
"description": "webpack build example",
"scripts": {
"build": "webpack --devtool source-map --config webpack.config.js",
"prepare": "npm run build"
},
"author": "",
"license": "ISC",
"dependencies": {
"gun": "github:amark/gun",
"html-webpack-plugin": "^5.5.0",
"webpack": "^5.72.1",
"webpack-cli": "^4.9.2"
}
}

View File

@ -0,0 +1,9 @@
define(function(require, exports, module) {
var Gun = require("gun");
var gun = new Gun();
gun.get("hello").get("world").put("from gun").on((data, key) => console.log(data, key));
});

View File

@ -0,0 +1,5 @@
<!DOCTYPE html>
<html>
<head></head>
<body></body>
</html>

View File

@ -0,0 +1,35 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
let plugins = [];
plugins.push(new HtmlWebpackPlugin({
filename: './index.html',
template: './src/index.html',
inject: true,
minify: false,
hash: false,
cache: false,
showErrors: false
}));
console.log("webpack config loaded");
module.exports = {
mode: "development",
// stats: 'minimal',
stats: 'normal',
// stats: 'verbose',
entry: [path.resolve(__dirname, './src/app.js')],
output: {
path: path.resolve(__dirname, './public'),
clean: true,
filename: './app.js'
},
plugins: plugins
};

23
gun.d.ts vendored Normal file
View File

@ -0,0 +1,23 @@
import { IGun, LEX } from './types/gun';
declare const Gun: IGun;
export default Gun;
import {} from './types/gun/IGun';
declare module './types/gun/IGun' {
export interface IGun {
window: Window
}
}
declare global {
interface Window {
Gun: IGun;
GUN: IGun;
}
interface StringConstructor {
match(t: string, o: LEX | string): boolean;
random(length?: number, alphabet?: string): string;
}
}

4764
gun.js

File diff suppressed because it is too large Load Diff

3
gun.min.js vendored

File diff suppressed because one or more lines are too long

19
index.d.ts vendored Normal file
View File

@ -0,0 +1,19 @@
export * from './types/gun';
export * from './types/sea';
import { IGun, LEX } from './types/gun';
import { ISEA } from './types/sea';
declare const Gun: IGun;
export default Gun;
export const SEA: ISEA;
declare global {
const Gun: IGun;
interface StringConstructor {
match(t: string, o: LEX | string): boolean;
random(length?: number, alphabet?: string): string;
}
}

13
lib/afore.js Normal file
View File

@ -0,0 +1,13 @@
function afore(tag, hear){
if(!tag){ return }
tag = tag.the; // grab the linked list root
var tmp = tag.to; // grab first listener
hear = tmp.on.on(tag.tag, hear); // add us to end
hear.to = tmp || hear.to; // make our next be current first
hear.back.to = hear.to; // make our back point to our next
tag.last = hear.back; // make last be same as before
hear.back = tag; // make our back be the start
tag.to = hear; // make the start be us
return hear;
}
if(typeof module !== "undefined"){ module.exports = afore } // afore(gun._.on('in'), function(){ })

View File

@ -7,7 +7,7 @@
var s = this;
opt = opt || {};
opt.bucket = opt.bucket || opt.Bucket || process.env.AWS_S3_BUCKET;
opt.region = opt.region || process.AWS_REGION || "us-east-1";
opt.region = opt.region || process.env.AWS_REGION || "us-east-1";
opt.accessKeyId = opt.key = opt.key || opt.accessKeyId || process.env.AWS_ACCESS_KEY_ID;
opt.secretAccessKey = opt.secret = opt.secret || opt.secretAccessKey || process.env.AWS_SECRET_ACCESS_KEY;
if(!opt.accessKeyId || !opt.secretAccessKey){

283
lib/axe.js Normal file
View File

@ -0,0 +1,283 @@
// I don't quite know where this should go yet, so putting it here
// what will probably wind up happening is that minimal AXE logic added to end of gun.js
// and then rest of AXE logic (here) will be moved back to gun/axe.js
// but for now... I gotta rush this out!
var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'), u;
Gun.on('opt', function(at){ start(at); this.to.next(at) }); // make sure to call the "next" middleware adapter.
// TODO: BUG: panic test/panic/1 & test/panic/3 fail when AXE is on.
function start(root){
if(root.axe){ return }
var opt = root.opt, peers = opt.peers;
if(false === opt.axe){ return }
if((typeof process !== "undefined") && 'false' === ''+(opt.env=process.env||'').AXE){ return }
Gun.log.once("AXE", "AXE relay enabled!");
var axe = root.axe = {}, tmp, id;
var mesh = opt.mesh = opt.mesh || Gun.Mesh(root); // DAM!
var dup = root.dup;
mesh.way = function(msg){
if(!msg){ return }
//relayUp(msg); // TEMPORARY!!!
if(msg.get){ return GET(msg) }
if(msg.put){ return }
fall(msg);
}
function GET(msg){
if(!msg){ return }
var via = (msg._||'').via, soul, has, tmp, ref;
if(!via || !via.id){ return fall(msg) }
// SUBSCRIPTION LOGIC MOVED TO GET'S ACK REPLY.
if(!(ref = REF(msg)._)){ return fall(msg) }
ref.asked = +new Date;
GET.turn(msg, ref.route, 0);
}
GET.turn = function(msg, route, turn){
var tmp = msg['#'], tag = dup.s[tmp], next;
if(!tmp || !tag){ return } // message timed out, GUN may require us to relay, tho AXE does not like that. Rethink?
// TOOD: BUG! Handle edge case where live updates occur while these turn hashes are being checked (they'll never be consistent), but we don't want to degrade to O(N), if we know the via asking peer got an update, then we should do something like cancel these turns asking for data.
// Ideas: Save a random seed that sorts the route, store it and the index. // Or indexing on lowest latency is probably better.
clearTimeout(tag.lack);
if(tag.ack && (tmp = tag['##']) && msg['##'] === tmp){ return } // hashes match, stop asking other peers!
next = (Object.maps(route||opt.peers)).slice(turn = turn || 0);
if(!next.length){
if(!route){ return } // asked all peers, stop asking!
GET.turn(msg, u, 0); // asked all subs, now now ask any peers. (not always the best idea, but stays )
return;
}
setTimeout.each(next, function(id){
var peer = opt.peers[id]; turn++;
if(!peer || !peer.wire){ route && route.delete(id); return } // bye! // TODO: CHECK IF 0 OTHER PEERS & UNSUBSCRIBE
if(mesh.say(msg, peer) === false){ return } // was self
if(0 == (turn % 3)){ return 1 }
}, function(){
tag['##'] = msg['##']; // should probably set this in a more clever manner, do live `in` checks ++ --, etc. but being lazy for now. // TODO: Yes, see `in` TODO, currently this might match against only in-mem cause no other peers reply, which is "fine", but could cause a false positive.
tag.lack = setTimeout(function(){ GET.turn(msg, route, turn) }, 25);
}, 3);
}
function fall(msg){ mesh.say(msg, opt.peers) }
function REF(msg){
var ref = '', soul, has, tmp;
if(!msg || !msg.get){ return ref }
if('string' == typeof (soul = msg.get['#'])){ ref = root.$.get(soul) }
if('string' == typeof (tmp = msg.get['.'])){ has = tmp } else { has = '' }
var via = (msg._||'').via, sub = (via.sub || (via.sub = new Object.Map)); (sub.get(soul) || (sub.set(soul, tmp = new Object.Map) && tmp)).set(has, 1); // {soul: {'':1, has: 1}} // TEMPORARILY REVERT AXE TOWER TYING TO SUBSCRIBING TO EVERYTHING. UNDO THIS!
via.id && ref._ && (ref._.route || (ref._.route = new Object.Map)).set(via.id, via); // SAME AS ^
return ref;
}
function LEX(lex){ return (lex = lex || '')['='] || lex['*'] || lex['>'] || lex }
root.on('in', function(msg){ var to = this.to, tmp;
if((tmp = msg['@']) && (tmp = dup.s[tmp])){
tmp.ack = (tmp.ack || 0) + 1; // count remote ACKs to GET. // TODO: If mismatch, should trigger next asks.
if(tmp.it && tmp.it.get && msg.put){ // WHEN SEEING A PUT REPLY TO A GET...
var get = tmp.it.get||'', ref = REF(tmp.it)._, via = (tmp.it._||'').via||'', sub;
if(via && ref){ // SUBSCRIBE THE PEER WHO ASKED VIA FOR IT:
//console.log("SUBSCRIBING", Object.maps(ref.route||''), "to", LEX(get['#']));
via.id && (ref.route || (ref.route = new Object.Map)).set(via.id, via);
sub = (via.sub || (via.sub = new Object.Map));
ref && (sub.get(LEX(get['#'])) || (sub.set(LEX(get['#']), sub = new Object.Map) && sub)).set(LEX(get['.']), 1); // {soul: {'':1, has: 1}}
via = (msg._||'').via||'';
if(via){ // BIDIRECTIONAL SUBSCRIBE: REPLIER IS NOW SUBSCRIBED. DO WE WANT THIS?
via.id && (ref.route || (ref.route = new Object.Map)).set(via.id, via);
sub = (via.sub || (via.sub = new Object.Map));
if(ref){
var soul = LEX(get['#']), sift = sub.get(soul), has = LEX(get['.']);
if(has){
(sift || (sub.set(soul, sift = new Object.Map) && sift)).set(has, 1);
} else
if(!sift){
sub.set(soul, sift = new Object.Map);
sift.set('', 1);
}
}
}
}
}
if((tmp = tmp.back)){ // backtrack OKs since AXE splits PUTs up.
setTimeout.each(Object.keys(tmp), function(id){
to.next({'#': msg['#'], '@': id, ok: msg.ok});
});
return;
}
}
to.next(msg);
});
root.on('create', function(root){
this.to.next(root);
var Q = {};
root.on('put', function(msg){
var eve = this, at = eve.as, put = msg.put, soul = put['#'], has = put['.'], val = put[':'], state = put['>'], q, tmp;
eve.to.next(msg);
if(msg['@']){ return } // acks send existing data, not updates, so no need to resend to others.
if(!soul || !has){ return }
var ref = root.$.get(soul)._, route = (ref||'').route;
if(!route){ return }
if(ref.skip && ref.skip.has == has){ ref.skip.now = msg['#']; return }
(ref.skip = {now: msg['#'], has: has}).to = setTimeout(function(){
setTimeout.each(Object.maps(route), function(pid){ var peer, tmp;
var skip = ref.skip||''; ref.skip = null;
if(!(peer = route.get(pid))){ return }
if(!peer.wire){ route.delete(pid); return } // bye!
var sub = (peer.sub || (peer.sub = new Object.Map)).get(soul);
if(!sub){ return }
if(!sub.get(has) && !sub.get('')){ return }
var put = peer.put || (peer.put = {});
var node = root.graph[soul], tmp;
if(node && u !== (tmp = node[has])){
state = state_is(node, has);
val = tmp;
}
put[soul] = state_ify(put[soul], has, state, val, soul);
tmp = dup.track(peer.next = peer.next || String.random(9));
(tmp.back || (tmp.back = {}))[''+(skip.now||msg['#'])] = 1;
if(peer.to){ return }
peer.to = setTimeout(function(){ flush(peer) }, opt.gap);
}) }, 9);
});
});
function flush(peer){
var msg = {'#': peer.next, put: peer.put, ok: {'@': 3, '/': mesh.near}}; // BUG: TODO: sub count!
// TODO: what about DAM's >< dedup? Current thinking is, don't use it, however, you could store first msg# & latest msg#, and if here... latest === first then likely it is the same >< thing, so if(firstMsg['><'][peer.id]){ return } don't send.
peer.next = peer.put = peer.to = null;
mesh.say(msg, peer);
}
var state_ify = Gun.state.ify, state_is = Gun.state.is;
function relayUp(msg){
mesh.say(msg, axe.up);
}
;(function(){ // THIS IS THE UP MODULE;
axe.up = {};
var hi = mesh.hear['?']; // lower-level integration with DAM! This is abnormal but helps performance.
mesh.hear['?'] = function(msg, peer){ var p; // deduplicate unnecessary connections:
hi(msg, peer);
if(!peer.pid){ return }
if(peer.pid === opt.pid){ mesh.bye(peer); return } // if I connected to myself, drop.
if(p = axe.up[peer.pid]){ // if we both connected to each other...
if(p === peer){ return } // do nothing if no conflict,
if(opt.pid > peer.pid){ // else deterministically sort
p = peer; // so we will wind up choosing the same to keep
peer = axe.up[p.pid]; // and the same to drop.
}
p.url = p.url || peer.url; // copy if not
mesh.bye(peer); // drop
axe.up[p.pid] = p; // update same to be same.
return;
}
if(!peer.url){ return }
axe.up[peer.pid] = peer;
if(axe.stay){ axe.stay() }
};
mesh.hear['opt'] = function(msg, peer){
if(msg.ok){ return }
var tmp = msg.opt;
if(!tmp){ return }
tmp = tmp.peers;
if(!tmp || 'string' != typeof tmp){ return }
if(99 <= Object.keys(axe.up).length){ return } // 99 TEMPORARILY UNTIL BENCHMARKED!
mesh.hi({id: tmp, url: tmp, retry: 9});
if(peer){ mesh.say({dam: 'opt', ok: 1, '@': msg['#']}, peer) }
}
axe.stay = function(){
clearTimeout(axe.stay.to);
axe.stay.to = setTimeout(function(tmp, urls){
if(!(tmp = root.stats && root.stats.stay)){ return }
urls = {}; Object.keys(axe.up||'').forEach(function(p){
p = (axe.up||'')[p]; if(p.url){ urls[p.url] = {} }
});
(tmp.axe = tmp.axe || {}).up = urls;
}, 1000 * 9);//1000 * 60);
};
setTimeout(function(tmp){
if(!(tmp = root.stats && root.stats.stay && root.stats.stay.axe)){ return }
if(!(tmp = tmp.up)){ return }
if(!(tmp instanceof Array)){ tmp = Object.keys(tmp) }
setTimeout.each(tmp||[], function(url){ mesh.hear.opt({opt: {peers: url}}) });
},1000);
}());
setTimeout(function(){ require('./service')(root) },9);
;(function(){ // THIS IS THE MOB MODULE;
//return; // WORK IN PROGRESS, TEST FINALIZED, NEED TO MAKE STABLE.
/*
AXE should have a couple of threshold items...
let's pretend there is a variable max peers connected
mob = 10000
if we get more peers than that...
we should start sending those peers a remote command
that they should connect to this or that other peer
and then once they (or before they do?) drop them from us.
sake of the test... gonna set that peer number to 1.
The mob threshold might be determined by other factors,
like how much RAM or CPU stress we have.
*/
opt.mob = opt.mob || parseFloat((opt.env||'').MOB) || 999999; // should be based on ulimit, some clouds as low as 10K.
// handle rebalancing a mob of peers:
root.on('hi', function(peer){
this.to.next(peer);
if(peer.url){ return } // I am assuming that if we are wanting to make an outbound connection to them, that we don't ever want to drop them unless our actual config settings change.
var count = /*Object.keys(opt.peers).length ||*/ mesh.near; // TODO: BUG! This is slow, use .near, but near is buggy right now, fix in DAM.
//console.log("are we mobbed?", opt.mob, Object.keys(opt.peers).length, mesh.near);
if(opt.mob >= count){ return } // TODO: Make dynamic based on RAM/CPU also. Or possibly even weird stuff like opt.mob / axe.up length?
var peers = {};Object.keys(axe.up).forEach(function(p){ p = axe.up[p]; p.url && (peers[p.url]={}) });
// TODO: BUG!!! Infinite reconnection loop happens if not enough relays, or if some are missing. For instance, :8766 says to connect to :8767 which then says to connect to :8766. To not DDoS when system overload, figure clever way to tell peers to retry later, that network does not have enough capacity?
mesh.say({dam: 'mob', mob: count, peers: peers}, peer);
setTimeout(function(){ mesh.bye(peer) }, 9); // something with better perf?
});
root.on('bye', function(peer){
this.to.next(peer);
});
}());
;(function(){ // THIS IS THE UNIVERSAL NOTIFICATION MODULE
var to = {}, key = {}, email = require('./email');
if(email.err){ return }
mesh.hear['tag'] = function(msg, peer, who){
if(who = key[msg.key]){ who.rate = Math.max(msg.rate||1000*60*15, 1000*60); return }
if(!msg.src || !msg.email){ return }
if(+new Date < peer.emailed + 1000*60*2){ mesh.say({dam:'tag',err:'too fast'},peer); return } // peer can only send notifications > 2min
var src; try{ src = new URL(msg.src = msg.src.split(/\s/)[0]); } catch(e){ return } // throws if invalid URL.
(who = (to[msg.email] = to[msg.email] || {go:{}})).go[''+src] = 1; // we're keeping in-memory for now, maybe will "stay" to disk in future.
peer.emailed = +new Date;
if(who.batch){ return }
key[who.key = Math.random().toString(36).slice(2)] = who;
who.batch = setTimeout(function(){
email.send({
from: process.env.EMAIL,
to: msg.email,
subject: "Notification:",
text: 'Someone or a bot tagged you at: (⚠️ only click link if you recognize & trust it ⚠️)\n'+
'[use #'+who.key+' to unsubscribe please mute this thread by tapping the top most "⋮" button and clicking mute]\n\n' +
Object.keys(who.go).join('\n'), // TODO: NEEDS TO BE CPU SCHEDULED
headers: {'message-id': '<123456789.8765@example.com>'} // hardcode id so all batches also group into the same email thread to reduce clutter.
}, function(err, r){
who.batch = null; who.go = {};
err && console.log("email TAG:", err);
});
}, who.rate || (1000*60*60*24)); // default to 1 day
};
}());
};
;(function(){
var from = Array.from;
Object.maps = function(o){
if(from && o instanceof Map){ return from(o.keys()) }
if(o instanceof Object.Map){ o = o.s }
return Object.keys(o);
}
if(from){ return Object.Map = Map }
(Object.Map = function(){ this.s = {} }).prototype = {set:function(k,v){this.s[k]=v;return this},get:function(k){return this.s[k]},delete:function(k){delete this.s[k]}};
}());

1
lib/book.js Normal file
View File

@ -0,0 +1 @@
console.log("Officially moved to gun.js core, use gun/src/book.js on own.");

View File

@ -1,24 +1,22 @@
var Gun = (typeof window !== "undefined")? window.Gun : require('../gun');
Gun.on('opt', function(root){
Gun.on('create', function(root){
this.to.next(root);
if(root.once){ return }
root.on('in', function(msg){
//Msg did not have a peer property saved before, so nothing ever went further
if(!msg.mesh || !msg.BYE){ return this.to.next(msg) }
var peer = msg.mesh.via;
(peer.bye = peer.bye || []).push(msg.BYE);
})
var mesh = root.opt.mesh;
if(!mesh){ return }
mesh.hear['bye'] = function(msg, peer){
(peer.byes = peer.byes || []).push(msg.bye);
}
root.on('bye', function(peer){
this.to.next(peer);
if(!peer.bye){ return }
var gun = root.gun;
Gun.obj.map(peer.bye, function(data){
if(!peer.byes){ return }
var gun = root.$;
Gun.obj.map(peer.byes, function(data){
Gun.obj.map(data, function(put, soul){
gun.get(soul).put(put);
});
});
peer.bye = [];
peer.byes = [];
});
});
@ -30,7 +28,7 @@ Gun.chain.bye = function(){
var tmp = data;
(data = {})[at.get] = tmp;
});
root.on('out', {BYE: data});
root.on('out', {bye: data});
return gun;
}
return bye;

32
lib/crashed.js Normal file
View File

@ -0,0 +1,32 @@
;(function(){ try {
var fs = require('fs'), logs = [], up = __dirname+'/../';
fs.readdir(up, function(err, list){ try{
var i = 0, f; while(f = list[i++]){
if(0 === f.indexOf('isolate-') && '.log' === f.slice(-4)){ logs.push(f) }
}
logs = logs.sort();
var i = 0, f, lf; while(f = list[i++]){
if(0 <= f.indexOf('-v8-') && '.log' === f.slice(-4)){ lf = f }
} f = lf;
if(!f){ return }
fs.rename(up+f, up+'v8.log', function(err,ok){
var i = 0, f; while(f = logs[i++]){ fs.unlink(up+f, noop) }
if(!process.env.EMAIL){ return } // ONLY EMAIL IF DEVELOPER OPTS IN!!!
email(); // ONLY EMAIL IF DEVELOPER OPTS IN!!!
});
}catch(e){} });
function noop(){};
function email(){ try{
if(!process.env.EMAIL){ return } // ONLY EMAIL IF DEVELOPER OPTS IN!!!
var address = process.env.EMAIL || "mark@gun.eco";
// you also have to specify your EMAIL_KEY gmail 2F' app's password (not reg) to send out.
require('./email').send({
text: "log attached",
from: address,
to: address,
subject: "GUN V8 LOG",
attachment:[{path: up+'v8.log', type:"text/plain", name:"v8.log"}]
}, noop);
}catch(e){} };
}catch(e){}
}());

75
lib/dom.js Normal file
View File

@ -0,0 +1,75 @@
;(function(){ // jQuery shim
// u = undefined, n = null, b = boolean = true/false, n = number, t = text, l = list = array, o = object, cb = callback = function, q = query CSS, k = key, eve = event.
if(window.$){ return }
(($ = window.$ = function(q, tag, I, u){
if(q instanceof $){ return q }
if(!((I = this) instanceof $)){ return new $(q, tag) }
if('string' != typeof q){ return I.tags = (q = q||[]).tags || (u === q.length)? [q] : q, I }
if('<' === q[0]){ return I.add(q) }
return q.split(",").forEach(function(q){ I.add((tag||document).querySelectorAll(q)) }), I;
}).fn = $.prototype).each = function(cb){ return $.each(this.tags, cb), this }
$.each = function(o, cb){ Object.keys(o).forEach(function(k){ cb(k, o[k]) }) }
$.isPlainObject = function(o){
return (o? (o instanceof Object && o.constructor === Object)
|| 'Object' === Object.prototype.toString.call(o).match(/^\[object (\w+)\]$/)[1]
: false);
}
$.fn.add = function(add, tmp, u){ if(!add){ return this }
if('<' === (tmp = add)[0]){ (add = document.createElement('div')).innerHTML = tmp; add = add.children[0] }
add = ('string' == typeof add)? $(add).tags : (u == add.length)? add : [].slice.call(add);
return this.tags = [].slice.call(this.tags||[]).concat(add), this;
}
$.fn.get = function(i, l, u){ return l = this.tags, (i === u)? l : l[i] }
$.fn.is = function(q, b){ return this.each(function(i, tag){ b = b || tag.matches(q) }), b }
$.fn.css = function(o){ return this.each(function(i, tag){ $.each(o, function(k,v){ tag.style[k] = v }) })}
$.fn.on = function(t, cb){ return this.each(function(i, tag){
t.split(" ").forEach(function(t){ tag.addEventListener(t, cb) });
})}
$.fn.val = function(t, k, f, u){
t = (t === u)? '' : (f = 1) && t;
k = k || 'value';
return this.each(function(i, tag){
if(f){ tag[k] = t }
else { t += (tag[k]||'') }
}), f? this : t;
}
$.fn.text = function(t){ return this.val(t, 'textContent') }
$.fn.html = function(html){ return this.val(html, 'innerHTML') }
$.fn.attr = function(attr,val){ return this.val(val, attr) }
$.fn.find = function(q, I, l){
I = $(), l = I.tags;
return this.each(function(i, tag){
$(q, tag).each(function(i, tag){
if(0 > l.indexOf(tag)){ l.push(tag) }
});
}), I;
}
$.fn.place = function(where, on, f, op, I){ return (I = this).each(function(i, tag){ $(on).each(function(i, node){
(f? tag : node)[op||'insertAdjacentElement'](({
'-1':'beforebegin', '-0.1': 'afterbegin', '0.1':'beforeend', '1': 'afterend'
})[where], (f? node : tag));
})})}
$.fn.append = function(html){ return $(html).place(0.1, this), this }
$.fn.appendTo = function(html){ return this.place(0.1, $(html)) }
function rev(o, I){ (I = $()).tags = [].slice.call(o.tags).reverse(); return I };
$.fn.prependTo = function(html){ return rev(this).place(-0.1, $(html)), this }
$.fn.prepend = function(html){ return rev($(html)).place(-0.1, this), this }
$.fn.parents = function(q, c, I, l, p){
I = $(), l = I.tags, p = 'parentElement';
this.each(function(i, tag){
if(c){ (c = {})[p] = tag ; tag = c }
while(tag){ if((tag = tag[p]) && $(tag).is(q)){
l.push(tag); if(c){ return }
}}
});
return I;
}
$.fn.closest = function(q, c){ return this.parents(q, 1) }
$.fn.clone = function(b, I, l){
I = $(), l = I.tags;
this.each(function(i, tag){
l.push(tag.cloneNode(true))
});
return I;
}
}());

12
lib/email.js Normal file
View File

@ -0,0 +1,12 @@
;(function(){
var email, fail = {send: function(opt, cb){ cb && cb("You do not have email installed.") } };
if(!process.env.EMAIL){ return module.exports = fail }
try{ email = require('emailjs') }catch(e){};
if(!email){ return module.exports = fail }
return module.exports = email.server.connect({
user: process.env.EMAIL,
password: process.env.EMAIL_KEY,
host: process.env.EMAIL_HOST || "smtp.gmail.com",
ssl: process.env.EMAIL_SSL || true
});
}());

View File

@ -5,26 +5,33 @@
this.to.next(root);
if(root.once){ return }
if(typeof process == 'undefined'){ return }
var util = process.memoryUsage;
var util = process.memoryUsage, heap;
if(!util){ return }
ev.max = parseFloat(root.opt.memory || process.env.WEB_MEMORY || 1399) * 0.8; // max_old_space_size defaults to 1400 MB. Note: old space !== memory space though.
try{ heap = require('v8').getHeapStatistics }catch(e){}
if(!heap){ return }
ev.max = parseFloat(root.opt.memory || (heap().heap_size_limit / 1024 / 1024) || process.env.WEB_MEMORY || 1399) * 0.8; // max_old_space_size defaults to 1400 MB. Note: old space !== memory space though. // KEEPING USED_HEA_SIZE < HEAP_SIZE_LIMIT ONLY THING TO BE BELOW TO PREVENT CRASH!
setInterval(check, 1000);
function check(){
var used = ev.used = util().rss / 1024 / 1024;
if(used < ev.max){ return }
setTimeout(GC, 1);
var used = util().rss / 1024 / 1024;
var hused = heap().used_heap_size / 1024 / 1024;
var tmp; if(tmp = console.STAT){ tmp.memax = parseFloat(ev.max.toFixed(1)); tmp.memused = parseFloat(used.toFixed(1)); tmp.memhused = parseFloat(hused.toFixed(1)); }
if(hused < ev.max && used < ev.max){ return }
//if(used < ev.max){ return }
console.STAT && console.STAT('evict memory:', hused.toFixed(), used.toFixed(), ev.max.toFixed());
GC();//setTimeout(GC, 1);
}
function GC(){
var S = +new Date;
var souls = Object.keys(root.graph||empty);
var toss = Math.ceil(souls.length * 0.01);
//var start = Gun.state(), i = toss;
Gun.list.map(souls, function(soul){
if(--toss < 0){ return }
root.gun.get(soul).off();
});
//console.log("evicted", i, 'nodes in', ((Gun.state() - start)/1000).toFixed(2), 'sec.');
setTimeout.each(souls, function(soul){
if(--toss < 0){ return 1 }
root.$.get(soul).off();
},0,99);
root.dup.drop(1000 * 9); // clean up message tracker
console.STAT && console.STAT(S, +new Date - S, 'evict');
}
/*
root.on('in', function(msg){

81
lib/fork.js Normal file
View File

@ -0,0 +1,81 @@
/*
describe('API Chain Features', function(){
describe('Gun.chain.fork', function(){
var gun = Gun();
var fork;
it('create fork', function(done){
fork = gun.fork().wire();
done();
});
it('put data via fork', function(done){
fork.get("fork-test").get("fork").put("test123").once(()=>done());
});
it('get data via main', function(done){
gun.get("fork-test").get("fork").once((data)=>{
expect(data).to.be("test123");
done();
});
});
it('put data via main', function(done){
gun.get("fork-test").get("main").put("test321").once(()=>done());
});
it('get data via fork', function(done){
fork.get("fork-test").get("main").once((data)=>{
expect(data).to.be("test321");
done();
});
});
})
})
*/
(function (Gun, u) {
/**
*
* credits:
* github:bmatusiak
*
*/
Gun.chain.fork = function(g) {
var gun = this._;
var w = {},
mesh = () => {
var root = gun.root,
opt = root.opt;
return opt.mesh || Gun.Mesh(root);
}
w.link = function() {
if (this._l) return this._l;
this._l = {
send: (msg) => {
if (!this.l || !this.l.onmessage)
throw 'not attached';
this.l.onmessage(msg);
}
}
return this._l;
};
w.attach = function(l) {
if (this.l)
throw 'already attached';
var peer = { wire: l };
l.onmessage = function(msg) {
mesh().hear(msg.data || msg, peer);
};
mesh().hi(this.l = l && peer);
};
w.wire = function(opts) {
var f = new Gun(opts);
f.fork(w);
return f;
};
if (g) {
w.attach(g.link());
g.attach(w.link());
}
return w;
};
})((typeof window !== "undefined") ? window.Gun : require('../gun'))

18
lib/fsrm.js Normal file
View File

@ -0,0 +1,18 @@
var fs = require('fs');
var nodePath = require('path');
var dir = __dirname + '/../';
module.exports = function rm(path, full) {
path = full || nodePath.join(dir, path);
if(!fs.existsSync(path)){ return }
fs.readdirSync(path).forEach(function(file,index){
var curPath = path + "/" + file;
if(fs.lstatSync(curPath).isDirectory()) { // recurse
rm(null, curPath);
} else { // delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
};

95
lib/hot.js Normal file
View File

@ -0,0 +1,95 @@
;(function(){
// on fires when shortcut keydowns or on touch after command selected and then touchdown
var m = meta;
m.edit({name: "Add", combo: ['A']});
m.edit({name: "Row", combo: ['A', 'R'],
on: function(eve){
m.tap().append('<div class="hold center" style="min-height: 9em; padding: 2%;">');
}
});
m.edit({name: "Columns", combo: ['A','C'],
on: function(eve){
var on = m.tap(), tmp, c;
var html = '<div class="unit col" style="min-height: 9em; padding: 2%;"></div>';
if(!on.children('.col').length){ html += html }
c = (tmp = on.append(html).children('.col')).length;
tmp.each(function(){
$(this).css('width', (100/c)+'%');
})
}
});
m.edit({name: "Text", combo: ['A','T'],
on: function(eve){
m.tap().append('<p contenteditable="true">Text</p>');
}
});
m.edit({name: "Drag", combo: ['D']});
;(function(){
$(document).on('click', function(){
var tmp = $('.m-on');
if(!tmp.length){ return }
tmp.removeClass('m-on');
})
m.edit({combo: [38], // up
on: function(eve){
var on = m.tap().removeClass('m-on');
on = on.prev().or(on.parent()).or(on);
on.addClass('m-on');
}, up: function(){
}
});
m.edit({combo: [40], // down
on: function(eve){
var on = m.tap().removeClass('m-on');
on = on.next().or(on.children().first()).or(on);
on.addClass('m-on');
}, up: function(){
}
});
m.edit({combo: [39], // right
on: function(eve){
var on = m.tap().removeClass('m-on');
on = on.children().first().or(on.next()).or(on.parent()).or(on);
on.addClass('m-on');
}, up: function(){
}
});
m.edit({combo: [37], // left
on: function(eve){
var on = m.tap().removeClass('m-on');
on = on.parent().or(on);
on.addClass('m-on');
}, up: function(){
}
});
}());
m.edit({name: "Turn", combo: ['T']});
m.edit({name: "Size", combo: ['S']});
m.edit({name: "X", combo: ['S','X'],
on: function(eve){
var on = m.tap(), was = on.width();
$(document).on('mousemove.tmp', function(eve){
var be = was + ((eve.pageX||0) - was);
on.css({'max-width': be, width: '100%'});
})
}, up: function(){ $(document).off('mousemove.tmp') }
});
m.edit({name: "Y", combo: ['S','Y'],
on: function(eve){
var on = m.tap(), was = on.height();
$(document).on('mousemove.tmp', function(eve){
var be = was + ((eve.pageY||0) - was);
on.css({'min-height': be});
})
}, up: function(){ $(document).off('mousemove.tmp') }
});
m.edit({name: "Fill", combo: ['F'],
on: function(eve){
var on = m.tap();
m.ask('Color name, code, or URL?', function(color){
var css = on.closest('p').length? 'color' : 'background';
on.css(css, color);
});
}
});
}());

131
lib/hub.js Normal file
View File

@ -0,0 +1,131 @@
const fs = require('fs');
const Gun = require('../index.js');
const gun = Gun();
let chokidar;
try { chokidar = require('chokidar') } catch (error) {
} // Must install chokidar to use this feature.
/**
* Watches a directory and send all its content in the database
* @constructor
* @param {string} what - Which directory hub should watch.
* @param {Object} options - https://gun.eco/docs/hub.js#options
*/
function watch(what, options) {
options = options ?? { msg: true, hubignore: false, alias: require('os').userInfo().username }
options.msg = options.msg ?? true;
options.hubignore = options.hubignore ?? false;
options.alias = options.alias ?? require('os').userInfo().username
let modifiedPath = options.alias;
let watcher;
try {
if (options.hubignore) {
watcher = chokidar.watch(what, {
persistent: true
});
} else if (!options.hubignore) {
watcher = chokidar.watch(what, {
ignored: /(^|[\/\\])\../, // ignore dotfiles
persistent: true
});
}
const log = console.log.bind(console);
let hubignore;
// Handle events !
watcher
.on('add', async function(path) {
if (options.hubignore && path.includes('.hubignore')) {
hubignore = fs.readFileSync(what + '/.hubignore', 'utf-8');
} else if (!path.includes('.hubignore') && !hubignore?.includes(path.substring(path.lastIndexOf("/") + 1))) {
if (options.msg) log(`File ${path} has been added`);
if(path[path.search(/^./gm)] === "/" || ".") {
gun.get('hub').get(modifiedPath + path.split(require('os').userInfo().username)[1]).put(fs.readFileSync(path, 'utf-8'))
} else {
gun.get('hub').get(modifiedPath + '/' + path.split(require('os').userInfo().username)[1]).put(fs.readFileSync(path, 'utf-8'))
}
} else {
if(options.msg) log(`The addition of ${path} has been ignored !`)
}
})
.on('change', async function(path) {
if (options.hubignore && path.includes('.hubignore')) {
hubignore = fs.readFileSync(what + '/.hubignore', 'utf-8');
} else if (!path.includes('.hubignore') && !hubignore?.includes(path.substring(path.lastIndexOf('/') + 1))) {
if (options.msg) log(`File ${path} has been changed`);
if(path[path.search(/^./gm)] === "/" || ".") {
gun.get('hub').get(modifiedPath + path.split(require('os').userInfo().username)[1]).put(fs.readFileSync(path, 'utf-8'))
} else {
gun.get('hub').get(modifiedPath + '/' + path.split(require('os').userInfo().username)[1]).put(fs.readFileSync(path, 'utf-8'))
}
} else {
if(options.msg) log(`The changes on ${path} has been ignored.`)
}
})
.on('unlink', async function (path) {
if (options.hubignore && path.includes('.hubignore')) {
hubignore = fs.readFileSync(what + '/.hubignore', 'utf-8');
} else if (!path.includes('.hubignore') && !hubignore?.includes(path.substring(path.lastIndexOf('/') + 1))) {
if(options.msg) log(`File ${path} has been removed`);
if(path[path.search(/^./gm)] === "/" || ".") {
gun.get('hub').get(modifiedPath + path.split(require('os').userInfo().username)[1]).put(null)
} else {
gun.get('hub').get(modifiedPath + '/' + path.split(require('os').userInfo().username)[1]).put(null)
}
} else {
if(options.msg) log(`The deletion of ${path} has been ignored!`)
}
})
if (options.msg) {
watcher
.on('addDir', path => log(`Directory ${path} has been added`))
.on('unlinkDir', path => log(`Directory ${path} has been removed`))
.on('error', error => log(`Watcher error: ${error}`))
.on('ready', () => log('Initial scan complete. Ready for changes'))
}
} catch (err) {
console.log('If you want to use the hub feature, you must install `chokidar` by typing `npm i chokidar` in your terminal.')
}
}
module.exports = { watch : watch }

46
lib/ipfs.js Normal file
View File

@ -0,0 +1,46 @@
console.log("IPFS PLUGIN NOT OFFICIALLY MAINTAINED! PROBABLY WON'T WORK! USE AT YOUR OWN RISK! PLEASE CONTRIBUTE FIXES!");
var opt = gun._.opt, u;
if (u === opt.ipfs.directory) {
opt.ipfs.directory = '/gun';
}
opt.store = {};
opt.store.put = function(file, data, cb){
var uri = opt.ipfs.directory + '/' + file;
opt.ipfs.instance.files.write(uri, Buffer.from(JSON.stringify(data)), {create:true})
.then(res => {
console.log('File written to IPFS directory', uri, res);
return opt.ipfs.instance.files.stat(opt.ipfs.directory, {hash:true});
}).then(res => {
console.log('Directory hash:', res.hash);
return opt.ipfs.instance.name.publish(res.hash);
// currently throws "This command must be run in online mode. Try running 'ipfs daemon' first." for some reason, maybe js-ipfs IPNS not ready yet
}).then(res => {
console.log('IPFS put request successful:', res);
cb(undefined, 1);
}).catch(error => {
console.error('IPFS put request failed', error);
});
}
opt.store.get = function(file, cb){
var uri = opt.ipfs.directory + '/' + file;
opt.ipfs.instance.files.read(uri, {})
.then(res => {
var data = JSON.parse(res.toString());
console.log(uri + ' was loaded from ipfs:', data);
cb(data);
});
}
opt.store.list = function(cb){
var stream = opt.ipfs.files.lsReadableStream(opt.ipfs.directory);
stream.on('data', (file) => {
console.log('ls', file.name);
if (cb(file.name)) {
stream.destroy();
}
});
stream.on('finish', () => {
cb();
});
}

703
lib/ison.js Normal file
View File

@ -0,0 +1,703 @@
/* **************************************************************************
* A modified version of yieldable-json package that's backwards compatible
* with GunDB's YSON implementation
*
* (c) Copyright IBM Corp. 2017
*
* This program and the accompanying materials are made available
* under the terms of the Apache License v2.0 which accompanies
* this distribution.
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* Contributors:
* Multiple authors (IBM Corp.) - initial implementation and documentation
* **************************************************************************/
;(function () {
var yson = {}, u;
let counter = 0;
let objStack = [];
let temp = '';
const limit = 100000;
function StringifyError(m) {
this.name = 'Error';
this.message = m;
}
/**
* Checking for unicode and backslash characters and replaces if any.
* @param { string }
* @return { string }
*/
let normalize = (string, flagN) => {
let retStr = '';
let transform = '';
let uc =
'/[\\\'\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4' +
'\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g';
let unicode = new RegExp(uc);
// Taking '\\' out of the loop to avoid change in
// order of execution of object entries resulting
// in unwanted side effect
string = string.replace(/\\/gi, '\\\\');
let escape = {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"': '\\"',
};
// Escape is implemented globally
for(var pattern in escape) {
var regex = new RegExp(pattern,'gi')
string = string.replace(regex, escape[pattern])
}
unicode.lastIndex = 0;
if (unicode.test(string)) {
// Unicode logic here
transform = string.replace(unicode, (a) => {
return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
if (flagN === 1) {
transform += temp;
transform += transform;
temp = '';
return '"' + transform + '"';
} else if (flagN === 2) {
return '"' + transform + '"';
} else {
temp += transform;
}
} else {
if (flagN === 1) {
retStr += temp;
retStr += string;
temp = '';
return '"' + retStr + '"';
} else if (flagN === 2) {
return '"' + string + '"';
} else {
temp += string;
return;
}
}
};
/**
* Obtain stringified value by yielding at required intensity
* @param { string} field
* @param { primitive data type } container
* @param { function or array } replacer
* @param { number or string } space
* @param { number } intensity
* @return { function } yieldCPU
*/
function * stringifyYield(field, container, replacer, space, intensity) {
let itr = 0;
let key = '';
let val = '';
let length = 0;
let tempVal = '';
let result = '';
let value = container[field];
// Made scope local handling async issues
let flag1 = 0;
let returnStr = '';
let subStr = '';
let len = 0;
// Yield the stringification at definite intervals
if (++counter > 512 * intensity) {
counter = 0;
yield val;
}
// Call replacer if one is present (SPEC)
if (typeof replacer === 'function') {
value = replacer.call(container, field, value);
}
switch (typeof value) {
case 'string':
if (value.length > limit) {
for (let l = 0; l < value.length; l += limit) {
flag1 = 0;
yield value;
subStr = value.substr(l, limit);
len += subStr.length;
if (len === value.length)
flag1 = 1;
returnStr = normalize(subStr, flag1);
}
} else
returnStr = normalize(value, 2);
return returnStr;
case 'number':
return isFinite(value)
? String(value)
: 'null';
case 'boolean':
case 'null':
return String(value);
case 'undefined':
return;
case 'function':
return 'null';
case 'object':
if (!value)
return 'null';
// Manage special cases of Arrays and Objects
let getResult = (decision) => {
if (result.length === 0)
if (decision)
return '{}';
else
return '[]';
else
if (decision)
if (space)
return '{\n' + space + result.join(',\n' + space) + '\n' + '}';
else
return '{' + result.join(',') + '}';
else
if (space)
return '[\n' + space + result.join(',\n' + space) + '\n' + ']';
else
return '[' + result.join(',') + ']';
};
result = [];
// If toJSON is present, invoke it (SPEC)
if (value && typeof value.toJSON === 'function') {
const response = value.toJSON(field);
if (response === undefined) {
return undefined;
}
if (typeof response === "number") {
result.push(value.toJSON(field));
} else {
result.push('"' + value.toJSON(field) + '"');
}
if (result.length === 0)
return '{}';
else
if (space)
return space + result.join(',\n' + space) + '\n';
else
return result.join(',');
}
// Array case
if (value && value.constructor === Array) {
length = value.length;
for (itr = 0; itr < length; itr += 1) {
tempVal =
yield *stringifyYield(itr, value, replacer, space, intensity) ||
'null';
if (tempVal !== undefined)
result.push(tempVal);
}
return getResult(false);
}
// Manage replacing object scenario (SPEC)
if (replacer && typeof replacer === 'object') {
length = replacer.length;
for (itr = 0; itr < length; itr += 1) {
if (typeof replacer[itr] === 'string') {
key = replacer[itr];
val = yield *stringifyYield(key, value, replacer, space, intensity);
if (val !== undefined)
result.push(normalize(key, 2) + (space
? ': '
: ':') + val);
}
}
} else {
// Object case
objStack.push(value);
for (key in value) {
if (typeof value[key] === 'object' && value[key] !== null &&
value[key] !== undefined) {
if (objStack.indexOf(value[key]) !== -1) {
return new StringifyError('Circular Structure Detected');
} else
objStack.push(value[key]);
}
if (Object.hasOwnProperty.call(value, key)) {
val = yield *stringifyYield(key, value, replacer, space, intensity);
if (val !== undefined)
result.push(normalize(key, 2) + (space
? ': '
: ':') + val);
}
objStack = objStack.filter((v, i, a) => { return v !== value[key] });
}
objStack = objStack.filter((v, i, a) => { return v !== value });
}
return getResult(true);
default:
return new StringifyError('Unexpected Character');
}
}
/**
* Calling appropriate functions each time.
* @param { primitive data types } value
* @param { function or array } replacer
* @param { number or string } space
* @param { number } intensity
* @param { function } callback
* @return { function } yieldCPU
*/
let stringifyWrapper = (value, replacer, space, intensity, callback) => {
let indent = '';
if (typeof space === 'number') {
indent = ' '.repeat(space);
} else if (typeof space === 'string') {
indent = space;
}
let yielding;
// To hold 'stringifyYield' genarator function
function * yieldBridge() {
yielding = yield *stringifyYield('', {'': value}, replacer, indent, 1);
}
let rs = yieldBridge();
let g = rs.next();
let yieldCPU = () => {
setTimeout(() => {
g = rs.next();
if (g && g.done === true) {
// Reinitializing the values at the end of API call
counter = 0;
temp = ''
objStack = [];
if (typeof yielding === 'object')
return callback(yielding, null);
else
return callback(null, yielding);
}
yieldCPU();
}, 0);
};
return yieldCPU();
};
/**
* This method parses a JSON text to produce an object or array.
* It can throw a SyntaxError exception, if the string is malformed.
* @param { string } text
* @param { function or array } reviver
* @param { number } intensity
* @param { function } cb
* @return { function } yieldCPU
*/
let parseWrapper = (text, reviver, intensity, cb) => {
let counter = 0;
let keyN = 0;
let parseStr = text;
let at = 0;
let ch = ' ';
let word = '';
function ParseError(m) {
this.name = 'ParseError';
this.message = m;
this.text = parseStr;
}
// Seek to the next character, after skipping white spaces, if any.
let seek = () => {
ch = parseStr.charAt && parseStr.charAt(at);
at++;
while (ch && ch <= ' ') {
seek();
}
return ch;
};
// Seek to the previous character, required in some special cases.
let unseek = () => {
ch = parseStr.charAt(--at);
};
// Match 'true', 'false' and 'null' built-ins.
let wordCheck = () => {
word = '';
do {
word += ch;
seek();
} while (ch.match(/[a-z]/i));
parseStr = parseStr.slice(at - 1);
at = 0;
return word;
};
// Process strings specially.
let normalizeUnicodedString = () => {
let inQuotes = ' ';
let tempIndex = at;
let index = 0;
let slash = 0;
let c = '"';
while (c) {
index = parseStr.indexOf('"', tempIndex + 1);
tempIndex = index;
ch = parseStr.charAt(tempIndex - 1);
while (ch === '\\') {
slash++;
ch = parseStr.charAt(tempIndex - (slash + 1));
}
if (slash % 2 === 0) {
inQuotes = parseStr.substring(at, index);
parseStr = parseStr.slice(++index);
slash = 0;
break;
} else
slash = 0;
}
// When parsing string values, look for " and \ characters.
index = inQuotes.indexOf('\\');
while (index >= 0) {
let escapee = {
'"': '"',
'\'': '\'',
'/': '/',
'\\': '\\',
b: '\b',
f: '\f',
n: '\n',
r: '\r',
t: '\t',
};
let hex = 0;
let i = 0;
let uffff = 0;
at = index;
ch = inQuotes.charAt(++at);
if (ch === 'u') {
uffff = 0;
for (i = 0; i < 4; i += 1) {
hex = parseInt(ch = inQuotes.charAt(++at), 16);
if (!isFinite(hex)) {
break;
}
uffff = uffff * 16 + hex;
}
inQuotes = inQuotes.slice(0, index) +
String.fromCharCode(uffff) + inQuotes.slice(index + 6);
at = index;
} else if (typeof escapee[ch] === 'string') {
inQuotes = inQuotes.slice(0, index) +
escapee[ch] + inQuotes.slice(index + 2);
at = index + 1;
} else
break;
index = inQuotes.indexOf('\\', at);
}
at = 0;
return inQuotes;
};
/**
* This function parses the current string and returns the JavaScript
* Object, through recursive method, and yielding back occasionally
* based on the intensity parameter.
* @return { object } returnObj
*/
function * parseYield() {
let key = '';
let returnObj = {};
let returnArr = [];
let v = '';
let inQuotes = '';
let num = 0;
let numHolder = '';
let addup = () => {
numHolder += ch;
seek();
};
// Handle premitive types. eg: JSON.parse(21)
if (typeof parseStr === 'number' || typeof parseStr === 'boolean' || typeof parseStr === "function" ||
parseStr === null) {
parseStr = '';
return text;
} else if (typeof parseStr === 'undefined') {
parseStr = undefined;
return text;
} else if (parseStr.charAt && parseStr.charAt(0) === '[' && parseStr.charAt(1) === ']') {
parseStr = '';
return [];
} else if (parseStr.charAt && parseStr.charAt(0) === '{' && parseStr.charAt(1) === '}') {
parseStr = '';
return {};
} else {
// Yield the parsing work at specified intervals.
if (++counter > 512 * intensity) {
counter = 0;
yield;
}
// Common case: non-premitive types.
if (keyN !== 1)
seek();
switch (ch) {
case '{':
// Object case
seek();
if (ch === '}') {
parseStr = parseStr.slice(at);
at = 0;
return returnObj;
}
do {
if (ch !== '"')
seek();
keyN = 1;
key = yield *parseYield();
keyN = 0;
seek();
returnObj[key] = yield *parseYield();
seek();
if (ch === '}') {
parseStr = parseStr.slice(at);
at = 0;
return returnObj;
}
} while (ch === ',');
return new ParseError('Bad object');
case '[':
// Array case
seek();
if (ch === ']') {
parseStr = parseStr.slice(at);
at = 0;
return returnArr;
}
unseek();
do {
v = yield *parseYield();
returnArr.push(v);
seek();
if (ch === ']') {
parseStr = parseStr.slice(at);
at = 0;
return returnArr;
}
} while (ch === ',');
return new ParseError('Bad array');
case '"':
parseStr = parseStr.slice(at - 1);
at = 0;
if (parseStr.charAt(0) === '"' && parseStr.charAt(1) === '"') {
parseStr = parseStr.slice(2);
at = 0;
return inQuotes;
} else {
seek();
return normalizeUnicodedString();
}
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
if (ch === '-') addup();
do {
addup();
if (ch === '.' || ch === 'e' || ch === 'E' ||
ch === '-' || ch === '+' ||
(ch >= String.fromCharCode(65) &&
ch <= String.fromCharCode(70)))
addup();
} while (ch === '-' || ch === '+' || (isFinite(ch) && ch !== ''));
num = Number(numHolder);
parseStr = parseStr.slice(at - 1);
at = 0;
return num;
case 't':
word = wordCheck();
if (word === 'true')
return true;
else return new ParseError('Unexpected character');
case 'f':
word = wordCheck();
if (word === 'false')
return false;
else return new ParseError('Unexpected character');
case 'n':
word = wordCheck();
if (word === 'null')
return null;
else return new ParseError('Unexpected character');
default:
return new ParseError('Unexpected character');
}
}
}
/**
* If there is a reviver function, we recursively walk the new structure,
* passing each name/value pair to the reviver function for possible
* transformation, starting with a temporary root object that holds the result
* in an empty key. If there is not a reviver function, we simply return the
* result.
* @param { object } yieldedObject
* @param { string } key
* @return { function } reviver
*/
let revive = (yieldedObject, key) => {
let k = '';
let v = '';
let val = yieldedObject[key];
if (val && typeof val === 'object') {
for (k in val) {
if (Object.prototype.hasOwnProperty.call(val, k)) {
v = revive(val, k);
if (v !== undefined)
val[k] = v;
else
delete val[k];
}
}
}
return reviver.call(yieldedObject, key, val);
};
let yielding = '';
// To hold 'parseYield' genarator function
function * yieldBridge() {
yielding = yield* parseYield();
}
let rs = yieldBridge();
let gen = rs.next();
// Main yield control logic.
let yieldCPU = () => {
setTimeout(() => {
gen = rs.next();
if (gen && gen.done === true) {
let isEmpty = (value) => {
if (value.charAt(0) === '}' || value.charAt(0) === ']')
value = value.substring(1, value.length);
return typeof value === 'string' && !value.trim();
};
if (typeof yielding === 'undefined')
return cb(new ParseError('Unexpected Character'), null);
else if (yielding instanceof ParseError)
return cb(yielding, null);
else if (!isEmpty(parseStr))
return cb(new ParseError('Unexpected Character'), null);
else {
if (reviver !== null) {
if (typeof reviver === 'function') {
let result = revive({'': yielding}, '');
return cb(null, result);
}
} else
return cb(null, yielding);
}
}
yieldCPU();
}), 0;
};
return yieldCPU();
};
/**
* Checks whether the provided space
* @param { string or number } space
* @return { string or number }
*/
let validateSpace = (space) => {
if (typeof space === 'number') {
space = Math.round(space);
if (space >= 1 && space <= 10)
return space;
else if (space < 1)
return 0;
else
return 10;
} else {
if (space.length <= 10)
return space;
else
return space.substr(0, 9);
}
};
/**
* Checks whether the provided intensity
* @param { number } intensity
* @return { number }
*/
let validateIntensity = (intensity) => {
intensity = Math.round(intensity);
if (intensity > 0 && intensity <= 32)
return intensity;
else if (intensity <= 0)
return 1;
else
return 32;
};
yson.parseAsync = function (data, callback, reviver = null, intensity = 1) {
//Bring parity with the in-built parser, that takes both string and buffer
if (Buffer.isBuffer(data))
data = data.toString();
if (!callback)
throw new Error('Missing Callback');
intensity = validateIntensity(intensity);
return parseWrapper(data, reviver, intensity, callback);
};
/**
* Error checking and call of appropriate functions for JSON stringify API
* @param { primitive data types } data
* @param { function or array } replacer
* @param { number or string } space
* @param { number } intensity
* @param { function } callback
* @return { function } stringifyWrapper
*/
yson.stringifyAsync = function(data, callback, replacer = null, space, intensity = 1) {
if (typeof callback !== 'function') {
throw new TypeError('Callback is not a function');
}
if (typeof space === 'number' || typeof space === 'string')
space = validateSpace(space);
if (typeof intensity === 'number')
intensity = validateIntensity(intensity);
return stringifyWrapper(data, replacer, space, intensity, callback);
}
if(typeof window != ''+u){ window.YSON = yson }
try{ if(typeof module != ''+u){ module.exports = yson } }catch(e){}
if(typeof JSON != ''+u){
JSON.parseAsync = yson.parseAsync;
JSON.stringifyAsync = yson.stringifyAsync;
}
}());

Some files were not shown because too many files have changed in this diff Show More