From 84ffe177475513258e2774f0716f4ec290fec639 Mon Sep 17 00:00:00 2001 From: 3alpha Date: Tue, 23 Jul 2024 12:29:41 +0200 Subject: [PATCH] add jsonrpcprovider header (#1996) * add jsonrpcprovider header * Update packages/installer/src/ethClient/ethersProvider.ts * add db dependency * untangle deps * Trim whitespaces * Update ethers and centralize ethers provider * bump toolkit version * Change to abstract provider in toolkit * Use version data from db (#1998) * Fix int tests toolkit (#1999) * fix int tests * comment out ipfs api url https://api.ipfs.dappnode.io * skip repository test --------- Co-authored-by: pablomendezroyo <41727368+pablomendezroyo@users.noreply.github.com> --- packages/dappmanager/package.json | 4 +- .../middlewares/ethForward/resolveDomain.ts | 4 +- .../dappmanager/src/calls/fetchDirectory.ts | 5 +-- packages/dappmanager/src/index.ts | 5 ++- packages/dyndns/package.json | 2 +- packages/installer/package.json | 4 +- packages/installer/src/dappnodeInstaller.ts | 10 ++--- .../installer/src/ethClient/clientStatus.ts | 29 +++--------- .../installer/src/ethClient/ethersProvider.ts | 19 ++++++-- packages/toolkit/package.json | 2 +- packages/toolkit/src/directory/directory.ts | 4 +- packages/toolkit/src/registry/registry.ts | 5 +-- .../toolkit/src/repository/apmRepository.ts | 16 +++---- packages/toolkit/src/repository/repository.ts | 5 ++- .../toolkit/test/directory/directory.test.ts | 2 +- .../toolkit/test/registry/registry.test.ts | 4 +- .../test/repository/repository.test.ts | 7 +-- packages/utils/src/index.ts | 2 +- yarn.lock | 44 ++++++++++++------- 19 files changed, 88 insertions(+), 85 deletions(-) diff --git a/packages/dappmanager/package.json b/packages/dappmanager/package.json index 1adb07bd1..6794102c9 100644 --- a/packages/dappmanager/package.json +++ b/packages/dappmanager/package.json @@ -38,7 +38,7 @@ "@dappnode/optimism": "^0.1.0", "@dappnode/params": "^0.1.0", "@dappnode/stakers": "^0.1.0", - "@dappnode/toolkit": "^0.1.21", + "@dappnode/toolkit": "^0.1.22", "@dappnode/types": "^0.1.36", "@dappnode/upnpc": "^0.1.0", "@dappnode/utils": "^0.1.0", @@ -65,7 +65,7 @@ "cookie-session": "^1.4.0", "cors": "^2.8.5", "deepmerge": "^2.2.1", - "ethers": "^6.9.0", + "ethers": "^6.10.0", "express": "^4.17.1", "express-fileupload": "^1.4.0", "express-rate-limit": "^6.7.0", diff --git a/packages/dappmanager/src/api/middlewares/ethForward/resolveDomain.ts b/packages/dappmanager/src/api/middlewares/ethForward/resolveDomain.ts index 17d8dd314..980adde61 100644 --- a/packages/dappmanager/src/api/middlewares/ethForward/resolveDomain.ts +++ b/packages/dappmanager/src/api/middlewares/ethForward/resolveDomain.ts @@ -1,5 +1,5 @@ import { ethers } from "ethers"; -import { getEthUrl } from "@dappnode/installer"; +import { getEthersProvider, getEthUrl } from "@dappnode/installer"; import resolverAbi from "./abi/resolverAbi.json" assert { type: "json" }; import ensAbi from "./abi/ens.json" assert { type: "json" }; import { Network, Content, NotFoundError, EnsResolverError } from "./types.js"; @@ -61,7 +61,7 @@ export function ResolveDomainWithCache(): (domain: string) => Promise { return async function (domain: string): Promise { const network = parseNetworkFromDomain(domain); const providerUrl = await _getEthersProviderByNetwork(network); - const provider = new ethers.JsonRpcProvider(providerUrl, "mainnet", { staticNetwork: true }); + const provider = await getEthersProvider(providerUrl); return _resolveDomain(domain, provider); }; } diff --git a/packages/dappmanager/src/calls/fetchDirectory.ts b/packages/dappmanager/src/calls/fetchDirectory.ts index 8a6c5fd5f..631171b28 100644 --- a/packages/dappmanager/src/calls/fetchDirectory.ts +++ b/packages/dappmanager/src/calls/fetchDirectory.ts @@ -8,7 +8,7 @@ import { getIsUpdated } from "@dappnode/utils"; import { throttle } from "lodash-es"; -import { getEthUrl } from "@dappnode/installer"; +import { getEthersProvider } from "@dappnode/installer"; import { DappNodeDirectory } from "@dappnode/toolkit"; import { dappnodeInstaller } from "../index.js"; @@ -18,8 +18,7 @@ const loadThrottle = 500; // 0.5 seconds * Fetches all package names in the custom dappnode directory. */ export async function fetchDirectory(): Promise { - const providerUrl = await getEthUrl(); - const directory = new DappNodeDirectory(providerUrl); + const directory = new DappNodeDirectory(await getEthersProvider()) ; const installedDnpList = await listPackages(); diff --git a/packages/dappmanager/src/index.ts b/packages/dappmanager/src/index.ts index dc7cc0a48..bcd6b3975 100644 --- a/packages/dappmanager/src/index.ts +++ b/packages/dappmanager/src/index.ts @@ -10,6 +10,7 @@ import { } from "@dappnode/hostscriptsservices"; import { DappnodeInstaller, + getEthersProvider, getEthUrl, getIpfsUrl, postRestartPatch @@ -58,9 +59,9 @@ try { } // Required db to be initialized -export const dappnodeInstaller = new DappnodeInstaller(ipfsUrl, ethUrl); +export const dappnodeInstaller = new DappnodeInstaller(ipfsUrl, await getEthersProvider()); -export const publicRegistry = new DappNodeRegistry(ethUrl, "public"); +export const publicRegistry = new DappNodeRegistry(await getEthersProvider(), "public"); // TODO: find a way to move the velow constants to the api itself const vpnApiClient = getVpnApiClient(params); diff --git a/packages/dyndns/package.json b/packages/dyndns/package.json index 549ac3b45..9a230dedf 100644 --- a/packages/dyndns/package.json +++ b/packages/dyndns/package.json @@ -22,7 +22,7 @@ "@dappnode/db": "^0.1.0", "@dappnode/logger": "^0.1.0", "@dappnode/params": "^0.1.0", - "ethers": "^6.9.0", + "ethers": "^6.10.0", "node-fetch": "^3.3.2" }, "devDependencies": { diff --git a/packages/installer/package.json b/packages/installer/package.json index 879aabe40..65c2311cd 100644 --- a/packages/installer/package.json +++ b/packages/installer/package.json @@ -29,10 +29,10 @@ "@dappnode/logger": "^0.1.0", "@dappnode/params": "^0.1.0", "@dappnode/schemas": "^0.1.14", - "@dappnode/toolkit": "^0.1.21", + "@dappnode/toolkit": "^0.1.22", "@dappnode/utils": "^0.1.0", "deepmerge": "2.2.1", - "ethers": "^6.9.0", + "ethers": "^6.10.0", "is-ipfs": "8.0.1", "lodash-es": "4.17.21", "node-fetch": "^3.3.2", diff --git a/packages/installer/src/dappnodeInstaller.ts b/packages/installer/src/dappnodeInstaller.ts index 26420aa94..5c6b3e8e0 100644 --- a/packages/installer/src/dappnodeInstaller.ts +++ b/packages/installer/src/dappnodeInstaller.ts @@ -27,8 +27,9 @@ import { computeGlobalEnvsFromDb } from "@dappnode/db"; import { getIsCore } from "@dappnode/utils"; import { sanitizeDependencies } from "./dappGet/utils/sanitizeDependencies.js"; import { parseTimeoutSeconds } from "./utils.js"; -import { getEthUrl } from "./ethClient/index.js"; +import { getEthersProvider } from "./ethClient/index.js"; import { omit } from "lodash-es"; +import { ethers } from "ethers"; /** * Returns the ipfsUrl to initialize the ipfs instance @@ -46,14 +47,13 @@ export function getIpfsUrl(): string { } export class DappnodeInstaller extends DappnodeRepository { - constructor(ipfsUrl: string, ethUrl: string, timeout?: number) { - super(ipfsUrl, ethUrl, timeout); + constructor(ipfsUrl: string, ethersProvider: ethers.JsonRpcProvider, timeout?: number) { + super(ipfsUrl, ethersProvider, timeout); } private async updateProviders(): Promise { - const newEthUrl = await getEthUrl(); const newIpfsUrl = getIpfsUrl(); - super.changeEthProvider(newEthUrl); + super.changeEthProvider(await getEthersProvider()); super.changeIpfsProvider(newIpfsUrl); } diff --git a/packages/installer/src/ethClient/clientStatus.ts b/packages/installer/src/ethClient/clientStatus.ts index 1ef6d532b..7f7370f56 100644 --- a/packages/installer/src/ethClient/clientStatus.ts +++ b/packages/installer/src/ethClient/clientStatus.ts @@ -8,6 +8,7 @@ import { parseEthersBlock, parseEthersSyncing } from "@dappnode/utils"; import { logs } from "@dappnode/logger"; import fetch from "node-fetch"; import { params } from "@dappnode/params"; +import { getEthersProvider } from "./ethersProvider.js"; /** * 7200 is the average blocks per day in Ethereum as Mon Nov 28 2022 @@ -174,23 +175,11 @@ export async function getMultiClientStatus( async function isSyncedWithRemoteExecution(localUrl: string): Promise { if (db.ethClientFallback.get() === "off") return true; // Check is synced with remote execution - const latestLocalBlock = await new ethers.JsonRpcProvider( - localUrl, - "mainnet", - { - staticNetwork: true, - } - ) + const latestLocalBlock = await (await getEthersProvider(localUrl)) .send("eth_blockNumber", []) .then(parseEthersBlock); - const latestRemoteBlock = await new ethers.JsonRpcProvider( - params.ETH_MAINNET_RPC_URL_REMOTE, - "mainnet", - { - staticNetwork: true, - } - ) + const latestRemoteBlock = await (await getEthersProvider(params.ETH_MAINNET_RPC_URL_REMOTE)) .send("eth_blockNumber", []) .then(parseEthersBlock); @@ -204,9 +193,7 @@ async function isSyncedWithRemoteExecution(localUrl: string): Promise { * @param url "http://geth.dappnode:8545" */ async function isSyncing(url: string): Promise { - const provider = new ethers.JsonRpcProvider(url, "mainnet", { - staticNetwork: true, - }); + const provider = await getEthersProvider(url); const syncing = await provider .send("eth_syncing", []) .then(parseEthersSyncing); @@ -238,9 +225,7 @@ async function isApmStateCorrect(url: string): Promise { const result = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000342f697066732f516d63516958454c42745363646278464357454a517a69664d54736b4e5870574a7a7a5556776d754e336d4d4361000000000000000000000000"; - const provider = new ethers.JsonRpcProvider(url, "mainnet", { - staticNetwork: true, - }); + const provider = await getEthersProvider(url); const res = await provider.send("eth_call", [testTxData, "latest"]); return res === result; @@ -257,9 +242,7 @@ async function isSyncedWithConsensus( execUrl: string, consUrl: string ): Promise { - const provider = new ethers.JsonRpcProvider(execUrl, "mainnet", { - staticNetwork: true, - }); + const provider = await getEthersProvider(execUrl); const execBlockNumber = await provider.getBlockNumber(); const execBlockHeadersResponse = await fetch( consUrl + "/eth/v2/beacon/blocks/head" diff --git a/packages/installer/src/ethClient/ethersProvider.ts b/packages/installer/src/ethClient/ethersProvider.ts index ebdd91dda..350806228 100644 --- a/packages/installer/src/ethClient/ethersProvider.ts +++ b/packages/installer/src/ethClient/ethersProvider.ts @@ -5,15 +5,28 @@ import { getMultiClientStatus } from "./clientStatus.js"; import { EthClientStatusError, EthProviderError } from "@dappnode/types"; import { emitSyncedNotification } from "./syncedNotification.js"; import { ethereumClient } from "./index.js"; +import { FetchRequest } from "ethers"; /** * Returns the url of the JSON RPC an Eth multi-client status and target * If the package target is not active it returns the remote URL * @returns initialized ethers instance */ -export async function getEthersProvider(): Promise { - const url = await getEthUrl(); - return new ethers.JsonRpcProvider(url, "mainnet", { staticNetwork: true }); +export async function getEthersProvider( + url?: string, + network?: string +): Promise { + const rpcUrl = url ?? (await getEthUrl()); + const rpcNetwork = network ?? "mainnet"; + const fetchRequest = new FetchRequest(rpcUrl); + const versionData = db.versionData.get(); + fetchRequest.setHeader( + "x-dappmanager-version", + `${versionData.version}-${db.versionData.get().commit?.slice(0, 8)}` + ); + return new ethers.JsonRpcProvider(fetchRequest, rpcNetwork, { + staticNetwork: true, + }); } /** diff --git a/packages/toolkit/package.json b/packages/toolkit/package.json index 72e396a86..3df42cf82 100644 --- a/packages/toolkit/package.json +++ b/packages/toolkit/package.json @@ -1,7 +1,7 @@ { "name": "@dappnode/toolkit", "type": "module", - "version": "0.1.21", + "version": "0.1.22", "description": "The DappNode Toolkit is a collection of shared smart contracts, types, and utility functions that can be used across various DappNode projects. This toolkit aims to simplify development by providing reusable code and a consistent set of interfaces and types. The package includes modules for ACL, APM, Apps, EVMScript, Params, Registry, and Types, each with their own set of submodules and functionalities. The toolkit is designed to be extensible, allowing for the easy addition of new modules as needed. Additionally, the toolkit includes comprehensive testing functionality and documentation to ensure the quality and usability of the code.", "main": "dist/index.js", "scripts": { diff --git a/packages/toolkit/src/directory/directory.ts b/packages/toolkit/src/directory/directory.ts index 5489489e2..1c8e12eb1 100644 --- a/packages/toolkit/src/directory/directory.ts +++ b/packages/toolkit/src/directory/directory.ts @@ -14,11 +14,11 @@ export class DappNodeDirectory { * Class constructor * @param ethUrl - The URL of the Ethereum node to connect to. */ - constructor(ethUrl: string) { + constructor(ethersProvider: ethers.AbstractProvider) { this.directoryContract = new ethers.Contract( directoryAddress, directoryAbi, - new ethers.JsonRpcProvider(ethUrl, "mainnet", { staticNetwork: true }) + ethersProvider ); } diff --git a/packages/toolkit/src/registry/registry.ts b/packages/toolkit/src/registry/registry.ts index ade3453c9..a9570b24b 100644 --- a/packages/toolkit/src/registry/registry.ts +++ b/packages/toolkit/src/registry/registry.ts @@ -26,7 +26,7 @@ export class DappNodeRegistry { * @param ethUrl - The URL of the Ethereum node to connect to. * @param registry - The type of the registry (DNP or Public). */ - constructor(ethUrl: string, registry: Registry) { + constructor(ethersProvider: ethers.AbstractProvider, registry: Registry) { this.registry = registry; if (registry === "dnp") { this.contractAddress = registryDnpAddress; @@ -35,11 +35,10 @@ export class DappNodeRegistry { this.contractAddress = registryPublicAddress; this.graphEndpoint = publicRegistryGraphEndpoint; } - this.registryContract = new ethers.Contract( this.contractAddress, registryAbi, - new ethers.JsonRpcProvider(ethUrl, "mainnet", { staticNetwork: true }) + ethersProvider ); this.nameSuffix = diff --git a/packages/toolkit/src/repository/apmRepository.ts b/packages/toolkit/src/repository/apmRepository.ts index 07f303ebb..c65c2b4e8 100644 --- a/packages/toolkit/src/repository/apmRepository.ts +++ b/packages/toolkit/src/repository/apmRepository.ts @@ -13,28 +13,22 @@ import { repositoryAbi } from "./params.js"; * ApmRepository is a class to interact with the DAppNode APM Repository Contract. */ export class ApmRepository { - private ethProvider: ethers.Provider; + private ethProvider: ethers.AbstractProvider; /** * Class constructor * @param ethUrl - The URL of the Ethereum node to connect to. */ - constructor(ethUrl: string) { - if (!ethUrl) throw new Error("Ethereum URL is required"); - this.ethProvider = new ethers.JsonRpcProvider(ethUrl, "mainnet", { - staticNetwork: true, - }); + constructor(ethersProvider: ethers.AbstractProvider) { + this.ethProvider = ethersProvider; } /** * Changes the Ethereum node to connect to. * @param ethUrl - The URL of the Ethereum node to connect to. */ - public changeEthProvider(ethUrl: string): void { - if (!ethUrl) throw new Error("Ethereum URL is required"); - this.ethProvider = new ethers.JsonRpcProvider(ethUrl, "mainnet", { - staticNetwork: true, - }); + public changeEthProvider(ethersProvider: ethers.AbstractProvider): void { + this.ethProvider = ethersProvider; } /** diff --git a/packages/toolkit/src/repository/repository.ts b/packages/toolkit/src/repository/repository.ts index 9fc02262c..652039589 100644 --- a/packages/toolkit/src/repository/repository.ts +++ b/packages/toolkit/src/repository/repository.ts @@ -32,6 +32,7 @@ import { } from "./releaseSignature.js"; import { isEnsDomain } from "../isEnsDomain.js"; import { dappnodeRegistry } from "./params.js"; +import { ethers } from "ethers"; const source = "ipfs" as const; @@ -50,8 +51,8 @@ export class DappnodeRepository extends ApmRepository { * @param ipfsUrl - The URL of the IPFS network node. * @param ethUrl - The URL of the Ethereum node to connect to. */ - constructor(ipfsUrl: string, ethUrl: string, timeout?: number) { - super(ethUrl); + constructor(ipfsUrl: string, ethersProvider: ethers.AbstractProvider, timeout?: number) { + super(ethersProvider); this.timeout = timeout || 30 * 1000; this.ipfs = create({ url: ipfsUrl, timeout: this.timeout }); } diff --git a/packages/toolkit/test/directory/directory.test.ts b/packages/toolkit/test/directory/directory.test.ts index 60648084c..e30666af5 100644 --- a/packages/toolkit/test/directory/directory.test.ts +++ b/packages/toolkit/test/directory/directory.test.ts @@ -5,7 +5,7 @@ import { expect } from "chai"; describe.skip("Dappnode Directory", function () { this.timeout(100000); const contract = new DappNodeDirectory( - `https://mainnet.infura.io/v3/${process.env.INFURA_MAINNET_KEY}` + new ethers.InfuraProvider("mainnet", process.env.INFURA_MAINNET_KEY) ); it(`should get directory pkgs`, async () => { diff --git a/packages/toolkit/test/registry/registry.test.ts b/packages/toolkit/test/registry/registry.test.ts index 1eaff7530..8abd74391 100644 --- a/packages/toolkit/test/registry/registry.test.ts +++ b/packages/toolkit/test/registry/registry.test.ts @@ -716,7 +716,7 @@ describe("Dappnode Registry", function () { }, ]; const contract = new DappNodeRegistry( - `https://mainnet.infura.io/v3/${process.env.INFURA_MAINNET_KEY}`, + new ethers.InfuraProvider("mainnet", process.env.INFURA_MAINNET_KEY), "dnp" ); const result = await contract.queryGraphNewRepos<"dnp">(); @@ -1254,7 +1254,7 @@ describe("Dappnode Registry", function () { ]; const contract = new DappNodeRegistry( - `https://mainnet.infura.io/v3/${process.env.INFURA_MAINNET_KEY}`, + new ethers.InfuraProvider("mainnet", process.env.INFURA_MAINNET_KEY), "public" ); diff --git a/packages/toolkit/test/repository/repository.test.ts b/packages/toolkit/test/repository/repository.test.ts index 72b6ed16f..fc33ca7ac 100644 --- a/packages/toolkit/test/repository/repository.test.ts +++ b/packages/toolkit/test/repository/repository.test.ts @@ -5,10 +5,11 @@ import path from "path"; import fs from "fs"; import { createHash } from "crypto"; import { ReleaseSignatureStatusCode, TrustedReleaseKey } from "@dappnode/types"; +import { ethers } from "ethers"; -describe("Dappnode Repository", function () { +describe.skip("Dappnode Repository", function () { const ipfsUrls = [ - "https://api.ipfs.dappnode.io", + //"https://api.ipfs.dappnode.io", "https://gateway.ipfs.dappnode.io", ]; @@ -29,7 +30,7 @@ describe("Dappnode Repository", function () { this.timeout(100000); const contract = new DappnodeRepository( ipfsUrl, - `https://mainnet.infura.io/v3/${process.env.INFURA_MAINNET_KEY}` + new ethers.InfuraProvider("mainnet", process.env.INFURA_MAINNET_KEY) ); it(`[${ipfsUrl}] Should get and validate package version for Prysm:${prysmVersion}`, async () => { diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index c49e6dacf..e5c33e8a0 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -49,4 +49,4 @@ export { computeSemverUpdateType } from "./computeSemverUpdateType.js"; export * from "./coreVersionId.js"; export { writeManifest } from "./writeManifest.js"; export { readManifestIfExists } from "./readManifestIfExists.js"; -export { removeCidrSuffix } from "./removeCidrSuffix.js"; +export { removeCidrSuffix } from "./removeCidrSuffix.js"; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 64c0eb439..9599aeb6d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9331,19 +9331,6 @@ ethers@^6.10.0: tslib "2.4.0" ws "8.5.0" -ethers@^6.9.0: - version "6.9.0" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.9.0.tgz#a4534bdcdfde306aee94ef32f3d5c70d7e33fcb9" - integrity sha512-pmfNyQzc2mseLe91FnT2vmNaTt8dDzhxZ/xItAV7uGsF4dI4ek2ufMu3rAkgQETL/TIs0GS5A+U05g9QyWnv3Q== - dependencies: - "@adraffy/ens-normalize" "1.10.0" - "@noble/curves" "1.2.0" - "@noble/hashes" "1.3.2" - "@types/node" "18.15.13" - aes-js "4.0.0-beta.5" - tslib "2.4.0" - ws "8.5.0" - ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -18640,7 +18627,7 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -18658,6 +18645,15 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -18763,7 +18759,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18777,6 +18773,13 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -21014,7 +21017,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -21031,6 +21034,15 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"