From ddd5c1908a16bc35ea9d4dcdf0f0f7a659874df8 Mon Sep 17 00:00:00 2001 From: David Dias Date: Sun, 11 Dec 2016 17:00:47 -0800 Subject: [PATCH 01/18] Initial commit --- .gitignore | 37 +++++++++++++++++++++++++++++++++++++ LICENSE | 21 +++++++++++++++++++++ README.md | 2 ++ 3 files changed, 60 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5148e52 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7789aab --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 libp2p + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..61acb44 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# interface-peer-discovery +A test suite and interface you can use to implement a peer-discovery. From bc27eb99b77c3a63dda14efaf5056a096f1c560e Mon Sep 17 00:00:00 2001 From: David Dias Date: Sat, 28 Jan 2017 20:28:37 +0000 Subject: [PATCH 02/18] docs: Initial spec --- .travis.yml | 38 +++++++++++++++++++++++ README.md | 77 +++++++++++++++++++++++++++++++++++++++++++++-- circle.yml | 12 ++++++++ img/badge.png | Bin 0 -> 6165 bytes img/badge.sketch | Bin 0 -> 106496 bytes img/badge.svg | 39 ++++++++++++++++++++++++ package.json | 42 ++++++++++++++++++++++++++ test/index.js | 1 + 8 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 .travis.yml create mode 100644 circle.yml create mode 100644 img/badge.png create mode 100644 img/badge.sketch create mode 100644 img/badge.svg create mode 100644 package.json create mode 100644 test/index.js diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..9d678dd --- /dev/null +++ b/.travis.yml @@ -0,0 +1,38 @@ +sudo: false +language: node_js + +matrix: + include: + - node_js: 4 + env: CXX=g++-4.8 + - node_js: 6 + env: + - SAUCE=true + - CXX=g++-4.8 + - node_js: stable + env: CXX=g++-4.8 + +# Make sure we have new NPM. +before_install: + - npm install -g npm + +script: + - npm run lint + - npm test + - npm run coverage + - make test + +before_script: + - export DISPLAY=:99.0 + - sh -e /etc/init.d/xvfb start + +after_success: + - npm run coverage-publish + +addons: + firefox: 'latest' + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 diff --git a/README.md b/README.md index 61acb44..4541803 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,75 @@ -# interface-peer-discovery -A test suite and interface you can use to implement a peer-discovery. +interface-peer-discovery +======================== + +[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) +[![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/) +[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) +[![Travis CI](https://travis-ci.org/ipfs/interface-peer-discovery.svg?branch=master)](https://travis-ci.org/ipfs/interface-peer-discovery) +[![Dependency Status](https://david-dm.org/ipfs/interface-peer-discovery.svg?style=flat-square)](https://david-dm.org/ipfs/interface-peer-discovery) +[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard) + +> A test suite and interface you can use to implement a peer discovery mechanism. + +The primary goal of this module is to enable developers to pick and swap their stream muxing module as they see fit for their application, without having to go through shims or compatibility issues. This module and test suite was heavily inspired by [abstract-blob-store](https://github.com/maxogden/abstract-blob-store). + +Publishing a test suite as a module lets multiple modules all ensure compatibility since they use the same test suite. + +The API is presented with both Node.js and Go primitives, however, there is not actual limitations for it to be extended for any other language, pushing forward the cross compatibility and interop through diferent stacks. + +## Modules that implement the interface + +- [JavaScript libp2p-mdns](https://github.com/libp2p/js-libp2p-mdns) +- [JavaScript libp2p-railing](https://github.com/libp2p/js-libp2p-railing) + +Send a PR to add a new one if you happen to find or write one. + +## Badge + +Include this badge in your readme if you make a new module that uses interface-peer-discovery API. + +![](/img/badge.png) + +## Usage + +### Node.js + +Install `interface-peer-discovery` as one of the dependencies of your project and as a test file. Then, using `mocha` (for JavaScript) or a test runner with compatible API, do: + +```js +const test = require('interface-peer-discovery') + +const common = { + setup (cb) { + cb(null, yourMuxer) + }, + teardown (cb) { + cb() + } +} + +// use all of the test suits +test(common) +``` + +### Go + +> WIP + +## API + +A valid (read: that follows this abstraction) stream muxer, must implement the following API. + +### `start` the service + +- `JavaScript` discovery.start(callback) +- `Go` NA + +### `stop` the service + +- `JavaScript` discovery.stop(callback) +- `Go` NA + +### discoverying peers + +- `JavaScript` discovery.on('peer', function (peerInfo) {}) +- `Go` NA diff --git a/circle.yml b/circle.yml new file mode 100644 index 0000000..434211a --- /dev/null +++ b/circle.yml @@ -0,0 +1,12 @@ +machine: + node: + version: stable + +dependencies: + pre: + - google-chrome --version + - wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - + - sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' + - sudo apt-get update + - sudo apt-get --only-upgrade install google-chrome-stable + - google-chrome --version diff --git a/img/badge.png b/img/badge.png new file mode 100644 index 0000000000000000000000000000000000000000..785abc493c3b0906e47b1690ffcdcadd588fa96e GIT binary patch literal 6165 zcmb7I^;Z;37p7BM7HL=-mXHpSE@=trkZur`?(hYcURtF=T4Ir0O1e8$O1fiNns5Jw z?}s~c&OK*lZp^*+IZvF9mI@I84FMV&8j+f+;(OFygAz$R9Msx7w%mf+(7oTQ$fMOx z(Cwq4QBA5T%IW)~AAiO5q?|_%@<+&GFkg{7m+&anFXqFMwZ%#B!vyShndh)oBW3#g zrJz&Eg?g&C83QKPLaewH(m)!|uwC!okfYUReh*9FJI_hdzbAhi{3i2)CXgthq0sG% zU>}IEryX$lveZ(%@f0L61=?D>KbnS$84$zHh<~rBZUo+v(R;k5b6gmUz_0;ow%>MS zIkGZKkm9?kDl5&4G7>AwqjZq}OSk*Il&Ev1;o_5?KzsL#S5s>~$15TW1_lNhw_C|F zV-0qrnqR((mZ@0eIj#P5tA4ZGbB8z_&kuWYA|N0bCzf*eSb@2Jt9JekUa2u|8~|B% znuWQzxDY+HEx4^@6CbZ0!r@O+9yTk6`uf=t-tiju*R2;IOpVK(akxRz7W+s9R-qE! zCnZuT-y^G?@h|*c^qLR=c)p>bK_mZdh^CfSt1-+mm5Yy0)LgN=-S4ohH$4GYL_~z! zzqM6@3p-P-(f8Qo+bbSJkeGqNe3`Mb&}^jv&upu?)U4K%cy02Y4dP&4u(P!cd=&lf3q^SZFC)Y@*y>v8v*8W=mZ zsed~&H8USk1ox;L0a)QcjrT>esJyvlV(AjaH#?`!lWH8mkw3=`1kQ?cFc^kgRMr z^~~7rn%4mVe+-25PVj14gKr6oL6-IJqumk#4i0vseS21)yuHB~ z0jnjF%Imx1`9C6M9H(Td9q3=)K3q<2khYLA?_cB!mnd_6j zlGcKPGnOnE3h&;%!;;}Qe3R4^4tpjdRpEENAsIdU2i49Mnh^gL6ab~?pvBz^e!ATq z-}sNQ7MUmNmb>h`>Nc*z7-F0B=3+=wG_P!~UWJT3`J#w?1qNB4mw7UBB#mW~Z|R0V z-nrSW5dH=6n0_RH#Ontw#_?@z{_x#>%$oka_;V?HOc=KebIPvGOr^a#q7_nw@OP4~= zP!`9!97=m_?SblCe!#B<8AERhYjICncNuC1Fpzb>h=nNFHKx4Zh@xT&({f~*tsi9I z87TxUY#%K*jx+y92Q;jN?=LrgZ#`){oNH?#U<^KskSBU0?Rd6m5j0M@UxIM<2CXMa zojB%&-Z|C$YA@<~8*;aI-?kag^O3;y?rPt@{rIQQm3Eg=yhDD7;ScL`I`gnc#Lkog z3HW>1GJlIKsT|PY!-rJ~?;RsD*-hx=8JE@SIY@}|?hcfq@PLGINWfX}|CaO6)xW1kLS zhp3FqT72EoY3DuaqD6DV>cq#ZS?wmx%8RPnwvqTLBQlzxRk!Bl3cc?GC)>o40~;fX zhpX1VKJRn61u$ZeTs^>MwHkrK*Qj@zJm82-N+TO>nMWU9Xn)oC=xAfmN$dAanX_(8 z$rGuQ7KPES+a20tbx?e!Wx#euAYWwJcCySPI@@?P zbu$-0Xe#Z0eitomxQxMd1aEdj3#AcrdWin6n@xzJS)w7V+PuTRUNmICH0!Ff$j$u2 zb?a_k3j9X``XE1~{S=^x-fln|-NQc49+t1CkPZ|Zt0<9#mr!^CRuB#x(M4y`> zvLik8y++8X1>DE(D@zrUI5I%W_kfeILB1#V+x&wlRu?jN$e$lFaWG=>+{g5njU z<4w>kyKX4yUrZ*nDnC35!WX@^Qsfide_!Zn(Ocmn9r3KSUiZkcQm9kaQki*1kd2pG zkgUhzwaL>yEV$;0lWXn~$LxB~`3&+6p|d|WPQIO0KSQ78&DFQ=9%Kxw?s^FrUQuMv z-RQImQ#r#P+Eir^mzrB^oRAzH>YJ;FKVGle-<)mW+r+x0?5M%B7Z5QVXnvG$S7Hdo zh!-;M!vby(7k>z`D8Hae@NZcT>v~MDFx%a(BQy0ala<5(GsRa4g?a9gHp^{kIVd(Pzw_wOJ5ztjeB#J+1?(UHJ%ekhGi zkKeE=gO=AJ>id^;{SCBQ#wG+T?aw+aRm_&{dl}$;JvxrEIkz1$ia*|)wy9}ZdFaRA zMda9hFa{VK3YYeeLDr1cr^H2u8)B!pD@L3+EM6{}um7MO481>gP{ORB9)v~e_LOdK zZ?8;{kUU-HKQCFp1Gy~vY;Ah`fkx}8cm+wOu)>c)b>FEVqmepmyzCZO6Oym4P@Q{l zVCX&_J1;3eC;3g6PBX3 z>?rDgLcQu?XXqIHq4ICf2O)=vwC)VEKcQC(xTj;e=2j*S4%Br2tnngvd3eMG`d1Kb zstW$bbN+Ezy}q8hx`iOD#r10g@%6`5Neoh)F9?iSUWpUEQ-GIl0s-69sPpE4ZhjLY1#Oy~X0ICc!^=4dLH zJfdia=Sl7%DKjKh*SWbXL?o``@1{>OfUs;hYIIcY6R$exdyKA!f0z|jHMfJ@a(o6H zEjBuk^s7R$(&Hoq)S7jE)e#rk@{qe}b)0xKP?~Xu4r~jmHJCODN}YD-vDR6?YK>WR zN}2kYOU75n8L|0I%1>~coO8C>Bfn$^O=Cnp9vhve$=9vM*tFeHfudDe;x+6Ld$H)L zLgDeY;ikOCnCBcOQPxoTi7=@sgQxI{lRgqKUbLy2$RlWVsS=edI%{ZKwtYmSS+SjV@TR=h@6#QS);!+Z6Hg++bS&9r=- zLgforF0EsCzPB~=I&Z1#e)y+9CU(p_u%;>scxM;~E)56p2bC`{Y?+S!XOLvPvYR52i+ z4nlQuSC-ez#lH+m%(dCWM>r{%kH@i3kF3G`g;?Y}i@KV=Qp=INnY?BmeW}f%OEzh& zRQ!BG(yRoGM~6f0^$`HA|M*(}kw-10pry3fm%LP4_nArm!ryt*OXo8sM^mJ#nvZ2L z*o4e0=x3W6sB^BF z^>^T54Y`__d?UF(AF%(SZ-F0~`O373^Iy?z+#j9+dPUcq;!?H8o&&OLRaP^>G;#b! z)F|Y5iOI2nnM33H);##UKQ}m6=XD|>(F_duwel7K;+&?|qXMzyB6lrWTkP%jjQ`cd zX0oZ;Bw+Pn*@=^;D(Xuknf%#bq|Vo^y0^zv(0tfM0h!r^@R^zSL}O&=KhwDLN#Q#* zYJ0`X2ntm`LWA~MEh#5~gntoEl)yT?Bzzzl-?&!Flp3L>llFCV$upKgbMl*uSZNeO z5#CHBur;C!dpO4jD;WvjLBeVMIZpbcC4m~(+gX-cEqt#Vb1OWNfBX*p{rQT9Ss&R8 z`Ka)MKlQ9V5nyyxLqJ=%Lme$BCm-k2@*to=;Tq^64n8jz&(>gaR+bT!(j@)s4Ml&= z9Km^D-#&Q`-WG?3ehb;0A*{V4njnIBs~U?7*FddBSv+s-DEbg#ZY588t{s??l_Ysk zE-N(Jg8!OTe~L`kZqdv;QEHx4x&bFL_A1Ld&3)@zEFN_QH(p+Tp8qC3L`Nbm+e|$Z zbvlVO*Ov9xj>c`5-$8?%iNTNB5yvu86=SHzC@UJs&bv%yfsvE~e3{uH-#&dUd9Jzj z!JV_|u=8m%myGoHhq*9a>(tN4 z*Bn)GNNhi0*}JEx4od;|XUYCD0|tl+m2FIXf0{I{WUE0)GW0JV9y%{PtMom|1_boE z_JwR8cff~vq}$tW$vidcS+z7)dLZ2!tHZn4mo%N86p8{Q9j0RFVhig^Y3!RE?{!#l z7Q&WecXY-M2zD;b?%y?;n;jA=+m#GVI^GF+Zn>iWoTt3?JGyt5<^~*<;Xy zNAMUO`x^)z2O=yvA6T%Gl)y+f!F2QIdVy_}C7z^p4yaiJ_k;W9kL;tik zh%d=$>^J-3az7r!CthQ4`SbZMJMsVUpy|0HjBt?+@-VMe-*K}#5aBoVEaU6L8mz3N z(9Nj!==@F!6W?SgS;lJG3OTQS!e_yU=GJPN^6Ta+(dI5`x5#OWZ(y-dx7T-}pr%W0 zZkK!Zr82&on_Hr5`-pEfUPbHcw#(z>&9o=1dzYk{1U%f6kgln%gvzle(hdJNvbVvA3T}~ zy_A?@NE^#Rq2UZdSvY+|+}pHhLEFAV9BX=wQ@%yr{o@!}-*)G3(t-E`4uv{}vC~U{ zStTWVyAqK-B-ETLUpCLrwBL-}*hjUjitA%c{0_bxublhcD@7Q5W6BRKWQU`%@T`umg0TGp} z!0TqYVhi78J8t3icbi}`)okkMUC)@|O*u_w#zxs#Pvha!5l8eRNyoPY$G+zn_ zqVhrU04*8o12!s6=&RuYyN8ywrSR_fySO{f|CoTQS@*@PH!mqOQ(Zq=Styh*e^#z8 z--PK@P6&sX{*3W%Y9)ujlvlj!yQ$#_1#rMyK%9wTaBa1 zsk7Mfcw>Xf{%)EPHWd}63sVBct5w4SeLamuW`jb(B)-8q3wjjpGTH zVNj*_mI%%lFMlYJ7JiEocF{4fJx8dH{Vih^J~qCnL5roU6~KC?BdK6yt*&LnikajR zNw1T95Xq$BxjK0w0<3@uNGjQCMW^*!Cg5G!*lz{I9JC6bQnz9xl=L#QGSp>`(*yx2 z$)8L3mME>+u6@5@9n1}R*+Vp-JQ6M$4Nx5KUmC2ZOHcbYbv9ENJNXQYJAuzQzc6P$ z+K+Qjc`7zg^^*3gxVolR3z`xD7?{cuLyf=<$7)s*;Hgeog2>J)?kbH$&`sj;x*lg^_^Jg zf3Y$Ld99XY>uPrS#;T!Eaq)`)?#yRg$EM{-#;)5FsYY0Ej@3vhkd->uE__myl354s zK4$YeThgx5aJSv^$P=96K`jjB-Ps`rO|Y&fXYhCS-U-lt^T!sSe^qo*HXZ?s0k|1* zu?J-YZ+!V9AZVvn-{VuvtVbqaC1H($uG-#1Z^-N4WM|K#mU&c(5zoUqlUX5td&;YA z>S!E7LL)4T(S;-z8*-l2jI2;ecvWVS_VUYI^b`RrsW*v!IUre{zo+kt8s}rliA-gE zsds@KVSQU-49$F6A3f91KDkcOJAla*HkP9^&y!ESSml~Hu|J6a(6baKMnxkQT@LPx zxDsEdTE1ZHI_TcVVuoSj_Vv)9`1M#!GF%|B ds|oP~38n(WUF?sYI~324rlzE&SSxQ8`9H!L2f_dV literal 0 HcmV?d00001 diff --git a/img/badge.sketch b/img/badge.sketch new file mode 100644 index 0000000000000000000000000000000000000000..51a982d06d62a16903e4e3c4283af1479bfb8438 GIT binary patch literal 106496 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 S4jaEosZHNM{jWoE?7sjWaGS0G literal 0 HcmV?d00001 diff --git a/img/badge.svg b/img/badge.svg new file mode 100644 index 0000000..8ecfc6d --- /dev/null +++ b/img/badge.svg @@ -0,0 +1,39 @@ + + + + badge + Created with Sketch. + + + + + + + + + + + + Peer Discovery + + + Compatibl + e + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..28acfea --- /dev/null +++ b/package.json @@ -0,0 +1,42 @@ +{ + "name": "interface-discovery", + "version": "0.0.0", + "description": "A test suite and interface you can use to implement a discovery interface.", + "main": "src/index.js", + "scripts": { + "lint": "aegir-lint", + "build": "aegir-build", + "test": "exit 0", + "release": "aegir-release", + "release-minor": "aegir-release --type minor", + "release-major": "aegir-release --type major" + }, + "pre-commit": [ + "lint", + "test" + ], + "repository": { + "type": "git", + "url": "https://github.com/libp2p/interface-peer-discovery.git" + }, + "keywords": [ + "IPFS" + ], + "author": "David Dias ", + "license": "MIT", + "bugs": { + "url": "https://github.com/libp2p/interface-peer-discovery/issues" + }, + "homepage": "https://github.com/libp2p/interface-peer-discovery", + "dependencies": { + }, + "devDependencies": { + "aegir": "^9.4.0" + }, + "engines": { + "node": ">=4.0.0", + "npm": ">=3.0.0" + }, + "contributors": [ + ] +} diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..ccacec3 --- /dev/null +++ b/test/index.js @@ -0,0 +1 @@ +'use strict' From 02f7a4fc0e07fb33febe196883836511b028c867 Mon Sep 17 00:00:00 2001 From: David Dias Date: Thu, 9 Feb 2017 08:55:04 -0800 Subject: [PATCH 03/18] chore: ^ to ~ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 28acfea..9ca5877 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "dependencies": { }, "devDependencies": { - "aegir": "^9.4.0" + "aegir": "^10.0.0" }, "engines": { "node": ">=4.0.0", From 8ad11e3bb25d49699e6ba9ded48a443765453fea Mon Sep 17 00:00:00 2001 From: David Dias Date: Thu, 9 Feb 2017 08:56:13 -0800 Subject: [PATCH 04/18] chore: update contributors --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 9ca5877..09b3d96 100644 --- a/package.json +++ b/package.json @@ -28,8 +28,7 @@ "url": "https://github.com/libp2p/interface-peer-discovery/issues" }, "homepage": "https://github.com/libp2p/interface-peer-discovery", - "dependencies": { - }, + "dependencies": {}, "devDependencies": { "aegir": "^10.0.0" }, @@ -38,5 +37,6 @@ "npm": ">=3.0.0" }, "contributors": [ + "David Dias " ] -} +} \ No newline at end of file From 1930b29e9752436ae9501f507fe4a118cb5a2404 Mon Sep 17 00:00:00 2001 From: David Dias Date: Thu, 9 Feb 2017 08:56:13 -0800 Subject: [PATCH 05/18] chore: release version v0.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 09b3d96..86bcbb2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "interface-discovery", - "version": "0.0.0", + "version": "0.0.1", "description": "A test suite and interface you can use to implement a discovery interface.", "main": "src/index.js", "scripts": { From 6eeed4cbcbc9bb0ab45b2f18f096704ec064d3b4 Mon Sep 17 00:00:00 2001 From: David Dias Date: Thu, 9 Feb 2017 08:56:37 -0800 Subject: [PATCH 07/18] chore: release version v0.0.2 --- .gitignore | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5148e52..1be92c3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +dist # Logs logs *.log diff --git a/package.json b/package.json index 86bcbb2..18c2060 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "interface-discovery", - "version": "0.0.1", + "version": "0.0.2", "description": "A test suite and interface you can use to implement a discovery interface.", "main": "src/index.js", "scripts": { From 0c841ede8dfacc10b712c6787f28a50dc36db690 Mon Sep 17 00:00:00 2001 From: David Dias Date: Tue, 20 Feb 2018 09:56:48 +0000 Subject: [PATCH 08/18] docs: update and polish the readme --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4541803..a2c27c7 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,11 @@ interface-peer-discovery [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) -[![Travis CI](https://travis-ci.org/ipfs/interface-peer-discovery.svg?branch=master)](https://travis-ci.org/ipfs/interface-peer-discovery) -[![Dependency Status](https://david-dm.org/ipfs/interface-peer-discovery.svg?style=flat-square)](https://david-dm.org/ipfs/interface-peer-discovery) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard) -> A test suite and interface you can use to implement a peer discovery mechanism. +> A test suite and interface you can use to implement a Peer Discovery module for libp2p. -The primary goal of this module is to enable developers to pick and swap their stream muxing module as they see fit for their application, without having to go through shims or compatibility issues. This module and test suite was heavily inspired by [abstract-blob-store](https://github.com/maxogden/abstract-blob-store). +The primary goal of this module is to enable developers to pick and/or swap their Peer Discovery modules as they see fit for their application, without having to go through shims or compatibility issues. This module and test suite was heavily inspired by [abstract-blob-store](https://github.com/maxogden/abstract-blob-store). Publishing a test suite as a module lets multiple modules all ensure compatibility since they use the same test suite. @@ -20,6 +18,9 @@ The API is presented with both Node.js and Go primitives, however, there is not - [JavaScript libp2p-mdns](https://github.com/libp2p/js-libp2p-mdns) - [JavaScript libp2p-railing](https://github.com/libp2p/js-libp2p-railing) +- [JavaScript libp2p-kad-dht](https://github.com/libp2p/js-libp2p-kad-dht) +- [JavaScript libp2p-webrtc-star](https://github.com/libp2p/js-libp2p-webrtc-star) +- [JavaScript libp2p-websocket-star](https://github.com/libp2p/js-libp2p-websocket-star) Send a PR to add a new one if you happen to find or write one. @@ -53,11 +54,11 @@ test(common) ### Go -> WIP +> WIP - go-libp2p does not have a test suite available for Peer Discovery yet. ## API -A valid (read: that follows this abstraction) stream muxer, must implement the following API. +A valid (read: that follows this abstraction) Peer Discovery module must implement the following API: ### `start` the service From 4fba00b7b1e3928ac46644b4959e80a49922cadc Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Wed, 31 Oct 2018 13:36:33 +0000 Subject: [PATCH 09/18] docs: add lead-maintainer --- README.md | 4 ++++ package.json | 1 + 2 files changed, 5 insertions(+) diff --git a/README.md b/README.md index a2c27c7..073adb1 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,10 @@ Publishing a test suite as a module lets multiple modules all ensure compatibili The API is presented with both Node.js and Go primitives, however, there is not actual limitations for it to be extended for any other language, pushing forward the cross compatibility and interop through diferent stacks. +## Lead Maintainer + +[Vasco Santos](https://github.com/vasco-santos). + ## Modules that implement the interface - [JavaScript libp2p-mdns](https://github.com/libp2p/js-libp2p-mdns) diff --git a/package.json b/package.json index 18c2060..1b7f8d9 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "interface-discovery", "version": "0.0.2", "description": "A test suite and interface you can use to implement a discovery interface.", + "leadMaintainer": "Vasco Santos ", "main": "src/index.js", "scripts": { "lint": "aegir-lint", From cf4cbd43b2c71a1b112e87b3f0bcd340b9ae1c79 Mon Sep 17 00:00:00 2001 From: Mike Goelzer Date: Wed, 3 Apr 2019 19:47:27 +0900 Subject: [PATCH 10/18] chore: remove circle ci (#4) See https://github.com/libp2p/team-mgmt/issues/25 Circle CI was deprecate and @jacobheun agreed to remove it from all js repos. This is the only non-JS repo where it still exists. Requesting confirmation from @jacobheun or @daviddias that it's ok to delete this file. --- circle.yml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 circle.yml diff --git a/circle.yml b/circle.yml deleted file mode 100644 index 434211a..0000000 --- a/circle.yml +++ /dev/null @@ -1,12 +0,0 @@ -machine: - node: - version: stable - -dependencies: - pre: - - google-chrome --version - - wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - - - sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' - - sudo apt-get update - - sudo apt-get --only-upgrade install google-chrome-stable - - google-chrome --version From 360dcfba12228b62b3205085c374d51cfca774fd Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Tue, 23 Apr 2019 10:56:11 +0100 Subject: [PATCH 11/18] chore: add discourse badge (#7) --- .travis.yml | 38 -------------------------------------- README.md | 8 ++++---- package.json | 2 +- 3 files changed, 5 insertions(+), 43 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9d678dd..0000000 --- a/.travis.yml +++ /dev/null @@ -1,38 +0,0 @@ -sudo: false -language: node_js - -matrix: - include: - - node_js: 4 - env: CXX=g++-4.8 - - node_js: 6 - env: - - SAUCE=true - - CXX=g++-4.8 - - node_js: stable - env: CXX=g++-4.8 - -# Make sure we have new NPM. -before_install: - - npm install -g npm - -script: - - npm run lint - - npm test - - npm run coverage - - make test - -before_script: - - export DISPLAY=:99.0 - - sh -e /etc/init.d/xvfb start - -after_success: - - npm run coverage-publish - -addons: - firefox: 'latest' - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-4.8 diff --git a/README.md b/README.md index 073adb1..91995a2 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ interface-peer-discovery ======================== -[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) -[![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/) -[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) -[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard) +[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://protocol.ai) +[![](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![](https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23libp2p) +[![Discourse posts](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg)](https://discuss.libp2p.io) > A test suite and interface you can use to implement a Peer Discovery module for libp2p. diff --git a/package.json b/package.json index 1b7f8d9..3482b9a 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "homepage": "https://github.com/libp2p/interface-peer-discovery", "dependencies": {}, "devDependencies": { - "aegir": "^10.0.0" + "aegir": "^18.2.2" }, "engines": { "node": ">=4.0.0", From e690d28e0dc6a2e2b253254b36da717f419e4add Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Thu, 26 Sep 2019 11:27:39 +0200 Subject: [PATCH 12/18] refactor: async --- .gitignore | 40 +++-------------------- .travis.yml | 10 ++++++ README.md | 33 ++++++++++--------- package.json | 35 ++++++++++++-------- src/index.js | 32 ++++++++++++++++++ test/{index.js => peer-discovery.spec.js} | 0 6 files changed, 87 insertions(+), 63 deletions(-) create mode 100644 .travis.yml create mode 100644 src/index.js rename test/{index.js => peer-discovery.spec.js} (100%) diff --git a/.gitignore b/.gitignore index 1be92c3..fd34c26 100644 --- a/.gitignore +++ b/.gitignore @@ -1,38 +1,8 @@ -dist -# Logs -logs -*.log -npm-debug.log* - -# Runtime data -pids -*.pid -*.seed - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov +**/node_modules/ +**/*.log +package-lock.json # Coverage directory used by tools like istanbul coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules -jspm_packages - -# Optional npm cache directory -.npm - -# Optional REPL history -.node_repl_history +docs +dist diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..68ade7c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: node_js +cache: npm +stages: + - check + +node_js: + - '10' + +script: + - npm run lint diff --git a/README.md b/README.md index 91995a2..7e29b93 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ The API is presented with both Node.js and Go primitives, however, there is not ## Modules that implement the interface - [JavaScript libp2p-mdns](https://github.com/libp2p/js-libp2p-mdns) -- [JavaScript libp2p-railing](https://github.com/libp2p/js-libp2p-railing) +- [JavaScript libp2p-bootstrap](https://github.com/libp2p/js-libp2p-bootstrap) - [JavaScript libp2p-kad-dht](https://github.com/libp2p/js-libp2p-kad-dht) - [JavaScript libp2p-webrtc-star](https://github.com/libp2p/js-libp2p-webrtc-star) - [JavaScript libp2p-websocket-star](https://github.com/libp2p/js-libp2p-websocket-star) @@ -44,11 +44,11 @@ Install `interface-peer-discovery` as one of the dependencies of your project an const test = require('interface-peer-discovery') const common = { - setup (cb) { - cb(null, yourMuxer) + setup () { + return YourDiscovery }, - teardown (cb) { - cb() + teardown () { + // Clean up any resources created by setup() } } @@ -56,25 +56,28 @@ const common = { test(common) ``` -### Go - -> WIP - go-libp2p does not have a test suite available for Peer Discovery yet. - ## API A valid (read: that follows this abstraction) Peer Discovery module must implement the following API: ### `start` the service -- `JavaScript` discovery.start(callback) -- `Go` NA +- `await discovery.start()` + +Start the discovery service. + +It returns a `Promise` ### `stop` the service -- `JavaScript` discovery.stop(callback) -- `Go` NA +- `await discovery.stop()` + +Stop the discovery service. + +It returns a `Promise` ### discoverying peers -- `JavaScript` discovery.on('peer', function (peerInfo) {}) -- `Go` NA +- `discovery.on('peer', (peerInfo) => {})` + +Everytime a peer is discovered by a discovery service, it emmits a `peer` event with the discover peer's [PeerInfo](https://github.com/libp2p/js-peer-info). diff --git a/package.json b/package.json index 3482b9a..70f51a7 100644 --- a/package.json +++ b/package.json @@ -5,22 +5,29 @@ "leadMaintainer": "Vasco Santos ", "main": "src/index.js", "scripts": { - "lint": "aegir-lint", - "build": "aegir-build", - "test": "exit 0", - "release": "aegir-release", - "release-minor": "aegir-release --type minor", - "release-major": "aegir-release --type major" + "lint": "aegir lint", + "test": "aegir test", + "build": "aegir build", + "release": "aegir release --no-test", + "release-minor": "aegir release --type minor --no-test", + "release-major": "aegir release --type major --no-test", + "coverage": "exit(0)", + "coverage-publish": "exit(0)" }, - "pre-commit": [ - "lint", - "test" + "pre-push": [ + "lint" ], "repository": { "type": "git", "url": "https://github.com/libp2p/interface-peer-discovery.git" }, "keywords": [ + "libp2p", + "network", + "p2p", + "peer", + "discovery", + "peer-to-peer", "IPFS" ], "author": "David Dias ", @@ -31,13 +38,15 @@ "homepage": "https://github.com/libp2p/interface-peer-discovery", "dependencies": {}, "devDependencies": { - "aegir": "^18.2.2" + "aegir": "^20.3.1", + "chai": "^4.2.0", + "dirty-chai": "^2.0.1" }, "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" + "node": ">=10.0.0", + "npm": ">=6.0.0" }, "contributors": [ "David Dias " ] -} \ No newline at end of file +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..5b00fbd --- /dev/null +++ b/src/index.js @@ -0,0 +1,32 @@ +/* eslint-env mocha */ +'use strict' + +module.exports = (common) => { + describe('interface-peer-discovery', () => { + let discovery + + before(() => { + discovery = common.setup() + }) + + after(() => common.teardown && common.teardown()) + + it('can start the service', async () => { + await discovery.start() + }) + + it('can start and stop the service', async () => { + await discovery.start() + await discovery.stop() + }) + + it('should not fail to stop the service if it was not started', async () => { + await discovery.stop() + }) + + it('should not fail to start the service if it is already started', async () => { + await discovery.start() + await discovery.start() + }) + }) +} diff --git a/test/index.js b/test/peer-discovery.spec.js similarity index 100% rename from test/index.js rename to test/peer-discovery.spec.js From b0b54db5b1d8418f2e8eb01ccf16eeb532c6c3dd Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Fri, 27 Sep 2019 11:48:45 +0200 Subject: [PATCH 13/18] chore: add basic discovery module for compliance spec --- .travis.yml | 34 ++++++++++++++++++++++++-- package.json | 16 +++++++------ test/compliance.spec.js | 13 ++++++++++ test/mock-discovery.js | 48 +++++++++++++++++++++++++++++++++++++ test/peer-discovery.spec.js | 1 - 5 files changed, 102 insertions(+), 10 deletions(-) create mode 100644 test/compliance.spec.js create mode 100644 test/mock-discovery.js delete mode 100644 test/peer-discovery.spec.js diff --git a/.travis.yml b/.travis.yml index 68ade7c..c7f74c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,39 @@ language: node_js cache: npm stages: - check + - test + - cov node_js: - '10' + - '12' -script: - - npm run lint +os: + - linux + - osx + - windows + +script: npx nyc -s npm run test:node -- --bail +after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov + +jobs: + include: + - stage: check + script: + - npx aegir dep-check + - npm run lint + + - stage: test + name: chrome + addons: + chrome: stable + script: npx aegir test -t browser -t webworker + + - stage: test + name: firefox + addons: + firefox: latest + script: npx aegir test -t browser -t webworker -- --browsers FirefoxHeadless + +notifications: + email: false diff --git a/package.json b/package.json index 70f51a7..d9b146e 100644 --- a/package.json +++ b/package.json @@ -6,13 +6,13 @@ "main": "src/index.js", "scripts": { "lint": "aegir lint", - "test": "aegir test", "build": "aegir build", - "release": "aegir release --no-test", - "release-minor": "aegir release --type minor --no-test", - "release-major": "aegir release --type major --no-test", - "coverage": "exit(0)", - "coverage-publish": "exit(0)" + "test": "aegir test", + "test:node": "aegir test -t node", + "test:browser": "aegir test -t browser -t webworker", + "release": "aegir release", + "release-minor": "aegir release --type minor", + "release-major": "aegir release --type major" }, "pre-push": [ "lint" @@ -40,7 +40,9 @@ "devDependencies": { "aegir": "^20.3.1", "chai": "^4.2.0", - "dirty-chai": "^2.0.1" + "dirty-chai": "^2.0.1", + "peer-id": "^0.13.3", + "peer-info": "^0.17.0" }, "engines": { "node": ">=10.0.0", diff --git a/test/compliance.spec.js b/test/compliance.spec.js new file mode 100644 index 0000000..1eadba9 --- /dev/null +++ b/test/compliance.spec.js @@ -0,0 +1,13 @@ +/* eslint-env mocha */ +'use strict' + +const tests = require('../src') +const MockDiscovery = require('./mock-discovery') + +describe('compliance tests', () => { + tests({ + setup () { + return new MockDiscovery() + } + }) +}) diff --git a/test/mock-discovery.js b/test/mock-discovery.js new file mode 100644 index 0000000..c64b878 --- /dev/null +++ b/test/mock-discovery.js @@ -0,0 +1,48 @@ +'use strict' + +const { EventEmitter } = require('events') + +const PeerId = require('peer-id') +const PeerInfo = require('peer-info') + +/** + * Emits 'peer' events on discovery. + */ +class MockDiscovery extends EventEmitter { + /** + * Constructs a new Bootstrap. + * + * @param {Object} options + * @param {number} options.discoveryDelay - the delay to find a peer (in milli-seconds) + */ + constructor (options = {}) { + super() + + this.options = options + this._isRunning = false + this._timer = null + } + + start () { + this._isRunning = true + this._discoverPeer() + } + + stop () { + clearTimeout(this._timer) + this._isRunning = false + } + + async _discoverPeer () { + if (!this._isRunning) return + + const peerId = await PeerId.create({ bits: 512 }) + const peerInfo = new PeerInfo(peerId) + + this._timer = setTimeout(() => { + this.emit('peer', peerInfo) + }, this.options.discoveryDelay || 1000) + } +} + +module.exports = MockDiscovery diff --git a/test/peer-discovery.spec.js b/test/peer-discovery.spec.js deleted file mode 100644 index ccacec3..0000000 --- a/test/peer-discovery.spec.js +++ /dev/null @@ -1 +0,0 @@ -'use strict' From 808b72fafd556c241e4f708113bf43fd6f178280 Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Fri, 27 Sep 2019 12:40:01 +0200 Subject: [PATCH 14/18] chore: update contributors --- package.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d9b146e..5cef568 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "interface-discovery", - "version": "0.0.2", + "version": "0.1.0", "description": "A test suite and interface you can use to implement a discovery interface.", "leadMaintainer": "Vasco Santos ", "main": "src/index.js", @@ -49,6 +49,9 @@ "npm": ">=6.0.0" }, "contributors": [ - "David Dias " + "David Dias ", + "Mike Goelzer ", + "Vasco Santos ", + "Vasco Santos " ] } From 6bb1f2a4cbdae6a3db8a874af480ea1796398da2 Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Fri, 27 Sep 2019 12:40:01 +0200 Subject: [PATCH 15/18] chore: release version v0.1.0 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..7ea310f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ + +# [0.1.0](https://github.com/libp2p/interface-peer-discovery/compare/v0.0.1...v0.1.0) (2019-09-27) + + + + +## 0.0.1 (2017-02-09) + + + From 2814c76e23edc2279bf960f5ecaf2060d402a83a Mon Sep 17 00:00:00 2001 From: Jacob Heun Date: Fri, 27 Sep 2019 13:32:45 +0200 Subject: [PATCH 16/18] fix: add async support to setup (#11) --- README.md | 4 ++-- src/index.js | 6 ++++-- test/compliance.spec.js | 6 +++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7e29b93..265cf45 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,10 @@ Include this badge in your readme if you make a new module that uses interface-p ### Node.js -Install `interface-peer-discovery` as one of the dependencies of your project and as a test file. Then, using `mocha` (for JavaScript) or a test runner with compatible API, do: +Install `interface-discovery` as one of the dependencies of your project and as a test file. Then, using `mocha` (for JavaScript) or a test runner with compatible API, do: ```js -const test = require('interface-peer-discovery') +const test = require('interface-discovery') const common = { setup () { diff --git a/src/index.js b/src/index.js index 5b00fbd..343a7db 100644 --- a/src/index.js +++ b/src/index.js @@ -5,12 +5,14 @@ module.exports = (common) => { describe('interface-peer-discovery', () => { let discovery - before(() => { - discovery = common.setup() + before(async () => { + discovery = await common.setup() }) after(() => common.teardown && common.teardown()) + afterEach('ensure discovery was stopped', () => discovery.stop()) + it('can start the service', async () => { await discovery.start() }) diff --git a/test/compliance.spec.js b/test/compliance.spec.js index 1eadba9..5b54fba 100644 --- a/test/compliance.spec.js +++ b/test/compliance.spec.js @@ -6,8 +6,12 @@ const MockDiscovery = require('./mock-discovery') describe('compliance tests', () => { tests({ - setup () { + async setup () { + await new Promise(resolve => setTimeout(resolve, 10)) return new MockDiscovery() + }, + async teardown () { + await new Promise(resolve => setTimeout(resolve, 10)) } }) }) From bee951f0369ca1c6541f4e0b8df01b1a273d58e5 Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Fri, 27 Sep 2019 13:33:34 +0200 Subject: [PATCH 17/18] chore: update contributors --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 5cef568..e897719 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "interface-discovery", - "version": "0.1.0", + "version": "0.1.1", "description": "A test suite and interface you can use to implement a discovery interface.", "leadMaintainer": "Vasco Santos ", "main": "src/index.js", @@ -50,6 +50,7 @@ }, "contributors": [ "David Dias ", + "Jacob Heun ", "Mike Goelzer ", "Vasco Santos ", "Vasco Santos " From 1f84bfc7493e48d0b68bb72f6af7aecdbe0783bd Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Fri, 27 Sep 2019 13:33:34 +0200 Subject: [PATCH 18/18] chore: release version v0.1.1 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ea310f..79bc3d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [0.1.1](https://github.com/libp2p/interface-peer-discovery/compare/v0.1.0...v0.1.1) (2019-09-27) + + +### Bug Fixes + +* add async support to setup ([#11](https://github.com/libp2p/interface-peer-discovery/issues/11)) ([2814c76](https://github.com/libp2p/interface-peer-discovery/commit/2814c76)) + + + # [0.1.0](https://github.com/libp2p/interface-peer-discovery/compare/v0.0.1...v0.1.0) (2019-09-27)