From deaf1bc8e19ee3eebf1c915ce91e9195308cf7dc Mon Sep 17 00:00:00 2001 From: JY Tan Date: Thu, 19 Feb 2026 18:58:41 -0800 Subject: [PATCH 01/15] Commit --- .github/workflows/e2e.yml | 1 + .gitignore | 2 + docs/rust-core-bindings.md | 62 + package-lock.json | 1191 ++++++++--------- package.json | 1 + src/core/rustCoreBinding.ts | 225 ++++ src/core/tracing/SpanTransformer.ts | 76 +- src/core/tracing/adapters/ApiSpanAdapter.ts | 46 +- src/core/types.ts | 1 + .../fetch/e2e-tests/cjs-fetch/run.sh | 2 +- .../fetch/e2e-tests/esm-fetch/run.sh | 2 +- .../firestore/e2e-tests/cjs-firestore/run.sh | 2 +- .../firestore/e2e-tests/esm-firestore/run.sh | 2 +- .../libraries/grpc/e2e-tests/cjs-grpc/run.sh | 2 +- .../libraries/grpc/e2e-tests/esm-grpc/run.sh | 2 +- .../libraries/http/e2e-tests/cjs-http/run.sh | 2 +- .../libraries/http/e2e-tests/esm-http/run.sh | 2 +- .../ioredis/e2e-tests/cjs-ioredis/run.sh | 2 +- .../ioredis/e2e-tests/esm-ioredis/run.sh | 2 +- .../mysql/e2e-tests/cjs-mysql/run.sh | 2 +- .../mysql/e2e-tests/esm-mysql/run.sh | 2 +- .../mysql2/e2e-tests/cjs-mysql2/run.sh | 2 +- .../mysql2/e2e-tests/esm-mysql2/run.sh | 2 +- .../nextjs/e2e-tests/cjs-nextjs/run.sh | 2 +- .../nextjs/e2e-tests/esm-nextjs/run.sh | 2 +- .../libraries/pg/e2e-tests/cjs-pg/run.sh | 2 +- .../libraries/pg/e2e-tests/esm-pg/run.sh | 2 +- .../postgres/e2e-tests/cjs-postgres/run.sh | 2 +- .../e2e-tests/cjs-postgres/src/index.ts | 19 +- .../postgres/e2e-tests/esm-postgres/run.sh | 2 +- .../e2e-tests/esm-postgres/src/index.ts | 19 +- .../prisma/e2e-tests/cjs-prisma/run.sh | 2 +- .../prisma/e2e-tests/esm-prisma/run.sh | 2 +- .../e2e-tests/cjs-upstash-redis-js/run.sh | 2 +- .../e2e-tests/esm-upstash-redis-js/run.sh | 2 +- 35 files changed, 1029 insertions(+), 662 deletions(-) create mode 100644 docs/rust-core-bindings.md create mode 100644 src/core/rustCoreBinding.ts diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 7b9f2f59..b8e5fa7f 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -57,6 +57,7 @@ jobs: - name: Run E2E tests for ${{ matrix.library }} env: DOCKER_DEFAULT_PLATFORM: linux/amd64 + TUSK_USE_RUST_CORE: "1" TUSK_CLI_VERSION: ${{ steps.tusk-version.outputs.version }} # Required for Firestore e2e tests FIREBASE_PROJECT_ID: ${{ vars.FIREBASE_PROJECT_ID }} diff --git a/.gitignore b/.gitignore index 1ed296e9..e04ee093 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,5 @@ Thumbs.db **/e2e-tests/**/.tusk/traces/ .direnv +experimental/ +benchmarks/results/ \ No newline at end of file diff --git a/docs/rust-core-bindings.md b/docs/rust-core-bindings.md new file mode 100644 index 00000000..d06629b7 --- /dev/null +++ b/docs/rust-core-bindings.md @@ -0,0 +1,62 @@ +# Rust Core Bindings + +This document explains how Rust acceleration works in the Node SDK, how to enable it, and what fallback behavior to expect. + +## Overview + +The SDK can offload selected hot-path logic to Rust via Node bindings (`@use-tusk/drift-core-node`), defined in the [`drift-core`](https://github.com/Use-Tusk/drift-core) repository. This is controlled by an environment flag and is designed to fail open. + +At a high level: + +- Node SDK logic remains the source of truth. +- Rust paths are opportunistic optimizations. +- If Rust is unavailable or fails at runtime, SDK behavior falls back to JavaScript equivalents. + +## Enablement + +Set: + +```bash +TUSK_USE_RUST_CORE=1 +``` + +Truthy values are `1` and `true` (case-insensitive). Any other value is treated as disabled. + +## Installation Requirements + +The Node SDK currently includes `@use-tusk/drift-core-node` as a regular dependency. + +Notes: + +- There is no Node equivalent of Python extras like `[rust]`. +- Rust acceleration is still runtime-gated by `TUSK_USE_RUST_CORE`. +- If the native binding cannot be loaded on a machine, the SDK continues on JavaScript code paths. + +## Platform Coverage and Native Binary Concerns + +Node native bindings depend on OS/arch/libc compatibility of published prebuilt artifacts. + +Practical implications: + +- Some platforms may not have a matching native artifact. +- On such platforms, direct use of `@use-tusk/drift-core-node` can fail at runtime. +- Within `drift-node-sdk`, Rust helper loading is guarded and fails open to non-Rust paths. + +Unlike Python wheels, this concern appears as Node native addon compatibility rather than wheel tag compatibility. + +## Fallback Behavior + +The bridge module is fail-open: + +- Rust calls are guarded behind a binding loader. +- If `TUSK_USE_RUST_CORE` is unset/falsey, Rust is skipped. +- If loading or a Rust call fails, helper functions return `null`. +- Calling code then uses the existing JavaScript implementation. + +This means users do not need Rust installed to run the SDK when Rust acceleration is disabled or unavailable. + +## Practical Guidance + +- Default production-safe posture: keep Rust disabled unless your deployment matrix is tested. +- Performance posture: enable Rust and benchmark on your workloads before broad rollout. +- Reliability posture: keep parity/smoke tests in CI to detect drift between JS and Rust paths. diff --git a/package-lock.json b/package-lock.json index 2f67fbe4..13f8c1a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.30", "license": "Apache-2.0", "dependencies": { + "@use-tusk/drift-core-node": "0.1.6", "import-in-the-middle": "^1.14.4", "js-yaml": "^4.1.0", "jsonpath": "^1.1.1", @@ -67,14 +68,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", - "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -115,13 +116,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.5" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -131,9 +132,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "license": "MIT", "dependencies": { @@ -145,9 +146,9 @@ } }, "node_modules/@bufbuild/buf": { - "version": "1.59.0", - "resolved": "https://registry.npmjs.org/@bufbuild/buf/-/buf-1.59.0.tgz", - "integrity": "sha512-VdLuGnFp1OKJaiMevlLow6Jcvv9omOyM02Qa1zexl8dBB4Ac2ggz6bpT3Zb06tmCnqd8tFrI/Im1fbom3CznlQ==", + "version": "1.65.0", + "resolved": "https://registry.npmjs.org/@bufbuild/buf/-/buf-1.65.0.tgz", + "integrity": "sha512-IQmIBB2CGbJAwx1NkuAWMuj4QGPnZ8mujbf4ckx9t6KI9EzfUzql1OyKi9qPrxlLAciI+kBIyPDQ2MIvXTxWUg==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -160,19 +161,19 @@ "node": ">=12" }, "optionalDependencies": { - "@bufbuild/buf-darwin-arm64": "1.59.0", - "@bufbuild/buf-darwin-x64": "1.59.0", - "@bufbuild/buf-linux-aarch64": "1.59.0", - "@bufbuild/buf-linux-armv7": "1.59.0", - "@bufbuild/buf-linux-x64": "1.59.0", - "@bufbuild/buf-win32-arm64": "1.59.0", - "@bufbuild/buf-win32-x64": "1.59.0" + "@bufbuild/buf-darwin-arm64": "1.65.0", + "@bufbuild/buf-darwin-x64": "1.65.0", + "@bufbuild/buf-linux-aarch64": "1.65.0", + "@bufbuild/buf-linux-armv7": "1.65.0", + "@bufbuild/buf-linux-x64": "1.65.0", + "@bufbuild/buf-win32-arm64": "1.65.0", + "@bufbuild/buf-win32-x64": "1.65.0" } }, "node_modules/@bufbuild/buf-darwin-arm64": { - "version": "1.59.0", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-arm64/-/buf-darwin-arm64-1.59.0.tgz", - "integrity": "sha512-d3JTxBCibC+C94JU0jwLMgo/WBhaAHBIRzZXaZ3Y8KREjTj3jhzAlelGZmCtQJyyE0l6DFSm3lQgMblJ5qlq/w==", + "version": "1.65.0", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-arm64/-/buf-darwin-arm64-1.65.0.tgz", + "integrity": "sha512-2U8CHjW1ysINYKwIPcc4WAiQPxe91RIjNtjpg+RC9rP0aZ7TpGm5MTMY5l3sN4drtmKdb9rBs3bMQsMNhSc90A==", "cpu": [ "arm64" ], @@ -187,9 +188,9 @@ } }, "node_modules/@bufbuild/buf-darwin-x64": { - "version": "1.59.0", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-x64/-/buf-darwin-x64-1.59.0.tgz", - "integrity": "sha512-eFnFB96GM6KjP5S8QFqjufjlMF41CVnXjkR8cIfR5jUXdwl1vf5S82Zv+cK1+Uogqhmt7AVBntd5Z+xmz4NKaw==", + "version": "1.65.0", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-x64/-/buf-darwin-x64-1.65.0.tgz", + "integrity": "sha512-aMqfc6pQC4L9dZpSD61XCEpPWKEtb1rXDPkK0/tzrfTWodnbaJ/elNoxsCGzbZVSMFeAdomUpXmSMrk8ALfWWw==", "cpu": [ "x64" ], @@ -204,9 +205,9 @@ } }, "node_modules/@bufbuild/buf-linux-aarch64": { - "version": "1.59.0", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-aarch64/-/buf-linux-aarch64-1.59.0.tgz", - "integrity": "sha512-g6DxTcJM29SBvqe42ll7HpkmTfecuG+PZYTysaxON9Y59fwtflhuLDpNqGhxWehHMkH11bFfpNeCGKjpGbVvkw==", + "version": "1.65.0", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-aarch64/-/buf-linux-aarch64-1.65.0.tgz", + "integrity": "sha512-gzqvY4PLRQ7g0+RlE9g+OL/6yPd5szG7e3Wd5bgjJzfKaQerNiQWaGyPLdcRsIM/WxJhT5e5lG8OrrWHwgQ9Ig==", "cpu": [ "arm64" ], @@ -221,9 +222,9 @@ } }, "node_modules/@bufbuild/buf-linux-armv7": { - "version": "1.59.0", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-armv7/-/buf-linux-armv7-1.59.0.tgz", - "integrity": "sha512-C92s+gmKnAyCzN7MdbtukRXOiW7e0hkeQrOie17vF6qWXPk2r9ix0WXZvg5gZr9R4zD8pOYwRVwYiB9zFXZOaA==", + "version": "1.65.0", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-armv7/-/buf-linux-armv7-1.65.0.tgz", + "integrity": "sha512-RpYFuPr9MKniD+WNfDgCclyvMu+/w9kK41OWr9sNnbS2BorujskwPiY0iTf5j+8+n/MeAnLIGlyC36+vUB/wIw==", "cpu": [ "arm" ], @@ -238,9 +239,9 @@ } }, "node_modules/@bufbuild/buf-linux-x64": { - "version": "1.59.0", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-x64/-/buf-linux-x64-1.59.0.tgz", - "integrity": "sha512-Pzc3TFm1t2fZ5uT7jkYBjyuLNKo5ji/wRl/lLLvOlTFRyqsSZBkFNQcJGHoHSej1yDWau16VMrAh0GN1rZfvAg==", + "version": "1.65.0", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-x64/-/buf-linux-x64-1.65.0.tgz", + "integrity": "sha512-0j06h1uKCXlOtrlNcTBkURazT+AwMNvuVxgJsYeUDnSliN05QS7LnBzPOwKg76ariSqlLo+QXk9eNtdhgVjYOg==", "cpu": [ "x64" ], @@ -255,9 +256,9 @@ } }, "node_modules/@bufbuild/buf-win32-arm64": { - "version": "1.59.0", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-arm64/-/buf-win32-arm64-1.59.0.tgz", - "integrity": "sha512-hS5VThgYNqbMFgY9SibDA/RXBdegw12jgrT2H+Tzaa2rvlSADck9ZAq9rwf2H0IvFJOqtR75Lejb+5Fx2rThpQ==", + "version": "1.65.0", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-arm64/-/buf-win32-arm64-1.65.0.tgz", + "integrity": "sha512-KBFsQ3iEityUuLTUCoXAO6ZTGUXWljSjK4upqofsYCb4OJeSeVguD7b09efkQt9ymKsXBt5wQicsRdkMJy/VEA==", "cpu": [ "arm64" ], @@ -272,9 +273,9 @@ } }, "node_modules/@bufbuild/buf-win32-x64": { - "version": "1.59.0", - "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-x64/-/buf-win32-x64-1.59.0.tgz", - "integrity": "sha512-JAGSF3oaKC2L/TelqvjB1N7oB5pTiviVr8mxiaxHyv4HpvcxCVdiO+iw0goRhZb4QHhYYswk2gLMezWHBxtR/g==", + "version": "1.65.0", + "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-x64/-/buf-win32-x64-1.65.0.tgz", + "integrity": "sha512-vJYzHjncSLdy4sPDW8kLqUldHh6Vucg6KabAflm7CDj29lU/HydV8T+nOVsXkoRMUf4+H/qy8WjnSMEtRkaogA==", "cpu": [ "x64" ], @@ -302,9 +303,9 @@ } }, "node_modules/@emnapi/core": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.0.tgz", - "integrity": "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", + "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", "dev": true, "license": "MIT", "optional": true, @@ -314,9 +315,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.0.tgz", - "integrity": "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", "dev": true, "license": "MIT", "optional": true, @@ -336,9 +337,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", "cpu": [ "ppc64" ], @@ -353,9 +354,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", "cpu": [ "arm" ], @@ -370,9 +371,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", "cpu": [ "arm64" ], @@ -387,9 +388,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", "cpu": [ "x64" ], @@ -404,9 +405,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", "cpu": [ "arm64" ], @@ -421,9 +422,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", "cpu": [ "x64" ], @@ -438,9 +439,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", "cpu": [ "arm64" ], @@ -455,9 +456,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", "cpu": [ "x64" ], @@ -472,9 +473,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", "cpu": [ "arm" ], @@ -489,9 +490,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", "cpu": [ "arm64" ], @@ -506,9 +507,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", "cpu": [ "ia32" ], @@ -523,9 +524,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", "cpu": [ "loong64" ], @@ -540,9 +541,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", "cpu": [ "mips64el" ], @@ -557,9 +558,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", "cpu": [ "ppc64" ], @@ -574,9 +575,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", "cpu": [ "riscv64" ], @@ -591,9 +592,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", "cpu": [ "s390x" ], @@ -608,9 +609,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", "cpu": [ "x64" ], @@ -625,9 +626,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", "cpu": [ "arm64" ], @@ -642,9 +643,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", "cpu": [ "x64" ], @@ -659,9 +660,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", "cpu": [ "arm64" ], @@ -676,9 +677,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", "cpu": [ "x64" ], @@ -693,9 +694,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", "cpu": [ "arm64" ], @@ -710,9 +711,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", "cpu": [ "x64" ], @@ -727,9 +728,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", "cpu": [ "arm64" ], @@ -744,9 +745,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", "cpu": [ "ia32" ], @@ -761,9 +762,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", "cpu": [ "x64" ], @@ -778,9 +779,9 @@ } }, "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==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -875,9 +876,9 @@ } }, "node_modules/@grpc/grpc-js": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.1.tgz", - "integrity": "sha512-sPxgEWtPUR3EnRJCEtbGZG2iX8LQDUls2wUS3o27jg07KqJFMq6YDeWvMo1wfpmy3rqRdS0rivpLwhqQtEyCuQ==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.3.tgz", + "integrity": "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1480,9 +1481,9 @@ } }, "node_modules/@ioredis/commands": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.4.0.tgz", - "integrity": "sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.5.0.tgz", + "integrity": "sha512-eUgLqrMf8nJkZxT24JvVRrQya1vZkQh8BBeYNwGDqa5I0VUi8ACx7uFvAaLxintokpTenkK6DASvo/bvNbBGow==", "dev": true, "license": "MIT" }, @@ -1604,9 +1605,9 @@ } }, "node_modules/@mapbox/node-pre-gyp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-2.0.0.tgz", - "integrity": "sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-2.0.3.tgz", + "integrity": "sha512-uwPAhccfFJlsfCxMYTwOdVfOz3xqyj8xYL3zJj8f0pb30tLohnnFPhLuqp4/qoEz8sNxe4SESZedcBojRefIzg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -1626,9 +1627,9 @@ } }, "node_modules/@mongodb-js/saslprep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.2.tgz", - "integrity": "sha512-QgA5AySqB27cGTXBFmnpifAi7HxoGUeezwo6p9dI03MuDB6Pp33zgclqVb6oVK3j6I9Vesg0+oojW2XxB59SGg==", + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.6.tgz", + "integrity": "sha512-y+x3H1xBZd38n10NZF/rEBlvDOOMQ6LKUTHqr8R9VkJ+mmQOYtJFxIlkkK8fZrtOiL6VixbOBWMbZGBdal3Z1g==", "dev": true, "license": "MIT", "dependencies": { @@ -1636,29 +1637,33 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz", - "integrity": "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", + "integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.5.0", - "@emnapi/runtime": "^1.5.0", + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@next/env": { - "version": "15.5.6", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.6.tgz", - "integrity": "sha512-3qBGRW+sCGzgbpc5TS1a0p7eNxnOarGVQhZxfvTdnV0gFI61lX7QNtQ4V1TSREctXzYn5NetbUsLvyqwLFJM6Q==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.12.tgz", + "integrity": "sha512-pUvdJN1on574wQHjaBfNGDt9Mz5utDSZFsIIQkMzPgNS8ZvT4H2mwOrOIClwsQOb6EGx5M76/CZr6G8i6pSpLg==", "dev": true, "license": "MIT" }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.6.tgz", - "integrity": "sha512-ES3nRz7N+L5Umz4KoGfZ4XX6gwHplwPhioVRc25+QNsDa7RtUF/z8wJcbuQ2Tffm5RZwuN2A063eapoJ1u4nPg==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.12.tgz", + "integrity": "sha512-RnRjBtH8S8eXCpUNkQ+543DUc7ys8y15VxmFU9HRqlo9BG3CcBUiwNtF8SNoi2xvGCVJq1vl2yYq+3oISBS0Zg==", "cpu": [ "arm64" ], @@ -1673,9 +1678,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.6.tgz", - "integrity": "sha512-JIGcytAyk9LQp2/nuVZPAtj8uaJ/zZhsKOASTjxDug0SPU9LAM3wy6nPU735M1OqacR4U20LHVF5v5Wnl9ptTA==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.12.tgz", + "integrity": "sha512-nqa9/7iQlboF1EFtNhWxQA0rQstmYRSBGxSM6g3GxvxHxcoeqVXfGNr9stJOme674m2V7r4E3+jEhhGvSQhJRA==", "cpu": [ "x64" ], @@ -1690,9 +1695,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.6.tgz", - "integrity": "sha512-qvz4SVKQ0P3/Im9zcS2RmfFL/UCQnsJKJwQSkissbngnB/12c6bZTCB0gHTexz1s6d/mD0+egPKXAIRFVS7hQg==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.12.tgz", + "integrity": "sha512-dCzAjqhDHwmoB2M4eYfVKqXs99QdQxNQVpftvP1eGVppamXh/OkDAwV737Zr0KPXEqRUMN4uCjh6mjO+XtF3Mw==", "cpu": [ "arm64" ], @@ -1707,9 +1712,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.6.tgz", - "integrity": "sha512-FsbGVw3SJz1hZlvnWD+T6GFgV9/NYDeLTNQB2MXoPN5u9VA9OEDy6fJEfePfsUKAhJufFbZLgp0cPxMuV6SV0w==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.12.tgz", + "integrity": "sha512-+fpGWvQiITgf7PUtbWY1H7qUSnBZsPPLyyq03QuAKpVoTy/QUx1JptEDTQMVvQhvizCEuNLEeghrQUyXQOekuw==", "cpu": [ "arm64" ], @@ -1724,9 +1729,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.6.tgz", - "integrity": "sha512-3QnHGFWlnvAgyxFxt2Ny8PTpXtQD7kVEeaFat5oPAHHI192WKYB+VIKZijtHLGdBBvc16tiAkPTDmQNOQ0dyrA==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.12.tgz", + "integrity": "sha512-jSLvgdRRL/hrFAPqEjJf1fFguC719kmcptjNVDJl26BnJIpjL3KH5h6mzR4mAweociLQaqvt4UyzfbFjgAdDcw==", "cpu": [ "x64" ], @@ -1741,9 +1746,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.6.tgz", - "integrity": "sha512-OsGX148sL+TqMK9YFaPFPoIaJKbFJJxFzkXZljIgA9hjMjdruKht6xDCEv1HLtlLNfkx3c5w2GLKhj7veBQizQ==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.12.tgz", + "integrity": "sha512-/uaF0WfmYqQgLfPmN6BvULwxY0dufI2mlN2JbOKqqceZh1G4hjREyi7pg03zjfyS6eqNemHAZPSoP84x17vo6w==", "cpu": [ "x64" ], @@ -1758,9 +1763,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.6.tgz", - "integrity": "sha512-ONOMrqWxdzXDJNh2n60H6gGyKed42Ieu6UTVPZteXpuKbLZTH4G4eBMsr5qWgOBA+s7F+uB4OJbZnrkEDnZ5Fg==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.12.tgz", + "integrity": "sha512-xhsL1OvQSfGmlL5RbOmU+FV120urrgFpYLq+6U8C6KIym32gZT6XF/SDE92jKzzlPWskkbjOKCpqk5m4i8PEfg==", "cpu": [ "arm64" ], @@ -1775,9 +1780,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.6.tgz", - "integrity": "sha512-pxK4VIjFRx1MY92UycLOOw7dTdvccWsNETQ0kDHkBlcFH1GrTLUjSiHU1ohrznnux6TqRHgv5oflhfIWZwVROQ==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.12.tgz", + "integrity": "sha512-Z1Dh6lhFkxvBDH1FoW6OU/L6prYwPSlwjLiZkExIAh8fbP6iI/M7iGTQAJPYJ9YFlWobCZ1PHbchFhFYb2ADkw==", "cpu": [ "x64" ], @@ -2000,9 +2005,9 @@ } }, "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.38.0.tgz", - "integrity": "sha512-kocjix+/sSggfJhwXqClZ3i9Y/MI0fp7b+g7kCRm6psy2dsf8uApTRclwG18h8Avm7C9+fnt+O36PspJ/OzoWg==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.39.0.tgz", + "integrity": "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2143,13 +2148,13 @@ "license": "BSD-3-Clause" }, "node_modules/@quansync/fs": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-0.1.5.tgz", - "integrity": "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-1.0.0.tgz", + "integrity": "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==", "dev": true, "license": "MIT", "dependencies": { - "quansync": "^0.2.11" + "quansync": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/sxzz" @@ -2275,9 +2280,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-beta.48", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.48.tgz", - "integrity": "sha512-dhhk6yq8VWoC9bEPqYbsZL09mHSwfI9VuTW5V0AKiE91R0FhcJyIPsOaDcvd1FXPZL6miTqlILwM2kRpGdEr2w==", + "version": "1.0.0-rc.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.5.tgz", + "integrity": "sha512-CUlplTujmbDWp2gamvrqVKi2Or8lmngXT1WxsizJfts7JrvfGhZObciaY/+CbdbS9qNnskvwMZNEhTPrn7b+WA==", "cpu": [ "x64" ], @@ -2446,9 +2451,9 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", "dev": true, "license": "MIT" }, @@ -2533,9 +2538,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.7.tgz", - "integrity": "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==", + "version": "4.19.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", "dev": true, "license": "MIT", "dependencies": { @@ -2613,9 +2618,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.24.tgz", - "integrity": "sha512-FE5u0ezmi6y9OZEzlJfg37mqqf6ZDSF2V/NLjUyGrR9uTZ7Sb9F7bLNZ03S4XVUNRWGA7Ck4c1kK+YnuWjl+DA==", + "version": "20.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.33.tgz", + "integrity": "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==", "dev": true, "license": "MIT", "dependencies": { @@ -2623,9 +2628,9 @@ } }, "node_modules/@types/pg": { - "version": "8.15.6", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.6.tgz", - "integrity": "sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.16.0.tgz", + "integrity": "sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2934,10 +2939,15 @@ "dev": true, "license": "ISC" }, + "node_modules/@use-tusk/drift-core-node": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@use-tusk/drift-core-node/-/drift-core-node-0.1.6.tgz", + "integrity": "sha512-xFvaZAbyykIoqVIEBfmuYWYquyC7C8QlWQyseQTfBK1l97YkXSZZEN3re9cgsIiqd/SNrrMZld/L9eIYmSOktg==" + }, "node_modules/@use-tusk/drift-schemas": { - "version": "0.1.24", - "resolved": "https://registry.npmjs.org/@use-tusk/drift-schemas/-/drift-schemas-0.1.24.tgz", - "integrity": "sha512-Y+xQfpseJdP4S2mcpOxxwn9oFvnhVlZ/6wvmaMxl1oAA9nraO8oN9e2inx9ft/MhwA1gwZ9mJAotfc1/MSFg0g==", + "version": "0.1.30", + "resolved": "https://registry.npmjs.org/@use-tusk/drift-schemas/-/drift-schemas-0.1.30.tgz", + "integrity": "sha512-gNU6JHqvI+BT0TvGvHjmFfPz+y4Q8vJAUdRG5mnqE6/wu+tfZla5J8nG27hd2DrpZJ3TK5kCjoG5LXlV3ftWEA==", "dev": true, "dependencies": { "@protobuf-ts/runtime": "^2.11.0", @@ -3003,9 +3013,9 @@ } }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -3034,9 +3044,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", "dev": true, "license": "MIT", "dependencies": { @@ -3361,14 +3371,14 @@ } }, "node_modules/axios": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", - "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", + "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", "dev": true, "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, @@ -3403,9 +3413,9 @@ } }, "node_modules/birpc": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.8.0.tgz", - "integrity": "sha512-Bz2a4qD/5GRhiHSwj30c/8kC8QGj12nNDwz3D4ErQ4Xhy35dsSDvF+RA/tWpjyU0pdGtSDiEk6B5fBGE1qNVhw==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", "dev": true, "license": "MIT", "funding": { @@ -3420,24 +3430,28 @@ "license": "MIT" }, "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", "dev": true, "license": "MIT", "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", - "debug": "^4.4.0", + "debug": "^4.4.3", "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", + "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", - "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" }, "engines": { "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/brace-expansion": { @@ -3564,9 +3578,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001754", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", - "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==", + "version": "1.0.30001770", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001770.tgz", + "integrity": "sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==", "dev": true, "funding": [ { @@ -3666,9 +3680,9 @@ "license": "MIT" }, "node_modules/ci-info": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", - "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", "dev": true, "funding": [ { @@ -3943,16 +3957,17 @@ } }, "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "dev": true, "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/content-type": { @@ -4081,6 +4096,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, "license": "MIT" }, "node_modules/define-data-property": { @@ -4160,9 +4176,9 @@ } }, "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -4345,9 +4361,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -4358,32 +4374,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" } }, "node_modules/escalade": { @@ -4417,22 +4433,21 @@ } }, "node_modules/escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", "license": "BSD-2-Clause", "dependencies": { "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" + "estraverse": "^5.2.0", + "esutils": "^2.0.2" }, "bin": { "escodegen": "bin/escodegen.js", "esgenerate": "bin/esgenerate.js" }, "engines": { - "node": ">=4.0" + "node": ">=6.0" }, "optionalDependencies": { "source-map": "~0.6.1" @@ -4451,65 +4466,6 @@ "node": ">=4" } }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "license": "MIT", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/eslint": { "version": "8.57.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", @@ -4696,9 +4652,9 @@ } }, "node_modules/esprima": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", - "integrity": "sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz", + "integrity": "sha512-S9VbPDU0adFErpDai3qDkjq8+G05ONtKzcyNrPKg/ZKa+tf879nX2KexNU95b31UoTJjRLInNBHHHjFPoCd7lQ==", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -4708,9 +4664,9 @@ } }, "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -4737,7 +4693,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -4770,19 +4725,20 @@ } }, "node_modules/express": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "dev": true, "license": "MIT", "dependencies": { "accepts": "^2.0.0", - "body-parser": "^2.2.0", + "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", + "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", @@ -4867,6 +4823,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, "license": "MIT" }, "node_modules/fast-safe-stringify": { @@ -4877,9 +4834,9 @@ "license": "MIT" }, "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "dev": true, "license": "ISC", "dependencies": { @@ -4954,9 +4911,9 @@ } }, "node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", "dev": true, "license": "MIT", "dependencies": { @@ -4968,7 +4925,11 @@ "statuses": "^2.0.1" }, "engines": { - "node": ">= 0.8" + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/find-up": { @@ -5072,9 +5033,9 @@ } }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dev": true, "license": "MIT", "dependencies": { @@ -5216,9 +5177,9 @@ } }, "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", + "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", "dev": true, "license": "MIT", "engines": { @@ -5268,9 +5229,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "version": "4.13.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", + "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", "dev": true, "license": "MIT", "dependencies": { @@ -5281,9 +5242,10 @@ } }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -5506,30 +5468,24 @@ "license": "MIT" }, "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "dev": true, "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/https-proxy-agent": { @@ -5547,9 +5503,9 @@ } }, "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "dev": true, "license": "MIT", "dependencies": { @@ -5557,6 +5513,10 @@ }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/ignore": { @@ -5661,13 +5621,13 @@ "license": "ISC" }, "node_modules/ioredis": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.8.2.tgz", - "integrity": "sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.9.3.tgz", + "integrity": "sha512-VI5tMCdeoxZWU5vjHWsiE/Su76JGhBvWF1MJnV9ZtGltHk9BmD48oDq8Tj8haZ85aceXZMxLNDQZRVo5QKNgXA==", "dev": true, "license": "MIT", "dependencies": { - "@ioredis/commands": "1.4.0", + "@ioredis/commands": "1.5.0", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", @@ -5906,9 +5866,9 @@ } }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -5995,24 +5955,24 @@ } }, "node_modules/jsonpath": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz", - "integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.2.1.tgz", + "integrity": "sha512-Jl6Jhk0jG+kP3yk59SSeGq7LFPR4JQz1DU0K+kXTysUhMostbhU3qh5mjTuf0PqFcXpAT7kvmMt9WxV10NyIgQ==", "license": "MIT", "dependencies": { - "esprima": "1.2.2", - "static-eval": "2.0.2", - "underscore": "1.12.1" + "esprima": "1.2.5", + "static-eval": "2.1.1", + "underscore": "1.13.6" } }, "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", "dev": true, "license": "MIT", "dependencies": { - "jws": "^3.2.2", + "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", @@ -6029,9 +5989,9 @@ } }, "node_modules/jwa": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", - "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", "dev": true, "license": "MIT", "dependencies": { @@ -6041,13 +6001,13 @@ } }, "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", "dev": true, "license": "MIT", "dependencies": { - "jwa": "^1.4.1", + "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, @@ -6115,9 +6075,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true, "license": "MIT" }, @@ -6206,19 +6166,16 @@ "license": "Apache-2.0" }, "node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } + "license": "ISC" }, "node_modules/lru.min": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz", - "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz", + "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", "dev": true, "license": "MIT", "engines": { @@ -6417,16 +6374,20 @@ } }, "node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "dev": true, "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/mimic-function": { @@ -6469,11 +6430,11 @@ } }, "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } @@ -6498,9 +6459,9 @@ "license": "MIT" }, "node_modules/mongodb": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.20.0.tgz", - "integrity": "sha512-Tl6MEIU3K4Rq3TSHd+sZQqRBoGlFsOgNrH5ltAcFBV62Re3Fd+FcaVf8uSEQFOJ51SDowDVttBTONMfoYWrWlQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.21.0.tgz", + "integrity": "sha512-URyb/VXMjJ4da46OeSXg+puO39XH9DeQpWCslifrRn9JWugy0D+DvvBvkm2WxmHe61O/H19JM66p1z7RHVkZ6A==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -6576,54 +6537,36 @@ } }, "node_modules/mysql2": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.15.3.tgz", - "integrity": "sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==", + "version": "3.17.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.17.3.tgz", + "integrity": "sha512-uCLmQMe1l96Sb6J3Ii8YJTOWJkhRmxlLJFdOfhD68jPpGTzK2fxEkFMpf5gewyHgUB0FJKzuAuPhYS+oPB0/vA==", "dev": true, "license": "MIT", "dependencies": { - "aws-ssl-profiles": "^1.1.1", + "aws-ssl-profiles": "^1.1.2", "denque": "^2.1.0", "generate-function": "^2.3.1", - "iconv-lite": "^0.7.0", - "long": "^5.2.1", - "lru.min": "^1.0.0", - "named-placeholders": "^1.1.3", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.2" + "iconv-lite": "^0.7.2", + "long": "^5.3.2", + "lru.min": "^1.1.4", + "named-placeholders": "^1.1.6", + "sql-escaper": "^1.3.3" }, "engines": { "node": ">= 8.0" } }, - "node_modules/mysql2/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/named-placeholders": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", - "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz", + "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", "dev": true, "license": "MIT", "dependencies": { - "lru-cache": "^7.14.1" + "lru.min": "^1.1.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=8.0.0" } }, "node_modules/nanoid": { @@ -6663,13 +6606,13 @@ } }, "node_modules/next": { - "version": "15.5.6", - "resolved": "https://registry.npmjs.org/next/-/next-15.5.6.tgz", - "integrity": "sha512-zTxsnI3LQo3c9HSdSf91O1jMNsEzIXDShXd4wVdg9y5shwLqBXi4ZtUUJyB86KGVSJLZx0PFONvO54aheGX8QQ==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.12.tgz", + "integrity": "sha512-Fi/wQ4Etlrn60rz78bebG1i1SR20QxvV8tVp6iJspjLUSHcZoeUXCt+vmWoEcza85ElZzExK/jJ/F6SvtGktjA==", "dev": true, "license": "MIT", "dependencies": { - "@next/env": "15.5.6", + "@next/env": "15.5.12", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", @@ -6682,14 +6625,14 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.5.6", - "@next/swc-darwin-x64": "15.5.6", - "@next/swc-linux-arm64-gnu": "15.5.6", - "@next/swc-linux-arm64-musl": "15.5.6", - "@next/swc-linux-x64-gnu": "15.5.6", - "@next/swc-linux-x64-musl": "15.5.6", - "@next/swc-win32-arm64-msvc": "15.5.6", - "@next/swc-win32-x64-msvc": "15.5.6", + "@next/swc-darwin-arm64": "15.5.12", + "@next/swc-darwin-x64": "15.5.12", + "@next/swc-linux-arm64-gnu": "15.5.12", + "@next/swc-linux-arm64-musl": "15.5.12", + "@next/swc-linux-x64-gnu": "15.5.12", + "@next/swc-linux-x64-musl": "15.5.12", + "@next/swc-win32-arm64-msvc": "15.5.12", + "@next/swc-win32-x64-msvc": "15.5.12", "sharp": "^0.34.3" }, "peerDependencies": { @@ -6832,6 +6775,17 @@ "node": ">= 0.4" } }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -6923,9 +6877,9 @@ } }, "node_modules/p-map": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", - "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", "dev": true, "license": "MIT", "engines": { @@ -7147,13 +7101,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, "node_modules/path-to-regexp": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", @@ -7183,15 +7130,15 @@ "license": "MIT" }, "node_modules/pg": { - "version": "8.16.3", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz", - "integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.18.0.tgz", + "integrity": "sha512-xqrUDL1b9MbkydY/s+VZ6v+xiMUmOUk7SS9d/1kpyQxoJ6U9AO1oIJyUWVZojbfe5Cc/oluutcgFG4L9RDP1iQ==", "dev": true, "license": "MIT", "dependencies": { - "pg-connection-string": "^2.9.1", - "pg-pool": "^3.10.1", - "pg-protocol": "^1.10.3", + "pg-connection-string": "^2.11.0", + "pg-pool": "^3.11.0", + "pg-protocol": "^1.11.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, @@ -7199,7 +7146,7 @@ "node": ">= 16.0.0" }, "optionalDependencies": { - "pg-cloudflare": "^1.2.7" + "pg-cloudflare": "^1.3.0" }, "peerDependencies": { "pg-native": ">=3.0.1" @@ -7211,17 +7158,17 @@ } }, "node_modules/pg-cloudflare": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.7.tgz", - "integrity": "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz", + "integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==", "dev": true, "license": "MIT", "optional": true }, "node_modules/pg-connection-string": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz", - "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.11.0.tgz", + "integrity": "sha512-kecgoJwhOpxYU21rZjULrmrBJ698U2RxXofKVzOn5UDj61BPj/qMb7diYUR1nLScCDbrztQFl1TaQZT0t1EtzQ==", "dev": true, "license": "MIT" }, @@ -7236,9 +7183,9 @@ } }, "node_modules/pg-pool": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz", - "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.11.0.tgz", + "integrity": "sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -7246,9 +7193,9 @@ } }, "node_modules/pg-protocol": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz", - "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.11.0.tgz", + "integrity": "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==", "dev": true, "license": "MIT" }, @@ -7358,9 +7305,9 @@ } }, "node_modules/postgres": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.7.tgz", - "integrity": "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==", + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.8.tgz", + "integrity": "sha512-d+JFcLM17njZaOLkv6SCev7uoLaBtfK86vMUXhW1Z4glPWh4jozno9APvW/XKFJ3CCxVoC7OL38BqRydtu5nGg==", "dev": true, "license": "Unlicense", "engines": { @@ -7382,9 +7329,9 @@ } }, "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", + "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", "dev": true, "license": "MIT", "engines": { @@ -7425,9 +7372,9 @@ } }, "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", "bin": { @@ -7513,9 +7460,9 @@ } }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -7529,9 +7476,9 @@ } }, "node_modules/quansync": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", - "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-1.0.0.tgz", + "integrity": "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==", "dev": true, "funding": [ { @@ -7587,42 +7534,25 @@ } }, "node_modules/raw-body": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", - "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.7.0", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.10" } }, - "node_modules/raw-body/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/react": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", - "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "dev": true, "license": "MIT", "peer": true, @@ -7631,9 +7561,9 @@ } }, "node_modules/react-dom": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", - "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "dev": true, "license": "MIT", "peer": true, @@ -7641,7 +7571,7 @@ "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.0" + "react": "^19.2.4" } }, "node_modules/readdirp": { @@ -7813,7 +7743,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -7878,9 +7808,9 @@ } }, "node_modules/rolldown-plugin-dts": { - "version": "0.17.5", - "resolved": "https://registry.npmjs.org/rolldown-plugin-dts/-/rolldown-plugin-dts-0.17.5.tgz", - "integrity": "sha512-dYzjLdhgsSIPmOCPJdDXiD6AUotAHVkGLNlSMdi3VmvTqk7O9H7uGzG2WGzgnDxZq6kZh31vZUbp9ZFoOhpySA==", + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/rolldown-plugin-dts/-/rolldown-plugin-dts-0.17.8.tgz", + "integrity": "sha512-76EEBlhF00yeY6M7VpMkWKI4r9WjuoMiOGey7j4D6zf3m0BR+ZrrY9hvSXdueJ3ljxSLq4DJBKFpX/X9+L7EKw==", "dev": true, "license": "MIT", "dependencies": { @@ -7889,13 +7819,13 @@ "@babel/types": "^7.28.5", "ast-kit": "^2.2.0", "birpc": "^2.8.0", - "debug": "^4.4.3", "dts-resolver": "^2.1.3", "get-tsconfig": "^4.13.0", - "magic-string": "^0.30.21" + "magic-string": "^0.30.21", + "obug": "^2.0.0" }, "engines": { - "node": ">=20.18.0" + "node": ">=20.19.0" }, "funding": { "url": "https://github.com/sponsors/sxzz" @@ -8017,9 +7947,9 @@ "peer": true }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -8029,34 +7959,32 @@ } }, "node_modules/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.3.5", + "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "mime-types": "^3.0.1", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", - "statuses": "^2.0.1" + "statuses": "^2.0.2" }, "engines": { "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/seq-queue": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==", - "dev": true - }, "node_modules/serialize-error": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", @@ -8087,9 +8015,9 @@ } }, "node_modules/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", "dev": true, "license": "MIT", "dependencies": { @@ -8100,6 +8028,10 @@ }, "engines": { "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/set-function-length": { @@ -8359,14 +8291,20 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/sqlstring": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "node_modules/sql-escaper": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/sql-escaper/-/sql-escaper-1.3.3.tgz", + "integrity": "sha512-BsTCV265VpTp8tm1wyIm1xqQCS+Q9NHx2Sr+WcnUrgLrQ6yiDIvHYJV5gHxsj1lMBy2zm5twLaZao8Jd+S8JJw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "bun": ">=1.0.0", + "deno": ">=2.0.0", + "node": ">=12.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/mysqljs/sql-escaper?sponsor=1" } }, "node_modules/stack-utils": { @@ -8400,12 +8338,12 @@ "license": "MIT" }, "node_modules/static-eval": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", - "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.1.tgz", + "integrity": "sha512-MgWpQ/ZjGieSVB3eOJVs4OA2LT/q1vx98KPCTTQPzq/aLr0YUXTsgryTXr4SLfR0ZfUUCiedM9n/ABeDIyy4mA==", "license": "MIT", "dependencies": { - "escodegen": "^1.8.1" + "escodegen": "^2.1.0" } }, "node_modules/statuses": { @@ -8570,9 +8508,9 @@ } }, "node_modules/superagent": { - "version": "10.2.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.3.tgz", - "integrity": "sha512-y/hkYGeXAj7wUMjxRbB21g/l6aAEituGXM9Rwl4o20+SX3e8YOSV6BxFXl+dL3Uk0mjSL3kCbNkwURm8/gEDig==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz", + "integrity": "sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8580,11 +8518,11 @@ "cookiejar": "^2.1.4", "debug": "^4.3.7", "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.4", + "form-data": "^4.0.5", "formidable": "^3.5.4", "methods": "^1.1.2", "mime": "2.6.0", - "qs": "^6.11.2" + "qs": "^6.14.1" }, "engines": { "node": ">=14.18.0" @@ -8631,9 +8569,9 @@ } }, "node_modules/supertap/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "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==", "dev": true, "license": "MIT", "dependencies": { @@ -8645,14 +8583,15 @@ } }, "node_modules/supertest": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.4.tgz", - "integrity": "sha512-tjLPs7dVyqgItVFirHYqe2T+MfWc2VOBQ8QFKKbWTA3PU7liZR8zoSpAi/C1k1ilm9RsXIKYf197oap9wXGVYg==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.2.2.tgz", + "integrity": "sha512-oK8WG9diS3DlhdUkcFn4tkNIiIbBx9lI2ClF8K+b2/m8Eyv47LSawxUzZQSNKUrVb2KsqeTDCcjAAVPYaSLVTA==", "dev": true, "license": "MIT", "dependencies": { + "cookie-signature": "^1.2.2", "methods": "^1.1.2", - "superagent": "^10.2.3" + "superagent": "^10.3.0" }, "engines": { "node": ">=14.18.0" @@ -8684,9 +8623,9 @@ } }, "node_modules/tar": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", - "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.9.tgz", + "integrity": "sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -8976,9 +8915,9 @@ } }, "node_modules/tsdown/node_modules/diff": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz", - "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", + "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -9007,13 +8946,13 @@ "license": "0BSD" }, "node_modules/tsx": { - "version": "4.20.6", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", - "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", + "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.25.0", + "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "bin": { @@ -9082,40 +9021,40 @@ } }, "node_modules/unconfig": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-7.4.0.tgz", - "integrity": "sha512-KM0SrvIvwQXJnbiSzur1Y+5jHSLVPhS31H5qzgjDQxGqS3PWrH6X7TxYX/JTuTlItarHkZ9ePK9t01Q6wu1c4Q==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-7.5.0.tgz", + "integrity": "sha512-oi8Qy2JV4D3UQ0PsopR28CzdQ3S/5A1zwsUwp/rosSbfhJ5z7b90bIyTwi/F7hCLD4SGcZVjDzd4XoUQcEanvA==", "dev": true, "license": "MIT", "dependencies": { - "@quansync/fs": "^0.1.5", + "@quansync/fs": "^1.0.0", "defu": "^6.1.4", "jiti": "^2.6.1", - "quansync": "^0.2.11", - "unconfig-core": "7.4.0" + "quansync": "^1.0.0", + "unconfig-core": "7.5.0" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/unconfig-core": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/unconfig-core/-/unconfig-core-7.4.0.tgz", - "integrity": "sha512-3ew7rvES5x2LCZ/QRKV3nQQpq7eFYuszQuvZrhTHxDPKc34QFjRXI17XGiZI+WQTVIXKYeBti4v3LS39NWmhmg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/unconfig-core/-/unconfig-core-7.5.0.tgz", + "integrity": "sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==", "dev": true, "license": "MIT", "dependencies": { - "@quansync/fs": "^0.1.5", - "quansync": "^0.2.11" + "@quansync/fs": "^1.0.0", + "quansync": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", "license": "MIT" }, "node_modules/undici-types": { @@ -9239,6 +9178,7 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9429,9 +9369,9 @@ } }, "node_modules/yaml": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", - "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "dev": true, "license": "ISC", "bin": { @@ -9439,6 +9379,9 @@ }, "engines": { "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" } }, "node_modules/yargs": { diff --git a/package.json b/package.json index b98471bb..c1172969 100644 --- a/package.json +++ b/package.json @@ -95,6 +95,7 @@ "typescript": "^5.0.0" }, "dependencies": { + "@use-tusk/drift-core-node": "0.1.6", "import-in-the-middle": "^1.14.4", "js-yaml": "^4.1.0", "jsonpath": "^1.1.1", diff --git a/src/core/rustCoreBinding.ts b/src/core/rustCoreBinding.ts new file mode 100644 index 00000000..b82c47a2 --- /dev/null +++ b/src/core/rustCoreBinding.ts @@ -0,0 +1,225 @@ +import type { + BuildSpanProtoBytesInput as RustBuildSpanProtoBytesInput, +} from "@use-tusk/drift-core-node"; + +type RustCoreNodeBinding = Pick< + typeof import("@use-tusk/drift-core-node"), + "processExportPayload" | "buildSpanProtoBytes" | "buildExportSpansRequestBytes" +>; + +export type ProcessExportPayloadResult = { + normalizedValue: unknown; + decodedValueHash: string; + decodedSchema: unknown; + decodedSchemaHash: string; +}; + +export type BuildSpanProtoBytesInput = { + traceId: string; + spanId: string; + parentSpanId: string; + name: string; + packageName: string; + instrumentationName: string; + submoduleName: string; + packageType: number; + environment?: string; + kind: number; + inputSchema: unknown; + outputSchema: unknown; + inputSchemaHash: string; + outputSchemaHash: string; + inputValueHash: string; + outputValueHash: string; + statusCode: number; + statusMessage: string; + isPreAppStart: boolean; + isRootSpan: boolean; + timestampSeconds: number; + timestampNanos: number; + durationSeconds: number; + durationNanos: number; + metadata?: unknown; + inputValue?: unknown; + outputValue?: unknown; + inputValueProtoStructBytes?: Buffer; + outputValueProtoStructBytes?: Buffer; +}; + +let bindingLoadAttempted = false; +let binding: RustCoreNodeBinding | null = null; + +function isRustCoreEnabled(): boolean { + const raw = process.env.TUSK_USE_RUST_CORE; + if (!raw) { + return false; + } + return raw === "1" || raw.toLowerCase() === "true"; +} + +function loadBinding(): RustCoreNodeBinding | null { + if (bindingLoadAttempted) { + return binding; + } + bindingLoadAttempted = true; + + if (!isRustCoreEnabled()) { + return null; + } + + try { + // eslint-disable-next-line @typescript-eslint/no-var-requires + binding = require("@use-tusk/drift-core-node") as RustCoreNodeBinding; + } catch { + binding = null; + } + return binding; +} + +function toRustSchemaMerges(schemaMerges?: Record): Record | undefined { + if (!schemaMerges) { + return undefined; + } + const out: Record = {}; + for (const [key, value] of Object.entries(schemaMerges)) { + out[key] = { + ...(value.encoding !== undefined ? { encoding: value.encoding } : {}), + ...(value.decodedType !== undefined ? { decoded_type: value.decodedType } : {}), + ...(value.matchImportance !== undefined ? { match_importance: value.matchImportance } : {}), + }; + } + return out; +} + +function normalizeSchemaKeys(value: any): any { + if (Array.isArray(value)) { + return value.map(normalizeSchemaKeys); + } + if (!value || typeof value !== "object") { + return value; + } + const out: Record = {}; + for (const [k, v] of Object.entries(value)) { + if (k === "decoded_type") { + out.decodedType = normalizeSchemaKeys(v); + } else if (k === "match_importance") { + out.matchImportance = normalizeSchemaKeys(v); + } else { + out[k] = normalizeSchemaKeys(v); + } + } + return out; +} + +function denormalizeSchemaKeys(value: any): any { + if (Array.isArray(value)) { + return value.map(denormalizeSchemaKeys); + } + if (!value || typeof value !== "object") { + return value; + } + const out: Record = {}; + for (const [k, v] of Object.entries(value)) { + if (k === "decodedType") { + out.decoded_type = denormalizeSchemaKeys(v); + } else if (k === "matchImportance") { + out.match_importance = denormalizeSchemaKeys(v); + } else { + out[k] = denormalizeSchemaKeys(v); + } + } + return out; +} + +export function processExportPayloadJsonable( + payload: unknown, + schemaMerges?: Record, +): ProcessExportPayloadResult | null { + const loaded = loadBinding(); + if (!loaded) { + return null; + } + + try { + const payloadJson = JSON.stringify(payload); + const rustSchemaMerges = toRustSchemaMerges(schemaMerges); + const schemaMergesJson = rustSchemaMerges ? JSON.stringify(rustSchemaMerges) : undefined; + const result = loaded.processExportPayload(payloadJson, schemaMergesJson); + + return { + normalizedValue: JSON.parse(result.normalizedJson), + decodedValueHash: result.decodedValueHash, + decodedSchema: normalizeSchemaKeys(JSON.parse(result.decodedSchemaJson)), + decodedSchemaHash: result.decodedSchemaHash, + }; + } catch { + return null; + } +} + +export function buildSpanProtoBytes(input: BuildSpanProtoBytesInput): Buffer | null { + const loaded = loadBinding(); + if (!loaded) { + return null; + } + try { + const rustInput: RustBuildSpanProtoBytesInput = { + traceId: input.traceId, + spanId: input.spanId, + parentSpanId: input.parentSpanId, + name: input.name, + packageName: input.packageName, + instrumentationName: input.instrumentationName, + submoduleName: input.submoduleName, + packageType: input.packageType, + environment: input.environment, + kind: input.kind, + inputSchemaJson: JSON.stringify(denormalizeSchemaKeys(input.inputSchema)), + outputSchemaJson: JSON.stringify(denormalizeSchemaKeys(input.outputSchema)), + inputSchemaHash: input.inputSchemaHash, + outputSchemaHash: input.outputSchemaHash, + inputValueHash: input.inputValueHash, + outputValueHash: input.outputValueHash, + statusCode: input.statusCode, + statusMessage: input.statusMessage, + isPreAppStart: input.isPreAppStart, + isRootSpan: input.isRootSpan, + timestampSeconds: input.timestampSeconds, + timestampNanos: input.timestampNanos, + durationSeconds: input.durationSeconds, + durationNanos: input.durationNanos, + metadataJson: input.metadata === undefined ? undefined : JSON.stringify(input.metadata), + inputValueJson: input.inputValue === undefined ? undefined : JSON.stringify(input.inputValue), + outputValueJson: input.outputValue === undefined ? undefined : JSON.stringify(input.outputValue), + inputValueProtoStructBytes: input.inputValueProtoStructBytes, + outputValueProtoStructBytes: input.outputValueProtoStructBytes, + }; + return loaded.buildSpanProtoBytes(rustInput); + } catch { + return null; + } +} + +export function buildExportSpansRequestBytes( + observableServiceId: string, + environment: string, + sdkVersion: string, + sdkInstanceId: string, + spanProtoBytesList: Buffer[], +): Buffer | null { + const loaded = loadBinding(); + if (!loaded) { + return null; + } + try { + return loaded.buildExportSpansRequestBytes( + observableServiceId, + environment, + sdkVersion, + sdkInstanceId, + spanProtoBytesList, + ); + } catch { + return null; + } +} diff --git a/src/core/tracing/SpanTransformer.ts b/src/core/tracing/SpanTransformer.ts index d09bc8ee..dd1ecea3 100644 --- a/src/core/tracing/SpanTransformer.ts +++ b/src/core/tracing/SpanTransformer.ts @@ -1,14 +1,46 @@ import { ReadableSpan } from "@opentelemetry/sdk-trace-base"; import { SpanKind as OtSpanKind } from "@opentelemetry/api"; -import { JsonSchemaHelper, JsonSchemaType, JsonSchema } from "./JsonSchemaHelper"; +import { JsonSchemaHelper, JsonSchemaType, JsonSchema, SchemaMerges } from "./JsonSchemaHelper"; import { CleanSpanData, TdSpanAttributes } from "../types"; import { PackageType, StatusCode } from "@use-tusk/drift-schemas/core/span"; import { logger } from "../utils"; +import { buildSpanProtoBytes, processExportPayloadJsonable } from "../rustCoreBinding"; /** * Utility class for transforming OpenTelemetry spans to CleanSpanData */ export class SpanTransformer { + private static processPayload( + data: unknown, + schemaMerges?: SchemaMerges, + ): { + normalizedValue: unknown; + schema: JsonSchema; + decodedValueHash: string; + decodedSchemaHash: string; + } { + const rustResult = processExportPayloadJsonable(data, schemaMerges); + if (rustResult) { + return { + normalizedValue: rustResult.normalizedValue, + schema: rustResult.decodedSchema as JsonSchema, + decodedValueHash: rustResult.decodedValueHash, + decodedSchemaHash: rustResult.decodedSchemaHash, + }; + } + + const { schema, decodedValueHash, decodedSchemaHash } = JsonSchemaHelper.generateSchemaAndHash( + data, + schemaMerges, + ); + return { + normalizedValue: data, + schema, + decodedValueHash, + decodedSchemaHash, + }; + } + /** * Transform OpenTelemetry span to clean JSON format with compile-time type safety * Return type is derived from protobuf schema but uses clean JSON. @@ -34,10 +66,11 @@ export class SpanTransformer { : undefined; const { + normalizedValue: normalizedInputData, schema: inputSchema, decodedValueHash: inputValueHash, decodedSchemaHash: inputSchemaHash, - } = JsonSchemaHelper.generateSchemaAndHash(inputData, inputSchemaMerges); + } = SpanTransformer.processPayload(inputData, inputSchemaMerges); // Process output data let outputData: unknown = {}; @@ -56,16 +89,18 @@ export class SpanTransformer { : undefined; ({ + normalizedValue: outputData, schema: outputSchema, decodedValueHash: outputValueHash, decodedSchemaHash: outputSchemaHash, - } = JsonSchemaHelper.generateSchemaAndHash(outputData, outputSchemaMerges)); + } = SpanTransformer.processPayload(outputData, outputSchemaMerges)); } else { ({ + normalizedValue: outputData, schema: outputSchema, decodedValueHash: outputValueHash, decodedSchemaHash: outputSchemaHash, - } = JsonSchemaHelper.generateSchemaAndHash(outputData)); + } = SpanTransformer.processPayload(outputData)); } let metadata: Record | undefined = undefined; @@ -85,6 +120,36 @@ export class SpanTransformer { } } + const protoSpanBytes = buildSpanProtoBytes({ + traceId: span.spanContext().traceId, + spanId: span.spanContext().spanId, + parentSpanId: span.parentSpanId || "", + name: (attributes[TdSpanAttributes.NAME] as string) || "", + packageName, + instrumentationName, + submoduleName: submoduleName || "", + packageType: ((attributes[TdSpanAttributes.PACKAGE_TYPE] as PackageType) || PackageType.UNSPECIFIED) as number, + environment, + kind: span.kind as number, + inputSchema, + outputSchema, + inputSchemaHash, + outputSchemaHash, + inputValueHash, + outputValueHash, + statusCode: span.status.code === 1 ? StatusCode.OK : StatusCode.ERROR, + statusMessage: span.status.message || "", + isPreAppStart: attributes[TdSpanAttributes.IS_PRE_APP_START] === true, + isRootSpan, + timestampSeconds: span.startTime[0], + timestampNanos: span.startTime[1], + durationSeconds: span.duration[0], + durationNanos: span.duration[1], + metadata, + inputValue: normalizedInputData, + outputValue: outputData, + }); + return { traceId: span.spanContext().traceId, spanId: span.spanContext().spanId, @@ -99,7 +164,7 @@ export class SpanTransformer { packageType: (attributes[TdSpanAttributes.PACKAGE_TYPE] as PackageType) ?? undefined, environment, - inputValue: inputData, + inputValue: normalizedInputData, outputValue: outputData, inputSchema, outputSchema, @@ -130,6 +195,7 @@ export class SpanTransformer { isRootSpan, metadata, transformMetadata, + protoSpanBytes: protoSpanBytes ?? undefined, } satisfies CleanSpanData; } diff --git a/src/core/tracing/adapters/ApiSpanAdapter.ts b/src/core/tracing/adapters/ApiSpanAdapter.ts index 570793c2..7d516fe0 100644 --- a/src/core/tracing/adapters/ApiSpanAdapter.ts +++ b/src/core/tracing/adapters/ApiSpanAdapter.ts @@ -2,12 +2,13 @@ import { ExportResult, ExportResultCode } from "@opentelemetry/core"; import type { SpanExportAdapter } from "../TdSpanExporter"; import { CleanSpanData } from "../../types"; import { SpanExportServiceClient } from "@use-tusk/drift-schemas/backend/span_export_service.client"; -import { ExportSpansRequest } from "@use-tusk/drift-schemas/backend/span_export_service"; +import { ExportSpansRequest, ExportSpansResponse } from "@use-tusk/drift-schemas/backend/span_export_service"; import { TwirpFetchTransport } from "@protobuf-ts/twirp-transport"; import { Span, PackageType, SpanKind as DriftSpanKind } from "@use-tusk/drift-schemas/core/span"; import { SpanKind as OtelSpanKind } from "@opentelemetry/api"; import { toStruct } from "../../utils/protobufUtils"; import { logger } from "../../utils/logger"; +import { buildExportSpansRequestBytes } from "../../rustCoreBinding"; export interface ApiSpanAdapterConfig { apiKey: string; @@ -25,6 +26,8 @@ const DRIFT_API_PATH = "/api/drift"; */ export class ApiSpanAdapter implements SpanExportAdapter { readonly name = "api"; + private apiKey: string; + private tuskBackendBaseUrl: string; private spanExportClient: SpanExportServiceClient; private observableServiceId: string; private environment?: string; @@ -32,6 +35,8 @@ export class ApiSpanAdapter implements SpanExportAdapter { private sdkInstanceId: string; constructor(config: ApiSpanAdapterConfig) { + this.apiKey = config.apiKey; + this.tuskBackendBaseUrl = config.tuskBackendBaseUrl; this.observableServiceId = config.observableServiceId; this.environment = config.environment; this.sdkVersion = config.sdkVersion; @@ -51,6 +56,45 @@ export class ApiSpanAdapter implements SpanExportAdapter { async exportSpans(spans: CleanSpanData[]): Promise { try { + const rustRequestBytes = buildExportSpansRequestBytes( + this.observableServiceId, + this.environment || "", + this.sdkVersion, + this.sdkInstanceId, + spans + .map((s) => s.protoSpanBytes) + .filter((s): s is Buffer => Buffer.isBuffer(s)), + ); + const allSpansHavePrebuiltBytes = spans.length > 0 && spans.every((s) => Buffer.isBuffer(s.protoSpanBytes)); + + if (allSpansHavePrebuiltBytes && rustRequestBytes) { + const response = await fetch( + `${this.tuskBackendBaseUrl}${DRIFT_API_PATH}/tusk.drift.backend.v1.SpanExportService/ExportSpans`, + { + method: "POST", + headers: { + "x-api-key": this.apiKey, + "x-td-skip-instrumentation": "true", + "Content-Type": "application/protobuf", + }, + body: new Uint8Array(rustRequestBytes), + }, + ); + + if (!response.ok) { + throw new Error(`Remote export failed with status ${response.status}`); + } + + const responseBytes = new Uint8Array(await response.arrayBuffer()); + const parsed = ExportSpansResponse.fromBinary(responseBytes); + if (!parsed.success) { + throw new Error(`Remote export failed: ${parsed.message}`); + } + + logger.debug(`Successfully exported ${spans.length} spans to remote endpoint (rust binary path)`); + return { code: ExportResultCode.SUCCESS }; + } + // Transform spans to protobuf format const protoSpans: Span[] = spans.map((span) => this.transformSpanToProtobuf(span)); diff --git a/src/core/types.ts b/src/core/types.ts index d7e02676..aaca155b 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -107,6 +107,7 @@ export type CleanSpanData = { // sdk-specific isUsed?: boolean; stackTrace?: string; + protoSpanBytes?: Buffer; }; export type MockRequestData = { diff --git a/src/instrumentation/libraries/fetch/e2e-tests/cjs-fetch/run.sh b/src/instrumentation/libraries/fetch/e2e-tests/cjs-fetch/run.sh index 55cb5d5a..dd9ca100 100755 --- a/src/instrumentation/libraries/fetch/e2e-tests/cjs-fetch/run.sh +++ b/src/instrumentation/libraries/fetch/e2e-tests/cjs-fetch/run.sh @@ -34,7 +34,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/fetch/e2e-tests/esm-fetch/run.sh b/src/instrumentation/libraries/fetch/e2e-tests/esm-fetch/run.sh index 4cb7ab08..8795bfb0 100755 --- a/src/instrumentation/libraries/fetch/e2e-tests/esm-fetch/run.sh +++ b/src/instrumentation/libraries/fetch/e2e-tests/esm-fetch/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/firestore/e2e-tests/cjs-firestore/run.sh b/src/instrumentation/libraries/firestore/e2e-tests/cjs-firestore/run.sh index 45af8741..8fa4f0cb 100755 --- a/src/instrumentation/libraries/firestore/e2e-tests/cjs-firestore/run.sh +++ b/src/instrumentation/libraries/firestore/e2e-tests/cjs-firestore/run.sh @@ -44,7 +44,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/firestore/e2e-tests/esm-firestore/run.sh b/src/instrumentation/libraries/firestore/e2e-tests/esm-firestore/run.sh index 8c55980a..e74dfdb8 100755 --- a/src/instrumentation/libraries/firestore/e2e-tests/esm-firestore/run.sh +++ b/src/instrumentation/libraries/firestore/e2e-tests/esm-firestore/run.sh @@ -44,7 +44,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/grpc/e2e-tests/cjs-grpc/run.sh b/src/instrumentation/libraries/grpc/e2e-tests/cjs-grpc/run.sh index c90b8a2a..4c0d9286 100755 --- a/src/instrumentation/libraries/grpc/e2e-tests/cjs-grpc/run.sh +++ b/src/instrumentation/libraries/grpc/e2e-tests/cjs-grpc/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/grpc/e2e-tests/esm-grpc/run.sh b/src/instrumentation/libraries/grpc/e2e-tests/esm-grpc/run.sh index 5bcbeca7..f113ea85 100755 --- a/src/instrumentation/libraries/grpc/e2e-tests/esm-grpc/run.sh +++ b/src/instrumentation/libraries/grpc/e2e-tests/esm-grpc/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/http/e2e-tests/cjs-http/run.sh b/src/instrumentation/libraries/http/e2e-tests/cjs-http/run.sh index 5e081718..b67bc91f 100755 --- a/src/instrumentation/libraries/http/e2e-tests/cjs-http/run.sh +++ b/src/instrumentation/libraries/http/e2e-tests/cjs-http/run.sh @@ -40,7 +40,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/http/e2e-tests/esm-http/run.sh b/src/instrumentation/libraries/http/e2e-tests/esm-http/run.sh index f7d0102e..847bf647 100755 --- a/src/instrumentation/libraries/http/e2e-tests/esm-http/run.sh +++ b/src/instrumentation/libraries/http/e2e-tests/esm-http/run.sh @@ -40,7 +40,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/ioredis/e2e-tests/cjs-ioredis/run.sh b/src/instrumentation/libraries/ioredis/e2e-tests/cjs-ioredis/run.sh index 89d5d240..9db922e9 100755 --- a/src/instrumentation/libraries/ioredis/e2e-tests/cjs-ioredis/run.sh +++ b/src/instrumentation/libraries/ioredis/e2e-tests/cjs-ioredis/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/ioredis/e2e-tests/esm-ioredis/run.sh b/src/instrumentation/libraries/ioredis/e2e-tests/esm-ioredis/run.sh index d10d67e7..5002f1d6 100755 --- a/src/instrumentation/libraries/ioredis/e2e-tests/esm-ioredis/run.sh +++ b/src/instrumentation/libraries/ioredis/e2e-tests/esm-ioredis/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/mysql/e2e-tests/cjs-mysql/run.sh b/src/instrumentation/libraries/mysql/e2e-tests/cjs-mysql/run.sh index f9b02f38..f656f6ee 100755 --- a/src/instrumentation/libraries/mysql/e2e-tests/cjs-mysql/run.sh +++ b/src/instrumentation/libraries/mysql/e2e-tests/cjs-mysql/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/mysql/e2e-tests/esm-mysql/run.sh b/src/instrumentation/libraries/mysql/e2e-tests/esm-mysql/run.sh index 09249948..396260ac 100755 --- a/src/instrumentation/libraries/mysql/e2e-tests/esm-mysql/run.sh +++ b/src/instrumentation/libraries/mysql/e2e-tests/esm-mysql/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/mysql2/e2e-tests/cjs-mysql2/run.sh b/src/instrumentation/libraries/mysql2/e2e-tests/cjs-mysql2/run.sh index 6044dcb9..6bfd9ca0 100755 --- a/src/instrumentation/libraries/mysql2/e2e-tests/cjs-mysql2/run.sh +++ b/src/instrumentation/libraries/mysql2/e2e-tests/cjs-mysql2/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/mysql2/e2e-tests/esm-mysql2/run.sh b/src/instrumentation/libraries/mysql2/e2e-tests/esm-mysql2/run.sh index 7867e91c..10ceb41e 100755 --- a/src/instrumentation/libraries/mysql2/e2e-tests/esm-mysql2/run.sh +++ b/src/instrumentation/libraries/mysql2/e2e-tests/esm-mysql2/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/nextjs/e2e-tests/cjs-nextjs/run.sh b/src/instrumentation/libraries/nextjs/e2e-tests/cjs-nextjs/run.sh index 424260bb..bedb39bc 100755 --- a/src/instrumentation/libraries/nextjs/e2e-tests/cjs-nextjs/run.sh +++ b/src/instrumentation/libraries/nextjs/e2e-tests/cjs-nextjs/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/nextjs/e2e-tests/esm-nextjs/run.sh b/src/instrumentation/libraries/nextjs/e2e-tests/esm-nextjs/run.sh index 78e9dc15..60f808e4 100755 --- a/src/instrumentation/libraries/nextjs/e2e-tests/esm-nextjs/run.sh +++ b/src/instrumentation/libraries/nextjs/e2e-tests/esm-nextjs/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/pg/e2e-tests/cjs-pg/run.sh b/src/instrumentation/libraries/pg/e2e-tests/cjs-pg/run.sh index 9b1805cb..05e8e2c0 100755 --- a/src/instrumentation/libraries/pg/e2e-tests/cjs-pg/run.sh +++ b/src/instrumentation/libraries/pg/e2e-tests/cjs-pg/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/pg/e2e-tests/esm-pg/run.sh b/src/instrumentation/libraries/pg/e2e-tests/esm-pg/run.sh index 643d9495..24b95e8d 100755 --- a/src/instrumentation/libraries/pg/e2e-tests/esm-pg/run.sh +++ b/src/instrumentation/libraries/pg/e2e-tests/esm-pg/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/postgres/e2e-tests/cjs-postgres/run.sh b/src/instrumentation/libraries/postgres/e2e-tests/cjs-postgres/run.sh index 33ee0467..a8f299d3 100755 --- a/src/instrumentation/libraries/postgres/e2e-tests/cjs-postgres/run.sh +++ b/src/instrumentation/libraries/postgres/e2e-tests/cjs-postgres/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/postgres/e2e-tests/cjs-postgres/src/index.ts b/src/instrumentation/libraries/postgres/e2e-tests/cjs-postgres/src/index.ts index e7469230..46e75e5e 100644 --- a/src/instrumentation/libraries/postgres/e2e-tests/cjs-postgres/src/index.ts +++ b/src/instrumentation/libraries/postgres/e2e-tests/cjs-postgres/src/index.ts @@ -199,18 +199,29 @@ app.post("/cache/insert", async (req: Request, res: Response) => { const { key, value } = req.body; const timestamp = Date.now(); + const insertKey = key || `test_key_${timestamp}`; + const insertValue = value || `test_value_${timestamp}`; + const expiresAt = new Date(Date.now() + 86400000); // 1 day from now const result = await db .insert(cacheTable) .values({ - key: key || `test_key_${timestamp}`, - value: value || `test_value_${timestamp}`, - expiresAt: new Date(Date.now() + 86400000), // 1 day from now + key: insertKey, + value: insertValue, + expiresAt, + }) + .onConflictDoUpdate({ + target: cacheTable.key, + set: { + value: insertValue, + expiresAt, + updatedAt: new Date(), + }, }) .returning(); res.json({ - message: "Cache entry inserted", + message: "Cache entry inserted or updated", data: result, }); } catch (error: any) { diff --git a/src/instrumentation/libraries/postgres/e2e-tests/esm-postgres/run.sh b/src/instrumentation/libraries/postgres/e2e-tests/esm-postgres/run.sh index 7234fbc7..9658e7c3 100755 --- a/src/instrumentation/libraries/postgres/e2e-tests/esm-postgres/run.sh +++ b/src/instrumentation/libraries/postgres/e2e-tests/esm-postgres/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/postgres/e2e-tests/esm-postgres/src/index.ts b/src/instrumentation/libraries/postgres/e2e-tests/esm-postgres/src/index.ts index f5eb7317..bd0d75d2 100644 --- a/src/instrumentation/libraries/postgres/e2e-tests/esm-postgres/src/index.ts +++ b/src/instrumentation/libraries/postgres/e2e-tests/esm-postgres/src/index.ts @@ -214,20 +214,31 @@ app.post("/cache/insert", async (req: Request, res: Response) => { const { key, value } = req.body; const timestamp = Date.now(); + const insertKey = key || `test_key_${timestamp}`; + const insertValue = value || `test_value_${timestamp}`; + const expiresAt = new Date(Date.now() + 86400000); // 1 day from now const result = await db .insert(cacheTable) .values({ - key: key || `test_key_${timestamp}`, - value: value || `test_value_${timestamp}`, - expiresAt: new Date(Date.now() + 86400000), // 1 day from now + key: insertKey, + value: insertValue, + expiresAt, + }) + .onConflictDoUpdate({ + target: cacheTable.key, + set: { + value: insertValue, + expiresAt, + updatedAt: new Date(), + }, }) .returning(); console.log("Insert result:", result); res.json({ - message: "Cache entry inserted", + message: "Cache entry inserted or updated", data: result, }); } catch (error: any) { diff --git a/src/instrumentation/libraries/prisma/e2e-tests/cjs-prisma/run.sh b/src/instrumentation/libraries/prisma/e2e-tests/cjs-prisma/run.sh index 52700583..e731ce0b 100755 --- a/src/instrumentation/libraries/prisma/e2e-tests/cjs-prisma/run.sh +++ b/src/instrumentation/libraries/prisma/e2e-tests/cjs-prisma/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/prisma/e2e-tests/esm-prisma/run.sh b/src/instrumentation/libraries/prisma/e2e-tests/esm-prisma/run.sh index 8d2170c6..f361dc43 100755 --- a/src/instrumentation/libraries/prisma/e2e-tests/esm-prisma/run.sh +++ b/src/instrumentation/libraries/prisma/e2e-tests/esm-prisma/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/upstash-redis-js/e2e-tests/cjs-upstash-redis-js/run.sh b/src/instrumentation/libraries/upstash-redis-js/e2e-tests/cjs-upstash-redis-js/run.sh index 1d894f03..6d7fe44d 100755 --- a/src/instrumentation/libraries/upstash-redis-js/e2e-tests/cjs-upstash-redis-js/run.sh +++ b/src/instrumentation/libraries/upstash-redis-js/e2e-tests/cjs-upstash-redis-js/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e diff --git a/src/instrumentation/libraries/upstash-redis-js/e2e-tests/esm-upstash-redis-js/run.sh b/src/instrumentation/libraries/upstash-redis-js/e2e-tests/esm-upstash-redis-js/run.sh index b6939298..63a270cf 100755 --- a/src/instrumentation/libraries/upstash-redis-js/e2e-tests/esm-upstash-redis-js/run.sh +++ b/src/instrumentation/libraries/upstash-redis-js/e2e-tests/esm-upstash-redis-js/run.sh @@ -33,7 +33,7 @@ echo -e "${BLUE}Starting test...${NC}" echo "" set +e -docker compose -p "$PROJECT_NAME" run --rm app +docker compose -p "$PROJECT_NAME" run --rm -e TUSK_USE_RUST_CORE="${TUSK_USE_RUST_CORE:-}" app EXIT_CODE=$? set -e From 19d66abc61ee3dfa481bf4f6494083ad57eb0c8d Mon Sep 17 00:00:00 2001 From: JY Tan Date: Thu, 19 Feb 2026 20:19:32 -0800 Subject: [PATCH 02/15] Try running mysql2 e2e sequentially --- src/instrumentation/libraries/mysql2/e2e-tests/run-all.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/instrumentation/libraries/mysql2/e2e-tests/run-all.sh b/src/instrumentation/libraries/mysql2/e2e-tests/run-all.sh index e546986e..3fc01f78 100755 --- a/src/instrumentation/libraries/mysql2/e2e-tests/run-all.sh +++ b/src/instrumentation/libraries/mysql2/e2e-tests/run-all.sh @@ -11,4 +11,4 @@ source "$SCRIPT_DIR/../../e2e-common/e2e-helpers.sh" # Run all E2E tests for mysql2 # Accepts optional base port parameter (default: 3000) -run_all_e2e_tests "$SCRIPT_DIR" "mysql2" "${1:-3000}" +run_all_e2e_tests "$SCRIPT_DIR" "mysql2" "${1:-3000}" "sequential" From 8decbfe5b50acc55d5da5c18999bd97e6b0b7c6c Mon Sep 17 00:00:00 2001 From: JY Tan Date: Thu, 19 Feb 2026 20:35:18 -0800 Subject: [PATCH 03/15] Try fix --- .../libraries/mysql2/Instrumentation.ts | 67 ++++++++++--------- .../mysql2/mocks/TdMysql2QueryMock.ts | 17 ++++- 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/src/instrumentation/libraries/mysql2/Instrumentation.ts b/src/instrumentation/libraries/mysql2/Instrumentation.ts index 878e4990..f4502d27 100644 --- a/src/instrumentation/libraries/mysql2/Instrumentation.ts +++ b/src/instrumentation/libraries/mysql2/Instrumentation.ts @@ -1549,6 +1549,9 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { callback: Function | undefined, context: Pool, ): any { + // Preserve request trace context across mysql2 callback/promise boundaries. + const parentContext = otelContext.active(); + if (callback) { // Callback-based getConnection const wrappedCallback = (error: Error | null, connection?: PoolConnection) => { @@ -1580,45 +1583,49 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { logger.error(`[Mysql2Instrumentation] error processing getConnection response:`, error); } } - return callback(error, connection); + return otelContext.with(parentContext, () => callback(error, connection)); }; - return originalGetConnection.call(context, wrappedCallback); + return otelContext.with(parentContext, () => originalGetConnection.call(context, wrappedCallback)); } else { // Promise-based getConnection - const promise = originalGetConnection.call(context); + const promise = otelContext.with(parentContext, () => originalGetConnection.call(context)); return promise .then((connection: PoolConnection) => { - logger.debug( - `[Mysql2Instrumentation] MySQL2 Pool getConnection completed successfully (${SpanUtils.getTraceInfo()})`, - ); - try { - SpanUtils.addSpanAttributes(spanInfo.span, { - outputValue: { - connected: true, - hasConnection: !!connection, - }, - }); - SpanUtils.endSpan(spanInfo.span, { code: SpanStatusCode.OK }); - } catch (error) { - logger.error(`[Mysql2Instrumentation] error processing getConnection response:`, error); - } - return connection; + return otelContext.with(parentContext, () => { + logger.debug( + `[Mysql2Instrumentation] MySQL2 Pool getConnection completed successfully (${SpanUtils.getTraceInfo()})`, + ); + try { + SpanUtils.addSpanAttributes(spanInfo.span, { + outputValue: { + connected: true, + hasConnection: !!connection, + }, + }); + SpanUtils.endSpan(spanInfo.span, { code: SpanStatusCode.OK }); + } catch (error) { + logger.error(`[Mysql2Instrumentation] error processing getConnection response:`, error); + } + return connection; + }); }) .catch((error: Error) => { - logger.debug( - `[Mysql2Instrumentation] MySQL2 Pool getConnection error: ${error.message} (${SpanUtils.getTraceInfo()})`, - ); - try { - SpanUtils.endSpan(spanInfo.span, { - code: SpanStatusCode.ERROR, - message: error.message, - }); - } catch (error) { - logger.error(`[Mysql2Instrumentation] error ending span:`, error); - } - throw error; + return otelContext.with(parentContext, () => { + logger.debug( + `[Mysql2Instrumentation] MySQL2 Pool getConnection error: ${error.message} (${SpanUtils.getTraceInfo()})`, + ); + try { + SpanUtils.endSpan(spanInfo.span, { + code: SpanStatusCode.ERROR, + message: error.message, + }); + } catch (error) { + logger.error(`[Mysql2Instrumentation] error ending span:`, error); + } + throw error; + }); }); } } diff --git a/src/instrumentation/libraries/mysql2/mocks/TdMysql2QueryMock.ts b/src/instrumentation/libraries/mysql2/mocks/TdMysql2QueryMock.ts index b26b41fa..b685420e 100644 --- a/src/instrumentation/libraries/mysql2/mocks/TdMysql2QueryMock.ts +++ b/src/instrumentation/libraries/mysql2/mocks/TdMysql2QueryMock.ts @@ -1,7 +1,7 @@ import { EventEmitter } from "events"; import { Readable } from "stream"; import { SpanKind } from "@opentelemetry/api"; -import { SpanInfo } from "../../../../core/tracing/SpanUtils"; +import { SpanInfo, SpanUtils } from "../../../../core/tracing/SpanUtils"; import { TuskDriftCore } from "../../../../core/TuskDrift"; import { findMockResponseAsync } from "../../../core/utils/mockResponseUtils"; import { logger } from "../../../../core/utils/logger"; @@ -142,6 +142,17 @@ export class TdMysql2QueryMock { if (!mockData) { const sql = queryConfig.sql || inputValue.sql || "UNKNOWN_QUERY"; logger.warn(`[Mysql2Instrumentation] No mock data found for MySQL2 query: ${sql}`); + logger.warn(`[Mysql2Instrumentation] Replay mock miss diagnostics`, { + traceId: spanInfo.traceId, + spanId: spanInfo.spanId, + replayTraceId: SpanUtils.getCurrentReplayTraceId(), + spanName, + submoduleName, + clientType: inputValue.clientType, + querySql: sql, + normalizedQuerySql: this._normalizeSqlForDebug(sql), + valuesCount: Array.isArray(inputValue.values) ? inputValue.values.length : 0, + }); throw new Error(`[Mysql2Instrumentation] No matching mock found for query: ${sql}`); } @@ -322,4 +333,8 @@ export class TdMysql2QueryMock { fields: [], }; } + + private _normalizeSqlForDebug(sql: string): string { + return sql.replace(/\s+/g, " ").trim().toLowerCase(); + } } From 5314c92329c2c4a2ea4ecd6c6967f93e6a9a7dff Mon Sep 17 00:00:00 2001 From: JY Tan Date: Fri, 20 Feb 2026 13:32:28 -0800 Subject: [PATCH 04/15] Fix --- .../libraries/mysql2/mocks/TdMysql2ConnectionMock.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts index ec774df9..197a3e56 100644 --- a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts +++ b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts @@ -69,6 +69,7 @@ export class TdMysql2ConnectionMock extends EventEmitter { queryConfig, inputValue, this.spanInfo, + "query", stackTrace, ); } else { @@ -111,6 +112,7 @@ export class TdMysql2ConnectionMock extends EventEmitter { queryConfig, inputValue, this.spanInfo, + "execute", stackTrace, ); } else { From 43212798c2c71f175829cd0a9caded83b5e6e3ae Mon Sep 17 00:00:00 2001 From: JY Tan Date: Fri, 20 Feb 2026 13:41:48 -0800 Subject: [PATCH 05/15] Print logs --- .../libraries/e2e-common/base-entrypoint.sh | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/instrumentation/libraries/e2e-common/base-entrypoint.sh b/src/instrumentation/libraries/e2e-common/base-entrypoint.sh index 5e9328fd..963f4808 100644 --- a/src/instrumentation/libraries/e2e-common/base-entrypoint.sh +++ b/src/instrumentation/libraries/e2e-common/base-entrypoint.sh @@ -35,6 +35,28 @@ NC='\033[0m' log() { echo -e "${2:-$NC}$1${NC}"; } +# Print targeted replay diagnostics to make CI failures actionable. +print_replay_diagnostics() { + log "================================================" "$YELLOW" + log "Replay diagnostics (from .tusk/logs)" "$YELLOW" + log "================================================" "$YELLOW" + + if [ ! -d ".tusk/logs" ]; then + log "No .tusk/logs directory found." "$YELLOW" + return + fi + + local patterns="Replay mock miss diagnostics|No matching mock found for query|Mysql2Instrumentation|ROLLBACK" + local matched + matched=$(grep -R --line-number -E "$patterns" .tusk/logs 2>/dev/null || true) + + if [ -n "$matched" ]; then + echo "$matched" + else + log "No matching replay diagnostics found in .tusk/logs." "$YELLOW" + fi +} + # Stop the server and all its child processes (npm spawns node underneath) stop_server() { if [ -n "$SERVER_PID" ]; then @@ -239,6 +261,7 @@ echo "$TEST_OUTPUT" # Check tusk exit code if [ $TUSK_EXIT -ne 0 ]; then log "Tusk tests failed with exit code $TUSK_EXIT" "$RED" + print_replay_diagnostics exit 1 fi @@ -249,6 +272,7 @@ ANY_FAILED=$(echo "$TEST_OUTPUT" | grep -c '"passed":\s*false' || true) log "================================================" if [ "$ANY_FAILED" -gt 0 ]; then log "Some tests failed!" "$RED" + print_replay_diagnostics exit 1 elif [ "$ALL_PASSED" -gt 0 ]; then log "All $ALL_PASSED tests passed!" "$GREEN" From 58c9005d5c8f595c1c985fbf0d5bd8f59af80fbf Mon Sep 17 00:00:00 2001 From: JY Tan Date: Fri, 20 Feb 2026 14:10:10 -0800 Subject: [PATCH 06/15] Fix mock clientType --- src/instrumentation/libraries/mysql2/Instrumentation.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/instrumentation/libraries/mysql2/Instrumentation.ts b/src/instrumentation/libraries/mysql2/Instrumentation.ts index f4502d27..364c47f1 100644 --- a/src/instrumentation/libraries/mysql2/Instrumentation.ts +++ b/src/instrumentation/libraries/mysql2/Instrumentation.ts @@ -1635,7 +1635,7 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { `[Mysql2Instrumentation] Background getConnection detected, returning mock connection`, ); - const mockConnection = new TdMysql2ConnectionMock(this, "pool"); + const mockConnection = new TdMysql2ConnectionMock(this, "poolConnection"); if (callback) { process.nextTick(() => callback(null, mockConnection)); @@ -1648,7 +1648,7 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { logger.debug(`[Mysql2Instrumentation] Replaying MySQL2 Pool getConnection`); // For pool getConnection operations, simulate returning a mock connection - const mockConnection = new TdMysql2ConnectionMock(this, "pool", spanInfo); + const mockConnection = new TdMysql2ConnectionMock(this, "poolConnection", spanInfo); if (callback) { process.nextTick(() => callback(null, mockConnection)); From 8623149b1def9bfba769452ffb3bfada6fb0d250 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Fri, 20 Feb 2026 14:19:17 -0800 Subject: [PATCH 07/15] Add more diagnostics output --- .../libraries/e2e-common/base-entrypoint.sh | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/instrumentation/libraries/e2e-common/base-entrypoint.sh b/src/instrumentation/libraries/e2e-common/base-entrypoint.sh index 963f4808..013a8944 100644 --- a/src/instrumentation/libraries/e2e-common/base-entrypoint.sh +++ b/src/instrumentation/libraries/e2e-common/base-entrypoint.sh @@ -50,11 +50,33 @@ print_replay_diagnostics() { local matched matched=$(grep -R --line-number -E "$patterns" .tusk/logs 2>/dev/null || true) - if [ -n "$matched" ]; then - echo "$matched" - else + if [ -z "$matched" ]; then log "No matching replay diagnostics found in .tusk/logs." "$YELLOW" + return fi + + echo "$matched" + log "" + log "Expanded miss contexts:" "$YELLOW" + + local miss_lines + miss_lines=$(grep -R --line-number "Replay mock miss diagnostics" .tusk/logs 2>/dev/null || true) + if [ -z "$miss_lines" ]; then + return + fi + + # Print a focused context window around each miss diagnostics block. + while IFS= read -r hit; do + [ -z "$hit" ] && continue + local file + local line + file=$(echo "$hit" | cut -d: -f1) + line=$(echo "$hit" | cut -d: -f2) + local start=$((line > 3 ? line - 3 : 1)) + local end=$((line + 20)) + log "--- $file:$start-$end ---" "$YELLOW" + sed -n "${start},${end}p" "$file" 2>/dev/null || true + done <<< "$miss_lines" } # Stop the server and all its child processes (npm spawns node underneath) From f1ba86fca5ce2d35639ed02b8ac3e015a69738ab Mon Sep 17 00:00:00 2001 From: JY Tan Date: Fri, 20 Feb 2026 14:28:15 -0800 Subject: [PATCH 08/15] Try this --- .../libraries/mysql2/mocks/TdMysql2ConnectionMock.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts index 197a3e56..fd1423a4 100644 --- a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts +++ b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts @@ -58,7 +58,7 @@ export class TdMysql2ConnectionMock extends EventEmitter { const rawInputValue = { sql: queryConfig.sql, - values: queryConfig.values || [], + values: queryConfig.values, clientType: this.clientType, // Use the stored clientType instead of hardcoded value }; @@ -101,7 +101,7 @@ export class TdMysql2ConnectionMock extends EventEmitter { const rawInputValue = { sql: queryConfig.sql, - values: queryConfig.values || [], + values: queryConfig.values, clientType: this.clientType, // Use the stored clientType instead of hardcoded value }; From b88a1d7c5fb4682ecae5e40f119d35ff8bcc57db Mon Sep 17 00:00:00 2001 From: JY Tan Date: Fri, 20 Feb 2026 14:38:36 -0800 Subject: [PATCH 09/15] Try again --- .../libraries/mysql2/mocks/TdMysql2ConnectionMock.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts index fd1423a4..d97a95fb 100644 --- a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts +++ b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts @@ -39,7 +39,8 @@ export class TdMysql2ConnectionMock extends EventEmitter { query(...args: any[]) { logger.debug(`[TdMysql2ConnectionMock] Mock connection query intercepted in REPLAY mode`); - const stackTrace = captureStackTrace(["TdMysql2ConnectionMock"]); + // Match recording-path stack trace normalization used by mysql2 instrumentation. + const stackTrace = captureStackTrace(["Mysql2Instrumentation"]); // Parse query arguments similar to the main query patch const queryConfig = this.mysql2Instrumentation.parseQueryArgs(args); @@ -82,7 +83,8 @@ export class TdMysql2ConnectionMock extends EventEmitter { execute(...args: any[]) { logger.debug(`[TdMysql2ConnectionMock] Mock connection execute intercepted in REPLAY mode`); - const stackTrace = captureStackTrace(["TdMysql2ConnectionMock"]); + // Match recording-path stack trace normalization used by mysql2 instrumentation. + const stackTrace = captureStackTrace(["Mysql2Instrumentation"]); // Parse execute arguments similar to the main execute patch const queryConfig = this.mysql2Instrumentation.parseQueryArgs(args); From 513a725b63a6b8cbbf2fe45222e667adaf2cdc33 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Fri, 20 Feb 2026 14:55:34 -0800 Subject: [PATCH 10/15] Try this --- .../libraries/mysql2/Instrumentation.ts | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/instrumentation/libraries/mysql2/Instrumentation.ts b/src/instrumentation/libraries/mysql2/Instrumentation.ts index 364c47f1..bface34f 100644 --- a/src/instrumentation/libraries/mysql2/Instrumentation.ts +++ b/src/instrumentation/libraries/mysql2/Instrumentation.ts @@ -32,6 +32,7 @@ const V3_11_5_TO_4_0 = ">=3.11.5 <4.0.0"; export class Mysql2Instrumentation extends TdInstrumentationBase { private readonly INSTRUMENTATION_NAME = "Mysql2Instrumentation"; + private readonly CONTEXT_BOUND_CONNECTION = Symbol("mysql2-context-bound-connection"); private mode: TuskDriftMode; private queryMock: TdMysql2QueryMock; @@ -1555,6 +1556,9 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { if (callback) { // Callback-based getConnection const wrappedCallback = (error: Error | null, connection?: PoolConnection) => { + const scopedConnection = connection + ? this._bindConnectionMethodsToContext(connection, parentContext) + : connection; if (error) { logger.debug( `[Mysql2Instrumentation] MySQL2 Pool getConnection error: ${error.message} (${SpanUtils.getTraceInfo()})`, @@ -1575,7 +1579,7 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true, - hasConnection: !!connection, + hasConnection: !!scopedConnection, }, }); SpanUtils.endSpan(spanInfo.span, { code: SpanStatusCode.OK }); @@ -1583,7 +1587,7 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { logger.error(`[Mysql2Instrumentation] error processing getConnection response:`, error); } } - return otelContext.with(parentContext, () => callback(error, connection)); + return otelContext.with(parentContext, () => callback(error, scopedConnection)); }; return otelContext.with(parentContext, () => originalGetConnection.call(context, wrappedCallback)); @@ -1593,6 +1597,7 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { return promise .then((connection: PoolConnection) => { + const scopedConnection = this._bindConnectionMethodsToContext(connection, parentContext); return otelContext.with(parentContext, () => { logger.debug( `[Mysql2Instrumentation] MySQL2 Pool getConnection completed successfully (${SpanUtils.getTraceInfo()})`, @@ -1601,14 +1606,14 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true, - hasConnection: !!connection, + hasConnection: !!scopedConnection, }, }); SpanUtils.endSpan(spanInfo.span, { code: SpanStatusCode.OK }); } catch (error) { logger.error(`[Mysql2Instrumentation] error processing getConnection response:`, error); } - return connection; + return scopedConnection; }); }) .catch((error: Error) => { @@ -1630,6 +1635,28 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { } } + private _bindConnectionMethodsToContext( + connection: PoolConnection, + parentContext: ReturnType, + ): PoolConnection { + const conn = connection as any; + if (!conn || conn[this.CONTEXT_BOUND_CONNECTION]) { + return connection; + } + + const methods = ["query", "execute", "beginTransaction", "commit", "rollback"]; + for (const method of methods) { + const original = conn[method]; + if (typeof original !== "function") continue; + conn[method] = (...args: any[]) => { + return otelContext.with(parentContext, () => original.apply(conn, args)); + }; + } + + conn[this.CONTEXT_BOUND_CONNECTION] = true; + return connection; + } + private handleNoOpReplayGetConnection(callback?: Function): any { logger.debug( `[Mysql2Instrumentation] Background getConnection detected, returning mock connection`, From c5c9315ce3b272d441b741f7615489dd23eafb69 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Fri, 20 Feb 2026 15:08:33 -0800 Subject: [PATCH 11/15] Try again --- .../libraries/mysql2/mocks/TdMysql2ConnectionMock.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts index d97a95fb..aa7d76b3 100644 --- a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts +++ b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts @@ -4,7 +4,6 @@ import { createMockInputValue } from "../../../../core/utils"; import { SpanInfo } from "../../../../core/tracing/SpanUtils"; import { logger } from "../../../../core/utils/logger"; import { QueryCallback } from "../types"; -import { captureStackTrace } from "src/instrumentation/core/utils"; /** * Mock MySQL2 connection/pool connection for replay mode @@ -39,8 +38,9 @@ export class TdMysql2ConnectionMock extends EventEmitter { query(...args: any[]) { logger.debug(`[TdMysql2ConnectionMock] Mock connection query intercepted in REPLAY mode`); - // Match recording-path stack trace normalization used by mysql2 instrumentation. - const stackTrace = captureStackTrace(["Mysql2Instrumentation"]); + // Avoid using stack trace as a hard matching key for connection-derived replay queries. + // Stack frames differ across environments (e.g. CI container/runtime), causing false misses. + const stackTrace: string | undefined = undefined; // Parse query arguments similar to the main query patch const queryConfig = this.mysql2Instrumentation.parseQueryArgs(args); @@ -83,8 +83,9 @@ export class TdMysql2ConnectionMock extends EventEmitter { execute(...args: any[]) { logger.debug(`[TdMysql2ConnectionMock] Mock connection execute intercepted in REPLAY mode`); - // Match recording-path stack trace normalization used by mysql2 instrumentation. - const stackTrace = captureStackTrace(["Mysql2Instrumentation"]); + // Avoid using stack trace as a hard matching key for connection-derived replay queries. + // Stack frames differ across environments (e.g. CI container/runtime), causing false misses. + const stackTrace: string | undefined = undefined; // Parse execute arguments similar to the main execute patch const queryConfig = this.mysql2Instrumentation.parseQueryArgs(args); From 9046d16735f79b69eee36335194f131050513f02 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Fri, 20 Feb 2026 15:17:34 -0800 Subject: [PATCH 12/15] Add more diagnostics --- .../libraries/e2e-common/base-entrypoint.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/instrumentation/libraries/e2e-common/base-entrypoint.sh b/src/instrumentation/libraries/e2e-common/base-entrypoint.sh index 013a8944..011aec02 100644 --- a/src/instrumentation/libraries/e2e-common/base-entrypoint.sh +++ b/src/instrumentation/libraries/e2e-common/base-entrypoint.sh @@ -266,6 +266,19 @@ if [ "$TRACE_COUNT" -eq 0 ]; then exit 1 fi +# Print focused trace-presence diagnostics for flaky SQL replay mismatches. +# This helps distinguish "not recorded" from "recorded but not matched in replay". +log "Trace SQL presence checks (recorded traces):" "$BLUE" +SQL_PATTERNS=( + "SELECT COUNT\\(\\*\\) as total FROM test_users" + "SAVEPOINT" + "ROLLBACK" +) +for pattern in "${SQL_PATTERNS[@]}"; do + count=$(grep -R -E -c "$pattern" .tusk/traces 2>/dev/null | awk -F: '{s+=$2} END {print s+0}') + log " pattern='$pattern' count=$count" "$BLUE" +done + # ============================================================ # Phase 3: Run Tusk Tests # ============================================================ From 811f8d875519b9f1e2d97dccd8ab268a30790c47 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Fri, 20 Feb 2026 16:10:17 -0800 Subject: [PATCH 13/15] Try this --- .../libraries/e2e-common/base-entrypoint.sh | 13 -------- .../libraries/mysql2/Instrumentation.ts | 33 ++++++++++++++++--- .../mysql2/mocks/TdMysql2ConnectionMock.ts | 8 ++--- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/instrumentation/libraries/e2e-common/base-entrypoint.sh b/src/instrumentation/libraries/e2e-common/base-entrypoint.sh index 011aec02..013a8944 100644 --- a/src/instrumentation/libraries/e2e-common/base-entrypoint.sh +++ b/src/instrumentation/libraries/e2e-common/base-entrypoint.sh @@ -266,19 +266,6 @@ if [ "$TRACE_COUNT" -eq 0 ]; then exit 1 fi -# Print focused trace-presence diagnostics for flaky SQL replay mismatches. -# This helps distinguish "not recorded" from "recorded but not matched in replay". -log "Trace SQL presence checks (recorded traces):" "$BLUE" -SQL_PATTERNS=( - "SELECT COUNT\\(\\*\\) as total FROM test_users" - "SAVEPOINT" - "ROLLBACK" -) -for pattern in "${SQL_PATTERNS[@]}"; do - count=$(grep -R -E -c "$pattern" .tusk/traces 2>/dev/null | awk -F: '{s+=$2} END {print s+0}') - log " pattern='$pattern' count=$count" "$BLUE" -done - # ============================================================ # Phase 3: Run Tusk Tests # ============================================================ diff --git a/src/instrumentation/libraries/mysql2/Instrumentation.ts b/src/instrumentation/libraries/mysql2/Instrumentation.ts index bface34f..758b8853 100644 --- a/src/instrumentation/libraries/mysql2/Instrumentation.ts +++ b/src/instrumentation/libraries/mysql2/Instrumentation.ts @@ -374,7 +374,7 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { } const inputValue: Mysql2InputValue = { - sql: queryConfig.sql, + sql: self.normalizeSqlForMockMatching(queryConfig.sql), values: queryConfig.values || [], clientType, }; @@ -485,7 +485,7 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { } const inputValue: Mysql2InputValue = { - sql: queryConfig.sql, + sql: self.normalizeSqlForMockMatching(queryConfig.sql), values: queryConfig.values || [], clientType, }; @@ -1403,6 +1403,29 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { return null; } + normalizeSqlForMockMatching(sql: string): string { + if (!sql) return sql; + + const trimmed = sql.trim(); + + // knex nested transactions: SAVEPOINT trx[;] + if (/^savepoint\s+trx\d+\s*;?$/i.test(trimmed)) { + return trimmed.replace(/^(savepoint\s+)trx\d+(\s*;?)$/i, "$1trx$2"); + } + + // knex savepoint release: RELEASE SAVEPOINT trx[;] + if (/^release\s+savepoint\s+trx\d+\s*;?$/i.test(trimmed)) { + return trimmed.replace(/^(release\s+savepoint\s+)trx\d+(\s*;?)$/i, "$1trx$2"); + } + + // knex rollback to savepoint: ROLLBACK TO SAVEPOINT trx[;] + if (/^rollback\s+to\s+savepoint\s+trx\d+\s*;?$/i.test(trimmed)) { + return trimmed.replace(/^(rollback\s+to\s+savepoint\s+)trx\d+(\s*;?)$/i, "$1trx$2"); + } + + return sql; + } + private _handleRecordQueryInSpan( spanInfo: SpanInfo, originalQuery: Function, @@ -1662,7 +1685,8 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { `[Mysql2Instrumentation] Background getConnection detected, returning mock connection`, ); - const mockConnection = new TdMysql2ConnectionMock(this, "poolConnection"); + // PoolConnection extends Connection; match record-mode naming/hashes. + const mockConnection = new TdMysql2ConnectionMock(this, "connection"); if (callback) { process.nextTick(() => callback(null, mockConnection)); @@ -1675,7 +1699,8 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { logger.debug(`[Mysql2Instrumentation] Replaying MySQL2 Pool getConnection`); // For pool getConnection operations, simulate returning a mock connection - const mockConnection = new TdMysql2ConnectionMock(this, "poolConnection", spanInfo); + // PoolConnection extends Connection; match record-mode naming/hashes. + const mockConnection = new TdMysql2ConnectionMock(this, "connection", spanInfo); if (callback) { process.nextTick(() => callback(null, mockConnection)); diff --git a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts index aa7d76b3..29deb7d9 100644 --- a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts +++ b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts @@ -58,8 +58,8 @@ export class TdMysql2ConnectionMock extends EventEmitter { } const rawInputValue = { - sql: queryConfig.sql, - values: queryConfig.values, + sql: this.mysql2Instrumentation.normalizeSqlForMockMatching(queryConfig.sql), + values: queryConfig.values || [], clientType: this.clientType, // Use the stored clientType instead of hardcoded value }; @@ -103,8 +103,8 @@ export class TdMysql2ConnectionMock extends EventEmitter { } const rawInputValue = { - sql: queryConfig.sql, - values: queryConfig.values, + sql: this.mysql2Instrumentation.normalizeSqlForMockMatching(queryConfig.sql), + values: queryConfig.values || [], clientType: this.clientType, // Use the stored clientType instead of hardcoded value }; From 7cd3803a56900f92f1d912adfe786341bf18b963 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Fri, 20 Feb 2026 17:44:07 -0800 Subject: [PATCH 14/15] Cleanup --- .../libraries/e2e-common/base-entrypoint.sh | 46 ------------------- .../libraries/mysql2/e2e-tests/run-all.sh | 2 +- .../mysql2/mocks/TdMysql2ConnectionMock.ts | 9 ++-- .../mysql2/mocks/TdMysql2QueryMock.ts | 15 ------ 4 files changed, 4 insertions(+), 68 deletions(-) diff --git a/src/instrumentation/libraries/e2e-common/base-entrypoint.sh b/src/instrumentation/libraries/e2e-common/base-entrypoint.sh index 013a8944..5e9328fd 100644 --- a/src/instrumentation/libraries/e2e-common/base-entrypoint.sh +++ b/src/instrumentation/libraries/e2e-common/base-entrypoint.sh @@ -35,50 +35,6 @@ NC='\033[0m' log() { echo -e "${2:-$NC}$1${NC}"; } -# Print targeted replay diagnostics to make CI failures actionable. -print_replay_diagnostics() { - log "================================================" "$YELLOW" - log "Replay diagnostics (from .tusk/logs)" "$YELLOW" - log "================================================" "$YELLOW" - - if [ ! -d ".tusk/logs" ]; then - log "No .tusk/logs directory found." "$YELLOW" - return - fi - - local patterns="Replay mock miss diagnostics|No matching mock found for query|Mysql2Instrumentation|ROLLBACK" - local matched - matched=$(grep -R --line-number -E "$patterns" .tusk/logs 2>/dev/null || true) - - if [ -z "$matched" ]; then - log "No matching replay diagnostics found in .tusk/logs." "$YELLOW" - return - fi - - echo "$matched" - log "" - log "Expanded miss contexts:" "$YELLOW" - - local miss_lines - miss_lines=$(grep -R --line-number "Replay mock miss diagnostics" .tusk/logs 2>/dev/null || true) - if [ -z "$miss_lines" ]; then - return - fi - - # Print a focused context window around each miss diagnostics block. - while IFS= read -r hit; do - [ -z "$hit" ] && continue - local file - local line - file=$(echo "$hit" | cut -d: -f1) - line=$(echo "$hit" | cut -d: -f2) - local start=$((line > 3 ? line - 3 : 1)) - local end=$((line + 20)) - log "--- $file:$start-$end ---" "$YELLOW" - sed -n "${start},${end}p" "$file" 2>/dev/null || true - done <<< "$miss_lines" -} - # Stop the server and all its child processes (npm spawns node underneath) stop_server() { if [ -n "$SERVER_PID" ]; then @@ -283,7 +239,6 @@ echo "$TEST_OUTPUT" # Check tusk exit code if [ $TUSK_EXIT -ne 0 ]; then log "Tusk tests failed with exit code $TUSK_EXIT" "$RED" - print_replay_diagnostics exit 1 fi @@ -294,7 +249,6 @@ ANY_FAILED=$(echo "$TEST_OUTPUT" | grep -c '"passed":\s*false' || true) log "================================================" if [ "$ANY_FAILED" -gt 0 ]; then log "Some tests failed!" "$RED" - print_replay_diagnostics exit 1 elif [ "$ALL_PASSED" -gt 0 ]; then log "All $ALL_PASSED tests passed!" "$GREEN" diff --git a/src/instrumentation/libraries/mysql2/e2e-tests/run-all.sh b/src/instrumentation/libraries/mysql2/e2e-tests/run-all.sh index 3fc01f78..e546986e 100755 --- a/src/instrumentation/libraries/mysql2/e2e-tests/run-all.sh +++ b/src/instrumentation/libraries/mysql2/e2e-tests/run-all.sh @@ -11,4 +11,4 @@ source "$SCRIPT_DIR/../../e2e-common/e2e-helpers.sh" # Run all E2E tests for mysql2 # Accepts optional base port parameter (default: 3000) -run_all_e2e_tests "$SCRIPT_DIR" "mysql2" "${1:-3000}" "sequential" +run_all_e2e_tests "$SCRIPT_DIR" "mysql2" "${1:-3000}" diff --git a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts index 29deb7d9..a7bdce43 100644 --- a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts +++ b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts @@ -4,6 +4,7 @@ import { createMockInputValue } from "../../../../core/utils"; import { SpanInfo } from "../../../../core/tracing/SpanUtils"; import { logger } from "../../../../core/utils/logger"; import { QueryCallback } from "../types"; +import { captureStackTrace } from "src/instrumentation/core/utils"; /** * Mock MySQL2 connection/pool connection for replay mode @@ -38,9 +39,7 @@ export class TdMysql2ConnectionMock extends EventEmitter { query(...args: any[]) { logger.debug(`[TdMysql2ConnectionMock] Mock connection query intercepted in REPLAY mode`); - // Avoid using stack trace as a hard matching key for connection-derived replay queries. - // Stack frames differ across environments (e.g. CI container/runtime), causing false misses. - const stackTrace: string | undefined = undefined; + const stackTrace = captureStackTrace(["Mysql2Instrumentation"]); // Parse query arguments similar to the main query patch const queryConfig = this.mysql2Instrumentation.parseQueryArgs(args); @@ -83,9 +82,7 @@ export class TdMysql2ConnectionMock extends EventEmitter { execute(...args: any[]) { logger.debug(`[TdMysql2ConnectionMock] Mock connection execute intercepted in REPLAY mode`); - // Avoid using stack trace as a hard matching key for connection-derived replay queries. - // Stack frames differ across environments (e.g. CI container/runtime), causing false misses. - const stackTrace: string | undefined = undefined; + const stackTrace = captureStackTrace(["Mysql2Instrumentation"]); // Parse execute arguments similar to the main execute patch const queryConfig = this.mysql2Instrumentation.parseQueryArgs(args); diff --git a/src/instrumentation/libraries/mysql2/mocks/TdMysql2QueryMock.ts b/src/instrumentation/libraries/mysql2/mocks/TdMysql2QueryMock.ts index b685420e..44d9a11b 100644 --- a/src/instrumentation/libraries/mysql2/mocks/TdMysql2QueryMock.ts +++ b/src/instrumentation/libraries/mysql2/mocks/TdMysql2QueryMock.ts @@ -142,17 +142,6 @@ export class TdMysql2QueryMock { if (!mockData) { const sql = queryConfig.sql || inputValue.sql || "UNKNOWN_QUERY"; logger.warn(`[Mysql2Instrumentation] No mock data found for MySQL2 query: ${sql}`); - logger.warn(`[Mysql2Instrumentation] Replay mock miss diagnostics`, { - traceId: spanInfo.traceId, - spanId: spanInfo.spanId, - replayTraceId: SpanUtils.getCurrentReplayTraceId(), - spanName, - submoduleName, - clientType: inputValue.clientType, - querySql: sql, - normalizedQuerySql: this._normalizeSqlForDebug(sql), - valuesCount: Array.isArray(inputValue.values) ? inputValue.values.length : 0, - }); throw new Error(`[Mysql2Instrumentation] No matching mock found for query: ${sql}`); } @@ -333,8 +322,4 @@ export class TdMysql2QueryMock { fields: [], }; } - - private _normalizeSqlForDebug(sql: string): string { - return sql.replace(/\s+/g, " ").trim().toLowerCase(); - } } From 91114dde8a85dcd0637c03c42a3959f0de9ff5e4 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Fri, 20 Feb 2026 17:57:51 -0800 Subject: [PATCH 15/15] Fix --- .../libraries/mysql2/Instrumentation.ts | 14 ++++++++++++-- .../mysql2/mocks/TdMysql2ConnectionMock.ts | 6 ++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/instrumentation/libraries/mysql2/Instrumentation.ts b/src/instrumentation/libraries/mysql2/Instrumentation.ts index 758b8853..e6796b66 100644 --- a/src/instrumentation/libraries/mysql2/Instrumentation.ts +++ b/src/instrumentation/libraries/mysql2/Instrumentation.ts @@ -33,6 +33,7 @@ const V3_11_5_TO_4_0 = ">=3.11.5 <4.0.0"; export class Mysql2Instrumentation extends TdInstrumentationBase { private readonly INSTRUMENTATION_NAME = "Mysql2Instrumentation"; private readonly CONTEXT_BOUND_CONNECTION = Symbol("mysql2-context-bound-connection"); + private readonly CONTEXT_BOUND_PARENT_CONTEXT = Symbol("mysql2-bound-parent-context"); private mode: TuskDriftMode; private queryMock: TdMysql2QueryMock; @@ -1663,7 +1664,15 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { parentContext: ReturnType, ): PoolConnection { const conn = connection as any; - if (!conn || conn[this.CONTEXT_BOUND_CONNECTION]) { + if (!conn) { + return connection; + } + + // PoolConnection objects are reused by mysql2 pools. Always refresh the + // request context so wrappers use the current checkout context. + conn[this.CONTEXT_BOUND_PARENT_CONTEXT] = parentContext; + + if (conn[this.CONTEXT_BOUND_CONNECTION]) { return connection; } @@ -1672,7 +1681,8 @@ export class Mysql2Instrumentation extends TdInstrumentationBase { const original = conn[method]; if (typeof original !== "function") continue; conn[method] = (...args: any[]) => { - return otelContext.with(parentContext, () => original.apply(conn, args)); + const boundContext = conn[this.CONTEXT_BOUND_PARENT_CONTEXT] ?? otelContext.active(); + return otelContext.with(boundContext, () => original.apply(conn, args)); }; } diff --git a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts index a7bdce43..a5483830 100644 --- a/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts +++ b/src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionMock.ts @@ -39,7 +39,8 @@ export class TdMysql2ConnectionMock extends EventEmitter { query(...args: any[]) { logger.debug(`[TdMysql2ConnectionMock] Mock connection query intercepted in REPLAY mode`); - const stackTrace = captureStackTrace(["Mysql2Instrumentation"]); + // Align replay stack traces with record path by removing both wrapper layers. + const stackTrace = captureStackTrace(["TdMysql2ConnectionMock", "Mysql2Instrumentation"]); // Parse query arguments similar to the main query patch const queryConfig = this.mysql2Instrumentation.parseQueryArgs(args); @@ -82,7 +83,8 @@ export class TdMysql2ConnectionMock extends EventEmitter { execute(...args: any[]) { logger.debug(`[TdMysql2ConnectionMock] Mock connection execute intercepted in REPLAY mode`); - const stackTrace = captureStackTrace(["Mysql2Instrumentation"]); + // Align replay stack traces with record path by removing both wrapper layers. + const stackTrace = captureStackTrace(["TdMysql2ConnectionMock", "Mysql2Instrumentation"]); // Parse execute arguments similar to the main execute patch const queryConfig = this.mysql2Instrumentation.parseQueryArgs(args);