diff --git a/.gitignore b/.gitignore index fc12776ac..9b2ed79f9 100644 --- a/.gitignore +++ b/.gitignore @@ -121,3 +121,10 @@ logs/oAuthClient-log.log /*.env.* .idea/* .idea + +# Vitest +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/client/.env.development.imex b/client/.env.development.imex index ef94b0621..d1383e6ef 100644 --- a/client/.env.development.imex +++ b/client/.env.development.imex @@ -12,3 +12,5 @@ VITE_APP_AXIOS_BASE_API_URL=/api/ VITE_APP_REPORTS_SERVER_URL=https://reports.test.imex.online VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc VITE_APP_INSTANCE=IMEX +TEST_USERNAME="test@imex.dev" +TEST_PASSWORD="test123" diff --git a/client/.env.development.rome b/client/.env.development.rome index 5d0c366fa..15408c90b 100644 --- a/client/.env.development.rome +++ b/client/.env.development.rome @@ -14,3 +14,5 @@ VITE_APP_REPORTS_SERVER_URL=https://reports.test.romeonline.io VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc VITE_APP_COUNTRY=USA VITE_APP_INSTANCE=ROME +TEST_USERNAME="test@imex.dev" +TEST_PASSWORD="test123" diff --git a/client/.gitignore b/client/.gitignore index 730a6b93c..0d780b332 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -1,3 +1,14 @@ +# Vitest +vitest-report*/ +vitest-coverage/ +*.vitest.log +test-output.txt + +# Playwright +playwright-report/ +test-results/ +playwright/.cache/ +*.playwright.log # Sentry Config File .sentryclirc diff --git a/client/package-lock.json b/client/package-lock.json index 289873fe4..325ee0d27 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -9,24 +9,23 @@ "version": "0.2.1", "hasInstallScript": true, "dependencies": { - "@ant-design/pro-layout": "^7.22.3", - "@apollo/client": "^3.13.5", + "@ant-design/pro-layout": "^7.22.4", + "@apollo/client": "^3.13.6", "@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.11.0", + "@sentry/vite-plugin": "^3.3.1", + "@splitsoftware/splitio-react": "^2.1.1", "@tanem/react-nprogress": "^5.0.53", - "@vitejs/plugin-react": "^4.3.4", - "antd": "^5.24.5", + "antd": "^5.24.6", "apollo-link-logger": "^2.0.1", "apollo-link-sentry": "^4.2.0", "autosize": "^6.0.1", @@ -59,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", @@ -72,16 +71,16 @@ "react-router-dom": "^6.30.0", "react-sticky": "^6.0.3", "react-virtuoso": "^4.12.5", - "recharts": "^2.15.0", + "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.0", + "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", @@ -91,29 +90,37 @@ "@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", - "@sentry/webpack-plugin": "^3.2.2", + "@eslint/js": "^9.24.0", + "@playwright/test": "^1.51.1", + "@sentry/webpack-plugin": "^3.3.1", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.3", + "@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", "os-browserify": "^0.3.0", + "playwright": "^1.51.1", "react-error-overlay": "^6.1.0", "redux-logger": "^3.0.6", "source-map-explorer": "^2.5.3", - "vite": "^6.2.3", + "vite": "^6.2.5", "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.1.1", "workbox-window": "^7.3.0" }, "engines": { @@ -123,6 +130,13 @@ "@rollup/rollup-linux-x64-gnu": "4.6.1" } }, + "node_modules/@adobe/css-tools": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.2.tgz", + "integrity": "sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A==", + "dev": true, + "license": "MIT" + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -238,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", @@ -286,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", @@ -305,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", @@ -382,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", @@ -423,6 +437,27 @@ } } }, + "node_modules/@asamuzakjp/css-color": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.1.tgz", + "integrity": "sha512-hpRD68SV2OMcZCsrbdkccTw5FXjNDLo5OuqSHyHZfwweGsDWZwDJ2+gONyNAbazZclobMirACLw0lk8WVxIqxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.2", + "@csstools/css-color-parser": "^3.0.8", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + } + }, + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/@babel/code-frame": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", @@ -674,6 +709,7 @@ "version": "7.26.5", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1902,6 +1938,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -1917,6 +1954,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2403,6 +2441,121 @@ "node": ">=6.9.0" } }, + "node_modules/@csstools/color-helpers": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", + "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.2.tgz", + "integrity": "sha512-TklMyb3uBB28b5uQdxjReG4L80NxAqgrECqLZFQbyLekwwlcDDS8r3f07DKqeo8C4926Br0gf/ZDe17Zv4wIuw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.8.tgz", + "integrity": "sha512-pdwotQjCCnRPuNi06jFuP68cykU1f3ZWExLe/8MQ1LOs8Xq+fTkYgd+2V8mWUWMrOn9iS2HftPVaMZDaXzGbhQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.0.2", + "@csstools/css-calc": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", + "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", + "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@ctrl/tinycolor": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", @@ -2413,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": { @@ -2738,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": { @@ -2773,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", @@ -2789,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", @@ -3340,6 +3493,22 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@playwright/test": { + "version": "1.51.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.51.1.tgz", + "integrity": "sha512-nM+kEaTSAoVlXmMPH10017vn3FSiFqr/bh4fKg9vmAdMfd9SDqRZNvPSiAHADc/itWak+qPvMPZQOPwCBW7k7Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.51.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -4009,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.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.9.0" + "@sentry/core": "9.11.0" }, "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.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.9.0" + "@sentry/core": "9.11.0" }, "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.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.9.0", - "@sentry/core": "9.9.0" + "@sentry-internal/browser-utils": "9.11.0", + "@sentry/core": "9.11.0" }, "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.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.9.0", - "@sentry/core": "9.9.0" + "@sentry-internal/replay": "9.11.0", + "@sentry/core": "9.11.0" }, "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.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.9.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.9.0.tgz", - "integrity": "sha512-pIMdkOC+iggZefBs6ck5fL1mBhbLzjdw/8K99iqSeDh+lLvmlHVZajAhPlmw50xfH8CyQ1s22dhcL+zXbg3NKw==", + "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.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.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.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.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.2", + "@sentry/babel-plugin-component-annotate": "3.3.1", "@sentry/cli": "2.42.2", "dotenv": "^16.3.1", "find-up": "^5.0.0", @@ -4131,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", @@ -4169,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": { @@ -4188,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" ], @@ -4235,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.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.9.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.9.0.tgz", - "integrity": "sha512-7BE2Lx5CNtHtlNSS7Z9HxKquohC0xhdFceO3NlMXlx+dZuVCMoQmLISB8SQEcHw+2VO24MvtP3LPEzdeNbkIfg==", + "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.9.0", - "@sentry/core": "9.9.0", + "@sentry/browser": "9.11.0", + "@sentry/core": "9.11.0", "hoist-non-react-statics": "^3.3.2" }, "engines": { @@ -4261,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.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.2", + "@sentry/bundler-plugin-core": "3.3.1", "unplugin": "1.0.1" }, "engines": { @@ -4274,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.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.2", + "@sentry/bundler-plugin-core": "3.3.1", "unplugin": "1.0.1", "uuid": "^9.0.0" }, @@ -4298,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", @@ -4316,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", @@ -4334,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.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.0.3", + "@splitsoftware/splitio": "11.2.0", "memoize-one": "^5.1.1", "shallowequal": "^1.1.0", "tslib": "^2.3.1" @@ -4391,10 +4775,135 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz", + "integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react": { + "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": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", @@ -4408,6 +4917,7 @@ "version": "7.6.8", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" @@ -4417,6 +4927,7 @@ "version": "7.4.4", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", @@ -4427,6 +4938,7 @@ "version": "7.20.6", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.20.7" @@ -4967,6 +5479,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==", + "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.26.0", @@ -4982,6 +5495,163 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" } }, + "node_modules/@vitest/expect": { + "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.1.1", + "@vitest/utils": "3.1.1", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "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.1.1", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/mocker/node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/@vitest/pretty-format": { + "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": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "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.1.1", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitest/snapshot": { + "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.1.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot/node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/@vitest/snapshot/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitest/spy": { + "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": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "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.1.1", + "loupe": "^3.1.3", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@wry/caches": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz", @@ -5090,10 +5760,25 @@ "node": ">=8" } }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/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", @@ -5239,6 +5924,16 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/array-buffer-byte-length": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", @@ -5439,6 +6134,16 @@ "util": "^0.12.5" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", @@ -6035,6 +6740,16 @@ "dev": true, "license": "MIT" }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -6055,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": { @@ -6069,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" @@ -6157,6 +6872,23 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chai": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", + "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/chalk": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", @@ -6231,6 +6963,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -6635,6 +7377,27 @@ "postcss-value-parser": "^4.0.2" } }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.3.0.tgz", + "integrity": "sha512-6r0NiY0xizYqfBvWp1G7WXJ06/bZyrk7Dc6PHql82C/pKGUTKu4yAX4Y8JPamb1ob9nBKuxWzCGTRuGwU3yxJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^3.1.1", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -6775,6 +7538,57 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/tr46": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.0.tgz", + "integrity": "sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", @@ -6867,6 +7681,13 @@ } } }, + "node_modules/decimal.js": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", + "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "dev": true, + "license": "MIT" + }, "node_modules/decimal.js-light": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", @@ -6902,6 +7723,16 @@ "dev": true, "license": "MIT" }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -7078,6 +7909,13 @@ "node": ">=6.0.0" } }, + "node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, "node_modules/dom-helpers": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", @@ -7269,6 +8107,19 @@ "node": ">=10.0.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/env-cmd": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/env-cmd/-/env-cmd-10.1.0.tgz", @@ -7819,20 +8670,10 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, "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": { @@ -7846,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", @@ -7963,22 +8804,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/eslint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -8032,19 +8857,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/eslint/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -8215,6 +9027,16 @@ "integrity": "sha512-g/aje2noHivrRSLbAUtBPWFbxKdKhgj/xr1vATDdUXPOFYJlQ62Ft0oy+72V6XLIpDJfHs6gXLbBLAolqOXYRw==", "license": "MIT" }, + "node_modules/expect-type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.0.tgz", + "integrity": "sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -8507,6 +9329,20 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "license": "ISC" }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -8567,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", @@ -9011,6 +9847,19 @@ "react-is": "^16.7.0" } }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/html-parse-stringify": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", @@ -9030,6 +9879,30 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -9110,6 +9983,19 @@ "@babel/runtime": "^7.23.2" } }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/idb": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", @@ -9196,6 +10082,16 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -9691,6 +10587,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -9941,21 +10844,6 @@ "node": ">=10" } }, - "node_modules/jake/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jake/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9972,18 +10860,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jake/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -10009,6 +10885,130 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdom": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.0.0.tgz", + "integrity": "sha512-BZYDGVAIriBWTpIxYzrXjv3E/4u8+/pSG5bQdIYCbNCGOvsPkDQfTVLAIXAf9ETdCpduCVTkDe2NNZ8NIwUVzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.2.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.1", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.1.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.0.tgz", + "integrity": "sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -10302,6 +11302,13 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", + "dev": true, + "license": "MIT" + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -10330,6 +11337,16 @@ "node": ">=12" } }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, "node_modules/magic-string": { "version": "0.30.8", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", @@ -11112,6 +12129,16 @@ "node": ">=6" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -11362,6 +12389,13 @@ "node": ">=8" } }, + "node_modules/nwsapi": { + "version": "2.2.19", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.19.tgz", + "integrity": "sha512-94bcyI3RsqiZufXjkr3ltkI86iEl+I7uiHVDtcq9wJUTwYQJ5odHDeSzkkrRzi80jJ8MaeZgqKjH1bAWAFw9bA==", + "dev": true, + "license": "MIT" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -11452,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" @@ -11754,6 +12789,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse5": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/pascal-case": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", @@ -11874,6 +12922,16 @@ "dev": true, "license": "MIT" }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, "node_modules/pbkdf2": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", @@ -11929,6 +12987,38 @@ "node": ">=10" } }, + "node_modules/playwright": { + "version": "1.51.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.1.tgz", + "integrity": "sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.51.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.51.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.1.tgz", + "integrity": "sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -11996,6 +13086,41 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT" + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -13153,6 +14278,7 @@ "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -13296,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", @@ -13342,6 +14468,20 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "license": "MIT" }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/redis-errors": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", @@ -13807,6 +14947,13 @@ "win32" ] }, + "node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true, + "license": "MIT" + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -13916,10 +15063,17 @@ "node": ">=10" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "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.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.3.tgz", + "integrity": "sha512-iGtg8kus4GrsGLRDLRBRHY9dNVA78ZaS7xr01cWnS7PEMQyFtTqBiyCrfpTYTZXRWM94akzckYjh8oADfFNTzw==", "license": "MIT", "dependencies": { "chokidar": "^4.0.0", @@ -13936,6 +15090,19 @@ "@parcel/watcher": "^2.4.1" } }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -14164,6 +15331,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -14299,22 +15473,6 @@ "node": ">=12" } }, - "node_modules/source-map-explorer/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/source-map-explorer/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -14376,19 +15534,6 @@ "node": ">= 8" } }, - "node_modules/source-map-explorer/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/source-map-explorer/node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -14484,12 +15629,26 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "license": "BSD-3-Clause" }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, "node_modules/standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", "license": "MIT" }, + "node_modules/std-env": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.1.tgz", + "integrity": "sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==", + "dev": true, + "license": "MIT" + }, "node_modules/stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -14751,6 +15910,19 @@ "node": ">=6" } }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -14774,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", @@ -14893,6 +16065,18 @@ } } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -14907,9 +16091,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", @@ -14928,6 +16112,13 @@ "node": ">=0.10" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, "node_modules/temp": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", @@ -15094,12 +16285,26 @@ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "license": "MIT" }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, "node_modules/tinycolor2": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", "license": "MIT" }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", @@ -15114,6 +16319,56 @@ "node": ">=12.0.0" } }, + "node_modules/tinypool": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", + "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "6.1.85", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.85.tgz", + "integrity": "sha512-gBdZ1RjCSevRPFix/hpaUWeak2/RNUZB4/8frF1r5uYMHjFptkiT0JXIebWvgI/0ZHXvxaUDDJshiA0j6GdL3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.85" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.85", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.85.tgz", + "integrity": "sha512-DTjUVvxckL1fIoPSb3KE7ISNtkWSawZdpfxGxwiIrZoO6EbHVDXXUIlIuWympPaeS+BLGyggozX/HTMsRAdsoA==", + "dev": true, + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -15132,6 +16387,19 @@ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", "license": "MIT" }, + "node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -15851,9 +17119,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.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.5.tgz", + "integrity": "sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==", "dev": true, "license": "MIT", "dependencies": { @@ -15922,6 +17190,43 @@ } } }, + "node_modules/vite-node": { + "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": { + "cac": "^6.7.14", + "debug": "^4.4.0", + "es-module-lexer": "^1.6.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-node/node_modules/es-module-lexer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", + "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite-node/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/vite-plugin-babel": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/vite-plugin-babel/-/vite-plugin-babel-1.3.0.tgz", @@ -15995,9 +17300,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": { @@ -16014,7 +17319,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" @@ -16082,6 +17387,21 @@ "sourcemap-codec": "^1.4.8" } }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/vite/node_modules/postcss": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", @@ -16111,6 +17431,93 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/vitest": { + "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.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.2.0", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "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.1.1", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.1.1", + "@vitest/ui": "3.1.1", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/vitest/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -16127,6 +17534,19 @@ "node": ">=0.10.0" } }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/warning": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", @@ -16163,6 +17583,29 @@ "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", "license": "MIT" }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -16277,6 +17720,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -16615,21 +18075,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -16657,6 +18102,23 @@ } } }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, "node_modules/xmlhttprequest-ssl": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", diff --git a/client/package.json b/client/package.json index f7e354160..b303e1037 100644 --- a/client/package.json +++ b/client/package.json @@ -8,24 +8,23 @@ "private": true, "proxy": "http://localhost:4000", "dependencies": { - "@ant-design/pro-layout": "^7.22.3", - "@apollo/client": "^3.13.5", + "@ant-design/pro-layout": "^7.22.4", + "@apollo/client": "^3.13.6", "@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.11.0", + "@sentry/vite-plugin": "^3.3.1", + "@splitsoftware/splitio-react": "^2.1.1", "@tanem/react-nprogress": "^5.0.53", - "@vitejs/plugin-react": "^4.3.4", - "antd": "^5.24.5", + "antd": "^5.24.6", "apollo-link-logger": "^2.0.1", "apollo-link-sentry": "^4.2.0", "autosize": "^6.0.1", @@ -58,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", @@ -71,16 +70,16 @@ "react-router-dom": "^6.30.0", "react-sticky": "^6.0.3", "react-virtuoso": "^4.12.5", - "recharts": "^2.15.0", + "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.0", + "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", @@ -100,7 +99,14 @@ "build:production:imex": "env-cmd -f .env.production.imex npm run build", "build:production:rome": "env-cmd -f .env.production.rome npm run build", "madge": "madge --image ./madge-graph.svg --extensions js,jsx,ts,tsx --circular .", - "eulaize": "node src/utils/eulaize.js" + "eulaize": "node src/utils/eulaize.js", + "test:unit": "vitest run", + "test:watch": "vitest", + "test:e2e:imex": "playwright test --config playwright.config.js", + "test:e2e:rome": "playwright test --config playwright.rome.config.js", + "test:e2e:imex:headed": "playwright test --config playwright.config.js --headed", + "test:e2e:rome:headed": "playwright test --config playwright.rome.config.js --headed", + "test:e2e:report": "playwright show-report" }, "browserslist": { "production": [ @@ -124,29 +130,37 @@ "@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", - "@sentry/webpack-plugin": "^3.2.2", + "@eslint/js": "^9.24.0", + "@playwright/test": "^1.51.1", + "@sentry/webpack-plugin": "^3.3.1", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.3", + "@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", "os-browserify": "^0.3.0", + "playwright": "^1.51.1", "react-error-overlay": "^6.1.0", "redux-logger": "^3.0.6", "source-map-explorer": "^2.5.3", - "vite": "^6.2.3", + "vite": "^6.2.5", "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.1.1", "workbox-window": "^7.3.0" } } diff --git a/client/playwright.config.js b/client/playwright.config.js new file mode 100644 index 000000000..1ffc0d207 --- /dev/null +++ b/client/playwright.config.js @@ -0,0 +1,25 @@ +import { defineConfig } from "@playwright/test"; +import dotenv from "dotenv"; + +dotenv.config({ + path: "./.env.development.imex", + prefix: "TEST_" +}); + +export default defineConfig({ + testDir: "./tests/e2e", + testMatch: "*.e2e.js", + timeout: 60 * 1000, + reporter: [["list"], ["html"]], + use: { + baseURL: "https://localhost:3000", + browser: "chromium", + ignoreHTTPSErrors: true + }, + webServer: { + command: "npm run start:imex", + ignoreHTTPSErrors: true, + url: "https://localhost:3000/health", // Health check endpoint will tell us when the server is ready + reuseExistingServer: !process.env.CI // Reuse server locally, not in CI + } +}); diff --git a/client/playwright.rome.config.js b/client/playwright.rome.config.js new file mode 100644 index 000000000..8378df05c --- /dev/null +++ b/client/playwright.rome.config.js @@ -0,0 +1,25 @@ +import { defineConfig } from "@playwright/test"; +import dotenv from "dotenv"; + +dotenv.config({ + path: "./.env.development.rome", + prefix: "TEST_" +}); + +export default defineConfig({ + testDir: "./tests/e2e", + testMatch: "*.e2e.js", + timeout: 60 * 1000, + reporter: [["list"], ["html"]], + use: { + baseURL: "https://localhost:3000", + browser: "chromium", + ignoreHTTPSErrors: true + }, + webServer: { + command: "npm run start:rome", + ignoreHTTPSErrors: true, + url: "https://localhost:3000/health", // Health check endpoint will tell us when the server is ready + reuseExistingServer: !process.env.CI // Reuse server locally, not in CI + } +}); diff --git a/client/src/App/App.container.jsx b/client/src/App/App.container.jsx index 67fd0f444..6702808d4 100644 --- a/client/src/App/App.container.jsx +++ b/client/src/App/App.container.jsx @@ -10,6 +10,7 @@ import client from "../utils/GraphQLClient"; import App from "./App"; import * as Sentry from "@sentry/react"; import themeProvider from "./themeProvider"; +import { CookiesProvider } from "react-cookie"; // Base Split configuration const config = { @@ -38,26 +39,28 @@ function AppContainer() { const { t } = useTranslation(); return ( - - - - - - - - - - + + + + + + + + + + + + ); } diff --git a/client/src/App/App.jsx b/client/src/App/App.jsx index 1cf4a8a06..3cda7fe8e 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")); @@ -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/components/alert/__snapshots__/alert.component.test.js.snap b/client/src/components/alert/__snapshots__/alert.component.test.js.snap deleted file mode 100644 index b872ff7b9..000000000 --- a/client/src/components/alert/__snapshots__/alert.component.test.js.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Alert component should render Alert component 1`] = `ShallowWrapper {}`; diff --git a/client/src/components/alert/alert.component.test.js b/client/src/components/alert/alert.component.test.js deleted file mode 100644 index b7c14b48a..000000000 --- a/client/src/components/alert/alert.component.test.js +++ /dev/null @@ -1,19 +0,0 @@ -import { shallow } from "enzyme"; -import React from "react"; -import Alert from "./alert.component"; - -describe("Alert component", () => { - let wrapper; - beforeEach(() => { - const mockProps = { - type: "error", - message: "Test error message." - }; - - wrapper = shallow(); - }); - - it("should render Alert component", () => { - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/client/src/components/alert/alert.component.test.jsx b/client/src/components/alert/alert.component.test.jsx new file mode 100644 index 000000000..a34644a4b --- /dev/null +++ b/client/src/components/alert/alert.component.test.jsx @@ -0,0 +1,31 @@ +import { render, screen } from "@testing-library/react"; +import { describe, expect, it } from "vitest"; +import AlertComponent from "./alert.component"; + +describe("AlertComponent", () => { + it("renders with default props", () => { + render(); + expect(screen.getByText("Default Alert")).toBeInTheDocument(); + expect(screen.getByRole("alert")).toHaveClass("ant-alert"); + }); + + it("applies type prop correctly", () => { + render(); + const alert = screen.getByRole("alert"); + expect(screen.getByText("Success Alert")).toBeInTheDocument(); + expect(alert).toHaveClass("ant-alert-success"); + }); + + it("displays description when provided", () => { + render(); + expect(screen.getByText("Error Alert")).toBeInTheDocument(); + expect(screen.getByText("Something went wrong")).toBeInTheDocument(); + expect(screen.getByRole("alert")).toHaveClass("ant-alert-error"); + }); + + it("is closable and shows icon when props are set", () => { + render(); + expect(screen.getByText("Warning Alert")).toBeInTheDocument(); + expect(screen.getByRole("button", { name: /close/i })).toBeInTheDocument(); // Close button + }); +}); diff --git a/client/src/components/allocations-assignment/__snapshots__/allocations-assignment.component.test.js.snap b/client/src/components/allocations-assignment/__snapshots__/allocations-assignment.component.test.js.snap deleted file mode 100644 index c0b9ed61d..000000000 --- a/client/src/components/allocations-assignment/__snapshots__/allocations-assignment.component.test.js.snap +++ /dev/null @@ -1,5 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AllocationsAssignmentComponent component should create an allocation on save 1`] = `ReactWrapper {}`; - -exports[`AllocationsAssignmentComponent component should render AllocationsAssignmentComponent component 1`] = `ReactWrapper {}`; diff --git a/client/src/components/allocations-assignment/allocations-assignment.component.test.js b/client/src/components/allocations-assignment/allocations-assignment.component.test.js deleted file mode 100644 index fe9c3628b..000000000 --- a/client/src/components/allocations-assignment/allocations-assignment.component.test.js +++ /dev/null @@ -1,35 +0,0 @@ -import { mount } from "enzyme"; -import React from "react"; -import { MockBodyshop } from "../../utils/TestingHelpers"; -import { AllocationsAssignmentComponent } from "./allocations-assignment.component"; - -describe("AllocationsAssignmentComponent component", () => { - let wrapper; - - beforeEach(() => { - const mockProps = { - bodyshop: MockBodyshop, - handleAssignment: jest.fn(), - assignment: {}, - setAssignment: jest.fn(), - visibilityState: [false, jest.fn()], - maxHours: 4 - }; - - wrapper = mount(); - }); - - it("should render AllocationsAssignmentComponent component", () => { - expect(wrapper).toMatchSnapshot(); - }); - - it("should render a list of employees", () => { - const empList = wrapper.find("#employeeSelector"); - expect(empList.children()).to.have.lengthOf(2); - }); - - it("should create an allocation on save", () => { - wrapper.find("Button").simulate("click"); - expect(wrapper).toMatchSnapshot(); - }); -}); 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/feature-wrapper/feature-wrapper.component.jsx b/client/src/components/feature-wrapper/feature-wrapper.component.jsx index afd0eb604..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(); @@ -78,7 +79,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); 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/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) => 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..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 @@ -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"; @@ -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("general.errors.submit-for-testing-error") + }); + } + } + }); + } + const menu = { items: menuItems, key: "popovermenu" 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/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/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 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")); diff --git a/client/src/redux/user/user.sagas.js b/client/src/redux/user/user.sagas.js index 3b3a07c91..35f3d9d97 100644 --- a/client/src/redux/user/user.sagas.js +++ b/client/src/redux/user/user.sagas.js @@ -340,6 +340,7 @@ export function* SetAuthLevelFromShopDetails({ payload }) { args: [], imex: () => { window.$crisp.push(["set", "user:company", [payload.shopname]]); + window.$crisp.push(["set", "session:segments", [[`region:${payload.region_config}`]]]); if (authRecord[0] && authRecord[0].user.validemail) { window.$crisp.push(["set", "user:email", [authRecord[0].user.email]]); } diff --git a/client/src/setupTests.js b/client/src/setupTests.js deleted file mode 100644 index 6f413a40b..000000000 --- a/client/src/setupTests.js +++ /dev/null @@ -1,4 +0,0 @@ -import { configure } from "enzyme"; -import Adapter from "enzyme-adapter-react-16"; - -configure({ adapter: new Adapter() }); diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index ccf90fc10..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", @@ -3679,7 +3682,8 @@ "signinerror": { "auth/user-disabled": "User account disabled. ", "auth/user-not-found": "A user with this email does not exist.", - "auth/wrong-password": "The email and password combination you provided is incorrect." + "auth/wrong-password": "The email and password combination you provided is incorrect.", + "auth/invalid-email": "A user with this email does not exist." } } }, diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 2f9fa9a2b..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", @@ -3679,7 +3682,8 @@ "signinerror": { "auth/user-disabled": "", "auth/user-not-found": "", - "auth/wrong-password": "" + "auth/wrong-password": "", + "auth/invalid-email": "" } } }, diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 888162de9..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", @@ -3679,7 +3683,8 @@ "signinerror": { "auth/user-disabled": "", "auth/user-not-found": "", - "auth/wrong-password": "" + "auth/wrong-password": "", + "auth/invalid-email": "" } } }, diff --git a/client/src/utils/TestingHelpers.js b/client/src/utils/TestingHelpers.js deleted file mode 100644 index 9b0ffd9b0..000000000 --- a/client/src/utils/TestingHelpers.js +++ /dev/null @@ -1,139 +0,0 @@ -export const MockBodyshop = { - address1: "123 Fake St", - address2: "Unit #100", - city: "Vancouver", - country: "Canada", - created_at: "2019-12-10T20:03:06.420853+00:00", - email: "snaptsoft@gmail.com", - federal_tax_id: "GST10150492", - id: "52b7357c-0edd-4c95-85c3-dfdbcdfad9ac", - insurance_vendor_id: "F123456", - logo_img_path: "https://www.snapt.ca/assets/logo-placeholder.png", - md_ro_statuses: { - statuses: [ - "Open", - "Scheduled", - "Arrived", - "Repair Plan", - "Parts", - "Body", - "Prep", - "Paint", - "Reassembly", - "Sublet", - "Detail", - "Completed", - "Delivered", - "Invoiced", - "Exported" - ], - open_statuses: ["Open", "Scheduled", "Arrived", "Repair Plan", "Parts", "Body", "Prep", "Paint"], - default_arrived: "Arrived", - default_exported: "Exported", - default_imported: "Open", - default_invoiced: "Invoiced", - default_completed: "Completed", - default_delivered: "Delivered", - default_scheduled: "Scheduled" - }, - md_order_statuses: { - statuses: ["Ordered", "Received", "Canceled", "Backordered"], - default_bo: "Backordered", - default_ordered: "Ordered", - default_canceled: "Canceled", - default_received: "Received" - }, - shopname: "Testing Collision", - state: "BC", - state_tax_id: "PST1000-2991", - updated_at: "2020-03-23T22:06:03.509544+00:00", - zip_post: "V6B 1M9", - region_config: "CA_BC", - md_responsibility_centers: { - costs: [ - "Aftermarket", - "ATS", - "Body", - "Detail", - "Daignostic", - "Electrical", - "Chrome", - "Frame", - "Mechanical", - "Refinish", - "Structural", - "Existing", - "Glass", - "LKQ", - "OEM", - "OEM Partial", - "Re-cored", - "Remanufactured", - "Other", - "Sublet", - "Towing" - ], - profits: [ - "Aftermarket", - "ATS", - "Body", - "Detail", - "Daignostic", - "Electrical", - "Chrome", - "Frame", - "Mechanical", - "Refinish", - "Structural", - "Existing", - "Glass", - "LKQ", - "OEM", - "OEM Partial", - "Re-cored", - "Remanufactured", - "Other", - "Sublet", - "Towing" - ], - defaults: { - ATS: "ATS", - LAB: "Body", - LAD: "Diagnostic", - LAE: "Electrical", - LAF: "Frame", - LAG: "Glass", - LAM: "Mechanical", - LAR: "Refinish", - LAS: "Structural", - LAU: "Detail", - PAA: "Aftermarket", - PAC: "Chrome", - PAL: "LKQ", - PAM: "Remanufactured", - PAN: "OEM", - PAO: "Other", - PAP: "OEM Partial", - PAR: "16", - TOW: "Towing" - } - }, - employees: [ - { - id: "075b744c-8919-49ca-abb2-ccd51040326d", - first_name: "Patrick", - last_name: "BODY123", - employee_number: "101", - cost_center: "Body", - __typename: "employees" - }, - { - id: "8cc787d3-1cfe-49d3-8a15-8469cd5c2e41", - first_name: "Patrick", - last_name: "Painter", - employee_number: "10211", - cost_center: "REFINISH", - __typename: "employees" - } - ] -}; diff --git a/client/tests/Button.test.jsx b/client/tests/Button.test.jsx new file mode 100644 index 000000000..b83bf36c3 --- /dev/null +++ b/client/tests/Button.test.jsx @@ -0,0 +1,14 @@ +// Button.test.jsx +import React from "react"; +import { render, screen } from "@testing-library/react"; +import { describe, it, expect } from "vitest"; +import { Button } from "antd"; +import "antd/dist/reset.css"; // Optional: include if needed for styling reset + +describe("AntD Button", () => { + it("renders with correct text", () => { + render(); + const button = screen.getByRole("button", { name: /click me/i }); + expect(button).toBeInTheDocument(); + }); +}); diff --git a/client/tests/e2e/homepage.e2e.js b/client/tests/e2e/homepage.e2e.js new file mode 100644 index 000000000..0cede9e0a --- /dev/null +++ b/client/tests/e2e/homepage.e2e.js @@ -0,0 +1,6 @@ +import { test, expect } from "@playwright/test"; + +test("homepage loads correctly", async ({ page }) => { + await page.goto("/"); + await expect(page.locator("h1")).toContainText("ImEX Online"); +}); diff --git a/client/tests/e2e/signin.e2e.js b/client/tests/e2e/signin.e2e.js new file mode 100644 index 000000000..3ad1f874b --- /dev/null +++ b/client/tests/e2e/signin.e2e.js @@ -0,0 +1,28 @@ +import { test, expect } from "@playwright/test"; +import { login } from "./utils/login"; + +test.describe("SignInComponent", () => { + test("successfully logs in with valid credentials", async ({ page }) => { + const email = process.env.TEST_USERNAME; + const password = process.env.TEST_PASSWORD; + + await login(page, { email, password }); + + // Additional assertions after login (optional) + await expect(page).toHaveURL(/\/manage\//); + }); + + test("displays error on invalid credentials", async ({ page }) => { + await page.goto("/"); // Adjust if login route differs + + // Fill form with invalid credentials + await page.fill('input[placeholder="Username"]', "wronguser@example.com"); + await page.fill('input[placeholder="Password"]', "wrongpassword"); + await page.click("button.login-btn"); + + // Check for error alert + const alert = page.locator(".ant-alert-error"); + await expect(alert).toBeVisible(); + await expect(alert).toContainText("A user with this email does not exist."); + }); +}); diff --git a/client/tests/e2e/utils/login.js b/client/tests/e2e/utils/login.js new file mode 100644 index 000000000..8b6c2e9f8 --- /dev/null +++ b/client/tests/e2e/utils/login.js @@ -0,0 +1,21 @@ +import { expect } from "@playwright/test"; + +export async function login(page, { email, password }) { + // Navigate to the login page + await page.goto("/"); // Adjust if your login route differs (e.g., '/login') + + // Fill email field + await page.fill('input[placeholder="Username"]', email); // Matches Ant Design Input placeholder + + // Fill password field + await page.fill('input[placeholder="Password"]', password); + + // Click login button + await page.click("button.login-btn"); + + // Wait for navigation or success indicator (e.g., redirect to /manage/) + await page.waitForURL(/\/manage\//, { timeout: 10000 }); // Adjust based on redirect + + // Verify successful login (e.g., check for a dashboard element) + await expect(page.locator("text=Manage")).toBeVisible(); // Adjust to your app’s post-login UI +} diff --git a/client/tests/setup.js b/client/tests/setup.js new file mode 100644 index 000000000..8b4799a23 --- /dev/null +++ b/client/tests/setup.js @@ -0,0 +1,5 @@ +import { afterEach } from "vitest"; +import { cleanup } from "@testing-library/react"; +import "@testing-library/jest-dom"; + +afterEach(() => cleanup()); diff --git a/client/tests/setupI18n.js b/client/tests/setupI18n.js new file mode 100644 index 000000000..91ae266fe --- /dev/null +++ b/client/tests/setupI18n.js @@ -0,0 +1,27 @@ +import i18n from "i18next"; +import { initReactI18next } from "react-i18next"; +import en_Translation from "../src/translations/en_us/common.json"; +import es_Translation from "../src/translations/es/common.json"; +import fr_Translation from "../src/translations/fr/common.json"; + +const resources = { + "en-US": en_Translation, + "fr-CA": fr_Translation, + "es-MX": es_Translation +}; + +i18n.use(initReactI18next).init({ + resources, + lng: "en-US", // Default to en-US for tests (no LanguageDetector) + fallbackLng: "en-US", + debug: false, // Disable debug in tests + react: { + useSuspense: false // Disable Suspense for Vitest + }, + interpolation: { + escapeValue: false, // React handles XSS + skipOnVariables: false + } +}); + +export default i18n; diff --git a/client/vitest.config.js b/client/vitest.config.js new file mode 100644 index 000000000..f5841b1bd --- /dev/null +++ b/client/vitest.config.js @@ -0,0 +1,19 @@ +import { defineConfig } from "vitest/config"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [react()], + test: { + environment: "jsdom", + globals: true, + setupFiles: "./tests/setup.js", + testTimeout: 10000 // 10 seconds (in milliseconds) + }, + css: { + preprocessorOptions: { + scss: { + silenceDeprecations: ["import"] // Suppress @import warnings + } + } + } +}); 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/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/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/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'; diff --git a/package-lock.json b/package-lock.json index 3ca7998d5..de7c7ba67 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.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,8 +26,7 @@ "bee-queue": "^1.7.1", "better-queue": "^3.8.12", "bluebird": "^3.7.2", - "body-parser": "^1.20.3", - "bullmq": "^5.44.4", + "bullmq": "^5.48.0", "chart.js": "^4.4.8", "cloudinary": "^2.6.0", "compression": "^1.8.0", @@ -35,7 +34,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", @@ -63,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", @@ -71,14 +70,17 @@ "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", "prettier": "^3.5.3", - "source-map-explorer": "^2.5.2" + "source-map-explorer": "^2.5.2", + "supertest": "^7.1.0", + "vitest": "^3.1.1" }, "engines": { "node": ">=18.0.0", @@ -288,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.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.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.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.782.0", + "@aws-sdk/region-config-resolver": "3.775.0", + "@aws-sdk/types": "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.782.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", @@ -356,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.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.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.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.782.0", + "@aws-sdk/region-config-resolver": "3.775.0", + "@aws-sdk/types": "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.782.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": { @@ -407,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.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.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.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", + "@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.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.782.0", + "@aws-sdk/util-user-agent-browser": "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", + "@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": { @@ -474,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.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.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.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.782.0", + "@aws-sdk/region-config-resolver": "3.775.0", + "@aws-sdk/types": "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.782.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", @@ -539,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.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.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.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.782.0", + "@aws-sdk/region-config-resolver": "3.775.0", + "@aws-sdk/types": "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.782.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": { @@ -590,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.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", "@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.782.0", + "@aws-sdk/region-config-resolver": "3.775.0", + "@aws-sdk/types": "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.782.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" }, @@ -639,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" }, @@ -661,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": { @@ -677,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": { @@ -698,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.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.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.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", + "@smithy/shared-ini-file-loader": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -722,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.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.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.782.0", + "@aws-sdk/credential-provider-process": "3.775.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", + "@smithy/shared-ini-file-loader": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -745,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": { @@ -762,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.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.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.782.0", + "@aws-sdk/core": "3.775.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", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -781,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.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.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.782.0", + "@aws-sdk/types": "3.775.0", + "@smithy/property-provider": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -798,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.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.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", @@ -815,7 +817,7 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@aws-sdk/client-s3": "^3.774.0" + "@aws-sdk/client-s3": "^3.782.0" } }, "node_modules/@aws-sdk/lib-storage/node_modules/buffer": { @@ -829,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" }, @@ -847,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": { @@ -862,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" }, @@ -886,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": { @@ -901,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": { @@ -915,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": { @@ -929,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": { @@ -944,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" }, @@ -969,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": { @@ -983,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.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.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.782.0", + "@smithy/core": "^3.2.0", + "@smithy/protocol-http": "^5.1.0", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -1001,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.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", "@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.782.0", + "@aws-sdk/region-config-resolver": "3.775.0", + "@aws-sdk/types": "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.782.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" }, @@ -1050,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": { @@ -1067,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.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.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": { @@ -1086,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": { @@ -1103,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.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.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.782.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": { @@ -1120,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": { @@ -1145,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.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.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": { @@ -1160,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": { @@ -1187,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.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.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.782.0", + "@aws-sdk/types": "3.775.0", + "@smithy/node-config-provider": "^4.0.2", + "@smithy/types": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -1223,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": { @@ -1400,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": { @@ -1483,6 +1485,431 @@ "integrity": "sha512-d5RjycE+MObE/hU+8OM5Zp4VjTwiPLRa8299fj7muOmR16fb942z8byoMbCErnGh0lBevvgkGrLclQDvINbIyg==", "license": "Apache-2.0" }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", + "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", + "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", + "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", + "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", + "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", + "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", + "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", @@ -1526,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": { @@ -1601,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": { @@ -2396,6 +2823,286 @@ "@redis/client": "^1.0.0" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@smithy/abort-controller": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.2.tgz", @@ -2486,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" }, @@ -2501,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": { @@ -2515,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": { @@ -2528,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": { @@ -2542,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": { @@ -2572,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": { @@ -2587,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" @@ -2602,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" }, @@ -2616,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": { @@ -2641,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" }, @@ -2655,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": { @@ -2856,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" @@ -3016,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": { @@ -3113,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": { @@ -3290,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" }, @@ -3445,6 +4152,119 @@ "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", "license": "MIT" }, + "node_modules/@vitest/expect": { + "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.1.1", + "@vitest/utils": "3.1.1", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "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.1.1", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "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": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "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.1.1", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "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.1.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "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": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "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.1.1", + "loupe": "^3.1.3", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@xmldom/is-dom-node": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@xmldom/is-dom-node/-/is-dom-node-1.0.1.tgz", @@ -3943,6 +4763,16 @@ "safer-buffer": "~2.1.0" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", @@ -4309,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.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", @@ -4356,6 +5186,16 @@ "node": ">= 0.8" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -4375,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", @@ -4388,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" @@ -4422,6 +5262,23 @@ "cargo-cp-artifact": "bin/cargo-cp-artifact.js" } }, + "node_modules/chai": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", + "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -4462,6 +5319,16 @@ "pnpm": ">=8" } }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, "node_modules/cheerio": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz", @@ -4667,6 +5534,16 @@ "node": ">=18" } }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/compress-commons": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", @@ -4857,6 +5734,13 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true, + "license": "MIT" + }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -5105,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", @@ -5122,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", @@ -5183,6 +6067,16 @@ "node": ">= 16" } }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -5724,10 +6618,17 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", + "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "dev": true, + "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" @@ -5778,6 +6679,47 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "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", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@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": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -5820,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", @@ -5881,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": { @@ -5897,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", @@ -6020,6 +6962,16 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -6057,6 +7009,16 @@ "node": ">=0.8.x" } }, + "node_modules/expect-type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.0.tgz", + "integrity": "sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/express": { "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", @@ -6523,6 +7485,21 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "license": "ISC" }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -6676,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", @@ -7426,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": { @@ -8311,6 +9288,13 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", + "dev": true, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -8351,6 +9335,16 @@ "node": ">=12" } }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -8542,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", @@ -8631,6 +9659,25 @@ "license": "MIT", "optional": true }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -8872,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" @@ -9223,6 +10271,23 @@ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, "node_modules/phone": { "version": "3.1.58", "resolved": "https://registry.npmjs.org/phone/-/phone-3.1.58.tgz", @@ -9257,6 +10322,35 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/pprof-format": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pprof-format/-/pprof-format-2.1.0.tgz", @@ -9651,6 +10745,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", @@ -9744,6 +10845,46 @@ "integrity": "sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw==", "license": "MIT" }, + "node_modules/rollup": { + "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.7" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@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" + } + }, "node_modules/rsa-pem-from-mod-exp": { "version": "0.8.6", "resolved": "https://registry.npmjs.org/rsa-pem-from-mod-exp/-/rsa-pem-from-mod-exp-0.8.6.tgz", @@ -10123,6 +11264,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -10465,6 +11613,16 @@ "node": ">=10" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/specificity": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz", @@ -10548,6 +11706,13 @@ "node": "*" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, "node_modules/standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", @@ -10563,6 +11728,13 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.1.tgz", + "integrity": "sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==", + "dev": true, + "license": "MIT" + }, "node_modules/stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -10833,6 +12005,54 @@ "pick-util": "^1.1.5" } }, + "node_modules/superagent": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", + "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^3.5.1", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/supertest": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.0.tgz", + "integrity": "sha512-5QeSO8hSrKghtcWEoPiO036fxH0Ii2wVQfFZSP0oqQhmjk8bOLhDFXr4JrvaFmPuEWUoq4znY3uSi8UzLKxGqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "methods": "^1.1.2", + "superagent": "^9.0.1" + }, + "engines": { + "node": ">=14.18.0" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -10991,6 +12211,50 @@ "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", "license": "MIT" }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", + "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tlhunter-sorted-set": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/tlhunter-sorted-set/-/tlhunter-sorted-set-0.1.0.tgz", @@ -11052,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", @@ -11300,6 +12564,171 @@ "node": ">= 0.8" } }, + "node_modules/vite": { + "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": { + "esbuild": "^0.25.0", + "postcss": "^8.5.3", + "rollup": "^4.30.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "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": { + "cac": "^6.7.14", + "debug": "^4.4.0", + "es-module-lexer": "^1.6.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "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.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.2.0", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "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.1.1", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.1.1", + "@vitest/ui": "3.1.1", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, "node_modules/web-resource-inliner": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-7.0.0.tgz", @@ -11602,6 +13031,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", diff --git a/package.json b/package.json index 9f2bf57f2..f33ea0d5c 100644 --- a/package.json +++ b/package.json @@ -10,17 +10,20 @@ "setup": "rm -rf node_modules && npm i && cd client && rm -rf node_modules && npm i", "setup:win": "rimraf node_modules && npm i && cd client && rimraf node_modules && npm i", "start": "node server.js", - "makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\"" + "makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\"", + "test:unit": "vitest run", + "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.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.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", @@ -30,8 +33,7 @@ "bee-queue": "^1.7.1", "better-queue": "^3.8.12", "bluebird": "^3.7.2", - "body-parser": "^1.20.3", - "bullmq": "^5.44.4", + "bullmq": "^5.48.0", "chart.js": "^4.4.8", "cloudinary": "^2.6.0", "compression": "^1.8.0", @@ -39,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", @@ -67,7 +69,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", @@ -75,13 +77,16 @@ "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", "prettier": "^3.5.3", - "source-map-explorer": "^2.5.2" + "source-map-explorer": "^2.5.2", + "supertest": "^7.1.0", + "vitest": "^3.1.1" } } diff --git a/server.js b/server.js index 52f5c6e9e..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"); @@ -84,8 +83,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 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. diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index f05ea7ec5..16c955467 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -2832,3 +2832,24 @@ 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 + 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/intellipay.js b/server/intellipay/intellipay.js index 4af4a50cc..29f8e978a 100644 --- a/server/intellipay/intellipay.js +++ b/server/intellipay/intellipay.js @@ -1,64 +1,22 @@ -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"); const axios = require("axios"); -const moment = require("moment"); const logger = require("../utils/logger"); -const { sendTaskEmail } = require("../email/sendemail"); -const generateEmailTemplate = require("../email/generateTemplate"); +const { isEmpty, isNumber } = require("lodash"); +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"); -const domain = process.env.NODE_ENV ? "secure" : "test"; - -const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager"); -const { InstanceRegion, InstanceEndpoints } = require("../utils/instanceMgr"); - -const client = new SecretsManagerClient({ - region: InstanceRegion() -}); - -const gqlClient = require("../graphql-client/graphql-client").client; - -const getShopCredentials = async (bodyshop) => { - // Development only - if (process.env.NODE_ENV === undefined) { - return { - merchantkey: process.env.INTELLIPAY_MERCHANTKEY, - apikey: process.env.INTELLIPAY_APIKEY - }; - } - - // Production code - 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 - }; - } - } -}; - -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 - } -}; - -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, @@ -74,17 +32,17 @@ exports.lightbox_credentials = 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 { @@ -95,7 +53,10 @@ exports.lightbox_credentials = 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); @@ -105,13 +66,14 @@ exports.lightbox_credentials = 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 @@ -119,7 +81,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, @@ -137,18 +105,17 @@ exports.payment_refund = 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 { @@ -161,7 +128,11 @@ exports.payment_refund = 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, { @@ -176,13 +147,14 @@ exports.payment_refund = 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 @@ -190,7 +162,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, @@ -210,17 +188,17 @@ exports.generate_payment_url = 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 { @@ -235,7 +213,10 @@ exports.generate_payment_url = 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, { @@ -251,18 +232,25 @@ exports.generate_payment_url = 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 }); } }; -//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, @@ -275,24 +263,24 @@ exports.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 { @@ -313,7 +301,7 @@ exports.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, { @@ -328,200 +316,92 @@ exports.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 }); } }; -exports.postback = async (req, res) => { +/** + * @description Handle the postback from Intellipay + * @param req + * @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 { - if ((!values.invoice || values.invoice === "") && !decodedComment) { - //invoice is specified through the pay link. Comment by IO. + // 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 }); - res.sendStatus(200); - return; + return res.sendStatus(200); } + // Process payment based on data type 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, { - parsedComment, - ...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, { - jobs, - parsedComment, - ...logResponseMeta - }); - - // Insert new payments - 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 - }); - }); - } - res.sendStatus(200); - } else if (values.invoice) { - const job = await gqlClient.request(queries.GET_JOB_BY_PK, { - id: values.invoice - }); - - 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, { - job, - bodyshop, - ...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: values.invoice, - 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.bodyshops_by_pk.id, - paymentid: paymentResult.id, - jobid: values.invoice, - declinereason: "Approved", - ext_paymentid: values.paymentid, - successful: true, - response: values - } - }); - - logger.log("intellipay-postback-invoice-response-success", "DEBUG", "api", null, { - responseResults, - ...logResponseMeta - }); - 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"); } } catch (error) { logger.log("intellipay-postback-error", "ERROR", "api", null, { message: error?.message, - ...logResponseMeta + ...logMeta }); - res.status(400).json({ successful: false, error: error.message, ...logResponseMeta }); + return res.status(400).json({ successful: false, error: error.message, ...logMeta }); } }; + +module.exports = { + lightboxCredentials, + paymentRefund, + generatePaymentUrl, + checkFee, + postBack +}; 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..21e4500a6 --- /dev/null +++ b/server/intellipay/lib/handleInvoiceBasedPayment.js @@ -0,0 +1,131 @@ +const handlePaymentValidationError = require("./handlePaymentValidationError"); +const { + GET_JOBID_BY_MERCHANTID_RONUMBER, + INSERT_PAYMENT_RESPONSE, + INSERT_NEW_PAYMENT, + GET_BODYSHOP_BY_MERCHANT_ID +} = require("../../graphql-client/queries"); + +const { sendTaskEmail } = require("../../email/sendemail"); +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) { + // 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 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 + ) + .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]; + 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..185089b41 --- /dev/null +++ b/server/intellipay/lib/handlePaymentValidationError.js @@ -0,0 +1,19 @@ +/** + * @description Log validation error and send response + * @param res + * @param logger + * @param logCode + * @param message + * @param logMeta + * @param returnCode + * @returns {*} + */ +const handlePaymentValidationError = (res, logger, logCode, message, logMeta, returnCode) => { + logger.log(logCode, "ERROR", "api", null, { + message, + ...logMeta + }); + return res.status(returnCode || 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/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..01352191e --- /dev/null +++ b/server/intellipay/lib/tests/handleInvoiceBasedPayment.test.js @@ -0,0 +1,130 @@ +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, + 200 + ); + }); + + 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/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/job/job-totals-USA.js b/server/job/job-totals-USA.js index dd850dc9b..5dc0d6740 100644 --- a/server/job/job-totals-USA.js +++ b/server/job/job-totals-USA.js @@ -1,7 +1,5 @@ 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 InstanceMgr = require("../utils/instanceMgr").default; @@ -45,9 +43,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 +58,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 +133,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-recorder.js b/server/job/job-totals-recorder.js new file mode 100644 index 000000000..d837db220 --- /dev/null +++ b/server/job/job-totals-recorder.js @@ -0,0 +1,139 @@ +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" + : InstanceMgr({ + imex: `job-totals-${envPrefix}`, + rome: `job-totals-${envPrefix}-rome` + }); + +/** + * 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 6182f9ced..d370b57df 100644 --- a/server/job/job-totals.js +++ b/server/job/job-totals.js @@ -30,6 +30,7 @@ exports.totalsSsu = async function (req, res) { id: id }); + // Capture the output of TotalsServerSide 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, { @@ -57,7 +58,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 +82,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..04a915b6b --- /dev/null +++ b/server/job/test/job-totals.test.js @@ -0,0 +1,72 @@ +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"; +import { isFunction } from "lodash"; // US version (rome) + +/** + * This function is used to replace the values in the object with their toObject() representation. + * @param key + * @param value + * @returns {*} + */ +const dineroReplacer = (key, value) => { + if (isFunction(value)) { + return value.toObject(); + } + return value; +}; + +/** + * 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", () => { + const fixturesDir = path.join(__dirname, "fixtures", "job-totals"); + + const fixtureFiles = fs.readdirSync(fixturesDir).filter((f) => f.endsWith(".json")); + + const dummyClient = { + request: async () => { + return {}; + } + }; + + 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 { environment, input, output: expectedOutput } = fixtureData; + + const req = { + body: { + job: input, + client: dummyClient + }, + user: {} + }; + + const computedOutput = + environment === "us" ? await TotalsServerSideUS(req, dummyRes) : await TotalsServerSideCA(req, dummyRes); + + 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..a0974757a --- /dev/null +++ b/server/job/utils/seralizeHelper.js @@ -0,0 +1,58 @@ +const fs = require("fs"); +const path = require("path"); +const { default: InstanceMgr } = require("../../utils/instanceMgr"); + +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 (value && typeof value === "object" && typeof value.toObject === "function") { + return value.toObject(); + } + return value; +}; + +/** + * Capture a fixture for job totals. + * @param inputData + * @param outputData + * @param saveLocally + */ +const captureFixture = (inputData, outputData, saveLocally) => { + const fileName = `${inputData.id}.json`; + const filePath = path.join(fixtureDir, fileName); + + const dataToSave = { + environment: InstanceMgr({ + imex: "ca", + rome: "us" + }), + meta: { + ro_number: inputData.ro_number, + updated_at: inputData.updated_at + }, + input: inputData, + output: outputData + }; + + // Save the file using our custom serializer. + if (saveLocally) { + if (!fs.existsSync(fixtureDir)) { + fs.mkdirSync(fixtureDir, { recursive: true }); + } + + fs.writeFileSync(filePath, JSON.stringify(dataToSave, serializeDinero, 2), "utf8"); + } + + return dataToSave; +}; + +module.exports = { + captureFixture, + serializeDinero +}; diff --git a/server/routes/intellipayRoutes.js b/server/routes/intellipayRoutes.js index ad0b87323..7a0425fd2 100644 --- a/server/routes/intellipayRoutes.js +++ b/server/routes/intellipayRoutes.js @@ -1,12 +1,18 @@ 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 +} = 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); module.exports = router; 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; diff --git a/server/tests/api.test.js b/server/tests/api.test.js new file mode 100644 index 000000000..ce5ccf72f --- /dev/null +++ b/server/tests/api.test.js @@ -0,0 +1,14 @@ +import { describe, it, expect } from "vitest"; +import request from "supertest"; +import express from "express"; + +const app = express(); +app.get("/api/health", (req, res) => res.json({ status: "ok" })); + +describe("API", () => { + it("returns health status", async () => { + const response = await request(app).get("/api/health"); + expect(response.status).toBe(200); + expect(response.body).toEqual({ status: "ok" }); + }); +}); diff --git a/server/tests/math.test.js b/server/tests/math.test.js new file mode 100644 index 000000000..551b921a5 --- /dev/null +++ b/server/tests/math.test.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from "vitest"; + +function add(a, b) { + return a + b; +} + +describe("Math", () => { + it("adds two numbers correctly", () => { + expect(add(2, 3)).toBe(5); + }); +}); diff --git a/vitest.config.js b/vitest.config.js new file mode 100644 index 000000000..c4b856ce5 --- /dev/null +++ b/vitest.config.js @@ -0,0 +1,13 @@ +const { defineConfig } = require("vitest/config"); + +module.exports = defineConfig({ + test: { + environment: "node", + globals: true, + 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 + } +});