From 5872b5d867396688a7f417023f347c3111aa7097 Mon Sep 17 00:00:00 2001 From: petruki <31597636+petruki@users.noreply.github.com> Date: Sun, 3 Nov 2024 13:43:35 -0800 Subject: [PATCH] Closes #542 - added Switcher Relay to GraphQL API schema --- npm-shrinkwrap.json | 223 ++++++++---------- package.json | 4 +- requests/Switcher API.postman_collection.json | 4 +- src/client/configuration-type.js | 45 +++- src/client/resolvers.js | 29 ++- src/services/config.js | 2 +- tests/client-api.test.js | 10 + tests/fixtures/db_client.js | 11 +- tests/graphql-utils/index.js | 55 ++++- 9 files changed, 243 insertions(+), 140 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 6815d35..d2498b2 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -23,7 +23,7 @@ "jsonwebtoken": "^9.0.2", "moment": "^2.30.1", "mongodb": "^6.10.0", - "mongoose": "^8.7.3", + "mongoose": "^8.8.0", "pino": "^9.5.0", "pino-pretty": "^11.3.0", "swagger-ui-express": "^5.0.1", @@ -32,7 +32,7 @@ }, "devDependencies": { "env-cmd": "^10.1.0", - "eslint": "^9.13.0", + "eslint": "^9.14.0", "jest": "^29.7.0", "jest-sonar-reporter": "^2.0.0", "node-notifier": "^10.0.1", @@ -55,9 +55,9 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.0.tgz", - "integrity": "sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", @@ -69,9 +69,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.0.tgz", - "integrity": "sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", "dev": true, "engines": { "node": ">=6.9.0" @@ -108,12 +108,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.0.tgz", - "integrity": "sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", "dev": true, "dependencies": { - "@babel/parser": "^7.26.0", + "@babel/parser": "^7.26.2", "@babel/types": "^7.26.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", @@ -219,9 +219,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.1.tgz", - "integrity": "sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "dev": true, "dependencies": { "@babel/types": "^7.26.0" @@ -546,9 +546,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.0.tgz", - "integrity": "sha512-gh7PdNombP8ftL8TinYC8Xd7WEypB8EKV4PI2h0eMzndKjPCXuo2zUiZtD2Hu+MSPt02Ty2MdS788ADl9ai1rA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -601,9 +601,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -619,9 +619,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.1.tgz", - "integrity": "sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz", + "integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==", "dev": true, "dependencies": { "levn": "^0.4.1" @@ -631,27 +631,40 @@ } }, "node_modules/@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "dependencies": { - "@humanfs/core": "^0.19.0", + "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" }, "engines": { "node": ">=18.18.0" } }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -666,9 +679,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.0.tgz", + "integrity": "sha512-xnRgu9DxZbkWak/te3fcytNyp8MTbuiZIaueg2rgEvBuN55n04nwLYLU9TX/VVlusc9L2ZNXi99nUFNkHXtr5g==", "dev": true, "engines": { "node": ">=18.18" @@ -1257,9 +1270,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.8.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.1.tgz", - "integrity": "sha512-k6Gi8Yyo8EtrNtkHXutUu2corfDf9su95VYVP10aGYMMROM6SAItZi0w1XszA6RtWTHSVp5OeFof37w0IEqCQg==", + "version": "22.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.7.tgz", + "integrity": "sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==", "dev": true, "dependencies": { "undici-types": "~6.19.8" @@ -1620,9 +1633,9 @@ } }, "node_modules/body-parser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.0.1.tgz", - "integrity": "sha512-PagxbjvuPH6tv0f/kdVbFGcb79D236SLcDTs6DrQ7GizJ88S1UWP4nMXFEo/I4fdhGRGabvFfFjVGm3M7U8JwA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.0.2.tgz", + "integrity": "sha512-SNMk0OONlQ01uk8EPeiBvTW7W4ovpL5b1O3t1sjpPgfxOQ6BqQJ6XjxinDPR79Z6HdcD5zBBwr5ssiTlgdNztQ==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -1633,11 +1646,10 @@ "on-finished": "2.4.1", "qs": "6.13.0", "raw-body": "^3.0.0", - "type-is": "~1.6.18", - "unpipe": "1.0.0" + "type-is": "~1.6.18" }, "engines": { - "node": ">= 0.10" + "node": ">=18" } }, "node_modules/body-parser/node_modules/debug": { @@ -1842,9 +1854,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001673", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001673.tgz", - "integrity": "sha512-WTrjUCSMp3LYX0nE12ECkV0a+e6LC85E0Auz75555/qr78Oc8YWhEPNfDd6SHdtlCMSzqtuXY0uyEMNRcsKpKw==", + "version": "1.0.30001677", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001677.tgz", + "integrity": "sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog==", "dev": true, "funding": [ { @@ -2065,9 +2077,9 @@ } }, "node_modules/cookie-signature": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.1.tgz", - "integrity": "sha512-78KWk9T26NhzXtuL26cIJ8/qNHANyJ/ZYrmEXFzUmhZdjpBv+DlWlOANRTGBt48YcyslsLrj0bMLFTmXvLRCOw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "engines": { "node": ">=6.6.0" } @@ -2270,9 +2282,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.5.47", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.47.tgz", - "integrity": "sha512-zS5Yer0MOYw4rtK2iq43cJagHZ8sXN0jDHDKzB+86gSBSAI4v07S97mcq+Gs2vclAxSh1j7vOAHxSVgduiiuVQ==", + "version": "1.5.50", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz", + "integrity": "sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==", "dev": true }, "node_modules/emittery": { @@ -2380,21 +2392,21 @@ } }, "node_modules/eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", + "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", + "@eslint/js": "9.14.0", "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -2402,9 +2414,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2440,9 +2452,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -2456,9 +2468,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2468,14 +2480,14 @@ } }, "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4594,13 +4606,13 @@ } }, "node_modules/mongoose": { - "version": "8.7.3", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.7.3.tgz", - "integrity": "sha512-Xl6+dzU5ZpEcDoJ8/AyrIdAwTY099QwpolvV73PIytpK13XqwllLq/9XeVzzLEQgmyvwBVGVgjmMrKbuezxrIA==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.8.0.tgz", + "integrity": "sha512-KluvgwnQB1GPOYZZXUHJRjS1TW6xxwTlf/YgjWExuuNanIe3W7VcR7dDXQVCIRk8L7NYge8EnoTcu2grWtN+XQ==", "dependencies": { "bson": "^6.7.0", "kareem": "2.6.3", - "mongodb": "6.9.0", + "mongodb": "~6.10.0", "mpath": "0.9.0", "mquery": "5.0.0", "ms": "2.1.3", @@ -4614,51 +4626,6 @@ "url": "https://opencollective.com/mongoose" } }, - "node_modules/mongoose/node_modules/mongodb": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.9.0.tgz", - "integrity": "sha512-UMopBVx1LmEUbW/QE0Hw18u583PEDVQmUmVzzBRH0o/xtE9DBRA5ZYLOjpLIa03i8FXjzvQECJcqoMvCXftTUA==", - "dependencies": { - "@mongodb-js/saslprep": "^1.1.5", - "bson": "^6.7.0", - "mongodb-connection-string-url": "^3.0.0" - }, - "engines": { - "node": ">=16.20.1" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.1.0", - "gcp-metadata": "^5.2.0", - "kerberos": "^2.0.1", - "mongodb-client-encryption": ">=6.0.0 <7", - "snappy": "^7.2.2", - "socks": "^2.7.1" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "gcp-metadata": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - }, - "socks": { - "optional": true - } - } - }, "node_modules/mpath": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", @@ -4711,9 +4678,9 @@ } }, "node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.4.tgz", - "integrity": "sha512-wpUq+QiKxrWk7U2pdvNSY9fNX62/k+7eEdlQMO0A3rU8tQ+vvzY/WzBhMz+GbQlATXZlXWYQqFWNFcn1SVvThA==", + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.1" @@ -6040,9 +6007,9 @@ } }, "node_modules/tslib": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", - "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/type-check": { "version": "0.4.0", diff --git a/package.json b/package.json index a19fc66..27c7be5 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "jsonwebtoken": "^9.0.2", "moment": "^2.30.1", "mongodb": "^6.10.0", - "mongoose": "^8.7.3", + "mongoose": "^8.8.0", "pino": "^9.5.0", "pino-pretty": "^11.3.0", "swagger-ui-express": "^5.0.1", @@ -59,7 +59,7 @@ }, "devDependencies": { "env-cmd": "^10.1.0", - "eslint": "^9.13.0", + "eslint": "^9.14.0", "jest": "^29.7.0", "jest-sonar-reporter": "^2.0.0", "node-notifier": "^10.0.1", diff --git a/requests/Switcher API.postman_collection.json b/requests/Switcher API.postman_collection.json index 0c5790e..7674702 100644 --- a/requests/Switcher API.postman_collection.json +++ b/requests/Switcher API.postman_collection.json @@ -5918,8 +5918,8 @@ "body": { "mode": "graphql", "graphql": { - "query": "query Domain(\r\n $_id: String, \r\n $name: String, \r\n $activated: Boolean, \r\n $environment: String, \r\n $_component: String) {\r\n domain(\r\n _id: $_id, \r\n name: $name, \r\n activated: $activated, \r\n environment: $environment,\r\n _component: $_component\r\n ) {\r\n _id\r\n name\r\n version\r\n description\r\n statusByEnv {\r\n env\r\n value\r\n }\r\n activated\r\n group {\r\n _id\r\n name\r\n description\r\n activated\r\n statusByEnv {\r\n env\r\n value\r\n }\r\n config {\r\n _id\r\n key\r\n description\r\n activated\r\n statusByEnv {\r\n env\r\n value\r\n }\r\n strategies {\r\n _id\r\n strategy\r\n activated\r\n statusByEnv {\r\n env\r\n value\r\n }\r\n operation\r\n values\r\n }\r\n components\r\n }\r\n }\r\n }\r\n}", - "variables": "{\r\n \"_id\": \"\",\r\n \"activated\": true,\r\n \"environment\": \"\",\r\n \"_component\": \"\"\r\n}" + "query": "query Domain(\r\n $_id: String, \r\n $name: String, \r\n $activated: Boolean, \r\n $environment: String, \r\n $_component: String) {\r\n domain(\r\n _id: $_id, \r\n name: $name, \r\n activated: $activated, \r\n environment: $environment,\r\n _component: $_component\r\n ) {\r\n _id\r\n name\r\n version\r\n description\r\n statusByEnv {\r\n env\r\n value\r\n }\r\n activated\r\n group {\r\n _id\r\n name\r\n description\r\n activated\r\n statusByEnv {\r\n env\r\n value\r\n }\r\n config {\r\n _id\r\n key\r\n description\r\n activated\r\n statusByEnv {\r\n env\r\n value\r\n }\r\n strategies {\r\n _id\r\n strategy\r\n activated\r\n statusByEnv {\r\n env\r\n value\r\n }\r\n operation\r\n values\r\n }\r\n relay {\r\n relay_type\r\n relay_method\r\n relay_endpoint\r\n description\r\n activated\r\n statusByEnv {\r\n env\r\n value\r\n }\r\n }\r\n components\r\n }\r\n }\r\n }\r\n}", + "variables": "{\r\n \"_id\": \"5e44eb76916dd10048d72542\",\r\n \"activated\": true,\r\n \"environment\": \"\",\r\n \"_component\": \"\"\r\n}" } }, "url": { diff --git a/src/client/configuration-type.js b/src/client/configuration-type.js index 96fef6a..f2ff27f 100644 --- a/src/client/configuration-type.js +++ b/src/client/configuration-type.js @@ -1,5 +1,5 @@ import { GraphQLObjectType, GraphQLString, GraphQLList, GraphQLBoolean, GraphQLFloat } from 'graphql'; -import { resolveConfigStrategy, resolveConfig, resolveGroupConfig, resolveEnvStatus } from './resolvers.js'; +import { resolveConfigStrategy, resolveConfig, resolveGroupConfig, resolveEnvStatus, resolveRelay } from './resolvers.js'; import { EnvType } from '../models/environment.js'; import { resolveFlatDomain, @@ -53,6 +53,43 @@ export const strategyType = new GraphQLObjectType({ } }); +export const relayType = new GraphQLObjectType({ + name: 'Relay', + fields: { + relay_type: { + type: GraphQLString, + resolve: (source) => source.type + }, + relay_method: { + type: GraphQLString, + resolve: (source) => source.method + }, + relay_endpoint: { + type: GraphQLString, + resolve: (source, _args, { environment }) => { + return source.endpoint[`${environment}`] === undefined ? + source.endpoint[`${EnvType.DEFAULT}`] : source.endpoint[`${environment}`]; + } + }, + description: { + type: GraphQLString + }, + activated: { + type: GraphQLBoolean, + resolve: (source, _args, { environment }) => { + return source.activated[`${environment}`] === undefined ? + source.activated[`${EnvType.DEFAULT}`] : source.activated[`${environment}`]; + } + }, + statusByEnv: { + type: new GraphQLList(envStatus), + resolve: (source) => { + return resolveEnvStatus(source); + } + }, + } +}); + export const configType = new GraphQLObjectType({ name: 'Config', fields: { @@ -103,6 +140,12 @@ export const configType = new GraphQLObjectType({ resolve: async (source) => { return resolveComponents(source); } + }, + relay: { + type: relayType, + resolve: (source, _args, context) => { + return resolveRelay(source, context); + } } } }); diff --git a/src/client/resolvers.js b/src/client/resolvers.js index 462999a..9f89adb 100644 --- a/src/client/resolvers.js +++ b/src/client/resolvers.js @@ -52,6 +52,17 @@ export async function resolveConfigStrategy(source, _id, strategy, operation, ac return strategies; } +export async function resolveRelay(source, context) { + const relay = source.relay; + const environment = context.environment ? context.environment : EnvType.DEFAULT; + + if (!relay.type || !relay.activated[environment] || !relay.endpoint[environment]) { + return null; + } + + return relay; +} + export async function resolveConfig(source, _id, key, activated, context) { const args = {}; @@ -62,7 +73,7 @@ export async function resolveConfig(source, _id, key, activated, context) { let configs = await Config.find({ group: source._id, ...args }).lean().exec(); if (activated !== undefined) { - configs = configs.filter(config => config.activated[context.environment || EnvType.DEFAULT] === activated); + configs = configs.filter(config => isElementActive(config, context.environment, activated)); } try { @@ -87,7 +98,7 @@ export async function resolveGroupConfig(source, _id, name, activated, context) let groups = await GroupConfig.find({ domain: source._id, ...args }).lean().exec(); if (activated !== undefined) { - groups = groups.filter(group => group.activated[context.environment || EnvType.DEFAULT] === activated); + groups = groups.filter(group => isElementActive(group, context.environment, activated)); } try { @@ -119,7 +130,7 @@ export async function resolveDomain(_id, name, activated, context) { } let domain = await Domain.findOne({ ...args }).lean().exec(); - if (activated !== undefined && domain?.activated[context.environment || EnvType.DEFAULT] !== activated) { + if (activated !== undefined && !isElementActive(domain, context.environment, activated)) { return null; } @@ -135,6 +146,18 @@ export async function resolveDomain(_id, name, activated, context) { return domain; } +/** + * Elemeents (Domain, Group, Config) can be activated in different environments. + * When the environment is not defined, the default environment activated flag is used. + */ +function isElementActive(element, environment, activated) { + if (element?.activated[environment || EnvType.DEFAULT] === undefined) { + return element?.activated[EnvType.DEFAULT] === activated; + } + + return element?.activated[environment || EnvType.DEFAULT] === activated; +} + /** * Resolve components first is used by SDKs to filter only configurations in which the component * exists resulting in a snapshot size reduction. diff --git a/src/services/config.js b/src/services/config.js index 1ee30b3..a15424c 100644 --- a/src/services/config.js +++ b/src/services/config.js @@ -331,7 +331,7 @@ export function isRelayValid(relay) { } const foundNotHttps = Object.values(relay.endpoint) - .filter(endpoint => !endpoint.toLowerCase().startsWith('https')); + .filter(endpoint => !String(endpoint).toLowerCase().startsWith('https')); if (foundNotHttps.length) { throw new BadRequestError('HTTPS required'); diff --git a/tests/client-api.test.js b/tests/client-api.test.js index 16a325a..1a0cbd7 100644 --- a/tests/client-api.test.js +++ b/tests/client-api.test.js @@ -57,6 +57,16 @@ describe('Testing domain', () => { expect(JSON.parse(req.text)).toMatchObject(JSON.parse(graphqlUtils.expected102)); }); + test('CLIENT_SUITE - Should return the Domain structure for Environment', async () => { + const req = await request(app) + .post('/adm-graphql') + .set('Authorization', `Bearer ${adminMasterAccountToken}`) + .send(graphqlUtils.domainQuery([['_id', domainId], ['environment', 'QA']], true, true, true)); + + expect(req.statusCode).toBe(200); + expect(JSON.parse(req.text)).toMatchObject(JSON.parse(graphqlUtils.expectedQA102)); + }); + test('CLIENT_SUITE - Should return 2 switchers when NOT filtered by Component', async () => { const req = await request(app) .post('/adm-graphql') diff --git a/tests/fixtures/db_client.js b/tests/fixtures/db_client.js index 698a0fb..013993d 100644 --- a/tests/fixtures/db_client.js +++ b/tests/fixtures/db_client.js @@ -5,7 +5,7 @@ import { randomUUID } from 'crypto'; import Admin from '../../src/models/admin'; import Domain from '../../src/models/domain'; import GroupConfig from '../../src/models/group-config'; -import { Config } from '../../src/models/config'; +import { Config, RelayMethods, RelayTypes } from '../../src/models/config'; import Component from '../../src/models/component'; import History from '../../src/models/history'; import { Metric } from '../../src/models/metric'; @@ -100,7 +100,14 @@ export const configDocument = { owner: adminMasterAccountId, components: [], group: groupConfigId, - domain: domainId + domain: domainId, + relay: { + type: RelayTypes.NOTIFICATION, + method: RelayMethods.POST, + endpoint: new Map().set(EnvType.DEFAULT, 'http://localhost:3000'), + description: 'Test Relay', + activated: new Map().set(EnvType.DEFAULT, true) + } }; export const configStrategyUSERId = new mongoose.Types.ObjectId(); diff --git a/tests/graphql-utils/index.js b/tests/graphql-utils/index.js index 38f8602..4f412fe 100644 --- a/tests/graphql-utils/index.js +++ b/tests/graphql-utils/index.js @@ -42,6 +42,17 @@ export const domainQuery = (where, group, config, strategy) => { strategies${elementQuery(strategy)} { strategy activated operation values statusByEnv { env value } } + relay { + relay_type + relay_method + relay_endpoint + description + activated + statusByEnv { + env + value + } + } components } } @@ -172,7 +183,49 @@ export const expected102 = ` "values":[ "10.0.0.0/24" ] - }] + }], + "relay": { + "relay_type": "NOTIFICATION", + "relay_method": "POST", + "relay_endpoint": "http://localhost:3000", + "description": "Test Relay", + "activated": true + } + }] + }] + } + } +}`; + +export const expectedQA102 = ` +{ + "data": { + "domain": { + "name": "Domain", + "version": 5, + "description": "Test Domain", + "activated": true, + "group": [{ + "name": "Group Test", + "description": "Test Group", + "activated": true, + "config": [{ + "key": "TEST_CONFIG_KEY", + "description": "Test config 1", + "activated": true, + "strategies": [], + "relay": null, + "components": [ + "TestApp" + ] + }, + { + "key": "TEST_CONFIG_KEY_PRD_QA", + "description": "Test config 2 - Off in PRD and ON in QA", + "activated": true, + "strategies": [], + "relay": null, + "components": [] }] }] }