From 867dde9db3a0e7c68d619bfbf502eee236dfdaaa Mon Sep 17 00:00:00 2001 From: SHIVANI PANDEY Date: Thu, 2 Jul 2026 13:55:05 +0530 Subject: [PATCH] =?UTF-8?q?Revert=20"fix(node-dependency-matrix):=20count?= =?UTF-8?q?=20gRPC=20test=20cases=20in=20recording=20calib=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e31c8a3b3f9153c0c86911f6c6b80beeee17767f. --- README.md | 1 - node-dependency-matrix/.dockerignore | 7 - node-dependency-matrix/.gitignore | 4 - node-dependency-matrix/Dockerfile | 33 - node-dependency-matrix/README.md | 105 - node-dependency-matrix/compose.yaml | 206 - node-dependency-matrix/entrypoint.sh | 23 - .../fixtures/expected-values.json | 571 --- node-dependency-matrix/k8s/README.md | 312 -- node-dependency-matrix/k8s/STAGING_RUNBOOK.md | 544 --- node-dependency-matrix/k8s/deploy-kind.sh | 124 - node-dependency-matrix/k8s/kind-config.yaml | 14 - .../k8s/manifests/00-localstack.yaml | 54 - .../k8s/manifests/01-mysql.yaml | 39 - .../k8s/manifests/02-postgres.yaml | 38 - .../k8s/manifests/03-mongo.yaml | 33 - .../k8s/manifests/04-redis.yaml | 37 - .../k8s/manifests/05-redpanda.yaml | 50 - .../k8s/manifests/06-fixture-service.yaml | 58 - .../k8s/manifests/07-tls-proxies.yaml | 297 -- .../k8s/manifests/08-app.yaml | 98 - node-dependency-matrix/k8s/port-forward.sh | 13 - node-dependency-matrix/package-lock.json | 3664 ----------------- node-dependency-matrix/package.json | 37 - .../proto/dependency_matrix.proto | 41 - .../scripts/compose_down.sh | 6 - node-dependency-matrix/scripts/compose_up.sh | 12 - .../scripts/generate_certs.sh | 63 - .../localstack-init/01-create-queue.sh | 4 - .../scripts/record_traffic.sh | 74 - .../scripts/send_grpc_traffic.sh | 59 - node-dependency-matrix/src/bin/app.ts | 389 -- .../src/bin/dependencyFixture.ts | 106 - node-dependency-matrix/src/bin/tlsProxy.ts | 52 - node-dependency-matrix/src/global.d.ts | 3 - node-dependency-matrix/src/lib/asyncJobs.ts | 129 - node-dependency-matrix/src/lib/config.ts | 82 - .../src/lib/dependencies.ts | 503 --- node-dependency-matrix/src/lib/log.ts | 21 - node-dependency-matrix/src/lib/proto.ts | 44 - node-dependency-matrix/tsconfig.json | 17 - 41 files changed, 7967 deletions(-) delete mode 100644 node-dependency-matrix/.dockerignore delete mode 100644 node-dependency-matrix/.gitignore delete mode 100644 node-dependency-matrix/Dockerfile delete mode 100644 node-dependency-matrix/README.md delete mode 100644 node-dependency-matrix/compose.yaml delete mode 100755 node-dependency-matrix/entrypoint.sh delete mode 100644 node-dependency-matrix/fixtures/expected-values.json delete mode 100644 node-dependency-matrix/k8s/README.md delete mode 100644 node-dependency-matrix/k8s/STAGING_RUNBOOK.md delete mode 100755 node-dependency-matrix/k8s/deploy-kind.sh delete mode 100644 node-dependency-matrix/k8s/kind-config.yaml delete mode 100644 node-dependency-matrix/k8s/manifests/00-localstack.yaml delete mode 100644 node-dependency-matrix/k8s/manifests/01-mysql.yaml delete mode 100644 node-dependency-matrix/k8s/manifests/02-postgres.yaml delete mode 100644 node-dependency-matrix/k8s/manifests/03-mongo.yaml delete mode 100644 node-dependency-matrix/k8s/manifests/04-redis.yaml delete mode 100644 node-dependency-matrix/k8s/manifests/05-redpanda.yaml delete mode 100644 node-dependency-matrix/k8s/manifests/06-fixture-service.yaml delete mode 100644 node-dependency-matrix/k8s/manifests/07-tls-proxies.yaml delete mode 100644 node-dependency-matrix/k8s/manifests/08-app.yaml delete mode 100755 node-dependency-matrix/k8s/port-forward.sh delete mode 100644 node-dependency-matrix/package-lock.json delete mode 100644 node-dependency-matrix/package.json delete mode 100644 node-dependency-matrix/proto/dependency_matrix.proto delete mode 100755 node-dependency-matrix/scripts/compose_down.sh delete mode 100755 node-dependency-matrix/scripts/compose_up.sh delete mode 100755 node-dependency-matrix/scripts/generate_certs.sh delete mode 100755 node-dependency-matrix/scripts/localstack-init/01-create-queue.sh delete mode 100755 node-dependency-matrix/scripts/record_traffic.sh delete mode 100755 node-dependency-matrix/scripts/send_grpc_traffic.sh delete mode 100644 node-dependency-matrix/src/bin/app.ts delete mode 100644 node-dependency-matrix/src/bin/dependencyFixture.ts delete mode 100644 node-dependency-matrix/src/bin/tlsProxy.ts delete mode 100644 node-dependency-matrix/src/global.d.ts delete mode 100644 node-dependency-matrix/src/lib/asyncJobs.ts delete mode 100644 node-dependency-matrix/src/lib/config.ts delete mode 100644 node-dependency-matrix/src/lib/dependencies.ts delete mode 100644 node-dependency-matrix/src/lib/log.ts delete mode 100644 node-dependency-matrix/src/lib/proto.ts delete mode 100644 node-dependency-matrix/tsconfig.json diff --git a/README.md b/README.md index ae9283a..c16195a 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,6 @@ This repo contains the sample for [Keploy's](https://keploy.io) JS Application. 8. [Node-JWT](https://github.com/keploy/samples-typescript/tree/main/node-jwt) 9. [Node-Mongoose](https://github.com/keploy/samples-typescript/tree/main/node-mongoose) 10. [Rest-Express-Mongo](https://github.com/keploy/samples-typescript/tree/main/rest-express-mongo) -11. [Node-Dependency-Matrix](https://github.com/keploy/samples-typescript/tree/main/node-dependency-matrix) ## Community Support ❤️ diff --git a/node-dependency-matrix/.dockerignore b/node-dependency-matrix/.dockerignore deleted file mode 100644 index a98267d..0000000 --- a/node-dependency-matrix/.dockerignore +++ /dev/null @@ -1,7 +0,0 @@ -node_modules -dist -.generated -README.md -k8s -scripts -keploy diff --git a/node-dependency-matrix/.gitignore b/node-dependency-matrix/.gitignore deleted file mode 100644 index e379bb9..0000000 --- a/node-dependency-matrix/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -dist -node_modules -.generated -keploy diff --git a/node-dependency-matrix/Dockerfile b/node-dependency-matrix/Dockerfile deleted file mode 100644 index 1bfd76b..0000000 --- a/node-dependency-matrix/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -FROM node:20-bookworm-slim@sha256:17281e8d1dc4d671976c6b89a12f47a44c2f390b63a989e2e327631041f544fd AS build - -WORKDIR /app - -COPY package*.json ./ -RUN npm ci - -COPY tsconfig.json ./ -COPY proto ./proto -COPY fixtures ./fixtures -COPY src ./src -COPY entrypoint.sh ./entrypoint.sh - -RUN npm run build && chmod +x /app/entrypoint.sh - -FROM node:20-bookworm-slim@sha256:17281e8d1dc4d671976c6b89a12f47a44c2f390b63a989e2e327631041f544fd - -WORKDIR /app - -RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && rm -rf /var/lib/apt/lists/* - -COPY --from=build /app/node_modules ./node_modules -COPY --from=build /app/dist ./dist -COPY --from=build /app/proto ./proto -COPY --from=build /app/fixtures ./fixtures -COPY --from=build /app/entrypoint.sh ./entrypoint.sh - -ENV NODE_ENV=production -ENV PORT=8080 -ENV GRPC_PORT=9090 - -ENTRYPOINT ["./entrypoint.sh"] -CMD ["node", "dist/bin/app.js"] diff --git a/node-dependency-matrix/README.md b/node-dependency-matrix/README.md deleted file mode 100644 index 3429b94..0000000 --- a/node-dependency-matrix/README.md +++ /dev/null @@ -1,105 +0,0 @@ -# Node Dependency Matrix - -This sample is a TypeScript application built to validate Keploy cloud record/replay against a broad dependency matrix. - -What it exposes: - -- incoming HTTP -- incoming gRPC -- outgoing HTTPS -- outgoing HTTP/2 -- outgoing gRPC -- outgoing MySQL -- outgoing Postgres -- outgoing Mongo -- outgoing Redis -- outgoing Kafka -- outgoing SQS-over-HTTPS -- outgoing generic TLS traffic -- an async background workflow that performs real outbound calls after a `202 Accepted` -- a noisy endpoint -- an expected replay failure endpoint -- duplicate-friendly GET and POST endpoints for static dedup verification - -## Quick start - -```bash -cd samples-typescript/node-dependency-matrix -npm install -npm run build -bash k8s/deploy-kind.sh -APP_URL=http://localhost:30081 bash scripts/record_traffic.sh -``` - -If the default host ports are already occupied, override them: - -```bash -HOST_PROXY_PORT=31080 HOST_APP_PORT=31081 HOST_GRPC_PORT=31090 bash k8s/deploy-kind.sh -APP_URL=http://localhost:31081 bash scripts/record_traffic.sh -``` - -Optional incoming gRPC traffic: - -```bash -GRPC_TARGET=localhost:30090 bash scripts/send_grpc_traffic.sh -``` - -## Docker Compose - -For a non-Kubernetes local stack: - -```bash -cd samples-typescript/node-dependency-matrix -npm install -bash scripts/compose_up.sh -APP_URL=http://localhost:38081 bash scripts/record_traffic.sh -GRPC_TARGET=localhost:39090 bash scripts/send_grpc_traffic.sh -``` - -To stop it: - -```bash -bash scripts/compose_down.sh -``` - -If `38081` or `39090` are occupied: - -```bash -APP_HTTP_PORT=48081 APP_GRPC_PORT=49090 bash scripts/compose_up.sh -APP_URL=http://localhost:48081 bash scripts/record_traffic.sh -GRPC_TARGET=localhost:49090 bash scripts/send_grpc_traffic.sh -``` - -## Keploy expectations - -The machine-readable contract is: - -```bash -fixtures/expected-values.json -``` - -Use it later in manual verification or other automation for: - -- testcase counts -- required and acceptable mock kinds -- scenario-to-mock-kind mapping -- the exact HTTP and gRPC traffic plans -- the async workflow contract and expected background scenarios -- hosted UI + Helm expectations for Kind -- total mock count ranges -- dedup expectations -- expected replay pass/noisy/fail scenarios - -## Kubernetes - -The full Kind and hosted UI flow is in: - -```bash -k8s/README.md -``` - -The detailed step-by-step staging runbook and troubleshooting guide is in: - -```bash -k8s/STAGING_RUNBOOK.md -``` diff --git a/node-dependency-matrix/compose.yaml b/node-dependency-matrix/compose.yaml deleted file mode 100644 index 340bc10..0000000 --- a/node-dependency-matrix/compose.yaml +++ /dev/null @@ -1,206 +0,0 @@ -name: node-dependency-matrix - -x-node-matrix-image: &node_matrix_image - build: - context: . - image: node-dependency-matrix:compose - -services: - app: - <<: *node_matrix_image - depends_on: - fixture-service: - condition: service_started - mysql: - condition: service_healthy - postgres: - condition: service_healthy - mongo-tls: - condition: service_started - redis-tls: - condition: service_started - redpanda: - condition: service_started - sqs-tls: - condition: service_started - environment: - PORT: "8080" - GRPC_PORT: "9090" - FIXTURE_HTTPS_BASE: https://fixture-service:8443 - FIXTURE_HTTP2_ORIGIN: https://fixture-service:9443 - FIXTURE_GRPC_TARGET: fixture-service:50051 - FIXTURE_GENERIC_HOST: fixture-service - FIXTURE_GENERIC_PORT: "9445" - MYSQL_URL: mysql://root@mysql:3306/matrix - POSTGRES_URL: postgresql://postgres@postgres:5432/matrix - MONGO_URL: mongodb://mongo-tls:27017/matrix?tls=true - REDIS_URL: rediss://redis-tls:6380 - KAFKA_BROKERS: redpanda:9092 - KAFKA_TOPIC: matrix-events - SQS_ENDPOINT: https://sqs-tls:4567 - SQS_QUEUE_URL: https://sqs-tls:4567/000000000000/dependency-matrix - SAMPLE_CA_CERT_PATH: /etc/sample-certs/ca.crt - COMBINED_CA_CERT_PATH: /tmp/node-dependency-matrix-ca-bundle.crt - NODE_EXTRA_CA_CERTS: /tmp/node-dependency-matrix-ca-bundle.crt - SSL_CERT_FILE: /tmp/node-dependency-matrix-ca-bundle.crt - ports: - - "${APP_HTTP_PORT:-38081}:8080" - - "${APP_GRPC_PORT:-39090}:9090" - volumes: - - ./.generated/certs:/etc/sample-certs:ro - - fixture-service: - <<: *node_matrix_image - command: ["node", "dist/bin/dependencyFixture.js"] - environment: - TLS_CERT_PATH: /etc/sample-certs/proxy.crt - TLS_KEY_PATH: /etc/sample-certs/proxy.key - volumes: - - ./.generated/certs:/etc/sample-certs:ro - - mysql: - image: mysql:8.0 - command: ["mysqld", "--default-authentication-plugin=mysql_native_password"] - environment: - MYSQL_ALLOW_EMPTY_PASSWORD: "yes" - MYSQL_DATABASE: matrix - healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot"] - interval: 5s - timeout: 5s - retries: 20 - - postgres: - image: postgres:16 - environment: - POSTGRES_HOST_AUTH_METHOD: trust - POSTGRES_DB: matrix - POSTGRES_USER: postgres - healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres -d matrix"] - interval: 5s - timeout: 5s - retries: 20 - - mongo: - image: mongo:7 - command: ["--bind_ip_all"] - - redis: - image: redis:7-alpine - - redpanda: - image: docker.redpanda.com/redpandadata/redpanda:v25.1.2 - command: - - redpanda - - start - - --overprovisioned - - --smp - - "1" - - --memory - - 512M - - --reserve-memory - - 0M - - --check=false - - --node-id - - "0" - - --kafka-addr - - PLAINTEXT://0.0.0.0:9092 - - --advertise-kafka-addr - - PLAINTEXT://redpanda:9092 - - --set - - redpanda.auto_create_topics_enabled=true - - localstack: - image: localstack/localstack:3.3 - environment: - SERVICES: sqs - AWS_DEFAULT_REGION: us-east-1 - volumes: - - ./scripts/localstack-init:/etc/localstack/init/ready.d:ro - - mysql-tls: - <<: *node_matrix_image - command: ["node", "dist/bin/tlsProxy.js"] - depends_on: - mysql: - condition: service_healthy - environment: - LISTEN_PORT: "3306" - TARGET_HOST: mysql - TARGET_PORT: "3306" - TLS_CERT_PATH: /etc/sample-certs/proxy.crt - TLS_KEY_PATH: /etc/sample-certs/proxy.key - volumes: - - ./.generated/certs:/etc/sample-certs:ro - - postgres-tls: - <<: *node_matrix_image - command: ["node", "dist/bin/tlsProxy.js"] - depends_on: - postgres: - condition: service_healthy - environment: - LISTEN_PORT: "5432" - TARGET_HOST: postgres - TARGET_PORT: "5432" - TLS_CERT_PATH: /etc/sample-certs/proxy.crt - TLS_KEY_PATH: /etc/sample-certs/proxy.key - volumes: - - ./.generated/certs:/etc/sample-certs:ro - - mongo-tls: - <<: *node_matrix_image - command: ["node", "dist/bin/tlsProxy.js"] - depends_on: - - mongo - environment: - LISTEN_PORT: "27017" - TARGET_HOST: mongo - TARGET_PORT: "27017" - TLS_CERT_PATH: /etc/sample-certs/proxy.crt - TLS_KEY_PATH: /etc/sample-certs/proxy.key - volumes: - - ./.generated/certs:/etc/sample-certs:ro - - redis-tls: - <<: *node_matrix_image - command: ["node", "dist/bin/tlsProxy.js"] - depends_on: - - redis - environment: - LISTEN_PORT: "6380" - TARGET_HOST: redis - TARGET_PORT: "6379" - TLS_CERT_PATH: /etc/sample-certs/proxy.crt - TLS_KEY_PATH: /etc/sample-certs/proxy.key - volumes: - - ./.generated/certs:/etc/sample-certs:ro - - kafka-tls: - <<: *node_matrix_image - command: ["node", "dist/bin/tlsProxy.js"] - depends_on: - - redpanda - environment: - LISTEN_PORT: "9094" - TARGET_HOST: redpanda - TARGET_PORT: "9092" - TLS_CERT_PATH: /etc/sample-certs/proxy.crt - TLS_KEY_PATH: /etc/sample-certs/proxy.key - volumes: - - ./.generated/certs:/etc/sample-certs:ro - - sqs-tls: - <<: *node_matrix_image - command: ["node", "dist/bin/tlsProxy.js"] - depends_on: - - localstack - environment: - LISTEN_PORT: "4567" - TARGET_HOST: localstack - TARGET_PORT: "4566" - TLS_CERT_PATH: /etc/sample-certs/proxy.crt - TLS_KEY_PATH: /etc/sample-certs/proxy.key - volumes: - - ./.generated/certs:/etc/sample-certs:ro diff --git a/node-dependency-matrix/entrypoint.sh b/node-dependency-matrix/entrypoint.sh deleted file mode 100755 index c87afee..0000000 --- a/node-dependency-matrix/entrypoint.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -set -eu - -COMBINED_CA_CERT_PATH="${COMBINED_CA_CERT_PATH:-/tmp/node-dependency-matrix-ca-bundle.crt}" - -rm -f "${COMBINED_CA_CERT_PATH}" - -if [ -n "${SAMPLE_CA_CERT_PATH:-}" ] && [ -f "${SAMPLE_CA_CERT_PATH}" ]; then - cat "${SAMPLE_CA_CERT_PATH}" > "${COMBINED_CA_CERT_PATH}" - cp "${SAMPLE_CA_CERT_PATH}" /usr/local/share/ca-certificates/node-dependency-matrix.crt - update-ca-certificates >/dev/null 2>&1 || true -fi - -if [ -f /tmp/keploy-tls/ca.crt ]; then - cat /tmp/keploy-tls/ca.crt >> "${COMBINED_CA_CERT_PATH}" -fi - -if [ ! -f "${COMBINED_CA_CERT_PATH}" ]; then - : > "${COMBINED_CA_CERT_PATH}" - >&2 echo "Warning: No CA certificates were found to create the combined CA bundle at '${COMBINED_CA_CERT_PATH}'. To fix this, either set SAMPLE_CA_CERT_PATH to a valid CA bundle file or mount /tmp/keploy-tls/ca.crt before starting this container so fixture endpoints can establish TLS correctly." -fi - -exec "$@" diff --git a/node-dependency-matrix/fixtures/expected-values.json b/node-dependency-matrix/fixtures/expected-values.json deleted file mode 100644 index 09c8469..0000000 --- a/node-dependency-matrix/fixtures/expected-values.json +++ /dev/null @@ -1,571 +0,0 @@ -{ - "sampleId": "node-dependency-matrix", - "cluster": { - "namespace": "default", - "deployment": "node-dependency-matrix", - "service": "node-dependency-matrix", - "podLabelSelector": "app=node-dependency-matrix", - "httpServicePort": 8080, - "grpcServicePort": 9090, - "httpNodePort": 30081, - "grpcNodePort": 30090, - "k8sProxyNodePort": 30080 - }, - "coverage": { - "incoming": { - "httpEndpoints": [ - "/health", - "/expectations", - "/deps/http", - "/deps/http2", - "/deps/grpc", - "/deps/mysql", - "/deps/postgres", - "/deps/mongo", - "/deps/redis", - "/deps/kafka", - "/deps/sqs", - "/deps/generic", - "/deps/all", - "/dedup/catalog", - "/dedup/order", - "/async/catalog-sync", - "/async/catalog-sync/:jobId", - "/async/catalog-sync/:jobId/wait", - "/noise/runtime", - "/expected-fail/time-window" - ], - "grpcMethods": [ - "/dependencymatrix.DependencyMatrix/Ping", - "/dependencymatrix.DependencyMatrix/RunDependencyScenario" - ] - }, - "transportNotes": { - "incomingHttp": "plaintext HTTP on the sample service", - "incomingGrpc": "plaintext gRPC on the sample service", - "outgoingHttp": "HTTPS to fixture-service", - "outgoingHttp2": "TLS HTTP/2 to fixture-service", - "outgoingGrpc": "TLS gRPC to fixture-service", - "outgoingMySql": "direct MySQL protocol to mysql:3306", - "outgoingPostgres": "direct Postgres protocol to postgres:5432", - "outgoingMongo": "Mongo over TLS through mongo-tls", - "outgoingRedis": "Redis over TLS through redis-tls", - "outgoingKafka": "direct Kafka protocol to redpanda:9092", - "outgoingSqs": "HTTPS to sqs-tls", - "outgoingGeneric": "raw TLS socket to fixture-service:9445" - }, - "outgoingPreferredMockKinds": [ - "Http", - "Http2", - "gRPC", - "MySQL", - "PostgresV2", - "Mongo", - "Redis", - "Kafka", - "Generic" - ], - "enterpriseSpecificOutgoingIntegrations": [ - "Redis", - "Kafka", - "SQS" - ], - "knownNonGoals": [ - "incoming TLS gRPC is not exercised in the default flow", - "the HTTP ingress coverage now includes GET plus POST JSON and headers, but not multipart/form-data or auth/session traffic", - "the async workflow validates in-pod background dependency capture, not a separate worker deployment", - "mysql-tls, postgres-tls, and kafka-tls deployments exist but are not used by the default app path" - ] - }, - "hostedUi": { - "supportedEnvironments": { - "prod": { - "uiBaseUrl": "https://app.keploy.io", - "clustersPageUrl": "https://app.keploy.io/clusters", - "apiServerUrl": "https://api.keploy.io", - "environment": "prod" - }, - "staging": { - "uiBaseUrl": "https://app.staging.keploy.io", - "clustersPageUrl": "https://app.staging.keploy.io/clusters", - "apiServerUrl": "https://api.staging.keploy.io", - "environment": "staging" - } - }, - "requiredHelmValues": { - "service.type": "NodePort", - "service.nodePort": 30080, - "proxy.insecure.enabled": true - }, - "consistencyRules": [ - "use the same environment in the UI domain, apiServerUrl, and Helm environment value", - "use the same ingress URL in the UI cluster entry and keploy.ingressUrl" - ] - }, - "localAccess": { - "portForward": { - "script": "k8s/port-forward.sh", - "resource": "svc/node-dependency-matrix", - "http": { - "localPort": 8080, - "remotePort": 8080, - "baseUrl": "http://localhost:8080" - }, - "grpc": { - "localPort": 9090, - "remotePort": 9090, - "target": "localhost:9090" - } - } - }, - "recording": { - "pods": { - "expectedReplicas": 1, - "expectedReadyContainersWhileRecording": 2 - }, - "httpTrafficScript": { - "path": "scripts/record_traffic.sh", - "expectedTestcasesExact": 19, - "requests": [ - { - "method": "GET", - "path": "/deps/http", - "count": 1, - "preferredMockKinds": [ - "Http" - ], - "acceptableMockKinds": [ - "Http" - ], - "replayExpectation": "pass" - }, - { - "method": "GET", - "path": "/deps/http2", - "count": 1, - "preferredMockKinds": [ - "Http2" - ], - "acceptableMockKinds": [ - "Http2", - "Generic", - "Http" - ], - "replayExpectation": "pass" - }, - { - "method": "GET", - "path": "/deps/grpc", - "count": 1, - "preferredMockKinds": [ - "gRPC" - ], - "acceptableMockKinds": [ - "gRPC", - "Generic", - "Http2" - ], - "replayExpectation": "pass" - }, - { - "method": "GET", - "path": "/deps/mysql", - "count": 1, - "preferredMockKinds": [ - "MySQL" - ], - "acceptableMockKinds": [ - "MySQL" - ], - "replayExpectation": "pass" - }, - { - "method": "GET", - "path": "/deps/postgres", - "count": 1, - "preferredMockKinds": [ - "PostgresV2" - ], - "acceptableMockKinds": [ - "PostgresV2", - "Generic" - ], - "replayExpectation": "pass" - }, - { - "method": "GET", - "path": "/deps/mongo", - "count": 1, - "preferredMockKinds": [ - "Mongo" - ], - "acceptableMockKinds": [ - "Mongo", - "Generic" - ], - "replayExpectation": "pass" - }, - { - "method": "GET", - "path": "/deps/redis", - "count": 1, - "preferredMockKinds": [ - "Redis" - ], - "acceptableMockKinds": [ - "Redis", - "Generic" - ], - "replayExpectation": "pass" - }, - { - "method": "GET", - "path": "/deps/kafka", - "count": 1, - "preferredMockKinds": [ - "Kafka" - ], - "acceptableMockKinds": [ - "Kafka", - "Generic" - ], - "replayExpectation": "pass" - }, - { - "method": "GET", - "path": "/deps/sqs", - "count": 1, - "preferredMockKinds": [ - "Http" - ], - "acceptableMockKinds": [ - "Http", - "Generic" - ], - "replayExpectation": "pass" - }, - { - "method": "GET", - "path": "/deps/generic", - "count": 1, - "preferredMockKinds": [ - "Generic" - ], - "acceptableMockKinds": [ - "Generic" - ], - "replayExpectation": "pass" - }, - { - "method": "GET", - "path": "/dedup/catalog?id=alpha", - "count": 3, - "replayExpectation": "pass", - "dedupExpectation": { - "duplicateCount": 2 - } - }, - { - "method": "GET", - "path": "/dedup/catalog?id=beta", - "count": 2, - "replayExpectation": "pass", - "dedupExpectation": { - "duplicateCount": 1 - } - }, - { - "method": "POST", - "path": "/dedup/order", - "count": 3, - "matchHint": "x-matrix-dedup-key=order-alpha", - "replayExpectation": "pass", - "dedupExpectation": { - "duplicateCount": 2 - } - }, - { - "method": "POST", - "path": "/dedup/order", - "count": 1, - "matchHint": "x-matrix-dedup-key=order-beta", - "replayExpectation": "pass" - }, - { - "method": "POST", - "path": "/async/catalog-sync", - "count": 1, - "requestBody": { - "jobId": "sync-alpha", - "catalogId": "alpha" - }, - "replayExpectation": "pass", - "backgroundScenarios": [ - "deps-http", - "deps-redis", - "deps-sqs" - ] - }, - { - "method": "GET", - "path": "/async/catalog-sync/sync-alpha/wait?timeoutMs=5000", - "count": 1, - "replayExpectation": "pass" - }, - { - "method": "GET", - "path": "/noise/runtime", - "count": 1, - "replayExpectation": "noisy" - }, - { - "method": "GET", - "path": "/expected-fail/time-window?ts=", - "count": 1, - "replayExpectation": "fail" - } - ] - }, - "asyncWorkflows": [ - { - "scenario": "async/catalog-sync", - "jobId": "sync-alpha", - "catalogId": "alpha", - "startRequest": { - "method": "POST", - "path": "/async/catalog-sync" - }, - "completionRequest": { - "method": "GET", - "path": "/async/catalog-sync/sync-alpha/wait?timeoutMs=5000" - }, - "backgroundScenarios": [ - "deps-http", - "deps-redis", - "deps-sqs" - ], - "replayExpectation": "pass" - } - ], - "grpcTrafficScript": { - "path": "scripts/send_grpc_traffic.sh", - "expectedAdditionalTestcasesExact": 2, - "calls": [ - { - "method": "/dependencymatrix.DependencyMatrix/Ping", - "request": { - "name": "matrix" - }, - "expectedAdditionalTestcases": 1 - }, - { - "method": "/dependencymatrix.DependencyMatrix/RunDependencyScenario", - "request": { - "scenario": "deps-http" - }, - "expectedAdditionalTestcases": 1, - "invokesScenario": "deps-http" - } - ] - }, - "mockSummary": { - "total": { - "min": 9, - "max": 250 - }, - "requiredKinds": [ - "Http" - ], - "preferredKinds": [ - "Http", - "Http2", - "gRPC", - "MySQL", - "PostgresV2", - "Mongo", - "Redis", - "Kafka", - "Generic" - ], - "fallbackKinds": { - "deps-http2": ["Http2", "Generic", "Http"], - "deps-grpc": ["gRPC", "Generic", "Http2"], - "deps-postgres": ["PostgresV2", "Generic"], - "deps-mongo": ["Mongo", "Generic"], - "deps-redis": ["Redis", "Generic"], - "deps-kafka": ["Kafka", "Generic"], - "deps-sqs": ["Http", "Generic"] - } - }, - "dedup": { - "expectedEntries": [ - { - "method": "GET", - "path": "/dedup/catalog", - "duplicateCount": 4 - }, - { - "method": "POST", - "path": "/dedup/order", - "duplicateCount": 3 - } - ] - } - }, - "replay": { - "scenarioCatalog": [ - { - "scenario": "deps-http", - "triggerPath": "/deps/http", - "replayExpectation": "pass", - "acceptableMockKinds": [ - "Http" - ] - }, - { - "scenario": "deps-http2", - "triggerPath": "/deps/http2", - "replayExpectation": "pass", - "acceptableMockKinds": [ - "Http2", - "Generic", - "Http" - ] - }, - { - "scenario": "deps-grpc", - "triggerPath": "/deps/grpc", - "replayExpectation": "pass", - "acceptableMockKinds": [ - "gRPC", - "Generic", - "Http2" - ] - }, - { - "scenario": "deps-mysql", - "triggerPath": "/deps/mysql", - "replayExpectation": "pass", - "acceptableMockKinds": [ - "MySQL" - ] - }, - { - "scenario": "deps-postgres", - "triggerPath": "/deps/postgres", - "replayExpectation": "pass", - "acceptableMockKinds": [ - "PostgresV2", - "Generic" - ] - }, - { - "scenario": "deps-mongo", - "triggerPath": "/deps/mongo", - "replayExpectation": "pass", - "acceptableMockKinds": [ - "Mongo", - "Generic" - ] - }, - { - "scenario": "deps-redis", - "triggerPath": "/deps/redis", - "replayExpectation": "pass", - "acceptableMockKinds": [ - "Redis", - "Generic" - ] - }, - { - "scenario": "deps-kafka", - "triggerPath": "/deps/kafka", - "replayExpectation": "pass", - "acceptableMockKinds": [ - "Kafka", - "Generic" - ] - }, - { - "scenario": "deps-sqs", - "triggerPath": "/deps/sqs", - "replayExpectation": "pass", - "acceptableMockKinds": [ - "Http", - "Generic" - ] - }, - { - "scenario": "deps-generic", - "triggerPath": "/deps/generic", - "replayExpectation": "pass", - "acceptableMockKinds": [ - "Generic" - ] - }, - { - "scenario": "dedup/catalog", - "triggerPath": "/dedup/catalog", - "replayExpectation": "pass" - }, - { - "scenario": "dedup/order", - "triggerPath": "/dedup/order", - "replayExpectation": "pass" - }, - { - "scenario": "async/catalog-sync", - "triggerPath": "/async/catalog-sync", - "replayExpectation": "pass" - }, - { - "scenario": "async/catalog-sync/wait", - "triggerPath": "/async/catalog-sync/:jobId/wait", - "replayExpectation": "pass" - }, - { - "scenario": "noise/runtime", - "triggerPath": "/noise/runtime", - "replayExpectation": "noisy" - }, - { - "scenario": "expected-fail/time-window", - "triggerPath": "/expected-fail/time-window", - "replayExpectation": "fail" - } - ], - "expectedPassScenarios": [ - "deps-http", - "deps-http2", - "deps-grpc", - "deps-mysql", - "deps-postgres", - "deps-mongo", - "deps-redis", - "deps-kafka", - "deps-sqs", - "deps-generic", - "dedup/catalog", - "dedup/order", - "async/catalog-sync", - "async/catalog-sync/wait" - ], - "expectedNoisyScenarios": [ - "noise/runtime" - ], - "expectedFailScenarios": [ - "expected-fail/time-window" - ], - "environmentAgnostic": true, - "globalNoiseSuggestions": { - "body": [ - "runtime.requestId", - "runtime.servedAt" - ], - "header": [ - "x-matrix-generated-at", - "etag" - ] - } - } -} diff --git a/node-dependency-matrix/k8s/README.md b/node-dependency-matrix/k8s/README.md deleted file mode 100644 index ec8bcdc..0000000 --- a/node-dependency-matrix/k8s/README.md +++ /dev/null @@ -1,312 +0,0 @@ -# Kubernetes Setup - -This sample is the Kind-based regression target for Keploy Enterprise + `k8s-proxy` recording in Kubernetes. - -What it covers: - -- incoming HTTP testcases -- incoming gRPC testcases -- outgoing HTTPS -- outgoing HTTP/2 -- outgoing gRPC -- outgoing MySQL -- outgoing Postgres -- outgoing Mongo over TLS -- outgoing Redis over TLS -- outgoing Kafka -- outgoing SQS over HTTPS -- outgoing generic TLS traffic -- POST JSON + header-driven ingress cases -- an async background workflow that fans out to HTTP, Redis, and SQS after the initial response -- noisy replay cases -- expected replay failures -- static dedup-friendly duplicate GET and POST requests - -Transport notes: - -- incoming HTTP is plaintext on the sample service -- incoming gRPC is plaintext on the sample service -- outgoing HTTPS, HTTP/2, gRPC, Mongo, Redis, SQS, and the generic socket flow use TLS in the default path -- outgoing MySQL, Postgres, and Kafka use direct protocol connections in the default path -- MySQL is started with `mysql_native_password` because the current Keploy MySQL recorder does not handle the default MySQL 8 `caching_sha2_password` handshake reliably during recording -- Mongo, Redis, and the generic TLS socket keep TLS but skip hostname verification because the current Keploy TLS MITM path for those flows does not preserve SANs reliably during recording -- `mysql-tls`, `postgres-tls`, and `kafka-tls` are deployed for experimentation, but they are not exercised by the default app config today -- the async workflow stays inside one pod; it validates background dependency capture, not multi-workload consumer coordination - -The official Keploy Kind flow is documented at [Kubernetes Local Setup (Kind)](https://keploy.io/docs/keploy-cloud/kubernetes-local-setup/). The VM-specific hosted UI flow in `Run k8s-proxy ( with our ui ) with the kind in our vm’s.pdf` adds the hostname/TLS details you need when the cluster is running on a VM and the browser is on your laptop. - -## 1. Prerequisites - -Install and verify: - -- Docker -- `kind` -- `kubectl` -- Helm -- access to a hosted Keploy UI environment - -You do not need a local `enterprise-ui` or `api-server` for this flow. Use whichever hosted environment you want and keep the UI domain, `apiServerUrl`, and Helm `environment` value consistent. - -## 2. Choose the ingress mode before you deploy - -You need one ingress URL for `k8s-proxy`, and the exact same URL must be used in: - -- the hosted UI cluster entry -- the Helm value `keploy.ingressUrl` -- your browser trust flow - -### Option A: same machine as the browser - -If the browser and the Kind cluster are on the same machine, use: - -```text -http://localhost:30080 -``` - -This matches the official doc and requires `proxy.insecure.enabled=true`. - -### Option B: Kind is running inside a VM - -If the cluster is on a VM and you are opening the hosted UI from your laptop, use a hostname that resolves to the VM IP and open the proxy over HTTPS: - -```text -https://:30080 -``` - -Do this first on the laptop: - -1. Add an `/etc/hosts` entry that maps the VM IP to the hostname you will use. -2. Open `https://:30080` once after `k8s-proxy` is installed and accept the self-signed certificate warning. -3. If Chrome ignores your hosts entry because of secure DNS, disable secure DNS or use a browser that honors the local hosts mapping. - -The PDF examples use hostnames like `https://ayush.sharma.io:30080` and `https://yogesh.keploy.io:30080`. - -## 3. Create the Kind cluster and deploy the sample - -From `samples-typescript/node-dependency-matrix/`: - -```bash -bash k8s/deploy-kind.sh -``` - -If `30080`, `30081`, or `30090` are already taken: - -```bash -HOST_PROXY_PORT=31080 HOST_APP_PORT=31081 HOST_GRPC_PORT=31090 bash k8s/deploy-kind.sh -``` - -If you want the deploy script to print the VM/domain ingress URL instead of `localhost`, set it before running: - -```bash -KEPLOY_INGRESS_URL=https://matrix.keploy.vm:30080 bash k8s/deploy-kind.sh -``` - -Or let the script build it for you: - -```bash -KEPLOY_INGRESS_HOST=matrix.keploy.vm bash k8s/deploy-kind.sh -``` - -If you need to recreate the cluster: - -```bash -kind delete cluster --name node-dependency-matrix -bash k8s/deploy-kind.sh -``` - -What `k8s/deploy-kind.sh` already does: - -- creates the Kind cluster with NodePort mappings for `30080`, `30081`, and `30090` -- generates the sample CA and leaf certs -- builds and loads the `node-dependency-matrix` image into Kind -- deploys MySQL, Postgres, Mongo, Redis, Redpanda, LocalStack, the TLS fixtures, and the app - -## 4. Validate the sample before involving Keploy - -Run these on the machine where Kind is running: - -```bash -curl http://localhost:30081/health -APP_URL=http://localhost:30081 bash scripts/record_traffic.sh -GRPC_TARGET=localhost:30090 bash scripts/send_grpc_traffic.sh -``` - -If you changed the host ports, keep using the overridden app/gRPC ports in the traffic scripts. - -## 5. Choose the hosted Keploy environment - -Supported examples: - -- production UI: `https://app.keploy.io/clusters` -- staging UI: `https://app.staging.keploy.io/clusters` - -Use the matching API server and Helm `environment` value: - -- production: `keploy.apiServerUrl=https://api.keploy.io`, `environment=prod` -- staging: `keploy.apiServerUrl=https://api.staging.keploy.io`, `environment=staging` - -The sample is environment-agnostic. Pick one environment and keep it consistent end to end. - -## 6. Create the cluster in the hosted UI - -Open your chosen hosted clusters page and create a new cluster with: - -- cluster name: `node-dependency-matrix` -- ingress URL: - - `http://localhost:30080` for localhost mode - - `https://:30080` for VM/domain mode - -If you changed the proxy host port, replace `30080` with that port everywhere. - -## 7. Install `k8s-proxy` from the UI-generated Helm command - -Copy the Helm command generated by the hosted UI you chose, then verify that the effective values are: - -- `keploy.clusterName=node-dependency-matrix` -- `keploy.apiServerUrl=` -- `environment=` -- `keploy.ingressUrl=` -- `service.type=NodePort` -- `service.nodePort=30080` -- `proxy.insecure.enabled=true` - -Notes: - -- `proxy.insecure.enabled=true` is required for the `http://localhost:30080` NodePort flow from the official doc. -- For the VM/domain flow, keep the hostname exactly consistent between the hosted UI entry, the Helm value, and your `/etc/hosts` entry. -- Do not mix environments. For example, do not use `app.staging.keploy.io` with `https://api.keploy.io`, and do not use `environment=prod` with staging URLs. - -After Helm install: - -```bash -kubectl get pods -n keploy -kubectl logs -n keploy -l app=k8s-proxy --tail=100 -f -``` - -Healthy signals: - -- the `k8s-proxy` pod reaches `Running` -- no repeated `401` login failures -- the hosted UI cluster page turns `Active` -- the `default` namespace and `node-dependency-matrix` deployment are visible in the UI - -## 8. Start recording in the hosted UI - -Record this deployment: - -- namespace: `default` -- deployment: `node-dependency-matrix` - -When recording starts, the app pod should roll and become `2/2` because the Keploy sidecar gets injected. - -Watch it: - -```bash -kubectl get pods -w -``` - -## 9. Generate record-time traffic - -Once the hosted UI has started recording and the pod is `2/2`, port-forward the app service: - -```bash -bash k8s/port-forward.sh -``` - -Then, in a second terminal, run: - -```bash -APP_URL=http://localhost:8080 bash scripts/record_traffic.sh -GRPC_TARGET=localhost:9090 bash scripts/send_grpc_traffic.sh -``` - -If `8080` or `9090` are already in use locally: - -```bash -LOCAL_HTTP_PORT=18080 LOCAL_GRPC_PORT=19090 bash k8s/port-forward.sh -APP_URL=http://localhost:18080 bash scripts/record_traffic.sh -GRPC_TARGET=localhost:19090 bash scripts/send_grpc_traffic.sh -``` - -Expected record-time behavior: - -- the deployment restarts when recording begins -- the restarted pod becomes `2/2` -- the sample traffic goes through `kubectl port-forward`, not the service NodePorts -- the HTTP script creates exactly 23 HTTP testcases -- the gRPC script adds 2 incoming gRPC testcases -- the mock inventory includes the supported outgoing kinds, with acceptable fallbacks captured in the expectations file -- the async workflow finishes and records background HTTP, Redis, and SQS activity -- the noisy endpoint is reported as noisy during replay -- the time-window endpoint is an intentional replay failure - -## 10. Use the machine-readable contract for replay and validation - -The contract is in: - -```bash -fixtures/expected-values.json -``` - -It now includes: - -- the supported incoming and outgoing coverage matrix -- the hosted UI and Helm expectations -- the exact HTTP and gRPC traffic plans -- the async workflow request/response and background dependency plan -- preferred and acceptable mock kinds per scenario -- dedup expectations -- expected pass/noisy/fail replay outcomes - -The sample also exposes the same contract over HTTP: - -```bash -curl http://localhost:30081/expectations -``` - -That endpoint is the easiest source for future automation because it keeps the traffic plan and verification contract next to the sample itself. - -## 11. Local validation traffic path - -The existing cluster validation flow uses two separate network paths: - -- the browser talks to `k8s-proxy` through the cluster ingress URL -- the sample traffic itself is sent through `kubectl port-forward` to the app service - -This sample now documents that explicitly. For local validation, port-forward the app service instead of sending sample traffic to the proxy ingress: - -```bash -bash k8s/port-forward.sh -``` - -Then use: - -```bash -curl http://localhost:8080/health -APP_URL=http://localhost:8080 bash scripts/record_traffic.sh -GRPC_TARGET=localhost:9090 bash scripts/send_grpc_traffic.sh -``` - -The same ports and service name are also captured in `fixtures/expected-values.json`. - -## 12. Troubleshooting - -If the cluster never becomes `Active`: - -- verify the ingress URL in the hosted UI exactly matches the Helm value -- check `kubectl logs -n keploy -l app=k8s-proxy` -- confirm the access key in the Helm command is valid for the environment you chose -- confirm the UI domain, `apiServerUrl`, and Helm `environment` all point to the same environment - -If the laptop browser cannot reach the VM-hosted proxy: - -- verify the VM IP to hostname mapping in `/etc/hosts` -- make sure the Kind control-plane NodePort is mapped to `30080` -- confirm the service exists with `kubectl -n keploy get svc` -- visit the HTTPS ingress URL once and accept the certificate warning - -If recording starts but the app pod never reaches `2/2`: - -- check `kubectl describe pod ` -- check `kubectl logs deployment/node-dependency-matrix` -- verify the Keploy webhook and sidecar injection are healthy in the `k8s-proxy` logs diff --git a/node-dependency-matrix/k8s/STAGING_RUNBOOK.md b/node-dependency-matrix/k8s/STAGING_RUNBOOK.md deleted file mode 100644 index 70a5a30..0000000 --- a/node-dependency-matrix/k8s/STAGING_RUNBOOK.md +++ /dev/null @@ -1,544 +0,0 @@ -# Staging K8s Runbook - -This is the end-to-end runbook for using `node-dependency-matrix` with: - -- a local Kind cluster -- hosted Keploy staging UI -- `k8s-proxy` -- manual recording and replay validation - -This document is based on the exact flow that was used to make the sample work on a Mac. - -## Scope - -This runbook covers: - -- local tool setup -- sample deployment into Kind -- cluster registration in hosted staging UI -- `k8s-proxy` Helm install -- record-time traffic generation -- replay expectations -- troubleshooting for the real errors that came up while stabilizing the sample - -## 1. Use the right branch - -```bash -cd /Users/asish/coding/work/regression-test-kube-cloud-flow/samples-typescript -git fetch origin -git checkout codex/node-dependency-matrix -git pull -cd node-dependency-matrix -``` - -The branch that contains the working setup is: - -- `codex/node-dependency-matrix` - -## 2. Install and verify tools - -You need: - -- Docker Desktop -- `kubectl` -- `kind` -- Helm -- Node.js + npm - -On this Mac, tool lookup was sometimes inconsistent between shells. If commands are missing, use: - -```bash -export PATH=/opt/homebrew/bin:/usr/local/bin:/Applications/Docker.app/Contents/Resources/bin:$PATH -``` - -Verify: - -```bash -docker --version -kubectl version --client -kind --version -helm version -node --version -npm --version -``` - -## 3. Deploy the sample into Kind - -Default ports: - -- proxy host port: `30080` -- app HTTP port: `30081` -- app gRPC port: `30090` - -If those ports are free: - -```bash -bash k8s/deploy-kind.sh -``` - -If they are not free, use custom host ports. This is what was used during the working validation: - -```bash -HOST_PROXY_PORT=31080 HOST_APP_PORT=31081 HOST_GRPC_PORT=31090 bash k8s/deploy-kind.sh -``` - -What this does: - -- creates the Kind cluster -- generates sample certs -- builds and loads the sample image -- deploys MySQL, Postgres, Mongo, Redis, Redpanda, LocalStack, TLS fixtures, and the app - -## 4. Validate the sample before involving Keploy - -For the custom-port setup: - -```bash -curl http://localhost:31081/health -APP_URL=http://localhost:31081 bash scripts/record_traffic.sh -GRPC_TARGET=localhost:31090 bash scripts/send_grpc_traffic.sh -``` - -For default ports, replace `31081/31090` with `30081/30090`. - -Expected behavior: - -- `/health` returns JSON with `status: ok` -- `record_traffic.sh` runs all scenarios and exits `0` -- `send_grpc_traffic.sh` returns a `pong` response and a `deps-http` scenario result - -## 5. Open hosted staging UI - -Use the staging cluster UI: - -- [https://app.staging.keploy.io/clusters](https://app.staging.keploy.io/clusters) - -When you create the cluster entry, use: - -- cluster name: `node-dependency-matrix` -- ingress URL: `http://localhost:31080` if you used custom host port `31080` -- ingress URL: `http://localhost:30080` if you used the default host port - -Important: - -- the browser-facing ingress URL must match the host port on your Mac -- the chart `service.nodePort` inside Kind still stays `30080` - -## 6. Install `k8s-proxy` - -Do not rely blindly on the UI-generated Helm command. Validate the effective values. - -For staging, the chart must effectively use: - -- `keploy.accessKey=` -- `keploy.clusterName=node-dependency-matrix` -- `keploy.apiServerUrl=https://api.staging.keploy.io` -- `keploy.ingressUrl=http://localhost:31080` or `http://localhost:30080` -- `environment=staging` -- `service.type=NodePort` -- `service.nodePort=30080` -- `proxy.insecure.enabled=true` - -Example for the custom host-port flow: - -```bash -export PATH=/opt/homebrew/bin:/usr/local/bin:/Applications/Docker.app/Contents/Resources/bin:$PATH - -helm upgrade --install k8s-proxy oci://docker.io/keploy/k8s-proxy-chart --version 3.3.8 \ - --namespace keploy \ - --create-namespace \ - --set keploy.accessKey="" \ - --set keploy.clusterName="node-dependency-matrix" \ - --set keploy.apiServerUrl="https://api.staging.keploy.io" \ - --set keploy.ingressUrl="http://localhost:31080" \ - --set environment="staging" \ - --set service.type="NodePort" \ - --set service.nodePort="30080" \ - --set proxy.insecure.enabled="true" -``` - -Why this matters: - -- the chart uses nested `keploy.*` values -- the top-level `apiServerUrl` value is not enough -- without `service.type=NodePort`, the browser cannot reach the cluster agent -- without `proxy.insecure.enabled=true`, localhost browser access becomes a TLS/cert problem - -## 7. Verify `k8s-proxy` - -```bash -export PATH=/opt/homebrew/bin:/usr/local/bin:/Applications/Docker.app/Contents/Resources/bin:$PATH - -kubectl get pods -n keploy -kubectl get svc -n keploy -kubectl logs -n keploy -l app=k8s-proxy --tail=100 -f -``` - -Healthy signals: - -- the pod is `Running` -- the cluster page in staging becomes `Active` -- logs include `Initial Login successful` -- logs point to `https://api.staging.keploy.io` -- the service exposes `8081:30080/TCP` - -## 8. Start recording - -In staging UI: - -1. Open cluster `node-dependency-matrix` -2. Find deployment `default / node-dependency-matrix` -3. Click `Record` -4. Keep the normal defaults in the recording dialog -5. Start recording - -While recording starts: - -```bash -export PATH=/opt/homebrew/bin:/usr/local/bin:/Applications/Docker.app/Contents/Resources/bin:$PATH -kubectl get pods -n default -w -``` - -Expected behavior: - -- the app deployment restarts -- the new app pod becomes `2/2 Running` - -That `2/2` is the app container plus the Keploy sidecar. - -## 9. Send record-time traffic - -Once the hosted UI has started recording and the pod is `2/2 Running`, port-forward the app service: - -```bash -cd /Users/asish/coding/work/regression-test-kube-cloud-flow/samples-typescript/node-dependency-matrix -bash k8s/port-forward.sh -``` - -Then, in a second terminal: - -```bash -cd /Users/asish/coding/work/regression-test-kube-cloud-flow/samples-typescript/node-dependency-matrix -APP_URL=http://localhost:8080 bash scripts/record_traffic.sh -GRPC_TARGET=localhost:9090 bash scripts/send_grpc_traffic.sh -``` - -If `8080` or `9090` are already in use locally: - -```bash -cd /Users/asish/coding/work/regression-test-kube-cloud-flow/samples-typescript/node-dependency-matrix -LOCAL_HTTP_PORT=18080 LOCAL_GRPC_PORT=19090 bash k8s/port-forward.sh -APP_URL=http://localhost:18080 bash scripts/record_traffic.sh -GRPC_TARGET=localhost:19090 bash scripts/send_grpc_traffic.sh -``` - -Important: - -- after Keploy starts recording, do not send sample traffic to `30081/30090` or `31081/31090` -- keep using the hosted UI ingress URL only for the browser and `k8s-proxy` - -What this record-time traffic hits: - -- `/deps/http` -- `/deps/http2` -- `/deps/grpc` -- `/deps/mysql` -- `/deps/postgres` -- `/deps/mongo` -- `/deps/redis` -- `/deps/kafka` -- `/deps/sqs` -- `/deps/generic` -- GET and POST dedup endpoints -- async background-sync start and wait endpoints -- noisy endpoint -- expected replay-failure endpoint -- incoming gRPC endpoints - -The seed script now prints each scenario name before it runs, so failures are obvious. - -## 10. Stop recording and inspect the run - -In the UI: - -1. Stop recording -2. Open the captured recordings -3. Compare what you see with: - - [expected-values.json](/Users/asish/coding/work/regression-test-kube-cloud-flow/samples-typescript/node-dependency-matrix/fixtures/expected-values.json) - -What to verify: - -- 23 HTTP testcases and 2 incoming gRPC testcases were captured -- mock kinds are present for supported outgoing dependencies -- dedup captured repeated GET and POST requests -- the async workflow completed and captured its background HTTP, Redis, and SQS calls -- the noisy endpoint is recorded -- the time-window endpoint is recorded - -## 11. Trigger replay - -From the UI, start replay for the recorded run. - -Expected replay contract is already encoded in: - -- [expected-values.json](/Users/asish/coding/work/regression-test-kube-cloud-flow/samples-typescript/node-dependency-matrix/fixtures/expected-values.json) - -In broad terms: - -- core dependency flows should pass -- async catalog sync should pass -- `noise/runtime` should be noisy -- `expected-fail/time-window` is an intentional replay-failure case - -## 12. How to refresh the app after code changes - -If you change the sample and want that new code in the live Kind cluster: - -```bash -cd /Users/asish/coding/work/regression-test-kube-cloud-flow/samples-typescript/node-dependency-matrix -npm run build -docker build --pull=false -t node-dependency-matrix:latest . -kind load docker-image node-dependency-matrix:latest --name node-dependency-matrix -kubectl rollout restart deployment/node-dependency-matrix -n default -kubectl rollout status deployment/node-dependency-matrix -n default --timeout=240s -``` - -Wait until the new pod is back at `2/2` before sending more traffic during an active recording window. - -## 13. Troubleshooting - -### Error: `Login failed, retrying... status code 401` - -Symptoms: - -- proxy logs show `https://api.keploy.io/cluster/login` -- repeated `401` -- cluster never becomes active - -Cause: - -- prod/staging mismatch, or -- wrong access key, or -- wrong chart values path - -Fix: - -1. Make sure you are using staging UI if you want staging. -2. Use nested `keploy.*` values in Helm, not only top-level values. -3. Set: - - `keploy.apiServerUrl=https://api.staging.keploy.io` - - `environment=staging` -4. Create a fresh cluster in staging UI if the access key may be stale. - -### Error: cluster page shows active heartbeat but agent is not reachable - -Symptoms: - -- cluster page is active -- deployment list is broken or agent connection fails - -Cause: - -- wrong ingress URL or wrong host port - -Fix: - -1. Check what host port your Kind cluster actually mapped. -2. If you used `HOST_PROXY_PORT=31080`, the hosted UI cluster entry and Helm `keploy.ingressUrl` must both use `http://localhost:31080`. -3. Keep `service.nodePort=30080` inside the chart. - -### Error: browser cannot connect to `https://localhost:30080` - -Cause: - -- the secure listener needs browser trust - -Fix: - -- Prefer `proxy.insecure.enabled=true` with `http://localhost:` for local Mac + hosted UI. - -That is the setup used here. - -### Error: pod never becomes `2/2` after record starts - -Symptoms: - -- recording starts in UI -- app pod restarts or hangs incorrectly -- sidecar is not present - -Fix: - -```bash -kubectl get pods -n default -kubectl describe pod -n default -kubectl logs -n keploy -l app=k8s-proxy --tail=200 -``` - -You want to confirm the webhook and restart flow succeeded. - -### Error: MySQL request returns `500` during recording - -Symptoms: - -- `/deps/mysql` fails during recording -- Keploy logs mention `caching_sha2_password` - -Cause: - -- Keploy’s MySQL recorder does not reliably handle the default MySQL 8 `caching_sha2_password` handshake - -Fix already applied in this sample: - -- MySQL is started with `mysql_native_password` - -Files: - -- [01-mysql.yaml](/Users/asish/coding/work/regression-test-kube-cloud-flow/samples-typescript/node-dependency-matrix/k8s/manifests/01-mysql.yaml) -- [compose.yaml](/Users/asish/coding/work/regression-test-kube-cloud-flow/samples-typescript/node-dependency-matrix/compose.yaml) - -### Error: Redis request fails with `ERR_TLS_CERT_ALTNAME_INVALID` - -Symptoms: - -- `/deps/redis` fails -- app logs mention hostname mismatch for `redis-tls` - -Cause: - -- current Keploy TLS MITM path for Redis does not preserve SANs in a way that satisfies strict hostname verification - -Fix already applied in this sample: - -- keep TLS -- skip hostname verification for that Redis client - -File: - -- [dependencies.ts](/Users/asish/coding/work/regression-test-kube-cloud-flow/samples-typescript/node-dependency-matrix/src/lib/dependencies.ts) - -### Error: Mongo request fails with hostname mismatch or server-selection timeout - -Symptoms: - -- `/deps/mongo` fails -- app logs mention `Hostname/IP does not match certificate's altnames` - or `Server selection timed out after 30000 ms` - -Cause: - -- same class of TLS MITM SAN mismatch as Redis -- Mongo topology discovery can also drift from the `mongo-tls` endpoint to the - plain upstream `mongo` service, which makes selection hang behind the TLS - proxy path - -Fix already applied in this sample: - -- keep TLS -- skip hostname verification for the Mongo client -- force a direct connection to the configured `mongo-tls` endpoint -- use polling server monitoring so the Mongo driver does not rely on the - default streaming monitor through the proxied path - -File: - -- [dependencies.ts](/Users/asish/coding/work/regression-test-kube-cloud-flow/samples-typescript/node-dependency-matrix/src/lib/dependencies.ts) - -### Error: generic TLS request fails with hostname mismatch - -Symptoms: - -- `/deps/generic` returns `500` -- app logs mention `fixture-service` alt-name mismatch - -Cause: - -- same class of TLS MITM SAN mismatch as Redis - -Fix already applied in this sample: - -- keep TLS -- skip hostname verification for the generic TLS socket - -File: - -- [dependencies.ts](/Users/asish/coding/work/regression-test-kube-cloud-flow/samples-typescript/node-dependency-matrix/src/lib/dependencies.ts) - -### Error: Docker build hangs on `load metadata for docker.io/library/node:20-bookworm-slim` - -Symptoms: - -- Docker stalls on the base image metadata step -- BuildKit hangs before the real build starts - -Fix: - -1. The Dockerfile is pinned to the exact digest that was already working locally. -2. Build with: - -```bash -docker build --pull=false -t node-dependency-matrix:latest . -``` - -File: - -- [Dockerfile](/Users/asish/coding/work/regression-test-kube-cloud-flow/samples-typescript/node-dependency-matrix/Dockerfile) - -### Error: `kubectl`, `helm`, `docker`, `npm`, or `node` are not found - -Cause: - -- shell PATH does not include Homebrew or Docker Desktop CLI locations - -Fix: - -```bash -export PATH=/opt/homebrew/bin:/usr/local/bin:/Applications/Docker.app/Contents/Resources/bin:$PATH -``` - -## 14. Commands that were used successfully in the working setup - -Deploy: - -```bash -HOST_PROXY_PORT=31080 HOST_APP_PORT=31081 HOST_GRPC_PORT=31090 bash k8s/deploy-kind.sh -``` - -Validate sample: - -```bash -curl http://localhost:31081/health -APP_URL=http://localhost:31081 bash scripts/record_traffic.sh -GRPC_TARGET=localhost:31090 bash scripts/send_grpc_traffic.sh -``` - -Install `k8s-proxy` for staging: - -```bash -helm upgrade --install k8s-proxy oci://docker.io/keploy/k8s-proxy-chart --version 3.3.8 \ - --namespace keploy \ - --create-namespace \ - --set keploy.accessKey="" \ - --set keploy.clusterName="node-dependency-matrix" \ - --set keploy.apiServerUrl="https://api.staging.keploy.io" \ - --set keploy.ingressUrl="http://localhost:31080" \ - --set environment="staging" \ - --set service.type="NodePort" \ - --set service.nodePort="30080" \ - --set proxy.insecure.enabled="true" -``` - -Verify proxy: - -```bash -kubectl get pods -n keploy -kubectl get svc -n keploy -kubectl logs -n keploy -l app=k8s-proxy --tail=100 -``` - -## 15. Cleanup - -```bash -helm uninstall -n keploy k8s-proxy -kind delete cluster --name node-dependency-matrix -``` diff --git a/node-dependency-matrix/k8s/deploy-kind.sh b/node-dependency-matrix/k8s/deploy-kind.sh deleted file mode 100755 index 093bdb3..0000000 --- a/node-dependency-matrix/k8s/deploy-kind.sh +++ /dev/null @@ -1,124 +0,0 @@ -#!/bin/bash -set -euo pipefail - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -CLUSTER_NAME="${KIND_CLUSTER_NAME:-node-dependency-matrix}" -KIND_CONTEXT="kind-${CLUSTER_NAME}" -KUBECTL=(kubectl --context "${KIND_CONTEXT}") -IMAGE_NAME="${IMAGE_NAME:-node-dependency-matrix:latest}" -KIND_NODE_IMAGE="${KIND_NODE_IMAGE:-}" -CERT_DIR="${ROOT_DIR}/.generated/certs" -HOST_PROXY_PORT="${HOST_PROXY_PORT:-30080}" -HOST_APP_PORT="${HOST_APP_PORT:-30081}" -HOST_GRPC_PORT="${HOST_GRPC_PORT:-30090}" -KEPLOY_INGRESS_URL="${KEPLOY_INGRESS_URL:-}" -KEPLOY_INGRESS_HOST="${KEPLOY_INGRESS_HOST:-localhost}" -KEPLOY_INGRESS_SCHEME="${KEPLOY_INGRESS_SCHEME:-}" -SKIP_DEPENDENCY_PULLS="${SKIP_DEPENDENCY_PULLS:-0}" - -DEPENDENCY_IMAGES=( - "mysql:8.0" - "postgres:16" - "mongo:7" - "redis:7-alpine" - "docker.redpanda.com/redpandadata/redpanda:v25.1.2" - "localstack/localstack:3.3" -) - -if ! kind get clusters | grep -qx "${CLUSTER_NAME}"; then - TMP_KIND_CONFIG="$(mktemp)" - cat > "${TMP_KIND_CONFIG}" </dev/null || true - done -fi - -docker build --pull=false -t "${IMAGE_NAME}" "${ROOT_DIR}" -kind load docker-image "${IMAGE_NAME}" --name "${CLUSTER_NAME}" - -"${KUBECTL[@]}" delete secret node-dependency-matrix-tls --ignore-not-found=true -"${KUBECTL[@]}" create secret generic node-dependency-matrix-tls \ - --from-file=ca.crt="${CERT_DIR}/ca.crt" \ - --from-file=proxy.crt="${CERT_DIR}/proxy.crt" \ - --from-file=proxy-fullchain.crt="${CERT_DIR}/proxy-fullchain.crt" \ - --from-file=proxy.key="${CERT_DIR}/proxy.key" - -"${KUBECTL[@]}" apply -f "${ROOT_DIR}/k8s/manifests" - -for tls_consumer in fixture-service mysql-tls postgres-tls mongo-tls redis-tls kafka-tls sqs-tls node-dependency-matrix; do - "${KUBECTL[@]}" rollout restart "deployment/${tls_consumer}" -done - -"${KUBECTL[@]}" rollout status deployment/mysql --timeout=180s -"${KUBECTL[@]}" rollout status deployment/postgres --timeout=180s -"${KUBECTL[@]}" rollout status deployment/mongo --timeout=180s -"${KUBECTL[@]}" rollout status deployment/redis --timeout=180s -"${KUBECTL[@]}" rollout status deployment/redpanda --timeout=180s -"${KUBECTL[@]}" rollout status deployment/localstack --timeout=180s -"${KUBECTL[@]}" rollout status deployment/fixture-service --timeout=180s -"${KUBECTL[@]}" rollout status deployment/mysql-tls --timeout=180s -"${KUBECTL[@]}" rollout status deployment/postgres-tls --timeout=180s -"${KUBECTL[@]}" rollout status deployment/mongo-tls --timeout=180s -"${KUBECTL[@]}" rollout status deployment/redis-tls --timeout=180s -"${KUBECTL[@]}" rollout status deployment/kafka-tls --timeout=180s -"${KUBECTL[@]}" rollout status deployment/sqs-tls --timeout=180s -"${KUBECTL[@]}" rollout status deployment/node-dependency-matrix --timeout=180s - -"${KUBECTL[@]}" get pods,svc - -if [[ -z "${KEPLOY_INGRESS_URL}" ]]; then - if [[ -z "${KEPLOY_INGRESS_SCHEME}" ]]; then - if [[ "${KEPLOY_INGRESS_HOST}" == "localhost" || "${KEPLOY_INGRESS_HOST}" == "127.0.0.1" ]]; then - KEPLOY_INGRESS_SCHEME="http" - else - KEPLOY_INGRESS_SCHEME="https" - fi - fi - - KEPLOY_INGRESS_URL="${KEPLOY_INGRESS_SCHEME}://${KEPLOY_INGRESS_HOST}:${HOST_PROXY_PORT}" -fi - -echo "" -echo "HTTP app: http://localhost:${HOST_APP_PORT}" -echo "gRPC app: localhost:${HOST_GRPC_PORT}" -echo "Keploy ingress URL: ${KEPLOY_INGRESS_URL}" -echo "Use that same ingress URL when you create the cluster in Keploy staging UI." diff --git a/node-dependency-matrix/k8s/kind-config.yaml b/node-dependency-matrix/k8s/kind-config.yaml deleted file mode 100644 index 45d945d..0000000 --- a/node-dependency-matrix/k8s/kind-config.yaml +++ /dev/null @@ -1,14 +0,0 @@ -kind: Cluster -apiVersion: kind.x-k8s.io/v1alpha4 -nodes: - - role: control-plane - extraPortMappings: - - containerPort: 30080 - hostPort: 30080 - protocol: TCP - - containerPort: 30081 - hostPort: 30081 - protocol: TCP - - containerPort: 30090 - hostPort: 30090 - protocol: TCP diff --git a/node-dependency-matrix/k8s/manifests/00-localstack.yaml b/node-dependency-matrix/k8s/manifests/00-localstack.yaml deleted file mode 100644 index 871a341..0000000 --- a/node-dependency-matrix/k8s/manifests/00-localstack.yaml +++ /dev/null @@ -1,54 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: localstack-init-scripts -data: - 01-create-queue.sh: | - #!/bin/sh - set -eu - awslocal sqs create-queue --queue-name dependency-matrix >/dev/null 2>&1 || true ---- -apiVersion: v1 -kind: Service -metadata: - name: localstack -spec: - selector: - app: localstack - ports: - - name: edge - port: 4566 - targetPort: 4566 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: localstack -spec: - replicas: 1 - selector: - matchLabels: - app: localstack - template: - metadata: - labels: - app: localstack - spec: - containers: - - name: localstack - image: localstack/localstack:3.3 - env: - - name: SERVICES - value: sqs - - name: AWS_DEFAULT_REGION - value: us-east-1 - ports: - - containerPort: 4566 - volumeMounts: - - name: init-scripts - mountPath: /etc/localstack/init/ready.d - volumes: - - name: init-scripts - configMap: - name: localstack-init-scripts - defaultMode: 0755 diff --git a/node-dependency-matrix/k8s/manifests/01-mysql.yaml b/node-dependency-matrix/k8s/manifests/01-mysql.yaml deleted file mode 100644 index 82098f8..0000000 --- a/node-dependency-matrix/k8s/manifests/01-mysql.yaml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: mysql -spec: - selector: - app: mysql - ports: - - name: mysql - port: 3306 - targetPort: 3306 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: mysql -spec: - replicas: 1 - selector: - matchLabels: - app: mysql - template: - metadata: - labels: - app: mysql - spec: - containers: - - name: mysql - image: mysql:8.0 - args: - - mysqld - - --default-authentication-plugin=mysql_native_password - env: - - name: MYSQL_ALLOW_EMPTY_PASSWORD - value: "yes" - - name: MYSQL_DATABASE - value: matrix - ports: - - containerPort: 3306 diff --git a/node-dependency-matrix/k8s/manifests/02-postgres.yaml b/node-dependency-matrix/k8s/manifests/02-postgres.yaml deleted file mode 100644 index 171eeee..0000000 --- a/node-dependency-matrix/k8s/manifests/02-postgres.yaml +++ /dev/null @@ -1,38 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: postgres -spec: - selector: - app: postgres - ports: - - name: postgres - port: 5432 - targetPort: 5432 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: postgres -spec: - replicas: 1 - selector: - matchLabels: - app: postgres - template: - metadata: - labels: - app: postgres - spec: - containers: - - name: postgres - image: postgres:16 - env: - - name: POSTGRES_HOST_AUTH_METHOD - value: trust - - name: POSTGRES_DB - value: matrix - - name: POSTGRES_USER - value: postgres - ports: - - containerPort: 5432 diff --git a/node-dependency-matrix/k8s/manifests/03-mongo.yaml b/node-dependency-matrix/k8s/manifests/03-mongo.yaml deleted file mode 100644 index 23234cc..0000000 --- a/node-dependency-matrix/k8s/manifests/03-mongo.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: mongo -spec: - selector: - app: mongo - ports: - - name: mongo - port: 27017 - targetPort: 27017 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: mongo -spec: - replicas: 1 - selector: - matchLabels: - app: mongo - template: - metadata: - labels: - app: mongo - spec: - containers: - - name: mongo - image: mongo:7 - args: - - --bind_ip_all - ports: - - containerPort: 27017 diff --git a/node-dependency-matrix/k8s/manifests/04-redis.yaml b/node-dependency-matrix/k8s/manifests/04-redis.yaml deleted file mode 100644 index 4bc0236..0000000 --- a/node-dependency-matrix/k8s/manifests/04-redis.yaml +++ /dev/null @@ -1,37 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: redis -spec: - selector: - app: redis - ports: - - name: redis - port: 6379 - targetPort: 6379 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: redis -spec: - replicas: 1 - selector: - matchLabels: - app: redis - template: - metadata: - labels: - app: redis - spec: - containers: - - name: redis - image: redis:7-alpine - args: - - redis-server - - --appendonly - - "no" - - --save - - "" - ports: - - containerPort: 6379 diff --git a/node-dependency-matrix/k8s/manifests/05-redpanda.yaml b/node-dependency-matrix/k8s/manifests/05-redpanda.yaml deleted file mode 100644 index 888bb65..0000000 --- a/node-dependency-matrix/k8s/manifests/05-redpanda.yaml +++ /dev/null @@ -1,50 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: redpanda -spec: - selector: - app: redpanda - ports: - - name: kafka - port: 9092 - targetPort: 9092 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: redpanda -spec: - replicas: 1 - selector: - matchLabels: - app: redpanda - template: - metadata: - labels: - app: redpanda - spec: - containers: - - name: redpanda - image: docker.redpanda.com/redpandadata/redpanda:v25.1.2 - args: - - redpanda - - start - - --overprovisioned - - --smp - - "1" - - --memory - - 512M - - --reserve-memory - - 0M - - --check=false - - --node-id - - "0" - - --kafka-addr - - PLAINTEXT://0.0.0.0:9092 - - --advertise-kafka-addr - - PLAINTEXT://redpanda:9092 - - --set - - redpanda.auto_create_topics_enabled=true - ports: - - containerPort: 9092 diff --git a/node-dependency-matrix/k8s/manifests/06-fixture-service.yaml b/node-dependency-matrix/k8s/manifests/06-fixture-service.yaml deleted file mode 100644 index 93acb31..0000000 --- a/node-dependency-matrix/k8s/manifests/06-fixture-service.yaml +++ /dev/null @@ -1,58 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: fixture-service -spec: - selector: - app: fixture-service - ports: - - name: https - port: 8443 - targetPort: 8443 - - name: http2 - port: 9443 - targetPort: 9443 - - name: grpc - port: 50051 - targetPort: 50051 - - name: generic - port: 9445 - targetPort: 9445 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: fixture-service -spec: - replicas: 1 - selector: - matchLabels: - app: fixture-service - template: - metadata: - labels: - app: fixture-service - spec: - containers: - - name: fixture-service - image: node-dependency-matrix:latest - imagePullPolicy: IfNotPresent - command: ["node", "dist/bin/dependencyFixture.js"] - env: - - name: TLS_CERT_PATH - value: /etc/sample-certs/proxy.crt - - name: TLS_KEY_PATH - value: /etc/sample-certs/proxy.key - ports: - - containerPort: 8443 - - containerPort: 9443 - - containerPort: 50051 - - containerPort: 9445 - volumeMounts: - - name: sample-tls - mountPath: /etc/sample-certs - readOnly: true - volumes: - - name: sample-tls - secret: - secretName: node-dependency-matrix-tls diff --git a/node-dependency-matrix/k8s/manifests/07-tls-proxies.yaml b/node-dependency-matrix/k8s/manifests/07-tls-proxies.yaml deleted file mode 100644 index 418081e..0000000 --- a/node-dependency-matrix/k8s/manifests/07-tls-proxies.yaml +++ /dev/null @@ -1,297 +0,0 @@ -apiVersion: v1 -kind: List -items: - - apiVersion: v1 - kind: Service - metadata: - name: mysql-tls - spec: - selector: - app: mysql-tls - ports: - - name: mysql - port: 3306 - targetPort: 3306 - - apiVersion: apps/v1 - kind: Deployment - metadata: - name: mysql-tls - spec: - replicas: 1 - selector: - matchLabels: - app: mysql-tls - template: - metadata: - labels: - app: mysql-tls - spec: - containers: - - name: mysql-tls - image: node-dependency-matrix:latest - imagePullPolicy: IfNotPresent - command: ["node", "dist/bin/tlsProxy.js"] - env: - - name: LISTEN_PORT - value: "3306" - - name: TARGET_HOST - value: mysql - - name: TARGET_PORT - value: "3306" - - name: TLS_CERT_PATH - value: /etc/sample-certs/proxy.crt - - name: TLS_KEY_PATH - value: /etc/sample-certs/proxy.key - volumeMounts: - - name: sample-tls - mountPath: /etc/sample-certs - readOnly: true - volumes: - - name: sample-tls - secret: - secretName: node-dependency-matrix-tls - - apiVersion: v1 - kind: Service - metadata: - name: postgres-tls - spec: - selector: - app: postgres-tls - ports: - - name: postgres - port: 5432 - targetPort: 5432 - - apiVersion: apps/v1 - kind: Deployment - metadata: - name: postgres-tls - spec: - replicas: 1 - selector: - matchLabels: - app: postgres-tls - template: - metadata: - labels: - app: postgres-tls - spec: - containers: - - name: postgres-tls - image: node-dependency-matrix:latest - imagePullPolicy: IfNotPresent - command: ["node", "dist/bin/tlsProxy.js"] - env: - - name: LISTEN_PORT - value: "5432" - - name: TARGET_HOST - value: postgres - - name: TARGET_PORT - value: "5432" - - name: TLS_CERT_PATH - value: /etc/sample-certs/proxy.crt - - name: TLS_KEY_PATH - value: /etc/sample-certs/proxy.key - volumeMounts: - - name: sample-tls - mountPath: /etc/sample-certs - readOnly: true - volumes: - - name: sample-tls - secret: - secretName: node-dependency-matrix-tls - - apiVersion: v1 - kind: Service - metadata: - name: mongo-tls - spec: - selector: - app: mongo-tls - ports: - - name: mongo - port: 27017 - targetPort: 27017 - - apiVersion: apps/v1 - kind: Deployment - metadata: - name: mongo-tls - spec: - replicas: 1 - selector: - matchLabels: - app: mongo-tls - template: - metadata: - labels: - app: mongo-tls - spec: - containers: - - name: mongo-tls - image: node-dependency-matrix:latest - imagePullPolicy: IfNotPresent - command: ["node", "dist/bin/tlsProxy.js"] - env: - - name: LISTEN_PORT - value: "27017" - - name: TARGET_HOST - value: mongo - - name: TARGET_PORT - value: "27017" - - name: TLS_CERT_PATH - value: /etc/sample-certs/proxy.crt - - name: TLS_KEY_PATH - value: /etc/sample-certs/proxy.key - volumeMounts: - - name: sample-tls - mountPath: /etc/sample-certs - readOnly: true - volumes: - - name: sample-tls - secret: - secretName: node-dependency-matrix-tls - - apiVersion: v1 - kind: Service - metadata: - name: redis-tls - spec: - selector: - app: redis-tls - ports: - - name: redis - port: 6380 - targetPort: 6380 - - apiVersion: apps/v1 - kind: Deployment - metadata: - name: redis-tls - spec: - replicas: 1 - selector: - matchLabels: - app: redis-tls - template: - metadata: - labels: - app: redis-tls - spec: - containers: - - name: redis-tls - image: node-dependency-matrix:latest - imagePullPolicy: IfNotPresent - command: ["node", "dist/bin/tlsProxy.js"] - env: - - name: LISTEN_PORT - value: "6380" - - name: TARGET_HOST - value: redis - - name: TARGET_PORT - value: "6379" - - name: TLS_CERT_PATH - value: /etc/sample-certs/proxy.crt - - name: TLS_KEY_PATH - value: /etc/sample-certs/proxy.key - volumeMounts: - - name: sample-tls - mountPath: /etc/sample-certs - readOnly: true - volumes: - - name: sample-tls - secret: - secretName: node-dependency-matrix-tls - - apiVersion: v1 - kind: Service - metadata: - name: kafka-tls - spec: - selector: - app: kafka-tls - ports: - - name: kafka - port: 9094 - targetPort: 9094 - - apiVersion: apps/v1 - kind: Deployment - metadata: - name: kafka-tls - spec: - replicas: 1 - selector: - matchLabels: - app: kafka-tls - template: - metadata: - labels: - app: kafka-tls - spec: - containers: - - name: kafka-tls - image: node-dependency-matrix:latest - imagePullPolicy: IfNotPresent - command: ["node", "dist/bin/tlsProxy.js"] - env: - - name: LISTEN_PORT - value: "9094" - - name: TARGET_HOST - value: redpanda - - name: TARGET_PORT - value: "9092" - - name: TLS_CERT_PATH - value: /etc/sample-certs/proxy.crt - - name: TLS_KEY_PATH - value: /etc/sample-certs/proxy.key - volumeMounts: - - name: sample-tls - mountPath: /etc/sample-certs - readOnly: true - volumes: - - name: sample-tls - secret: - secretName: node-dependency-matrix-tls - - apiVersion: v1 - kind: Service - metadata: - name: sqs-tls - spec: - selector: - app: sqs-tls - ports: - - name: https - port: 4567 - targetPort: 4567 - - apiVersion: apps/v1 - kind: Deployment - metadata: - name: sqs-tls - spec: - replicas: 1 - selector: - matchLabels: - app: sqs-tls - template: - metadata: - labels: - app: sqs-tls - spec: - containers: - - name: sqs-tls - image: node-dependency-matrix:latest - imagePullPolicy: IfNotPresent - command: ["node", "dist/bin/tlsProxy.js"] - env: - - name: LISTEN_PORT - value: "4567" - - name: TARGET_HOST - value: localstack - - name: TARGET_PORT - value: "4566" - - name: TLS_CERT_PATH - value: /etc/sample-certs/proxy.crt - - name: TLS_KEY_PATH - value: /etc/sample-certs/proxy.key - volumeMounts: - - name: sample-tls - mountPath: /etc/sample-certs - readOnly: true - volumes: - - name: sample-tls - secret: - secretName: node-dependency-matrix-tls diff --git a/node-dependency-matrix/k8s/manifests/08-app.yaml b/node-dependency-matrix/k8s/manifests/08-app.yaml deleted file mode 100644 index 2393eaf..0000000 --- a/node-dependency-matrix/k8s/manifests/08-app.yaml +++ /dev/null @@ -1,98 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: node-dependency-matrix -spec: - type: NodePort - selector: - app: node-dependency-matrix - ports: - - name: http - port: 8080 - targetPort: 8080 - nodePort: 30081 - - name: grpc - port: 9090 - targetPort: 9090 - nodePort: 30090 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: node-dependency-matrix -spec: - replicas: 1 - selector: - matchLabels: - app: node-dependency-matrix - template: - metadata: - labels: - app: node-dependency-matrix - spec: - containers: - - name: node-dependency-matrix - image: node-dependency-matrix:latest - imagePullPolicy: IfNotPresent - env: - - name: PORT - value: "8080" - - name: GRPC_PORT - value: "9090" - - name: FIXTURE_HTTPS_BASE - value: https://fixture-service:8443 - - name: FIXTURE_HTTP2_ORIGIN - value: https://fixture-service:9443 - - name: FIXTURE_GRPC_TARGET - value: fixture-service:50051 - - name: FIXTURE_GENERIC_HOST - value: fixture-service - - name: FIXTURE_GENERIC_PORT - value: "9445" - - name: MYSQL_URL - value: mysql://root@mysql:3306/matrix - - name: POSTGRES_URL - value: postgresql://postgres@postgres:5432/matrix - - name: MONGO_URL - value: mongodb://mongo-tls:27017/matrix?tls=true - - name: REDIS_URL - value: rediss://redis-tls:6380 - - name: KAFKA_BROKERS - value: redpanda:9092 - - name: KAFKA_TOPIC - value: matrix-events - - name: SQS_ENDPOINT - value: https://sqs-tls:4567 - - name: SQS_QUEUE_URL - value: https://sqs-tls:4567/000000000000/dependency-matrix - - name: SAMPLE_CA_CERT_PATH - value: /etc/sample-certs/ca.crt - - name: COMBINED_CA_CERT_PATH - value: /tmp/node-dependency-matrix-ca-bundle.crt - - name: NODE_EXTRA_CA_CERTS - value: /tmp/node-dependency-matrix-ca-bundle.crt - - name: SSL_CERT_FILE - value: /tmp/node-dependency-matrix-ca-bundle.crt - ports: - - containerPort: 8080 - - containerPort: 9090 - readinessProbe: - httpGet: - path: /health - port: 8080 - initialDelaySeconds: 5 - periodSeconds: 5 - livenessProbe: - httpGet: - path: /health - port: 8080 - initialDelaySeconds: 10 - periodSeconds: 10 - volumeMounts: - - name: sample-tls - mountPath: /etc/sample-certs - readOnly: true - volumes: - - name: sample-tls - secret: - secretName: node-dependency-matrix-tls diff --git a/node-dependency-matrix/k8s/port-forward.sh b/node-dependency-matrix/k8s/port-forward.sh deleted file mode 100755 index cf96738..0000000 --- a/node-dependency-matrix/k8s/port-forward.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -set -euo pipefail - -NAMESPACE="${NAMESPACE:-default}" -RESOURCE="${RESOURCE:-svc/node-dependency-matrix}" -LOCAL_HTTP_PORT="${LOCAL_HTTP_PORT:-8080}" -REMOTE_HTTP_PORT="${REMOTE_HTTP_PORT:-8080}" -LOCAL_GRPC_PORT="${LOCAL_GRPC_PORT:-9090}" -REMOTE_GRPC_PORT="${REMOTE_GRPC_PORT:-9090}" - -kubectl -n "${NAMESPACE}" port-forward "${RESOURCE}" \ - "${LOCAL_HTTP_PORT}:${REMOTE_HTTP_PORT}" \ - "${LOCAL_GRPC_PORT}:${REMOTE_GRPC_PORT}" diff --git a/node-dependency-matrix/package-lock.json b/node-dependency-matrix/package-lock.json deleted file mode 100644 index 0494c12..0000000 --- a/node-dependency-matrix/package-lock.json +++ /dev/null @@ -1,3664 +0,0 @@ -{ - "name": "node-dependency-matrix", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "node-dependency-matrix", - "version": "1.0.0", - "dependencies": { - "@aws-sdk/client-sqs": "^3.893.0", - "@grpc/grpc-js": "^1.14.0", - "@grpc/proto-loader": "^0.8.0", - "@smithy/node-http-handler": "^4.4.5", - "express": "^4.21.2", - "ioredis": "^5.8.1", - "kafkajs": "^2.2.4", - "mongodb": "^6.20.0", - "mysql2": "^3.15.3", - "pg": "^8.16.3" - }, - "devDependencies": { - "@types/express": "^4.17.21", - "@types/node": "^24.7.2", - "@types/pg": "^8.15.5", - "tsx": "^4.20.6", - "typescript": "^5.9.3" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@aws-crypto/sha256-browser": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", - "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-js": "^5.2.0", - "@aws-crypto/supports-web-crypto": "^5.2.0", - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/sha256-js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", - "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-crypto/supports-web-crypto": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", - "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-crypto/util": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", - "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.222.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-sqs": { - "version": "3.1015.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sqs/-/client-sqs-3.1015.0.tgz", - "integrity": "sha512-j194LgVzJDydlWjVT+HBR3X5GGvEOFrv123ODWww29necxiq7wy4qFZm/2CF+X/OxQL5zA0gxuCgCqDJIk0UNw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.24", - "@aws-sdk/credential-provider-node": "^3.972.25", - "@aws-sdk/middleware-host-header": "^3.972.8", - "@aws-sdk/middleware-logger": "^3.972.8", - "@aws-sdk/middleware-recursion-detection": "^3.972.8", - "@aws-sdk/middleware-sdk-sqs": "^3.972.17", - "@aws-sdk/middleware-user-agent": "^3.972.25", - "@aws-sdk/region-config-resolver": "^3.972.9", - "@aws-sdk/types": "^3.973.6", - "@aws-sdk/util-endpoints": "^3.996.5", - "@aws-sdk/util-user-agent-browser": "^3.972.8", - "@aws-sdk/util-user-agent-node": "^3.973.11", - "@smithy/config-resolver": "^4.4.13", - "@smithy/core": "^3.23.12", - "@smithy/fetch-http-handler": "^5.3.15", - "@smithy/hash-node": "^4.2.12", - "@smithy/invalid-dependency": "^4.2.12", - "@smithy/md5-js": "^4.2.12", - "@smithy/middleware-content-length": "^4.2.12", - "@smithy/middleware-endpoint": "^4.4.27", - "@smithy/middleware-retry": "^4.4.44", - "@smithy/middleware-serde": "^4.2.15", - "@smithy/middleware-stack": "^4.2.12", - "@smithy/node-config-provider": "^4.3.12", - "@smithy/node-http-handler": "^4.5.0", - "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.7", - "@smithy/types": "^4.13.1", - "@smithy/url-parser": "^4.2.12", - "@smithy/util-base64": "^4.3.2", - "@smithy/util-body-length-browser": "^4.2.2", - "@smithy/util-body-length-node": "^4.2.3", - "@smithy/util-defaults-mode-browser": "^4.3.43", - "@smithy/util-defaults-mode-node": "^4.2.47", - "@smithy/util-endpoints": "^3.3.3", - "@smithy/util-middleware": "^4.2.12", - "@smithy/util-retry": "^4.2.12", - "@smithy/util-utf8": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/core": { - "version": "3.973.24", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.24.tgz", - "integrity": "sha512-vvf82RYQu2GidWAuQq+uIzaPz9V0gSCXVqdVzRosgl5rXcspXOpSD3wFreGGW6AYymPr97Z69kjVnLePBxloDw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@aws-sdk/xml-builder": "^3.972.15", - "@smithy/core": "^3.23.12", - "@smithy/node-config-provider": "^4.3.12", - "@smithy/property-provider": "^4.2.12", - "@smithy/protocol-http": "^5.3.12", - "@smithy/signature-v4": "^5.3.12", - "@smithy/smithy-client": "^4.12.7", - "@smithy/types": "^4.13.1", - "@smithy/util-base64": "^4.3.2", - "@smithy/util-middleware": "^4.2.12", - "@smithy/util-utf8": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.22", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.22.tgz", - "integrity": "sha512-cXp0VTDWT76p3hyK5D51yIKEfpf6/zsUvMfaB8CkyqadJxMQ8SbEeVroregmDlZbtG31wkj9ei0WnftmieggLg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.973.24", - "@aws-sdk/types": "^3.973.6", - "@smithy/property-provider": "^4.2.12", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.24", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.24.tgz", - "integrity": "sha512-h694K7+tRuepSRJr09wTvQfaEnjzsKZ5s7fbESrVds02GT/QzViJ94/HCNwM7bUfFxqpPXHxulZfL6Cou0dwPg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.973.24", - "@aws-sdk/types": "^3.973.6", - "@smithy/fetch-http-handler": "^5.3.15", - "@smithy/node-http-handler": "^4.5.0", - "@smithy/property-provider": "^4.2.12", - "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.7", - "@smithy/types": "^4.13.1", - "@smithy/util-stream": "^4.5.20", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.972.24", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.24.tgz", - "integrity": "sha512-O46fFmv0RDFWiWEA9/e6oW92BnsyAXuEgTTasxHligjn2RCr9L/DK773m/NoFaL3ZdNAUz8WxgxunleMnHAkeQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.973.24", - "@aws-sdk/credential-provider-env": "^3.972.22", - "@aws-sdk/credential-provider-http": "^3.972.24", - "@aws-sdk/credential-provider-login": "^3.972.24", - "@aws-sdk/credential-provider-process": "^3.972.22", - "@aws-sdk/credential-provider-sso": "^3.972.24", - "@aws-sdk/credential-provider-web-identity": "^3.972.24", - "@aws-sdk/nested-clients": "^3.996.14", - "@aws-sdk/types": "^3.973.6", - "@smithy/credential-provider-imds": "^4.2.12", - "@smithy/property-provider": "^4.2.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.24", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.24.tgz", - "integrity": "sha512-sIk8oa6AzDoUhxsR11svZESqvzGuXesw62Rl2oW6wguZx8i9cdGCvkFg+h5K7iucUZP8wyWibUbJMc+J66cu5g==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.973.24", - "@aws-sdk/nested-clients": "^3.996.14", - "@aws-sdk/types": "^3.973.6", - "@smithy/property-provider": "^4.2.12", - "@smithy/protocol-http": "^5.3.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.25", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.25.tgz", - "integrity": "sha512-m7dR0Dsva2P+VUpL+VkC0WwiDby5pgmWXkRVDB5rlwv0jXJrQJf7YMtCoM8Wjk0H9jPeCYOxOXXcIgp/qp5Alg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.22", - "@aws-sdk/credential-provider-http": "^3.972.24", - "@aws-sdk/credential-provider-ini": "^3.972.24", - "@aws-sdk/credential-provider-process": "^3.972.22", - "@aws-sdk/credential-provider-sso": "^3.972.24", - "@aws-sdk/credential-provider-web-identity": "^3.972.24", - "@aws-sdk/types": "^3.973.6", - "@smithy/credential-provider-imds": "^4.2.12", - "@smithy/property-provider": "^4.2.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.22", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.22.tgz", - "integrity": "sha512-Os32s8/4gTZjBk5BtoS/cuTILaj+K72d0dVG7TCJX/fC4598cxwLDmf1AEHEpER5oL3K//yETjvFaz0V8oO5Xw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.973.24", - "@aws-sdk/types": "^3.973.6", - "@smithy/property-provider": "^4.2.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.972.24", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.24.tgz", - "integrity": "sha512-PaFv7snEfypU2yXkpvfyWgddEbDLtgVe51wdZlinhc2doubBjUzJZZpgwuF2Jenl1FBydMhNpMjD6SBUM3qdSA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.973.24", - "@aws-sdk/nested-clients": "^3.996.14", - "@aws-sdk/token-providers": "3.1015.0", - "@aws-sdk/types": "^3.973.6", - "@smithy/property-provider": "^4.2.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.24", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.24.tgz", - "integrity": "sha512-J6H4R1nvr3uBTqD/EeIPAskrBtET4WFfNhpFySr2xW7bVZOXpQfPjrLSIx65jcNjBmLXzWq8QFLdVoGxiGG/SA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.973.24", - "@aws-sdk/nested-clients": "^3.996.14", - "@aws-sdk/types": "^3.973.6", - "@smithy/property-provider": "^4.2.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.972.8", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.8.tgz", - "integrity": "sha512-wAr2REfKsqoKQ+OkNqvOShnBoh+nkPurDKW7uAeVSu6kUECnWlSJiPvnoqxGlfousEY/v9LfS9sNc46hjSYDIQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@smithy/protocol-http": "^5.3.12", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.972.8", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.972.8.tgz", - "integrity": "sha512-CWl5UCM57WUFaFi5kB7IBY1UmOeLvNZAZ2/OZ5l20ldiJ3TiIz1pC65gYj8X0BCPWkeR1E32mpsCk1L1I4n+lA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.972.8", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.8.tgz", - "integrity": "sha512-BnnvYs2ZEpdlmZ2PNlV2ZyQ8j8AEkMTjN79y/YA475ER1ByFYrkVR85qmhni8oeTaJcDqbx364wDpitDAA/wCA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@aws/lambda-invoke-store": "^0.2.2", - "@smithy/protocol-http": "^5.3.12", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-sqs": { - "version": "3.972.17", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sqs/-/middleware-sdk-sqs-3.972.17.tgz", - "integrity": "sha512-LnzPRRoDXGtlFV2G1p2rsY6fRKrbf6Pvvc21KliSLw3+NmQca2+Aa1QIMRbpQvZYedsSqkGYwxe+qvXwQ2uxDw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@smithy/smithy-client": "^4.12.7", - "@smithy/types": "^4.13.1", - "@smithy/util-hex-encoding": "^4.2.2", - "@smithy/util-utf8": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.972.25", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.25.tgz", - "integrity": "sha512-QxiMPofvOt8SwSynTOmuZfvvPM1S9QfkESBxB22NMHTRXCJhR5BygLl8IXfC4jELiisQgwsgUby21GtXfX3f/g==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.973.24", - "@aws-sdk/types": "^3.973.6", - "@aws-sdk/util-endpoints": "^3.996.5", - "@smithy/core": "^3.23.12", - "@smithy/protocol-http": "^5.3.12", - "@smithy/types": "^4.13.1", - "@smithy/util-retry": "^4.2.12", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients": { - "version": "3.996.14", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.14.tgz", - "integrity": "sha512-fSESKvh1VbfjtV3QMnRkCPZWkUbQof6T/DOpiLp33yP2wA+rbwwnZeG3XT3Ekljgw2I8X4XaQPnw+zSR8yxJ5Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.24", - "@aws-sdk/middleware-host-header": "^3.972.8", - "@aws-sdk/middleware-logger": "^3.972.8", - "@aws-sdk/middleware-recursion-detection": "^3.972.8", - "@aws-sdk/middleware-user-agent": "^3.972.25", - "@aws-sdk/region-config-resolver": "^3.972.9", - "@aws-sdk/types": "^3.973.6", - "@aws-sdk/util-endpoints": "^3.996.5", - "@aws-sdk/util-user-agent-browser": "^3.972.8", - "@aws-sdk/util-user-agent-node": "^3.973.11", - "@smithy/config-resolver": "^4.4.13", - "@smithy/core": "^3.23.12", - "@smithy/fetch-http-handler": "^5.3.15", - "@smithy/hash-node": "^4.2.12", - "@smithy/invalid-dependency": "^4.2.12", - "@smithy/middleware-content-length": "^4.2.12", - "@smithy/middleware-endpoint": "^4.4.27", - "@smithy/middleware-retry": "^4.4.44", - "@smithy/middleware-serde": "^4.2.15", - "@smithy/middleware-stack": "^4.2.12", - "@smithy/node-config-provider": "^4.3.12", - "@smithy/node-http-handler": "^4.5.0", - "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.7", - "@smithy/types": "^4.13.1", - "@smithy/url-parser": "^4.2.12", - "@smithy/util-base64": "^4.3.2", - "@smithy/util-body-length-browser": "^4.2.2", - "@smithy/util-body-length-node": "^4.2.3", - "@smithy/util-defaults-mode-browser": "^4.3.43", - "@smithy/util-defaults-mode-node": "^4.2.47", - "@smithy/util-endpoints": "^3.3.3", - "@smithy/util-middleware": "^4.2.12", - "@smithy/util-retry": "^4.2.12", - "@smithy/util-utf8": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.972.9", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.9.tgz", - "integrity": "sha512-eQ+dFU05ZRC/lC2XpYlYSPlXtX3VT8sn5toxN2Fv7EXlMoA2p9V7vUBKqHunfD4TRLpxUq8Y8Ol/nCqiv327Ng==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@smithy/config-resolver": "^4.4.13", - "@smithy/node-config-provider": "^4.3.12", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.1015.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1015.0.tgz", - "integrity": "sha512-3OSD4y110nisRhHzFOjoEeHU4GQL4KpzkX9PxzWaiZe0Yg2+thZKM0Pn9DjYwezH5JYfh/K++xK/SE0IHGrmCQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.973.24", - "@aws-sdk/nested-clients": "^3.996.14", - "@aws-sdk/types": "^3.973.6", - "@smithy/property-provider": "^4.2.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/types": { - "version": "3.973.6", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.6.tgz", - "integrity": "sha512-Atfcy4E++beKtwJHiDln2Nby8W/mam64opFPTiHEqgsthqeydFS1pY+OUlN1ouNOmf8ArPU/6cDS65anOP3KQw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.996.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.996.5.tgz", - "integrity": "sha512-Uh93L5sXFNbyR5sEPMzUU8tJ++Ku97EY4udmC01nB8Zu+xfBPwpIwJ6F7snqQeq8h2pf+8SGN5/NoytfKgYPIw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@smithy/types": "^4.13.1", - "@smithy/url-parser": "^4.2.12", - "@smithy/util-endpoints": "^3.3.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/util-locate-window": { - "version": "3.965.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.5.tgz", - "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.972.8", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.8.tgz", - "integrity": "sha512-B3KGXJviV2u6Cdw2SDY2aDhoJkVfY/Q/Trwk2CMSkikE1Oi6gRzxhvhIfiRpHfmIsAhV4EA54TVEX8K6CbHbkA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.973.6", - "@smithy/types": "^4.13.1", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.973.11", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.11.tgz", - "integrity": "sha512-1qdXbXo2s5MMLpUvw00284LsbhtlQ4ul7Zzdn5n+7p4WVgCMLqhxImpHIrjSoc72E/fyc4Wq8dLtUld2Gsh+lA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/middleware-user-agent": "^3.972.25", - "@aws-sdk/types": "^3.973.6", - "@smithy/node-config-provider": "^4.3.12", - "@smithy/types": "^4.13.1", - "@smithy/util-config-provider": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } - } - }, - "node_modules/@aws-sdk/xml-builder": { - "version": "3.972.15", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.15.tgz", - "integrity": "sha512-PxMRlCFNiQnke9YR29vjFQwz4jq+6Q04rOVFeTDR2K7Qpv9h9FOWOxG+zJjageimYbWqE3bTuLjmryWHAWbvaA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "fast-xml-parser": "5.5.8", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws/lambda-invoke-store": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz", - "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz", - "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz", - "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz", - "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz", - "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz", - "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz", - "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz", - "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz", - "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz", - "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz", - "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz", - "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz", - "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz", - "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz", - "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz", - "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz", - "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz", - "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz", - "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz", - "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz", - "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz", - "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz", - "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz", - "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz", - "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz", - "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz", - "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@grpc/grpc-js": { - "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==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/proto-loader": "^0.8.0", - "@js-sdsl/ordered-map": "^4.4.2" - }, - "engines": { - "node": ">=12.10.0" - } - }, - "node_modules/@grpc/proto-loader": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", - "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", - "license": "Apache-2.0", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.5.3", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@ioredis/commands": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.5.1.tgz", - "integrity": "sha512-JH8ZL/ywcJyR9MmJ5BNqZllXNZQqQbnVZOqpPQqE1vHiFgAw4NHbvE0FOduNU8IX9babitBT46571OnPTT0Zcw==", - "license": "MIT" - }, - "node_modules/@js-sdsl/ordered-map": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", - "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/@mongodb-js/saslprep": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.6.tgz", - "integrity": "sha512-y+x3H1xBZd38n10NZF/rEBlvDOOMQ6LKUTHqr8R9VkJ+mmQOYtJFxIlkkK8fZrtOiL6VixbOBWMbZGBdal3Z1g==", - "license": "MIT", - "dependencies": { - "sparse-bitfield": "^3.0.3" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "license": "BSD-3-Clause" - }, - "node_modules/@smithy/abort-controller": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.12.tgz", - "integrity": "sha512-xolrFw6b+2iYGl6EcOL7IJY71vvyZ0DJ3mcKtpykqPe2uscwtzDZJa1uVQXyP7w9Dd+kGwYnPbMsJrGISKiY/Q==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/config-resolver": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.13.tgz", - "integrity": "sha512-iIzMC5NmOUP6WL6o8iPBjFhUhBZ9pPjpUpQYWMUFQqKyXXzOftbfK8zcQCz/jFV1Psmf05BK5ypx4K2r4Tnwdg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.3.12", - "@smithy/types": "^4.13.1", - "@smithy/util-config-provider": "^4.2.2", - "@smithy/util-endpoints": "^3.3.3", - "@smithy/util-middleware": "^4.2.12", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/core": { - "version": "3.23.12", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.23.12.tgz", - "integrity": "sha512-o9VycsYNtgC+Dy3I0yrwCqv9CWicDnke0L7EVOrZtJpjb2t0EjaEofmMrYc0T1Kn3yk32zm6cspxF9u9Bj7e5w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.3.12", - "@smithy/types": "^4.13.1", - "@smithy/url-parser": "^4.2.12", - "@smithy/util-base64": "^4.3.2", - "@smithy/util-body-length-browser": "^4.2.2", - "@smithy/util-middleware": "^4.2.12", - "@smithy/util-stream": "^4.5.20", - "@smithy/util-utf8": "^4.2.2", - "@smithy/uuid": "^1.1.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.12.tgz", - "integrity": "sha512-cr2lR792vNZcYMriSIj+Um3x9KWrjcu98kn234xA6reOAFMmbRpQMOv8KPgEmLLtx3eldU6c5wALKFqNOhugmg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.3.12", - "@smithy/property-provider": "^4.2.12", - "@smithy/types": "^4.13.1", - "@smithy/url-parser": "^4.2.12", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "5.3.15", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.15.tgz", - "integrity": "sha512-T4jFU5N/yiIfrtrsb9uOQn7RdELdM/7HbyLNr6uO/mpkj1ctiVs7CihVr51w4LyQlXWDpXFn4BElf1WmQvZu/A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.3.12", - "@smithy/querystring-builder": "^4.2.12", - "@smithy/types": "^4.13.1", - "@smithy/util-base64": "^4.3.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/hash-node": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.12.tgz", - "integrity": "sha512-QhBYbGrbxTkZ43QoTPrK72DoYviDeg6YKDrHTMJbbC+A0sml3kSjzFtXP7BtbyJnXojLfTQldGdUR0RGD8dA3w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "@smithy/util-buffer-from": "^4.2.2", - "@smithy/util-utf8": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/invalid-dependency": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.12.tgz", - "integrity": "sha512-/4F1zb7Z8LOu1PalTdESFHR0RbPwHd3FcaG1sI3UEIriQTWakysgJr65lc1jj6QY5ye7aFsisajotH6UhWfm/g==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/is-array-buffer": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.2.tgz", - "integrity": "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/md5-js": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.12.tgz", - "integrity": "sha512-W/oIpHCpWU2+iAkfZYyGWE+qkpuf3vEXHLxQQDx9FPNZTTdnul0dZ2d/gUFrtQ5je1G2kp4cjG0/24YueG2LbQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "@smithy/util-utf8": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-content-length": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.12.tgz", - "integrity": "sha512-YE58Yz+cvFInWI/wOTrB+DbvUVz/pLn5mC5MvOV4fdRUc6qGwygyngcucRQjAhiCEbmfLOXX0gntSIcgMvAjmA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.3.12", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-endpoint": { - "version": "4.4.27", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.27.tgz", - "integrity": "sha512-T3TFfUgXQlpcg+UdzcAISdZpj4Z+XECZ/cefgA6wLBd6V4lRi0svN2hBouN/be9dXQ31X4sLWz3fAQDf+nt6BA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.23.12", - "@smithy/middleware-serde": "^4.2.15", - "@smithy/node-config-provider": "^4.3.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", - "@smithy/url-parser": "^4.2.12", - "@smithy/util-middleware": "^4.2.12", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-retry": { - "version": "4.4.44", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.44.tgz", - "integrity": "sha512-Y1Rav7m5CFRPQyM4CI0koD/bXjyjJu3EQxZZhtLGD88WIrBrQ7kqXM96ncd6rYnojwOo/u9MXu57JrEvu/nLrA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.3.12", - "@smithy/protocol-http": "^5.3.12", - "@smithy/service-error-classification": "^4.2.12", - "@smithy/smithy-client": "^4.12.7", - "@smithy/types": "^4.13.1", - "@smithy/util-middleware": "^4.2.12", - "@smithy/util-retry": "^4.2.12", - "@smithy/uuid": "^1.1.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-serde": { - "version": "4.2.15", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.15.tgz", - "integrity": "sha512-ExYhcltZSli0pgAKOpQQe1DLFBLryeZ22605y/YS+mQpdNWekum9Ujb/jMKfJKgjtz1AZldtwA/wCYuKJgjjlg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.23.12", - "@smithy/protocol-http": "^5.3.12", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-stack": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.12.tgz", - "integrity": "sha512-kruC5gRHwsCOuyCd4ouQxYjgRAym2uDlCvQ5acuMtRrcdfg7mFBg6blaxcJ09STpt3ziEkis6bhg1uwrWU7txw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-config-provider": { - "version": "4.3.12", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.12.tgz", - "integrity": "sha512-tr2oKX2xMcO+rBOjobSwVAkV05SIfUKz8iI53rzxEmgW3GOOPOv0UioSDk+J8OpRQnpnhsO3Af6IEBabQBVmiw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.2.12", - "@smithy/shared-ini-file-loader": "^4.4.7", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.5.0.tgz", - "integrity": "sha512-Rnq9vQWiR1+/I6NZZMNzJHV6pZYyEHt2ZnuV3MG8z2NNenC4i/8Kzttz7CjZiHSmsN5frhXhg17z3Zqjjhmz1A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/abort-controller": "^4.2.12", - "@smithy/protocol-http": "^5.3.12", - "@smithy/querystring-builder": "^4.2.12", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/property-provider": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.12.tgz", - "integrity": "sha512-jqve46eYU1v7pZ5BM+fmkbq3DerkSluPr5EhvOcHxygxzD05ByDRppRwRPPpFrsFo5yDtCYLKu+kreHKVrvc7A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/protocol-http": { - "version": "5.3.12", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.12.tgz", - "integrity": "sha512-fit0GZK9I1xoRlR4jXmbLhoN0OdEpa96ul8M65XdmXnxXkuMxM0Y8HDT0Fh0Xb4I85MBvBClOzgSrV1X2s1Hxw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/querystring-builder": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.12.tgz", - "integrity": "sha512-6wTZjGABQufekycfDGMEB84BgtdOE/rCVTov+EDXQ8NHKTUNIp/j27IliwP7tjIU9LR+sSzyGBOXjeEtVgzCHg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "@smithy/util-uri-escape": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/querystring-parser": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.12.tgz", - "integrity": "sha512-P2OdvrgiAKpkPNKlKUtWbNZKB1XjPxM086NeVhK+W+wI46pIKdWBe5QyXvhUm3MEcyS/rkLvY8rZzyUdmyDZBw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/service-error-classification": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.12.tgz", - "integrity": "sha512-LlP29oSQN0Tw0b6D0Xo6BIikBswuIiGYbRACy5ujw/JgWSzTdYj46U83ssf6Ux0GyNJVivs2uReU8pt7Eu9okQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/shared-ini-file-loader": { - "version": "4.4.7", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.7.tgz", - "integrity": "sha512-HrOKWsUb+otTeo1HxVWeEb99t5ER1XrBi/xka2Wv6NVmTbuCUC1dvlrksdvxFtODLBjsC+PHK+fuy2x/7Ynyiw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/signature-v4": { - "version": "5.3.12", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.12.tgz", - "integrity": "sha512-B/FBwO3MVOL00DaRSXfXfa/TRXRheagt/q5A2NM13u7q+sHS59EOVGQNfG7DkmVtdQm5m3vOosoKAXSqn/OEgw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^4.2.2", - "@smithy/protocol-http": "^5.3.12", - "@smithy/types": "^4.13.1", - "@smithy/util-hex-encoding": "^4.2.2", - "@smithy/util-middleware": "^4.2.12", - "@smithy/util-uri-escape": "^4.2.2", - "@smithy/util-utf8": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/smithy-client": { - "version": "4.12.7", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.12.7.tgz", - "integrity": "sha512-q3gqnwml60G44FECaEEsdQMplYhDMZYCtYhMCzadCnRnnHIobZJjegmdoUo6ieLQlPUzvrMdIJUpx6DoPmzANQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.23.12", - "@smithy/middleware-endpoint": "^4.4.27", - "@smithy/middleware-stack": "^4.2.12", - "@smithy/protocol-http": "^5.3.12", - "@smithy/types": "^4.13.1", - "@smithy/util-stream": "^4.5.20", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/types": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.13.1.tgz", - "integrity": "sha512-787F3yzE2UiJIQ+wYW1CVg2odHjmaWLGksnKQHUrK/lYZSEcy1msuLVvxaR/sI2/aDe9U+TBuLsXnr3vod1g0g==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/url-parser": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.12.tgz", - "integrity": "sha512-wOPKPEpso+doCZGIlr+e1lVI6+9VAKfL4kZWFgzVgGWY2hZxshNKod4l2LXS3PRC9otH/JRSjtEHqQ/7eLciRA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/querystring-parser": "^4.2.12", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-base64": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.2.tgz", - "integrity": "sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^4.2.2", - "@smithy/util-utf8": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-body-length-browser": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.2.tgz", - "integrity": "sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-body-length-node": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.3.tgz", - "integrity": "sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-buffer-from": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.2.tgz", - "integrity": "sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-config-provider": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.2.tgz", - "integrity": "sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.3.43", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.43.tgz", - "integrity": "sha512-Qd/0wCKMaXxev/z00TvNzGCH2jlKKKxXP1aDxB6oKwSQthe3Og2dMhSayGCnsma1bK/kQX1+X7SMP99t6FgiiQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.2.12", - "@smithy/smithy-client": "^4.12.7", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.2.47", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.47.tgz", - "integrity": "sha512-qSRbYp1EQ7th+sPFuVcVO05AE0QH635hycdEXlpzIahqHHf2Fyd/Zl+8v0XYMJ3cgDVPa0lkMefU7oNUjAP+DQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/config-resolver": "^4.4.13", - "@smithy/credential-provider-imds": "^4.2.12", - "@smithy/node-config-provider": "^4.3.12", - "@smithy/property-provider": "^4.2.12", - "@smithy/smithy-client": "^4.12.7", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-endpoints": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.3.3.tgz", - "integrity": "sha512-VACQVe50j0HZPjpwWcjyT51KUQ4AnsvEaQ2lKHOSL4mNLD0G9BjEniQ+yCt1qqfKfiAHRAts26ud7hBjamrwig==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.3.12", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-hex-encoding": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.2.tgz", - "integrity": "sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-middleware": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.12.tgz", - "integrity": "sha512-Er805uFUOvgc0l8nv0e0su0VFISoxhJ/AwOn3gL2NWNY2LUEldP5WtVcRYSQBcjg0y9NfG8JYrCJaYDpupBHJQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-retry": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.12.tgz", - "integrity": "sha512-1zopLDUEOwumjcHdJ1mwBHddubYF8GMQvstVCLC54Y46rqoHwlIU+8ZzUeaBcD+WCJHyDGSeZ2ml9YSe9aqcoQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/service-error-classification": "^4.2.12", - "@smithy/types": "^4.13.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-stream": { - "version": "4.5.20", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.20.tgz", - "integrity": "sha512-4yXLm5n/B5SRBR2p8cZ90Sbv4zL4NKsgxdzCzp/83cXw2KxLEumt5p+GAVyRNZgQOSrzXn9ARpO0lUe8XSlSDw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/fetch-http-handler": "^5.3.15", - "@smithy/node-http-handler": "^4.5.0", - "@smithy/types": "^4.13.1", - "@smithy/util-base64": "^4.3.2", - "@smithy/util-buffer-from": "^4.2.2", - "@smithy/util-hex-encoding": "^4.2.2", - "@smithy/util-utf8": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-uri-escape": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.2.tgz", - "integrity": "sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-utf8": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.2.tgz", - "integrity": "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/uuid": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.2.tgz", - "integrity": "sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.6", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", - "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/express": { - "version": "4.17.25", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", - "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "^1" - } - }, - "node_modules/@types/express-serve-static-core": { - "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": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/http-errors": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "24.12.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz", - "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/@types/pg": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.20.0.tgz", - "integrity": "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^2.2.0" - } - }, - "node_modules/@types/qs": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz", - "integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", - "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", - "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "<1" - } - }, - "node_modules/@types/serve-static/node_modules/@types/send": { - "version": "0.17.6", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", - "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/webidl-conversions": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", - "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", - "license": "MIT" - }, - "node_modules/@types/whatwg-url": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", - "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", - "license": "MIT", - "dependencies": { - "@types/webidl-conversions": "*" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "node_modules/aws-ssl-profiles": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", - "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", - "license": "MIT", - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/bowser": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", - "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", - "license": "MIT" - }, - "node_modules/bson": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", - "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", - "license": "Apache-2.0", - "engines": { - "node": ">=16.20.1" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.27.4", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz", - "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.4", - "@esbuild/android-arm": "0.27.4", - "@esbuild/android-arm64": "0.27.4", - "@esbuild/android-x64": "0.27.4", - "@esbuild/darwin-arm64": "0.27.4", - "@esbuild/darwin-x64": "0.27.4", - "@esbuild/freebsd-arm64": "0.27.4", - "@esbuild/freebsd-x64": "0.27.4", - "@esbuild/linux-arm": "0.27.4", - "@esbuild/linux-arm64": "0.27.4", - "@esbuild/linux-ia32": "0.27.4", - "@esbuild/linux-loong64": "0.27.4", - "@esbuild/linux-mips64el": "0.27.4", - "@esbuild/linux-ppc64": "0.27.4", - "@esbuild/linux-riscv64": "0.27.4", - "@esbuild/linux-s390x": "0.27.4", - "@esbuild/linux-x64": "0.27.4", - "@esbuild/netbsd-arm64": "0.27.4", - "@esbuild/netbsd-x64": "0.27.4", - "@esbuild/openbsd-arm64": "0.27.4", - "@esbuild/openbsd-x64": "0.27.4", - "@esbuild/openharmony-arm64": "0.27.4", - "@esbuild/sunos-x64": "0.27.4", - "@esbuild/win32-arm64": "0.27.4", - "@esbuild/win32-ia32": "0.27.4", - "@esbuild/win32-x64": "0.27.4" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/fast-xml-builder": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz", - "integrity": "sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "dependencies": { - "path-expression-matcher": "^1.1.3" - } - }, - "node_modules/fast-xml-parser": { - "version": "5.5.8", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.5.8.tgz", - "integrity": "sha512-Z7Fh2nVQSb2d+poDViM063ix2ZGt9jmY1nWhPfHBOK2Hgnb/OW3P4Et3P/81SEej0J7QbWtJqxO05h8QYfK7LQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "dependencies": { - "fast-xml-builder": "^1.1.4", - "path-expression-matcher": "^1.2.0", - "strnum": "^2.2.0" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, - "node_modules/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "license": "MIT", - "dependencies": { - "is-property": "^1.0.2" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-tsconfig": { - "version": "4.13.7", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", - "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ioredis": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.10.1.tgz", - "integrity": "sha512-HuEDBTI70aYdx1v6U97SbNx9F1+svQKBDo30o0b9fw055LMepzpOOd0Ccg9Q6tbqmBSJaMuY0fB7yw9/vjBYCA==", - "license": "MIT", - "dependencies": { - "@ioredis/commands": "1.5.1", - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.4", - "denque": "^2.1.0", - "lodash.defaults": "^4.2.0", - "lodash.isarguments": "^3.1.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" - }, - "engines": { - "node": ">=12.22.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ioredis" - } - }, - "node_modules/ioredis/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/ioredis/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", - "license": "MIT" - }, - "node_modules/kafkajs": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/kafkajs/-/kafkajs-2.2.4.tgz", - "integrity": "sha512-j/YeapB1vfPT2iOIUn/vxdyKEuhuY2PxMBvf5JWux6iSaukAccrMtXEY/Lb7OvavDhOWME589bpLrEdnVHjfjA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "license": "MIT" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "license": "MIT" - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", - "license": "MIT" - }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, - "node_modules/lru.min": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz", - "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", - "license": "MIT", - "engines": { - "bun": ">=1.0.0", - "deno": ">=1.30.0", - "node": ">=8.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wellwelwel" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "license": "MIT" - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mongodb": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.21.0.tgz", - "integrity": "sha512-URyb/VXMjJ4da46OeSXg+puO39XH9DeQpWCslifrRn9JWugy0D+DvvBvkm2WxmHe61O/H19JM66p1z7RHVkZ6A==", - "license": "Apache-2.0", - "dependencies": { - "@mongodb-js/saslprep": "^1.3.0", - "bson": "^6.10.4", - "mongodb-connection-string-url": "^3.0.2" - }, - "engines": { - "node": ">=16.20.1" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", - "gcp-metadata": "^5.2.0", - "kerberos": "^2.0.1", - "mongodb-client-encryption": ">=6.0.0 <7", - "snappy": "^7.3.2", - "socks": "^2.7.1" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "gcp-metadata": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - }, - "socks": { - "optional": true - } - } - }, - "node_modules/mongodb-connection-string-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", - "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", - "license": "Apache-2.0", - "dependencies": { - "@types/whatwg-url": "^11.0.2", - "whatwg-url": "^14.1.0 || ^13.0.0" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/mysql2": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.20.0.tgz", - "integrity": "sha512-eCLUs7BNbgA6nf/MZXsaBO1SfGs0LtLVrJD3WeWq+jPLDWkSufTD+aGMwykfUVPdZnblaUK1a8G/P63cl9FkKg==", - "license": "MIT", - "dependencies": { - "aws-ssl-profiles": "^1.1.2", - "denque": "^2.1.0", - "generate-function": "^2.3.1", - "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" - }, - "peerDependencies": { - "@types/node": ">= 8" - } - }, - "node_modules/mysql2/node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "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.6", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz", - "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", - "license": "MIT", - "dependencies": { - "lru.min": "^1.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-expression-matcher": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.2.0.tgz", - "integrity": "sha512-DwmPWeFn+tq7TiyJ2CxezCAirXjFxvaiD03npak3cRjlP9+OjTmSy1EpIrEbh+l6JgUundniloMLDQ/6VTdhLQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" - }, - "node_modules/pg": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.20.0.tgz", - "integrity": "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==", - "license": "MIT", - "dependencies": { - "pg-connection-string": "^2.12.0", - "pg-pool": "^3.13.0", - "pg-protocol": "^1.13.0", - "pg-types": "2.2.0", - "pgpass": "1.0.5" - }, - "engines": { - "node": ">= 16.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.3.0" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz", - "integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==", - "license": "MIT", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.12.0.tgz", - "integrity": "sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ==", - "license": "MIT" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "license": "ISC", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-pool": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.13.0.tgz", - "integrity": "sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA==", - "license": "MIT", - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.13.0.tgz", - "integrity": "sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==", - "license": "MIT" - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "license": "MIT", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "license": "MIT", - "dependencies": { - "split2": "^4.1.0" - } - }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", - "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/protobufjs": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", - "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", - "license": "MIT", - "dependencies": { - "redis-errors": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/send": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", - "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.4.1", - "range-parser": "~1.2.1", - "statuses": "~2.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/serve-static": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", - "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "~0.19.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "license": "MIT", - "dependencies": { - "memory-pager": "^1.0.2" - } - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "license": "ISC", - "engines": { - "node": ">= 10.x" - } - }, - "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==", - "license": "MIT", - "engines": { - "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/standard-as-callback": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", - "license": "MIT" - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strnum": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.2.tgz", - "integrity": "sha512-DnR90I+jtXNSTXWdwrEy9FakW7UX+qUZg28gj5fk2vxxl7uS/3bpI4fjFYVmdK9etptYBPNkpahuQnEwhwECqA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT" - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tsx": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", - "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.27.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "license": "MIT" - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", - "license": "MIT", - "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - } - } -} diff --git a/node-dependency-matrix/package.json b/node-dependency-matrix/package.json deleted file mode 100644 index 8b583c8..0000000 --- a/node-dependency-matrix/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "node-dependency-matrix", - "version": "1.0.0", - "private": true, - "description": "TypeScript sample app for exercising Keploy cloud record/replay dependency flows.", - "main": "dist/bin/app.js", - "scripts": { - "build": "tsc -p tsconfig.json", - "start": "node dist/bin/app.js", - "start:app": "node dist/bin/app.js", - "start:fixture": "node dist/bin/dependencyFixture.js", - "start:tls-proxy": "node dist/bin/tlsProxy.js", - "dev": "tsx watch src/bin/app.ts" - }, - "engines": { - "node": ">=20" - }, - "dependencies": { - "@aws-sdk/client-sqs": "^3.893.0", - "@grpc/grpc-js": "^1.14.0", - "@grpc/proto-loader": "^0.8.0", - "@smithy/node-http-handler": "^4.4.5", - "express": "^4.21.2", - "ioredis": "^5.8.1", - "kafkajs": "^2.2.4", - "mongodb": "^6.20.0", - "mysql2": "^3.15.3", - "pg": "^8.16.3" - }, - "devDependencies": { - "@types/express": "^4.17.21", - "@types/node": "^24.7.2", - "@types/pg": "^8.15.5", - "tsx": "^4.20.6", - "typescript": "^5.9.3" - } -} diff --git a/node-dependency-matrix/proto/dependency_matrix.proto b/node-dependency-matrix/proto/dependency_matrix.proto deleted file mode 100644 index 2c37110..0000000 --- a/node-dependency-matrix/proto/dependency_matrix.proto +++ /dev/null @@ -1,41 +0,0 @@ -syntax = "proto3"; - -package dependencymatrix; - -service DependencyFixture { - rpc GetDependencyQuote (QuoteRequest) returns (QuoteReply); -} - -service DependencyMatrix { - rpc Ping (PingRequest) returns (PingReply); - rpc RunDependencyScenario (ScenarioRequest) returns (ScenarioReply); -} - -message QuoteRequest { - string scenario = 1; -} - -message QuoteReply { - string scenario = 1; - string message = 2; - int64 unix_time = 3; -} - -message PingRequest { - string name = 1; -} - -message PingReply { - string message = 1; - string sample_id = 2; -} - -message ScenarioRequest { - string scenario = 1; -} - -message ScenarioReply { - string scenario = 1; - string status = 2; - string payload_json = 3; -} diff --git a/node-dependency-matrix/scripts/compose_down.sh b/node-dependency-matrix/scripts/compose_down.sh deleted file mode 100755 index fa270e1..0000000 --- a/node-dependency-matrix/scripts/compose_down.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -set -euo pipefail - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" - -docker compose -f "${ROOT_DIR}/compose.yaml" down -v "$@" diff --git a/node-dependency-matrix/scripts/compose_up.sh b/node-dependency-matrix/scripts/compose_up.sh deleted file mode 100755 index 8a781dc..0000000 --- a/node-dependency-matrix/scripts/compose_up.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -euo pipefail - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" - -bash "${ROOT_DIR}/scripts/generate_certs.sh" "${ROOT_DIR}/.generated/certs" - -docker compose -f "${ROOT_DIR}/compose.yaml" up --build -d "$@" - -echo "" -echo "Compose app HTTP: http://localhost:${APP_HTTP_PORT:-38081}" -echo "Compose app gRPC: localhost:${APP_GRPC_PORT:-39090}" diff --git a/node-dependency-matrix/scripts/generate_certs.sh b/node-dependency-matrix/scripts/generate_certs.sh deleted file mode 100755 index adbbdae..0000000 --- a/node-dependency-matrix/scripts/generate_certs.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash -set -euo pipefail - -OUTPUT_DIR="${1:-.generated/certs}" -mkdir -p "${OUTPUT_DIR}" - -CA_CONFIG="${OUTPUT_DIR}/ca.cnf" -SERVER_CONFIG="${OUTPUT_DIR}/server.cnf" - -cat > "${CA_CONFIG}" <<'EOF' -[req] -distinguished_name = req_distinguished_name -x509_extensions = v3_ca -prompt = no - -[req_distinguished_name] -CN = node-dependency-matrix-ca - -[v3_ca] -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid:always,issuer -basicConstraints = critical, CA:true -keyUsage = critical, keyCertSign, cRLSign -EOF - -cat > "${SERVER_CONFIG}" <<'EOF' -[req] -distinguished_name = req_distinguished_name -req_extensions = v3_server -prompt = no - -[req_distinguished_name] -CN = node-dependency-matrix - -[v3_server] -basicConstraints = critical, CA:false -keyUsage = critical, digitalSignature, keyEncipherment -extendedKeyUsage = serverAuth -subjectAltName = @alt_names - -[alt_names] -DNS.1 = fixture-service -DNS.2 = mysql-tls -DNS.3 = postgres-tls -DNS.4 = mongo-tls -DNS.5 = redis-tls -DNS.6 = kafka-tls -DNS.7 = sqs-tls -DNS.8 = localhost -IP.1 = 127.0.0.1 -EOF - -openssl genrsa -out "${OUTPUT_DIR}/ca.key" 2048 >/dev/null 2>&1 -openssl req -x509 -new -nodes -key "${OUTPUT_DIR}/ca.key" -sha256 -days 3650 -out "${OUTPUT_DIR}/ca.crt" -config "${CA_CONFIG}" >/dev/null 2>&1 - -openssl genrsa -out "${OUTPUT_DIR}/proxy.key" 2048 >/dev/null 2>&1 -openssl req -new -key "${OUTPUT_DIR}/proxy.key" -out "${OUTPUT_DIR}/proxy.csr" -config "${SERVER_CONFIG}" >/dev/null 2>&1 -openssl x509 -req -in "${OUTPUT_DIR}/proxy.csr" -CA "${OUTPUT_DIR}/ca.crt" -CAkey "${OUTPUT_DIR}/ca.key" -CAcreateserial -out "${OUTPUT_DIR}/proxy.crt" -days 3650 -sha256 -extensions v3_server -extfile "${SERVER_CONFIG}" >/dev/null 2>&1 -cat "${OUTPUT_DIR}/proxy.crt" "${OUTPUT_DIR}/ca.crt" > "${OUTPUT_DIR}/proxy-fullchain.crt" - -rm -f "${OUTPUT_DIR}/proxy.csr" "${OUTPUT_DIR}/ca.srl" "${CA_CONFIG}" "${SERVER_CONFIG}" - -echo "Generated certs in ${OUTPUT_DIR}" diff --git a/node-dependency-matrix/scripts/localstack-init/01-create-queue.sh b/node-dependency-matrix/scripts/localstack-init/01-create-queue.sh deleted file mode 100755 index b9409b3..0000000 --- a/node-dependency-matrix/scripts/localstack-init/01-create-queue.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -set -eu - -awslocal sqs create-queue --queue-name dependency-matrix >/dev/null 2>&1 || true diff --git a/node-dependency-matrix/scripts/record_traffic.sh b/node-dependency-matrix/scripts/record_traffic.sh deleted file mode 100755 index ae277cf..0000000 --- a/node-dependency-matrix/scripts/record_traffic.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash -set -euo pipefail - -APP_URL="${APP_URL:-http://localhost:30081}" - -echo "Using APP_URL=${APP_URL}" - -show_recording_hint() { - cat >&2 <<'EOF' -Hint: if this target is a Keploy-hosted recording pod in Kubernetes, send sample traffic through port-forward instead of the app NodePorts: - kubectl -n default port-forward svc/node-dependency-matrix 8080:8080 9090:9090 - APP_URL=http://localhost:8080 bash scripts/record_traffic.sh -EOF -} - -preflight() { - local expectations_status - expectations_status="$(curl -sS -o /dev/null -w '%{http_code}' "${APP_URL}/expectations" || true)" - if [[ "${expectations_status}" == "200" ]]; then - return - fi - - echo "Preflight failed: ${APP_URL}/expectations returned ${expectations_status:-connection-error}." >&2 - if [[ "${APP_URL}" =~ localhost:(30081|31081)$ ]]; then - show_recording_hint - fi - exit 1 -} - -run() { - local scenario="$1" - local path="$2" - echo - echo "==> ${scenario}" - curl -fsS "${APP_URL}${path}" - echo -} - -post_json() { - local scenario="$1" - local path="$2" - local body="$3" - shift 3 - echo - echo "==> ${scenario}" - curl -fsS -X POST "${APP_URL}${path}" -H "content-type: application/json" "$@" --data "${body}" - echo -} - -preflight - -run "deps-http" "/deps/http" -run "deps-http2" "/deps/http2" -run "deps-grpc" "/deps/grpc" -run "deps-mysql" "/deps/mysql" -run "deps-postgres" "/deps/postgres" -run "deps-mongo" "/deps/mongo" -run "deps-redis" "/deps/redis" -run "deps-kafka" "/deps/kafka" -run "deps-sqs" "/deps/sqs" -run "deps-generic" "/deps/generic" -run "dedup-alpha-1" "/dedup/catalog?id=alpha" -run "dedup-alpha-2" "/dedup/catalog?id=alpha" -run "dedup-alpha-3" "/dedup/catalog?id=alpha" -run "dedup-beta-1" "/dedup/catalog?id=beta" -run "dedup-beta-2" "/dedup/catalog?id=beta" -post_json "dedup-order-alpha-1" "/dedup/order" '{"customerTier":"gold","items":[{"quantity":2,"sku":"sku-2"},{"sku":"sku-1","quantity":1}],"orderId":"order-alpha"}' -H "x-matrix-dedup-key: order-alpha" -post_json "dedup-order-alpha-2" "/dedup/order" '{"orderId":"order-alpha","items":[{"sku":"sku-1","quantity":1},{"sku":"sku-2","quantity":2}],"customerTier":"gold"}' -H "x-matrix-dedup-key: order-alpha" -post_json "dedup-order-alpha-3" "/dedup/order" '{"items":[{"sku":"sku-2","quantity":2},{"quantity":1,"sku":"sku-1"}],"customerTier":"gold","orderId":"order-alpha"}' -H "x-matrix-dedup-key: order-alpha" -post_json "dedup-order-beta-1" "/dedup/order" '{"customerTier":"silver","items":[{"sku":"sku-3","quantity":1}],"orderId":"order-beta"}' -H "x-matrix-dedup-key: order-beta" -post_json "async-catalog-sync-start" "/async/catalog-sync" '{"jobId":"sync-alpha","catalogId":"alpha"}' -H "x-matrix-correlation-id: sync-alpha" -run "async-catalog-sync-wait" "/async/catalog-sync/sync-alpha/wait?timeoutMs=5000" -run "noise-runtime" "/noise/runtime" -run "expected-fail-time-window" "/expected-fail/time-window?ts=$(date +%s)" diff --git a/node-dependency-matrix/scripts/send_grpc_traffic.sh b/node-dependency-matrix/scripts/send_grpc_traffic.sh deleted file mode 100755 index 6b161c6..0000000 --- a/node-dependency-matrix/scripts/send_grpc_traffic.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash -set -euo pipefail - -GRPC_TARGET="${GRPC_TARGET:-localhost:30090}" - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" - -show_recording_hint() { - cat >&2 <<'EOF' -Hint: if this target is a Keploy-hosted recording pod in Kubernetes, send sample traffic through port-forward instead of the app NodePorts: - kubectl -n default port-forward svc/node-dependency-matrix 8080:8080 9090:9090 - GRPC_TARGET=localhost:9090 bash scripts/send_grpc_traffic.sh -EOF -} - -if ! output="$( - GRPC_TARGET="${GRPC_TARGET}" ROOT_DIR="${ROOT_DIR}" node <<'NODE' 2>&1 -const path = require('path'); -const grpc = require('@grpc/grpc-js'); -const protoLoader = require('@grpc/proto-loader'); - -const rootDir = process.env.ROOT_DIR; -const target = process.env.GRPC_TARGET; -const protoPath = path.join(rootDir, 'proto', 'dependency_matrix.proto'); -const packageDefinition = protoLoader.loadSync(protoPath, { - keepCase: false, - longs: String, - enums: String, - defaults: true, - oneofs: true -}); -const proto = grpc.loadPackageDefinition(packageDefinition).dependencymatrix; -const client = new proto.DependencyMatrix(target, grpc.credentials.createInsecure()); - -client.Ping({ name: 'matrix' }, (pingErr, pingRes) => { - if (pingErr) { - console.error(pingErr); - process.exit(1); - } - console.log(JSON.stringify(pingRes)); - client.RunDependencyScenario({ scenario: 'deps-http' }, (scenarioErr, scenarioRes) => { - if (scenarioErr) { - console.error(scenarioErr); - process.exit(1); - } - console.log(JSON.stringify(scenarioRes)); - client.close(); - }); -}); -NODE - )"; then - printf '%s\n' "${output}" >&2 - if [[ "${output}" == *"ECONNREFUSED"* ]] && [[ "${GRPC_TARGET}" =~ localhost:(30090|31090)$ ]]; then - show_recording_hint - fi - exit 1 -fi - -printf '%s\n' "${output}" diff --git a/node-dependency-matrix/src/bin/app.ts b/node-dependency-matrix/src/bin/app.ts deleted file mode 100644 index 34a62d3..0000000 --- a/node-dependency-matrix/src/bin/app.ts +++ /dev/null @@ -1,389 +0,0 @@ -import * as grpc from '@grpc/grpc-js'; -import express, { Response } from 'express'; - -import { getCatalogSyncJob, startCatalogSyncJob, waitForCatalogSyncJob } from '../lib/asyncJobs'; -import { loadConfig, readExpectationsJson } from '../lib/config'; -import { - runAllDependencyScenarios, - runGenericScenario, - runGrpcScenario, - runHttp2Scenario, - runHttpScenario, - runKafkaScenario, - runMongoScenario, - runMySqlScenario, - runNamedScenario, - runPostgresScenario, - runRedisScenario, - runSqsScenario -} from '../lib/dependencies'; -import { error, info } from '../lib/log'; -import { loadMatrixProto } from '../lib/proto'; - -const config = loadConfig(); -const app = express(); - -app.use(express.json()); - -interface DedupOrderLineItem { - quantity: number; - sku: string; -} - -interface DedupOrderPayload { - customerTier: string; - items: DedupOrderLineItem[]; - orderId: string; -} - -function logScenarioStart(name: string): void { - info('scenario started', { scenario: name }); -} - -function logScenarioSuccess(name: string, payload: unknown): void { - info('scenario completed', { scenario: name, payload }); -} - -function logScenarioFailure(name: string, err: unknown): void { - error('scenario failed', { - scenario: name, - error: err instanceof Error ? err.message : String(err) - }); -} - -async function executeScenario(res: Response, scenarioName: string, runner: () => Promise): Promise { - logScenarioStart(scenarioName); - - try { - const result = await runner(); - logScenarioSuccess(scenarioName, { status: 'ok' }); - res.status(200).json(result); - } catch (err) { - logScenarioFailure(scenarioName, err); - res.status(500).json({ - scenario: scenarioName, - status: 'error', - error: err instanceof Error ? err.message : String(err) - }); - } -} - -function stableSerialize(value: unknown): string { - if (Array.isArray(value)) { - return `[${value.map((item) => stableSerialize(item)).join(',')}]`; - } - - if (value && typeof value === 'object') { - const record = value as Record; - return `{${Object.keys(record) - .sort() - .map((key) => `${JSON.stringify(key)}:${stableSerialize(record[key])}`) - .join(',')}}`; - } - - return JSON.stringify(value) ?? 'null'; -} - -function normalizeDedupOrder(body: unknown): DedupOrderPayload | null { - if (!body || typeof body !== 'object') { - return null; - } - - const source = body as Record; - const orderId = typeof source.orderId === 'string' ? source.orderId.trim() : ''; - if (!orderId) { - return null; - } - - const customerTier = typeof source.customerTier === 'string' && source.customerTier.trim() ? source.customerTier.trim() : 'standard'; - const rawItems = Array.isArray(source.items) ? source.items : []; - - const items = rawItems - .map((item) => { - if (!item || typeof item !== 'object') { - return null; - } - - const record = item as Record; - const sku = typeof record.sku === 'string' ? record.sku.trim() : ''; - const quantity = typeof record.quantity === 'number' ? record.quantity : Number.parseInt(String(record.quantity ?? ''), 10); - if (!sku || !Number.isInteger(quantity) || quantity <= 0) { - return null; - } - - return { - sku, - quantity - }; - }) - .filter((item): item is DedupOrderLineItem => item !== null) - .sort((left, right) => left.sku.localeCompare(right.sku) || left.quantity - right.quantity); - - if (items.length === 0) { - return null; - } - - return { - orderId, - customerTier, - items - }; -} - -function parseTimeoutMs(raw: unknown, fallback: number, max: number): number { - if (typeof raw !== 'string') { - return fallback; - } - - const parsed = Number.parseInt(raw, 10); - if (Number.isNaN(parsed) || parsed <= 0) { - return fallback; - } - - return Math.min(parsed, max); -} - -app.get('/health', (_req, res) => { - res.json({ - status: 'ok', - sampleId: config.sampleId - }); -}); - -app.get('/expectations', (_req, res) => { - res.type('application/json').send(readExpectationsJson(config)); -}); - -app.get('/deps/http', async (_req, res) => executeScenario(res, 'deps-http', () => runHttpScenario(config))); -app.get('/deps/http2', async (_req, res) => executeScenario(res, 'deps-http2', () => runHttp2Scenario(config))); -app.get('/deps/grpc', async (_req, res) => executeScenario(res, 'deps-grpc', () => runGrpcScenario(config))); -app.get('/deps/mysql', async (_req, res) => executeScenario(res, 'deps-mysql', () => runMySqlScenario(config))); -app.get('/deps/postgres', async (_req, res) => executeScenario(res, 'deps-postgres', () => runPostgresScenario(config))); -app.get('/deps/mongo', async (_req, res) => executeScenario(res, 'deps-mongo', () => runMongoScenario(config))); -app.get('/deps/redis', async (_req, res) => executeScenario(res, 'deps-redis', () => runRedisScenario(config))); -app.get('/deps/kafka', async (_req, res) => executeScenario(res, 'deps-kafka', () => runKafkaScenario(config))); -app.get('/deps/sqs', async (_req, res) => executeScenario(res, 'deps-sqs', () => runSqsScenario(config))); -app.get('/deps/generic', async (_req, res) => executeScenario(res, 'deps-generic', () => runGenericScenario(config))); -app.get('/deps/all', async (_req, res) => executeScenario(res, 'deps-all', () => runAllDependencyScenarios(config))); - -app.get('/dedup/catalog', (req, res) => { - const itemId = typeof req.query.id === 'string' ? req.query.id : 'alpha'; - logScenarioStart('dedup/catalog'); - - const payload = { - scenario: 'dedup/catalog', - itemId, - description: `catalog-${itemId}`, - stablePrice: 42 - }; - - logScenarioSuccess('dedup/catalog', payload); - res.json(payload); -}); - -app.post('/dedup/order', (req, res) => { - const normalizedOrder = normalizeDedupOrder(req.body); - if (!normalizedOrder) { - return res.status(400).json({ - scenario: 'dedup/order', - error: 'orderId and at least one valid item are required' - }); - } - - const dedupKey = req.get('x-matrix-dedup-key')?.trim() || normalizedOrder.orderId; - logScenarioStart('dedup/order'); - - const payload = { - scenario: 'dedup/order', - dedupKey, - order: normalizedOrder, - stableFingerprint: stableSerialize({ - dedupKey, - order: normalizedOrder - }) - }; - - logScenarioSuccess('dedup/order', payload); - return res.json(payload); -}); - -app.post('/async/catalog-sync', (req, res) => { - const jobId = typeof req.body?.jobId === 'string' ? req.body.jobId.trim() : ''; - const catalogId = typeof req.body?.catalogId === 'string' && req.body.catalogId.trim() ? req.body.catalogId.trim() : 'alpha'; - const correlationId = req.get('x-matrix-correlation-id')?.trim() || jobId; - - if (!jobId) { - return res.status(400).json({ - scenario: 'async/catalog-sync', - error: 'jobId is required' - }); - } - - logScenarioStart('async/catalog-sync'); - const payload = startCatalogSyncJob(config, { - jobId, - catalogId, - correlationId - }); - logScenarioSuccess('async/catalog-sync', payload); - return res.status(202).json(payload); -}); - -app.get('/async/catalog-sync/:jobId', (req, res) => { - const payload = getCatalogSyncJob(req.params.jobId); - if (!payload) { - return res.status(404).json({ - scenario: 'async/catalog-sync', - error: 'job not found', - jobId: req.params.jobId - }); - } - - return res.json(payload); -}); - -app.get('/async/catalog-sync/:jobId/wait', async (req, res) => { - const timeoutMs = parseTimeoutMs(req.query.timeoutMs, 5000, 15000); - logScenarioStart('async/catalog-sync/wait'); - - const payload = await waitForCatalogSyncJob(req.params.jobId, timeoutMs); - if (!payload) { - logScenarioFailure('async/catalog-sync/wait', 'job not found'); - return res.status(404).json({ - scenario: 'async/catalog-sync/wait', - error: 'job not found', - jobId: req.params.jobId - }); - } - - if (payload.status === 'completed') { - logScenarioSuccess('async/catalog-sync/wait', { - jobId: payload.jobId, - status: payload.status, - completedScenarios: payload.completedScenarios - }); - return res.json(payload); - } - - if (payload.status === 'failed') { - logScenarioFailure('async/catalog-sync/wait', payload.error ?? 'async job failed'); - return res.status(500).json(payload); - } - - logScenarioFailure('async/catalog-sync/wait', `timed out after ${timeoutMs}ms`); - return res.status(504).json({ - ...payload, - scenario: 'async/catalog-sync/wait', - error: `timed out after ${timeoutMs}ms` - }); -}); - -app.get('/noise/runtime', (_req, res) => { - const payload = { - scenario: 'noise/runtime', - runtime: { - requestId: crypto.randomUUID(), - servedAt: new Date().toISOString() - } - }; - - res.setHeader('x-matrix-generated-at', new Date().toISOString()); - res.setHeader('etag', `"${crypto.randomUUID()}"`); - logScenarioSuccess('noise/runtime', payload); - res.json(payload); -}); - -app.get('/expected-fail/time-window', (req, res) => { - const ts = typeof req.query.ts === 'string' ? Number.parseInt(req.query.ts, 10) : Number.NaN; - const now = Math.floor(Date.now() / 1000); - - if (Number.isNaN(ts)) { - return res.status(400).json({ - scenario: 'expected-fail/time-window', - error: 'ts query parameter is required' - }); - } - - const diff = Math.abs(now - ts); - if (diff > 2) { - return res.status(400).json({ - scenario: 'expected-fail/time-window', - diff, - now - }); - } - - return res.status(200).json({ - scenario: 'expected-fail/time-window', - diff, - now - }); -}); - -const httpServer = app.listen(config.port, () => { - info('http server listening', { - port: config.port, - sampleId: config.sampleId - }); -}); - -const proto = loadMatrixProto(config.protoPath); -const grpcServer = new grpc.Server(); - -grpcServer.addService(proto.dependencymatrix.DependencyMatrix.service, { - Ping( - call: grpc.ServerUnaryCall<{ name: string }, { message: string; sampleId: string }>, - callback: grpc.sendUnaryData<{ message: string; sampleId: string }> - ) { - callback(null, { - message: `pong:${call.request.name || 'matrix'}`, - sampleId: config.sampleId - }); - }, - - async RunDependencyScenario( - call: grpc.ServerUnaryCall<{ scenario: string }, { scenario: string; status: string; payloadJson: string }>, - callback: grpc.sendUnaryData<{ scenario: string; status: string; payloadJson: string }> - ) { - try { - const result = await runNamedScenario(config, call.request.scenario); - callback(null, { - scenario: result.scenario, - status: 'ok', - payloadJson: JSON.stringify(result.payload) - }); - } catch (err) { - callback({ - code: grpc.status.INTERNAL, - message: err instanceof Error ? err.message : String(err), - name: 'RunDependencyScenarioError' - }); - } - } -}); - -grpcServer.bindAsync(`0.0.0.0:${config.grpcPort}`, grpc.ServerCredentials.createInsecure(), (err) => { - if (err) { - error('grpc server failed to bind', { error: err.message }); - process.exitCode = 1; - return; - } - - grpcServer.start(); - info('grpc server listening', { - port: config.grpcPort - }); -}); - -const shutdown = (): void => { - info('shutdown started'); - grpcServer.tryShutdown(() => { - httpServer.close(() => { - info('shutdown complete'); - process.exit(0); - }); - }); -}; - -process.on('SIGINT', shutdown); -process.on('SIGTERM', shutdown); diff --git a/node-dependency-matrix/src/bin/dependencyFixture.ts b/node-dependency-matrix/src/bin/dependencyFixture.ts deleted file mode 100644 index cee8096..0000000 --- a/node-dependency-matrix/src/bin/dependencyFixture.ts +++ /dev/null @@ -1,106 +0,0 @@ -import fs from 'node:fs'; -import http2 from 'node:http2'; -import path from 'node:path'; -import tls from 'node:tls'; - -import * as grpc from '@grpc/grpc-js'; -import express from 'express'; - -import { loadConfig } from '../lib/config'; -import { info } from '../lib/log'; -import { loadMatrixProto } from '../lib/proto'; - -const config = loadConfig(); -const cert = fs.readFileSync(config.proxyCertPath); -const key = fs.readFileSync(config.proxyKeyPath); - -const app = express(); -app.get('/http-json', (req, res) => { - res.json({ - source: 'fixture-service', - protocol: 'http', - echo: req.query.source ?? 'unknown' - }); -}); - -const httpsServer = tls.createServer({ cert, key }, (socket) => { - socket.once('data', (data) => { - const input = data.toString('utf8'); - if (input.startsWith('GET ') || input.startsWith('POST ')) { - socket.destroy(); - } - }); -}); -httpsServer.close(); - -const httpsApp = app.listen(0); -httpsApp.close(); - -require('node:https') - .createServer({ cert, key }, app) - .listen(8443, () => { - info('fixture https server listening', { port: 8443 }); - }); - -http2 - .createSecureServer({ cert, key }) - .on('stream', (stream, headers) => { - if (headers[':path'] === '/http2-ping') { - stream.respond({ - ':status': 200, - 'content-type': 'application/json' - }); - stream.end( - JSON.stringify({ - source: 'fixture-service', - protocol: 'http2', - path: '/http2-ping' - }) - ); - return; - } - - stream.respond({ ':status': 404 }); - stream.end(); - }) - .listen(9443, () => { - info('fixture http2 server listening', { port: 9443 }); - }); - -tls - .createServer({ cert, key }, (socket) => { - socket.on('data', (data) => { - const response = `fixture-ack:${data.toString('utf8').trim()}\n`; - socket.write(response); - }); - }) - .listen(9445, () => { - info('fixture generic tls server listening', { port: 9445 }); - }); - -const proto = loadMatrixProto(config.protoPath); -const grpcServer = new grpc.Server(); -grpcServer.addService(proto.dependencymatrix.DependencyFixture.service, { - GetDependencyQuote( - call: grpc.ServerUnaryCall<{ scenario: string }, { scenario: string; message: string; unixTime: number }>, - callback: grpc.sendUnaryData<{ scenario: string; message: string; unixTime: number }> - ) { - callback(null, { - scenario: call.request.scenario || 'unknown', - message: 'fixture-service-ready', - unixTime: Math.floor(Date.now() / 1000) - }); - } -}); - -grpcServer.bindAsync( - '0.0.0.0:50051', - grpc.ServerCredentials.createSsl(null, [{ cert_chain: cert, private_key: key }]), - (err) => { - if (err) { - throw err; - } - grpcServer.start(); - info('fixture grpc server listening', { port: 50051 }); - } -); diff --git a/node-dependency-matrix/src/bin/tlsProxy.ts b/node-dependency-matrix/src/bin/tlsProxy.ts deleted file mode 100644 index faea562..0000000 --- a/node-dependency-matrix/src/bin/tlsProxy.ts +++ /dev/null @@ -1,52 +0,0 @@ -import fs from 'node:fs'; -import net from 'node:net'; -import tls from 'node:tls'; - -import { loadConfig } from '../lib/config'; -import { error, info } from '../lib/log'; - -const config = loadConfig(); -const listenPort = Number.parseInt(process.env.LISTEN_PORT ?? '0', 10); -const targetHost = process.env.TARGET_HOST; -const targetPort = Number.parseInt(process.env.TARGET_PORT ?? '0', 10); - -if (!listenPort || !targetHost || !targetPort) { - throw new Error('LISTEN_PORT, TARGET_HOST and TARGET_PORT are required'); -} - -const cert = fs.readFileSync(config.proxyCertPath); -const key = fs.readFileSync(config.proxyKeyPath); - -const server = tls.createServer({ cert, key }, (sourceSocket) => { - const targetSocket = net.connect(targetPort, targetHost, () => { - sourceSocket.pipe(targetSocket); - targetSocket.pipe(sourceSocket); - }); - - sourceSocket.on('error', (err) => { - error('tls proxy source socket error', { - listenPort, - targetHost, - targetPort, - error: err.message - }); - }); - - targetSocket.on('error', (err) => { - error('tls proxy target socket error', { - listenPort, - targetHost, - targetPort, - error: err.message - }); - sourceSocket.destroy(err); - }); -}); - -server.listen(listenPort, '0.0.0.0', () => { - info('tls proxy listening', { - listenPort, - targetHost, - targetPort - }); -}); diff --git a/node-dependency-matrix/src/global.d.ts b/node-dependency-matrix/src/global.d.ts deleted file mode 100644 index cb2d573..0000000 --- a/node-dependency-matrix/src/global.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare const crypto: { - randomUUID(): string; -}; diff --git a/node-dependency-matrix/src/lib/asyncJobs.ts b/node-dependency-matrix/src/lib/asyncJobs.ts deleted file mode 100644 index e232131..0000000 --- a/node-dependency-matrix/src/lib/asyncJobs.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { AppConfig } from './config'; -import { runHttpScenario, runRedisScenario, runSqsScenario } from './dependencies'; -import { error, info } from './log'; - -type CatalogSyncStatus = 'queued' | 'running' | 'completed' | 'failed'; - -interface CatalogSyncJobState { - jobId: string; - catalogId: string; - correlationId: string; - status: CatalogSyncStatus; - plannedScenarios: string[]; - completedScenarios: string[]; - protocols: string[]; - error?: string; -} - -export interface CatalogSyncJobSnapshot { - scenario: 'async/catalog-sync'; - jobId: string; - catalogId: string; - correlationId: string; - status: CatalogSyncStatus; - plannedScenarios: string[]; - completedScenarios: string[]; - protocols: string[]; - error?: string; -} - -interface CatalogSyncRequest { - jobId: string; - catalogId: string; - correlationId: string; -} - -const catalogSyncRunners = [ - ['deps-http', runHttpScenario], - ['deps-redis', runRedisScenario], - ['deps-sqs', runSqsScenario] -] as const; - -const catalogSyncJobs = new Map(); - -function snapshotJob(state: CatalogSyncJobState): CatalogSyncJobSnapshot { - return { - scenario: 'async/catalog-sync', - jobId: state.jobId, - catalogId: state.catalogId, - correlationId: state.correlationId, - status: state.status, - plannedScenarios: [...state.plannedScenarios], - completedScenarios: [...state.completedScenarios], - protocols: [...state.protocols], - ...(state.error ? { error: state.error } : {}) - }; -} - -async function runCatalogSyncJob(config: AppConfig, state: CatalogSyncJobState): Promise { - state.status = 'running'; - info('async catalog sync started', { - scenario: 'async/catalog-sync', - jobId: state.jobId, - catalogId: state.catalogId, - correlationId: state.correlationId - }); - - try { - for (const [_expectedScenario, runner] of catalogSyncRunners) { - const result = await runner(config); - state.completedScenarios.push(result.scenario); - state.protocols.push(result.protocol); - } - - state.status = 'completed'; - info('async catalog sync completed', { ...snapshotJob(state) }); - } catch (err) { - state.status = 'failed'; - state.error = err instanceof Error ? err.message : String(err); - error('async catalog sync failed', { - scenario: 'async/catalog-sync', - jobId: state.jobId, - catalogId: state.catalogId, - error: state.error - }); - } -} - -export function startCatalogSyncJob(config: AppConfig, request: CatalogSyncRequest): CatalogSyncJobSnapshot { - const state: CatalogSyncJobState = { - jobId: request.jobId, - catalogId: request.catalogId, - correlationId: request.correlationId, - status: 'queued', - plannedScenarios: catalogSyncRunners.map(([scenario]) => scenario), - completedScenarios: [], - protocols: [] - }; - - catalogSyncJobs.set(state.jobId, state); - setImmediate(() => { - void runCatalogSyncJob(config, state); - }); - - return snapshotJob(state); -} - -export function getCatalogSyncJob(jobId: string): CatalogSyncJobSnapshot | null { - const job = catalogSyncJobs.get(jobId); - return job ? snapshotJob(job) : null; -} - -export async function waitForCatalogSyncJob(jobId: string, timeoutMs: number): Promise { - const deadline = Date.now() + timeoutMs; - - while (Date.now() <= deadline) { - const snapshot = getCatalogSyncJob(jobId); - if (!snapshot) { - return null; - } - - if (snapshot.status === 'completed' || snapshot.status === 'failed') { - return snapshot; - } - - await new Promise((resolve) => setTimeout(resolve, 50)); - } - - return getCatalogSyncJob(jobId); -} diff --git a/node-dependency-matrix/src/lib/config.ts b/node-dependency-matrix/src/lib/config.ts deleted file mode 100644 index 98b1ad2..0000000 --- a/node-dependency-matrix/src/lib/config.ts +++ /dev/null @@ -1,82 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; - -export interface AppConfig { - port: number; - grpcPort: number; - sampleId: string; - fixtureHttpsBase: string; - fixtureHttp2Origin: string; - fixtureGrpcTarget: string; - fixtureGenericHost: string; - fixtureGenericPort: number; - mysqlUrl: string; - postgresUrl: string; - mongoUrl: string; - redisUrl: string; - kafkaBrokers: string[]; - kafkaTopic: string; - sqsEndpoint: string; - sqsQueueUrl: string; - sqsRegion: string; - caBundlePath: string; - proxyCertPath: string; - proxyKeyPath: string; - expectationsPath: string; - protoPath: string; -} - -function readNumber(name: string, fallback: number): number { - const raw = process.env[name]; - if (!raw) { - return fallback; - } - - const parsed = Number.parseInt(raw, 10); - return Number.isNaN(parsed) ? fallback : parsed; -} - -function splitCsv(raw: string | undefined, fallback: string[]): string[] { - if (!raw) { - return fallback; - } - return raw - .split(',') - .map((item) => item.trim()) - .filter(Boolean); -} - -export function loadConfig(): AppConfig { - const workdir = process.cwd(); - const expectationsPath = path.join(workdir, 'fixtures', 'expected-values.json'); - const protoPath = path.join(workdir, 'proto', 'dependency_matrix.proto'); - - return { - port: readNumber('PORT', 8080), - grpcPort: readNumber('GRPC_PORT', 9090), - sampleId: process.env.SAMPLE_ID ?? 'node-dependency-matrix', - fixtureHttpsBase: process.env.FIXTURE_HTTPS_BASE ?? 'https://fixture-service:8443', - fixtureHttp2Origin: process.env.FIXTURE_HTTP2_ORIGIN ?? 'https://fixture-service:9443', - fixtureGrpcTarget: process.env.FIXTURE_GRPC_TARGET ?? 'fixture-service:50051', - fixtureGenericHost: process.env.FIXTURE_GENERIC_HOST ?? 'fixture-service', - fixtureGenericPort: readNumber('FIXTURE_GENERIC_PORT', 9445), - mysqlUrl: process.env.MYSQL_URL ?? 'mysql://root@mysql:3306/matrix', - postgresUrl: process.env.POSTGRES_URL ?? 'postgresql://postgres@postgres:5432/matrix', - mongoUrl: process.env.MONGO_URL ?? 'mongodb://mongo-tls:27017/matrix?tls=true', - redisUrl: process.env.REDIS_URL ?? 'rediss://redis-tls:6380', - kafkaBrokers: splitCsv(process.env.KAFKA_BROKERS, ['redpanda:9092']), - kafkaTopic: process.env.KAFKA_TOPIC ?? 'matrix-events', - sqsEndpoint: process.env.SQS_ENDPOINT ?? 'https://sqs-tls:4567', - sqsQueueUrl: process.env.SQS_QUEUE_URL ?? 'https://sqs-tls:4567/000000000000/dependency-matrix', - sqsRegion: process.env.SQS_REGION ?? 'us-east-1', - caBundlePath: process.env.COMBINED_CA_CERT_PATH ?? process.env.NODE_EXTRA_CA_CERTS ?? '/tmp/node-dependency-matrix-ca-bundle.crt', - proxyCertPath: process.env.TLS_CERT_PATH ?? '/etc/sample-certs/proxy.crt', - proxyKeyPath: process.env.TLS_KEY_PATH ?? '/etc/sample-certs/proxy.key', - expectationsPath, - protoPath - }; -} - -export function readExpectationsJson(config: AppConfig): string { - return fs.readFileSync(config.expectationsPath, 'utf8'); -} diff --git a/node-dependency-matrix/src/lib/dependencies.ts b/node-dependency-matrix/src/lib/dependencies.ts deleted file mode 100644 index b649a55..0000000 --- a/node-dependency-matrix/src/lib/dependencies.ts +++ /dev/null @@ -1,503 +0,0 @@ -import fs from 'node:fs'; -import http2 from 'node:http2'; -import https from 'node:https'; -import tls from 'node:tls'; -import { promisify } from 'node:util'; -import { URL } from 'node:url'; - -import { DeleteMessageCommand, ReceiveMessageCommand, SendMessageCommand, SQSClient } from '@aws-sdk/client-sqs'; -import * as grpc from '@grpc/grpc-js'; -import { Kafka } from 'kafkajs'; -import Redis from 'ioredis'; -import { MongoClient } from 'mongodb'; -import mysql from 'mysql2/promise'; -import { Client as PgClient } from 'pg'; -import { NodeHttpHandler } from '@smithy/node-http-handler'; - -import { AppConfig } from './config'; -import { error, info } from './log'; -import { FixtureGrpcClient, loadMatrixProto } from './proto'; - -type ScenarioPayload = Record; - -export interface ScenarioResult { - scenario: string; - protocol: string; - payload: ScenarioPayload; -} - -let cachedCaBundle: Buffer | undefined; -function readCaBundle(config: AppConfig): Buffer { - if (!cachedCaBundle) { - cachedCaBundle = fs.readFileSync(config.caBundlePath); - } - return cachedCaBundle; -} - -export async function runHttpScenario(config: AppConfig): Promise { - const target = new URL(`${config.fixtureHttpsBase}/http-json?source=app`); - const payload = await new Promise<{ status: number; body: ScenarioPayload }>((resolve, reject) => { - const request = https.request( - { - protocol: target.protocol, - hostname: target.hostname, - port: target.port, - path: `${target.pathname}${target.search}`, - method: 'GET', - ca: readCaBundle(config), - rejectUnauthorized: true - }, - (response) => { - const chunks: Buffer[] = []; - response.on('data', (chunk) => chunks.push(Buffer.from(chunk))); - response.on('end', () => { - const body = Buffer.concat(chunks).toString('utf8'); - resolve({ - status: response.statusCode ?? 0, - body: JSON.parse(body) as ScenarioPayload - }); - }); - } - ); - - request.on('error', reject); - request.end(); - }); - - return { - scenario: 'deps-http', - protocol: 'Http', - payload: { - status: payload.status, - body: payload.body - } - }; -} - -export async function runHttp2Scenario(config: AppConfig): Promise { - const client = http2.connect(config.fixtureHttp2Origin, { - ca: readCaBundle(config) - }); - - try { - const payload = await new Promise((resolve, reject) => { - const request = client.request({ - ':method': 'GET', - ':path': '/http2-ping' - }); - - const chunks: Buffer[] = []; - - request.on('response', () => undefined); - request.on('data', (chunk) => chunks.push(Buffer.from(chunk))); - request.on('end', () => resolve(Buffer.concat(chunks).toString('utf8'))); - request.on('error', reject); - request.end(); - }); - - return { - scenario: 'deps-http2', - protocol: 'Http2', - payload: JSON.parse(payload) as ScenarioPayload - }; - } finally { - client.close(); - } -} - -export async function runGrpcScenario(config: AppConfig): Promise { - const proto = loadMatrixProto(config.protoPath); - const ClientCtor = proto.dependencymatrix.DependencyFixture; - const client = new ClientCtor( - config.fixtureGrpcTarget, - grpc.credentials.createSsl(readCaBundle(config)) - ) as unknown as FixtureGrpcClient; - const getQuote = promisify<{ scenario: string }, { scenario: string; message: string; unixTime: string | number }>( - client.GetDependencyQuote.bind(client) - ); - - try { - const response = await getQuote({ scenario: 'deps-grpc' }); - - return { - scenario: 'deps-grpc', - protocol: 'gRPC', - payload: { - scenario: response.scenario, - message: response.message, - unixTime: Number(response.unixTime) - } - }; - } finally { - client.close(); - } -} - -export async function runMySqlScenario(config: AppConfig): Promise { - const connection = await mysql.createConnection({ - uri: config.mysqlUrl - }); - - try { - await connection.execute(` - CREATE TABLE IF NOT EXISTS matrix_events ( - sample_key VARCHAR(64) PRIMARY KEY, - sample_value VARCHAR(128) NOT NULL, - touched_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP - ) - `); - - await connection.execute( - ` - INSERT INTO matrix_events (sample_key, sample_value) - VALUES (?, ?) - ON DUPLICATE KEY UPDATE sample_value = VALUES(sample_value) - `, - ['mysql-scenario', 'mysql-value'] - ); - - const [rows] = await connection.query( - 'SELECT sample_key, sample_value FROM matrix_events WHERE sample_key = ?', - ['mysql-scenario'] - ); - - return { - scenario: 'deps-mysql', - protocol: 'MySQL', - payload: { - rowCount: rows.length, - row: rows[0] ?? null - } - }; - } finally { - await connection.end(); - } -} - -export async function runPostgresScenario(config: AppConfig): Promise { - const client = new PgClient({ - connectionString: config.postgresUrl - }); - - await client.connect(); - - try { - await client.query(` - CREATE TABLE IF NOT EXISTS matrix_events ( - sample_key TEXT PRIMARY KEY, - sample_value TEXT NOT NULL - ) - `); - - await client.query( - ` - INSERT INTO matrix_events (sample_key, sample_value) - VALUES ($1, $2) - ON CONFLICT (sample_key) DO UPDATE SET sample_value = EXCLUDED.sample_value - `, - ['postgres-scenario', 'postgres-value'] - ); - - const result = await client.query( - 'SELECT sample_key, sample_value FROM matrix_events WHERE sample_key = $1', - ['postgres-scenario'] - ); - - return { - scenario: 'deps-postgres', - protocol: 'PostgresV2', - payload: { - rowCount: result.rowCount, - row: result.rows[0] ?? null - } - }; - } finally { - await client.end(); - } -} - -export async function runMongoScenario(config: AppConfig): Promise { - const client = new MongoClient(config.mongoUrl, { - tlsCAFile: config.caBundlePath, - // The TLS helper fronts a single upstream mongo service. Keep the driver - // pinned to the provided endpoint so topology discovery does not drift to - // the plain upstream service and hang server selection. - directConnection: true, - // Transparent sidecars do better with the driver's polling heartbeat mode - // than with the default streaming monitor. - serverMonitoringMode: 'poll', - // Keploy's current TLS MITM path does not preserve SANs reliably for - // Mongo, so keep CA validation but skip strict hostname checks. - tlsAllowInvalidHostnames: true - }); - await client.connect(); - - try { - const database = client.db('matrix'); - const collection = database.collection('events'); - - await collection.updateOne( - { sampleKey: 'mongo-scenario' }, - { - $set: { - sampleValue: 'mongo-value', - updatedAt: new Date().toISOString() - } - }, - { upsert: true } - ); - - const document = await collection.findOne({ sampleKey: 'mongo-scenario' }, { projection: { _id: 0 } }); - - return { - scenario: 'deps-mongo', - protocol: 'Mongo', - payload: document ?? {} - }; - } finally { - await client.close(); - } -} - -export async function runRedisScenario(config: AppConfig): Promise { - const client = new Redis(config.redisUrl, { - tls: { - ca: readCaBundle(config), - rejectUnauthorized: true, - checkServerIdentity: () => undefined - }, - lazyConnect: true, - maxRetriesPerRequest: 1 - }); - client.on('error', () => undefined); - - await client.connect(); - - try { - await client.set('matrix:redis-scenario', 'redis-value'); - const value = await client.get('matrix:redis-scenario'); - - return { - scenario: 'deps-redis', - protocol: 'Redis', - payload: { - value - } - }; - } finally { - client.disconnect(); - } -} - -export async function runKafkaScenario(config: AppConfig): Promise { - const kafka = new Kafka({ - clientId: config.sampleId, - brokers: config.kafkaBrokers, - ssl: false, - retry: { - retries: 0 - } - }); - - const admin = kafka.admin(); - - await admin.connect(); - - try { - const cluster = await admin.describeCluster(); - const topics = await admin.listTopics(); - - return { - scenario: 'deps-kafka', - protocol: 'Kafka', - payload: { - brokerCount: cluster.brokers.length, - controller: cluster.controller ?? null, - topicCount: topics.length, - hasMatrixTopic: topics.includes(config.kafkaTopic) - } - }; - } finally { - await admin.disconnect().catch(() => undefined); - } -} - -export async function runSqsScenario(config: AppConfig): Promise { - const client = new SQSClient({ - endpoint: config.sqsEndpoint, - region: config.sqsRegion, - md5: false, - requestHandler: new NodeHttpHandler({ - httpsAgent: new https.Agent({ - ca: readCaBundle(config), - rejectUnauthorized: true - }) - }), - credentials: { - accessKeyId: 'test', - secretAccessKey: 'test' - } - }); - - const sendResult = await client.send( - new SendMessageCommand({ - QueueUrl: config.sqsQueueUrl, - MessageBody: JSON.stringify({ - sampleId: config.sampleId, - scenario: 'deps-sqs', - sentAt: new Date().toISOString() - }) - }) - ); - - const receiveResult = await client.send( - new ReceiveMessageCommand({ - QueueUrl: config.sqsQueueUrl, - MaxNumberOfMessages: 1, - WaitTimeSeconds: 0 - }) - ); - - const receiptHandle = receiveResult.Messages?.[0]?.ReceiptHandle; - if (receiptHandle) { - await client.send( - new DeleteMessageCommand({ - QueueUrl: config.sqsQueueUrl, - ReceiptHandle: receiptHandle - }) - ); - } - - return { - scenario: 'deps-sqs', - protocol: 'SQS', - payload: { - sentMessageId: sendResult.MessageId ?? null, - receivedMessages: receiveResult.Messages?.length ?? 0 - } - }; -} - -export async function runGenericScenario(config: AppConfig): Promise { - const payload = await new Promise((resolve, reject) => { - let settled = false; - const socket = tls.connect( - { - host: config.fixtureGenericHost, - port: config.fixtureGenericPort, - ca: readCaBundle(config), - rejectUnauthorized: true, - checkServerIdentity: () => undefined - }, - () => { - socket.end('matrix-generic\n'); - } - ); - - const fail = (err: Error) => { - if (settled) { - return; - } - - settled = true; - socket.destroy(); - reject(err); - }; - - socket.setTimeout(3000, () => { - fail(new Error('generic socket timeout')); - }); - - socket.once('data', (data) => { - if (settled) { - return; - } - - settled = true; - resolve(data.toString('utf8').trim()); - socket.destroy(); - }); - - socket.once('end', () => { - fail(new Error('generic socket closed before response')); - }); - - socket.once('error', (err) => { - fail(err); - }); - }); - - return { - scenario: 'deps-generic', - protocol: 'Generic', - payload: { - echoed: payload - } - }; -} - -export async function runNamedScenario(config: AppConfig, scenario: string): Promise { - switch (scenario) { - case 'http': - case 'deps-http': - return runHttpScenario(config); - case 'http2': - case 'deps-http2': - return runHttp2Scenario(config); - case 'grpc': - case 'deps-grpc': - return runGrpcScenario(config); - case 'mysql': - case 'deps-mysql': - return runMySqlScenario(config); - case 'postgres': - case 'deps-postgres': - return runPostgresScenario(config); - case 'mongo': - case 'deps-mongo': - return runMongoScenario(config); - case 'redis': - case 'deps-redis': - return runRedisScenario(config); - case 'kafka': - case 'deps-kafka': - return runKafkaScenario(config); - case 'sqs': - case 'deps-sqs': - return runSqsScenario(config); - case 'generic': - case 'deps-generic': - return runGenericScenario(config); - default: - throw new Error(`unsupported scenario: ${scenario}`); - } -} - -export async function runAllDependencyScenarios(config: AppConfig): Promise { - const runners = [ - runHttpScenario, - runHttp2Scenario, - runGrpcScenario, - runMySqlScenario, - runPostgresScenario, - runMongoScenario, - runRedisScenario, - runKafkaScenario, - runSqsScenario, - runGenericScenario - ]; - - const results: ScenarioResult[] = []; - for (const runner of runners) { - try { - results.push(await runner(config)); - } catch (err) { - error('dependency scenario failed', { - scenario: runner.name, - error: err instanceof Error ? err.message : String(err) - }); - throw err; - } - } - return results; -} diff --git a/node-dependency-matrix/src/lib/log.ts b/node-dependency-matrix/src/lib/log.ts deleted file mode 100644 index 3bcc056..0000000 --- a/node-dependency-matrix/src/lib/log.ts +++ /dev/null @@ -1,21 +0,0 @@ -type LogLevel = 'INFO' | 'ERROR'; - -function log(level: LogLevel, message: string, details: Record = {}): void { - const payload = { - level, - message, - ts: new Date().toISOString(), - ...details - }; - - const output = level === 'ERROR' ? console.error : console.log; - output(JSON.stringify(payload)); -} - -export function info(message: string, details: Record = {}): void { - log('INFO', message, details); -} - -export function error(message: string, details: Record = {}): void { - log('ERROR', message, details); -} diff --git a/node-dependency-matrix/src/lib/proto.ts b/node-dependency-matrix/src/lib/proto.ts deleted file mode 100644 index 222ec28..0000000 --- a/node-dependency-matrix/src/lib/proto.ts +++ /dev/null @@ -1,44 +0,0 @@ -import path from 'node:path'; - -import * as grpc from '@grpc/grpc-js'; -import * as protoLoader from '@grpc/proto-loader'; - -const loaderOptions: protoLoader.Options = { - keepCase: false, - longs: String, - enums: String, - defaults: true, - oneofs: true -}; - -export interface FixtureGrpcClient extends grpc.Client { - GetDependencyQuote( - request: { scenario: string }, - callback: (error: grpc.ServiceError | null, response: { scenario: string; message: string; unixTime: string | number }) => void - ): void; -} - -export interface MatrixGrpcClient extends grpc.Client { - Ping( - request: { name: string }, - callback: (error: grpc.ServiceError | null, response: { message: string; sampleId: string }) => void - ): void; - - RunDependencyScenario( - request: { scenario: string }, - callback: (error: grpc.ServiceError | null, response: { scenario: string; status: string; payloadJson: string }) => void - ): void; -} - -export interface LoadedProto { - dependencymatrix: { - DependencyFixture: grpc.ServiceClientConstructor; - DependencyMatrix: grpc.ServiceClientConstructor; - }; -} - -export function loadMatrixProto(protoPath: string): LoadedProto { - const absolutePath = path.resolve(protoPath); - const packageDefinition = protoLoader.loadSync(absolutePath, loaderOptions); - return grpc.loadPackageDefinition(packageDefinition) as unknown as LoadedProto; -} diff --git a/node-dependency-matrix/tsconfig.json b/node-dependency-matrix/tsconfig.json deleted file mode 100644 index 97b1ff3..0000000 --- a/node-dependency-matrix/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "commonjs", - "lib": ["ES2022"], - "rootDir": "./src", - "outDir": "./dist", - "moduleResolution": "node", - "resolveJsonModule": true, - "esModuleInterop": true, - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "types": ["node"] - }, - "include": ["src/**/*.ts"] -}