diff --git a/karma.conf.cjs b/karma.conf.cjs index dcdf6e3694..12ec027d8d 100644 --- a/karma.conf.cjs +++ b/karma.conf.cjs @@ -1,15 +1,18 @@ const webpack = require("webpack"); -const playwright = require('playwright'); +const playwright = require("playwright"); process.env.CHROME_BIN = playwright.chromium.executablePath(); process.env.FIREFOX_BIN = playwright.firefox.executablePath(); +const path = require("path"); +const tsConfigFile = path.resolve(__dirname, "./tsconfig.dev.json"); + module.exports = function (config) { config.set({ frameworks: ["webpack", "mocha"], files: ["src/**/!(node).spec.ts"], preprocessors: { - "src/**/!(node).spec.ts": ["webpack"] + "src/**/!(node).spec.ts": ["webpack"], }, envPreprocessor: ["CI"], reporters: ["progress"], @@ -17,13 +20,19 @@ module.exports = function (config) { singleRun: true, client: { mocha: { - timeout: 6000 // Default is 2s - } + timeout: 6000, // Default is 2s + }, }, webpack: { mode: "development", module: { - rules: [{ test: /\.([cm]?ts|tsx)$/, loader: "ts-loader" }] + rules: [ + { + test: /\.([cm]?ts|tsx)$/, + loader: "ts-loader", + options: { configFile: tsConfigFile }, + }, + ], }, plugins: [ new webpack.DefinePlugin({ @@ -31,19 +40,19 @@ module.exports = function (config) { "process.env.DISPLAY": "Browser", }), new webpack.ProvidePlugin({ - process: "process/browser.js" - }) + process: "process/browser.js", + }), ], resolve: { extensions: [".ts", ".tsx", ".js"], extensionAlias: { ".js": [".js", ".ts"], ".cjs": [".cjs", ".cts"], - ".mjs": [".mjs", ".mts"] - } + ".mjs": [".mjs", ".mts"], + }, }, stats: { warnings: false }, - devtool: "inline-source-map" - } + devtool: "inline-source-map", + }, }); }; diff --git a/package.json b/package.json index d7a89a8276..1861d56030 100644 --- a/package.json +++ b/package.json @@ -29,9 +29,9 @@ "check": "run-s check:*", "check:workspaces": "npm run check --workspaces --if-present", "check:ws": "[ $(ls -1 ./packages|wc -l) -eq $(cat package.json | jq '.workspaces | length') ] || exit 1 # check no packages left behind", - "test": "NODE_ENV=test npm run test --workspaces --if-present", - "test:browser": "NODE_ENV=test npm run test:browser --workspaces --if-present", - "test:node": "NODE_ENV=test npm run test:node --workspaces --if-present", + "test": "npm run test --workspaces --if-present", + "test:browser": "npm run test:browser --workspaces --if-present", + "test:node": "npm run test:node --workspaces --if-present", "proto": "npm run proto --workspaces --if-present", "deploy": "node ci/deploy.js", "doc": "run-s doc:*", diff --git a/packages/core/package.json b/packages/core/package.json index 30edd99477..0218dfe8a9 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -57,12 +57,12 @@ "fix": "run-s fix:*", "fix:lint": "eslint src *.js --fix", "check": "run-s check:*", - "check:tsc": "tsc -p tsconfig.dev.json", + "check:tsc": "tsc -p tsconfig.json", "check:lint": "eslint src *.js", "check:spelling": "cspell \"{README.md,src/**/*.ts}\"", - "test": "NODE_ENV=test run-s test:*", + "test": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json run-s test:*", "test:node": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json mocha", - "test:browser": "NODE_ENV=test karma start karma.conf.cjs", + "test:browser": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json karma start karma.conf.cjs", "watch:build": "tsc -p tsconfig.json -w", "watch:test": "mocha --watch", "prepublish": "npm run build", diff --git a/packages/core/src/lib/filter/index.ts b/packages/core/src/lib/filter/index.ts index cadf1720c2..b3089b527f 100644 --- a/packages/core/src/lib/filter/index.ts +++ b/packages/core/src/lib/filter/index.ts @@ -110,7 +110,7 @@ class Subscription { async (source) => await all(source) ); - if (!res || !res.length) { + if (!res?.[0]) { throw Error( `No response received for request ${request.requestId}: ${res}` ); @@ -203,7 +203,7 @@ class Subscription { async (source) => await all(source) ); - if (!res || !res.length) { + if (!res?.[0]) { throw Error( `No response received for request ${request.requestId}: ${res}` ); @@ -246,7 +246,7 @@ class Subscription { async (source) => await all(source) ); - if (!res || !res.length) { + if (!res?.[0]) { throw Error( `No response received for request ${request.requestId}: ${res}` ); diff --git a/packages/core/src/lib/filterPeers.ts b/packages/core/src/lib/filterPeers.ts index 816c3bd5b5..1ac1ef76b9 100644 --- a/packages/core/src/lib/filterPeers.ts +++ b/packages/core/src/lib/filterPeers.ts @@ -43,7 +43,10 @@ export function filterPeersByDiscovery( // Fill up to numPeers with remaining random peers if needed while (selectedPeers.length < numPeers && nonBootstrapPeers.length > 0) { const randomIndex = Math.floor(Math.random() * nonBootstrapPeers.length); - const randomPeer = nonBootstrapPeers.splice(randomIndex, 1)[0]; + const randomPeer = nonBootstrapPeers[randomIndex]; + if (!randomPeer) { + continue; + } selectedPeers.push(randomPeer); } diff --git a/packages/core/src/lib/store/index.ts b/packages/core/src/lib/store/index.ts index 8b77adb605..cf6f8b01e2 100644 --- a/packages/core/src/lib/store/index.ts +++ b/packages/core/src/lib/store/index.ts @@ -237,9 +237,12 @@ class Store extends BaseProtocol implements IStore { ); } - // we can be certain that there is only one pubsub topic in the query const pubsubTopicForQuery = uniquePubsubTopicsInQuery[0]; + if (!pubsubTopicForQuery) { + throw Error("Cannot find a pubsub topic to use for query."); + } + ensurePubsubTopicIsConfigured(pubsubTopicForQuery, this.pubsubTopics); // check that the pubsubTopic from the Cursor and Decoder match @@ -287,6 +290,10 @@ class Store extends BaseProtocol implements IStore { }) )[0]; + if (!peer) { + throw Error("Failed executing query: missing a peer."); + } + for await (const messages of paginate( this.getStream.bind(this, peer), queryOpts, diff --git a/packages/core/src/lib/wait_for_remote_peer.ts b/packages/core/src/lib/wait_for_remote_peer.ts index ae5d5cf849..7ae1a35fe9 100644 --- a/packages/core/src/lib/wait_for_remote_peer.ts +++ b/packages/core/src/lib/wait_for_remote_peer.ts @@ -89,7 +89,7 @@ async function waitForConnectedPeer( if (peers.length) { if (!metadataService) { - log.info(`${codec} peer found: `, peers[0].id.toString()); + log.info(`${codec} peer found: `, peers[0]?.id.toString()); return; } diff --git a/packages/dns-discovery/package.json b/packages/dns-discovery/package.json index e0f7aee34f..77f6521b00 100644 --- a/packages/dns-discovery/package.json +++ b/packages/dns-discovery/package.json @@ -40,12 +40,12 @@ "check": "run-s check:*", "check:lint": "eslint src --ext .ts", "check:spelling": "cspell \"{README.md,src/**/*.ts}\"", - "check:tsc": "tsc -p tsconfig.dev.json", + "check:tsc": "tsc -p tsconfig.json", "prepublish": "npm run build", "reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build", - "test": "NODE_ENV=test run-s test:*", + "test": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json run-s test:*", "test:node": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json mocha", - "test:browser": "NODE_ENV=test karma start karma.conf.cjs" + "test:browser": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json karma start karma.conf.cjs" }, "engines": { "node": ">=18" diff --git a/packages/dns-discovery/src/dns.ts b/packages/dns-discovery/src/dns.ts index b17b25d4c5..04d0d6b88b 100644 --- a/packages/dns-discovery/src/dns.ts +++ b/packages/dns-discovery/src/dns.ts @@ -8,7 +8,7 @@ import type { import { Logger } from "@waku/utils"; import { DnsOverHttps } from "./dns_over_https.js"; -import { ENRTree } from "./enrtree.js"; +import { ENRTree, ENRTreeValues } from "./enrtree.js"; import { fetchNodesUntilCapabilitiesFulfilled, yieldNodesUntilCapabilitiesFulfilled @@ -41,8 +41,7 @@ export class DnsNodeDiscovery { enrTreeUrls: string[], wantedNodeCapabilityCount: Partial ): Promise { - const networkIndex = Math.floor(Math.random() * enrTreeUrls.length); - const { publicKey, domain } = ENRTree.parseTree(enrTreeUrls[networkIndex]); + const { publicKey, domain } = DnsNodeDiscovery.parseTree(enrTreeUrls); const context: SearchContext = { domain, publicKey, @@ -78,8 +77,7 @@ export class DnsNodeDiscovery { enrTreeUrls: string[], wantedNodeCapabilityCount: Partial ): AsyncGenerator { - const networkIndex = Math.floor(Math.random() * enrTreeUrls.length); - const { publicKey, domain } = ENRTree.parseTree(enrTreeUrls[networkIndex]); + const { publicKey, domain } = DnsNodeDiscovery.parseTree(enrTreeUrls); const context: SearchContext = { domain, publicKey, @@ -149,8 +147,9 @@ export class DnsNodeDiscovery { subdomain: string, context: SearchContext ): Promise { - if (this._DNSTreeCache[subdomain]) { - return this._DNSTreeCache[subdomain]; + const currentCache = this._DNSTreeCache[subdomain]; + if (currentCache) { + return currentCache; } // Location is either the top level tree entry host or a subdomain of it. @@ -161,9 +160,13 @@ export class DnsNodeDiscovery { const response = await this.dns.resolveTXT(location); - if (!response.length) + if (!response.length) { throw new Error("Received empty result array while fetching TXT record"); - if (!response[0].length) throw new Error("Received empty TXT record"); + } + + if (!response[0]?.length) { + throw new Error("Received empty TXT record"); + } // Branch entries can be an array of strings of comma delimited subdomains, with // some subdomain strings split across the array elements @@ -172,6 +175,17 @@ export class DnsNodeDiscovery { this._DNSTreeCache[subdomain] = result; return result; } + + private static parseTree(enrTreeUrls: string[]): ENRTreeValues { + const networkIndex = Math.floor(Math.random() * enrTreeUrls.length); + const enrTree = enrTreeUrls[networkIndex]; + + if (!enrTree) { + throw Error(`Failed to read ENR tree for the network: ${networkIndex}`); + } + + return ENRTree.parseTree(enrTree); + } } function getEntryType(entry: string): string { @@ -211,5 +225,5 @@ function selectRandomPath(branches: string[], context: SearchContext): string { index = Math.floor(Math.random() * branches.length); } while (circularRefs[index]); - return branches[index]; + return branches[index] as string; } diff --git a/packages/dns-discovery/src/enrtree.ts b/packages/dns-discovery/src/enrtree.ts index 7a1412c29b..f6023bb912 100644 --- a/packages/dns-discovery/src/enrtree.ts +++ b/packages/dns-discovery/src/enrtree.ts @@ -40,6 +40,10 @@ export class ENRTree { // (Trailing recovery bit must be trimmed to pass `ecdsaVerify` method) const signedComponent = root.split(" sig")[0]; + if (!signedComponent) { + throw Error(`Signature component is missing, got: ${signedComponent}`); + } + const signedComponentBuffer = utf8ToBytes(signedComponent); const signatureBuffer = fromString(rootValues.signature, "base64url").slice( 0, @@ -113,11 +117,18 @@ export class ENRTree { * either further branch entries or ENR records. */ static parseBranch(branch: string): string[] { - if (!branch.startsWith(this.BRANCH_PREFIX)) - throw new Error( + if (!branch.startsWith(this.BRANCH_PREFIX)) { + throw Error( `ENRTree branch entry must start with '${this.BRANCH_PREFIX}'` ); + } + + const enrPart = branch.split(this.BRANCH_PREFIX)[1]; + + if (!enrPart) { + throw Error(`ENRTree branch does not have data`); + } - return branch.split(this.BRANCH_PREFIX)[1].split(","); + return enrPart.split(","); } } diff --git a/packages/enr/package.json b/packages/enr/package.json index 77fcf5ff8f..eda46bfc37 100644 --- a/packages/enr/package.json +++ b/packages/enr/package.json @@ -40,10 +40,10 @@ "check": "run-s check:*", "check:lint": "eslint src --ext .ts", "check:spelling": "cspell \"{README.md,src/**/*.ts}\"", - "check:tsc": "tsc -p tsconfig.dev.json", - "test": "NODE_ENV=test run-s test:*", + "check:tsc": "tsc -p tsconfig.json", + "test": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json run-s test:*", "test:node": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json mocha", - "test:browser": "NODE_ENV=test karma start karma.conf.cjs", + "test:browser": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json karma start karma.conf.cjs", "prepublish": "npm run build", "reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build" }, diff --git a/packages/enr/src/decoder.ts b/packages/enr/src/decoder.ts index e01cd5f189..06e3571b74 100644 --- a/packages/enr/src/decoder.ts +++ b/packages/enr/src/decoder.ts @@ -30,7 +30,7 @@ async function fromValues(values: Uint8Array[]): Promise { const obj: Record = {}; for (let i = 0; i < kvs.length; i += 2) { try { - obj[bytesToUtf8(kvs[i])] = kvs[i + 1]; + obj[bytesToUtf8(kvs[i] as Uint8Array)] = kvs[i + 1] as Uint8Array; } catch (e) { log.error("Failed to decode ENR key to UTF-8, skipping it", kvs[i], e); } diff --git a/packages/enr/src/enr.ts b/packages/enr/src/enr.ts index edc02f8a08..93c8c7bfa2 100644 --- a/packages/enr/src/enr.ts +++ b/packages/enr/src/enr.ts @@ -73,25 +73,23 @@ export class ENR extends RawEnr implements IEnr { setLocationMultiaddr(multiaddr: Multiaddr): void { const protoNames = multiaddr.protoNames(); - if ( - protoNames.length !== 2 && - protoNames[1] !== "udp" && - protoNames[1] !== "tcp" - ) { + const protocol = protoNames[1]; + if (protoNames.length !== 2 && protocol !== "udp" && protocol !== "tcp") { throw new Error("Invalid multiaddr"); } + const tuples = multiaddr.tuples(); - if (!tuples[0][1] || !tuples[1][1]) { + if (!tuples[0]?.[1] || !tuples[1]?.[1] || !protocol) { throw new Error("Invalid multiaddr"); } // IPv4 if (tuples[0][0] === 4) { this.set("ip", tuples[0][1]); - this.set(protoNames[1], tuples[1][1]); + this.set(protocol, tuples[1][1]); } else { this.set("ip6", tuples[0][1]); - this.set(protoNames[1] + "6", tuples[1][1]); + this.set(protocol + "6", tuples[1][1]); } } diff --git a/packages/enr/src/raw_enr.ts b/packages/enr/src/raw_enr.ts index b7c607880e..b1e828a7e9 100644 --- a/packages/enr/src/raw_enr.ts +++ b/packages/enr/src/raw_enr.ts @@ -153,7 +153,7 @@ export class RawEnr extends Map { */ get waku2(): Waku2 | undefined { const raw = this.get("waku2"); - if (raw) return decodeWaku2(raw[0]); + if (raw) return decodeWaku2(raw[0] as number); return; } diff --git a/packages/interfaces/package.json b/packages/interfaces/package.json index 8b0a51c5a5..da62669a23 100644 --- a/packages/interfaces/package.json +++ b/packages/interfaces/package.json @@ -39,7 +39,7 @@ "check": "run-s check:*", "check:lint": "eslint src", "check:spelling": "cspell \"{README.md,src/**/*.ts}\"", - "check:tsc": "tsc -p tsconfig.dev.json", + "check:tsc": "tsc -p tsconfig.json", "prepublish": "npm run build", "reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build" }, diff --git a/packages/message-encryption/package.json b/packages/message-encryption/package.json index 6cc43e9b10..27cd7b54cb 100644 --- a/packages/message-encryption/package.json +++ b/packages/message-encryption/package.json @@ -61,10 +61,10 @@ "check": "run-s check:*", "check:lint": "eslint src *.js", "check:spelling": "cspell \"{README.md,src/**/*.ts}\"", - "check:tsc": "tsc -p tsconfig.dev.json", - "test": "NODE_ENV=test run-s test:*", + "check:tsc": "tsc -p tsconfig.json", + "test": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json run-s test:*", "test:node": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json mocha", - "test:browser": "NODE_ENV=test karma start karma.conf.cjs", + "test:browser": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json karma start karma.conf.cjs", "prepublish": "npm run build", "reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build" }, diff --git a/packages/message-encryption/src/crypto/ecies.ts b/packages/message-encryption/src/crypto/ecies.ts index a53d3ef558..5fc04141ee 100644 --- a/packages/message-encryption/src/crypto/ecies.ts +++ b/packages/message-encryption/src/crypto/ecies.ts @@ -185,8 +185,12 @@ export async function decrypt( (macKey) => [hash.slice(0, 16), macKey] ); + if (!encryptionKey || !macKey) { + throw Error("Failed to get parameters from the hash."); + } + if (!(await hmacSha256Verify(macKey, cipherAndIv, msgMac))) { - throw new Error("Incorrect MAC"); + throw Error("Incorrect MAC"); } return aesCtrDecrypt(iv, encryptionKey, ciphertext); diff --git a/packages/message-hash/package.json b/packages/message-hash/package.json index fd420f6156..d4e1bdde5d 100644 --- a/packages/message-hash/package.json +++ b/packages/message-hash/package.json @@ -35,12 +35,12 @@ "fix": "run-s fix:*", "fix:lint": "eslint src *.js --fix", "check": "run-s check:*", - "check:tsc": "tsc -p tsconfig.dev.json", + "check:tsc": "tsc -p tsconfig.json", "check:lint": "eslint src *.js", "check:spelling": "cspell \"{README.md,src/**/*.ts}\"", - "test": "NODE_ENV=test run-s test:*", + "test": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json run-s test:*", "test:node": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json mocha", - "test:browser": "NODE_ENV=test karma start karma.conf.cjs", + "test:browser": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json karma start karma.conf.cjs", "watch:build": "tsc -p tsconfig.json -w", "watch:test": "mocha --watch", "prepublish": "npm run build", diff --git a/packages/peer-exchange/package.json b/packages/peer-exchange/package.json index 624cd23d14..3c9f221c0f 100644 --- a/packages/peer-exchange/package.json +++ b/packages/peer-exchange/package.json @@ -40,7 +40,7 @@ "check": "run-s check:*", "check:lint": "eslint src *.js", "check:spelling": "cspell \"{README.md,src/**/*.ts}\"", - "check:tsc": "tsc -p tsconfig.dev.json", + "check:tsc": "tsc -p tsconfig.json", "prepublish": "npm run build", "reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build" }, diff --git a/packages/proto/package.json b/packages/proto/package.json index eba220e078..ddf35ef771 100644 --- a/packages/proto/package.json +++ b/packages/proto/package.json @@ -36,7 +36,7 @@ "build:esm": "tsc", "build:bundle": "rollup --config rollup.config.js", "proto": "rimraf src/lib/*.ts; protons src/lib/*.proto", - "check:tsc": "tsc -p tsconfig.dev.json", + "check:tsc": "tsc -p tsconfig.json", "prepublish": "npm run build", "reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build" }, diff --git a/packages/relay/package.json b/packages/relay/package.json index 9576b053c6..59798148d1 100644 --- a/packages/relay/package.json +++ b/packages/relay/package.json @@ -35,11 +35,11 @@ "fix": "run-s fix:*", "fix:lint": "eslint src *.js --fix", "check": "run-s check:*", - "check:tsc": "tsc -p tsconfig.dev.json", + "check:tsc": "tsc -p tsconfig.json", "check:lint": "eslint src *.js", "check:spelling": "cspell \"{README.md,src/**/*.ts}\"", - "test": "NODE_ENV=test run-s test:*", - "test:node": "TS_NODE_PROJECT=./tsconfig.dev.json mocha", + "test": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json run-s test:*", + "test:node": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json mocha", "watch:build": "tsc -p tsconfig.json -w", "watch:test": "mocha --watch", "prepublish": "npm run build", diff --git a/packages/relay/src/constants.ts b/packages/relay/src/constants.ts index 067084d991..6c02e4d59b 100644 --- a/packages/relay/src/constants.ts +++ b/packages/relay/src/constants.ts @@ -4,7 +4,7 @@ export const minute = 60 * second; /** * RelayCodec is the libp2p identifier for the waku relay protocol */ -export const RelayCodecs = ["/vac/waku/relay/2.0.0"]; +export const RelayCodec = "/vac/waku/relay/2.0.0"; /** * RelayGossipFactor affects how many peers we will emit gossip to at each heartbeat. diff --git a/packages/relay/src/index.ts b/packages/relay/src/index.ts index a5f6f241f7..1fc224e9b6 100644 --- a/packages/relay/src/index.ts +++ b/packages/relay/src/index.ts @@ -28,7 +28,7 @@ import { isWireSizeUnderCap, toAsyncIterator } from "@waku/utils"; import { pushOrInitMapSet } from "@waku/utils"; import { Logger } from "@waku/utils"; -import { RelayCodecs } from "./constants.js"; +import { RelayCodec } from "./constants.js"; import { messageValidator } from "./message_validator.js"; import { TopicOnlyDecoder } from "./topic_only_message.js"; @@ -50,7 +50,7 @@ class Relay implements IRelay { public readonly pubsubTopics: Set; private defaultDecoder: IDecoder; - public static multicodec: string = RelayCodecs[0]; + public static multicodec: string = RelayCodec; public readonly gossipSub: GossipSub; /** @@ -292,7 +292,7 @@ export function wakuGossipSub( fallbackToFloodsub: false }; const pubsub = new GossipSub(components, init); - pubsub.multicodecs = RelayCodecs; + pubsub.multicodecs = [RelayCodec]; return pubsub; }; } diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 9181543b16..56d2230acb 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -53,7 +53,7 @@ "check": "run-s check:*", "check:lint": "eslint src *.js", "check:spelling": "cspell \"{README.md,src/**/*.ts}\"", - "check:tsc": "tsc -p tsconfig.dev.json", + "check:tsc": "tsc -p tsconfig.json", "prepublish": "npm run build", "reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build" }, diff --git a/packages/tests/package.json b/packages/tests/package.json index 9fbb1ab196..e61436f54f 100644 --- a/packages/tests/package.json +++ b/packages/tests/package.json @@ -41,9 +41,9 @@ "check:lint": "eslint src tests", "check:spelling": "cspell \"{README.md,{tests,src}/**/*.ts}\"", "check:tsc": "tsc -p tsconfig.dev.json", - "test": "NODE_ENV=test run-s test:*", - "test:node": "NODE_ENV=test node ./src/run-tests.js \"tests/**/!(*.optional).spec.ts\"", - "test:optional": "NODE_ENV=test node ./src/run-tests.js \"tests/**/@(*.optional).spec.ts\"", + "test": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json run-s test:*", + "test:node": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json node ./src/run-tests.js \"tests/**/!(*.optional).spec.ts\"", + "test:optional": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json node ./src/run-tests.js \"tests/**/@(*.optional).spec.ts\"", "reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build" }, "engines": { diff --git a/packages/tests/tests/store/multiple_pubsub.spec.ts b/packages/tests/tests/store/multiple_pubsub.spec.ts index cfac638e96..e76494f100 100644 --- a/packages/tests/tests/store/multiple_pubsub.spec.ts +++ b/packages/tests/tests/store/multiple_pubsub.spec.ts @@ -3,8 +3,7 @@ import type { ContentTopicInfo, IMessage, LightNode } from "@waku/interfaces"; import { createLightNode, Protocols } from "@waku/sdk"; import { contentTopicToPubsubTopic, - pubsubTopicToSingleShardInfo, - singleShardInfosToShardInfo + pubsubTopicToSingleShardInfo } from "@waku/utils"; import { expect } from "chai"; @@ -31,6 +30,7 @@ import { sendMessagesAutosharding, shardInfo1, shardInfoBothShards, + singleShardInfosToShardInfo, startAndConnectLightNode, totalMsgs } from "./utils.js"; diff --git a/packages/tests/tests/store/utils.ts b/packages/tests/tests/store/utils.ts index d1b88161d0..e1225358c8 100644 --- a/packages/tests/tests/store/utils.ts +++ b/packages/tests/tests/store/utils.ts @@ -148,3 +148,23 @@ export const adjustDate = (baseDate: Date, adjustMs: number): Date => { adjusted.setTime(adjusted.getTime() + adjustMs); return adjusted; }; + +export const singleShardInfosToShardInfo = ( + singleShardInfos: SingleShardInfo[] +): ShardInfo => { + if (singleShardInfos.length === 0) throw new Error("Invalid shard"); + + const clusterIds = singleShardInfos.map((shardInfo) => shardInfo.clusterId); + if (new Set(clusterIds).size !== 1) { + throw new Error("Passed shard infos have different clusterIds"); + } + + const shards = singleShardInfos + .map((shardInfo) => shardInfo.shard) + .filter((shard): shard is number => shard !== undefined); + + return { + clusterId: singleShardInfos[0].clusterId, + shards + }; +}; diff --git a/packages/tests/tsconfig.json b/packages/tests/tsconfig.json index 693102ecc2..36c4347b3b 100644 --- a/packages/tests/tsconfig.json +++ b/packages/tests/tsconfig.json @@ -3,7 +3,8 @@ "compilerOptions": { "outDir": "dist/", "rootDir": "src", - "tsBuildInfoFile": "dist/.tsbuildinfo" + "tsBuildInfoFile": "dist/.tsbuildinfo", + "noUncheckedIndexedAccess": false, }, "include": ["src", "src/run-tests.js"], "exclude": ["src/**/*.spec.ts", "src/test_utils"] diff --git a/packages/utils/package.json b/packages/utils/package.json index 77341da5aa..f36ce82b3c 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -57,7 +57,7 @@ "check": "run-s check:*", "check:lint": "eslint src *.js", "check:spelling": "cspell \"{README.md,src/**/*.ts}\"", - "check:tsc": "tsc -p tsconfig.dev.json", + "check:tsc": "tsc -p tsconfig.json", "prepublish": "npm run build", "reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build", "test": "NODE_ENV=test run-s test:*", diff --git a/packages/utils/src/common/random_subset.ts b/packages/utils/src/common/random_subset.ts index 20d0ca83ce..84ad1d306f 100644 --- a/packages/utils/src/common/random_subset.ts +++ b/packages/utils/src/common/random_subset.ts @@ -22,8 +22,8 @@ function shuffle(arr: T[]): T[] { for (let i = 0; i < arr.length; i++) { const j = randInt(); - const tmp = arr[i]; - arr[i] = arr[j]; + const tmp = arr[i] as T; + arr[i] = arr[j] as T; arr[j] = tmp; } return arr; diff --git a/packages/utils/src/common/relay_shard_codec.ts b/packages/utils/src/common/relay_shard_codec.ts index 91dea7b4ea..063dd3be8a 100644 --- a/packages/utils/src/common/relay_shard_codec.ts +++ b/packages/utils/src/common/relay_shard_codec.ts @@ -52,7 +52,7 @@ export const encodeRelayShard = (shardInfo: ShardInfo): Uint8Array => { // rs format (Index List) view.setUint8(2, shards.length); for (let i = 0, offset = 3; i < shards.length; i++, offset += 2) { - view.setUint16(offset, shards[i]); + view.setUint16(offset, shards[i] as number); } } diff --git a/packages/utils/src/common/sharding.ts b/packages/utils/src/common/sharding.ts index 236ebc0f1f..67c7c48da4 100644 --- a/packages/utils/src/common/sharding.ts +++ b/packages/utils/src/common/sharding.ts @@ -19,26 +19,6 @@ export const singleShardInfoToPubsubTopic = ( return `/waku/2/rs/${shardInfo.clusterId}/${shardInfo.shard}`; }; -export const singleShardInfosToShardInfo = ( - singleShardInfos: SingleShardInfo[] -): ShardInfo => { - if (singleShardInfos.length === 0) throw new Error("Invalid shard"); - - const clusterIds = singleShardInfos.map((shardInfo) => shardInfo.clusterId); - if (new Set(clusterIds).size !== 1) { - throw new Error("Passed shard infos have different clusterIds"); - } - - const shards = singleShardInfos - .map((shardInfo) => shardInfo.shard) - .filter((shard): shard is number => shard !== undefined); - - return { - clusterId: singleShardInfos[0].clusterId, - shards - }; -}; - export const shardInfoToPubsubTopics = ( shardInfo: Partial ): PubsubTopic[] => { @@ -80,15 +60,15 @@ export const pubsubTopicToSingleShardInfo = ( const parts = pubsubTopics.split("/"); if ( - parts.length != 6 || + parts.length !== 6 || parts[1] !== "waku" || parts[2] !== "2" || parts[3] !== "rs" ) throw new Error("Invalid pubsub topic"); - const clusterId = parseInt(parts[4]); - const shard = parseInt(parts[5]); + const clusterId = parseInt(parts[4] as string); + const shard = parseInt(parts[5] as string); if (isNaN(clusterId) || isNaN(shard)) throw new Error("Invalid clusterId or shard"); @@ -131,7 +111,7 @@ export function ensureValidContentTopic(contentTopic: string): ContentTopic { // Validate generation field if present let generation = 0; if (parts.length == 6) { - generation = parseInt(parts[1]); + generation = parseInt(parts[1] as string); if (isNaN(generation)) { throw new Error("Invalid generation field in content topic"); } @@ -141,29 +121,33 @@ export function ensureValidContentTopic(contentTopic: string): ContentTopic { } // Validate remaining fields const fields = parts.splice(-4); - // Validate application field - if (fields[0].length == 0) { + + const application = fields[0]; + if (!application || application?.length == 0) { throw new Error("Application field cannot be empty"); } - // Validate version field - if (fields[1].length == 0) { + + const version = fields[1]; + if (!version || version?.length == 0) { throw new Error("Version field cannot be empty"); } - // Validate topic name field - if (fields[2].length == 0) { + + const topicName = fields[2]; + if (!topicName || topicName?.length == 0) { throw new Error("Topic name field cannot be empty"); } - // Validate encoding field - if (fields[3].length == 0) { + + const encoding = fields[3]; + if (!encoding || encoding?.length == 0) { throw new Error("Encoding field cannot be empty"); } return { generation, - application: fields[0], - version: fields[1], - topicName: fields[2], - encoding: fields[3] + application, + version, + topicName, + encoding }; } diff --git a/packages/utils/src/libp2p/index.ts b/packages/utils/src/libp2p/index.ts index 04c37c7d6d..348cc0278c 100644 --- a/packages/utils/src/libp2p/index.ts +++ b/packages/utils/src/libp2p/index.ts @@ -61,7 +61,7 @@ export async function getPeersForProtocol( const peers: Peer[] = []; await peerStore.forEach((peer) => { for (let i = 0; i < protocols.length; i++) { - if (peer.protocols.includes(protocols[i])) { + if (peer.protocols.includes(protocols[i] as string)) { peers.push(peer); break; } diff --git a/tsconfig.dev.json b/tsconfig.dev.json index 17eb953a8b..02ffa814d0 100644 --- a/tsconfig.dev.json +++ b/tsconfig.dev.json @@ -3,6 +3,6 @@ "compilerOptions": { "module": "ESNext", "moduleResolution": "Bundler", - "noEmit": true + "noUncheckedIndexedAccess": false, } } diff --git a/tsconfig.json b/tsconfig.json index 5a268831bf..bbf3bcf06b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -37,6 +37,7 @@ /* Experimental Options */ // "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, // "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, + "noUncheckedIndexedAccess": true, "lib": ["es2022", "dom"], "types": ["node", "mocha"],