From 546fb5a2713d74520263f7e6d043c0181261b8d9 Mon Sep 17 00:00:00 2001 From: Nishant Arora <1895906+whizzzkid@users.noreply.github.com> Date: Wed, 9 Nov 2022 15:23:03 -0700 Subject: [PATCH] feat: update to ipfs-geoip v9 (#2061) https://github.com/ipfs-shipyard/ipfs-geoip/releases/tag/v9.0.0 https://github.com/ipfs-shipyard/ipfs-geoip/releases/tag/v9.0.1 --- config-overrides.js | 83 +++++++++++++------- package-lock.json | 50 +++--------- package.json | 2 +- src/bundles/peer-locations.js | 12 ++- src/bundles/peer-locations.test.js | 121 +++++++++++++++-------------- src/peers/PeersPage.js | 2 +- 6 files changed, 131 insertions(+), 139 deletions(-) diff --git a/config-overrides.js b/config-overrides.js index 8f6ce18eb..d71387c48 100644 --- a/config-overrides.js +++ b/config-overrides.js @@ -5,46 +5,69 @@ * @see https://alchemy.com/blog/how-to-polyfill-node-core-modules-in-webpack-5 */ const webpack = require('webpack') +const PURE_ESM_MODULES = [ + 'ipfs-geoip' +] /** + * This function goes through the loader rules and applies modifier function to the said rule. + * Validation can be set within the modifier function. * * @param {import('webpack').RuleSetRule[]} rules + * @param {function} modifier defaults to identity function + * @returns {import('webpack').RuleSetRule[]} */ -function modifyBabelLoaderRule (rules, root = true) { - const foundRules = [] - rules.forEach((rule, i) => { - if (rule.loader != null) { - if (rule.loader.includes('babel-loader')) { - foundRules.push(rule) - } - } else if (rule.use?.loader != null) { - if (typeof rule.use.loader !== 'string') { - if (rule.use.loader.find(loader => loader.indexOf('babel-loader') >= 0)) { - foundRules.push(rule) - } - } else if (rule.use.loader.indexOf('babel-loader') >= 0) { - foundRules.push(rule) - } - } else if (rule.oneOf) { - const nestedRules = modifyBabelLoaderRule(rule.oneOf, false) - foundRules.push(...nestedRules) +function modifyBabelLoaderRules (rules, modifier = r => r) { + return rules.map(rule => { + if (rule.oneOf) { + rule.oneOf = modifyBabelLoaderRules(rule.oneOf, modifier) + } else if (rule.use) { + rule.use = modifyBabelLoaderRules(rule.use, modifier) + } else { + rule = modifier(rule) } + return rule }) +} - if (root) { - foundRules.forEach((rule, index) => { - if (rule.include?.indexOf('src') >= 0) { - console.log('Found CRA babel-loader rule for source files. Modifying it to instrument for code coverage.') - console.log('rule: ', rule) - rule.options.plugins.push('istanbul') +/** + * Adds exclude rules for pure ESM Modules. + * + * @param {import('webpack').RuleSetRule[]} rules + * @returns {import('webpack').RuleSetRule[]} + */ +function modifyBabelLoaderRuleForBuild (rules) { + return modifyBabelLoaderRules(rules, rule => { + if (rule.loader && rule.loader.includes('babel-loader')) { + if ('exclude' in rule) { + if (!Array.isArray(rule.exclude)) { + rule.exclude = [rule.exclude] + } + PURE_ESM_MODULES.forEach(module => { + rule.exclude.push(new RegExp(`node_modules/${module}`)) + }) } - }) - } + } + return rule + }) +} - return foundRules +/** + * Adds instrumentation plugin for code coverage in test mode. + * + * @param {import('webpack').RuleSetRule[]} rules + * @returns {import('webpack').RuleSetRule[]} + */ +function modifyBabelLoaderRuleForTest (rules) { + return modifyBabelLoaderRules(rules, rule => { + if (rule.options && rule.options.plugins) { + rule.options.plugins.push('istanbul') + } + return rule + }) } -function webpackOverride (config) { +function webpackOverride(config) { const fallback = config.resolve.fallback || {} Object.assign(fallback, { @@ -63,10 +86,12 @@ function webpackOverride (config) { }) ]) + config.module.rules = modifyBabelLoaderRuleForBuild(config.module.rules) + // Instrument for code coverage in development mode const REACT_APP_ENV = process.env.REACT_APP_ENV ?? process.env.NODE_ENV ?? 'production' if (REACT_APP_ENV === 'test') { - modifyBabelLoaderRule(config.module.rules) + config.module.rules = modifyBabelLoaderRuleForTest(config.module.rules) } return config diff --git a/package-lock.json b/package-lock.json index 54340dbfb..29443af35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "intl-messageformat": "^9.11.3", "ip": "^1.1.5", "ipfs-css": "^1.4.0", - "ipfs-geoip": "^8.0.0", + "ipfs-geoip": "9.0.1", "ipfs-http-client": "49.0.2", "ipfs-provider": "^2.1.0", "ipld-explorer-components": "^2.4.1", @@ -35647,27 +35647,12 @@ "dev": true }, "node_modules/ipfs-geoip": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/ipfs-geoip/-/ipfs-geoip-8.0.0.tgz", - "integrity": "sha512-MK9QSM828QdeNu169tgRt7Dl4lVFnriQoHfLn48I9th8x3v6NxevSI/ej3c2sEMLtVe2OeR3Ae70sOuuwYozuQ==", - "dependencies": { - "cids": "^1.1.6", - "ip": "^1.1.5", - "it-concat": "^1.0.3", - "p-memoize": "^4.0.1", - "web-encoding": "^1.1.0" - }, + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ipfs-geoip/-/ipfs-geoip-9.0.1.tgz", + "integrity": "sha512-ZPqNSQ1nJmu/67vxWajXaNH5+bzWvpXGDPtoow1tlmiiLgnNmag8tp6dVgOJsbma6BteFrK0PVSAV3/NAibKYQ==", "engines": { - "node": ">=14.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipfs-geoip/node_modules/it-concat": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/it-concat/-/it-concat-1.0.3.tgz", - "integrity": "sha512-sjeZQ1BWQ9U/W2oI09kZgUyvSWzQahTkOkLIsnEPgyqZFaF9ME5gV6An4nMjlyhXKWQMKEakQU8oRHs2SdmeyA==", - "dependencies": { - "bl": "^4.0.0" + "node": ">=16.0.0", + "npm": ">=8.0.0" } }, "node_modules/ipfs-grpc-client": { @@ -97481,26 +97466,9 @@ } }, "ipfs-geoip": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/ipfs-geoip/-/ipfs-geoip-8.0.0.tgz", - "integrity": "sha512-MK9QSM828QdeNu169tgRt7Dl4lVFnriQoHfLn48I9th8x3v6NxevSI/ej3c2sEMLtVe2OeR3Ae70sOuuwYozuQ==", - "requires": { - "cids": "^1.1.6", - "ip": "^1.1.5", - "it-concat": "^1.0.3", - "p-memoize": "^4.0.1", - "web-encoding": "^1.1.0" - }, - "dependencies": { - "it-concat": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/it-concat/-/it-concat-1.0.3.tgz", - "integrity": "sha512-sjeZQ1BWQ9U/W2oI09kZgUyvSWzQahTkOkLIsnEPgyqZFaF9ME5gV6An4nMjlyhXKWQMKEakQU8oRHs2SdmeyA==", - "requires": { - "bl": "^4.0.0" - } - } - } + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ipfs-geoip/-/ipfs-geoip-9.0.1.tgz", + "integrity": "sha512-ZPqNSQ1nJmu/67vxWajXaNH5+bzWvpXGDPtoow1tlmiiLgnNmag8tp6dVgOJsbma6BteFrK0PVSAV3/NAibKYQ==" }, "ipfs-grpc-client": { "version": "0.10.0", diff --git a/package.json b/package.json index 3cccdad3d..fc8587e4d 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "intl-messageformat": "^9.11.3", "ip": "^1.1.5", "ipfs-css": "^1.4.0", - "ipfs-geoip": "^8.0.0", + "ipfs-geoip": "9.0.1", "ipfs-http-client": "49.0.2", "ipfs-provider": "^2.1.0", "ipld-explorer-components": "^2.4.1", diff --git a/src/bundles/peer-locations.js b/src/bundles/peer-locations.js index 8a5bf2368..2122f150f 100644 --- a/src/bundles/peer-locations.js +++ b/src/bundles/peer-locations.js @@ -1,6 +1,6 @@ import { createAsyncResourceBundle, createSelector } from 'redux-bundler' import { getConfiguredCache } from 'money-clip' -import geoip from 'ipfs-geoip' +import { lookup } from 'ipfs-geoip' import PQueue from 'p-queue' import HLRU from 'hashlru' import Multiaddr from 'multiaddr' @@ -32,10 +32,8 @@ function createPeersLocations (opts) { const bundle = createAsyncResourceBundle({ name: 'peerLocations', actionBaseType: 'PEER_LOCATIONS', - getPromise: async ({ store, getIpfs }) => { - const peers = store.selectPeers() - return peerLocResolver.findLocations(peers, getIpfs) - }, + getPromise: ({ store }) => peerLocResolver.findLocations( + store.selectAvailableGatewayUrl(), store.selectPeers()), staleAfter: UPDATE_EVERY, retryAfter: UPDATE_EVERY, persist: false, @@ -227,7 +225,7 @@ class PeerLocationResolver { this.pass = 0 } - async findLocations (peers, getIpfs) { + async findLocations (gatewayUrls, peers) { const res = {} for (const p of this.optimizedPeerSet(peers)) { @@ -257,7 +255,7 @@ class PeerLocationResolver { this.geoipLookupPromises.set(ipv4Addr, this.queue.add(async () => { try { - const data = await geoip.lookup(getIpfs(), ipv4Addr) + const data = await lookup(gatewayUrls, ipv4Addr) await this.geoipCache.set(ipv4Addr, data) } catch (e) { // mark this one as failed so we don't retry again diff --git a/src/bundles/peer-locations.test.js b/src/bundles/peer-locations.test.js index 5f8b7ba94..9e3e0a33b 100644 --- a/src/bundles/peer-locations.test.js +++ b/src/bundles/peer-locations.test.js @@ -274,55 +274,58 @@ describe('PeerLocationResolver', () => { const result = await getPromise({ store: { - selectPeers: () => [{ - peer: '1aaa1', - latency: 'n/a', - addr: { - stringTuples: () => [[4, '123.123.123.123']] + selectPeers: () => [ + { + peer: '1aaa1', + latency: 'n/a', + addr: { + stringTuples: () => [[4, '123.123.123.123']] + } + }, + { + peer: '1b1', + latency: '1ms', + addr: { + stringTuples: () => [[4, '127.0.0.1']] + } + }, + { + peer: '3b3', + latency: '1ms', + addr: { + stringTuples: () => [[4, '16.19.16.19']] + } + }, + { + peer: '44asd', + latency: '1ms', + addr: { + stringTuples: () => [[4, '4.4.4.4']] + } + }, + { + peer: '4sameAs4', + latency: '1ms', + addr: { + stringTuples: () => [[4, '4.4.4.4']] + } + }, + { + peer: 'newPeerThatShouldThrow', + latency: '100s', + addr: { + stringTuples: () => [[4, '5.5.5.5']] + } + }, + { + peer: 'sameIpAs1', + latency: 'n/a', + addr: { + stringTuples: () => [[4, '123.123.123.123']] + } } - }, - { - peer: '1b1', - latency: '1ms', - addr: { - stringTuples: () => [[4, '127.0.0.1']] - } - }, - { - peer: '3b3', - latency: '1ms', - addr: { - stringTuples: () => [[4, '16.19.16.19']] - } - }, - { - peer: '44asd', - latency: '1ms', - addr: { - stringTuples: () => [[4, '4.4.4.4']] - } - }, - { - peer: '4sameAs4', - latency: '1ms', - addr: { - stringTuples: () => [[4, '4.4.4.4']] - } - }, - { - peer: 'newPeerThatShouldThrow', - latency: '100s', - addr: { - stringTuples: () => [[4, '5.5.5.5']] - } - }, - { - peer: 'sameIpAs1', - latency: 'n/a', - addr: { - stringTuples: () => [[4, '123.123.123.123']] - } - }] + ], + selectAvailableGatewayUrl: () => 'https://ipfs.io' }, getIpfs: () => 'smth' }) @@ -346,10 +349,13 @@ describe('PeerLocationResolver', () => { } })) + const mockStore = { + selectAvailableGatewayUrl: () => 'https://ipfs.io', + selectPeers: () => peers + } + const result = await getPromise({ - store: { - selectPeers: () => peers - } + store: mockStore }) expect(result).toEqual({ @@ -368,10 +374,9 @@ describe('PeerLocationResolver', () => { // ==== 100 ==== const result100 = await getPromise({ - store: { - selectPeers: () => peers - } + store: mockStore }) + const expect100 = new Array(100).fill().reduce((prev, _, index) => ({ ...prev, [`${index}aa`]: 'location-cached' @@ -382,9 +387,7 @@ describe('PeerLocationResolver', () => { // ==== 200 ==== const result200 = await getPromise({ - store: { - selectPeers: () => peers - } + store: mockStore }) const expect200 = new Array(200).fill().reduce((prev, _, index) => ({ ...prev, @@ -396,9 +399,7 @@ describe('PeerLocationResolver', () => { // ==== Over 200 ==== const resultMore = await getPromise({ - store: { - selectPeers: () => peers - } + store: mockStore }) const expectMore = new Array(1000).fill().reduce((prev, _, index) => ({ diff --git a/src/peers/PeersPage.js b/src/peers/PeersPage.js index 9097babd6..c075cf687 100644 --- a/src/peers/PeersPage.js +++ b/src/peers/PeersPage.js @@ -15,7 +15,7 @@ import AddConnection from './AddConnection/AddConnection' import CliTutorMode from '../components/cli-tutor-mode/CliTutorMode' import { cliCmdKeys, cliCommandList } from '../bundles/files/consts' -const PeersPage = ({ t, toursEnabled, handleJoyrideCallback, isCliTutorModeEnabled }) => ( +const PeersPage = ({ t, toursEnabled, handleJoyrideCallback }) => (