From 240478ce2ce01abd6d43c93cfefe4162a5a9ced3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Tue, 6 Jan 2026 21:59:08 +0100 Subject: [PATCH 01/18] refactor [NET-1606]: Bundle `utils` separately for browser and NodeJS (#3321) This pull request introduces significant improvements to the `@streamr/utils` package, focusing on robust browser and Node.js environment support, build configuration enhancements, and codebase modernization. The main changes include a new dual build and export system for browser and Node.js, environment variable handling refactoring, and the replacement of Node.js-specific APIs with cross-platform polyfills. ### Changes **Build and packaging enhancements:** - Added a dual build system using a new `rollup.config.mts` to generate separate browser and Node.js bundles, with appropriate module resolution and aliasing for each environment. (`packages/utils/rollup.config.mts`) - Updated `package.json` to use the `exports` field for conditional exports (browser vs. Node.js), adjusted the `files` array, and added new build scripts and dependencies for Rollup and polyfills. (`packages/utils/package.json`) [[1]](diffhunk://#diff-21f8eb1d7a149d42ab0454ea905d44f624ff1d0aeb6d7a88d75b42962ca6b053L10-R36) [[2]](diffhunk://#diff-21f8eb1d7a149d42ab0454ea905d44f624ff1d0aeb6d7a88d75b42962ca6b053R47-R69) - Introduced a `prebuild` and `postbuild` step to streamline the build process and ensure clean output. (`packages/utils/package.json`) **Cross-platform and polyfill improvements:** - Replaced direct Node.js API usage (e.g., `crypto`, `os`) with cross-platform abstractions and browser polyfills (e.g., `buffer-shim`, `path-browserify`, custom `os` and `env` shims for browsers). (`packages/utils/src/browser/crypto.ts`, `packages/utils/src/browser/env.ts`, `packages/utils/src/browser/os.ts`, `packages/utils/src/exports-browser.ts`, `packages/utils/src/keyToArrayIndex.ts`, `packages/utils/karma.config.ts`) [[1]](diffhunk://#diff-285b8e8fa583afc20697242820c6adb2419720d1c2056c6ecb7d8617060c1a51R1-R23) [[2]](diffhunk://#diff-245bac5c3851ffe8bc18571e59cf298ecb92e78d093c47fb8b1cef8c740174feR1-R5) [[3]](diffhunk://#diff-0106994557e39509eb1269938f670aa46dea2f4ab6e6e0e7c06124b973cfa268R1-R6) [[4]](diffhunk://#diff-394788f4b1559a7010d4d4a1ae7f96a11cb992f358a46090cfb9c1eebfbfac05L1-R1) [[5]](diffhunk://#diff-394788f4b1559a7010d4d4a1ae7f96a11cb992f358a46090cfb9c1eebfbfac05L28-R28) F8929faeL1) - Removed the old `crossPlatformCrypto.ts` in favor of new environment-specific implementations. (`packages/utils/src/crossPlatformCrypto.ts`) **Environment variable handling:** - Refactored all environment variable access to use a unified `env` abstraction, ensuring safe access in both Node.js and browser contexts. (`packages/utils/src/Logger.ts`, `packages/utils/src/browser/env.ts`) [[1]](diffhunk://#diff-312c84735c8ba55bd72f753e86af89e6c8f1b058ac23ac2290d447c64b7fd6d4R5) [[2]](diffhunk://#diff-312c84735c8ba55bd72f753e86af89e6c8f1b058ac23ac2290d447c64b7fd6d4L21-R36) [[3]](diffhunk://#diff-312c84735c8ba55bd72f753e86af89e6c8f1b058ac23ac2290d447c64b7fd6d4L46-R45) [[4]](diffhunk://#diff-312c84735c8ba55bd72f753e86af89e6c8f1b058ac23ac2290d447c64b7fd6d4L98-R97) [[5]](diffhunk://#diff-312c84735c8ba55bd72f753e86af89e6c8f1b058ac23ac2290d447c64b7fd6d4L117-R116) [[6]](diffhunk://#diff-91ff14206456eacaae372406d303b78f2a1ca01c710b6f0f005a8ee20b2cf50eR1-R19) **Testing and configuration:** - Updated Jest and Karma configurations to support new module aliases and environment-specific code paths. (`packages/utils/jest.config.ts`, `packages/utils/karma.config.ts`) ([packages/utils/jest.config.tsL1-R11](diffhunk://#diff-138963f3d6083e08b3091ffdcd032a655c4738ba0a41476560753dd9f6b1efeaL1-R11), F8929faeL1) **Code modernization and cleanup:** - Updated cryptographic utilities to use new cross-platform imports and types, improving maintainability and browser compatibility. (`packages/utils/src/SigningUtil.ts`, `packages/utils/src/exports.ts`) [[1]](diffhunk://#diff-264c1a909477860ce2ed2c73f193874422c99397476f8d74ec602ccd11b80512L9-R9) [[2]](diffhunk://#diff-264c1a909477860ce2ed2c73f193874422c99397476f8d74ec602ccd11b80512L21-L23) [[3]](diffhunk://#diff-264c1a909477860ce2ed2c73f193874422c99397476f8d74ec602ccd11b80512L61-R57) [[4]](diffhunk://#diff-264c1a909477860ce2ed2c73f193874422c99397476f8d74ec602ccd11b80512L94-R90) [[5]](diffhunk://#diff-264c1a909477860ce2ed2c73f193874422c99397476f8d74ec602ccd11b80512L170-R166) [[6]](diffhunk://#diff-264c1a909477860ce2ed2c73f193874422c99397476f8d74ec602ccd11b80512L202-R200) [[7]](diffhunk://#diff-264c1a909477860ce2ed2c73f193874422c99397476f8d74ec602ccd11b80512L232-R231) [[8]](diffhunk://#diff-264c1a909477860ce2ed2c73f193874422c99397476f8d74ec602ccd11b80512L246-R244) [[9]](diffhunk://#diff-264c1a909477860ce2ed2c73f193874422c99397476f8d74ec602ccd11b80512L260-R258) [[10]](diffhunk://#diff-d700ca1a1d7a0254f811405cb99a0f7eba3b8ec8396aede7362c8c842fbb7a56L56-R56) **Additional minor improvements:** - Added `@streamr/utils` to the Docker build bootstrap step. (`Dockerfile.node`) These changes collectively make the `@streamr/utils` package more robust, easier to consume in different environments, and simpler to maintain. --- > [!NOTE] > Modernizes `@streamr/utils` for first-class browser and Node.js support with dual bundles, conditional exports, and polyfilled APIs. > > - New Rollup config (`packages/utils/rollup.config.mts`) outputs `exports-browser.*` and `exports-nodejs.*`; `package.json` uses conditional `exports` and updated build scripts > - Introduces env/crypto platform shims: `src/nodejs/{env,crypto}.ts` and `src/browser/{env,crypto,os}.ts`; removes `src/crossPlatformCrypto.ts` > - Replaces Node-only APIs with cross-platform imports: `Logger` reads from `@/env`; hashing via `computeMd5`; updated `SigningUtil` to use `@/crypto` > - Adds browser entry `src/exports-browser.ts` (includes `buffer-shim`) and path aliases for both envs; updates Jest/Karma configs and tsconfigs (`tsconfig.{node,browser,jest,karma}.json`) > - Updates `packages/utils/package.json` fields (`main/module/types`, `files`) and dependencies (Rollup, plugins, polyfills) > - Docker build now bootstraps `@streamr/utils` in `Dockerfile.node` > > Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit b3774ce419f55c14f16c4ef07c344c6c5a3ec64d. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot). --- Dockerfile.node | 1 + package-lock.json | 2407 ++++++++++++----- packages/utils/jest.config.ts | 12 +- packages/utils/karma.config.ts | 8 +- packages/utils/package.json | 41 +- packages/utils/rollup.config.mts | 156 ++ packages/utils/src/Logger.ts | 19 +- packages/utils/src/SigningUtil.ts | 24 +- packages/utils/src/browser/crypto.ts | 23 + packages/utils/src/browser/env.ts | 19 + packages/utils/src/browser/os.ts | 5 + packages/utils/src/crossPlatformCrypto.ts | 15 - packages/utils/src/exports-browser.ts | 6 + packages/utils/src/exports.ts | 2 +- packages/utils/src/keyToArrayIndex.ts | 5 +- packages/utils/src/nodejs/crypto.ts | 23 + packages/utils/src/nodejs/env.ts | 6 + packages/utils/test/Metric.test.ts | 2 +- .../utils/test/composeAbortSignals.test.ts | 2 +- packages/utils/tsconfig.browser.json | 20 + packages/utils/tsconfig.jest.json | 18 + packages/utils/tsconfig.json | 9 +- packages/utils/tsconfig.karma.json | 10 +- packages/utils/tsconfig.node.json | 24 + tsconfig.browser.json | 28 + 25 files changed, 2184 insertions(+), 701 deletions(-) create mode 100644 packages/utils/rollup.config.mts create mode 100644 packages/utils/src/browser/crypto.ts create mode 100644 packages/utils/src/browser/env.ts create mode 100644 packages/utils/src/browser/os.ts delete mode 100644 packages/utils/src/crossPlatformCrypto.ts create mode 100644 packages/utils/src/exports-browser.ts create mode 100644 packages/utils/src/nodejs/crypto.ts create mode 100644 packages/utils/src/nodejs/env.ts create mode 100644 packages/utils/tsconfig.browser.json create mode 100644 packages/utils/tsconfig.node.json create mode 100644 tsconfig.browser.json diff --git a/Dockerfile.node b/Dockerfile.node index 2e3a36cca5..d9ae3d746f 100644 --- a/Dockerfile.node +++ b/Dockerfile.node @@ -3,6 +3,7 @@ FROM node:${NODE_VERSION}-bullseye AS build WORKDIR /usr/src/network COPY . . RUN --mount=type=cache,target=/root/.npm \ + npm run bootstrap-pkg --package=@streamr/utils && \ npm run bootstrap-pkg --package=@streamr/proto-rpc && \ npm run bootstrap-pkg --package=@streamr/autocertifier-client && \ npm run bootstrap-pkg --package=@streamr/dht && \ diff --git a/package-lock.json b/package-lock.json index cb16735f4a..4233cc3f0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3035,622 +3035,764 @@ "tslib": "^2.4.0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=18" } }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/@esbuild/android-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "cpu": [ + "arm" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@eslint/config-array": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", - "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "node_modules/@esbuild/android-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/@eslint/core": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz", - "integrity": "sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", - "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@esbuild/linux-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "cpu": [ + "loong64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/@eslint/js": { - "version": "9.39.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", - "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "cpu": [ + "mips64el" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" + "node": ">=18" } }, - "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/plugin-kit": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.6.tgz", - "integrity": "sha512-+0TjwR1eAUdZtvv/ir1mGX+v0tUoR3VEPB8Up0LLJC+whRW0GgBBtpbOkg/a/U4Dxa6l5a3l9AJ1aWIQVyoWJA==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "cpu": [ + "riscv64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.11.0", - "levn": "^0.4.1" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "cpu": [ + "s390x" + ], + "dev": true, "license": "MIT", - "optional": true + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "node_modules/@esbuild/linux-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18.18.0" + "node": ">=18" } }, - "node_modules/@humanfs/node": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=18.18.0" + "node": ">=18" } }, - "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=18" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=18" } }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", - "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=18" } }, - "node_modules/@hutson/parse-repository-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", - "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@inquirer/ansi": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.1.tgz", - "integrity": "sha512-yqq0aJW/5XPhi5xOAL1xRCpe1eh8UFVgYFpFsjEqmIR8rKLyP+HINvFXwUaxYICflJrVlxnp7lLN6As735kVpw==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { "node": ">=18" } }, - "node_modules/@inquirer/checkbox": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.0.tgz", - "integrity": "sha512-5+Q3PKH35YsnoPTh75LucALdAxom6xh5D1oeY561x4cqBuH24ZFVyFREPe14xgnrtmGu3EEt1dIi60wRVSnGCw==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.1", - "@inquirer/core": "^10.3.0", - "@inquirer/figures": "^1.0.14", - "@inquirer/type": "^3.0.9", - "yoctocolors-cjs": "^2.1.2" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } } }, - "node_modules/@inquirer/confirm": { - "version": "5.1.19", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.19.tgz", - "integrity": "sha512-wQNz9cfcxrtEnUyG5PndC8g3gZ7lGDBzmWiXZkX8ot3vfZ+/BLjR8EvyGX4YzQLeVqtAlY/YScZpW7CW8qMoDQ==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "cpu": [ + "ia32" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.0", - "@inquirer/type": "^3.0.9" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } } }, - "node_modules/@inquirer/core": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.0.tgz", - "integrity": "sha512-Uv2aPPPSK5jeCplQmQ9xadnFx2Zhj9b5Dj7bU6ZeCdDNNY11nhYy4btcSdtDguHqCT2h5oNeQTcUNSGGLA7NTA==", + "node_modules/@esbuild/win32-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.1", - "@inquirer/figures": "^1.0.14", - "@inquirer/type": "^3.0.9", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } } }, - "node_modules/@inquirer/editor": { - "version": "4.2.21", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.21.tgz", - "integrity": "sha512-MjtjOGjr0Kh4BciaFShYpZ1s9400idOdvQ5D7u7lE6VztPFoyLcVNE5dXBmEEIQq5zi4B9h2kU+q7AVBxJMAkQ==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.0", - "@inquirer/external-editor": "^1.0.2", - "@inquirer/type": "^3.0.9" + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependencies": { - "@types/node": ">=18" + "funding": { + "url": "https://opencollective.com/eslint" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@inquirer/expand": { - "version": "4.0.21", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.21.tgz", - "integrity": "sha512-+mScLhIcbPFmuvU3tAGBed78XvYHSvCl6dBiYMlzCLhpr0bzGzd8tfivMMeqND6XZiaZ1tgusbUHJEfc6YzOdA==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.0", - "@inquirer/type": "^3.0.9", - "yoctocolors-cjs": "^2.1.2" - }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@inquirer/external-editor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.2.tgz", - "integrity": "sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, "license": "MIT", - "dependencies": { - "chardet": "^2.1.0", - "iconv-lite": "^0.7.0" - }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@inquirer/external-editor/node_modules/iconv-lite": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", - "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", - "license": "MIT", + "node_modules/@eslint/config-array": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", + "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" }, "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@inquirer/figures": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.14.tgz", - "integrity": "sha512-DbFgdt+9/OZYFM+19dbpXOSeAstPy884FPy1KjDu4anWwymZeOYhMY1mdFri172htv6mvc/uvIAAi7b7tvjJBQ==", + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@inquirer/input": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.2.5.tgz", - "integrity": "sha512-7GoWev7P6s7t0oJbenH0eQ0ThNdDJbEAEtVt9vsrYZ9FulIokvd823yLyhQlWHJPGce1wzP53ttfdCZmonMHyA==", - "license": "MIT", + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", "dependencies": { - "@inquirer/core": "^10.3.0", - "@inquirer/type": "^3.0.9" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "*" } }, - "node_modules/@inquirer/number": { - "version": "3.0.21", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.21.tgz", - "integrity": "sha512-5QWs0KGaNMlhbdhOSCFfKsW+/dcAVC2g4wT/z2MCiZM47uLgatC5N20kpkDQf7dHx+XFct/MJvvNGy6aYJn4Pw==", - "license": "MIT", + "node_modules/@eslint/core": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz", + "integrity": "sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@inquirer/core": "^10.3.0", - "@inquirer/type": "^3.0.9" + "@types/json-schema": "^7.0.15" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@inquirer/password": { - "version": "4.0.21", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.21.tgz", - "integrity": "sha512-xxeW1V5SbNFNig2pLfetsDb0svWlKuhmr7MPJZMYuDnCTkpVBI+X/doudg4pznc1/U+yYmWFFOi4hNvGgUo7EA==", + "node_modules/@eslint/eslintrc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^1.0.1", - "@inquirer/core": "^10.3.0", - "@inquirer/type": "^3.0.9" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@inquirer/prompts": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.9.0.tgz", - "integrity": "sha512-X7/+dG9SLpSzRkwgG5/xiIzW0oMrV3C0HOa7YHG1WnrLK+vCQHfte4k/T80059YBdei29RBC3s+pSMvPJDU9/A==", + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "license": "MIT", "dependencies": { - "@inquirer/checkbox": "^4.3.0", - "@inquirer/confirm": "^5.1.19", - "@inquirer/editor": "^4.2.21", - "@inquirer/expand": "^4.0.21", - "@inquirer/input": "^4.2.5", - "@inquirer/number": "^3.0.21", - "@inquirer/password": "^4.0.21", - "@inquirer/rawlist": "^4.1.9", - "@inquirer/search": "^3.2.0", - "@inquirer/select": "^4.4.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@inquirer/rawlist": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.9.tgz", - "integrity": "sha512-AWpxB7MuJrRiSfTKGJ7Y68imYt8P9N3Gaa7ySdkFj1iWjr6WfbGAhdZvw/UnhFXTHITJzxGUI9k8IX7akAEBCg==", + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.0", - "@inquirer/type": "^3.0.9", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@inquirer/search": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.0.tgz", - "integrity": "sha512-a5SzB/qrXafDX1Z4AZW3CsVoiNxcIYCzYP7r9RzrfMpaLpB+yWi5U8BWagZyLmwR0pKbbL5umnGRd0RzGVI8bQ==", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.0", - "@inquirer/figures": "^1.0.14", - "@inquirer/type": "^3.0.9", - "yoctocolors-cjs": "^2.1.2" - }, "engines": { "node": ">=18" }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@inquirer/select": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.0.tgz", - "integrity": "sha512-kaC3FHsJZvVyIjYBs5Ih8y8Bj4P/QItQWrZW22WJax7zTN+ZPXVGuOM55vzbdCP9zKUiBd9iEJVdesujfF+cAA==", - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.1", - "@inquirer/core": "^10.3.0", + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", + "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.6.tgz", + "integrity": "sha512-+0TjwR1eAUdZtvv/ir1mGX+v0tUoR3VEPB8Up0LLJC+whRW0GgBBtpbOkg/a/U4Dxa6l5a3l9AJ1aWIQVyoWJA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.11.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", + "optional": true + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@hutson/parse-repository-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", + "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@inquirer/ansi": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.1.tgz", + "integrity": "sha512-yqq0aJW/5XPhi5xOAL1xRCpe1eh8UFVgYFpFsjEqmIR8rKLyP+HINvFXwUaxYICflJrVlxnp7lLN6As735kVpw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/checkbox": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.0.tgz", + "integrity": "sha512-5+Q3PKH35YsnoPTh75LucALdAxom6xh5D1oeY561x4cqBuH24ZFVyFREPe14xgnrtmGu3EEt1dIi60wRVSnGCw==", + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.1", + "@inquirer/core": "^10.3.0", "@inquirer/figures": "^1.0.14", "@inquirer/type": "^3.0.9", "yoctocolors-cjs": "^2.1.2" @@ -3667,15 +3809,14 @@ } } }, - "node_modules/@inquirer/testing": { - "version": "2.1.51", - "resolved": "https://registry.npmjs.org/@inquirer/testing/-/testing-2.1.51.tgz", - "integrity": "sha512-ZY1mp+AAxhwdJ+IzioKTPgxyqHWLGYZpOzQ3nkHJ8CMp+vpRtI5k94fktBbIXCsjNtOEm8SMttgLPKEK9si2nQ==", - "dev": true, + "node_modules/@inquirer/confirm": { + "version": "5.1.19", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.19.tgz", + "integrity": "sha512-wQNz9cfcxrtEnUyG5PndC8g3gZ7lGDBzmWiXZkX8ot3vfZ+/BLjR8EvyGX4YzQLeVqtAlY/YScZpW7CW8qMoDQ==", "license": "MIT", "dependencies": { - "@inquirer/type": "^3.0.9", - "mute-stream": "^2.0.0" + "@inquirer/core": "^10.3.0", + "@inquirer/type": "^3.0.9" }, "engines": { "node": ">=18" @@ -3689,11 +3830,21 @@ } } }, - "node_modules/@inquirer/type": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.9.tgz", - "integrity": "sha512-QPaNt/nmE2bLGQa9b7wwyRJoLZ7pN6rcyXvzU0YCmivmJyq1BVo94G98tStRWkoD1RgDX5C+dPlhhHzNdu/W/w==", + "node_modules/@inquirer/core": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.0.tgz", + "integrity": "sha512-Uv2aPPPSK5jeCplQmQ9xadnFx2Zhj9b5Dj7bU6ZeCdDNNY11nhYy4btcSdtDguHqCT2h5oNeQTcUNSGGLA7NTA==", "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.1", + "@inquirer/figures": "^1.0.14", + "@inquirer/type": "^3.0.9", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, "engines": { "node": ">=18" }, @@ -3706,202 +3857,493 @@ } } }, - "node_modules/@isaacs/balanced-match": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", - "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", - "dev": true, + "node_modules/@inquirer/editor": { + "version": "4.2.21", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.21.tgz", + "integrity": "sha512-MjtjOGjr0Kh4BciaFShYpZ1s9400idOdvQ5D7u7lE6VztPFoyLcVNE5dXBmEEIQq5zi4B9h2kU+q7AVBxJMAkQ==", "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.0", + "@inquirer/external-editor": "^1.0.2", + "@inquirer/type": "^3.0.9" + }, "engines": { - "node": "20 || >=22" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@isaacs/brace-expansion": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", - "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", - "dev": true, + "node_modules/@inquirer/expand": { + "version": "4.0.21", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.21.tgz", + "integrity": "sha512-+mScLhIcbPFmuvU3tAGBed78XvYHSvCl6dBiYMlzCLhpr0bzGzd8tfivMMeqND6XZiaZ1tgusbUHJEfc6YzOdA==", "license": "MIT", "dependencies": { - "@isaacs/balanced-match": "^4.0.1" + "@inquirer/core": "^10.3.0", + "@inquirer/type": "^3.0.9", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": "20 || >=22" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "license": "ISC", + "node_modules/@inquirer/external-editor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.2.tgz", + "integrity": "sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==", + "license": "MIT", "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + "chardet": "^2.1.0", + "iconv-lite": "^0.7.0" }, "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" + "node": ">=18" }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/@inquirer/external-editor/node_modules/iconv-lite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, "engines": { - "node": ">=12" + "node": ">=0.10.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" + "node_modules/@inquirer/figures": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.14.tgz", + "integrity": "sha512-DbFgdt+9/OZYFM+19dbpXOSeAstPy884FPy1KjDu4anWwymZeOYhMY1mdFri172htv6mvc/uvIAAi7b7tvjJBQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/@inquirer/input": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.2.5.tgz", + "integrity": "sha512-7GoWev7P6s7t0oJbenH0eQ0ThNdDJbEAEtVt9vsrYZ9FulIokvd823yLyhQlWHJPGce1wzP53ttfdCZmonMHyA==", "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "@inquirer/core": "^10.3.0", + "@inquirer/type": "^3.0.9" }, "engines": { - "node": ">=12" + "node": ">=18" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/@inquirer/number": { + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.21.tgz", + "integrity": "sha512-5QWs0KGaNMlhbdhOSCFfKsW+/dcAVC2g4wT/z2MCiZM47uLgatC5N20kpkDQf7dHx+XFct/MJvvNGy6aYJn4Pw==", "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "@inquirer/core": "^10.3.0", + "@inquirer/type": "^3.0.9" }, "engines": { - "node": ">=12" + "node": ">=18" }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "node_modules/@inquirer/password": { + "version": "4.0.21", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.21.tgz", + "integrity": "sha512-xxeW1V5SbNFNig2pLfetsDb0svWlKuhmr7MPJZMYuDnCTkpVBI+X/doudg4pznc1/U+yYmWFFOi4hNvGgUo7EA==", "license": "MIT", "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "@inquirer/ansi": "^1.0.1", + "@inquirer/core": "^10.3.0", + "@inquirer/type": "^3.0.9" }, "engines": { - "node": ">=12" + "node": ">=18" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "license": "ISC", + "node_modules/@inquirer/prompts": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.9.0.tgz", + "integrity": "sha512-X7/+dG9SLpSzRkwgG5/xiIzW0oMrV3C0HOa7YHG1WnrLK+vCQHfte4k/T80059YBdei29RBC3s+pSMvPJDU9/A==", + "license": "MIT", "dependencies": { - "minipass": "^7.0.4" + "@inquirer/checkbox": "^4.3.0", + "@inquirer/confirm": "^5.1.19", + "@inquirer/editor": "^4.2.21", + "@inquirer/expand": "^4.0.21", + "@inquirer/input": "^4.2.5", + "@inquirer/number": "^3.0.21", + "@inquirer/password": "^4.0.21", + "@inquirer/rawlist": "^4.1.9", + "@inquirer/search": "^3.2.0", + "@inquirer/select": "^4.4.0" }, "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@isaacs/fs-minipass/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@isaacs/string-locale-compare": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", - "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "license": "ISC", + "node_modules/@inquirer/rawlist": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.9.tgz", + "integrity": "sha512-AWpxB7MuJrRiSfTKGJ7Y68imYt8P9N3Gaa7ySdkFj1iWjr6WfbGAhdZvw/UnhFXTHITJzxGUI9k8IX7akAEBCg==", + "license": "MIT", "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "@inquirer/core": "^10.3.0", + "@inquirer/type": "^3.0.9", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@inquirer/search": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.0.tgz", + "integrity": "sha512-a5SzB/qrXafDX1Z4AZW3CsVoiNxcIYCzYP7r9RzrfMpaLpB+yWi5U8BWagZyLmwR0pKbbL5umnGRd0RzGVI8bQ==", "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@inquirer/core": "^10.3.0", + "@inquirer/figures": "^1.0.14", + "@inquirer/type": "^3.0.9", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@inquirer/select": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.0.tgz", + "integrity": "sha512-kaC3FHsJZvVyIjYBs5Ih8y8Bj4P/QItQWrZW22WJax7zTN+ZPXVGuOM55vzbdCP9zKUiBd9iEJVdesujfF+cAA==", "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@inquirer/ansi": "^1.0.1", + "@inquirer/core": "^10.3.0", + "@inquirer/figures": "^1.0.14", + "@inquirer/type": "^3.0.9", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "node_modules/@inquirer/testing": { + "version": "2.1.51", + "resolved": "https://registry.npmjs.org/@inquirer/testing/-/testing-2.1.51.tgz", + "integrity": "sha512-ZY1mp+AAxhwdJ+IzioKTPgxyqHWLGYZpOzQ3nkHJ8CMp+vpRtI5k94fktBbIXCsjNtOEm8SMttgLPKEK9si2nQ==", + "dev": true, "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@inquirer/type": "^3.0.9", + "mute-stream": "^2.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.9.tgz", + "integrity": "sha512-QPaNt/nmE2bLGQa9b7wwyRJoLZ7pN6rcyXvzU0YCmivmJyq1BVo94G98tStRWkoD1RgDX5C+dPlhhHzNdu/W/w==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@isaacs/fs-minipass/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", + "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { @@ -4361,9 +4803,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -6792,65 +7234,439 @@ "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", "dev": true, - "license": "MIT" + "license": "MIT" + }, + "node_modules/@protobuf-ts/plugin": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/plugin/-/plugin-2.11.1.tgz", + "integrity": "sha512-HyuprDcw0bEEJqkOWe1rnXUP0gwYLij8YhPuZyZk6cJbIgc/Q0IFgoHQxOXNIXAcXM4Sbehh6kjVnCzasElw1A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@bufbuild/protobuf": "^2.4.0", + "@bufbuild/protoplugin": "^2.4.0", + "@protobuf-ts/protoc": "^2.11.1", + "@protobuf-ts/runtime": "^2.11.1", + "@protobuf-ts/runtime-rpc": "^2.11.1", + "typescript": "^3.9" + }, + "bin": { + "protoc-gen-dump": "bin/protoc-gen-dump", + "protoc-gen-ts": "bin/protoc-gen-ts" + } + }, + "node_modules/@protobuf-ts/plugin/node_modules/typescript": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/@protobuf-ts/protoc": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/protoc/-/protoc-2.11.1.tgz", + "integrity": "sha512-mUZJaV0daGO6HUX90o/atzQ6A7bbN2RSuHtdwo8SSF2Qoe3zHwa4IHyCN1evftTeHfLmdz+45qo47sL+5P8nyg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "protoc": "protoc.js" + } + }, + "node_modules/@protobuf-ts/runtime": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime/-/runtime-2.11.1.tgz", + "integrity": "sha512-KuDaT1IfHkugM2pyz+FwiY80ejWrkH1pAtOBOZFuR6SXEFTsnb/jiQWQ1rCIrcKx2BtyxnxW6BWwsVSA/Ie+WQ==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@protobuf-ts/runtime-rpc": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime-rpc/-/runtime-rpc-2.11.1.tgz", + "integrity": "sha512-4CqqUmNA+/uMz00+d3CYKgElXO9VrEbucjnBFEjqI4GuDrEQ32MaI3q+9qPBvIGOlL4PmHXrzM32vBPWRhQKWQ==", + "license": "Apache-2.0", + "dependencies": { + "@protobuf-ts/runtime": "^2.11.1" + } + }, + "node_modules/@rollup/plugin-alias": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-5.1.1.tgz", + "integrity": "sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.3.tgz", + "integrity": "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] }, - "node_modules/@protobuf-ts/plugin": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/@protobuf-ts/plugin/-/plugin-2.11.1.tgz", - "integrity": "sha512-HyuprDcw0bEEJqkOWe1rnXUP0gwYLij8YhPuZyZk6cJbIgc/Q0IFgoHQxOXNIXAcXM4Sbehh6kjVnCzasElw1A==", + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@bufbuild/protobuf": "^2.4.0", - "@bufbuild/protoplugin": "^2.4.0", - "@protobuf-ts/protoc": "^2.11.1", - "@protobuf-ts/runtime": "^2.11.1", - "@protobuf-ts/runtime-rpc": "^2.11.1", - "typescript": "^3.9" - }, - "bin": { - "protoc-gen-dump": "bin/protoc-gen-dump", - "protoc-gen-ts": "bin/protoc-gen-ts" - } + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@protobuf-ts/plugin/node_modules/typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "cpu": [ + "ia32" + ], "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@protobuf-ts/protoc": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/@protobuf-ts/protoc/-/protoc-2.11.1.tgz", - "integrity": "sha512-mUZJaV0daGO6HUX90o/atzQ6A7bbN2RSuHtdwo8SSF2Qoe3zHwa4IHyCN1evftTeHfLmdz+45qo47sL+5P8nyg==", + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", - "bin": { - "protoc": "protoc.js" - } - }, - "node_modules/@protobuf-ts/runtime": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime/-/runtime-2.11.1.tgz", - "integrity": "sha512-KuDaT1IfHkugM2pyz+FwiY80ejWrkH1pAtOBOZFuR6SXEFTsnb/jiQWQ1rCIrcKx2BtyxnxW6BWwsVSA/Ie+WQ==", - "license": "(Apache-2.0 AND BSD-3-Clause)" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@protobuf-ts/runtime-rpc": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime-rpc/-/runtime-rpc-2.11.1.tgz", - "integrity": "sha512-4CqqUmNA+/uMz00+d3CYKgElXO9VrEbucjnBFEjqI4GuDrEQ32MaI3q+9qPBvIGOlL4PmHXrzM32vBPWRhQKWQ==", - "license": "Apache-2.0", - "dependencies": { - "@protobuf-ts/runtime": "^2.11.1" - } + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, "node_modules/@rtsao/scc": { "version": "1.1.0", @@ -8056,6 +8872,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/md5": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@types/md5/-/md5-2.3.6.tgz", + "integrity": "sha512-WD69gNXtRBnpknfZcb4TRQ0XJQbUPZcai/Qdhmka3sxUR3Et8NrXoeAoknG/LghYHTf4ve795rInVYHBTQdNVA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/merge2": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/@types/merge2/-/merge2-1.4.4.tgz", @@ -8156,6 +8979,13 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/responselike": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", @@ -10811,6 +11641,15 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "license": "MIT" }, + "node_modules/buffer-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-shim/-/buffer-shim-1.0.1.tgz", + "integrity": "sha512-VG1oTE6Ecr9h/Gx3XOXue0F1vQaQlkBd3tGAzpL7Fsu+8f1Jbtk5ORPkrVLA/ADBTQ08bcPt3HanaZ7tUfJqMg==", + "license": "ISC", + "peerDependencies": { + "buffer": "^6.0.3" + } + }, "node_modules/buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", @@ -11138,6 +11977,15 @@ "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", "license": "MIT" }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, "node_modules/check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -12201,6 +13049,15 @@ "node": ">= 8" } }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, "node_modules/crypto-browserify": { "version": "3.12.1", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", @@ -13473,6 +14330,48 @@ "node": ">=0.12" } }, + "node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -13988,6 +14887,13 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -16398,6 +17304,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "license": "MIT" + }, "node_modules/is-bun-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", @@ -16607,6 +17519,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true, + "license": "MIT" + }, "node_modules/is-nan": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", @@ -19360,6 +20279,16 @@ "node": "20 || >=22" } }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -19627,6 +20556,17 @@ "node": ">= 0.4" } }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "license": "BSD-3-Clause", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -22808,7 +23748,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true, "license": "MIT" }, "node_modules/path-exists": { @@ -24378,6 +25317,71 @@ "node": ">=8.0" } }, + "node_modules/rollup": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-dts": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.3.0.tgz", + "integrity": "sha512-d0UrqxYd8KyZ6i3M2Nx7WOMy708qsV/7fTHMHxCMCBOAe3V/U7OMPu5GkX8hC+cmkHhzGnfeYongl1IgiooddA==", + "dev": true, + "license": "LGPL-3.0-only", + "dependencies": { + "magic-string": "^0.30.21" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/Swatinem" + }, + "optionalDependencies": { + "@babel/code-frame": "^7.27.1" + }, + "peerDependencies": { + "rollup": "^3.29.4 || ^4", + "typescript": "^4.5 || ^5.0" + } + }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", @@ -27057,6 +28061,26 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/tsyringe": { "version": "4.10.0", "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz", @@ -29205,17 +30229,110 @@ "dependencies": { "@noble/curves": "^1.9.7", "@noble/post-quantum": "^0.4.1", + "buffer": "^6.0.3", + "buffer-shim": "^1.0.1", "eventemitter3": "^5.0.0", "lodash": "^4.17.21", + "md5": "^2.3.0", + "path-browserify": "^1.0.1", "pino": "^10.1.0", "pino-pretty": "^13.1.2", + "readable-stream": "^4.7.0", "secp256k1": "^5.0.1", "sha3": "^2.1.4" }, "devDependencies": { + "@rollup/plugin-alias": "^5.1.1", + "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", "@types/lodash": "^4.17.21", - "@types/secp256k1": "^4.0.7" + "@types/md5": "^2.3.6", + "@types/secp256k1": "^4.0.7", + "rimraf": "^6.1.2", + "rollup": "^4.53.3", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0" + } + }, + "packages/utils/node_modules/glob": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", + "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/utils/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/utils/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "packages/utils/node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/utils/node_modules/rimraf": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", + "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.0", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } } } diff --git a/packages/utils/jest.config.ts b/packages/utils/jest.config.ts index 550da64839..18301ec7c1 100644 --- a/packages/utils/jest.config.ts +++ b/packages/utils/jest.config.ts @@ -1 +1,11 @@ -export { default } from '../../jest.config' +import type { Config } from "@jest/types" +import defaultConfig from "../../jest.config" + +const config: Config.InitialOptions = { + ...defaultConfig, + moduleNameMapper: { + "^@/(.*)$": "/src/nodejs/$1", + }, +} + +export default config diff --git a/packages/utils/karma.config.ts b/packages/utils/karma.config.ts index 79cb15a828..8929fae25f 100644 --- a/packages/utils/karma.config.ts +++ b/packages/utils/karma.config.ts @@ -1,4 +1,5 @@ import { createKarmaConfig, createWebpackConfig } from '@streamr/browser-test-runner' +import { resolve } from 'path' const TEST_PATHS = ['test/**/*.ts'] @@ -6,5 +7,10 @@ export default createKarmaConfig(TEST_PATHS, createWebpackConfig({ libraryName: 'utils', fallback: { module: false - } + }, + alias: { + '@': resolve(__dirname, 'src/browser'), + os: resolve(__dirname, 'src/browser/os.ts'), + path: 'path-browserify', + }, })) diff --git a/packages/utils/package.json b/packages/utils/package.json index 391dd6d446..60ab043f18 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -7,17 +7,36 @@ "url": "git+https://github.com/streamr-dev/network.git", "directory": "packages/utils" }, - "main": "./dist/src/exports.js", - "types": "./dist/src/exports.d.ts", + "main": "./dist/exports-nodejs.cjs", + "module": "./dist/exports-nodejs.mjs", + "types": "./dist/exports-nodejs.d.ts", + "exports": { + ".": { + "browser": { + "types": "./dist/exports-browser.d.ts", + "import": "./dist/exports-browser.mjs", + "require": "./dist/exports-browser.cjs" + }, + "default": { + "types": "./dist/exports-nodejs.d.ts", + "import": "./dist/exports-nodejs.mjs", + "require": "./dist/exports-nodejs.cjs" + } + } + }, "files": [ - "dist", + "dist/exports-nodejs.*", + "dist/exports-browser.*", "!*.tsbuildinfo", "README.md", "LICENSE" ], "scripts": { + "prebuild": "npm run reset-self", "build": "tsc -b", - "check": "tsc -p tsconfig.jest.json", + "postbuild": "NODE_OPTIONS=\"--import tsx\" rollup -c rollup.config.mts", + "check": "tsc -b tsconfig.jest.json", + "reset-self": "rimraf --glob '**/*.tsbuildinfo'", "clean": "jest --clearCache --config '{}' || true; rm -rf dist *.tsbuildinfo node_modules/.cache || true", "eslint": "eslint --cache --cache-location=node_modules/.cache/.eslintcache/ '*/**/*.{js,ts}'", "test": "jest", @@ -28,16 +47,28 @@ "dependencies": { "@noble/curves": "^1.9.7", "@noble/post-quantum": "^0.4.1", + "buffer": "^6.0.3", + "buffer-shim": "^1.0.1", "eventemitter3": "^5.0.0", "lodash": "^4.17.21", + "md5": "^2.3.0", + "path-browserify": "^1.0.1", "pino": "^10.1.0", "pino-pretty": "^13.1.2", + "readable-stream": "^4.7.0", "secp256k1": "^5.0.1", "sha3": "^2.1.4" }, "devDependencies": { + "@rollup/plugin-alias": "^5.1.1", + "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", "@types/lodash": "^4.17.21", - "@types/secp256k1": "^4.0.7" + "@types/md5": "^2.3.6", + "@types/secp256k1": "^4.0.7", + "rimraf": "^6.1.2", + "rollup": "^4.53.3", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0" } } diff --git a/packages/utils/rollup.config.mts b/packages/utils/rollup.config.mts new file mode 100644 index 0000000000..3ed70c0823 --- /dev/null +++ b/packages/utils/rollup.config.mts @@ -0,0 +1,156 @@ +import { defineConfig, type RollupOptions } from 'rollup' +import { dts } from 'rollup-plugin-dts' +import alias, { type Alias } from '@rollup/plugin-alias' +import { nodeResolve } from '@rollup/plugin-node-resolve' +import { fileURLToPath } from 'node:url' + +const nodejsAliases: Alias[] = [ + { + find: /^@\//, + replacement: fileURLToPath( + new URL('./dist/nodejs/src/nodejs/', import.meta.url) + ), + }, +] + +const browserAliases: Alias[] = [ + { + find: /^@\//, + replacement: fileURLToPath( + new URL('./dist/browser/src/browser/', import.meta.url) + ), + }, + { + find: 'os', + replacement: fileURLToPath( + new URL('./dist/browser/src/browser/os.js', import.meta.url) + ), + }, + { + find: 'path', + replacement: 'path-browserify', + }, + { + find: 'stream', + replacement: 'readable-stream', + }, + { + find: /^pino$/, + replacement: 'pino/browser', + }, +] + +export default defineConfig([ + nodejs(), + nodejsTypes(), + browser(), + browserTypes(), +]) + +function nodejs(): RollupOptions { + return { + input: './dist/nodejs/src/exports.js', + output: [ + { + format: 'es', + file: './dist/exports-nodejs.mjs', + sourcemap: true, + }, + { + format: 'cjs', + file: './dist/exports-nodejs.cjs', + sourcemap: true, + }, + ], + plugins: [ + alias({ + entries: nodejsAliases, + }), + nodeResolve({ + preferBuiltins: true, + }), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} + +function browser(): RollupOptions { + return { + input: './dist/browser/src/exports-browser.js', + output: [ + { + format: 'es', + file: './dist/exports-browser.mjs', + sourcemap: true, + }, + { + format: 'cjs', + file: './dist/exports-browser.cjs', + sourcemap: true, + }, + ], + plugins: [ + alias({ + entries: browserAliases, + }), + nodeResolve({ + browser: true, + preferBuiltins: false, + }), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} + +function nodejsTypes(): RollupOptions { + return { + input: './dist/nodejs/src/exports.d.ts', + output: [ + { + file: './dist/exports-nodejs.d.ts', + }, + ], + plugins: [ + alias({ + entries: nodejsAliases, + }), + nodeResolve(), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} + +function browserTypes(): RollupOptions { + return { + input: './dist/browser/src/exports-browser.d.ts', + output: [ + { + file: './dist/exports-browser.d.ts', + }, + ], + plugins: [ + alias({ + entries: browserAliases, + }), + nodeResolve({ + browser: true, + preferBuiltins: false, + }), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} diff --git a/packages/utils/src/Logger.ts b/packages/utils/src/Logger.ts index 4fa44199db..6f89733df1 100644 --- a/packages/utils/src/Logger.ts +++ b/packages/utils/src/Logger.ts @@ -2,6 +2,7 @@ import pino from 'pino' import path from 'path' import without from 'lodash/without' import padEnd from 'lodash/padEnd' +import { env } from '@/env' export type LogLevel = 'silent' | 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' @@ -18,23 +19,21 @@ const parseBoolean = (value: string | undefined) => { } } -declare let window: any - /** - * Disabled when in browser or when environment variable DISABLE_PRETTY_LOG is set to true. + * Disabled when environment variable DISABLE_PRETTY_LOG is set to true. */ function isPrettyPrintDisabled(): boolean { - return typeof window === 'object' || (parseBoolean(process.env.DISABLE_PRETTY_LOG) ?? false) + return parseBoolean(env.DISABLE_PRETTY_LOG) ?? false } function isJestRunning(): boolean { - return process.env.JEST_WORKER_ID !== undefined + return env.JEST_WORKER_ID !== undefined } const rootLogger = pino({ name: 'rootLogger', - enabled: !process.env.NOLOG, - level: process.env.LOG_LEVEL ?? 'info', + enabled: !env.NOLOG, + level: env.LOG_LEVEL ?? 'info', formatters: { level: (label) => { return { level: label } // log level as string instead of number @@ -43,7 +42,7 @@ const rootLogger = pino({ transport: isPrettyPrintDisabled() ? undefined : { target: 'pino-pretty', options: { - colorize: parseBoolean(process.env.LOG_COLORS) ?? true, + colorize: parseBoolean(env.LOG_COLORS) ?? true, singleLine: true, translateTime: 'yyyy-mm-dd"T"HH:MM:ss.l', ignore: 'pid,hostname', @@ -95,7 +94,7 @@ export class Logger { name: Logger.createName(loggerModule), ...contextBindings }, { - level: process.env.LOG_LEVEL ?? defaultLogLevel + level: env.LOG_LEVEL ?? defaultLogLevel }) this.fatal = wrappedMethodCall(this.logger.fatal.bind(this.logger)) this.error = wrappedMethodCall(this.logger.error.bind(this.logger)) @@ -114,7 +113,7 @@ export class Logger { const parts = parsedPath.dir.split(path.sep) fileId = parts[parts.length - 1] } - const longName = without([process.env.STREAMR_APPLICATION_ID, fileId], undefined).join(':') + const longName = without([env.STREAMR_APPLICATION_ID, fileId], undefined).join(':') return isPrettyPrintDisabled() ? longName : padEnd(longName.substring(0, this.NAME_LENGTH), this.NAME_LENGTH, ' ') } diff --git a/packages/utils/src/SigningUtil.ts b/packages/utils/src/SigningUtil.ts index 23104621d0..96d7490bec 100644 --- a/packages/utils/src/SigningUtil.ts +++ b/packages/utils/src/SigningUtil.ts @@ -6,8 +6,7 @@ import { randomBytes } from '@noble/post-quantum/utils' import { p256 } from '@noble/curves/p256' import { areEqualBinaries, binaryToHex } from './binaryUtils' import type { UserIDRaw } from './UserID' -import { getSubtle } from './crossPlatformCrypto' -import type { webcrypto } from 'crypto' +import { type CryptoKey, getSubtle, type Jwk } from '@/crypto' export const KEY_TYPES = [ 'ECDSA_SECP256K1_EVM', @@ -18,9 +17,6 @@ export const KEY_TYPES = [ export type KeyType = typeof KEY_TYPES[number] const ECDSA_SECP256K1_EVM_SIGN_MAGIC = '\u0019Ethereum Signed Message:\n' -const keccak = new Keccak(256) - -const subtleCrypto = getSubtle() export interface KeyPair { publicKey: Uint8Array @@ -58,7 +54,7 @@ export class EcdsaSecp256k1Evm extends SigningUtil { } keccakHash(message: Uint8Array, useEthereumMagic: boolean = true): Buffer { - keccak.reset() + const keccak = new Keccak(256) keccak.update(useEthereumMagic ? Buffer.concat([ Buffer.from(ECDSA_SECP256K1_EVM_SIGN_MAGIC + message.length), message @@ -91,7 +87,7 @@ export class EcdsaSecp256k1Evm extends SigningUtil { throw new Error(`Expected 65 bytes (an ECDSA uncompressed public key with header byte). Got length: ${publicKey.length}`) } const pubKeyWithoutFirstByte = publicKey.subarray(1, publicKey.length) - keccak.reset() + const keccak = new Keccak(256) keccak.update(Buffer.from(pubKeyWithoutFirstByte)) const hashOfPubKey = keccak.digest('binary') return hashOfPubKey.subarray(12, hashOfPubKey.length) @@ -167,7 +163,7 @@ export class EcdsaSecp256r1 extends SigningUtil { throw new Error(`Unexpected public key length: ${publicKey.length}`) } - privateKeyToJWK(privateKey: Uint8Array): webcrypto.JsonWebKey { + privateKeyToJWK(privateKey: Uint8Array): Jwk { const publicKey = this.getPublicKeyFromPrivateKey(privateKey, false) // uncompressed publicKey = [header (1 byte), x (32 bytes), y (32 bytes) const x = publicKey.subarray(1, 33) @@ -199,7 +195,9 @@ export class EcdsaSecp256r1 extends SigningUtil { * Pass the privateKey in JsonWebKey format for a slight performance gain. * You can convert raw keys to JWK using the privateKeyToJWK function. */ - async createSignature(payload: Uint8Array, privateKey: Uint8Array | webcrypto.JsonWebKey): Promise { + async createSignature(payload: Uint8Array, privateKey: Uint8Array | Jwk): Promise { + const subtleCrypto = getSubtle() + const jwk = privateKey instanceof Uint8Array ? this.privateKeyToJWK(privateKey) : privateKey /** @@ -229,8 +227,8 @@ export class EcdsaSecp256r1 extends SigningUtil { return new Uint8Array(signature) } - private async publicKeyToCryptoKey(publicKey: Uint8Array): Promise { - return subtleCrypto.importKey( + private async publicKeyToCryptoKey(publicKey: Uint8Array): Promise { + return getSubtle().importKey( 'raw', publicKey, { @@ -243,7 +241,7 @@ export class EcdsaSecp256r1 extends SigningUtil { } async verifySignature(publicKey: UserIDRaw, payload: Uint8Array, signature: Uint8Array): Promise { - let key: webcrypto.CryptoKey + let key: CryptoKey | undefined try { key = await this.publicKeyToCryptoKey(publicKey) @@ -257,7 +255,7 @@ export class EcdsaSecp256r1 extends SigningUtil { } } - const isValid = await subtleCrypto.verify( + const isValid = await getSubtle().verify( { name: 'ECDSA', hash: { name: 'SHA-256' } diff --git a/packages/utils/src/browser/crypto.ts b/packages/utils/src/browser/crypto.ts new file mode 100644 index 0000000000..2afacd1136 --- /dev/null +++ b/packages/utils/src/browser/crypto.ts @@ -0,0 +1,23 @@ +import md5 from 'md5' + +export function getSubtle(): SubtleCrypto { + const { crypto } = globalThis + + if (!crypto?.subtle) { + const url = + 'https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto' + throw new Error( + `SubtleCrypto not supported. This feature is available only in secure contexts (HTTPS). ${url}` + ) + } + + return crypto.subtle +} + +export function computeMd5(input: string): Buffer { + return Buffer.from(md5(input), 'hex') +} + +export type Jwk = JsonWebKey + +export type CryptoKey = globalThis.CryptoKey diff --git a/packages/utils/src/browser/env.ts b/packages/utils/src/browser/env.ts new file mode 100644 index 0000000000..bd33e9013f --- /dev/null +++ b/packages/utils/src/browser/env.ts @@ -0,0 +1,19 @@ +/** + * Browser-safe environment object. + * + * `process.env` is NOT available in browsers unless explicitly polyfilled + * by the bundler or runtime. This guard prevents runtime errors and falls + * back to an empty object when no polyfill exists. + */ +const defaultEnv: Record = + typeof process !== 'undefined' && process?.env ? process.env : {} + +/** + * Application environment values. + * + * Values here are browser-safe defaults and override any polyfilled + * `process.env` values if present. + */ +export const env = Object.assign(defaultEnv, { + DISABLE_PRETTY_LOG: 'true', +}) diff --git a/packages/utils/src/browser/os.ts b/packages/utils/src/browser/os.ts new file mode 100644 index 0000000000..bb4d2b93e8 --- /dev/null +++ b/packages/utils/src/browser/os.ts @@ -0,0 +1,5 @@ +const os = { + homedir: (): string => '/' +} + +export default os diff --git a/packages/utils/src/crossPlatformCrypto.ts b/packages/utils/src/crossPlatformCrypto.ts deleted file mode 100644 index fa04d35144..0000000000 --- a/packages/utils/src/crossPlatformCrypto.ts +++ /dev/null @@ -1,15 +0,0 @@ -import crypto from 'crypto' - -declare const self: any - -export function getSubtle(): crypto.webcrypto.SubtleCrypto { - // in browser main thread, self === window - // in web workers, self is defined but window is not - // in node.js, self is undefined - const subtle = typeof self !== 'undefined' ? self?.crypto?.subtle : crypto.webcrypto.subtle - if (!subtle) { - const url = 'https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto' - throw new Error(`SubtleCrypto not supported. This feature is available only in secure contexts (HTTPS) & Node 16+. ${url}`) - } - return subtle -} diff --git a/packages/utils/src/exports-browser.ts b/packages/utils/src/exports-browser.ts new file mode 100644 index 0000000000..a0a5ae2ca5 --- /dev/null +++ b/packages/utils/src/exports-browser.ts @@ -0,0 +1,6 @@ +/** + * `buffer-shim` polyfills `globalThis.Buffer` in browsers via `buffer` package. + */ +import 'buffer-shim' + +export * from './exports' diff --git a/packages/utils/src/exports.ts b/packages/utils/src/exports.ts index c485f4b9bf..d91d4cb134 100644 --- a/packages/utils/src/exports.ts +++ b/packages/utils/src/exports.ts @@ -53,5 +53,5 @@ export { type UserID, type UserIDRaw, toUserId, toUserIdRaw, isValidUserId, isEt export type { HexString } from './HexString' export type { ChangeFieldType, MapKey } from './types' export { type WeiAmount, multiplyWeiAmount } from './WeiAmount' -export { getSubtle } from './crossPlatformCrypto' +export { getSubtle, computeMd5 } from '@/crypto' export { SigningUtil, EcdsaSecp256k1Evm, EcdsaSecp256r1, MlDsa87, type KeyType, KEY_TYPES } from './SigningUtil' diff --git a/packages/utils/src/keyToArrayIndex.ts b/packages/utils/src/keyToArrayIndex.ts index c248b02fb8..0fa87dde28 100644 --- a/packages/utils/src/keyToArrayIndex.ts +++ b/packages/utils/src/keyToArrayIndex.ts @@ -1,4 +1,4 @@ -import crypto from 'crypto' +import { computeMd5 } from '@/crypto' /** * Computes a deterministic index for a given string or number key. @@ -25,7 +25,6 @@ export function keyToArrayIndex(lengthOfArray: number, key: string | number): nu } // String key handling - const buffer = crypto.createHash('md5').update(key).digest() - const intHash = buffer.readInt32LE(0) + const intHash = computeMd5(key).readInt32LE(0) return Math.abs(intHash) % lengthOfArray } diff --git a/packages/utils/src/nodejs/crypto.ts b/packages/utils/src/nodejs/crypto.ts new file mode 100644 index 0000000000..769931c1b1 --- /dev/null +++ b/packages/utils/src/nodejs/crypto.ts @@ -0,0 +1,23 @@ +import crypto, { type webcrypto } from 'crypto' + +export function getSubtle(): crypto.webcrypto.SubtleCrypto { + const subtle = crypto.webcrypto.subtle + + if (!subtle) { + const url = + 'https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto' + throw new Error( + `SubtleCrypto not supported. This feature is available only in Node 16+. ${url}` + ) + } + + return subtle +} + +export type Jwk = webcrypto.JsonWebKey + +export type CryptoKey = webcrypto.CryptoKey + +export function computeMd5(input: string): Buffer { + return crypto.createHash('md5').update(input).digest() +} diff --git a/packages/utils/src/nodejs/env.ts b/packages/utils/src/nodejs/env.ts new file mode 100644 index 0000000000..7c9e55cfbb --- /dev/null +++ b/packages/utils/src/nodejs/env.ts @@ -0,0 +1,6 @@ +/** + * Node.js environment object. + * + * Directly exposes `process.env`. + */ +export const env: Record = process.env diff --git a/packages/utils/test/Metric.test.ts b/packages/utils/test/Metric.test.ts index b34acab019..d0f10a4345 100644 --- a/packages/utils/test/Metric.test.ts +++ b/packages/utils/test/Metric.test.ts @@ -1,5 +1,5 @@ import { wait } from '../src/wait' -import { AverageMetric, CountMetric, LevelMetric, MetricsContext, MetricsReport, RateMetric } from '../src/Metric' +import { AverageMetric, CountMetric, LevelMetric, MetricsContext, type MetricsReport, RateMetric } from '../src/Metric' import { until } from '../src/until' const REPORT_INTERVAL = 100 diff --git a/packages/utils/test/composeAbortSignals.test.ts b/packages/utils/test/composeAbortSignals.test.ts index 417e313ec8..60e8269f55 100644 --- a/packages/utils/test/composeAbortSignals.test.ts +++ b/packages/utils/test/composeAbortSignals.test.ts @@ -1,4 +1,4 @@ -import { ComposedAbortSignal, composeAbortSignals } from '../src/composeAbortSignals' +import { type ComposedAbortSignal, composeAbortSignals } from '../src/composeAbortSignals' import range from 'lodash/range' describe('composeAbortSignals', () => { diff --git a/packages/utils/tsconfig.browser.json b/packages/utils/tsconfig.browser.json new file mode 100644 index 0000000000..abb91eabd0 --- /dev/null +++ b/packages/utils/tsconfig.browser.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.browser.json", + "compilerOptions": { + "outDir": "dist/browser", + "baseUrl": ".", + + /* Mapping */ + "paths": { + "@/*": [ + "src/browser/*" + ] + } + }, + "include": [ + "src" + ], + "exclude": [ + "src/nodejs" + ] +} diff --git a/packages/utils/tsconfig.jest.json b/packages/utils/tsconfig.jest.json index a826798cda..7746d1c6d4 100644 --- a/packages/utils/tsconfig.jest.json +++ b/packages/utils/tsconfig.jest.json @@ -1,7 +1,25 @@ { "extends": "../../tsconfig.jest.json", + "compilerOptions": { + "module": "preserve", + "moduleResolution": "bundler", + "baseUrl": ".", + + /* Mapping */ + "paths": { + "@/*": [ + "src/nodejs/*" + ] + } + }, "include": [ "src", "test" + ], + "exclude": [ + "src/browser" + ], + "references": [ + { "path": "./tsconfig.browser.json" } ] } diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json index 126cae2a06..9a557a2379 100644 --- a/packages/utils/tsconfig.json +++ b/packages/utils/tsconfig.json @@ -1,9 +1,10 @@ { - "extends": "../../tsconfig.node.json", + "files": [], "compilerOptions": { - "outDir": "dist" + "composite": true }, - "include": [ - "src" + "references": [ + { "path": "./tsconfig.node.json" }, + { "path": "./tsconfig.browser.json" } ] } diff --git a/packages/utils/tsconfig.karma.json b/packages/utils/tsconfig.karma.json index 14f74739f8..662d21a06b 100644 --- a/packages/utils/tsconfig.karma.json +++ b/packages/utils/tsconfig.karma.json @@ -5,7 +5,15 @@ "jest", "jest-extended" ], - "outDir": "dist" + "outDir": "dist/karma", + "baseUrl": ".", + + /* Mapping */ + "paths": { + "@/*": [ + "src/browser/*" + ] + } }, "include": [ "src" diff --git a/packages/utils/tsconfig.node.json b/packages/utils/tsconfig.node.json new file mode 100644 index 0000000000..a5a0284500 --- /dev/null +++ b/packages/utils/tsconfig.node.json @@ -0,0 +1,24 @@ +{ + "extends": "../../tsconfig.node.json", + "compilerOptions": { + "outDir": "dist/nodejs", + + /* Resolution */ + "moduleResolution": "bundler", + "module": "preserve", + "baseUrl": ".", + + /* Mapping */ + "paths": { + "@/*": [ + "src/nodejs/*" + ] + } + }, + "include": [ + "src" + ], + "exclude": [ + "src/browser" + ] +} diff --git a/tsconfig.browser.json b/tsconfig.browser.json new file mode 100644 index 0000000000..4094e8dc8b --- /dev/null +++ b/tsconfig.browser.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["ES2022", "DOM"], + "module": "ESNext", + "types": [], + "skipLibCheck": true, + "declaration": true, + "composite": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "verbatimModuleSyntax": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true, + "noImplicitOverride": true, + "noImplicitAny": true + }, + "include": [], + "exclude": [] +} From 07b492404a386c030cdf5e245737399c912e91e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Tue, 6 Jan 2026 22:15:57 +0100 Subject: [PATCH 02/18] refactor: Side-effect free `utils` (#3322) This pull request refactors and improves utility modules in the codebase, focusing on the `Logger` and `SigningUtil` classes, as well as minor optimizations in binary utilities and error handling. The main changes include a redesign of the logger initialization for better encapsulation, simplification of the signing utility instantiation logic, and minor performance and correctness tweaks. > [!NOTE] > This is just the first step (alongside the recent `utils` refactoring). Other packages will follow to make the whole thing much more convenient to use. ## Changes **Logger improvements:** - Refactored the `Logger` class to encapsulate the root logger initialization in a static method, removing the global `rootLogger` variable and improving encapsulation. The logger now lazily initializes the root logger as needed. [[1]](diffhunk://#diff-312c84735c8ba55bd72f753e86af89e6c8f1b058ac23ac2290d447c64b7fd6d4L33-R68) [[2]](diffhunk://#diff-312c84735c8ba55bd72f753e86af89e6c8f1b058ac23ac2290d447c64b7fd6d4L54-L78) [[3]](diffhunk://#diff-312c84735c8ba55bd72f753e86af89e6c8f1b058ac23ac2290d447c64b7fd6d4L91-R99) - Improved the logger method wrapping logic to ensure consistent logging behavior in browser environments. [[1]](diffhunk://#diff-312c84735c8ba55bd72f753e86af89e6c8f1b058ac23ac2290d447c64b7fd6d4L33-R68) [[2]](diffhunk://#diff-312c84735c8ba55bd72f753e86af89e6c8f1b058ac23ac2290d447c64b7fd6d4L54-L78) **Signing utility simplification:** - Simplified the `SigningUtil.getInstance` method by replacing the static `keyTypeToInstance` map with a switch statement that directly instantiates the correct class for each key type. This removes unnecessary static instances and clarifies the instantiation logic. [[1]](diffhunk://#diff-264c1a909477860ce2ed2c73f193874422c99397476f8d74ec602ccd11b80512L34-L38) [[2]](diffhunk://#diff-264c1a909477860ce2ed2c73f193874422c99397476f8d74ec602ccd11b80512L318-L326) **Utility optimizations:** - Updated `binaryUtils.ts` to create new `TextEncoder` and `TextDecoder` instances on each call instead of using shared instances, preventing potential state issues and improving reliability. **Error handling improvements:** - Moved the creation of the logger instance inside the `executeSafePromise` function to ensure a fresh logger is used for each invocation, and removed the unnecessary top-level logger instance. ## Future steps * Propagate the same technique throughout the other packages. --- packages/utils/src/Logger.ts | 60 ++++++++++++++---------- packages/utils/src/SigningUtil.ts | 22 ++++----- packages/utils/src/binaryUtils.ts | 7 +-- packages/utils/src/executeSafePromise.ts | 4 +- 4 files changed, 47 insertions(+), 46 deletions(-) diff --git a/packages/utils/src/Logger.ts b/packages/utils/src/Logger.ts index 6f89733df1..1c3d43efb8 100644 --- a/packages/utils/src/Logger.ts +++ b/packages/utils/src/Logger.ts @@ -30,31 +30,6 @@ function isJestRunning(): boolean { return env.JEST_WORKER_ID !== undefined } -const rootLogger = pino({ - name: 'rootLogger', - enabled: !env.NOLOG, - level: env.LOG_LEVEL ?? 'info', - formatters: { - level: (label) => { - return { level: label } // log level as string instead of number - } - }, - transport: isPrettyPrintDisabled() ? undefined : { - target: 'pino-pretty', - options: { - colorize: parseBoolean(env.LOG_COLORS) ?? true, - singleLine: true, - translateTime: 'yyyy-mm-dd"T"HH:MM:ss.l', - ignore: 'pid,hostname', - levelFirst: true, - sync: isJestRunning(), - }, - }, - browser: { - asObject: true - } -}) - /** * This whole monstrosity exists only because pino in browser environment will not print a log message * when invoking `logger.info(undefined, 'msg') instead you need to call `logger.info(msg)`. @@ -76,6 +51,39 @@ export type LoggerModule = string | { id: string } export class Logger { static NAME_LENGTH = 25 + private static rootLogger: pino.Logger | undefined + + private static getRootLogger(): pino.Logger { + Logger.rootLogger ??= pino({ + name: 'rootLogger', + enabled: !env.NOLOG, + level: env.LOG_LEVEL ?? 'info', + formatters: { + level: (label) => { + return { level: label } // log level as string instead of number + }, + }, + transport: isPrettyPrintDisabled() + ? undefined + : { + target: 'pino-pretty', + options: { + colorize: parseBoolean(env.LOG_COLORS) ?? true, + singleLine: true, + translateTime: 'yyyy-mm-dd"T"HH:MM:ss.l', + ignore: 'pid,hostname', + levelFirst: true, + sync: isJestRunning(), + }, + }, + browser: { + asObject: true, + }, + }) + + return Logger.rootLogger + } + private readonly logger: pino.Logger fatal: (msg: string, metadata?: Record) => void error: (msg: string, metadata?: Record) => void @@ -88,7 +96,7 @@ export class Logger { loggerModule: LoggerModule, contextBindings?: Record, defaultLogLevel: LogLevel = 'info', - parentLogger: pino.Logger = rootLogger + parentLogger: pino.Logger = Logger.getRootLogger() ) { this.logger = parentLogger.child({ name: Logger.createName(loggerModule), diff --git a/packages/utils/src/SigningUtil.ts b/packages/utils/src/SigningUtil.ts index 96d7490bec..2a664f2a8f 100644 --- a/packages/utils/src/SigningUtil.ts +++ b/packages/utils/src/SigningUtil.ts @@ -31,11 +31,16 @@ export abstract class SigningUtil { abstract assertValidKeyPair(publicKey: UserIDRaw, privateKey: Uint8Array): void static getInstance(type: KeyType): SigningUtil { - const util = keyTypeToInstance[type] - if (!util) { - throw new Error(`Unknown key pair type: ${type}`) + switch (type) { + case 'ECDSA_SECP256K1_EVM': + return new EcdsaSecp256k1Evm() + case 'ECDSA_SECP256R1': + return new EcdsaSecp256r1() + case 'ML_DSA_87': + return new MlDsa87() + default: + throw new Error(`Unknown key pair type: ${type}`) } - return util } } @@ -315,13 +320,4 @@ export class MlDsa87 extends SigningUtil { throw new Error(`The given ML-DSA public key and private key don't match!`) } } - -} - -// Declared at the bottom of the file because the classes need to be -// declared first. TS makes sure all KeyPairTypes are present. -const keyTypeToInstance: Record = { - ECDSA_SECP256K1_EVM: new EcdsaSecp256k1Evm(), - ECDSA_SECP256R1: new EcdsaSecp256r1(), - ML_DSA_87: new MlDsa87() } diff --git a/packages/utils/src/binaryUtils.ts b/packages/utils/src/binaryUtils.ts index 288aa0fbba..e9d3bc05ae 100644 --- a/packages/utils/src/binaryUtils.ts +++ b/packages/utils/src/binaryUtils.ts @@ -1,12 +1,9 @@ -const textEncoder = new TextEncoder() -const textDecoder = new TextDecoder() - export const binaryToUtf8 = (bytes: Uint8Array): string => { - return textDecoder.decode(bytes) + return new TextDecoder().decode(bytes) } export const utf8ToBinary = (utf8: string): Uint8Array => { - return textEncoder.encode(utf8) + return new TextEncoder().encode(utf8) } export const binaryToHex = (bytes: Uint8Array, addPrefix = false): string => { diff --git a/packages/utils/src/executeSafePromise.ts b/packages/utils/src/executeSafePromise.ts index 9b79cc19fb..a464e9b461 100644 --- a/packages/utils/src/executeSafePromise.ts +++ b/packages/utils/src/executeSafePromise.ts @@ -1,7 +1,5 @@ import { Logger } from './Logger' -const logger = new Logger('executeSafePromise') - /** * Execute a promise that should never reject. If it does, log the error and exit the process * (in Node/Electron) or throw an unhandled error (in browsers). @@ -9,9 +7,11 @@ const logger = new Logger('executeSafePromise') * to reject (unless something is really wrong). */ export const executeSafePromise = async (createPromise: () => Promise): Promise => { + try { return await createPromise() } catch (err: any) { + const logger = new Logger('executeSafePromise') logger.fatal('Assertion failure!', { message: err?.message, err }) // Check if we're in a Node/Electron environment From e9c757c33c1d437eefc364fca418ad655cea8284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Tue, 6 Jan 2026 23:42:27 +0100 Subject: [PATCH 03/18] refactor: Bundle `autocertifier-client` (#3330) This pull request introduces a new bundling workflow for the `autocertifier-client` package, adding Rollup-based builds for both JavaScript and TypeScript types. It also updates the package configuration to support both CommonJS and ES module outputs, improves build script management, and refines the package's file exports for better distribution. ### Build system integration * Added a new `rollup.config.mts` file to bundle both CommonJS (`exports.cjs`) and ES module (`exports.mjs`) outputs, as well as generate TypeScript type definitions using Rollup and relevant plugins. * Updated `tsconfig.json` to use `module: preserve` and `moduleResolution: bundler` for compatibility with the new bundling setup. ### Package configuration improvements * Modified `package.json` to specify both `main` (CommonJS) and `module` (ESM) entry points, and refined the `files` field to export only the necessary bundle outputs. * Added new build scripts (`postbuild`, `reset-self`) and improved the build pipeline to include cleaning up build artifacts and running Rollup after TypeScript compilation. ### Dependency updates * Added Rollup, plugins for node resolution and type definitions, `tsx`, and `rimraf` as development dependencies to support the new build process. --- package-lock.json | 317 +++++++++++++----- packages/autocertifier-client/package.json | 18 +- .../autocertifier-client/rollup.config.mts | 54 +++ packages/autocertifier-client/tsconfig.json | 7 +- packages/utils/package.json | 8 +- packages/utils/rollup.config.mts | 4 +- 6 files changed, 303 insertions(+), 105 deletions(-) create mode 100644 packages/autocertifier-client/rollup.config.mts diff --git a/package-lock.json b/package-lock.json index 4233cc3f0b..81d0ce2a97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7361,9 +7361,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", - "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", + "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", "cpu": [ "arm" ], @@ -7375,9 +7375,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", - "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", + "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", "cpu": [ "arm64" ], @@ -7389,9 +7389,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", - "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", + "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", "cpu": [ "arm64" ], @@ -7403,9 +7403,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", - "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", + "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", "cpu": [ "x64" ], @@ -7417,9 +7417,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", - "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", + "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", "cpu": [ "arm64" ], @@ -7431,9 +7431,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", - "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", + "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", "cpu": [ "x64" ], @@ -7445,9 +7445,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", - "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", + "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", "cpu": [ "arm" ], @@ -7459,9 +7459,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", - "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", + "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", "cpu": [ "arm" ], @@ -7473,9 +7473,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", - "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", + "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", "cpu": [ "arm64" ], @@ -7487,9 +7487,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", - "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", + "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", "cpu": [ "arm64" ], @@ -7501,9 +7501,23 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", - "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", + "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", + "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", "cpu": [ "loong64" ], @@ -7515,9 +7529,23 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", - "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", + "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", + "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", "cpu": [ "ppc64" ], @@ -7529,9 +7557,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", - "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", + "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", "cpu": [ "riscv64" ], @@ -7543,9 +7571,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", - "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", + "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", "cpu": [ "riscv64" ], @@ -7557,9 +7585,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", - "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", + "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", "cpu": [ "s390x" ], @@ -7571,9 +7599,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", - "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", + "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", "cpu": [ "x64" ], @@ -7585,9 +7613,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", - "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", + "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", "cpu": [ "x64" ], @@ -7598,10 +7626,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", + "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", - "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", + "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", "cpu": [ "arm64" ], @@ -7613,9 +7655,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", - "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", + "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", "cpu": [ "arm64" ], @@ -7627,9 +7669,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", - "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", + "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", "cpu": [ "ia32" ], @@ -7641,9 +7683,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", - "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", + "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", "cpu": [ "x64" ], @@ -7655,9 +7697,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", - "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", + "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", "cpu": [ "x64" ], @@ -25318,9 +25360,9 @@ } }, "node_modules/rollup": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", - "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", + "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", "dev": true, "license": "MIT", "dependencies": { @@ -25334,28 +25376,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.3", - "@rollup/rollup-android-arm64": "4.53.3", - "@rollup/rollup-darwin-arm64": "4.53.3", - "@rollup/rollup-darwin-x64": "4.53.3", - "@rollup/rollup-freebsd-arm64": "4.53.3", - "@rollup/rollup-freebsd-x64": "4.53.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", - "@rollup/rollup-linux-arm-musleabihf": "4.53.3", - "@rollup/rollup-linux-arm64-gnu": "4.53.3", - "@rollup/rollup-linux-arm64-musl": "4.53.3", - "@rollup/rollup-linux-loong64-gnu": "4.53.3", - "@rollup/rollup-linux-ppc64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-musl": "4.53.3", - "@rollup/rollup-linux-s390x-gnu": "4.53.3", - "@rollup/rollup-linux-x64-gnu": "4.53.3", - "@rollup/rollup-linux-x64-musl": "4.53.3", - "@rollup/rollup-openharmony-arm64": "4.53.3", - "@rollup/rollup-win32-arm64-msvc": "4.53.3", - "@rollup/rollup-win32-ia32-msvc": "4.53.3", - "@rollup/rollup-win32-x64-gnu": "4.53.3", - "@rollup/rollup-win32-x64-msvc": "4.53.3", + "@rollup/rollup-android-arm-eabi": "4.55.1", + "@rollup/rollup-android-arm64": "4.55.1", + "@rollup/rollup-darwin-arm64": "4.55.1", + "@rollup/rollup-darwin-x64": "4.55.1", + "@rollup/rollup-freebsd-arm64": "4.55.1", + "@rollup/rollup-freebsd-x64": "4.55.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", + "@rollup/rollup-linux-arm-musleabihf": "4.55.1", + "@rollup/rollup-linux-arm64-gnu": "4.55.1", + "@rollup/rollup-linux-arm64-musl": "4.55.1", + "@rollup/rollup-linux-loong64-gnu": "4.55.1", + "@rollup/rollup-linux-loong64-musl": "4.55.1", + "@rollup/rollup-linux-ppc64-gnu": "4.55.1", + "@rollup/rollup-linux-ppc64-musl": "4.55.1", + "@rollup/rollup-linux-riscv64-gnu": "4.55.1", + "@rollup/rollup-linux-riscv64-musl": "4.55.1", + "@rollup/rollup-linux-s390x-gnu": "4.55.1", + "@rollup/rollup-linux-x64-gnu": "4.55.1", + "@rollup/rollup-linux-x64-musl": "4.55.1", + "@rollup/rollup-openbsd-x64": "4.55.1", + "@rollup/rollup-openharmony-arm64": "4.55.1", + "@rollup/rollup-win32-arm64-msvc": "4.55.1", + "@rollup/rollup-win32-ia32-msvc": "4.55.1", + "@rollup/rollup-win32-x64-gnu": "4.55.1", + "@rollup/rollup-win32-x64-msvc": "4.55.1", "fsevents": "~2.3.2" } }, @@ -29817,7 +29862,93 @@ "node-forge": "^1.3.2" }, "devDependencies": { - "@types/node-forge": "^1.3.14" + "@rollup/plugin-node-resolve": "^16.0.3", + "@types/node-forge": "^1.3.14", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0" + } + }, + "packages/autocertifier-client/node_modules/glob": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", + "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/autocertifier-client/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/autocertifier-client/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "packages/autocertifier-client/node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/autocertifier-client/node_modules/rimraf": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", + "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.0", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "packages/autocertifier-server": { @@ -30249,7 +30380,7 @@ "@types/md5": "^2.3.6", "@types/secp256k1": "^4.0.7", "rimraf": "^6.1.2", - "rollup": "^4.53.3", + "rollup": "^4.55.1", "rollup-plugin-dts": "^6.3.0", "tsx": "^4.21.0" } diff --git a/packages/autocertifier-client/package.json b/packages/autocertifier-client/package.json index 6fbebb0aee..0b71ae70e2 100644 --- a/packages/autocertifier-client/package.json +++ b/packages/autocertifier-client/package.json @@ -7,18 +7,21 @@ "url": "git+https://github.com/streamr-dev/network.git", "directory": "packages/autocertifier-client" }, - "main": "dist/src/exports.js", - "types": "dist/src/exports.d.ts", + "main": "./dist/exports.cjs", + "module": "./dist/exports.js", + "types": "./dist/exports.d.ts", "files": [ - "dist", + "dist/exports.*", "!*.tsbuildinfo" ], "license": "STREAMR NETWORK OPEN SOURCE LICENSE", "author": "Streamr Network AG ", "scripts": { - "prebuild": "./proto.sh", + "prebuild": "npm run reset-self && ./proto.sh", "build": "tsc -b", + "postbuild": "NODE_OPTIONS='--import tsx' rollup -c rollup.config.mts", "check": "tsc --noEmit", + "reset-self": "rimraf --glob '**/*.tsbuildinfo'", "clean": "rm -rf dist generated *.tsbuildinfo node_modules/.cache || true", "eslint": "eslint --cache --cache-location=node_modules/.cache/.eslintcache/ '*/**/*.{js,ts}'" }, @@ -29,6 +32,11 @@ "node-forge": "^1.3.2" }, "devDependencies": { - "@types/node-forge": "^1.3.14" + "@rollup/plugin-node-resolve": "^16.0.3", + "@types/node-forge": "^1.3.14", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0" } } diff --git a/packages/autocertifier-client/rollup.config.mts b/packages/autocertifier-client/rollup.config.mts new file mode 100644 index 0000000000..cc1fbda131 --- /dev/null +++ b/packages/autocertifier-client/rollup.config.mts @@ -0,0 +1,54 @@ +import { defineConfig, type RollupOptions } from 'rollup' +import { dts } from 'rollup-plugin-dts' +import { nodeResolve } from '@rollup/plugin-node-resolve' + +export default defineConfig([ + nodejs(), + nodejsTypes(), +]) + +function nodejs(): RollupOptions { + return { + input: './dist/src/exports.js', + output: [ + { + format: 'es', + file: './dist/exports.js', + sourcemap: true, + }, + { + format: 'cjs', + file: './dist/exports.cjs', + sourcemap: true, + }, + ], + plugins: [ + nodeResolve({ + preferBuiltins: true, + }), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} + +function nodejsTypes(): RollupOptions { + return { + input: './dist/src/exports.d.ts', + output: [ + { + file: './dist/exports.d.ts', + }, + ], + plugins: [ + nodeResolve(), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} diff --git a/packages/autocertifier-client/tsconfig.json b/packages/autocertifier-client/tsconfig.json index 9bb9cf3b51..be7119ed21 100644 --- a/packages/autocertifier-client/tsconfig.json +++ b/packages/autocertifier-client/tsconfig.json @@ -1,7 +1,12 @@ { "extends": "../../tsconfig.node.json", "compilerOptions": { - "outDir": "dist" + "outDir": "dist", + + /* Resolution */ + "module": "preserve", + "moduleResolution": "bundler", + "baseUrl": "." }, "include": [ "src" diff --git a/packages/utils/package.json b/packages/utils/package.json index 60ab043f18..9352f67a35 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -8,18 +8,18 @@ "directory": "packages/utils" }, "main": "./dist/exports-nodejs.cjs", - "module": "./dist/exports-nodejs.mjs", + "module": "./dist/exports-nodejs.js", "types": "./dist/exports-nodejs.d.ts", "exports": { ".": { "browser": { "types": "./dist/exports-browser.d.ts", - "import": "./dist/exports-browser.mjs", + "import": "./dist/exports-browser.js", "require": "./dist/exports-browser.cjs" }, "default": { "types": "./dist/exports-nodejs.d.ts", - "import": "./dist/exports-nodejs.mjs", + "import": "./dist/exports-nodejs.js", "require": "./dist/exports-nodejs.cjs" } } @@ -67,7 +67,7 @@ "@types/md5": "^2.3.6", "@types/secp256k1": "^4.0.7", "rimraf": "^6.1.2", - "rollup": "^4.53.3", + "rollup": "^4.55.1", "rollup-plugin-dts": "^6.3.0", "tsx": "^4.21.0" } diff --git a/packages/utils/rollup.config.mts b/packages/utils/rollup.config.mts index 3ed70c0823..b68619a3e1 100644 --- a/packages/utils/rollup.config.mts +++ b/packages/utils/rollup.config.mts @@ -53,7 +53,7 @@ function nodejs(): RollupOptions { output: [ { format: 'es', - file: './dist/exports-nodejs.mjs', + file: './dist/exports-nodejs.js', sourcemap: true, }, { @@ -83,7 +83,7 @@ function browser(): RollupOptions { output: [ { format: 'es', - file: './dist/exports-browser.mjs', + file: './dist/exports-browser.js', sourcemap: true, }, { From d32481f8e648d7c35118cd64614d2d27fe32c246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Wed, 7 Jan 2026 13:07:25 +0100 Subject: [PATCH 04/18] refactor: Bundle `browser-test-runner` (#3333) This pull request refactors the build and packaging process for the `browser-test-runner` package, introducing Rollup for bundling, improving module resolution, and updating various scripts and dependencies. The changes make the package outputs more consistent, enhance compatibility (especially for Electron and Karma), and modernize the codebase with ES module syntax and improved path handling. ## Changes **Build & packaging improvements:** * Added a new `rollup.config.mts` configuration to bundle outputs for CommonJS, ES modules, Electron preload, and type declarations using Rollup. * Updated `package.json` to define `main`, `module`, and `types` entry points, specify more granular files for publishing, and add build scripts (`prebuild`, `postbuild`, `reset-self`). * Added new devDependencies for Rollup, plugins, and build tooling in `package.json`. * Updated `tsconfig.json` to use `"module": "preserve"` and `"moduleResolution": "bundler"` for better compatibility with modern bundlers. **Code modernization & compatibility:** * Switched from CommonJS `require` to ES module `import` syntax in `karma-setup.js` for `expect`. * Improved path resolution in `createKarmaConfig.ts` to use `fileURLToPath` and `import.meta.url` for locating setup and preload files, ensuring compatibility with ESM and Electron environments. [[1]](diffhunk://#diff-ce10c51de1f8215dc5ff71f630122f7f6ed1d768f3c0e83f0978654b3ac3701fR2-R10) [[2]](diffhunk://#diff-ce10c51de1f8215dc5ff71f630122f7f6ed1d768f3c0e83f0978654b3ac3701fL61-R62) * Updated `createWebpackConfig.ts` to explicitly set `timers: false` in the `fallback` object for module resolution. --- package-lock.json | 86 +++++++++++++++++ packages/autocertifier-client/package.json | 2 +- packages/browser-test-runner/package.json | 21 +++- .../browser-test-runner/rollup.config.mts | 95 +++++++++++++++++++ .../src/createKarmaConfig.ts | 5 +- .../src/createWebpackConfig.ts | 5 +- .../browser-test-runner/src/karma-setup.js | 2 +- packages/browser-test-runner/tsconfig.json | 7 +- packages/utils/package.json | 2 +- 9 files changed, 213 insertions(+), 12 deletions(-) create mode 100644 packages/browser-test-runner/rollup.config.mts diff --git a/package-lock.json b/package-lock.json index 81d0ce2a97..9db43b5e82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29987,6 +29987,7 @@ "devDependencies": { "@electron/rebuild": "^4.0.1", "@jest/fake-timers": "^30.0.5", + "@rollup/plugin-node-resolve": "^16.0.3", "buffer": "^6.0.3", "electron": "^34.0.0", "expect": "^30.0.5", @@ -30000,10 +30001,95 @@ "karma-spec-reporter": "^0.0.36", "karma-webpack": "^5.0.1", "node-polyfill-webpack-plugin": "^4.1.0", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0", "webpack": "^5.103.0", "webpack-cli": "^6.0.1" } }, + "packages/browser-test-runner/node_modules/glob": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", + "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/browser-test-runner/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/browser-test-runner/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "packages/browser-test-runner/node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/browser-test-runner/node_modules/rimraf": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", + "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.0", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "packages/cdn-location": { "name": "@streamr/cdn-location", "version": "103.2.0", diff --git a/packages/autocertifier-client/package.json b/packages/autocertifier-client/package.json index 0b71ae70e2..c6a3abc6fb 100644 --- a/packages/autocertifier-client/package.json +++ b/packages/autocertifier-client/package.json @@ -21,7 +21,7 @@ "build": "tsc -b", "postbuild": "NODE_OPTIONS='--import tsx' rollup -c rollup.config.mts", "check": "tsc --noEmit", - "reset-self": "rimraf --glob '**/*.tsbuildinfo'", + "reset-self": "rimraf --glob 'dist/**/*.tsbuildinfo'", "clean": "rm -rf dist generated *.tsbuildinfo node_modules/.cache || true", "eslint": "eslint --cache --cache-location=node_modules/.cache/.eslintcache/ '*/**/*.{js,ts}'" }, diff --git a/packages/browser-test-runner/package.json b/packages/browser-test-runner/package.json index bdf09514a4..5dee6d7307 100644 --- a/packages/browser-test-runner/package.json +++ b/packages/browser-test-runner/package.json @@ -8,18 +8,24 @@ "url": "git+https://github.com/streamr-dev/network.git", "directory": "packages/browser-test-runner" }, - "main": "./dist/src/exports.js", - "browser": { - "./dist/src/exports.js": false - }, + "main": "./dist/exports.cjs", + "module": "./dist/exports.js", + "types": "./dist/exports.d.ts", "files": [ - "dist", + "dist/exports.*", + "dist/preload.cjs", + "dist/preload.cjs.map", + "dist/karma-setup.js", + "dist/karma-setup.js.map", "!*.tsbuildinfo", "LICENSE" ], "scripts": { + "prebuild": "npm run reset-self", "build": "tsc -b", + "postbuild": "NODE_OPTIONS='--import tsx' rollup -c rollup.config.mts", "check": "tsc --noEmit", + "reset-self": "rimraf --glob 'dist/**/*.tsbuildinfo'", "eslint": "eslint --cache --cache-location=node_modules/.cache/.eslintcache/ '**/*.{js,ts}'" }, "author": "Streamr Network AG ", @@ -27,6 +33,7 @@ "devDependencies": { "@electron/rebuild": "^4.0.1", "@jest/fake-timers": "^30.0.5", + "@rollup/plugin-node-resolve": "^16.0.3", "buffer": "^6.0.3", "electron": "^34.0.0", "expect": "^30.0.5", @@ -40,6 +47,10 @@ "karma-spec-reporter": "^0.0.36", "karma-webpack": "^5.0.1", "node-polyfill-webpack-plugin": "^4.1.0", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0", "webpack": "^5.103.0", "webpack-cli": "^6.0.1" } diff --git a/packages/browser-test-runner/rollup.config.mts b/packages/browser-test-runner/rollup.config.mts new file mode 100644 index 0000000000..394651dd05 --- /dev/null +++ b/packages/browser-test-runner/rollup.config.mts @@ -0,0 +1,95 @@ +import { defineConfig, type RollupOptions } from 'rollup' +import { dts } from 'rollup-plugin-dts' +import { nodeResolve } from '@rollup/plugin-node-resolve' + +export default defineConfig([ + ...nodejs(), + nodejsTypes(), +]) + +function nodejs(): RollupOptions[] { + return [ + { + input: './dist/src/exports.js', + output: [ + { + format: 'es', + file: './dist/exports.js', + sourcemap: true, + }, + { + format: 'cjs', + file: './dist/exports.cjs', + sourcemap: true, + }, + ], + plugins: [ + nodeResolve({ + preferBuiltins: true, + }), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + }, + { + /** + * We need a CJS preload file for Electron apps - that's the only format they support. + */ + input: './dist/src/preload.js', + output: [ + { + format: 'cjs', + file: './dist/preload.cjs', + sourcemap: true, + }, + ], + external: [ + /node_modules/, + /@streamr\//, + ], + }, + { + /** + * For Karma test runner. We only need ES module format here. + */ + input: './dist/src/karma-setup.js', + output: [ + { + format: 'es', + file: './dist/karma-setup.js', + sourcemap: true, + }, + ], + plugins: [ + nodeResolve({ + preferBuiltins: true, + }), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + }, + ] +} + +function nodejsTypes(): RollupOptions { + return { + input: './dist/src/exports.d.ts', + output: [ + { + file: './dist/exports.d.ts', + }, + ], + plugins: [ + nodeResolve(), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} diff --git a/packages/browser-test-runner/src/createKarmaConfig.ts b/packages/browser-test-runner/src/createKarmaConfig.ts index 38d09d8285..dd169dd8cf 100644 --- a/packages/browser-test-runner/src/createKarmaConfig.ts +++ b/packages/browser-test-runner/src/createKarmaConfig.ts @@ -1,4 +1,5 @@ import fs from 'fs' +import { fileURLToPath } from 'url' import type { Configuration, ExternalItem } from 'webpack' const DEBUG_MODE = process.env.BROWSER_TEST_DEBUG_MODE ?? false @@ -6,7 +7,7 @@ const DEBUG_MODE = process.env.BROWSER_TEST_DEBUG_MODE ?? false export const createKarmaConfig = ( testPaths: string[], webpackConfig: () => Configuration, localDirectory?: string ): (config: any) => any => { - const setupFiles = [__dirname + '/karma-setup.js'] + const setupFiles = [fileURLToPath(new URL('./karma-setup.js', import.meta.url))] if (localDirectory !== undefined) { const localSetupFile = localDirectory + '/karma-setup.js' @@ -58,7 +59,7 @@ export const createKarmaConfig = ( browserWindowOptions: { webPreferences: { contextIsolation: false, - preload: __dirname + '/preload.js', + preload: fileURLToPath(new URL('./preload.cjs', import.meta.url)), webSecurity: false, sandbox: false, nodeIntegration: true diff --git a/packages/browser-test-runner/src/createWebpackConfig.ts b/packages/browser-test-runner/src/createWebpackConfig.ts index 293d89f9d6..c779946dd6 100644 --- a/packages/browser-test-runner/src/createWebpackConfig.ts +++ b/packages/browser-test-runner/src/createWebpackConfig.ts @@ -44,7 +44,10 @@ export const createWebpackConfig = ( resolve: { extensions: ['.ts', '.js'], alias, - fallback, + fallback: { + timers: false, + ...fallback + }, }, output: { sourceMapFilename: `[name].[contenthash].js.map`, diff --git a/packages/browser-test-runner/src/karma-setup.js b/packages/browser-test-runner/src/karma-setup.js index ad535f344a..e31ed48ce2 100644 --- a/packages/browser-test-runner/src/karma-setup.js +++ b/packages/browser-test-runner/src/karma-setup.js @@ -3,7 +3,7 @@ import * as jestMock from 'jest-mock' -const expect = require('expect').default +import expect from 'expect' import { ModernFakeTimers } from '@jest/fake-timers' diff --git a/packages/browser-test-runner/tsconfig.json b/packages/browser-test-runner/tsconfig.json index 126cae2a06..9544356da2 100644 --- a/packages/browser-test-runner/tsconfig.json +++ b/packages/browser-test-runner/tsconfig.json @@ -1,7 +1,12 @@ { "extends": "../../tsconfig.node.json", "compilerOptions": { - "outDir": "dist" + "outDir": "dist", + + /* Resolution */ + "module": "preserve", + "moduleResolution": "bundler", + "baseUrl": "." }, "include": [ "src" diff --git a/packages/utils/package.json b/packages/utils/package.json index 9352f67a35..deb81ebe9c 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -36,7 +36,7 @@ "build": "tsc -b", "postbuild": "NODE_OPTIONS=\"--import tsx\" rollup -c rollup.config.mts", "check": "tsc -b tsconfig.jest.json", - "reset-self": "rimraf --glob '**/*.tsbuildinfo'", + "reset-self": "rimraf --glob 'dist/**/*.tsbuildinfo'", "clean": "jest --clearCache --config '{}' || true; rm -rf dist *.tsbuildinfo node_modules/.cache || true", "eslint": "eslint --cache --cache-location=node_modules/.cache/.eslintcache/ '*/**/*.{js,ts}'", "test": "jest", From 9f2d6f368aa8cbbf1f48acfaae0432738fedc4a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Wed, 7 Jan 2026 15:09:35 +0100 Subject: [PATCH 05/18] refactor: Bundle `cdn-location` (#3335) > [!NOTE] > Looks like #3332 is too much at once - lotta failing tests and what not. I will deal with each of them packages separately. This pull request updates the build and packaging setup for the `@streamr/cdn-location` package. The main improvements are the introduction of a Rollup build process to generate both CommonJS and ES module outputs, refined output file structure, and enhancements to the development workflow. ## Changes **Build system and packaging improvements:** * Added a new `rollup.config.mts` file to configure Rollup to bundle the package into both ES module (`exports.js`) and CommonJS (`exports.cjs`) formats, as well as to generate type declarations (`exports.d.ts`). This setup also marks dependencies as external to avoid bundling them. * Updated `package.json` to point to the new output files, specify both `main` (CommonJS) and `module` (ESM) entry points, and restrict the published files to only the relevant outputs. * Added Rollup and related plugins (`@rollup/plugin-node-resolve`, `rollup-plugin-dts`, `tsx`) as dev dependencies, and introduced a `postbuild` script to run Rollup after TypeScript compilation. Also added a `prebuild` script to clean up build info files. * Updated `tsconfig.json` to use `"module": "preserve"` and `"moduleResolution": "bundler"` for better compatibility with the new bundling process. **Monorepo integration:** * Included `@streamr/cdn-location` in the monorepo bootstrap process in the root `Dockerfile.node`, ensuring it is built alongside other packages. --- Dockerfile.node | 1 + package-lock.json | 88 ++++++++++++++++++++++++- packages/cdn-location/package.json | 17 +++-- packages/cdn-location/rollup.config.mts | 54 +++++++++++++++ packages/cdn-location/tsconfig.json | 7 +- 5 files changed, 161 insertions(+), 6 deletions(-) create mode 100644 packages/cdn-location/rollup.config.mts diff --git a/Dockerfile.node b/Dockerfile.node index d9ae3d746f..576e11bd71 100644 --- a/Dockerfile.node +++ b/Dockerfile.node @@ -6,6 +6,7 @@ RUN --mount=type=cache,target=/root/.npm \ npm run bootstrap-pkg --package=@streamr/utils && \ npm run bootstrap-pkg --package=@streamr/proto-rpc && \ npm run bootstrap-pkg --package=@streamr/autocertifier-client && \ + npm run bootstrap-pkg --package=@streamr/cdn-location && \ npm run bootstrap-pkg --package=@streamr/dht && \ npm run bootstrap-pkg --package=@streamr/trackerless-network && \ npm run bootstrap-pkg --package=@streamr/sdk && \ diff --git a/package-lock.json b/package-lock.json index 9db43b5e82..ec8c831cf5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30099,7 +30099,93 @@ "haversine": "^1.1.1" }, "devDependencies": { - "@types/haversine": "^1.1.8" + "@rollup/plugin-node-resolve": "^16.0.3", + "@types/haversine": "^1.1.8", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0" + } + }, + "packages/cdn-location/node_modules/glob": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", + "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/cdn-location/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/cdn-location/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "packages/cdn-location/node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/cdn-location/node_modules/rimraf": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", + "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.0", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "packages/cli-tools": { diff --git a/packages/cdn-location/package.json b/packages/cdn-location/package.json index e23265e26c..1e742e5e43 100644 --- a/packages/cdn-location/package.json +++ b/packages/cdn-location/package.json @@ -7,10 +7,11 @@ "url": "git+https://github.com/streamr-dev/network.git", "directory": "packages/cdn-location" }, - "main": "dist/src/exports.js", - "types": "dist/src/exports.d.ts", + "main": "./dist/exports.cjs", + "module": "./dist/exports.js", + "types": "./dist/exports.d.ts", "files": [ - "dist", + "dist/exports.*", "!*.tsbuildinfo", "README.md", "LICENSE" @@ -18,8 +19,11 @@ "license": "Apache-2.0", "author": "Streamr Network AG ", "scripts": { + "prebuild": "npm run reset-self", "build": "tsc -b", + "postbuild": "NODE_OPTIONS='--import tsx' rollup -c rollup.config.mts", "check": "tsc -p tsconfig.jest.json", + "reset-self": "rimraf --glob 'dist/**/*.tsbuildinfo'", "clean": "jest --clearCache --config '{}' || true; rm -rf dist *.tsbuildinfo node_modules/.cache || true", "eslint": "eslint --cache --cache-location=node_modules/.cache/.eslintcache/ '*/**/*.{js,ts}'", "test": "jest test/integration", @@ -32,6 +36,11 @@ "haversine": "^1.1.1" }, "devDependencies": { - "@types/haversine": "^1.1.8" + "@rollup/plugin-node-resolve": "^16.0.3", + "@types/haversine": "^1.1.8", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0" } } diff --git a/packages/cdn-location/rollup.config.mts b/packages/cdn-location/rollup.config.mts new file mode 100644 index 0000000000..cc1fbda131 --- /dev/null +++ b/packages/cdn-location/rollup.config.mts @@ -0,0 +1,54 @@ +import { defineConfig, type RollupOptions } from 'rollup' +import { dts } from 'rollup-plugin-dts' +import { nodeResolve } from '@rollup/plugin-node-resolve' + +export default defineConfig([ + nodejs(), + nodejsTypes(), +]) + +function nodejs(): RollupOptions { + return { + input: './dist/src/exports.js', + output: [ + { + format: 'es', + file: './dist/exports.js', + sourcemap: true, + }, + { + format: 'cjs', + file: './dist/exports.cjs', + sourcemap: true, + }, + ], + plugins: [ + nodeResolve({ + preferBuiltins: true, + }), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} + +function nodejsTypes(): RollupOptions { + return { + input: './dist/src/exports.d.ts', + output: [ + { + file: './dist/exports.d.ts', + }, + ], + plugins: [ + nodeResolve(), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} diff --git a/packages/cdn-location/tsconfig.json b/packages/cdn-location/tsconfig.json index 5621ed82fc..6ad637ddb1 100644 --- a/packages/cdn-location/tsconfig.json +++ b/packages/cdn-location/tsconfig.json @@ -1,7 +1,12 @@ { "extends": "../../tsconfig.node.json", "compilerOptions": { - "outDir": "dist" + "outDir": "dist", + + /* Resolution */ + "module": "preserve", + "moduleResolution": "bundler", + "baseUrl": "." }, "include": [ "src" From e5728bd499235056ce8e5fdd1cfa680d9c17d307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Wed, 7 Jan 2026 15:22:02 +0100 Subject: [PATCH 06/18] refactor: Bundle `test-utils`; clean-up the testing setup (#3334) This pull request refactors the packaging and module setup for the `@streamr/test-utils` package, modernizing its build process and improving TypeScript and module resolution support. The changes include switching to a Rollup-based build, updating exports for better compatibility, consolidating custom matcher types, and cleaning up obsolete files. These updates make the package easier to consume in different environments and improve developer experience. ### Build and packaging improvements * Added a new `rollup.config.mts` configuration and switched the build process to use Rollup for both JavaScript and TypeScript declaration files, including new scripts in `package.json` for prebuild and postbuild steps. [[1]](diffhunk://#diff-a0a6d5226837d528f922340045f16689ae1305f9e13444f02cd5af3c8ca27ebcR1-R99) [[2]](diffhunk://#diff-d7a3fa8faf23a3288372b5fa5679e4f24c0be0dbb8da3c3399315a40fc4b872cL10-R51) [[3]](diffhunk://#diff-d7a3fa8faf23a3288372b5fa5679e4f24c0be0dbb8da3c3399315a40fc4b872cR70-R76) * Updated the `package.json` exports and files fields to provide clear entry points for both ESM and CommonJS consumers, and to expose custom matcher modules directly. ### TypeScript and module resolution enhancements * Improved TypeScript configuration by updating `typesVersions` and `tsconfig.json` to use bundler-style module resolution and by referencing matcher types directly from `customMatchers` instead of a separate file. [[1]](diffhunk://#diff-d7a3fa8faf23a3288372b5fa5679e4f24c0be0dbb8da3c3399315a40fc4b872cL10-R51) [[2]](diffhunk://#diff-aac742816d4fdf853f9ea01d95b5631fc3fcde78870b2bcdde087dbbe4f5f0a1L8-R12) [[3]](diffhunk://#diff-d78d8c40e5585d63387aa1f7cd3c261e2d617035b9b2aff3bf311fd565a72b6bL13-R13) [[4]](diffhunk://#diff-88900faaa35c4ab3f7ca3ff3f6ef788ac93135bb928f89b7aeab37cd3f97a7a1L21-R21) * Removed the obsolete `customMatcherTypes.ts` file and consolidated matcher type declarations into `customMatchers.ts`, simplifying global type augmentation for Jest and Expect. [[1]](diffhunk://#diff-33cb836509b8b233d42419de8f746d81d5e3f1f11b224bb9a0d430c4a724daccL1-L13) [[2]](diffhunk://#diff-46302ca607b0d6e06ec1cf8d6774e378afb302a28a344ee7765e008421e4b392L50-R68) ### Code cleanup and consistency * Updated imports and exports throughout the codebase to use named exports for `customMatchers` and to ensure matcher setup is consistent and direct. [[1]](diffhunk://#diff-818e39864728c9de8dcb73c4efb093d655013cc3cd4e72376ae986e41a94485fL179-R179) [[2]](diffhunk://#diff-d236e791996dddf0961df2f1c25d2c9a8433a4b116f60e7549d07f4fe3bfd61bL1-R1) [[3]](diffhunk://#diff-6d98f04c9981e55112650c9b4b981c328ada96a1c3cc51d285f71f1377e206bbL1-R1) * Removed the legacy `setupCustomMatchers.js` alias file, as setup is now handled via direct exports and improved build outputs. --- package-lock.json | 88 ++++++++++++++++- packages/sdk/test/types/global.d.ts | 2 +- packages/test-utils/customMatcherTypes.d.ts | 11 --- packages/test-utils/package.json | 50 +++++++++- packages/test-utils/rollup.config.mts | 99 +++++++++++++++++++ packages/test-utils/setupCustomMatchers.js | 10 -- packages/test-utils/src/customMatcherTypes.ts | 13 --- packages/test-utils/src/customMatchers.ts | 20 +++- packages/test-utils/src/index.ts | 3 +- .../test-utils/src/setupCustomMatchers.ts | 3 +- .../test-utils/test/customMatchers.test.ts | 2 +- packages/test-utils/tsconfig.json | 6 +- tsconfig.jest.json | 2 +- tsconfig.karma.json | 2 +- 14 files changed, 261 insertions(+), 50 deletions(-) delete mode 100644 packages/test-utils/customMatcherTypes.d.ts create mode 100644 packages/test-utils/rollup.config.mts delete mode 100644 packages/test-utils/setupCustomMatchers.js delete mode 100644 packages/test-utils/src/customMatcherTypes.ts diff --git a/package-lock.json b/package-lock.json index ec8c831cf5..ed3aff8c43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30487,8 +30487,94 @@ "lodash": "^4.17.21" }, "devDependencies": { + "@rollup/plugin-node-resolve": "^16.0.3", "@types/cors": "^2.8.19", - "@types/express": "^5.0.1" + "@types/express": "^5.0.1", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0" + } + }, + "packages/test-utils/node_modules/glob": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", + "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/test-utils/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/test-utils/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "packages/test-utils/node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/test-utils/node_modules/rimraf": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", + "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.0", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "packages/trackerless-network": { diff --git a/packages/sdk/test/types/global.d.ts b/packages/sdk/test/types/global.d.ts index 3d154612b2..a0c38efe3f 100644 --- a/packages/sdk/test/types/global.d.ts +++ b/packages/sdk/test/types/global.d.ts @@ -1,2 +1,2 @@ import 'jest-extended' -import '@streamr/test-utils/customMatcherTypes' +import '@streamr/test-utils/customMatchers' diff --git a/packages/test-utils/customMatcherTypes.d.ts b/packages/test-utils/customMatcherTypes.d.ts deleted file mode 100644 index 6e4effea9e..0000000000 --- a/packages/test-utils/customMatcherTypes.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * This file injects custom matcher types into Jest. - * - * The actual type declarations are in "./dist/src/customMatcherTypes.d.ts", and this file serves - * as an alias. In a dependent library the type information is typically injected by adding - * an import statement to test/types/global.d.ts. Since this file is listed in package.json's - * "files" section, we can import the types like this: - * import '@streamr/test-utils/customMatcherTypes' - */ - -/// diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 1465ce1a1a..4ca64a5f90 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -7,17 +7,52 @@ "url": "git+https://github.com/streamr-dev/network.git", "directory": "packages/test-utils" }, - "main": "./dist/src/index.js", - "types": "./dist/src/index.d.ts", + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.cjs", + "default": "./dist/index.js" + }, + "./setupCustomMatchers": { + "types": "./dist/setupCustomMatchers.d.ts", + "import": "./dist/setupCustomMatchers.js", + "require": "./dist/setupCustomMatchers.cjs", + "default": "./dist/setupCustomMatchers.js" + }, + "./customMatchers": { + "types": "./dist/customMatchers.d.ts", + "import": "./dist/customMatchers.js", + "require": "./dist/customMatchers.cjs", + "default": "./dist/customMatchers.js" + } + }, + "typesVersions": { + "*": { + "customMatchers": [ + "dist/customMatchers.d.ts" + ], + "setupCustomMatchers": [ + "dist/setupCustomMatchers.d.ts" + ] + } + }, "files": [ "dist", + "!dist/src", "!*.tsbuildinfo", - "setupCustomMatchers.js", - "customMatcherTypes.d.ts" + "LICENSE", + "README.md" ], "scripts": { + "prebuild": "npm run reset-self", "build": "tsc -b", + "postbuild": "NODE_OPTIONS='--import tsx' rollup -c rollup.config.mts", "check": "tsc -p tsconfig.jest.json", + "reset-self": "rimraf --glob 'dist/**/*.tsbuildinfo'", "clean": "jest --clearCache --config '{}' || true; rm -rf dist *.tsbuildinfo node_modules/.cache || true", "test": "jest", "eslint": "eslint --cache --cache-location=node_modules/.cache/.eslintcache/ '*/**/*.{js,ts}'" @@ -36,7 +71,12 @@ "lodash": "^4.17.21" }, "devDependencies": { + "@rollup/plugin-node-resolve": "^16.0.3", "@types/cors": "^2.8.19", - "@types/express": "^5.0.1" + "@types/express": "^5.0.1", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0" } } diff --git a/packages/test-utils/rollup.config.mts b/packages/test-utils/rollup.config.mts new file mode 100644 index 0000000000..efde0221cc --- /dev/null +++ b/packages/test-utils/rollup.config.mts @@ -0,0 +1,99 @@ +import { defineConfig, type RollupOptions } from 'rollup' +import { dts } from 'rollup-plugin-dts' +import { nodeResolve } from '@rollup/plugin-node-resolve' + +export default defineConfig([ + nodejs(), + ...nodejsTypes(), +]) + +function nodejs(): RollupOptions { + return { + input: [ + './dist/src/index.js', + './dist/src/customMatchers.js', + './dist/src/setupCustomMatchers.js', + ], + output: [ + { + format: 'es', + dir: './dist', + entryFileNames: '[name].js', + chunkFileNames: '[name].[hash].js', + sourcemap: true, + }, + { + format: 'cjs', + dir: './dist', + entryFileNames: '[name].cjs', + chunkFileNames: '[name].[hash].cjs', + sourcemap: true, + }, + ], + plugins: [ + nodeResolve({ + preferBuiltins: true, + }), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} + +function nodejsTypes(): RollupOptions[] { + return [ + { + input: './dist/src/index.d.ts', + output: [ + { file: './dist/index.d.ts' }, + ], + plugins: [ + nodeResolve(), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + }, + { + input: './dist/src/customMatchers.d.ts', + output: [ + { file: './dist/customMatchers.d.ts' }, + ], + plugins: [ + nodeResolve(), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + }, + { + input: './dist/src/setupCustomMatchers.d.ts', + output: [ + { file: './dist/setupCustomMatchers.d.ts' }, + ], + plugins: [ + nodeResolve(), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + onwarn(warning, rollupWarn) { + /** + * setupCustomMatchers.d.ts is an empty file, so rollup dts plugin + * generates an EMPTY_BUNDLE warning. We can safely ignore it. + */ + if (warning.code !== 'EMPTY_BUNDLE') { + rollupWarn(warning) + } + } + } + ] +} diff --git a/packages/test-utils/setupCustomMatchers.js b/packages/test-utils/setupCustomMatchers.js deleted file mode 100644 index d9832f05f7..0000000000 --- a/packages/test-utils/setupCustomMatchers.js +++ /dev/null @@ -1,10 +0,0 @@ -/* - * This file adds the custom matcher functionality to Jest. - * - * The actual setup is in "./dist/src/setupCustomMatchers.js", and this file serves as an alias. - * Since this file is listed in package.json's "files" section, we can setup the custom matchers - * like this: - * setupFilesAfterEnv: ['@streamr/test-utils/setupCustomMatchers'] - */ - -require('./dist/src/setupCustomMatchers') diff --git a/packages/test-utils/src/customMatcherTypes.ts b/packages/test-utils/src/customMatcherTypes.ts deleted file mode 100644 index 90b0653dc6..0000000000 --- a/packages/test-utils/src/customMatcherTypes.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { CustomMatchers } from './customMatchers' - -// we could ES2015 module syntax (https://jestjs.io/docs/expect#expectextendmatchers), -// but the IDE doesn't find custom matchers if we do that -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace jest { - // eslint-disable-next-line @typescript-eslint/no-empty-object-type - interface Expect extends CustomMatchers {} - // eslint-disable-next-line @typescript-eslint/no-empty-object-type - interface Matchers extends CustomMatchers {} - } -} diff --git a/packages/test-utils/src/customMatchers.ts b/packages/test-utils/src/customMatchers.ts index ea67328cec..075c570f48 100644 --- a/packages/test-utils/src/customMatchers.ts +++ b/packages/test-utils/src/customMatchers.ts @@ -47,4 +47,22 @@ const toEqualBinary = ( } } -export { toEqualBinary } +export const customMatchers = { + toEqualBinary +} + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace jest { + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + interface Matchers extends CustomMatchers {} + } +} + +declare module 'expect' { + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + interface AsymmetricMatchers extends CustomMatchers {} + + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + interface Matchers extends CustomMatchers {} +} diff --git a/packages/test-utils/src/index.ts b/packages/test-utils/src/index.ts index e6cc6958b5..3ad11e5639 100644 --- a/packages/test-utils/src/index.ts +++ b/packages/test-utils/src/index.ts @@ -176,8 +176,7 @@ type MethodNames = { // Pick only methods of T export type Methods = Pick> -import * as customMatchers from './customMatchers' -export { customMatchers } +export { customMatchers } from './customMatchers' const TEST_CHAIN_CONFIG = CHAIN_CONFIG.dev2 diff --git a/packages/test-utils/src/setupCustomMatchers.ts b/packages/test-utils/src/setupCustomMatchers.ts index d2479902d0..3f6b11f567 100644 --- a/packages/test-utils/src/setupCustomMatchers.ts +++ b/packages/test-utils/src/setupCustomMatchers.ts @@ -1,3 +1,2 @@ -import * as customMatchers from './customMatchers' - +import { customMatchers } from './customMatchers' expect.extend(customMatchers) diff --git a/packages/test-utils/test/customMatchers.test.ts b/packages/test-utils/test/customMatchers.test.ts index 985b54cb2b..51388e96f5 100644 --- a/packages/test-utils/test/customMatchers.test.ts +++ b/packages/test-utils/test/customMatchers.test.ts @@ -1,4 +1,4 @@ -import {} from '../src/customMatcherTypes' +import '../src/customMatchers' describe('custom matchers', () => { it('happy path', () => { diff --git a/packages/test-utils/tsconfig.json b/packages/test-utils/tsconfig.json index 33cb004949..bc8bf7329e 100644 --- a/packages/test-utils/tsconfig.json +++ b/packages/test-utils/tsconfig.json @@ -5,7 +5,11 @@ "types": [ "node", "jest" - ] + ], + + /* Resolution */ + "moduleResolution": "bundler", + "module": "preserve" }, "include": [ "src" diff --git a/tsconfig.jest.json b/tsconfig.jest.json index 819ffe9c34..a000f066f1 100644 --- a/tsconfig.jest.json +++ b/tsconfig.jest.json @@ -10,7 +10,7 @@ "node", "jest", "jest-extended", - "@streamr/test-utils/customMatcherTypes" + "@streamr/test-utils/customMatchers" ], "sourceMap": false } diff --git a/tsconfig.karma.json b/tsconfig.karma.json index 599e6fba27..6558ff9a48 100644 --- a/tsconfig.karma.json +++ b/tsconfig.karma.json @@ -18,7 +18,7 @@ "types": [ "jest", "jest-extended", - "@streamr/test-utils/customMatcherTypes" + "@streamr/test-utils/customMatchers" ], "sourceMap": true, "skipLibCheck": true, From 642e7755b61db0af15b858ab02bf5c84fc86042e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Wed, 7 Jan 2026 16:17:58 +0100 Subject: [PATCH 07/18] refactor: Bundle `geoip-location` (#3336) This pull request introduces significant improvements to the build and packaging process for the `@streamr/geoip-location` package, including the addition of a Rollup build step, updates to the package entry points, and enhancements to development dependencies. These changes ensure better compatibility and distribution of the package in both CommonJS and ES module formats, streamline type definitions, and improve build script reliability. **Build and packaging improvements:** * Added a new Rollup configuration (`rollup.config.mts`) to bundle output files in both ES and CommonJS formats and to generate type definitions, improving compatibility and distribution. * Updated the `package.json` entry points to explicitly specify CommonJS (`main`), ES module (`module`), and type definitions (`types`) outputs; adjusted the `files` field to exclude unnecessary files from the published package. * Enhanced build scripts in `package.json` by adding `prebuild`, `postbuild`, and `reset-self` steps to automate cleaning and bundling, improving reliability and developer experience. **Dependency and configuration updates:** * Added development dependencies for Rollup, its plugins, and related utilities (`@rollup/plugin-node-resolve`, `rollup`, `rollup-plugin-dts`, `tsx`, `rimraf`) to support the new build process. * Updated TypeScript configuration (`tsconfig.json`) to use `moduleResolution: bundler` and `module: preserve`, aligning with the new bundling approach. **Integration:** * Included the `@streamr/geoip-location` package in the Docker build process to ensure it is bootstrapped along with other packages. --- Dockerfile.node | 1 + package-lock.json | 88 ++++++++++++++++++++++- packages/geoip-location/package.json | 21 ++++-- packages/geoip-location/rollup.config.mts | 52 ++++++++++++++ packages/geoip-location/tsconfig.json | 7 +- 5 files changed, 160 insertions(+), 9 deletions(-) create mode 100644 packages/geoip-location/rollup.config.mts diff --git a/Dockerfile.node b/Dockerfile.node index 576e11bd71..fcdedd6ace 100644 --- a/Dockerfile.node +++ b/Dockerfile.node @@ -7,6 +7,7 @@ RUN --mount=type=cache,target=/root/.npm \ npm run bootstrap-pkg --package=@streamr/proto-rpc && \ npm run bootstrap-pkg --package=@streamr/autocertifier-client && \ npm run bootstrap-pkg --package=@streamr/cdn-location && \ + npm run bootstrap-pkg --package=@streamr/geoip-location && \ npm run bootstrap-pkg --package=@streamr/dht && \ npm run bootstrap-pkg --package=@streamr/trackerless-network && \ npm run bootstrap-pkg --package=@streamr/sdk && \ diff --git a/package-lock.json b/package-lock.json index ed3aff8c43..ac92d21482 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30282,9 +30282,95 @@ "uuid": "^11.1.0" }, "devDependencies": { + "@rollup/plugin-node-resolve": "^16.0.3", "@types/long-timeout": "^0.1.2", "@types/tar": "^6.1.11", - "express": "^5.2.0" + "express": "^5.2.0", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0" + } + }, + "packages/geoip-location/node_modules/glob": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", + "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/geoip-location/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/geoip-location/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "packages/geoip-location/node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/geoip-location/node_modules/rimraf": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", + "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.0", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "packages/node": { diff --git a/packages/geoip-location/package.json b/packages/geoip-location/package.json index 5ee83e0e2c..45dc348dd1 100644 --- a/packages/geoip-location/package.json +++ b/packages/geoip-location/package.json @@ -7,15 +7,14 @@ "url": "git+https://github.com/streamr-dev/network.git", "directory": "packages/geoip-location" }, - "main": "dist/src/exports.js", + "main": "./dist/exports.cjs", + "module": "./dist/exports.js", + "types": "./dist/exports.d.ts", "browser": { - "dist/src/exports.js": false, - "dist/src/GeoIpLocator.js": false, - "dist/src/downloadGeoIpDatabase.js": false + "./dist/exports.js": false }, - "types": "dist/src/exports.d.ts", "files": [ - "dist", + "dist/exports.*", "!*.tsbuildinfo", "README.md", "LICENSE" @@ -23,8 +22,11 @@ "license": "Apache-2.0", "author": "Streamr Network AG ", "scripts": { + "prebuild": "npm run reset-self", "build": "tsc -b", + "postbuild": "NODE_OPTIONS='--import tsx' rollup -c rollup.config.mts", "check": "tsc -p tsconfig.jest.json", + "reset-self": "rimraf --glob 'dist/**/*.tsbuildinfo'", "clean": "jest --clearCache --config '{}' || true; rm -rf dist *.tsbuildinfo node_modules/.cache || true", "eslint": "eslint --cache --cache-location=node_modules/.cache/.eslintcache/ '*/**/*.{js,ts}'", "test": "jest test/unit", @@ -39,8 +41,13 @@ "uuid": "^11.1.0" }, "devDependencies": { + "@rollup/plugin-node-resolve": "^16.0.3", "@types/long-timeout": "^0.1.2", "@types/tar": "^6.1.11", - "express": "^5.2.0" + "express": "^5.2.0", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0" } } diff --git a/packages/geoip-location/rollup.config.mts b/packages/geoip-location/rollup.config.mts new file mode 100644 index 0000000000..517b0f9b30 --- /dev/null +++ b/packages/geoip-location/rollup.config.mts @@ -0,0 +1,52 @@ +import { defineConfig, type RollupOptions } from 'rollup' +import { dts } from 'rollup-plugin-dts' +import { nodeResolve } from '@rollup/plugin-node-resolve' + +export default defineConfig([ + nodejs(), + nodejsTypes(), +]) + +function nodejs(): RollupOptions { + return { + input: './dist/src/exports.js', + output: [ + { + format: 'es', + file: './dist/exports.js', + sourcemap: true, + }, + { + format: 'cjs', + file: './dist/exports.cjs', + sourcemap: true, + }, + ], + plugins: [ + nodeResolve({ + preferBuiltins: true, + }), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} + +function nodejsTypes(): RollupOptions { + return { + input: './dist/src/exports.d.ts', + output: [ + { file: './dist/exports.d.ts' }, + ], + plugins: [ + nodeResolve(), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} diff --git a/packages/geoip-location/tsconfig.json b/packages/geoip-location/tsconfig.json index 5621ed82fc..6ad637ddb1 100644 --- a/packages/geoip-location/tsconfig.json +++ b/packages/geoip-location/tsconfig.json @@ -1,7 +1,12 @@ { "extends": "../../tsconfig.node.json", "compilerOptions": { - "outDir": "dist" + "outDir": "dist", + + /* Resolution */ + "module": "preserve", + "moduleResolution": "bundler", + "baseUrl": "." }, "include": [ "src" From c057fe930b7b7e95fce45dfb9cf786b98e7416cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Wed, 7 Jan 2026 16:44:18 +0100 Subject: [PATCH 08/18] Bundle `proto-rpc` (#3337) This pull request updates the build and packaging pipeline for the `proto-rpc` package to improve module output, type bundling, and cleanup. The changes introduce Rollup for bundling, refine the output structure, and add supporting scripts and dependencies. **Build and packaging improvements:** * Added a new `rollup.config.mts` configuration file to bundle both CommonJS (`exports.cjs`) and ES module (`exports.js`) outputs, as well as generate bundled type definitions (`exports.d.ts`). * Updated `package.json` to point `main` to `./dist/src/exports.cjs`, add a `module` entry for ESM, and restrict the published files to only the bundled outputs. * Added a `postbuild` script to run Rollup after TypeScript compilation, and a `reset-self` script to clean up build artifacts before building. **Dependency updates:** * Added build-related devDependencies: `rollup`, `rollup-plugin-dts`, `@rollup/plugin-node-resolve`, `tsx`, and `rimraf` for improved bundling and cleanup. **TypeScript configuration:** * Updated `tsconfig.json` to use `module: preserve` and `moduleResolution: bundler` to better support the new bundling workflow. --- package-lock.json | 88 +++++++++++++++++++++++++++- packages/proto-rpc/package.json | 19 ++++-- packages/proto-rpc/rollup.config.mts | 52 ++++++++++++++++ packages/proto-rpc/tsconfig.json | 7 ++- 4 files changed, 158 insertions(+), 8 deletions(-) create mode 100644 packages/proto-rpc/rollup.config.mts diff --git a/package-lock.json b/package-lock.json index ac92d21482..c289d914a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30455,15 +30455,101 @@ "uuid": "^11.1.0" }, "devDependencies": { + "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", "@streamr/test-utils": "103.2.0", - "@types/lodash": "^4.17.21" + "@types/lodash": "^4.17.21", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0" }, "optionalDependencies": { "bufferutil": "^4.0.9", "utf-8-validate": "^6.0.5" } }, + "packages/proto-rpc/node_modules/glob": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", + "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/proto-rpc/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/proto-rpc/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "packages/proto-rpc/node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/proto-rpc/node_modules/rimraf": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", + "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.0", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "packages/sdk": { "name": "@streamr/sdk", "version": "103.2.0", diff --git a/packages/proto-rpc/package.json b/packages/proto-rpc/package.json index a8e0ec204b..97f7ce64d9 100644 --- a/packages/proto-rpc/package.json +++ b/packages/proto-rpc/package.json @@ -7,10 +7,11 @@ "url": "git+https://github.com/streamr-dev/network.git", "directory": "packages/proto-rpc" }, - "main": "dist/src/exports.js", - "types": "dist/src/exports.d.ts", + "main": "./dist/exports.cjs", + "module": "./dist/exports.js", + "types": "./dist/exports.d.ts", "files": [ - "dist", + "dist/exports.*", "!*.tsbuildinfo", "README.md", "LICENSE" @@ -18,10 +19,11 @@ "license": "(Apache-2.0 AND BSD-3-Clause)", "author": "Streamr Network AG ", "scripts": { - "prebuild": "./proto.sh", + "prebuild": "npm run reset-self && ./proto.sh", "build": "tsc -b", - "build-browser": "webpack --mode=development --progress", + "postbuild": "NODE_OPTIONS='--import tsx' rollup -c rollup.config.mts", "check": "./test-proto.sh && tsc -b tsconfig.jest.json", + "reset-self": "rimraf --glob 'dist/**/*.tsbuildinfo'", "clean": "jest --clearCache --config '{}' || true; rm -rf dist generated *.tsbuildinfo node_modules/.cache || true", "eslint": "./test-proto.sh && eslint --cache --cache-location=node_modules/.cache/.eslintcache/ '*/**/*.{js,ts}'", "test": "./test-proto.sh && npm run test-unit && npm run test-integration", @@ -38,9 +40,14 @@ "uuid": "^11.1.0" }, "devDependencies": { + "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", "@streamr/test-utils": "103.2.0", - "@types/lodash": "^4.17.21" + "@types/lodash": "^4.17.21", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "tsx": "^4.21.0" }, "optionalDependencies": { "bufferutil": "^4.0.9", diff --git a/packages/proto-rpc/rollup.config.mts b/packages/proto-rpc/rollup.config.mts new file mode 100644 index 0000000000..517b0f9b30 --- /dev/null +++ b/packages/proto-rpc/rollup.config.mts @@ -0,0 +1,52 @@ +import { defineConfig, type RollupOptions } from 'rollup' +import { dts } from 'rollup-plugin-dts' +import { nodeResolve } from '@rollup/plugin-node-resolve' + +export default defineConfig([ + nodejs(), + nodejsTypes(), +]) + +function nodejs(): RollupOptions { + return { + input: './dist/src/exports.js', + output: [ + { + format: 'es', + file: './dist/exports.js', + sourcemap: true, + }, + { + format: 'cjs', + file: './dist/exports.cjs', + sourcemap: true, + }, + ], + plugins: [ + nodeResolve({ + preferBuiltins: true, + }), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} + +function nodejsTypes(): RollupOptions { + return { + input: './dist/src/exports.d.ts', + output: [ + { file: './dist/exports.d.ts' }, + ], + plugins: [ + nodeResolve(), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} diff --git a/packages/proto-rpc/tsconfig.json b/packages/proto-rpc/tsconfig.json index 9bb9cf3b51..be7119ed21 100644 --- a/packages/proto-rpc/tsconfig.json +++ b/packages/proto-rpc/tsconfig.json @@ -1,7 +1,12 @@ { "extends": "../../tsconfig.node.json", "compilerOptions": { - "outDir": "dist" + "outDir": "dist", + + /* Resolution */ + "module": "preserve", + "moduleResolution": "bundler", + "baseUrl": "." }, "include": [ "src" From 6ffc84d2f45572befc45292d38f720ee4933ca2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Wed, 7 Jan 2026 23:13:24 +0100 Subject: [PATCH 09/18] refactor: Bundle `dht` (#3338) This pull request introduces a major refactor and modernization of the DHT package's build system, module exports, and browser/node environment separation. The changes migrate the package to a dual build (Node.js and browser), introduce a Rollup-based bundling pipeline, clean up legacy scripts, and refactor source code organization and imports for clarity and maintainability. ## Changes The most important changes are: **Build system & package exports modernization:** - Switched to a Rollup-based build process, with a new `rollup.config.mts` that generates separate Node.js and browser bundles (both JS and type declarations), and added relevant plugins and scripts to `package.json`. This replaces the previous postbuild shell script and package.json rewrite script, which have been removed. - Updated the `exports` field in `package.json` to provide proper entrypoints and type definitions for both browser and Node.js consumers, ensuring correct module resolution and compatibility with modern bundlers. **Source code refactoring & browser/node separation:** - Moved browser-specific connection classes to a dedicated `src/browser/` directory, renamed classes for clarity (e.g., `WebrtcConnection` instead of `BrowserWebrtcConnection`), and updated imports throughout the codebase to use consistent paths and new module aliases. - Introduced browser stubs for Node.js-only features (e.g., `WebsocketServer`, `GeoIpLocator`, `AutoCertifierClient`), which throw errors when used in the browser, improving developer experience and preventing runtime failures. **Testing & module resolution:** - Added and updated module aliasing in test and build configs (`jest.config.ts`, `karma.config.ts`) to ensure the correct environment-specific implementations are used during testing and bundling. **Code quality & internal refactors:** - Improved code clarity by updating imports to use named imports for `EventEmitter`, moving utility functions to dedicated helper files, and cleaning up legacy or redundant code. **Documentation:** - Updated documentation to reflect refactored class names, improving consistency between code and docs. --- docs/docs/help/operator-faq.md | 10 +- package-lock.json | 118 ++++++++++++++- packages/dht/jest.config.ts | 3 + packages/dht/karma.config.ts | 18 ++- packages/dht/package.json | 42 ++++-- packages/dht/rollup.config.mts | 142 ++++++++++++++++++ packages/dht/scripts/postbuild.sh | 10 -- packages/dht/scripts/rewrite-package.ts | 42 ------ packages/dht/scripts/tsconfig.json | 6 - .../WebrtcConnection.ts} | 24 ++- .../WebsocketClientConnection.ts} | 4 +- packages/dht/src/browser/WebsocketServer.ts | 29 ++++ .../dht/src/browser/createGeoipLocator.ts | 5 + .../defaultAutoCertifierClientFactory.ts | 13 ++ .../dht/src/browser/isBrowserEnvironment.ts | 1 + packages/dht/src/connection/Connection.ts | 2 +- .../src/connection/ConnectionLockRpcLocal.ts | 2 +- .../dht/src/connection/ConnectionManager.ts | 18 +-- .../dht/src/connection/ConnectorFacade.ts | 3 +- .../dht/src/connection/ManagedConnection.ts | 4 +- .../dht/src/connection/PendingConnection.ts | 4 +- .../dht/src/connection/connectivityChecker.ts | 2 +- .../connection/connectivityRequestHandler.ts | 2 +- .../getNodeIdOrUnknownFromPeerDescriptor.ts | 27 ++++ .../src/connection/webrtc/WebrtcConnector.ts | 19 +-- .../webrtc/WebrtcConnectorRpcLocal.ts | 4 +- packages/dht/src/connection/webrtc/consts.ts | 1 + .../connection/webrtc/iceServerAsString.ts | 2 +- packages/dht/src/connection/webrtc/types.ts | 7 + .../AbstractWebsocketClientConnection.ts | 2 +- .../websocket/AutoCertifierClientFacade.ts | 26 +--- .../websocket/WebsocketClientConnector.ts | 8 +- .../websocket/WebsocketServerConnection.ts | 2 +- .../websocket/WebsocketServerConnector.ts | 9 +- .../dht/src/connection/websocket/types.ts | 20 +++ packages/dht/src/dht/DhtNode.ts | 10 +- packages/dht/src/dht/PeerManager.ts | 12 +- packages/dht/src/dht/consts.ts | 2 + packages/dht/src/dht/contact/ContactList.ts | 2 +- .../dht/src/dht/contact/RingContactList.ts | 2 +- .../dht/src/dht/contact/SortedContactList.ts | 6 +- .../dht/src/dht/contact/getClosestNodes.ts | 2 +- .../dht/src/dht/discovery/DiscoverySession.ts | 7 +- .../dht/src/dht/discovery/PeerDiscovery.ts | 2 +- .../dht/src/dht/helpers/getPeerDistance.ts | 9 ++ .../RecursiveOperationManager.ts | 8 +- .../RecursiveOperationSession.ts | 2 +- .../dht/src/dht/routing/RoutingSession.ts | 2 +- packages/dht/src/exports.ts | 4 +- .../helpers/browser/isBrowserEnvironment.ts | 1 - .../browser/isBrowserEnvironment_override.ts | 3 - .../dht/src/helpers/createPeerDescriptor.ts | 11 +- packages/dht/src/helpers/offering.ts | 5 +- packages/dht/src/helpers/protoClasses.ts | 1 - packages/dht/src/helpers/protoToString.ts | 1 - packages/dht/src/identifiers.ts | 5 +- .../WebrtcConnection.ts} | 39 ++--- .../WebsocketClientConnection.ts} | 4 +- .../websocket => nodejs}/WebsocketServer.ts | 24 +-- packages/dht/src/nodejs/createGeoipLocator.ts | 11 ++ .../defaultAutoCertifierClientFactory.ts | 28 ++++ .../dht/src/nodejs/isBrowserEnvironment.ts | 1 + .../src/{types => nodejs}/textencoding.d.ts | 0 .../dht/src/types/WebrtcConnectionParams.ts | 12 ++ .../WebsocketServerMemoryLeak.test.ts | 4 +- .../dht/test/end-to-end/Layer0Webrtc.test.ts | 2 +- packages/dht/test/integration/DhtNode.test.ts | 4 +- .../dht/test/integration/Websocket.test.ts | 4 +- .../unit/AutoCertifierClientFacade.test.ts | 2 +- .../dht/test/unit/ConnectionManager.test.ts | 3 +- .../dht/test/unit/DiscoverySession.test.ts | 5 +- packages/dht/test/unit/Handshaker.test.ts | 2 +- .../dht/test/unit/ManagedConnection.test.ts | 2 +- .../dht/test/unit/PendingConnection.test.ts | 2 +- .../dht/test/unit/WebrtcConnection.test.ts | 6 +- .../dht/test/unit/WebsocketServer.test.ts | 2 +- .../test/unit/createPeerDescriptor.test.ts | 8 +- .../dht/test/unit/getClosestNodes.test.ts | 6 +- packages/dht/test/utils/FakeTransport.ts | 2 +- .../dht/test/utils/mock/MockConnection.ts | 2 +- packages/dht/test/utils/topology.ts | 4 +- packages/dht/tsconfig.browser-generated.json | 10 ++ packages/dht/tsconfig.browser.json | 44 ++++++ packages/dht/tsconfig.jest.json | 18 ++- packages/dht/tsconfig.json | 16 +- packages/dht/tsconfig.karma.json | 15 +- ...ated.json => tsconfig.node-generated.json} | 2 +- packages/dht/tsconfig.node.json | 33 ++++ packages/trackerless-network/karma.config.ts | 11 +- packages/utils/package.json | 10 +- packages/utils/src/exports.ts | 1 + 91 files changed, 733 insertions(+), 334 deletions(-) create mode 100644 packages/dht/rollup.config.mts delete mode 100755 packages/dht/scripts/postbuild.sh delete mode 100644 packages/dht/scripts/rewrite-package.ts delete mode 100644 packages/dht/scripts/tsconfig.json rename packages/dht/src/{connection/webrtc/BrowserWebrtcConnection.ts => browser/WebrtcConnection.ts} (92%) rename packages/dht/src/{connection/websocket/BrowserWebsocketClientConnection.ts => browser/WebsocketClientConnection.ts} (90%) create mode 100644 packages/dht/src/browser/WebsocketServer.ts create mode 100644 packages/dht/src/browser/createGeoipLocator.ts create mode 100644 packages/dht/src/browser/defaultAutoCertifierClientFactory.ts create mode 100644 packages/dht/src/browser/isBrowserEnvironment.ts create mode 100644 packages/dht/src/connection/helpers/getNodeIdOrUnknownFromPeerDescriptor.ts create mode 100644 packages/dht/src/connection/webrtc/consts.ts create mode 100644 packages/dht/src/connection/webrtc/types.ts create mode 100644 packages/dht/src/connection/websocket/types.ts create mode 100644 packages/dht/src/dht/consts.ts create mode 100644 packages/dht/src/dht/helpers/getPeerDistance.ts delete mode 100644 packages/dht/src/helpers/browser/isBrowserEnvironment.ts delete mode 100644 packages/dht/src/helpers/browser/isBrowserEnvironment_override.ts rename packages/dht/src/{connection/webrtc/NodeWebrtcConnection.ts => nodejs/WebrtcConnection.ts} (88%) rename packages/dht/src/{connection/websocket/NodeWebsocketClientConnection.ts => nodejs/WebsocketClientConnection.ts} (89%) rename packages/dht/src/{connection/websocket => nodejs}/WebsocketServer.ts (90%) create mode 100644 packages/dht/src/nodejs/createGeoipLocator.ts create mode 100644 packages/dht/src/nodejs/defaultAutoCertifierClientFactory.ts create mode 100644 packages/dht/src/nodejs/isBrowserEnvironment.ts rename packages/dht/src/{types => nodejs}/textencoding.d.ts (100%) create mode 100644 packages/dht/src/types/WebrtcConnectionParams.ts create mode 100644 packages/dht/tsconfig.browser-generated.json create mode 100644 packages/dht/tsconfig.browser.json rename packages/dht/{tsconfig.generated.json => tsconfig.node-generated.json} (75%) create mode 100644 packages/dht/tsconfig.node.json diff --git a/docs/docs/help/operator-faq.md b/docs/docs/help/operator-faq.md index 3a7bbc98ad..7f0c82c343 100644 --- a/docs/docs/help/operator-faq.md +++ b/docs/docs/help/operator-faq.md @@ -179,10 +179,10 @@ Recheck operator address from the hub & reconfigure your node to use the correct I’m receiving the following warning message. ```JSON -WARN [2023-11-10T10:01:42.418] (NodeWebRtcConnection): Failed to set remote descriptor for peer 0a3849076d8a43b19b876fbc6eba935f -WARN [2023-11-10T10:01:42.421] (NodeWebRtcConnection): Failed to set remote candidate for peer 0a3849076d8a43b19b876fbc6eba935f -WARN [2023-11-10T10:01:42.622] (NodeWebRtcConnection): Failed to set remote candidate for peer 0a3849076d8a43b19b876fbc6eba935f -WARN [2023-11-10T10:01:42.867] (NodeWebRtcConnection): Failed to set remote candidate for peer 0a3849076d8a43b19b876fbc6eba935f +WARN [2023-11-10T10:01:42.418] (WebRtcConnection): Failed to set remote descriptor for peer 0a3849076d8a43b19b876fbc6eba935f +WARN [2023-11-10T10:01:42.421] (WebRtcConnection): Failed to set remote candidate for peer 0a3849076d8a43b19b876fbc6eba935f +WARN [2023-11-10T10:01:42.622] (WebRtcConnection): Failed to set remote candidate for peer 0a3849076d8a43b19b876fbc6eba935f +WARN [2023-11-10T10:01:42.867] (WebRtcConnection): Failed to set remote candidate for peer 0a3849076d8a43b19b876fbc6eba935f ``` **Explanation:** @@ -332,4 +332,4 @@ You'll need to pay the early exit fee of 5k DATA. The unwithdrawn earnings from #### What are some tips for staying safe on Streamr? - Consider starting small with your stake amount and use common sense to never stake more than you can afford to lose. A professional audit of the incentive layer has been completed by Cyfrin, but nothing can be guaranteed of course. - If you want to stake on a sponsorship, DO NOT click on the "Sponsor". That's for funding the sponsorship, not staking! Instead, go to the sponsorship you want to stake on and click "Join as an operator” and enter the amount. -- There may be an increase in activity by scammers. A common approach is to pretend to offer help or tech support in direct messages (something we never do). Report any account that is asking you to sign transactions or asking for any sort of credentials such as your private key. These accounts are trying to steal your tokens. It’s advised you disable DMs on Discord. More tips can be found in #server-safety-guide. \ No newline at end of file +- There may be an increase in activity by scammers. A common approach is to pretend to offer help or tech support in direct messages (something we never do). Report any account that is asking you to sign transactions or asking for any sort of credentials such as your private key. These accounts are trying to steal your tokens. It’s advised you disable DMs on Discord. More tips can be found in #server-safety-guide. diff --git a/package-lock.json b/package-lock.json index c289d914a5..0076f1b555 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7295,11 +7295,32 @@ } }, "node_modules/@rollup/plugin-alias": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-5.1.1.tgz", - "integrity": "sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-6.0.0.tgz", + "integrity": "sha512-tPCzJOtS7uuVZd+xPhoy5W4vThe6KWXNmsFCNktaAh5RTqcLiSfT4huPQIXkgJ6YCOjJHvecOAzQxLFhPxKr+g==", "dev": true, "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "rollup": ">=4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-json": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0" + }, "engines": { "node": ">=14.0.0" }, @@ -30243,6 +30264,9 @@ "ws": "^8.18.3" }, "devDependencies": { + "@rollup/plugin-alias": "^6.0.0", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", "@streamr/test-utils": "103.2.0", "@types/heap": "^0.2.35", @@ -30252,14 +30276,35 @@ "@types/ws": "^8.18.1", "jest-leak-detector": "^27.3.1", "jest-matcher-utils": "^30.0.5", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", "ts-essentials": "^10.1.1", - "ts-node": "^10.9.2" + "tsx": "^4.21.0" }, "optionalDependencies": { "bufferutil": "^4.0.9", "utf-8-validate": "^6.0.5" } }, + "packages/dht/node_modules/glob": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", + "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "packages/dht/node_modules/ipaddr.js": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", @@ -30269,6 +30314,69 @@ "node": ">= 10" } }, + "packages/dht/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/dht/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "packages/dht/node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/dht/node_modules/rimraf": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", + "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.0", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "packages/geoip-location": { "name": "@streamr/geoip-location", "version": "103.2.0", @@ -30803,7 +30911,7 @@ "sha3": "^2.1.4" }, "devDependencies": { - "@rollup/plugin-alias": "^5.1.1", + "@rollup/plugin-alias": "^6.0.0", "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", "@types/lodash": "^4.17.21", diff --git a/packages/dht/jest.config.ts b/packages/dht/jest.config.ts index 829ec460e5..330629096c 100644 --- a/packages/dht/jest.config.ts +++ b/packages/dht/jest.config.ts @@ -3,6 +3,9 @@ import defaultConfig from '../../jest.config' const config: Config.InitialOptions = { ...defaultConfig, + moduleNameMapper: { + '^@/(.*)$': '/src/nodejs/$1' + }, setupFilesAfterEnv: [ ...defaultConfig.setupFilesAfterEnv, './test/utils/customMatchers.ts', diff --git a/packages/dht/karma.config.ts b/packages/dht/karma.config.ts index 505d61e569..0ac143cf8d 100644 --- a/packages/dht/karma.config.ts +++ b/packages/dht/karma.config.ts @@ -7,18 +7,22 @@ const TEST_PATHS = [ './test/end-to-end/**/!(RecoveryFromFailedAutoCertification*|memory-leak*|GeoIpLayer0*).ts' ] -const NodeWebrtcConnection = resolve(__dirname, 'src/connection/webrtc/NodeWebrtcConnection.ts') -const BrowserWebrtcConnection = resolve(__dirname, 'src/connection/webrtc/BrowserWebrtcConnection.ts') -const NodeWebsocketClientConnection = resolve(__dirname, 'src/connection/websocket/NodeWebsocketClientConnection.ts') -const BrowserWebsocketClientConnection = resolve(__dirname, 'src/connection/websocket/BrowserWebsocketClientConnection.ts') - export default createKarmaConfig( TEST_PATHS, createWebpackConfig({ libraryName: 'dht', alias: { - [NodeWebrtcConnection]: BrowserWebrtcConnection, - [NodeWebsocketClientConnection]: BrowserWebsocketClientConnection + /** + * Selectively alias only browser-specific implementations here. The rest stays in `nodejs/` + * because these (like WebsocketServer) are needed for testing and running WebSocket-based + * code in Electron environment. + * + * This also proves that the "browser" test are really nodejs-flavoured browser tests where + * we still depend on NodeJS elements. + */ + '@/WebrtcConnection': resolve(__dirname, 'src/browser/WebrtcConnection.ts'), + '@/WebsocketClientConnection': resolve(__dirname, 'src/browser/WebsocketClientConnection.ts'), + '@': resolve(__dirname, 'src/nodejs'), }, fallback: { module: false diff --git a/packages/dht/package.json b/packages/dht/package.json index eac24b4a71..f4292396b8 100644 --- a/packages/dht/package.json +++ b/packages/dht/package.json @@ -7,26 +7,36 @@ "url": "git+https://github.com/streamr-dev/network.git", "directory": "packages/dht" }, - "main": "./dist/src/exports.js", - "types": "./dist/src/exports.d.ts", - "browser": { - "./dist/src/connection/webrtc/NodeWebrtcConnection.js": "./dist/src/connection/webrtc/BrowserWebrtcConnection.js", - "./dist/src/connection/websocket/NodeWebsocketClientConnection.js": "./dist/src/connection/websocket/BrowserWebsocketClientConnection.js", - "./dist/src/helpers/browser/isBrowserEnvironment.js": "./dist/src/helpers/browser/isBrowserEnvironment_override.js" + "main": "./dist/exports-nodejs.cjs", + "module": "./dist/exports-nodejs.js", + "types": "./dist/exports-nodejs.d.ts", + "exports": { + ".": { + "types": "./dist/exports-nodejs.d.ts", + "browser": { + "types": "./dist/exports-browser.d.ts", + "import": "./dist/exports-browser.js", + "require": "./dist/exports-browser.cjs" + }, + "import": "./dist/exports-nodejs.js", + "require": "./dist/exports-nodejs.cjs", + "default": "./dist/exports-nodejs.js" + } }, - "license": "STREAMR NETWORK OPEN SOURCE LICENSE", - "author": "Streamr Network AG ", "files": [ - "dist", + "dist/exports-nodejs.*", + "dist/exports-browser.*", "!*.tsbuildinfo", "README.md" ], + "license": "STREAMR NETWORK OPEN SOURCE LICENSE", + "author": "Streamr Network AG ", "scripts": { - "prebuild": "./proto.sh", - "postbuild": "./scripts/postbuild.sh", + "prebuild": "npm run reset-self && ./proto.sh", "build": "tsc -b", - "build-browser": "webpack --mode=development --progress", + "postbuild": "NODE_OPTIONS='--import tsx' rollup -c rollup.config.mts", "check": "tsc -b tsconfig.jest.json", + "reset-self": "rimraf --glob 'dist/**/*.tsbuildinfo'", "clean": "jest --clearCache --config '{}' || true; rm -rf dist generated *.tsbuildinfo node_modules/.cache || true", "eslint": "eslint --cache --cache-location=node_modules/.cache/.eslintcache/ '*/**/*.{js,ts}'", "test": "npm run test-unit && npm run test-integration && npm run test-end-to-end", @@ -57,6 +67,9 @@ "ws": "^8.18.3" }, "devDependencies": { + "@rollup/plugin-alias": "^6.0.0", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", "@streamr/test-utils": "103.2.0", "@types/heap": "^0.2.35", @@ -66,8 +79,11 @@ "@types/ws": "^8.18.1", "jest-leak-detector": "^27.3.1", "jest-matcher-utils": "^30.0.5", + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", "ts-essentials": "^10.1.1", - "ts-node": "^10.9.2" + "tsx": "^4.21.0" }, "optionalDependencies": { "bufferutil": "^4.0.9", diff --git a/packages/dht/rollup.config.mts b/packages/dht/rollup.config.mts new file mode 100644 index 0000000000..1b57140fe8 --- /dev/null +++ b/packages/dht/rollup.config.mts @@ -0,0 +1,142 @@ +import { defineConfig, type RollupOptions } from 'rollup' +import { dts } from 'rollup-plugin-dts' +import alias, { type Alias } from '@rollup/plugin-alias' +import { nodeResolve } from '@rollup/plugin-node-resolve' +import json from '@rollup/plugin-json' +import { fileURLToPath } from 'url' + +const nodejsAliases: Alias[] = [ + { + find: /^@\//, + replacement: fileURLToPath( + new URL('./dist/nodejs/src/nodejs/', import.meta.url) + ), + }, +] + +const browserAliases: Alias[] = [ + { + find: /^@\//, + replacement: fileURLToPath( + new URL('./dist/browser/src/browser/', import.meta.url) + ), + }, +] + +export default defineConfig([ + nodejs(), + nodejsTypes(), + browser(), + browserTypes(), +]) + +function nodejs(): RollupOptions { + return { + input: './dist/nodejs/src/exports.js', + output: [ + { + format: 'es', + file: './dist/exports-nodejs.js', + sourcemap: true, + }, + { + format: 'cjs', + file: './dist/exports-nodejs.cjs', + sourcemap: true, + }, + ], + plugins: [ + json(), + alias({ + entries: nodejsAliases, + }), + nodeResolve({ + preferBuiltins: true, + }), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + + } +} + +function nodejsTypes(): RollupOptions { + return { + input: './dist/nodejs/src/exports.d.ts', + output: [ + { + file: './dist/exports-nodejs.d.ts', + }, + ], + plugins: [ + alias({ + entries: nodejsAliases, + }), + nodeResolve(), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + + } +} + +function browser(): RollupOptions { + return { + input: './dist/browser/src/exports.js', + output: [ + { + format: 'es', + file: './dist/exports-browser.js', + sourcemap: true, + }, + { + format: 'cjs', + file: './dist/exports-browser.cjs', + sourcemap: true, + }, + ], + plugins: [ + json(), + alias({ + entries: browserAliases, + }), + nodeResolve({ + preferBuiltins: false, + browser: true, + }), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + + } +} + +function browserTypes(): RollupOptions { + return { + input: './dist/browser/src/exports.d.ts', + output: [ + { file: './dist/exports-browser.d.ts' }, + ], + plugins: [ + alias({ + entries: browserAliases, + }), + nodeResolve({ + preferBuiltins: false, + browser: true, + }), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} diff --git a/packages/dht/scripts/postbuild.sh b/packages/dht/scripts/postbuild.sh deleted file mode 100755 index 70efe8acad..0000000000 --- a/packages/dht/scripts/postbuild.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -mkdir -p dist - -SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) - -cd "${SCRIPT_DIR}/.." - -# Sanitize the final package.json -npx ts-node scripts/rewrite-package.ts diff --git a/packages/dht/scripts/rewrite-package.ts b/packages/dht/scripts/rewrite-package.ts deleted file mode 100644 index 9069678779..0000000000 --- a/packages/dht/scripts/rewrite-package.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * This script overwrites the package.json file inside the dist folder while - * adjusting relative pathnames for exports. Since the compiled output is inside - * "dist", but the original package.json references paths as if it's in the root, - * we need to strip "dist" from all export fields (main, types, …). - * - * This ensures that consumers of the package (incl. bundlers like Webpack) import - * the correct files without referencing "dist" in their paths, maintaining proper - * module resolution. - */ - -import pkg from '../package.json' -import * as fs from 'node:fs' -import path from 'node:path' - -function fixPathname(pathname: string): string { - return pathname.startsWith('./dist') - ? `./${path.relative('./dist', pathname)}` - : pathname -} - -const { main, types, browser, scripts: _scripts, ...rest } = pkg - -const newPkg = { - ...rest, - main: fixPathname(main), - types: fixPathname(types), - browser: Object.entries(browser).reduce( - (memo, [fromPathname, toPathname]) => ({ - ...memo, - [fixPathname(fromPathname)]: - typeof toPathname === 'string' - ? fixPathname(toPathname) - : toPathname, - }), - {} - ), -} - -const dist = path.resolve(__dirname, '../dist/package.json') - -fs.writeFileSync(dist, JSON.stringify(newPkg, null, 2)) diff --git a/packages/dht/scripts/tsconfig.json b/packages/dht/scripts/tsconfig.json deleted file mode 100644 index 5a03dbdeb8..0000000000 --- a/packages/dht/scripts/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "..", - "include": [ - "**/*" - ] -} diff --git a/packages/dht/src/connection/webrtc/BrowserWebrtcConnection.ts b/packages/dht/src/browser/WebrtcConnection.ts similarity index 92% rename from packages/dht/src/connection/webrtc/BrowserWebrtcConnection.ts rename to packages/dht/src/browser/WebrtcConnection.ts index 956fadc3cb..d4cb5a0acf 100644 --- a/packages/dht/src/connection/webrtc/BrowserWebrtcConnection.ts +++ b/packages/dht/src/browser/WebrtcConnection.ts @@ -1,11 +1,11 @@ -/// - -import EventEmitter from 'eventemitter3' -import { WebrtcConnectionEvents, IWebrtcConnection, RtcDescription } from './IWebrtcConnection' -import { IConnection, ConnectionID, ConnectionType } from '../IConnection' +import { EventEmitter } from 'eventemitter3' +import { WebrtcConnectionEvents, IWebrtcConnection, RtcDescription } from '../connection/webrtc/IWebrtcConnection' +import { IConnection, ConnectionID, ConnectionType } from '../connection/IConnection' import { Logger } from '@streamr/utils' -import { EARLY_TIMEOUT, IceServer } from './WebrtcConnector' -import { createRandomConnectionId } from '../Connection' +import { IceServer } from '../connection/webrtc/types' +import { EARLY_TIMEOUT } from '../connection/webrtc/consts' +import { createRandomConnectionId } from '../connection/Connection' +import type { WebrtcConnectionParams } from '../types/WebrtcConnectionParams' enum DisconnectedRtcPeerConnectionStateEnum { DISCONNECTED = 'disconnected', @@ -13,13 +13,9 @@ enum DisconnectedRtcPeerConnectionStateEnum { CLOSED = 'closed', } -const logger = new Logger('BrowserWebrtcConnection') - -interface Params { - iceServers?: IceServer[] -} +const logger = new Logger('WebrtcConnection (browser)') -export class NodeWebrtcConnection extends EventEmitter implements IWebrtcConnection, IConnection { +export class WebrtcConnection extends EventEmitter implements IWebrtcConnection, IConnection { public connectionId: ConnectionID public readonly connectionType: ConnectionType = ConnectionType.WEBRTC @@ -37,7 +33,7 @@ export class NodeWebrtcConnection extends EventEmitter i private earlyTimeout: NodeJS.Timeout private readonly messageQueue: Uint8Array[] = [] - constructor(params: Params) { + constructor(params: WebrtcConnectionParams) { super() this.connectionId = createRandomConnectionId() this.iceServers = params.iceServers ?? [] diff --git a/packages/dht/src/connection/websocket/BrowserWebsocketClientConnection.ts b/packages/dht/src/browser/WebsocketClientConnection.ts similarity index 90% rename from packages/dht/src/connection/websocket/BrowserWebsocketClientConnection.ts rename to packages/dht/src/browser/WebsocketClientConnection.ts index 4b0f01acb9..b0569991f9 100644 --- a/packages/dht/src/connection/websocket/BrowserWebsocketClientConnection.ts +++ b/packages/dht/src/browser/WebsocketClientConnection.ts @@ -1,8 +1,8 @@ import { Logger } from '@streamr/utils' import { ICloseEvent, IMessageEvent, w3cwebsocket as Websocket } from 'websocket' -import { AbstractWebsocketClientConnection } from './AbstractWebsocketClientConnection' +import { AbstractWebsocketClientConnection } from '../connection/websocket/AbstractWebsocketClientConnection' -const logger = new Logger('BrowserWebsocketClientConnection') +const logger = new Logger('WebsocketClientConnection (browser)') const BINARY_TYPE = 'arraybuffer' diff --git a/packages/dht/src/browser/WebsocketServer.ts b/packages/dht/src/browser/WebsocketServer.ts new file mode 100644 index 0000000000..3737e9f805 --- /dev/null +++ b/packages/dht/src/browser/WebsocketServer.ts @@ -0,0 +1,29 @@ +/* eslint-disable class-methods-use-this */ +import { EventEmitter } from 'eventemitter3' +import type { + IWebsocketServer, + WebsocketServerEvents, +} from '../connection/websocket/types' + +/** + * A stub WebsocketServer for browser environment. + */ + +export class WebsocketServer extends EventEmitter implements IWebsocketServer { + constructor(_params: unknown) { + super() + } + + public async start(): Promise { + throw new Error('WebsocketServer is not supported in browser environment') + } + + public async stop(): Promise { + throw new Error('WebsocketServer is not supported in browser environment') + } + + public updateCertificate(_cert: string, _key: string): void { + throw new Error('WebsocketServer is not supported in browser environment') + } +} + diff --git a/packages/dht/src/browser/createGeoipLocator.ts b/packages/dht/src/browser/createGeoipLocator.ts new file mode 100644 index 0000000000..4168594166 --- /dev/null +++ b/packages/dht/src/browser/createGeoipLocator.ts @@ -0,0 +1,5 @@ +import type { GeoIpLocator } from '@streamr/geoip-location' + +export const createGeoipLocator = (_geoIpDatabaseFolder: string): Promise => { + throw new Error('GeoIpLocator is not supported in browser environment') +} diff --git a/packages/dht/src/browser/defaultAutoCertifierClientFactory.ts b/packages/dht/src/browser/defaultAutoCertifierClientFactory.ts new file mode 100644 index 0000000000..773cafc3e7 --- /dev/null +++ b/packages/dht/src/browser/defaultAutoCertifierClientFactory.ts @@ -0,0 +1,13 @@ +import { AutoCertifierClient } from '@streamr/autocertifier-client' +import { ListeningRpcCommunicator } from '../transport/ListeningRpcCommunicator' + +export const defaultAutoCertifierClientFactory = ( + _configFile: string, + _autoCertifierUrl: string, + _autoCertifierRpcCommunicator: ListeningRpcCommunicator, + _wsServerPort: number +): AutoCertifierClient => { + throw new Error( + 'AutoCertifierClient is not supported in browser environment' + ) +} diff --git a/packages/dht/src/browser/isBrowserEnvironment.ts b/packages/dht/src/browser/isBrowserEnvironment.ts new file mode 100644 index 0000000000..ccc0a7d7af --- /dev/null +++ b/packages/dht/src/browser/isBrowserEnvironment.ts @@ -0,0 +1 @@ +export const isBrowserEnvironment = true diff --git a/packages/dht/src/connection/Connection.ts b/packages/dht/src/connection/Connection.ts index a0bf8a052e..4d3141ed8f 100644 --- a/packages/dht/src/connection/Connection.ts +++ b/packages/dht/src/connection/Connection.ts @@ -1,4 +1,4 @@ -import EventEmitter from 'eventemitter3' +import { EventEmitter } from 'eventemitter3' import { PeerDescriptor } from '../../generated/packages/dht/protos/DhtRpc' import { ConnectionID, ConnectionType, ConnectionEvents } from './IConnection' import { v4 as uuid } from 'uuid' diff --git a/packages/dht/src/connection/ConnectionLockRpcLocal.ts b/packages/dht/src/connection/ConnectionLockRpcLocal.ts index 2a09fc4212..48228fcdca 100644 --- a/packages/dht/src/connection/ConnectionLockRpcLocal.ts +++ b/packages/dht/src/connection/ConnectionLockRpcLocal.ts @@ -12,7 +12,7 @@ import { } from '../../generated/packages/dht/protos/DhtRpc' import { IConnectionLockRpc } from '../../generated/packages/dht/protos/DhtRpc.server' import { DhtCallContext } from '../rpc-protocol/DhtCallContext' -import { getNodeIdOrUnknownFromPeerDescriptor } from './ConnectionManager' +import { getNodeIdOrUnknownFromPeerDescriptor } from './helpers/getNodeIdOrUnknownFromPeerDescriptor' import { LockID } from './ConnectionLockStates' import { DhtAddress, areEqualPeerDescriptors, toNodeId } from '../identifiers' diff --git a/packages/dht/src/connection/ConnectionManager.ts b/packages/dht/src/connection/ConnectionManager.ts index a9023c3afa..763706cb64 100644 --- a/packages/dht/src/connection/ConnectionManager.ts +++ b/packages/dht/src/connection/ConnectionManager.ts @@ -28,6 +28,7 @@ import { ConnectionsView } from './ConnectionsView' import { OutputBuffer } from './OutputBuffer' import { IConnection } from './IConnection' import { PendingConnection } from './PendingConnection' +import { getNodeIdOrUnknownFromPeerDescriptor } from './helpers/getNodeIdOrUnknownFromPeerDescriptor' export interface ConnectionManagerOptions { maxConnections?: number @@ -99,23 +100,6 @@ type Endpoint = ConnectedEndpoint | ConnectingEndpoint const INTERNAL_SERVICE_ID = 'system/connection-manager' -// Form an string representation from a peer description which can be undefined. This output -// should only be used only for log output. TODO remove this method if we no longer use -// peerDescriptors which can be undefined, e.g. -// - if we refactor ConnectionManager so that it doesn't process handshake requests too early -// and therefore this.localPeerDescriptor can't be undefine (NET-1129) -// - if the peerDescriptor of ManagedConnection is always available -// - if we create stricter types for incoming messages (message.sourceDescriptor or -// disconnectNotice.peerDescriptor) -// - if ManagedConnection#peerDescriptor is never undefined -export const getNodeIdOrUnknownFromPeerDescriptor = (peerDescriptor: PeerDescriptor | undefined): string => { - if (peerDescriptor !== undefined) { - return toNodeId(peerDescriptor) - } else { - return 'unknown' - } -} - export class ConnectionManager extends EventEmitter implements ITransport, ConnectionsView, ConnectionLocker { private options: ConnectionManagerOptions diff --git a/packages/dht/src/connection/ConnectorFacade.ts b/packages/dht/src/connection/ConnectorFacade.ts index 58a3ad164f..50c38cabe9 100644 --- a/packages/dht/src/connection/ConnectorFacade.ts +++ b/packages/dht/src/connection/ConnectorFacade.ts @@ -7,7 +7,8 @@ import { ITransport } from '../transport/ITransport' import { PortRange, TlsCertificate } from './ConnectionManager' import { Simulator } from './simulator/Simulator' import { SimulatorConnector } from './simulator/SimulatorConnector' -import { IceServer, WebrtcConnector } from './webrtc/WebrtcConnector' +import { WebrtcConnector } from './webrtc/WebrtcConnector' +import type { IceServer } from './webrtc/types' import { WebsocketClientConnector } from './websocket/WebsocketClientConnector' import { DhtAddress } from '../identifiers' import { WebsocketServerConnector, WebsocketServerConnectorOptions } from './websocket/WebsocketServerConnector' diff --git a/packages/dht/src/connection/ManagedConnection.ts b/packages/dht/src/connection/ManagedConnection.ts index 36c15c1dae..b17d5f9d20 100644 --- a/packages/dht/src/connection/ManagedConnection.ts +++ b/packages/dht/src/connection/ManagedConnection.ts @@ -2,8 +2,8 @@ import { ConnectionID, IConnection } from './IConnection' import * as Err from '../helpers/errors' import { PeerDescriptor } from '../../generated/packages/dht/protos/DhtRpc' import { Logger } from '@streamr/utils' -import EventEmitter from 'eventemitter3' -import { getNodeIdOrUnknownFromPeerDescriptor } from './ConnectionManager' +import { EventEmitter } from 'eventemitter3' +import { getNodeIdOrUnknownFromPeerDescriptor } from './helpers/getNodeIdOrUnknownFromPeerDescriptor' import { DhtAddress, toNodeId } from '../identifiers' import { createRandomConnectionId } from './Connection' diff --git a/packages/dht/src/connection/PendingConnection.ts b/packages/dht/src/connection/PendingConnection.ts index b0c0c05bcd..d6bb7a0503 100644 --- a/packages/dht/src/connection/PendingConnection.ts +++ b/packages/dht/src/connection/PendingConnection.ts @@ -1,7 +1,7 @@ -import EventEmitter from 'eventemitter3' +import { EventEmitter } from 'eventemitter3' import { PeerDescriptor } from '../../generated/packages/dht/protos/DhtRpc' import { Logger, setAbortableTimeout } from '@streamr/utils' -import { getNodeIdOrUnknownFromPeerDescriptor } from './ConnectionManager' +import { getNodeIdOrUnknownFromPeerDescriptor } from './helpers/getNodeIdOrUnknownFromPeerDescriptor' import { IConnection } from './IConnection' export interface PendingConnectionEvents { diff --git a/packages/dht/src/connection/connectivityChecker.ts b/packages/dht/src/connection/connectivityChecker.ts index b924e4d923..23e144d603 100644 --- a/packages/dht/src/connection/connectivityChecker.ts +++ b/packages/dht/src/connection/connectivityChecker.ts @@ -6,7 +6,7 @@ import { Message, PeerDescriptor } from '../../generated/packages/dht/protos/DhtRpc' import { IConnection } from './IConnection' -import { WebsocketClientConnection } from './websocket/NodeWebsocketClientConnection' +import { WebsocketClientConnection } from '@/WebsocketClientConnection' import { connectivityMethodToWebsocketUrl } from './websocket/WebsocketClientConnector' import { isMaybeSupportedProtocolVersion } from '../helpers/version' diff --git a/packages/dht/src/connection/connectivityRequestHandler.ts b/packages/dht/src/connection/connectivityRequestHandler.ts index 1fdb5f8957..89baca0233 100644 --- a/packages/dht/src/connection/connectivityRequestHandler.ts +++ b/packages/dht/src/connection/connectivityRequestHandler.ts @@ -11,7 +11,7 @@ import { IConnection } from './IConnection' import { WebsocketServerConnection } from './websocket/WebsocketServerConnection' import { connectivityMethodToWebsocketUrl } from './websocket/WebsocketClientConnector' import { LOCAL_PROTOCOL_VERSION } from '../helpers/version' -import { GeoIpLocator } from '@streamr/geoip-location' +import type { GeoIpLocator } from '@streamr/geoip-location' export const DISABLE_CONNECTIVITY_PROBE = 0 diff --git a/packages/dht/src/connection/helpers/getNodeIdOrUnknownFromPeerDescriptor.ts b/packages/dht/src/connection/helpers/getNodeIdOrUnknownFromPeerDescriptor.ts new file mode 100644 index 0000000000..9b33c318a6 --- /dev/null +++ b/packages/dht/src/connection/helpers/getNodeIdOrUnknownFromPeerDescriptor.ts @@ -0,0 +1,27 @@ +import type { PeerDescriptor } from '../../../generated/packages/dht/protos/DhtRpc' +import { toNodeId } from '../../identifiers' + +/** + * Retrieves a string representation of a node ID from a given peer descriptor. + * If the peer descriptor is undefined, it returns 'unknown'. + * + * This function is intended for logging purposes only and should be removed + * if the conditions outlined in the TODO comment are met, such as: + * - Refactoring ConnectionManager to prevent early processing of handshake requests, + * ensuring this.localPeerDescriptor is never undefined (NET-1129). + * - Ensuring the peerDescriptor of ManagedConnection is always available. + * - Creating stricter types for incoming messages, such as message.sourceDescriptor + * or disconnectNotice.peerDescriptor. + * - Guaranteeing that ManagedConnection#peerDescriptor is never undefined. + * + * @param peerDescriptor - The peer descriptor from which to derive the node ID, + * or undefined if not available. + * @returns A string representation of the node ID or 'unknown' if the peer descriptor is undefined. + */ +export const getNodeIdOrUnknownFromPeerDescriptor = (peerDescriptor: PeerDescriptor | undefined): string => { + if (peerDescriptor !== undefined) { + return toNodeId(peerDescriptor) + } else { + return 'unknown' + } +} diff --git a/packages/dht/src/connection/webrtc/WebrtcConnector.ts b/packages/dht/src/connection/webrtc/WebrtcConnector.ts index 694673b7b7..96dbe41cf9 100644 --- a/packages/dht/src/connection/webrtc/WebrtcConnector.ts +++ b/packages/dht/src/connection/webrtc/WebrtcConnector.ts @@ -7,7 +7,7 @@ import { } from '../../../generated/packages/dht/protos/DhtRpc' import { ITransport } from '../../transport/ITransport' import { ListeningRpcCommunicator } from '../../transport/ListeningRpcCommunicator' -import { NodeWebrtcConnection } from './NodeWebrtcConnection' +import { WebrtcConnection } from '@/WebrtcConnection' import { WebrtcConnectorRpcRemote } from './WebrtcConnectorRpcRemote' import { WebrtcConnectorRpcClient } from '../../../generated/packages/dht/protos/DhtRpc.client' import { Logger } from '@streamr/utils' @@ -20,6 +20,7 @@ import { getOfferer } from '../../helpers/offering' import { acceptHandshake, createIncomingHandshaker, createOutgoingHandshaker, rejectHandshake } from '../Handshaker' import { isMaybeSupportedProtocolVersion } from '../../helpers/version' import { PendingConnection } from '../PendingConnection' +import type { IceServer } from './types' const logger = new Logger('WebrtcConnector') @@ -32,8 +33,6 @@ export const replaceInternalIpWithExternalIp = (candidate: string, ip: string): return parsed.join(' ') } -export const EARLY_TIMEOUT = 5000 - export interface WebrtcConnectorOptions { onNewConnection: (connection: PendingConnection) => boolean transport: ITransport @@ -46,17 +45,9 @@ export interface WebrtcConnectorOptions { portRange?: PortRange } -export interface IceServer { - url: string - port: number - username?: string - password?: string - tcp?: boolean -} - export interface ConnectingConnection { managedConnection: PendingConnection - connection: NodeWebrtcConnection + connection: WebrtcConnection } export class WebrtcConnector { @@ -204,8 +195,8 @@ export class WebrtcConnector { return pendingConnection } - private createConnection(targetPeerDescriptor: PeerDescriptor): NodeWebrtcConnection { - return new NodeWebrtcConnection({ + private createConnection(targetPeerDescriptor: PeerDescriptor): WebrtcConnection { + return new WebrtcConnection({ remotePeerDescriptor: targetPeerDescriptor, iceServers: this.options.iceServers, bufferThresholdLow: this.options.bufferThresholdLow, diff --git a/packages/dht/src/connection/webrtc/WebrtcConnectorRpcLocal.ts b/packages/dht/src/connection/webrtc/WebrtcConnectorRpcLocal.ts index 84e18284a0..8c91b542bf 100644 --- a/packages/dht/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +++ b/packages/dht/src/connection/webrtc/WebrtcConnectorRpcLocal.ts @@ -11,7 +11,7 @@ import { import { IWebrtcConnectorRpc } from '../../../generated/packages/dht/protos/DhtRpc.server' import { DhtCallContext } from '../../rpc-protocol/DhtCallContext' import { ListeningRpcCommunicator } from '../../transport/ListeningRpcCommunicator' -import { NodeWebrtcConnection } from './NodeWebrtcConnection' +import type { WebrtcConnection } from '@/WebrtcConnection' import { DhtAddress, toNodeId } from '../../identifiers' import { ConnectionID } from '../IConnection' import { ConnectingConnection } from './WebrtcConnector' @@ -50,7 +50,7 @@ export class WebrtcConnectorRpcLocal implements IWebrtcConnectorRpc { async rtcOffer(request: RtcOffer, context: ServerCallContext): Promise { const remotePeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor! const nodeId = toNodeId(remotePeerDescriptor) - let connection: NodeWebrtcConnection + let connection: WebrtcConnection let pendingConnection: PendingConnection if (!this.options.ongoingConnectAttempts.has(nodeId)) { diff --git a/packages/dht/src/connection/webrtc/consts.ts b/packages/dht/src/connection/webrtc/consts.ts new file mode 100644 index 0000000000..c07acfd5eb --- /dev/null +++ b/packages/dht/src/connection/webrtc/consts.ts @@ -0,0 +1 @@ +export const EARLY_TIMEOUT = 5000 diff --git a/packages/dht/src/connection/webrtc/iceServerAsString.ts b/packages/dht/src/connection/webrtc/iceServerAsString.ts index c204464c07..4ffdb588e8 100644 --- a/packages/dht/src/connection/webrtc/iceServerAsString.ts +++ b/packages/dht/src/connection/webrtc/iceServerAsString.ts @@ -1,4 +1,4 @@ -import { IceServer } from './WebrtcConnector' +import { IceServer } from './types' export function iceServerAsString({ url, port, username, password, tcp }: IceServer): string { const [protocol, hostname] = url.split(':') diff --git a/packages/dht/src/connection/webrtc/types.ts b/packages/dht/src/connection/webrtc/types.ts new file mode 100644 index 0000000000..f0b1acb566 --- /dev/null +++ b/packages/dht/src/connection/webrtc/types.ts @@ -0,0 +1,7 @@ +export interface IceServer { + url: string + port: number + username?: string + password?: string + tcp?: boolean +} diff --git a/packages/dht/src/connection/websocket/AbstractWebsocketClientConnection.ts b/packages/dht/src/connection/websocket/AbstractWebsocketClientConnection.ts index 1db4e88e47..fdc2565ff7 100644 --- a/packages/dht/src/connection/websocket/AbstractWebsocketClientConnection.ts +++ b/packages/dht/src/connection/websocket/AbstractWebsocketClientConnection.ts @@ -1,4 +1,4 @@ -import EventEmitter from 'eventemitter3' +import { EventEmitter } from 'eventemitter3' import { createRandomConnectionId } from '../Connection' import { ConnectionEvents, ConnectionID, ConnectionType, IConnection } from '../IConnection' import { Logger } from '@streamr/utils' diff --git a/packages/dht/src/connection/websocket/AutoCertifierClientFacade.ts b/packages/dht/src/connection/websocket/AutoCertifierClientFacade.ts index e228801c17..28c0442f0e 100644 --- a/packages/dht/src/connection/websocket/AutoCertifierClientFacade.ts +++ b/packages/dht/src/connection/websocket/AutoCertifierClientFacade.ts @@ -1,36 +1,14 @@ import { - AutoCertifierClient, - HasSessionRequest, - HasSessionResponse, - CertifiedSubdomain, + type CertifiedSubdomain, SERVICE_ID as AUTO_CERTIFIER_SERVICE_ID, - HasSession } from '@streamr/autocertifier-client' import { ListeningRpcCommunicator } from '../../transport/ListeningRpcCommunicator' import { Logger, waitForEvent } from '@streamr/utils' import { ITransport } from '../../transport/ITransport' +import { defaultAutoCertifierClientFactory } from '@/defaultAutoCertifierClientFactory' const START_TIMEOUT = 60 * 1000 -const defaultAutoCertifierClientFactory = ( - configFile: string, - autoCertifierUrl: string, - autoCertifierRpcCommunicator: ListeningRpcCommunicator, - wsServerPort: number -) => new AutoCertifierClient( - configFile, - wsServerPort, - autoCertifierUrl, - (_serviceId: string, rpcMethodName: string, method: HasSession) => { - autoCertifierRpcCommunicator.registerRpcMethod( - HasSessionRequest, - HasSessionResponse, - rpcMethodName, - method - ) - } -) - export interface IAutoCertifierClient { start(): Promise stop(): void diff --git a/packages/dht/src/connection/websocket/WebsocketClientConnector.ts b/packages/dht/src/connection/websocket/WebsocketClientConnector.ts index 5dc5b0e573..4fb0b51178 100644 --- a/packages/dht/src/connection/websocket/WebsocketClientConnector.ts +++ b/packages/dht/src/connection/websocket/WebsocketClientConnector.ts @@ -1,4 +1,4 @@ -import { WebsocketClientConnection } from './NodeWebsocketClientConnection' +import { WebsocketClientConnection } from '@/WebsocketClientConnection' import { ConnectionType } from '../IConnection' import { ListeningRpcCommunicator } from '../../transport/ListeningRpcCommunicator' import { WebsocketClientConnectorRpcLocal } from './WebsocketClientConnectorRpcLocal' @@ -7,13 +7,13 @@ import { PeerDescriptor, WebsocketConnectionRequest } from '../../../generated/packages/dht/protos/DhtRpc' -import { WebsocketServer } from './WebsocketServer' +import type { IWebsocketServer } from './types' import { createOutgoingHandshaker } from '../Handshaker' import { ServerCallContext } from '@protobuf-ts/runtime-rpc' import { expectedConnectionType } from '../../helpers/Connectivity' import { Empty } from '../../../generated/google/protobuf/empty' import { DhtAddress, toNodeId } from '../../identifiers' -import { GeoIpLocator } from '@streamr/geoip-location' +import type { GeoIpLocator } from '@streamr/geoip-location' import { PendingConnection } from '../PendingConnection' export type Action = 'connectivityRequest' | 'connectivityProbe' @@ -31,7 +31,7 @@ export interface WebsocketClientConnectorOptions { export class WebsocketClientConnector { public static readonly WEBSOCKET_CONNECTOR_SERVICE_ID = 'system/websocket-connector' - private readonly websocketServer?: WebsocketServer + private readonly websocketServer?: IWebsocketServer private geoIpLocator?: GeoIpLocator private localPeerDescriptor?: PeerDescriptor diff --git a/packages/dht/src/connection/websocket/WebsocketServerConnection.ts b/packages/dht/src/connection/websocket/WebsocketServerConnection.ts index fe0378021f..4d7f599c0b 100644 --- a/packages/dht/src/connection/websocket/WebsocketServerConnection.ts +++ b/packages/dht/src/connection/websocket/WebsocketServerConnection.ts @@ -1,4 +1,4 @@ -import EventEmitter from 'eventemitter3' +import { EventEmitter } from 'eventemitter3' import { IConnection, ConnectionID, ConnectionEvents, ConnectionType } from '../IConnection' import WebSocket from 'ws' import { Logger } from '@streamr/utils' diff --git a/packages/dht/src/connection/websocket/WebsocketServerConnector.ts b/packages/dht/src/connection/websocket/WebsocketServerConnector.ts index 06f09dfc8b..7492f66c85 100644 --- a/packages/dht/src/connection/websocket/WebsocketServerConnector.ts +++ b/packages/dht/src/connection/websocket/WebsocketServerConnector.ts @@ -1,7 +1,8 @@ -import { GeoIpLocator } from '@streamr/geoip-location' +import type { GeoIpLocator } from '@streamr/geoip-location' +import { createGeoipLocator } from '@/createGeoipLocator' import { ListeningRpcCommunicator } from '../../transport/ListeningRpcCommunicator' import { Action, connectivityMethodToWebsocketUrl } from './WebsocketClientConnector' -import { WebsocketServer } from './WebsocketServer' +import { WebsocketServer } from '@/WebsocketServer' import { areEqualPeerDescriptors, DhtAddress, toNodeId } from '../../identifiers' import { AutoCertifierClientFacade } from './AutoCertifierClientFacade' import { ConnectivityResponse, HandshakeError, PeerDescriptor } from '../../../generated/packages/dht/protos/DhtRpc' @@ -96,10 +97,8 @@ export class WebsocketServerConnector { }) if (this.options.geoIpDatabaseFolder) { - const geoIpLocator = new GeoIpLocator(this.options.geoIpDatabaseFolder) try { - await geoIpLocator.start() - this.geoIpLocator = geoIpLocator + this.geoIpLocator = await createGeoipLocator(this.options.geoIpDatabaseFolder) } catch (err) { logger.error('Failed to start GeoIpLocator', { err }) } diff --git a/packages/dht/src/connection/websocket/types.ts b/packages/dht/src/connection/websocket/types.ts new file mode 100644 index 0000000000..974f21c32c --- /dev/null +++ b/packages/dht/src/connection/websocket/types.ts @@ -0,0 +1,20 @@ +import type { EventEmitter } from 'eventemitter3' +import type { PortRange, TlsCertificate } from '../ConnectionManager' +import type { IConnection } from '../IConnection' + +export interface WebsocketServerEvents { + connected: ((connection: IConnection) => void) +} + +export interface WebsocketServerOptions { + portRange: PortRange + enableTls: boolean + tlsCertificate?: TlsCertificate + maxMessageSize?: number +} + +export interface IWebsocketServer extends EventEmitter { + start(): Promise + stop(): Promise + updateCertificate(cert: string, key: string): void +} diff --git a/packages/dht/src/dht/DhtNode.ts b/packages/dht/src/dht/DhtNode.ts index 11f7f16bd1..9c632c4772 100644 --- a/packages/dht/src/dht/DhtNode.ts +++ b/packages/dht/src/dht/DhtNode.ts @@ -13,8 +13,7 @@ import type { MarkRequired } from 'ts-essentials' import { ConnectionLocker, ConnectionManager, PortRange, TlsCertificate } from '../connection/ConnectionManager' import { ConnectionsView } from '../connection/ConnectionsView' import { DefaultConnectorFacade, DefaultConnectorFacadeOptions } from '../connection/ConnectorFacade' -import { IceServer } from '../connection/webrtc/WebrtcConnector' -import { isBrowserEnvironment } from '../helpers/browser/isBrowserEnvironment' +import type { IceServer } from '../connection/webrtc/types' import { createPeerDescriptor } from '../helpers/createPeerDescriptor' import { DhtAddress, KADEMLIA_ID_LENGTH_IN_BYTES, toNodeId } from '../identifiers' import { Any } from '../../generated/google/protobuf/any' @@ -54,6 +53,8 @@ import { LocalDataStore } from './store/LocalDataStore' import { StoreManager } from './store/StoreManager' import { StoreRpcRemote } from './store/StoreRpcRemote' import { getLocalRegionByCoordinates, getLocalRegionWithCache } from '@streamr/cdn-location' +import { isBrowserEnvironment } from '@/isBrowserEnvironment' +import { CONTROL_LAYER_NODE_SERVICE_ID } from './consts' export interface DhtNodeEvents extends TransportEvents { nearbyContactAdded: (peerDescriptor: PeerDescriptor) => void @@ -132,9 +133,6 @@ const logger = new Logger('DhtNode') export const NUMBER_OF_NODES_PER_KBUCKET_DEFAULT = 8 const PERIODICAL_PING_INTERVAL = 60 * 1000 -// TODO move this to trackerless-network package and change serviceId to be a required paramater -export const CONTROL_LAYER_NODE_SERVICE_ID = 'layer0' - export class DhtNode extends EventEmitter implements ITransport { private readonly options: StrictDhtNodeOptions @@ -200,7 +198,7 @@ export class DhtNode extends EventEmitter implements ITransport { logger.trace(`Starting new Streamr Network DHT Node with serviceId ${this.options.serviceId}`) this.started = true - if (isBrowserEnvironment()) { + if (isBrowserEnvironment) { this.options.websocketPortRange = undefined if (this.options.peerDescriptor) { this.options.peerDescriptor.websocket = undefined diff --git a/packages/dht/src/dht/PeerManager.ts b/packages/dht/src/dht/PeerManager.ts index d05cfb92db..1039f58e84 100644 --- a/packages/dht/src/dht/PeerManager.ts +++ b/packages/dht/src/dht/PeerManager.ts @@ -1,11 +1,9 @@ -import { - Logger -} from '@streamr/utils' -import EventEmitter from 'eventemitter3' +import { Logger } from '@streamr/utils' +import { EventEmitter } from 'eventemitter3' import KBucket from 'k-bucket' import { LockID } from '../connection/ConnectionLockStates' import { ConnectionLocker } from '../connection/ConnectionManager' -import { DhtAddress, DhtAddressRaw, toNodeId, toDhtAddressRaw } from '../identifiers' +import { DhtAddress, toNodeId, toDhtAddressRaw } from '../identifiers' import { PeerDescriptor } from '../../generated/packages/dht/protos/DhtRpc' @@ -54,10 +52,6 @@ export interface PeerManagerEvents { kBucketEmpty: () => void } -export const getDistance = (nodeIdOrDataKeyRaw1: DhtAddressRaw, nodeIdOrDataKeyRaw2: DhtAddressRaw): number => { - return KBucket.distance(nodeIdOrDataKeyRaw1, nodeIdOrDataKeyRaw2) -} - export class PeerManager extends EventEmitter { // Glossary: diff --git a/packages/dht/src/dht/consts.ts b/packages/dht/src/dht/consts.ts new file mode 100644 index 0000000000..eee28b1fd8 --- /dev/null +++ b/packages/dht/src/dht/consts.ts @@ -0,0 +1,2 @@ +// TODO move this to trackerless-network package and change serviceId to be a required paramater +export const CONTROL_LAYER_NODE_SERVICE_ID = 'layer0' diff --git a/packages/dht/src/dht/contact/ContactList.ts b/packages/dht/src/dht/contact/ContactList.ts index 8e4e6a0ff5..05f6f41c99 100644 --- a/packages/dht/src/dht/contact/ContactList.ts +++ b/packages/dht/src/dht/contact/ContactList.ts @@ -1,4 +1,4 @@ -import EventEmitter from 'eventemitter3' +import { EventEmitter } from 'eventemitter3' import { DhtAddress } from '../../identifiers' export interface Events { diff --git a/packages/dht/src/dht/contact/RingContactList.ts b/packages/dht/src/dht/contact/RingContactList.ts index fea502e8a8..27bf9ebb65 100644 --- a/packages/dht/src/dht/contact/RingContactList.ts +++ b/packages/dht/src/dht/contact/RingContactList.ts @@ -2,7 +2,7 @@ import { PeerDescriptor } from '../../../generated/packages/dht/protos/DhtRpc' import { OrderedMap } from '@js-sdsl/ordered-map' import { RingDistance, RingId, RingIdRaw, getLeftDistance, getRightDistance, getRingIdFromPeerDescriptor, getRingIdFromRaw } from './ringIdentifiers' import { DhtAddress, toNodeId } from '../../identifiers' -import EventEmitter from 'eventemitter3' +import { EventEmitter } from 'eventemitter3' import { Events } from './ContactList' export interface RingContacts { diff --git a/packages/dht/src/dht/contact/SortedContactList.ts b/packages/dht/src/dht/contact/SortedContactList.ts index 73c0055022..f110ae014e 100755 --- a/packages/dht/src/dht/contact/SortedContactList.ts +++ b/packages/dht/src/dht/contact/SortedContactList.ts @@ -1,7 +1,7 @@ import { Events } from './ContactList' import sortedIndexBy from 'lodash/sortedIndexBy' -import EventEmitter from 'eventemitter3' -import { getDistance } from '../PeerManager' +import { EventEmitter } from 'eventemitter3' +import { getPeerDistance } from '../helpers/getPeerDistance' import { DhtAddress, toDhtAddressRaw } from '../../identifiers' // add other getters in the future if needed @@ -120,7 +120,7 @@ export class SortedContactList DhtAddress }> extend // TODO inline this method? private distanceToReferenceId(id: DhtAddress): number { // TODO maybe this class should store the referenceId also as DhtAddressRaw so that we don't need to convert it here? - return getDistance(toDhtAddressRaw(this.options.referenceId), toDhtAddressRaw(id)) + return getPeerDistance(toDhtAddressRaw(this.options.referenceId), toDhtAddressRaw(id)) } public removeContact(id: DhtAddress): boolean { diff --git a/packages/dht/src/dht/contact/getClosestNodes.ts b/packages/dht/src/dht/contact/getClosestNodes.ts index 864687b807..2266d1ee52 100644 --- a/packages/dht/src/dht/contact/getClosestNodes.ts +++ b/packages/dht/src/dht/contact/getClosestNodes.ts @@ -1,4 +1,4 @@ -import { PeerDescriptor } from '../../exports' +import { PeerDescriptor } from '../../../generated/packages/dht/protos/DhtRpc' import { DhtAddress } from '../../identifiers' import { Contact } from './Contact' import { SortedContactList } from './SortedContactList' diff --git a/packages/dht/src/dht/discovery/DiscoverySession.ts b/packages/dht/src/dht/discovery/DiscoverySession.ts index 700aaca223..940e039390 100644 --- a/packages/dht/src/dht/discovery/DiscoverySession.ts +++ b/packages/dht/src/dht/discovery/DiscoverySession.ts @@ -3,7 +3,8 @@ import { v4 } from 'uuid' import { DhtAddress, toNodeId, toDhtAddressRaw } from '../../identifiers' import { PeerDescriptor } from '../../../generated/packages/dht/protos/DhtRpc' import { DhtNodeRpcRemote } from '../DhtNodeRpcRemote' -import { PeerManager, getDistance } from '../PeerManager' +import { PeerManager } from '../PeerManager' +import { getPeerDistance } from '../helpers/getPeerDistance' import { getClosestNodes } from '../contact/getClosestNodes' const logger = new Logger('DiscoverySession') @@ -60,10 +61,10 @@ export class DiscoverySession { this.ongoingRequests.delete(nodeId) const targetId = toDhtAddressRaw(this.options.targetId) const oldClosestNeighbor = this.getClosestNeighbor() - const oldClosestDistance = getDistance(targetId, oldClosestNeighbor.nodeId) + const oldClosestDistance = getPeerDistance(targetId, oldClosestNeighbor.nodeId) this.addContacts(contacts) const newClosestNeighbor = this.getClosestNeighbor() - const newClosestDistance = getDistance(targetId, newClosestNeighbor.nodeId) + const newClosestDistance = getPeerDistance(targetId, newClosestNeighbor.nodeId) if (newClosestDistance >= oldClosestDistance) { this.noProgressCounter++ } diff --git a/packages/dht/src/dht/discovery/PeerDiscovery.ts b/packages/dht/src/dht/discovery/PeerDiscovery.ts index b1dd5d1663..42ea56e029 100644 --- a/packages/dht/src/dht/discovery/PeerDiscovery.ts +++ b/packages/dht/src/dht/discovery/PeerDiscovery.ts @@ -16,7 +16,7 @@ import { getClosestNodes } from '../contact/getClosestNodes' import { RingIdRaw, getRingIdRawFromPeerDescriptor } from '../contact/ringIdentifiers' import { DiscoverySession } from './DiscoverySession' import { RingDiscoverySession } from './RingDiscoverySession' -import { CONTROL_LAYER_NODE_SERVICE_ID } from '../DhtNode' +import { CONTROL_LAYER_NODE_SERVICE_ID } from '../consts' interface PeerDiscoveryOptions { localPeerDescriptor: PeerDescriptor diff --git a/packages/dht/src/dht/helpers/getPeerDistance.ts b/packages/dht/src/dht/helpers/getPeerDistance.ts new file mode 100644 index 0000000000..592619929d --- /dev/null +++ b/packages/dht/src/dht/helpers/getPeerDistance.ts @@ -0,0 +1,9 @@ +import KBucket from 'k-bucket' +import { DhtAddressRaw } from '../../identifiers' + +export const getPeerDistance = ( + nodeIdOrDataKeyRaw1: DhtAddressRaw, + nodeIdOrDataKeyRaw2: DhtAddressRaw +): number => { + return KBucket.distance(nodeIdOrDataKeyRaw1, nodeIdOrDataKeyRaw2) +} diff --git a/packages/dht/src/dht/recursive-operation/RecursiveOperationManager.ts b/packages/dht/src/dht/recursive-operation/RecursiveOperationManager.ts index bea14f6bc2..0cffa8b837 100644 --- a/packages/dht/src/dht/recursive-operation/RecursiveOperationManager.ts +++ b/packages/dht/src/dht/recursive-operation/RecursiveOperationManager.ts @@ -24,8 +24,8 @@ import { createRouteMessageAck } from '../routing/RouterRpcLocal' import { ServiceID } from '../../types/ServiceID' import { RecursiveOperationRpcLocal } from './RecursiveOperationRpcLocal' import { DhtAddress, areEqualPeerDescriptors, toDhtAddress, toNodeId, toDhtAddressRaw } from '../../identifiers' -import { getDistance } from '../PeerManager' -import { ConnectionsView } from '../../exports' +import { getPeerDistance } from '../helpers/getPeerDistance' +import { ConnectionsView } from '../../connection/ConnectionsView' interface RecursiveOperationManagerOptions { rpcCommunicator: RoutingRpcCommunicator @@ -233,8 +233,8 @@ export class RecursiveOperationManager { private isPeerCloserToIdThanSelf(peer: PeerDescriptor, nodeIdOrDataKey: DhtAddress): boolean { const nodeIdOrDataKeyRaw = toDhtAddressRaw(nodeIdOrDataKey) - const distance1 = getDistance(peer.nodeId, nodeIdOrDataKeyRaw) - const distance2 = getDistance(this.options.localPeerDescriptor.nodeId, nodeIdOrDataKeyRaw) + const distance1 = getPeerDistance(peer.nodeId, nodeIdOrDataKeyRaw) + const distance2 = getPeerDistance(this.options.localPeerDescriptor.nodeId, nodeIdOrDataKeyRaw) return distance1 < distance2 } diff --git a/packages/dht/src/dht/recursive-operation/RecursiveOperationSession.ts b/packages/dht/src/dht/recursive-operation/RecursiveOperationSession.ts index 18dfde8355..b23d98c055 100644 --- a/packages/dht/src/dht/recursive-operation/RecursiveOperationSession.ts +++ b/packages/dht/src/dht/recursive-operation/RecursiveOperationSession.ts @@ -1,4 +1,4 @@ -import EventEmitter from 'eventemitter3' +import { EventEmitter } from 'eventemitter3' import { v4 } from 'uuid' import { DataEntry, diff --git a/packages/dht/src/dht/routing/RoutingSession.ts b/packages/dht/src/dht/routing/RoutingSession.ts index 355078b3c2..4237d76849 100644 --- a/packages/dht/src/dht/routing/RoutingSession.ts +++ b/packages/dht/src/dht/routing/RoutingSession.ts @@ -1,6 +1,6 @@ import { SortedContactList } from '../contact/SortedContactList' import { Logger } from '@streamr/utils' -import EventEmitter from 'eventemitter3' +import { EventEmitter } from 'eventemitter3' import { v4 } from 'uuid' import { PeerDescriptor, RouteMessageWrapper } from '../../../generated/packages/dht/protos/DhtRpc' import { RouterRpcRemote, ROUTING_TIMEOUT } from './RouterRpcRemote' diff --git a/packages/dht/src/exports.ts b/packages/dht/src/exports.ts index 6fe245fe1e..bfc02b6260 100644 --- a/packages/dht/src/exports.ts +++ b/packages/dht/src/exports.ts @@ -12,9 +12,9 @@ export type { LockID } from './connection/ConnectionLockStates' export { DefaultConnectorFacade } from './connection/ConnectorFacade' export type { DhtRpcOptions } from './rpc-protocol/DhtRpcOptions' export { RpcRemote, EXISTING_CONNECTION_TIMEOUT } from './dht/contact/RpcRemote' -export type { IceServer } from './connection/webrtc/WebrtcConnector' +export type { IceServer } from './connection/webrtc/types' export { DhtCallContext } from './rpc-protocol/DhtCallContext' -export { WebsocketClientConnection } from './connection/websocket/NodeWebsocketClientConnection' +export { WebsocketClientConnection } from '@/WebsocketClientConnection' export { ManagedConnection } from './connection/ManagedConnection' export { PendingConnection } from './connection/PendingConnection' export type { IConnection } from './connection/IConnection' diff --git a/packages/dht/src/helpers/browser/isBrowserEnvironment.ts b/packages/dht/src/helpers/browser/isBrowserEnvironment.ts deleted file mode 100644 index ac3c121acb..0000000000 --- a/packages/dht/src/helpers/browser/isBrowserEnvironment.ts +++ /dev/null @@ -1 +0,0 @@ -export const isBrowserEnvironment = (): boolean => false diff --git a/packages/dht/src/helpers/browser/isBrowserEnvironment_override.ts b/packages/dht/src/helpers/browser/isBrowserEnvironment_override.ts deleted file mode 100644 index 38c7c9c2ac..0000000000 --- a/packages/dht/src/helpers/browser/isBrowserEnvironment_override.ts +++ /dev/null @@ -1,3 +0,0 @@ -// webpack overwrites the isBrowserEnvironment.ts with this file when it creates the browser bundle - -export const isBrowserEnvironment = (): boolean => true diff --git a/packages/dht/src/helpers/createPeerDescriptor.ts b/packages/dht/src/helpers/createPeerDescriptor.ts index f9c05f8a14..b7731d7e76 100644 --- a/packages/dht/src/helpers/createPeerDescriptor.ts +++ b/packages/dht/src/helpers/createPeerDescriptor.ts @@ -1,6 +1,5 @@ -import { EcdsaSecp256k1Evm } from '@streamr/utils' -import crypto from 'crypto' -import { isBrowserEnvironment } from '../helpers/browser/isBrowserEnvironment' +import { EcdsaSecp256k1Evm, randomBytes } from '@streamr/utils' +import { isBrowserEnvironment } from '@/isBrowserEnvironment' import { createPeerDescriptorSignaturePayload } from '../helpers/createPeerDescriptorSignaturePayload' import { DhtAddress, DhtAddressRaw, toDhtAddressRaw } from '../identifiers' import { @@ -30,8 +29,8 @@ const calculateNodeIdRaw = async (ipAddress: number, privateKey: Uint8Array): Pr export const createPeerDescriptor = async (connectivityResponse: ConnectivityResponse, region: number, nodeId?: DhtAddress): Promise => { - const privateKey = crypto.randomBytes(32) - const publicKey = crypto.randomBytes(20) // TODO calculate publicKey from privateKey + const privateKey = randomBytes(32) + const publicKey = randomBytes(20) // TODO calculate publicKey from privateKey let nodeIdRaw: DhtAddressRaw if (nodeId !== undefined) { nodeIdRaw = toDhtAddressRaw(nodeId) @@ -40,7 +39,7 @@ export const createPeerDescriptor = async (connectivityResponse: ConnectivityRes } const ret: PeerDescriptor = { nodeId: nodeIdRaw, - type: isBrowserEnvironment() ? NodeType.BROWSER : NodeType.NODEJS, + type: isBrowserEnvironment ? NodeType.BROWSER : NodeType.NODEJS, ipAddress: connectivityResponse.ipAddress, region, publicKey diff --git a/packages/dht/src/helpers/offering.ts b/packages/dht/src/helpers/offering.ts index fc103de7c0..297364f8b0 100644 --- a/packages/dht/src/helpers/offering.ts +++ b/packages/dht/src/helpers/offering.ts @@ -1,4 +1,4 @@ -import crypto from 'crypto' +import { computeMd5 } from '@streamr/utils' import { DhtAddress } from '../identifiers' type Offerer = 'local' | 'remote' @@ -10,6 +10,5 @@ export const getOfferer = (localNodeId: DhtAddress, remoteNodeId: DhtAddress): O } const getOfferingHash = (idPair: string): number => { - const buffer = crypto.createHash('md5').update(idPair).digest() - return buffer.readInt32LE(0) + return computeMd5(idPair).readInt32LE(0) } diff --git a/packages/dht/src/helpers/protoClasses.ts b/packages/dht/src/helpers/protoClasses.ts index 1af21d297e..7c42f7903f 100644 --- a/packages/dht/src/helpers/protoClasses.ts +++ b/packages/dht/src/helpers/protoClasses.ts @@ -25,7 +25,6 @@ import { LockRequest, UnlockRequest, LockResponse - } from '../../generated/packages/dht/protos/DhtRpc' export const protoClasses: IMessageType[] = [ diff --git a/packages/dht/src/helpers/protoToString.ts b/packages/dht/src/helpers/protoToString.ts index 0eb1d64e5b..9dc6e2cb40 100644 --- a/packages/dht/src/helpers/protoToString.ts +++ b/packages/dht/src/helpers/protoToString.ts @@ -1,5 +1,4 @@ import { IMessageType } from '@protobuf-ts/runtime' - import { protoClasses } from './protoClasses' import { protoClasses as rpcProtoClasses } from '@streamr/proto-rpc' diff --git a/packages/dht/src/identifiers.ts b/packages/dht/src/identifiers.ts index 1be870bb7d..5177ab7470 100644 --- a/packages/dht/src/identifiers.ts +++ b/packages/dht/src/identifiers.ts @@ -1,5 +1,4 @@ -import { BrandedString, areEqualBinaries, binaryToHex, hexToBinary } from '@streamr/utils' -import crypto from 'crypto' +import { BrandedString, areEqualBinaries, binaryToHex, hexToBinary, randomBytes } from '@streamr/utils' import { PeerDescriptor } from '../generated/packages/dht/protos/DhtRpc' // https://www.scs.stanford.edu/~dm/home/papers/kpos.pdf @@ -25,5 +24,5 @@ export const areEqualPeerDescriptors = (peerDescriptor1: PeerDescriptor, peerDes } export const randomDhtAddress = (): DhtAddress => { - return toDhtAddress(crypto.randomBytes(KADEMLIA_ID_LENGTH_IN_BYTES)) + return toDhtAddress(randomBytes(KADEMLIA_ID_LENGTH_IN_BYTES)) } diff --git a/packages/dht/src/connection/webrtc/NodeWebrtcConnection.ts b/packages/dht/src/nodejs/WebrtcConnection.ts similarity index 88% rename from packages/dht/src/connection/webrtc/NodeWebrtcConnection.ts rename to packages/dht/src/nodejs/WebrtcConnection.ts index 7d0434f50b..88dd2b0916 100644 --- a/packages/dht/src/connection/webrtc/NodeWebrtcConnection.ts +++ b/packages/dht/src/nodejs/WebrtcConnection.ts @@ -1,26 +1,19 @@ -import { IWebrtcConnection, WebrtcConnectionEvents } from './IWebrtcConnection' -import { ConnectionType, IConnection, ConnectionID } from '../IConnection' -import { PeerDescriptor } from '../../../generated/packages/dht/protos/DhtRpc' -import EventEmitter from 'eventemitter3' +import { IWebrtcConnection, WebrtcConnectionEvents } from '../connection/webrtc/IWebrtcConnection' +import { ConnectionType, IConnection, ConnectionID } from '../connection/IConnection' +import { PeerDescriptor } from '../../generated/packages/dht/protos/DhtRpc' +import { EventEmitter } from 'eventemitter3' import { DataChannel, DescriptionType, PeerConnection, initLogger } from 'node-datachannel' import { Logger } from '@streamr/utils' -import { IllegalRtcPeerConnectionState } from '../../helpers/errors' -import { iceServerAsString } from './iceServerAsString' -import { IceServer, EARLY_TIMEOUT } from './WebrtcConnector' -import { PortRange } from '../ConnectionManager' -import { toNodeId } from '../../identifiers' -import { createRandomConnectionId } from '../Connection' - -const logger = new Logger('NodeWebrtcConnection') - -export interface Params { - remotePeerDescriptor: PeerDescriptor - bufferThresholdHigh?: number - bufferThresholdLow?: number - maxMessageSize?: number - iceServers?: IceServer[] // TODO make this parameter required (empty array is a good fallback which can be set by the caller if needed) - portRange?: PortRange -} +import { IllegalRtcPeerConnectionState } from '../helpers/errors' +import { iceServerAsString } from '../connection/webrtc/iceServerAsString' +import { IceServer } from '../connection/webrtc/types' +import { EARLY_TIMEOUT } from '../connection/webrtc/consts' +import { PortRange } from '../connection/ConnectionManager' +import { toNodeId } from '../identifiers' +import { createRandomConnectionId } from '../connection/Connection' +import type { WebrtcConnectionParams } from '../types/WebrtcConnectionParams' + +const logger = new Logger('WebrtcConnection (Node)') // Re-defined accoring to https://github.com/microsoft/TypeScript/blob/main/src/lib/dom.generated.d.ts // because importing single dom definitions in not possible @@ -38,7 +31,7 @@ initLogger('Fatal') type RtcPeerConnectionState = keyof typeof RtcPeerConnectionStateEnum -export class NodeWebrtcConnection extends EventEmitter implements IConnection, IWebrtcConnection { +export class WebrtcConnection extends EventEmitter implements IConnection, IWebrtcConnection { public connectionId: ConnectionID private connection?: PeerConnection @@ -57,7 +50,7 @@ export class NodeWebrtcConnection extends EventEmitter i private offering?: boolean private readonly earlyTimeout: NodeJS.Timeout - constructor(params: Params) { + constructor(params: WebrtcConnectionParams) { super() this.connectionId = createRandomConnectionId() this.iceServers = params.iceServers ?? [] diff --git a/packages/dht/src/connection/websocket/NodeWebsocketClientConnection.ts b/packages/dht/src/nodejs/WebsocketClientConnection.ts similarity index 89% rename from packages/dht/src/connection/websocket/NodeWebsocketClientConnection.ts rename to packages/dht/src/nodejs/WebsocketClientConnection.ts index d0c15c33fd..98fd2263a5 100644 --- a/packages/dht/src/connection/websocket/NodeWebsocketClientConnection.ts +++ b/packages/dht/src/nodejs/WebsocketClientConnection.ts @@ -1,8 +1,8 @@ import { Logger, binaryToUtf8 } from '@streamr/utils' import { WebSocket } from 'ws' -import { AbstractWebsocketClientConnection } from './AbstractWebsocketClientConnection' +import { AbstractWebsocketClientConnection } from '../connection/websocket/AbstractWebsocketClientConnection' -const logger = new Logger('NodeWebsocketClientConnection') +const logger = new Logger('WebsocketClientConnection (Node)') const BINARY_TYPE = 'nodebuffer' diff --git a/packages/dht/src/connection/websocket/WebsocketServer.ts b/packages/dht/src/nodejs/WebsocketServer.ts similarity index 90% rename from packages/dht/src/connection/websocket/WebsocketServer.ts rename to packages/dht/src/nodejs/WebsocketServer.ts index 785de0e403..21cae994aa 100644 --- a/packages/dht/src/connection/websocket/WebsocketServer.ts +++ b/packages/dht/src/nodejs/WebsocketServer.ts @@ -1,32 +1,20 @@ import { createServer as createHttpServer, Server as HttpServer, IncomingMessage, ServerResponse } from 'http' import { createServer as createHttpsServer, Server as HttpsServer } from 'https' -import EventEmitter from 'eventemitter3' +import { EventEmitter } from 'eventemitter3' import WebSocket, { WebSocketServer } from 'ws' -import { WebsocketServerConnection } from './WebsocketServerConnection' +import { WebsocketServerConnection } from '../connection/websocket/WebsocketServerConnection' import { Logger, asAbortable } from '@streamr/utils' import { createSelfSignedCertificate } from '@streamr/autocertifier-client' -import { WebsocketServerStartError } from '../../helpers/errors' -import { PortRange, TlsCertificate } from '../ConnectionManager' +import { WebsocketServerStartError } from '../helpers/errors' import range from 'lodash/range' import fs from 'fs' import { v4 as uuid } from 'uuid' import { parse } from 'url' -import { IConnection } from '../IConnection' +import type { IWebsocketServer, WebsocketServerEvents, WebsocketServerOptions } from '../connection/websocket/types' -const logger = new Logger('WebsocketServer') +const logger = new Logger('WebsocketServer (Node)') -interface WebsocketServerOptions { - portRange: PortRange - enableTls: boolean - tlsCertificate?: TlsCertificate - maxMessageSize?: number -} - -interface Events { - connected: ((connection: IConnection) => void) -} - -export class WebsocketServer extends EventEmitter { +export class WebsocketServer extends EventEmitter implements IWebsocketServer { private httpServer?: HttpServer | HttpsServer private wsServer?: WebSocketServer diff --git a/packages/dht/src/nodejs/createGeoipLocator.ts b/packages/dht/src/nodejs/createGeoipLocator.ts new file mode 100644 index 0000000000..36f1eb8f13 --- /dev/null +++ b/packages/dht/src/nodejs/createGeoipLocator.ts @@ -0,0 +1,11 @@ +import { GeoIpLocator } from '@streamr/geoip-location' + +export const createGeoipLocator = async ( + geoIpDatabaseFolder: string +): Promise => { + const geoIpLocator = new GeoIpLocator(geoIpDatabaseFolder) + + await geoIpLocator.start() + + return geoIpLocator +} diff --git a/packages/dht/src/nodejs/defaultAutoCertifierClientFactory.ts b/packages/dht/src/nodejs/defaultAutoCertifierClientFactory.ts new file mode 100644 index 0000000000..50367d8c20 --- /dev/null +++ b/packages/dht/src/nodejs/defaultAutoCertifierClientFactory.ts @@ -0,0 +1,28 @@ +import { + AutoCertifierClient, + HasSessionRequest, + HasSessionResponse, + type HasSession, +} from '@streamr/autocertifier-client' +import { ListeningRpcCommunicator } from '../transport/ListeningRpcCommunicator' + +export const defaultAutoCertifierClientFactory = ( + configFile: string, + autoCertifierUrl: string, + autoCertifierRpcCommunicator: ListeningRpcCommunicator, + wsServerPort: number +): AutoCertifierClient => { + return new AutoCertifierClient( + configFile, + wsServerPort, + autoCertifierUrl, + (_serviceId: string, rpcMethodName: string, method: HasSession) => { + autoCertifierRpcCommunicator.registerRpcMethod( + HasSessionRequest, + HasSessionResponse, + rpcMethodName, + method + ) + } + ) +} diff --git a/packages/dht/src/nodejs/isBrowserEnvironment.ts b/packages/dht/src/nodejs/isBrowserEnvironment.ts new file mode 100644 index 0000000000..5f58603e88 --- /dev/null +++ b/packages/dht/src/nodejs/isBrowserEnvironment.ts @@ -0,0 +1 @@ +export const isBrowserEnvironment = false diff --git a/packages/dht/src/types/textencoding.d.ts b/packages/dht/src/nodejs/textencoding.d.ts similarity index 100% rename from packages/dht/src/types/textencoding.d.ts rename to packages/dht/src/nodejs/textencoding.d.ts diff --git a/packages/dht/src/types/WebrtcConnectionParams.ts b/packages/dht/src/types/WebrtcConnectionParams.ts new file mode 100644 index 0000000000..24eff16f79 --- /dev/null +++ b/packages/dht/src/types/WebrtcConnectionParams.ts @@ -0,0 +1,12 @@ +import { PeerDescriptor } from '../../generated/packages/dht/protos/DhtRpc' +import { PortRange } from '../connection/ConnectionManager' +import { IceServer } from '../connection/webrtc/types' + +export interface WebrtcConnectionParams { + remotePeerDescriptor: PeerDescriptor + bufferThresholdHigh?: number + bufferThresholdLow?: number + maxMessageSize?: number + iceServers?: IceServer[] // TODO make this parameter required (empty array is a good fallback which can be set by the caller if needed) + portRange?: PortRange +} diff --git a/packages/dht/test/benchmark/WebsocketServerMemoryLeak.test.ts b/packages/dht/test/benchmark/WebsocketServerMemoryLeak.test.ts index ef12daf395..ff1826f4b3 100644 --- a/packages/dht/test/benchmark/WebsocketServerMemoryLeak.test.ts +++ b/packages/dht/test/benchmark/WebsocketServerMemoryLeak.test.ts @@ -1,8 +1,8 @@ /* eslint-disable no-console */ import { wait } from '@streamr/utils' -import { WebsocketServer } from '../../src/connection/websocket/WebsocketServer' -import { WebsocketClientConnection } from '../../src/connection/websocket/NodeWebsocketClientConnection' +import { WebsocketServer } from '@/WebsocketServer' +import { WebsocketClientConnection } from '@/WebsocketClientConnection' // This 'test' is meant to be run manually using the following command: // node --inspect ../../../../node_modules/.bin/jest WebsocketServerMemoryLeak.test.ts diff --git a/packages/dht/test/end-to-end/Layer0Webrtc.test.ts b/packages/dht/test/end-to-end/Layer0Webrtc.test.ts index 73996badea..fa6bd42c7d 100644 --- a/packages/dht/test/end-to-end/Layer0Webrtc.test.ts +++ b/packages/dht/test/end-to-end/Layer0Webrtc.test.ts @@ -3,7 +3,7 @@ import { ConnectionManager } from '../../src/connection/ConnectionManager' import { DhtNode } from '../../src/dht/DhtNode' import { PeerDescriptor } from '../../generated/packages/dht/protos/DhtRpc' import { createMockPeerDescriptor } from '../utils/utils' -import { toNodeId } from '../../src/exports' +import { toNodeId } from './../../src/identifiers' describe('Layer0 with WebRTC connections', () => { diff --git a/packages/dht/test/integration/DhtNode.test.ts b/packages/dht/test/integration/DhtNode.test.ts index bfac847c1c..1822d5139d 100644 --- a/packages/dht/test/integration/DhtNode.test.ts +++ b/packages/dht/test/integration/DhtNode.test.ts @@ -2,7 +2,9 @@ import { until } from '@streamr/utils' import range from 'lodash/range' import without from 'lodash/without' import { DhtNodeRpcLocal } from '../../src/dht/DhtNodeRpcLocal' -import { DhtNode, ListeningRpcCommunicator, toNodeId } from '../../src/exports' +import { toNodeId } from '../../src/identifiers' +import { DhtNode } from '../../src/dht/DhtNode' +import { ListeningRpcCommunicator } from '../../src/transport/ListeningRpcCommunicator' import { ClosestPeersRequest, ClosestPeersResponse, PeerDescriptor, PingRequest, PingResponse } from '../../generated/packages/dht/protos/DhtRpc' import { FakeEnvironment } from '../utils/FakeTransport' import { createMockPeerDescriptor } from '../utils/utils' diff --git a/packages/dht/test/integration/Websocket.test.ts b/packages/dht/test/integration/Websocket.test.ts index de2a6e52c8..65901b93ff 100644 --- a/packages/dht/test/integration/Websocket.test.ts +++ b/packages/dht/test/integration/Websocket.test.ts @@ -1,6 +1,6 @@ -import { WebsocketServer } from '../../src/connection/websocket/WebsocketServer' +import { WebsocketServer } from '@/WebsocketServer' import { IConnection } from '../../src/connection/IConnection' -import { WebsocketClientConnection } from '../../src/connection/websocket/NodeWebsocketClientConnection' +import { WebsocketClientConnection } from '@/WebsocketClientConnection' import { Logger } from '@streamr/utils' const logger = new Logger('Websocket.test') diff --git a/packages/dht/test/unit/AutoCertifierClientFacade.test.ts b/packages/dht/test/unit/AutoCertifierClientFacade.test.ts index 280033d269..99b6da3587 100644 --- a/packages/dht/test/unit/AutoCertifierClientFacade.test.ts +++ b/packages/dht/test/unit/AutoCertifierClientFacade.test.ts @@ -1,4 +1,4 @@ -import EventEmitter from 'eventemitter3' +import { EventEmitter } from 'eventemitter3' import { AutoCertifierClientFacade, IAutoCertifierClient } from '../../src/connection/websocket/AutoCertifierClientFacade' import { MockTransport } from '../utils/mock/MockTransport' diff --git a/packages/dht/test/unit/ConnectionManager.test.ts b/packages/dht/test/unit/ConnectionManager.test.ts index df96e10f0c..ab768aa779 100644 --- a/packages/dht/test/unit/ConnectionManager.test.ts +++ b/packages/dht/test/unit/ConnectionManager.test.ts @@ -1,6 +1,7 @@ import { MetricsContext } from '@streamr/utils' import { ConnectionManager } from '../../src/connection/ConnectionManager' -import { toNodeId, PendingConnection } from '../../src/exports' +import { toNodeId } from '../../src/identifiers' +import { PendingConnection } from '../../src/connection/PendingConnection' import { FakeConnectorFacade } from '../utils/FakeConnectorFacade' import { MockConnection } from '../utils/mock/MockConnection' import { createMockPeerDescriptor } from '../utils/utils' diff --git a/packages/dht/test/unit/DiscoverySession.test.ts b/packages/dht/test/unit/DiscoverySession.test.ts index 2111eb3163..8e50d3feff 100644 --- a/packages/dht/test/unit/DiscoverySession.test.ts +++ b/packages/dht/test/unit/DiscoverySession.test.ts @@ -1,7 +1,8 @@ import { Multimap, wait } from '@streamr/utils' import sampleSize from 'lodash/sampleSize' import { DhtNodeRpcRemote } from '../../src/dht/DhtNodeRpcRemote' -import { PeerManager, getDistance } from '../../src/dht/PeerManager' +import { PeerManager } from '../../src/dht/PeerManager' +import { getPeerDistance } from '../../src/dht/helpers/getPeerDistance' import { DiscoverySession } from '../../src/dht/discovery/DiscoverySession' import { DhtAddress, toNodeId, toDhtAddressRaw } from '../../src/identifiers' import { NodeType, PeerDescriptor } from '../../generated/packages/dht/protos/DhtRpc' @@ -79,7 +80,7 @@ describe('DiscoverySession', () => { // Each queried node should closer to the target than the previous queried node, because we // use parallelism=1 and noProgressLimit=1 const distancesToTarget = queriedNodes - .map((nodeId) => getDistance(toDhtAddressRaw(nodeId), toDhtAddressRaw(targetId))) + .map((nodeId) => getPeerDistance(toDhtAddressRaw(nodeId), toDhtAddressRaw(targetId))) for (let i = 1; i < distancesToTarget.length ; i++) { expect(distancesToTarget[i]).toBeLessThan(distancesToTarget[i - 1]) } diff --git a/packages/dht/test/unit/Handshaker.test.ts b/packages/dht/test/unit/Handshaker.test.ts index d06dbcd32d..e51ec44226 100644 --- a/packages/dht/test/unit/Handshaker.test.ts +++ b/packages/dht/test/unit/Handshaker.test.ts @@ -1,4 +1,4 @@ -import EventEmitter from 'eventemitter3' +import { EventEmitter } from 'eventemitter3' import { acceptHandshake, createHandshakeRequest, diff --git a/packages/dht/test/unit/ManagedConnection.test.ts b/packages/dht/test/unit/ManagedConnection.test.ts index 76ba758255..e62cf9e947 100644 --- a/packages/dht/test/unit/ManagedConnection.test.ts +++ b/packages/dht/test/unit/ManagedConnection.test.ts @@ -1,5 +1,5 @@ import { wait } from '@streamr/utils' -import { ManagedConnection } from '../../src/exports' +import { ManagedConnection } from '../../src/connection/ManagedConnection' import { MockConnection } from '../utils/mock/MockConnection' import { createMockPeerDescriptor } from '../utils/utils' diff --git a/packages/dht/test/unit/PendingConnection.test.ts b/packages/dht/test/unit/PendingConnection.test.ts index df8ea9bfaa..f98628bcfa 100644 --- a/packages/dht/test/unit/PendingConnection.test.ts +++ b/packages/dht/test/unit/PendingConnection.test.ts @@ -1,5 +1,5 @@ import { wait, waitForEvent } from '@streamr/utils' -import { PendingConnection } from '../../src/exports' +import { PendingConnection } from '../../src/connection/PendingConnection' import { createMockPeerDescriptor } from '../utils/utils' import { MockConnection } from '../utils/mock/MockConnection' diff --git a/packages/dht/test/unit/WebrtcConnection.test.ts b/packages/dht/test/unit/WebrtcConnection.test.ts index 1b0ec560ea..2ad4a703e4 100644 --- a/packages/dht/test/unit/WebrtcConnection.test.ts +++ b/packages/dht/test/unit/WebrtcConnection.test.ts @@ -1,14 +1,14 @@ import { waitForEvent } from '@streamr/utils' -import { NodeWebrtcConnection } from '../../src/connection/webrtc/NodeWebrtcConnection' +import { WebrtcConnection } from '@/WebrtcConnection' import { createMockPeerDescriptor } from '../utils/utils' describe('WebrtcConnection', () => { - let connection: NodeWebrtcConnection + let connection: WebrtcConnection beforeEach(() => { const peerDescriptor = createMockPeerDescriptor() - connection = new NodeWebrtcConnection({ + connection = new WebrtcConnection({ remotePeerDescriptor: peerDescriptor }) }) diff --git a/packages/dht/test/unit/WebsocketServer.test.ts b/packages/dht/test/unit/WebsocketServer.test.ts index b389291f51..6b537d936f 100644 --- a/packages/dht/test/unit/WebsocketServer.test.ts +++ b/packages/dht/test/unit/WebsocketServer.test.ts @@ -1,4 +1,4 @@ -import { WebsocketServer } from '../../src/connection/websocket/WebsocketServer' +import { WebsocketServer } from '@/WebsocketServer' describe('WebsocketServer', () => { diff --git a/packages/dht/test/unit/createPeerDescriptor.test.ts b/packages/dht/test/unit/createPeerDescriptor.test.ts index 3b5fdf36bb..cd467d88ad 100644 --- a/packages/dht/test/unit/createPeerDescriptor.test.ts +++ b/packages/dht/test/unit/createPeerDescriptor.test.ts @@ -1,6 +1,6 @@ import { ipv4ToNumber } from '@streamr/utils' import { createPeerDescriptor } from '../../src/helpers/createPeerDescriptor' -import { isBrowserEnvironment } from '../../src/helpers/browser/isBrowserEnvironment' +import { isBrowserEnvironment } from '@/isBrowserEnvironment' import { NodeType } from '../../generated/packages/dht/protos/DhtRpc' import { randomDhtAddress, toDhtAddressRaw } from '../../src/identifiers' import { getRandomRegion } from '../../src/connection/simulator/pings' @@ -18,7 +18,7 @@ describe('createPeerDescriptor', () => { const peerDescriptor = await createPeerDescriptor(connectivityResponse, region) expect(peerDescriptor).toEqual({ nodeId: expect.any(Uint8Array), - type: isBrowserEnvironment() ? NodeType.BROWSER : NodeType.NODEJS, + type: isBrowserEnvironment ? NodeType.BROWSER : NodeType.NODEJS, ipAddress: ipv4ToNumber(IP_ADDRESS), publicKey: expect.any(Uint8Array), signature: expect.any(Uint8Array), @@ -38,7 +38,7 @@ describe('createPeerDescriptor', () => { const peerDescriptor = await createPeerDescriptor(connectivityResponse, region) expect(peerDescriptor).toEqual({ nodeId: expect.any(Uint8Array), - type: isBrowserEnvironment() ? NodeType.BROWSER : NodeType.NODEJS, + type: isBrowserEnvironment ? NodeType.BROWSER : NodeType.NODEJS, ipAddress: ipv4ToNumber(IP_ADDRESS), publicKey: expect.any(Uint8Array), signature: expect.any(Uint8Array), @@ -59,7 +59,7 @@ describe('createPeerDescriptor', () => { const peerDescriptor = await createPeerDescriptor(connectivityResponse, region, nodeId) expect(peerDescriptor).toEqual({ nodeId: toDhtAddressRaw(nodeId), - type: isBrowserEnvironment() ? NodeType.BROWSER : NodeType.NODEJS, + type: isBrowserEnvironment ? NodeType.BROWSER : NodeType.NODEJS, ipAddress: ipv4ToNumber(IP_ADDRESS), publicKey: expect.any(Uint8Array), signature: expect.any(Uint8Array), diff --git a/packages/dht/test/unit/getClosestNodes.test.ts b/packages/dht/test/unit/getClosestNodes.test.ts index f69003cb9e..4b196dc68f 100644 --- a/packages/dht/test/unit/getClosestNodes.test.ts +++ b/packages/dht/test/unit/getClosestNodes.test.ts @@ -1,11 +1,11 @@ import range from 'lodash/range' import sampleSize from 'lodash/sampleSize' import sortBy from 'lodash/sortBy' -import { getDistance } from '../../src/dht/PeerManager' +import { getPeerDistance } from '../../src/dht/helpers/getPeerDistance' import { getClosestNodes } from '../../src/dht/contact/getClosestNodes' import { DhtAddress, randomDhtAddress, toNodeId, toDhtAddressRaw } from '../../src/identifiers' import { createMockPeerDescriptor } from '../utils/utils' -import { PeerDescriptor } from '../../src/exports' +import { PeerDescriptor } from '../../generated/packages/dht/protos/DhtRpc' describe('getClosestNodes', () => { @@ -25,7 +25,7 @@ describe('getClosestNodes', () => { const expected = sortBy( peerDescriptors.filter((n) => !excluded.has(toNodeId(n))), - (peerDescriptor: PeerDescriptor) => getDistance(peerDescriptor.nodeId, toDhtAddressRaw(referenceId)) + (peerDescriptor: PeerDescriptor) => getPeerDistance(peerDescriptor.nodeId, toDhtAddressRaw(referenceId)) ).slice(0, 5) expect(actual).toEqual(expected) }) diff --git a/packages/dht/test/utils/FakeTransport.ts b/packages/dht/test/utils/FakeTransport.ts index c5796c153e..f736362826 100644 --- a/packages/dht/test/utils/FakeTransport.ts +++ b/packages/dht/test/utils/FakeTransport.ts @@ -2,7 +2,7 @@ import { EventEmitter } from 'eventemitter3' import { DhtAddress, toDhtAddress, toNodeId } from '../../src/identifiers' import { Message, PeerDescriptor } from '../../generated/packages/dht/protos/DhtRpc' import { DEFAULT_SEND_OPTIONS, ITransport, SendOptions, TransportEvents } from '../../src/transport/ITransport' -import { ConnectionsView } from '../../src/exports' +import { ConnectionsView } from '../../src/connection/ConnectionsView' // TODO extract ConnectionsView functionality to FakeConnectionsView class FakeTransport extends EventEmitter implements ITransport, ConnectionsView { diff --git a/packages/dht/test/utils/mock/MockConnection.ts b/packages/dht/test/utils/mock/MockConnection.ts index 126789ef5b..d84b5d1770 100644 --- a/packages/dht/test/utils/mock/MockConnection.ts +++ b/packages/dht/test/utils/mock/MockConnection.ts @@ -1,4 +1,4 @@ -import EventEmitter from 'eventemitter3' +import { EventEmitter } from 'eventemitter3' import { ConnectionEvents, IConnection } from '../../../src/connection/IConnection' export class MockConnection extends EventEmitter implements IConnection { diff --git a/packages/dht/test/utils/topology.ts b/packages/dht/test/utils/topology.ts index 4215a7842a..3f69460128 100644 --- a/packages/dht/test/utils/topology.ts +++ b/packages/dht/test/utils/topology.ts @@ -4,7 +4,7 @@ import minBy from 'lodash/minBy' import range from 'lodash/range' import without from 'lodash/without' import { SortedContactList } from '../../src/dht/contact/SortedContactList' -import { getDistance } from '../../src/dht/PeerManager' +import { getPeerDistance } from '../../src/dht/helpers/getPeerDistance' export const getTopologyPartitions = (topology: Multimap): Set[] => { let partitions: Set[] = [] @@ -72,7 +72,7 @@ export const createTestTopology = (nodeCount: number, minNeighorCount: number): const closestNodedId = getClosestNodes(nodeId, otherNodes, 1, false)[0] return [nodeId, closestNodedId] }) - const mergePair = minBy(closestPairs, (pair) => getDistance(toDhtAddressRaw(pair[0]), toDhtAddressRaw(pair[1])))! + const mergePair = minBy(closestPairs, (pair) => getPeerDistance(toDhtAddressRaw(pair[0]), toDhtAddressRaw(pair[1])))! topology.add(mergePair[0], mergePair[1]) topology.add(mergePair[1], mergePair[0]) } diff --git a/packages/dht/tsconfig.browser-generated.json b/packages/dht/tsconfig.browser-generated.json new file mode 100644 index 0000000000..69e11fa259 --- /dev/null +++ b/packages/dht/tsconfig.browser-generated.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.browser.json", + "compilerOptions": { + "noImplicitOverride": false + }, + "include": [ + "generated" + ], + "exclude": [] +} diff --git a/packages/dht/tsconfig.browser.json b/packages/dht/tsconfig.browser.json new file mode 100644 index 0000000000..9b498b4bbd --- /dev/null +++ b/packages/dht/tsconfig.browser.json @@ -0,0 +1,44 @@ +{ + "extends": "../../tsconfig.browser.json", + "compilerOptions": { + "outDir": "dist/browser", + "baseUrl": ".", + + /* Mapping */ + "paths": { + "@/*": [ + "src/browser/*" + ] + }, + + /* @todo Make verbatimModuleSyntax (true) work. */ + "verbatimModuleSyntax": false, + + /* @todo Make useUnknownInCatchVariables (true) work. */ + "useUnknownInCatchVariables": false, + + /* @todo Make erasableSyntaxOnly (true) work. */ + "erasableSyntaxOnly": false, + + /* @todo Make noUnusedLocals (true) work. */ + "noUnusedLocals": false, + + /* @todo Make noUnusedParameters (true) work. */ + "noUnusedParameters": false + }, + "include": [ + "src", + "package.json" + ], + "exclude": [ + "src/nodejs" + ], + "references": [ + { "path": "../utils" }, + { "path": "../proto-rpc" }, + { "path": "../cdn-location" }, + { "path": "../geoip-location" }, + { "path": "../autocertifier-client" }, + { "path": "./tsconfig.browser-generated.json" } + ] +} diff --git a/packages/dht/tsconfig.jest.json b/packages/dht/tsconfig.jest.json index 033d864c42..e506dbfe70 100644 --- a/packages/dht/tsconfig.jest.json +++ b/packages/dht/tsconfig.jest.json @@ -1,12 +1,24 @@ { "extends": "../../tsconfig.jest.json", + "compilerOptions": { + "baseUrl": ".", + + /* Mapping */ + "paths": { + "@/*": [ + "src/nodejs/*" + ] + } + }, "include": [ "src", "test", - "package.json", - "scripts" + "package.json" + ], + "exclude": [ + "src/browser" ], "references": [ - { "path": "./tsconfig.generated.json" } + { "path": "./tsconfig.node-generated.json" } ] } diff --git a/packages/dht/tsconfig.json b/packages/dht/tsconfig.json index e5441a57dd..9a557a2379 100644 --- a/packages/dht/tsconfig.json +++ b/packages/dht/tsconfig.json @@ -1,18 +1,10 @@ { - "extends": "../../tsconfig.node.json", + "files": [], "compilerOptions": { - "outDir": "dist" + "composite": true }, - "include": [ - "src", - "package.json" - ], "references": [ - { "path": "../utils" }, - { "path": "../proto-rpc" }, - { "path": "../cdn-location" }, - { "path": "../geoip-location" }, - { "path": "../autocertifier-client" }, - { "path": "./tsconfig.generated.json" } + { "path": "./tsconfig.node.json" }, + { "path": "./tsconfig.browser.json" } ] } diff --git a/packages/dht/tsconfig.karma.json b/packages/dht/tsconfig.karma.json index 28bd6d922c..b5fd515e7a 100644 --- a/packages/dht/tsconfig.karma.json +++ b/packages/dht/tsconfig.karma.json @@ -1,10 +1,21 @@ { "extends": "../../tsconfig.karma.json", "compilerOptions": { - "outDir": "dist" + "outDir": "dist/karma", + "baseUrl": ".", + + /* Mapping */ + "paths": { + "@/*": [ + "src/browser/*" + ] + } }, "include": [ "src", "package.json" - ] + ], + "exclude": [ + "src/nodejs" + ], } diff --git a/packages/dht/tsconfig.generated.json b/packages/dht/tsconfig.node-generated.json similarity index 75% rename from packages/dht/tsconfig.generated.json rename to packages/dht/tsconfig.node-generated.json index 4ce2cee0f2..b57b4a74d3 100644 --- a/packages/dht/tsconfig.generated.json +++ b/packages/dht/tsconfig.node-generated.json @@ -1,5 +1,5 @@ { - "extends": "./tsconfig.json", + "extends": "./tsconfig.node.json", "compilerOptions": { "noImplicitOverride": false }, diff --git a/packages/dht/tsconfig.node.json b/packages/dht/tsconfig.node.json new file mode 100644 index 0000000000..8f9dd4cfbc --- /dev/null +++ b/packages/dht/tsconfig.node.json @@ -0,0 +1,33 @@ +{ + "extends": "../../tsconfig.node.json", + "compilerOptions": { + "outDir": "dist/nodejs", + + /* Mapping */ + "paths": { + "@/*": [ + "src/nodejs/*" + ] + }, + + /* Resolution */ + "module": "preserve", + "moduleResolution": "bundler", + "baseUrl": "." + }, + "include": [ + "src", + "package.json" + ], + "exclude": [ + "src/browser" + ], + "references": [ + { "path": "../utils" }, + { "path": "../proto-rpc" }, + { "path": "../cdn-location" }, + { "path": "../geoip-location" }, + { "path": "../autocertifier-client" }, + { "path": "./tsconfig.node-generated.json" } + ] +} diff --git a/packages/trackerless-network/karma.config.ts b/packages/trackerless-network/karma.config.ts index 4d2fb6f2be..e7779dfd9e 100644 --- a/packages/trackerless-network/karma.config.ts +++ b/packages/trackerless-network/karma.config.ts @@ -10,12 +10,11 @@ const TEST_PATHS = [ export default createKarmaConfig(TEST_PATHS, createWebpackConfig({ libraryName: 'trackerless-network', alias: { - [resolve(__dirname, '../dht/src/connection/webrtc/NodeWebrtcConnection.ts')]: - resolve(__dirname, '../dht/src/connection/webrtc/BrowserWebrtcConnection.ts'), - [resolve(__dirname, '../dht/src/connection/websocket/NodeWebsocketClientConnection.ts')]: - resolve(__dirname, '../dht/src/connection/websocket/BrowserWebsocketClientConnection.ts'), - '@streamr/dht': resolve('../dht/src/exports.ts'), - '@streamr/proto-rpc': resolve('../proto-rpc/src/exports.ts'), + /** + * @todo Our "browser" tests use the Node.js build of DHT package – needed + * for WebSocket/Simulator stuff, but still, very confusing. + */ + '@streamr/dht': resolve(__dirname, '../dht/dist/exports-nodejs.cjs'), }, fallback: { module: false diff --git a/packages/utils/package.json b/packages/utils/package.json index deb81ebe9c..4489ccda48 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -12,16 +12,14 @@ "types": "./dist/exports-nodejs.d.ts", "exports": { ".": { + "types": "./dist/exports-nodejs.d.ts", "browser": { "types": "./dist/exports-browser.d.ts", "import": "./dist/exports-browser.js", "require": "./dist/exports-browser.cjs" }, - "default": { - "types": "./dist/exports-nodejs.d.ts", - "import": "./dist/exports-nodejs.js", - "require": "./dist/exports-nodejs.cjs" - } + "import": "./dist/exports-nodejs.js", + "require": "./dist/exports-nodejs.cjs" } }, "files": [ @@ -60,7 +58,7 @@ "sha3": "^2.1.4" }, "devDependencies": { - "@rollup/plugin-alias": "^5.1.1", + "@rollup/plugin-alias": "^6.0.0", "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", "@types/lodash": "^4.17.21", diff --git a/packages/utils/src/exports.ts b/packages/utils/src/exports.ts index d91d4cb134..635f8f7a78 100644 --- a/packages/utils/src/exports.ts +++ b/packages/utils/src/exports.ts @@ -55,3 +55,4 @@ export type { ChangeFieldType, MapKey } from './types' export { type WeiAmount, multiplyWeiAmount } from './WeiAmount' export { getSubtle, computeMd5 } from '@/crypto' export { SigningUtil, EcdsaSecp256k1Evm, EcdsaSecp256r1, MlDsa87, type KeyType, KEY_TYPES } from './SigningUtil' +export { randomBytes } from '@noble/post-quantum/utils' From 20ed5084468e5ad1bbdb67a36994c82fb7fd5537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Thu, 8 Jan 2026 00:46:53 +0100 Subject: [PATCH 10/18] refactor: Bundle `trackerless-network` (#3339) This pull request introduces several improvements to the `trackerless-network` and `utils` packages, focusing on standardizing cryptographic utilities, modernizing the build process, and refining TypeScript configuration. The main highlights include replacing direct `crypto` usage for SHA-1 with a shared utility function, introducing a Rollup-based build pipeline, and reorganizing TypeScript project references and configuration. **Build system modernization and configuration:** * Added a `rollup.config.mts` file and updated `package.json` scripts and dependencies in `trackerless-network` to use Rollup for bundling, including both CommonJS and ES module outputs, and improved the file structure for published artifacts. * Refactored TypeScript configuration by moving most settings and references to a new `tsconfig.node.json`, leaving `tsconfig.json` as a minimal entry point for project references. **Cryptographic utility standardization:** * Introduced a shared `computeSha1` function in the `utils` package, with both browser and Node.js implementations, and re-exported it for use in other packages. * Updated `ContentDeliveryManager.ts` in `trackerless-network` to use the new `computeSha1` utility instead of directly using Node's `crypto.createHash`, improving cross-platform compatibility. **Minor code cleanups:** * Standardized `EventEmitter` import in `PlumtreeManager.ts` for consistency. --- package-lock.json | 102 +++++++++++++++++- packages/trackerless-network/package.json | 20 ++-- .../trackerless-network/rollup.config.mts | 54 ++++++++++ .../src/ContentDeliveryManager.ts | 4 +- .../plumtree/PlumtreeManager.ts | 2 +- .../tsconfig.generated.json | 2 +- packages/trackerless-network/tsconfig.json | 13 +-- .../trackerless-network/tsconfig.node.json | 20 ++++ packages/utils/package.json | 1 + packages/utils/src/browser/crypto.ts | 5 + packages/utils/src/exports.ts | 2 +- packages/utils/src/nodejs/crypto.ts | 4 + 12 files changed, 207 insertions(+), 22 deletions(-) create mode 100644 packages/trackerless-network/rollup.config.mts create mode 100644 packages/trackerless-network/tsconfig.node.json diff --git a/package-lock.json b/package-lock.json index 0076f1b555..52fa236332 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30874,12 +30874,99 @@ "yallist": "^5.0.0" }, "devDependencies": { + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", "@streamr/test-utils": "103.2.0", "@types/lodash": "^4.17.21", "@types/yallist": "^5.0.0", "expect": "^30.0.5", - "ts-node": "^10.9.2" + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "ts-node": "^10.9.2", + "tsx": "^4.21.0" + } + }, + "packages/trackerless-network/node_modules/glob": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", + "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/trackerless-network/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/trackerless-network/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "packages/trackerless-network/node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/trackerless-network/node_modules/rimraf": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", + "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.0", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "packages/trackerless-network/node_modules/yallist": { @@ -30897,6 +30984,7 @@ "license": "Apache-2.0", "dependencies": { "@noble/curves": "^1.9.7", + "@noble/hashes": "^2.0.1", "@noble/post-quantum": "^0.4.1", "buffer": "^6.0.3", "buffer-shim": "^1.0.1", @@ -30923,6 +31011,18 @@ "tsx": "^4.21.0" } }, + "packages/utils/node_modules/@noble/hashes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "packages/utils/node_modules/glob": { "version": "13.0.0", "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", diff --git a/packages/trackerless-network/package.json b/packages/trackerless-network/package.json index 35fdda4c22..bb7642e465 100644 --- a/packages/trackerless-network/package.json +++ b/packages/trackerless-network/package.json @@ -7,20 +7,22 @@ "url": "git+https://github.com/streamr-dev/network-monorepo.git", "directory": "packages/trackerless-network" }, - "main": "dist/src/exports.js", - "types": "dist/src/exports.d.ts", + "main": "./dist/exports.cjs", + "module": "./dist/exports.js", + "types": "./dist/exports.d.ts", "files": [ - "dist", + "dist/exports.*", "!*.tsbuildinfo", "README.md" ], "license": "STREAMR NETWORK OPEN SOURCE LICENSE", "author": "Streamr Network AG ", "scripts": { + "prebuild": "npm run reset-self && ./proto.sh", "build": "tsc -b", - "build-browser": "webpack --mode=development --progress", - "prebuild": "./proto.sh", + "postbuild": "NODE_OPTIONS='--import tsx' rollup -c rollup.config.mts", "check": "tsc -b tsconfig.jest.json", + "reset-self": "rimraf --glob 'dist/**/*.tsbuildinfo'", "clean": "jest --clearCache --config '{}' || true; rm -rf dist generated *.tsbuildinfo node_modules/.cache || true", "coverage": "jest --coverage", "eslint": "eslint --cache --cache-location=node_modules/.cache/.eslintcache/ '*/**/*.{js,ts}'", @@ -45,11 +47,17 @@ "yallist": "^5.0.0" }, "devDependencies": { + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", "@streamr/test-utils": "103.2.0", "@types/lodash": "^4.17.21", "@types/yallist": "^5.0.0", "expect": "^30.0.5", - "ts-node": "^10.9.2" + "rimraf": "^6.1.2", + "rollup": "^4.55.1", + "rollup-plugin-dts": "^6.3.0", + "ts-node": "^10.9.2", + "tsx": "^4.21.0" } } diff --git a/packages/trackerless-network/rollup.config.mts b/packages/trackerless-network/rollup.config.mts new file mode 100644 index 0000000000..7c9b709e26 --- /dev/null +++ b/packages/trackerless-network/rollup.config.mts @@ -0,0 +1,54 @@ +import { defineConfig, type RollupOptions } from 'rollup' +import { dts } from 'rollup-plugin-dts' +import { nodeResolve } from '@rollup/plugin-node-resolve' +import json from '@rollup/plugin-json' + +export default defineConfig([ + nodejs(), + nodejsTypes(), +]) + +function nodejs(): RollupOptions { + return { + input: './dist/src/exports.js', + output: [ + { + format: 'es', + file: './dist/exports.js', + sourcemap: true, + }, + { + format: 'cjs', + file: './dist/exports.cjs', + sourcemap: true, + }, + ], + plugins: [ + json(), + nodeResolve({ + preferBuiltins: true, + }), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} + +function nodejsTypes(): RollupOptions { + return { + input: './dist/src/exports.d.ts', + output: [ + { file: './dist/exports.d.ts' }, + ], + plugins: [ + nodeResolve(), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} diff --git a/packages/trackerless-network/src/ContentDeliveryManager.ts b/packages/trackerless-network/src/ContentDeliveryManager.ts index 7b8a48b12d..81d98697f6 100644 --- a/packages/trackerless-network/src/ContentDeliveryManager.ts +++ b/packages/trackerless-network/src/ContentDeliveryManager.ts @@ -10,6 +10,7 @@ import { toNodeId } from '@streamr/dht' import { + computeSha1, Logger, Metric, MetricsContext, @@ -18,7 +19,6 @@ import { UserID, toStreamPartID } from '@streamr/utils' -import { createHash } from 'crypto' import { EventEmitter } from 'eventemitter3' import sampleSize from 'lodash/sampleSize' import { ProxyDirection, StreamMessage } from '../generated/packages/trackerless-network/protos/NetworkRpc' @@ -85,7 +85,7 @@ export interface StreamPartDeliveryOptions { } export const streamPartIdToDataKey = (streamPartId: StreamPartID): DhtAddress => { - return toDhtAddress(new Uint8Array((createHash('sha1').update(streamPartId).digest()))) + return toDhtAddress(computeSha1(streamPartId)) } export class ContentDeliveryManager extends EventEmitter { diff --git a/packages/trackerless-network/src/content-delivery-layer/plumtree/PlumtreeManager.ts b/packages/trackerless-network/src/content-delivery-layer/plumtree/PlumtreeManager.ts index 27bc9ef607..a38b0d2e1f 100644 --- a/packages/trackerless-network/src/content-delivery-layer/plumtree/PlumtreeManager.ts +++ b/packages/trackerless-network/src/content-delivery-layer/plumtree/PlumtreeManager.ts @@ -9,7 +9,7 @@ import { NodeList } from '../NodeList' import { PlumtreeRpcLocal } from './PlumtreeRpcLocal' import { PlumtreeRpcRemote } from './PlumtreeRpcRemote' import { ContentDeliveryRpcClient, PlumtreeRpcClient } from '../../../generated/packages/trackerless-network/protos/NetworkRpc.client' -import EventEmitter from 'eventemitter3' +import { EventEmitter } from 'eventemitter3' import { Logger } from '@streamr/utils' import { ContentDeliveryRpcRemote } from '../ContentDeliveryRpcRemote' import { PausedNeighbors } from './PausedNeighbors' diff --git a/packages/trackerless-network/tsconfig.generated.json b/packages/trackerless-network/tsconfig.generated.json index 4ce2cee0f2..b57b4a74d3 100644 --- a/packages/trackerless-network/tsconfig.generated.json +++ b/packages/trackerless-network/tsconfig.generated.json @@ -1,5 +1,5 @@ { - "extends": "./tsconfig.json", + "extends": "./tsconfig.node.json", "compilerOptions": { "noImplicitOverride": false }, diff --git a/packages/trackerless-network/tsconfig.json b/packages/trackerless-network/tsconfig.json index 0933004e01..667d1ae42d 100644 --- a/packages/trackerless-network/tsconfig.json +++ b/packages/trackerless-network/tsconfig.json @@ -1,16 +1,9 @@ { - "extends": "../../tsconfig.node.json", + "files": [], "compilerOptions": { - "outDir": "dist" + "composite": true }, - "include": [ - "src", - "package.json" - ], "references": [ - { "path": "../utils" }, - { "path": "../proto-rpc" }, - { "path": "../dht" }, - { "path": "./tsconfig.generated.json" } + { "path": "./tsconfig.node.json" } ] } diff --git a/packages/trackerless-network/tsconfig.node.json b/packages/trackerless-network/tsconfig.node.json new file mode 100644 index 0000000000..abc81532e1 --- /dev/null +++ b/packages/trackerless-network/tsconfig.node.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.node.json", + "compilerOptions": { + "outDir": "dist", + + /* Resolution */ + "moduleResolution": "bundler", + "module": "preserve" + }, + "include": [ + "src", + "package.json" + ], + "references": [ + { "path": "../utils" }, + { "path": "../proto-rpc" }, + { "path": "../dht" }, + { "path": "./tsconfig.generated.json" } + ] +} diff --git a/packages/utils/package.json b/packages/utils/package.json index 4489ccda48..d3692fccac 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -44,6 +44,7 @@ "license": "Apache-2.0", "dependencies": { "@noble/curves": "^1.9.7", + "@noble/hashes": "^2.0.1", "@noble/post-quantum": "^0.4.1", "buffer": "^6.0.3", "buffer-shim": "^1.0.1", diff --git a/packages/utils/src/browser/crypto.ts b/packages/utils/src/browser/crypto.ts index 2afacd1136..8fa85a7bc8 100644 --- a/packages/utils/src/browser/crypto.ts +++ b/packages/utils/src/browser/crypto.ts @@ -1,4 +1,5 @@ import md5 from 'md5' +import { sha1 } from '@noble/hashes/legacy.js' export function getSubtle(): SubtleCrypto { const { crypto } = globalThis @@ -18,6 +19,10 @@ export function computeMd5(input: string): Buffer { return Buffer.from(md5(input), 'hex') } +export function computeSha1(input: string): Buffer { + return Buffer.from(sha1(new TextEncoder().encode(input))) +} + export type Jwk = JsonWebKey export type CryptoKey = globalThis.CryptoKey diff --git a/packages/utils/src/exports.ts b/packages/utils/src/exports.ts index 635f8f7a78..1cf9d85ddc 100644 --- a/packages/utils/src/exports.ts +++ b/packages/utils/src/exports.ts @@ -53,6 +53,6 @@ export { type UserID, type UserIDRaw, toUserId, toUserIdRaw, isValidUserId, isEt export type { HexString } from './HexString' export type { ChangeFieldType, MapKey } from './types' export { type WeiAmount, multiplyWeiAmount } from './WeiAmount' -export { getSubtle, computeMd5 } from '@/crypto' +export { getSubtle, computeMd5, computeSha1 } from '@/crypto' export { SigningUtil, EcdsaSecp256k1Evm, EcdsaSecp256r1, MlDsa87, type KeyType, KEY_TYPES } from './SigningUtil' export { randomBytes } from '@noble/post-quantum/utils' diff --git a/packages/utils/src/nodejs/crypto.ts b/packages/utils/src/nodejs/crypto.ts index 769931c1b1..72c5e5938c 100644 --- a/packages/utils/src/nodejs/crypto.ts +++ b/packages/utils/src/nodejs/crypto.ts @@ -21,3 +21,7 @@ export type CryptoKey = webcrypto.CryptoKey export function computeMd5(input: string): Buffer { return crypto.createHash('md5').update(input).digest() } + +export function computeSha1(input: string): Buffer { + return crypto.createHash('sha1').update(input).digest() +} From aaa927807b2b280eb48b7da7cb04d61817dfdb01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Fri, 9 Jan 2026 12:58:59 +0100 Subject: [PATCH 11/18] feat: Bundle a limited version of `autocertifier-client` for the browser (#3340) This pull request updates the `autocertifier-client` package to provide separate builds and type definitions for Node.js and browser environments, and refactors how the `SERVICE_ID` constant is exported. The changes improve compatibility, allow for better tree-shaking, and clarify the package's entry points for different platforms. > [!note] > This adds a very minimalistic set of features used by browser bundles of other packages. ## Changes **Multi-platform build and exports:** * The `package.json` now defines separate entry points and type definitions for Node.js (`exports-nodejs.*`) and browser (`exports-browser.*`) builds, and introduces an `exports` map to clarify usage in different environments. * The Rollup configuration (`rollup.config.mts`) is updated to produce both Node.js and browser bundles and their corresponding type definitions, using separate output files for each platform. [[1]](diffhunk://#diff-aa7340f6df268dc8fead031bb0c353a91b48aaba1de3a92f4453e889522380baR8-R9) [[2]](diffhunk://#diff-aa7340f6df268dc8fead031bb0c353a91b48aaba1de3a92f4453e889522380baL16-R23) [[3]](diffhunk://#diff-aa7340f6df268dc8fead031bb0c353a91b48aaba1de3a92f4453e889522380baL42-R44) [[4]](diffhunk://#diff-aa7340f6df268dc8fead031bb0c353a91b48aaba1de3a92f4453e889522380baR57-R106) **Exports and type improvements:** * A new `exports-browser.ts` file is added to explicitly export `SERVICE_ID`, `CertifiedSubdomain`, and `AutoCertifierClient` types for browser consumers. * The main `exports.ts` file now imports `SERVICE_ID` from a new `consts.ts` file, rather than directly from `AutoCertifierClient.ts`, improving modularity. [[1]](diffhunk://#diff-863c50d9a2d9e6354ead53c9a0774fc7b77195d1a0c810fccfbf8e7927003accL1-R2) [[2]](diffhunk://#diff-b305f800b166c6cb29b81990e96817430b44b06cca6151f539758e0d4255c468R1) * The `SERVICE_ID` constant is moved from `AutoCertifierClient.ts` to a new `consts.ts` module and is imported where needed, clarifying its source and reducing coupling. [[1]](diffhunk://#diff-eb1e0fd9ae3d2c3a37ffef96ff63e73956c8926dcbe11a391e39d9c83d9aefd0R11) [[2]](diffhunk://#diff-eb1e0fd9ae3d2c3a37ffef96ff63e73956c8926dcbe11a391e39d9c83d9aefd0L38) [[3]](diffhunk://#diff-b305f800b166c6cb29b81990e96817430b44b06cca6151f539758e0d4255c468R1) **Minor improvements:** * The DHT package updates its imports to use `type`-only imports for `AutoCertifierClient`, improving type safety and clarity. * Minor formatting cleanup in the DHT browser Rollup config. ## Things to know * It may not be clear to the team that the Karma tests are a mixture of browser and NodeJS environments. Although Karma is meant to aim at the browser testing, there are 2 Karma setups now that explicitly point to NodeJS versions of other packages in order to work. 1. `trackerless-network` points to NodeJS build of `dht`. 2. `dht` points to NodeJS build of `autocertifier-client`. This does work, and is way easier to grasp if we talk about it openly and explicitly. And that's how the setups are now. We may want to address it as an issue in the future, and come up with much better separation though. --- packages/autocertifier-client/package.json | 22 +++++-- .../autocertifier-client/rollup.config.mts | 58 ++++++++++++++++++- .../src/AutoCertifierClient.ts | 2 +- packages/autocertifier-client/src/consts.ts | 1 + .../src/exports-browser.ts | 3 + packages/autocertifier-client/src/exports.ts | 3 +- packages/dht/karma.config.ts | 6 ++ packages/dht/rollup.config.mts | 1 - .../defaultAutoCertifierClientFactory.ts | 2 +- 9 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 packages/autocertifier-client/src/consts.ts create mode 100644 packages/autocertifier-client/src/exports-browser.ts diff --git a/packages/autocertifier-client/package.json b/packages/autocertifier-client/package.json index c6a3abc6fb..b79c057f45 100644 --- a/packages/autocertifier-client/package.json +++ b/packages/autocertifier-client/package.json @@ -7,11 +7,25 @@ "url": "git+https://github.com/streamr-dev/network.git", "directory": "packages/autocertifier-client" }, - "main": "./dist/exports.cjs", - "module": "./dist/exports.js", - "types": "./dist/exports.d.ts", + "main": "./dist/exports-nodejs.cjs", + "module": "./dist/exports-nodejs.js", + "types": "./dist/exports-nodejs.d.ts", + "exports": { + ".": { + "types": "./dist/exports-nodejs.d.ts", + "browser": { + "types": "./dist/exports-browser.d.ts", + "import": "./dist/exports-browser.js", + "require": "./dist/exports-browser.cjs" + }, + "import": "./dist/exports-nodejs.js", + "require": "./dist/exports-nodejs.cjs", + "default": "./dist/exports-nodejs.js" + } + }, "files": [ - "dist/exports.*", + "dist/exports-nodejs.*", + "dist/exports-browser.*", "!*.tsbuildinfo" ], "license": "STREAMR NETWORK OPEN SOURCE LICENSE", diff --git a/packages/autocertifier-client/rollup.config.mts b/packages/autocertifier-client/rollup.config.mts index cc1fbda131..12ffd4670e 100644 --- a/packages/autocertifier-client/rollup.config.mts +++ b/packages/autocertifier-client/rollup.config.mts @@ -5,6 +5,8 @@ import { nodeResolve } from '@rollup/plugin-node-resolve' export default defineConfig([ nodejs(), nodejsTypes(), + browser(), + browserTypes(), ]) function nodejs(): RollupOptions { @@ -13,12 +15,12 @@ function nodejs(): RollupOptions { output: [ { format: 'es', - file: './dist/exports.js', + file: './dist/exports-nodejs.js', sourcemap: true, }, { format: 'cjs', - file: './dist/exports.cjs', + file: './dist/exports-nodejs.cjs', sourcemap: true, }, ], @@ -39,7 +41,7 @@ function nodejsTypes(): RollupOptions { input: './dist/src/exports.d.ts', output: [ { - file: './dist/exports.d.ts', + file: './dist/exports-nodejs.d.ts', }, ], plugins: [ @@ -52,3 +54,53 @@ function nodejsTypes(): RollupOptions { ], } } + +function browser(): RollupOptions { + return { + input: './dist/src/exports-browser.js', + output: [ + { + format: 'es', + file: './dist/exports-browser.js', + sourcemap: true, + }, + { + format: 'cjs', + file: './dist/exports-browser.cjs', + sourcemap: true, + }, + ], + plugins: [ + nodeResolve({ + preferBuiltins: false, + browser: true, + }), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} + +function browserTypes(): RollupOptions { + return { + input: './dist/src/exports-browser.d.ts', + output: [ + { + file: './dist/exports-browser.d.ts', + }, + ], + plugins: [ + nodeResolve({ + preferBuiltins: false, + browser: true, + }), + dts(), + ], + external: [ + /node_modules/, + /@streamr\//, + ], + } +} diff --git a/packages/autocertifier-client/src/AutoCertifierClient.ts b/packages/autocertifier-client/src/AutoCertifierClient.ts index 56e9b9b127..87fd22817b 100644 --- a/packages/autocertifier-client/src/AutoCertifierClient.ts +++ b/packages/autocertifier-client/src/AutoCertifierClient.ts @@ -8,6 +8,7 @@ import { CertifiedSubdomain } from './data/CertifiedSubdomain' import fs from 'fs' import path from 'path' import * as forge from 'node-forge' +import { SERVICE_ID } from './consts' interface AutoCertifierClientEvents { updatedCertificate: (domain: CertifiedSubdomain) => void @@ -35,7 +36,6 @@ const getBaseDirectory = (directory: string): string => { return path.sep } -export const SERVICE_ID = 'system/auto-certificer' const ONE_DAY = 1000 * 60 * 60 * 24 const MAX_INT_32 = 2147483647 diff --git a/packages/autocertifier-client/src/consts.ts b/packages/autocertifier-client/src/consts.ts new file mode 100644 index 0000000000..fc7da60ba7 --- /dev/null +++ b/packages/autocertifier-client/src/consts.ts @@ -0,0 +1 @@ +export const SERVICE_ID = 'system/auto-certificer' diff --git a/packages/autocertifier-client/src/exports-browser.ts b/packages/autocertifier-client/src/exports-browser.ts new file mode 100644 index 0000000000..5fdf5e3905 --- /dev/null +++ b/packages/autocertifier-client/src/exports-browser.ts @@ -0,0 +1,3 @@ +export { SERVICE_ID } from './consts' +export type { CertifiedSubdomain } from './data/CertifiedSubdomain' +export type { AutoCertifierClient } from './AutoCertifierClient' diff --git a/packages/autocertifier-client/src/exports.ts b/packages/autocertifier-client/src/exports.ts index 1dfbe9542b..aef9ce6e35 100644 --- a/packages/autocertifier-client/src/exports.ts +++ b/packages/autocertifier-client/src/exports.ts @@ -1,4 +1,5 @@ -export { AutoCertifierClient, SERVICE_ID, type HasSession } from './AutoCertifierClient' +export { AutoCertifierClient, type HasSession } from './AutoCertifierClient' +export { SERVICE_ID } from './consts' export type { CertifiedSubdomain } from './data/CertifiedSubdomain' export type { Session } from './data/Session' export type { UpdateIpAndPortRequest } from './data/UpdateIpAndPortRequest' diff --git a/packages/dht/karma.config.ts b/packages/dht/karma.config.ts index 0ac143cf8d..a304099ecc 100644 --- a/packages/dht/karma.config.ts +++ b/packages/dht/karma.config.ts @@ -12,6 +12,12 @@ export default createKarmaConfig( createWebpackConfig({ libraryName: 'dht', alias: { + /** + * Our "browser" tests use the Node.js build of `autocertifier-client` package – needed + * for certifications stuff, but still, very confusing. + */ + '@streamr/autocertifier-client': resolve(__dirname, '../autocertifier-client/dist/exports-nodejs.cjs'), + /** * Selectively alias only browser-specific implementations here. The rest stays in `nodejs/` * because these (like WebsocketServer) are needed for testing and running WebSocket-based diff --git a/packages/dht/rollup.config.mts b/packages/dht/rollup.config.mts index 1b57140fe8..e517ff650a 100644 --- a/packages/dht/rollup.config.mts +++ b/packages/dht/rollup.config.mts @@ -114,7 +114,6 @@ function browser(): RollupOptions { /node_modules/, /@streamr\//, ], - } } diff --git a/packages/dht/src/browser/defaultAutoCertifierClientFactory.ts b/packages/dht/src/browser/defaultAutoCertifierClientFactory.ts index 773cafc3e7..aae07665f8 100644 --- a/packages/dht/src/browser/defaultAutoCertifierClientFactory.ts +++ b/packages/dht/src/browser/defaultAutoCertifierClientFactory.ts @@ -1,4 +1,4 @@ -import { AutoCertifierClient } from '@streamr/autocertifier-client' +import type { AutoCertifierClient } from '@streamr/autocertifier-client' import { ListeningRpcCommunicator } from '../transport/ListeningRpcCommunicator' export const defaultAutoCertifierClientFactory = ( From 5e7a542a747c1e3c0891630fd4e27c9c9d58d836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Fri, 9 Jan 2026 13:54:28 +0100 Subject: [PATCH 12/18] Clean-up process only if available (#3341) This pull request adds environment-specific cleanup handling to the `NetworkStack` module, ensuring that network instances are properly stopped when the Node.js process exits or when the browser window unloads. The changes improve resource management and reliability across different runtime environments. **Environment-specific cleanup logic:** * Added a check to only register process exit event handlers (such as `exit`, `SIGINT`, `uncaughtException`, etc.) in Node.js environments, preventing unnecessary or erroneous event handling in browsers. * Ensured that browser-specific cleanup using the `window.unload` event remains separate and is only registered in browser environments. --- .../trackerless-network/src/NetworkStack.ts | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/packages/trackerless-network/src/NetworkStack.ts b/packages/trackerless-network/src/NetworkStack.ts index a6d2601359..4198d0481c 100644 --- a/packages/trackerless-network/src/NetworkStack.ts +++ b/packages/trackerless-network/src/NetworkStack.ts @@ -32,19 +32,47 @@ const stopInstances = async () => { const clonedInstances = [...instances] await Promise.all(clonedInstances.map((instance) => instance.stop())) } -const EXIT_EVENTS = [`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `unhandledRejection`, `SIGTERM`] -EXIT_EVENTS.forEach((event) => { - process.on(event, async (eventArg) => { - const isError = (event === 'uncaughtException') || (event === 'unhandledRejection') - if (isError) { - logger.error(`exit event: ${event}`, eventArg) - } - await stopInstances() - process.exit(isError ? 1 : 0) + +/** + * @todo The following cleanup logic is currently handled inside this module for both Node.js and + * browser environments. Consider refactoring it into a higher-level integration layer if lifecycle + * management is centralized elsewhere. + */ +if (typeof process === 'object' && typeof process?.on === 'function') { + /** + * @todo The `exit` event shouldn't use an async handler because the event loop is already + * shutting down, so async work won't complete. Calling `process.exit()` inside an `exit` + * handler is also redundant and may cause issues. Remove `exit` from `EXIT_EVENTS` + * or omit it entirely, since other signal handlers already terminate the process. + */ + const EXIT_EVENTS = [`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `unhandledRejection`, `SIGTERM`] + EXIT_EVENTS.forEach((event) => { + /** + * @todo Registering handlers at module load time can cause side effects. Use explicit + * or lazy initialization to improve control and testability. + */ + process.on(event, async (eventArg) => { + const isError = (event === 'uncaughtException') || (event === 'unhandledRejection') + if (isError) { + logger.error(`exit event: ${event}`, eventArg) + } + /** + * @todo Async `stopInstances()` may be interrupted by `process.exit()`. Use + * synchronous cleanup or a timeout, and wait for cleanup on graceful signals + * but exit quickly on error events. + */ + await stopInstances() + process.exit(isError ? 1 : 0) + }) }) -}) +} + declare let window: any if (typeof window === 'object') { + /** + * @todo Registering handlers at module load time can cause side effects. Use explicit + * or lazy initialization to improve control and testability. + */ window.addEventListener('unload', async () => { await stopInstances() }) From d490e1ee7869cfaaed9c489a27b57dcaf3c5f38b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Fri, 9 Jan 2026 14:46:22 +0100 Subject: [PATCH 13/18] feat: Expose cross-env cipher utils from `utils` package (#3342) This pull request adds support for AES encryption and decryption utilities for both browser and Node.js environments, updates the build configuration to bundle necessary dependencies, and ensures that new cryptographic functions are exported for use throughout the codebase. ## Changes **Cryptography utilities:** * Added `createCipheriv` and `createDecipheriv` functions to `browser/crypto.ts` using `browserify-aes` for AES support in the browser, with input validation for supported suites. * Added corresponding `createCipheriv` and `createDecipheriv` functions to `nodejs/crypto.ts` using Node's native `crypto` module for Node.js support. * Exported the new cryptographic functions from `exports.ts` for use in other modules. **Dependency management:** * Added `browserify-aes` and `md5.js` to dependencies, and `@rollup/plugin-commonjs` and `@rollup/plugin-json` to devDependencies in `package.json` to support new crypto utilities and bundling. [[1]](diffhunk://#diff-21f8eb1d7a149d42ab0454ea905d44f624ff1d0aeb6d7a88d75b42962ca6b053R49-R55) [[2]](diffhunk://#diff-21f8eb1d7a149d42ab0454ea905d44f624ff1d0aeb6d7a88d75b42962ca6b053R65-R66) **Build configuration:** * Updated `rollup.config.mts` to include CommonJS and JSON plugins, and modified the `external` configuration to ensure required dependencies (like `browserify-aes` and `md5.js`) are bundled, avoiding outdated versions from other packages. [[1]](diffhunk://#diff-e934d663fa3257013d51e6e713d05f6e071a51be17d28891e77d7f00c22bcbf7R5-R6) [[2]](diffhunk://#diff-e934d663fa3257013d51e6e713d05f6e071a51be17d28891e77d7f00c22bcbf7R101-R114) ## Next steps * Use `createCipheriv` and `createDecipheriv` in StreamrTV's `tv-engine` package, and in the SDK. --- package-lock.json | 73 +++++++++++++++++++------- packages/utils/package.json | 5 ++ packages/utils/rollup.config.mts | 11 +++- packages/utils/src/browser/crypto.ts | 34 ++++++++++++ packages/utils/src/browserify-aes.d.ts | 44 ++++++++++++++++ packages/utils/src/exports.ts | 2 +- packages/utils/src/nodejs/crypto.ts | 16 ++++++ 7 files changed, 163 insertions(+), 22 deletions(-) create mode 100644 packages/utils/src/browserify-aes.d.ts diff --git a/package-lock.json b/package-lock.json index 52fa236332..21de4d1001 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7312,6 +7312,33 @@ } } }, + "node_modules/@rollup/plugin-commonjs": { + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-29.0.0.tgz", + "integrity": "sha512-U2YHaxR2cU/yAiwKJtJRhnyLk7cifnQw0zUpISsocBDoHDJn+HTV74ABqnwr5bEgWUwFZC9oFL6wLe21lHu5eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "fdir": "^6.2.0", + "is-reference": "1.2.1", + "magic-string": "^0.30.3", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=16.0.0 || 14 >= 14.17" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/plugin-json": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", @@ -9027,21 +9054,14 @@ "license": "MIT" }, "node_modules/@types/readable-stream": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.18.tgz", - "integrity": "sha512-21jK/1j+Wg+7jVw1xnSwy/2Q1VgVjWuFssbYGTREPUBeZ+rqVFl2udq0IkxzPC0ZhOzVceUbyIACFZKLqKEBlA==", + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.23.tgz", + "integrity": "sha512-wwXrtQvbMHxCbBgjHaMGEmImFTQxxpfMOR/ZoQnXxB1woqkUbdLGFDgauo00Py9IudiaqSeiBiulSV9i6XIPig==", "license": "MIT", "dependencies": { - "@types/node": "*", - "safe-buffer": "~5.1.1" + "@types/node": "*" } }, - "node_modules/@types/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -11449,7 +11469,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, "license": "MIT", "dependencies": { "buffer-xor": "^1.0.3", @@ -11717,7 +11736,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", - "dev": true, "license": "MIT" }, "node_modules/bufferutil": { @@ -12162,7 +12180,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", - "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.4", @@ -12526,6 +12543,13 @@ "dev": true, "license": "ISC" }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, "node_modules/compare-func": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", @@ -13066,7 +13090,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, "license": "MIT", "dependencies": { "cipher-base": "^1.0.1", @@ -15105,7 +15128,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, "license": "MIT", "dependencies": { "md5.js": "^1.3.4", @@ -16614,7 +16636,6 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", - "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.4", @@ -17678,6 +17699,16 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -20634,7 +20665,6 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, "license": "MIT", "dependencies": { "hash-base": "^3.0.0", @@ -25354,7 +25384,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, "license": "MIT", "dependencies": { "hash-base": "^3.0.0", @@ -25953,7 +25982,6 @@ "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, "license": "(MIT AND BSD-3-Clause)", "dependencies": { "inherits": "^2.0.1", @@ -30986,11 +31014,13 @@ "@noble/curves": "^1.9.7", "@noble/hashes": "^2.0.1", "@noble/post-quantum": "^0.4.1", + "browserify-aes": "^1.2.0", "buffer": "^6.0.3", "buffer-shim": "^1.0.1", "eventemitter3": "^5.0.0", "lodash": "^4.17.21", "md5": "^2.3.0", + "md5.js": "^1.3.5", "path-browserify": "^1.0.1", "pino": "^10.1.0", "pino-pretty": "^13.1.2", @@ -31000,10 +31030,13 @@ }, "devDependencies": { "@rollup/plugin-alias": "^6.0.0", + "@rollup/plugin-commonjs": "^29.0.0", + "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", "@types/lodash": "^4.17.21", "@types/md5": "^2.3.6", + "@types/readable-stream": "^4.0.23", "@types/secp256k1": "^4.0.7", "rimraf": "^6.1.2", "rollup": "^4.55.1", diff --git a/packages/utils/package.json b/packages/utils/package.json index d3692fccac..3694aa2b9e 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -46,11 +46,13 @@ "@noble/curves": "^1.9.7", "@noble/hashes": "^2.0.1", "@noble/post-quantum": "^0.4.1", + "browserify-aes": "^1.2.0", "buffer": "^6.0.3", "buffer-shim": "^1.0.1", "eventemitter3": "^5.0.0", "lodash": "^4.17.21", "md5": "^2.3.0", + "md5.js": "^1.3.5", "path-browserify": "^1.0.1", "pino": "^10.1.0", "pino-pretty": "^13.1.2", @@ -60,10 +62,13 @@ }, "devDependencies": { "@rollup/plugin-alias": "^6.0.0", + "@rollup/plugin-commonjs": "^29.0.0", + "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", "@types/lodash": "^4.17.21", "@types/md5": "^2.3.6", + "@types/readable-stream": "^4.0.23", "@types/secp256k1": "^4.0.7", "rimraf": "^6.1.2", "rollup": "^4.55.1", diff --git a/packages/utils/rollup.config.mts b/packages/utils/rollup.config.mts index b68619a3e1..ed7ba94871 100644 --- a/packages/utils/rollup.config.mts +++ b/packages/utils/rollup.config.mts @@ -2,6 +2,8 @@ import { defineConfig, type RollupOptions } from 'rollup' import { dts } from 'rollup-plugin-dts' import alias, { type Alias } from '@rollup/plugin-alias' import { nodeResolve } from '@rollup/plugin-node-resolve' +import cjs from '@rollup/plugin-commonjs' +import json from '@rollup/plugin-json' import { fileURLToPath } from 'node:url' const nodejsAliases: Alias[] = [ @@ -96,13 +98,20 @@ function browser(): RollupOptions { alias({ entries: browserAliases, }), + cjs(), + json(), nodeResolve({ browser: true, preferBuiltins: false, }), ], external: [ - /node_modules/, + /** + * We need to bundle some dependencies in. This will make sure we use the local `md5.js` + * and not the one shipped with `create-hash` (which is outdated and has issues with + * modern bundlers). + */ + /node_modules\/(?!browserify-aes|cipher-base|evp_bytestokey|md5.js|hash-base)/, /@streamr\//, ], } diff --git a/packages/utils/src/browser/crypto.ts b/packages/utils/src/browser/crypto.ts index 8fa85a7bc8..70559b3648 100644 --- a/packages/utils/src/browser/crypto.ts +++ b/packages/utils/src/browser/crypto.ts @@ -1,5 +1,11 @@ import md5 from 'md5' +import { + createCipheriv as createCipherivUtil, + createDecipheriv as createDecipherivUtil, +} from 'browserify-aes' +import aesModes from 'browserify-aes/modes' import { sha1 } from '@noble/hashes/legacy.js' +import type { Transform } from 'readable-stream' export function getSubtle(): SubtleCrypto { const { crypto } = globalThis @@ -26,3 +32,31 @@ export function computeSha1(input: string): Buffer { export type Jwk = JsonWebKey export type CryptoKey = globalThis.CryptoKey + +export function createCipheriv( + algorithm: string, + key: Buffer | Uint8Array, + iv: Buffer | Uint8Array | null +): Transform { + const suite = algorithm.toLowerCase() + + if (aesModes[suite]) { + return createCipherivUtil(suite, key, iv) + } + + throw new TypeError(`Invalid suite type. In browser only AES is supported but got ${algorithm}.`) +} + +export function createDecipheriv( + algorithm: string, + key: Buffer | Uint8Array, + iv: Buffer | Uint8Array | null +): Transform { + const suite = algorithm.toLowerCase() + + if (aesModes[suite]) { + return createDecipherivUtil(suite, key, iv) + } + + throw new TypeError(`Invalid suite type. In browser only AES is supported but got ${algorithm}.`) +} diff --git a/packages/utils/src/browserify-aes.d.ts b/packages/utils/src/browserify-aes.d.ts new file mode 100644 index 0000000000..47f6e60108 --- /dev/null +++ b/packages/utils/src/browserify-aes.d.ts @@ -0,0 +1,44 @@ +declare module 'browserify-aes' { + import type { Transform } from 'readable-stream' + + export interface CipherOptions { + iv?: Buffer | Uint8Array | null + authTagLength?: number + } + + export interface DecipherOptions { + iv?: Buffer | Uint8Array | null + authTagLength?: number + } + + export function createCipher( + algorithm: string, + password: string | Buffer + ): Transform + + export function createCipheriv( + algorithm: string, + key: Buffer | Uint8Array, + iv: Buffer | Uint8Array | null, + options?: CipherOptions + ): Transform + + export function createDecipher( + algorithm: string, + password: string | Buffer + ): Transform + + export function createDecipheriv( + algorithm: string, + key: Buffer | Uint8Array, + iv: Buffer | Uint8Array | null, + options?: DecipherOptions + ): Transform + + export function getCiphers(): string[] +} + +declare module 'browserify-aes/modes' { + const modes: Record + export default modes +} diff --git a/packages/utils/src/exports.ts b/packages/utils/src/exports.ts index 1cf9d85ddc..519581734d 100644 --- a/packages/utils/src/exports.ts +++ b/packages/utils/src/exports.ts @@ -53,6 +53,6 @@ export { type UserID, type UserIDRaw, toUserId, toUserIdRaw, isValidUserId, isEt export type { HexString } from './HexString' export type { ChangeFieldType, MapKey } from './types' export { type WeiAmount, multiplyWeiAmount } from './WeiAmount' -export { getSubtle, computeMd5, computeSha1 } from '@/crypto' +export { getSubtle, computeMd5, computeSha1, createCipheriv, createDecipheriv } from '@/crypto' export { SigningUtil, EcdsaSecp256k1Evm, EcdsaSecp256r1, MlDsa87, type KeyType, KEY_TYPES } from './SigningUtil' export { randomBytes } from '@noble/post-quantum/utils' diff --git a/packages/utils/src/nodejs/crypto.ts b/packages/utils/src/nodejs/crypto.ts index 72c5e5938c..cfeb7c8573 100644 --- a/packages/utils/src/nodejs/crypto.ts +++ b/packages/utils/src/nodejs/crypto.ts @@ -25,3 +25,19 @@ export function computeMd5(input: string): Buffer { export function computeSha1(input: string): Buffer { return crypto.createHash('sha1').update(input).digest() } + +export function createCipheriv( + algorithm: string, + key: Buffer | Uint8Array, + iv: Buffer | Uint8Array | null +): crypto.Cipheriv { + return crypto.createCipheriv(algorithm, key, iv) +} + +export function createDecipheriv( + algorithm: string, + key: Buffer | Uint8Array, + iv: Buffer | Uint8Array | null +): crypto.Decipheriv { + return crypto.createDecipheriv(algorithm, key, iv) +} From 8284f4fdcc449ce754d4462f92651657e421fc55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Fri, 9 Jan 2026 14:51:26 +0100 Subject: [PATCH 14/18] release: v103.2.0-experiment.0 --- packages/autocertifier-client/package.json | 4 ++-- packages/autocertifier-server/package.json | 10 +++++----- packages/cdn-location/package.json | 4 ++-- packages/cli-tools/package.json | 12 ++++++------ packages/dht/package.json | 14 +++++++------- packages/geoip-location/package.json | 4 ++-- packages/node/package.json | 10 +++++----- packages/proto-rpc/package.json | 6 +++--- packages/sdk/package.json | 12 ++++++------ packages/test-utils/package.json | 4 ++-- packages/trackerless-network/package.json | 10 +++++----- packages/utils/package.json | 2 +- 12 files changed, 46 insertions(+), 46 deletions(-) diff --git a/packages/autocertifier-client/package.json b/packages/autocertifier-client/package.json index b79c057f45..c016a9fe6a 100644 --- a/packages/autocertifier-client/package.json +++ b/packages/autocertifier-client/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/autocertifier-client", - "version": "103.2.0", + "version": "103.2.0-experiment.0", "description": "Autocertifier Client for Streamr Network", "repository": { "type": "git", @@ -41,7 +41,7 @@ }, "dependencies": { "@protobuf-ts/runtime-rpc": "^2.8.2", - "@streamr/utils": "103.2.0", + "@streamr/utils": "103.2.0-experiment.0", "eventemitter3": "^5.0.0", "node-forge": "^1.3.2" }, diff --git a/packages/autocertifier-server/package.json b/packages/autocertifier-server/package.json index 85079ac178..4e0e899598 100644 --- a/packages/autocertifier-server/package.json +++ b/packages/autocertifier-server/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/autocertifier-server", - "version": "103.2.0", + "version": "103.2.0-experiment.0", "description": "Server for providing TLS Certificates", "repository": { "type": "git", @@ -34,10 +34,10 @@ }, "dependencies": { "@aws-sdk/client-route-53": "^3.936.0", - "@streamr/autocertifier-client": "103.2.0", - "@streamr/dht": "103.2.0", - "@streamr/proto-rpc": "103.2.0", - "@streamr/utils": "103.2.0", + "@streamr/autocertifier-client": "103.2.0-experiment.0", + "@streamr/dht": "103.2.0-experiment.0", + "@streamr/proto-rpc": "103.2.0-experiment.0", + "@streamr/utils": "103.2.0-experiment.0", "acme-client": "^5.4.0", "body-parser": "^2.2.1", "dns2": "^2.1.0", diff --git a/packages/cdn-location/package.json b/packages/cdn-location/package.json index 1e742e5e43..f9dc0cb869 100644 --- a/packages/cdn-location/package.json +++ b/packages/cdn-location/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/cdn-location", - "version": "103.2.0", + "version": "103.2.0-experiment.0", "description": "Library for getting own approximate location by querying CDN servers", "repository": { "type": "git", @@ -32,7 +32,7 @@ "generate-data-from-tsp-solution": "./data-generation/generateDataFromTSPSolverResult.sh" }, "dependencies": { - "@streamr/utils": "103.2.0", + "@streamr/utils": "103.2.0-experiment.0", "haversine": "^1.1.1" }, "devDependencies": { diff --git a/packages/cli-tools/package.json b/packages/cli-tools/package.json index 68407cecff..37339d2ead 100644 --- a/packages/cli-tools/package.json +++ b/packages/cli-tools/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/cli-tools", - "version": "103.2.0", + "version": "103.2.0-experiment.0", "description": "Command line tools for Streamr", "repository": { "type": "git", @@ -33,11 +33,11 @@ "license": "AGPL-3.0", "dependencies": { "@streamr/config": "^5.9.2", - "@streamr/dht": "103.2.0", + "@streamr/dht": "103.2.0-experiment.0", "@streamr/network-contracts": "^9.1.0", - "@streamr/sdk": "103.2.0", - "@streamr/trackerless-network": "103.2.0", - "@streamr/utils": "103.2.0", + "@streamr/sdk": "103.2.0-experiment.0", + "@streamr/trackerless-network": "103.2.0-experiment.0", + "@streamr/utils": "103.2.0-experiment.0", "commander": "^14.0.2", "easy-table": "^1.1.1", "ethers": "^6.13.0", @@ -46,7 +46,7 @@ "semver": "^7.7.3" }, "devDependencies": { - "@streamr/test-utils": "103.2.0", + "@streamr/test-utils": "103.2.0-experiment.0", "@types/event-stream": "^4.0.6", "@types/lodash": "^4.17.21", "@types/merge2": "^1.4.4", diff --git a/packages/dht/package.json b/packages/dht/package.json index f4292396b8..1af4e78ff3 100644 --- a/packages/dht/package.json +++ b/packages/dht/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/dht", - "version": "103.2.0", + "version": "103.2.0-experiment.0", "description": "Streamr Network DHT", "repository": { "type": "git", @@ -50,11 +50,11 @@ "@js-sdsl/ordered-map": "^4.4.2", "@protobuf-ts/runtime": "^2.8.2", "@protobuf-ts/runtime-rpc": "^2.8.2", - "@streamr/autocertifier-client": "103.2.0", - "@streamr/cdn-location": "103.2.0", - "@streamr/geoip-location": "103.2.0", - "@streamr/proto-rpc": "103.2.0", - "@streamr/utils": "103.2.0", + "@streamr/autocertifier-client": "103.2.0-experiment.0", + "@streamr/cdn-location": "103.2.0-experiment.0", + "@streamr/geoip-location": "103.2.0-experiment.0", + "@streamr/proto-rpc": "103.2.0-experiment.0", + "@streamr/utils": "103.2.0-experiment.0", "eventemitter3": "^5.0.0", "heap": "^0.2.6", "ipaddr.js": "^2.0.1", @@ -71,7 +71,7 @@ "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", - "@streamr/test-utils": "103.2.0", + "@streamr/test-utils": "103.2.0-experiment.0", "@types/heap": "^0.2.35", "@types/k-bucket": "^5.0.1", "@types/lodash": "^4.17.21", diff --git a/packages/geoip-location/package.json b/packages/geoip-location/package.json index 45dc348dd1..32b197bf56 100644 --- a/packages/geoip-location/package.json +++ b/packages/geoip-location/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/geoip-location", - "version": "103.2.0", + "version": "103.2.0-experiment.0", "description": "Library for getting location information from IP addresses based on MaxMind GeoLite2 databases", "repository": { "type": "git", @@ -33,7 +33,7 @@ "test-unit": "jest test/unit" }, "dependencies": { - "@streamr/utils": "103.2.0", + "@streamr/utils": "103.2.0-experiment.0", "eventemitter3": "^5.0.0", "long-timeout": "^0.1.1", "mmdb-lib": "^3.0.1", diff --git a/packages/node/package.json b/packages/node/package.json index 9a3446a227..9b5cb1ecf7 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/node", - "version": "103.2.0", + "version": "103.2.0-experiment.0", "description": "A full-featured node implementation for the Streamr Network", "repository": { "type": "git", @@ -39,9 +39,9 @@ "dependencies": { "@inquirer/prompts": "^7.9.0", "@streamr/config": "^5.9.2", - "@streamr/dht": "103.2.0", - "@streamr/sdk": "103.2.0", - "@streamr/utils": "103.2.0", + "@streamr/dht": "103.2.0-experiment.0", + "@streamr/sdk": "103.2.0-experiment.0", + "@streamr/utils": "103.2.0-experiment.0", "aedes": "^0.51.3", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", @@ -65,7 +65,7 @@ "devDependencies": { "@inquirer/testing": "^2.1.51", "@streamr/network-contracts": "^9.1.0", - "@streamr/test-utils": "103.2.0", + "@streamr/test-utils": "103.2.0-experiment.0", "@types/cors": "^2.8.19", "@types/express": "^5.0.1", "@types/heap": "^0.2.35", diff --git a/packages/proto-rpc/package.json b/packages/proto-rpc/package.json index 97f7ce64d9..ce4e2eb2c3 100644 --- a/packages/proto-rpc/package.json +++ b/packages/proto-rpc/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/proto-rpc", - "version": "103.2.0", + "version": "103.2.0-experiment.0", "description": "Proto-RPC", "repository": { "type": "git", @@ -34,7 +34,7 @@ "dependencies": { "@protobuf-ts/runtime": "^2.8.2", "@protobuf-ts/runtime-rpc": "^2.8.2", - "@streamr/utils": "103.2.0", + "@streamr/utils": "103.2.0-experiment.0", "eventemitter3": "^5.0.0", "lodash": "^4.17.21", "uuid": "^11.1.0" @@ -42,7 +42,7 @@ "devDependencies": { "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", - "@streamr/test-utils": "103.2.0", + "@streamr/test-utils": "103.2.0-experiment.0", "@types/lodash": "^4.17.21", "rimraf": "^6.1.2", "rollup": "^4.55.1", diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 79a1bce3bd..737b3f98ea 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/sdk", - "version": "103.2.0", + "version": "103.2.0-experiment.0", "description": "JavaScript / TypeScript SDK for Streamr", "repository": { "type": "git", @@ -60,7 +60,7 @@ "@babel/preset-env": "^7.28.5", "@babel/preset-typescript": "^7.28.5", "@jest/globals": "^30.0.5", - "@streamr/test-utils": "103.2.0", + "@streamr/test-utils": "103.2.0-experiment.0", "@types/heap": "^0.2.35", "@types/lodash": "^4.17.21", "ajv": "^8.17.1", @@ -98,11 +98,11 @@ "@protobuf-ts/runtime": "^2.8.2", "@protobuf-ts/runtime-rpc": "^2.8.2", "@streamr/config": "^5.9.2", - "@streamr/dht": "103.2.0", + "@streamr/dht": "103.2.0-experiment.0", "@streamr/network-contracts": "^9.1.0", - "@streamr/proto-rpc": "103.2.0", - "@streamr/trackerless-network": "103.2.0", - "@streamr/utils": "103.2.0", + "@streamr/proto-rpc": "103.2.0-experiment.0", + "@streamr/trackerless-network": "103.2.0-experiment.0", + "@streamr/utils": "103.2.0-experiment.0", "core-js": "^3.47.0", "env-paths": "^2.2.1", "ethers": "^6.13.0", diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 4ca64a5f90..7015228bad 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/test-utils", - "version": "103.2.0", + "version": "103.2.0-experiment.0", "description": "A collection of shared test utilities", "repository": { "type": "git", @@ -62,7 +62,7 @@ "dependencies": { "@streamr/config": "^5.9.2", "@streamr/network-contracts": "^9.1.0", - "@streamr/utils": "103.2.0", + "@streamr/utils": "103.2.0-experiment.0", "cors": "^2.8.5", "ethers": "^6.13.0", "express": "^5.2.0", diff --git a/packages/trackerless-network/package.json b/packages/trackerless-network/package.json index bb7642e465..ded51c75f5 100644 --- a/packages/trackerless-network/package.json +++ b/packages/trackerless-network/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/trackerless-network", - "version": "103.2.0", + "version": "103.2.0-experiment.0", "description": "Minimal and extendable implementation of the Streamr Network node.", "repository": { "type": "git", @@ -37,9 +37,9 @@ "dependencies": { "@protobuf-ts/runtime": "^2.8.2", "@protobuf-ts/runtime-rpc": "^2.8.2", - "@streamr/dht": "103.2.0", - "@streamr/proto-rpc": "103.2.0", - "@streamr/utils": "103.2.0", + "@streamr/dht": "103.2.0-experiment.0", + "@streamr/proto-rpc": "103.2.0-experiment.0", + "@streamr/utils": "103.2.0-experiment.0", "eventemitter3": "^5.0.0", "lodash": "^4.17.21", "ts-essentials": "^10.1.1", @@ -50,7 +50,7 @@ "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", - "@streamr/test-utils": "103.2.0", + "@streamr/test-utils": "103.2.0-experiment.0", "@types/lodash": "^4.17.21", "@types/yallist": "^5.0.0", "expect": "^30.0.5", diff --git a/packages/utils/package.json b/packages/utils/package.json index 3694aa2b9e..df6aba825a 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/utils", - "version": "103.2.0", + "version": "103.2.0-experiment.0", "description": "A collection of shared common utilities", "repository": { "type": "git", From f26a940f7f1f11707465348f4714dc02494caafc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Mon, 12 Jan 2026 13:25:31 +0100 Subject: [PATCH 15/18] refactor: Address feedback on bundles + minor tweaks (#3343) This pull request primarily refactors the naming and usage of the default AutoCertifier client factory functions for clarity and consistency, and makes a minor cryptographic utility update. The most important changes are grouped below. ### Refactoring and Consistency Improvements * Renamed `defaultAutoCertifierClientFactory` to `createDefaultAutocertifierClient` in both `browser` and `nodejs` implementations, and updated all imports and usages accordingly for clarity and consistency. [[1]](diffhunk://#diff-acea4cfec95dcee32462af3b41a61f06b65b43b29d9aec7fba9af92b75afc309L4-R4) [[2]](diffhunk://#diff-3564c07adda6cca35da167730df18b4a93073619cad8b132a840fa129c2924f5L9-R9) [[3]](diffhunk://#diff-05c4f4f30929641c70e23ccb069dfaa5bd450bab1643a0f91fadaea4be72dddaL8-R8) [[4]](diffhunk://#diff-05c4f4f30929641c70e23ccb069dfaa5bd450bab1643a0f91fadaea4be72dddaL43-R43) ### Utility and Cryptography Updates * Updated the `computeSha1` function in `crypto.ts` to use `utf8ToBinary` for string-to-binary conversion, improving encoding reliability. Also imported `utf8ToBinary` from `src/binaryUtils`. [[1]](diffhunk://#diff-285b8e8fa583afc20697242820c6adb2419720d1c2056c6ecb7d8617060c1a51R9) [[2]](diffhunk://#diff-285b8e8fa583afc20697242820c6adb2419720d1c2056c6ecb7d8617060c1a51L29-R30) --- ...erClientFactory.ts => createDefaultAutocertifierClient.ts} | 2 +- .../dht/src/connection/websocket/AutoCertifierClientFacade.ts | 4 ++-- ...erClientFactory.ts => createDefaultAutocertifierClient.ts} | 2 +- packages/utils/src/browser/crypto.ts | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) rename packages/dht/src/browser/{defaultAutoCertifierClientFactory.ts => createDefaultAutocertifierClient.ts} (89%) rename packages/dht/src/nodejs/{defaultAutoCertifierClientFactory.ts => createDefaultAutocertifierClient.ts} (93%) diff --git a/packages/dht/src/browser/defaultAutoCertifierClientFactory.ts b/packages/dht/src/browser/createDefaultAutocertifierClient.ts similarity index 89% rename from packages/dht/src/browser/defaultAutoCertifierClientFactory.ts rename to packages/dht/src/browser/createDefaultAutocertifierClient.ts index aae07665f8..c35a20c620 100644 --- a/packages/dht/src/browser/defaultAutoCertifierClientFactory.ts +++ b/packages/dht/src/browser/createDefaultAutocertifierClient.ts @@ -1,7 +1,7 @@ import type { AutoCertifierClient } from '@streamr/autocertifier-client' import { ListeningRpcCommunicator } from '../transport/ListeningRpcCommunicator' -export const defaultAutoCertifierClientFactory = ( +export const createDefaultAutocertifierClient = ( _configFile: string, _autoCertifierUrl: string, _autoCertifierRpcCommunicator: ListeningRpcCommunicator, diff --git a/packages/dht/src/connection/websocket/AutoCertifierClientFacade.ts b/packages/dht/src/connection/websocket/AutoCertifierClientFacade.ts index 28c0442f0e..92851181da 100644 --- a/packages/dht/src/connection/websocket/AutoCertifierClientFacade.ts +++ b/packages/dht/src/connection/websocket/AutoCertifierClientFacade.ts @@ -5,7 +5,7 @@ import { import { ListeningRpcCommunicator } from '../../transport/ListeningRpcCommunicator' import { Logger, waitForEvent } from '@streamr/utils' import { ITransport } from '../../transport/ITransport' -import { defaultAutoCertifierClientFactory } from '@/defaultAutoCertifierClientFactory' +import { createDefaultAutocertifierClient } from '@/createDefaultAutocertifierClient' const START_TIMEOUT = 60 * 1000 @@ -40,7 +40,7 @@ export class AutoCertifierClientFacade { this.options = options this.rpcCommunicator = new ListeningRpcCommunicator(AUTO_CERTIFIER_SERVICE_ID, options.transport) this.autoCertifierClient = options.createClientFactory ? options.createClientFactory() - : defaultAutoCertifierClientFactory( + : createDefaultAutocertifierClient( options.configFile, options.url, this.rpcCommunicator, diff --git a/packages/dht/src/nodejs/defaultAutoCertifierClientFactory.ts b/packages/dht/src/nodejs/createDefaultAutocertifierClient.ts similarity index 93% rename from packages/dht/src/nodejs/defaultAutoCertifierClientFactory.ts rename to packages/dht/src/nodejs/createDefaultAutocertifierClient.ts index 50367d8c20..70c600f3cd 100644 --- a/packages/dht/src/nodejs/defaultAutoCertifierClientFactory.ts +++ b/packages/dht/src/nodejs/createDefaultAutocertifierClient.ts @@ -6,7 +6,7 @@ import { } from '@streamr/autocertifier-client' import { ListeningRpcCommunicator } from '../transport/ListeningRpcCommunicator' -export const defaultAutoCertifierClientFactory = ( +export const createDefaultAutocertifierClient = ( configFile: string, autoCertifierUrl: string, autoCertifierRpcCommunicator: ListeningRpcCommunicator, diff --git a/packages/utils/src/browser/crypto.ts b/packages/utils/src/browser/crypto.ts index 70559b3648..de13cf1715 100644 --- a/packages/utils/src/browser/crypto.ts +++ b/packages/utils/src/browser/crypto.ts @@ -6,6 +6,7 @@ import { import aesModes from 'browserify-aes/modes' import { sha1 } from '@noble/hashes/legacy.js' import type { Transform } from 'readable-stream' +import { utf8ToBinary } from '../binaryUtils' export function getSubtle(): SubtleCrypto { const { crypto } = globalThis @@ -26,7 +27,7 @@ export function computeMd5(input: string): Buffer { } export function computeSha1(input: string): Buffer { - return Buffer.from(sha1(new TextEncoder().encode(input))) + return Buffer.from(sha1(utf8ToBinary(input))) } export type Jwk = JsonWebKey From ba0a07762382f2755b0aef798e0aba2dc1789832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Mon, 12 Jan 2026 15:11:03 +0100 Subject: [PATCH 16/18] refactor: Explicit `node` exports for jest (mainly) (#3344) This pull request updates the `exports` fields in several `package.json` files to explicitly add a `"node"` export condition for Node.js-specific builds. This improves compatibility and clarity when these packages are imported in different environments, ensuring that the correct entry points are used for Node.js. **Package export improvements:** * Added a `"node"` export condition pointing to the Node.js CommonJS build in `packages/autocertifier-client/package.json`, `packages/dht/package.json`, and `packages/utils/package.json` to clarify and standardize Node.js entry points. [[1]](diffhunk://#diff-ce36aa2971623458d0b35543ec3caf4e8df12445e570d4c599e3142a79b87de5R21) [[2]](diffhunk://#diff-48deceddbbe98a41ff1d0f560db132548031fbd96d790c09ffeed924a20e8a05R21) [[3]](diffhunk://#diff-21f8eb1d7a149d42ab0454ea905d44f624ff1d0aeb6d7a88d75b42962ca6b053R21-R24) * Updated `packages/test-utils/package.json` to add `"node"` export conditions for the main entry and sub-exports (`./setupCustomMatchers`, `./customMatchers`), ensuring correct resolution in Node.js environments. --- packages/autocertifier-client/package.json | 1 + packages/dht/package.json | 1 + packages/test-utils/package.json | 3 +++ packages/utils/package.json | 7 +++++-- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/autocertifier-client/package.json b/packages/autocertifier-client/package.json index c016a9fe6a..9c09b8289b 100644 --- a/packages/autocertifier-client/package.json +++ b/packages/autocertifier-client/package.json @@ -18,6 +18,7 @@ "import": "./dist/exports-browser.js", "require": "./dist/exports-browser.cjs" }, + "node": "./dist/exports-nodejs.cjs", "import": "./dist/exports-nodejs.js", "require": "./dist/exports-nodejs.cjs", "default": "./dist/exports-nodejs.js" diff --git a/packages/dht/package.json b/packages/dht/package.json index 1af4e78ff3..0aedb4c7fe 100644 --- a/packages/dht/package.json +++ b/packages/dht/package.json @@ -18,6 +18,7 @@ "import": "./dist/exports-browser.js", "require": "./dist/exports-browser.cjs" }, + "node": "./dist/exports-nodejs.cjs", "import": "./dist/exports-nodejs.js", "require": "./dist/exports-nodejs.cjs", "default": "./dist/exports-nodejs.js" diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 7015228bad..8a5abcdb36 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -13,18 +13,21 @@ "exports": { ".": { "types": "./dist/index.d.ts", + "node": "./dist/index.cjs", "import": "./dist/index.js", "require": "./dist/index.cjs", "default": "./dist/index.js" }, "./setupCustomMatchers": { "types": "./dist/setupCustomMatchers.d.ts", + "node": "./dist/setupCustomMatchers.cjs", "import": "./dist/setupCustomMatchers.js", "require": "./dist/setupCustomMatchers.cjs", "default": "./dist/setupCustomMatchers.js" }, "./customMatchers": { "types": "./dist/customMatchers.d.ts", + "node": "./dist/customMatchers.cjs", "import": "./dist/customMatchers.js", "require": "./dist/customMatchers.cjs", "default": "./dist/customMatchers.js" diff --git a/packages/utils/package.json b/packages/utils/package.json index df6aba825a..247391e0ac 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -16,10 +16,13 @@ "browser": { "types": "./dist/exports-browser.d.ts", "import": "./dist/exports-browser.js", - "require": "./dist/exports-browser.cjs" + "require": "./dist/exports-browser.cjs", + "default": "./dist/exports-browser.js" }, + "node": "./dist/exports-nodejs.cjs", "import": "./dist/exports-nodejs.js", - "require": "./dist/exports-nodejs.cjs" + "require": "./dist/exports-nodejs.cjs", + "default": "./dist/exports-nodejs.js" } }, "files": [ From 16f565a0c366aaa8d92ce93f2d8c8197ed55c569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Mon, 12 Jan 2026 15:14:59 +0100 Subject: [PATCH 17/18] Make experiments releasable via gh --- .github/workflows/publish-npm.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 71376637a2..9c86cb8b04 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -14,6 +14,7 @@ on: - alpha - internal - testnet-three + - experiment jobs: publish: runs-on: ubuntu-latest From ca89cf856649ee3151f24d9ff7ce7e67d394ae98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Roli=C5=84ski?= Date: Mon, 12 Jan 2026 15:13:06 +0100 Subject: [PATCH 18/18] release: v103.2.0-experiment.1 --- packages/autocertifier-client/package.json | 4 ++-- packages/autocertifier-server/package.json | 10 +++++----- packages/cdn-location/package.json | 4 ++-- packages/cli-tools/package.json | 12 ++++++------ packages/dht/package.json | 14 +++++++------- packages/geoip-location/package.json | 4 ++-- packages/node/package.json | 10 +++++----- packages/proto-rpc/package.json | 6 +++--- packages/sdk/package.json | 12 ++++++------ packages/test-utils/package.json | 4 ++-- packages/trackerless-network/package.json | 10 +++++----- packages/utils/package.json | 2 +- 12 files changed, 46 insertions(+), 46 deletions(-) diff --git a/packages/autocertifier-client/package.json b/packages/autocertifier-client/package.json index 9c09b8289b..eecca476aa 100644 --- a/packages/autocertifier-client/package.json +++ b/packages/autocertifier-client/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/autocertifier-client", - "version": "103.2.0-experiment.0", + "version": "103.2.0-experiment.1", "description": "Autocertifier Client for Streamr Network", "repository": { "type": "git", @@ -42,7 +42,7 @@ }, "dependencies": { "@protobuf-ts/runtime-rpc": "^2.8.2", - "@streamr/utils": "103.2.0-experiment.0", + "@streamr/utils": "103.2.0-experiment.1", "eventemitter3": "^5.0.0", "node-forge": "^1.3.2" }, diff --git a/packages/autocertifier-server/package.json b/packages/autocertifier-server/package.json index 4e0e899598..afbc24fe84 100644 --- a/packages/autocertifier-server/package.json +++ b/packages/autocertifier-server/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/autocertifier-server", - "version": "103.2.0-experiment.0", + "version": "103.2.0-experiment.1", "description": "Server for providing TLS Certificates", "repository": { "type": "git", @@ -34,10 +34,10 @@ }, "dependencies": { "@aws-sdk/client-route-53": "^3.936.0", - "@streamr/autocertifier-client": "103.2.0-experiment.0", - "@streamr/dht": "103.2.0-experiment.0", - "@streamr/proto-rpc": "103.2.0-experiment.0", - "@streamr/utils": "103.2.0-experiment.0", + "@streamr/autocertifier-client": "103.2.0-experiment.1", + "@streamr/dht": "103.2.0-experiment.1", + "@streamr/proto-rpc": "103.2.0-experiment.1", + "@streamr/utils": "103.2.0-experiment.1", "acme-client": "^5.4.0", "body-parser": "^2.2.1", "dns2": "^2.1.0", diff --git a/packages/cdn-location/package.json b/packages/cdn-location/package.json index f9dc0cb869..bef3ad37eb 100644 --- a/packages/cdn-location/package.json +++ b/packages/cdn-location/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/cdn-location", - "version": "103.2.0-experiment.0", + "version": "103.2.0-experiment.1", "description": "Library for getting own approximate location by querying CDN servers", "repository": { "type": "git", @@ -32,7 +32,7 @@ "generate-data-from-tsp-solution": "./data-generation/generateDataFromTSPSolverResult.sh" }, "dependencies": { - "@streamr/utils": "103.2.0-experiment.0", + "@streamr/utils": "103.2.0-experiment.1", "haversine": "^1.1.1" }, "devDependencies": { diff --git a/packages/cli-tools/package.json b/packages/cli-tools/package.json index 37339d2ead..e7a798bb5c 100644 --- a/packages/cli-tools/package.json +++ b/packages/cli-tools/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/cli-tools", - "version": "103.2.0-experiment.0", + "version": "103.2.0-experiment.1", "description": "Command line tools for Streamr", "repository": { "type": "git", @@ -33,11 +33,11 @@ "license": "AGPL-3.0", "dependencies": { "@streamr/config": "^5.9.2", - "@streamr/dht": "103.2.0-experiment.0", + "@streamr/dht": "103.2.0-experiment.1", "@streamr/network-contracts": "^9.1.0", - "@streamr/sdk": "103.2.0-experiment.0", - "@streamr/trackerless-network": "103.2.0-experiment.0", - "@streamr/utils": "103.2.0-experiment.0", + "@streamr/sdk": "103.2.0-experiment.1", + "@streamr/trackerless-network": "103.2.0-experiment.1", + "@streamr/utils": "103.2.0-experiment.1", "commander": "^14.0.2", "easy-table": "^1.1.1", "ethers": "^6.13.0", @@ -46,7 +46,7 @@ "semver": "^7.7.3" }, "devDependencies": { - "@streamr/test-utils": "103.2.0-experiment.0", + "@streamr/test-utils": "103.2.0-experiment.1", "@types/event-stream": "^4.0.6", "@types/lodash": "^4.17.21", "@types/merge2": "^1.4.4", diff --git a/packages/dht/package.json b/packages/dht/package.json index 0aedb4c7fe..1abf88468a 100644 --- a/packages/dht/package.json +++ b/packages/dht/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/dht", - "version": "103.2.0-experiment.0", + "version": "103.2.0-experiment.1", "description": "Streamr Network DHT", "repository": { "type": "git", @@ -51,11 +51,11 @@ "@js-sdsl/ordered-map": "^4.4.2", "@protobuf-ts/runtime": "^2.8.2", "@protobuf-ts/runtime-rpc": "^2.8.2", - "@streamr/autocertifier-client": "103.2.0-experiment.0", - "@streamr/cdn-location": "103.2.0-experiment.0", - "@streamr/geoip-location": "103.2.0-experiment.0", - "@streamr/proto-rpc": "103.2.0-experiment.0", - "@streamr/utils": "103.2.0-experiment.0", + "@streamr/autocertifier-client": "103.2.0-experiment.1", + "@streamr/cdn-location": "103.2.0-experiment.1", + "@streamr/geoip-location": "103.2.0-experiment.1", + "@streamr/proto-rpc": "103.2.0-experiment.1", + "@streamr/utils": "103.2.0-experiment.1", "eventemitter3": "^5.0.0", "heap": "^0.2.6", "ipaddr.js": "^2.0.1", @@ -72,7 +72,7 @@ "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", - "@streamr/test-utils": "103.2.0-experiment.0", + "@streamr/test-utils": "103.2.0-experiment.1", "@types/heap": "^0.2.35", "@types/k-bucket": "^5.0.1", "@types/lodash": "^4.17.21", diff --git a/packages/geoip-location/package.json b/packages/geoip-location/package.json index 32b197bf56..38b7c3ceab 100644 --- a/packages/geoip-location/package.json +++ b/packages/geoip-location/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/geoip-location", - "version": "103.2.0-experiment.0", + "version": "103.2.0-experiment.1", "description": "Library for getting location information from IP addresses based on MaxMind GeoLite2 databases", "repository": { "type": "git", @@ -33,7 +33,7 @@ "test-unit": "jest test/unit" }, "dependencies": { - "@streamr/utils": "103.2.0-experiment.0", + "@streamr/utils": "103.2.0-experiment.1", "eventemitter3": "^5.0.0", "long-timeout": "^0.1.1", "mmdb-lib": "^3.0.1", diff --git a/packages/node/package.json b/packages/node/package.json index 9b5cb1ecf7..6afef75b8c 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/node", - "version": "103.2.0-experiment.0", + "version": "103.2.0-experiment.1", "description": "A full-featured node implementation for the Streamr Network", "repository": { "type": "git", @@ -39,9 +39,9 @@ "dependencies": { "@inquirer/prompts": "^7.9.0", "@streamr/config": "^5.9.2", - "@streamr/dht": "103.2.0-experiment.0", - "@streamr/sdk": "103.2.0-experiment.0", - "@streamr/utils": "103.2.0-experiment.0", + "@streamr/dht": "103.2.0-experiment.1", + "@streamr/sdk": "103.2.0-experiment.1", + "@streamr/utils": "103.2.0-experiment.1", "aedes": "^0.51.3", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", @@ -65,7 +65,7 @@ "devDependencies": { "@inquirer/testing": "^2.1.51", "@streamr/network-contracts": "^9.1.0", - "@streamr/test-utils": "103.2.0-experiment.0", + "@streamr/test-utils": "103.2.0-experiment.1", "@types/cors": "^2.8.19", "@types/express": "^5.0.1", "@types/heap": "^0.2.35", diff --git a/packages/proto-rpc/package.json b/packages/proto-rpc/package.json index ce4e2eb2c3..7adf4b94b0 100644 --- a/packages/proto-rpc/package.json +++ b/packages/proto-rpc/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/proto-rpc", - "version": "103.2.0-experiment.0", + "version": "103.2.0-experiment.1", "description": "Proto-RPC", "repository": { "type": "git", @@ -34,7 +34,7 @@ "dependencies": { "@protobuf-ts/runtime": "^2.8.2", "@protobuf-ts/runtime-rpc": "^2.8.2", - "@streamr/utils": "103.2.0-experiment.0", + "@streamr/utils": "103.2.0-experiment.1", "eventemitter3": "^5.0.0", "lodash": "^4.17.21", "uuid": "^11.1.0" @@ -42,7 +42,7 @@ "devDependencies": { "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", - "@streamr/test-utils": "103.2.0-experiment.0", + "@streamr/test-utils": "103.2.0-experiment.1", "@types/lodash": "^4.17.21", "rimraf": "^6.1.2", "rollup": "^4.55.1", diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 737b3f98ea..3d76cac685 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/sdk", - "version": "103.2.0-experiment.0", + "version": "103.2.0-experiment.1", "description": "JavaScript / TypeScript SDK for Streamr", "repository": { "type": "git", @@ -60,7 +60,7 @@ "@babel/preset-env": "^7.28.5", "@babel/preset-typescript": "^7.28.5", "@jest/globals": "^30.0.5", - "@streamr/test-utils": "103.2.0-experiment.0", + "@streamr/test-utils": "103.2.0-experiment.1", "@types/heap": "^0.2.35", "@types/lodash": "^4.17.21", "ajv": "^8.17.1", @@ -98,11 +98,11 @@ "@protobuf-ts/runtime": "^2.8.2", "@protobuf-ts/runtime-rpc": "^2.8.2", "@streamr/config": "^5.9.2", - "@streamr/dht": "103.2.0-experiment.0", + "@streamr/dht": "103.2.0-experiment.1", "@streamr/network-contracts": "^9.1.0", - "@streamr/proto-rpc": "103.2.0-experiment.0", - "@streamr/trackerless-network": "103.2.0-experiment.0", - "@streamr/utils": "103.2.0-experiment.0", + "@streamr/proto-rpc": "103.2.0-experiment.1", + "@streamr/trackerless-network": "103.2.0-experiment.1", + "@streamr/utils": "103.2.0-experiment.1", "core-js": "^3.47.0", "env-paths": "^2.2.1", "ethers": "^6.13.0", diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 8a5abcdb36..53f0ba2e50 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/test-utils", - "version": "103.2.0-experiment.0", + "version": "103.2.0-experiment.1", "description": "A collection of shared test utilities", "repository": { "type": "git", @@ -65,7 +65,7 @@ "dependencies": { "@streamr/config": "^5.9.2", "@streamr/network-contracts": "^9.1.0", - "@streamr/utils": "103.2.0-experiment.0", + "@streamr/utils": "103.2.0-experiment.1", "cors": "^2.8.5", "ethers": "^6.13.0", "express": "^5.2.0", diff --git a/packages/trackerless-network/package.json b/packages/trackerless-network/package.json index ded51c75f5..8dabcd40b1 100644 --- a/packages/trackerless-network/package.json +++ b/packages/trackerless-network/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/trackerless-network", - "version": "103.2.0-experiment.0", + "version": "103.2.0-experiment.1", "description": "Minimal and extendable implementation of the Streamr Network node.", "repository": { "type": "git", @@ -37,9 +37,9 @@ "dependencies": { "@protobuf-ts/runtime": "^2.8.2", "@protobuf-ts/runtime-rpc": "^2.8.2", - "@streamr/dht": "103.2.0-experiment.0", - "@streamr/proto-rpc": "103.2.0-experiment.0", - "@streamr/utils": "103.2.0-experiment.0", + "@streamr/dht": "103.2.0-experiment.1", + "@streamr/proto-rpc": "103.2.0-experiment.1", + "@streamr/utils": "103.2.0-experiment.1", "eventemitter3": "^5.0.0", "lodash": "^4.17.21", "ts-essentials": "^10.1.1", @@ -50,7 +50,7 @@ "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.3", "@streamr/browser-test-runner": "^0.0.1", - "@streamr/test-utils": "103.2.0-experiment.0", + "@streamr/test-utils": "103.2.0-experiment.1", "@types/lodash": "^4.17.21", "@types/yallist": "^5.0.0", "expect": "^30.0.5", diff --git a/packages/utils/package.json b/packages/utils/package.json index 247391e0ac..ac268963aa 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@streamr/utils", - "version": "103.2.0-experiment.0", + "version": "103.2.0-experiment.1", "description": "A collection of shared common utilities", "repository": { "type": "git",