From 21dc1d9b6b372a12fc7467d1753d65714f622816 Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Fri, 26 Mar 2021 16:00:27 +0100 Subject: [PATCH 1/7] feat: add types --- .github/workflows/main.yml | 74 ++++++++++++++++++++++++++++++++++++ package.json | 25 +++++++++--- src/address-sort.js | 10 +++++ src/ip-port-to-multiaddr.js | 17 +++++---- src/multiaddr/is-loopback.js | 5 +++ src/multiaddr/is-private.js | 5 +++ src/stream-to-ma-conn.js | 26 ++++++++++--- tsconfig.json | 9 +++++ 8 files changed, 153 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/main.yml create mode 100644 tsconfig.json diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..25fc395 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,74 @@ +name: ci +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: npm install + - run: npx aegir lint + - run: npx aegir ts -p check + - run: npx aegir build + - run: npx aegir dep-check + - uses: ipfs/aegir/actions/bundle-size@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + test-node: + needs: check + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [windows-latest, ubuntu-latest, macos-latest] + node: [14, 15] + fail-fast: true + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node }} + - run: npm install + - run: npx nyc --reporter=lcov aegir test -t node -- --bail + - uses: codecov/codecov-action@v1 + test-chrome: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: npm install + - run: npx aegir test -t browser -t webworker --bail + test-firefox: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: npm install + - run: npx aegir test -t browser -t webworker --bail -- --browsers FirefoxHeadless + test-webkit: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: microsoft/playwright-github-action@v1 + - run: npm install + - run: npx aegir test -t browser -t webworker --bail -- --browser webkit + test-electron-main: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: npm install + - run: npx xvfb-maybe aegir test -t electron-main --bail + test-electron-renderer: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: npm install + - run: npx xvfb-maybe aegir test -t electron-renderer --bail \ No newline at end of file diff --git a/package.json b/package.json index be3f1d7..611e8ef 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,17 @@ "description": "Package to aggregate shared logic and dependencies for the libp2p ecosystem", "leadMaintainer": "Vasco Santos ", "main": "src/index.js", + "types": "dist/src/index.d.ts", + "typesVersions": { + "*": { + "src/*": [ + "dist/src/*", + "dist/src/*/index" + ] + } + }, "scripts": { + "prepare": "aegir build --no-bundle", "test": "aegir test", "test:browser": "aegir test -t browser", "test:node": "aegir test -t node", @@ -29,18 +39,21 @@ }, "homepage": "https://github.com/libp2p/js-libp2p-utils#readme", "devDependencies": { - "aegir": "^27.0.0", + "@types/debug": "^4.1.5", + "aegir": "^32.1.0", "it-pair": "^1.0.0", "it-pipe": "^1.1.0", - "streaming-iterables": "^5.0.3" + "libp2p-interfaces": "^0.8.4", + "streaming-iterables": "^5.0.3", + "util": "^0.12.3" }, "dependencies": { "abortable-iterator": "^3.0.0", - "debug": "^4.2.0", - "err-code": "^2.0.3", - "ip-address": "^6.1.0", + "debug": "^4.3.0", + "err-code": "^3.0.1", + "ip-address": "^7.1.0", "is-loopback-addr": "^1.0.0", - "multiaddr": "^8.0.0", + "multiaddr": "^8.1.2", "private-ip": "^2.1.1" }, "contributors": [ diff --git a/src/address-sort.js b/src/address-sort.js index 0a49143..9e9468e 100644 --- a/src/address-sort.js +++ b/src/address-sort.js @@ -2,6 +2,16 @@ const isPrivate = require('./multiaddr/is-private') +/** + * @typedef {import('multiaddr')} Multiaddr + */ + +/** + * @typedef {Object} Address + * @property {Multiaddr} multiaddr peer multiaddr. + * @property {boolean} isCertified obtained from a signed peer record. + */ + /** * Compare function for array.sort(). * This sort aims to move the private adresses to the end of the array. diff --git a/src/ip-port-to-multiaddr.js b/src/ip-port-to-multiaddr.js index f928b60..85a9751 100644 --- a/src/ip-port-to-multiaddr.js +++ b/src/ip-port-to-multiaddr.js @@ -21,25 +21,28 @@ function ipPortToMultiaddr (ip, port) { throw errCode(new Error(`invalid ip provided: ${ip}`), errors.ERR_INVALID_IP_PARAMETER) } + // @ts-ignore parseInt expects only string port = parseInt(port) if (isNaN(port)) { throw errCode(new Error(`invalid port provided: ${port}`), errors.ERR_INVALID_PORT_PARAMETER) } - if (new Address4(ip).isValid()) { + try { + // Test valid IPv4 + new Address4(ip) // eslint-disable-line no-new return multiaddr(`/ip4/${ip}/tcp/${port}`) - } - - const ip6 = new Address6(ip) + } catch (_) {} - if (ip6.isValid()) { + try { + // Test valid IPv6 + const ip6 = new Address6(ip) return ip6.is4() ? multiaddr(`/ip4/${ip6.to4().correctForm()}/tcp/${port}`) : multiaddr(`/ip6/${ip}/tcp/${port}`) + } catch (err) { + throw errCode(new Error(`invalid ip:port for creating a multiaddr: ${ip}:${port}`), errors.ERR_INVALID_IP) } - - throw errCode(new Error(`invalid ip:port for creating a multiaddr: ${ip}:${port}`), errors.ERR_INVALID_IP) } module.exports = ipPortToMultiaddr diff --git a/src/multiaddr/is-loopback.js b/src/multiaddr/is-loopback.js index 1c11c1c..b30b709 100644 --- a/src/multiaddr/is-loopback.js +++ b/src/multiaddr/is-loopback.js @@ -1,7 +1,12 @@ 'use strict' +// @ts-ignore is-loopback-addr does not publish types const isLoopbackAddr = require('is-loopback-addr') +/** + * @typedef {import('multiaddr')} Multiaddr + */ + /** * Check if a given multiaddr is a loopback address. * diff --git a/src/multiaddr/is-private.js b/src/multiaddr/is-private.js index 69192b7..67e293b 100644 --- a/src/multiaddr/is-private.js +++ b/src/multiaddr/is-private.js @@ -1,7 +1,12 @@ 'use strict' +// @ts-ignore private-ip does not publish types const isIpPrivate = require('private-ip') +/** + * @typedef {import('multiaddr')} Multiaddr + */ + /** * Check if a given multiaddr has a private address. * diff --git a/src/stream-to-ma-conn.js b/src/stream-to-ma-conn.js index 91a3f4b..4e8802a 100644 --- a/src/stream-to-ma-conn.js +++ b/src/stream-to-ma-conn.js @@ -1,14 +1,25 @@ 'use strict' const abortable = require('abortable-iterator') -const log = require('debug')('libp2p:stream:converter') +const debug = require('debug') +const log = debug('libp2p:stream:converter') + +/** + * @typedef {import('multiaddr')} Multiaddr + * @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream + * + * @typedef {Object} Timeline + * @property {number} open - connection opening timestamp. + * @property {number} [upgraded] - connection upgraded timestamp. + * @property {number} [close] + */ /** * Convert a duplex iterable into a MultiaddrConnection. * https://github.com/libp2p/interface-transport#multiaddrconnection * * @param {object} streamProperties - * @param {DuplexStream} streamProperties.stream + * @param {MuxedStream} streamProperties.stream * @param {Multiaddr} streamProperties.remoteAddr * @param {Multiaddr} streamProperties.localAddr * @param {object} [options] @@ -17,8 +28,12 @@ const log = require('debug')('libp2p:stream:converter') function streamToMaConnection ({ stream, remoteAddr, localAddr }, options = {}) { const { sink, source } = stream const maConn = { + /** + * @param {Uint8Array} source + */ async sink (source) { if (options.signal) { + // @ts-ignore abortable has no type definitions source = abortable(source, options.signal) } @@ -35,15 +50,16 @@ function streamToMaConnection ({ stream, remoteAddr, localAddr }, options = {}) } close() }, - + // @ts-ignore abortable has no type definitions source: options.signal ? abortable(source, options.signal) : source, conn: stream, localAddr, remoteAddr, - timeline: { open: Date.now() }, + /** @type {Timeline} */ + timeline: { open: Date.now(), close: undefined }, close () { - sink([]) + sink(new Uint8Array(0)) close() } } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5b9a618 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "./node_modules/aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ] +} \ No newline at end of file From b0d06da6575635203c27e3a250805463775b48e2 Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Fri, 26 Mar 2021 18:14:12 +0100 Subject: [PATCH 2/7] chore: remove travis ci --- .travis.yml | 52 ---------------------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index bd3dcaf..0000000 --- a/.travis.yml +++ /dev/null @@ -1,52 +0,0 @@ -language: node_js -cache: npm -stages: - - check - - test - - cov - -node_js: - - '10' - - '12' - -os: - - linux - - osx - -script: npx nyc -s npm run test:node -- --bail -after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov - -jobs: - include: - - os: windows - filter_secrets: false - cache: false - - - stage: check - script: - - npx aegir commitlint --travis - - 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 - - - stage: test - name: electron - services: - - xvfb - script: - - npm run test:electron - - npm run test:electron-renderer - -notifications: - email: false From 2d5eaf165c0c20587b913b9ed5aef4facf412d3a Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Fri, 26 Mar 2021 18:57:07 +0100 Subject: [PATCH 3/7] chore: add package.json files --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index 611e8ef..104ea06 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,10 @@ ] } }, + "files": [ + "src", + "dist" + ], "scripts": { "prepare": "aegir build --no-bundle", "test": "aegir test", From c92a92c5bdd2f9ce9e64aa98e43bacb51b56721b Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Mon, 29 Mar 2021 15:12:41 +0200 Subject: [PATCH 4/7] fix: connection close should return promise --- src/stream-to-ma-conn.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/stream-to-ma-conn.js b/src/stream-to-ma-conn.js index 4e8802a..55be5bb 100644 --- a/src/stream-to-ma-conn.js +++ b/src/stream-to-ma-conn.js @@ -6,6 +6,7 @@ const log = debug('libp2p:stream:converter') /** * @typedef {import('multiaddr')} Multiaddr + * @typedef {import('libp2p-interfaces/src/transport/types').MultiaddrConnection} MultiaddrConnection * @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream * * @typedef {Object} Timeline @@ -57,10 +58,9 @@ function streamToMaConnection ({ stream, remoteAddr, localAddr }, options = {}) remoteAddr, /** @type {Timeline} */ timeline: { open: Date.now(), close: undefined }, - close () { sink(new Uint8Array(0)) - close() + return close() } } @@ -68,6 +68,7 @@ function streamToMaConnection ({ stream, remoteAddr, localAddr }, options = {}) if (!maConn.timeline.close) { maConn.timeline.close = Date.now() } + return Promise.resolve() } return maConn From f510e8f931b11bc07e295389bf61840c13065f2b Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Tue, 6 Apr 2021 15:35:59 +0200 Subject: [PATCH 5/7] chore: apply suggestions from code review Co-authored-by: Hugo Dias --- src/ip-port-to-multiaddr.js | 5 +++-- src/stream-to-ma-conn.js | 2 +- tsconfig.json | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ip-port-to-multiaddr.js b/src/ip-port-to-multiaddr.js index 85a9751..7540f2e 100644 --- a/src/ip-port-to-multiaddr.js +++ b/src/ip-port-to-multiaddr.js @@ -21,8 +21,9 @@ function ipPortToMultiaddr (ip, port) { throw errCode(new Error(`invalid ip provided: ${ip}`), errors.ERR_INVALID_IP_PARAMETER) } - // @ts-ignore parseInt expects only string - port = parseInt(port) + if (typeof port === 'string') { + port = parseInt(port) + } if (isNaN(port)) { throw errCode(new Error(`invalid port provided: ${port}`), errors.ERR_INVALID_PORT_PARAMETER) diff --git a/src/stream-to-ma-conn.js b/src/stream-to-ma-conn.js index 55be5bb..b7040a5 100644 --- a/src/stream-to-ma-conn.js +++ b/src/stream-to-ma-conn.js @@ -34,7 +34,7 @@ function streamToMaConnection ({ stream, remoteAddr, localAddr }, options = {}) */ async sink (source) { if (options.signal) { - // @ts-ignore abortable has no type definitions + // @ts-ignore ts infers source template will be a number source = abortable(source, options.signal) } diff --git a/tsconfig.json b/tsconfig.json index 5b9a618..5fe8ea4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,9 @@ { - "extends": "./node_modules/aegir/src/config/tsconfig.aegir.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" }, "include": [ "src" ] -} \ No newline at end of file +} From 73714236de0b855c0e58188ca9c5adda1d24da6d Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Tue, 6 Apr 2021 21:57:05 +0200 Subject: [PATCH 6/7] chore: address review --- package.json | 2 +- src/ip-port-to-multiaddr.js | 10 ++++++++-- src/stream-to-ma-conn.js | 4 ++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 104ea06..7d1e0c1 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "aegir": "^32.1.0", "it-pair": "^1.0.0", "it-pipe": "^1.1.0", - "libp2p-interfaces": "^0.8.4", + "libp2p-interfaces": "libp2p/js-libp2p-interfaces#chore/update-types", "streaming-iterables": "^5.0.3", "util": "^0.12.3" }, diff --git a/src/ip-port-to-multiaddr.js b/src/ip-port-to-multiaddr.js index 7540f2e..dfd27f0 100644 --- a/src/ip-port-to-multiaddr.js +++ b/src/ip-port-to-multiaddr.js @@ -1,5 +1,9 @@ 'use strict' +const debug = require('debug') +const log = Object.assign(debug('libp2p:ip-port-to-multiaddr'), { + error: debug('libp2p:ip-port-to-multiaddr:err') +}) const multiaddr = require('multiaddr') const errCode = require('err-code') const { Address4, Address6 } = require('ip-address') @@ -33,7 +37,7 @@ function ipPortToMultiaddr (ip, port) { // Test valid IPv4 new Address4(ip) // eslint-disable-line no-new return multiaddr(`/ip4/${ip}/tcp/${port}`) - } catch (_) {} + } catch {} try { // Test valid IPv6 @@ -42,7 +46,9 @@ function ipPortToMultiaddr (ip, port) { ? multiaddr(`/ip4/${ip6.to4().correctForm()}/tcp/${port}`) : multiaddr(`/ip6/${ip}/tcp/${port}`) } catch (err) { - throw errCode(new Error(`invalid ip:port for creating a multiaddr: ${ip}:${port}`), errors.ERR_INVALID_IP) + const errMsg = `invalid ip:port for creating a multiaddr: ${ip}:${port}` + log.error(errMsg) + throw errCode(new Error(errMsg), errors.ERR_INVALID_IP) } } diff --git a/src/stream-to-ma-conn.js b/src/stream-to-ma-conn.js index b7040a5..2c2ac18 100644 --- a/src/stream-to-ma-conn.js +++ b/src/stream-to-ma-conn.js @@ -1,6 +1,6 @@ 'use strict' -const abortable = require('abortable-iterator') +const { source: abortable } = require('abortable-iterator') const debug = require('debug') const log = debug('libp2p:stream:converter') @@ -25,6 +25,7 @@ const log = debug('libp2p:stream:converter') * @param {Multiaddr} streamProperties.localAddr * @param {object} [options] * @param {AbortSignal} [options.signal] + * @returns {MultiaddrConnection} */ function streamToMaConnection ({ stream, remoteAddr, localAddr }, options = {}) { const { sink, source } = stream @@ -51,7 +52,6 @@ function streamToMaConnection ({ stream, remoteAddr, localAddr }, options = {}) } close() }, - // @ts-ignore abortable has no type definitions source: options.signal ? abortable(source, options.signal) : source, conn: stream, localAddr, From 64a90eecc6b4d5386b99a4b8ff3f0318a02b0ebf Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Wed, 7 Apr 2021 09:45:23 +0200 Subject: [PATCH 7/7] chore: update interfaces --- package.json | 2 +- src/stream-to-ma-conn.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 7d1e0c1..1d50cfa 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "aegir": "^32.1.0", "it-pair": "^1.0.0", "it-pipe": "^1.1.0", - "libp2p-interfaces": "libp2p/js-libp2p-interfaces#chore/update-types", + "libp2p-interfaces": "^0.9.0", "streaming-iterables": "^5.0.3", "util": "^0.12.3" }, diff --git a/src/stream-to-ma-conn.js b/src/stream-to-ma-conn.js index 2c2ac18..335d461 100644 --- a/src/stream-to-ma-conn.js +++ b/src/stream-to-ma-conn.js @@ -6,7 +6,6 @@ const log = debug('libp2p:stream:converter') /** * @typedef {import('multiaddr')} Multiaddr - * @typedef {import('libp2p-interfaces/src/transport/types').MultiaddrConnection} MultiaddrConnection * @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream * * @typedef {Object} Timeline @@ -25,7 +24,7 @@ const log = debug('libp2p:stream:converter') * @param {Multiaddr} streamProperties.localAddr * @param {object} [options] * @param {AbortSignal} [options.signal] - * @returns {MultiaddrConnection} + * @returns {import('libp2p-interfaces/src/transport/types').MultiaddrConnection} */ function streamToMaConnection ({ stream, remoteAddr, localAddr }, options = {}) { const { sink, source } = stream