From ba4da3e35c2b25bff1f9bafd181ca8c33ac58751 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 1 Apr 2025 12:04:14 -0400 Subject: [PATCH 01/34] feature/IO-2885-IntelliPay-App-Postback-Support - Packages --- client/package-lock.json | 553 +++++++++---- client/package.json | 28 +- package-lock.json | 1636 +++++++++++++++++++------------------- package.json | 22 +- 4 files changed, 1227 insertions(+), 1012 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index af00cf920..dbfeed6ca 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -9,23 +9,23 @@ "version": "0.2.1", "hasInstallScript": true, "dependencies": { - "@ant-design/pro-layout": "^7.22.3", + "@ant-design/pro-layout": "^7.22.4", "@apollo/client": "^3.13.5", "@emotion/is-prop-valid": "^1.3.1", "@fingerprintjs/fingerprintjs": "^4.6.1", "@firebase/analytics": "^0.10.12", - "@firebase/app": "^0.11.3", - "@firebase/auth": "^1.9.1", + "@firebase/app": "^0.11.4", + "@firebase/auth": "^1.10.0", "@firebase/firestore": "^4.7.10", "@firebase/messaging": "^0.12.17", "@jsreport/browser-client": "^3.1.0", "@reduxjs/toolkit": "^2.6.1", - "@sentry/cli": "^2.42.4", - "@sentry/react": "^9.9.0", - "@sentry/vite-plugin": "^3.2.2", - "@splitsoftware/splitio-react": "^2.0.1", + "@sentry/cli": "^2.43.0", + "@sentry/react": "^9.10.1", + "@sentry/vite-plugin": "^3.2.4", + "@splitsoftware/splitio-react": "^2.1.0", "@tanem/react-nprogress": "^5.0.53", - "antd": "^5.24.5", + "antd": "^5.24.6", "apollo-link-logger": "^2.0.1", "apollo-link-sentry": "^4.2.0", "autosize": "^6.0.1", @@ -70,7 +70,7 @@ "react-resizable": "^3.0.5", "react-router-dom": "^6.30.0", "react-sticky": "^6.0.3", - "react-virtuoso": "^4.12.5", + "react-virtuoso": "^4.12.6", "recharts": "^2.15.0", "redux": "^5.0.1", "redux-actions": "^3.0.3", @@ -78,7 +78,7 @@ "redux-saga": "^1.3.0", "redux-state-sync": "^3.1.4", "reselect": "^5.1.1", - "sass": "^1.86.0", + "sass": "^1.86.1", "socket.io-client": "^4.8.1", "styled-components": "^6.1.16", "subscriptions-transport-ws": "^0.11.0", @@ -95,7 +95,7 @@ "@emotion/react": "^11.14.0", "@eslint/js": "^9.23.0", "@playwright/test": "^1.51.1", - "@sentry/webpack-plugin": "^3.2.2", + "@sentry/webpack-plugin": "^3.2.4", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.2.0", @@ -114,13 +114,13 @@ "react-error-overlay": "^6.1.0", "redux-logger": "^3.0.6", "source-map-explorer": "^2.5.3", - "vite": "^6.2.3", + "vite": "^6.2.4", "vite-plugin-babel": "^1.3.0", "vite-plugin-eslint": "^1.8.1", "vite-plugin-node-polyfills": "^0.23.0", - "vite-plugin-pwa": "^0.21.2", + "vite-plugin-pwa": "^1.0.0", "vite-plugin-style-import": "^2.0.0", - "vitest": "^3.0.9", + "vitest": "^3.1.1", "workbox-window": "^7.3.0" }, "engines": { @@ -252,15 +252,15 @@ } }, "node_modules/@ant-design/pro-layout": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@ant-design/pro-layout/-/pro-layout-7.22.3.tgz", - "integrity": "sha512-di/EOMDuoMDRjBweqesYyCxEYr2LCmO82y6A4bSwmmJ6ehxN7HGC73Wx4RuBkzDR7kHLTOXt7WxI6875ENT8mg==", + "version": "7.22.4", + "resolved": "https://registry.npmjs.org/@ant-design/pro-layout/-/pro-layout-7.22.4.tgz", + "integrity": "sha512-X2WO4L2itXemX4zhS+0NG+8kXQD5SX9sG+zjx/15BmIO3FvsUGqOHgoCg0vhd424EiyPj7WtdMZJ39G1xdgDwA==", "license": "MIT", "dependencies": { "@ant-design/cssinjs": "^1.21.1", "@ant-design/icons": "^5.0.0", - "@ant-design/pro-provider": "2.15.3", - "@ant-design/pro-utils": "2.16.4", + "@ant-design/pro-provider": "2.15.4", + "@ant-design/pro-utils": "2.17.0", "@babel/runtime": "^7.18.0", "@umijs/route-utils": "^4.0.0", "@umijs/use-params": "^1.0.9", @@ -300,9 +300,9 @@ } }, "node_modules/@ant-design/pro-provider": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/@ant-design/pro-provider/-/pro-provider-2.15.3.tgz", - "integrity": "sha512-jUBCuRrhAXNMumSZ++704/zEg/7U1k2N3jMVBgtirvVaCAk5O9iZQKK4W3O3LRFc+D8yO16sXjsxhawvdGL4cA==", + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/@ant-design/pro-provider/-/pro-provider-2.15.4.tgz", + "integrity": "sha512-DBX0JNUNOYXAucVqd/zTdqtXckCDqr2Lo85KIku2YzWdhptDPDZRTNqL04JShjGejDl8fzwQ8yREHgVUfzn6Gg==", "license": "MIT", "dependencies": { "@ant-design/cssinjs": "^1.21.1", @@ -319,13 +319,13 @@ } }, "node_modules/@ant-design/pro-utils": { - "version": "2.16.4", - "resolved": "https://registry.npmjs.org/@ant-design/pro-utils/-/pro-utils-2.16.4.tgz", - "integrity": "sha512-PFxqF0fsUsLj8ORvJSuMgVv9NDHwAxZaglzPN/u3jZX7rWYcrHD04EMJEXooZaSyT6Q4+j7SqXDx6oBsdb9zNw==", + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@ant-design/pro-utils/-/pro-utils-2.17.0.tgz", + "integrity": "sha512-hHKUISjMEoS+E5ltJWyvNTrlEA3IimZNxtDrEhorRIbgVYAlmEN5Mj/ESSofzDM3+UlxiI5+A/Y6IHkByTfDEA==", "license": "MIT", "dependencies": { "@ant-design/icons": "^5.0.0", - "@ant-design/pro-provider": "2.15.3", + "@ant-design/pro-provider": "2.15.4", "@babel/runtime": "^7.18.0", "classnames": "^2.3.2", "dayjs": "^1.11.10", @@ -2926,9 +2926,9 @@ } }, "node_modules/@firebase/app": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.11.3.tgz", - "integrity": "sha512-QlTZl/RcqPSonYxB87n8KgAUW2L6ZZz0W4D91PVmQ1tJPsKsKPrWAFHL0ii2cQW6FxTxfNjbZ7kucuIcKXk3tw==", + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.11.4.tgz", + "integrity": "sha512-GPREsZjfSaHzwyC6cI/Cqvzf6zxqMzya+25tSpUstdqC2w0IdfxEfOMjfdW7bDfVEf4Rb4Nb6gfoOAgVSp4c4g==", "license": "Apache-2.0", "dependencies": { "@firebase/component": "0.6.13", @@ -2942,9 +2942,9 @@ } }, "node_modules/@firebase/auth": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.9.1.tgz", - "integrity": "sha512-9KKo5SNVkyJzftsW+daS+PGDbeJ+MFJWXQFHDqqPPH3acWHtiNnGHH5HGpIJErEELrsm9xMPie5zfZ0XpGU8+w==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.10.0.tgz", + "integrity": "sha512-S7SqBsN7sIQsftNE3bitLlK+4bWrTHY+Rx2JFlNitgVYu2nK8W8ZQrkG8GCEwiFPq0B2vZ9pO5kVTFfq2sP96A==", "license": "Apache-2.0", "dependencies": { "@firebase/component": "0.6.13", @@ -4178,88 +4178,88 @@ "license": "MIT" }, "node_modules/@sentry-internal/browser-utils": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.9.0.tgz", - "integrity": "sha512-V/YhKLis98JFkqBGZaEBlDNFpJHJjoCvNb05raAYXdITfDIl37Kxqj0zX+IzyRhqnswkQ+DBTyoEoci09IR2bQ==", + "version": "9.10.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.10.1.tgz", + "integrity": "sha512-O/ibpHbKfpG+xtZuEzbLNtLcbanRcDYGxT+QbslVItmcS9GjMSwvMpp1jnD9Y7/LIFtv7O1gJZ9Hrz///lLprw==", "license": "MIT", "dependencies": { - "@sentry/core": "9.9.0" + "@sentry/core": "9.10.1" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/feedback": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.9.0.tgz", - "integrity": "sha512-hrxuOLm0Xsnx75hTNt3eLgNNjER3egrHZShdRzlMiakfKpA9f2X10z75vlZmT5ZUygDQnp9UVUnu28cDuVb9Zw==", + "version": "9.10.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.10.1.tgz", + "integrity": "sha512-DM32eAzRvXk36iGBWtlLZA88QzOFBODd+kbz55X4Py+1bDNdRc3Vl6214uuAr7iweHcOQy1rIvmAeO8Xusp7tQ==", "license": "MIT", "dependencies": { - "@sentry/core": "9.9.0" + "@sentry/core": "9.10.1" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/replay": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.9.0.tgz", - "integrity": "sha512-EWczKMu3qiZ0SUUWU3zkGod+AWD/VQCLiQw+tw+PEpdHbRZIdYKsEptengZCFKthrwe2QmYpVCTSRxGvujJ/6g==", + "version": "9.10.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.10.1.tgz", + "integrity": "sha512-nqG33NwojtteL8e3Qg/SOu0BsTJ9R7AjpmQIlOpFGL007nzKgcJHOngewd7FEHyB+F3iOI0MoI9iEWhRFEGRLw==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "9.9.0", - "@sentry/core": "9.9.0" + "@sentry-internal/browser-utils": "9.10.1", + "@sentry/core": "9.10.1" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.9.0.tgz", - "integrity": "sha512-YK0ixGjquahGpNsQskCEVwycdHlwNBLCx9XJr1BmGnlOw6fUCmpyVetaGg/ZyhkzKGNXAGoTa4s7FUFnAG4bKg==", + "version": "9.10.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.10.1.tgz", + "integrity": "sha512-fxrpqElqdsAQrzVly0V/XaljhAlwwMk+iGyf+wZeK6RwEPVxtoxXVfx7fEEtPn+gortqQR09N/zH179hefjuaw==", "license": "MIT", "dependencies": { - "@sentry-internal/replay": "9.9.0", - "@sentry/core": "9.9.0" + "@sentry-internal/replay": "9.10.1", + "@sentry/core": "9.10.1" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/babel-plugin-component-annotate": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.2.2.tgz", - "integrity": "sha512-D+SKQ266ra/wo87s9+UI/rKQi3qhGPCR8eSCDe0VJudhjHsqyNU+JJ5lnIGCgmZaWFTXgdBP/gdr1Iz1zqGs4Q==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.2.4.tgz", + "integrity": "sha512-yBzRn3GEUSv1RPtE4xB4LnuH74ZxtdoRJ5cmQ9i6mzlmGDxlrnKuvem5++AolZTE9oJqAD3Tx2rd1PqmpWnLoA==", "license": "MIT", "engines": { "node": ">= 14" } }, "node_modules/@sentry/browser": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.9.0.tgz", - "integrity": "sha512-pIMdkOC+iggZefBs6ck5fL1mBhbLzjdw/8K99iqSeDh+lLvmlHVZajAhPlmw50xfH8CyQ1s22dhcL+zXbg3NKw==", + "version": "9.10.1", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.10.1.tgz", + "integrity": "sha512-9RWjcyskhnDK2Q6LntFR90EqZD5+DXcXNqeTlE+mpVf65y7wz+9SIuVjAMP7qiDBwfxNbmTxiVCXeCuQnnATsQ==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "9.9.0", - "@sentry-internal/feedback": "9.9.0", - "@sentry-internal/replay": "9.9.0", - "@sentry-internal/replay-canvas": "9.9.0", - "@sentry/core": "9.9.0" + "@sentry-internal/browser-utils": "9.10.1", + "@sentry-internal/feedback": "9.10.1", + "@sentry-internal/replay": "9.10.1", + "@sentry-internal/replay-canvas": "9.10.1", + "@sentry/core": "9.10.1" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/bundler-plugin-core": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.2.2.tgz", - "integrity": "sha512-YGrtmqQ2jMixccX2slVG/Lw7pCGJL3DGB3clmY9mO8QBEBIN3/gEANiHJVWwRidpUOS/0b7yVVGAdwZ87oPwTg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.2.4.tgz", + "integrity": "sha512-YMj9XW5W2JA89EeweE7CPKLDz245LBsI1JhCmqpt/bjSvmsSIAAPsLYnvIJBS3LQFm0OhtG8NB54PTi96dAcMA==", "license": "MIT", "dependencies": { "@babel/core": "^7.18.5", - "@sentry/babel-plugin-component-annotate": "3.2.2", + "@sentry/babel-plugin-component-annotate": "3.2.4", "@sentry/cli": "2.42.2", "dotenv": "^16.3.1", "find-up": "^5.0.0", @@ -4300,6 +4300,105 @@ "@sentry/cli-win32-x64": "2.42.2" } }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-darwin": { + "version": "2.42.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.42.2.tgz", + "integrity": "sha512-GtJSuxER7Vrp1IpxdUyRZzcckzMnb4N5KTW7sbTwUiwqARRo+wxS+gczYrS8tdgtmXs5XYhzhs+t4d52ITHMIg==", + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-arm": { + "version": "2.42.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.42.2.tgz", + "integrity": "sha512-7udCw+YL9lwq+9eL3WLspvnuG+k5Icg92YE7zsteTzWLwgPVzaxeZD2f8hwhsu+wmL+jNqbpCRmktPteh3i2mg==", + "cpu": [ + "arm" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-arm64": { + "version": "2.42.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.42.2.tgz", + "integrity": "sha512-BOxzI7sgEU5Dhq3o4SblFXdE9zScpz6EXc5Zwr1UDZvzgXZGosUtKVc7d1LmkrHP8Q2o18HcDWtF3WvJRb5Zpw==", + "cpu": [ + "arm64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-i686": { + "version": "2.42.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.42.2.tgz", + "integrity": "sha512-Sw/dQp5ZPvKnq3/y7wIJyxTUJYPGoTX/YeMbDs8BzDlu9to2LWV3K3r7hE7W1Lpbaw4tSquUHiQjP5QHCOS7aQ==", + "cpu": [ + "x86", + "ia32" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-x64": { + "version": "2.42.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.42.2.tgz", + "integrity": "sha512-mU4zUspAal6TIwlNLBV5oq6yYqiENnCWSxtSQVzWs0Jyq97wtqGNG9U+QrnwjJZ+ta/hvye9fvL2X25D/RxHQw==", + "cpu": [ + "x64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-win32-i686": { + "version": "2.42.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.42.2.tgz", + "integrity": "sha512-iHvFHPGqgJMNqXJoQpqttfsv2GI3cGodeTq4aoVLU/BT3+hXzbV0x1VpvvEhncJkDgDicJpFLM8sEPHb3b8abw==", + "cpu": [ + "x86", + "ia32" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-win32-x64": { "version": "2.42.2", "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.42.2.tgz", @@ -4338,9 +4437,9 @@ } }, "node_modules/@sentry/cli": { - "version": "2.42.4", - "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.42.4.tgz", - "integrity": "sha512-BoSZDAWJiz/40tu6LuMDkSgwk4xTsq6zwqYoUqLU3vKBR/VsaaQGvu6EWxZXORthfZU2/5Agz0+t220cge6VQw==", + "version": "2.43.0", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.43.0.tgz", + "integrity": "sha512-gBE3bkx+PBJxopTrzIJLX4xHe5S0w87q5frIveWKDZ5ulVIU6YWnVumay0y07RIEweUEj3IYva1qH6HG2abfiA==", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { @@ -4357,19 +4456,135 @@ "node": ">= 10" }, "optionalDependencies": { - "@sentry/cli-darwin": "2.42.4", - "@sentry/cli-linux-arm": "2.42.4", - "@sentry/cli-linux-arm64": "2.42.4", - "@sentry/cli-linux-i686": "2.42.4", - "@sentry/cli-linux-x64": "2.42.4", - "@sentry/cli-win32-i686": "2.42.4", - "@sentry/cli-win32-x64": "2.42.4" + "@sentry/cli-darwin": "2.43.0", + "@sentry/cli-linux-arm": "2.43.0", + "@sentry/cli-linux-arm64": "2.43.0", + "@sentry/cli-linux-i686": "2.43.0", + "@sentry/cli-linux-x64": "2.43.0", + "@sentry/cli-win32-arm64": "2.43.0", + "@sentry/cli-win32-i686": "2.43.0", + "@sentry/cli-win32-x64": "2.43.0" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.43.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.43.0.tgz", + "integrity": "sha512-0MYvRHJowXOMNY5W6XF4p9GQNH3LuQ+IHAQwVbZOsfwnEv8e20rf9BiPPzmJ9sIjZSWYR4yIqm6dBp6ABJFbGQ==", + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.43.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.43.0.tgz", + "integrity": "sha512-c2Fwb6HrFL1nbaGV4uRhHC1wEJPR+wfpKN5y06PgSNNbd10YrECAB3tqBHXC8CEmhuDyFR+ORGZ7VbswfCWEEQ==", + "cpu": [ + "arm" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.43.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.43.0.tgz", + "integrity": "sha512-7URSaNjbEJQZyYJ33XK3pVKl6PU2oO9ETF6R/4Cz2FmU3fecACLKVldv7+OuNl9aspLZ62mnPMDvT732/Fp2Ug==", + "cpu": [ + "arm64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.43.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.43.0.tgz", + "integrity": "sha512-bFo/tpMZeMJ275HPGmAENREchnBxhALOOpZAphSyalUu3pGZ+EETEtlSLrKyVNJo26Dye5W7GlrYUV9+rkyCtg==", + "cpu": [ + "x86", + "ia32" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.43.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.43.0.tgz", + "integrity": "sha512-EbAmKXUNU/Ii4pNGVRCepU6ks1M43wStMKx3pibrUTllrrCwqYKyPxRRdoFYySHkduwCxnoKZcLEg9vWZ3qS6A==", + "cpu": [ + "x64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-arm64": { + "version": "2.43.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.43.0.tgz", + "integrity": "sha512-KmJRCdQQGLSErJvrcGcN+yWo68m+5OdluhyJHsVYMOQknwu8YMOWLm12EIa+4t4GclDvwg5xcxLccCuiWMJUZw==", + "cpu": [ + "arm64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.43.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.43.0.tgz", + "integrity": "sha512-ZWxZdOyZX7NJ/CTskzg+dJ2xTpobFLXVNMOMq0HiwdhqXP2zYYJzKnIt3mHNJYA40zYFODGSgxIamodjpB8BuA==", + "cpu": [ + "x86", + "ia32" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" } }, "node_modules/@sentry/cli-win32-x64": { - "version": "2.42.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.42.4.tgz", - "integrity": "sha512-OIBj3uaQ6nAERSm5Dcf8UIhyElEEwMNsZEEppQpN4IKl0mrwb/57AznM23Dvpu6GR8WGbVQUSolt879YZR5E9g==", + "version": "2.43.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.43.0.tgz", + "integrity": "sha512-S/IRQYAziEnjpyROhnqzTqShDq3m8jcevXx+q5f49uQnFbfYcTgS1sdrEPqqao/K2boOWbffxYtTkvBiB/piQQ==", "cpu": [ "x64" ], @@ -4404,22 +4619,22 @@ } }, "node_modules/@sentry/core": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.9.0.tgz", - "integrity": "sha512-GxKvx8PSgoWhLLS+/WBGIXy7rsFcnJBPDqFXIfcAGy89k2j06d9IP0kiIc63qBGStSUkh5FFJLPTakZ5RXiFXA==", + "version": "9.10.1", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.10.1.tgz", + "integrity": "sha512-TE2zZV3Od4131mZNgFo2Mv4aKU8FXxL0s96yqRvmV+8AU57mJoycMXBnmNSYfWuDICbPJTVAp+3bYMXwX7N5YA==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@sentry/react": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.9.0.tgz", - "integrity": "sha512-7BE2Lx5CNtHtlNSS7Z9HxKquohC0xhdFceO3NlMXlx+dZuVCMoQmLISB8SQEcHw+2VO24MvtP3LPEzdeNbkIfg==", + "version": "9.10.1", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.10.1.tgz", + "integrity": "sha512-DYBs3F+F2elWEhWvp3HmBmORhAlTBbY0KsRj+Lt2mOSEfiz8WWrS3Ibe+9QmErVdjQZy68ic9Yt84MHL/rlmkQ==", "license": "MIT", "dependencies": { - "@sentry/browser": "9.9.0", - "@sentry/core": "9.9.0", + "@sentry/browser": "9.10.1", + "@sentry/core": "9.10.1", "hoist-non-react-statics": "^3.3.2" }, "engines": { @@ -4430,12 +4645,12 @@ } }, "node_modules/@sentry/vite-plugin": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-3.2.2.tgz", - "integrity": "sha512-WSkHOhZszMrIE9zmx2l4JhMnMlZmN/yAoHyf59pwFLIMctuZak6lNPbTbIFkFHDzIJ9Nut5RAVsw1qjmWc1PTA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-3.2.4.tgz", + "integrity": "sha512-ZRn5TLlq5xtwKOqaWP+XqS1PYVfbBCgsbMk7wW2Ly6EgF9wYePvtLqKgYnE3hwPg2LpBnRPR2ti1ohlUkR+wXA==", "license": "MIT", "dependencies": { - "@sentry/bundler-plugin-core": "3.2.2", + "@sentry/bundler-plugin-core": "3.2.4", "unplugin": "1.0.1" }, "engines": { @@ -4443,13 +4658,13 @@ } }, "node_modules/@sentry/webpack-plugin": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-3.2.2.tgz", - "integrity": "sha512-6OkVKNOjKk8P9j7oh6svZ+kEP1i9YIHBC2aGWL2XsgeZTIrMBxJAXtOf+qSrfMAxEtibSroGVOMQc/y3WJTQtg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-3.2.4.tgz", + "integrity": "sha512-LCuNu5LXPSCq2BNke1zvEW8CXL4SPBsCjYexAx51PZ6Lp87VxWcCxGqXhr37MGpYwY10A1r31/XOe69iXHJjGA==", "dev": true, "license": "MIT", "dependencies": { - "@sentry/bundler-plugin-core": "3.2.2", + "@sentry/bundler-plugin-core": "3.2.4", "unplugin": "1.0.1", "uuid": "^9.0.0" }, @@ -4467,12 +4682,12 @@ "license": "MIT" }, "node_modules/@splitsoftware/splitio": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio/-/splitio-11.0.3.tgz", - "integrity": "sha512-UtoixGfICCj52FfaVdI186Czw0qCvvEyCw/OtJVTsgM4Zq0k2mY8yKzQ7tSB/HJtzbUVnuPoxkwEcj0479stmg==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio/-/splitio-11.2.0.tgz", + "integrity": "sha512-M0TK8jlhLBv4+PchzBvn5R33MZzvRTInauGKGeaTpbxI+zq/g58meaNEiLRJxNw1lAWOjPhPRLIVg+V3Mf+uaA==", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.0.2", + "@splitsoftware/splitio-commons": "2.2.0", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -4485,9 +4700,9 @@ } }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.2.tgz", - "integrity": "sha512-r2m3kwWnSuROT+7zTzhWBrM0DMRBGJNQcTyvXw8zLPPmBs/PnmAnxCy7uRpfMHOGbP9Q3Iju0bU/H5dG8svyiw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.2.0.tgz", + "integrity": "sha512-ywWDh2fM4/EqJ1AByjXM13gAal+z/WSGiBQ5OZmjpL/iqFLENy3yo/GwsxR/ataOi27XbRQTeQbE/eD7HVnWiA==", "license": "Apache-2.0", "dependencies": { "@types/ioredis": "^4.28.0", @@ -4503,12 +4718,12 @@ } }, "node_modules/@splitsoftware/splitio-react": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-2.0.1.tgz", - "integrity": "sha512-Jky3o46w+CO2+x6TN3kzQ4CoASKX4PqtDqSTHY6n5JXBC2CqhlXuvODoMYXKzolOsndku+aL7+Mlavbn7b+2lw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-2.1.0.tgz", + "integrity": "sha512-iAGXl/qadHVFUQA/+asX8UGwDPpNi6WCKhNIzLZ6NSvt38+M8Bpc3CMnkYNEXsNsz1J+C26ICsMZ067YQ96k6g==", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio": "11.0.3", + "@splitsoftware/splitio": "11.2.0", "memoize-one": "^5.1.1", "shallowequal": "^1.1.0", "tslib": "^2.3.1" @@ -5281,14 +5496,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz", - "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.1.tgz", + "integrity": "sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.9", - "@vitest/utils": "3.0.9", + "@vitest/spy": "3.1.1", + "@vitest/utils": "3.1.1", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -5297,13 +5512,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz", - "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.1.tgz", + "integrity": "sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.9", + "@vitest/spy": "3.1.1", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -5344,9 +5559,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", - "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.1.tgz", + "integrity": "sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==", "dev": true, "license": "MIT", "dependencies": { @@ -5357,13 +5572,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz", - "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.1.tgz", + "integrity": "sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.0.9", + "@vitest/utils": "3.1.1", "pathe": "^2.0.3" }, "funding": { @@ -5378,13 +5593,13 @@ "license": "MIT" }, "node_modules/@vitest/snapshot": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz", - "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.1.tgz", + "integrity": "sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.9", + "@vitest/pretty-format": "3.1.1", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -5410,9 +5625,9 @@ "license": "MIT" }, "node_modules/@vitest/spy": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz", - "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.1.tgz", + "integrity": "sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5423,13 +5638,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz", - "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.1.tgz", + "integrity": "sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.9", + "@vitest/pretty-format": "3.1.1", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, @@ -5561,9 +5776,9 @@ } }, "node_modules/antd": { - "version": "5.24.5", - "resolved": "https://registry.npmjs.org/antd/-/antd-5.24.5.tgz", - "integrity": "sha512-1lAv/G+9ewQanyoAo3JumQmIlVxwo5QwWGb6QCHYc40Cq0NxC/EzITcjsgq1PSaTUpLkKq8A2l7Fjtu47vqQBg==", + "version": "5.24.6", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.24.6.tgz", + "integrity": "sha512-xIlTa/1CTbgkZsdU/dOXkYvJXb9VoiMwsaCzpKFH2zAEY3xqOfwQ57/DdG7lAdrWP7QORtSld4UA6suxzuTHXw==", "license": "MIT", "dependencies": { "@ant-design/colors": "^7.2.0", @@ -14159,9 +14374,9 @@ } }, "node_modules/react-virtuoso": { - "version": "4.12.5", - "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.12.5.tgz", - "integrity": "sha512-YeCbRRsC9CLf0buD0Rct7WsDbzf+yBU1wGbo05/XjbcN2nJuhgh040m3y3+6HVogTZxEqVm45ac9Fpae4/MxRQ==", + "version": "4.12.6", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.12.6.tgz", + "integrity": "sha512-bfvS6aCL1ehXmq39KRiz/vxznGUbtA27I5I24TYCe1DhMf84O3aVNCIwrSjYQjkJGJGzY46ihdN8WkYlemuhMQ==", "license": "MIT", "peerDependencies": { "react": ">=16 || >=17 || >= 18 || >= 19", @@ -14855,9 +15070,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.86.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.0.tgz", - "integrity": "sha512-zV8vGUld/+mP4KbMLJMX7TyGCuUp7hnkOScgCMsWuHtns8CWBoz+vmEhoGMXsaJrbUP8gj+F1dLvVe79sK8UdA==", + "version": "1.86.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.1.tgz", + "integrity": "sha512-Yaok4XELL1L9Im/ZUClKu//D2OP1rOljKj0Gf34a+GzLbMveOzL7CfqYo+JUa5Xt1nhTCW+OcKp/FtR7/iqj1w==", "license": "MIT", "dependencies": { "chokidar": "^4.0.0", @@ -15875,9 +16090,9 @@ } }, "node_modules/swr": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.2.tgz", - "integrity": "sha512-RosxFpiabojs75IwQ316DGoDRmOqtiAj0tg8wCcbEu4CiLZBs/a9QNtHV7TUfDXmmlgqij/NqzKq/eLelyv9xA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.3.tgz", + "integrity": "sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==", "license": "MIT", "dependencies": { "dequal": "^2.0.3", @@ -16903,9 +17118,9 @@ } }, "node_modules/vite": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz", - "integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==", + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.4.tgz", + "integrity": "sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==", "dev": true, "license": "MIT", "dependencies": { @@ -16975,9 +17190,9 @@ } }, "node_modules/vite-node": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz", - "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.1.tgz", + "integrity": "sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==", "dev": true, "license": "MIT", "dependencies": { @@ -17084,9 +17299,9 @@ } }, "node_modules/vite-plugin-pwa": { - "version": "0.21.2", - "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.21.2.tgz", - "integrity": "sha512-vFhH6Waw8itNu37hWUJxL50q+CBbNcMVzsKaYHQVrfxTt3ihk3PeLO22SbiP1UNWzcEPaTQv+YVxe4G0KOjAkg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-1.0.0.tgz", + "integrity": "sha512-X77jo0AOd5OcxmWj3WnVti8n7Kw2tBgV1c8MCXFclrSlDV23ePzv2eTDIALXI2Qo6nJ5pZJeZAuX0AawvRfoeA==", "dev": true, "license": "MIT", "dependencies": { @@ -17103,7 +17318,7 @@ "url": "https://github.com/sponsors/antfu" }, "peerDependencies": { - "@vite-pwa/assets-generator": "^0.2.6", + "@vite-pwa/assets-generator": "^1.0.0", "vite": "^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", "workbox-build": "^7.3.0", "workbox-window": "^7.3.0" @@ -17216,31 +17431,31 @@ } }, "node_modules/vitest": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz", - "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.1.tgz", + "integrity": "sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.0.9", - "@vitest/mocker": "3.0.9", - "@vitest/pretty-format": "^3.0.9", - "@vitest/runner": "3.0.9", - "@vitest/snapshot": "3.0.9", - "@vitest/spy": "3.0.9", - "@vitest/utils": "3.0.9", + "@vitest/expect": "3.1.1", + "@vitest/mocker": "3.1.1", + "@vitest/pretty-format": "^3.1.1", + "@vitest/runner": "3.1.1", + "@vitest/snapshot": "3.1.1", + "@vitest/spy": "3.1.1", + "@vitest/utils": "3.1.1", "chai": "^5.2.0", "debug": "^4.4.0", - "expect-type": "^1.1.0", + "expect-type": "^1.2.0", "magic-string": "^0.30.17", "pathe": "^2.0.3", - "std-env": "^3.8.0", + "std-env": "^3.8.1", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.9", + "vite-node": "3.1.1", "why-is-node-running": "^2.3.0" }, "bin": { @@ -17256,8 +17471,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.9", - "@vitest/ui": "3.0.9", + "@vitest/browser": "3.1.1", + "@vitest/ui": "3.1.1", "happy-dom": "*", "jsdom": "*" }, diff --git a/client/package.json b/client/package.json index db79ba1eb..391c90759 100644 --- a/client/package.json +++ b/client/package.json @@ -8,23 +8,23 @@ "private": true, "proxy": "http://localhost:4000", "dependencies": { - "@ant-design/pro-layout": "^7.22.3", + "@ant-design/pro-layout": "^7.22.4", "@apollo/client": "^3.13.5", "@emotion/is-prop-valid": "^1.3.1", "@fingerprintjs/fingerprintjs": "^4.6.1", "@firebase/analytics": "^0.10.12", - "@firebase/app": "^0.11.3", - "@firebase/auth": "^1.9.1", + "@firebase/app": "^0.11.4", + "@firebase/auth": "^1.10.0", "@firebase/firestore": "^4.7.10", "@firebase/messaging": "^0.12.17", "@jsreport/browser-client": "^3.1.0", "@reduxjs/toolkit": "^2.6.1", - "@sentry/cli": "^2.42.4", - "@sentry/react": "^9.9.0", - "@sentry/vite-plugin": "^3.2.2", - "@splitsoftware/splitio-react": "^2.0.1", + "@sentry/cli": "^2.43.0", + "@sentry/react": "^9.10.1", + "@sentry/vite-plugin": "^3.2.4", + "@splitsoftware/splitio-react": "^2.1.0", "@tanem/react-nprogress": "^5.0.53", - "antd": "^5.24.5", + "antd": "^5.24.6", "apollo-link-logger": "^2.0.1", "apollo-link-sentry": "^4.2.0", "autosize": "^6.0.1", @@ -69,7 +69,7 @@ "react-resizable": "^3.0.5", "react-router-dom": "^6.30.0", "react-sticky": "^6.0.3", - "react-virtuoso": "^4.12.5", + "react-virtuoso": "^4.12.6", "recharts": "^2.15.0", "redux": "^5.0.1", "redux-actions": "^3.0.3", @@ -77,7 +77,7 @@ "redux-saga": "^1.3.0", "redux-state-sync": "^3.1.4", "reselect": "^5.1.1", - "sass": "^1.86.0", + "sass": "^1.86.1", "socket.io-client": "^4.8.1", "styled-components": "^6.1.16", "subscriptions-transport-ws": "^0.11.0", @@ -135,7 +135,7 @@ "@emotion/react": "^11.14.0", "@eslint/js": "^9.23.0", "@playwright/test": "^1.51.1", - "@sentry/webpack-plugin": "^3.2.2", + "@sentry/webpack-plugin": "^3.2.4", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.2.0", @@ -154,13 +154,13 @@ "react-error-overlay": "^6.1.0", "redux-logger": "^3.0.6", "source-map-explorer": "^2.5.3", - "vite": "^6.2.3", + "vite": "^6.2.4", "vite-plugin-babel": "^1.3.0", "vite-plugin-eslint": "^1.8.1", "vite-plugin-node-polyfills": "^0.23.0", - "vite-plugin-pwa": "^0.21.2", + "vite-plugin-pwa": "^1.0.0", "vite-plugin-style-import": "^2.0.0", - "vitest": "^3.0.9", + "vitest": "^3.1.1", "workbox-window": "^7.3.0" } } diff --git a/package-lock.json b/package-lock.json index 7c4c6bfe9..79f584f36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,14 +9,14 @@ "version": "0.2.0", "license": "UNLICENSED", "dependencies": { - "@aws-sdk/client-cloudwatch-logs": "^3.772.0", - "@aws-sdk/client-elasticache": "^3.772.0", - "@aws-sdk/client-s3": "^3.772.0", - "@aws-sdk/client-secrets-manager": "^3.772.0", - "@aws-sdk/client-ses": "^3.772.0", - "@aws-sdk/credential-provider-node": "^3.772.0", - "@aws-sdk/lib-storage": "^3.774.0", - "@aws-sdk/s3-request-presigner": "^3.774.0", + "@aws-sdk/client-cloudwatch-logs": "^3.777.0", + "@aws-sdk/client-elasticache": "^3.777.0", + "@aws-sdk/client-s3": "^3.779.0", + "@aws-sdk/client-secrets-manager": "^3.777.0", + "@aws-sdk/client-ses": "^3.777.0", + "@aws-sdk/credential-provider-node": "^3.777.0", + "@aws-sdk/lib-storage": "^3.779.0", + "@aws-sdk/s3-request-presigner": "^3.779.0", "@opensearch-project/opensearch": "^2.13.0", "@socket.io/admin-ui": "^0.5.1", "@socket.io/redis-adapter": "^8.3.0", @@ -27,7 +27,7 @@ "better-queue": "^3.8.12", "bluebird": "^3.7.2", "body-parser": "^1.20.3", - "bullmq": "^5.44.4", + "bullmq": "^5.45.2", "chart.js": "^4.4.8", "cloudinary": "^2.6.0", "compression": "^1.8.0", @@ -35,7 +35,7 @@ "cors": "2.8.5", "crisp-status-reporter": "^1.2.2", "csrf": "^3.1.0", - "dd-trace": "^5.43.0", + "dd-trace": "^5.45.0", "dinero.js": "^1.9.1", "dotenv": "^16.4.5", "express": "^4.21.1", @@ -80,7 +80,7 @@ "prettier": "^3.5.3", "source-map-explorer": "^2.5.2", "supertest": "^7.1.0", - "vitest": "^3.0.9" + "vitest": "^3.1.1" }, "engines": { "node": ">=18.0.0", @@ -290,51 +290,51 @@ } }, "node_modules/@aws-sdk/client-cloudwatch-logs": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.774.0.tgz", - "integrity": "sha512-P+qEZJMd4kZVbTs2YRvBHOYlRd0U7bgpbEhRoYRS6vOWymRinQaxj/KCaw1cmdBILj502CUieFGj6DEYAbiNzQ==", + "version": "3.777.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.777.0.tgz", + "integrity": "sha512-ebrO1ZlgSKEYERegcKnyjC0VkvLnxDm2HES78N54MiMQCfFCUJ3W6xx2aoKVSVWaUrGUaY13Cd67h/X0RhuU6g==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.774.0", - "@aws-sdk/credential-provider-node": "3.774.0", - "@aws-sdk/middleware-host-header": "3.774.0", - "@aws-sdk/middleware-logger": "3.734.0", - "@aws-sdk/middleware-recursion-detection": "3.772.0", - "@aws-sdk/middleware-user-agent": "3.774.0", - "@aws-sdk/region-config-resolver": "3.734.0", - "@aws-sdk/types": "3.734.0", - "@aws-sdk/util-endpoints": "3.743.0", - "@aws-sdk/util-user-agent-browser": "3.734.0", - "@aws-sdk/util-user-agent-node": "3.774.0", - "@smithy/config-resolver": "^4.0.1", - "@smithy/core": "^3.1.5", - "@smithy/eventstream-serde-browser": "^4.0.1", - "@smithy/eventstream-serde-config-resolver": "^4.0.1", - "@smithy/eventstream-serde-node": "^4.0.1", - "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/hash-node": "^4.0.1", - "@smithy/invalid-dependency": "^4.0.1", - "@smithy/middleware-content-length": "^4.0.1", - "@smithy/middleware-endpoint": "^4.0.6", - "@smithy/middleware-retry": "^4.0.7", - "@smithy/middleware-serde": "^4.0.2", - "@smithy/middleware-stack": "^4.0.1", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/node-http-handler": "^4.0.3", - "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", - "@smithy/url-parser": "^4.0.1", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/credential-provider-node": "3.777.0", + "@aws-sdk/middleware-host-header": "3.775.0", + "@aws-sdk/middleware-logger": "3.775.0", + "@aws-sdk/middleware-recursion-detection": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/region-config-resolver": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-user-agent-browser": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.775.0", + "@smithy/config-resolver": "^4.1.0", + "@smithy/core": "^3.2.0", + "@smithy/eventstream-serde-browser": "^4.0.2", + "@smithy/eventstream-serde-config-resolver": "^4.1.0", + "@smithy/eventstream-serde-node": "^4.0.2", + "@smithy/fetch-http-handler": "^5.0.2", + "@smithy/hash-node": "^4.0.2", + "@smithy/invalid-dependency": "^4.0.2", + "@smithy/middleware-content-length": "^4.0.2", + "@smithy/middleware-endpoint": "^4.1.0", + "@smithy/middleware-retry": "^4.1.0", + "@smithy/middleware-serde": "^4.0.3", + "@smithy/middleware-stack": "^4.0.2", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/node-http-handler": "^4.0.4", + "@smithy/protocol-http": "^5.1.0", + "@smithy/smithy-client": "^4.2.0", + "@smithy/types": "^4.2.0", + "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.7", - "@smithy/util-defaults-mode-node": "^4.0.7", - "@smithy/util-endpoints": "^3.0.1", - "@smithy/util-middleware": "^4.0.1", - "@smithy/util-retry": "^4.0.1", + "@smithy/util-defaults-mode-browser": "^4.0.8", + "@smithy/util-defaults-mode-node": "^4.0.8", + "@smithy/util-endpoints": "^3.0.2", + "@smithy/util-middleware": "^4.0.2", + "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "@types/uuid": "^9.0.1", "tslib": "^2.6.2", @@ -358,50 +358,50 @@ } }, "node_modules/@aws-sdk/client-elasticache": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-elasticache/-/client-elasticache-3.774.0.tgz", - "integrity": "sha512-uBWSLt6p5tSZCdoizuNyytGiZBFgtUAnXH7GnYH1tVzPeQoQb5GI5of5cDw9lFIIR6DWpYjA7JZ7EEmNvvD7rw==", + "version": "3.777.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-elasticache/-/client-elasticache-3.777.0.tgz", + "integrity": "sha512-6MzXEyUwVIxJqNQh4rvSE32OweJtG9PYdp3UxXfoiuslJnuHgPxWMRpvJIkF/hLeAjfQf4cPii5pBYrfHDbz+g==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.774.0", - "@aws-sdk/credential-provider-node": "3.774.0", - "@aws-sdk/middleware-host-header": "3.774.0", - "@aws-sdk/middleware-logger": "3.734.0", - "@aws-sdk/middleware-recursion-detection": "3.772.0", - "@aws-sdk/middleware-user-agent": "3.774.0", - "@aws-sdk/region-config-resolver": "3.734.0", - "@aws-sdk/types": "3.734.0", - "@aws-sdk/util-endpoints": "3.743.0", - "@aws-sdk/util-user-agent-browser": "3.734.0", - "@aws-sdk/util-user-agent-node": "3.774.0", - "@smithy/config-resolver": "^4.0.1", - "@smithy/core": "^3.1.5", - "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/hash-node": "^4.0.1", - "@smithy/invalid-dependency": "^4.0.1", - "@smithy/middleware-content-length": "^4.0.1", - "@smithy/middleware-endpoint": "^4.0.6", - "@smithy/middleware-retry": "^4.0.7", - "@smithy/middleware-serde": "^4.0.2", - "@smithy/middleware-stack": "^4.0.1", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/node-http-handler": "^4.0.3", - "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", - "@smithy/url-parser": "^4.0.1", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/credential-provider-node": "3.777.0", + "@aws-sdk/middleware-host-header": "3.775.0", + "@aws-sdk/middleware-logger": "3.775.0", + "@aws-sdk/middleware-recursion-detection": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/region-config-resolver": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-user-agent-browser": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.775.0", + "@smithy/config-resolver": "^4.1.0", + "@smithy/core": "^3.2.0", + "@smithy/fetch-http-handler": "^5.0.2", + "@smithy/hash-node": "^4.0.2", + "@smithy/invalid-dependency": "^4.0.2", + "@smithy/middleware-content-length": "^4.0.2", + "@smithy/middleware-endpoint": "^4.1.0", + "@smithy/middleware-retry": "^4.1.0", + "@smithy/middleware-serde": "^4.0.3", + "@smithy/middleware-stack": "^4.0.2", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/node-http-handler": "^4.0.4", + "@smithy/protocol-http": "^5.1.0", + "@smithy/smithy-client": "^4.2.0", + "@smithy/types": "^4.2.0", + "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.7", - "@smithy/util-defaults-mode-node": "^4.0.7", - "@smithy/util-endpoints": "^3.0.1", - "@smithy/util-middleware": "^4.0.1", - "@smithy/util-retry": "^4.0.1", + "@smithy/util-defaults-mode-browser": "^4.0.8", + "@smithy/util-defaults-mode-node": "^4.0.8", + "@smithy/util-endpoints": "^3.0.2", + "@smithy/util-middleware": "^4.0.2", + "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", - "@smithy/util-waiter": "^4.0.2", + "@smithy/util-waiter": "^4.0.3", "tslib": "^2.6.2" }, "engines": { @@ -409,66 +409,66 @@ } }, "node_modules/@aws-sdk/client-s3": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.774.0.tgz", - "integrity": "sha512-HQ5Xi01r/Pv2IpzPTf5acrN0g/yJQalheDCYbBSA8VU31zoYiT/w5kLFWYJHQDB2hRozh2DB/VC/VDmntkWXxA==", + "version": "3.779.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.779.0.tgz", + "integrity": "sha512-Lagz+ersQaLNYkpOU9V12PYspT//lGvhPXlKU3OXDj3whDchdqUdtRKY8rmV+jli4KXe+udx/hj2yqrFRfKGvQ==", "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.774.0", - "@aws-sdk/credential-provider-node": "3.774.0", - "@aws-sdk/middleware-bucket-endpoint": "3.734.0", - "@aws-sdk/middleware-expect-continue": "3.734.0", - "@aws-sdk/middleware-flexible-checksums": "3.774.0", - "@aws-sdk/middleware-host-header": "3.774.0", - "@aws-sdk/middleware-location-constraint": "3.734.0", - "@aws-sdk/middleware-logger": "3.734.0", - "@aws-sdk/middleware-recursion-detection": "3.772.0", - "@aws-sdk/middleware-sdk-s3": "3.774.0", - "@aws-sdk/middleware-ssec": "3.734.0", - "@aws-sdk/middleware-user-agent": "3.774.0", - "@aws-sdk/region-config-resolver": "3.734.0", - "@aws-sdk/signature-v4-multi-region": "3.774.0", - "@aws-sdk/types": "3.734.0", - "@aws-sdk/util-endpoints": "3.743.0", - "@aws-sdk/util-user-agent-browser": "3.734.0", - "@aws-sdk/util-user-agent-node": "3.774.0", - "@aws-sdk/xml-builder": "3.734.0", - "@smithy/config-resolver": "^4.0.1", - "@smithy/core": "^3.1.5", - "@smithy/eventstream-serde-browser": "^4.0.1", - "@smithy/eventstream-serde-config-resolver": "^4.0.1", - "@smithy/eventstream-serde-node": "^4.0.1", - "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/hash-blob-browser": "^4.0.1", - "@smithy/hash-node": "^4.0.1", - "@smithy/hash-stream-node": "^4.0.1", - "@smithy/invalid-dependency": "^4.0.1", - "@smithy/md5-js": "^4.0.1", - "@smithy/middleware-content-length": "^4.0.1", - "@smithy/middleware-endpoint": "^4.0.6", - "@smithy/middleware-retry": "^4.0.7", - "@smithy/middleware-serde": "^4.0.2", - "@smithy/middleware-stack": "^4.0.1", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/node-http-handler": "^4.0.3", - "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", - "@smithy/url-parser": "^4.0.1", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/credential-provider-node": "3.777.0", + "@aws-sdk/middleware-bucket-endpoint": "3.775.0", + "@aws-sdk/middleware-expect-continue": "3.775.0", + "@aws-sdk/middleware-flexible-checksums": "3.775.0", + "@aws-sdk/middleware-host-header": "3.775.0", + "@aws-sdk/middleware-location-constraint": "3.775.0", + "@aws-sdk/middleware-logger": "3.775.0", + "@aws-sdk/middleware-recursion-detection": "3.775.0", + "@aws-sdk/middleware-sdk-s3": "3.775.0", + "@aws-sdk/middleware-ssec": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/region-config-resolver": "3.775.0", + "@aws-sdk/signature-v4-multi-region": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-user-agent-browser": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.775.0", + "@aws-sdk/xml-builder": "3.775.0", + "@smithy/config-resolver": "^4.1.0", + "@smithy/core": "^3.2.0", + "@smithy/eventstream-serde-browser": "^4.0.2", + "@smithy/eventstream-serde-config-resolver": "^4.1.0", + "@smithy/eventstream-serde-node": "^4.0.2", + "@smithy/fetch-http-handler": "^5.0.2", + "@smithy/hash-blob-browser": "^4.0.2", + "@smithy/hash-node": "^4.0.2", + "@smithy/hash-stream-node": "^4.0.2", + "@smithy/invalid-dependency": "^4.0.2", + "@smithy/md5-js": "^4.0.2", + "@smithy/middleware-content-length": "^4.0.2", + "@smithy/middleware-endpoint": "^4.1.0", + "@smithy/middleware-retry": "^4.1.0", + "@smithy/middleware-serde": "^4.0.3", + "@smithy/middleware-stack": "^4.0.2", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/node-http-handler": "^4.0.4", + "@smithy/protocol-http": "^5.1.0", + "@smithy/smithy-client": "^4.2.0", + "@smithy/types": "^4.2.0", + "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.7", - "@smithy/util-defaults-mode-node": "^4.0.7", - "@smithy/util-endpoints": "^3.0.1", - "@smithy/util-middleware": "^4.0.1", - "@smithy/util-retry": "^4.0.1", - "@smithy/util-stream": "^4.1.2", + "@smithy/util-defaults-mode-browser": "^4.0.8", + "@smithy/util-defaults-mode-node": "^4.0.8", + "@smithy/util-endpoints": "^3.0.2", + "@smithy/util-middleware": "^4.0.2", + "@smithy/util-retry": "^4.0.2", + "@smithy/util-stream": "^4.2.0", "@smithy/util-utf8": "^4.0.0", - "@smithy/util-waiter": "^4.0.2", + "@smithy/util-waiter": "^4.0.3", "tslib": "^2.6.2" }, "engines": { @@ -476,48 +476,48 @@ } }, "node_modules/@aws-sdk/client-secrets-manager": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.774.0.tgz", - "integrity": "sha512-AoVpmzLY/PW/0H6hcc/Rn/uisDTFE7WX/oWZ8qU2gYMuH3z2VUAIhHQZq3mNpXH4ZlWPH+sDA8cG1tCc8dgVqA==", + "version": "3.777.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.777.0.tgz", + "integrity": "sha512-HqBGQPFUZMTOkQJB6JLv7Jopfz+cBP4spzjpBlZ/JeJShMAXw9To2mxi22jU5qGGWPGH5y4tVXnw4aVf2TOPhQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.774.0", - "@aws-sdk/credential-provider-node": "3.774.0", - "@aws-sdk/middleware-host-header": "3.774.0", - "@aws-sdk/middleware-logger": "3.734.0", - "@aws-sdk/middleware-recursion-detection": "3.772.0", - "@aws-sdk/middleware-user-agent": "3.774.0", - "@aws-sdk/region-config-resolver": "3.734.0", - "@aws-sdk/types": "3.734.0", - "@aws-sdk/util-endpoints": "3.743.0", - "@aws-sdk/util-user-agent-browser": "3.734.0", - "@aws-sdk/util-user-agent-node": "3.774.0", - "@smithy/config-resolver": "^4.0.1", - "@smithy/core": "^3.1.5", - "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/hash-node": "^4.0.1", - "@smithy/invalid-dependency": "^4.0.1", - "@smithy/middleware-content-length": "^4.0.1", - "@smithy/middleware-endpoint": "^4.0.6", - "@smithy/middleware-retry": "^4.0.7", - "@smithy/middleware-serde": "^4.0.2", - "@smithy/middleware-stack": "^4.0.1", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/node-http-handler": "^4.0.3", - "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", - "@smithy/url-parser": "^4.0.1", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/credential-provider-node": "3.777.0", + "@aws-sdk/middleware-host-header": "3.775.0", + "@aws-sdk/middleware-logger": "3.775.0", + "@aws-sdk/middleware-recursion-detection": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/region-config-resolver": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-user-agent-browser": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.775.0", + "@smithy/config-resolver": "^4.1.0", + "@smithy/core": "^3.2.0", + "@smithy/fetch-http-handler": "^5.0.2", + "@smithy/hash-node": "^4.0.2", + "@smithy/invalid-dependency": "^4.0.2", + "@smithy/middleware-content-length": "^4.0.2", + "@smithy/middleware-endpoint": "^4.1.0", + "@smithy/middleware-retry": "^4.1.0", + "@smithy/middleware-serde": "^4.0.3", + "@smithy/middleware-stack": "^4.0.2", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/node-http-handler": "^4.0.4", + "@smithy/protocol-http": "^5.1.0", + "@smithy/smithy-client": "^4.2.0", + "@smithy/types": "^4.2.0", + "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.7", - "@smithy/util-defaults-mode-node": "^4.0.7", - "@smithy/util-endpoints": "^3.0.1", - "@smithy/util-middleware": "^4.0.1", - "@smithy/util-retry": "^4.0.1", + "@smithy/util-defaults-mode-browser": "^4.0.8", + "@smithy/util-defaults-mode-node": "^4.0.8", + "@smithy/util-endpoints": "^3.0.2", + "@smithy/util-middleware": "^4.0.2", + "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "@types/uuid": "^9.0.1", "tslib": "^2.6.2", @@ -541,50 +541,50 @@ } }, "node_modules/@aws-sdk/client-ses": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.774.0.tgz", - "integrity": "sha512-EWZRm9nV7xFQYjFmk259gf1Mp40MuJ1KWHbY5y6EYt3dkuYFJnqAdBETB3tzbC0EmIkVSR1Uzxc72jRS8klvHg==", + "version": "3.777.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.777.0.tgz", + "integrity": "sha512-COZ6Yb5qt/JLmWtJG1rGXhvTFnaWHt0X8r9j0uGFuSRhLcguItxYlOnIskYePz/NJ0u/OXYbad0uG1M4V5IJ/w==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.774.0", - "@aws-sdk/credential-provider-node": "3.774.0", - "@aws-sdk/middleware-host-header": "3.774.0", - "@aws-sdk/middleware-logger": "3.734.0", - "@aws-sdk/middleware-recursion-detection": "3.772.0", - "@aws-sdk/middleware-user-agent": "3.774.0", - "@aws-sdk/region-config-resolver": "3.734.0", - "@aws-sdk/types": "3.734.0", - "@aws-sdk/util-endpoints": "3.743.0", - "@aws-sdk/util-user-agent-browser": "3.734.0", - "@aws-sdk/util-user-agent-node": "3.774.0", - "@smithy/config-resolver": "^4.0.1", - "@smithy/core": "^3.1.5", - "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/hash-node": "^4.0.1", - "@smithy/invalid-dependency": "^4.0.1", - "@smithy/middleware-content-length": "^4.0.1", - "@smithy/middleware-endpoint": "^4.0.6", - "@smithy/middleware-retry": "^4.0.7", - "@smithy/middleware-serde": "^4.0.2", - "@smithy/middleware-stack": "^4.0.1", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/node-http-handler": "^4.0.3", - "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", - "@smithy/url-parser": "^4.0.1", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/credential-provider-node": "3.777.0", + "@aws-sdk/middleware-host-header": "3.775.0", + "@aws-sdk/middleware-logger": "3.775.0", + "@aws-sdk/middleware-recursion-detection": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/region-config-resolver": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-user-agent-browser": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.775.0", + "@smithy/config-resolver": "^4.1.0", + "@smithy/core": "^3.2.0", + "@smithy/fetch-http-handler": "^5.0.2", + "@smithy/hash-node": "^4.0.2", + "@smithy/invalid-dependency": "^4.0.2", + "@smithy/middleware-content-length": "^4.0.2", + "@smithy/middleware-endpoint": "^4.1.0", + "@smithy/middleware-retry": "^4.1.0", + "@smithy/middleware-serde": "^4.0.3", + "@smithy/middleware-stack": "^4.0.2", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/node-http-handler": "^4.0.4", + "@smithy/protocol-http": "^5.1.0", + "@smithy/smithy-client": "^4.2.0", + "@smithy/types": "^4.2.0", + "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.7", - "@smithy/util-defaults-mode-node": "^4.0.7", - "@smithy/util-endpoints": "^3.0.1", - "@smithy/util-middleware": "^4.0.1", - "@smithy/util-retry": "^4.0.1", + "@smithy/util-defaults-mode-browser": "^4.0.8", + "@smithy/util-defaults-mode-node": "^4.0.8", + "@smithy/util-endpoints": "^3.0.2", + "@smithy/util-middleware": "^4.0.2", + "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", - "@smithy/util-waiter": "^4.0.2", + "@smithy/util-waiter": "^4.0.3", "tslib": "^2.6.2" }, "engines": { @@ -592,47 +592,47 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.774.0.tgz", - "integrity": "sha512-bN+wd2gpTq+DNJ/fZdam/mX6K3TcVdZBIvxaVtg+imep6xAuRukdFhsoG0cDzk96+WHPCOhkyi+6lFljCof43Q==", + "version": "3.777.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.777.0.tgz", + "integrity": "sha512-0+z6CiAYIQa7s6FJ+dpBYPi9zr9yY5jBg/4/FGcwYbmqWPXwL9Thdtr0FearYRZgKl7bhL3m3dILCCfWqr3teQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.774.0", - "@aws-sdk/middleware-host-header": "3.774.0", - "@aws-sdk/middleware-logger": "3.734.0", - "@aws-sdk/middleware-recursion-detection": "3.772.0", - "@aws-sdk/middleware-user-agent": "3.774.0", - "@aws-sdk/region-config-resolver": "3.734.0", - "@aws-sdk/types": "3.734.0", - "@aws-sdk/util-endpoints": "3.743.0", - "@aws-sdk/util-user-agent-browser": "3.734.0", - "@aws-sdk/util-user-agent-node": "3.774.0", - "@smithy/config-resolver": "^4.0.1", - "@smithy/core": "^3.1.5", - "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/hash-node": "^4.0.1", - "@smithy/invalid-dependency": "^4.0.1", - "@smithy/middleware-content-length": "^4.0.1", - "@smithy/middleware-endpoint": "^4.0.6", - "@smithy/middleware-retry": "^4.0.7", - "@smithy/middleware-serde": "^4.0.2", - "@smithy/middleware-stack": "^4.0.1", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/node-http-handler": "^4.0.3", - "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", - "@smithy/url-parser": "^4.0.1", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/middleware-host-header": "3.775.0", + "@aws-sdk/middleware-logger": "3.775.0", + "@aws-sdk/middleware-recursion-detection": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/region-config-resolver": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-user-agent-browser": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.775.0", + "@smithy/config-resolver": "^4.1.0", + "@smithy/core": "^3.2.0", + "@smithy/fetch-http-handler": "^5.0.2", + "@smithy/hash-node": "^4.0.2", + "@smithy/invalid-dependency": "^4.0.2", + "@smithy/middleware-content-length": "^4.0.2", + "@smithy/middleware-endpoint": "^4.1.0", + "@smithy/middleware-retry": "^4.1.0", + "@smithy/middleware-serde": "^4.0.3", + "@smithy/middleware-stack": "^4.0.2", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/node-http-handler": "^4.0.4", + "@smithy/protocol-http": "^5.1.0", + "@smithy/smithy-client": "^4.2.0", + "@smithy/types": "^4.2.0", + "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.7", - "@smithy/util-defaults-mode-node": "^4.0.7", - "@smithy/util-endpoints": "^3.0.1", - "@smithy/util-middleware": "^4.0.1", - "@smithy/util-retry": "^4.0.1", + "@smithy/util-defaults-mode-browser": "^4.0.8", + "@smithy/util-defaults-mode-node": "^4.0.8", + "@smithy/util-endpoints": "^3.0.2", + "@smithy/util-middleware": "^4.0.2", + "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -641,20 +641,20 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.774.0.tgz", - "integrity": "sha512-JDkAAlPyGWMX42L4Cv8mxybwHTOoFweNbNrOc5oQJhFxZAe1zkW4uLTEfr79vYhnXCFbThCyPpBotmo3U2vULA==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.775.0.tgz", + "integrity": "sha512-8vpW4WihVfz0DX+7WnnLGm3GuQER++b0IwQG35JlQMlgqnc44M//KbJPsIHA0aJUJVwJAEShgfr5dUbY8WUzaA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.734.0", - "@smithy/core": "^3.1.5", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/property-provider": "^4.0.1", - "@smithy/protocol-http": "^5.0.1", - "@smithy/signature-v4": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", - "@smithy/util-middleware": "^4.0.1", + "@aws-sdk/types": "3.775.0", + "@smithy/core": "^3.2.0", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/property-provider": "^4.0.2", + "@smithy/protocol-http": "^5.1.0", + "@smithy/signature-v4": "^5.0.2", + "@smithy/smithy-client": "^4.2.0", + "@smithy/types": "^4.2.0", + "@smithy/util-middleware": "^4.0.2", "fast-xml-parser": "4.4.1", "tslib": "^2.6.2" }, @@ -663,15 +663,15 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.774.0.tgz", - "integrity": "sha512-FkSDBi9Ly0bmzyrMDeqQq1lGsFMrrd/bIB3c9VD4Llh0sPLxB/DU31+VTPTuQ0pBPz4sX5Vay6tLy43DStzcFQ==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.775.0.tgz", + "integrity": "sha512-6ESVxwCbGm7WZ17kY1fjmxQud43vzJFoLd4bmlR+idQSWdqlzGDYdcfzpjDKTcivdtNrVYmFvcH1JBUwCRAZhw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.774.0", - "@aws-sdk/types": "3.734.0", - "@smithy/property-provider": "^4.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@smithy/property-provider": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -679,20 +679,20 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.774.0.tgz", - "integrity": "sha512-iurWGQColf52HpHeHCQs/LnSjZ0Ufq3VtSQx/6QdZwIhmgbbqvGMAaBJg41SQjWhpqdufE96HzcaCJw/lnCefQ==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.775.0.tgz", + "integrity": "sha512-PjDQeDH/J1S0yWV32wCj2k5liRo0ssXMseCBEkCsD3SqsU8o5cU82b0hMX4sAib/RkglCSZqGO0xMiN0/7ndww==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.774.0", - "@aws-sdk/types": "3.734.0", - "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/node-http-handler": "^4.0.3", - "@smithy/property-provider": "^4.0.1", - "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", - "@smithy/util-stream": "^4.1.2", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@smithy/fetch-http-handler": "^5.0.2", + "@smithy/node-http-handler": "^4.0.4", + "@smithy/property-provider": "^4.0.2", + "@smithy/protocol-http": "^5.1.0", + "@smithy/smithy-client": "^4.2.0", + "@smithy/types": "^4.2.0", + "@smithy/util-stream": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -700,23 +700,23 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.774.0.tgz", - "integrity": "sha512-+AsJOX9pGsnGPAC8wQw7LAO8ZfXzjXTjJxSP1fvg04PX7OBk4zwhVaryH6pu5raan+9cVbfEO1Z7EEMdkweGQA==", + "version": "3.777.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.777.0.tgz", + "integrity": "sha512-1X9mCuM9JSQPmQ+D2TODt4THy6aJWCNiURkmKmTIPRdno7EIKgAqrr/LLN++K5mBf54DZVKpqcJutXU2jwo01A==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.774.0", - "@aws-sdk/credential-provider-env": "3.774.0", - "@aws-sdk/credential-provider-http": "3.774.0", - "@aws-sdk/credential-provider-process": "3.774.0", - "@aws-sdk/credential-provider-sso": "3.774.0", - "@aws-sdk/credential-provider-web-identity": "3.774.0", - "@aws-sdk/nested-clients": "3.774.0", - "@aws-sdk/types": "3.734.0", - "@smithy/credential-provider-imds": "^4.0.1", - "@smithy/property-provider": "^4.0.1", - "@smithy/shared-ini-file-loader": "^4.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/credential-provider-env": "3.775.0", + "@aws-sdk/credential-provider-http": "3.775.0", + "@aws-sdk/credential-provider-process": "3.775.0", + "@aws-sdk/credential-provider-sso": "3.777.0", + "@aws-sdk/credential-provider-web-identity": "3.777.0", + "@aws-sdk/nested-clients": "3.777.0", + "@aws-sdk/types": "3.775.0", + "@smithy/credential-provider-imds": "^4.0.2", + "@smithy/property-provider": "^4.0.2", + "@smithy/shared-ini-file-loader": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -724,22 +724,22 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.774.0.tgz", - "integrity": "sha512-/t+TNhHNW6BNyf7Lgv6I0NUfFk6/dz4+6dUjopRxpDVJtp1YvNza0Zhl25ffRkqX4CKmuXyJYusDbbObcsncUA==", + "version": "3.777.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.777.0.tgz", + "integrity": "sha512-ZD66ywx1Q0KyUSuBXZIQzBe3Q7MzX8lNwsrCU43H3Fww+Y+HB3Ncws9grhSdNhKQNeGmZ+MgKybuZYaaeLwJEQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.774.0", - "@aws-sdk/credential-provider-http": "3.774.0", - "@aws-sdk/credential-provider-ini": "3.774.0", - "@aws-sdk/credential-provider-process": "3.774.0", - "@aws-sdk/credential-provider-sso": "3.774.0", - "@aws-sdk/credential-provider-web-identity": "3.774.0", - "@aws-sdk/types": "3.734.0", - "@smithy/credential-provider-imds": "^4.0.1", - "@smithy/property-provider": "^4.0.1", - "@smithy/shared-ini-file-loader": "^4.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/credential-provider-env": "3.775.0", + "@aws-sdk/credential-provider-http": "3.775.0", + "@aws-sdk/credential-provider-ini": "3.777.0", + "@aws-sdk/credential-provider-process": "3.775.0", + "@aws-sdk/credential-provider-sso": "3.777.0", + "@aws-sdk/credential-provider-web-identity": "3.777.0", + "@aws-sdk/types": "3.775.0", + "@smithy/credential-provider-imds": "^4.0.2", + "@smithy/property-provider": "^4.0.2", + "@smithy/shared-ini-file-loader": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -747,16 +747,16 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.774.0.tgz", - "integrity": "sha512-lycBRY1NeWa46LefN258m1MRVUPQgvf6TPA6ZYajyq6/dCr6BPeuUoUAyrzePTPlxV/M25YXNiyORHjjwlK0ug==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.775.0.tgz", + "integrity": "sha512-A6k68H9rQp+2+7P7SGO90Csw6nrUEm0Qfjpn9Etc4EboZhhCLs9b66umUsTsSBHus4FDIe5JQxfCUyt1wgNogg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.774.0", - "@aws-sdk/types": "3.734.0", - "@smithy/property-provider": "^4.0.1", - "@smithy/shared-ini-file-loader": "^4.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@smithy/property-provider": "^4.0.2", + "@smithy/shared-ini-file-loader": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -764,18 +764,18 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.774.0.tgz", - "integrity": "sha512-j7vbGCWF6dVpd9qiT0PQGzY4NKf8KUa86sSoosGGbtu0dV9T/Y0s/fvPZ0F8ZyuPIKUMJaBpIJYZ/ECZRfT2mg==", + "version": "3.777.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.777.0.tgz", + "integrity": "sha512-9mPz7vk9uE4PBVprfINv4tlTkyq1OonNevx2DiXC1LY4mCUCNN3RdBwAY0BTLzj0uyc3k5KxFFNbn3/8ZDQP7w==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.774.0", - "@aws-sdk/core": "3.774.0", - "@aws-sdk/token-providers": "3.774.0", - "@aws-sdk/types": "3.734.0", - "@smithy/property-provider": "^4.0.1", - "@smithy/shared-ini-file-loader": "^4.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/client-sso": "3.777.0", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/token-providers": "3.777.0", + "@aws-sdk/types": "3.775.0", + "@smithy/property-provider": "^4.0.2", + "@smithy/shared-ini-file-loader": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -783,16 +783,16 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.774.0.tgz", - "integrity": "sha512-kuE5Hdqm9xXdrYBWCU6l2aM3W3HBtZrIBgyf0y41LulJHwld1nvIySus/lILdzbipmUAv9FI07B8TF5y7p/aFA==", + "version": "3.777.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.777.0.tgz", + "integrity": "sha512-uGCqr47fnthkqwq5luNl2dksgcpHHjSXz2jUra7TXtFOpqvnhOW8qXjoa1ivlkq8qhqlaZwCzPdbcN0lXpmLzQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.774.0", - "@aws-sdk/nested-clients": "3.774.0", - "@aws-sdk/types": "3.734.0", - "@smithy/property-provider": "^4.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/nested-clients": "3.777.0", + "@aws-sdk/types": "3.775.0", + "@smithy/property-provider": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -800,14 +800,14 @@ } }, "node_modules/@aws-sdk/lib-storage": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.774.0.tgz", - "integrity": "sha512-xB3rD+F5pt+JLJaUt5eakCJ3+CUa8PXk9nxgN2VozfpuvuR6A/l3lnxmP5wYLhw1I9hxJLV9AD1/QYcibdBjtQ==", + "version": "3.779.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.779.0.tgz", + "integrity": "sha512-AZfykrCgfnhlb5d5uyThHsqIwt41PYgnUTMyDuk4hbuKbiY8pfOiPdg8BYsC59iD2T4Iw9NujYhWUD+l8zNKcw==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.0.1", - "@smithy/middleware-endpoint": "^4.0.6", - "@smithy/smithy-client": "^4.1.6", + "@smithy/abort-controller": "^4.0.2", + "@smithy/middleware-endpoint": "^4.1.0", + "@smithy/smithy-client": "^4.2.0", "buffer": "5.6.0", "events": "3.3.0", "stream-browserify": "3.0.0", @@ -817,7 +817,7 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@aws-sdk/client-s3": "^3.774.0" + "@aws-sdk/client-s3": "^3.779.0" } }, "node_modules/@aws-sdk/lib-storage/node_modules/buffer": { @@ -831,16 +831,16 @@ } }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { - "version": "3.734.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.734.0.tgz", - "integrity": "sha512-etC7G18aF7KdZguW27GE/wpbrNmYLVT755EsFc8kXpZj8D6AFKxc7OuveinJmiy0bYXAMspJUWsF6CrGpOw6CQ==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.775.0.tgz", + "integrity": "sha512-qogMIpVChDYr4xiUNC19/RDSw/sKoHkAhouS6Skxiy6s27HBhow1L3Z1qVYXuBmOZGSWPU0xiyZCvOyWrv9s+Q==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.734.0", + "@aws-sdk/types": "3.775.0", "@aws-sdk/util-arn-parser": "3.723.0", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/protocol-http": "^5.0.1", - "@smithy/types": "^4.1.0", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/protocol-http": "^5.1.0", + "@smithy/types": "^4.2.0", "@smithy/util-config-provider": "^4.0.0", "tslib": "^2.6.2" }, @@ -849,14 +849,14 @@ } }, "node_modules/@aws-sdk/middleware-expect-continue": { - "version": "3.734.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.734.0.tgz", - "integrity": "sha512-P38/v1l6HjuB2aFUewt7ueAW5IvKkFcv5dalPtbMGRhLeyivBOHwbCyuRKgVs7z7ClTpu9EaViEGki2jEQqEsQ==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.775.0.tgz", + "integrity": "sha512-Apd3owkIeUW5dnk3au9np2IdW2N0zc9NjTjHiH+Mx3zqwSrc+m+ANgJVgk9mnQjMzU/vb7VuxJ0eqdEbp5gYsg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.734.0", - "@smithy/protocol-http": "^5.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/types": "3.775.0", + "@smithy/protocol-http": "^5.1.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -864,22 +864,22 @@ } }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.774.0.tgz", - "integrity": "sha512-S0vs+U7sEZkRRnjf05KCbEHDduyxGgNPq+ZeaiyWbs5yTZ8wzSYrSzMAKcbCqAseNVYQbpGMXDh8tnzx6H/ihw==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.775.0.tgz", + "integrity": "sha512-OmHLfRIb7IIXsf9/X/pMOlcSV3gzW/MmtPSZTkrz5jCTKzWXd7eRoyOJqewjsaC6KMAxIpNU77FoAd16jOZ21A==", "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.774.0", - "@aws-sdk/types": "3.734.0", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/types": "3.775.0", "@smithy/is-array-buffer": "^4.0.0", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/protocol-http": "^5.0.1", - "@smithy/types": "^4.1.0", - "@smithy/util-middleware": "^4.0.1", - "@smithy/util-stream": "^4.1.2", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/protocol-http": "^5.1.0", + "@smithy/types": "^4.2.0", + "@smithy/util-middleware": "^4.0.2", + "@smithy/util-stream": "^4.2.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -888,14 +888,14 @@ } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.774.0.tgz", - "integrity": "sha512-7QHA0ZyEBVfyJqmIc0FW4MUtPdrWhDsHQudsvBCHFS+mqP5fhpU/o4e5RQ+0M7tQqDE65+8MrZRniRa+Txz3xA==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.775.0.tgz", + "integrity": "sha512-tkSegM0Z6WMXpLB8oPys/d+umYIocvO298mGvcMCncpRl77L9XkvSLJIFzaHes+o7djAgIduYw8wKIMStFss2w==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.734.0", - "@smithy/protocol-http": "^5.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/types": "3.775.0", + "@smithy/protocol-http": "^5.1.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -903,13 +903,13 @@ } }, "node_modules/@aws-sdk/middleware-location-constraint": { - "version": "3.734.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.734.0.tgz", - "integrity": "sha512-EJEIXwCQhto/cBfHdm3ZOeLxd2NlJD+X2F+ZTOxzokuhBtY0IONfC/91hOo5tWQweerojwshSMHRCKzRv1tlwg==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.775.0.tgz", + "integrity": "sha512-8TMXEHZXZTFTckQLyBT5aEI8fX11HZcwZseRifvBKKpj0RZDk4F0EEYGxeNSPpUQ7n+PRWyfAEnnZNRdAj/1NQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.734.0", - "@smithy/types": "^4.1.0", + "@aws-sdk/types": "3.775.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -917,13 +917,13 @@ } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.734.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.734.0.tgz", - "integrity": "sha512-mUMFITpJUW3LcKvFok176eI5zXAUomVtahb9IQBwLzkqFYOrMJvWAvoV4yuxrJ8TlQBG8gyEnkb9SnhZvjg67w==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.775.0.tgz", + "integrity": "sha512-FaxO1xom4MAoUJsldmR92nT1G6uZxTdNYOFYtdHfd6N2wcNaTuxgjIvqzg5y7QIH9kn58XX/dzf1iTjgqUStZw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.734.0", - "@smithy/types": "^4.1.0", + "@aws-sdk/types": "3.775.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -931,14 +931,14 @@ } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.772.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.772.0.tgz", - "integrity": "sha512-zg0LjJa4v7fcLzn5QzZvtVS+qyvmsnu7oQnb86l6ckduZpWDCDC9+A0ZzcXTrxblPCJd3JqkoG1+Gzi4S4Ny/Q==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.775.0.tgz", + "integrity": "sha512-GLCzC8D0A0YDG5u3F5U03Vb9j5tcOEFhr8oc6PDk0k0vm5VwtZOE6LvK7hcCSoAB4HXyOUM0sQuXrbaAh9OwXA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.734.0", - "@smithy/protocol-http": "^5.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/types": "3.775.0", + "@smithy/protocol-http": "^5.1.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -946,23 +946,23 @@ } }, "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.774.0.tgz", - "integrity": "sha512-iMEaOj+S8LZfg7fZaSfXQ8YDtEfOSBiQUllyxzaVhSYlM7IeNDbpBdCWnRi34VrI1J1AuryMdX/foU9JNSTLXg==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.775.0.tgz", + "integrity": "sha512-zsvcu7cWB28JJ60gVvjxPCI7ZU7jWGcpNACPiZGyVtjYXwcxyhXbYEVDSWKsSA6ERpz9XrpLYod8INQWfW3ECg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.774.0", - "@aws-sdk/types": "3.734.0", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/types": "3.775.0", "@aws-sdk/util-arn-parser": "3.723.0", - "@smithy/core": "^3.1.5", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/protocol-http": "^5.0.1", - "@smithy/signature-v4": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", + "@smithy/core": "^3.2.0", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/protocol-http": "^5.1.0", + "@smithy/signature-v4": "^5.0.2", + "@smithy/smithy-client": "^4.2.0", + "@smithy/types": "^4.2.0", "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.1", - "@smithy/util-stream": "^4.1.2", + "@smithy/util-middleware": "^4.0.2", + "@smithy/util-stream": "^4.2.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -971,13 +971,13 @@ } }, "node_modules/@aws-sdk/middleware-ssec": { - "version": "3.734.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.734.0.tgz", - "integrity": "sha512-d4yd1RrPW/sspEXizq2NSOUivnheac6LPeLSLnaeTbBG9g1KqIqvCzP1TfXEqv2CrWfHEsWtJpX7oyjySSPvDQ==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.775.0.tgz", + "integrity": "sha512-Iw1RHD8vfAWWPzBBIKaojO4GAvQkHOYIpKdAfis/EUSUmSa79QsnXnRqsdcE0mCB0Ylj23yi+ah4/0wh9FsekA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.734.0", - "@smithy/types": "^4.1.0", + "@aws-sdk/types": "3.775.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -985,17 +985,17 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.774.0.tgz", - "integrity": "sha512-SVDeBV6DESgc9zex1Wk5XYbUqRI1tmJYQor47uKqD18r6UaCpvzVOBP4x8l/6hteAYxsWER6ZZmsjBQkenEuFQ==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.775.0.tgz", + "integrity": "sha512-7Lffpr1ptOEDE1ZYH1T78pheEY1YmeXWBfFt/amZ6AGsKSLG+JPXvof3ltporTGR2bhH/eJPo7UHCglIuXfzYg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.774.0", - "@aws-sdk/types": "3.734.0", - "@aws-sdk/util-endpoints": "3.743.0", - "@smithy/core": "^3.1.5", - "@smithy/protocol-http": "^5.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@aws-sdk/util-endpoints": "3.775.0", + "@smithy/core": "^3.2.0", + "@smithy/protocol-http": "^5.1.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -1003,47 +1003,47 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.774.0.tgz", - "integrity": "sha512-00+UiYvxiZaDFVzn87kPpiZ/GiEWNaTNzC82C+bIyXt1M9AnAR6PAnnvMErTFwyG+Un6n2ai/I81wvJ1ftFmeQ==", + "version": "3.777.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.777.0.tgz", + "integrity": "sha512-bmmVRsCjuYlStYPt06hr+f8iEyWg7+AklKCA8ZLDEJujXhXIowgUIqXmqpTkXwkVvDQ9tzU7hxaONjyaQCGybA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.774.0", - "@aws-sdk/middleware-host-header": "3.774.0", - "@aws-sdk/middleware-logger": "3.734.0", - "@aws-sdk/middleware-recursion-detection": "3.772.0", - "@aws-sdk/middleware-user-agent": "3.774.0", - "@aws-sdk/region-config-resolver": "3.734.0", - "@aws-sdk/types": "3.734.0", - "@aws-sdk/util-endpoints": "3.743.0", - "@aws-sdk/util-user-agent-browser": "3.734.0", - "@aws-sdk/util-user-agent-node": "3.774.0", - "@smithy/config-resolver": "^4.0.1", - "@smithy/core": "^3.1.5", - "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/hash-node": "^4.0.1", - "@smithy/invalid-dependency": "^4.0.1", - "@smithy/middleware-content-length": "^4.0.1", - "@smithy/middleware-endpoint": "^4.0.6", - "@smithy/middleware-retry": "^4.0.7", - "@smithy/middleware-serde": "^4.0.2", - "@smithy/middleware-stack": "^4.0.1", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/node-http-handler": "^4.0.3", - "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", - "@smithy/url-parser": "^4.0.1", + "@aws-sdk/core": "3.775.0", + "@aws-sdk/middleware-host-header": "3.775.0", + "@aws-sdk/middleware-logger": "3.775.0", + "@aws-sdk/middleware-recursion-detection": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/region-config-resolver": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-user-agent-browser": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.775.0", + "@smithy/config-resolver": "^4.1.0", + "@smithy/core": "^3.2.0", + "@smithy/fetch-http-handler": "^5.0.2", + "@smithy/hash-node": "^4.0.2", + "@smithy/invalid-dependency": "^4.0.2", + "@smithy/middleware-content-length": "^4.0.2", + "@smithy/middleware-endpoint": "^4.1.0", + "@smithy/middleware-retry": "^4.1.0", + "@smithy/middleware-serde": "^4.0.3", + "@smithy/middleware-stack": "^4.0.2", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/node-http-handler": "^4.0.4", + "@smithy/protocol-http": "^5.1.0", + "@smithy/smithy-client": "^4.2.0", + "@smithy/types": "^4.2.0", + "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.7", - "@smithy/util-defaults-mode-node": "^4.0.7", - "@smithy/util-endpoints": "^3.0.1", - "@smithy/util-middleware": "^4.0.1", - "@smithy/util-retry": "^4.0.1", + "@smithy/util-defaults-mode-browser": "^4.0.8", + "@smithy/util-defaults-mode-node": "^4.0.8", + "@smithy/util-endpoints": "^3.0.2", + "@smithy/util-middleware": "^4.0.2", + "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -1052,16 +1052,16 @@ } }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.734.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.734.0.tgz", - "integrity": "sha512-Lvj1kPRC5IuJBr9DyJ9T9/plkh+EfKLy+12s/mykOy1JaKHDpvj+XGy2YO6YgYVOb8JFtaqloid+5COtje4JTQ==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.775.0.tgz", + "integrity": "sha512-40iH3LJjrQS3LKUJAl7Wj0bln7RFPEvUYKFxtP8a+oKFDO0F65F52xZxIJbPn6sHkxWDAnZlGgdjZXM3p2g5wQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.734.0", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/types": "3.775.0", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/types": "^4.2.0", "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.1", + "@smithy/util-middleware": "^4.0.2", "tslib": "^2.6.2" }, "engines": { @@ -1069,18 +1069,18 @@ } }, "node_modules/@aws-sdk/s3-request-presigner": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.774.0.tgz", - "integrity": "sha512-vD37Nq7+ChUkXSoDqkNMXu37R8kRDUo13pOfYgesSI4HA970fjXP1T4Mf2131Ms/NuYbBHNn330+3MAkbbYKxg==", + "version": "3.779.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.779.0.tgz", + "integrity": "sha512-L3mGSh6/9gf3FBVrQziCkuLbaRJMeNbLr6tg9ZSymJcDRzRqAiCWnHrenAavTnAAnm+Lu62Fg/A4g3T+YT+gEg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/signature-v4-multi-region": "3.774.0", - "@aws-sdk/types": "3.734.0", - "@aws-sdk/util-format-url": "3.734.0", - "@smithy/middleware-endpoint": "^4.0.6", - "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", + "@aws-sdk/signature-v4-multi-region": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@aws-sdk/util-format-url": "3.775.0", + "@smithy/middleware-endpoint": "^4.1.0", + "@smithy/protocol-http": "^5.1.0", + "@smithy/smithy-client": "^4.2.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -1088,16 +1088,16 @@ } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.774.0.tgz", - "integrity": "sha512-vQwATjZfl5vxfO+BDUH7nUnhfKoIJMnBmOxmUh4N10PWlz3WWwkT/YtH79nVpr+y1eM6GQUSGuNa4Reda6SaFA==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.775.0.tgz", + "integrity": "sha512-cnGk8GDfTMJ8p7+qSk92QlIk2bmTmFJqhYxcXZ9PysjZtx0xmfCMxnG3Hjy1oU2mt5boPCVSOptqtWixayM17g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.774.0", - "@aws-sdk/types": "3.734.0", - "@smithy/protocol-http": "^5.0.1", - "@smithy/signature-v4": "^5.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/middleware-sdk-s3": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@smithy/protocol-http": "^5.1.0", + "@smithy/signature-v4": "^5.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -1105,16 +1105,16 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.774.0.tgz", - "integrity": "sha512-DDERwCduWFFXj7gx3qvnaB8GlnCUpQ8ZA03qI4QFokWu3EyHNK+hjp3nN5Dg81fI0Z82LRe30Q2uDsLBwNCZDg==", + "version": "3.777.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.777.0.tgz", + "integrity": "sha512-Yc2cDONsHOa4dTSGOev6Ng2QgTKQUEjaUnsyKd13pc/nLLz/WLqHiQ/o7PcnKERJxXGs1g1C6l3sNXiX+kbnFQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/nested-clients": "3.774.0", - "@aws-sdk/types": "3.734.0", - "@smithy/property-provider": "^4.0.1", - "@smithy/shared-ini-file-loader": "^4.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/nested-clients": "3.777.0", + "@aws-sdk/types": "3.775.0", + "@smithy/property-provider": "^4.0.2", + "@smithy/shared-ini-file-loader": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -1122,12 +1122,12 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.734.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.734.0.tgz", - "integrity": "sha512-o11tSPTT70nAkGV1fN9wm/hAIiLPyWX6SuGf+9JyTp7S/rC2cFWhR26MvA69nplcjNaXVzB0f+QFrLXXjOqCrg==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.775.0.tgz", + "integrity": "sha512-ZoGKwa4C9fC9Av6bdfqcW6Ix5ot05F/S4VxWR2nHuMv7hzfmAjTOcUiWT7UR4hM/U0whf84VhDtXN/DWAk52KA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.1.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -1147,14 +1147,14 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.743.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.743.0.tgz", - "integrity": "sha512-sN1l559zrixeh5x+pttrnd0A3+r34r0tmPkJ/eaaMaAzXqsmKU/xYre9K3FNnsSS1J1k4PEfk/nHDTVUgFYjnw==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.775.0.tgz", + "integrity": "sha512-yjWmUgZC9tUxAo8Uaplqmq0eUh0zrbZJdwxGRKdYxfm4RG6fMw1tj52+KkatH7o+mNZvg1GDcVp/INktxonJLw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.734.0", - "@smithy/types": "^4.1.0", - "@smithy/util-endpoints": "^3.0.1", + "@aws-sdk/types": "3.775.0", + "@smithy/types": "^4.2.0", + "@smithy/util-endpoints": "^3.0.2", "tslib": "^2.6.2" }, "engines": { @@ -1162,14 +1162,14 @@ } }, "node_modules/@aws-sdk/util-format-url": { - "version": "3.734.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.734.0.tgz", - "integrity": "sha512-TxZMVm8V4aR/QkW9/NhujvYpPZjUYqzLwSge5imKZbWFR806NP7RMwc5ilVuHF/bMOln/cVHkl42kATElWBvNw==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.775.0.tgz", + "integrity": "sha512-Nw4nBeyCbWixoGh8NcVpa/i8McMA6RXJIjQFyloJLaPr7CPquz7ZbSl0MUWMFVwP/VHaJ7B+lNN3Qz1iFCEP/Q==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.734.0", - "@smithy/querystring-builder": "^4.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/types": "3.775.0", + "@smithy/querystring-builder": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -1189,27 +1189,27 @@ } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.734.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.734.0.tgz", - "integrity": "sha512-xQTCus6Q9LwUuALW+S76OL0jcWtMOVu14q+GoLnWPUM7QeUw963oQcLhF7oq0CtaLLKyl4GOUfcwc773Zmwwng==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.775.0.tgz", + "integrity": "sha512-txw2wkiJmZKVdDbscK7VBK+u+TJnRtlUjRTLei+elZg2ADhpQxfVAQl436FUeIv6AhB/oRHW6/K/EAGXUSWi0A==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.734.0", - "@smithy/types": "^4.1.0", + "@aws-sdk/types": "3.775.0", + "@smithy/types": "^4.2.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.774.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.774.0.tgz", - "integrity": "sha512-kFmnK4sf5Wco8mkzO2PszqDXEwtQ5H896tUxqWDQhk67NtOLsHYfg98ymOBWWudth2POaldiIx6KFXtg0DvLLQ==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.775.0.tgz", + "integrity": "sha512-N9yhTevbizTOMo3drH7Eoy6OkJ3iVPxhV7dwb6CMAObbLneS36CSfA6xQXupmHWcRvZPTz8rd1JGG3HzFOau+g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.774.0", - "@aws-sdk/types": "3.734.0", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/types": "3.775.0", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -1225,12 +1225,12 @@ } }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.734.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.734.0.tgz", - "integrity": "sha512-Zrjxi5qwGEcUsJ0ru7fRtW74WcTS0rbLcehoFB+rN1GRi2hbLcFaYs4PwVA5diLeAJH0gszv3x4Hr/S87MfbKQ==", + "version": "3.775.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.775.0.tgz", + "integrity": "sha512-b9NGO6FKJeLGYnV7Z1yvcP1TNU4dkD5jNsLWOF1/sygZoASaQhNOlaiJ/1OH331YQ1R1oWk38nBb0frsYkDsOQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.1.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -1402,9 +1402,9 @@ "license": "Apache-2.0" }, "node_modules/@datadog/native-appsec": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@datadog/native-appsec/-/native-appsec-8.5.0.tgz", - "integrity": "sha512-95y+fm7jd+3iknzuu57pWEPw9fcK9uSBCPiB4kSPHszHu3bESlZM553tc4ANsz+X3gMkYGVg2pgSydG77nSDJw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@datadog/native-appsec/-/native-appsec-8.5.1.tgz", + "integrity": "sha512-g6cjIafeObxVV+zJ2U1TDWVBio+MC8/4QR0EmgZ9afvhgtXRXyth3/DUOBSLUoMvCbduHwl6CV9sBf+tbSksVg==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -1486,9 +1486,9 @@ "license": "Apache-2.0" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", - "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", + "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", "cpu": [ "ppc64" ], @@ -1503,9 +1503,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", - "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", + "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", "cpu": [ "arm" ], @@ -1520,9 +1520,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", - "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", + "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", "cpu": [ "arm64" ], @@ -1537,9 +1537,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", - "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", + "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", "cpu": [ "x64" ], @@ -1554,9 +1554,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", - "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", + "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", "cpu": [ "arm64" ], @@ -1571,9 +1571,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", - "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", + "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", "cpu": [ "x64" ], @@ -1588,9 +1588,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", - "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", + "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", "cpu": [ "arm64" ], @@ -1605,9 +1605,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", - "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", + "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", "cpu": [ "x64" ], @@ -1622,9 +1622,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", - "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", + "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", "cpu": [ "arm" ], @@ -1639,9 +1639,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", - "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", + "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", "cpu": [ "arm64" ], @@ -1656,9 +1656,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", - "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", + "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", "cpu": [ "ia32" ], @@ -1673,9 +1673,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", - "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", + "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", "cpu": [ "loong64" ], @@ -1690,9 +1690,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", - "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", + "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", "cpu": [ "mips64el" ], @@ -1707,9 +1707,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", - "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", + "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", "cpu": [ "ppc64" ], @@ -1724,9 +1724,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", - "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", + "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", "cpu": [ "riscv64" ], @@ -1741,9 +1741,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", - "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", + "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", "cpu": [ "s390x" ], @@ -1758,9 +1758,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", - "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", + "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", "cpu": [ "x64" ], @@ -1775,9 +1775,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", - "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", + "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", "cpu": [ "arm64" ], @@ -1792,9 +1792,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", - "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", + "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", "cpu": [ "x64" ], @@ -1809,9 +1809,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", - "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", + "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", "cpu": [ "arm64" ], @@ -1826,9 +1826,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", - "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", + "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", "cpu": [ "x64" ], @@ -1843,9 +1843,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", - "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", + "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", "cpu": [ "x64" ], @@ -1860,9 +1860,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", - "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", + "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", "cpu": [ "arm64" ], @@ -1877,9 +1877,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", - "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", + "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", "cpu": [ "ia32" ], @@ -1894,9 +1894,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", - "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", + "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", "cpu": [ "x64" ], @@ -2824,9 +2824,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.37.0.tgz", - "integrity": "sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.38.0.tgz", + "integrity": "sha512-ldomqc4/jDZu/xpYU+aRxo3V4mGCV9HeTgUBANI3oIQMOL+SsxB+S2lxMpkFp5UamSS3XuTMQVbsS24R4J4Qjg==", "cpu": [ "arm" ], @@ -2838,9 +2838,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.37.0.tgz", - "integrity": "sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.38.0.tgz", + "integrity": "sha512-VUsgcy4GhhT7rokwzYQP+aV9XnSLkkhlEJ0St8pbasuWO/vwphhZQxYEKUP3ayeCYLhk6gEtacRpYP/cj3GjyQ==", "cpu": [ "arm64" ], @@ -2852,9 +2852,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.37.0.tgz", - "integrity": "sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.38.0.tgz", + "integrity": "sha512-buA17AYXlW9Rn091sWMq1xGUvWQFOH4N1rqUxGJtEQzhChxWjldGCCup7r/wUnaI6Au8sKXpoh0xg58a7cgcpg==", "cpu": [ "arm64" ], @@ -2866,9 +2866,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.37.0.tgz", - "integrity": "sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.38.0.tgz", + "integrity": "sha512-Mgcmc78AjunP1SKXl624vVBOF2bzwNWFPMP4fpOu05vS0amnLcX8gHIge7q/lDAHy3T2HeR0TqrriZDQS2Woeg==", "cpu": [ "x64" ], @@ -2880,9 +2880,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.37.0.tgz", - "integrity": "sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.38.0.tgz", + "integrity": "sha512-zzJACgjLbQTsscxWqvrEQAEh28hqhebpRz5q/uUd1T7VTwUNZ4VIXQt5hE7ncs0GrF+s7d3S4on4TiXUY8KoQA==", "cpu": [ "arm64" ], @@ -2894,9 +2894,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.37.0.tgz", - "integrity": "sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.38.0.tgz", + "integrity": "sha512-hCY/KAeYMCyDpEE4pTETam0XZS4/5GXzlLgpi5f0IaPExw9kuB+PDTOTLuPtM10TlRG0U9OSmXJ+Wq9J39LvAg==", "cpu": [ "x64" ], @@ -2908,9 +2908,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.37.0.tgz", - "integrity": "sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.38.0.tgz", + "integrity": "sha512-mimPH43mHl4JdOTD7bUMFhBdrg6f9HzMTOEnzRmXbOZqjijCw8LA5z8uL6LCjxSa67H2xiLFvvO67PT05PRKGg==", "cpu": [ "arm" ], @@ -2922,9 +2922,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.37.0.tgz", - "integrity": "sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.38.0.tgz", + "integrity": "sha512-tPiJtiOoNuIH8XGG8sWoMMkAMm98PUwlriOFCCbZGc9WCax+GLeVRhmaxjJtz6WxrPKACgrwoZ5ia/uapq3ZVg==", "cpu": [ "arm" ], @@ -2936,9 +2936,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.37.0.tgz", - "integrity": "sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.38.0.tgz", + "integrity": "sha512-wZco59rIVuB0tjQS0CSHTTUcEde+pXQWugZVxWaQFdQQ1VYub/sTrNdY76D1MKdN2NB48JDuGABP6o6fqos8mA==", "cpu": [ "arm64" ], @@ -2950,9 +2950,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.37.0.tgz", - "integrity": "sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.38.0.tgz", + "integrity": "sha512-fQgqwKmW0REM4LomQ+87PP8w8xvU9LZfeLBKybeli+0yHT7VKILINzFEuggvnV9M3x1Ed4gUBmGUzCo/ikmFbQ==", "cpu": [ "arm64" ], @@ -2964,9 +2964,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.37.0.tgz", - "integrity": "sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.38.0.tgz", + "integrity": "sha512-hz5oqQLXTB3SbXpfkKHKXLdIp02/w3M+ajp8p4yWOWwQRtHWiEOCKtc9U+YXahrwdk+3qHdFMDWR5k+4dIlddg==", "cpu": [ "loong64" ], @@ -2978,9 +2978,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.37.0.tgz", - "integrity": "sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.38.0.tgz", + "integrity": "sha512-NXqygK/dTSibQ+0pzxsL3r4Xl8oPqVoWbZV9niqOnIHV/J92fe65pOir0xjkUZDRSPyFRvu+4YOpJF9BZHQImw==", "cpu": [ "ppc64" ], @@ -2992,9 +2992,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.37.0.tgz", - "integrity": "sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.38.0.tgz", + "integrity": "sha512-GEAIabR1uFyvf/jW/5jfu8gjM06/4kZ1W+j1nWTSSB3w6moZEBm7iBtzwQ3a1Pxos2F7Gz+58aVEnZHU295QTg==", "cpu": [ "riscv64" ], @@ -3006,9 +3006,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.37.0.tgz", - "integrity": "sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.38.0.tgz", + "integrity": "sha512-9EYTX+Gus2EGPbfs+fh7l95wVADtSQyYw4DfSBcYdUEAmP2lqSZY0Y17yX/3m5VKGGJ4UmIH5LHLkMJft3bYoA==", "cpu": [ "riscv64" ], @@ -3020,9 +3020,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.37.0.tgz", - "integrity": "sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.38.0.tgz", + "integrity": "sha512-Mpp6+Z5VhB9VDk7RwZXoG2qMdERm3Jw07RNlXHE0bOnEeX+l7Fy4bg+NxfyN15ruuY3/7Vrbpm75J9QHFqj5+Q==", "cpu": [ "s390x" ], @@ -3034,9 +3034,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.37.0.tgz", - "integrity": "sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.38.0.tgz", + "integrity": "sha512-vPvNgFlZRAgO7rwncMeE0+8c4Hmc+qixnp00/Uv3ht2x7KYrJ6ERVd3/R0nUtlE6/hu7/HiiNHJ/rP6knRFt1w==", "cpu": [ "x64" ], @@ -3048,9 +3048,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.37.0.tgz", - "integrity": "sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.38.0.tgz", + "integrity": "sha512-q5Zv+goWvQUGCaL7fU8NuTw8aydIL/C9abAVGCzRReuj5h30TPx4LumBtAidrVOtXnlB+RZkBtExMsfqkMfb8g==", "cpu": [ "x64" ], @@ -3062,9 +3062,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.37.0.tgz", - "integrity": "sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.38.0.tgz", + "integrity": "sha512-u/Jbm1BU89Vftqyqbmxdq14nBaQjQX1HhmsdBWqSdGClNaKwhjsg5TpW+5Ibs1mb8Es9wJiMdl86BcmtUVXNZg==", "cpu": [ "arm64" ], @@ -3076,9 +3076,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.37.0.tgz", - "integrity": "sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.38.0.tgz", + "integrity": "sha512-mqu4PzTrlpNHHbu5qleGvXJoGgHpChBlrBx/mEhTPpnAL1ZAYFlvHD7rLK839LLKQzqEQMFJfGrrOHItN4ZQqA==", "cpu": [ "ia32" ], @@ -3090,9 +3090,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.37.0.tgz", - "integrity": "sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.38.0.tgz", + "integrity": "sha512-jjqy3uWlecfB98Psxb5cD6Fny9Fupv9LrDSPTQZUROqjvZmcCqNu4UMl7qqhlUUGpwiAkotj6GYu4SZdcr/nLw==", "cpu": [ "x64" ], @@ -3193,13 +3193,13 @@ } }, "node_modules/@smithy/eventstream-codec": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.1.tgz", - "integrity": "sha512-Q2bCAAR6zXNVtJgifsU16ZjKGqdw/DyecKNgIgi7dlqw04fqDu0mnq+JmGphqheypVc64CYq3azSuCpAdFk2+A==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.2.tgz", + "integrity": "sha512-p+f2kLSK7ZrXVfskU/f5dzksKTewZk8pJLPvER3aFHPt76C2MxD9vNatSfLzzQSQB4FNO96RK4PSXfhD1TTeMQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^4.1.0", + "@smithy/types": "^4.2.0", "@smithy/util-hex-encoding": "^4.0.0", "tslib": "^2.6.2" }, @@ -3208,13 +3208,13 @@ } }, "node_modules/@smithy/eventstream-serde-browser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.1.tgz", - "integrity": "sha512-HbIybmz5rhNg+zxKiyVAnvdM3vkzjE6ccrJ620iPL8IXcJEntd3hnBl+ktMwIy12Te/kyrSbUb8UCdnUT4QEdA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.2.tgz", + "integrity": "sha512-CepZCDs2xgVUtH7ZZ7oDdZFH8e6Y2zOv8iiX6RhndH69nlojCALSKK+OXwZUgOtUZEUaZ5e1hULVCHYbCn7pug==", "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.1", - "@smithy/types": "^4.1.0", + "@smithy/eventstream-serde-universal": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -3222,12 +3222,12 @@ } }, "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.0.1.tgz", - "integrity": "sha512-lSipaiq3rmHguHa3QFF4YcCM3VJOrY9oq2sow3qlhFY+nBSTF/nrO82MUQRPrxHQXA58J5G1UnU2WuJfi465BA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.1.0.tgz", + "integrity": "sha512-1PI+WPZ5TWXrfj3CIoKyUycYynYJgZjuQo8U+sphneOtjsgrttYybdqESFReQrdWJ+LKt6NEdbYzmmfDBmjX2A==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.1.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -3235,13 +3235,13 @@ } }, "node_modules/@smithy/eventstream-serde-node": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.1.tgz", - "integrity": "sha512-o4CoOI6oYGYJ4zXo34U8X9szDe3oGjmHgsMGiZM0j4vtNoT+h80TLnkUcrLZR3+E6HIxqW+G+9WHAVfl0GXK0Q==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.2.tgz", + "integrity": "sha512-C5bJ/C6x9ENPMx2cFOirspnF9ZsBVnBMtP6BdPl/qYSuUawdGQ34Lq0dMcf42QTjUZgWGbUIZnz6+zLxJlb9aw==", "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.1", - "@smithy/types": "^4.1.0", + "@smithy/eventstream-serde-universal": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -3249,13 +3249,13 @@ } }, "node_modules/@smithy/eventstream-serde-universal": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.1.tgz", - "integrity": "sha512-Z94uZp0tGJuxds3iEAZBqGU2QiaBHP4YytLUjwZWx+oUeohCsLyUm33yp4MMBmhkuPqSbQCXq5hDet6JGUgHWA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.2.tgz", + "integrity": "sha512-St8h9JqzvnbB52FtckiHPN4U/cnXcarMniXRXTKn0r4b4XesZOGiAyUdj1aXbqqn1icSqBlzzUsCl6nPB018ng==", "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-codec": "^4.0.1", - "@smithy/types": "^4.1.0", + "@smithy/eventstream-codec": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -3279,14 +3279,14 @@ } }, "node_modules/@smithy/hash-blob-browser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.1.tgz", - "integrity": "sha512-rkFIrQOKZGS6i1D3gKJ8skJ0RlXqDvb1IyAphksaFOMzkn3v3I1eJ8m7OkLj0jf1McP63rcCEoLlkAn/HjcTRw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.2.tgz", + "integrity": "sha512-3g188Z3DyhtzfBRxpZjU8R9PpOQuYsbNnyStc/ZVS+9nVX1f6XeNOa9IrAh35HwwIZg+XWk8bFVtNINVscBP+g==", "license": "Apache-2.0", "dependencies": { "@smithy/chunked-blob-reader": "^5.0.0", "@smithy/chunked-blob-reader-native": "^4.0.0", - "@smithy/types": "^4.1.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -3294,12 +3294,12 @@ } }, "node_modules/@smithy/hash-node": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.1.tgz", - "integrity": "sha512-TJ6oZS+3r2Xu4emVse1YPB3Dq3d8RkZDKcPr71Nj/lJsdAP1c7oFzYqEn1IBc915TsgLl2xIJNuxCz+gLbLE0w==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.2.tgz", + "integrity": "sha512-VnTpYPnRUE7yVhWozFdlxcYknv9UN7CeOqSrMH+V877v4oqtVYuoqhIhtSjmGPvYrYnAkaM61sLMKHvxL138yg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.1.0", + "@smithy/types": "^4.2.0", "@smithy/util-buffer-from": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" @@ -3309,12 +3309,12 @@ } }, "node_modules/@smithy/hash-stream-node": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.1.tgz", - "integrity": "sha512-U1rAE1fxmReCIr6D2o/4ROqAQX+GffZpyMt3d7njtGDr2pUNmAKRWa49gsNVhCh2vVAuf3wXzWwNr2YN8PAXIw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.2.tgz", + "integrity": "sha512-POWDuTznzbIwlEXEvvXoPMS10y0WKXK790soe57tFRfvf4zBHyzE529HpZMqmDdwG9MfFflnyzndUQ8j78ZdSg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.1.0", + "@smithy/types": "^4.2.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -3323,12 +3323,12 @@ } }, "node_modules/@smithy/invalid-dependency": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.1.tgz", - "integrity": "sha512-gdudFPf4QRQ5pzj7HEnu6FhKRi61BfH/Gk5Yf6O0KiSbr1LlVhgjThcvjdu658VE6Nve8vaIWB8/fodmS1rBPQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.2.tgz", + "integrity": "sha512-GatB4+2DTpgWPday+mnUkoumP54u/MDM/5u44KF9hIu8jF0uafZtQLcdfIKkIcUNuF/fBojpLEHZS/56JqPeXQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.1.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -3348,12 +3348,12 @@ } }, "node_modules/@smithy/md5-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.1.tgz", - "integrity": "sha512-HLZ647L27APi6zXkZlzSFZIjpo8po45YiyjMGJZM3gyDY8n7dPGdmxIIljLm4gPt/7rRvutLTTkYJpZVfG5r+A==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.2.tgz", + "integrity": "sha512-Hc0R8EiuVunUewCse2syVgA2AfSRco3LyAv07B/zCOMa+jpXI9ll+Q21Nc6FAlYPcpNcAXqBzMhNs1CD/pP2bA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.1.0", + "@smithy/types": "^4.2.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -3362,13 +3362,13 @@ } }, "node_modules/@smithy/middleware-content-length": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.1.tgz", - "integrity": "sha512-OGXo7w5EkB5pPiac7KNzVtfCW2vKBTZNuCctn++TTSOMpe6RZO/n6WEC1AxJINn3+vWLKW49uad3lo/u0WJ9oQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.2.tgz", + "integrity": "sha512-hAfEXm1zU+ELvucxqQ7I8SszwQ4znWMbNv6PLMndN83JJN41EPuS93AIyh2N+gJ6x8QFhzSO6b7q2e6oClDI8A==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.0.1", - "@smithy/types": "^4.1.0", + "@smithy/protocol-http": "^5.1.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -3563,16 +3563,16 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.0.1.tgz", - "integrity": "sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.0.2.tgz", + "integrity": "sha512-Mz+mc7okA73Lyz8zQKJNyr7lIcHLiPYp0+oiqiMNc/t7/Kf2BENs5d63pEj7oPqdjaum6g0Fc8wC78dY1TgtXw==", "license": "Apache-2.0", "dependencies": { "@smithy/is-array-buffer": "^4.0.0", - "@smithy/protocol-http": "^5.0.1", - "@smithy/types": "^4.1.0", + "@smithy/protocol-http": "^5.1.0", + "@smithy/types": "^4.2.0", "@smithy/util-hex-encoding": "^4.0.0", - "@smithy/util-middleware": "^4.0.1", + "@smithy/util-middleware": "^4.0.2", "@smithy/util-uri-escape": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" @@ -3723,13 +3723,13 @@ } }, "node_modules/@smithy/util-endpoints": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.1.tgz", - "integrity": "sha512-zVdUENQpdtn9jbpD9SCFK4+aSiavRb9BxEtw9ZGUR1TYo6bBHbIoi7VkrFQ0/RwZlzx0wRBaRmPclj8iAoJCLA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.2.tgz", + "integrity": "sha512-6QSutU5ZyrpNbnd51zRTL7goojlcnuOB55+F9VBD+j8JpRY50IGamsjlycrmpn8PQkmJucFW8A0LSfXj7jjtLQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.0.1", - "@smithy/types": "^4.1.0", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -3820,13 +3820,13 @@ } }, "node_modules/@smithy/util-waiter": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.2.tgz", - "integrity": "sha512-piUTHyp2Axx3p/kc2CIJkYSv0BAaheBQmbACZgQSSfWUumWNW+R1lL+H9PDBxKJkvOeEX+hKYEFiwO8xagL8AQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.3.tgz", + "integrity": "sha512-JtaY3FxmD+te+KSI2FJuEcfNC9T/DGGVf551babM7fAaXhjJUt7oSYurH1Devxd2+BOSUACCgt3buinx4UnmEA==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.0.1", - "@smithy/types": "^4.1.0", + "@smithy/abort-controller": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -3997,9 +3997,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "dev": true, "license": "MIT" }, @@ -4153,14 +4153,14 @@ "license": "MIT" }, "node_modules/@vitest/expect": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz", - "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.1.tgz", + "integrity": "sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.9", - "@vitest/utils": "3.0.9", + "@vitest/spy": "3.1.1", + "@vitest/utils": "3.1.1", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -4169,13 +4169,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz", - "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.1.tgz", + "integrity": "sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.9", + "@vitest/spy": "3.1.1", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -4196,9 +4196,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", - "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.1.tgz", + "integrity": "sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==", "dev": true, "license": "MIT", "dependencies": { @@ -4209,13 +4209,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz", - "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.1.tgz", + "integrity": "sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.0.9", + "@vitest/utils": "3.1.1", "pathe": "^2.0.3" }, "funding": { @@ -4223,13 +4223,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz", - "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.1.tgz", + "integrity": "sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.9", + "@vitest/pretty-format": "3.1.1", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -4238,9 +4238,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz", - "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.1.tgz", + "integrity": "sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4251,13 +4251,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz", - "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.1.tgz", + "integrity": "sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.9", + "@vitest/pretty-format": "3.1.1", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, @@ -5139,9 +5139,9 @@ } }, "node_modules/bullmq": { - "version": "5.44.4", - "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.44.4.tgz", - "integrity": "sha512-0BjgABM/7U85Fxatj586ftsoWiGdjmg7fR7PwRYNOOGfvGpiUX9nQoUmx+9VZW/OtHO/4um/BVh2Y2S9BEhKFg==", + "version": "5.45.2", + "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.45.2.tgz", + "integrity": "sha512-wHZfcD4z4aLolxREmwNNDSbfh7USeq2e3yu5W2VGkzHMUcrH0fzZuRuCMsjD0XKS9ViK1U854oM9yWR6ftPeDA==", "license": "MIT", "dependencies": { "cron-parser": "^4.9.0", @@ -5989,14 +5989,14 @@ } }, "node_modules/dd-trace": { - "version": "5.43.0", - "resolved": "https://registry.npmjs.org/dd-trace/-/dd-trace-5.43.0.tgz", - "integrity": "sha512-WtPUSZfEosSHYVBFR48FqfYBFor8QchKwAKo+LYtbgTPtFzYKyBV/FJUqYE6sDF15Raf4sJVt/LOscywgj2zEw==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/dd-trace/-/dd-trace-5.45.0.tgz", + "integrity": "sha512-LrojHQa/5b7vY+v222aAuLC9LgaTEos6byrzhZQ8frFi5b+WlyfBtdjo7lA050dvvxMAU7c+vl5jKHa3D8swbg==", "hasInstallScript": true, "license": "(Apache-2.0 OR BSD-3-Clause)", "dependencies": { "@datadog/libdatadog": "^0.5.0", - "@datadog/native-appsec": "8.5.0", + "@datadog/native-appsec": "8.5.1", "@datadog/native-iast-rewriter": "2.8.0", "@datadog/native-iast-taint-tracking": "3.3.0", "@datadog/native-metrics": "^3.1.0", @@ -6006,7 +6006,7 @@ "@opentelemetry/api": ">=1.0.0 <1.9.0", "@opentelemetry/core": "^1.14.0", "crypto-randomuuid": "^1.0.0", - "dc-polyfill": "^0.1.4", + "dc-polyfill": "0.1.6", "ignore": "^5.2.4", "import-in-the-middle": "1.13.1", "istanbul-lib-coverage": "3.2.0", @@ -6680,9 +6680,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", - "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", + "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -6693,31 +6693,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.1", - "@esbuild/android-arm": "0.25.1", - "@esbuild/android-arm64": "0.25.1", - "@esbuild/android-x64": "0.25.1", - "@esbuild/darwin-arm64": "0.25.1", - "@esbuild/darwin-x64": "0.25.1", - "@esbuild/freebsd-arm64": "0.25.1", - "@esbuild/freebsd-x64": "0.25.1", - "@esbuild/linux-arm": "0.25.1", - "@esbuild/linux-arm64": "0.25.1", - "@esbuild/linux-ia32": "0.25.1", - "@esbuild/linux-loong64": "0.25.1", - "@esbuild/linux-mips64el": "0.25.1", - "@esbuild/linux-ppc64": "0.25.1", - "@esbuild/linux-riscv64": "0.25.1", - "@esbuild/linux-s390x": "0.25.1", - "@esbuild/linux-x64": "0.25.1", - "@esbuild/netbsd-arm64": "0.25.1", - "@esbuild/netbsd-x64": "0.25.1", - "@esbuild/openbsd-arm64": "0.25.1", - "@esbuild/openbsd-x64": "0.25.1", - "@esbuild/sunos-x64": "0.25.1", - "@esbuild/win32-arm64": "0.25.1", - "@esbuild/win32-ia32": "0.25.1", - "@esbuild/win32-x64": "0.25.1" + "@esbuild/aix-ppc64": "0.25.2", + "@esbuild/android-arm": "0.25.2", + "@esbuild/android-arm64": "0.25.2", + "@esbuild/android-x64": "0.25.2", + "@esbuild/darwin-arm64": "0.25.2", + "@esbuild/darwin-x64": "0.25.2", + "@esbuild/freebsd-arm64": "0.25.2", + "@esbuild/freebsd-x64": "0.25.2", + "@esbuild/linux-arm": "0.25.2", + "@esbuild/linux-arm64": "0.25.2", + "@esbuild/linux-ia32": "0.25.2", + "@esbuild/linux-loong64": "0.25.2", + "@esbuild/linux-mips64el": "0.25.2", + "@esbuild/linux-ppc64": "0.25.2", + "@esbuild/linux-riscv64": "0.25.2", + "@esbuild/linux-s390x": "0.25.2", + "@esbuild/linux-x64": "0.25.2", + "@esbuild/netbsd-arm64": "0.25.2", + "@esbuild/netbsd-x64": "0.25.2", + "@esbuild/openbsd-arm64": "0.25.2", + "@esbuild/openbsd-x64": "0.25.2", + "@esbuild/sunos-x64": "0.25.2", + "@esbuild/win32-arm64": "0.25.2", + "@esbuild/win32-ia32": "0.25.2", + "@esbuild/win32-x64": "0.25.2" } }, "node_modules/escalade": { @@ -10804,13 +10804,13 @@ "license": "MIT" }, "node_modules/rollup": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.37.0.tgz", - "integrity": "sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.38.0.tgz", + "integrity": "sha512-5SsIRtJy9bf1ErAOiFMFzl64Ex9X5V7bnJ+WlFMb+zmP459OSWCEG7b0ERZ+PEU7xPt4OG3RHbrp1LJlXxYTrw==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.6" + "@types/estree": "1.0.7" }, "bin": { "rollup": "dist/bin/rollup" @@ -10820,26 +10820,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.37.0", - "@rollup/rollup-android-arm64": "4.37.0", - "@rollup/rollup-darwin-arm64": "4.37.0", - "@rollup/rollup-darwin-x64": "4.37.0", - "@rollup/rollup-freebsd-arm64": "4.37.0", - "@rollup/rollup-freebsd-x64": "4.37.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.37.0", - "@rollup/rollup-linux-arm-musleabihf": "4.37.0", - "@rollup/rollup-linux-arm64-gnu": "4.37.0", - "@rollup/rollup-linux-arm64-musl": "4.37.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.37.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.37.0", - "@rollup/rollup-linux-riscv64-gnu": "4.37.0", - "@rollup/rollup-linux-riscv64-musl": "4.37.0", - "@rollup/rollup-linux-s390x-gnu": "4.37.0", - "@rollup/rollup-linux-x64-gnu": "4.37.0", - "@rollup/rollup-linux-x64-musl": "4.37.0", - "@rollup/rollup-win32-arm64-msvc": "4.37.0", - "@rollup/rollup-win32-ia32-msvc": "4.37.0", - "@rollup/rollup-win32-x64-msvc": "4.37.0", + "@rollup/rollup-android-arm-eabi": "4.38.0", + "@rollup/rollup-android-arm64": "4.38.0", + "@rollup/rollup-darwin-arm64": "4.38.0", + "@rollup/rollup-darwin-x64": "4.38.0", + "@rollup/rollup-freebsd-arm64": "4.38.0", + "@rollup/rollup-freebsd-x64": "4.38.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.38.0", + "@rollup/rollup-linux-arm-musleabihf": "4.38.0", + "@rollup/rollup-linux-arm64-gnu": "4.38.0", + "@rollup/rollup-linux-arm64-musl": "4.38.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.38.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.38.0", + "@rollup/rollup-linux-riscv64-gnu": "4.38.0", + "@rollup/rollup-linux-riscv64-musl": "4.38.0", + "@rollup/rollup-linux-s390x-gnu": "4.38.0", + "@rollup/rollup-linux-x64-gnu": "4.38.0", + "@rollup/rollup-linux-x64-musl": "4.38.0", + "@rollup/rollup-win32-arm64-msvc": "4.38.0", + "@rollup/rollup-win32-ia32-msvc": "4.38.0", + "@rollup/rollup-win32-x64-msvc": "4.38.0", "fsevents": "~2.3.2" } }, @@ -12523,9 +12523,9 @@ } }, "node_modules/vite": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz", - "integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==", + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.4.tgz", + "integrity": "sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==", "dev": true, "license": "MIT", "dependencies": { @@ -12595,9 +12595,9 @@ } }, "node_modules/vite-node": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz", - "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.1.tgz", + "integrity": "sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==", "dev": true, "license": "MIT", "dependencies": { @@ -12618,31 +12618,31 @@ } }, "node_modules/vitest": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz", - "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.1.tgz", + "integrity": "sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.0.9", - "@vitest/mocker": "3.0.9", - "@vitest/pretty-format": "^3.0.9", - "@vitest/runner": "3.0.9", - "@vitest/snapshot": "3.0.9", - "@vitest/spy": "3.0.9", - "@vitest/utils": "3.0.9", + "@vitest/expect": "3.1.1", + "@vitest/mocker": "3.1.1", + "@vitest/pretty-format": "^3.1.1", + "@vitest/runner": "3.1.1", + "@vitest/snapshot": "3.1.1", + "@vitest/spy": "3.1.1", + "@vitest/utils": "3.1.1", "chai": "^5.2.0", "debug": "^4.4.0", - "expect-type": "^1.1.0", + "expect-type": "^1.2.0", "magic-string": "^0.30.17", "pathe": "^2.0.3", - "std-env": "^3.8.0", + "std-env": "^3.8.1", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.9", + "vite-node": "3.1.1", "why-is-node-running": "^2.3.0" }, "bin": { @@ -12658,8 +12658,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.9", - "@vitest/ui": "3.0.9", + "@vitest/browser": "3.1.1", + "@vitest/ui": "3.1.1", "happy-dom": "*", "jsdom": "*" }, diff --git a/package.json b/package.json index d95e7a731..409d1ce60 100644 --- a/package.json +++ b/package.json @@ -15,14 +15,14 @@ "test:watch": "vitest" }, "dependencies": { - "@aws-sdk/client-cloudwatch-logs": "^3.772.0", - "@aws-sdk/client-elasticache": "^3.772.0", - "@aws-sdk/client-s3": "^3.772.0", - "@aws-sdk/client-secrets-manager": "^3.772.0", - "@aws-sdk/client-ses": "^3.772.0", - "@aws-sdk/credential-provider-node": "^3.772.0", - "@aws-sdk/lib-storage": "^3.774.0", - "@aws-sdk/s3-request-presigner": "^3.774.0", + "@aws-sdk/client-cloudwatch-logs": "^3.777.0", + "@aws-sdk/client-elasticache": "^3.777.0", + "@aws-sdk/client-s3": "^3.779.0", + "@aws-sdk/client-secrets-manager": "^3.777.0", + "@aws-sdk/client-ses": "^3.777.0", + "@aws-sdk/credential-provider-node": "^3.777.0", + "@aws-sdk/lib-storage": "^3.779.0", + "@aws-sdk/s3-request-presigner": "^3.779.0", "@opensearch-project/opensearch": "^2.13.0", "@socket.io/admin-ui": "^0.5.1", "@socket.io/redis-adapter": "^8.3.0", @@ -33,7 +33,7 @@ "better-queue": "^3.8.12", "bluebird": "^3.7.2", "body-parser": "^1.20.3", - "bullmq": "^5.44.4", + "bullmq": "^5.45.2", "chart.js": "^4.4.8", "cloudinary": "^2.6.0", "compression": "^1.8.0", @@ -41,7 +41,7 @@ "cors": "2.8.5", "crisp-status-reporter": "^1.2.2", "csrf": "^3.1.0", - "dd-trace": "^5.43.0", + "dd-trace": "^5.45.0", "dinero.js": "^1.9.1", "dotenv": "^16.4.5", "express": "^4.21.1", @@ -86,6 +86,6 @@ "prettier": "^3.5.3", "source-map-explorer": "^2.5.2", "supertest": "^7.1.0", - "vitest": "^3.0.9" + "vitest": "^3.1.1" } } From 8e105f0b36a58b42dcdf1cb6a40935ca121ac891 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 1 Apr 2025 12:20:50 -0400 Subject: [PATCH 02/34] feature/IO-2885-IntelliPay-App-Postback-Support - Replace/Remove body-parser with Expresses built in body parsing middleware --- package-lock.json | 1 - package.json | 1 - server.js | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 79f584f36..ffe02c7ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,6 @@ "bee-queue": "^1.7.1", "better-queue": "^3.8.12", "bluebird": "^3.7.2", - "body-parser": "^1.20.3", "bullmq": "^5.45.2", "chart.js": "^4.4.8", "cloudinary": "^2.6.0", diff --git a/package.json b/package.json index 409d1ce60..aa3c57951 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ "bee-queue": "^1.7.1", "better-queue": "^3.8.12", "bluebird": "^3.7.2", - "body-parser": "^1.20.3", "bullmq": "^5.45.2", "chart.js": "^4.4.8", "cloudinary": "^2.6.0", diff --git a/server.js b/server.js index 52f5c6e9e..117c38145 100644 --- a/server.js +++ b/server.js @@ -84,8 +84,8 @@ const SOCKETIO_CORS_ORIGIN_DEV = ["http://localhost:3333", "https://localhost:33 const applyMiddleware = ({ app }) => { app.use(compression()); app.use(cookieParser()); - app.use(bodyParser.json({ limit: "50mb" })); - app.use(bodyParser.urlencoded({ limit: "50mb", extended: true })); + app.use(express.json({ limit: "50mb" })); + app.use(express.urlencoded({ limit: "50mb", extended: true })); app.use(cors({ credentials: true, exposedHeaders: ["set-cookie"] })); // Helper middleware From 0ef2814de309b0f414a6fc20c5195ef25750f86c Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 1 Apr 2025 12:33:41 -0400 Subject: [PATCH 03/34] feature/IO-2885-IntelliPay-App-Postback-Support - Clean intellipay.js, add new route scaffolding --- server/intellipay/intellipay.js | 75 +++++++++++++++++++++++++------ server/routes/intellipayRoutes.js | 20 ++++++--- 2 files changed, 75 insertions(+), 20 deletions(-) diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js index 4af4a50cc..a58d45240 100644 --- a/server/intellipay/intellipay.js +++ b/server/intellipay/intellipay.js @@ -1,7 +1,3 @@ -const path = require("path"); -require("dotenv").config({ - path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`) -}); const queries = require("../graphql-client/queries"); const Dinero = require("dinero.js"); const qs = require("query-string"); @@ -10,18 +6,22 @@ const moment = require("moment"); const logger = require("../utils/logger"); const { sendTaskEmail } = require("../email/sendemail"); const generateEmailTemplate = require("../email/generateTemplate"); - -const domain = process.env.NODE_ENV ? "secure" : "test"; - const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager"); const { InstanceRegion, InstanceEndpoints } = require("../utils/instanceMgr"); +const domain = process.env.NODE_ENV ? "secure" : "test"; + const client = new SecretsManagerClient({ region: InstanceRegion() }); const gqlClient = require("../graphql-client/graphql-client").client; +/** + * @description Get shop credentials from AWS Secrets Manager + * @param bodyshop + * @returns {Promise<{error}|{merchantkey: *, apikey: *}|any>} + */ const getShopCredentials = async (bodyshop) => { // Development only if (process.env.NODE_ENV === undefined) { @@ -49,16 +49,27 @@ const getShopCredentials = async (bodyshop) => { } }; +/** + * @description Decode the comment from base64 + * @param comment + * @returns {any|null} + */ const decodeComment = (comment) => { try { return comment ? JSON.parse(Buffer.from(comment, "base64").toString()) : null; - // eslint-disable-next-line no-unused-vars + // eslint-disable-next-line no-unused-vars } catch (error) { return null; // Handle malformed base64 string gracefully } }; -exports.lightbox_credentials = async (req, res) => { +/** + * @description Get lightbox credentials for the shop + * @param req + * @param res + * @returns {Promise} + */ +const lightboxCredentials = async (req, res) => { const decodedComment = decodeComment(req.body?.comment); const logMeta = { iPayData: req.body?.iPayData, @@ -119,7 +130,13 @@ exports.lightbox_credentials = async (req, res) => { } }; -exports.payment_refund = async (req, res) => { +/** + * @description Process payment refund + * @param req + * @param res + * @returns {Promise} + */ +const paymentRefund = async (req, res) => { const decodedComment = decodeComment(req.body.iPayData?.comment); const logResponseMeta = { iPayData: req.body?.iPayData, @@ -190,7 +207,13 @@ exports.payment_refund = async (req, res) => { } }; -exports.generate_payment_url = async (req, res) => { +/** + * @description Generate payment URL for the shop + * @param req + * @param res + * @returns {Promise} + */ +const generatePaymentUrl = async (req, res) => { const decodedComment = decodeComment(req.body.comment); const logResponseMeta = { iPayData: req.body?.iPayData, @@ -261,8 +284,14 @@ exports.generate_payment_url = async (req, res) => { } }; -//Reference: https://intellipay.com/dist/webapi26.html#operation/fee -exports.checkfee = async (req, res) => { +/** + * @description Check the fee for a given amount + * Reference: https://intellipay.com/dist/webapi26.html#operation/fee + * @param req + * @param res + * @returns {Promise} + */ +const checkFee = async (req, res) => { const logResponseMeta = { bodyshop: { id: req.body?.bodyshop?.id, @@ -359,7 +388,13 @@ exports.checkfee = async (req, res) => { } }; -exports.postback = async (req, res) => { +/** + * @description Handle the postback from Intellipay + * @param req + * @param res + * @returns {Promise} + */ +const postBack = async (req, res) => { const { body: values } = req; const decodedComment = decodeComment(values?.comment); @@ -474,6 +509,7 @@ exports.postback = async (req, res) => { const bodyshop = await gqlClient.request(queries.GET_BODYSHOP_BY_ID, { id: job.jobs_by_pk.shopid }); + const ipMapping = bodyshop.bodyshops_by_pk.intellipay_config?.payment_map; logger.log("intellipay-postback-invoice-job-fetched", "DEBUG", "api", null, { @@ -525,3 +561,14 @@ exports.postback = async (req, res) => { res.status(400).json({ successful: false, error: error.message, ...logResponseMeta }); } }; + +const postBackCallBack = async (req, res) => {}; + +module.exports = { + lightboxCredentials, + paymentRefund, + generatePaymentUrl, + checkFee, + postBack, + postBackCallBack +}; diff --git a/server/routes/intellipayRoutes.js b/server/routes/intellipayRoutes.js index ad0b87323..7c3a2ecec 100644 --- a/server/routes/intellipayRoutes.js +++ b/server/routes/intellipayRoutes.js @@ -1,12 +1,20 @@ const express = require("express"); const router = express.Router(); const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware"); -const { lightbox_credentials, payment_refund, generate_payment_url, postback, checkfee } = require("../intellipay/intellipay"); +const { + lightboxCredentials, + paymentRefund, + generatePaymentUrl, + postBack, + checkFee, + postBackCallBack +} = require("../intellipay/intellipay"); -router.post("/lightbox_credentials", validateFirebaseIdTokenMiddleware, lightbox_credentials); -router.post("/payment_refund", validateFirebaseIdTokenMiddleware, payment_refund); -router.post("/generate_payment_url", validateFirebaseIdTokenMiddleware, generate_payment_url); -router.post("/checkfee", validateFirebaseIdTokenMiddleware, checkfee); -router.post("/postback", postback); +router.post("/lightbox_credentials", validateFirebaseIdTokenMiddleware, lightboxCredentials); +router.post("/payment_refund", validateFirebaseIdTokenMiddleware, paymentRefund); +router.post("/generate_payment_url", validateFirebaseIdTokenMiddleware, generatePaymentUrl); +router.post("/checkfee", validateFirebaseIdTokenMiddleware, checkFee); +router.post("/postback", postBack); +router.post("/postback-callback", postBackCallBack); module.exports = router; From 09c1a8ae35c233e1cb7f0202a3ce3789a5b1ce41 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 1 Apr 2025 12:57:32 -0400 Subject: [PATCH 04/34] feature/IO-2885-IntelliPay-App-Postback-Support - Clean intellipay.js --- server/intellipay/intellipay.js | 110 ++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 48 deletions(-) diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js index a58d45240..169e27fd2 100644 --- a/server/intellipay/intellipay.js +++ b/server/intellipay/intellipay.js @@ -8,6 +8,7 @@ const { sendTaskEmail } = require("../email/sendemail"); const generateEmailTemplate = require("../email/generateTemplate"); const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager"); const { InstanceRegion, InstanceEndpoints } = require("../utils/instanceMgr"); +const { isEmpty, isNumber } = require("lodash"); const domain = process.env.NODE_ENV ? "secure" : "test"; @@ -57,7 +58,6 @@ const getShopCredentials = async (bodyshop) => { const decodeComment = (comment) => { try { return comment ? JSON.parse(Buffer.from(comment, "base64").toString()) : null; - // eslint-disable-next-line no-unused-vars } catch (error) { return null; // Handle malformed base64 string gracefully } @@ -85,17 +85,17 @@ const lightboxCredentials = async (req, res) => { const shopCredentials = await getShopCredentials(req.body.bodyshop); - if (shopCredentials.error) { + if (shopCredentials?.error) { logger.log("intellipay-credentials-error", "ERROR", req.user?.email, null, { message: shopCredentials.error?.message, ...logMeta }); - res.json({ + + return res.json({ message: shopCredentials.error?.message, type: "intellipay-credentials-error", ...logMeta }); - return; } try { @@ -116,13 +116,14 @@ const lightboxCredentials = async (req, res) => { ...logMeta }); - res.send(response.data); + return res.send(response.data); } catch (error) { logger.log("intellipay-lightbox-error", "ERROR", req.user?.email, null, { message: error?.message, ...logMeta }); - res.json({ + + return res.json({ message: error?.message, type: "intellipay-lightbox-error", ...logMeta @@ -154,18 +155,17 @@ const paymentRefund = async (req, res) => { const shopCredentials = await getShopCredentials(req.body.bodyshop); - if (shopCredentials.error) { + if (shopCredentials?.error) { logger.log("intellipay-refund-credentials-error", "ERROR", req.user?.email, null, { credentialsError: shopCredentials.error, ...logResponseMeta }); - res.status(400).json({ + return res.status(400).json({ credentialsError: shopCredentials.error, type: "intellipay-refund-credentials-error", ...logResponseMeta }); - return; } try { @@ -193,13 +193,14 @@ const paymentRefund = async (req, res) => { ...logResponseMeta }); - res.send(response.data); + return res.send(response.data); } catch (error) { logger.log("intellipay-refund-error", "ERROR", req.user?.email, null, { message: error?.message, ...logResponseMeta }); - res.status(500).json({ + + return res.status(500).json({ message: error?.message, type: "intellipay-refund-error", ...logResponseMeta @@ -233,17 +234,17 @@ const generatePaymentUrl = async (req, res) => { const shopCredentials = await getShopCredentials(req.body.bodyshop); - if (shopCredentials.error) { + if (shopCredentials?.error) { logger.log("intellipay-generate-payment-url-credentials-error", "ERROR", req.user?.email, null, { message: shopCredentials.error?.message, ...logResponseMeta }); - res.status(400).json({ + + return res.status(400).json({ message: shopCredentials.error?.message, type: "intellipay-generate-payment-url-credentials-error", ...logResponseMeta }); - return; } try { @@ -274,13 +275,14 @@ const generatePaymentUrl = async (req, res) => { ...logResponseMeta }); - res.send(response.data); + return res.send(response.data); } catch (error) { logger.log("intellipay-generate-payment-url-error", "ERROR", req.user?.email, null, { message: error?.message, ...logResponseMeta }); - res.status(500).json({ message: error?.message, ...logResponseMeta }); + + return res.status(500).json({ message: error?.message, ...logResponseMeta }); } }; @@ -304,24 +306,24 @@ const checkFee = async (req, res) => { logger.log("intellipay-checkfee-request-received", "DEBUG", req.user?.email, null, logResponseMeta); - if (!req.body.amount || req.body.amount <= 0) { + if (!isNumber(req.body?.amount) || req.body?.amount <= 0) { logger.log("intellipay-checkfee-skip", "DEBUG", req.user?.email, null, { message: "Amount is zero or undefined, skipping fee check.", ...logResponseMeta }); - res.json({ fee: 0 }); - return; + + return res.json({ fee: 0 }); } const shopCredentials = await getShopCredentials(req.body.bodyshop); - if (shopCredentials.error) { + if (shopCredentials?.error) { logger.log("intellipay-checkfee-credentials-error", "ERROR", req.user?.email, null, { message: shopCredentials.error?.message, ...logResponseMeta }); - res.status(400).json({ error: shopCredentials.error?.message, ...logResponseMeta }); - return; + + return res.status(400).json({ error: shopCredentials.error?.message, ...logResponseMeta }); } try { @@ -357,34 +359,40 @@ const checkFee = async (req, res) => { message: response.data?.error, ...logResponseMeta }); - res.status(400).json({ + + return res.status(400).json({ error: response.data?.error, type: "intellipay-checkfee-api-error", ...logResponseMeta }); - } else if (response.data < 0) { + } + + if (response.data < 0) { logger.log("intellipay-checkfee-negative-fee", "ERROR", req.user?.email, null, { message: "Fee amount returned is negative.", ...logResponseMeta }); - res.json({ + + return res.json({ error: "Fee amount negative. Check API credentials & account configuration.", ...logResponseMeta, type: "intellipay-checkfee-negative-fee" }); - } else { - logger.log("intellipay-checkfee-success", "DEBUG", req.user?.email, null, { - fee: response.data, - ...logResponseMeta - }); - res.json({ fee: response.data, ...logResponseMeta }); } + + logger.log("intellipay-checkfee-success", "DEBUG", req.user?.email, null, { + fee: response.data, + ...logResponseMeta + }); + + return res.json({ fee: response.data, ...logResponseMeta }); } catch (error) { logger.log("intellipay-checkfee-error", "ERROR", req.user?.email, null, { message: error?.message, ...logResponseMeta }); - res.status(500).json({ error: error?.message, logResponseMeta }); + + return res.status(500).json({ error: error?.message, logResponseMeta }); } }; @@ -406,19 +414,15 @@ const postBack = async (req, res) => { logger.log("intellipay-postback-received", "DEBUG", "api", null, logResponseMeta); try { - if ((!values.invoice || values.invoice === "") && !decodedComment) { - //invoice is specified through the pay link. Comment by IO. + if (isEmpty(values?.invoice) && !decodedComment) { logger.log("intellipay-postback-ignored", "DEBUG", "api", null, { message: "No invoice or comment provided", ...logResponseMeta }); - res.sendStatus(200); - return; + return res.sendStatus(200); } if (decodedComment) { - //Shifted the order to have this first to retain backwards compatibility for the old style of short link. - //This has been triggered by IO and may have multiple jobs. const parsedComment = decodedComment; logger.log("intellipay-postback-parsed-comment", "DEBUG", "api", null, { @@ -426,18 +430,16 @@ const postBack = async (req, res) => { ...logResponseMeta }); - //Adding in the user email to the short pay email. - //Need to check this to ensure backwards compatibility for clients that don't update. - const partialPayments = Array.isArray(parsedComment) ? parsedComment : parsedComment.payments; - // Fetch jobs by job IDs const jobs = await gqlClient.request(queries.GET_JOBS_BY_PKS, { ids: partialPayments.map((p) => p.jobid) }); + const bodyshop = await gqlClient.request(queries.GET_BODYSHOP_BY_ID, { id: jobs.jobs[0].shopid }); + const ipMapping = bodyshop.bodyshops_by_pk.intellipay_config?.payment_map; logger.log("intellipay-postback-jobs-fetched", "DEBUG", "api", null, { @@ -446,7 +448,6 @@ const postBack = async (req, res) => { ...logResponseMeta }); - // Insert new payments const paymentResult = await gqlClient.request(queries.INSERT_NEW_PAYMENT, { paymentInput: partialPayments.map((p) => ({ amount: p.amount, @@ -476,7 +477,7 @@ const postBack = async (req, res) => { ...logResponseMeta }); - if (values.origin === "OneLink" && parsedComment.userEmail) { + if (values?.origin === "OneLink" && parsedComment?.userEmail) { sendTaskEmail({ to: parsedComment.userEmail, subject: `New Payment(s) Received - RO ${jobs.jobs.map((j) => j.ro_number).join(", ")}`, @@ -500,8 +501,11 @@ const postBack = async (req, res) => { }); }); } - res.sendStatus(200); - } else if (values.invoice) { + + return res.sendStatus(200); + } + + if (values?.invoice) { const job = await gqlClient.request(queries.GET_JOB_BY_PK, { id: values.invoice }); @@ -551,14 +555,24 @@ const postBack = async (req, res) => { responseResults, ...logResponseMeta }); - res.sendStatus(200); + + return res.sendStatus(200); } + + // Default case: no valid conditions met + logger.log("intellipay-postback-invalid", "WARN", "api", null, { + message: "No valid invoice or comment provided", + ...logResponseMeta + }); + + return res.status(400).send("Bad Request: No valid invoice or comment provided"); } catch (error) { logger.log("intellipay-postback-error", "ERROR", "api", null, { message: error?.message, ...logResponseMeta }); - res.status(400).json({ successful: false, error: error.message, ...logResponseMeta }); + + return res.status(400).json({ successful: false, error: error.message, ...logResponseMeta }); } }; From c78b9866a3321a32f7d127f9f7f6810aa8e2e7db Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 1 Apr 2025 15:15:48 -0400 Subject: [PATCH 05/34] feature/IO-2885-IntelliPay-App-Postback - Finish ticket --- .../down.sql | 4 + .../up.sql | 2 + server/graphql-client/queries.js | 12 ++ server/intellipay/intellipay.js | 110 ++++++++++++++---- server/routes/intellipayRoutes.js | 4 +- 5 files changed, 108 insertions(+), 24 deletions(-) create mode 100644 hasura/migrations/1743531377681_alter_table_public_bodyshops_add_column_intellipay_merchant_id/down.sql create mode 100644 hasura/migrations/1743531377681_alter_table_public_bodyshops_add_column_intellipay_merchant_id/up.sql diff --git a/hasura/migrations/1743531377681_alter_table_public_bodyshops_add_column_intellipay_merchant_id/down.sql b/hasura/migrations/1743531377681_alter_table_public_bodyshops_add_column_intellipay_merchant_id/down.sql new file mode 100644 index 000000000..2d6bb5c01 --- /dev/null +++ b/hasura/migrations/1743531377681_alter_table_public_bodyshops_add_column_intellipay_merchant_id/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."bodyshops" add column "intellipay_merchant_id" text +-- null unique; diff --git a/hasura/migrations/1743531377681_alter_table_public_bodyshops_add_column_intellipay_merchant_id/up.sql b/hasura/migrations/1743531377681_alter_table_public_bodyshops_add_column_intellipay_merchant_id/up.sql new file mode 100644 index 000000000..90006bbda --- /dev/null +++ b/hasura/migrations/1743531377681_alter_table_public_bodyshops_add_column_intellipay_merchant_id/up.sql @@ -0,0 +1,2 @@ +alter table "public"."bodyshops" add column "intellipay_merchant_id" text + null unique; diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index f05ea7ec5..44a7cbffb 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -2832,3 +2832,15 @@ exports.GET_DOCUMENTS_BY_IDS = ` takenat } }`; + +exports.GET_JOBID_BY_MERCHANTID_RONUMBER = ` +query GET_JOBID_BY_MERCHANTID_RONUMBER($merchantID: String!, $roNumber: String!) { + jobs(where: {ro_number: {_eq: $roNumber}, bodyshop: {intellipay_merchant_id: {_eq: $merchantID}}}) { + id + shopid + bodyshop { + id + intellipay_config + } + } +}`; diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js index 169e27fd2..be8d9f24c 100644 --- a/server/intellipay/intellipay.js +++ b/server/intellipay/intellipay.js @@ -18,21 +18,52 @@ const client = new SecretsManagerClient({ const gqlClient = require("../graphql-client/graphql-client").client; +/** + * Generates a properly formatted Cpteller API URL + * @param {Object} options - URL configuration options + * @param {string} options.apiType - 'webapi' or 'custapi' + * @param {string} [options.version] - API version (e.g., '26' for webapi) + * @param {Object} [options.params] - URL query parameters + * @returns {string} - The formatted Cpteller URL + */ +const getCptellerUrl = (options) => { + const { apiType = "webapi", version, params = {} } = options; + + // Base URL construction + let url = `https://${domain}.cpteller.com/api/`; + + // Add version if specified for webapi + if (apiType === "webapi" && version) { + url += `${version}/`; + } + + // Add the API endpoint + url += `${apiType}.cfc`; + + // Add query parameters if any exist + const queryParams = new URLSearchParams(params).toString(); + if (queryParams) { + url += `?${queryParams}`; + } + + return url; +}; + /** * @description Get shop credentials from AWS Secrets Manager * @param bodyshop * @returns {Promise<{error}|{merchantkey: *, apikey: *}|any>} */ const getShopCredentials = async (bodyshop) => { - // Development only - if (process.env.NODE_ENV === undefined) { + // In Dev/Testing we will use the environment variables + if (process.env?.NODE_ENV !== "production") { return { merchantkey: process.env.INTELLIPAY_MERCHANTKEY, apikey: process.env.INTELLIPAY_APIKEY }; } - // Production code + // In Production we will use the AWS Secrets Manager if (bodyshop?.imexshopid) { try { const secret = await client.send( @@ -106,7 +137,10 @@ const lightboxCredentials = async (req, res) => { ...shopCredentials, operatingenv: "businessattended" }), - url: `https://${domain}.cpteller.com/api/custapi.cfc?method=autoterminal${req.body.refresh ? "_refresh" : ""}` //autoterminal_refresh + url: getCptellerUrl({ + apiType: "custapi", + params: { method: `autoterminal${req.body.refresh ? "_refresh" : ""}` } + }) }; const response = await axios(options); @@ -178,7 +212,11 @@ const paymentRefund = async (req, res) => { paymentid: req.body.paymentid, amount: req.body.amount }), - url: `https://${domain}.cpteller.com/api/26/webapi.cfc?method=payment_refund` + url: getCptellerUrl({ + apiType: "webapi", + version: "26", + params: { method: "payment_refund" } + }) }; logger.log("intellipay-refund-options-prepared", "DEBUG", req.user?.email, null, { @@ -259,7 +297,10 @@ const generatePaymentUrl = async (req, res) => { invoice: req.body.invoice, createshorturl: true }), - url: `https://${domain}.cpteller.com/api/custapi.cfc?method=generate_lightbox_url` + url: getCptellerUrl({ + apiType: "custapi", + params: { method: "generate_lightbox_url" } + }) }; logger.log("intellipay-generate-payment-url-options-prepared", "DEBUG", req.user?.email, null, { @@ -344,7 +385,7 @@ const checkFee = async (req, res) => { }, { sort: false } // Ensure query string order is preserved ), - url: `https://${domain}.cpteller.com/api/26/webapi.cfc` + url: getCptellerUrl({ apiType: "webapi", version: "26" }) }; logger.log("intellipay-checkfee-options-prepared", "DEBUG", req.user?.email, null, { @@ -506,19 +547,49 @@ const postBack = async (req, res) => { } if (values?.invoice) { - const job = await gqlClient.request(queries.GET_JOB_BY_PK, { - id: values.invoice + // Early Bail on Merchant ID + if (!values?.merchantid) { + logger.log("intellipay-postback-no-merchantid", "ERROR", "api", null, { + message: "Merchant ID is missing", + ...logResponseMeta + }); + + return res.status(400).send("Bad Request: Merchant ID is missing"); + } + + const result = await gqlClient.request(queries.GET_JOBID_BY_MERCHANTID_RONUMBER, { + merchantID: values.merchantid, + roNumber: values.invoice }); - const bodyshop = await gqlClient.request(queries.GET_BODYSHOP_BY_ID, { - id: job.jobs_by_pk.shopid - }); + // Early Bail on No Jobs Found + if (!result?.jobs?.length) { + logger.log("intellipay-postback-job-not-found", "ERROR", "api", null, { + message: "Job not found", + ...logResponseMeta + }); - const ipMapping = bodyshop.bodyshops_by_pk.intellipay_config?.payment_map; + return res.status(400).send("Bad Request: Job not found"); + } + + const job = result?.jobs?.[0]; + + const bodyshop = job?.bodyshop; + + // Early Bail on no Bodyshop Found + if (!bodyshop) { + logger.log("intellipay-postback-bodyshop-not-found", "ERROR", "api", null, { + message: "Bodyshop not found", + ...logResponseMeta + }); + + return res.status(400).send("Bad Request: Bodyshop not found"); + } + + const ipMapping = bodyshop?.intellipay_config?.payment_map; logger.log("intellipay-postback-invoice-job-fetched", "DEBUG", "api", null, { job, - bodyshop, ...logResponseMeta }); @@ -528,7 +599,7 @@ const postBack = async (req, res) => { transactionid: values.authcode, payer: "Customer", type: ipMapping ? ipMapping[(values.cardtype || "").toLowerCase()] || values.cardtype : values.cardtype, - jobid: values.invoice, + jobid: job.id, date: moment(Date.now()) } }); @@ -541,9 +612,9 @@ const postBack = async (req, res) => { const responseResults = await gqlClient.request(queries.INSERT_PAYMENT_RESPONSE, { paymentResponse: { amount: values.total, - bodyshopid: bodyshop.bodyshops_by_pk.id, + bodyshopid: bodyshop.id, paymentid: paymentResult.id, - jobid: values.invoice, + jobid: job.id, declinereason: "Approved", ext_paymentid: values.paymentid, successful: true, @@ -576,13 +647,10 @@ const postBack = async (req, res) => { } }; -const postBackCallBack = async (req, res) => {}; - module.exports = { lightboxCredentials, paymentRefund, generatePaymentUrl, checkFee, - postBack, - postBackCallBack + postBack }; diff --git a/server/routes/intellipayRoutes.js b/server/routes/intellipayRoutes.js index 7c3a2ecec..7a0425fd2 100644 --- a/server/routes/intellipayRoutes.js +++ b/server/routes/intellipayRoutes.js @@ -6,8 +6,7 @@ const { paymentRefund, generatePaymentUrl, postBack, - checkFee, - postBackCallBack + checkFee } = require("../intellipay/intellipay"); router.post("/lightbox_credentials", validateFirebaseIdTokenMiddleware, lightboxCredentials); @@ -15,6 +14,5 @@ router.post("/payment_refund", validateFirebaseIdTokenMiddleware, paymentRefund) router.post("/generate_payment_url", validateFirebaseIdTokenMiddleware, generatePaymentUrl); router.post("/checkfee", validateFirebaseIdTokenMiddleware, checkFee); router.post("/postback", postBack); -router.post("/postback-callback", postBackCallBack); module.exports = router; From 9bf6ba9cf082c1e9e00986b00b021057161630b2 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 2 Apr 2025 11:09:03 -0400 Subject: [PATCH 06/34] feature/IO-2885-IntelliPay-App-Postback - Refactor / Add Tests --- server/intellipay/intellipay.js | 295 ++-------------- server/intellipay/intellipay.test.js | 316 ++++++++++++++++++ .../{ => lib}/aws-secrets-manager.js | 0 server/intellipay/lib/decodeComment.js | 14 + server/intellipay/lib/getCptellerUrl.js | 34 ++ server/intellipay/lib/getPaymentType.js | 12 + server/intellipay/lib/getShopCredentials.js | 40 +++ .../lib/handleCommentBasedPayment.js | 81 +++++ .../lib/handleInvoiceBasedPayment.js | 101 ++++++ .../lib/handlePaymentValidationError.js | 18 + .../lib/sendPaymentNotificationEmail.js | 41 +++ vitest.config.js | 9 +- 12 files changed, 686 insertions(+), 275 deletions(-) create mode 100644 server/intellipay/intellipay.test.js rename server/intellipay/{ => lib}/aws-secrets-manager.js (100%) create mode 100644 server/intellipay/lib/decodeComment.js create mode 100644 server/intellipay/lib/getCptellerUrl.js create mode 100644 server/intellipay/lib/getPaymentType.js create mode 100644 server/intellipay/lib/getShopCredentials.js create mode 100644 server/intellipay/lib/handleCommentBasedPayment.js create mode 100644 server/intellipay/lib/handleInvoiceBasedPayment.js create mode 100644 server/intellipay/lib/handlePaymentValidationError.js create mode 100644 server/intellipay/lib/sendPaymentNotificationEmail.js diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js index be8d9f24c..29f8e978a 100644 --- a/server/intellipay/intellipay.js +++ b/server/intellipay/intellipay.js @@ -1,98 +1,14 @@ -const queries = require("../graphql-client/queries"); const Dinero = require("dinero.js"); const qs = require("query-string"); const axios = require("axios"); -const moment = require("moment"); const logger = require("../utils/logger"); -const { sendTaskEmail } = require("../email/sendemail"); -const generateEmailTemplate = require("../email/generateTemplate"); -const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager"); -const { InstanceRegion, InstanceEndpoints } = require("../utils/instanceMgr"); const { isEmpty, isNumber } = require("lodash"); - -const domain = process.env.NODE_ENV ? "secure" : "test"; - -const client = new SecretsManagerClient({ - region: InstanceRegion() -}); - -const gqlClient = require("../graphql-client/graphql-client").client; - -/** - * Generates a properly formatted Cpteller API URL - * @param {Object} options - URL configuration options - * @param {string} options.apiType - 'webapi' or 'custapi' - * @param {string} [options.version] - API version (e.g., '26' for webapi) - * @param {Object} [options.params] - URL query parameters - * @returns {string} - The formatted Cpteller URL - */ -const getCptellerUrl = (options) => { - const { apiType = "webapi", version, params = {} } = options; - - // Base URL construction - let url = `https://${domain}.cpteller.com/api/`; - - // Add version if specified for webapi - if (apiType === "webapi" && version) { - url += `${version}/`; - } - - // Add the API endpoint - url += `${apiType}.cfc`; - - // Add query parameters if any exist - const queryParams = new URLSearchParams(params).toString(); - if (queryParams) { - url += `?${queryParams}`; - } - - return url; -}; - -/** - * @description Get shop credentials from AWS Secrets Manager - * @param bodyshop - * @returns {Promise<{error}|{merchantkey: *, apikey: *}|any>} - */ -const getShopCredentials = async (bodyshop) => { - // In Dev/Testing we will use the environment variables - if (process.env?.NODE_ENV !== "production") { - return { - merchantkey: process.env.INTELLIPAY_MERCHANTKEY, - apikey: process.env.INTELLIPAY_APIKEY - }; - } - - // In Production we will use the AWS Secrets Manager - if (bodyshop?.imexshopid) { - try { - const secret = await client.send( - new GetSecretValueCommand({ - SecretId: `intellipay-credentials-${bodyshop.imexshopid}`, - VersionStage: "AWSCURRENT" // VersionStage defaults to AWSCURRENT if unspecified - }) - ); - return JSON.parse(secret.SecretString); - } catch (error) { - return { - error: error.message - }; - } - } -}; - -/** - * @description Decode the comment from base64 - * @param comment - * @returns {any|null} - */ -const decodeComment = (comment) => { - try { - return comment ? JSON.parse(Buffer.from(comment, "base64").toString()) : null; - } catch (error) { - return null; // Handle malformed base64 string gracefully - } -}; +const handleCommentBasedPayment = require("./lib/handleCommentBasedPayment"); +const handleInvoiceBasedPayment = require("./lib/handleInvoiceBasedPayment"); +const logValidationError = require("./lib/handlePaymentValidationError"); +const getCptellerUrl = require("./lib/getCptellerUrl"); +const getShopCredentials = require("./lib/getShopCredentials"); +const decodeComment = require("./lib/decodeComment"); /** * @description Get lightbox credentials for the shop @@ -443,207 +359,42 @@ const checkFee = async (req, res) => { * @param res * @returns {Promise} */ +/** + * Handle the postback from Intellipay payment system + */ const postBack = async (req, res) => { const { body: values } = req; const decodedComment = decodeComment(values?.comment); + const logMeta = { iprequest: values, decodedComment }; - const logResponseMeta = { - iprequest: values, - decodedComment - }; - - logger.log("intellipay-postback-received", "DEBUG", "api", null, logResponseMeta); + logger.log("intellipay-postback-received", "DEBUG", "api", null, logMeta); try { + // Handle empty/invalid requests if (isEmpty(values?.invoice) && !decodedComment) { logger.log("intellipay-postback-ignored", "DEBUG", "api", null, { message: "No invoice or comment provided", - ...logResponseMeta + ...logMeta }); return res.sendStatus(200); } + // Process payment based on data type if (decodedComment) { - const parsedComment = decodedComment; - - logger.log("intellipay-postback-parsed-comment", "DEBUG", "api", null, { - parsedComment, - ...logResponseMeta - }); - - const partialPayments = Array.isArray(parsedComment) ? parsedComment : parsedComment.payments; - - const jobs = await gqlClient.request(queries.GET_JOBS_BY_PKS, { - ids: partialPayments.map((p) => p.jobid) - }); - - const bodyshop = await gqlClient.request(queries.GET_BODYSHOP_BY_ID, { - id: jobs.jobs[0].shopid - }); - - const ipMapping = bodyshop.bodyshops_by_pk.intellipay_config?.payment_map; - - logger.log("intellipay-postback-jobs-fetched", "DEBUG", "api", null, { - jobs, - parsedComment, - ...logResponseMeta - }); - - const paymentResult = await gqlClient.request(queries.INSERT_NEW_PAYMENT, { - paymentInput: partialPayments.map((p) => ({ - amount: p.amount, - transactionid: values.authcode, - payer: "Customer", - type: ipMapping ? ipMapping[(values.cardtype || "").toLowerCase()] || values.cardtype : values.cardtype, - jobid: p.jobid, - date: moment(Date.now()), - payment_responses: { - data: { - amount: values.total, - bodyshopid: bodyshop.bodyshops_by_pk.id, - jobid: p.jobid, - declinereason: "Approved", - ext_paymentid: values.paymentid, - successful: true, - response: values - } - } - })) - }); - - logger.log("intellipay-postback-payment-success", "DEBUG", "api", null, { - paymentResult, - jobs, - parsedComment, - ...logResponseMeta - }); - - if (values?.origin === "OneLink" && parsedComment?.userEmail) { - sendTaskEmail({ - to: parsedComment.userEmail, - subject: `New Payment(s) Received - RO ${jobs.jobs.map((j) => j.ro_number).join(", ")}`, - type: "html", - html: generateEmailTemplate({ - header: "New Payment(s) Received", - subHeader: "", - body: jobs.jobs - .map( - (job) => - `Reference: ${job.ro_number || "N/A"} | ${job.ownr_co_nm ? job.ownr_co_nm : `${job.ownr_fn || ""} ${job.ownr_ln || ""}`.trim()} | ${`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${job.v_model_desc || ""}`.trim()} | $${partialPayments.find((p) => p.jobid === job.id).amount}` - ) - .join("
") - }) - }).catch((error) => { - logger.log("intellipay-postback-email-error", "ERROR", "api", null, { - message: error.message, - jobs, - paymentResult, - ...logResponseMeta - }); - }); - } - - return res.sendStatus(200); + return await handleCommentBasedPayment(values, decodedComment, logger, logMeta, res); + } else if (values?.invoice) { + return await handleInvoiceBasedPayment(values, logger, logMeta, res); + } else { + // This should be caught by first validation, but as a safeguard + logValidationError("intellipay-postback-invalid", "No valid invoice or comment provided", logMeta); + return res.status(400).send("Bad Request: No valid invoice or comment provided"); } - - if (values?.invoice) { - // Early Bail on Merchant ID - if (!values?.merchantid) { - logger.log("intellipay-postback-no-merchantid", "ERROR", "api", null, { - message: "Merchant ID is missing", - ...logResponseMeta - }); - - return res.status(400).send("Bad Request: Merchant ID is missing"); - } - - const result = await gqlClient.request(queries.GET_JOBID_BY_MERCHANTID_RONUMBER, { - merchantID: values.merchantid, - roNumber: values.invoice - }); - - // Early Bail on No Jobs Found - if (!result?.jobs?.length) { - logger.log("intellipay-postback-job-not-found", "ERROR", "api", null, { - message: "Job not found", - ...logResponseMeta - }); - - return res.status(400).send("Bad Request: Job not found"); - } - - const job = result?.jobs?.[0]; - - const bodyshop = job?.bodyshop; - - // Early Bail on no Bodyshop Found - if (!bodyshop) { - logger.log("intellipay-postback-bodyshop-not-found", "ERROR", "api", null, { - message: "Bodyshop not found", - ...logResponseMeta - }); - - return res.status(400).send("Bad Request: Bodyshop not found"); - } - - const ipMapping = bodyshop?.intellipay_config?.payment_map; - - logger.log("intellipay-postback-invoice-job-fetched", "DEBUG", "api", null, { - job, - ...logResponseMeta - }); - - const paymentResult = await gqlClient.request(queries.INSERT_NEW_PAYMENT, { - paymentInput: { - amount: values.total, - transactionid: values.authcode, - payer: "Customer", - type: ipMapping ? ipMapping[(values.cardtype || "").toLowerCase()] || values.cardtype : values.cardtype, - jobid: job.id, - date: moment(Date.now()) - } - }); - - logger.log("intellipay-postback-invoice-payment-success", "DEBUG", "api", null, { - paymentResult, - ...logResponseMeta - }); - - const responseResults = await gqlClient.request(queries.INSERT_PAYMENT_RESPONSE, { - paymentResponse: { - amount: values.total, - bodyshopid: bodyshop.id, - paymentid: paymentResult.id, - jobid: job.id, - declinereason: "Approved", - ext_paymentid: values.paymentid, - successful: true, - response: values - } - }); - - logger.log("intellipay-postback-invoice-response-success", "DEBUG", "api", null, { - responseResults, - ...logResponseMeta - }); - - return res.sendStatus(200); - } - - // Default case: no valid conditions met - logger.log("intellipay-postback-invalid", "WARN", "api", null, { - message: "No valid invoice or comment provided", - ...logResponseMeta - }); - - return res.status(400).send("Bad Request: No valid invoice or comment provided"); } catch (error) { logger.log("intellipay-postback-error", "ERROR", "api", null, { message: error?.message, - ...logResponseMeta + ...logMeta }); - - return res.status(400).json({ successful: false, error: error.message, ...logResponseMeta }); + return res.status(400).json({ successful: false, error: error.message, ...logMeta }); } }; diff --git a/server/intellipay/intellipay.test.js b/server/intellipay/intellipay.test.js new file mode 100644 index 000000000..472e2ea0f --- /dev/null +++ b/server/intellipay/intellipay.test.js @@ -0,0 +1,316 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; + +const getPaymentType = require("./lib/getPaymentType"); +const decodeComment = require("./lib/decodeComment"); +const getCptellerUrl = require("./lib/getCptellerUrl"); +const handlePaymentValidationError = require("./lib/handlePaymentValidationError"); +const getShopCredentials = require("./lib/getShopCredentials"); + +/** + * @description Decode a base64-encoded JSON comment + */ +describe("decodeComment", () => { + it("decodes a valid base64-encoded JSON comment", () => { + // {"test":"data"} encoded in base64 + const encoded = "eyJ0ZXN0IjoiZGF0YSJ9"; + const expected = { test: "data" }; + expect(decodeComment(encoded)).toEqual(expected); + }); + + it("decodes a complex base64-encoded JSON with payments", () => { + // {"payments":[{"jobid":"123"}]} encoded in base64 + const encoded = "eyJwYXltZW50cyI6W3siam9iaWQiOiIxMjMifV19"; + const expected = { payments: [{ jobid: "123" }] }; + expect(decodeComment(encoded)).toEqual(expected); + }); + + it("returns null when comment is null", () => { + expect(decodeComment(null)).toBeNull(); + }); + + it("returns null when comment is undefined", () => { + expect(decodeComment(undefined)).toBeNull(); + }); + + it("returns null when comment is an empty string", () => { + expect(decodeComment("")).toBeNull(); + }); + + it("returns null when comment is malformed base64", () => { + expect(decodeComment("!@#$%")).toBeNull(); + }); + + it("returns null when comment is valid base64 but not valid JSON", () => { + // "invalid" in base64 is "aW52YWxpZA==" + expect(decodeComment("aW52YWxpZA==")).toBeNull(); + }); +}); + +/** + * @description Get the payment type based on the card type + */ +describe("getPaymentType", () => { + it("returns mapped value when card type exists in mapping", () => { + const ipMapping = { visa: "Visa Card", amex: "American Express" }; + expect(getPaymentType(ipMapping, "visa")).toBe("Visa Card"); + }); + + it("returns original value when card type not in mapping", () => { + const ipMapping = { visa: "Visa Card" }; + expect(getPaymentType(ipMapping, "mastercard")).toBe("mastercard"); + }); + + it("handles lowercase conversion", () => { + const ipMapping = { visa: "Visa Card" }; + expect(getPaymentType(ipMapping, "VISA")).toBe("Visa Card"); + }); + + it("handles null mapping", () => { + expect(getPaymentType(null, "visa")).toBe("visa"); + }); + + it("handles undefined mapping", () => { + expect(getPaymentType(undefined, "visa")).toBe("visa"); + }); + + it("handles empty string card type", () => { + const ipMapping = { visa: "Visa Card" }; + expect(getPaymentType(ipMapping, "")).toBe(""); + }); + + it("handles undefined card type", () => { + const ipMapping = { visa: "Visa Card" }; + expect(getPaymentType(ipMapping, undefined)).toBe(undefined); + }); +}); + +/** + * @description Get the CPTeller URL based on environment and parameters + */ +describe("getCptellerUrl", () => { + const originalEnv = process.env.NODE_ENV; + + afterEach(() => { + // Restore the original NODE_ENV after each test + process.env.NODE_ENV = originalEnv; + }); + + it("uses test domain in non-production environment", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({ apiType: "webapi" }); + expect(url).toEqual("https://test.cpteller.com/api/webapi.cfc"); + }); + + it("uses secure domain in production environment", () => { + process.env.NODE_ENV = "production"; + const url = getCptellerUrl({ apiType: "webapi" }); + expect(url).toEqual("https://secure.cpteller.com/api/webapi.cfc"); + }); + + it("adds version number for webapi type", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({ apiType: "webapi", version: "26" }); + expect(url).toEqual("https://test.cpteller.com/api/26/webapi.cfc"); + }); + + it("constructs custapi URL without version number", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({ apiType: "custapi", version: "26" }); + expect(url).toEqual("https://test.cpteller.com/api/custapi.cfc"); + }); + + it("adds query parameters to the URL", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({ + apiType: "webapi", + params: { method: "payment_refund", test: "value" } + }); + expect(url).toEqual("https://test.cpteller.com/api/webapi.cfc?method=payment_refund&test=value"); + }); + + it("handles empty params object", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({ apiType: "webapi", params: {} }); + expect(url).toEqual("https://test.cpteller.com/api/webapi.cfc"); + }); + + it("defaults to webapi when no apiType is provided", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({}); + expect(url).toEqual("https://test.cpteller.com/api/webapi.cfc"); + }); + + it("combines version and query parameters correctly", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({ + apiType: "webapi", + version: "26", + params: { method: "fee" } + }); + expect(url).toEqual("https://test.cpteller.com/api/26/webapi.cfc?method=fee"); + }); +}); + +/** + * @description Get shop credentials from AWS Secrets Manager or environment variables + */ + +describe("getShopCredentials", () => { + const originalEnv = { ...process.env }; + let mockSend; + + beforeEach(() => { + // Create a mock function for send + mockSend = vi.fn(); + + // Mock the entire AWS SDK module + vi.mock("@aws-sdk/client-secrets-manager", () => { + return { + SecretsManagerClient: vi.fn(() => ({ + send: mockSend + })), + GetSecretValueCommand: vi.fn((input) => input) + }; + }); + + // Setup test environment variables + process.env.INTELLIPAY_MERCHANTKEY = "test-merchant-key"; + process.env.INTELLIPAY_APIKEY = "test-api-key"; + + // Clear module cache to ensure fresh mock is used + vi.resetModules(); + }); + + afterEach(() => { + // Restore environment and clear mocks + process.env = { ...originalEnv }; + vi.restoreAllMocks(); + vi.unmock("@aws-sdk/client-secrets-manager"); + }); + + it("returns environment variables in non-production environment", async () => { + process.env.NODE_ENV = "development"; + + const result = await getShopCredentials({ imexshopid: "12345" }); + + expect(result).toEqual({ + merchantkey: "test-merchant-key", + apikey: "test-api-key" + }); + expect(mockSend).not.toHaveBeenCalled(); + }); + + it("returns undefined when imexshopid is missing in production", async () => { + process.env.NODE_ENV = "production"; + + const result = await getShopCredentials({ name: "Test Shop" }); + + expect(result).toBeUndefined(); + expect(mockSend).not.toHaveBeenCalled(); + }); + + it("returns undefined for null bodyshop in production", async () => { + process.env.NODE_ENV = "production"; + + const result = await getShopCredentials(null); + + expect(result).toBeUndefined(); + expect(mockSend).not.toHaveBeenCalled(); + }); + + it("returns undefined for undefined bodyshop in production", async () => { + process.env.NODE_ENV = "production"; + + const result = await getShopCredentials(undefined); + + expect(result).toBeUndefined(); + expect(mockSend).not.toHaveBeenCalled(); + }); +}); + +/** + * @description Handle payment validation errors + */ +describe("handlePaymentValidationError", () => { + it("logs error and sends 400 response", () => { + // Create mock objects + const mockLog = vi.fn(); + const mockLogger = { log: mockLog }; + const mockRes = { + status: vi.fn().mockReturnThis(), + send: vi.fn().mockReturnThis() + }; + + // Test data + const logCode = "test-validation-error"; + const message = "Invalid data"; + const logMeta = { field: "test", value: 123 }; + + // Call the function + const result = handlePaymentValidationError(mockRes, mockLogger, logCode, message, logMeta); + + // Verify logger.log was called correctly + expect(mockLog).toHaveBeenCalledWith(logCode, "ERROR", "api", null, { message, ...logMeta }); + + // Verify res.status was called with 400 + expect(mockRes.status).toHaveBeenCalledWith(400); + + // Verify res.send was called with correct message + expect(mockRes.send).toHaveBeenCalledWith(`Bad Request: ${message}`); + + // Verify the function returns the response + expect(result).toBe(mockRes); + }); + + it("formats different error messages correctly", () => { + const mockLog = vi.fn(); + const mockLogger = { log: mockLog }; + const mockRes = { + status: vi.fn().mockReturnThis(), + send: vi.fn().mockReturnThis() + }; + + handlePaymentValidationError(mockRes, mockLogger, "error-code", "Custom error"); + + expect(mockRes.send).toHaveBeenCalledWith("Bad Request: Custom error"); + }); + + it("passes different logCodes to logger", () => { + const mockLog = vi.fn(); + const mockLogger = { log: mockLog }; + const mockRes = { + status: vi.fn().mockReturnThis(), + send: vi.fn().mockReturnThis() + }; + + handlePaymentValidationError(mockRes, mockLogger, "custom-log-code", "Error message"); + + expect(mockLog).toHaveBeenCalledWith("custom-log-code", "ERROR", "api", null, { message: "Error message" }); + }); + + it("works with minimal logMeta", () => { + const mockLog = vi.fn(); + const mockLogger = { log: mockLog }; + const mockRes = { + status: vi.fn().mockReturnThis(), + send: vi.fn().mockReturnThis() + }; + + handlePaymentValidationError(mockRes, mockLogger, "error-code", "Error message", {}); + + expect(mockLog).toHaveBeenCalledWith("error-code", "ERROR", "api", null, { message: "Error message" }); + }); + + it("works with undefined logMeta", () => { + const mockLog = vi.fn(); + const mockLogger = { log: mockLog }; + const mockRes = { + status: vi.fn().mockReturnThis(), + send: vi.fn().mockReturnThis() + }; + + handlePaymentValidationError(mockRes, mockLogger, "error-code", "Error message"); + + expect(mockLog).toHaveBeenCalledWith("error-code", "ERROR", "api", null, { message: "Error message" }); + }); +}); diff --git a/server/intellipay/aws-secrets-manager.js b/server/intellipay/lib/aws-secrets-manager.js similarity index 100% rename from server/intellipay/aws-secrets-manager.js rename to server/intellipay/lib/aws-secrets-manager.js diff --git a/server/intellipay/lib/decodeComment.js b/server/intellipay/lib/decodeComment.js new file mode 100644 index 000000000..324e4e643 --- /dev/null +++ b/server/intellipay/lib/decodeComment.js @@ -0,0 +1,14 @@ +/** + * @description Decode the comment from base64 + * @param comment + * @returns {any|null} + */ +const decodeComment = (comment) => { + try { + return comment ? JSON.parse(Buffer.from(comment, "base64").toString()) : null; + } catch (error) { + return null; // Handle malformed base64 string gracefully + } +}; + +module.exports = decodeComment; diff --git a/server/intellipay/lib/getCptellerUrl.js b/server/intellipay/lib/getCptellerUrl.js new file mode 100644 index 000000000..358ce1c5e --- /dev/null +++ b/server/intellipay/lib/getCptellerUrl.js @@ -0,0 +1,34 @@ +/** + * Generates a properly formatted Cpteller API URL + * @param {Object} options - URL configuration options + * @param {string} options.apiType - 'webapi' or 'custapi' + * @param {string} [options.version] - API version (e.g., '26' for webapi) + * @param {Object} [options.params] - URL query parameters + * @returns {string} - The formatted Cpteller URL + */ +const getCptellerUrl = (options) => { + const domain = process.env?.NODE_ENV === "production" ? "secure" : "test"; + + const { apiType = "webapi", version, params = {} } = options; + + // Base URL construction + let url = `https://${domain}.cpteller.com/api/`; + + // Add version if specified for webapi + if (apiType === "webapi" && version) { + url += `${version}/`; + } + + // Add the API endpoint + url += `${apiType}.cfc`; + + // Add query parameters if any exist + const queryParams = new URLSearchParams(params).toString(); + if (queryParams) { + url += `?${queryParams}`; + } + + return url; +}; + +module.exports = getCptellerUrl; diff --git a/server/intellipay/lib/getPaymentType.js b/server/intellipay/lib/getPaymentType.js new file mode 100644 index 000000000..08be4f81b --- /dev/null +++ b/server/intellipay/lib/getPaymentType.js @@ -0,0 +1,12 @@ +/** + * @description Get payment type based on IP mapping + * @param ipMapping + * @param cardType + * @returns {*} + */ +const getPaymentType = (ipMapping, cardType) => { + const normalizedCardType = (cardType || "").toLowerCase(); + return ipMapping ? ipMapping[normalizedCardType] || cardType : cardType; +}; + +module.exports = getPaymentType; diff --git a/server/intellipay/lib/getShopCredentials.js b/server/intellipay/lib/getShopCredentials.js new file mode 100644 index 000000000..da18b9d25 --- /dev/null +++ b/server/intellipay/lib/getShopCredentials.js @@ -0,0 +1,40 @@ +const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager"); +const { InstanceRegion } = require("../../utils/instanceMgr"); + +const client = new SecretsManagerClient({ + region: InstanceRegion() +}); + +/** + * @description Get shop credentials from AWS Secrets Manager + * @param bodyshop + * @returns {Promise<{error}|{merchantkey: *, apikey: *}|any>} + */ +const getShopCredentials = async (bodyshop) => { + // In Dev/Testing we will use the environment variables + if (process.env?.NODE_ENV !== "production") { + return { + merchantkey: process.env.INTELLIPAY_MERCHANTKEY, + apikey: process.env.INTELLIPAY_APIKEY + }; + } + + // In Production, we will use the AWS Secrets Manager + if (bodyshop?.imexshopid) { + try { + const secret = await client.send( + new GetSecretValueCommand({ + SecretId: `intellipay-credentials-${bodyshop.imexshopid}`, + VersionStage: "AWSCURRENT" // VersionStage defaults to AWSCURRENT if unspecified + }) + ); + return JSON.parse(secret.SecretString); + } catch (error) { + return { + error: error.message + }; + } + } +}; + +module.exports = getShopCredentials; diff --git a/server/intellipay/lib/handleCommentBasedPayment.js b/server/intellipay/lib/handleCommentBasedPayment.js new file mode 100644 index 000000000..535e92ab8 --- /dev/null +++ b/server/intellipay/lib/handleCommentBasedPayment.js @@ -0,0 +1,81 @@ +const sendPaymentNotificationEmail = require("./sendPaymentNotificationEmail"); +const { INSERT_NEW_PAYMENT, GET_BODYSHOP_BY_ID, GET_JOBS_BY_PKS } = require("../../graphql-client/queries"); +const getPaymentType = require("./getPaymentType"); +const moment = require("moment"); + +const gqlClient = require("../../graphql-client/graphql-client").client; + +/** + * @description Handle comment-based payment processing + * @param values + * @param decodedComment + * @param logger + * @param logMeta + * @param res + * @returns {Promise<*>} + */ +const handleCommentBasedPayment = async (values, decodedComment, logger, logMeta, res) => { + logger.log("intellipay-postback-parsed-comment", "DEBUG", "api", null, { + parsedComment: decodedComment, + ...logMeta + }); + + const partialPayments = Array.isArray(decodedComment) ? decodedComment : decodedComment.payments; + + // Fetch job data + const jobs = await gqlClient.request(GET_JOBS_BY_PKS, { + ids: partialPayments.map((p) => p.jobid) + }); + + // Fetch bodyshop data + const bodyshop = await gqlClient.request(GET_BODYSHOP_BY_ID, { + id: jobs.jobs[0].shopid + }); + + const ipMapping = bodyshop.bodyshops_by_pk.intellipay_config?.payment_map; + + logger.log("intellipay-postback-jobs-fetched", "DEBUG", "api", null, { + jobs, + parsedComment: decodedComment, + ...logMeta + }); + + // Create payment records + const paymentResult = await gqlClient.request(INSERT_NEW_PAYMENT, { + paymentInput: partialPayments.map((p) => ({ + amount: p.amount, + transactionid: values.authcode, + payer: "Customer", + type: getPaymentType(ipMapping, values.cardtype), + jobid: p.jobid, + date: moment(Date.now()), + payment_responses: { + data: { + amount: values.total, + bodyshopid: bodyshop.bodyshops_by_pk.id, + jobid: p.jobid, + declinereason: "Approved", + ext_paymentid: values.paymentid, + successful: true, + response: values + } + } + })) + }); + + logger.log("intellipay-postback-payment-success", "DEBUG", "api", null, { + paymentResult, + jobs, + parsedComment: decodedComment, + ...logMeta + }); + + // Send notification email if needed + if (values?.origin === "OneLink" && decodedComment?.userEmail) { + await sendPaymentNotificationEmail(decodedComment.userEmail, jobs, partialPayments, logger, logMeta); + } + + return res.sendStatus(200); +}; + +module.exports = handleCommentBasedPayment; diff --git a/server/intellipay/lib/handleInvoiceBasedPayment.js b/server/intellipay/lib/handleInvoiceBasedPayment.js new file mode 100644 index 000000000..f99378d56 --- /dev/null +++ b/server/intellipay/lib/handleInvoiceBasedPayment.js @@ -0,0 +1,101 @@ +const handlePaymentValidationError = require("./handlePaymentValidationError"); +const { + GET_JOBID_BY_MERCHANTID_RONUMBER, + INSERT_PAYMENT_RESPONSE, + INSERT_NEW_PAYMENT +} = require("../../graphql-client/queries"); +const getPaymentType = require("./getPaymentType"); +const moment = require("moment"); + +const gqlClient = require("../../graphql-client/graphql-client").client; + +/** + * @description Handle invoice-based payment processing + * @param values + * @param logger + * @param logMeta + * @param res + * @returns {Promise<*>} + */ +const handleInvoiceBasedPayment = async (values, logger, logMeta, res) => { + // Validate required fields + if (!values.merchantid) { + return handlePaymentValidationError( + res, + logger, + "intellipay-postback-no-merchantid", + "Merchant ID is missing", + logMeta + ); + } + + // Fetch job data + const result = await gqlClient.request(GET_JOBID_BY_MERCHANTID_RONUMBER, { + merchantID: values.merchantid, + roNumber: values.invoice + }); + + if (!result?.jobs?.length) { + return handlePaymentValidationError(res, logger, "intellipay-postback-job-not-found", "Job not found", logMeta); + } + + const job = result.jobs[0]; + const bodyshop = job?.bodyshop; + + if (!bodyshop) { + return handlePaymentValidationError( + res, + logger, + "intellipay-postback-bodyshop-not-found", + "Bodyshop not found", + logMeta + ); + } + + const ipMapping = bodyshop.intellipay_config?.payment_map; + + logger.log("intellipay-postback-invoice-job-fetched", "DEBUG", "api", null, { + job, + ...logMeta + }); + + // Create payment record + const paymentResult = await gqlClient.request(INSERT_NEW_PAYMENT, { + paymentInput: { + amount: values.total, + transactionid: values.authcode, + payer: "Customer", + type: getPaymentType(ipMapping, values.cardtype), + jobid: job.id, + date: moment(Date.now()) + } + }); + + logger.log("intellipay-postback-invoice-payment-success", "DEBUG", "api", null, { + paymentResult, + ...logMeta + }); + + // Create payment response record + const responseResults = await gqlClient.request(INSERT_PAYMENT_RESPONSE, { + paymentResponse: { + amount: values.total, + bodyshopid: bodyshop.id, + paymentid: paymentResult.id, + jobid: job.id, + declinereason: "Approved", + ext_paymentid: values.paymentid, + successful: true, + response: values + } + }); + + logger.log("intellipay-postback-invoice-response-success", "DEBUG", "api", null, { + responseResults, + ...logMeta + }); + + return res.sendStatus(200); +}; + +module.exports = handleInvoiceBasedPayment; diff --git a/server/intellipay/lib/handlePaymentValidationError.js b/server/intellipay/lib/handlePaymentValidationError.js new file mode 100644 index 000000000..fccf7a75f --- /dev/null +++ b/server/intellipay/lib/handlePaymentValidationError.js @@ -0,0 +1,18 @@ +/** + * @description Log validation error and send response + * @param res + * @param logger + * @param logCode + * @param message + * @param logMeta + * @returns {*} + */ +const handlePaymentValidationError = (res, logger, logCode, message, logMeta) => { + logger.log(logCode, "ERROR", "api", null, { + message, + ...logMeta + }); + return res.status(400).send(`Bad Request: ${message}`); +}; + +module.exports = handlePaymentValidationError; diff --git a/server/intellipay/lib/sendPaymentNotificationEmail.js b/server/intellipay/lib/sendPaymentNotificationEmail.js new file mode 100644 index 000000000..2f83d3a3b --- /dev/null +++ b/server/intellipay/lib/sendPaymentNotificationEmail.js @@ -0,0 +1,41 @@ +const { sendTaskEmail } = require("../../email/sendemail"); +const generateEmailTemplate = require("../../email/generateTemplate"); + +/** + * @description Send notification email to the user + * @param userEmail + * @param jobs + * @param partialPayments + * @param logger + * @param logMeta + * @returns {Promise} + */ +const sendPaymentNotificationEmail = async (userEmail, jobs, partialPayments, logger, logMeta) => { + try { + await sendTaskEmail({ + to: userEmail, + subject: `New Payment(s) Received - RO ${jobs.jobs.map((j) => j.ro_number).join(", ")}`, + type: "html", + html: generateEmailTemplate({ + header: "New Payment(s) Received", + subHeader: "", + body: jobs.jobs + .map( + (job) => + `Reference: ${job.ro_number || "N/A"} | ${ + job.ownr_co_nm ? job.ownr_co_nm : `${job.ownr_fn || ""} ${job.ownr_ln || ""}`.trim() + } | ${`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${job.v_model_desc || ""}`.trim()} | $${partialPayments.find((p) => p.jobid === job.id).amount}` + ) + .join("
") + }) + }); + } catch (error) { + logger.log("intellipay-postback-email-error", "ERROR", "api", null, { + message: error.message, + jobs, + ...logMeta + }); + } +}; + +module.exports = sendPaymentNotificationEmail; diff --git a/vitest.config.js b/vitest.config.js index 7757f9a7e..c4b856ce5 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -1,10 +1,13 @@ -import { defineConfig } from "vitest/config"; +const { defineConfig } = require("vitest/config"); -export default defineConfig({ +module.exports = defineConfig({ test: { environment: "node", globals: true, - include: ["./server/tests/**/*.{test,spec}.[jt]s"], // Only search /tests in root + include: [ + "./server/tests/**/*.{test,spec}.[jt]s", // Existing pattern for /server/tests + "./server/**/*.test.js" // New pattern for test.js in server and subfolders + ], exclude: ["**/client/**", "**/node_modules/**", "**/dist/**"] // Explicitly exclude /client } }); From 09c4662436ab77b6461ae3598e8a45be7effa054 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 2 Apr 2025 11:34:48 -0400 Subject: [PATCH 07/34] feature/IO-2885-IntelliPay-App-Postback - Add Tests --- package-lock.json | 48 +++++- package.json | 1 + .../tests/handleCommentBasedPayment.test.js | 152 ++++++++++++++++++ .../tests/handleInvoiceBasedPayment.test.js | 129 +++++++++++++++ .../intellipay/{ => tests}/intellipay.test.js | 10 +- 5 files changed, 332 insertions(+), 8 deletions(-) create mode 100644 server/intellipay/lib/tests/handleCommentBasedPayment.test.js create mode 100644 server/intellipay/lib/tests/handleInvoiceBasedPayment.test.js rename server/intellipay/{ => tests}/intellipay.test.js (96%) diff --git a/package-lock.json b/package-lock.json index ffe02c7ec..09da429eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -75,6 +75,7 @@ "eslint": "^9.23.0", "eslint-plugin-react": "^7.37.4", "globals": "^15.15.0", + "mock-require": "^3.0.3", "p-limit": "^3.1.0", "prettier": "^3.5.3", "source-map-explorer": "^2.5.2", @@ -8402,9 +8403,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "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": { @@ -9535,6 +9536,40 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/mock-require": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/mock-require/-/mock-require-3.0.3.tgz", + "integrity": "sha512-lLzfLHcyc10MKQnNUCv7dMcoY/2Qxd6wJfbqCcVk3LDb8An4hF6ohk5AztrvgKhJCqj36uyzi/p5se+tvyD+Wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-caller-file": "^1.0.2", + "normalize-path": "^2.1.1" + }, + "engines": { + "node": ">=4.3.0" + } + }, + "node_modules/mock-require/node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true, + "license": "ISC" + }, + "node_modules/mock-require/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/module-details-from-path": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", @@ -10709,6 +10744,13 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true, + "license": "ISC" + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", diff --git a/package.json b/package.json index aa3c57951..0a95a146e 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "eslint": "^9.23.0", "eslint-plugin-react": "^7.37.4", "globals": "^15.15.0", + "mock-require": "^3.0.3", "p-limit": "^3.1.0", "prettier": "^3.5.3", "source-map-explorer": "^2.5.2", diff --git a/server/intellipay/lib/tests/handleCommentBasedPayment.test.js b/server/intellipay/lib/tests/handleCommentBasedPayment.test.js new file mode 100644 index 000000000..9fd7f4ffc --- /dev/null +++ b/server/intellipay/lib/tests/handleCommentBasedPayment.test.js @@ -0,0 +1,152 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; +import mockRequire from "mock-require"; + +const gqlRequestMock = { request: vi.fn() }; +const getPaymentTypeMock = vi.fn(() => "American Express"); +const sendPaymentNotificationEmailMock = vi.fn(); + +let handleCommentBasedPayment; + +beforeEach(() => { + vi.resetModules(); + vi.clearAllMocks(); + + // Mock dependencies using mock-require BEFORE requiring the target module + mockRequire("../../../graphql-client/graphql-client", { + client: gqlRequestMock + }); + + mockRequire("../getPaymentType", getPaymentTypeMock); + mockRequire("../sendPaymentNotificationEmail", sendPaymentNotificationEmailMock); + + // Now require the module under test + handleCommentBasedPayment = require("../handleCommentBasedPayment"); + + // Chain your GraphQL mocks + gqlRequestMock.request + .mockResolvedValueOnce({ + jobs: [ + { + id: "c1ffe09c-e7d4-46b3-aac5-f23e39563181", + shopid: "bfec8c8c-b7f1-49e0-be4c-524455f4e582" + } + ] + }) + .mockResolvedValueOnce({ + bodyshops_by_pk: { + id: "bfec8c8c-b7f1-49e0-be4c-524455f4e582", + intellipay_config: { + payment_map: { + amex: "American Express" + } + } + } + }) + .mockResolvedValueOnce({ + insert_payments: { + returning: [{ id: "5dfda3c4-c0a6-4b09-a73d-176ed0ac6499" }] + } + }); +}); + +describe("handleCommentBasedPayment", () => { + const mockLogger = { log: vi.fn() }; + const mockRes = { sendStatus: vi.fn() }; + + const values = { + authcode: "5557301", + total: "0.01", + origin: "Dejavoo", + paymentid: "24294378", + cardtype: "Amex" + }; + + const decodedComment = { + payments: [{ jobid: "c1ffe09c-e7d4-46b3-aac5-f23e39563181", amount: 0.01 }], + userEmail: "test@example.com" + }; + + const logMeta = { op: "xyz123" }; + + it("processes comment-based payment and returns 200", async () => { + await handleCommentBasedPayment(values, decodedComment, mockLogger, logMeta, mockRes); + + expect(gqlRequestMock.request).toHaveBeenCalledTimes(3); + expect(getPaymentTypeMock).toHaveBeenCalledWith({ amex: "American Express" }, "Amex"); + expect(sendPaymentNotificationEmailMock).not.toHaveBeenCalled(); + expect(mockRes.sendStatus).toHaveBeenCalledWith(200); + }); + + it("sends notification if origin is OneLink and userEmail exists", async () => { + const oneLinkValues = { ...values, origin: "OneLink" }; + + await handleCommentBasedPayment(oneLinkValues, decodedComment, mockLogger, logMeta, mockRes); + + expect(sendPaymentNotificationEmailMock).toHaveBeenCalledWith( + "test@example.com", + expect.anything(), + expect.anything(), + mockLogger, + logMeta + ); + + expect(mockRes.sendStatus).toHaveBeenCalledWith(200); + }); + + it("handles decodedComment as a direct array", async () => { + const arrayComment = [{ jobid: "c1ffe09c-e7d4-46b3-aac5-f23e39563181", amount: 0.01 }]; + + await handleCommentBasedPayment(values, arrayComment, mockLogger, logMeta, mockRes); + + expect(gqlRequestMock.request).toHaveBeenCalledTimes(3); + expect(mockRes.sendStatus).toHaveBeenCalledWith(200); + }); + + it("does not send email if origin is OneLink but userEmail is missing", async () => { + const commentWithoutEmail = { + payments: decodedComment.payments + // no userEmail + }; + + const oneLinkValues = { ...values, origin: "OneLink" }; + + await handleCommentBasedPayment(oneLinkValues, commentWithoutEmail, mockLogger, logMeta, mockRes); + + expect(sendPaymentNotificationEmailMock).not.toHaveBeenCalled(); + expect(mockRes.sendStatus).toHaveBeenCalledWith(200); + }); + + it("logs important stages of the process", async () => { + await handleCommentBasedPayment(values, decodedComment, mockLogger, logMeta, mockRes); + + const logCalls = mockLogger.log.mock.calls.map(([tag]) => tag); + + expect(logCalls).toContain("intellipay-postback-parsed-comment"); + expect(logCalls).toContain("intellipay-postback-payment-success"); + }); + + it("handles missing payment_map safely", async () => { + gqlRequestMock.request.mockReset(); // 🧹 Clear previous .mockResolvedValueOnce calls + + gqlRequestMock.request + .mockResolvedValueOnce({ + jobs: [{ id: "job1", shopid: "shop1" }] + }) + .mockResolvedValueOnce({ + bodyshops_by_pk: { + id: "shop1", + intellipay_config: null + } + }) + .mockResolvedValueOnce({ + insert_payments: { + returning: [{ id: "payment1" }] + } + }); + + await handleCommentBasedPayment(values, decodedComment, mockLogger, logMeta, mockRes); + + expect(getPaymentTypeMock).toHaveBeenCalledWith(undefined, "Amex"); + expect(mockRes.sendStatus).toHaveBeenCalledWith(200); + }); +}); diff --git a/server/intellipay/lib/tests/handleInvoiceBasedPayment.test.js b/server/intellipay/lib/tests/handleInvoiceBasedPayment.test.js new file mode 100644 index 000000000..b2a886e2f --- /dev/null +++ b/server/intellipay/lib/tests/handleInvoiceBasedPayment.test.js @@ -0,0 +1,129 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; +import mockRequire from "mock-require"; + +const gqlRequestMock = { request: vi.fn() }; +const getPaymentTypeMock = vi.fn(() => "Visa"); +const handlePaymentValidationErrorMock = vi.fn(); + +let handleInvoiceBasedPayment; + +beforeEach(() => { + vi.resetModules(); + vi.clearAllMocks(); + + mockRequire("../../../graphql-client/graphql-client", { + client: gqlRequestMock + }); + + mockRequire("../getPaymentType", getPaymentTypeMock); + mockRequire("../handlePaymentValidationError", handlePaymentValidationErrorMock); + + handleInvoiceBasedPayment = require("../handleInvoiceBasedPayment"); + + gqlRequestMock.request + .mockResolvedValueOnce({ + jobs: [ + { + id: "job123", + bodyshop: { + id: "shop123", + intellipay_config: { + payment_map: { + visa: "Visa" + } + } + } + } + ] + }) + .mockResolvedValueOnce({ + id: "payment123" + }) + .mockResolvedValueOnce({ + insert_payment_response: { + returning: [{ id: "response123" }] + } + }); +}); + +describe("handleInvoiceBasedPayment", () => { + const mockLogger = { log: vi.fn() }; + const mockRes = { sendStatus: vi.fn() }; + + const values = { + merchantid: "m123", + invoice: "INV-001", + total: 100.0, + authcode: "AUTH123", + cardtype: "visa", + paymentid: "P789" + }; + + const logMeta = { op: "abc123" }; + + it("processes a valid invoice-based payment", async () => { + await handleInvoiceBasedPayment(values, mockLogger, logMeta, mockRes); + + expect(gqlRequestMock.request).toHaveBeenCalledTimes(3); + expect(getPaymentTypeMock).toHaveBeenCalledWith({ visa: "Visa" }, "visa"); + expect(mockRes.sendStatus).toHaveBeenCalledWith(200); + expect(handlePaymentValidationErrorMock).not.toHaveBeenCalled(); + }); + + it("handles missing merchantid with validation error", async () => { + const invalidValues = { ...values, merchantid: undefined }; + + await handleInvoiceBasedPayment(invalidValues, mockLogger, logMeta, mockRes); + + expect(handlePaymentValidationErrorMock).toHaveBeenCalledWith( + mockRes, + mockLogger, + "intellipay-postback-no-merchantid", + "Merchant ID is missing", + logMeta + ); + expect(gqlRequestMock.request).not.toHaveBeenCalled(); + }); + + it("handles job not found with validation error", async () => { + gqlRequestMock.request.mockReset(); + gqlRequestMock.request.mockResolvedValueOnce({ jobs: [] }); + + await handleInvoiceBasedPayment(values, mockLogger, logMeta, mockRes); + + expect(handlePaymentValidationErrorMock).toHaveBeenCalledWith( + mockRes, + mockLogger, + "intellipay-postback-job-not-found", + "Job not found", + logMeta + ); + }); + + it("handles missing bodyshop with validation error", async () => { + gqlRequestMock.request.mockReset(); + gqlRequestMock.request.mockResolvedValueOnce({ + jobs: [{ id: "job123", bodyshop: null }] + }); + + await handleInvoiceBasedPayment(values, mockLogger, logMeta, mockRes); + + expect(handlePaymentValidationErrorMock).toHaveBeenCalledWith( + mockRes, + mockLogger, + "intellipay-postback-bodyshop-not-found", + "Bodyshop not found", + logMeta + ); + }); + + it("logs all expected stages of the process", async () => { + await handleInvoiceBasedPayment(values, mockLogger, logMeta, mockRes); + + const logTags = mockLogger.log.mock.calls.map(([tag]) => tag); + + expect(logTags).toContain("intellipay-postback-invoice-job-fetched"); + expect(logTags).toContain("intellipay-postback-invoice-payment-success"); + expect(logTags).toContain("intellipay-postback-invoice-response-success"); + }); +}); diff --git a/server/intellipay/intellipay.test.js b/server/intellipay/tests/intellipay.test.js similarity index 96% rename from server/intellipay/intellipay.test.js rename to server/intellipay/tests/intellipay.test.js index 472e2ea0f..689bfa517 100644 --- a/server/intellipay/intellipay.test.js +++ b/server/intellipay/tests/intellipay.test.js @@ -1,10 +1,10 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; -const getPaymentType = require("./lib/getPaymentType"); -const decodeComment = require("./lib/decodeComment"); -const getCptellerUrl = require("./lib/getCptellerUrl"); -const handlePaymentValidationError = require("./lib/handlePaymentValidationError"); -const getShopCredentials = require("./lib/getShopCredentials"); +const getPaymentType = require("../lib/getPaymentType"); +const decodeComment = require("../lib/decodeComment"); +const getCptellerUrl = require("../lib/getCptellerUrl"); +const handlePaymentValidationError = require("../lib/handlePaymentValidationError"); +const getShopCredentials = require("../lib/getShopCredentials"); /** * @description Decode a base64-encoded JSON comment From 41e43dda963b1fe7fb15b450eca284748d32325a Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 2 Apr 2025 11:59:54 -0400 Subject: [PATCH 08/34] feature/IO-2885-IntelliPay-App-Postback-Support - Cleanup --- .../lib/tests/intelliPayGeneralLibs.test.js | 277 +++++++++++++++ server/intellipay/tests/intellipay.test.js | 316 ------------------ 2 files changed, 277 insertions(+), 316 deletions(-) create mode 100644 server/intellipay/lib/tests/intelliPayGeneralLibs.test.js delete mode 100644 server/intellipay/tests/intellipay.test.js diff --git a/server/intellipay/lib/tests/intelliPayGeneralLibs.test.js b/server/intellipay/lib/tests/intelliPayGeneralLibs.test.js new file mode 100644 index 000000000..9c9bec789 --- /dev/null +++ b/server/intellipay/lib/tests/intelliPayGeneralLibs.test.js @@ -0,0 +1,277 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; + +const getPaymentType = require("../getPaymentType"); +const decodeComment = require("../decodeComment"); +const getCptellerUrl = require("../getCptellerUrl"); +const handlePaymentValidationError = require("../handlePaymentValidationError"); +const getShopCredentials = require("../getShopCredentials"); + +describe("Payment Processing Functions", () => { + // DecodeComment Tests + describe("decodeComment", () => { + it("decodes a valid base64-encoded JSON comment", () => { + const encoded = "eyJ0ZXN0IjoiZGF0YSJ9"; + const expected = { test: "data" }; + expect(decodeComment(encoded)).toEqual(expected); + }); + + it("decodes a complex base64-encoded JSON with payments", () => { + const encoded = "eyJwYXltZW50cyI6W3siam9iaWQiOiIxMjMifV19"; + const expected = { payments: [{ jobid: "123" }] }; + expect(decodeComment(encoded)).toEqual(expected); + }); + + it("returns null when comment is null", () => { + expect(decodeComment(null)).toBeNull(); + }); + + it("returns null when comment is undefined", () => { + expect(decodeComment(undefined)).toBeNull(); + }); + + it("returns null when comment is an empty string", () => { + expect(decodeComment("")).toBeNull(); + }); + + it("returns null when comment is malformed base64", () => { + expect(decodeComment("!@#$%")).toBeNull(); + }); + + it("returns null when comment is valid base64 but not valid JSON", () => { + expect(decodeComment("aW52YWxpZA==")).toBeNull(); + }); + }); + + // GetPaymentType Tests + describe("getPaymentType", () => { + it("returns mapped value when card type exists in mapping", () => { + const ipMapping = { visa: "Visa Card", amex: "American Express" }; + expect(getPaymentType(ipMapping, "visa")).toBe("Visa Card"); + }); + + it("returns original value when card type not in mapping", () => { + const ipMapping = { visa: "Visa Card" }; + expect(getPaymentType(ipMapping, "mastercard")).toBe("mastercard"); + }); + + it("handles lowercase conversion", () => { + const ipMapping = { visa: "Visa Card" }; + expect(getPaymentType(ipMapping, "VISA")).toBe("Visa Card"); + }); + + it("handles null mapping", () => { + expect(getPaymentType(null, "visa")).toBe("visa"); + }); + + it("handles undefined mapping", () => { + expect(getPaymentType(undefined, "visa")).toBe("visa"); + }); + + it("handles empty string card type", () => { + const ipMapping = { visa: "Visa Card" }; + expect(getPaymentType(ipMapping, "")).toBe(""); + }); + + it("handles undefined card type", () => { + const ipMapping = { visa: "Visa Card" }; + expect(getPaymentType(ipMapping, undefined)).toBe(undefined); + }); + }); + + // GetCptellerUrl Tests + describe("getCptellerUrl", () => { + const originalEnv = process.env.NODE_ENV; + + afterEach(() => { + process.env.NODE_ENV = originalEnv; + }); + + it("uses test domain in non-production environment", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({ apiType: "webapi" }); + expect(url).toEqual("https://test.cpteller.com/api/webapi.cfc"); + }); + + it("uses secure domain in production environment", () => { + process.env.NODE_ENV = "production"; + const url = getCptellerUrl({ apiType: "webapi" }); + expect(url).toEqual("https://secure.cpteller.com/api/webapi.cfc"); + }); + + it("adds version number for webapi type", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({ apiType: "webapi", version: "26" }); + expect(url).toEqual("https://test.cpteller.com/api/26/webapi.cfc"); + }); + + it("constructs custapi URL without version number", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({ apiType: "custapi", version: "26" }); + expect(url).toEqual("https://test.cpteller.com/api/custapi.cfc"); + }); + + it("adds query parameters to the URL", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({ + apiType: "webapi", + params: { method: "payment_refund", test: "value" } + }); + expect(url).toEqual("https://test.cpteller.com/api/webapi.cfc?method=payment_refund&test=value"); + }); + + it("handles empty params object", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({ apiType: "webapi", params: {} }); + expect(url).toEqual("https://test.cpteller.com/api/webapi.cfc"); + }); + + it("defaults to webapi when no apiType is provided", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({}); + expect(url).toEqual("https://test.cpteller.com/api/webapi.cfc"); + }); + + it("combines version and query parameters correctly", () => { + process.env.NODE_ENV = ""; + const url = getCptellerUrl({ + apiType: "webapi", + version: "26", + params: { method: "fee" } + }); + expect(url).toEqual("https://test.cpteller.com/api/26/webapi.cfc?method=fee"); + }); + }); + + // GetShopCredentials Tests + describe("getShopCredentials", () => { + const originalEnv = { ...process.env }; + let mockSend; + + beforeEach(() => { + mockSend = vi.fn(); + vi.mock("@aws-sdk/client-secrets-manager", () => { + return { + SecretsManagerClient: vi.fn(() => ({ + send: mockSend + })), + GetSecretValueCommand: vi.fn((input) => input) + }; + }); + + process.env.INTELLIPAY_MERCHANTKEY = "test-merchant-key"; + process.env.INTELLIPAY_APIKEY = "test-api-key"; + vi.resetModules(); + }); + + afterEach(() => { + process.env = { ...originalEnv }; + vi.restoreAllMocks(); + vi.unmock("@aws-sdk/client-secrets-manager"); + }); + + it("returns environment variables in non-production environment", async () => { + process.env.NODE_ENV = "development"; + const result = await getShopCredentials({ imexshopid: "12345" }); + expect(result).toEqual({ + merchantkey: "test-merchant-key", + apikey: "test-api-key" + }); + expect(mockSend).not.toHaveBeenCalled(); + }); + + it("returns undefined when imexshopid is missing in production", async () => { + process.env.NODE_ENV = "production"; + const result = await getShopCredentials({ name: "Test Shop" }); + expect(result).toBeUndefined(); + expect(mockSend).not.toHaveBeenCalled(); + }); + + it("returns undefined for null bodyshop in production", async () => { + process.env.NODE_ENV = "production"; + const result = await getShopCredentials(null); + expect(result).toBeUndefined(); + expect(mockSend).not.toHaveBeenCalled(); + }); + + it("returns undefined for undefined bodyshop in production", async () => { + process.env.NODE_ENV = "production"; + const result = await getShopCredentials(undefined); + expect(result).toBeUndefined(); + expect(mockSend).not.toHaveBeenCalled(); + }); + }); + + // HandlePaymentValidationError Tests + describe("handlePaymentValidationError", () => { + it("logs error and sends 400 response", () => { + const mockLog = vi.fn(); + const mockLogger = { log: mockLog }; + const mockRes = { + status: vi.fn().mockReturnThis(), + send: vi.fn().mockReturnThis() + }; + + const logCode = "test-validation-error"; + const message = "Invalid data"; + const logMeta = { field: "test", value: 123 }; + + const result = handlePaymentValidationError(mockRes, mockLogger, logCode, message, logMeta); + + expect(mockLog).toHaveBeenCalledWith(logCode, "ERROR", "api", null, { + message, + ...logMeta + }); + expect(mockRes.status).toHaveBeenCalledWith(400); + expect(mockRes.send).toHaveBeenCalledWith(`Bad Request: ${message}`); + expect(result).toBe(mockRes); + }); + + it("formats different error messages correctly", () => { + const mockLog = vi.fn(); + const mockLogger = { log: mockLog }; + const mockRes = { + status: vi.fn().mockReturnThis(), + send: vi.fn().mockReturnThis() + }; + + handlePaymentValidationError(mockRes, mockLogger, "error-code", "Custom error"); + expect(mockRes.send).toHaveBeenCalledWith("Bad Request: Custom error"); + }); + + it("passes different logCodes to logger", () => { + const mockLog = vi.fn(); + const mockLogger = { log: mockLog }; + const mockRes = { + status: vi.fn().mockReturnThis(), + send: vi.fn().mockReturnThis() + }; + + handlePaymentValidationError(mockRes, mockLogger, "custom-log-code", "Error message"); + expect(mockLog).toHaveBeenCalledWith("custom-log-code", "ERROR", "api", null, { message: "Error message" }); + }); + + it("works with minimal logMeta", () => { + const mockLog = vi.fn(); + const mockLogger = { log: mockLog }; + const mockRes = { + status: vi.fn().mockReturnThis(), + send: vi.fn().mockReturnThis() + }; + + handlePaymentValidationError(mockRes, mockLogger, "error-code", "Error message", {}); + expect(mockLog).toHaveBeenCalledWith("error-code", "ERROR", "api", null, { message: "Error message" }); + }); + + it("works with undefined logMeta", () => { + const mockLog = vi.fn(); + const mockLogger = { log: mockLog }; + const mockRes = { + status: vi.fn().mockReturnThis(), + send: vi.fn().mockReturnThis() + }; + + handlePaymentValidationError(mockRes, mockLogger, "error-code", "Error message"); + expect(mockLog).toHaveBeenCalledWith("error-code", "ERROR", "api", null, { message: "Error message" }); + }); + }); +}); diff --git a/server/intellipay/tests/intellipay.test.js b/server/intellipay/tests/intellipay.test.js deleted file mode 100644 index 689bfa517..000000000 --- a/server/intellipay/tests/intellipay.test.js +++ /dev/null @@ -1,316 +0,0 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; - -const getPaymentType = require("../lib/getPaymentType"); -const decodeComment = require("../lib/decodeComment"); -const getCptellerUrl = require("../lib/getCptellerUrl"); -const handlePaymentValidationError = require("../lib/handlePaymentValidationError"); -const getShopCredentials = require("../lib/getShopCredentials"); - -/** - * @description Decode a base64-encoded JSON comment - */ -describe("decodeComment", () => { - it("decodes a valid base64-encoded JSON comment", () => { - // {"test":"data"} encoded in base64 - const encoded = "eyJ0ZXN0IjoiZGF0YSJ9"; - const expected = { test: "data" }; - expect(decodeComment(encoded)).toEqual(expected); - }); - - it("decodes a complex base64-encoded JSON with payments", () => { - // {"payments":[{"jobid":"123"}]} encoded in base64 - const encoded = "eyJwYXltZW50cyI6W3siam9iaWQiOiIxMjMifV19"; - const expected = { payments: [{ jobid: "123" }] }; - expect(decodeComment(encoded)).toEqual(expected); - }); - - it("returns null when comment is null", () => { - expect(decodeComment(null)).toBeNull(); - }); - - it("returns null when comment is undefined", () => { - expect(decodeComment(undefined)).toBeNull(); - }); - - it("returns null when comment is an empty string", () => { - expect(decodeComment("")).toBeNull(); - }); - - it("returns null when comment is malformed base64", () => { - expect(decodeComment("!@#$%")).toBeNull(); - }); - - it("returns null when comment is valid base64 but not valid JSON", () => { - // "invalid" in base64 is "aW52YWxpZA==" - expect(decodeComment("aW52YWxpZA==")).toBeNull(); - }); -}); - -/** - * @description Get the payment type based on the card type - */ -describe("getPaymentType", () => { - it("returns mapped value when card type exists in mapping", () => { - const ipMapping = { visa: "Visa Card", amex: "American Express" }; - expect(getPaymentType(ipMapping, "visa")).toBe("Visa Card"); - }); - - it("returns original value when card type not in mapping", () => { - const ipMapping = { visa: "Visa Card" }; - expect(getPaymentType(ipMapping, "mastercard")).toBe("mastercard"); - }); - - it("handles lowercase conversion", () => { - const ipMapping = { visa: "Visa Card" }; - expect(getPaymentType(ipMapping, "VISA")).toBe("Visa Card"); - }); - - it("handles null mapping", () => { - expect(getPaymentType(null, "visa")).toBe("visa"); - }); - - it("handles undefined mapping", () => { - expect(getPaymentType(undefined, "visa")).toBe("visa"); - }); - - it("handles empty string card type", () => { - const ipMapping = { visa: "Visa Card" }; - expect(getPaymentType(ipMapping, "")).toBe(""); - }); - - it("handles undefined card type", () => { - const ipMapping = { visa: "Visa Card" }; - expect(getPaymentType(ipMapping, undefined)).toBe(undefined); - }); -}); - -/** - * @description Get the CPTeller URL based on environment and parameters - */ -describe("getCptellerUrl", () => { - const originalEnv = process.env.NODE_ENV; - - afterEach(() => { - // Restore the original NODE_ENV after each test - process.env.NODE_ENV = originalEnv; - }); - - it("uses test domain in non-production environment", () => { - process.env.NODE_ENV = ""; - const url = getCptellerUrl({ apiType: "webapi" }); - expect(url).toEqual("https://test.cpteller.com/api/webapi.cfc"); - }); - - it("uses secure domain in production environment", () => { - process.env.NODE_ENV = "production"; - const url = getCptellerUrl({ apiType: "webapi" }); - expect(url).toEqual("https://secure.cpteller.com/api/webapi.cfc"); - }); - - it("adds version number for webapi type", () => { - process.env.NODE_ENV = ""; - const url = getCptellerUrl({ apiType: "webapi", version: "26" }); - expect(url).toEqual("https://test.cpteller.com/api/26/webapi.cfc"); - }); - - it("constructs custapi URL without version number", () => { - process.env.NODE_ENV = ""; - const url = getCptellerUrl({ apiType: "custapi", version: "26" }); - expect(url).toEqual("https://test.cpteller.com/api/custapi.cfc"); - }); - - it("adds query parameters to the URL", () => { - process.env.NODE_ENV = ""; - const url = getCptellerUrl({ - apiType: "webapi", - params: { method: "payment_refund", test: "value" } - }); - expect(url).toEqual("https://test.cpteller.com/api/webapi.cfc?method=payment_refund&test=value"); - }); - - it("handles empty params object", () => { - process.env.NODE_ENV = ""; - const url = getCptellerUrl({ apiType: "webapi", params: {} }); - expect(url).toEqual("https://test.cpteller.com/api/webapi.cfc"); - }); - - it("defaults to webapi when no apiType is provided", () => { - process.env.NODE_ENV = ""; - const url = getCptellerUrl({}); - expect(url).toEqual("https://test.cpteller.com/api/webapi.cfc"); - }); - - it("combines version and query parameters correctly", () => { - process.env.NODE_ENV = ""; - const url = getCptellerUrl({ - apiType: "webapi", - version: "26", - params: { method: "fee" } - }); - expect(url).toEqual("https://test.cpteller.com/api/26/webapi.cfc?method=fee"); - }); -}); - -/** - * @description Get shop credentials from AWS Secrets Manager or environment variables - */ - -describe("getShopCredentials", () => { - const originalEnv = { ...process.env }; - let mockSend; - - beforeEach(() => { - // Create a mock function for send - mockSend = vi.fn(); - - // Mock the entire AWS SDK module - vi.mock("@aws-sdk/client-secrets-manager", () => { - return { - SecretsManagerClient: vi.fn(() => ({ - send: mockSend - })), - GetSecretValueCommand: vi.fn((input) => input) - }; - }); - - // Setup test environment variables - process.env.INTELLIPAY_MERCHANTKEY = "test-merchant-key"; - process.env.INTELLIPAY_APIKEY = "test-api-key"; - - // Clear module cache to ensure fresh mock is used - vi.resetModules(); - }); - - afterEach(() => { - // Restore environment and clear mocks - process.env = { ...originalEnv }; - vi.restoreAllMocks(); - vi.unmock("@aws-sdk/client-secrets-manager"); - }); - - it("returns environment variables in non-production environment", async () => { - process.env.NODE_ENV = "development"; - - const result = await getShopCredentials({ imexshopid: "12345" }); - - expect(result).toEqual({ - merchantkey: "test-merchant-key", - apikey: "test-api-key" - }); - expect(mockSend).not.toHaveBeenCalled(); - }); - - it("returns undefined when imexshopid is missing in production", async () => { - process.env.NODE_ENV = "production"; - - const result = await getShopCredentials({ name: "Test Shop" }); - - expect(result).toBeUndefined(); - expect(mockSend).not.toHaveBeenCalled(); - }); - - it("returns undefined for null bodyshop in production", async () => { - process.env.NODE_ENV = "production"; - - const result = await getShopCredentials(null); - - expect(result).toBeUndefined(); - expect(mockSend).not.toHaveBeenCalled(); - }); - - it("returns undefined for undefined bodyshop in production", async () => { - process.env.NODE_ENV = "production"; - - const result = await getShopCredentials(undefined); - - expect(result).toBeUndefined(); - expect(mockSend).not.toHaveBeenCalled(); - }); -}); - -/** - * @description Handle payment validation errors - */ -describe("handlePaymentValidationError", () => { - it("logs error and sends 400 response", () => { - // Create mock objects - const mockLog = vi.fn(); - const mockLogger = { log: mockLog }; - const mockRes = { - status: vi.fn().mockReturnThis(), - send: vi.fn().mockReturnThis() - }; - - // Test data - const logCode = "test-validation-error"; - const message = "Invalid data"; - const logMeta = { field: "test", value: 123 }; - - // Call the function - const result = handlePaymentValidationError(mockRes, mockLogger, logCode, message, logMeta); - - // Verify logger.log was called correctly - expect(mockLog).toHaveBeenCalledWith(logCode, "ERROR", "api", null, { message, ...logMeta }); - - // Verify res.status was called with 400 - expect(mockRes.status).toHaveBeenCalledWith(400); - - // Verify res.send was called with correct message - expect(mockRes.send).toHaveBeenCalledWith(`Bad Request: ${message}`); - - // Verify the function returns the response - expect(result).toBe(mockRes); - }); - - it("formats different error messages correctly", () => { - const mockLog = vi.fn(); - const mockLogger = { log: mockLog }; - const mockRes = { - status: vi.fn().mockReturnThis(), - send: vi.fn().mockReturnThis() - }; - - handlePaymentValidationError(mockRes, mockLogger, "error-code", "Custom error"); - - expect(mockRes.send).toHaveBeenCalledWith("Bad Request: Custom error"); - }); - - it("passes different logCodes to logger", () => { - const mockLog = vi.fn(); - const mockLogger = { log: mockLog }; - const mockRes = { - status: vi.fn().mockReturnThis(), - send: vi.fn().mockReturnThis() - }; - - handlePaymentValidationError(mockRes, mockLogger, "custom-log-code", "Error message"); - - expect(mockLog).toHaveBeenCalledWith("custom-log-code", "ERROR", "api", null, { message: "Error message" }); - }); - - it("works with minimal logMeta", () => { - const mockLog = vi.fn(); - const mockLogger = { log: mockLog }; - const mockRes = { - status: vi.fn().mockReturnThis(), - send: vi.fn().mockReturnThis() - }; - - handlePaymentValidationError(mockRes, mockLogger, "error-code", "Error message", {}); - - expect(mockLog).toHaveBeenCalledWith("error-code", "ERROR", "api", null, { message: "Error message" }); - }); - - it("works with undefined logMeta", () => { - const mockLog = vi.fn(); - const mockLogger = { log: mockLog }; - const mockRes = { - status: vi.fn().mockReturnThis(), - send: vi.fn().mockReturnThis() - }; - - handlePaymentValidationError(mockRes, mockLogger, "error-code", "Error message"); - - expect(mockLog).toHaveBeenCalledWith("error-code", "ERROR", "api", null, { message: "Error message" }); - }); -}); From 3e9e6baf32396c0d92b7b275ede39f42d6ab0211 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Wed, 2 Apr 2025 13:56:02 -0700 Subject: [PATCH 09/34] IO-3193 Reconciliation Zero Part Price or Qty Signed-off-by: Allan Carr --- .../job-reconciliation-modal.component.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/components/job-reconciliation-modal/job-reconciliation-modal.component.jsx b/client/src/components/job-reconciliation-modal/job-reconciliation-modal.component.jsx index 730614fc0..6a2ca8bec 100644 --- a/client/src/components/job-reconciliation-modal/job-reconciliation-modal.component.jsx +++ b/client/src/components/job-reconciliation-modal/job-reconciliation-modal.component.jsx @@ -1,9 +1,9 @@ import { Col, Row } from "antd"; -import React, { useState } from "react"; +import { useState } from "react"; +import InstanceRenderManager from "../../utils/instanceRenderMgr"; import JobReconciliationBillsTable from "../job-reconciliation-bills-table/job-reconciliation-bills-table.component"; import JobReconciliationPartsTable from "../job-reconciliation-parts-table/job-reconciliation-parts-table.component"; import JobReconciliationTotals from "../job-reconciliation-totals/job-reconciliation-totals.component"; -import InstanceRenderManager from "../../utils/instanceRenderMgr"; export default function JobReconciliationModalComponent({ job, bills }) { const jobLineState = useState([]); @@ -20,7 +20,7 @@ export default function JobReconciliationModalComponent({ job, bills }) { const filterFunction = InstanceRenderManager({ imex: (j) => - (j.part_type !== null && j.part_type !== "PAE") || + (j.part_type !== null && j.part_type !== "PAE" && j.act_price !== 0 && j.part_qty !== 0) || (j.line_desc && j.line_desc.toLowerCase().includes("towing") && j.lbr_op === "OP13") || j.db_ref === "936004", //ADD SHIPPING LINE. rome: (j) => From b44b71072f1d2db82040b2f56b99938c262230a6 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 3 Apr 2025 13:10:24 -0400 Subject: [PATCH 10/34] feature/IO-3198-Seperate-Socket-Provider-useSocket --- client/src/App/App.jsx | 2 +- .../chat-affix/chat-affix.container.jsx | 2 +- .../chat-archive-button.component.jsx | 2 +- ...chat-conversation-title-tags.component.jsx | 2 +- .../chat-conversation.container.jsx | 2 +- .../chat-label/chat-label.component.jsx | 2 +- .../chat-new-conversation.component.jsx | 2 +- .../chat-open-button.component.jsx | 2 +- .../chat-popup/chat-popup.component.jsx | 2 +- .../chat-tag-ro/chat-tag-ro.container.jsx | 2 +- .../components/header/header.component.jsx | 2 +- .../schedule-event.component.jsx | 2 +- .../job-detail-cards.component.jsx | 3 ++- .../jobs-detail-header-actions.component.jsx | 2 +- .../notification-center.container.jsx | 2 +- .../payments-generate-link.component.jsx | 2 +- .../production-board-kanban.container.jsx | 2 +- .../production-list-detail.component.jsx | 2 +- .../production-list-table.container.jsx | 2 +- .../profile-my/profile-my.component.jsx | 2 +- .../{useSocket.jsx => socketProvider.jsx} | 20 ++++--------------- client/src/contexts/SocketIO/useSocket.js | 13 ++++++++++++ .../jobs-detail.page.component.jsx | 2 +- .../pages/manage/manage.page.component.jsx | 2 +- 24 files changed, 40 insertions(+), 38 deletions(-) rename client/src/contexts/SocketIO/{useSocket.jsx => socketProvider.jsx} (96%) create mode 100644 client/src/contexts/SocketIO/useSocket.js diff --git a/client/src/App/App.jsx b/client/src/App/App.jsx index 1cf4a8a06..1b26476ff 100644 --- a/client/src/App/App.jsx +++ b/client/src/App/App.jsx @@ -21,8 +21,8 @@ import "./App.styles.scss"; import Eula from "../components/eula/eula.component"; import InstanceRenderMgr from "../utils/instanceRenderMgr"; import ProductFruitsWrapper from "./ProductFruitsWrapper.jsx"; -import { SocketProvider } from "../contexts/SocketIO/useSocket.jsx"; import { NotificationProvider } from "../contexts/Notifications/notificationContext.jsx"; +import SocketProvider from "../contexts/SocketIO/socketProvider.jsx"; const ResetPassword = lazy(() => import("../pages/reset-password/reset-password.component")); const ManagePage = lazy(() => import("../pages/manage/manage.page.container")); diff --git a/client/src/components/chat-affix/chat-affix.container.jsx b/client/src/components/chat-affix/chat-affix.container.jsx index c757598c6..9885b8551 100644 --- a/client/src/components/chat-affix/chat-affix.container.jsx +++ b/client/src/components/chat-affix/chat-affix.container.jsx @@ -3,11 +3,11 @@ import { getToken } from "@firebase/messaging"; import axios from "axios"; import { useEffect } from "react"; import { useTranslation } from "react-i18next"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; import { messaging, requestForToken } from "../../firebase/firebase.utils"; import ChatPopupComponent from "../chat-popup/chat-popup.component"; import "./chat-affix.styles.scss"; import { registerMessagingHandlers, unregisterMessagingHandlers } from "./registerMessagingSocketHandlers"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; export function ChatAffixContainer({ bodyshop, chatVisible }) { const { t } = useTranslation(); diff --git a/client/src/components/chat-archive-button/chat-archive-button.component.jsx b/client/src/components/chat-archive-button/chat-archive-button.component.jsx index 24eb9cea4..5b055c3a6 100644 --- a/client/src/components/chat-archive-button/chat-archive-button.component.jsx +++ b/client/src/components/chat-archive-button/chat-archive-button.component.jsx @@ -3,10 +3,10 @@ import { Button } from "antd"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { TOGGLE_CONVERSATION_ARCHIVE } from "../../graphql/conversations.queries"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors.js"; import { connect } from "react-redux"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop diff --git a/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx b/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx index e85ed6270..32ca5cad0 100644 --- a/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx +++ b/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx @@ -4,10 +4,10 @@ import { Link } from "react-router-dom"; import { logImEXEvent } from "../../firebase/firebase.utils"; import { REMOVE_CONVERSATION_TAG } from "../../graphql/job-conversations.queries"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors.js"; import { connect } from "react-redux"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop diff --git a/client/src/components/chat-conversation/chat-conversation.container.jsx b/client/src/components/chat-conversation/chat-conversation.container.jsx index 853c4851f..f951aabd1 100644 --- a/client/src/components/chat-conversation/chat-conversation.container.jsx +++ b/client/src/components/chat-conversation/chat-conversation.container.jsx @@ -3,11 +3,11 @@ import axios from "axios"; import { useCallback, useEffect, useState } from "react"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; import { CONVERSATION_SUBSCRIPTION_BY_PK, GET_CONVERSATION_DETAILS } from "../../graphql/conversations.queries"; import { selectSelectedConversation } from "../../redux/messaging/messaging.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors"; import ChatConversationComponent from "./chat-conversation.component"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; const mapStateToProps = createStructuredSelector({ selectedConversation: selectSelectedConversation, diff --git a/client/src/components/chat-label/chat-label.component.jsx b/client/src/components/chat-label/chat-label.component.jsx index 6fccd1390..1152acf29 100644 --- a/client/src/components/chat-label/chat-label.component.jsx +++ b/client/src/components/chat-label/chat-label.component.jsx @@ -4,11 +4,11 @@ import { Input, Spin, Tag, Tooltip } from "antd"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { UPDATE_CONVERSATION_LABEL } from "../../graphql/conversations.queries"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors.js"; import { connect } from "react-redux"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop diff --git a/client/src/components/chat-new-conversation/chat-new-conversation.component.jsx b/client/src/components/chat-new-conversation/chat-new-conversation.component.jsx index 8806974bf..c3fd81a68 100644 --- a/client/src/components/chat-new-conversation/chat-new-conversation.component.jsx +++ b/client/src/components/chat-new-conversation/chat-new-conversation.component.jsx @@ -5,7 +5,7 @@ import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { openChatByPhone } from "../../redux/messaging/messaging.actions"; import PhoneFormItem, { PhoneItemFormatterValidation } from "../form-items-formatted/phone-form-item.component"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser diff --git a/client/src/components/chat-open-button/chat-open-button.component.jsx b/client/src/components/chat-open-button/chat-open-button.component.jsx index 68b9cd8b2..76db997cd 100644 --- a/client/src/components/chat-open-button/chat-open-button.component.jsx +++ b/client/src/components/chat-open-button/chat-open-button.component.jsx @@ -7,7 +7,7 @@ import PhoneNumberFormatter from "../../utils/PhoneFormatter"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import { searchingForConversation } from "../../redux/messaging/messaging.selectors"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; const mapStateToProps = createStructuredSelector({ diff --git a/client/src/components/chat-popup/chat-popup.component.jsx b/client/src/components/chat-popup/chat-popup.component.jsx index 2ae16b129..01c5b3e85 100644 --- a/client/src/components/chat-popup/chat-popup.component.jsx +++ b/client/src/components/chat-popup/chat-popup.component.jsx @@ -12,9 +12,9 @@ import ChatConversationListComponent from "../chat-conversation-list/chat-conver import ChatConversationContainer from "../chat-conversation/chat-conversation.container"; import ChatNewConversation from "../chat-new-conversation/chat-new-conversation.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; import "./chat-popup.styles.scss"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; const mapStateToProps = createStructuredSelector({ selectedConversation: selectSelectedConversation, diff --git a/client/src/components/chat-tag-ro/chat-tag-ro.container.jsx b/client/src/components/chat-tag-ro/chat-tag-ro.container.jsx index 2a12d96db..d6c5bef4c 100644 --- a/client/src/components/chat-tag-ro/chat-tag-ro.container.jsx +++ b/client/src/components/chat-tag-ro/chat-tag-ro.container.jsx @@ -8,10 +8,10 @@ import { logImEXEvent } from "../../firebase/firebase.utils"; import { INSERT_CONVERSATION_TAG } from "../../graphql/job-conversations.queries"; import { SEARCH_FOR_JOBS } from "../../graphql/jobs.queries"; import ChatTagRo from "./chat-tag-ro.component"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors.js"; import { connect } from "react-redux"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx index 407bfd8a5..effe2fbf9 100644 --- a/client/src/components/header/header.component.jsx +++ b/client/src/components/header/header.component.jsx @@ -40,7 +40,6 @@ import { RiSurveyLine } from "react-icons/ri"; import { connect } from "react-redux"; import { Link } from "react-router-dom"; import { createStructuredSelector } from "reselect"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; import { GET_UNREAD_COUNT } from "../../graphql/notifications.queries.js"; import { selectRecentItems, selectSelectedHeader } from "../../redux/application/application.selectors"; import { setModalContext } from "../../redux/modals/modals.actions"; @@ -51,6 +50,7 @@ import InstanceRenderManager from "../../utils/instanceRenderMgr"; import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; import LockWrapper from "../lock-wrapper/lock-wrapper.component"; import NotificationCenterContainer from "../notification-center/notification-center.container.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; // Redux mappings const mapStateToProps = createStructuredSelector({ diff --git a/client/src/components/job-at-change/schedule-event.component.jsx b/client/src/components/job-at-change/schedule-event.component.jsx index eb53dffd4..4facb2a19 100644 --- a/client/src/components/job-at-change/schedule-event.component.jsx +++ b/client/src/components/job-at-change/schedule-event.component.jsx @@ -8,7 +8,7 @@ import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { Link, useLocation, useNavigate } from "react-router-dom"; import { createStructuredSelector } from "reselect"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; import { UPDATE_APPOINTMENT } from "../../graphql/appointments.queries"; import { openChatByPhone, setMessage } from "../../redux/messaging/messaging.actions"; import { setModalContext } from "../../redux/modals/modals.actions"; diff --git a/client/src/components/job-detail-cards/job-detail-cards.component.jsx b/client/src/components/job-detail-cards/job-detail-cards.component.jsx index 5e5df5b58..d114816ed 100644 --- a/client/src/components/job-detail-cards/job-detail-cards.component.jsx +++ b/client/src/components/job-detail-cards/job-detail-cards.component.jsx @@ -6,7 +6,8 @@ import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { Link, useLocation, useNavigate } from "react-router-dom"; import { createStructuredSelector } from "reselect"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; + import { logImEXEvent } from "../../firebase/firebase.utils"; import { QUERY_JOB_CARD_DETAILS, UPDATE_JOB } from "../../graphql/jobs.queries"; import { insertAuditTrail } from "../../redux/application/application.actions.js"; diff --git a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx index 02a6b3494..9488c60e1 100644 --- a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx +++ b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx @@ -9,7 +9,7 @@ import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { Link, useNavigate } from "react-router-dom"; import { createStructuredSelector } from "reselect"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; import { auth, logImEXEvent } from "../../firebase/firebase.utils"; import { CANCEL_APPOINTMENTS_BY_JOB_ID, INSERT_MANUAL_APPT } from "../../graphql/appointments.queries"; import { GET_CURRENT_QUESTIONSET_ID, INSERT_CSI } from "../../graphql/csi.queries"; diff --git a/client/src/components/notification-center/notification-center.container.jsx b/client/src/components/notification-center/notification-center.container.jsx index ae12552f3..a2924aa3a 100644 --- a/client/src/components/notification-center/notification-center.container.jsx +++ b/client/src/components/notification-center/notification-center.container.jsx @@ -3,10 +3,10 @@ import { useQuery } from "@apollo/client"; import { connect } from "react-redux"; import NotificationCenterComponent from "./notification-center.component"; import { GET_NOTIFICATIONS } from "../../graphql/notifications.queries"; -import { INITIAL_NOTIFICATIONS, useSocket } from "../../contexts/SocketIO/useSocket.jsx"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors.js"; import day from "../../utils/day.js"; +import { INITIAL_NOTIFICATIONS, useSocket } from "../../contexts/SocketIO/useSocket.js"; // This will be used to poll for notifications when the socket is disconnected const NOTIFICATION_POLL_INTERVAL_SECONDS = 60; diff --git a/client/src/components/payments-generate-link/payments-generate-link.component.jsx b/client/src/components/payments-generate-link/payments-generate-link.component.jsx index 7e121621f..4c1fb5fef 100644 --- a/client/src/components/payments-generate-link/payments-generate-link.component.jsx +++ b/client/src/components/payments-generate-link/payments-generate-link.component.jsx @@ -10,7 +10,7 @@ import { createStructuredSelector } from "reselect"; import { openChatByPhone, setMessage } from "../../redux/messaging/messaging.actions"; import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors"; import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, diff --git a/client/src/components/production-board-kanban/production-board-kanban.container.jsx b/client/src/components/production-board-kanban/production-board-kanban.container.jsx index 3b0c4066f..536f1193e 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.container.jsx +++ b/client/src/components/production-board-kanban/production-board-kanban.container.jsx @@ -12,7 +12,7 @@ import { QUERY_KANBAN_SETTINGS } from "../../graphql/user.queries"; import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors"; import ProductionBoardKanbanComponent from "./production-board-kanban.component"; import { useSplitTreatments } from "@splitsoftware/splitio-react"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, diff --git a/client/src/components/production-list-detail/production-list-detail.component.jsx b/client/src/components/production-list-detail/production-list-detail.component.jsx index 7db55bd07..d05110fc5 100644 --- a/client/src/components/production-list-detail/production-list-detail.component.jsx +++ b/client/src/components/production-list-detail/production-list-detail.component.jsx @@ -7,7 +7,7 @@ import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { useLocation, useNavigate } from "react-router-dom"; import { createStructuredSelector } from "reselect"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; import { logImEXEvent } from "../../firebase/firebase.utils.js"; import { QUERY_JOB_CARD_DETAILS, UPDATE_JOB } from "../../graphql/jobs.queries"; import { insertAuditTrail } from "../../redux/application/application.actions.js"; diff --git a/client/src/components/production-list-table/production-list-table.container.jsx b/client/src/components/production-list-table/production-list-table.container.jsx index 373222a65..17aba9b16 100644 --- a/client/src/components/production-list-table/production-list-table.container.jsx +++ b/client/src/components/production-list-table/production-list-table.container.jsx @@ -10,7 +10,7 @@ import { import ProductionListTable from "./production-list-table.component"; import _ from "lodash"; import { useSplitTreatments } from "@splitsoftware/splitio-react"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; export default function ProductionListTableContainer({ bodyshop, subscriptionType = "direct" }) { const client = useApolloClient(); diff --git a/client/src/components/profile-my/profile-my.component.jsx b/client/src/components/profile-my/profile-my.component.jsx index d17547cf0..0b3180d0a 100644 --- a/client/src/components/profile-my/profile-my.component.jsx +++ b/client/src/components/profile-my/profile-my.component.jsx @@ -8,7 +8,7 @@ import { selectCurrentUser } from "../../redux/user/user.selectors"; import { logImEXEvent, updateCurrentPassword } from "../../firebase/firebase.utils"; import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; import NotificationSettingsForm from "../notification-settings/notification-settings-form.component.jsx"; const mapStateToProps = createStructuredSelector({ diff --git a/client/src/contexts/SocketIO/useSocket.jsx b/client/src/contexts/SocketIO/socketProvider.jsx similarity index 96% rename from client/src/contexts/SocketIO/useSocket.jsx rename to client/src/contexts/SocketIO/socketProvider.jsx index 70f52311f..efc77ea7c 100644 --- a/client/src/contexts/SocketIO/useSocket.jsx +++ b/client/src/contexts/SocketIO/socketProvider.jsx @@ -1,4 +1,5 @@ -import { createContext, useContext, useEffect, useRef, useState } from "react"; +// SocketProvider.js +import { useEffect, useRef, useState } from "react"; import SocketIO from "socket.io-client"; import { auth } from "../../firebase/firebase.utils"; import { store } from "../../redux/store"; @@ -15,10 +16,7 @@ import { import { useMutation } from "@apollo/client"; import { useTranslation } from "react-i18next"; import { useSplitTreatments } from "@splitsoftware/splitio-react"; - -const SocketContext = createContext(null); - -const INITIAL_NOTIFICATIONS = 10; +import { SocketContext, INITIAL_NOTIFICATIONS } from "./useSocket.js"; /** * Socket Provider - Scenario Notifications / Web Socket related items @@ -216,7 +214,6 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser }) => { }; const handleNotification = (data) => { - // Scenario Notifications have been disabled, bail. if (Realtime_Notifications_UI?.treatment !== "on") { return; } @@ -336,7 +333,6 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser }) => { }; const handleSyncNotificationRead = ({ notificationId, timestamp }) => { - // Scenario Notifications have been disabled, bail. if (Realtime_Notifications_UI?.treatment !== "on") { return; } @@ -378,7 +374,6 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser }) => { }; const handleSyncAllNotificationsRead = ({ timestamp }) => { - // Scenario Notifications have been disabled, bail. if (Realtime_Notifications_UI?.treatment !== "on") { return; } @@ -490,11 +485,4 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser }) => { ); }; -const useSocket = () => { - const context = useContext(SocketContext); - // NOTE: Not sure if we absolutely require this, does cause slipups on dev env - if (!context) throw new Error("useSocket must be used within a SocketProvider"); - return context; -}; - -export { SocketContext, SocketProvider, INITIAL_NOTIFICATIONS, useSocket }; +export default SocketProvider; diff --git a/client/src/contexts/SocketIO/useSocket.js b/client/src/contexts/SocketIO/useSocket.js new file mode 100644 index 000000000..d9a6f9b84 --- /dev/null +++ b/client/src/contexts/SocketIO/useSocket.js @@ -0,0 +1,13 @@ +import { createContext, useContext } from "react"; + +const SocketContext = createContext(null); + +const INITIAL_NOTIFICATIONS = 10; + +const useSocket = () => { + const context = useContext(SocketContext); + if (!context) throw new Error("useSocket must be used within a SocketProvider"); + return context; +}; + +export { SocketContext, INITIAL_NOTIFICATIONS, useSocket }; diff --git a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx index d5b6776ee..6afe3ba15 100644 --- a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx +++ b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx @@ -56,7 +56,7 @@ import { DateTimeFormat } from "../../utils/DateFormatter"; import dayjs from "../../utils/day"; import UndefinedToNull from "../../utils/undefinedtonull"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; import JobWatcherToggleContainer from "../../components/job-watcher-toggle/job-watcher-toggle.container.jsx"; const mapStateToProps = createStructuredSelector({ diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx index e813eaae0..b6148aa1d 100644 --- a/client/src/pages/manage/manage.page.component.jsx +++ b/client/src/pages/manage/manage.page.component.jsx @@ -20,7 +20,6 @@ import PartnerPingComponent from "../../components/partner-ping/partner-ping.com import PrintCenterModalContainer from "../../components/print-center-modal/print-center-modal.container"; import ShopSubStatusComponent from "../../components/shop-sub-status/shop-sub-status.component"; import { requestForToken } from "../../firebase/firebase.utils"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; import { selectBodyshop, selectInstanceConflict } from "../../redux/user/user.selectors"; import UpdateAlert from "../../components/update-alert/update-alert.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr.js"; @@ -29,6 +28,7 @@ import WssStatusDisplayComponent from "../../components/wss-status-display/wss-s import { selectAlerts } from "../../redux/application/application.selectors.js"; import { addAlerts } from "../../redux/application/application.actions.js"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; +import { useSocket } from "../../contexts/SocketIO/useSocket.js"; const JobsPage = lazy(() => import("../jobs/jobs.page")); From 320ad065d040d5aa53c744e4937d53a10a93de5f Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 4 Apr 2025 13:19:44 -0400 Subject: [PATCH 11/34] feature/IO-2769-Job-Totals-testing: Setup testing method for job totals --- .gitignore | 2 +- Dockerfile | 3 +- server/job/job-totals-USA.js | 24 ++++++++--- server/job/job-totals.js | 17 +++++++- server/job/test/job-totals.test.js | 68 ++++++++++++++++++++++++++++++ server/job/utils/seralizeHelper.js | 47 +++++++++++++++++++++ 6 files changed, 151 insertions(+), 10 deletions(-) create mode 100644 server/job/test/job-totals.test.js create mode 100644 server/job/utils/seralizeHelper.js diff --git a/.gitignore b/.gitignore index bf7f3dac7..9b2ed79f9 100644 --- a/.gitignore +++ b/.gitignore @@ -127,4 +127,4 @@ vitest-report*/ vitest-coverage/ *.vitest.log test-output.txt - +server/job/test/fixtures diff --git a/Dockerfile b/Dockerfile index 8afe15df4..bab946292 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,4 +56,5 @@ COPY . . EXPOSE 4000 9229 # Start the application -CMD ["nodemon", "--legacy-watch", "--inspect=0.0.0.0:9229", "server.js"] +RUN echo "Starting the application..." +CMD ["nodemon", "--ignore", "./server/job/test/fixtures", "--legacy-watch", "--inspect=0.0.0.0:9229", "server.js"] diff --git a/server/job/job-totals-USA.js b/server/job/job-totals-USA.js index dd850dc9b..2b92702bb 100644 --- a/server/job/job-totals-USA.js +++ b/server/job/job-totals-USA.js @@ -1,8 +1,7 @@ const Dinero = require("dinero.js"); const queries = require("../graphql-client/queries"); -// const adminClient = require("../graphql-client/graphql-client").client; -// const _ = require("lodash"); const logger = require("../utils/logger"); +const { captureFixture } = require("./utils/seralizeHelper"); const InstanceMgr = require("../utils/instanceMgr").default; //****************************************************** */ @@ -33,7 +32,15 @@ exports.totalsSsu = async function (req, res) { id: id }); - const newTotals = await TotalsServerSide({ body: { job: job.jobs_by_pk, client: client } }, res, true); + // Extract the job data (the input for TotalsServerSide) + const inputForTotals = job.jobs_by_pk; + + const newTotals = await TotalsServerSide({ body: { job: inputForTotals, client: client } }, res, true); + + // Capture fixture data (input and output), using job.id for the filename. + if (process.env?.SAVE_TOTALS_DATA) { + captureFixture(inputForTotals, inputForTotals, newTotals); + } const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, { jobId: id, @@ -45,9 +52,11 @@ exports.totalsSsu = async function (req, res) { } }); - if (result) { - res.status(200).send(); + if (!result) { + throw new Error("Failed to update job totals"); } + + res.status(200).send(); } catch (error) { logger.log("job-totals-ssu-USA-error", "ERROR", req?.user?.email, id, { jobid: id, @@ -58,7 +67,7 @@ exports.totalsSsu = async function (req, res) { } }; -//IMPORTANT*** These two functions MUST be mirrrored. +//IMPORTANT*** These two functions MUST be mirrored. async function TotalsServerSide(req, res) { const { job, client } = req.body; await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user }); @@ -133,6 +142,9 @@ async function TotalsServerSide(req, res) { } } +// Exported for testing purposes. +exports.TotalsServerSide = TotalsServerSide; + async function Totals(req, res) { const { job, id } = req.body; diff --git a/server/job/job-totals.js b/server/job/job-totals.js index 6182f9ced..92edcd238 100644 --- a/server/job/job-totals.js +++ b/server/job/job-totals.js @@ -1,6 +1,7 @@ const Dinero = require("dinero.js"); const queries = require("../graphql-client/queries"); const logger = require("../utils/logger"); +const { captureFixture } = require("./utils/seralizeHelper"); //****************************************************** */ //****************************************************** */ @@ -30,7 +31,16 @@ exports.totalsSsu = async function (req, res) { id: id }); - const newTotals = await TotalsServerSide({ body: { job: job.jobs_by_pk, client: client } }, res, true); + // Extract the job data (the input for TotalsServerSide) + const inputForTotals = job.jobs_by_pk; + + // Capture the output of TotalsServerSide + const newTotals = await TotalsServerSide({ body: { job: inputForTotals, client: client } }, res, true); + + // Capture fixture data (input and output), using job.id for the filename. + if (process.env?.SAVE_TOTALS_DATA) { + captureFixture(inputForTotals, inputForTotals, newTotals); + } const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, { jobId: id, @@ -57,7 +67,7 @@ exports.totalsSsu = async function (req, res) { } }; -//IMPORTANT*** These two functions MUST be mirrrored. +//IMPORTANT*** These two functions MUST be mirrored. async function TotalsServerSide(req, res) { const { job, client } = req.body; await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user }); @@ -81,6 +91,9 @@ async function TotalsServerSide(req, res) { } } +// Exported for testing purposes +exports.TotalsServerSide = TotalsServerSide; + async function Totals(req, res) { const { job, id } = req.body; diff --git a/server/job/test/job-totals.test.js b/server/job/test/job-totals.test.js new file mode 100644 index 000000000..b0a30a29f --- /dev/null +++ b/server/job/test/job-totals.test.js @@ -0,0 +1,68 @@ +import fs from "fs"; +import path from "path"; +import { describe, it, expect } from "vitest"; +import { TotalsServerSide } from "../job-totals"; // adjust the path as needed +import Dinero from "dinero.js"; + +// A custom replacer to normalize Dinero objects +function dineroReplacer(key, value) { + if (value && typeof value === "object" && typeof value.toObject === "function") { + return value.toObject(); + } + return value; +} + +// Normalization function to convert any Dinero instances to plain objects +function normalizeOutput(obj) { + return JSON.parse(JSON.stringify(obj, dineroReplacer)); +} + +describe("TotalsServerSide fixture tests", () => { + // Define the fixture directory. + // For example, if this test file is at /server/job/test/, + // then the fixtures are in /server/job/test/fixtures/job-totals/ + const fixturesDir = path.join(__dirname, "fixtures", "job-totals"); + + // Read all fixture JSON files from the fixture directory. + const fixtureFiles = fs.readdirSync(fixturesDir).filter((f) => f.endsWith(".json")); + + // Create a dummy client. If your TotalsServerSide uses client.request, + // make sure these paths are either not triggered or stubbed accordingly. + const dummyClient = { + request: async () => { + // Return an empty object (or any other value that makes sense for your tests). + return {}; + } + }; + + // Create a dummy response object. TotalsServerSide might only use it to send error statuses. + const dummyRes = { + status: () => ({ send: () => {} }) + }; + + fixtureFiles.forEach((file) => { + it(`should produce matching output for fixture file ${file}`, async () => { + const fixturePath = path.join(fixturesDir, file); + const fixtureData = JSON.parse(fs.readFileSync(fixturePath, "utf8")); + + const { input, output: expectedOutput } = fixtureData; + + const req = { + body: { + job: input, + client: dummyClient + }, + user: {} + }; + + // Call the TotalsServerSide function with the fixture input. + const computedOutput = await TotalsServerSide(req, dummyRes); + + // Normalize both computed and expected outputs so that any Dinero objects are replaced with their plain representation. + const normalizedComputed = normalizeOutput(computedOutput); + const normalizedExpected = normalizeOutput(expectedOutput); + + expect(normalizedComputed).toEqual(normalizedExpected); + }); + }); +}); diff --git a/server/job/utils/seralizeHelper.js b/server/job/utils/seralizeHelper.js new file mode 100644 index 000000000..b95779b7b --- /dev/null +++ b/server/job/utils/seralizeHelper.js @@ -0,0 +1,47 @@ +const fs = require("fs"); +const path = require("path"); + +const fixtureDir = path.join(__dirname, "..", "test", "fixtures", "job-totals"); + +/** + * Custom serializer for Dinero.js objects. + * @param key + * @param value + * @returns {*} + */ +const serializeDinero = (key, value) => { + // If the value has a toObject method (as in Dinero instances), use it. + if (value && typeof value === "object" && typeof value.toObject === "function") { + return value.toObject(); + } + return value; +}; + +/** + * Capture a fixture for job totals. + * @param job + * @param inputData + * @param outputData + */ +const captureFixture = (job, inputData, outputData) => { + if (!fs.existsSync(fixtureDir)) { + fs.mkdirSync(fixtureDir, { recursive: true }); + } + + // Use job.id to label the file. + const fileName = `${job.id}.json`; + const filePath = path.join(fixtureDir, fileName); + + const dataToSave = { + input: inputData, + output: outputData + }; + + // Save the file using our custom serializer. + fs.writeFileSync(filePath, JSON.stringify(dataToSave, serializeDinero, 2), "utf8"); +}; + +module.exports = { + captureFixture, + serializeDinero +}; From add88659a4010144519c45e4484290493831e2cf Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 4 Apr 2025 13:23:33 -0400 Subject: [PATCH 12/34] feature/IO-2769-Job-Totals-testing: Setup testing method for job totals --- server/job/test/job-totals.test.js | 37 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/server/job/test/job-totals.test.js b/server/job/test/job-totals.test.js index b0a30a29f..d615d169c 100644 --- a/server/job/test/job-totals.test.js +++ b/server/job/test/job-totals.test.js @@ -1,41 +1,44 @@ import fs from "fs"; import path from "path"; import { describe, it, expect } from "vitest"; -import { TotalsServerSide } from "../job-totals"; // adjust the path as needed -import Dinero from "dinero.js"; +import { TotalsServerSide } from "../job-totals"; -// A custom replacer to normalize Dinero objects -function dineroReplacer(key, value) { +/** + * This function is used to replace the values in the object with their + * @param key + * @param value + * @returns {*} + */ +const dineroReplacer = (key, value) => { if (value && typeof value === "object" && typeof value.toObject === "function") { return value.toObject(); } return value; -} +}; -// Normalization function to convert any Dinero instances to plain objects -function normalizeOutput(obj) { +/** + * Normalizes the output of the TotalsServerSide function by converting + * @param obj + * @returns {any} + */ +const normalizeOutput = (obj) => { return JSON.parse(JSON.stringify(obj, dineroReplacer)); -} +}; +/** + * This test suite is designed to validate the functionality of the TotalsServerSide function + */ describe("TotalsServerSide fixture tests", () => { - // Define the fixture directory. - // For example, if this test file is at /server/job/test/, - // then the fixtures are in /server/job/test/fixtures/job-totals/ const fixturesDir = path.join(__dirname, "fixtures", "job-totals"); - // Read all fixture JSON files from the fixture directory. const fixtureFiles = fs.readdirSync(fixturesDir).filter((f) => f.endsWith(".json")); - // Create a dummy client. If your TotalsServerSide uses client.request, - // make sure these paths are either not triggered or stubbed accordingly. const dummyClient = { request: async () => { - // Return an empty object (or any other value that makes sense for your tests). return {}; } }; - // Create a dummy response object. TotalsServerSide might only use it to send error statuses. const dummyRes = { status: () => ({ send: () => {} }) }; @@ -55,10 +58,8 @@ describe("TotalsServerSide fixture tests", () => { user: {} }; - // Call the TotalsServerSide function with the fixture input. const computedOutput = await TotalsServerSide(req, dummyRes); - // Normalize both computed and expected outputs so that any Dinero objects are replaced with their plain representation. const normalizedComputed = normalizeOutput(computedOutput); const normalizedExpected = normalizeOutput(expectedOutput); From 27a3932c084eb7e4d5749f1f57314b54602b79b2 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 4 Apr 2025 13:43:19 -0400 Subject: [PATCH 13/34] feature/IO-2769-Job-Totals-testing: Allow for both american and canadian capture + tests --- server/job/job-totals-USA.js | 9 ++++++++- server/job/job-totals.js | 10 +++++++++- server/job/test/job-totals.test.js | 8 +++++--- server/job/utils/seralizeHelper.js | 11 ++++++++--- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/server/job/job-totals-USA.js b/server/job/job-totals-USA.js index 2b92702bb..cf22c3adc 100644 --- a/server/job/job-totals-USA.js +++ b/server/job/job-totals-USA.js @@ -39,7 +39,14 @@ exports.totalsSsu = async function (req, res) { // Capture fixture data (input and output), using job.id for the filename. if (process.env?.SAVE_TOTALS_DATA) { - captureFixture(inputForTotals, inputForTotals, newTotals); + captureFixture( + inputForTotals, + newTotals, + InstanceMgr({ + imex: "ca", + rome: "us" + }) + ); } const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, { diff --git a/server/job/job-totals.js b/server/job/job-totals.js index 92edcd238..f9c2ec8fa 100644 --- a/server/job/job-totals.js +++ b/server/job/job-totals.js @@ -2,6 +2,7 @@ const Dinero = require("dinero.js"); const queries = require("../graphql-client/queries"); const logger = require("../utils/logger"); const { captureFixture } = require("./utils/seralizeHelper"); +const { default: InstanceMgr } = require("../utils/instanceMgr"); //****************************************************** */ //****************************************************** */ @@ -39,7 +40,14 @@ exports.totalsSsu = async function (req, res) { // Capture fixture data (input and output), using job.id for the filename. if (process.env?.SAVE_TOTALS_DATA) { - captureFixture(inputForTotals, inputForTotals, newTotals); + captureFixture( + inputForTotals, + newTotals, + InstanceMgr({ + imex: "ca", + rome: "us" + }) + ); } const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, { diff --git a/server/job/test/job-totals.test.js b/server/job/test/job-totals.test.js index d615d169c..6f5af805b 100644 --- a/server/job/test/job-totals.test.js +++ b/server/job/test/job-totals.test.js @@ -1,7 +1,8 @@ import fs from "fs"; import path from "path"; import { describe, it, expect } from "vitest"; -import { TotalsServerSide } from "../job-totals"; +import { TotalsServerSide as TotalsServerSideCA } from "../job-totals"; // Canadian version (imex) +import { TotalsServerSide as TotalsServerSideUS } from "../job-totals-USA"; // US version (rome) /** * This function is used to replace the values in the object with their @@ -48,7 +49,7 @@ describe("TotalsServerSide fixture tests", () => { const fixturePath = path.join(fixturesDir, file); const fixtureData = JSON.parse(fs.readFileSync(fixturePath, "utf8")); - const { input, output: expectedOutput } = fixtureData; + const { environment, input, output: expectedOutput } = fixtureData; const req = { body: { @@ -58,7 +59,8 @@ describe("TotalsServerSide fixture tests", () => { user: {} }; - const computedOutput = await TotalsServerSide(req, dummyRes); + const computedOutput = + environment === "us" ? await TotalsServerSideUS(req, dummyRes) : await TotalsServerSideCA(req, dummyRes); const normalizedComputed = normalizeOutput(computedOutput); const normalizedExpected = normalizeOutput(expectedOutput); diff --git a/server/job/utils/seralizeHelper.js b/server/job/utils/seralizeHelper.js index b95779b7b..3d7aae03c 100644 --- a/server/job/utils/seralizeHelper.js +++ b/server/job/utils/seralizeHelper.js @@ -19,20 +19,25 @@ const serializeDinero = (key, value) => { /** * Capture a fixture for job totals. - * @param job * @param inputData * @param outputData + * @param environment */ -const captureFixture = (job, inputData, outputData) => { +const captureFixture = (inputData, outputData, environment) => { if (!fs.existsSync(fixtureDir)) { fs.mkdirSync(fixtureDir, { recursive: true }); } // Use job.id to label the file. - const fileName = `${job.id}.json`; + const fileName = `${inputData.id}.json`; const filePath = path.join(fixtureDir, fileName); const dataToSave = { + environment: environment, + meta: { + ro_number: inputData.ro_number, + updated_at: inputData.updated_at + }, input: inputData, output: outputData }; From 8323fa669685528a9e7e90eff5a9a550cc34e5a7 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 4 Apr 2025 13:45:45 -0400 Subject: [PATCH 14/34] feature/IO-2769-Job-Totals-testing: Allow for both american and canadian capture + tests --- server/job/utils/seralizeHelper.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/job/utils/seralizeHelper.js b/server/job/utils/seralizeHelper.js index 3d7aae03c..d526af30f 100644 --- a/server/job/utils/seralizeHelper.js +++ b/server/job/utils/seralizeHelper.js @@ -10,7 +10,6 @@ const fixtureDir = path.join(__dirname, "..", "test", "fixtures", "job-totals"); * @returns {*} */ const serializeDinero = (key, value) => { - // If the value has a toObject method (as in Dinero instances), use it. if (value && typeof value === "object" && typeof value.toObject === "function") { return value.toObject(); } @@ -28,7 +27,6 @@ const captureFixture = (inputData, outputData, environment) => { fs.mkdirSync(fixtureDir, { recursive: true }); } - // Use job.id to label the file. const fileName = `${inputData.id}.json`; const filePath = path.join(fixtureDir, fileName); From 51c2d3351a17cd3c6d4b16a4f1f5ac82493a555f Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 4 Apr 2025 13:47:38 -0400 Subject: [PATCH 15/34] feature/IO-2769-Job-Totals-testing: Allow for both american and canadian capture + tests --- server/job/job-totals-USA.js | 9 +-------- server/job/job-totals.js | 9 +-------- server/job/utils/seralizeHelper.js | 9 ++++++--- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/server/job/job-totals-USA.js b/server/job/job-totals-USA.js index cf22c3adc..f125217f5 100644 --- a/server/job/job-totals-USA.js +++ b/server/job/job-totals-USA.js @@ -39,14 +39,7 @@ exports.totalsSsu = async function (req, res) { // Capture fixture data (input and output), using job.id for the filename. if (process.env?.SAVE_TOTALS_DATA) { - captureFixture( - inputForTotals, - newTotals, - InstanceMgr({ - imex: "ca", - rome: "us" - }) - ); + captureFixture(inputForTotals, newTotals); } const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, { diff --git a/server/job/job-totals.js b/server/job/job-totals.js index f9c2ec8fa..2984573a6 100644 --- a/server/job/job-totals.js +++ b/server/job/job-totals.js @@ -40,14 +40,7 @@ exports.totalsSsu = async function (req, res) { // Capture fixture data (input and output), using job.id for the filename. if (process.env?.SAVE_TOTALS_DATA) { - captureFixture( - inputForTotals, - newTotals, - InstanceMgr({ - imex: "ca", - rome: "us" - }) - ); + captureFixture(inputForTotals, newTotals); } const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, { diff --git a/server/job/utils/seralizeHelper.js b/server/job/utils/seralizeHelper.js index d526af30f..6ea69b5b8 100644 --- a/server/job/utils/seralizeHelper.js +++ b/server/job/utils/seralizeHelper.js @@ -1,5 +1,6 @@ const fs = require("fs"); const path = require("path"); +const { default: InstanceMgr } = require("../../utils/instanceMgr"); const fixtureDir = path.join(__dirname, "..", "test", "fixtures", "job-totals"); @@ -20,9 +21,8 @@ const serializeDinero = (key, value) => { * Capture a fixture for job totals. * @param inputData * @param outputData - * @param environment */ -const captureFixture = (inputData, outputData, environment) => { +const captureFixture = (inputData, outputData) => { if (!fs.existsSync(fixtureDir)) { fs.mkdirSync(fixtureDir, { recursive: true }); } @@ -31,7 +31,10 @@ const captureFixture = (inputData, outputData, environment) => { const filePath = path.join(fixtureDir, fileName); const dataToSave = { - environment: environment, + environment: InstanceMgr({ + imex: "ca", + rome: "us" + }), meta: { ro_number: inputData.ro_number, updated_at: inputData.updated_at From 7ddec0bb0fa75fbbe1e0d7770a519ce84588f958 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 4 Apr 2025 13:49:21 -0400 Subject: [PATCH 16/34] feature/IO-2769-Job-Totals-testing: Allow for both american and canadian capture + tests --- server/job/job-totals.js | 1 - 1 file changed, 1 deletion(-) diff --git a/server/job/job-totals.js b/server/job/job-totals.js index 2984573a6..278fa9bfa 100644 --- a/server/job/job-totals.js +++ b/server/job/job-totals.js @@ -2,7 +2,6 @@ const Dinero = require("dinero.js"); const queries = require("../graphql-client/queries"); const logger = require("../utils/logger"); const { captureFixture } = require("./utils/seralizeHelper"); -const { default: InstanceMgr } = require("../utils/instanceMgr"); //****************************************************** */ //****************************************************** */ From 14630378784a917b9198a26b60273197b0b6f3d2 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 4 Apr 2025 13:54:53 -0400 Subject: [PATCH 17/34] feature/IO-2769-Job-Totals-testing: Allow for both american and canadian capture + tests --- server/job/test/job-totals.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/job/test/job-totals.test.js b/server/job/test/job-totals.test.js index 6f5af805b..059b0bb1e 100644 --- a/server/job/test/job-totals.test.js +++ b/server/job/test/job-totals.test.js @@ -5,7 +5,7 @@ import { TotalsServerSide as TotalsServerSideCA } from "../job-totals"; // Canad import { TotalsServerSide as TotalsServerSideUS } from "../job-totals-USA"; // US version (rome) /** - * This function is used to replace the values in the object with their + * This function is used to replace the values in the object with their toObject() representation. * @param key * @param value * @returns {*} From f777d26cc19c93f641f15f2d010695453725a1ad Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 4 Apr 2025 14:15:30 -0400 Subject: [PATCH 18/34] feature/IO-2769-Job-Totals-testing: Allow for both american and canadian capture + tests --- server/job/job-totals-USA.js | 2 +- server/job/job-totals.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/job/job-totals-USA.js b/server/job/job-totals-USA.js index f125217f5..8cde6ebb3 100644 --- a/server/job/job-totals-USA.js +++ b/server/job/job-totals-USA.js @@ -38,7 +38,7 @@ exports.totalsSsu = async function (req, res) { const newTotals = await TotalsServerSide({ body: { job: inputForTotals, client: client } }, res, true); // Capture fixture data (input and output), using job.id for the filename. - if (process.env?.SAVE_TOTALS_DATA) { + if (process.env?.SAVE_TOTALS_DATA === "true") { captureFixture(inputForTotals, newTotals); } diff --git a/server/job/job-totals.js b/server/job/job-totals.js index 278fa9bfa..3aba47d1f 100644 --- a/server/job/job-totals.js +++ b/server/job/job-totals.js @@ -38,7 +38,7 @@ exports.totalsSsu = async function (req, res) { const newTotals = await TotalsServerSide({ body: { job: inputForTotals, client: client } }, res, true); // Capture fixture data (input and output), using job.id for the filename. - if (process.env?.SAVE_TOTALS_DATA) { + if (process.env?.SAVE_TOTALS_DATA === "true") { captureFixture(inputForTotals, newTotals); } From db09d09428ed01f7ec5ac4fa4cd2dcd10c4b1301 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 7 Apr 2025 12:11:53 -0400 Subject: [PATCH 19/34] release/2025-04-11 - Fix Packages --- client/package-lock.json | 227 +++++++++++++++--------------- client/package.json | 28 ++-- package-lock.json | 293 ++++++++++++++++++++------------------- package.json | 26 ++-- 4 files changed, 288 insertions(+), 286 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index dbfeed6ca..12559bc12 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "dependencies": { "@ant-design/pro-layout": "^7.22.4", - "@apollo/client": "^3.13.5", + "@apollo/client": "^3.13.6", "@emotion/is-prop-valid": "^1.3.1", "@fingerprintjs/fingerprintjs": "^4.6.1", "@firebase/analytics": "^0.10.12", @@ -21,8 +21,8 @@ "@jsreport/browser-client": "^3.1.0", "@reduxjs/toolkit": "^2.6.1", "@sentry/cli": "^2.43.0", - "@sentry/react": "^9.10.1", - "@sentry/vite-plugin": "^3.2.4", + "@sentry/react": "^9.11.0", + "@sentry/vite-plugin": "^3.3.1", "@splitsoftware/splitio-react": "^2.1.0", "@tanem/react-nprogress": "^5.0.53", "antd": "^5.24.6", @@ -58,7 +58,7 @@ "react-dom": "^18.3.1", "react-drag-listview": "^2.0.0", "react-grid-gallery": "^1.0.1", - "react-grid-layout": "1.3.4", + "react-grid-layout": "^1.3.4", "react-i18next": "^15.4.1", "react-icons": "^5.5.0", "react-image-lightbox": "^5.1.4", @@ -70,17 +70,17 @@ "react-resizable": "^3.0.5", "react-router-dom": "^6.30.0", "react-sticky": "^6.0.3", - "react-virtuoso": "^4.12.6", - "recharts": "^2.15.0", + "react-virtuoso": "^4.12.5", + "recharts": "^2.15.2", "redux": "^5.0.1", "redux-actions": "^3.0.3", "redux-persist": "^6.0.0", "redux-saga": "^1.3.0", "redux-state-sync": "^3.1.4", "reselect": "^5.1.1", - "sass": "^1.86.1", + "sass": "^1.86.3", "socket.io-client": "^4.8.1", - "styled-components": "^6.1.16", + "styled-components": "^6.1.17", "subscriptions-transport-ws": "^0.11.0", "use-memo-one": "^1.1.3", "vite-plugin-ejs": "^1.7.0", @@ -90,22 +90,22 @@ "@ant-design/icons": "^6.0.0", "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/preset-react": "^7.26.3", - "@dotenvx/dotenvx": "^1.39.0", + "@dotenvx/dotenvx": "^1.39.1", "@emotion/babel-plugin": "^11.13.5", "@emotion/react": "^11.14.0", - "@eslint/js": "^9.23.0", + "@eslint/js": "^9.24.0", "@playwright/test": "^1.51.1", - "@sentry/webpack-plugin": "^3.2.4", + "@sentry/webpack-plugin": "^3.3.1", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.2.0", + "@testing-library/react": "^16.3.0", "@vitejs/plugin-react": "^4.3.4", "browserslist": "^4.24.4", "browserslist-to-esbuild": "^2.1.1", "chalk": "^5.4.1", "eslint": "^8.57.1", "eslint-config-react-app": "^7.0.1", - "eslint-plugin-react": "^7.37.4", + "eslint-plugin-react": "^7.37.5", "globals": "^15.15.0", "jsdom": "^26.0.0", "memfs": "^4.17.0", @@ -114,7 +114,7 @@ "react-error-overlay": "^6.1.0", "redux-logger": "^3.0.6", "source-map-explorer": "^2.5.3", - "vite": "^6.2.4", + "vite": "^6.2.5", "vite-plugin-babel": "^1.3.0", "vite-plugin-eslint": "^1.8.1", "vite-plugin-node-polyfills": "^0.23.0", @@ -396,9 +396,9 @@ } }, "node_modules/@apollo/client": { - "version": "3.13.5", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.5.tgz", - "integrity": "sha512-ceHa1lApLAiGmUur4V+G/CrjwVwHYujfB7U5HM++poCgHpfGn6eet8YGM93fgeWjYX85SaqwdZbQk18IVwhRHg==", + "version": "3.13.6", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.6.tgz", + "integrity": "sha512-G6A8uNb13V/Tv4TJQOs5PnxuE5Rf5D2dMnBQcg9mng1Eo4YBecwFEJ0L022mraq/dLB0jD5tiAESOD2bTyJ6gg==", "license": "MIT", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", @@ -2566,9 +2566,9 @@ } }, "node_modules/@dotenvx/dotenvx": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.39.0.tgz", - "integrity": "sha512-qGfDpL/3S17MQYXpR3HkBS5xNQ7wiFlqLdpr+iIQzv17aMRcSlgL4EjMIsYFZ540Dq17J+y5FVElA1AkVoXiUA==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.39.1.tgz", + "integrity": "sha512-FIjEB/s3TSQBYnYA64GPkXJrOR6w5J52SSnl6gSoq1tp+4r9zLjaAsf65AgDv5emA4ypm90gVWv1XX0/bfHA/A==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -2891,9 +2891,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz", - "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==", + "version": "9.24.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz", + "integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==", "dev": true, "license": "MIT", "engines": { @@ -4178,88 +4178,88 @@ "license": "MIT" }, "node_modules/@sentry-internal/browser-utils": { - "version": "9.10.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.10.1.tgz", - "integrity": "sha512-O/ibpHbKfpG+xtZuEzbLNtLcbanRcDYGxT+QbslVItmcS9GjMSwvMpp1jnD9Y7/LIFtv7O1gJZ9Hrz///lLprw==", + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.11.0.tgz", + "integrity": "sha512-XS71kRf7lw5St/Jc9G2Viy1cKgqGoPHqUAykXEtFt38JVXdf1TY/dSbKv/PAgNqMvC1xvdTsN0HF/81o7DNUEA==", "license": "MIT", "dependencies": { - "@sentry/core": "9.10.1" + "@sentry/core": "9.11.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/feedback": { - "version": "9.10.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.10.1.tgz", - "integrity": "sha512-DM32eAzRvXk36iGBWtlLZA88QzOFBODd+kbz55X4Py+1bDNdRc3Vl6214uuAr7iweHcOQy1rIvmAeO8Xusp7tQ==", + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.11.0.tgz", + "integrity": "sha512-50KiRmrF1Ldr+KoRawqcCYVk7TAVP8K/I81Jk9YWwlp1+Pu1ArpYDmTNCLXTgoyiyO38aHefKGZJX6AKFuSsUQ==", "license": "MIT", "dependencies": { - "@sentry/core": "9.10.1" + "@sentry/core": "9.11.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/replay": { - "version": "9.10.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.10.1.tgz", - "integrity": "sha512-nqG33NwojtteL8e3Qg/SOu0BsTJ9R7AjpmQIlOpFGL007nzKgcJHOngewd7FEHyB+F3iOI0MoI9iEWhRFEGRLw==", + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.11.0.tgz", + "integrity": "sha512-0k24h58O/2VQw1dwT/zQiWvUzLNQxpxbrVN/MYPT7czSEhI+1bX8fxMHXZORl2JqhetImMXzxH3XkuHQPEqQMg==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "9.10.1", - "@sentry/core": "9.10.1" + "@sentry-internal/browser-utils": "9.11.0", + "@sentry/core": "9.11.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "9.10.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.10.1.tgz", - "integrity": "sha512-fxrpqElqdsAQrzVly0V/XaljhAlwwMk+iGyf+wZeK6RwEPVxtoxXVfx7fEEtPn+gortqQR09N/zH179hefjuaw==", + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.11.0.tgz", + "integrity": "sha512-ZcRg8TWfF0ucjK2i+4TY/blRNJ7YKrgMpx19pFj6eCOJ1K8geSkAFPIfDHcQEwIU1ZTN+HiCwx0JvTI9YZxjfg==", "license": "MIT", "dependencies": { - "@sentry-internal/replay": "9.10.1", - "@sentry/core": "9.10.1" + "@sentry-internal/replay": "9.11.0", + "@sentry/core": "9.11.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/babel-plugin-component-annotate": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.2.4.tgz", - "integrity": "sha512-yBzRn3GEUSv1RPtE4xB4LnuH74ZxtdoRJ5cmQ9i6mzlmGDxlrnKuvem5++AolZTE9oJqAD3Tx2rd1PqmpWnLoA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.3.1.tgz", + "integrity": "sha512-5GOxGT7lZN+I8A7Vp0rWY+726FDKEw8HnFiebe51rQrMbfGfCu2Aw9uSM0nT9OG6xhV6WvGccIcCszTPs4fUZQ==", "license": "MIT", "engines": { "node": ">= 14" } }, "node_modules/@sentry/browser": { - "version": "9.10.1", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.10.1.tgz", - "integrity": "sha512-9RWjcyskhnDK2Q6LntFR90EqZD5+DXcXNqeTlE+mpVf65y7wz+9SIuVjAMP7qiDBwfxNbmTxiVCXeCuQnnATsQ==", + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.11.0.tgz", + "integrity": "sha512-DSDj8wQJoiLqqOcntl+7phjd8l8KN9A0vaV7mZNHWbrHU3MVwXqTyLyERRLC6wi0t7F5kqczqa3xLmKjK/fMZg==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "9.10.1", - "@sentry-internal/feedback": "9.10.1", - "@sentry-internal/replay": "9.10.1", - "@sentry-internal/replay-canvas": "9.10.1", - "@sentry/core": "9.10.1" + "@sentry-internal/browser-utils": "9.11.0", + "@sentry-internal/feedback": "9.11.0", + "@sentry-internal/replay": "9.11.0", + "@sentry-internal/replay-canvas": "9.11.0", + "@sentry/core": "9.11.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/bundler-plugin-core": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.2.4.tgz", - "integrity": "sha512-YMj9XW5W2JA89EeweE7CPKLDz245LBsI1JhCmqpt/bjSvmsSIAAPsLYnvIJBS3LQFm0OhtG8NB54PTi96dAcMA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.3.1.tgz", + "integrity": "sha512-Dd6xaWb293j9otEJ1yJqG2Ra6zB49OPzMNdIkdP8wdY+S9UFQE5PyKTyredmPY7hqCc005OrUQZolIIo9Zl13A==", "license": "MIT", "dependencies": { "@babel/core": "^7.18.5", - "@sentry/babel-plugin-component-annotate": "3.2.4", + "@sentry/babel-plugin-component-annotate": "3.3.1", "@sentry/cli": "2.42.2", "dotenv": "^16.3.1", "find-up": "^5.0.0", @@ -4619,22 +4619,22 @@ } }, "node_modules/@sentry/core": { - "version": "9.10.1", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.10.1.tgz", - "integrity": "sha512-TE2zZV3Od4131mZNgFo2Mv4aKU8FXxL0s96yqRvmV+8AU57mJoycMXBnmNSYfWuDICbPJTVAp+3bYMXwX7N5YA==", + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.11.0.tgz", + "integrity": "sha512-qfb4ahGZubbrNh1MnbEqyHFp87rIwQIZapyQLCaYpudXrP1biEpLOV3mMDvDJWCdX460hoOwQ3SkwipV3We/7w==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@sentry/react": { - "version": "9.10.1", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.10.1.tgz", - "integrity": "sha512-DYBs3F+F2elWEhWvp3HmBmORhAlTBbY0KsRj+Lt2mOSEfiz8WWrS3Ibe+9QmErVdjQZy68ic9Yt84MHL/rlmkQ==", + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.11.0.tgz", + "integrity": "sha512-sH/3KnDsLxBFRoxPyIpab7OewkfStdZQQwgpfv8R0yDKpGg4lU7KdTccryFvWL123UpHC7ydPWjdcfC8YV/EPQ==", "license": "MIT", "dependencies": { - "@sentry/browser": "9.10.1", - "@sentry/core": "9.10.1", + "@sentry/browser": "9.11.0", + "@sentry/core": "9.11.0", "hoist-non-react-statics": "^3.3.2" }, "engines": { @@ -4645,12 +4645,12 @@ } }, "node_modules/@sentry/vite-plugin": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-3.2.4.tgz", - "integrity": "sha512-ZRn5TLlq5xtwKOqaWP+XqS1PYVfbBCgsbMk7wW2Ly6EgF9wYePvtLqKgYnE3hwPg2LpBnRPR2ti1ohlUkR+wXA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-3.3.1.tgz", + "integrity": "sha512-eIIIHqVOTO0m7+3aTg//gVi11XNpKi4G0xA45hjz46UmRiToVfqgBH7Dsn1qRrDxa7YPYCdREQkyGEINlElT2A==", "license": "MIT", "dependencies": { - "@sentry/bundler-plugin-core": "3.2.4", + "@sentry/bundler-plugin-core": "3.3.1", "unplugin": "1.0.1" }, "engines": { @@ -4658,13 +4658,13 @@ } }, "node_modules/@sentry/webpack-plugin": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-3.2.4.tgz", - "integrity": "sha512-LCuNu5LXPSCq2BNke1zvEW8CXL4SPBsCjYexAx51PZ6Lp87VxWcCxGqXhr37MGpYwY10A1r31/XOe69iXHJjGA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-3.3.1.tgz", + "integrity": "sha512-AFRnGNUnlIvq3M+ADdfWb+DIXWKK6yYEkVPAyOppkjO+cL/19gjXMdvAwv+CMFts28YCFKF8Kr3pamUiCmwodA==", "dev": true, "license": "MIT", "dependencies": { - "@sentry/bundler-plugin-core": "3.2.4", + "@sentry/bundler-plugin-core": "3.3.1", "unplugin": "1.0.1", "uuid": "^9.0.0" }, @@ -4865,9 +4865,9 @@ } }, "node_modules/@testing-library/react": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.2.0.tgz", - "integrity": "sha512-2cSskAvA1QNtKc8Y9VJQRv0tm3hLVgxRGDB+KYhIaPQJ1I+RHbhIXcM+zClKXzMes/wshsMVzf4B9vS4IZpqDQ==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.0.tgz", + "integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==", "dev": true, "license": "MIT", "dependencies": { @@ -6770,9 +6770,9 @@ } }, "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6784,14 +6784,14 @@ } }, "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -8671,9 +8671,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", - "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, "license": "MIT", "dependencies": { @@ -8687,7 +8687,7 @@ "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.8", + "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", @@ -9403,18 +9403,18 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", - "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "get-proto": "^1.0.0", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", @@ -12486,15 +12486,16 @@ } }, "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "es-object-atoms": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -14374,9 +14375,9 @@ } }, "node_modules/react-virtuoso": { - "version": "4.12.6", - "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.12.6.tgz", - "integrity": "sha512-bfvS6aCL1ehXmq39KRiz/vxznGUbtA27I5I24TYCe1DhMf84O3aVNCIwrSjYQjkJGJGzY46ihdN8WkYlemuhMQ==", + "version": "4.12.5", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.12.5.tgz", + "integrity": "sha512-YeCbRRsC9CLf0buD0Rct7WsDbzf+yBU1wGbo05/XjbcN2nJuhgh040m3y3+6HVogTZxEqVm45ac9Fpae4/MxRQ==", "license": "MIT", "peerDependencies": { "react": ">=16 || >=17 || >= 18 || >= 19", @@ -14421,9 +14422,9 @@ } }, "node_modules/recharts": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.1.tgz", - "integrity": "sha512-v8PUTUlyiDe56qUj82w/EDVuzEFXwEHp9/xOowGAZwfLjB9uAy3GllQVIYMWF6nU+qibx85WF75zD7AjqoT54Q==", + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.2.tgz", + "integrity": "sha512-xv9lVztv3ingk7V3Jf05wfAZbM9Q2umJzu5t/cfnAK7LUslNrGT7LPBr74G+ok8kSCeFMaePmWMg0rcYOnczTw==", "license": "MIT", "dependencies": { "clsx": "^2.0.0", @@ -15070,9 +15071,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.86.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.1.tgz", - "integrity": "sha512-Yaok4XELL1L9Im/ZUClKu//D2OP1rOljKj0Gf34a+GzLbMveOzL7CfqYo+JUa5Xt1nhTCW+OcKp/FtR7/iqj1w==", + "version": "1.86.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.3.tgz", + "integrity": "sha512-iGtg8kus4GrsGLRDLRBRHY9dNVA78ZaS7xr01cWnS7PEMQyFtTqBiyCrfpTYTZXRWM94akzckYjh8oADfFNTzw==", "license": "MIT", "dependencies": { "chokidar": "^4.0.0", @@ -15945,9 +15946,9 @@ } }, "node_modules/styled-components": { - "version": "6.1.16", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.16.tgz", - "integrity": "sha512-KpWB6ORAWGmbWM10cDJfEV6sXc/uVkkkQV3SLwTNQ/E/PqWgNHIoMSLh1Lnk2FkB9+JHK7uuMq1i+9ArxDD7iQ==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.17.tgz", + "integrity": "sha512-97D7DwWanI7nN24v0D4SvbfjLE9656umNSJZkBkDIWL37aZqG/wRQ+Y9pWtXyBIM/NSfcBzHLErEsqHmJNSVUg==", "license": "MIT", "dependencies": { "@emotion/is-prop-valid": "1.2.2", @@ -17118,9 +17119,9 @@ } }, "node_modules/vite": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.4.tgz", - "integrity": "sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==", + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.5.tgz", + "integrity": "sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/client/package.json b/client/package.json index 391c90759..7795b1ff0 100644 --- a/client/package.json +++ b/client/package.json @@ -9,7 +9,7 @@ "proxy": "http://localhost:4000", "dependencies": { "@ant-design/pro-layout": "^7.22.4", - "@apollo/client": "^3.13.5", + "@apollo/client": "^3.13.6", "@emotion/is-prop-valid": "^1.3.1", "@fingerprintjs/fingerprintjs": "^4.6.1", "@firebase/analytics": "^0.10.12", @@ -20,8 +20,8 @@ "@jsreport/browser-client": "^3.1.0", "@reduxjs/toolkit": "^2.6.1", "@sentry/cli": "^2.43.0", - "@sentry/react": "^9.10.1", - "@sentry/vite-plugin": "^3.2.4", + "@sentry/react": "^9.11.0", + "@sentry/vite-plugin": "^3.3.1", "@splitsoftware/splitio-react": "^2.1.0", "@tanem/react-nprogress": "^5.0.53", "antd": "^5.24.6", @@ -57,7 +57,7 @@ "react-dom": "^18.3.1", "react-drag-listview": "^2.0.0", "react-grid-gallery": "^1.0.1", - "react-grid-layout": "1.3.4", + "react-grid-layout": "^1.3.4", "react-i18next": "^15.4.1", "react-icons": "^5.5.0", "react-image-lightbox": "^5.1.4", @@ -69,17 +69,17 @@ "react-resizable": "^3.0.5", "react-router-dom": "^6.30.0", "react-sticky": "^6.0.3", - "react-virtuoso": "^4.12.6", - "recharts": "^2.15.0", + "react-virtuoso": "^4.12.5", + "recharts": "^2.15.2", "redux": "^5.0.1", "redux-actions": "^3.0.3", "redux-persist": "^6.0.0", "redux-saga": "^1.3.0", "redux-state-sync": "^3.1.4", "reselect": "^5.1.1", - "sass": "^1.86.1", + "sass": "^1.86.3", "socket.io-client": "^4.8.1", - "styled-components": "^6.1.16", + "styled-components": "^6.1.17", "subscriptions-transport-ws": "^0.11.0", "use-memo-one": "^1.1.3", "vite-plugin-ejs": "^1.7.0", @@ -130,22 +130,22 @@ "@ant-design/icons": "^6.0.0", "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/preset-react": "^7.26.3", - "@dotenvx/dotenvx": "^1.39.0", + "@dotenvx/dotenvx": "^1.39.1", "@emotion/babel-plugin": "^11.13.5", "@emotion/react": "^11.14.0", - "@eslint/js": "^9.23.0", + "@eslint/js": "^9.24.0", "@playwright/test": "^1.51.1", - "@sentry/webpack-plugin": "^3.2.4", + "@sentry/webpack-plugin": "^3.3.1", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.2.0", + "@testing-library/react": "^16.3.0", "@vitejs/plugin-react": "^4.3.4", "browserslist": "^4.24.4", "browserslist-to-esbuild": "^2.1.1", "chalk": "^5.4.1", "eslint": "^8.57.1", "eslint-config-react-app": "^7.0.1", - "eslint-plugin-react": "^7.37.4", + "eslint-plugin-react": "^7.37.5", "globals": "^15.15.0", "jsdom": "^26.0.0", "memfs": "^4.17.0", @@ -154,7 +154,7 @@ "react-error-overlay": "^6.1.0", "redux-logger": "^3.0.6", "source-map-explorer": "^2.5.3", - "vite": "^6.2.4", + "vite": "^6.2.5", "vite-plugin-babel": "^1.3.0", "vite-plugin-eslint": "^1.8.1", "vite-plugin-node-polyfills": "^0.23.0", diff --git a/package-lock.json b/package-lock.json index 09da429eb..b80b3ff4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,14 +9,14 @@ "version": "0.2.0", "license": "UNLICENSED", "dependencies": { - "@aws-sdk/client-cloudwatch-logs": "^3.777.0", - "@aws-sdk/client-elasticache": "^3.777.0", - "@aws-sdk/client-s3": "^3.779.0", - "@aws-sdk/client-secrets-manager": "^3.777.0", - "@aws-sdk/client-ses": "^3.777.0", - "@aws-sdk/credential-provider-node": "^3.777.0", - "@aws-sdk/lib-storage": "^3.779.0", - "@aws-sdk/s3-request-presigner": "^3.779.0", + "@aws-sdk/client-cloudwatch-logs": "^3.782.0", + "@aws-sdk/client-elasticache": "^3.782.0", + "@aws-sdk/client-s3": "^3.782.0", + "@aws-sdk/client-secrets-manager": "^3.782.0", + "@aws-sdk/client-ses": "^3.782.0", + "@aws-sdk/credential-provider-node": "^3.782.0", + "@aws-sdk/lib-storage": "^3.782.0", + "@aws-sdk/s3-request-presigner": "^3.782.0", "@opensearch-project/opensearch": "^2.13.0", "@socket.io/admin-ui": "^0.5.1", "@socket.io/redis-adapter": "^8.3.0", @@ -26,7 +26,7 @@ "bee-queue": "^1.7.1", "better-queue": "^3.8.12", "bluebird": "^3.7.2", - "bullmq": "^5.45.2", + "bullmq": "^5.47.2", "chart.js": "^4.4.8", "cloudinary": "^2.6.0", "compression": "^1.8.0", @@ -62,7 +62,7 @@ "socket.io": "^4.8.1", "socket.io-adapter": "^2.5.5", "ssh2-sftp-client": "^11.0.0", - "twilio": "^5.5.1", + "twilio": "^5.5.2", "uuid": "^11.1.0", "winston": "^3.17.0", "winston-cloudwatch": "^6.3.0", @@ -70,10 +70,10 @@ "xmlbuilder2": "^3.1.1" }, "devDependencies": { - "@eslint/js": "^9.23.0", + "@eslint/js": "^9.24.0", "@trivago/prettier-plugin-sort-imports": "^5.2.2", - "eslint": "^9.23.0", - "eslint-plugin-react": "^7.37.4", + "eslint": "^9.24.0", + "eslint-plugin-react": "^7.37.5", "globals": "^15.15.0", "mock-require": "^3.0.3", "p-limit": "^3.1.0", @@ -290,24 +290,24 @@ } }, "node_modules/@aws-sdk/client-cloudwatch-logs": { - "version": "3.777.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.777.0.tgz", - "integrity": "sha512-ebrO1ZlgSKEYERegcKnyjC0VkvLnxDm2HES78N54MiMQCfFCUJ3W6xx2aoKVSVWaUrGUaY13Cd67h/X0RhuU6g==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.782.0.tgz", + "integrity": "sha512-hUyMYWebb1HRCSK9jynWRQfNJoRhPaScvbePTPkNJybrVAo+7q2D5/nFP6burroRSWfYEaJXRNgr1besLjZZBA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", - "@aws-sdk/credential-provider-node": "3.777.0", + "@aws-sdk/credential-provider-node": "3.782.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", - "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", - "@aws-sdk/util-user-agent-node": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/eventstream-serde-browser": "^4.0.2", @@ -358,24 +358,24 @@ } }, "node_modules/@aws-sdk/client-elasticache": { - "version": "3.777.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-elasticache/-/client-elasticache-3.777.0.tgz", - "integrity": "sha512-6MzXEyUwVIxJqNQh4rvSE32OweJtG9PYdp3UxXfoiuslJnuHgPxWMRpvJIkF/hLeAjfQf4cPii5pBYrfHDbz+g==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-elasticache/-/client-elasticache-3.782.0.tgz", + "integrity": "sha512-brN4paoCUMtGrt4rm23B0/9V6jdKzlc/630u8AJtTeeKCHLMQhzl4O1TJKh0jPvEs2xXt4uNLquKpIxKPQcMVQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", - "@aws-sdk/credential-provider-node": "3.777.0", + "@aws-sdk/credential-provider-node": "3.782.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", - "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", - "@aws-sdk/util-user-agent-node": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", @@ -409,16 +409,16 @@ } }, "node_modules/@aws-sdk/client-s3": { - "version": "3.779.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.779.0.tgz", - "integrity": "sha512-Lagz+ersQaLNYkpOU9V12PYspT//lGvhPXlKU3OXDj3whDchdqUdtRKY8rmV+jli4KXe+udx/hj2yqrFRfKGvQ==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.782.0.tgz", + "integrity": "sha512-V6JR2JAGYQY7J8wk5un5n/ja2nfCUyyoRCF8Du8JL91NGI8i41Mdr/TzuOGwTgFl6RSXb/ge1K1jk30OH4MugQ==", "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.775.0", - "@aws-sdk/credential-provider-node": "3.777.0", + "@aws-sdk/credential-provider-node": "3.782.0", "@aws-sdk/middleware-bucket-endpoint": "3.775.0", "@aws-sdk/middleware-expect-continue": "3.775.0", "@aws-sdk/middleware-flexible-checksums": "3.775.0", @@ -428,13 +428,13 @@ "@aws-sdk/middleware-recursion-detection": "3.775.0", "@aws-sdk/middleware-sdk-s3": "3.775.0", "@aws-sdk/middleware-ssec": "3.775.0", - "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/signature-v4-multi-region": "3.775.0", "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", - "@aws-sdk/util-user-agent-node": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.782.0", "@aws-sdk/xml-builder": "3.775.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", @@ -476,24 +476,24 @@ } }, "node_modules/@aws-sdk/client-secrets-manager": { - "version": "3.777.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.777.0.tgz", - "integrity": "sha512-HqBGQPFUZMTOkQJB6JLv7Jopfz+cBP4spzjpBlZ/JeJShMAXw9To2mxi22jU5qGGWPGH5y4tVXnw4aVf2TOPhQ==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.782.0.tgz", + "integrity": "sha512-j2n8717Q7HeQgyXjdiUwuE0Pk80nOaDacWvEmmMr2w+DYXLvdXrOThbyy3jItt5XQw8mhaC8KZ4RfK6dqUlwGA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", - "@aws-sdk/credential-provider-node": "3.777.0", + "@aws-sdk/credential-provider-node": "3.782.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", - "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", - "@aws-sdk/util-user-agent-node": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", @@ -541,24 +541,24 @@ } }, "node_modules/@aws-sdk/client-ses": { - "version": "3.777.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.777.0.tgz", - "integrity": "sha512-COZ6Yb5qt/JLmWtJG1rGXhvTFnaWHt0X8r9j0uGFuSRhLcguItxYlOnIskYePz/NJ0u/OXYbad0uG1M4V5IJ/w==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.782.0.tgz", + "integrity": "sha512-ZfnbiRwW9CnmwIgKChPVT06PB0GOjVoUXu2SZHW/PZbgFuLokkqAbRScEVnwtBLF6NR1k5Msg74HH4HRimRDtA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", - "@aws-sdk/credential-provider-node": "3.777.0", + "@aws-sdk/credential-provider-node": "3.782.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", - "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", - "@aws-sdk/util-user-agent-node": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", @@ -592,9 +592,9 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.777.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.777.0.tgz", - "integrity": "sha512-0+z6CiAYIQa7s6FJ+dpBYPi9zr9yY5jBg/4/FGcwYbmqWPXwL9Thdtr0FearYRZgKl7bhL3m3dILCCfWqr3teQ==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.782.0.tgz", + "integrity": "sha512-5GlJBejo8wqMpSSEKb45WE82YxI2k73YuebjLH/eWDNQeE6VI5Bh9lA1YQ7xNkLLH8hIsb0pSfKVuwh0VEzVrg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", @@ -603,12 +603,12 @@ "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", - "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", - "@aws-sdk/util-user-agent-node": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", @@ -700,18 +700,18 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.777.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.777.0.tgz", - "integrity": "sha512-1X9mCuM9JSQPmQ+D2TODt4THy6aJWCNiURkmKmTIPRdno7EIKgAqrr/LLN++K5mBf54DZVKpqcJutXU2jwo01A==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.782.0.tgz", + "integrity": "sha512-wd4KdRy2YjLsE4Y7pz00470Iip06GlRHkG4dyLW7/hFMzEO2o7ixswCWp6J2VGZVAX64acknlv2Q0z02ebjmhw==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/core": "3.775.0", "@aws-sdk/credential-provider-env": "3.775.0", "@aws-sdk/credential-provider-http": "3.775.0", "@aws-sdk/credential-provider-process": "3.775.0", - "@aws-sdk/credential-provider-sso": "3.777.0", - "@aws-sdk/credential-provider-web-identity": "3.777.0", - "@aws-sdk/nested-clients": "3.777.0", + "@aws-sdk/credential-provider-sso": "3.782.0", + "@aws-sdk/credential-provider-web-identity": "3.782.0", + "@aws-sdk/nested-clients": "3.782.0", "@aws-sdk/types": "3.775.0", "@smithy/credential-provider-imds": "^4.0.2", "@smithy/property-provider": "^4.0.2", @@ -724,17 +724,17 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.777.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.777.0.tgz", - "integrity": "sha512-ZD66ywx1Q0KyUSuBXZIQzBe3Q7MzX8lNwsrCU43H3Fww+Y+HB3Ncws9grhSdNhKQNeGmZ+MgKybuZYaaeLwJEQ==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.782.0.tgz", + "integrity": "sha512-HZiAF+TCEyKjju9dgysjiPIWgt/+VerGaeEp18mvKLNfgKz1d+/82A2USEpNKTze7v3cMFASx3CvL8yYyF7mJw==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/credential-provider-env": "3.775.0", "@aws-sdk/credential-provider-http": "3.775.0", - "@aws-sdk/credential-provider-ini": "3.777.0", + "@aws-sdk/credential-provider-ini": "3.782.0", "@aws-sdk/credential-provider-process": "3.775.0", - "@aws-sdk/credential-provider-sso": "3.777.0", - "@aws-sdk/credential-provider-web-identity": "3.777.0", + "@aws-sdk/credential-provider-sso": "3.782.0", + "@aws-sdk/credential-provider-web-identity": "3.782.0", "@aws-sdk/types": "3.775.0", "@smithy/credential-provider-imds": "^4.0.2", "@smithy/property-provider": "^4.0.2", @@ -764,14 +764,14 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.777.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.777.0.tgz", - "integrity": "sha512-9mPz7vk9uE4PBVprfINv4tlTkyq1OonNevx2DiXC1LY4mCUCNN3RdBwAY0BTLzj0uyc3k5KxFFNbn3/8ZDQP7w==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.782.0.tgz", + "integrity": "sha512-1y1ucxTtTIGDSNSNxriQY8msinilhe9gGvQpUDYW9gboyC7WQJPDw66imy258V6osdtdi+xoHzVCbCz3WhosMQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.777.0", + "@aws-sdk/client-sso": "3.782.0", "@aws-sdk/core": "3.775.0", - "@aws-sdk/token-providers": "3.777.0", + "@aws-sdk/token-providers": "3.782.0", "@aws-sdk/types": "3.775.0", "@smithy/property-provider": "^4.0.2", "@smithy/shared-ini-file-loader": "^4.0.2", @@ -783,13 +783,13 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.777.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.777.0.tgz", - "integrity": "sha512-uGCqr47fnthkqwq5luNl2dksgcpHHjSXz2jUra7TXtFOpqvnhOW8qXjoa1ivlkq8qhqlaZwCzPdbcN0lXpmLzQ==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.782.0.tgz", + "integrity": "sha512-xCna0opVPaueEbJoclj5C6OpDNi0Gynj+4d7tnuXGgQhTHPyAz8ZyClkVqpi5qvHTgxROdUEDxWqEO5jqRHZHQ==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/core": "3.775.0", - "@aws-sdk/nested-clients": "3.777.0", + "@aws-sdk/nested-clients": "3.782.0", "@aws-sdk/types": "3.775.0", "@smithy/property-provider": "^4.0.2", "@smithy/types": "^4.2.0", @@ -800,9 +800,9 @@ } }, "node_modules/@aws-sdk/lib-storage": { - "version": "3.779.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.779.0.tgz", - "integrity": "sha512-AZfykrCgfnhlb5d5uyThHsqIwt41PYgnUTMyDuk4hbuKbiY8pfOiPdg8BYsC59iD2T4Iw9NujYhWUD+l8zNKcw==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.782.0.tgz", + "integrity": "sha512-UQYnIzpBReLko2XhDgG/rWpoHTWv4/zqUNl4XJXZRo9akLzrxGKtPrp5nJ4OLUkH3tIm1cvmI3XlSjHUW/OxWw==", "license": "Apache-2.0", "dependencies": { "@smithy/abort-controller": "^4.0.2", @@ -817,7 +817,7 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@aws-sdk/client-s3": "^3.779.0" + "@aws-sdk/client-s3": "^3.782.0" } }, "node_modules/@aws-sdk/lib-storage/node_modules/buffer": { @@ -985,14 +985,14 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.775.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.775.0.tgz", - "integrity": "sha512-7Lffpr1ptOEDE1ZYH1T78pheEY1YmeXWBfFt/amZ6AGsKSLG+JPXvof3ltporTGR2bhH/eJPo7UHCglIuXfzYg==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.782.0.tgz", + "integrity": "sha512-i32H2R6IItX+bQ2p4+v2gGO2jA80jQoJO2m1xjU9rYWQW3+ErWy4I5YIuQHTBfb6hSdAHbaRfqPDgbv9J2rjEg==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/core": "3.775.0", "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-endpoints": "3.782.0", "@smithy/core": "^3.2.0", "@smithy/protocol-http": "^5.1.0", "@smithy/types": "^4.2.0", @@ -1003,9 +1003,9 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.777.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.777.0.tgz", - "integrity": "sha512-bmmVRsCjuYlStYPt06hr+f8iEyWg7+AklKCA8ZLDEJujXhXIowgUIqXmqpTkXwkVvDQ9tzU7hxaONjyaQCGybA==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.782.0.tgz", + "integrity": "sha512-QOYC8q7luzHFXrP0xYAqBctoPkynjfV0r9dqntFu4/IWMTyC1vlo1UTxFAjIPyclYw92XJyEkVCVg9v/nQnsUA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", @@ -1014,12 +1014,12 @@ "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", - "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.775.0", + "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", - "@aws-sdk/util-user-agent-node": "3.775.0", + "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", @@ -1069,9 +1069,9 @@ } }, "node_modules/@aws-sdk/s3-request-presigner": { - "version": "3.779.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.779.0.tgz", - "integrity": "sha512-L3mGSh6/9gf3FBVrQziCkuLbaRJMeNbLr6tg9ZSymJcDRzRqAiCWnHrenAavTnAAnm+Lu62Fg/A4g3T+YT+gEg==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.782.0.tgz", + "integrity": "sha512-Er8hdjc9zkxTh15MjdnMYggtUrGknDiuD1FwdW035kn/kwWop587G9rnRa1crhmyKRjLMn0Ki3fsyFUm/943XA==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/signature-v4-multi-region": "3.775.0", @@ -1105,12 +1105,12 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.777.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.777.0.tgz", - "integrity": "sha512-Yc2cDONsHOa4dTSGOev6Ng2QgTKQUEjaUnsyKd13pc/nLLz/WLqHiQ/o7PcnKERJxXGs1g1C6l3sNXiX+kbnFQ==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.782.0.tgz", + "integrity": "sha512-4tPuk/3+THPrzKaXW4jE2R67UyGwHLFizZ47pcjJWbhb78IIJAy94vbeqEQ+veS84KF5TXcU7g5jGTXC0D70Wg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/nested-clients": "3.777.0", + "@aws-sdk/nested-clients": "3.782.0", "@aws-sdk/types": "3.775.0", "@smithy/property-provider": "^4.0.2", "@smithy/shared-ini-file-loader": "^4.0.2", @@ -1147,9 +1147,9 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.775.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.775.0.tgz", - "integrity": "sha512-yjWmUgZC9tUxAo8Uaplqmq0eUh0zrbZJdwxGRKdYxfm4RG6fMw1tj52+KkatH7o+mNZvg1GDcVp/INktxonJLw==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.782.0.tgz", + "integrity": "sha512-/RJOAO7o7HI6lEa4ASbFFLHGU9iPK876BhsVfnl54MvApPVYWQ9sHO0anOUim2S5lQTwd/6ghuH3rFYSq/+rdw==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.775.0", @@ -1201,12 +1201,12 @@ } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.775.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.775.0.tgz", - "integrity": "sha512-N9yhTevbizTOMo3drH7Eoy6OkJ3iVPxhV7dwb6CMAObbLneS36CSfA6xQXupmHWcRvZPTz8rd1JGG3HzFOau+g==", + "version": "3.782.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.782.0.tgz", + "integrity": "sha512-dMFkUBgh2Bxuw8fYZQoH/u3H4afQ12VSkzEi//qFiDTwbKYq+u+RYjc8GLDM6JSK1BShMu5AVR7HD4ap1TYUnA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.775.0", + "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/types": "3.775.0", "@smithy/node-config-provider": "^4.0.2", "@smithy/types": "^4.2.0", @@ -1953,9 +1953,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", - "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", + "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2028,9 +2028,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz", - "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==", + "version": "9.24.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz", + "integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==", "dev": true, "license": "MIT", "engines": { @@ -5139,9 +5139,9 @@ } }, "node_modules/bullmq": { - "version": "5.45.2", - "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.45.2.tgz", - "integrity": "sha512-wHZfcD4z4aLolxREmwNNDSbfh7USeq2e3yu5W2VGkzHMUcrH0fzZuRuCMsjD0XKS9ViK1U854oM9yWR6ftPeDA==", + "version": "5.47.2", + "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.47.2.tgz", + "integrity": "sha512-JMI2uEV3YjohGTcy4Cqt/4LHEXcBA2BVS7x4XS7sv4qa5oLdsZh9p5fkwSWg6f8lqtcHbm3ceXkTFR0JC9gayw==", "license": "MIT", "dependencies": { "cron-parser": "^4.9.0", @@ -5215,9 +5215,9 @@ } }, "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -5228,13 +5228,13 @@ } }, "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -6626,9 +6626,9 @@ "license": "MIT" }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -6762,19 +6762,19 @@ } }, "node_modules/eslint": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz", - "integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==", + "version": "9.24.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz", + "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.2", + "@eslint/config-array": "^0.20.0", "@eslint/config-helpers": "^0.2.0", "@eslint/core": "^0.12.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.23.0", + "@eslint/js": "9.24.0", "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -6823,9 +6823,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", - "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, "license": "MIT", "dependencies": { @@ -6839,7 +6839,7 @@ "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.8", + "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", @@ -7653,17 +7653,17 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", - "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "get-proto": "^1.0.0", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", @@ -9919,15 +9919,16 @@ } }, "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "es-object-atoms": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -12315,9 +12316,9 @@ "license": "Unlicense" }, "node_modules/twilio": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/twilio/-/twilio-5.5.1.tgz", - "integrity": "sha512-b1gLd2eMsCSCHRerp3GQUedVlz0nCTt5FbyPxDPmMvk5cm6eIPk4ZTp5JNpgucARZgpCB2uUACJbdcidEHAUBA==", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/twilio/-/twilio-5.5.2.tgz", + "integrity": "sha512-yrRh6immcL5xEVX7VmHsl3vU01x/fmqxf38kvxMrrtvEtAkYARYOPor9lt5T7964zC7l31k5sTrnLJmd2jjeOA==", "license": "MIT", "dependencies": { "axios": "^1.7.8", diff --git a/package.json b/package.json index 0a95a146e..f7f07bdc1 100644 --- a/package.json +++ b/package.json @@ -15,14 +15,14 @@ "test:watch": "vitest" }, "dependencies": { - "@aws-sdk/client-cloudwatch-logs": "^3.777.0", - "@aws-sdk/client-elasticache": "^3.777.0", - "@aws-sdk/client-s3": "^3.779.0", - "@aws-sdk/client-secrets-manager": "^3.777.0", - "@aws-sdk/client-ses": "^3.777.0", - "@aws-sdk/credential-provider-node": "^3.777.0", - "@aws-sdk/lib-storage": "^3.779.0", - "@aws-sdk/s3-request-presigner": "^3.779.0", + "@aws-sdk/client-cloudwatch-logs": "^3.782.0", + "@aws-sdk/client-elasticache": "^3.782.0", + "@aws-sdk/client-s3": "^3.782.0", + "@aws-sdk/client-secrets-manager": "^3.782.0", + "@aws-sdk/client-ses": "^3.782.0", + "@aws-sdk/credential-provider-node": "^3.782.0", + "@aws-sdk/lib-storage": "^3.782.0", + "@aws-sdk/s3-request-presigner": "^3.782.0", "@opensearch-project/opensearch": "^2.13.0", "@socket.io/admin-ui": "^0.5.1", "@socket.io/redis-adapter": "^8.3.0", @@ -32,7 +32,7 @@ "bee-queue": "^1.7.1", "better-queue": "^3.8.12", "bluebird": "^3.7.2", - "bullmq": "^5.45.2", + "bullmq": "^5.47.2", "chart.js": "^4.4.8", "cloudinary": "^2.6.0", "compression": "^1.8.0", @@ -68,7 +68,7 @@ "socket.io": "^4.8.1", "socket.io-adapter": "^2.5.5", "ssh2-sftp-client": "^11.0.0", - "twilio": "^5.5.1", + "twilio": "^5.5.2", "uuid": "^11.1.0", "winston": "^3.17.0", "winston-cloudwatch": "^6.3.0", @@ -76,10 +76,10 @@ "xmlbuilder2": "^3.1.1" }, "devDependencies": { - "@eslint/js": "^9.23.0", + "@eslint/js": "^9.24.0", "@trivago/prettier-plugin-sort-imports": "^5.2.2", - "eslint": "^9.23.0", - "eslint-plugin-react": "^7.37.4", + "eslint": "^9.24.0", + "eslint-plugin-react": "^7.37.5", "globals": "^15.15.0", "mock-require": "^3.0.3", "p-limit": "^3.1.0", From 6d33622b4e5b22fe1d9a0cc3ef85b5a9308d812f Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 7 Apr 2025 13:01:23 -0400 Subject: [PATCH 20/34] release/2025-04-11 - Add Ivana to Usage Report --- server/data/usageReport.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server/data/usageReport.js b/server/data/usageReport.js index 66fec2fca..af1d6ec75 100644 --- a/server/data/usageReport.js +++ b/server/data/usageReport.js @@ -55,7 +55,12 @@ exports.default = async (req, res) => { const csv = converter.json2csv(shopList, { emptyFieldValue: "" }); emailer .sendTaskEmail({ - to: ["patrick.fic@convenient-brands.com", "bradley.rhoades@convenient-brands.com", "jrome@rometech.com"], + to: [ + "patrick.fic@convenient-brands.com", + "bradley.rhoades@convenient-brands.com", + "jrome@rometech.com", + "ivana@imexsystems.ca" + ], subject: `RO Usage Report - ${moment().format("MM/DD/YYYY")}`, text: ` Usage Report for ${moment().format("MM/DD/YYYY")} for Rome Online Customers. From 5f6648841018b810468e091a00705ca69836669f Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 7 Apr 2025 13:06:47 -0400 Subject: [PATCH 21/34] release/2025-04-11 - Remove unused constant from server.js --- server.js | 1 - 1 file changed, 1 deletion(-) diff --git a/server.js b/server.js index 117c38145..341e4ae60 100644 --- a/server.js +++ b/server.js @@ -16,7 +16,6 @@ const cors = require("cors"); const http = require("http"); const Redis = require("ioredis"); const express = require("express"); -const bodyParser = require("body-parser"); const compression = require("compression"); const cookieParser = require("cookie-parser"); const { Server } = require("socket.io"); From 3691d32aaa4fccaf098d5ff0092731d0da212f0e Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Mon, 7 Apr 2025 17:36:39 -0700 Subject: [PATCH 22/34] IO-3202 HasFeatureAccess Boolean Signed-off-by: Allan Carr --- .../feature-wrapper/feature-wrapper.component.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/src/components/feature-wrapper/feature-wrapper.component.jsx b/client/src/components/feature-wrapper/feature-wrapper.component.jsx index afd0eb604..6576d2f30 100644 --- a/client/src/components/feature-wrapper/feature-wrapper.component.jsx +++ b/client/src/components/feature-wrapper/feature-wrapper.component.jsx @@ -78,7 +78,11 @@ export function HasFeatureAccess({ featureName, bodyshop, bypass, debug = false } return true; } - return bodyshop?.features?.allAccess || dayjs(bodyshop?.features[featureName]).isAfter(dayjs()); + return ( + bodyshop?.features?.allAccess || + bodyshop?.features[featureName] || + dayjs(bodyshop?.features[featureName]).isAfter(dayjs()) + ); } export default connect(mapStateToProps, null)(FeatureWrapper); From a18ce18d7245ba07d2013a31c879cf7e6db9f531 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 8 Apr 2025 11:42:27 -0400 Subject: [PATCH 23/34] feature/IO-2769-Job-Totals-Testing --- .../jobs-detail-header-actions.component.jsx | 63 ++++++--- client/src/translations/en_us/common.json | 9 +- client/src/translations/es/common.json | 9 +- client/src/translations/fr/common.json | 10 +- docker-compose.yml | 1 + download-job-totals-fixtures.js | 77 ++++++++++ package.json | 3 +- server/job/job-totals-USA.js | 13 +- server/job/job-totals-recorder.js | 133 ++++++++++++++++++ server/job/job-totals.js | 11 +- server/job/utils/seralizeHelper.js | 17 ++- server/routes/jobRoutes.js | 2 + 12 files changed, 295 insertions(+), 53 deletions(-) create mode 100644 download-job-totals-fixtures.js create mode 100644 server/job/job-totals-recorder.js diff --git a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx index 9488c60e1..860bb7e98 100644 --- a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx +++ b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx @@ -133,6 +133,16 @@ export function JobsDetailHeaderActions({ const { socket } = useSocket(); const notification = useNotification(); + const isDevEnv = import.meta.env.DEV; + const isProdEnv = import.meta.env.PROD; + const userEmail = currentUser?.email || ""; + + const devEmails = ["imex.dev", "rome.dev"]; + const prodEmails = ["imex.prod", "rome.prod", "imex.test", "rome.test"]; + + const hasValidEmail = (emails) => emails.some((email) => userEmail.endsWith(email)); + const canSubmitForTesting = (isDevEnv && hasValidEmail(devEmails)) || (isProdEnv && hasValidEmail(prodEmails)); + const { treatments: { ImEXPay } } = useSplitTreatments({ @@ -171,7 +181,7 @@ export function JobsDetailHeaderActions({ { defaultOpenStatus: bodyshop.md_ro_statuses.default_imported }, (newJobId) => { history(`/manage/jobs/${newJobId}`); - notification["success"]({ + notification.success({ message: t("jobs.successes.duplicated") }); }, @@ -181,7 +191,7 @@ export function JobsDetailHeaderActions({ const handleDuplicateConfirm = () => DuplicateJob(client, job.id, { defaultOpenStatus: bodyshop.md_ro_statuses.default_imported }, (newJobId) => { history(`/manage/jobs/${newJobId}`); - notification["success"]({ + notification.success({ message: t("jobs.successes.duplicated") }); }); @@ -217,13 +227,13 @@ export function JobsDetailHeaderActions({ const result = await deleteJob({ variables: { id: job.id } }); if (!result.errors) { - notification["success"]({ + notification.success({ message: t("jobs.successes.delete") }); //go back to jobs list. history(`/manage/`); } else { - notification["error"]({ + notification.error({ message: t("jobs.errors.deleted", { error: JSON.stringify(result.errors) }) @@ -275,9 +285,9 @@ export function JobsDetailHeaderActions({ }); if (!result.errors) { - notification["success"]({ message: t("csi.successes.created") }); + notification.success({ message: t("csi.successes.created") }); } else { - notification["error"]({ + notification.error({ message: t("csi.errors.creating", { message: JSON.stringify(result.errors) }) @@ -316,7 +326,7 @@ export function JobsDetailHeaderActions({ `${window.location.protocol}//${window.location.host}/csi/${result.data.insert_csi.returning[0].id}` ); } else { - notification["error"]({ + notification.error({ message: t("messaging.error.invalidphone") }); } @@ -328,7 +338,7 @@ export function JobsDetailHeaderActions({ ); } } else { - notification["error"]({ + notification.error({ message: t("csi.errors.notconfigured") }); } @@ -358,7 +368,7 @@ export function JobsDetailHeaderActions({ }); setMessage(`${window.location.protocol}//${window.location.host}/csi/${job.csiinvites[0].id}`); } else { - notification["error"]({ + notification.error({ message: t("messaging.error.invalidphone") }); } @@ -398,7 +408,7 @@ export function JobsDetailHeaderActions({ }); if (!result.errors) { - notification["success"]({ + notification.success({ message: t("jobs.successes.voided") }); insertAuditTrail({ @@ -409,7 +419,7 @@ export function JobsDetailHeaderActions({ //go back to jobs list. history(`/manage/`); } else { - notification["error"]({ + notification.error({ message: t("jobs.errors.voiding", { error: JSON.stringify(result.errors) }) @@ -442,7 +452,7 @@ export function JobsDetailHeaderActions({ console.log("handle -> XML", QbXmlResponse); } catch (error) { console.log("Error getting QBXML from Server.", error); - notification["error"]({ + notification.error({ message: t("jobs.errors.exporting", { error: "Unable to retrieve QBXML. " + JSON.stringify(error.message) }) @@ -460,7 +470,7 @@ export function JobsDetailHeaderActions({ }); } catch (error) { console.log("Error connecting to quickbooks or partner.", error); - notification["error"]({ + notification.error({ message: t("jobs.errors.exporting-partner") }); @@ -556,7 +566,7 @@ export function JobsDetailHeaderActions({ } }); if (!jobUpdate.errors) { - notification["success"]({ + notification.success({ message: t("appointments.successes.canceled") }); insertAuditTrail({ @@ -931,11 +941,11 @@ export function JobsDetailHeaderActions({ }); if (!result.errors) { - notification["success"]({ + notification.success({ message: t("jobs.successes.partsqueue") }); } else { - notification["error"]({ + notification.error({ message: t("jobs.errors.saving", { error: JSON.stringify(result.errors) }) @@ -1111,6 +1121,27 @@ export function JobsDetailHeaderActions({ }); } + if (canSubmitForTesting) { + menuItems.push({ + key: "submitfortesting", + id: "job-actions-submitfortesting", + label: t("menus.jobsactions.submit-for-testing"), + onClick: async () => { + try { + await axios.post("/job/totals-recorder", { id: job.id }); + notification.success({ + message: t("general.messages.submit-for-testing") + }); + } catch (err) { + console.error(`Error submitting job for testing: ${err?.message}`); + notification.error({ + message: t("genera.errors.submit-for-testing-error") + }); + } + } + }); + } + const menu = { items: menuItems, key: "popovermenu" diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index b2ca3146e..9e161fb7b 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -1220,7 +1220,8 @@ "errors": { "fcm": "You must allow notification permissions to have real time messaging. Click to try again.", "notfound": "No record was found.", - "sizelimit": "The selected items exceed the size limit." + "sizelimit": "The selected items exceed the size limit.", + "submit-for-testing": "Error submitting Job for testing." }, "itemtypes": { "contract": "CC Contract", @@ -1322,7 +1323,8 @@ "partnernotrunning": "{{app}} has detected that the partner is not running. Please ensure it is running to enable full functionality.", "rbacunauth": "You are not authorized to view this content. Please reach out to your shop manager to change your access level.", "unsavedchanges": "You have unsaved changes.", - "unsavedchangespopup": "You have unsaved changes. Are you sure you want to leave?" + "unsavedchangespopup": "You have unsaved changes. Are you sure you want to leave?", + "submit-for-testing": "Submitted Job for testing successfully." }, "validation": { "dateRangeExceeded": "The date range has been exceeded.", @@ -2314,7 +2316,8 @@ "duplicate": "Duplicate this Job", "duplicatenolines": "Duplicate this Job without Repair Data", "newcccontract": "Create Courtesy Car Contract", - "void": "Void Job" + "void": "Void Job", + "submit-for-testing": "Submit for Testing" }, "jobsdetail": { "claimdetail": "Claim Details", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index b32bbaacc..53e0c10ca 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -1220,7 +1220,8 @@ "errors": { "fcm": "", "notfound": "", - "sizelimit": "" + "sizelimit": "", + "submit-for-testing": "" }, "itemtypes": { "contract": "", @@ -1322,7 +1323,8 @@ "partnernotrunning": "", "rbacunauth": "", "unsavedchanges": "Usted tiene cambios no guardados.", - "unsavedchangespopup": "" + "unsavedchangespopup": "", + "submit-for-testing": "" }, "validation": { "dateRangeExceeded": "", @@ -2314,7 +2316,8 @@ "duplicate": "", "duplicatenolines": "", "newcccontract": "", - "void": "" + "void": "", + "submit-for-testing": "" }, "jobsdetail": { "claimdetail": "Detalles de la reclamación", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index e054c842c..8ae310fb4 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -1220,7 +1220,8 @@ "errors": { "fcm": "", "notfound": "", - "sizelimit": "" + "sizelimit": "", + "submit-for-testing": "" }, "itemtypes": { "contract": "", @@ -1322,7 +1323,9 @@ "partnernotrunning": "", "rbacunauth": "", "unsavedchanges": "Vous avez des changements non enregistrés.", - "unsavedchangespopup": "" + "unsavedchangespopup": "", + "submit-for-testing": "" + }, "validation": { "dateRangeExceeded": "", @@ -2314,7 +2317,8 @@ "duplicate": "", "duplicatenolines": "", "newcccontract": "", - "void": "" + "void": "", + "submit-for-testing": "" }, "jobsdetail": { "claimdetail": "Détails de la réclamation", diff --git a/docker-compose.yml b/docker-compose.yml index c5c456ee6..0bc96311c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -117,6 +117,7 @@ services: aws --endpoint-url=http://localstack:4566 secretsmanager create-secret --name CHATTER_PRIVATE_KEY --secret-string file:///tmp/certs/io-ftp-test.key aws --endpoint-url=http://localstack:4566 logs create-log-group --log-group-name development --region ca-central-1 aws --endpoint-url=http://localstack:4566 s3api create-bucket --bucket imex-large-log --create-bucket-configuration LocationConstraint=ca-central-1 + aws --endpoint-url=http://localstack:4566 s3api create-bucket --bucket imex-job-totals --create-bucket-configuration LocationConstraint=ca-central-1 " # Node App: The Main IMEX API node-app: diff --git a/download-job-totals-fixtures.js b/download-job-totals-fixtures.js new file mode 100644 index 000000000..39d2199a0 --- /dev/null +++ b/download-job-totals-fixtures.js @@ -0,0 +1,77 @@ +const fs = require("fs"); +const path = require("path"); +const logger = require("./server/utils/logger"); // Assuming same logger utility +const s3Client = require("./server/utils/s3"); // Using the S3 client utilities with LocalStack support + +// Set bucket name for development with LocalStack +const S3_BUCKET_NAME = "imex-job-totals"; + +// Set fixtures directory path +const FIXTURES_DIR = path.join(__dirname, "server", "job", "test", "fixtures", "job-totals"); + +const ensureFixturesDirectory = () => { + if (!fs.existsSync(FIXTURES_DIR)) { + fs.mkdirSync(FIXTURES_DIR, { recursive: true }); + logger.log(`Created fixtures directory: ${FIXTURES_DIR}`, "info"); + } +}; + +const downloadJsonFiles = async (userInfo = { email: "system" }) => { + logger.log(`Starting download of JSON files from bucket: ${S3_BUCKET_NAME}`, "debug", userInfo.email); + + try { + ensureFixturesDirectory(); + const contents = await s3Client.listFilesInS3Bucket(S3_BUCKET_NAME); + + if (!contents.length) { + logger.log("No files found in bucket", "info", userInfo.email); + return; + } + + logger.log(`Found ${contents.length} files in bucket`, "info", userInfo.email); + + for (const item of contents) { + if (!item.Key.endsWith(".json")) { + logger.log(`Skipping non-JSON file: ${item.Key}`, "debug", userInfo.email); + continue; + } + + logger.log(`Downloading: ${item.Key}`, "debug", userInfo.email); + const fileData = await s3Client.downloadFileFromS3({ + bucketName: S3_BUCKET_NAME, + key: item.Key + }); + + const fileContent = await fileData.transformToString(); + const fileName = path.basename(item.Key); + const filePath = path.join(FIXTURES_DIR, fileName); + + fs.writeFileSync(filePath, fileContent); + logger.log(`Saved: ${filePath}`, "info", userInfo.email); + } + + logger.log("Download completed successfully", "info", userInfo.email); + } catch (error) { + logger.log("Failed to download JSON files", "error", userInfo.email, null, { + error: error?.message, + stack: error?.stack + }); + throw error; // Re-throw to trigger process exit with error code + } +}; + +// Run the download if script is executed directly +if (require.main === module) { + (async () => { + try { + await downloadJsonFiles(); + console.log("Script completed successfully"); + process.exit(0); // Explicitly exit with success code + } catch (error) { + console.error("Fatal error downloading files:", error); + process.exit(1); // Explicitly exit with error code + } + })(); +} + +module.exports = downloadJsonFiles; diff --git a/package.json b/package.json index f7f07bdc1..fd36fef86 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "start": "node server.js", "makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\"", "test:unit": "vitest run", - "test:watch": "vitest" + "test:watch": "vitest", + "job-totals-fixtures:local": "docker exec node-app /usr/bin/node /app/download-job-totals-fixtures.js" }, "dependencies": { "@aws-sdk/client-cloudwatch-logs": "^3.782.0", diff --git a/server/job/job-totals-USA.js b/server/job/job-totals-USA.js index 8cde6ebb3..2febf83ae 100644 --- a/server/job/job-totals-USA.js +++ b/server/job/job-totals-USA.js @@ -1,7 +1,6 @@ const Dinero = require("dinero.js"); const queries = require("../graphql-client/queries"); const logger = require("../utils/logger"); -const { captureFixture } = require("./utils/seralizeHelper"); const InstanceMgr = require("../utils/instanceMgr").default; //****************************************************** */ @@ -31,16 +30,8 @@ exports.totalsSsu = async function (req, res) { const job = await client.setHeaders({ Authorization: BearerToken }).request(queries.GET_JOB_BY_PK, { id: id }); - - // Extract the job data (the input for TotalsServerSide) - const inputForTotals = job.jobs_by_pk; - - const newTotals = await TotalsServerSide({ body: { job: inputForTotals, client: client } }, res, true); - - // Capture fixture data (input and output), using job.id for the filename. - if (process.env?.SAVE_TOTALS_DATA === "true") { - captureFixture(inputForTotals, newTotals); - } + p; + const newTotals = await TotalsServerSide({ body: { job: job.jobs_by_pk, client: client } }, res, true); const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, { jobId: id, diff --git a/server/job/job-totals-recorder.js b/server/job/job-totals-recorder.js new file mode 100644 index 000000000..66edad974 --- /dev/null +++ b/server/job/job-totals-recorder.js @@ -0,0 +1,133 @@ +const logger = require("../utils/logger"); +const queries = require("../graphql-client/queries"); +const moment = require("moment"); +const { captureFixture } = require("./utils/seralizeHelper"); +const { TotalsServerSide: totalsServerSideCA } = require("./job-totals"); // Canadian version (imex) +const { TotalsServerSide: totalsServerSideUS } = require("./job-totals-USA"); +const InstanceMgr = require("../utils/instanceMgr").default; +const { uploadFileToS3 } = require("../utils/s3"); + +// requires two buckets be made per env, job-totals-test, job-totals-production, locally it will +// use `job-totals` in the owncloud stack + +/** + * Returns the environment prefix based on NODE_ENV + * @returns {string} + */ +const getEnvPrefix = () => { + switch (process.env?.NODE_ENV) { + case "test": + return "test"; + case "production": + return "production"; + default: + return "test"; + } +}; + +const envPrefix = getEnvPrefix(); + +const S3_BUCKET_NAME = process.env?.NODE_ENV === "development" ? "imex-job-totals" : `job-totals-${envPrefix}`; + +/** + * Generates a unique S3 key for the job totals file + * @param {string} jobId - The job ID + * @returns {string} - S3 key with timestamp + */ +const generateS3Key = (jobId) => `${jobId}-${moment().toISOString()}.json`; + +/** + * Uploads job totals data to S3 + * @param {object} data - The data to upload + * @param {string} jobId - The job ID + * @param {object} userInfo - User information for logging + * @returns {Promise} - The S3 key + */ +const uploadJobTotalsToS3 = async (data, jobId, userInfo) => { + const key = generateS3Key(jobId); + + try { + await uploadFileToS3({ + bucketName: S3_BUCKET_NAME, + key: key, + content: JSON.stringify(data, null, 2), + contentType: "application/json" + }); + + logger.log(`Job totals uploaded successfully to ${key}`, "info", userInfo.email, jobId); + return key; + } catch (error) { + logger.log("Failed to upload job totals to S3", "error", userInfo.email, jobId, { + error: error?.message, + stack: error?.stack + }); + throw error; // Re-throw for the main handler to catch + } +}; + +/** + * Fetches job data using GraphQL + * @param {object} client - GraphQL client + * @param {string} token - Bearer token + * @param {string} jobId - Job ID to fetch + * @returns {Promise} - Job data + */ +const fetchJobData = async (client, token, jobId) => { + return client + .setHeaders({ Authorization: token }) + .request(queries.GET_JOB_BY_PK, { id: jobId }) + .then((response) => response.jobs_by_pk); +}; + +/** + * This function is used to capture job totals json files. + * @param {object} req - Express request + * @param {object} res - Express response + * @returns {Promise} + */ +const jobTotalsRecorder = async (req, res) => { + const { id: jobId } = req.body; + const bearerToken = req.BearerToken; + const client = req.userGraphQLClient; + const userEmail = req?.user?.email; + + logger.log("Starting job totals recording", "debug", userEmail, jobId); + + try { + // Fetch job data + const jobData = await fetchJobData(client, bearerToken, jobId); + + // Get the appropriate totals function based on instance + const totalsFunction = InstanceMgr({ + imex: totalsServerSideCA, + rome: totalsServerSideUS + }); + + // Calculate the totals + const calculatedTotals = await totalsFunction({ body: { job: jobData, client }, req }, res, true); + + // Prepare data for storage + const dataToSave = captureFixture(jobData, calculatedTotals); + + // Upload to S3 + await uploadJobTotalsToS3(dataToSave, jobId, { email: userEmail }); + + res.status(200).json({ success: true, message: "Job totals recorded successfully" }); + } catch (error) { + logger.log("Failed to record job totals", "error", userEmail, jobId, { + error: error?.message, + stack: error?.stack + }); + + // Avoid sending response if it's already been sent + if (!res.headersSent) { + res.status(503).json({ + success: false, + message: "Error processing job totals", + error: error.message + }); + } + } +}; + +module.exports = jobTotalsRecorder; diff --git a/server/job/job-totals.js b/server/job/job-totals.js index 3aba47d1f..d370b57df 100644 --- a/server/job/job-totals.js +++ b/server/job/job-totals.js @@ -1,7 +1,6 @@ const Dinero = require("dinero.js"); const queries = require("../graphql-client/queries"); const logger = require("../utils/logger"); -const { captureFixture } = require("./utils/seralizeHelper"); //****************************************************** */ //****************************************************** */ @@ -31,16 +30,8 @@ exports.totalsSsu = async function (req, res) { id: id }); - // Extract the job data (the input for TotalsServerSide) - const inputForTotals = job.jobs_by_pk; - // Capture the output of TotalsServerSide - const newTotals = await TotalsServerSide({ body: { job: inputForTotals, client: client } }, res, true); - - // Capture fixture data (input and output), using job.id for the filename. - if (process.env?.SAVE_TOTALS_DATA === "true") { - captureFixture(inputForTotals, newTotals); - } + const newTotals = await TotalsServerSide({ body: { job: job.jobs_by_pk, client: client } }, res, true); const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, { jobId: id, diff --git a/server/job/utils/seralizeHelper.js b/server/job/utils/seralizeHelper.js index 6ea69b5b8..a0974757a 100644 --- a/server/job/utils/seralizeHelper.js +++ b/server/job/utils/seralizeHelper.js @@ -21,12 +21,9 @@ const serializeDinero = (key, value) => { * Capture a fixture for job totals. * @param inputData * @param outputData + * @param saveLocally */ -const captureFixture = (inputData, outputData) => { - if (!fs.existsSync(fixtureDir)) { - fs.mkdirSync(fixtureDir, { recursive: true }); - } - +const captureFixture = (inputData, outputData, saveLocally) => { const fileName = `${inputData.id}.json`; const filePath = path.join(fixtureDir, fileName); @@ -44,7 +41,15 @@ const captureFixture = (inputData, outputData) => { }; // Save the file using our custom serializer. - fs.writeFileSync(filePath, JSON.stringify(dataToSave, serializeDinero, 2), "utf8"); + if (saveLocally) { + if (!fs.existsSync(fixtureDir)) { + fs.mkdirSync(fixtureDir, { recursive: true }); + } + + fs.writeFileSync(filePath, JSON.stringify(dataToSave, serializeDinero, 2), "utf8"); + } + + return dataToSave; }; module.exports = { diff --git a/server/routes/jobRoutes.js b/server/routes/jobRoutes.js index 6a83271dd..aab3e8823 100644 --- a/server/routes/jobRoutes.js +++ b/server/routes/jobRoutes.js @@ -7,6 +7,7 @@ const eventAuthorizationMiddleware = require("../middleware/eventAuthorizationMI const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware"); const { totals, statustransition, totalsSsu, costing, lifecycle, costingmulti, jobUpdated } = require("../job/job"); const withUserGraphQLClientMiddleware = require("../middleware/withUserGraphQLClientMiddleware"); +const jobTotalsRecorder = require("../job/job-totals-recorder"); router.post("/totals", validateFirebaseIdTokenMiddleware, withUserGraphQLClientMiddleware, totals); router.post("/statustransition", eventAuthorizationMiddleware, statustransition); @@ -17,5 +18,6 @@ router.post("/costingmulti", validateFirebaseIdTokenMiddleware, withUserGraphQLC router.post("/partsscan", validateFirebaseIdTokenMiddleware, withUserGraphQLClientMiddleware, partsScan); router.post("/ppc", validateFirebaseIdTokenMiddleware, withUserGraphQLClientMiddleware, ppc.generatePpc); router.post("/job-updated", eventAuthorizationMiddleware, jobUpdated); +router.post("/totals-recorder", validateFirebaseIdTokenMiddleware, withUserGraphQLClientMiddleware, jobTotalsRecorder); module.exports = router; From cd56c50cf9c9329c49b5807dc4d0b737b4965ada Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 8 Apr 2025 11:46:16 -0400 Subject: [PATCH 24/34] feature/IO-2769-Job-Totals-Testing --- server/job/job-totals-USA.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/job/job-totals-USA.js b/server/job/job-totals-USA.js index 2febf83ae..5dc0d6740 100644 --- a/server/job/job-totals-USA.js +++ b/server/job/job-totals-USA.js @@ -30,7 +30,7 @@ exports.totalsSsu = async function (req, res) { const job = await client.setHeaders({ Authorization: BearerToken }).request(queries.GET_JOB_BY_PK, { id: id }); - p; + const newTotals = await TotalsServerSide({ body: { job: job.jobs_by_pk, client: client } }, res, true); const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, { From 3cc4f1c63e161ad6c111b5a122afaf326f337145 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 8 Apr 2025 12:00:43 -0400 Subject: [PATCH 25/34] feature/IO-2769-Job-Totals-Testing - fix typo --- .../jobs-detail-header-actions.component.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx index 860bb7e98..1db81a3b1 100644 --- a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx +++ b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx @@ -1135,7 +1135,7 @@ export function JobsDetailHeaderActions({ } catch (err) { console.error(`Error submitting job for testing: ${err?.message}`); notification.error({ - message: t("genera.errors.submit-for-testing-error") + message: t("general.errors.submit-for-testing-error") }); } } From c169bb5d5dbbf2dd22abbfa386f0eabb1196d5ea Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 8 Apr 2025 12:19:33 -0400 Subject: [PATCH 26/34] feature/IO-2769-Job-Totals-Testing - update end point --- server/job/job-totals-recorder.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/server/job/job-totals-recorder.js b/server/job/job-totals-recorder.js index 66edad974..d837db220 100644 --- a/server/job/job-totals-recorder.js +++ b/server/job/job-totals-recorder.js @@ -27,7 +27,13 @@ const getEnvPrefix = () => { const envPrefix = getEnvPrefix(); -const S3_BUCKET_NAME = process.env?.NODE_ENV === "development" ? "imex-job-totals" : `job-totals-${envPrefix}`; +const S3_BUCKET_NAME = + process.env?.NODE_ENV === "development" + ? "imex-job-totals" + : InstanceMgr({ + imex: `job-totals-${envPrefix}`, + rome: `job-totals-${envPrefix}-rome` + }); /** * Generates a unique S3 key for the job totals file From 0a68d2791d86b47ec814b7b26190e605d7428e44 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Tue, 8 Apr 2025 09:51:52 -0700 Subject: [PATCH 27/34] IO-3202 HasFeatureAccess Boolean Signed-off-by: Allan Carr --- .../components/feature-wrapper/feature-wrapper.component.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/components/feature-wrapper/feature-wrapper.component.jsx b/client/src/components/feature-wrapper/feature-wrapper.component.jsx index 6576d2f30..7dabea2ac 100644 --- a/client/src/components/feature-wrapper/feature-wrapper.component.jsx +++ b/client/src/components/feature-wrapper/feature-wrapper.component.jsx @@ -20,6 +20,7 @@ function FeatureWrapper({ children, upsellComponent, bypass, + // eslint-disable-next-line no-unused-vars ...restProps }) { const { t } = useTranslation(); @@ -80,7 +81,7 @@ export function HasFeatureAccess({ featureName, bodyshop, bypass, debug = false } return ( bodyshop?.features?.allAccess || - bodyshop?.features[featureName] || + bodyshop?.features?.[featureName] || dayjs(bodyshop?.features[featureName]).isAfter(dayjs()) ); } From e33ff2a45d398e32b4e7e63a7affaebe622d4296 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 8 Apr 2025 17:04:50 -0400 Subject: [PATCH 28/34] feature/IO-2769-Job-Totals-Testing - cleanup --- server/job/test/job-totals.test.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/job/test/job-totals.test.js b/server/job/test/job-totals.test.js index 059b0bb1e..04a915b6b 100644 --- a/server/job/test/job-totals.test.js +++ b/server/job/test/job-totals.test.js @@ -2,7 +2,8 @@ import fs from "fs"; import path from "path"; import { describe, it, expect } from "vitest"; import { TotalsServerSide as TotalsServerSideCA } from "../job-totals"; // Canadian version (imex) -import { TotalsServerSide as TotalsServerSideUS } from "../job-totals-USA"; // US version (rome) +import { TotalsServerSide as TotalsServerSideUS } from "../job-totals-USA"; +import { isFunction } from "lodash"; // US version (rome) /** * This function is used to replace the values in the object with their toObject() representation. @@ -11,7 +12,7 @@ import { TotalsServerSide as TotalsServerSideUS } from "../job-totals-USA"; // U * @returns {*} */ const dineroReplacer = (key, value) => { - if (value && typeof value === "object" && typeof value.toObject === "function") { + if (isFunction(value)) { return value.toObject(); } return value; From c5181d1c5d400621c5288484404ba57d76c0b4df Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 8 Apr 2025 18:10:28 -0400 Subject: [PATCH 29/34] feature/IO-2769-Job-Totals-Testing - non-related --- server/graphql-client/queries.js | 9 ++++++ .../lib/handleInvoiceBasedPayment.js | 32 +++++++++++++++++-- .../lib/handlePaymentValidationError.js | 5 +-- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index 44a7cbffb..16c955467 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -2841,6 +2841,15 @@ query GET_JOBID_BY_MERCHANTID_RONUMBER($merchantID: String!, $roNumber: String!) bodyshop { id intellipay_config + email } } }`; + +exports.GET_BODYSHOP_BY_MERCHANT_ID = ` +query GET_BODYSHOP_BY_MERCHANTID($merchantID: String!) { + bodyshops(where: {intellipay_merchant_id: {_eq: $merchantID}}) { + id + email + } +}`; diff --git a/server/intellipay/lib/handleInvoiceBasedPayment.js b/server/intellipay/lib/handleInvoiceBasedPayment.js index f99378d56..5a6bad360 100644 --- a/server/intellipay/lib/handleInvoiceBasedPayment.js +++ b/server/intellipay/lib/handleInvoiceBasedPayment.js @@ -2,8 +2,11 @@ const handlePaymentValidationError = require("./handlePaymentValidationError"); const { GET_JOBID_BY_MERCHANTID_RONUMBER, INSERT_PAYMENT_RESPONSE, - INSERT_NEW_PAYMENT + INSERT_NEW_PAYMENT, + GET_BODYSHOP_BY_MERCHANT_ID } = require("../../graphql-client/queries"); + +const { sendServerEmail } = require("../../email/sendemail"); const getPaymentType = require("./getPaymentType"); const moment = require("moment"); @@ -36,7 +39,32 @@ const handleInvoiceBasedPayment = async (values, logger, logMeta, res) => { }); if (!result?.jobs?.length) { - return handlePaymentValidationError(res, logger, "intellipay-postback-job-not-found", "Job not found", logMeta); + // Fetch bodyshop data + const bodyshop = await gqlClient.request(GET_BODYSHOP_BY_MERCHANT_ID, { + merchantID: values.merchantid + }); + + if (bodyshop?.bodyshops?.[0]) { + // Note: changed bodyshops to bodyshop to match query name + const email = bodyshop.bodyshops[0].email; + await sendServerEmail({ + subject: `Failed to Insert Payment`, + text: `The system has attempted to insert a payment that was generated by your merchant terminal but could not find an associated invoice. Transaction details are below. Please input this payment to your system manually.\n\n${Object.keys( + values + ) + .map((key) => `${key}: ${values[key]}`) + .join("\n")}` + }); + } + + return handlePaymentValidationError( + res, + logger, + "intellipay-postback-job-not-found", + "Job not found", + logMeta, + 200 + ); } const job = result.jobs[0]; diff --git a/server/intellipay/lib/handlePaymentValidationError.js b/server/intellipay/lib/handlePaymentValidationError.js index fccf7a75f..185089b41 100644 --- a/server/intellipay/lib/handlePaymentValidationError.js +++ b/server/intellipay/lib/handlePaymentValidationError.js @@ -5,14 +5,15 @@ * @param logCode * @param message * @param logMeta + * @param returnCode * @returns {*} */ -const handlePaymentValidationError = (res, logger, logCode, message, logMeta) => { +const handlePaymentValidationError = (res, logger, logCode, message, logMeta, returnCode) => { logger.log(logCode, "ERROR", "api", null, { message, ...logMeta }); - return res.status(400).send(`Bad Request: ${message}`); + return res.status(returnCode || 400).send(`Bad Request: ${message}`); }; module.exports = handlePaymentValidationError; From 2bcad68351c435c6b76864eefe01d0d30bb1e69f Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 8 Apr 2025 18:14:20 -0400 Subject: [PATCH 30/34] feature/IO-2769-Job-Totals-Testing - non-related --- server/intellipay/lib/handleInvoiceBasedPayment.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/intellipay/lib/handleInvoiceBasedPayment.js b/server/intellipay/lib/handleInvoiceBasedPayment.js index 5a6bad360..21e4500a6 100644 --- a/server/intellipay/lib/handleInvoiceBasedPayment.js +++ b/server/intellipay/lib/handleInvoiceBasedPayment.js @@ -6,7 +6,7 @@ const { GET_BODYSHOP_BY_MERCHANT_ID } = require("../../graphql-client/queries"); -const { sendServerEmail } = require("../../email/sendemail"); +const { sendTaskEmail } = require("../../email/sendemail"); const getPaymentType = require("./getPaymentType"); const moment = require("moment"); @@ -47,7 +47,9 @@ const handleInvoiceBasedPayment = async (values, logger, logMeta, res) => { if (bodyshop?.bodyshops?.[0]) { // Note: changed bodyshops to bodyshop to match query name const email = bodyshop.bodyshops[0].email; - await sendServerEmail({ + + await sendTaskEmail({ + to: email, subject: `Failed to Insert Payment`, text: `The system has attempted to insert a payment that was generated by your merchant terminal but could not find an associated invoice. Transaction details are below. Please input this payment to your system manually.\n\n${Object.keys( values From 2c47e5d852ff3562c89686f289c5effd43859584 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 9 Apr 2025 11:18:09 -0400 Subject: [PATCH 31/34] feature/IO-2769-Job-Totals-Testing - updated tests --- server/intellipay/lib/tests/handleInvoiceBasedPayment.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/intellipay/lib/tests/handleInvoiceBasedPayment.test.js b/server/intellipay/lib/tests/handleInvoiceBasedPayment.test.js index b2a886e2f..01352191e 100644 --- a/server/intellipay/lib/tests/handleInvoiceBasedPayment.test.js +++ b/server/intellipay/lib/tests/handleInvoiceBasedPayment.test.js @@ -96,7 +96,8 @@ describe("handleInvoiceBasedPayment", () => { mockLogger, "intellipay-postback-job-not-found", "Job not found", - logMeta + logMeta, + 200 ); }); From fbea9fde2769cea2cd3c461dcced2610246a0e72 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 9 Apr 2025 09:33:37 -0700 Subject: [PATCH 32/34] IO-3066 Add additional CIECA fields for new partner --- client/src/graphql/parts-orders.queries.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/src/graphql/parts-orders.queries.js b/client/src/graphql/parts-orders.queries.js index 2fa4aa777..de51fab3d 100644 --- a/client/src/graphql/parts-orders.queries.js +++ b/client/src/graphql/parts-orders.queries.js @@ -78,6 +78,9 @@ export const QUERY_PARTS_ORDER_OEC = gql` } ro_number clm_no + cieca_stl + cieca_ttl + cieca_pfl asgn_no asgn_date state_tax_rate @@ -164,6 +167,7 @@ export const QUERY_PARTS_ORDER_OEC = gql` loss_desc loss_of_use loss_type + materials ownr_addr1 ownr_addr2 ownr_city From 037efff81c92215470160ee2abfd402ed0cb74c9 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 9 Apr 2025 12:52:23 -0400 Subject: [PATCH 33/34] feature/IO-2769-Job-Totals-Testing - packages, final update --- client/package-lock.json | 8 ++++---- client/package.json | 2 +- package-lock.json | 8 ++++---- package.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 12559bc12..325ee0d27 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -23,7 +23,7 @@ "@sentry/cli": "^2.43.0", "@sentry/react": "^9.11.0", "@sentry/vite-plugin": "^3.3.1", - "@splitsoftware/splitio-react": "^2.1.0", + "@splitsoftware/splitio-react": "^2.1.1", "@tanem/react-nprogress": "^5.0.53", "antd": "^5.24.6", "apollo-link-logger": "^2.0.1", @@ -4718,9 +4718,9 @@ } }, "node_modules/@splitsoftware/splitio-react": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-2.1.0.tgz", - "integrity": "sha512-iAGXl/qadHVFUQA/+asX8UGwDPpNi6WCKhNIzLZ6NSvt38+M8Bpc3CMnkYNEXsNsz1J+C26ICsMZ067YQ96k6g==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-2.1.1.tgz", + "integrity": "sha512-cUMyIdsgzDEFgUZxoV/PyjQR0OXt+Ffqqjh2LVcADsVDpTGUf95ydEVYaszZRVoYYj+hMw9xMw6Yfr0b+uejIQ==", "license": "Apache-2.0", "dependencies": { "@splitsoftware/splitio": "11.2.0", diff --git a/client/package.json b/client/package.json index 7795b1ff0..b303e1037 100644 --- a/client/package.json +++ b/client/package.json @@ -22,7 +22,7 @@ "@sentry/cli": "^2.43.0", "@sentry/react": "^9.11.0", "@sentry/vite-plugin": "^3.3.1", - "@splitsoftware/splitio-react": "^2.1.0", + "@splitsoftware/splitio-react": "^2.1.1", "@tanem/react-nprogress": "^5.0.53", "antd": "^5.24.6", "apollo-link-logger": "^2.0.1", diff --git a/package-lock.json b/package-lock.json index b80b3ff4c..de7c7ba67 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,7 @@ "bee-queue": "^1.7.1", "better-queue": "^3.8.12", "bluebird": "^3.7.2", - "bullmq": "^5.47.2", + "bullmq": "^5.48.0", "chart.js": "^4.4.8", "cloudinary": "^2.6.0", "compression": "^1.8.0", @@ -5139,9 +5139,9 @@ } }, "node_modules/bullmq": { - "version": "5.47.2", - "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.47.2.tgz", - "integrity": "sha512-JMI2uEV3YjohGTcy4Cqt/4LHEXcBA2BVS7x4XS7sv4qa5oLdsZh9p5fkwSWg6f8lqtcHbm3ceXkTFR0JC9gayw==", + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.48.0.tgz", + "integrity": "sha512-fUtQrkefr6VAYYPjLXKHR6scWhwGI/0ok1wfAEPyhq8aRnJK8PJGEXUSssTEzDShadgLLXCmIOsVyhbs5/XWWg==", "license": "MIT", "dependencies": { "cron-parser": "^4.9.0", diff --git a/package.json b/package.json index fd36fef86..f33ea0d5c 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "bee-queue": "^1.7.1", "better-queue": "^3.8.12", "bluebird": "^3.7.2", - "bullmq": "^5.47.2", + "bullmq": "^5.48.0", "chart.js": "^4.4.8", "cloudinary": "^2.6.0", "compression": "^1.8.0", From 84f41b2c1182fcf78bc9e5b3ecb10f37b318ff76 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 10 Apr 2025 12:27:54 -0400 Subject: [PATCH 34/34] feature/IO-3045-Product-Fruits-Tours-Modifications - Add in roles prop on Product fruits, tie the usage of it to a new db bodyshop var tours_enabled. --- client/src/App/App.jsx | 7 +++---- client/src/App/ProductFruitsWrapper.jsx | 18 ++++++++++++++---- client/src/graphql/bodyshop.queries.js | 2 ++ hasura/metadata/tables.yaml | 2 ++ .../down.sql | 4 ++++ .../up.sql | 2 ++ 6 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 hasura/migrations/1744302073757_alter_table_public_bodyshops_add_column_tours_enabled/down.sql create mode 100644 hasura/migrations/1744302073757_alter_table_public_bodyshops_add_column_tours_enabled/up.sql diff --git a/client/src/App/App.jsx b/client/src/App/App.jsx index 1b26476ff..3cda7fe8e 100644 --- a/client/src/App/App.jsx +++ b/client/src/App/App.jsx @@ -142,11 +142,10 @@ export function App({ bodyshop, checkUserSession, currentUser, online, setOnline > + { + const featureProps = bodyshop?.features + ? Object.entries(bodyshop.features).reduce((acc, [key, value]) => { + acc[key] = value === true || (typeof value === "string" && dayjs(value).isAfter(dayjs())); + return acc; + }, {}) + : {}; -const ProductFruitsWrapper = React.memo(({ currentUser, workspaceCode }) => { return ( workspaceCode && currentUser?.authorized === true && @@ -14,7 +22,8 @@ const ProductFruitsWrapper = React.memo(({ currentUser, workspaceCode }) => { language="en" user={{ email: currentUser.email, - username: currentUser.email + username: currentUser.email, + props: featureProps }} /> ) @@ -28,5 +37,6 @@ ProductFruitsWrapper.propTypes = { authorized: PropTypes.bool, email: PropTypes.string }), - workspaceCode: PropTypes.string + workspaceCode: PropTypes.string, + bodyshop: PropTypes.object }; diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js index 32a93980f..59651017d 100644 --- a/client/src/graphql/bodyshop.queries.js +++ b/client/src/graphql/bodyshop.queries.js @@ -57,6 +57,7 @@ export const QUERY_BODYSHOP = gql` logo_img_path md_ro_statuses md_order_statuses + tours_enabled md_functionality_toggles shopname state @@ -186,6 +187,7 @@ export const UPDATE_SHOP = gql` phone federal_tax_id id + tours_enabled insurance_vendor_id logo_img_path md_ro_statuses diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index 4d1f5192e..e783e3935 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -965,6 +965,7 @@ - insurance_vendor_id - intakechecklist - intellipay_config + - intellipay_merchant_id - jc_hourly_rates - jobsizelimit - last_name_first @@ -1023,6 +1024,7 @@ - template_header - textid - timezone + - tours_enabled - tt_allow_post_to_invoiced - tt_enforce_hours_for_tech_console - updated_at diff --git a/hasura/migrations/1744302073757_alter_table_public_bodyshops_add_column_tours_enabled/down.sql b/hasura/migrations/1744302073757_alter_table_public_bodyshops_add_column_tours_enabled/down.sql new file mode 100644 index 000000000..9cc955aae --- /dev/null +++ b/hasura/migrations/1744302073757_alter_table_public_bodyshops_add_column_tours_enabled/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."bodyshops" add column "tours_enabled" boolean +-- not null default 'true'; diff --git a/hasura/migrations/1744302073757_alter_table_public_bodyshops_add_column_tours_enabled/up.sql b/hasura/migrations/1744302073757_alter_table_public_bodyshops_add_column_tours_enabled/up.sql new file mode 100644 index 000000000..edf9c83e2 --- /dev/null +++ b/hasura/migrations/1744302073757_alter_table_public_bodyshops_add_column_tours_enabled/up.sql @@ -0,0 +1,2 @@ +alter table "public"."bodyshops" add column "tours_enabled" boolean + not null default 'true';