From 9e8f157d7079d9b992a585d807d24e1a13fbbb7c Mon Sep 17 00:00:00 2001 From: David Date: Fri, 12 Jun 2026 11:33:37 +0200 Subject: [PATCH 1/5] fix security --- apps/backend/.env.example | 10 +- apps/backend/Dockerfile | 2 +- apps/backend/package-lock.json | 3378 ++++++----------- apps/backend/package.json | 2 + apps/backend/src/app.module.ts | 10 +- .../src/application/auth/auth.service.ts | 83 +- .../src/application/auth/jwt.strategy.ts | 6 +- .../controllers/auth.controller.ts | 148 +- .../src/application/dto/auth-login.dto.ts | 20 +- .../services/csv-booking.service.ts | 64 +- .../security/security.config.ts | 56 +- apps/backend/src/main.ts | 4 + .../[locale]/blog/[slug]/BlogPostContent.tsx | 7 +- .../app/[locale]/dashboard/documents/page.tsx | 7 +- .../app/[locale]/forgot-password/page.tsx | 9 +- .../app/[locale]/verify-email/page.tsx | 13 +- apps/frontend/app/api/health/route.ts | 6 + apps/frontend/package-lock.json | 829 +++- apps/frontend/package.json | 3 +- apps/frontend/src/hooks/useBookings.ts | 6 +- apps/frontend/src/lib/api/audit.ts | 6 +- apps/frontend/src/lib/api/auth.ts | 25 +- apps/frontend/src/lib/api/bookings.ts | 6 +- apps/frontend/src/lib/api/client.ts | 284 +- apps/frontend/src/lib/api/csv-rates.ts | 22 +- apps/frontend/src/lib/api/gdpr.ts | 16 +- apps/frontend/src/lib/api/index.ts | 3 +- apps/frontend/src/lib/api/ports.ts | 8 +- .../frontend/src/lib/context/auth-context.tsx | 54 +- .../src/lib/context/cookie-context.tsx | 4 +- apps/frontend/src/types/api.ts | 1 - docker/docker-compose.full.yml | 4 +- 32 files changed, 2246 insertions(+), 2850 deletions(-) create mode 100644 apps/frontend/app/api/health/route.ts diff --git a/apps/backend/.env.example b/apps/backend/.env.example index 612a8fa..e12d10d 100644 --- a/apps/backend/.env.example +++ b/apps/backend/.env.example @@ -18,11 +18,19 @@ REDIS_PORT=6379 REDIS_PASSWORD=xpeditis_redis_password REDIS_DB=0 -# JWT +# JWT (JWT_SECRET must be at least 32 characters) JWT_SECRET=your-super-secret-jwt-key-change-this-in-production JWT_ACCESS_EXPIRATION=15m JWT_REFRESH_EXPIRATION=7d +# Auth cookies — domain shared between frontend and API in production +# (e.g. .xpeditis.com). Leave unset for localhost development. +# COOKIE_DOMAIN=.xpeditis.com + +# Secret used to derive carrier document passwords (min 16 chars). +# Falls back to JWT_SECRET when unset. +# DOCUMENT_PASSWORD_SECRET=your-document-password-secret + # OAuth2 - Google GOOGLE_CLIENT_ID=your-google-client-id GOOGLE_CLIENT_SECRET=your-google-client-secret diff --git a/apps/backend/Dockerfile b/apps/backend/Dockerfile index 93a4dc9..921c1a2 100644 --- a/apps/backend/Dockerfile +++ b/apps/backend/Dockerfile @@ -74,7 +74,7 @@ EXPOSE 4000 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ - CMD node -e "require('http').get('http://localhost:4000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))" + CMD node -e "require('http').get('http://localhost:4000/api/v1/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))" # Set environment variables ENV NODE_ENV=production \ diff --git a/apps/backend/package-lock.json b/apps/backend/package-lock.json index 314ba0b..ce43f91 100644 --- a/apps/backend/package-lock.json +++ b/apps/backend/package-lock.json @@ -35,6 +35,7 @@ "class-transformer": "^0.5.1", "class-validator": "^0.14.2", "compression": "^1.8.1", + "cookie-parser": "^1.4.7", "csv-parse": "^6.1.0", "exceljs": "^4.4.0", "handlebars": "^4.7.8", @@ -71,6 +72,7 @@ "@nestjs/testing": "^10.2.10", "@types/bcrypt": "^5.0.2", "@types/compression": "^1.8.1", + "@types/cookie-parser": "^1.4.10", "@types/express": "^4.17.21", "@types/jest": "^29.5.11", "@types/multer": "^2.0.0", @@ -258,23 +260,6 @@ "tslib": "^2.1.0" } }, - "node_modules/@apm-js-collab/code-transformer": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@apm-js-collab/code-transformer/-/code-transformer-0.8.2.tgz", - "integrity": "sha512-YRjJjNq5KFSjDUoqu5pFUWrrsvGOxl6c3bu+uMFc9HNNptZ2rNU/TI2nLw4jnhQNtka972Ee2m3uqbvDQtPeCA==", - "license": "Apache-2.0" - }, - "node_modules/@apm-js-collab/tracing-hooks": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@apm-js-collab/tracing-hooks/-/tracing-hooks-0.3.1.tgz", - "integrity": "sha512-Vu1CbmPURlN5fTboVuKMoJjbO5qcq9fA5YXpskx3dXe/zTBvjODFoerw+69rVBlRLrJpwPqSDqEuJDEKIrTldw==", - "license": "Apache-2.0", - "dependencies": { - "@apm-js-collab/code-transformer": "^0.8.0", - "debug": "^4.4.1", - "module-details-from-path": "^1.0.4" - } - }, "node_modules/@aws-crypto/crc32": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", @@ -477,334 +462,254 @@ "node": ">=14.0.0" } }, + "node_modules/@aws-sdk/checksums": { + "version": "3.1000.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/checksums/-/checksums-3.1000.5.tgz", + "integrity": "sha512-zOXUUnilC6lgCsQtp77p/QNPmRlTES9Xi6tlDwbR6kfC/kz5PCzZckgHWm5z+8DskdwuMAbFDq61x3zr10GEEQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@aws-sdk/client-s3": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.906.0.tgz", - "integrity": "sha512-6JQGrmQBHjnARQR+HSaj8DvLRbXTpPa8knYi1veT709JHXVkCkNNLKs7ULjVNCpSffRpzVYJn+eONHKj3Y0knQ==", + "version": "3.1066.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1066.0.tgz", + "integrity": "sha512-jfJTg6Xbyws8+YF5sVQXgCA01elkenGEYeX6+HQOovu9m/Td1Ln2xcY3lHKetVNltdArp5rykjNd56z7bnA9dw==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.906.0", - "@aws-sdk/credential-provider-node": "3.906.0", - "@aws-sdk/middleware-bucket-endpoint": "3.901.0", - "@aws-sdk/middleware-expect-continue": "3.901.0", - "@aws-sdk/middleware-flexible-checksums": "3.906.0", - "@aws-sdk/middleware-host-header": "3.901.0", - "@aws-sdk/middleware-location-constraint": "3.901.0", - "@aws-sdk/middleware-logger": "3.901.0", - "@aws-sdk/middleware-recursion-detection": "3.901.0", - "@aws-sdk/middleware-sdk-s3": "3.906.0", - "@aws-sdk/middleware-ssec": "3.901.0", - "@aws-sdk/middleware-user-agent": "3.906.0", - "@aws-sdk/region-config-resolver": "3.901.0", - "@aws-sdk/signature-v4-multi-region": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@aws-sdk/util-endpoints": "3.901.0", - "@aws-sdk/util-user-agent-browser": "3.901.0", - "@aws-sdk/util-user-agent-node": "3.906.0", - "@aws-sdk/xml-builder": "3.901.0", - "@smithy/config-resolver": "^4.3.0", - "@smithy/core": "^3.14.0", - "@smithy/eventstream-serde-browser": "^4.2.0", - "@smithy/eventstream-serde-config-resolver": "^4.3.0", - "@smithy/eventstream-serde-node": "^4.2.0", - "@smithy/fetch-http-handler": "^5.3.0", - "@smithy/hash-blob-browser": "^4.2.0", - "@smithy/hash-node": "^4.2.0", - "@smithy/hash-stream-node": "^4.2.0", - "@smithy/invalid-dependency": "^4.2.0", - "@smithy/md5-js": "^4.2.0", - "@smithy/middleware-content-length": "^4.2.0", - "@smithy/middleware-endpoint": "^4.3.0", - "@smithy/middleware-retry": "^4.4.0", - "@smithy/middleware-serde": "^4.2.0", - "@smithy/middleware-stack": "^4.2.0", - "@smithy/node-config-provider": "^4.3.0", - "@smithy/node-http-handler": "^4.3.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/smithy-client": "^4.7.0", - "@smithy/types": "^4.6.0", - "@smithy/url-parser": "^4.2.0", - "@smithy/util-base64": "^4.2.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.0", - "@smithy/util-defaults-mode-browser": "^4.2.0", - "@smithy/util-defaults-mode-node": "^4.2.0", - "@smithy/util-endpoints": "^3.2.0", - "@smithy/util-middleware": "^4.2.0", - "@smithy/util-retry": "^4.2.0", - "@smithy/util-stream": "^4.4.0", - "@smithy/util-utf8": "^4.2.0", - "@smithy/util-waiter": "^4.2.0", - "@smithy/uuid": "^1.1.0", + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/credential-provider-node": "^3.972.55", + "@aws-sdk/middleware-flexible-checksums": "^3.974.30", + "@aws-sdk/middleware-sdk-s3": "^3.972.51", + "@aws-sdk/signature-v4-multi-region": "^3.996.34", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.972.51", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.51.tgz", + "integrity": "sha512-keQgcIUTcHL0Qn7guhsuLaxQU36r9norCrxgaPH4DNCwon4TPtXdI/UdYuycl9vj3Dlwc3YR1dfL3U+6iIwJ6w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/signature-v4-multi-region": "^3.996.34", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/client-sesv2": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sesv2/-/client-sesv2-3.906.0.tgz", - "integrity": "sha512-nfqIkDtAvbwQOEPXKPb0a5We3tXhCM41A3C4oY+ttRPyYUecYgo3N0dIIH9ejuVA9ejBmfCIAuR9hx5TZ5ih6A==", + "version": "3.1066.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sesv2/-/client-sesv2-3.1066.0.tgz", + "integrity": "sha512-E50B56dRW18AKSonLg/O30Sjbj7VaGrj7JNy+TEejtLTEL35LDJW1yHXOzPZ5h12eXXo9H0fHZxYZVVS1xblIw==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.906.0", - "@aws-sdk/credential-provider-node": "3.906.0", - "@aws-sdk/middleware-host-header": "3.901.0", - "@aws-sdk/middleware-logger": "3.901.0", - "@aws-sdk/middleware-recursion-detection": "3.901.0", - "@aws-sdk/middleware-user-agent": "3.906.0", - "@aws-sdk/region-config-resolver": "3.901.0", - "@aws-sdk/signature-v4-multi-region": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@aws-sdk/util-endpoints": "3.901.0", - "@aws-sdk/util-user-agent-browser": "3.901.0", - "@aws-sdk/util-user-agent-node": "3.906.0", - "@smithy/config-resolver": "^4.3.0", - "@smithy/core": "^3.14.0", - "@smithy/fetch-http-handler": "^5.3.0", - "@smithy/hash-node": "^4.2.0", - "@smithy/invalid-dependency": "^4.2.0", - "@smithy/middleware-content-length": "^4.2.0", - "@smithy/middleware-endpoint": "^4.3.0", - "@smithy/middleware-retry": "^4.4.0", - "@smithy/middleware-serde": "^4.2.0", - "@smithy/middleware-stack": "^4.2.0", - "@smithy/node-config-provider": "^4.3.0", - "@smithy/node-http-handler": "^4.3.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/smithy-client": "^4.7.0", - "@smithy/types": "^4.6.0", - "@smithy/url-parser": "^4.2.0", - "@smithy/util-base64": "^4.2.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.0", - "@smithy/util-defaults-mode-browser": "^4.2.0", - "@smithy/util-defaults-mode-node": "^4.2.0", - "@smithy/util-endpoints": "^3.2.0", - "@smithy/util-middleware": "^4.2.0", - "@smithy/util-retry": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/credential-provider-node": "^3.972.55", + "@aws-sdk/signature-v4-multi-region": "^3.996.34", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.906.0.tgz", - "integrity": "sha512-GGDwjW2cLzoEF5A1tBlZQZXzhlZzuM6cKNbSxUsCcBXtPAX03eb2GKApVy1SzpD03nTJk5T6GicGAm+BzK+lEg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.906.0", - "@aws-sdk/middleware-host-header": "3.901.0", - "@aws-sdk/middleware-logger": "3.901.0", - "@aws-sdk/middleware-recursion-detection": "3.901.0", - "@aws-sdk/middleware-user-agent": "3.906.0", - "@aws-sdk/region-config-resolver": "3.901.0", - "@aws-sdk/types": "3.901.0", - "@aws-sdk/util-endpoints": "3.901.0", - "@aws-sdk/util-user-agent-browser": "3.901.0", - "@aws-sdk/util-user-agent-node": "3.906.0", - "@smithy/config-resolver": "^4.3.0", - "@smithy/core": "^3.14.0", - "@smithy/fetch-http-handler": "^5.3.0", - "@smithy/hash-node": "^4.2.0", - "@smithy/invalid-dependency": "^4.2.0", - "@smithy/middleware-content-length": "^4.2.0", - "@smithy/middleware-endpoint": "^4.3.0", - "@smithy/middleware-retry": "^4.4.0", - "@smithy/middleware-serde": "^4.2.0", - "@smithy/middleware-stack": "^4.2.0", - "@smithy/node-config-provider": "^4.3.0", - "@smithy/node-http-handler": "^4.3.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/smithy-client": "^4.7.0", - "@smithy/types": "^4.6.0", - "@smithy/url-parser": "^4.2.0", - "@smithy/util-base64": "^4.2.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.0", - "@smithy/util-defaults-mode-browser": "^4.2.0", - "@smithy/util-defaults-mode-node": "^4.2.0", - "@smithy/util-endpoints": "^3.2.0", - "@smithy/util-middleware": "^4.2.0", - "@smithy/util-retry": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/core": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.906.0.tgz", - "integrity": "sha512-+FuwAcozee8joVfjwly/8kSFNCvQOkcQYjINUckqBkdjO4iCRfOgSaz+0JMpMcYgVPnnyZv62gJ2g0bj0U+YDQ==", + "version": "3.974.20", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.974.20.tgz", + "integrity": "sha512-7sDi2B2N3mc3nf1nz6FyEx/FCrJ1N1QnBmraHHQNabFaeAh2IaOOLml48/rHOD1bICHgTRkbBgNTvUzEr5Z35g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.901.0", - "@aws-sdk/xml-builder": "3.901.0", - "@smithy/core": "^3.14.0", - "@smithy/node-config-provider": "^4.3.0", - "@smithy/property-provider": "^4.2.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/signature-v4": "^5.3.0", - "@smithy/smithy-client": "^4.7.0", - "@smithy/types": "^4.6.0", - "@smithy/util-base64": "^4.2.0", - "@smithy/util-middleware": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", + "@aws-sdk/types": "^3.973.12", + "@aws-sdk/xml-builder": "^3.972.29", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/core": "^3.24.6", + "@smithy/signature-v4": "^5.4.6", + "@smithy/types": "^4.14.3", + "bowser": "^2.11.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.906.0.tgz", - "integrity": "sha512-vtMDguMci2aXhkgEqg1iqyQ7vVcafpx9uypksM6FQsNr3Cc/8I6HgfBAja6BuPwkaCn9NoMnG0/iuuOWr8P9dg==", + "version": "3.972.46", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.46.tgz", + "integrity": "sha512-+GPXVS2srMOlH74S+SmC1gVuP2TvUZ0siuC0onKO93q+udP+M72dmY8wJfVQ5CX9z/9X5A1HHwz5yRIGBtskvQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@smithy/property-provider": "^4.2.0", - "@smithy/types": "^4.6.0", + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.906.0.tgz", - "integrity": "sha512-L97N2SUkZp03s1LJZ1sCkUaUZ7m9T72faaadn05wyst/iXonSZKPHYMQVWGYhTC2OtRV0FQvBXIAqFZsNGQD0Q==", + "version": "3.972.48", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.48.tgz", + "integrity": "sha512-fA5loSdlocacRxyUXtpoHSMuk5rsIKRDzQYVMnMxjcmFeZshaJlJ8lymy/hYKji6sne/UmNGj5pxuEs6kq/Qcg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@smithy/fetch-http-handler": "^5.3.0", - "@smithy/node-http-handler": "^4.3.0", - "@smithy/property-provider": "^4.2.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/smithy-client": "^4.7.0", - "@smithy/types": "^4.6.0", - "@smithy/util-stream": "^4.4.0", + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.906.0.tgz", - "integrity": "sha512-r7TbHD80WXo42kTEC5bqa4b87ho3T3yd2VEKo1qbEmOUovocntO8HC3JxHYr0XSeZ82DEYxLARb84akWjabPzg==", + "version": "3.972.53", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.53.tgz", + "integrity": "sha512-ZfdhIOR41q8TcWEnUac+gCOb+O2LBWdHLmjedXpXz4IEFW2ppNuFcm6p0sMTavpM+zD5TYfpH5Gp7guRyqSgsQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.906.0", - "@aws-sdk/credential-provider-env": "3.906.0", - "@aws-sdk/credential-provider-http": "3.906.0", - "@aws-sdk/credential-provider-process": "3.906.0", - "@aws-sdk/credential-provider-sso": "3.906.0", - "@aws-sdk/credential-provider-web-identity": "3.906.0", - "@aws-sdk/nested-clients": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@smithy/credential-provider-imds": "^4.2.0", - "@smithy/property-provider": "^4.2.0", - "@smithy/shared-ini-file-loader": "^4.3.0", - "@smithy/types": "^4.6.0", + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/credential-provider-env": "^3.972.46", + "@aws-sdk/credential-provider-http": "^3.972.48", + "@aws-sdk/credential-provider-login": "^3.972.52", + "@aws-sdk/credential-provider-process": "^3.972.46", + "@aws-sdk/credential-provider-sso": "^3.972.52", + "@aws-sdk/credential-provider-web-identity": "^3.972.52", + "@aws-sdk/nested-clients": "^3.997.20", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/credential-provider-imds": "^4.3.7", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.52", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.52.tgz", + "integrity": "sha512-9hu2oR0qH7Fst5Tzdx+UWxm+w5zCXtErTLtOOW5hwwQc170CLwOeniRxyFY6s9mHfGEfC5zFukNBdKBwJR8mhQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/nested-clients": "^3.997.20", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.906.0.tgz", - "integrity": "sha512-xga127vP0rFxiHjEUjLe6Yf4hQ/AZinOF4AqQr/asWQO+/uwh3aH8nXcS4lkpZNygxMHbuNXm7Xg504GKCMlLQ==", + "version": "3.972.55", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.55.tgz", + "integrity": "sha512-zMGLa/dhESVqmCD7mmIFFKSwSFrJGScvCXcjvBZEVOOMauFS5JRQvLTMukFpMEFWiV6dTAlsen2ATDBulLPtbg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.906.0", - "@aws-sdk/credential-provider-http": "3.906.0", - "@aws-sdk/credential-provider-ini": "3.906.0", - "@aws-sdk/credential-provider-process": "3.906.0", - "@aws-sdk/credential-provider-sso": "3.906.0", - "@aws-sdk/credential-provider-web-identity": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@smithy/credential-provider-imds": "^4.2.0", - "@smithy/property-provider": "^4.2.0", - "@smithy/shared-ini-file-loader": "^4.3.0", - "@smithy/types": "^4.6.0", + "@aws-sdk/credential-provider-env": "^3.972.46", + "@aws-sdk/credential-provider-http": "^3.972.48", + "@aws-sdk/credential-provider-ini": "^3.972.53", + "@aws-sdk/credential-provider-process": "^3.972.46", + "@aws-sdk/credential-provider-sso": "^3.972.52", + "@aws-sdk/credential-provider-web-identity": "^3.972.52", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/credential-provider-imds": "^4.3.7", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.906.0.tgz", - "integrity": "sha512-P8R4GpDLppe+8mp+SOj1fKaY3AwDULCi/fqMSJjvf8qN6OM+vGGpFP3iXvkjFYyyV+8nRXY+HQCLRoZKpRtzMg==", + "version": "3.972.46", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.46.tgz", + "integrity": "sha512-VUoNFBIjWrUN8NbFiQiuxQEgFjvziAlBRPK+ddh27aj65gk0BYu6bLZnrdrNZwpW6vAihtSUtEMQ1PUJ32QRPA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@smithy/property-provider": "^4.2.0", - "@smithy/shared-ini-file-loader": "^4.3.0", - "@smithy/types": "^4.6.0", + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.906.0.tgz", - "integrity": "sha512-wYljHU7yNEzt7ngZZ21FWh+RlO16gTpWvXyRqlryuCgIWugHD8bl7JphGnUN1md5/v+mCRuGK58JoFGZq+qrjA==", + "version": "3.972.52", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.52.tgz", + "integrity": "sha512-nb2/n4o/HQf+FVpVbZe9vCTFngmuDoIsltMgLAtjixaKzvzhB4J8WSDFyWgnErgLHk55ctWH+I4PU+LIHhyffg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.906.0", - "@aws-sdk/core": "3.906.0", - "@aws-sdk/token-providers": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@smithy/property-provider": "^4.2.0", - "@smithy/shared-ini-file-loader": "^4.3.0", - "@smithy/types": "^4.6.0", + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/nested-clients": "^3.997.20", + "@aws-sdk/token-providers": "3.1066.0", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.906.0.tgz", - "integrity": "sha512-V9PurepVko8+iyEvI9WAlk5dXJ1uWIW03RPLnNBEmeCqFjjit16HrNaaVvnp9fQbG7CSKSGqK026SjDgtKGKYA==", + "version": "3.972.52", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.52.tgz", + "integrity": "sha512-lKj6aRSGbqLmpYmM24bY7a1Xmfcq2vkE3hv8CSPYfc1yCu0BPu/XEJ1L4Fm61MsU6ULLNSG8UGsffNoFUBjESA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.906.0", - "@aws-sdk/nested-clients": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@smithy/property-provider": "^4.2.0", - "@smithy/shared-ini-file-loader": "^4.3.0", - "@smithy/types": "^4.6.0", + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/nested-clients": "^3.997.20", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/lib-storage": { @@ -838,353 +743,100 @@ "ieee754": "^1.1.4" } }, - "node_modules/@aws-sdk/middleware-bucket-endpoint": { - "version": "3.901.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.901.0.tgz", - "integrity": "sha512-mPF3N6eZlVs9G8aBSzvtoxR1RZqMo1aIwR+X8BAZSkhfj55fVF2no4IfPXfdFO3I66N+zEQ8nKoB0uTATWrogQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.901.0", - "@aws-sdk/util-arn-parser": "3.893.0", - "@smithy/node-config-provider": "^4.3.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", - "@smithy/util-config-provider": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-expect-continue": { - "version": "3.901.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.901.0.tgz", - "integrity": "sha512-bwq9nj6MH38hlJwOY9QXIDwa6lI48UsaZpaXbdD71BljEIRlxDzfB4JaYb+ZNNK7RIAdzsP/K05mJty6KJAQHw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.901.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.906.0.tgz", - "integrity": "sha512-vbOf5Pf2bRjw+Is1OsUKKP88uPKES8/B3c3yq0B72Y4ZgZEDymXIxGvZYPkThLk266PH7eHo+ZneZjkdfz6Zbg==", + "version": "3.974.30", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.974.30.tgz", + "integrity": "sha512-OaIhub+3yTgfFWPzKO8OzOZFIMUoJaiS5v67y3spQg7SoULGoMx4jKVBbE+uhnzkiZXQ+rEDS0RqrK4/aD1yJw==", "license": "Apache-2.0", "dependencies": { - "@aws-crypto/crc32": "5.2.0", - "@aws-crypto/crc32c": "5.2.0", - "@aws-crypto/util": "5.2.0", - "@aws-sdk/core": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@smithy/is-array-buffer": "^4.2.0", - "@smithy/node-config-provider": "^4.3.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", - "@smithy/util-middleware": "^4.2.0", - "@smithy/util-stream": "^4.4.0", - "@smithy/util-utf8": "^4.2.0", + "@aws-sdk/checksums": "^3.1000.5", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.901.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.901.0.tgz", - "integrity": "sha512-yWX7GvRmqBtbNnUW7qbre3GvZmyYwU0WHefpZzDTYDoNgatuYq6LgUIQ+z5C04/kCRoFkAFrHag8a3BXqFzq5A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.901.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-location-constraint": { - "version": "3.901.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.901.0.tgz", - "integrity": "sha512-MuCS5R2ngNoYifkVt05CTULvYVWX0dvRT0/Md4jE3a0u0yMygYy31C1zorwfE/SUgAQXyLmUx8ATmPp9PppImQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.901.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.901.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.901.0.tgz", - "integrity": "sha512-UoHebjE7el/tfRo8/CQTj91oNUm+5Heus5/a4ECdmWaSCHCS/hXTsU3PTTHAY67oAQR8wBLFPfp3mMvXjB+L2A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.901.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.901.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.901.0.tgz", - "integrity": "sha512-Wd2t8qa/4OL0v/oDpCHHYkgsXJr8/ttCxrvCKAt0H1zZe2LlRhY9gpDVKqdertfHrHDj786fOvEQA28G1L75Dg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.901.0", - "@aws/lambda-invoke-store": "^0.0.1", - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.906.0.tgz", - "integrity": "sha512-8Ztl5natyVXOvpk/en2j9Bjn2t8vawjbvgcU0/ZF5/JtA1rKSTctRXusICJgCovFHzaAH2MVhA51nnp3d8rViA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@aws-sdk/util-arn-parser": "3.893.0", - "@smithy/core": "^3.14.0", - "@smithy/node-config-provider": "^4.3.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/signature-v4": "^5.3.0", - "@smithy/smithy-client": "^4.7.0", - "@smithy/types": "^4.6.0", - "@smithy/util-config-provider": "^4.2.0", - "@smithy/util-middleware": "^4.2.0", - "@smithy/util-stream": "^4.4.0", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-ssec": { - "version": "3.901.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.901.0.tgz", - "integrity": "sha512-YiLLJmA3RvjL38mFLuu8fhTTGWtp2qT24VqpucgfoyziYcTgIQkJJmKi90Xp6R6/3VcArqilyRgM1+x8i/em+Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.901.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.906.0.tgz", - "integrity": "sha512-CMAjq2oCEv5EEvmlFvio8t4KQL2jGORyDQu7oLj4l0a2biPgxbwL3utalbm9yKty1rQM5zKpaa7id7ZG3X1f6A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@aws-sdk/util-endpoints": "3.901.0", - "@smithy/core": "^3.14.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.906.0.tgz", - "integrity": "sha512-0/r0bh/9Bm14lVe+jAzQQB2ufq9S4Vd9Wg5rZn8RhrhKl6y/DC1aRzOo2kJTNu5pCbVfQsd/VXLLnkcbOrDy6A==", + "version": "3.997.20", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.20.tgz", + "integrity": "sha512-IYJuLpXp2DEILVQpQOy0PMpkftv0AHEOCn52o0atyOaumA0CdWQ3klPyXdViGYLbNpESsVFMVybvHUeZAuiGxA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.906.0", - "@aws-sdk/middleware-host-header": "3.901.0", - "@aws-sdk/middleware-logger": "3.901.0", - "@aws-sdk/middleware-recursion-detection": "3.901.0", - "@aws-sdk/middleware-user-agent": "3.906.0", - "@aws-sdk/region-config-resolver": "3.901.0", - "@aws-sdk/types": "3.901.0", - "@aws-sdk/util-endpoints": "3.901.0", - "@aws-sdk/util-user-agent-browser": "3.901.0", - "@aws-sdk/util-user-agent-node": "3.906.0", - "@smithy/config-resolver": "^4.3.0", - "@smithy/core": "^3.14.0", - "@smithy/fetch-http-handler": "^5.3.0", - "@smithy/hash-node": "^4.2.0", - "@smithy/invalid-dependency": "^4.2.0", - "@smithy/middleware-content-length": "^4.2.0", - "@smithy/middleware-endpoint": "^4.3.0", - "@smithy/middleware-retry": "^4.4.0", - "@smithy/middleware-serde": "^4.2.0", - "@smithy/middleware-stack": "^4.2.0", - "@smithy/node-config-provider": "^4.3.0", - "@smithy/node-http-handler": "^4.3.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/smithy-client": "^4.7.0", - "@smithy/types": "^4.6.0", - "@smithy/url-parser": "^4.2.0", - "@smithy/util-base64": "^4.2.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.0", - "@smithy/util-defaults-mode-browser": "^4.2.0", - "@smithy/util-defaults-mode-node": "^4.2.0", - "@smithy/util-endpoints": "^3.2.0", - "@smithy/util-middleware": "^4.2.0", - "@smithy/util-retry": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/signature-v4-multi-region": "^3.996.34", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.901.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.901.0.tgz", - "integrity": "sha512-7F0N888qVLHo4CSQOsnkZ4QAp8uHLKJ4v3u09Ly5k4AEStrSlFpckTPyUx6elwGL+fxGjNE2aakK8vEgzzCV0A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.901.0", - "@smithy/node-config-provider": "^4.3.0", - "@smithy/types": "^4.6.0", - "@smithy/util-config-provider": "^4.2.0", - "@smithy/util-middleware": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/s3-request-presigner": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.906.0.tgz", - "integrity": "sha512-gNdFoyerUYSE+xtSi+WCuBOw54PTZmvjri/lDq5Can3a7uOQnMSZLaIjFrCRV5RZlLyCPnb3VWy3hIWOppnYvQ==", + "version": "3.1066.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.1066.0.tgz", + "integrity": "sha512-hgjGUVKggCKcwS+e7HOoHlElQrhz4nlZkMWGKez/Ycjv2qZaQeTZ8Ps7HGOrpqR3KBPWt7iSrOBcOCVoUYYRWw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/signature-v4-multi-region": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@aws-sdk/util-format-url": "3.901.0", - "@smithy/middleware-endpoint": "^4.3.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/smithy-client": "^4.7.0", - "@smithy/types": "^4.6.0", + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/signature-v4-multi-region": "^3.996.34", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.906.0.tgz", - "integrity": "sha512-zqxRN8/dSrAaAEi5oXIeScsrbDkS63+ZyaBrkC6bc8Jd/bCvJM6D4LjJJxIOPBNXuF0bNhBIlTmqwtbkiqCwZw==", + "version": "3.996.34", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.34.tgz", + "integrity": "sha512-mx1L5qlumSOt/nKM3BFaHE2HVkWwz0i4Bw0pyYO42FfX/FeLlo8YI6csC0gSPprEk6fTIqI+CZN9RwUwKd5krQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/signature-v4": "^5.3.0", - "@smithy/types": "^4.6.0", + "@aws-sdk/types": "^3.973.12", + "@smithy/signature-v4": "^5.4.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.906.0.tgz", - "integrity": "sha512-gdxXleCjMUAKnyR/1ksdnv3Fuifr9iuaeEtINRHkwVluwcORabEdOlxW36th2QdkpTTyP1hW35VATz2R6v/i2Q==", + "version": "3.1066.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1066.0.tgz", + "integrity": "sha512-UqEUJq7dqa44hneLDUcX7UJy95cg8YqEWyakRpvIPnrNS3Mq+UlQHgCDGu5pvwAPtlIW4qcYbvW6reG6++FyvA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.906.0", - "@aws-sdk/nested-clients": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@smithy/property-provider": "^4.2.0", - "@smithy/shared-ini-file-loader": "^4.3.0", - "@smithy/types": "^4.6.0", + "@aws-sdk/core": "^3.974.20", + "@aws-sdk/nested-clients": "^3.997.20", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/types": { - "version": "3.901.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.901.0.tgz", - "integrity": "sha512-FfEM25hLEs4LoXsLXQ/q6X6L4JmKkKkbVFpKD4mwfVHtRVQG6QxJiCPcrkcPISquiy6esbwK2eh64TWbiD60cg==", + "version": "3.973.12", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.12.tgz", + "integrity": "sha512-43ajd1NF0RMgX5k0hxCNUyEdrtFUsb2aHT2QvpktSC/2Eyb2Jr/JPVqdp0XIoaHWikZJq5tNWSLO6kB5q2eMCA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.6.0", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/util-arn-parser": { - "version": "3.893.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.893.0.tgz", - "integrity": "sha512-u8H4f2Zsi19DGnwj5FSZzDMhytYF/bCh37vAtBsn3cNDL3YG578X5oc+wSX54pM3tOxS+NY7tvOAo52SW7koUA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.901.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.901.0.tgz", - "integrity": "sha512-5nZP3hGA8FHEtKvEQf4Aww5QZOkjLW1Z+NixSd+0XKfHvA39Ah5sZboScjLx0C9kti/K3OGW1RCx5K9Zc3bZqg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.901.0", - "@smithy/types": "^4.6.0", - "@smithy/url-parser": "^4.2.0", - "@smithy/util-endpoints": "^3.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/util-format-url": { - "version": "3.901.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.901.0.tgz", - "integrity": "sha512-GGUnJKrh3OF1F3YRSWtwPLbN904Fcfxf03gujyq1rcrDRPEkzoZB+2BzNkB27SsU6lAlwNq+4aRlZRVUloPiag==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.901.0", - "@smithy/querystring-builder": "^4.2.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/util-locate-window": { @@ -1199,60 +851,24 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.901.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.901.0.tgz", - "integrity": "sha512-Ntb6V/WFI21Ed4PDgL/8NSfoZQQf9xzrwNgiwvnxgAl/KvAvRBgQtqj5gHsDX8Nj2YmJuVoHfH9BGjL9VQ4WNg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.901.0", - "@smithy/types": "^4.6.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.906.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.906.0.tgz", - "integrity": "sha512-9Gaglw80E9UZ5FctCp5pZAzT40/vC4Oo0fcNXsfplLkpWqTU+NTdTRMYe3TMZ1/v1/JZKuGUVyHiuo/xLu3NmA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/middleware-user-agent": "3.906.0", - "@aws-sdk/types": "3.901.0", - "@smithy/node-config-provider": "^4.3.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } - } - }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.901.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.901.0.tgz", - "integrity": "sha512-pxFCkuAP7Q94wMTNPAwi6hEtNrp/BdFf+HOrIEeFQsk4EoOmpKY3I6S+u6A9Wg295J80Kh74LqDWM22ux3z6Aw==", + "version": "3.972.29", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.29.tgz", + "integrity": "sha512-fk0niuGFxfi8yIJuMVM4mhwObkiQSuwZFj3tAPrLVx64Pk3BkrEIpqjzHKY4hKoEBUD6Jg/S74Zj9jy+5F3DnQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.6.0", - "fast-xml-parser": "5.2.5", + "@smithy/types": "^4.14.3", + "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws/lambda-invoke-store": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.0.1.tgz", - "integrity": "sha512-ORHRQ2tmvnBXc8t/X9Z8IcSbBA4xTLKuN873FopzklHMeqBst7YG0d+AX97inkvDX+NChYtSr+qGfcqGFaI8Zw==", + "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" @@ -1720,9 +1336,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1888,9 +1504,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -1905,9 +1521,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -1923,9 +1539,9 @@ "license": "MIT" }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -2035,9 +1651,9 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -2046,9 +1662,9 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -2231,9 +1847,9 @@ } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "license": "MIT", "dependencies": { @@ -2494,9 +2110,9 @@ } }, "node_modules/@jest/reporters/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -2527,9 +2143,9 @@ } }, "node_modules/@jest/reporters/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -2921,9 +2537,9 @@ } }, "node_modules/@nestjs/core": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.20.tgz", - "integrity": "sha512-kRdtyKA3+Tu70N3RQ4JgmO1E3LzAMs/eppj7SfjabC7TgqNWoS4RLhWl4BqmsNVmjj6D5jgfPVtHtgYkU3AfpQ==", + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.22.tgz", + "integrity": "sha512-6IX9+VwjiKtCjx+mXVPncpkQ5ZjKfmssOZPFexmT+6T9H9wZ3svpYACAo7+9e7Nr9DZSoRZw3pffkJP7Z0UjaA==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -3002,14 +2618,14 @@ } }, "node_modules/@nestjs/platform-express": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.20.tgz", - "integrity": "sha512-rh97mX3rimyf4xLMLHuTOBKe6UD8LOJ14VlJ1F/PTd6C6ZK9Ak6EHuJvdaGcSFQhd3ZMBh3I6CuujKGW9pNdIg==", + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.22.tgz", + "integrity": "sha512-ySSq7Py/DFozzZdNDH67m/vHoeVdphDniWBnl6q5QVoXldDdrZIHLXLRMPayTDh5A95nt7jjJzmD4qpTbNQ6tA==", "license": "MIT", "dependencies": { - "body-parser": "1.20.3", + "body-parser": "1.20.4", "cors": "2.8.5", - "express": "4.21.2", + "express": "4.22.1", "multer": "2.0.2", "tslib": "2.8.1" }, @@ -3023,9 +2639,9 @@ } }, "node_modules/@nestjs/platform-socket.io": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.20.tgz", - "integrity": "sha512-8wqJ7kJnvRC6T1o1U3NNnuzjaMJU43R4hvzKKba7GSdMN6j2Jfzz/vq5gHDx9xbXOAmfsc9bvaIiZegXxvHoJA==", + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.22.tgz", + "integrity": "sha512-xxGw3R0Ihr51/Omq23z3//bKmCXyVKaikxbH0/pkwqMsQrxkUv9NabNUZ22b4Jnlwwi02X+zlwo8GRa9u8oV9g==", "license": "MIT", "dependencies": { "socket.io": "4.8.1", @@ -3099,9 +2715,9 @@ } }, "node_modules/@nestjs/testing": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.20.tgz", - "integrity": "sha512-nMkRDukDKskdPruM6EsgMq7yJua+CPZM6I6FrLP8yXw8BiVSPv9Nm0CtcGGwt3kgZF9hfxKjGqLjsvVBsv6Vfw==", + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.22.tgz", + "integrity": "sha512-HO9aPus3bAedAC+jKVAA8jTdaj4fs5M9fing4giHrcYV2txe9CvC1l1WAjwQ9RDhEHdugjY4y+FZA/U/YqPZrA==", "dev": true, "license": "MIT", "dependencies": { @@ -3154,9 +2770,9 @@ } }, "node_modules/@nestjs/websockets": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.20.tgz", - "integrity": "sha512-tafsPPvQfAXc+cfxvuRDzS5V+Ixg8uVJq8xSocU24yVl/Xp6ajmhqiGiaVjYOX8mXY0NV836QwEZxHF7WvKHSw==", + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.22.tgz", + "integrity": "sha512-OLd4i0Faq7vgdtB5vVUrJ54hWEtcXy9poJ6n7kbbh/5ms+KffUl+wwGsbe7uSXLrkoyI8xXU6fZPkFArI+XiRg==", "license": "MIT", "dependencies": { "iterare": "1.2.1", @@ -3189,6 +2805,18 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@nodable/entities": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.1.tgz", + "integrity": "sha512-Pig3HxDIoMgjdEH8OCf/dkcTmLFjJRjWuq8jSnklu284/TKOPibSRERmOykiwmyXTtv61mP+44f3GMx0tLAyjg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3252,18 +2880,18 @@ "license": "MIT" }, "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", + "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==", "license": "Apache-2.0", "engines": { "node": ">=8.0.0" } }, "node_modules/@opentelemetry/api-logs": { - "version": "0.204.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.204.0.tgz", - "integrity": "sha512-DqxY8yoAaiBPivoJD4UtgrMS8gEmzZ5lnaxzPojzLVHBGqPxgWm4zcuvcUHZiqQ6kRX2Klel2r9y8cA2HAtqpw==", + "version": "0.214.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.214.0.tgz", + "integrity": "sha512-40lSJeqYO8Uz2Yj7u94/SJWE/wONa7rmMKjI1ZcIjgf3MHNHv1OZUCrCETGuaRF62d5pQD1wKIW+L4lmSMTzZA==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.3.0" @@ -3272,22 +2900,10 @@ "node": ">=8.0.0" } }, - "node_modules/@opentelemetry/context-async-hooks": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.1.0.tgz", - "integrity": "sha512-zOyetmZppnwTyPrt4S7jMfXiSX9yyfF0hxlA8B5oo2TtKl+/RGCy7fi4DrBfIf3lCPrkKsRBWZZD7RFojK7FDg==", - "license": "Apache-2.0", - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, "node_modules/@opentelemetry/core": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.1.0.tgz", - "integrity": "sha512-RMEtHsxJs/GiHHxYT58IY57UXAQTuUnZVco6ymDEqTNlJKTimM4qPUPVe8InNFyBjhHBEAx4k3Q8LtNayBsbUQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.8.0.tgz", + "integrity": "sha512-hd1Lfh8p545nNz+jq1Ejfz+Mn1hyLuxYn1YzTfFNrxr8urEWMNQLPf1Th8kjOH+HxwawCrtgBp8JpBUR4ZSgww==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" @@ -3300,14 +2916,14 @@ } }, "node_modules/@opentelemetry/instrumentation": { - "version": "0.204.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.204.0.tgz", - "integrity": "sha512-vV5+WSxktzoMP8JoYWKeopChy6G3HKk4UQ2hESCRDUUTZqQ3+nM3u8noVG0LmNfRWwcFBnbZ71GKC7vaYYdJ1g==", + "version": "0.214.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.214.0.tgz", + "integrity": "sha512-MHqEX5Dk59cqVah5LiARMACku7jXSVk9iVDWOea4x3cr7VfdByeDCURK6o1lntT1JS/Tsovw01UJrBhN3/uC5w==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.204.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1" + "@opentelemetry/api-logs": "0.214.0", + "import-in-the-middle": "^3.0.0", + "require-in-the-middle": "^8.0.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -3316,388 +2932,13 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-amqplib": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.51.0.tgz", - "integrity": "sha512-XGmjYwjVRktD4agFnWBWQXo9SiYHKBxR6Ag3MLXwtLE4R99N3a08kGKM5SC1qOFKIELcQDGFEFT9ydXMH00Luw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-connect": { - "version": "0.48.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.48.0.tgz", - "integrity": "sha512-OMjc3SFL4pC16PeK+tDhwP7MRvDPalYCGSvGqUhX5rASkI2H0RuxZHOWElYeXkV0WP+70Gw6JHWac/2Zqwmhdw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/connect": "3.4.38" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-dataloader": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.22.0.tgz", - "integrity": "sha512-bXnTcwtngQsI1CvodFkTemrrRSQjAjZxqHVc+CJZTDnidT0T6wt3jkKhnsjU/Kkkc0lacr6VdRpCu2CUWa0OKw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-express": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.53.0.tgz", - "integrity": "sha512-r/PBafQmFYRjuxLYEHJ3ze1iBnP2GDA1nXOSS6E02KnYNZAVjj6WcDA1MSthtdAUUK0XnotHvvWM8/qz7DMO5A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-fs": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.24.0.tgz", - "integrity": "sha512-HjIxJ6CBRD770KNVaTdMXIv29Sjz4C1kPCCK5x1Ujpc6SNnLGPqUVyJYZ3LUhhnHAqdbrl83ogVWjCgeT4Q0yw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-generic-pool": { - "version": "0.48.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.48.0.tgz", - "integrity": "sha512-TLv/On8pufynNR+pUbpkyvuESVASZZKMlqCm4bBImTpXKTpqXaJJ3o/MUDeMlM91rpen+PEv2SeyOKcHCSlgag==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-graphql": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.52.0.tgz", - "integrity": "sha512-3fEJ8jOOMwopvldY16KuzHbRhPk8wSsOTSF0v2psmOCGewh6ad+ZbkTx/xyUK9rUdUMWAxRVU0tFpj4Wx1vkPA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-hapi": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.51.0.tgz", - "integrity": "sha512-qyf27DaFNL1Qhbo/da+04MSCw982B02FhuOS5/UF+PMhM61CcOiu7fPuXj8TvbqyReQuJFljXE6UirlvoT/62g==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-http": { - "version": "0.204.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.204.0.tgz", - "integrity": "sha512-1afJYyGRA4OmHTv0FfNTrTAzoEjPQUYgd+8ih/lX0LlZBnGio/O80vxA0lN3knsJPS7FiDrsDrWq25K7oAzbkw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.1.0", - "@opentelemetry/instrumentation": "0.204.0", - "@opentelemetry/semantic-conventions": "^1.29.0", - "forwarded-parse": "2.1.2" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-ioredis": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.52.0.tgz", - "integrity": "sha512-rUvlyZwI90HRQPYicxpDGhT8setMrlHKokCtBtZgYxQWRF5RBbG4q0pGtbZvd7kyseuHbFpA3I/5z7M8b/5ywg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/redis-common": "^0.38.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-kafkajs": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.14.0.tgz", - "integrity": "sha512-kbB5yXS47dTIdO/lfbbXlzhvHFturbux4EpP0+6H78Lk0Bn4QXiZQW7rmZY1xBCY16mNcCb8Yt0mhz85hTnSVA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.30.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-knex": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.49.0.tgz", - "integrity": "sha512-NKsRRT27fbIYL4Ix+BjjP8h4YveyKc+2gD6DMZbr5R5rUeDqfC8+DTfIt3c3ex3BIc5Vvek4rqHnN7q34ZetLQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.33.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-koa": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.52.0.tgz", - "integrity": "sha512-JJSBYLDx/mNSy8Ibi/uQixu2rH0bZODJa8/cz04hEhRaiZQoeJ5UrOhO/mS87IdgVsHrnBOsZ6vDu09znupyuA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-lru-memoizer": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.49.0.tgz", - "integrity": "sha512-ctXu+O/1HSadAxtjoEg2w307Z5iPyLOMM8IRNwjaKrIpNAthYGSOanChbk1kqY6zU5CrpkPHGdAT6jk8dXiMqw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-mongodb": { - "version": "0.57.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.57.0.tgz", - "integrity": "sha512-KD6Rg0KSHWDkik+qjIOWoksi1xqSpix8TSPfquIK1DTmd9OTFb5PHmMkzJe16TAPVEuElUW8gvgP59cacFcrMQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-mongoose": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.51.0.tgz", - "integrity": "sha512-gwWaAlhhV2By7XcbyU3DOLMvzsgeaymwP/jktDC+/uPkCmgB61zurwqOQdeiRq9KAf22Y2dtE5ZLXxytJRbEVA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-mysql": { - "version": "0.50.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.50.0.tgz", - "integrity": "sha512-duKAvMRI3vq6u9JwzIipY9zHfikN20bX05sL7GjDeLKr2qV0LQ4ADtKST7KStdGcQ+MTN5wghWbbVdLgNcB3rA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/mysql": "2.15.27" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-mysql2": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.51.0.tgz", - "integrity": "sha512-zT2Wg22Xn43RyfU3NOUmnFtb5zlDI0fKcijCj9AcK9zuLZ4ModgtLXOyBJSSfO+hsOCZSC1v/Fxwj+nZJFdzLQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@opentelemetry/sql-common": "^0.41.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-pg": { - "version": "0.57.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.57.0.tgz", - "integrity": "sha512-dWLGE+r5lBgm2A8SaaSYDE3OKJ/kwwy5WLyGyzor8PLhUL9VnJRiY6qhp4njwhnljiLtzeffRtG2Mf/YyWLeTw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.34.0", - "@opentelemetry/sql-common": "^0.41.0", - "@types/pg": "8.15.5", - "@types/pg-pool": "2.0.6" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-redis": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.53.0.tgz", - "integrity": "sha512-WUHV8fr+8yo5RmzyU7D5BIE1zwiaNQcTyZPwtxlfr7px6NYYx7IIpSihJK7WA60npWynfxxK1T67RAVF0Gdfjg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/redis-common": "^0.38.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-tedious": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.23.0.tgz", - "integrity": "sha512-3TMTk/9VtlRonVTaU4tCzbg4YqW+Iq/l5VnN2e5whP6JgEg/PKfrGbqQ+CxQWNLfLaQYIUgEZqAn5gk/inh1uQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/tedious": "^4.0.14" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-undici": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.15.0.tgz", - "integrity": "sha512-sNFGA/iCDlVkNjzTzPRcudmI11vT/WAfAguRdZY9IspCw02N4WSC72zTuQhSMheh2a1gdeM9my1imnKRvEEvEg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.7.0" - } - }, - "node_modules/@opentelemetry/redis-common": { - "version": "0.38.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.38.2.tgz", - "integrity": "sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA==", - "license": "Apache-2.0", - "engines": { - "node": "^18.19.0 || >=20.6.0" - } - }, "node_modules/@opentelemetry/resources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.1.0.tgz", - "integrity": "sha512-1CJjf3LCvoefUOgegxi8h6r4B/wLSzInyhGP2UmIBYNlo4Qk5CZ73e1eEyWmfXvFtm1ybkmfb2DqWvspsYLrWw==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.8.0.tgz", + "integrity": "sha512-qmXQ27ilDbUK/vGMqwL8D4/rhn76C+sherM4wTbjlfknR8Nvfc/hCxjRJPhkzZzUsPiNg16SA31NxMabwttRjg==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.1.0", + "@opentelemetry/core": "2.8.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { @@ -3708,13 +2949,13 @@ } }, "node_modules/@opentelemetry/sdk-trace-base": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.1.0.tgz", - "integrity": "sha512-uTX9FBlVQm4S2gVQO1sb5qyBLq/FPjbp+tmGoxu4tIgtYGmBYB44+KX/725RFDe30yBSaA9Ml9fqphe1hbUyLQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.8.0.tgz", + "integrity": "sha512-mhU4jp+vW0mGbFRd+GeXHvmfA4aDqWjBjLC3pE5XMpLs0IE2ryYb019Ts2AQrOq67gaTF25D91+fgvEHDZEnuQ==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.1.0", - "@opentelemetry/resources": "2.1.0", + "@opentelemetry/core": "2.8.0", + "@opentelemetry/resources": "2.8.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { @@ -3725,29 +2966,14 @@ } }, "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.37.0.tgz", - "integrity": "sha512-JD6DerIKdJGmRp4jQyX5FlrQjA4tjOw1cvfsPAZXfOOEErMUHjPcPSICS+6WnM0nB0efSFARh0KAZss+bvExOA==", + "version": "1.41.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.41.1.tgz", + "integrity": "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==", "license": "Apache-2.0", "engines": { "node": ">=14" } }, - "node_modules/@opentelemetry/sql-common": { - "version": "0.41.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.41.2.tgz", - "integrity": "sha512-4mhWm3Z8z+i508zQJ7r6Xi7y4mmoJpdvH0fZPFRkWrdp5fq7hhZ2HhYokEOLkfqSMgPR4Z9EyB3DBkbKGOqZiQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0" - } - }, "node_modules/@paralleldrive/cuid2": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz", @@ -3790,50 +3016,6 @@ "url": "https://opencollective.com/pkgr" } }, - "node_modules/@prisma/instrumentation": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-6.15.0.tgz", - "integrity": "sha512-6TXaH6OmDkMOQvOxwLZ8XS51hU2v4A3vmE2pSijCIiGRJYyNeMcL6nMHQMyYdZRD8wl7LF3Wzc+AMPMV/9Oo7A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || ^0.56.0 || ^0.57.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.8" - } - }, - "node_modules/@prisma/instrumentation/node_modules/@opentelemetry/api-logs": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.57.2.tgz", - "integrity": "sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.3.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@prisma/instrumentation/node_modules/@opentelemetry/instrumentation": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.57.2.tgz", - "integrity": "sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.57.2", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, "node_modules/@react-leaflet/core": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-3.0.0.tgz", @@ -3846,9 +3028,9 @@ } }, "node_modules/@sentry-internal/node-cpu-profiler": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/node-cpu-profiler/-/node-cpu-profiler-2.2.0.tgz", - "integrity": "sha512-oLHVYurqZfADPh5hvmQYS5qx8t0UZzT2u6+/68VXsFruQEOnYJTODKgU3BVLmemRs3WE6kCJjPeFdHVYOQGSzQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/node-cpu-profiler/-/node-cpu-profiler-2.4.1.tgz", + "integrity": "sha512-Wnkik+RLvRUZEB8Zx5ofgPdcC8bCSoiUUiyH6TorrLK6PBPerbjK48c2GsJf6l5Hc5GAhA3fitueVLATB0XhWQ==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -3859,113 +3041,117 @@ "node": ">=18" } }, + "node_modules/@sentry-internal/server-utils": { + "version": "10.57.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/server-utils/-/server-utils-10.57.0.tgz", + "integrity": "sha512-Qu8ETmX/ITzteG7Im46b9HOxKKzeaIeqNvftaIlFURu1RUQdHbtGerS7QOmXzwnhuqNGNeiCQYkduB798IfRqA==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.57.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@sentry/core": { - "version": "10.19.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.19.0.tgz", - "integrity": "sha512-OqZjYDYsK6ZmBG5UzML0uKiKq//G6mMwPcszfuCsFgPt+pg5giUCrCUbt5VIVkHdN1qEEBk321JO2haU5n2Eig==", + "version": "10.57.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.57.0.tgz", + "integrity": "sha512-kntItTA2kiT0YpL7encXaF6mkdZMB+y48lwj8w1wkfBpfJAC7sifdgrzLQZqmsqVNE3crg9VfufaAGA+78uFMg==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@sentry/node": { - "version": "10.19.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.19.0.tgz", - "integrity": "sha512-GUN/UVRsqnXd4O8GCxR8F682nyYemeO4mr0Yc5JPz0CxT2gYkemuifT29bFOont8V5o055WJv32NrQnZcm/nyg==", + "version": "10.57.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.57.0.tgz", + "integrity": "sha512-7KEStrJ97wPf1fA5nU5ONeTTcIIlh7oT8OMffEVA1PXmlhFoXhcQZVzr4rM+zj9tfMWT01og5Ng/Grgh3dN+FA==", "license": "MIT", "dependencies": { - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^2.1.0", - "@opentelemetry/core": "^2.1.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/instrumentation-amqplib": "0.51.0", - "@opentelemetry/instrumentation-connect": "0.48.0", - "@opentelemetry/instrumentation-dataloader": "0.22.0", - "@opentelemetry/instrumentation-express": "0.53.0", - "@opentelemetry/instrumentation-fs": "0.24.0", - "@opentelemetry/instrumentation-generic-pool": "0.48.0", - "@opentelemetry/instrumentation-graphql": "0.52.0", - "@opentelemetry/instrumentation-hapi": "0.51.0", - "@opentelemetry/instrumentation-http": "0.204.0", - "@opentelemetry/instrumentation-ioredis": "0.52.0", - "@opentelemetry/instrumentation-kafkajs": "0.14.0", - "@opentelemetry/instrumentation-knex": "0.49.0", - "@opentelemetry/instrumentation-koa": "0.52.0", - "@opentelemetry/instrumentation-lru-memoizer": "0.49.0", - "@opentelemetry/instrumentation-mongodb": "0.57.0", - "@opentelemetry/instrumentation-mongoose": "0.51.0", - "@opentelemetry/instrumentation-mysql": "0.50.0", - "@opentelemetry/instrumentation-mysql2": "0.51.0", - "@opentelemetry/instrumentation-pg": "0.57.0", - "@opentelemetry/instrumentation-redis": "0.53.0", - "@opentelemetry/instrumentation-tedious": "0.23.0", - "@opentelemetry/instrumentation-undici": "0.15.0", - "@opentelemetry/resources": "^2.1.0", - "@opentelemetry/sdk-trace-base": "^2.1.0", - "@opentelemetry/semantic-conventions": "^1.37.0", - "@prisma/instrumentation": "6.15.0", - "@sentry/core": "10.19.0", - "@sentry/node-core": "10.19.0", - "@sentry/opentelemetry": "10.19.0", - "import-in-the-middle": "^1.14.2", - "minimatch": "^9.0.0" + "@opentelemetry/api": "^1.9.1", + "@opentelemetry/core": "^2.6.1", + "@opentelemetry/instrumentation": "^0.214.0", + "@opentelemetry/sdk-trace-base": "^2.6.1", + "@opentelemetry/semantic-conventions": "^1.40.0", + "@sentry-internal/server-utils": "10.57.0", + "@sentry/core": "10.57.0", + "@sentry/node-core": "10.57.0", + "@sentry/opentelemetry": "10.57.0", + "import-in-the-middle": "^3.0.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/node-core": { - "version": "10.19.0", - "resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.19.0.tgz", - "integrity": "sha512-m3xTaIDSh1V88K+e1zaGwKKuhDUAHMX1nncJmsGm8Hwg7FLK2fdr7wm9IJaIF0S1E4R38oHC4kZdL+ebrUghDg==", + "version": "10.57.0", + "resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.57.0.tgz", + "integrity": "sha512-2v2IF6MfTiu7pimWEq2rYhZsmlwyNbs3bHUsrYFPeP/Rpa6ObDuUWPdVEzJjfyK+AqqYZYxZdV0l3+B13kTEmQ==", "license": "MIT", "dependencies": { - "@apm-js-collab/tracing-hooks": "^0.3.1", - "@sentry/core": "10.19.0", - "@sentry/opentelemetry": "10.19.0", - "import-in-the-middle": "^1.14.2" + "@sentry/core": "10.57.0", + "@sentry/opentelemetry": "10.57.0", + "import-in-the-middle": "^3.0.0" }, "engines": { "node": ">=18" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", + "@opentelemetry/exporter-trace-otlp-http": ">=0.57.0 <1", "@opentelemetry/instrumentation": ">=0.57.1 <1", - "@opentelemetry/resources": "^1.30.1 || ^2.1.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", - "@opentelemetry/semantic-conventions": "^1.37.0" + "@opentelemetry/semantic-conventions": "^1.39.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@opentelemetry/core": { + "optional": true + }, + "@opentelemetry/exporter-trace-otlp-http": { + "optional": true + }, + "@opentelemetry/instrumentation": { + "optional": true + }, + "@opentelemetry/sdk-trace-base": { + "optional": true + }, + "@opentelemetry/semantic-conventions": { + "optional": true + } } }, "node_modules/@sentry/opentelemetry": { - "version": "10.19.0", - "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.19.0.tgz", - "integrity": "sha512-o1NWDWXM4flBIqqBECcaZ+y0TS44UxQh5BtTTPJzkU0FsWOytn9lp9ccVi7qBMb7Zrl3rw3Q0BRNETKVG5Ag/w==", + "version": "10.57.0", + "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.57.0.tgz", + "integrity": "sha512-iwRz8cEK0GOISG34aJRO8GdYOk3nfpuT6dT2GDQrxw8f7JjkJKx9LPU8MaenOFa4MhY+Z02hI6NNcrbsoI3cXg==", "license": "MIT", "dependencies": { - "@sentry/core": "10.19.0" + "@sentry/core": "10.57.0" }, "engines": { "node": ">=18" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", - "@opentelemetry/semantic-conventions": "^1.37.0" + "@opentelemetry/semantic-conventions": "^1.39.0" } }, "node_modules/@sentry/profiling-node": { - "version": "10.19.0", - "resolved": "https://registry.npmjs.org/@sentry/profiling-node/-/profiling-node-10.19.0.tgz", - "integrity": "sha512-PRFlxHLngxkJkzZkxD6deWtwzUtBo6EYPJkcPneDo/q29skQGtzVfPaWwNTldnOBBfgjtpA90hZLQoKuffxvqA==", + "version": "10.57.0", + "resolved": "https://registry.npmjs.org/@sentry/profiling-node/-/profiling-node-10.57.0.tgz", + "integrity": "sha512-0E6eWOCVOuXTFCrHxyPA0zgjypmeCJAbtgnvLFF+kmdkzeBb02KmXaJ8lre9SSjHmWAeI2jA6URJiKGOxgE0YQ==", "license": "MIT", "dependencies": { - "@sentry-internal/node-cpu-profiler": "^2.2.0", - "@sentry/core": "10.19.0", - "@sentry/node": "10.19.0" + "@sentry-internal/node-cpu-profiler": "^2.4.0", + "@sentry/core": "10.57.0", + "@sentry/node": "10.57.0" }, "bin": { "sentry-prune-profiler-binaries": "scripts/prune-profiler-binaries.js" @@ -4035,62 +3221,14 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/chunked-blob-reader": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.2.0.tgz", - "integrity": "sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/chunked-blob-reader-native": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.2.1.tgz", - "integrity": "sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-base64": "^4.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/config-resolver": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.3.0.tgz", - "integrity": "sha512-9oH+n8AVNiLPK/iK/agOsoWfrKZ3FGP3502tkksd6SRsKMYiu7AFX0YXo6YBADdsAj7C+G/aLKdsafIJHxuCkQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.3.0", - "@smithy/types": "^4.6.0", - "@smithy/util-config-provider": "^4.2.0", - "@smithy/util-middleware": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/core": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.15.0.tgz", - "integrity": "sha512-VJWncXgt+ExNn0U2+Y7UywuATtRYaodGQKFo9mDyh70q+fJGedfrqi2XuKU1BhiLeXgg6RZrW7VEKfeqFhHAJA==", + "version": "3.24.6", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.24.6.tgz", + "integrity": "sha512-wBXDRup6UU97VKyaiRo8AssnfStPtG0oAAfpq/bC0a1YYau8pM86YB4kM6ccoVi1mS8l/UHbn9oDM+7uozr/ug==", "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-serde": "^4.2.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-middleware": "^4.2.0", - "@smithy/util-stream": "^4.5.0", - "@smithy/util-utf8": "^4.2.0", - "@smithy/uuid": "^1.1.0", + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { @@ -4098,85 +3236,13 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.0.tgz", - "integrity": "sha512-SOhFVvFH4D5HJZytb0bLKxCrSnwcqPiNlrw+S4ZXjMnsC+o9JcUQzbZOEQcA8yv9wJFNhfsUiIUKiEnYL68Big==", + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.3.8.tgz", + "integrity": "sha512-5cAM+KZC02sTqDt6NaLXyu50M/GNMd1eTzDVR8Lb0BBsVtu7RWHo47VPPEEv1vt3Yub6uzr+M5FHC+GtoT0USg==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.0", - "@smithy/property-provider": "^4.2.0", - "@smithy/types": "^4.6.0", - "@smithy/url-parser": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-codec": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.0.tgz", - "integrity": "sha512-XE7CtKfyxYiNZ5vz7OvyTf1osrdbJfmUy+rbh+NLQmZumMGvY0mT0Cq1qKSfhrvLtRYzMsOBuRpi10dyI0EBPg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^4.6.0", - "@smithy/util-hex-encoding": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-browser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.0.tgz", - "integrity": "sha512-U53p7fcrk27k8irLhOwUu+UYnBqsXNLKl1XevOpsxK3y1Lndk8R7CSiZV6FN3fYFuTPuJy5pP6qa/bjDzEkRvA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/eventstream-serde-universal": "^4.2.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.0.tgz", - "integrity": "sha512-uwx54t8W2Yo9Jr3nVF5cNnkAAnMCJ8Wrm+wDlQY6rY/IrEgZS3OqagtCu/9ceIcZFQ1zVW/zbN9dxb5esuojfA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-node": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.0.tgz", - "integrity": "sha512-yjM2L6QGmWgJjVu/IgYd6hMzwm/tf4VFX0lm8/SvGbGBwc+aFl3hOzvO/e9IJ2XI+22Tx1Zg3vRpFRs04SWFcg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/eventstream-serde-universal": "^4.2.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-universal": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.0.tgz", - "integrity": "sha512-C3jxz6GeRzNyGKhU7oV656ZbuHY93mrfkT12rmjDdZch142ykjn8do+VOkeRNjSGKw01p4g+hdalPYPhmMwk1g==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/eventstream-codec": "^4.2.0", - "@smithy/types": "^4.6.0", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { @@ -4184,72 +3250,13 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.1.tgz", - "integrity": "sha512-3AvYYbB+Dv5EPLqnJIAgYw/9+WzeBiUYS8B+rU0pHq5NMQMvrZmevUROS4V2GAt0jEOn9viBzPLrZE+riTNd5Q==", + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.4.6.tgz", + "integrity": "sha512-FEwEYJ1jlBKdhe9TPzfghEi1bP55ZeEImlDkEa62bBBYzUcnB6RUCyuiS2mqKt6ZVjUbBgcNhzfIctH+Hevx9g==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.0", - "@smithy/querystring-builder": "^4.2.0", - "@smithy/types": "^4.6.0", - "@smithy/util-base64": "^4.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/hash-blob-browser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.1.tgz", - "integrity": "sha512-Os9cg1fTXMwuqbvjemELlf+HB5oEeVyZmYsTbAtDQBmjGyibjmbeeqcaw7xOJLIHrkH/u0wAYabNcN6FRTqMRg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/chunked-blob-reader": "^5.2.0", - "@smithy/chunked-blob-reader-native": "^4.2.1", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/hash-node": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.0.tgz", - "integrity": "sha512-ugv93gOhZGysTctZh9qdgng8B+xO0cj+zN0qAZ+Sgh7qTQGPOJbMdIuyP89KNfUyfAqFSNh5tMvC+h2uCpmTtA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.6.0", - "@smithy/util-buffer-from": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/hash-stream-node": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.2.0.tgz", - "integrity": "sha512-8dELAuGv+UEjtzrpMeNBZc1sJhO8GxFVV/Yh21wE35oX4lOE697+lsMHBoUIFAUuYkTMIeu0EuJSEsH7/8Y+UQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.6.0", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/invalid-dependency": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.0.tgz", - "integrity": "sha512-ZmK5X5fUPAbtvRcUPtk28aqIClVhbfcmfoS4M7UQBTnDdrNxhsrxYVv0ZEl5NaPSyExsPWqL4GsPlRvtlwg+2A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.6.0", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { @@ -4268,34 +3275,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/md5-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.0.tgz", - "integrity": "sha512-LFEPniXGKRQArFmDQ3MgArXlClFJMsXDteuQQY8WG1/zzv6gVSo96+qpkuu1oJp4MZsKrwchY0cuAoPKzEbaNA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.6.0", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-content-length": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.0.tgz", - "integrity": "sha512-6ZAnwrXFecrA4kIDOcz6aLBhU5ih2is2NdcZtobBDSdSHtE9a+MThB5uqyK4XXesdOCvOcbCm2IGB95birTSOQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/middleware-endpoint": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.1.tgz", @@ -4315,26 +3294,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/middleware-retry": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.1.tgz", - "integrity": "sha512-wXxS4ex8cJJteL0PPQmWYkNi9QKDWZIpsndr0wZI2EL+pSSvA/qqxXU60gBOJoIc2YgtZSWY/PE86qhKCCKP1w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.3.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/service-error-classification": "^4.2.0", - "@smithy/smithy-client": "^4.7.1", - "@smithy/types": "^4.6.0", - "@smithy/util-middleware": "^4.2.0", - "@smithy/util-retry": "^4.2.0", - "@smithy/uuid": "^1.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/middleware-serde": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.0.tgz", @@ -4378,15 +3337,13 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.3.0.tgz", - "integrity": "sha512-RHZ/uWCmSNZ8cneoWEVsVwMZBKy/8123hEpm57vgGXA3Irf/Ja4v9TVshHK2ML5/IqzAZn0WhINHOP9xl+Qy6Q==", + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.7.7.tgz", + "integrity": "sha512-ZAFvHXrEk6K180EVhmZVg8GU5pUH5BSFqRs27JW3j1qEFx9YyYwWFx17x/MHcjALYimGAji7qEOlF1++be+G5A==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.2.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/querystring-builder": "^4.2.0", - "@smithy/types": "^4.6.0", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { @@ -4419,20 +3376,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/querystring-builder": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.0.tgz", - "integrity": "sha512-Q4oFD0ZmI8yJkiPPeGUITZj++4HHYCW3pYBYfIobUCkYpI6mbkzmG1MAQQ3lJYYWj3iNqfzOenUZu+jqdPQ16A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.6.0", - "@smithy/util-uri-escape": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/querystring-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.0.tgz", @@ -4446,18 +3389,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/service-error-classification": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.0.tgz", - "integrity": "sha512-Ylv1ttUeKatpR0wEOMnHf1hXMktPUMObDClSWl2TpCVT4DwtJhCeighLzSLbgH3jr5pBNM0LDXT5yYxUvZ9WpA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.6.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/shared-ini-file-loader": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.3.0.tgz", @@ -4472,18 +3403,13 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.0.tgz", - "integrity": "sha512-MKNyhXEs99xAZaFhm88h+3/V+tCRDQ+PrDzRqL0xdDpq4gjxcMmf5rBA3YXgqZqMZ/XwemZEurCBQMfxZOWq/g==", + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.4.6.tgz", + "integrity": "sha512-Ojg4B6oIDlIr1R86xCDJt1zJWnYa0VINmqdjfe9qxWjdRivHalZ3iSlQgVqYbW0MdpFOC5XfHEWsnbmdnpIILQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/is-array-buffer": "^4.2.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", - "@smithy/util-hex-encoding": "^4.2.0", - "@smithy/util-middleware": "^4.2.0", - "@smithy/util-uri-escape": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", "tslib": "^2.6.2" }, "engines": { @@ -4509,9 +3435,9 @@ } }, "node_modules/@smithy/types": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.6.0.tgz", - "integrity": "sha512-4lI9C8NzRPOv66FaY1LL1O/0v0aLVrq/mXP/keUa9mJOApEeae43LsLd2kZRUJw91gxOQfLIrV3OvqPgWz1YsA==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.14.3.tgz", + "integrity": "sha512-YupL0ZWmFtJexUN2cHzkvvF/b9pKrtAIfT1o7/oY/Ppu8IYeZ+lDPM5vZdQJaSeA132dJCqojjGC9NhXeF71VQ==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -4548,30 +3474,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/util-body-length-browser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.0.tgz", - "integrity": "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-body-length-node": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz", - "integrity": "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/util-buffer-from": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.0.tgz", @@ -4585,65 +3487,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/util-config-provider": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.0.tgz", - "integrity": "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.0.tgz", - "integrity": "sha512-H4MAj8j8Yp19Mr7vVtGgi7noJjvjJbsKQJkvNnLlrIFduRFT5jq5Eri1k838YW7rN2g5FTnXpz5ktKVr1KVgPQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.2.0", - "@smithy/smithy-client": "^4.7.1", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.1.tgz", - "integrity": "sha512-PuDcgx7/qKEMzV1QFHJ7E4/MMeEjaA7+zS5UNcHCLPvvn59AeZQ0DSDGMpqC2xecfa/1cNGm4l8Ec/VxCuY7Ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/config-resolver": "^4.3.0", - "@smithy/credential-provider-imds": "^4.2.0", - "@smithy/node-config-provider": "^4.3.0", - "@smithy/property-provider": "^4.2.0", - "@smithy/smithy-client": "^4.7.1", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-endpoints": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.0.tgz", - "integrity": "sha512-TXeCn22D56vvWr/5xPqALc9oO+LN+QpFjrSM7peG/ckqEPoI3zaKZFp+bFwfmiHhn5MGWPaLCqDOJPPIixk9Wg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.3.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/util-hex-encoding": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.0.tgz", @@ -4669,20 +3512,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/util-retry": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.0.tgz", - "integrity": "sha512-BWSiuGbwRnEE2SFfaAZEX0TqaxtvtSYPM/J73PFVm+A29Fg1HTPiYFb8TmX1DXp4hgcdyJcNQmprfd5foeORsg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/service-error-classification": "^4.2.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/util-stream": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.0.tgz", @@ -4702,18 +3531,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/util-uri-escape": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz", - "integrity": "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/util-utf8": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", @@ -4727,32 +3544,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/util-waiter": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.0.tgz", - "integrity": "sha512-0Z+nxUU4/4T+SL8BCNN4ztKdQjToNvUYmkF1kXO5T7Yz3Gafzh0HeIG6mrkN8Fz3gn9hSyxuAT+6h4vM+iQSBQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/abort-controller": "^4.2.0", - "@smithy/types": "^4.6.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/uuid": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.0.tgz", - "integrity": "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", @@ -4907,11 +3698,22 @@ "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/cookie-parser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.10.tgz", + "integrity": "sha512-B4xqkqfZ8Wek+rCOeRxsjMS9OgvzebEzzLYw7NHYuvzb7IdxOkI0ZHGgeEBX4PUM7QGVvNSK60T3OvWj3YfBRg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/express": "*" + } + }, "node_modules/@types/cookiejar": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", @@ -5119,15 +3921,6 @@ "@types/express": "*" } }, - "node_modules/@types/mysql": { - "version": "2.15.27", - "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.27.tgz", - "integrity": "sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/node": { "version": "20.19.19", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.19.tgz", @@ -5232,26 +4025,6 @@ "@types/node": "*" } }, - "node_modules/@types/pg": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.5.tgz", - "integrity": "sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^2.2.0" - } - }, - "node_modules/@types/pg-pool": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", - "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", - "license": "MIT", - "dependencies": { - "@types/pg": "*" - } - }, "node_modules/@types/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", @@ -5299,12 +4072,6 @@ "@types/node": "*" } }, - "node_modules/@types/shimmer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", - "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", - "license": "MIT" - }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -5336,15 +4103,6 @@ "@types/superagent": "^8.1.0" } }, - "node_modules/@types/tedious": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", - "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", @@ -5358,6 +4116,15 @@ "integrity": "sha512-7bcUmDyS6PN3EuD9SlGGOxM77F8WLVsrwkxyWxKnxzmXoequ6c7741QBrANq6htVRGOITJ7z72mTP6Z4XyuG+Q==", "license": "MIT" }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -5750,6 +4517,15 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -5782,9 +4558,9 @@ } }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -5839,6 +4615,18 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/ajv": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", @@ -5972,9 +4760,9 @@ } }, "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -5983,6 +4771,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/anynum": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.0.tgz", + "integrity": "sha512-xjR9/zBVnUOP6ztMIIgShjsxui80nQUQH+5xJnvrYLs+90bF25/KJqaAi8mk+B4RDtX1Nspi6fmp4YTEts8SfA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/app-root-path": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", @@ -6038,9 +4838,9 @@ } }, "node_modules/archiver-utils/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -6075,9 +4875,9 @@ "license": "MIT" }, "node_modules/archiver-utils/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -6221,14 +5021,15 @@ } }, "node_modules/axios": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.17.0.tgz", + "integrity": "sha512-J8SwNxprqqpbfenehxWYXE7CW+wM1BB4w3+N+g+/Wx40xM4rsLrfPmHHxSWIxJLYDgSY/HqlFPIYb2/S3rxafw==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" } }, "node_modules/babel-jest": { @@ -6402,13 +5203,16 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.13.tgz", - "integrity": "sha512-7s16KR8io8nIBWQyCYhmFhd+ebIzb9VKTzki+wOJXHTxTnV6+mFGH3+Jwn1zoKaY9/H9T/0BcKCZnzXljPnpSQ==", + "version": "2.10.36", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.36.tgz", + "integrity": "sha512-lVq/Df7LXlO79MVaaUHztSwWiG9oXoWHlgvNS51v8Dpd4+G4/VIy6qYePTw31nAVls33nUtnfezYeLkYAak9dg==", "dev": true, "license": "Apache-2.0", "bin": { - "baseline-browser-mapping": "dist/cli.js" + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/big-integer": { @@ -6463,23 +5267,23 @@ "license": "MIT" }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "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", + "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.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "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" + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8", @@ -6514,9 +5318,9 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -6544,9 +5348,9 @@ } }, "node_modules/browserslist": { - "version": "4.26.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", - "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", "dev": true, "funding": [ { @@ -6564,11 +5368,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.8.9", - "caniuse-lite": "^1.0.30001746", - "electron-to-chromium": "^1.5.227", - "node-releases": "^2.0.21", - "update-browserslist-db": "^1.1.3" + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" @@ -6760,9 +5564,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001748", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001748.tgz", - "integrity": "sha512-5P5UgAr0+aBmNiplks08JLw+AW/XG/SurlgZLgB1dDLfAw7EfRGxIwzPHxdSCGY/BTKDqIVyJL87cCN6s0ZR0w==", + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", "dev": true, "funding": [ { @@ -6917,6 +5721,7 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, "license": "MIT" }, "node_modules/class-transformer": { @@ -7293,6 +6098,28 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/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.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -7650,9 +6477,9 @@ "license": "MIT" }, "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "devOptional": true, "license": "BSD-3-Clause", "engines": { @@ -7846,14 +6673,14 @@ } }, "node_modules/editorconfig": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", - "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.7.tgz", + "integrity": "sha512-e0GOtq/aTQhVdNyDU9e02+wz9oDDM+SIOQxWME2QRjzRX5yyLAuHDE+0aE8vHb9XRC8XD37eO2u57+F09JqFhw==", "license": "MIT", "dependencies": { "@one-ini/wasm": "0.1.1", "commander": "^10.0.0", - "minimatch": "9.0.1", + "minimatch": "^9.0.1", "semver": "^7.5.3" }, "bin": { @@ -7872,21 +6699,6 @@ "node": ">=14" } }, - "node_modules/editorconfig/node_modules/minimatch": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -7894,9 +6706,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.232", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.232.tgz", - "integrity": "sha512-ENirSe7wf8WzyPCibqKUG1Cg43cPaxH4wRR7AJsX7MCABCHBIOFqvaYODSLKUuZdraxUTHRE/0A2Aq8BYKEHOg==", + "version": "1.5.371", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.371.tgz", + "integrity": "sha512-e9htk9mAYL6AzmkEhSvVVw7IWGSBJ/Bqdn2eRyRLrj1g6sncN4WbFt5qnILYoCktktr45pyjIrOiRvBThQ808w==", "dev": true, "license": "ISC" }, @@ -7938,20 +6750,21 @@ } }, "node_modules/engine.io": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", - "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", + "version": "6.6.8", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.8.tgz", + "integrity": "sha512-2agL3ueZhqxoVrfmntO8yuVj+uNSlIOnhykYHk3Cq0ShYPdUjjUiSJrQvXjq01I9jAuI0Zl2YO8Evv5Mqytm5g==", "license": "MIT", "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", + "@types/ws": "^8.5.12", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.7.2", "cors": "~2.8.5", - "debug": "~4.3.1", + "debug": "~4.4.1", "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" + "ws": "~8.20.1" }, "engines": { "node": ">=10.2.0" @@ -7975,32 +6788,15 @@ "node": ">= 0.6" } }, - "node_modules/engine.io/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/enhanced-resolve": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", - "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.0.tgz", + "integrity": "sha512-SkE2t82KlkkxQRVMVLAGKxLfORGQfrkx5dkj+vlgXRVNEdPc4eZcR+J/Fvj8C+yKSFH5L0q3NFlyufOVQnCcYQ==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.3" }, "engines": { "node": ">=10.13.0" @@ -8268,9 +7064,9 @@ } }, "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -8285,9 +7081,9 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -8316,9 +7112,9 @@ "license": "MIT" }, "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -8454,9 +7250,9 @@ } }, "node_modules/exceljs/node_modules/tmp": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", "license": "MIT", "engines": { "node": ">=14.14" @@ -8529,39 +7325,39 @@ } }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "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", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", + "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", + "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", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", + "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.13.0", + "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", + "send": "~0.19.0", + "serve-static": "~1.16.2", "setprototypeof": "1.2.0", - "statuses": "2.0.1", + "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -8590,9 +7386,9 @@ "license": "MIT" }, "node_modules/express/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==", + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "license": "MIT" }, "node_modules/external-editor": { @@ -8688,10 +7484,10 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "license": "MIT" }, - "node_modules/fast-xml-parser": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", - "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", + "node_modules/fast-xml-builder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz", + "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==", "funding": [ { "type": "github", @@ -8700,7 +7496,26 @@ ], "license": "MIT", "dependencies": { - "strnum": "^2.1.0" + "path-expression-matcher": "^1.5.0", + "xml-naming": "^0.1.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.7.3.tgz", + "integrity": "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "@nodable/entities": "^2.1.0", + "fast-xml-builder": "^1.1.7", + "path-expression-matcher": "^1.5.0", + "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" @@ -8727,15 +7542,15 @@ } }, "node_modules/fengari": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/fengari/-/fengari-0.1.4.tgz", - "integrity": "sha512-6ujqUuiIYmcgkGz8MGAdERU57EIluGGPSUgGPTsco657EHa+srq0S3/YUl/r9kx1+D+d4rGfYObd+m8K22gB1g==", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/fengari/-/fengari-0.1.5.tgz", + "integrity": "sha512-0DS4Nn4rV8qyFlQCpKK8brT61EUtswynrpfFTcgLErcilBIBskSMQ86fO2WVuybr14ywyKdRjv91FiRZwnEuvQ==", "dev": true, "license": "MIT", "dependencies": { - "readline-sync": "^1.4.9", - "sprintf-js": "^1.1.1", - "tmp": "^0.0.33" + "readline-sync": "^1.4.10", + "sprintf-js": "^1.1.3", + "tmp": "^0.2.5" } }, "node_modules/fengari-interop": { @@ -8755,6 +7570,16 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/fengari/node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, "node_modules/fflate": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", @@ -8831,17 +7656,17 @@ } }, "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "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", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "statuses": "2.0.1", + "statuses": "~2.0.2", "unpipe": "~1.0.0" }, "engines": { @@ -8896,16 +7721,16 @@ } }, "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", @@ -9009,9 +7834,9 @@ } }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -9020,9 +7845,9 @@ } }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -9033,9 +7858,9 @@ } }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -9073,12 +7898,6 @@ "node": ">= 0.6" } }, - "node_modules/forwarded-parse": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", - "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", - "license": "MIT" - }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -9153,9 +7972,9 @@ } }, "node_modules/fstream/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -9184,9 +8003,9 @@ } }, "node_modules/fstream/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -9411,9 +8230,9 @@ "license": "MIT" }, "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", "license": "MIT", "dependencies": { "minimist": "^1.2.5", @@ -9588,19 +8407,36 @@ } }, "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" } }, "node_modules/human-signals": { @@ -9679,17 +8515,26 @@ } }, "node_modules/import-in-the-middle": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", - "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-3.0.2.tgz", + "integrity": "sha512-LGLYRl0A2gtyUJb2WDliBHmk6TtlHwdDjxonacZ8QrEs/ZW+YDgNv2QAfjRQWpS8HqvNcq6GGnN6jrOa5FysDQ==", "license": "Apache-2.0", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", - "cjs-module-lexer": "^1.2.2", - "module-details-from-path": "^1.0.3" + "cjs-module-lexer": "^2.2.0", + "module-details-from-path": "^1.0.4" + }, + "engines": { + "node": ">=18" } }, + "node_modules/import-in-the-middle/node_modules/cjs-module-lexer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", + "license": "MIT" + }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", @@ -9859,6 +8704,7 @@ "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -10268,9 +9114,9 @@ } }, "node_modules/jest-config/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -10301,9 +9147,9 @@ } }, "node_modules/jest-config/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -10631,9 +9477,9 @@ } }, "node_modules/jest-runtime/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -10664,9 +9510,9 @@ } }, "node_modules/jest-runtime/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -10727,9 +9573,9 @@ } }, "node_modules/jest-util/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -10871,38 +9717,11 @@ "node": ">=14" } }, - "node_modules/js-beautify/node_modules/abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/js-beautify/node_modules/nopt": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", - "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", - "license": "ISC", - "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/js-cookie": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", - "license": "MIT", - "engines": { - "node": ">=14" - } + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.8.tgz", + "integrity": "sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw==", + "license": "MIT" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -11113,12 +9932,12 @@ } }, "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz", + "integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==", "license": "MIT", "dependencies": { - "jwa": "^1.4.1", + "jwa": "^1.4.2", "safe-buffer": "^5.0.1" } }, @@ -11268,13 +10087,17 @@ "license": "ISC" }, "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", "dev": true, "license": "MIT", "engines": { "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/locate-path": { @@ -11578,9 +10401,9 @@ } }, "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -11634,12 +10457,12 @@ } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -11667,70 +10490,70 @@ } }, "node_modules/mjml": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml/-/mjml-4.16.1.tgz", - "integrity": "sha512-urrG5JD4vmYNT6kdNHwxeCuiPPR0VFonz4slYQhCBXWS8/KsYxkY2wnYA+vfOLq91aQnMvJzVcUK+ye9z7b51w==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml/-/mjml-4.18.0.tgz", + "integrity": "sha512-rQM4aqFRrNvV1k733e8hJSopBjZvoSdBpRYzNTMAN+As0jqJsO5eN0wTT2IFtfe4PREzzu5b06RkPiUQdd0IIg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", - "mjml-cli": "4.16.1", - "mjml-core": "4.16.1", - "mjml-migrate": "4.16.1", - "mjml-preset-core": "4.16.1", - "mjml-validator": "4.16.1" + "mjml-cli": "4.18.0", + "mjml-core": "4.18.0", + "mjml-migrate": "4.18.0", + "mjml-preset-core": "4.18.0", + "mjml-validator": "4.18.0" }, "bin": { "mjml": "bin/mjml" } }, "node_modules/mjml-accordion": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-accordion/-/mjml-accordion-4.16.1.tgz", - "integrity": "sha512-WqBaDmov7uI15dDVZ5UK6ngNwVhhXawW+xlCVbjs21wmskoG4lXc1j+28trODqGELk3BcQOqjO8Ee6Ytijp4PA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-accordion/-/mjml-accordion-4.18.0.tgz", + "integrity": "sha512-9PUmy2JxIOGgAaVHvgVYX21nVAo3o/+wJckTTF/YTLGAqB+nm+44buxRzaXxVk7qXRwbCNfE8c8mlGVNh7vB1g==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-body": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-body/-/mjml-body-4.16.1.tgz", - "integrity": "sha512-A19pJ2HXqc7A5pKc8Il/d1cH5yyO2Jltwit3eUKDrZ/fBfYxVWZVPNuMooqt6QyC26i+xhhVbVsRNTwL1Aclqg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-body/-/mjml-body-4.18.0.tgz", + "integrity": "sha512-34AwX70/7NkRIajPsa5j6NySRiNrlLatTKhiLwTVFiVtrEFlfCcbeMNmdVixI3Ldvs8209ZC6euaAnXDRyR1zw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-button": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-button/-/mjml-button-4.16.1.tgz", - "integrity": "sha512-z2YsSEDHU4ubPMLAJhgopq3lnftjRXURmG8A+K/QIH4Js6xHIuSNzCgVbBl13/rB1hwc2RxUP839JoLt3M1FRg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-button/-/mjml-button-4.18.0.tgz", + "integrity": "sha512-ZsWMI0j7EcFCMqbqdVwMWhmsVc03FhmypWXokKopGhwySn4IAB4AOURonRmFrO7k6sDeQ+iJ9QtTu7jA+S8wmg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-carousel": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-carousel/-/mjml-carousel-4.16.1.tgz", - "integrity": "sha512-Xna+lSHJGMiPxDG3kvcK3OfEDQbkgyXEz0XebN7zpLDs1Mo4IXe8qI7fFnDASckwC14gmdPwh/YcLlQ4nkzwrQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-carousel/-/mjml-carousel-4.18.0.tgz", + "integrity": "sha512-wY4g1CHCOoVSZuar7CLFon/qkPbICu71IT+6pa4BDwkAiaAMAemZPyy+a+iIUgdc8kHgSuHGsGf6PQzBSMWRZA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-cli": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-cli/-/mjml-cli-4.16.1.tgz", - "integrity": "sha512-1dTGWOKucdNImjLzDZfz1+aWjjZW4nRW5pNUMOdcIhgGpygYGj1X4/R8uhrC61CGQXusUrHyojQNVks/aBm9hQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-cli/-/mjml-cli-4.18.0.tgz", + "integrity": "sha512-N6CnA4o/q/VRnGPxTzvVnjAEcF7WUVVQGYfS9SPAp0qwyf7RysMmewdS9yN8GwXwZV6L2sKdn+3ANNi2FNsJ7w==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", @@ -11740,10 +10563,10 @@ "js-beautify": "^1.6.14", "lodash": "^4.17.21", "minimatch": "^9.0.3", - "mjml-core": "4.16.1", - "mjml-migrate": "4.16.1", - "mjml-parser-xml": "4.16.1", - "mjml-validator": "4.16.1", + "mjml-core": "4.18.0", + "mjml-migrate": "4.18.0", + "mjml-parser-xml": "4.18.0", + "mjml-validator": "4.18.0", "yargs": "^17.7.2" }, "bin": { @@ -11751,20 +10574,20 @@ } }, "node_modules/mjml-column": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-column/-/mjml-column-4.16.1.tgz", - "integrity": "sha512-olScfxGEC0hp3VGzJUn7/znu7g9QlU1PsVRNL7yGKIUiZM/foysYimErBq2CfkF+VkEA9ZlMMeRLGNFEW7H3qQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-column/-/mjml-column-4.18.0.tgz", + "integrity": "sha512-0QZ1whxbHUmJaRT8tW+wmr3fWZ/kpsHKAd24c7Z/N1Otm/U2G0T/FFEFJ6cB25X6ZN0K40QZ8L9gdLfiSVuRbA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-core": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-core/-/mjml-core-4.16.1.tgz", - "integrity": "sha512-sT7VbcUyd3m68tyZvK/cYbZIn7J3E4A+AFtAxI2bxj4Mz8QPjpz6BUGXkRJcYYxvNYVA+2rBFCFRXe5ErsVMVg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-core/-/mjml-core-4.18.0.tgz", + "integrity": "sha512-yey72LszXvIo5p0R6DB+YU8er/nP2wPsqpLKQCB0H8vG0WRT1sbSUvnCUOkKGn7subuyWDTdzHKbQO3XYIOmvg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", @@ -11774,154 +10597,154 @@ "js-beautify": "^1.6.14", "juice": "^10.0.0", "lodash": "^4.17.21", - "mjml-migrate": "4.16.1", - "mjml-parser-xml": "4.16.1", - "mjml-validator": "4.16.1" + "mjml-migrate": "4.18.0", + "mjml-parser-xml": "4.18.0", + "mjml-validator": "4.18.0" } }, "node_modules/mjml-divider": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-divider/-/mjml-divider-4.16.1.tgz", - "integrity": "sha512-KNqk0V3VRXU0f3yoziFUl1TboeRJakm+7B7NmGRUj13AJrEkUela2Y4/u0wPk8GMC8Qd25JTEdbVHlImfyNIQQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-divider/-/mjml-divider-4.18.0.tgz", + "integrity": "sha512-FmGUVJqi4RYroh7y85vDx0aUKZgECkxHtMQ4pkLGQbZ2g93/Qt0Ek88DVCNJ5XwUAQQkE/TvrGMLHp3CIqpQ9Q==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-group": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-group/-/mjml-group-4.16.1.tgz", - "integrity": "sha512-pjNEpS9iTh0LGeYZXhfhI27pwFFTAiqx+5Q420P4ebLbeT5Vsmr8TrcaB/gEPNn/eLrhzH/IssvnFOh5Zlmrlg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-group/-/mjml-group-4.18.0.tgz", + "integrity": "sha512-28ABkXsKljBqj7XCC8GkQ94xz8HEU2XTyD+9LTlkDafzGp/MGJb8DcLh/7IkxCwqkQWyeMiDNLf1djsQ909Vxw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-head": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-head/-/mjml-head-4.16.1.tgz", - "integrity": "sha512-R/YA6wxnUZHknJ2H7TT6G6aXgNY7B3bZrAbJQ4I1rV/l0zXL9kfjz2EpkPfT0KHzS1cS2J1pK/5cn9/KHvHA2Q==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-head/-/mjml-head-4.18.0.tgz", + "integrity": "sha512-DS0adpIAsVMDIk2DOsHzjg+RNjQU0fF8jiVP9BmdRHVGrLPmpL9wIHZk2KvsKvZe7VaXXBijFt3DZ5/CQ/+D7Q==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-head-attributes": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-head-attributes/-/mjml-head-attributes-4.16.1.tgz", - "integrity": "sha512-JHFpSlQLJomQwKrdptXTdAfpo3u3bSezM/4JfkCi53MBmxNozWzQ/b8lX3fnsTSf9oywkEEGZD44M2emnTWHug==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-head-attributes/-/mjml-head-attributes-4.18.0.tgz", + "integrity": "sha512-nLzix1wrMnojE0RPGhk4iKqSRwHKjie2EPzgKT7CDzfqN+Ref03E5Q19x3cQTLgxvq3C3CnvCQBfnhoS3Eakug==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-head-breakpoint": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-head-breakpoint/-/mjml-head-breakpoint-4.16.1.tgz", - "integrity": "sha512-b4C/bZCMV1k/br2Dmqfp/mhYPkcZpBQdMpAOAaI8na7HmdS4rE/seJUfeCUr7fy/7BvbmsN2iAAttP54C4bn/A==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-head-breakpoint/-/mjml-head-breakpoint-4.18.0.tgz", + "integrity": "sha512-k6rwff+7i+vTQYJ/CjBfE20qNqPaW60IRH2x2oEPuCzmwDmoVWOcplJIuotSqIAdfwF9hLkICknisp1BpczVlQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-head-font": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-head-font/-/mjml-head-font-4.16.1.tgz", - "integrity": "sha512-Bw3s5HSeWX3wVq4EJnBS8OOgw/RP4zO0pbidv7T+VqKunUEuUwCEaLZyuTyhBqJ61QiPOehBBGBDGwYyVaJGVg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-head-font/-/mjml-head-font-4.18.0.tgz", + "integrity": "sha512-ao8HB5nf+Dmxw4GO6lMMOlnj1lNZONai0GC9RobrZgPlghZw6hpURWGpkON7pQcy6XnOHwYwkV7Go/npzA2i7w==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-head-html-attributes": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-head-html-attributes/-/mjml-head-html-attributes-4.16.1.tgz", - "integrity": "sha512-GtT0vb6rb/dyrdPzlMQTtMjCwUyXINAHcUR+IGi1NTx8xoHWUjmWPQ/v95IhgelsuQgynuLWVPundfsPn8/PTQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-head-html-attributes/-/mjml-head-html-attributes-4.18.0.tgz", + "integrity": "sha512-xaQE1rthe0RrNotwEr71X1tE+QQ489Yc0ynMm3oNMrohDI/TaCeazx8GAHPMM7VLduDA8D4A5wkZ6PuEvlJu4w==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-head-preview": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-head-preview/-/mjml-head-preview-4.16.1.tgz", - "integrity": "sha512-5iDM5ZO0JWgucIFJG202kGKVQQWpn1bOrySIIp2fQn1hCXQaefAPYduxu7xDRtnHeSAw623IxxKzZutOB8PMSg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-head-preview/-/mjml-head-preview-4.18.0.tgz", + "integrity": "sha512-2JvYqhbLyU/+Te6/1AXxzTNoHYCDYhXOVZP7wMvU4t7K34pXqyRUNO405atyHUY1MRafrl6RJ8cIx0x5vUX7PA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-head-style": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-head-style/-/mjml-head-style-4.16.1.tgz", - "integrity": "sha512-P6NnbG3+y1Ow457jTifI9FIrpkVSxEHTkcnDXRtq3fA5UR7BZf3dkrWQvsXelm6DYCSGUY0eVuynPPOj71zetQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-head-style/-/mjml-head-style-4.18.0.tgz", + "integrity": "sha512-nEwDHkAqY3Fm7QWeAZc/a7MakZpXh6THfrE8/AWrfpgzTHrD/wihNUc09ztNpr6z/K1+JWgQfSF2BRc+X3P46g==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-head-title": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-head-title/-/mjml-head-title-4.16.1.tgz", - "integrity": "sha512-s7X9XkIu46xKXvjlZBGkpfsTcgVqpiQjAm0OrHRV9E5TLaICoojmNqEz5CTvvlTz7olGoskI1gzJlnhKxPmkXQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-head-title/-/mjml-head-title-4.18.0.tgz", + "integrity": "sha512-0Hm8o50rPMUQLSCOOa4D4pz9NajmCDccLvBYE4fwKdeUXjSJ6bwAYeMpveel8oNZMDUVJ4Hx+PskisEGHMHM2w==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-hero": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-hero/-/mjml-hero-4.16.1.tgz", - "integrity": "sha512-1q6hsG7l2hgdJeNjSNXVPkvvSvX5eJR5cBvIkSbIWqT297B1WIxwcT65Nvfr1FpkEALeswT4GZPSfvTuXyN8hg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-hero/-/mjml-hero-4.18.0.tgz", + "integrity": "sha512-rujm0ROM4QGWw77vnl3NaVaCKXrT4xTSHeAnkHKiY5AuRf6HPTgEtutq5pdel/y6Q9GrmxvN3HRESum7tpJCJw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-image": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-image/-/mjml-image-4.16.1.tgz", - "integrity": "sha512-snTULRoskjMNPxajSFIp4qA/EjZ56N0VXsAfDQ9ZTXZs0Mo3vy2N81JDGNVRmKkAJyPEwN77zrAHbic0Ludm1w==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-image/-/mjml-image-4.18.0.tgz", + "integrity": "sha512-e09NkoYwvzMcTv7V6H5doWD6Te2E1y2EvOLQJoXKVdQpDwyBWGdfnZke0scJGdA58HLAB+0mLYogpLwmfLaP5Q==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-migrate": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-migrate/-/mjml-migrate-4.16.1.tgz", - "integrity": "sha512-4SuaFWyu1Hg948ODHz1gF5oXrhgRI1LgtWMRE+Aoz4F6SSA7kL78iJqEVvouOHCpcxQStDdiZo8/KeuQ1llEAw==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-migrate/-/mjml-migrate-4.18.0.tgz", + "integrity": "sha512-qfNCgW9zhJIsbPyXFA5RT/WY4mlje3N0WhHHOsHc0nY89Q01DenyslUy9nLLGXwi4K5FHS58oCjwWbMhwDcj1w==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "js-beautify": "^1.6.14", "lodash": "^4.17.21", - "mjml-core": "4.16.1", - "mjml-parser-xml": "4.16.1", + "mjml-core": "4.18.0", + "mjml-parser-xml": "4.18.0", "yargs": "^17.7.2" }, "bin": { @@ -11929,20 +10752,20 @@ } }, "node_modules/mjml-navbar": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-navbar/-/mjml-navbar-4.16.1.tgz", - "integrity": "sha512-lLlTOU3pVvlnmIJ/oHbyuyV8YZ99mnpRvX+1ieIInFElOchEBLoq1Mj+RRfaf2EV/q3MCHPyYUZbDITKtqdMVg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-navbar/-/mjml-navbar-4.18.0.tgz", + "integrity": "sha512-uho/MS2tfNAe+V9u2X7NoCco34MDbdp30ETA8009Qo1VCP/D8lZ+s69WGRPu6hvN/Y2pzBgZly++CMg3qFZqBQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-parser-xml": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-parser-xml/-/mjml-parser-xml-4.16.1.tgz", - "integrity": "sha512-QsHnPgVGgzcLX82wn1uP53X9pIUP3H6bJMad9R1v2F1A9rhaKK+wctxvXWBp4+XXJOv3SqpE5GDBEQPWNs5IgQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-parser-xml/-/mjml-parser-xml-4.18.0.tgz", + "integrity": "sha512-sHSsZg4afY1heThuJzxa1Kvfh/QzB7/9P5fFUHeVnnxb07ZTXnhXWA6YbobdND5/l9+5yjN5/UgqDZm3tIT4Uw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", @@ -11971,124 +10794,124 @@ } }, "node_modules/mjml-preset-core": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-preset-core/-/mjml-preset-core-4.16.1.tgz", - "integrity": "sha512-D7ogih4k31xCvj2u5cATF8r6Z1yTbjMnR+rs19fZ35gXYhl0B8g4cARwXVCu0WcU4vs/3adInAZ8c54NL5ruWA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-preset-core/-/mjml-preset-core-4.18.0.tgz", + "integrity": "sha512-x3l8vMVtsaqM/jauMeZIN7HFD2t5A28J4U0o4849yIlRxiWguLFV5l3BL8Byol+YLkoLuT9PjaZs9RYv+FGfeg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", - "mjml-accordion": "4.16.1", - "mjml-body": "4.16.1", - "mjml-button": "4.16.1", - "mjml-carousel": "4.16.1", - "mjml-column": "4.16.1", - "mjml-divider": "4.16.1", - "mjml-group": "4.16.1", - "mjml-head": "4.16.1", - "mjml-head-attributes": "4.16.1", - "mjml-head-breakpoint": "4.16.1", - "mjml-head-font": "4.16.1", - "mjml-head-html-attributes": "4.16.1", - "mjml-head-preview": "4.16.1", - "mjml-head-style": "4.16.1", - "mjml-head-title": "4.16.1", - "mjml-hero": "4.16.1", - "mjml-image": "4.16.1", - "mjml-navbar": "4.16.1", - "mjml-raw": "4.16.1", - "mjml-section": "4.16.1", - "mjml-social": "4.16.1", - "mjml-spacer": "4.16.1", - "mjml-table": "4.16.1", - "mjml-text": "4.16.1", - "mjml-wrapper": "4.16.1" + "mjml-accordion": "4.18.0", + "mjml-body": "4.18.0", + "mjml-button": "4.18.0", + "mjml-carousel": "4.18.0", + "mjml-column": "4.18.0", + "mjml-divider": "4.18.0", + "mjml-group": "4.18.0", + "mjml-head": "4.18.0", + "mjml-head-attributes": "4.18.0", + "mjml-head-breakpoint": "4.18.0", + "mjml-head-font": "4.18.0", + "mjml-head-html-attributes": "4.18.0", + "mjml-head-preview": "4.18.0", + "mjml-head-style": "4.18.0", + "mjml-head-title": "4.18.0", + "mjml-hero": "4.18.0", + "mjml-image": "4.18.0", + "mjml-navbar": "4.18.0", + "mjml-raw": "4.18.0", + "mjml-section": "4.18.0", + "mjml-social": "4.18.0", + "mjml-spacer": "4.18.0", + "mjml-table": "4.18.0", + "mjml-text": "4.18.0", + "mjml-wrapper": "4.18.0" } }, "node_modules/mjml-raw": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-raw/-/mjml-raw-4.16.1.tgz", - "integrity": "sha512-xQrosP9iNNCrfMnYjJzlzV6fzAysRuv3xuB/JuTuIbS74odvGItxXNnYLUEvwGnslO4ij2J4Era62ExEC3ObNQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-raw/-/mjml-raw-4.18.0.tgz", + "integrity": "sha512-F/kViAwXm3ccPP52kw++/mHQbcYbYYxC8JH15TZxH8GLVZkX5CGKgcBrHhDK7WoIlfEIsVRZ6IZdlHjH8vgyxw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-section": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-section/-/mjml-section-4.16.1.tgz", - "integrity": "sha512-VxKc+7wEWRsAny9mT464LaaYklz20OUIRDH8XV88LK+8JSd05vcbnEI0eneye6Hly0NIwHARbOI6ssLtNPojIQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-section/-/mjml-section-4.18.0.tgz", + "integrity": "sha512-bB8My9zvIEkTOxej+TrjEeaeRT0lsypGeRADtdrRZXeqUClkkuCnCXlsNKSLGT8ZRqjUqWRc5z8ubDOvGk2+Gg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-social": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-social/-/mjml-social-4.16.1.tgz", - "integrity": "sha512-u7k+s7LEY5vB0huJL1aEnkwfJmLX8mln4PDNciO+71/pbi7VRuLuUWqnxHbg7HPP130vJp0tqOrpyIIbxmHlHA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-social/-/mjml-social-4.18.0.tgz", + "integrity": "sha512-iAQc9g59L6L3VHDd55BxeIvk/zHkxflxmvuyYyOOvpmmKAvUBC//ULfpxiiM4yupofsThqFfrO+wc8d4kTRkbQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-spacer": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-spacer/-/mjml-spacer-4.16.1.tgz", - "integrity": "sha512-HZ9S2Ap3WUf5gYEzs16D8J7wxRG82ReLXd7dM8CSXcfIiqbTUYuApakNlk2cMDOskK9Od1axy8aAirDa7hzv4Q==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-spacer/-/mjml-spacer-4.18.0.tgz", + "integrity": "sha512-FK/0f5IBiONgaRpwNBs7G8EbLdAbmYqcIfHR8O8tP4LipAChLQKHO9vX3vrRMGLBZZNTESLObcFSVWmA40Mfpw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-table": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-table/-/mjml-table-4.16.1.tgz", - "integrity": "sha512-JCG/9JFYkx93cSNgxbPBb7KXQjJTa0roEDlKqPC6MkQ3XIy1zCS/jOdZCfhlB2Y9T/9l2AuVBheyK7f7Oftfeg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-table/-/mjml-table-4.18.0.tgz", + "integrity": "sha512-vJysCPUL3CHcsQDAFpW+skzBtY0RYsmMBYswI4WX0B05GLKlOjXqpYOwcmAupWeGoBVL5r/t28ynu2PqnOlN3w==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-text": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-text/-/mjml-text-4.16.1.tgz", - "integrity": "sha512-BmwDXhI+HEe4klEHM9KAXzYxLoUqU97GZI3XMiNdBPSsxKve2x/PSEfRPxEyRaoIpWPsh4HnQBJANzfTgiemSQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-text/-/mjml-text-4.18.0.tgz", + "integrity": "sha512-hBLmF3JgveUKktKQFWHqHAr7qr92j1CxAvq7mtpDUgiWgyPFzqRX8mUsFYgZ7DmRxG4UE+Kzpt8/YFd9+E98lw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1" + "mjml-core": "4.18.0" } }, "node_modules/mjml-validator": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-validator/-/mjml-validator-4.16.1.tgz", - "integrity": "sha512-lCePRig7cTLCpkqBk1GAUs+BS3rbO+Nmle+rHLZo5rrHgJJOkozHAJbmaEs9p29KXx0OoUTj+JVMncpUQeCSFA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-validator/-/mjml-validator-4.18.0.tgz", + "integrity": "sha512-JmpWAsNTUlAxJOz2zHYfF8Vod8OzM3Qp5JXtrVw5tivZQzq88ZfqVGuqsas51z0pp1/ilfD4lC17YGfGwKGyhA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4" } }, "node_modules/mjml-wrapper": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/mjml-wrapper/-/mjml-wrapper-4.16.1.tgz", - "integrity": "sha512-OfbKR8dym5vJ4z+n1L0vFfuGfnD8Y1WKrn4rjEuvCWWSE4BeXd/rm4OHy2JKgDo3Wg7kxLkz9ghEO4kFMOKP5g==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/mjml-wrapper/-/mjml-wrapper-4.18.0.tgz", + "integrity": "sha512-TZeOvLjIhXEK60rjWNiYhEYNlv5GKYahE+96ifcT5OGkWkRA0DsQDfp+6VI32OS5VxsfKq2h/UdERPlQijjpAQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", "lodash": "^4.17.21", - "mjml-core": "4.16.1", - "mjml-section": "4.16.1" + "mjml-core": "4.18.0", + "mjml-section": "4.18.0" } }, "node_modules/mkdirp": { @@ -12229,9 +11052,9 @@ } }, "node_modules/node-abi": { - "version": "3.78.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.78.0.tgz", - "integrity": "sha512-E2wEyrgX/CqvicaQYU3Ze1PFGjc4QYPGsjUrlYkqAE0WjHEZwgOsGMPMzkMse4LjJbDmaEuDX3CM036j5K2DSQ==", + "version": "3.92.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", + "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", "license": "MIT", "dependencies": { "semver": "^7.3.5" @@ -12296,21 +11119,39 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.23", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.23.tgz", - "integrity": "sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==", + "version": "2.0.47", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz", + "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/nodemailer": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.9.tgz", - "integrity": "sha512-9/Qm0qXIByEP8lEV2qOqcAW7bRpL8CR9jcTwk3NBnHJNmP9fIJ86g2fgmIXqHY+nj55ZEMwWqYAT2QTDpRUYiQ==", + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.13.tgz", + "integrity": "sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw==", "license": "MIT-0", "engines": { "node": ">=6.0.0" } }, + "node_modules/nopt": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "license": "ISC", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -12727,6 +11568,21 @@ "node": ">=8" } }, + "node_modules/path-expression-matcher": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz", + "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -12749,6 +11605,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, "license": "MIT" }, "node_modules/path-scurry": { @@ -13348,10 +12205,13 @@ } }, "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } }, "node_modules/pump": { "version": "3.0.3", @@ -13391,12 +12251,12 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "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.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -13442,16 +12302,6 @@ "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", "license": "MIT" }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -13462,15 +12312,15 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "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.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" @@ -13544,9 +12394,9 @@ } }, "node_modules/readdir-glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -13568,9 +12418,9 @@ } }, "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -13664,23 +12514,23 @@ } }, "node_modules/require-in-the-middle": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", - "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-8.0.1.tgz", + "integrity": "sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==", "license": "MIT", "dependencies": { "debug": "^4.3.5", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.8" + "module-details-from-path": "^1.0.3" }, "engines": { - "node": ">=8.6.0" + "node": ">=9.3.0 || >=8.10.0 <9.0.0" } }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.16.0", @@ -13806,9 +12656,9 @@ } }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -13839,9 +12689,9 @@ } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -13968,9 +12818,9 @@ } }, "node_modules/schema-utils/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -14020,24 +12870,24 @@ } }, "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "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": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "range-parser": "~1.2.1", - "statuses": "2.0.1" + "statuses": "~2.0.2" }, "engines": { "node": ">= 0.8.0" @@ -14058,35 +12908,16 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "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.0" + "send": "~0.19.1" }, "engines": { "node": ">= 0.8.0" @@ -14162,12 +12993,6 @@ "node": ">=8" } }, - "node_modules/shimmer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", - "license": "BSD-2-Clause" - }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -14297,62 +13122,28 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", - "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.7.tgz", + "integrity": "sha512-e0LyK91f3cUxTmv95/KzoLg47+zF+s/sbxRGDNsyG4dmIP8ZSX8ax6byOxfJXeNNtS/8AZlfD+uP7gBeR7DLlg==", "license": "MIT", "dependencies": { - "debug": "~4.3.4", - "ws": "~8.17.1" - } - }, - "node_modules/socket.io-adapter/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "debug": "~4.4.1", + "ws": "~8.20.1" } }, "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" + "debug": "~4.4.1" }, "engines": { "node": ">=10.0.0" } }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/socket.io/node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -14472,9 +13263,9 @@ "license": "MIT" }, "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "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" @@ -14627,16 +13418,19 @@ } }, "node_modules/strnum": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", - "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.4.0.tgz", + "integrity": "sha512-sHrVyWWdq28RbhjuJdZsA1SnGRJV6NiXbk6AXBxDOsgAcA+lmpUZCYjOdLBxkXMwis6RRe7dlZt4VlIWFVzkmg==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" } ], - "license": "MIT" + "license": "MIT", + "dependencies": { + "anynum": "^1.0.0" + } }, "node_modules/strtok3": { "version": "10.3.4", @@ -14721,6 +13515,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -14762,9 +13557,9 @@ } }, "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "dev": true, "license": "MIT", "engines": { @@ -14811,16 +13606,15 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.14", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", - "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "engines": { @@ -14834,12 +13628,39 @@ "webpack": "^5.1.0" }, "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, "@swc/core": { "optional": true }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, "esbuild": { "optional": true }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, "uglify-js": { "optional": true } @@ -14919,9 +13740,9 @@ } }, "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -14952,9 +13773,9 @@ } }, "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -15522,9 +14343,9 @@ } }, "node_modules/typeorm/node_modules/uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -15690,9 +14511,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -15796,9 +14617,9 @@ } }, "node_modules/validator": { - "version": "13.15.15", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz", - "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==", + "version": "13.15.35", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.35.tgz", + "integrity": "sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw==", "license": "MIT", "engines": { "node": ">= 0.10" @@ -15824,13 +14645,12 @@ } }, "node_modules/watchpack": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", - "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz", + "integrity": "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==", "dev": true, "license": "MIT", "dependencies": { - "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" }, "engines": { @@ -15980,38 +14800,36 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.102.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.102.0.tgz", - "integrity": "sha512-hUtqAR3ZLVEYDEABdBioQCIqSoguHbFn1K7WlPPWSuXmx0031BD73PSE35jKyftdSh4YLDoQNgK4pqBt5Q82MA==", + "version": "5.107.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.2.tgz", + "integrity": "sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-import-phases": "^1.0.3", - "browserslist": "^4.24.5", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.3", - "es-module-lexer": "^1.2.1", + "enhanced-resolve": "^5.22.0", + "es-module-lexer": "^2.1.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", "neo-async": "^2.6.2", - "schema-utils": "^4.3.2", - "tapable": "^2.2.3", - "terser-webpack-plugin": "^5.3.11", - "watchpack": "^2.4.4", - "webpack-sources": "^3.3.3" + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.5.0", + "watchpack": "^2.5.1", + "webpack-sources": "^3.5.0" }, "bin": { "webpack": "bin/webpack.js" @@ -16040,15 +14858,23 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" } }, + "node_modules/webpack/node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/webpack/node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -16075,6 +14901,17 @@ "node": ">=4.0" } }, + "node_modules/webpack/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/webpack/node_modules/schema-utils": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", @@ -16219,9 +15056,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -16239,6 +15076,21 @@ } } }, + "node_modules/xml-naming": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz", + "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", @@ -16356,9 +15208,9 @@ } }, "node_modules/zip-stream/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -16387,9 +15239,9 @@ } }, "node_modules/zip-stream/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" diff --git a/apps/backend/package.json b/apps/backend/package.json index e4b30a7..c83f196 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -51,6 +51,7 @@ "class-transformer": "^0.5.1", "class-validator": "^0.14.2", "compression": "^1.8.1", + "cookie-parser": "^1.4.7", "csv-parse": "^6.1.0", "exceljs": "^4.4.0", "handlebars": "^4.7.8", @@ -87,6 +88,7 @@ "@nestjs/testing": "^10.2.10", "@types/bcrypt": "^5.0.2", "@types/compression": "^1.8.1", + "@types/cookie-parser": "^1.4.10", "@types/express": "^4.17.21", "@types/jest": "^29.5.11", "@types/multer": "^2.0.0", diff --git a/apps/backend/src/app.module.ts b/apps/backend/src/app.module.ts index 2ad8548..d2cb4ed 100644 --- a/apps/backend/src/app.module.ts +++ b/apps/backend/src/app.module.ts @@ -39,6 +39,7 @@ import { CsvRateModule } from './infrastructure/carriers/csv-loader/csv-rate.mod // Import global guards import { ApiKeyOrJwtGuard } from './application/guards/api-key-or-jwt.guard'; +import { HealthController } from './application/controllers/health.controller'; import { CustomThrottlerGuard } from './application/guards/throttle.guard'; @Module({ @@ -59,9 +60,14 @@ import { CustomThrottlerGuard } from './application/guards/throttle.guard'; REDIS_HOST: Joi.string().required(), REDIS_PORT: Joi.number().default(6379), REDIS_PASSWORD: Joi.string().required(), - JWT_SECRET: Joi.string().required(), + JWT_SECRET: Joi.string().min(32).required(), JWT_ACCESS_EXPIRATION: Joi.string().default('15m'), JWT_REFRESH_EXPIRATION: Joi.string().default('7d'), + // Cookie domain for auth cookies (e.g. ".xpeditis.com" so the frontend + // and API subdomains share them). Unset = host-only (fine for localhost). + COOKIE_DOMAIN: Joi.string().optional(), + // Secret used to derive carrier document passwords (falls back to JWT_SECRET) + DOCUMENT_PASSWORD_SECRET: Joi.string().min(16).optional(), // SMTP Configuration SMTP_HOST: Joi.string().required(), SMTP_PORT: Joi.number().default(2525), @@ -185,7 +191,7 @@ import { CustomThrottlerGuard } from './application/guards/throttle.guard'; ApiKeysModule, LogsModule, ], - controllers: [], + controllers: [HealthController], providers: [ // Global authentication guard — supports both JWT (frontend) and API key (Gold/Platinium) // All routes are protected by default, use @Public() to bypass diff --git a/apps/backend/src/application/auth/auth.service.ts b/apps/backend/src/application/auth/auth.service.ts index 208c9f9..1808174 100644 --- a/apps/backend/src/application/auth/auth.service.ts +++ b/apps/backend/src/application/auth/auth.service.ts @@ -21,6 +21,7 @@ import { } from '@domain/ports/out/organization.repository'; import { Organization } from '@domain/entities/organization.entity'; import { EmailPort, EMAIL_PORT } from '@domain/ports/out/email.port'; +import { CachePort, CACHE_PORT } from '@domain/ports/out/cache.port'; import { v4 as uuidv4 } from 'uuid'; import { RegisterOrganizationDto } from '../dto/auth-login.dto'; import { SubscriptionService } from '../services/subscription.service'; @@ -34,6 +35,7 @@ export interface JwtPayload { plan?: string; // subscription plan (BRONZE, SILVER, GOLD, PLATINIUM) planFeatures?: string[]; // plan feature flags type: 'access' | 'refresh'; + rememberMe?: boolean; // drives auth cookie persistence across refreshes } @Injectable() @@ -47,6 +49,8 @@ export class AuthService { private readonly organizationRepository: OrganizationRepository, @Inject(EMAIL_PORT) private readonly emailService: EmailPort, + @Inject(CACHE_PORT) + private readonly cache: CachePort, @InjectRepository(PasswordResetTokenOrmEntity) private readonly passwordResetTokenRepository: Repository, private readonly jwtService: JwtService, @@ -93,6 +97,11 @@ export class AuthService { // - Otherwise, default to USER let userRole: UserRole; if (invitationRole) { + // Invitations can only grant non-admin roles — reject anything else + const allowedInvitationRoles: UserRole[] = [UserRole.MANAGER, UserRole.USER, UserRole.VIEWER]; + if (!allowedInvitationRoles.includes(invitationRole as UserRole)) { + throw new BadRequestException('Invalid invitation role'); + } userRole = invitationRole as UserRole; } else if (organizationData) { // User creating a new organization becomes MANAGER @@ -146,7 +155,8 @@ export class AuthService { */ async login( email: string, - password: string + password: string, + rememberMe = false ): Promise<{ accessToken: string; refreshToken: string; user: any }> { this.logger.log(`Login attempt for: ${email}`); @@ -166,7 +176,7 @@ export class AuthService { throw new UnauthorizedException('Invalid credentials'); } - const tokens = await this.generateTokens(user); + const tokens = await this.generateTokens(user, rememberMe); this.logger.log(`User logged in successfully: ${email}`); @@ -188,7 +198,7 @@ export class AuthService { */ async refreshAccessToken( refreshToken: string - ): Promise<{ accessToken: string; refreshToken: string }> { + ): Promise<{ accessToken: string; refreshToken: string; rememberMe: boolean }> { try { const payload = await this.jwtService.verifyAsync(refreshToken, { secret: this.configService.get('JWT_SECRET'), @@ -198,23 +208,66 @@ export class AuthService { throw new UnauthorizedException('Invalid token type'); } + if (await this.isRefreshTokenRevoked(refreshToken)) { + throw new UnauthorizedException('Refresh token has been revoked'); + } + const user = await this.userRepository.findById(payload.sub); if (!user || !user.isActive) { throw new UnauthorizedException('User not found or inactive'); } - const tokens = await this.generateTokens(user); + const rememberMe = payload.rememberMe === true; + const tokens = await this.generateTokens(user, rememberMe); this.logger.log(`Access token refreshed for user: ${user.email}`); - return tokens; + return { ...tokens, rememberMe }; } catch (error: any) { this.logger.error(`Token refresh failed: ${error?.message || 'Unknown error'}`); throw new UnauthorizedException('Invalid or expired refresh token'); } } + /** + * Logout — revoke the refresh token so it can no longer be used. + * The revocation list lives in Redis with a TTL matching the token's + * remaining lifetime, so entries clean themselves up. + */ + async logout(refreshToken?: string): Promise { + if (!refreshToken) { + return; + } + + try { + const payload = this.jwtService.decode(refreshToken) as JwtPayload & { exp?: number }; + const remainingSeconds = payload?.exp + ? Math.max(payload.exp - Math.floor(Date.now() / 1000), 1) + : 7 * 24 * 60 * 60; + + await this.cache.set(this.revokedTokenKey(refreshToken), true, remainingSeconds); + this.logger.log(`Refresh token revoked for user: ${payload?.email ?? 'unknown'}`); + } catch (error) { + // Never block logout on revocation failures — log and continue + this.logger.error(`Failed to revoke refresh token: ${error}`); + } + } + + private async isRefreshTokenRevoked(refreshToken: string): Promise { + try { + return (await this.cache.get(this.revokedTokenKey(refreshToken))) === true; + } catch (error) { + this.logger.error(`Failed to check refresh token revocation: ${error}`); + return false; + } + } + + private revokedTokenKey(refreshToken: string): string { + const hash = crypto.createHash('sha256').update(refreshToken).digest('hex'); + return `auth:revoked-refresh:${hash}`; + } + /** * Initiate password reset — generates token and sends email */ @@ -234,13 +287,15 @@ export class AuthService { { usedAt: new Date() } ); - // Generate a secure random token + // Generate a secure random token; only its hash is stored so a database + // leak cannot be used to take over accounts via pending reset tokens const token = crypto.randomBytes(32).toString('hex'); + const tokenHash = this.hashResetToken(token); const expiresAt = new Date(Date.now() + 60 * 60 * 1000); // 1 hour await this.passwordResetTokenRepository.save({ userId: user.id, - token, + token: tokenHash, expiresAt, usedAt: null, }); @@ -254,7 +309,9 @@ export class AuthService { * Reset password using token from email */ async resetPassword(token: string, newPassword: string): Promise { - const resetToken = await this.passwordResetTokenRepository.findOne({ where: { token } }); + const resetToken = await this.passwordResetTokenRepository.findOne({ + where: { token: this.hashResetToken(token) }, + }); if (!resetToken) { throw new BadRequestException('Token de réinitialisation invalide ou expiré'); @@ -293,6 +350,10 @@ export class AuthService { this.logger.log(`Password reset successfully for user: ${user.email}`); } + private hashResetToken(token: string): string { + return crypto.createHash('sha256').update(token).digest('hex'); + } + /** * Validate user from JWT payload */ @@ -309,7 +370,10 @@ export class AuthService { /** * Generate access and refresh tokens */ - private async generateTokens(user: User): Promise<{ accessToken: string; refreshToken: string }> { + private async generateTokens( + user: User, + rememberMe = false + ): Promise<{ accessToken: string; refreshToken: string }> { // ADMIN users always get PLATINIUM plan with no expiration let plan = 'BRONZE'; let planFeatures: string[] = []; @@ -355,6 +419,7 @@ export class AuthService { plan, planFeatures, type: 'refresh', + rememberMe, }; const [accessToken, refreshToken] = await Promise.all([ diff --git a/apps/backend/src/application/auth/jwt.strategy.ts b/apps/backend/src/application/auth/jwt.strategy.ts index 437d1a8..83dd766 100644 --- a/apps/backend/src/application/auth/jwt.strategy.ts +++ b/apps/backend/src/application/auth/jwt.strategy.ts @@ -35,7 +35,11 @@ export class JwtStrategy extends PassportStrategy(Strategy) { private readonly authService: AuthService ) { super({ - jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), + jwtFromRequest: ExtractJwt.fromExtractors([ + ExtractJwt.fromAuthHeaderAsBearerToken(), + // httpOnly cookie set by the auth endpoints (XSS-safe storage) + (req: { cookies?: Record }) => req?.cookies?.accessToken ?? null, + ]), ignoreExpiration: false, secretOrKey: configService.get('JWT_SECRET'), }); diff --git a/apps/backend/src/application/controllers/auth.controller.ts b/apps/backend/src/application/controllers/auth.controller.ts index 756bcea..75e99fe 100644 --- a/apps/backend/src/application/controllers/auth.controller.ts +++ b/apps/backend/src/application/controllers/auth.controller.ts @@ -8,10 +8,15 @@ import { Get, Inject, NotFoundException, + UnauthorizedException, InternalServerErrorException, Logger, + Req, + Res, } from '@nestjs/common'; +import type { Request, Response } from 'express'; import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger'; +import { Throttle } from '@nestjs/throttler'; import { AuthService } from '../auth/auth.service'; import { LoginDto, @@ -29,6 +34,24 @@ import { JwtAuthGuard } from '../guards/jwt-auth.guard'; import { UserRepository, USER_REPOSITORY } from '@domain/ports/out/user.repository'; import { UserMapper } from '../mappers/user.mapper'; import { InvitationService } from '../services/invitation.service'; +import { + AUTH_COOKIE_NAMES, + authCookieOptions, +} from '../../infrastructure/security/security.config'; + +const REFRESH_COOKIE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000; // 7 days + +/** + * Escape user-provided text before interpolating it into HTML emails + */ +function escapeHtml(value: string): string { + return value + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} /** * Authentication Controller @@ -52,6 +75,33 @@ export class AuthController { @Inject(EMAIL_PORT) private readonly emailService: EmailPort ) {} + /** + * Deliver tokens as httpOnly cookies so they are out of reach of XSS. + * When rememberMe is false the cookies are session-scoped (cleared when + * the browser closes); otherwise they persist for the refresh window. + */ + private setAuthCookies( + res: Response, + tokens: { accessToken: string; refreshToken: string }, + rememberMe: boolean + ): void { + const maxAgeMs = rememberMe ? REFRESH_COOKIE_MAX_AGE_MS : undefined; + res.cookie(AUTH_COOKIE_NAMES.accessToken, tokens.accessToken, authCookieOptions({ maxAgeMs })); + res.cookie( + AUTH_COOKIE_NAMES.refreshToken, + tokens.refreshToken, + authCookieOptions({ maxAgeMs }) + ); + // Readable flag (no token inside) so the frontend knows a session exists + res.cookie(AUTH_COOKIE_NAMES.session, '1', authCookieOptions({ maxAgeMs, httpOnly: false })); + } + + private clearAuthCookies(res: Response): void { + res.clearCookie(AUTH_COOKIE_NAMES.accessToken, authCookieOptions()); + res.clearCookie(AUTH_COOKIE_NAMES.refreshToken, authCookieOptions()); + res.clearCookie(AUTH_COOKIE_NAMES.session, authCookieOptions({ httpOnly: false })); + } + /** * Register a new user * @@ -61,6 +111,7 @@ export class AuthController { * @returns Access token, refresh token, and user info */ @Public() + @Throttle({ default: { limit: 5, ttl: 60000 } }) @Post('register') @HttpCode(HttpStatus.CREATED) @ApiOperation({ @@ -80,7 +131,10 @@ export class AuthController { status: 400, description: 'Validation error (invalid email, weak password, etc.)', }) - async register(@Body() dto: RegisterDto): Promise { + async register( + @Body() dto: RegisterDto, + @Res({ passthrough: true }) res: Response + ): Promise { // If invitation token is provided, verify and use it let invitationOrganizationId: string | undefined; let invitationRole: string | undefined; @@ -101,12 +155,14 @@ export class AuthController { dto.lastName = dto.lastName || invitation.lastName; } + // Joining an existing organization is only allowed through a verified + // invitation token — never from a caller-supplied organization ID. const result = await this.authService.register( dto.email, dto.password, dto.firstName, dto.lastName, - invitationOrganizationId || dto.organizationId, + invitationOrganizationId, dto.organization, invitationRole ); @@ -116,6 +172,8 @@ export class AuthController { await this.invitationService.markInvitationAsUsed(dto.invitationToken); } + this.setAuthCookies(res, result, false); + return { accessToken: result.accessToken, refreshToken: result.refreshToken, @@ -132,6 +190,7 @@ export class AuthController { * @returns Access token, refresh token, and user info */ @Public() + @Throttle({ default: { limit: 5, ttl: 60000 } }) @Post('login') @HttpCode(HttpStatus.OK) @ApiOperation({ @@ -147,8 +206,14 @@ export class AuthController { status: 401, description: 'Invalid credentials or inactive account', }) - async login(@Body() dto: LoginDto): Promise { - const result = await this.authService.login(dto.email, dto.password); + async login( + @Body() dto: LoginDto, + @Res({ passthrough: true }) res: Response + ): Promise { + const rememberMe = dto.rememberMe === true; + const result = await this.authService.login(dto.email, dto.password, rememberMe); + + this.setAuthCookies(res, result, rememberMe); return { accessToken: result.accessToken, @@ -166,6 +231,7 @@ export class AuthController { * @returns New access token */ @Public() + @Throttle({ default: { limit: 20, ttl: 60000 } }) @Post('refresh') @HttpCode(HttpStatus.OK) @ApiOperation({ @@ -175,10 +241,10 @@ export class AuthController { }) @ApiResponse({ status: 200, - description: 'Token refreshed successfully', + description: 'Token refreshed successfully — new tokens are set as httpOnly cookies', schema: { properties: { - accessToken: { type: 'string', example: 'eyJhbGciOiJIUzI1NiIs...' }, + success: { type: 'boolean', example: true }, }, }, }) @@ -186,27 +252,40 @@ export class AuthController { status: 401, description: 'Invalid or expired refresh token', }) - async refresh(@Body() dto: RefreshTokenDto): Promise<{ accessToken: string }> { - const result = await this.authService.refreshAccessToken(dto.refreshToken); + async refresh( + @Body() dto: RefreshTokenDto, + @Req() req: Request, + @Res({ passthrough: true }) res: Response + ): Promise<{ success: boolean }> { + // Prefer the httpOnly cookie; fall back to the body for legacy clients + const refreshToken = req.cookies?.[AUTH_COOKIE_NAMES.refreshToken] || dto.refreshToken; - return { accessToken: result.accessToken }; + if (!refreshToken) { + this.clearAuthCookies(res); + throw new UnauthorizedException('No refresh token provided'); + } + + const result = await this.authService.refreshAccessToken(refreshToken); + + this.setAuthCookies(res, result, result.rememberMe); + + // Tokens are intentionally NOT returned in the body: an XSS payload could + // otherwise call this endpoint and exfiltrate a fresh access token. + return { success: true }; } /** - * Logout (placeholder) + * Logout * - * Currently a no-op endpoint. With JWT, logout is typically handled client-side - * by removing tokens. For more security, implement token blacklisting with Redis. - * - * @returns Success message + * Revokes the refresh token (Redis blacklist) and clears the auth cookies. + * The access token naturally expires within 15 minutes. */ - @UseGuards(JwtAuthGuard) + @Public() @Post('logout') @HttpCode(HttpStatus.OK) - @ApiBearerAuth() @ApiOperation({ summary: 'Logout', - description: 'Logout the current user. Currently handled client-side by removing tokens.', + description: 'Revoke the refresh token and clear authentication cookies.', }) @ApiResponse({ status: 200, @@ -217,9 +296,15 @@ export class AuthController { }, }, }) - async logout(): Promise<{ message: string }> { - // TODO: Implement token blacklisting with Redis for more security - // For now, logout is handled client-side by removing tokens + async logout( + @Req() req: Request, + @Res({ passthrough: true }) res: Response + ): Promise<{ message: string }> { + const refreshToken = req.cookies?.[AUTH_COOKIE_NAMES.refreshToken]; + + await this.authService.logout(refreshToken); + this.clearAuthCookies(res); + return { message: 'Logout successful' }; } @@ -227,6 +312,7 @@ export class AuthController { * Contact form — forwards message to contact@xpeditis.com */ @Public() + @Throttle({ default: { limit: 3, ttl: 60000 } }) @Post('contact') @HttpCode(HttpStatus.OK) @ApiOperation({ @@ -245,7 +331,13 @@ export class AuthController { other: 'Autre', }; - const subjectLabel = subjectLabels[dto.subject] || dto.subject; + const subjectLabel = escapeHtml(subjectLabels[dto.subject] || dto.subject); + const firstName = escapeHtml(dto.firstName); + const lastName = escapeHtml(dto.lastName); + const email = escapeHtml(dto.email); + const company = dto.company ? escapeHtml(dto.company) : undefined; + const phone = dto.phone ? escapeHtml(dto.phone) : undefined; + const message = escapeHtml(dto.message); const html = `
@@ -256,14 +348,14 @@ export class AuthController { - + - + - ${dto.company ? `` : ''} - ${dto.phone ? `` : ''} + ${company ? `` : ''} + ${phone ? `` : ''} @@ -271,7 +363,7 @@ export class AuthController {
Nom${dto.firstName} ${dto.lastName}${firstName} ${lastName}
Email${dto.email}${email}
Entreprise${dto.company}
Téléphone${dto.phone}
Entreprise${company}
Téléphone${phone}
Sujet ${subjectLabel}

Message :

-

${dto.message}

+

${message}

@@ -284,7 +376,7 @@ export class AuthController { await this.emailService.send({ to: 'contact@xpeditis.com', replyTo: dto.email, - subject: `[Contact] ${subjectLabel} — ${dto.firstName} ${dto.lastName}`, + subject: `[Contact] ${subjectLabels[dto.subject] || dto.subject} — ${dto.firstName} ${dto.lastName}`, html, }); } catch (error) { @@ -301,6 +393,7 @@ export class AuthController { * Forgot password — sends reset email */ @Public() + @Throttle({ default: { limit: 3, ttl: 60000 } }) @Post('forgot-password') @HttpCode(HttpStatus.OK) @ApiOperation({ @@ -319,6 +412,7 @@ export class AuthController { * Reset password using token from email */ @Public() + @Throttle({ default: { limit: 5, ttl: 60000 } }) @Post('reset-password') @HttpCode(HttpStatus.OK) @ApiOperation({ diff --git a/apps/backend/src/application/dto/auth-login.dto.ts b/apps/backend/src/application/dto/auth-login.dto.ts index 93a292c..c5a7fd0 100644 --- a/apps/backend/src/application/dto/auth-login.dto.ts +++ b/apps/backend/src/application/dto/auth-login.dto.ts @@ -248,18 +248,7 @@ export class RegisterDto { invitationToken?: string; @ApiPropertyOptional({ - example: '550e8400-e29b-41d4-a716-446655440000', - description: - 'Organization ID (optional - for invited users). If not provided, organization data must be provided.', - required: false, - }) - @IsString() - @IsOptional() - organizationId?: string; - - @ApiPropertyOptional({ - description: - 'Organization data (required if organizationId and invitationToken are not provided)', + description: 'Organization data (required if invitationToken is not provided)', type: RegisterOrganizationDto, required: false, }) @@ -304,10 +293,11 @@ export class AuthResponseDto { } export class RefreshTokenDto { - @ApiProperty({ + @ApiPropertyOptional({ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', - description: 'Refresh token', + description: 'Refresh token (optional — the httpOnly cookie is preferred)', }) @IsString() - refreshToken: string; + @IsOptional() + refreshToken?: string; } diff --git a/apps/backend/src/application/services/csv-booking.service.ts b/apps/backend/src/application/services/csv-booking.service.ts index 8ef2668..f22516a 100644 --- a/apps/backend/src/application/services/csv-booking.service.ts +++ b/apps/backend/src/application/services/csv-booking.service.ts @@ -8,6 +8,7 @@ import { } from '@nestjs/common'; import { v4 as uuidv4 } from 'uuid'; import * as argon2 from 'argon2'; +import * as crypto from 'crypto'; import { CsvBooking, CsvBookingStatus, DocumentType } from '@domain/entities/csv-booking.entity'; import { PortCode } from '@domain/value-objects/port-code.vo'; import { TypeOrmCsvBookingRepository } from '../../infrastructure/persistence/typeorm/repositories/csv-booking.repository'; @@ -81,17 +82,54 @@ export class CsvBookingService { const year = new Date().getFullYear(); const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // No 0, O, 1, I for clarity let code = ''; + const randomBytes = crypto.randomBytes(6); for (let i = 0; i < 6; i++) { - code += chars.charAt(Math.floor(Math.random() * chars.length)); + code += chars.charAt(randomBytes[i] % chars.length); } return `XPD-${year}-${code}`; } /** - * Extract the password from booking number (last 6 characters) + * Derive the document-access password for a booking. + * + * The password is an HMAC of the booking ID keyed with a server-side secret, + * so it can be re-computed when (re)sending carrier emails but cannot be + * guessed from any data visible to third parties (unlike the previous + * scheme, which reused the last 6 characters of the booking number). */ - private extractPasswordFromBookingNumber(bookingNumber: string): string { - return bookingNumber.split('-').pop() || bookingNumber.slice(-6); + private deriveDocumentPassword(bookingId: string): string { + const secret = process.env.DOCUMENT_PASSWORD_SECRET || process.env.JWT_SECRET || ''; + const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // No 0, O, 1, I for clarity + const digest = crypto.createHmac('sha256', secret).update(`doc-password:${bookingId}`).digest(); + let password = ''; + for (let i = 0; i < 8; i++) { + password += chars.charAt(digest[i] % chars.length); + } + return password; + } + + /** + * Re-sync the stored password hash with the derived password and return the + * plaintext for inclusion in the carrier email. Self-heals bookings created + * before the HMAC-based scheme. + */ + private async syncDocumentPassword(bookingId: string): Promise { + const password = this.deriveDocumentPassword(bookingId); + + const ormBooking = await this.csvBookingRepository['repository'].findOne({ + where: { id: bookingId }, + }); + if (ormBooking) { + const matches = ormBooking.passwordHash + ? await argon2.verify(ormBooking.passwordHash, password).catch(() => false) + : false; + if (!matches) { + ormBooking.passwordHash = await argon2.hash(password); + await this.csvBookingRepository['repository'].save(ormBooking); + } + } + + return password; } /** @@ -114,7 +152,7 @@ export class CsvBookingService { const confirmationToken = uuidv4(); const bookingId = uuidv4(); const bookingNumber = this.generateBookingNumber(); - const documentPassword = this.extractPasswordFromBookingNumber(bookingNumber); + const documentPassword = this.deriveDocumentPassword(bookingId); // Hash the password for storage const passwordHash = await argon2.hash(documentPassword); @@ -292,9 +330,7 @@ export class CsvBookingService { where: { id: bookingId }, }); const bookingNumber = ormBooking?.bookingNumber; - const documentPassword = bookingNumber - ? this.extractPasswordFromBookingNumber(bookingNumber) - : undefined; + const documentPassword = await this.syncDocumentPassword(booking.id); // NOW send email to carrier try { @@ -464,9 +500,7 @@ export class CsvBookingService { where: { id: bookingId }, }); const bookingNumber = ormBooking?.bookingNumber; - const documentPassword = bookingNumber - ? this.extractPasswordFromBookingNumber(bookingNumber) - : undefined; + const documentPassword = await this.syncDocumentPassword(booking.id); await this.emailAdapter.sendCsvBookingRequest(booking.carrierEmail, { bookingId: booking.id, @@ -521,9 +555,7 @@ export class CsvBookingService { where: { id: bookingId }, }); const bookingNumber = ormBooking?.bookingNumber; - const documentPassword = bookingNumber - ? this.extractPasswordFromBookingNumber(bookingNumber) - : undefined; + const documentPassword = await this.syncDocumentPassword(booking.id); // Send email to carrier try { @@ -784,9 +816,7 @@ export class CsvBookingService { // Extract password from booking number for the email const bookingNumber = ormBooking?.bookingNumber; - const documentPassword = bookingNumber - ? this.extractPasswordFromBookingNumber(bookingNumber) - : undefined; + const documentPassword = await this.syncDocumentPassword(booking.id); // Send document access email to carrier try { diff --git a/apps/backend/src/infrastructure/security/security.config.ts b/apps/backend/src/infrastructure/security/security.config.ts index 97f4de1..fd4ffef 100644 --- a/apps/backend/src/infrastructure/security/security.config.ts +++ b/apps/backend/src/infrastructure/security/security.config.ts @@ -107,21 +107,6 @@ export const corsConfig = { maxAge: 86400, // 24 hours }; -/** - * Session Configuration - */ -export const sessionConfig = { - secret: process.env.SESSION_SECRET || 'change-this-secret', - resave: false, - saveUninitialized: false, - cookie: { - httpOnly: true, - secure: process.env.NODE_ENV === 'production', // HTTPS only in production - sameSite: 'strict' as const, - maxAge: 7200000, // 2 hours - }, -}; - /** * Password Policy */ @@ -155,19 +140,36 @@ export const fileUploadConfig = { }; /** - * JWT Configuration + * Auth Cookie Configuration + * + * Tokens are delivered as httpOnly cookies so they are not readable from + * JavaScript (XSS mitigation). COOKIE_DOMAIN must be set in production when + * the API and the frontend live on different subdomains (e.g. ".xpeditis.com"). */ -export const jwtConfig = { - accessToken: { - secret: process.env.JWT_SECRET || 'change-this-secret', - expiresIn: '15m', // 15 minutes - }, - refreshToken: { - secret: process.env.JWT_REFRESH_SECRET || 'change-this-refresh-secret', - expiresIn: '7d', // 7 days - }, - algorithm: 'HS256' as const, -}; +export const AUTH_COOKIE_NAMES = { + accessToken: 'accessToken', + refreshToken: 'refreshToken', + /** Non-httpOnly flag the frontend reads to know a session exists (contains no token) */ + session: 'xpeditis_session', +} as const; + +export function authCookieOptions(options?: { maxAgeMs?: number; httpOnly?: boolean }): { + httpOnly: boolean; + secure: boolean; + sameSite: 'lax'; + path: string; + domain?: string; + maxAge?: number; +} { + return { + httpOnly: options?.httpOnly ?? true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + path: '/', + ...(process.env.COOKIE_DOMAIN ? { domain: process.env.COOKIE_DOMAIN } : {}), + ...(options?.maxAgeMs ? { maxAge: options.maxAgeMs } : {}), + }; +} /** * Brute Force Protection diff --git a/apps/backend/src/main.ts b/apps/backend/src/main.ts index c562168..62f8a3c 100644 --- a/apps/backend/src/main.ts +++ b/apps/backend/src/main.ts @@ -5,6 +5,7 @@ import { ConfigService } from '@nestjs/config'; import { I18nService, I18nValidationExceptionFilter, I18nValidationPipe } from 'nestjs-i18n'; import helmet from 'helmet'; import compression from 'compression'; +import cookieParser from 'cookie-parser'; import { AppModule } from './app.module'; import { Logger } from 'nestjs-pino'; import { helmetConfig, corsConfig } from './infrastructure/security/security.config'; @@ -33,6 +34,9 @@ async function bootstrap() { // Compression for API responses app.use(compression()); + // Parse cookies (httpOnly auth cookies) + app.use(cookieParser()); + // CORS with strict configuration app.enableCors(corsConfig); diff --git a/apps/frontend/app/[locale]/blog/[slug]/BlogPostContent.tsx b/apps/frontend/app/[locale]/blog/[slug]/BlogPostContent.tsx index 0ed58fa..2a3e11b 100644 --- a/apps/frontend/app/[locale]/blog/[slug]/BlogPostContent.tsx +++ b/apps/frontend/app/[locale]/blog/[slug]/BlogPostContent.tsx @@ -6,6 +6,7 @@ import { ArrowLeft, Calendar, User, Tag, Clock, Share2, BookOpen, Anchor } from import { Link } from '@/i18n/navigation'; import { LandingHeader, LandingFooter } from '@/components/layout'; import { getBlogPost, type BlogPost } from '@/lib/api/blog'; +import DOMPurify from 'isomorphic-dompurify'; const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000'; @@ -107,9 +108,9 @@ export default function BlogPostContent({ slug }: { slug: string }) { if (notFound || !post) return ; const readingTime = estimateReadingTime(post.content); - const processedContent = post.content.replace( - /src="(\/api\/v1\/blog\/images\/[^"]+)"/g, - `src="${API_BASE_URL}$1"` + // Sanitize the admin-authored HTML before rendering (stored-XSS defense in depth) + const processedContent = DOMPurify.sanitize( + post.content.replace(/src="(\/api\/v1\/blog\/images\/[^"]+)"/g, `src="${API_BASE_URL}$1"`) ); const handleShare = () => { diff --git a/apps/frontend/app/[locale]/dashboard/documents/page.tsx b/apps/frontend/app/[locale]/dashboard/documents/page.tsx index fc276b0..bbcf494 100644 --- a/apps/frontend/app/[locale]/dashboard/documents/page.tsx +++ b/apps/frontend/app/[locale]/dashboard/documents/page.tsx @@ -3,7 +3,6 @@ import { useState, useEffect, useCallback, useRef } from 'react'; import { useTranslations, useLocale } from 'next-intl'; import { listCsvBookings, CsvBookingResponse } from '@/lib/api/bookings'; -import { getAuthToken } from '@/lib/api/client'; import { FileText, Image as ImageIcon, FileEdit, FileSpreadsheet, Paperclip } from 'lucide-react'; import type { ReactNode } from 'react'; import ExportButton from '@/components/ExportButton'; @@ -278,10 +277,9 @@ export default function UserDocumentsPage() { const formData = new FormData(); addFiles.forEach(file => formData.append('documents', file)); - const token = getAuthToken(); const response = await fetch( `${process.env.NEXT_PUBLIC_API_URL}/api/v1/csv-bookings/${selectedBookingId}/documents`, - { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: formData } + { method: 'POST', credentials: 'include', body: formData } ); if (!response.ok) { @@ -336,10 +334,9 @@ export default function UserDocumentsPage() { const formData = new FormData(); formData.append('document', replaceFile); - const token = getAuthToken(); const response = await fetch( `${process.env.NEXT_PUBLIC_API_URL}/api/v1/csv-bookings/${documentToReplace.bookingId}/documents/${documentToReplace.id}`, - { method: 'PATCH', headers: { Authorization: `Bearer ${token}` }, body: formData } + { method: 'PATCH', credentials: 'include', body: formData } ); if (!response.ok) { diff --git a/apps/frontend/app/[locale]/forgot-password/page.tsx b/apps/frontend/app/[locale]/forgot-password/page.tsx index 94d1983..3c5c82d 100644 --- a/apps/frontend/app/[locale]/forgot-password/page.tsx +++ b/apps/frontend/app/[locale]/forgot-password/page.tsx @@ -68,7 +68,14 @@ export default function ForgotPasswordPage() {

/g, '>') + .replace(/"/g, '"'), + }), }} />

{t('successHint')}

diff --git a/apps/frontend/app/[locale]/verify-email/page.tsx b/apps/frontend/app/[locale]/verify-email/page.tsx index 7b54bed..884c227 100644 --- a/apps/frontend/app/[locale]/verify-email/page.tsx +++ b/apps/frontend/app/[locale]/verify-email/page.tsx @@ -1,11 +1,11 @@ 'use client'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, Suspense } from 'react'; import { useSearchParams } from 'next/navigation'; import { Link, useRouter } from '@/i18n/navigation'; import { useTranslations } from 'next-intl'; -export default function VerifyEmailPage() { +function VerifyEmailContent() { const t = useTranslations('auth.verifyEmail'); const searchParams = useSearchParams(); const router = useRouter(); @@ -140,3 +140,12 @@ export default function VerifyEmailPage() {
); } + +export default function VerifyEmailPage() { + // useSearchParams() requires a Suspense boundary for prerendering (Next 14.2+) + return ( + + + + ); +} diff --git a/apps/frontend/app/api/health/route.ts b/apps/frontend/app/api/health/route.ts new file mode 100644 index 0000000..3c72963 --- /dev/null +++ b/apps/frontend/app/api/health/route.ts @@ -0,0 +1,6 @@ +/** + * Health check endpoint used by the Docker HEALTHCHECK. + */ +export function GET() { + return Response.json({ status: 'ok', timestamp: new Date().toISOString() }); +} diff --git a/apps/frontend/package-lock.json b/apps/frontend/package-lock.json index 993e439..2099f19 100644 --- a/apps/frontend/package-lock.json +++ b/apps/frontend/package-lock.json @@ -36,9 +36,10 @@ "date-fns": "^4.1.0", "file-saver": "^2.0.5", "framer-motion": "^12.23.24", + "isomorphic-dompurify": "^3.16.0", "leaflet": "^1.9.4", "lucide-react": "^0.294.0", - "next": "14.0.4", + "next": "^14.2.35", "next-intl": "^4.9.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -89,6 +90,53 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@asamuzakjp/css-color": { + "version": "5.1.11", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz", + "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==", + "license": "MIT", + "dependencies": { + "@asamuzakjp/generational-cache": "^1.0.1", + "@csstools/css-calc": "^3.2.0", + "@csstools/css-color-parser": "^4.1.0", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz", + "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==", + "license": "MIT", + "dependencies": { + "@asamuzakjp/generational-cache": "^1.0.1", + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.2.1", + "is-potential-custom-element-name": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/generational-cache": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz", + "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==", + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "license": "MIT" + }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -615,6 +663,152 @@ "dev": true, "license": "MIT" }, + "node_modules/@bramus/specificity": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.0" + }, + "bin": { + "specificity": "bin/cli.js" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", + "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@csstools/css-calc": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.2.1.tgz", + "integrity": "sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.3.tgz", + "integrity": "sha512-DOgvIPkikIOixQRlD4YF31VN6fLLUTdrzhfRbis8vm0kMTgIbEPX0Ip/YX9fOeV9iywAS4sUUbTclpan7yYP8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^6.0.2", + "@csstools/css-calc": "^3.2.1" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.5.tgz", + "integrity": "sha512-oNjBvzLq2GPZtJphCjLqXow/cHySHSgtxvKZb7OqSZ/xHgw6NWNhfad+6AB9cLeVm6eA9d/qMll3JdEHjy6M+A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, "node_modules/@emnapi/core": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz", @@ -712,6 +906,23 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@exodus/bytes": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz", + "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==", + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, "node_modules/@floating-ui/core": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", @@ -757,18 +968,18 @@ "license": "MIT" }, "node_modules/@formatjs/icu-messageformat-parser": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.4.tgz", - "integrity": "sha512-JVY39ROgLt+pIYngo6piyj4OVfZmXs/2FkC4wLS+ql1Eig/sGJKB7YwDO/5bkJFkfwaFAeIpgEiJc8hiYxNalw==", + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.11.tgz", + "integrity": "sha512-NVsuNsc2dUVG9+4HBJ/srScxtA/18LqGgwtop/tuN/OIBjVl6QA+0KhfZQddDD9sEh2LeVjLFPGVU3ixa3blcA==", "license": "MIT", "dependencies": { - "@formatjs/icu-skeleton-parser": "2.1.4" + "@formatjs/icu-skeleton-parser": "2.1.10" } }, "node_modules/@formatjs/icu-skeleton-parser": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.4.tgz", - "integrity": "sha512-8bSFZbrlvGX11ywMZxtgkPBt5Q8/etyts7j7j+GWpOVK1g43zwMIH3LZxk43HAtEP7L/jtZ+OZaMiFTOiBj9CA==", + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.10.tgz", + "integrity": "sha512-XuSva+8ZGawk8VnD5VD6UeH8KarQ/Z022zgjHDoHmlNiAewstXuuzXc0Hk5pGFSdG+nNw5bfJKXqj1ZXHn9yUA==", "license": "MIT" }, "node_modules/@formatjs/intl-localematcher": { @@ -962,9 +1173,9 @@ } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "license": "MIT", "dependencies": { @@ -1424,9 +1635,9 @@ } }, "node_modules/@next/env": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.0.4.tgz", - "integrity": "sha512-irQnbMLbUNQpP1wcE5NstJtbuA/69kRfzBrpAD7Gsn8zm/CY6YQYc3HQBz8QPxwISG26tIm5afvvVbu508oBeQ==", + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz", + "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -1440,9 +1651,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz", - "integrity": "sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz", + "integrity": "sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==", "cpu": [ "arm64" ], @@ -1456,9 +1667,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz", - "integrity": "sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz", + "integrity": "sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==", "cpu": [ "x64" ], @@ -1472,9 +1683,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz", - "integrity": "sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz", + "integrity": "sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==", "cpu": [ "arm64" ], @@ -1488,9 +1699,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz", - "integrity": "sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz", + "integrity": "sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==", "cpu": [ "arm64" ], @@ -1504,9 +1715,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz", - "integrity": "sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz", + "integrity": "sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==", "cpu": [ "x64" ], @@ -1520,9 +1731,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz", - "integrity": "sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz", + "integrity": "sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==", "cpu": [ "x64" ], @@ -1536,9 +1747,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz", - "integrity": "sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz", + "integrity": "sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==", "cpu": [ "arm64" ], @@ -1552,9 +1763,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz", - "integrity": "sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz", + "integrity": "sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==", "cpu": [ "ia32" ], @@ -1568,9 +1779,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz", - "integrity": "sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz", + "integrity": "sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==", "cpu": [ "x64" ], @@ -1949,7 +2160,7 @@ "version": "1.56.0", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.0.tgz", "integrity": "sha512-Tzh95Twig7hUwwNe381/K3PggZBZblKUe2wv25oIpzWLr6Z0m4KgV1ZVIjnR6GM9ANEqjZD7XsZEa6JL/7YEgg==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "dependencies": { "playwright": "1.56.0" @@ -2965,11 +3176,12 @@ "license": "Apache-2.0" }, "node_modules/@swc/helpers": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz", - "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", "license": "Apache-2.0", "dependencies": { + "@swc/counter": "^0.1.3", "tslib": "^2.4.0" } }, @@ -3676,9 +3888,9 @@ } }, "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", + "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", "dev": true, "license": "MIT", "engines": { @@ -3984,6 +4196,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/use-sync-external-store": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", @@ -4098,9 +4317,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "dev": true, "license": "MIT", "dependencies": { @@ -4485,7 +4704,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, "license": "MIT", "dependencies": { "debug": "4" @@ -4495,9 +4713,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -4876,14 +5094,15 @@ } }, "node_modules/axios": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.17.0.tgz", + "integrity": "sha512-J8SwNxprqqpbfenehxWYXE7CW+wM1BB4w3+N+g+/Wx40xM4rsLrfPmHHxSWIxJLYDgSY/HqlFPIYb2/S3rxafw==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" } }, "node_modules/axobject-query": { @@ -5038,6 +5257,15 @@ "baseline-browser-mapping": "dist/cli.js" } }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -5051,9 +5279,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -5502,6 +5730,19 @@ "node": ">= 8" } }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, "node_modules/css.escape": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", @@ -5765,7 +6006,6 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -5783,7 +6023,6 @@ "version": "10.6.0", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", - "dev": true, "license": "MIT" }, "node_modules/decimal.js-light": { @@ -5996,6 +6235,15 @@ "node": ">=12" } }, + "node_modules/dompurify": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.9.tgz", + "integrity": "sha512-4dPSRMRDqHvs0V4YDFCsaIZo4if5u0xM+llyxiM2fwuZFdKArUBAF3VtI2+n8NKg9P870WMdYk0UhqQNoWXbfQ==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -6972,16 +7220,16 @@ } }, "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", @@ -7043,9 +7291,9 @@ } }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -7333,12 +7581,6 @@ "node": ">=10.13.0" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "license": "BSD-2-Clause" - }, "node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -7548,7 +7790,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, "license": "MIT", "dependencies": { "agent-base": "6", @@ -7582,9 +7823,9 @@ } }, "node_modules/icu-minify": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/icu-minify/-/icu-minify-4.9.1.tgz", - "integrity": "sha512-6NkfF9GHHFouqnz+wuiLjCWQiyxoEyJ5liUv4Jxxo/8wyhV7MY0L0iTEGDAVEa4aAD58WqTxFMa20S5nyMjwNw==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/icu-minify/-/icu-minify-4.13.0.tgz", + "integrity": "sha512-SIFMeUHZJjzS5RvIGvybKvWoHjDm9cGVEs2EpJ8PmywOdJLWyblPm7TdPLLoUtkJtwQD7iGhl2WMptZ+N0on+w==", "funding": [ { "type": "individual", @@ -7717,15 +7958,21 @@ } }, "node_modules/intl-messageformat": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-11.2.1.tgz", - "integrity": "sha512-1gAVEUt3wEPvTqML4Fsw9klZV5j0vszQxayP/fi6gUroAc8AUHiNaisBKLWxybL1AdWq1mP07YV1q8v4N92ilQ==", + "version": "11.2.8", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-11.2.8.tgz", + "integrity": "sha512-l323RCl3qJDVQ8U9j74ut/hVMdg3VPsOHpVMDvFfz9qiq4dPO5ooVYFNVUzzrpgG39a+RLzcXyJb8VFgIU+tUA==", "license": "BSD-3-Clause", "dependencies": { - "@formatjs/fast-memoize": "3.1.2", - "@formatjs/icu-messageformat-parser": "3.5.4" + "@formatjs/fast-memoize": "3.1.6", + "@formatjs/icu-messageformat-parser": "3.5.11" } }, + "node_modules/intl-messageformat/node_modules/@formatjs/fast-memoize": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-3.1.6.tgz", + "integrity": "sha512-H5aexk1Le7T9TPmscacZ+1pR6CTa2n1wq+HDVGXhH8TzUlQQpeXzZs91dRtmFHrbeNbjPFPfQujUqm7MHgVoXQ==", + "license": "MIT" + }, "node_modules/is-arguments": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", @@ -8048,7 +8295,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true, "license": "MIT" }, "node_modules/is-regex": { @@ -8222,6 +8468,194 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, + "node_modules/isomorphic-dompurify": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/isomorphic-dompurify/-/isomorphic-dompurify-3.16.0.tgz", + "integrity": "sha512-KzTJsMuVPqPwBOD0F6jKXoV/+v8CSx0rxVp+/67KV6Xbw++0zD/avT3bZsgwR0M5QRMiOE+QqQtoZLEJYy1C4Q==", + "license": "MIT", + "dependencies": { + "dompurify": "^3.4.8", + "jsdom": "^29.1.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24.0.0" + } + }, + "node_modules/isomorphic-dompurify/node_modules/data-urls": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/isomorphic-dompurify/node_modules/entities": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/isomorphic-dompurify/node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.6.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/isomorphic-dompurify/node_modules/jsdom": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz", + "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==", + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^5.1.11", + "@asamuzakjp/dom-selector": "^7.1.1", + "@bramus/specificity": "^2.4.2", + "@csstools/css-syntax-patches-for-csstree": "^1.1.3", + "@exodus/bytes": "^1.15.0", + "css-tree": "^3.2.1", + "data-urls": "^7.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.3.5", + "parse5": "^8.0.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.1", + "undici": "^7.25.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.1", + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.1", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/isomorphic-dompurify/node_modules/lru-cache": { + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/isomorphic-dompurify/node_modules/parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", + "license": "MIT", + "dependencies": { + "entities": "^8.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/isomorphic-dompurify/node_modules/tough-cookie": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz", + "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/isomorphic-dompurify/node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/isomorphic-dompurify/node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/isomorphic-dompurify/node_modules/webidl-conversions": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=20" + } + }, + "node_modules/isomorphic-dompurify/node_modules/whatwg-mimetype": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/isomorphic-dompurify/node_modules/whatwg-url": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz", + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.11.0", + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/isomorphic-dompurify/node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -9268,10 +9702,20 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -9589,6 +10033,12 @@ "node": ">= 0.4" } }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "license": "CC0-1.0" + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -9660,9 +10110,9 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -9710,7 +10160,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/mz": { @@ -9725,9 +10174,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "funding": [ { "type": "github", @@ -9775,19 +10224,18 @@ } }, "node_modules/next": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/next/-/next-14.0.4.tgz", - "integrity": "sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA==", + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.35.tgz", + "integrity": "sha512-KhYd2Hjt/O1/1aZVX3dCwGXM1QmOV4eNM2UTacK5gipDdPN/oHHK/4oVGy7X8GMfPMsUTUEmGlsy0EY1YGAkig==", "license": "MIT", "dependencies": { - "@next/env": "14.0.4", - "@swc/helpers": "0.5.2", + "@next/env": "14.2.35", + "@swc/helpers": "0.5.5", "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001406", + "caniuse-lite": "^1.0.30001579", "graceful-fs": "^4.2.11", "postcss": "8.4.31", - "styled-jsx": "5.1.1", - "watchpack": "2.4.0" + "styled-jsx": "5.1.1" }, "bin": { "next": "dist/bin/next" @@ -9796,18 +10244,19 @@ "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.0.4", - "@next/swc-darwin-x64": "14.0.4", - "@next/swc-linux-arm64-gnu": "14.0.4", - "@next/swc-linux-arm64-musl": "14.0.4", - "@next/swc-linux-x64-gnu": "14.0.4", - "@next/swc-linux-x64-musl": "14.0.4", - "@next/swc-win32-arm64-msvc": "14.0.4", - "@next/swc-win32-ia32-msvc": "14.0.4", - "@next/swc-win32-x64-msvc": "14.0.4" + "@next/swc-darwin-arm64": "14.2.33", + "@next/swc-darwin-x64": "14.2.33", + "@next/swc-linux-arm64-gnu": "14.2.33", + "@next/swc-linux-arm64-musl": "14.2.33", + "@next/swc-linux-x64-gnu": "14.2.33", + "@next/swc-linux-x64-musl": "14.2.33", + "@next/swc-win32-arm64-msvc": "14.2.33", + "@next/swc-win32-ia32-msvc": "14.2.33", + "@next/swc-win32-x64-msvc": "14.2.33" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", "react": "^18.2.0", "react-dom": "^18.2.0", "sass": "^1.3.0" @@ -9816,15 +10265,18 @@ "@opentelemetry/api": { "optional": true }, + "@playwright/test": { + "optional": true + }, "sass": { "optional": true } } }, "node_modules/next-intl": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.9.1.tgz", - "integrity": "sha512-N7ga0CjtYcdxNvaKNIi6eJ2mmatlHK5hp8rt0YO2Omoc1m0gean242/Ukdj6+gJNiReBVcYIjK0HZeNx7CV1ug==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.13.0.tgz", + "integrity": "sha512-OvNq2v5XLx4EkQOsAhVE9g+6zdb83XHusADCXXtIW4LILYnjEVaeINdr1lkVWKSjzwNUiMSlH5N4K0OQTRiv6A==", "funding": [ { "type": "individual", @@ -9836,11 +10288,11 @@ "@formatjs/intl-localematcher": "^0.8.1", "@parcel/watcher": "^2.4.1", "@swc/core": "^1.15.2", - "icu-minify": "^4.9.1", + "icu-minify": "^4.13.0", "negotiator": "^1.0.0", - "next-intl-swc-plugin-extractor": "^4.9.1", + "next-intl-swc-plugin-extractor": "^4.13.0", "po-parser": "^2.1.1", - "use-intl": "^4.9.1" + "use-intl": "^4.13.0" }, "peerDependencies": { "next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", @@ -9853,9 +10305,9 @@ } }, "node_modules/next-intl-swc-plugin-extractor": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.9.1.tgz", - "integrity": "sha512-8whJJ6oxJz8JqkHarggmmuEDyXgC7nEnaPhZD91CJwEWW4xp0AST3Mw17YxvHyP2vAF3taWfFbs1maD+WWtz3w==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.13.0.tgz", + "integrity": "sha512-6S/fJI0KXvLCL8nhBo9P8eGaJPzmwJBTCzX0NaUIj0VyU8U89d//T+vjMLdNIXl5MlLaYH7B9MbAjb8Mvu+tqQ==", "license": "MIT" }, "node_modules/next-intl/node_modules/@swc/core": { @@ -10368,9 +10820,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -10470,7 +10922,7 @@ "version": "1.56.0", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.0.tgz", "integrity": "sha512-X5Q1b8lOdWIE4KAoHpW3SE8HvUB+ZZsUoN64ZhjnN8dOb1UpujxBtENGiZFE+9F/yhzJwYa+ca3u43FeLbboHA==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "dependencies": { "playwright-core": "1.56.0" @@ -10489,7 +10941,7 @@ "version": "1.56.0", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.0.tgz", "integrity": "sha512-1SXl7pMfemAMSDn5rkPeZljxOCYAmQnYLBTExuh6E8USHXGSX3dx6lYZN/xPpTz1vimXmPA9CDnILvmJaB8aSQ==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" @@ -10530,9 +10982,9 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "funding": [ { "type": "opencollective", @@ -10549,7 +11001,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -10886,10 +11338,13 @@ } }, "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } }, "node_modules/psl": { "version": "1.15.0", @@ -10908,7 +11363,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -11242,6 +11696,15 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -11450,7 +11913,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, "license": "ISC", "dependencies": { "xmlchars": "^2.2.0" @@ -12037,18 +12499,19 @@ } }, "node_modules/sucrase/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/sucrase/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -12066,12 +12529,12 @@ } }, "node_modules/sucrase/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -12109,7 +12572,6 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true, "license": "MIT" }, "node_modules/tailwind-merge": { @@ -12253,9 +12715,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -12265,6 +12727,24 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tldts": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.2.tgz", + "integrity": "sha512-kCwffuaH8ntKtygnWe1b4BJKWiCUH30n5KfoTr6IchcXOwR7chAOFJxFrH3vjANafUYrIA4a7SDL+nn7SiR4Sw==", + "license": "MIT", + "dependencies": { + "tldts-core": "^7.4.2" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.2.tgz", + "integrity": "sha512-nwEyF4vl4RSJjwSjBUmOSxc3BFPoIFdlRthJ6e+5v9P3bHNsoD06UjuqMUspqp7vsEZ1beaHi1km+optiE17yA==", + "license": "MIT" + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -12521,6 +13001,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", @@ -12647,9 +13136,9 @@ } }, "node_modules/use-intl": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.9.1.tgz", - "integrity": "sha512-iGVV/xFYlhe3btafRlL8RPLD2Jsuet4yqn9DR6LWWbMhULsJnXgLonDkzDmsAIBIwFtk02oJuX/Ox2vwHKF+UQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.13.0.tgz", + "integrity": "sha512-fAFDrWaASxlhXOipcOyb5VDD+YONqj6+8O8EcG/J7RBoOUF3A8YahRWLN+mBxYMrlMQB8N6Voqk5X+YC+HSL0A==", "funding": [ { "type": "individual", @@ -12660,7 +13149,7 @@ "dependencies": { "@formatjs/fast-memoize": "^3.1.0", "@schummar/icu-type-parser": "1.21.5", - "icu-minify": "^4.9.1", + "icu-minify": "^4.13.0", "intl-messageformat": "^11.1.0" }, "peerDependencies": { @@ -12770,19 +13259,6 @@ "makeerror": "1.0.12" } }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "license": "MIT", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -13020,9 +13496,9 @@ } }, "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "dev": true, "license": "MIT", "engines": { @@ -13076,7 +13552,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true, "license": "MIT" }, "node_modules/y18n": { diff --git a/apps/frontend/package.json b/apps/frontend/package.json index f235cf5..85fdba1 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -42,9 +42,10 @@ "date-fns": "^4.1.0", "file-saver": "^2.0.5", "framer-motion": "^12.23.24", + "isomorphic-dompurify": "^3.16.0", "leaflet": "^1.9.4", "lucide-react": "^0.294.0", - "next": "14.0.4", + "next": "^14.2.35", "next-intl": "^4.9.1", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/apps/frontend/src/hooks/useBookings.ts b/apps/frontend/src/hooks/useBookings.ts index 423b759..0be1bb4 100644 --- a/apps/frontend/src/hooks/useBookings.ts +++ b/apps/frontend/src/hooks/useBookings.ts @@ -41,9 +41,7 @@ export function useBookings(initialFilters?: BookingFilters) { queryParams.append('pageSize', String(filters.pageSize || 20)); const response = await fetch(`/api/v1/bookings/advanced/search?${queryParams.toString()}`, { - headers: { - Authorization: `Bearer ${localStorage.getItem('accessToken')}`, - }, + credentials: 'include', }); if (!response.ok) { @@ -102,9 +100,9 @@ export function useBookings(initialFilters?: BookingFilters) { try { const response = await fetch('/api/v1/bookings/export', { method: 'POST', + credentials: 'include', headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${localStorage.getItem('accessToken')}`, }, body: JSON.stringify({ format: options.format, diff --git a/apps/frontend/src/lib/api/audit.ts b/apps/frontend/src/lib/api/audit.ts index 8cf781b..b6701f2 100644 --- a/apps/frontend/src/lib/api/audit.ts +++ b/apps/frontend/src/lib/api/audit.ts @@ -108,11 +108,7 @@ export async function exportAuditLogs(params?: { `${process.env.NEXT_PUBLIC_API_URL}/api/v1/audit/export?${queryParams.toString()}`, { method: 'GET', - headers: { - Authorization: `Bearer ${ - typeof window !== 'undefined' ? localStorage.getItem('access_token') : '' - }`, - }, + credentials: 'include', } ); diff --git a/apps/frontend/src/lib/api/auth.ts b/apps/frontend/src/lib/api/auth.ts index df0c62b..ff620b1 100644 --- a/apps/frontend/src/lib/api/auth.ts +++ b/apps/frontend/src/lib/api/auth.ts @@ -4,7 +4,7 @@ * Endpoints for user authentication and session management */ -import { get, post, setAuthTokens, clearAuthTokens } from './client'; +import { get, post, clearAuthTokens } from './client'; import type { RegisterRequest, LoginRequest, @@ -19,12 +19,8 @@ import type { * POST /api/v1/auth/register */ export async function register(data: RegisterRequest): Promise { - const response = await post('/api/v1/auth/register', data, false); - - // Store tokens - setAuthTokens(response.accessToken, response.refreshToken); - - return response; + // Tokens are delivered as httpOnly cookies by the backend + return post('/api/v1/auth/register', data, false); } /** @@ -32,21 +28,18 @@ export async function register(data: RegisterRequest): Promise { * POST /api/v1/auth/login */ export async function login(data: LoginRequest & { rememberMe?: boolean }): Promise { - const { rememberMe, ...loginData } = data; - const response = await post('/api/v1/auth/login', loginData, false); - - // Store tokens — localStorage if rememberMe, sessionStorage otherwise - setAuthTokens(response.accessToken, response.refreshToken, rememberMe ?? false); - - return response; + // Tokens are delivered as httpOnly cookies by the backend; + // rememberMe drives cookie persistence server-side + return post('/api/v1/auth/login', data, false); } /** * Refresh access token * POST /api/v1/auth/refresh */ -export async function refreshToken(data: RefreshTokenRequest): Promise<{ accessToken: string }> { - return post<{ accessToken: string }>('/api/v1/auth/refresh', data, false); +export async function refreshToken(data?: RefreshTokenRequest): Promise<{ success: boolean }> { + // The backend reads the httpOnly refresh cookie and rotates the cookies + return post<{ success: boolean }>('/api/v1/auth/refresh', data ?? {}, false); } /** diff --git a/apps/frontend/src/lib/api/bookings.ts b/apps/frontend/src/lib/api/bookings.ts index 3018eee..206802a 100644 --- a/apps/frontend/src/lib/api/bookings.ts +++ b/apps/frontend/src/lib/api/bookings.ts @@ -181,11 +181,7 @@ export async function exportBookings(params: { `${process.env.NEXT_PUBLIC_API_URL}/api/v1/bookings/export?${queryParams.toString()}`, { method: 'GET', - headers: { - Authorization: `Bearer ${ - typeof window !== 'undefined' ? localStorage.getItem('access_token') : '' - }`, - }, + credentials: 'include', } ); diff --git a/apps/frontend/src/lib/api/client.ts b/apps/frontend/src/lib/api/client.ts index 660c4ae..7f12967 100644 --- a/apps/frontend/src/lib/api/client.ts +++ b/apps/frontend/src/lib/api/client.ts @@ -1,47 +1,37 @@ /** * API Client Base * - * Core HTTP client with authentication and error handling + * Core HTTP client with authentication and error handling. + * + * Authentication relies on httpOnly cookies set by the backend + * (`accessToken` / `refreshToken`), so no token is ever stored in + * localStorage or readable from JavaScript (XSS mitigation). + * The non-httpOnly `xpeditis_session` flag cookie (which contains no + * token) tells the frontend whether a session exists. */ const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000'; +const SESSION_FLAG_COOKIE = 'xpeditis_session'; + // Track if we're currently refreshing to avoid multiple simultaneous refresh requests let isRefreshing = false; -let refreshSubscribers: Array<(token: string) => void> = []; +let refreshSubscribers: Array<() => void> = []; /** - * Get authentication token — checks localStorage first (remember me), then sessionStorage + * Whether an authenticated session exists (based on the readable flag cookie + * set by the backend alongside the httpOnly token cookies). */ -export function getAuthToken(): string | null { - if (typeof window === 'undefined') return null; - return localStorage.getItem('access_token') || sessionStorage.getItem('access_token'); +export function hasSession(): boolean { + if (typeof document === 'undefined') return false; + return document.cookie.split('; ').some(cookie => cookie.startsWith(`${SESSION_FLAG_COOKIE}=`)); } /** - * Get refresh token — checks localStorage first (remember me), then sessionStorage - */ -export function getRefreshToken(): string | null { - if (typeof window === 'undefined') return null; - return localStorage.getItem('refresh_token') || sessionStorage.getItem('refresh_token'); -} - -/** - * Set authentication tokens. - * rememberMe=true → localStorage (persists across browser sessions) - * rememberMe=false → sessionStorage (cleared when browser closes) - */ -export function setAuthTokens(accessToken: string, refreshToken: string, rememberMe = false): void { - if (typeof window === 'undefined') return; - const storage = rememberMe ? localStorage : sessionStorage; - storage.setItem('access_token', accessToken); - storage.setItem('refresh_token', refreshToken); - // Sync to cookie so Next.js middleware can read it for route protection - document.cookie = `accessToken=${accessToken}; path=/; SameSite=Lax`; -} - -/** - * Clear authentication tokens from both storages + * Clear client-side auth state. + * Token cookies are httpOnly and are cleared by the backend on logout; + * this removes the user cache and any tokens left over from the legacy + * localStorage-based auth. */ export function clearAuthTokens(): void { if (typeof window === 'undefined') return; @@ -51,41 +41,39 @@ export function clearAuthTokens(): void { sessionStorage.removeItem('access_token'); sessionStorage.removeItem('refresh_token'); sessionStorage.removeItem('user'); - // Expire the middleware cookie + // Expire the legacy middleware cookie and the session flag (best effort — + // the backend clears the authoritative httpOnly cookies) document.cookie = 'accessToken=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax'; + document.cookie = `${SESSION_FLAG_COOKIE}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax`; } /** - * Add subscriber to be notified when token is refreshed + * Add subscriber to be notified when the session is refreshed */ -function subscribeTokenRefresh(callback: (token: string) => void): void { +function subscribeTokenRefresh(callback: () => void): void { refreshSubscribers.push(callback); } /** - * Notify all subscribers that token has been refreshed + * Notify all subscribers that the session has been refreshed */ -function onTokenRefreshed(token: string): void { - refreshSubscribers.forEach(callback => callback(token)); +function onTokenRefreshed(): void { + refreshSubscribers.forEach(callback => callback()); refreshSubscribers = []; } /** - * Refresh access token using refresh token + * Refresh the session — the backend reads the httpOnly refresh cookie and + * sets new token cookies on success. */ -async function refreshAccessToken(): Promise { - const refreshToken = getRefreshToken(); - - if (!refreshToken) { - throw new Error('No refresh token available'); - } - +async function refreshSession(): Promise { const response = await fetch(`${API_BASE_URL}/api/v1/auth/refresh`, { method: 'POST', + credentials: 'include', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ refreshToken }), + body: JSON.stringify({}), }); if (!response.ok) { @@ -95,54 +83,24 @@ async function refreshAccessToken(): Promise { if (typeof window !== 'undefined') { window.location.href = '/login'; } - throw new Error('Failed to refresh token'); + throw new Error('Failed to refresh session'); } - - const data = await response.json(); - const newAccessToken = data.accessToken; - - // Update access token in the same storage that holds the refresh token - if (typeof window !== 'undefined') { - const storage = localStorage.getItem('refresh_token') ? localStorage : sessionStorage; - storage.setItem('access_token', newAccessToken); - document.cookie = `accessToken=${newAccessToken}; path=/; SameSite=Lax`; - } - - return newAccessToken; } /** - * Create headers with authentication + * Create headers (auth is carried by httpOnly cookies, not headers) */ -export function createHeaders(includeAuth = true): HeadersInit { - const headers: HeadersInit = { +export function createHeaders(_includeAuth = true): HeadersInit { + return { 'Content-Type': 'application/json', }; - - if (includeAuth) { - const token = getAuthToken(); - if (token) { - headers['Authorization'] = `Bearer ${token}`; - } - } - - return headers; } /** * Create headers for multipart form data */ -export function createMultipartHeaders(includeAuth = true): HeadersInit { - const headers: HeadersInit = {}; - - if (includeAuth) { - const token = getAuthToken(); - if (token) { - headers['Authorization'] = `Bearer ${token}`; - } - } - - return headers; +export function createMultipartHeaders(_includeAuth = true): HeadersInit { + return {}; } /** @@ -160,7 +118,7 @@ export class ApiError extends Error { } /** - * Make API request with automatic token refresh on 401 + * Make API request with automatic session refresh on 401 */ export async function apiRequest( endpoint: string, @@ -171,6 +129,7 @@ export async function apiRequest( const response = await fetch(url, { ...options, + credentials: 'include', headers: { ...options.headers, }, @@ -184,10 +143,8 @@ export async function apiRequest( endpoint.includes('/auth/refresh'); if (response.status === 401 && !isRetry && !isAuthEndpoint) { - // Check if we have a refresh token - const refreshToken = getRefreshToken(); - if (!refreshToken) { - // No refresh token, redirect to login + if (!hasSession()) { + // No session, redirect to login clearAuthTokens(); if (typeof window !== 'undefined') { window.location.href = '/login'; @@ -195,46 +152,21 @@ export async function apiRequest( throw new ApiError('Session expired', 401); } - // Try to refresh the token + // Try to refresh the session (cookies are updated server-side) try { if (!isRefreshing) { isRefreshing = true; - const newAccessToken = await refreshAccessToken(); + await refreshSession(); isRefreshing = false; - onTokenRefreshed(newAccessToken); + onTokenRefreshed(); - // Retry the original request with new token - const newHeaders = { ...options.headers }; - if (newHeaders && typeof newHeaders === 'object' && 'Authorization' in newHeaders) { - (newHeaders as any)['Authorization'] = `Bearer ${newAccessToken}`; - } - - return apiRequest( - endpoint, - { - ...options, - headers: newHeaders, - }, - true - ); + return apiRequest(endpoint, options, true); } else { - // Already refreshing, wait for the new token + // Already refreshing, wait for it to complete return new Promise((resolve, reject) => { - subscribeTokenRefresh(async (newAccessToken: string) => { - const newHeaders = { ...options.headers }; - if (newHeaders && typeof newHeaders === 'object' && 'Authorization' in newHeaders) { - (newHeaders as any)['Authorization'] = `Bearer ${newAccessToken}`; - } - + subscribeTokenRefresh(async () => { try { - const result = await apiRequest( - endpoint, - { - ...options, - headers: newHeaders, - }, - true - ); + const result = await apiRequest(endpoint, options, true); resolve(result); } catch (error) { reject(error); @@ -320,43 +252,39 @@ export async function upload( const response = await fetch(url, { method: 'POST', + credentials: 'include', headers: createMultipartHeaders(includeAuth), body: formData, }); // Handle 401 Unauthorized for file uploads - if (response.status === 401) { - const refreshToken = getRefreshToken(); - if (refreshToken) { - try { - const newAccessToken = await refreshAccessToken(); - // Retry upload with new token - const retryResponse = await fetch(url, { - method: 'POST', - headers: { - ...createMultipartHeaders(includeAuth), - Authorization: `Bearer ${newAccessToken}`, - }, - body: formData, - }); + if (response.status === 401 && hasSession()) { + try { + await refreshSession(); + // Retry upload with refreshed cookies + const retryResponse = await fetch(url, { + method: 'POST', + credentials: 'include', + headers: createMultipartHeaders(includeAuth), + body: formData, + }); - if (!retryResponse.ok) { - const error = await retryResponse.json().catch(() => ({})); - throw new ApiError( - error.message || `Upload failed: ${retryResponse.statusText}`, - retryResponse.status, - error - ); - } - - return retryResponse.json(); - } catch (refreshError) { - clearAuthTokens(); - if (typeof window !== 'undefined') { - window.location.href = '/login'; - } - throw refreshError; + if (!retryResponse.ok) { + const error = await retryResponse.json().catch(() => ({})); + throw new ApiError( + error.message || `Upload failed: ${retryResponse.statusText}`, + retryResponse.status, + error + ); } + + return retryResponse.json(); + } catch (refreshError) { + clearAuthTokens(); + if (typeof window !== 'undefined') { + window.location.href = '/login'; + } + throw refreshError; } } @@ -384,45 +312,41 @@ export async function download( const response = await fetch(url, { method: 'GET', + credentials: 'include', headers: createHeaders(includeAuth), }); // Handle 401 Unauthorized for downloads - if (response.status === 401) { - const refreshToken = getRefreshToken(); - if (refreshToken) { - try { - const newAccessToken = await refreshAccessToken(); - // Retry download with new token - const retryResponse = await fetch(url, { - method: 'GET', - headers: { - ...createHeaders(includeAuth), - Authorization: `Bearer ${newAccessToken}`, - }, - }); + if (response.status === 401 && hasSession()) { + try { + await refreshSession(); + // Retry download with refreshed cookies + const retryResponse = await fetch(url, { + method: 'GET', + credentials: 'include', + headers: createHeaders(includeAuth), + }); - if (!retryResponse.ok) { - throw new ApiError(`Download failed: ${retryResponse.statusText}`, retryResponse.status); - } - - const blob = await retryResponse.blob(); - const downloadUrl = window.URL.createObjectURL(blob); - const link = document.createElement('a'); - link.href = downloadUrl; - link.download = filename; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - window.URL.revokeObjectURL(downloadUrl); - return; - } catch (refreshError) { - clearAuthTokens(); - if (typeof window !== 'undefined') { - window.location.href = '/login'; - } - throw refreshError; + if (!retryResponse.ok) { + throw new ApiError(`Download failed: ${retryResponse.statusText}`, retryResponse.status); } + + const blob = await retryResponse.blob(); + const downloadUrl = window.URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = downloadUrl; + link.download = filename; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(downloadUrl); + return; + } catch (refreshError) { + clearAuthTokens(); + if (typeof window !== 'undefined') { + window.location.href = '/login'; + } + throw refreshError; } } diff --git a/apps/frontend/src/lib/api/csv-rates.ts b/apps/frontend/src/lib/api/csv-rates.ts index 7b1ba4e..9e737bf 100644 --- a/apps/frontend/src/lib/api/csv-rates.ts +++ b/apps/frontend/src/lib/api/csv-rates.ts @@ -14,27 +14,12 @@ import { const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000'; /** - * Get authentication token from localStorage - */ -function getAuthToken(): string | null { - if (typeof window === 'undefined') return null; - return localStorage.getItem('access_token'); -} - -/** - * Create headers with authentication + * Create headers — auth is carried by httpOnly cookies (credentials: 'include') */ function createHeaders(): HeadersInit { - const headers: HeadersInit = { + return { 'Content-Type': 'application/json', }; - - const token = getAuthToken(); - if (token) { - headers['Authorization'] = `Bearer ${token}`; - } - - return headers; } /** @@ -45,6 +30,7 @@ export async function searchCsvRates( ): Promise { const response = await fetch(`${API_BASE_URL}/api/v1/rates/search-csv`, { method: 'POST', + credentials: 'include', headers: createHeaders(), body: JSON.stringify(request), }); @@ -63,6 +49,7 @@ export async function searchCsvRates( export async function getAvailableCompanies(): Promise { const response = await fetch(`${API_BASE_URL}/api/v1/rates/companies`, { method: 'GET', + credentials: 'include', headers: createHeaders(), }); @@ -79,6 +66,7 @@ export async function getAvailableCompanies(): Promise { export async function getFilterOptions(): Promise { const response = await fetch(`${API_BASE_URL}/api/v1/rates/filters/options`, { method: 'GET', + credentials: 'include', headers: createHeaders(), }); diff --git a/apps/frontend/src/lib/api/gdpr.ts b/apps/frontend/src/lib/api/gdpr.ts index c6f9a95..7493df4 100644 --- a/apps/frontend/src/lib/api/gdpr.ts +++ b/apps/frontend/src/lib/api/gdpr.ts @@ -53,11 +53,7 @@ export interface GdprDataExportResponse { export async function requestDataExport(): Promise { const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/v1/gdpr/export`, { method: 'GET', - headers: { - Authorization: `Bearer ${ - typeof window !== 'undefined' ? localStorage.getItem('accessToken') : '' - }`, - }, + credentials: 'include', }); if (!response.ok) { @@ -74,11 +70,7 @@ export async function requestDataExport(): Promise { export async function requestDataExportCSV(): Promise { const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/v1/gdpr/export/csv`, { method: 'GET', - headers: { - Authorization: `Bearer ${ - typeof window !== 'undefined' ? localStorage.getItem('accessToken') : '' - }`, - }, + credentials: 'include', }); if (!response.ok) { @@ -96,11 +88,9 @@ export async function requestDataExportCSV(): Promise { export async function requestAccountDeletion(confirmEmail: string, reason?: string): Promise { const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/v1/gdpr/delete-account`, { method: 'DELETE', + credentials: 'include', headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${ - typeof window !== 'undefined' ? localStorage.getItem('accessToken') : '' - }`, }, body: JSON.stringify({ confirmEmail, reason }), }); diff --git a/apps/frontend/src/lib/api/index.ts b/apps/frontend/src/lib/api/index.ts index 6a56e2e..595c792 100644 --- a/apps/frontend/src/lib/api/index.ts +++ b/apps/frontend/src/lib/api/index.ts @@ -10,8 +10,7 @@ // Base client utilities export { - getAuthToken, - setAuthTokens, + hasSession, clearAuthTokens, createHeaders, apiRequest, diff --git a/apps/frontend/src/lib/api/ports.ts b/apps/frontend/src/lib/api/ports.ts index ba0ab82..1eee57a 100644 --- a/apps/frontend/src/lib/api/ports.ts +++ b/apps/frontend/src/lib/api/ports.ts @@ -34,12 +34,6 @@ export interface PortSearchResponse { * Search ports by query (autocomplete) */ export async function searchPorts(params: PortSearchParams): Promise { - // Use the same key as the rest of the app: 'access_token' with underscore - const token = typeof window !== 'undefined' ? localStorage.getItem('access_token') : null; - if (!token) { - throw new Error('No access token found'); - } - const queryParams = new URLSearchParams({ query: params.query, }); @@ -54,9 +48,9 @@ export async function searchPorts(params: PortSearchParams): Promise { - return !!getAuthToken(); - }; - - // Helper function to get stored user - const getStoredUser = (): UserPayload | null => { - if (typeof window === 'undefined') return null; - const storedUser = localStorage.getItem('user'); - return storedUser ? JSON.parse(storedUser) : null; + return hasSession(); }; useEffect(() => { @@ -62,31 +55,20 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const checkAuth = async () => { try { if (isAuthenticated()) { - // Try to fetch current user from API (will auto-refresh token if expired) + // Try to fetch current user from API (will auto-refresh the session if expired) try { const currentUser = await getCurrentUser(); setUser(currentUser); - // Update stored user - localStorage.setItem('user', JSON.stringify(currentUser)); } catch (apiError) { console.error('Failed to fetch user from API:', apiError); - // If API fails after token refresh attempt, clear everything - if (typeof window !== 'undefined') { - localStorage.removeItem('access_token'); - localStorage.removeItem('refresh_token'); - localStorage.removeItem('user'); - } + // If API fails after session refresh attempt, clear everything + clearAuthTokens(); setUser(null); } } } catch (error) { - console.error('Auth check failed, clearing tokens:', error); - // Token invalid or no user data, clear storage - if (typeof window !== 'undefined') { - localStorage.removeItem('access_token'); - localStorage.removeItem('refresh_token'); - localStorage.removeItem('user'); - } + console.error('Auth check failed, clearing session:', error); + clearAuthTokens(); setUser(null); } finally { setLoading(false); @@ -122,14 +104,9 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { ) => { try { await apiLogin({ email, password, rememberMe }); - // Fetch complete user profile after login + // Fetch complete user profile after login (session lives in httpOnly cookies) const currentUser = await getCurrentUser(); setUser(currentUser); - // Store user in the same storage as the tokens - if (typeof window !== 'undefined') { - const storage = rememberMe ? localStorage : sessionStorage; - storage.setItem('user', JSON.stringify(currentUser)); - } router.push(redirectTo); } catch (error) { throw error; @@ -144,14 +121,10 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { organizationId: string; }) => { try { - const response = await apiRegister(data); + await apiRegister(data); // Fetch complete user profile after registration const currentUser = await getCurrentUser(); setUser(currentUser); - // Store user in localStorage - if (typeof window !== 'undefined') { - localStorage.setItem('user', JSON.stringify(currentUser)); - } router.push('/dashboard'); } catch (error) { throw error; @@ -163,10 +136,6 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { await apiLogout(); } finally { setUser(null); - // Clear user from localStorage - if (typeof window !== 'undefined') { - localStorage.removeItem('user'); - } router.push('/login'); } }; @@ -175,9 +144,6 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { try { const currentUser = await getCurrentUser(); setUser(currentUser); - if (typeof window !== 'undefined') { - localStorage.setItem('user', JSON.stringify(currentUser)); - } } catch (error) { console.error('Failed to refresh user:', error); } diff --git a/apps/frontend/src/lib/context/cookie-context.tsx b/apps/frontend/src/lib/context/cookie-context.tsx index 9dd3f73..f7f91ec 100644 --- a/apps/frontend/src/lib/context/cookie-context.tsx +++ b/apps/frontend/src/lib/context/cookie-context.tsx @@ -13,7 +13,7 @@ import { updateConsentPreferences, type CookiePreferences, } from '../api/gdpr'; -import { getAuthToken } from '../api/client'; +import { hasSession } from '../api/client'; const STORAGE_KEY = 'cookieConsent'; const STORAGE_DATE_KEY = 'cookieConsentDate'; @@ -49,7 +49,7 @@ export function CookieProvider({ children }: { children: React.ReactNode }) { // Check if user is authenticated const isAuthenticated = useCallback(() => { - return !!getAuthToken(); + return hasSession(); }, []); // Load preferences from localStorage diff --git a/apps/frontend/src/types/api.ts b/apps/frontend/src/types/api.ts index d658af9..dfa65a8 100644 --- a/apps/frontend/src/types/api.ts +++ b/apps/frontend/src/types/api.ts @@ -27,7 +27,6 @@ export interface RegisterRequest { firstName: string; lastName: string; invitationToken?: string; // For invited users (token-based) - organizationId?: string; // For invited users (ID-based) organization?: RegisterOrganizationData; // For new users } diff --git a/docker/docker-compose.full.yml b/docker/docker-compose.full.yml index 9e08ebf..5ba5a92 100644 --- a/docker/docker-compose.full.yml +++ b/docker/docker-compose.full.yml @@ -103,8 +103,8 @@ services: REDIS_PASSWORD: xpeditis_redis_password REDIS_DB: 0 - # JWT - JWT_SECRET: dev-secret-jwt-key-for-docker + # JWT (must be at least 32 characters — enforced at startup) + JWT_SECRET: dev-secret-jwt-key-for-docker-local-only-0123456789 JWT_ACCESS_EXPIRATION: 15m JWT_REFRESH_EXPIRATION: 7d From bd52819f281e9fb65186626118f175ba38d12612 Mon Sep 17 00:00:00 2001 From: David Date: Sat, 13 Jun 2026 11:53:17 +0200 Subject: [PATCH 2/5] fix admin page --- apps/frontend/app/[locale]/{dashboard => }/admin/blog/page.tsx | 0 .../frontend/app/[locale]/{dashboard => }/admin/bookings/page.tsx | 0 .../app/[locale]/{dashboard => }/admin/csv-rates/page.tsx | 0 .../app/[locale]/{dashboard => }/admin/documents/page.tsx | 0 apps/frontend/app/[locale]/{dashboard => }/admin/logs/page.tsx | 0 .../app/[locale]/{dashboard => }/admin/organizations/page.tsx | 0 apps/frontend/app/[locale]/{dashboard => }/admin/users/page.tsx | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename apps/frontend/app/[locale]/{dashboard => }/admin/blog/page.tsx (100%) rename apps/frontend/app/[locale]/{dashboard => }/admin/bookings/page.tsx (100%) rename apps/frontend/app/[locale]/{dashboard => }/admin/csv-rates/page.tsx (100%) rename apps/frontend/app/[locale]/{dashboard => }/admin/documents/page.tsx (100%) rename apps/frontend/app/[locale]/{dashboard => }/admin/logs/page.tsx (100%) rename apps/frontend/app/[locale]/{dashboard => }/admin/organizations/page.tsx (100%) rename apps/frontend/app/[locale]/{dashboard => }/admin/users/page.tsx (100%) diff --git a/apps/frontend/app/[locale]/dashboard/admin/blog/page.tsx b/apps/frontend/app/[locale]/admin/blog/page.tsx similarity index 100% rename from apps/frontend/app/[locale]/dashboard/admin/blog/page.tsx rename to apps/frontend/app/[locale]/admin/blog/page.tsx diff --git a/apps/frontend/app/[locale]/dashboard/admin/bookings/page.tsx b/apps/frontend/app/[locale]/admin/bookings/page.tsx similarity index 100% rename from apps/frontend/app/[locale]/dashboard/admin/bookings/page.tsx rename to apps/frontend/app/[locale]/admin/bookings/page.tsx diff --git a/apps/frontend/app/[locale]/dashboard/admin/csv-rates/page.tsx b/apps/frontend/app/[locale]/admin/csv-rates/page.tsx similarity index 100% rename from apps/frontend/app/[locale]/dashboard/admin/csv-rates/page.tsx rename to apps/frontend/app/[locale]/admin/csv-rates/page.tsx diff --git a/apps/frontend/app/[locale]/dashboard/admin/documents/page.tsx b/apps/frontend/app/[locale]/admin/documents/page.tsx similarity index 100% rename from apps/frontend/app/[locale]/dashboard/admin/documents/page.tsx rename to apps/frontend/app/[locale]/admin/documents/page.tsx diff --git a/apps/frontend/app/[locale]/dashboard/admin/logs/page.tsx b/apps/frontend/app/[locale]/admin/logs/page.tsx similarity index 100% rename from apps/frontend/app/[locale]/dashboard/admin/logs/page.tsx rename to apps/frontend/app/[locale]/admin/logs/page.tsx diff --git a/apps/frontend/app/[locale]/dashboard/admin/organizations/page.tsx b/apps/frontend/app/[locale]/admin/organizations/page.tsx similarity index 100% rename from apps/frontend/app/[locale]/dashboard/admin/organizations/page.tsx rename to apps/frontend/app/[locale]/admin/organizations/page.tsx diff --git a/apps/frontend/app/[locale]/dashboard/admin/users/page.tsx b/apps/frontend/app/[locale]/admin/users/page.tsx similarity index 100% rename from apps/frontend/app/[locale]/dashboard/admin/users/page.tsx rename to apps/frontend/app/[locale]/admin/users/page.tsx From c6eaaf354a54e34bf565b501f3ba4b69f7d44446 Mon Sep 17 00:00:00 2001 From: David Date: Sat, 13 Jun 2026 11:53:27 +0200 Subject: [PATCH 3/5] fix admin page --- apps/frontend/app/[locale]/admin/layout.tsx | 211 ++++++++++++ .../app/[locale]/admin/login/page.tsx | 128 ++++++++ apps/frontend/app/[locale]/admin/page.tsx | 8 + .../dashboard/admin/[[...rest]]/page.tsx | 11 + .../app/[locale]/dashboard/layout.tsx | 10 +- apps/frontend/messages/en.json | 299 +++++++++++++++--- apps/frontend/messages/fr.json | 242 +++++++++++--- apps/frontend/middleware.ts | 7 +- .../components/admin/AdminPanelDropdown.tsx | 117 ------- 9 files changed, 824 insertions(+), 209 deletions(-) create mode 100644 apps/frontend/app/[locale]/admin/layout.tsx create mode 100644 apps/frontend/app/[locale]/admin/login/page.tsx create mode 100644 apps/frontend/app/[locale]/admin/page.tsx create mode 100644 apps/frontend/app/[locale]/dashboard/admin/[[...rest]]/page.tsx delete mode 100644 apps/frontend/src/components/admin/AdminPanelDropdown.tsx diff --git a/apps/frontend/app/[locale]/admin/layout.tsx b/apps/frontend/app/[locale]/admin/layout.tsx new file mode 100644 index 0000000..547dab6 --- /dev/null +++ b/apps/frontend/app/[locale]/admin/layout.tsx @@ -0,0 +1,211 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { useTranslations } from 'next-intl'; +import { useAuth } from '@/lib/context/auth-context'; +import { Link, usePathname, useRouter } from '@/i18n/navigation'; +import LanguageSwitcher from '@/components/LanguageSwitcher'; +import NotificationDropdown from '@/components/NotificationDropdown'; +import Image from 'next/image'; +import { + Users, + Building2, + Package, + FileText, + BarChart3, + Newspaper, + ScrollText, + ArrowLeft, + LogOut, + ShieldCheck, + type LucideIcon, +} from 'lucide-react'; + +interface AdminNavItem { + key: string; + href: string; + icon: LucideIcon; +} + +const adminNavItems: AdminNavItem[] = [ + { key: 'users', href: '/admin/users', icon: Users }, + { key: 'organizations', href: '/admin/organizations', icon: Building2 }, + { key: 'bookings', href: '/admin/bookings', icon: Package }, + { key: 'documents', href: '/admin/documents', icon: FileText }, + { key: 'csvRates', href: '/admin/csv-rates', icon: BarChart3 }, + { key: 'blog', href: '/admin/blog', icon: Newspaper }, + { key: 'logs', href: '/admin/logs', icon: ScrollText }, +]; + +export default function AdminLayout({ children }: { children: React.ReactNode }) { + const { user, logout, loading, isAuthenticated } = useAuth(); + const pathname = usePathname(); + const router = useRouter(); + const tItems = useTranslations('components.adminPanelDropdown'); + const tAdmin = useTranslations('admin'); + const [sidebarOpen, setSidebarOpen] = useState(false); + + // The /admin/login page lives under this segment but must render without the + // admin chrome and without triggering the role guard. + const isLoginRoute = pathname === '/admin/login'; + + useEffect(() => { + if (isLoginRoute || loading) return; + if (!isAuthenticated) { + router.replace('/admin/login'); + return; + } + if (user && user.role !== 'ADMIN') { + router.replace('/dashboard'); + } + }, [isLoginRoute, loading, isAuthenticated, user, router]); + + if (isLoginRoute) { + return <>{children}; + } + + const authorized = isAuthenticated && user?.role === 'ADMIN'; + + if (loading || !authorized) { + return ( +
+
+
+ ); + } + + const isActive = (href: string) => pathname === href || pathname.startsWith(href + '/'); + + return ( +
+ {sidebarOpen && ( +
setSidebarOpen(false)} + /> + )} + +
+
+
+ + Xpeditis + + +
+ +
+ + {tAdmin('panelTitle')} +
+ + + +
+ + + {tAdmin('backToApp')} + + +
+
+ {user?.firstName?.[0]} + {user?.lastName?.[0]} +
+
+

+ {user?.firstName} {user?.lastName} +

+

{user?.email}

+
+
+ + +
+
+
+ +
+
+ +

+ {adminNavItems.find(item => isActive(item.href)) + ? tItems(`items.${adminNavItems.find(item => isActive(item.href))!.key}` as any) + : tAdmin('title')} +

+
+ + +
+
+ +
{children}
+
+
+ ); +} diff --git a/apps/frontend/app/[locale]/admin/login/page.tsx b/apps/frontend/app/[locale]/admin/login/page.tsx new file mode 100644 index 0000000..befdf59 --- /dev/null +++ b/apps/frontend/app/[locale]/admin/login/page.tsx @@ -0,0 +1,128 @@ +'use client'; + +import { useState } from 'react'; +import { useTranslations } from 'next-intl'; +import { Link, useRouter } from '@/i18n/navigation'; +import Image from 'next/image'; +import { ShieldCheck } from 'lucide-react'; +import { login as apiLogin, getCurrentUser, logout as apiLogout } from '@/lib/api/auth'; +import { useAuth } from '@/lib/context/auth-context'; + +export default function AdminLoginPage() { + const t = useTranslations('admin.login'); + const router = useRouter(); + const { refreshUser } = useAuth(); + + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(''); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(''); + setIsLoading(true); + + try { + await apiLogin({ email, password, rememberMe: false }); + const me = await getCurrentUser(); + + if (me.role !== 'ADMIN') { + // Valid credentials but not an administrator — drop the session. + await apiLogout(); + setError(t('notAdmin')); + return; + } + + await refreshUser(); + router.replace('/admin'); + } catch (err) { + setError(t('error')); + } finally { + setIsLoading(false); + } + }; + + return ( +
+
+ +
+
+
+ Xpeditis +
+ + {t('badge')} +
+

{t('title')}

+

{t('subtitle')}

+
+ + {error && ( +
+

{error}

+
+ )} + +
+
+ + setEmail(e.target.value)} + className="input w-full" + placeholder={t('emailPlaceholder')} + autoComplete="email" + disabled={isLoading} + required + /> +
+ +
+ + setPassword(e.target.value)} + className="input w-full" + placeholder={t('passwordPlaceholder')} + autoComplete="current-password" + disabled={isLoading} + required + /> +
+ + +
+ +
+ + {t('backToApp')} + +
+
+
+
+ ); +} diff --git a/apps/frontend/app/[locale]/admin/page.tsx b/apps/frontend/app/[locale]/admin/page.tsx new file mode 100644 index 0000000..3bfe280 --- /dev/null +++ b/apps/frontend/app/[locale]/admin/page.tsx @@ -0,0 +1,8 @@ +import { redirect } from 'next/navigation'; + +type Params = { locale: string }; + +export default async function AdminIndexPage({ params }: { params: Promise }) { + const { locale } = await params; + redirect(`/${locale}/admin/users`); +} diff --git a/apps/frontend/app/[locale]/dashboard/admin/[[...rest]]/page.tsx b/apps/frontend/app/[locale]/dashboard/admin/[[...rest]]/page.tsx new file mode 100644 index 0000000..293c86d --- /dev/null +++ b/apps/frontend/app/[locale]/dashboard/admin/[[...rest]]/page.tsx @@ -0,0 +1,11 @@ +import { redirect } from 'next/navigation'; + +// Legacy redirect: the admin area moved from /dashboard/admin/* to /admin/*. +// Keeps old links and bookmarks working. +type Params = { locale: string; rest?: string[] }; + +export default async function LegacyAdminRedirect({ params }: { params: Promise }) { + const { locale, rest } = await params; + const sub = rest && rest.length ? `/${rest.join('/')}` : ''; + redirect(`/${locale}/admin${sub}`); +} diff --git a/apps/frontend/app/[locale]/dashboard/layout.tsx b/apps/frontend/app/[locale]/dashboard/layout.tsx index e409c35..0b1321b 100644 --- a/apps/frontend/app/[locale]/dashboard/layout.tsx +++ b/apps/frontend/app/[locale]/dashboard/layout.tsx @@ -6,7 +6,6 @@ import { useState, useEffect } from 'react'; import { useTranslations } from 'next-intl'; import NotificationDropdown from '@/components/NotificationDropdown'; import LanguageSwitcher from '@/components/LanguageSwitcher'; -import AdminPanelDropdown from '@/components/admin/AdminPanelDropdown'; import Image from 'next/image'; import { BarChart3, @@ -21,6 +20,7 @@ import { Key, Home, User, + ShieldCheck, } from 'lucide-react'; import { useSubscription } from '@/lib/context/subscription-context'; import StatusBadge from '@/components/ui/StatusBadge'; @@ -159,7 +159,13 @@ export default function DashboardLayout({ children }: { children: React.ReactNod {user?.role === 'ADMIN' && (
- + + + {t('nav.admin')} +
)} diff --git a/apps/frontend/messages/en.json b/apps/frontend/messages/en.json index a5e917c..6249a1d 100644 --- a/apps/frontend/messages/en.json +++ b/apps/frontend/messages/en.json @@ -27,6 +27,26 @@ "continue": "Continue", "submit": "Submit" }, + "admin": { + "title": "Administration", + "panelTitle": "Administration", + "backToApp": "Back to app", + "logout": "Log out", + "login": { + "badge": "Restricted access", + "title": "Admin sign in", + "subtitle": "Access the Xpeditis administration area", + "emailLabel": "Email", + "emailPlaceholder": "you@company.com", + "passwordLabel": "Password", + "passwordPlaceholder": "********", + "submit": "Sign in", + "submitting": "Signing in...", + "notAdmin": "Access denied: this account is not an administrator.", + "error": "Sign in failed. Please check your credentials.", + "backToApp": "Back to site" + } + }, "language": { "label": "Language", "fr": "Français", @@ -303,7 +323,8 @@ "wiki": "Maritime Wiki", "organization": "Organization", "apiKeys": "API Keys", - "users": "Users" + "users": "Users", + "admin": "Administration" }, "topbar": { "defaultTitle": "Dashboard" @@ -1723,7 +1744,10 @@ ], "extensionsTitle": "Coverage Extensions", "extensions": [ - { "name": "War clause", "description": "Covers losses due to war, terrorism, piracy" }, + { + "name": "War clause", + "description": "Covers losses due to war, terrorism, piracy" + }, { "name": "Strikes clause", "description": "Covers losses due to strikes, riots, civil commotion" @@ -1849,15 +1873,42 @@ "colItem": "Item", "colAmount": "Amount", "exampleItems": [ - { "item": "Base ocean freight", "amount": "1,200 USD" }, - { "item": "BAF (Bunker)", "amount": "350 USD" }, - { "item": "CAF (Currency)", "amount": "50 USD" }, - { "item": "THC Origin", "amount": "180 USD" }, - { "item": "THC Destination", "amount": "220 USD" }, - { "item": "B/L Fee", "amount": "55 USD" }, - { "item": "ISPS", "amount": "30 USD" }, - { "item": "Pre-carriage", "amount": "250 USD" }, - { "item": "Total", "amount": "2,335 USD" } + { + "item": "Base ocean freight", + "amount": "1,200 USD" + }, + { + "item": "BAF (Bunker)", + "amount": "350 USD" + }, + { + "item": "CAF (Currency)", + "amount": "50 USD" + }, + { + "item": "THC Origin", + "amount": "180 USD" + }, + { + "item": "THC Destination", + "amount": "220 USD" + }, + { + "item": "B/L Fee", + "amount": "55 USD" + }, + { + "item": "ISPS", + "amount": "30 USD" + }, + { + "item": "Pre-carriage", + "amount": "250 USD" + }, + { + "item": "Total", + "amount": "2,335 USD" + } ] }, "conteneurs": { @@ -1929,7 +1980,10 @@ ], "specialEquipmentTitle": "Special Equipment", "specialEquipment": [ - { "name": "ISO Tank", "description": "For liquids, chemicals, food products in bulk" }, + { + "name": "ISO Tank", + "description": "For liquids, chemicals, food products in bulk" + }, { "name": "Bulk Container", "description": "For dry bulk (grains, minerals) — top hatch" @@ -1951,11 +2005,26 @@ "condition": "Standard general cargo", "recommendation": "20' or 40' Dry depending on volume" }, - { "condition": "Temperature-sensitive goods", "recommendation": "Reefer 20' or 40'" }, - { "condition": "Over-height cargo (> 2.2m)", "recommendation": "Open Top or Flat Rack" }, - { "condition": "Over-length/weight cargo", "recommendation": "Flat Rack or Platform" }, - { "condition": "Bulk liquids", "recommendation": "ISO Tank" }, - { "condition": "Volume < 15 m³", "recommendation": "Consider LCL" } + { + "condition": "Temperature-sensitive goods", + "recommendation": "Reefer 20' or 40'" + }, + { + "condition": "Over-height cargo (> 2.2m)", + "recommendation": "Open Top or Flat Rack" + }, + { + "condition": "Over-length/weight cargo", + "recommendation": "Flat Rack or Platform" + }, + { + "condition": "Bulk liquids", + "recommendation": "ISO Tank" + }, + { + "condition": "Volume < 15 m³", + "recommendation": "Consider LCL" + } ] }, "documentsTransport": { @@ -2143,7 +2212,10 @@ "type": "VAT", "description": "Applied on (customs value + import duties + transport). 20% standard rate." }, - { "type": "Excise Duties", "description": "Specific to alcohol, tobacco, hydrocarbons." } + { + "type": "Excise Duties", + "description": "Specific to alcohol, tobacco, hydrocarbons." + } ] }, "imdg": { @@ -2202,8 +2274,16 @@ "description": "Toxic and infectious substances", "subdivisions": ["6.1 Toxic substances", "6.2 Infectious substances"] }, - { "class": "Class 7", "name": "Radioactive", "description": "Radioactive materials" }, - { "class": "Class 8", "name": "Corrosive", "description": "Corrosive substances" }, + { + "class": "Class 7", + "name": "Radioactive", + "description": "Radioactive materials" + }, + { + "class": "Class 8", + "name": "Corrosive", + "description": "Corrosive substances" + }, { "class": "Class 9", "name": "Miscellaneous", @@ -2239,8 +2319,14 @@ "group": "Group I (X)", "description": "High danger — most stringent packaging requirements" }, - { "group": "Group II (Y)", "description": "Medium danger — standard packaging" }, - { "group": "Group III (Z)", "description": "Low danger — less stringent requirements" } + { + "group": "Group II (Y)", + "description": "Medium danger — standard packaging" + }, + { + "group": "Group III (Z)", + "description": "Low danger — less stringent requirements" + } ], "labelingTitle": "Labeling and Placarding", "labelingContent": "Each package must display: UN number, proper shipping name, hazard labels and class. Containers must display 250mm × 250mm placards matching the IMDG class. Mixed loads require labels for each dangerous good.", @@ -2264,7 +2350,11 @@ "lcl": "< 15 m³ or < 10 tonnes", "fcl": "> 15 m³ or full container" }, - { "criterion": "Price", "lcl": "Per CBM (m³) or tonne", "fcl": "Fixed per container" }, + { + "criterion": "Price", + "lcl": "Per CBM (m³) or tonne", + "fcl": "Fixed per container" + }, { "criterion": "Security", "lcl": "Moderate (shared with others)", @@ -2373,7 +2463,10 @@ "role": "Applicant (Importer)", "description": "The buyer who requests the L/C at their bank" }, - { "role": "Issuing Bank", "description": "The importer's bank that issues the L/C" }, + { + "role": "Issuing Bank", + "description": "The importer's bank that issues the L/C" + }, { "role": "Beneficiary (Exporter)", "description": "The seller who benefits from the L/C" @@ -2397,7 +2490,10 @@ "name": "Commercial Invoice", "description": "In exact conformity with the L/C — amounts, currencies, description" }, - { "name": "Packing List", "description": "Consistent with invoice and B/L" }, + { + "name": "Packing List", + "description": "Consistent with invoice and B/L" + }, { "name": "Insurance Certificate", "description": "Required if CIF or CIP — amounts and coverage per L/C" @@ -2437,7 +2533,10 @@ "label": "Presentation deadline", "description": "Number of days after shipment to present documents (typically 21 days)" }, - { "label": "L/C expiry", "description": "Final deadline for all document presentation" } + { + "label": "L/C expiry", + "description": "Final deadline for all document presentation" + } ], "costsTitle": "Costs", "costsItems": [ @@ -2449,8 +2548,14 @@ "label": "Confirmation commission", "description": "0.2–0.5% per quarter (confirming bank)" }, - { "label": "Amendment fee", "description": "Fixed fee per amendment" }, - { "label": "Discrepancy fee", "description": "Fixed fee in case of document discrepancy" } + { + "label": "Amendment fee", + "description": "Fixed fee per amendment" + }, + { + "label": "Discrepancy fee", + "description": "Fixed fee in case of document discrepancy" + } ] }, "portsRoutes": { @@ -2529,16 +2634,66 @@ "colCountry": "Country", "colTeu": "TEU / year", "ports": [ - { "rank": 1, "port": "Shanghai", "country": "China", "teu": "47M" }, - { "rank": 2, "port": "Singapore", "country": "Singapore", "teu": "37M" }, - { "rank": 3, "port": "Ningbo-Zhoushan", "country": "China", "teu": "33M" }, - { "rank": 4, "port": "Shenzhen", "country": "China", "teu": "29M" }, - { "rank": 5, "port": "Guangzhou", "country": "China", "teu": "24M" }, - { "rank": 6, "port": "Qingdao", "country": "China", "teu": "24M" }, - { "rank": 7, "port": "Busan", "country": "South Korea", "teu": "22M" }, - { "rank": 8, "port": "Tianjin", "country": "China", "teu": "21M" }, - { "rank": 9, "port": "Dubai (Jebel Ali)", "country": "UAE", "teu": "15M" }, - { "rank": 10, "port": "Rotterdam", "country": "Netherlands", "teu": "15M" } + { + "rank": 1, + "port": "Shanghai", + "country": "China", + "teu": "47M" + }, + { + "rank": 2, + "port": "Singapore", + "country": "Singapore", + "teu": "37M" + }, + { + "rank": 3, + "port": "Ningbo-Zhoushan", + "country": "China", + "teu": "33M" + }, + { + "rank": 4, + "port": "Shenzhen", + "country": "China", + "teu": "29M" + }, + { + "rank": 5, + "port": "Guangzhou", + "country": "China", + "teu": "24M" + }, + { + "rank": 6, + "port": "Qingdao", + "country": "China", + "teu": "24M" + }, + { + "rank": 7, + "port": "Busan", + "country": "South Korea", + "teu": "22M" + }, + { + "rank": 8, + "port": "Tianjin", + "country": "China", + "teu": "21M" + }, + { + "rank": 9, + "port": "Dubai (Jebel Ali)", + "country": "UAE", + "teu": "15M" + }, + { + "rank": 10, + "port": "Rotterdam", + "country": "Netherlands", + "teu": "15M" + } ], "hubGatewayTitle": "Hub vs Gateway", "hubTitle": "Hub Port", @@ -2576,7 +2731,11 @@ "description": "Empty weight of the container (shown on the door)", "example": "2,200 kg (20')" }, - { "element": "Cargo", "description": "Gross weight of all goods", "example": "Variable" }, + { + "element": "Cargo", + "description": "Gross weight of all goods", + "example": "Variable" + }, { "element": "Packaging", "description": "Pallets, cartons, plastic film...", @@ -2642,10 +2801,22 @@ "consequenceValue": "Re-weighing at shipper's expense, possible delay", "sanctionsTitle": "Sanctions by Region", "sanctions": [ - { "region": "France", "sanction": "Fine up to €7,500 and refusal to load" }, - { "region": "USA", "sanction": "Refusal to load, fine from coast guard" }, - { "region": "China", "sanction": "Refusal to load, port penalties" }, - { "region": "European Union", "sanction": "Variable application by member state" } + { + "region": "France", + "sanction": "Fine up to €7,500 and refusal to load" + }, + { + "region": "USA", + "sanction": "Refusal to load, fine from coast guard" + }, + { + "region": "China", + "sanction": "Refusal to load, port penalties" + }, + { + "region": "European Union", + "sanction": "Variable application by member state" + } ], "tipsTitle": "Best Practices", "tips": [ @@ -2740,13 +2911,41 @@ "colTime": "Transit Time", "colVia": "Via", "transitTimes": [ - { "route": "Shanghai → Rotterdam", "time": "28–32 days", "via": "Suez" }, - { "route": "Shanghai → Le Havre", "time": "30–35 days", "via": "Suez" }, - { "route": "Shanghai → Los Angeles", "time": "12–15 days", "via": "Direct Pacific" }, - { "route": "Shanghai → New York", "time": "35–40 days", "via": "Suez or Panama" }, - { "route": "Rotterdam → New York", "time": "10–14 days", "via": "Direct Atlantic" }, - { "route": "Mumbai → Rotterdam", "time": "18–22 days", "via": "Suez" }, - { "route": "Santos → Rotterdam", "time": "18–22 days", "via": "Direct Atlantic" } + { + "route": "Shanghai → Rotterdam", + "time": "28–32 days", + "via": "Suez" + }, + { + "route": "Shanghai → Le Havre", + "time": "30–35 days", + "via": "Suez" + }, + { + "route": "Shanghai → Los Angeles", + "time": "12–15 days", + "via": "Direct Pacific" + }, + { + "route": "Shanghai → New York", + "time": "35–40 days", + "via": "Suez or Panama" + }, + { + "route": "Rotterdam → New York", + "time": "10–14 days", + "via": "Direct Atlantic" + }, + { + "route": "Mumbai → Rotterdam", + "time": "18–22 days", + "via": "Suez" + }, + { + "route": "Santos → Rotterdam", + "time": "18–22 days", + "via": "Direct Atlantic" + } ], "transitNote": "Note: These times are indicative and vary depending on rotations, transshipments and conditions.", "freeTimeTitle": "Free Time (Free Days)", diff --git a/apps/frontend/messages/fr.json b/apps/frontend/messages/fr.json index 62a4e8c..7bdb629 100644 --- a/apps/frontend/messages/fr.json +++ b/apps/frontend/messages/fr.json @@ -27,6 +27,26 @@ "continue": "Continuer", "submit": "Envoyer" }, + "admin": { + "title": "Espace administration", + "panelTitle": "Administration", + "backToApp": "Retour à l'application", + "logout": "Déconnexion", + "login": { + "badge": "Accès réservé", + "title": "Connexion administrateur", + "subtitle": "Accédez à l'espace d'administration Xpeditis", + "emailLabel": "Email", + "emailPlaceholder": "vous@entreprise.com", + "passwordLabel": "Mot de passe", + "passwordPlaceholder": "********", + "submit": "Se connecter", + "submitting": "Connexion...", + "notAdmin": "Accès refusé : ce compte n'est pas administrateur.", + "error": "Échec de la connexion. Vérifiez vos identifiants.", + "backToApp": "Retour au site" + } + }, "language": { "label": "Langue", "fr": "Français", @@ -303,7 +323,8 @@ "wiki": "Wiki Maritime", "organization": "Organisation", "apiKeys": "Clés API", - "users": "Utilisateurs" + "users": "Utilisateurs", + "admin": "Administration" }, "topbar": { "defaultTitle": "Tableau de bord" @@ -1858,15 +1879,42 @@ "colItem": "Poste", "colAmount": "Montant", "exampleItems": [ - { "item": "Fret maritime de base", "amount": "1 200 USD" }, - { "item": "BAF (Bunker)", "amount": "350 USD" }, - { "item": "CAF (Devise)", "amount": "50 USD" }, - { "item": "THC Origine", "amount": "180 USD" }, - { "item": "THC Destination", "amount": "220 USD" }, - { "item": "Frais B/L", "amount": "55 USD" }, - { "item": "ISPS", "amount": "30 USD" }, - { "item": "Pré-acheminement", "amount": "250 USD" }, - { "item": "Total", "amount": "2 335 USD" } + { + "item": "Fret maritime de base", + "amount": "1 200 USD" + }, + { + "item": "BAF (Bunker)", + "amount": "350 USD" + }, + { + "item": "CAF (Devise)", + "amount": "50 USD" + }, + { + "item": "THC Origine", + "amount": "180 USD" + }, + { + "item": "THC Destination", + "amount": "220 USD" + }, + { + "item": "Frais B/L", + "amount": "55 USD" + }, + { + "item": "ISPS", + "amount": "30 USD" + }, + { + "item": "Pré-acheminement", + "amount": "250 USD" + }, + { + "item": "Total", + "amount": "2 335 USD" + } ] }, "conteneurs": { @@ -1975,8 +2023,14 @@ "condition": "Marchandises hors-gabarit / très lourdes", "recommendation": "Flat Rack ou Plateforme" }, - { "condition": "Liquides en vrac", "recommendation": "ISO Tank" }, - { "condition": "Volume < 15 m³", "recommendation": "Envisager le LCL" } + { + "condition": "Liquides en vrac", + "recommendation": "ISO Tank" + }, + { + "condition": "Volume < 15 m³", + "recommendation": "Envisager le LCL" + } ] }, "documentsTransport": { @@ -2226,8 +2280,16 @@ "description": "Matières toxiques et infectieuses", "subdivisions": ["6.1 Matières toxiques", "6.2 Matières infectieuses"] }, - { "class": "Classe 7", "name": "Radioactifs", "description": "Matières radioactives" }, - { "class": "Classe 8", "name": "Corrosifs", "description": "Matières corrosives" }, + { + "class": "Classe 7", + "name": "Radioactifs", + "description": "Matières radioactives" + }, + { + "class": "Classe 8", + "name": "Corrosifs", + "description": "Matières corrosives" + }, { "class": "Classe 9", "name": "Divers", @@ -2263,8 +2325,14 @@ "group": "Groupe I (X)", "description": "Grand danger — exigences d'emballage les plus strictes" }, - { "group": "Groupe II (Y)", "description": "Danger moyen — emballage standard" }, - { "group": "Groupe III (Z)", "description": "Faible danger — exigences moins strictes" } + { + "group": "Groupe II (Y)", + "description": "Danger moyen — emballage standard" + }, + { + "group": "Groupe III (Z)", + "description": "Faible danger — exigences moins strictes" + } ], "labelingTitle": "Étiquetage et Placardage", "labelingContent": "Chaque colis doit afficher : numéro ONU, désignation officielle de transport, étiquettes de danger et classe. Les conteneurs doivent afficher des plaques-étiquettes de 250mm × 250mm correspondant à la classe IMDG. Les chargements mixtes requièrent des étiquettes pour chaque marchandise dangereuse.", @@ -2428,7 +2496,10 @@ "name": "Facture Commerciale", "description": "En exacte conformité avec la L/C — montants, devises, description" }, - { "name": "Liste de Colisage", "description": "Cohérente avec la facture et le B/L" }, + { + "name": "Liste de Colisage", + "description": "Cohérente avec la facture et le B/L" + }, { "name": "Certificat d'Assurance", "description": "Requis si CIF ou CIP — montants et couverture selon L/C" @@ -2483,7 +2554,10 @@ "label": "Commission de confirmation", "description": "0,2–0,5% par trimestre (banque confirmatrice)" }, - { "label": "Frais d'amendement", "description": "Frais fixes par amendement" }, + { + "label": "Frais d'amendement", + "description": "Frais fixes par amendement" + }, { "label": "Frais de réserve", "description": "Frais fixes en cas de réserve sur les documents" @@ -2566,16 +2640,66 @@ "colCountry": "Pays", "colTeu": "TEU / an", "ports": [ - { "rank": 1, "port": "Shanghai", "country": "Chine", "teu": "47M" }, - { "rank": 2, "port": "Singapour", "country": "Singapour", "teu": "37M" }, - { "rank": 3, "port": "Ningbo-Zhoushan", "country": "Chine", "teu": "33M" }, - { "rank": 4, "port": "Shenzhen", "country": "Chine", "teu": "29M" }, - { "rank": 5, "port": "Guangzhou", "country": "Chine", "teu": "24M" }, - { "rank": 6, "port": "Qingdao", "country": "Chine", "teu": "24M" }, - { "rank": 7, "port": "Busan", "country": "Corée du Sud", "teu": "22M" }, - { "rank": 8, "port": "Tianjin", "country": "Chine", "teu": "21M" }, - { "rank": 9, "port": "Dubaï (Jebel Ali)", "country": "EAU", "teu": "15M" }, - { "rank": 10, "port": "Rotterdam", "country": "Pays-Bas", "teu": "15M" } + { + "rank": 1, + "port": "Shanghai", + "country": "Chine", + "teu": "47M" + }, + { + "rank": 2, + "port": "Singapour", + "country": "Singapour", + "teu": "37M" + }, + { + "rank": 3, + "port": "Ningbo-Zhoushan", + "country": "Chine", + "teu": "33M" + }, + { + "rank": 4, + "port": "Shenzhen", + "country": "Chine", + "teu": "29M" + }, + { + "rank": 5, + "port": "Guangzhou", + "country": "Chine", + "teu": "24M" + }, + { + "rank": 6, + "port": "Qingdao", + "country": "Chine", + "teu": "24M" + }, + { + "rank": 7, + "port": "Busan", + "country": "Corée du Sud", + "teu": "22M" + }, + { + "rank": 8, + "port": "Tianjin", + "country": "Chine", + "teu": "21M" + }, + { + "rank": 9, + "port": "Dubaï (Jebel Ali)", + "country": "EAU", + "teu": "15M" + }, + { + "rank": 10, + "port": "Rotterdam", + "country": "Pays-Bas", + "teu": "15M" + } ], "hubGatewayTitle": "Hub vs Gateway", "hubTitle": "Port Hub", @@ -2683,10 +2807,22 @@ "consequenceValue": "Nouvelle pesée à la charge de l'expéditeur, retard possible", "sanctionsTitle": "Sanctions par Région", "sanctions": [ - { "region": "France", "sanction": "Amende jusqu'à 7 500€ et refus d'embarquement" }, - { "region": "USA", "sanction": "Refus d'embarquement, amende par la garde côtière" }, - { "region": "Chine", "sanction": "Refus d'embarquement, pénalités portuaires" }, - { "region": "Union Européenne", "sanction": "Application variable selon pays membre" } + { + "region": "France", + "sanction": "Amende jusqu'à 7 500€ et refus d'embarquement" + }, + { + "region": "USA", + "sanction": "Refus d'embarquement, amende par la garde côtière" + }, + { + "region": "Chine", + "sanction": "Refus d'embarquement, pénalités portuaires" + }, + { + "region": "Union Européenne", + "sanction": "Application variable selon pays membre" + } ], "tipsTitle": "Bonnes Pratiques", "tips": [ @@ -2781,13 +2917,41 @@ "colTime": "Transit Time", "colVia": "Via", "transitTimes": [ - { "route": "Shanghai → Rotterdam", "time": "28–32 jours", "via": "Suez" }, - { "route": "Shanghai → Le Havre", "time": "30–35 jours", "via": "Suez" }, - { "route": "Shanghai → Los Angeles", "time": "12–15 jours", "via": "Pacifique direct" }, - { "route": "Shanghai → New York", "time": "35–40 jours", "via": "Suez ou Panama" }, - { "route": "Rotterdam → New York", "time": "10–14 jours", "via": "Atlantique direct" }, - { "route": "Mumbai → Rotterdam", "time": "18–22 jours", "via": "Suez" }, - { "route": "Santos → Rotterdam", "time": "18–22 jours", "via": "Atlantique direct" } + { + "route": "Shanghai → Rotterdam", + "time": "28–32 jours", + "via": "Suez" + }, + { + "route": "Shanghai → Le Havre", + "time": "30–35 jours", + "via": "Suez" + }, + { + "route": "Shanghai → Los Angeles", + "time": "12–15 jours", + "via": "Pacifique direct" + }, + { + "route": "Shanghai → New York", + "time": "35–40 jours", + "via": "Suez ou Panama" + }, + { + "route": "Rotterdam → New York", + "time": "10–14 jours", + "via": "Atlantique direct" + }, + { + "route": "Mumbai → Rotterdam", + "time": "18–22 jours", + "via": "Suez" + }, + { + "route": "Santos → Rotterdam", + "time": "18–22 jours", + "via": "Atlantique direct" + } ], "transitNote": "Note : Ces temps sont indicatifs et varient selon les rotations, transbordements et conditions.", "freeTimeTitle": "Free Time (Jours Gratuits)", diff --git a/apps/frontend/middleware.ts b/apps/frontend/middleware.ts index fc46853..1d0ef69 100644 --- a/apps/frontend/middleware.ts +++ b/apps/frontend/middleware.ts @@ -29,6 +29,7 @@ const prefixPublicPaths = [ '/press', '/contact', '/carrier', + '/admin/login', '/pricing', '/docs', '/privacy', @@ -71,7 +72,11 @@ export default function middleware(request: NextRequest) { const token = request.cookies.get('accessToken')?.value; if (!isPublicPath && !token) { - const loginUrl = new URL(`/${resolvedLocale}/login`, request.url); + // The admin area has its own entry point — send unauthenticated visitors + // to the dedicated admin login instead of the regular one. + const isAdminArea = pathWithoutLocale === '/admin' || pathWithoutLocale.startsWith('/admin/'); + const loginPath = isAdminArea ? '/admin/login' : '/login'; + const loginUrl = new URL(`/${resolvedLocale}${loginPath}`, request.url); loginUrl.searchParams.set('redirect', pathname); return NextResponse.redirect(loginUrl); } diff --git a/apps/frontend/src/components/admin/AdminPanelDropdown.tsx b/apps/frontend/src/components/admin/AdminPanelDropdown.tsx deleted file mode 100644 index 3e53c5b..0000000 --- a/apps/frontend/src/components/admin/AdminPanelDropdown.tsx +++ /dev/null @@ -1,117 +0,0 @@ -'use client'; - -import { useState, useRef, useEffect } from 'react'; -import { useTranslations } from 'next-intl'; -import { Link, usePathname } from '@/i18n/navigation'; -import { - Users, - Building2, - Package, - FileText, - BarChart3, - Settings, - ScrollText, - Newspaper, - type LucideIcon, -} from 'lucide-react'; - -interface AdminMenuItem { - key: string; - href: string; - icon: LucideIcon; -} - -const adminMenuItems: AdminMenuItem[] = [ - { key: 'users', href: '/dashboard/admin/users', icon: Users }, - { key: 'organizations', href: '/dashboard/admin/organizations', icon: Building2 }, - { key: 'bookings', href: '/dashboard/admin/bookings', icon: Package }, - { key: 'documents', href: '/dashboard/admin/documents', icon: FileText }, - { key: 'csvRates', href: '/dashboard/admin/csv-rates', icon: BarChart3 }, - { key: 'blog', href: '/dashboard/admin/blog', icon: Newspaper }, - { key: 'logs', href: '/dashboard/admin/logs', icon: ScrollText }, -]; - -export default function AdminPanelDropdown() { - const t = useTranslations('components.adminPanelDropdown'); - const [isOpen, setIsOpen] = useState(false); - const dropdownRef = useRef(null); - const pathname = usePathname(); - - useEffect(() => { - function handleClickOutside(event: MouseEvent) { - if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { - setIsOpen(false); - } - } - - if (isOpen) { - document.addEventListener('mousedown', handleClickOutside); - } - - return () => { - document.removeEventListener('mousedown', handleClickOutside); - }; - }, [isOpen]); - - useEffect(() => { - setIsOpen(false); - }, [pathname]); - - const isActiveRoute = adminMenuItems.some(item => pathname.startsWith(item.href)); - - return ( -
- {/* Trigger Button */} - - - {/* Dropdown Menu */} - {isOpen && ( -
-
- {adminMenuItems.map(item => { - const isActive = pathname.startsWith(item.href); - const IconComponent = item.icon; - const name = t(`items.${item.key}` as any); - const description = t(`items.${item.key}Desc` as any); - return ( - - -
-
- {name} -
-
{description}
-
- - ); - })} -
-
- )} -
- ); -} From 5aed7d81cedd25e559aba686a7759fb159649a04 Mon Sep 17 00:00:00 2001 From: David Date: Sat, 13 Jun 2026 12:01:19 +0200 Subject: [PATCH 4/5] fix mdp see --- .../app/[locale]/admin/login/page.tsx | 37 +++++--- .../app/[locale]/admin/users/page.tsx | 26 ++++-- .../app/[locale]/dashboard/profile/page.tsx | 92 ++++++++++++++----- apps/frontend/app/[locale]/login/page.tsx | 46 ++++++---- apps/frontend/app/[locale]/register/page.tsx | 76 ++++++++++----- .../app/[locale]/reset-password/page.tsx | 76 ++++++++++----- apps/frontend/messages/en.json | 4 +- apps/frontend/messages/fr.json | 4 +- .../src/components/admin/CarrierForm.tsx | 27 ++++-- 9 files changed, 280 insertions(+), 108 deletions(-) diff --git a/apps/frontend/app/[locale]/admin/login/page.tsx b/apps/frontend/app/[locale]/admin/login/page.tsx index befdf59..9392a3e 100644 --- a/apps/frontend/app/[locale]/admin/login/page.tsx +++ b/apps/frontend/app/[locale]/admin/login/page.tsx @@ -4,17 +4,19 @@ import { useState } from 'react'; import { useTranslations } from 'next-intl'; import { Link, useRouter } from '@/i18n/navigation'; import Image from 'next/image'; -import { ShieldCheck } from 'lucide-react'; +import { ShieldCheck, Eye, EyeOff } from 'lucide-react'; import { login as apiLogin, getCurrentUser, logout as apiLogout } from '@/lib/api/auth'; import { useAuth } from '@/lib/context/auth-context'; export default function AdminLoginPage() { const t = useTranslations('admin.login'); + const tCommon = useTranslations('common'); const router = useRouter(); const { refreshUser } = useAuth(); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); + const [showPassword, setShowPassword] = useState(false); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(''); @@ -94,17 +96,28 @@ export default function AdminLoginPage() { - setPassword(e.target.value)} - className="input w-full" - placeholder={t('passwordPlaceholder')} - autoComplete="current-password" - disabled={isLoading} - required - /> +
+ setPassword(e.target.value)} + className="input w-full pr-12" + placeholder={t('passwordPlaceholder')} + autoComplete="current-password" + disabled={isLoading} + required + /> + +
+
+
{passwordForm.formState.errors.currentPassword && (

{passwordForm.formState.errors.currentPassword.message} @@ -347,13 +369,24 @@ export default function ProfilePage() { > {t('passwordForm.new')} - +

+ + +
{passwordForm.formState.errors.newPassword && (

{passwordForm.formState.errors.newPassword.message} @@ -369,13 +402,30 @@ export default function ProfilePage() { > {t('passwordForm.confirm')} - +

+ + +
{passwordForm.formState.errors.confirmPassword && (

{passwordForm.formState.errors.confirmPassword.message} diff --git a/apps/frontend/app/[locale]/login/page.tsx b/apps/frontend/app/[locale]/login/page.tsx index 17e4fe3..106ed1c 100644 --- a/apps/frontend/app/[locale]/login/page.tsx +++ b/apps/frontend/app/[locale]/login/page.tsx @@ -5,6 +5,7 @@ import { Link } from '@/i18n/navigation'; import Image from 'next/image'; import { useSearchParams } from 'next/navigation'; import { useTranslations } from 'next-intl'; +import { Eye, EyeOff } from 'lucide-react'; import { useAuth } from '@/lib/context/auth-context'; function AnimatedCounter({ @@ -97,9 +98,11 @@ function LoginPageContent() { const tLogin = useTranslations('auth.login'); const tPanel = useTranslations('auth.sidePanel'); const tFooter = useTranslations('auth.footerLinks'); + const tCommon = useTranslations('common'); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [rememberMe, setRememberMe] = useState(false); + const [showPassword, setShowPassword] = useState(false); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(''); const [fieldErrors, setFieldErrors] = useState({}); @@ -262,22 +265,33 @@ function LoginPageContent() { > {tLogin('passwordLabel')} - +

+ + +
{fieldErrors.password && (

(1); const [statsActive, setStatsActive] = useState(false); @@ -81,6 +83,8 @@ function RegisterPageContent() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); + const [showPassword, setShowPassword] = useState(false); + const [showConfirmPassword, setShowConfirmPassword] = useState(false); const [organizationName, setOrganizationName] = useState(''); const [organizationType, setOrganizationType] = useState('FREIGHT_FORWARDER'); @@ -513,17 +517,28 @@ function RegisterPageContent() { - setPassword(e.target.value)} - className="input w-full" - placeholder={t('passwordPlaceholder')} - autoComplete="new-password" - disabled={isLoading} - /> +

+ setPassword(e.target.value)} + className="input w-full pr-12" + placeholder={t('passwordPlaceholder')} + autoComplete="new-password" + disabled={isLoading} + /> + +

{t('passwordHint')}

@@ -531,17 +546,34 @@ function RegisterPageContent() { - setConfirmPassword(e.target.value)} - className="input w-full" - placeholder={t('passwordPlaceholder')} - autoComplete="new-password" - disabled={isLoading} - /> +
+ setConfirmPassword(e.target.value)} + className="input w-full pr-12" + placeholder={t('passwordPlaceholder')} + autoComplete="new-password" + disabled={isLoading} + /> + +
+

{t('passwordHint')}

@@ -177,17 +192,34 @@ function ResetPasswordContent() { - setConfirmPassword(e.target.value)} - className="input w-full" - placeholder="••••••••••••" - autoComplete="new-password" - disabled={loading} - /> +
+ setConfirmPassword(e.target.value)} + className="input w-full pr-12" + placeholder="••••••••••••" + autoComplete="new-password" + disabled={loading} + /> + +
+ {/* Rate Limit */} From 6b9ad95811c0779dd3f37c60fd04b4fa093f322e Mon Sep 17 00:00:00 2001 From: David Date: Sat, 13 Jun 2026 12:17:06 +0200 Subject: [PATCH 5/5] fix logs --- .../src/application/auth/auth.module.ts | 4 + .../src/application/auth/auth.service.ts | 16 +++- .../controllers/auth.controller.ts | 89 +++++++++++++++++-- 3 files changed, 99 insertions(+), 10 deletions(-) diff --git a/apps/backend/src/application/auth/auth.module.ts b/apps/backend/src/application/auth/auth.module.ts index e044f9f..2647bb5 100644 --- a/apps/backend/src/application/auth/auth.module.ts +++ b/apps/backend/src/application/auth/auth.module.ts @@ -22,6 +22,7 @@ import { InvitationService } from '../services/invitation.service'; import { InvitationsController } from '../controllers/invitations.controller'; import { EmailModule } from '../../infrastructure/email/email.module'; import { SubscriptionsModule } from '../subscriptions/subscriptions.module'; +import { AuditModule } from '../audit/audit.module'; @Module({ imports: [ @@ -53,6 +54,9 @@ import { SubscriptionsModule } from '../subscriptions/subscriptions.module'; // Subscriptions module for license checks SubscriptionsModule, + + // Audit module for login/logout tracking + AuditModule, ], controllers: [AuthController, InvitationsController], providers: [ diff --git a/apps/backend/src/application/auth/auth.service.ts b/apps/backend/src/application/auth/auth.service.ts index 1808174..040ff1b 100644 --- a/apps/backend/src/application/auth/auth.service.ts +++ b/apps/backend/src/application/auth/auth.service.ts @@ -235,9 +235,11 @@ export class AuthService { * The revocation list lives in Redis with a TTL matching the token's * remaining lifetime, so entries clean themselves up. */ - async logout(refreshToken?: string): Promise { + async logout( + refreshToken?: string + ): Promise<{ userId: string; email: string; organizationId: string } | null> { if (!refreshToken) { - return; + return null; } try { @@ -248,9 +250,19 @@ export class AuthService { await this.cache.set(this.revokedTokenKey(refreshToken), true, remainingSeconds); this.logger.log(`Refresh token revoked for user: ${payload?.email ?? 'unknown'}`); + + if (payload?.sub) { + return { + userId: payload.sub, + email: payload.email, + organizationId: payload.organizationId, + }; + } + return null; } catch (error) { // Never block logout on revocation failures — log and continue this.logger.error(`Failed to revoke refresh token: ${error}`); + return null; } } diff --git a/apps/backend/src/application/controllers/auth.controller.ts b/apps/backend/src/application/controllers/auth.controller.ts index 75e99fe..2735571 100644 --- a/apps/backend/src/application/controllers/auth.controller.ts +++ b/apps/backend/src/application/controllers/auth.controller.ts @@ -34,6 +34,8 @@ import { JwtAuthGuard } from '../guards/jwt-auth.guard'; import { UserRepository, USER_REPOSITORY } from '@domain/ports/out/user.repository'; import { UserMapper } from '../mappers/user.mapper'; import { InvitationService } from '../services/invitation.service'; +import { AuditService } from '../services/audit.service'; +import { AuditAction } from '@domain/entities/audit-log.entity'; import { AUTH_COOKIE_NAMES, authCookieOptions, @@ -72,9 +74,26 @@ export class AuthController { private readonly authService: AuthService, @Inject(USER_REPOSITORY) private readonly userRepository: UserRepository, private readonly invitationService: InvitationService, + private readonly auditService: AuditService, @Inject(EMAIL_PORT) private readonly emailService: EmailPort ) {} + /** + * Extract the client IP and user agent from the request so we can record + * *who* connected and *from where* in the audit trail. + */ + private getClientInfo(req: Request): { ipAddress?: string; userAgent?: string } { + const forwardedFor = req.headers['x-forwarded-for']; + const ipAddress = + (Array.isArray(forwardedFor) ? forwardedFor[0] : forwardedFor?.split(',')[0]?.trim()) || + req.ip || + req.socket?.remoteAddress; + return { + ipAddress, + userAgent: req.headers['user-agent'], + }; + } + /** * Deliver tokens as httpOnly cookies so they are out of reach of XSS. * When rememberMe is false the cookies are session-scoped (cleared when @@ -208,18 +227,59 @@ export class AuthController { }) async login( @Body() dto: LoginDto, + @Req() req: Request, @Res({ passthrough: true }) res: Response ): Promise { const rememberMe = dto.rememberMe === true; - const result = await this.authService.login(dto.email, dto.password, rememberMe); + const { ipAddress, userAgent } = this.getClientInfo(req); - this.setAuthCookies(res, result, rememberMe); + try { + const result = await this.authService.login(dto.email, dto.password, rememberMe); - return { - accessToken: result.accessToken, - refreshToken: result.refreshToken, - user: result.user, - }; + this.setAuthCookies(res, result, rememberMe); + + // Audit log: record who logged in, when and from where + await this.auditService.logSuccess( + AuditAction.USER_LOGIN, + result.user.id, + result.user.email, + result.user.organizationId, + { + resourceType: 'user', + resourceId: result.user.id, + ipAddress, + userAgent, + metadata: { rememberMe }, + } + ); + + this.logger.log(`Login success: ${result.user.email} from ${ipAddress ?? 'unknown IP'}`); + + return { + accessToken: result.accessToken, + refreshToken: result.refreshToken, + user: result.user, + }; + } catch (error: any) { + // Audit log: record failed login attempts (the attempted email is the + // only identity we have — the credentials did not match a valid user) + await this.auditService.logFailure( + AuditAction.USER_LOGIN, + 'unknown', + dto.email, + 'unknown', + error?.message || 'Invalid credentials', + { + resourceType: 'user', + ipAddress, + userAgent, + } + ); + + this.logger.warn(`Login failed for ${dto.email} from ${ipAddress ?? 'unknown IP'}`); + + throw error; + } } /** @@ -302,9 +362,22 @@ export class AuthController { ): Promise<{ message: string }> { const refreshToken = req.cookies?.[AUTH_COOKIE_NAMES.refreshToken]; - await this.authService.logout(refreshToken); + const loggedOutUser = await this.authService.logout(refreshToken); this.clearAuthCookies(res); + // Audit log: record who logged out and when + if (loggedOutUser) { + const { ipAddress, userAgent } = this.getClientInfo(req); + await this.auditService.logSuccess( + AuditAction.USER_LOGOUT, + loggedOutUser.userId, + loggedOutUser.email, + loggedOutUser.organizationId, + { resourceType: 'user', resourceId: loggedOutUser.userId, ipAddress, userAgent } + ); + this.logger.log(`Logout: ${loggedOutUser.email} from ${ipAddress ?? 'unknown IP'}`); + } + return { message: 'Logout successful' }; }