diff --git a/package-lock.json b/package-lock.json index e835904443..2ecc5c21eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -314,6 +314,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -853,18 +854,6 @@ "dev": true, "license": "MIT" }, - "lib/msal-angular/node_modules/@angular-devkit/build-angular/node_modules/@types/node": { - "version": "25.2.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.3.tgz", - "integrity": "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "undici-types": "~7.16.0" - } - }, "lib/msal-angular/node_modules/@angular-devkit/build-angular/node_modules/@vitejs/plugin-basic-ssl": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.2.0.tgz", @@ -1042,6 +1031,7 @@ "integrity": "sha512-c76x1t+OiSstPsvJdHmV8Q4taF+8SxWKqiY750fOjpd01it4jJbU6YQqIroC6Xie7154zZIxOTHH2uTj+nm5qA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -1059,6 +1049,7 @@ "integrity": "sha512-CrV02Omzw/QtfjlEVXVPJVXipdx83NuA+qSASZYrxrhKFusUZyK3P/Zznqg+wiAeNDbedQwMUVqoAARHf0xQrw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -1076,6 +1067,7 @@ "integrity": "sha512-N4TMtLfImJIoMaRL6mx7885UBeQidywptHH6ACZj71Ar6++DBc1mMlcwuvbeJCd3r3y8MQ5nLv5PZSN/tHr13w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "7.26.9", "@jridgewell/sourcemap-codec": "^1.4.14", @@ -1150,6 +1142,7 @@ "integrity": "sha512-+QRrf0Igt8ccUWXHA+7doK5W6ODyhHdqVyblSlcQ8OciwkzIIGGEYNZom5OZyWMh+oI54lcSeyV2O3xaDepSrQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -1186,6 +1179,7 @@ "integrity": "sha512-eahtsHPyXTYLARs9YOlXhnXGgzw0wcyOcDkBvNWK/3lA0NHIgIHmQgXAmBo+cJ+g9skiEQTD2OmSrrwbFKWJkw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -1246,6 +1240,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -1839,6 +1834,7 @@ "resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-19.2.2.tgz", "integrity": "sha512-dFuwFsDJMBSd1YtmLLcX5bNNUCQUlRqgf34aXA+79PmkOP+0eF8GP2949wq3+jMjmFTNm80Oo8IUYiSLwklKCQ==", "dev": true, + "peer": true, "dependencies": { "@rollup/plugin-json": "^6.1.0", "@rollup/wasm-node": "^4.24.0", @@ -1925,6 +1921,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", @@ -2103,6 +2100,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2117,8 +2115,7 @@ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "lib/msal-angular/node_modules/watchpack": { "version": "2.4.2", @@ -2139,6 +2136,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz", "integrity": "sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==", "dev": true, + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", @@ -2281,6 +2279,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.57.tgz", "integrity": "sha512-f3T4y6VU4fVQDKVqJV4Uppy8c1p/sVvS3peyqxyWnzkqXFJLRU7Y1Bl7rMS1Qe9z0v4M6McY0Fp9yBsgHJUsWQ==", "dev": true, + "peer": true, "dependencies": { "undici-types": "~6.19.2" } @@ -3204,6 +3203,7 @@ "integrity": "sha512-3MscvODxRVxc3Cs0ZlHI5Pk5rEvE80otfvxZTMksOZuPlv1B+S8MjWfc3X3jk9SbyUEzODBEH55iCaBHD48V3g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -3216,7 +3216,6 @@ "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz", "integrity": "sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==", "dev": true, - "peer": true, "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", @@ -3234,7 +3233,6 @@ "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", "dev": true, - "peer": true, "engines": { "node": ">=10" } @@ -3243,15 +3241,13 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@apidevtools/swagger-parser": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.1.1.tgz", "integrity": "sha512-u/kozRnsPO/x8QtKYJOqoGtC4kH6yg1lfYkB9Au0WhYB0FNLpyFusttQtvhlwjtG3rOwiRz4D8DnnXa8iEpIKA==", "dev": true, - "peer": true, "dependencies": { "@apidevtools/json-schema-ref-parser": "11.7.2", "@apidevtools/openapi-schemas": "^2.1.0", @@ -3287,7 +3283,6 @@ "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", "dev": true, - "peer": true, "peerDependencies": { "ajv": "^8.5.0" }, @@ -3313,7 +3308,6 @@ "resolved": "https://registry.npmjs.org/@azure/arm-appservice/-/arm-appservice-13.0.3.tgz", "integrity": "sha512-Vu011o3/bikQNwtjouwmUJud+Z6Brcjij2D0omPWClRGg8i5gBfOYSpDkFGkHbhGlaky4fgvfkxD0uHGq34uYA==", "dev": true, - "peer": true, "dependencies": { "@azure/abort-controller": "^1.0.0", "@azure/core-auth": "^1.3.0", @@ -3332,7 +3326,6 @@ "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", "dev": true, - "peer": true, "dependencies": { "tslib": "^2.2.0" }, @@ -3345,7 +3338,6 @@ "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.1.tgz", "integrity": "sha512-JbZtIqfEulsIA0rC3zM7jfF4KkOnye9aKcaO/jJqxJRm/gM6lAjEv7sL4njW8D+35l50P1f+UuH5OqN+UKJqNA==", "dev": true, - "peer": true, "dependencies": { "@azure/abort-controller": "^1.0.0", "@azure/core-auth": "^1.3.0", @@ -3364,7 +3356,6 @@ "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", "dev": true, - "peer": true, "dependencies": { "tslib": "^2.2.0" }, @@ -3377,7 +3368,6 @@ "resolved": "https://registry.npmjs.org/@azure/arm-storage/-/arm-storage-17.2.1.tgz", "integrity": "sha512-J2jmTPv8ZraSHDTz9l2Bx8gNL3ktfDDWo2mxWfzarn64O9Fjhb+l85YWyubGy2xUdeGuZPKzvQLltGv8bSu8eQ==", "dev": true, - "peer": true, "dependencies": { "@azure/abort-controller": "^1.0.0", "@azure/core-auth": "^1.3.0", @@ -3396,7 +3386,6 @@ "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", "dev": true, - "peer": true, "dependencies": { "tslib": "^2.2.0" }, @@ -3409,7 +3398,6 @@ "resolved": "https://registry.npmjs.org/@azure/arm-subscriptions/-/arm-subscriptions-5.1.0.tgz", "integrity": "sha512-6BeOF2eQWNLq22ch7xP9RxYnPjtGev54OUCGggKOWoOvmesK7jUZbIyLk8JeXDT21PEl7iyYnxw78gxJ7zBxQw==", "dev": true, - "peer": true, "dependencies": { "@azure/abort-controller": "^1.0.0", "@azure/core-auth": "^1.3.0", @@ -3428,7 +3416,6 @@ "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", "dev": true, - "peer": true, "dependencies": { "tslib": "^2.2.0" }, @@ -3751,6 +3738,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -4558,6 +4546,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.27.1.tgz", "integrity": "sha512-p9OkPbZ5G7UT1MofwYFigGebnrzGJacoBSQM0/6bi/PUMVE+qlWDD/OalvQKbwgQzU6dl0xAv6r4X7Jme0RYxA==", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -6147,6 +6136,7 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -6267,6 +6257,7 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -8664,6 +8655,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "peer": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -8710,15 +8702,13 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@feathersjs/hooks": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/@feathersjs/hooks/-/hooks-0.6.5.tgz", "integrity": "sha512-WtcEoG/imdHRvC3vofGi/OcgH+cjHHhO0AfEeTlsnrKLjVKKBXV6aoIrB2nHZPpE7iW5sA7AZMR6bPD8ytxN+w==", "dev": true, - "peer": true, "engines": { "node": ">= 10" } @@ -9484,6 +9474,7 @@ "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.3.2.tgz", "integrity": "sha512-G1ytyOoHh5BphmEBxSwALin3n1KGNYB6yImbICcRQdzXfOGbuJ9Jske/Of5Sebk339NSGGNfUshnzK8YWkTPsQ==", "dev": true, + "peer": true, "dependencies": { "@inquirer/checkbox": "^4.1.2", "@inquirer/confirm": "^5.1.6", @@ -9932,50 +9923,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, - "node_modules/@jest/core/node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "optional": true, - "peer": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, "node_modules/@jest/diff-sequences": { "version": "30.0.1", "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", @@ -10338,8 +10285,7 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@jsonjoy.com/base64": { "version": "1.1.2", @@ -10663,7 +10609,6 @@ "resolved": "https://registry.npmjs.org/@microsoft/app-manifest/-/app-manifest-1.0.1.tgz", "integrity": "sha512-W4fw8JX/9CPATwNAi9dc25rCK/b3qSnoClVDzGfbYuy6ewY9FHgkwk/C1NzC8k/YwZAsKwMhHOvXUCt3u9ak3Q==", "dev": true, - "peer": true, "dependencies": { "@types/fs-extra": "^11.0.1", "@types/node-fetch": "^2.6.9", @@ -10678,7 +10623,6 @@ "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", "dev": true, - "peer": true, "dependencies": { "@types/jsonfile": "*", "@types/node": "*" @@ -10706,7 +10650,6 @@ "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", "dev": true, - "peer": true, "peerDependencies": { "ajv": "^8.5.0" }, @@ -10721,7 +10664,6 @@ "resolved": "https://registry.npmjs.org/@microsoft/dev-tunnels-contracts/-/dev-tunnels-contracts-1.1.9.tgz", "integrity": "sha512-OayhehwI+CnO0Wr53e29ZJZWGsNA5yVG7r54qmZSLc5HxA5Cozk4hP7EbYDCXkxh4NbQoT1dhTzC8bkRo+wWXw==", "dev": true, - "peer": true, "dependencies": { "buffer": "^5.2.1", "debug": "^4.1.1", @@ -10733,7 +10675,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -10751,7 +10692,6 @@ "resolved": "https://registry.npmjs.org/@microsoft/dev-tunnels-management/-/dev-tunnels-management-1.1.9.tgz", "integrity": "sha512-wGuFEzvRiWZmDxQMGKEjOKhEIVnLiG6vRUuM9Hwqxpe/kbiyA2WiUyEVpniNPaaw8gDHTf9zJHnPNNj0JiL5mA==", "dev": true, - "peer": true, "dependencies": { "@microsoft/dev-tunnels-contracts": ">1.1.8", "axios": "^1.6.2", @@ -10765,7 +10705,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -10783,7 +10722,6 @@ "resolved": "https://registry.npmjs.org/@microsoft/m365-spec-parser/-/m365-spec-parser-0.2.8.tgz", "integrity": "sha512-G26jdZo6TQNEwpsY95p96RWLtuqzGhrqPFacKJgtODlWmYGj63InMvSdwTDNlZ610SdA9nZUqvULFWmDE/VNqg==", "dev": true, - "peer": true, "dependencies": { "@apidevtools/swagger-parser": "^10.1.1", "@microsoft/app-manifest": "1.0.1", @@ -10801,7 +10739,6 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", "dev": true, - "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -10841,6 +10778,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -10887,7 +10825,6 @@ "integrity": "sha512-AowuJwrrUxeF9Bq/frxuy9YZjK/ECk3pi0UBXl3CQLZ4XNWfgWatiFi/UWpyHDLccFs+0Za3nNYATFvgsxEFwQ==", "dev": true, "hasInstallScript": true, - "peer": true, "dependencies": { "@azure/arm-subscriptions": "^5.0.0", "@azure/core-auth": "^1.4.0", @@ -10930,7 +10867,6 @@ "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.16.0.tgz", "integrity": "sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA==", "dev": true, - "peer": true, "engines": { "node": ">=0.8.0" } @@ -10940,7 +10876,6 @@ "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.16.2.tgz", "integrity": "sha512-An7l1hEr0w1HMMh1LU+rtDtqL7/jw74ORlc9Wnh06v7TU/xpG39/Zdr1ZJu3QpjUfKJ+E0/OXMW8DRSWTlh7qQ==", "dev": true, - "peer": true, "dependencies": { "@azure/msal-common": "14.16.0", "jsonwebtoken": "^9.0.0", @@ -10955,7 +10890,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-1.5.2.tgz", "integrity": "sha512-CifrkgQjDkUkWexmgYYNyB5603HhTHI91vLFeQXh6qrTKiCMVASol01Rs1cv6LP/A2WccZSRlJKZhbaBIs/9ZA==", "dev": true, - "peer": true, "dependencies": { "@inquirer/core": "^6.0.0", "@inquirer/type": "^1.1.6", @@ -10972,7 +10906,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-6.0.0.tgz", "integrity": "sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw==", "dev": true, - "peer": true, "dependencies": { "@inquirer/type": "^1.1.6", "@types/mute-stream": "^0.0.4", @@ -10998,7 +10931,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-2.0.17.tgz", "integrity": "sha512-EqzhGryzmGpy2aJf6LxJVhndxYmFs+m8cxXzf8nejb1DE3sabf6mUgBcp4J0jAUEiAcYzqmkqRr7LPFh/WdnXA==", "dev": true, - "peer": true, "dependencies": { "@inquirer/core": "^6.0.0", "@inquirer/type": "^1.1.6", @@ -11013,7 +10945,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-6.0.0.tgz", "integrity": "sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw==", "dev": true, - "peer": true, "dependencies": { "@inquirer/type": "^1.1.6", "@types/mute-stream": "^0.0.4", @@ -11039,7 +10970,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-5.1.2.tgz", "integrity": "sha512-w3PMZH5rahrukn8/I7P9Ihil+twgLTUHDZtJlJyBbUKyPaOSSQjLZkb0PpncVhin1gCaMgOFXy6iNPgcZUoo2w==", "dev": true, - "peer": true, "dependencies": { "@inquirer/type": "^1.1.6", "@types/mute-stream": "^0.0.4", @@ -11065,7 +10995,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-1.2.15.tgz", "integrity": "sha512-gQ77Ls09x5vKLVNMH9q/7xvYPT6sIs5f7URksw+a2iJZ0j48tVS6crLqm2ugG33tgXHIwiEqkytY60Zyh5GkJQ==", "dev": true, - "peer": true, "dependencies": { "@inquirer/core": "^6.0.0", "@inquirer/type": "^1.1.6", @@ -11081,7 +11010,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-6.0.0.tgz", "integrity": "sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw==", "dev": true, - "peer": true, "dependencies": { "@inquirer/type": "^1.1.6", "@types/mute-stream": "^0.0.4", @@ -11107,7 +11035,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-1.1.16.tgz", "integrity": "sha512-TGLU9egcuo+s7PxphKUCnJnpCIVY32/EwPCLLuu+gTvYiD8hZgx8Z2niNQD36sa6xcfpdLY6xXDBiL/+g1r2XQ==", "dev": true, - "peer": true, "dependencies": { "@inquirer/core": "^6.0.0", "@inquirer/type": "^1.1.6", @@ -11123,7 +11050,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-6.0.0.tgz", "integrity": "sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw==", "dev": true, - "peer": true, "dependencies": { "@inquirer/type": "^1.1.6", "@types/mute-stream": "^0.0.4", @@ -11149,7 +11075,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-1.2.16.tgz", "integrity": "sha512-Ou0LaSWvj1ni+egnyQ+NBtfM1885UwhRCMtsRt2bBO47DoC1dwtCa+ZUNgrxlnCHHF0IXsbQHYtIIjFGAavI4g==", "dev": true, - "peer": true, "dependencies": { "@inquirer/core": "^6.0.0", "@inquirer/type": "^1.1.6", @@ -11164,7 +11089,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-6.0.0.tgz", "integrity": "sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw==", "dev": true, - "peer": true, "dependencies": { "@inquirer/type": "^1.1.6", "@types/mute-stream": "^0.0.4", @@ -11190,7 +11114,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-1.1.16.tgz", "integrity": "sha512-aZYZVHLUXZ2gbBot+i+zOJrks1WaiI95lvZCn1sKfcw6MtSSlYC8uDX8sTzQvAsQ8epHoP84UNvAIT0KVGOGqw==", "dev": true, - "peer": true, "dependencies": { "@inquirer/core": "^6.0.0", "@inquirer/type": "^1.1.6", @@ -11206,7 +11129,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-6.0.0.tgz", "integrity": "sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw==", "dev": true, - "peer": true, "dependencies": { "@inquirer/type": "^1.1.6", "@types/mute-stream": "^0.0.4", @@ -11232,7 +11154,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-3.3.2.tgz", "integrity": "sha512-k52mOMRvTUejrqyF1h8Z07chC+sbaoaUYzzr1KrJXyj7yaX7Nrh0a9vktv8TuocRwIJOQMaj5oZEmkspEcJFYQ==", "dev": true, - "peer": true, "dependencies": { "@inquirer/checkbox": "^1.5.2", "@inquirer/confirm": "^2.0.17", @@ -11253,7 +11174,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-6.0.0.tgz", "integrity": "sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw==", "dev": true, - "peer": true, "dependencies": { "@inquirer/type": "^1.1.6", "@types/mute-stream": "^0.0.4", @@ -11279,7 +11199,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-1.2.16.tgz", "integrity": "sha512-pZ6TRg2qMwZAOZAV6TvghCtkr53dGnK29GMNQ3vMZXSNguvGqtOVc4j/h1T8kqGJFagjyfBZhUPGwNS55O5qPQ==", "dev": true, - "peer": true, "dependencies": { "@inquirer/core": "^6.0.0", "@inquirer/type": "^1.1.6", @@ -11294,7 +11213,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-6.0.0.tgz", "integrity": "sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw==", "dev": true, - "peer": true, "dependencies": { "@inquirer/type": "^1.1.6", "@types/mute-stream": "^0.0.4", @@ -11320,7 +11238,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-1.3.3.tgz", "integrity": "sha512-RzlRISXWqIKEf83FDC9ZtJ3JvuK1l7aGpretf41BCWYrvla2wU8W8MTRNMiPrPJ+1SIqrRC1nZdZ60hD9hRXLg==", "dev": true, - "peer": true, "dependencies": { "@inquirer/core": "^6.0.0", "@inquirer/type": "^1.1.6", @@ -11337,7 +11254,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-6.0.0.tgz", "integrity": "sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw==", "dev": true, - "peer": true, "dependencies": { "@inquirer/type": "^1.1.6", "@types/mute-stream": "^0.0.4", @@ -11363,7 +11279,6 @@ "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.5.tgz", "integrity": "sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==", "dev": true, - "peer": true, "dependencies": { "mute-stream": "^1.0.0" }, @@ -11376,7 +11291,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.57.tgz", "integrity": "sha512-f3T4y6VU4fVQDKVqJV4Uppy8c1p/sVvS3peyqxyWnzkqXFJLRU7Y1Bl7rMS1Qe9z0v4M6McY0Fp9yBsgHJUsWQ==", "dev": true, - "peer": true, "dependencies": { "undici-types": "~6.19.2" } @@ -11386,7 +11300,6 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, - "peer": true, "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -11402,7 +11315,6 @@ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", "dev": true, - "peer": true, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -11412,7 +11324,6 @@ "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", "dev": true, - "peer": true, "engines": { "node": ">=0.12.0" } @@ -11422,7 +11333,6 @@ "resolved": "https://registry.npmjs.org/@microsoft/teamsfx-api/-/teamsfx-api-0.23.1.tgz", "integrity": "sha512-XmXX2dccOEU3lbYgOlijfwxmkXp6nO88JWx9P1al/1aMgbIeup2Y2H37Vmz2VwfIQC/i75FbbbbwqYjG2skQjQ==", "dev": true, - "peer": true, "dependencies": { "@azure/core-auth": "^1.4.0", "@microsoft/teams-manifest": "0.1.5", @@ -11438,7 +11348,6 @@ "resolved": "https://registry.npmjs.org/@microsoft/teamsfx-core/-/teamsfx-core-2.0.9.tgz", "integrity": "sha512-6zA/vvpHViROP6eDbnjS8PtPyyB4eZGH/cgTiOHeiRHznT9Pkd3rqFvaIHPEDhv2g76llHEk2gTFSqL7QFovAQ==", "dev": true, - "peer": true, "dependencies": { "@apidevtools/swagger-parser": "^10.1.0", "@azure/arm-appservice": "^13.0.0", @@ -11498,7 +11407,6 @@ "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.16.0.tgz", "integrity": "sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA==", "dev": true, - "peer": true, "engines": { "node": ">=0.8.0" } @@ -11508,7 +11416,6 @@ "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.16.2.tgz", "integrity": "sha512-An7l1hEr0w1HMMh1LU+rtDtqL7/jw74ORlc9Wnh06v7TU/xpG39/Zdr1ZJu3QpjUfKJ+E0/OXMW8DRSWTlh7qQ==", "dev": true, - "peer": true, "dependencies": { "@azure/msal-common": "14.16.0", "jsonwebtoken": "^9.0.0", @@ -11523,7 +11430,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -11540,7 +11446,6 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, - "peer": true, "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -11556,7 +11461,6 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, - "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -11568,8 +11472,7 @@ "version": "0.1.14", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@microsoft/tsdoc": { "version": "0.15.1", @@ -12148,6 +12051,7 @@ "version": "5.17.1", "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.17.1.tgz", "integrity": "sha512-2B33kQf+GmPnrvXXweWAx+crbiUEsxCdCN979QDYnlH9ox4pd+0/IBriWLV+l6ORoBF60w39cWjFnJYGFdzXcw==", + "peer": true, "dependencies": { "@babel/runtime": "^7.23.9", "@mui/core-downloads-tracker": "^5.17.1", @@ -13201,6 +13105,7 @@ "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", "dev": true, + "peer": true, "dependencies": { "@octokit/auth-token": "^2.4.4", "@octokit/graphql": "^4.5.8", @@ -13385,7 +13290,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -13406,7 +13310,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -13427,7 +13330,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -13448,7 +13350,6 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -13469,7 +13370,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -13490,7 +13390,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -13511,7 +13410,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -13532,7 +13430,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -13553,7 +13450,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -13574,7 +13470,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -13595,7 +13490,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -13616,7 +13510,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -13637,7 +13530,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -13773,6 +13665,7 @@ "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -13782,7 +13675,6 @@ "version": "2.10.5", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.5.tgz", "integrity": "sha512-eifa0o+i8dERnngJwKrfp3dEq7ia5XFyoqB17S4gK8GhsQE4/P8nxOfQSE0zQHxzzLo/cmF+7+ywEQ7wK7Fb+w==", - "peer": true, "dependencies": { "debug": "^4.4.1", "extract-zip": "^2.0.1", @@ -13803,7 +13695,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -13821,7 +13712,6 @@ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", "license": "MIT", - "peer": true, "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" @@ -13835,7 +13725,6 @@ "version": "3.1.7", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "peer": true, "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", @@ -13868,6 +13757,7 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz", "integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==", + "peer": true, "dependencies": { "cluster-key-slot": "1.1.2", "generic-pool": "3.9.0", @@ -14715,6 +14605,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", @@ -15669,8 +15560,7 @@ "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "peer": true + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" }, "node_modules/@trysound/sax": { "version": "0.2.0", @@ -15766,8 +15656,7 @@ "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, - "peer": true + "dev": true }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -15874,6 +15763,7 @@ "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -16128,7 +16018,6 @@ "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", "dev": true, - "peer": true, "dependencies": { "@types/node": "*" } @@ -16137,6 +16026,7 @@ "version": "22.15.29", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.29.tgz", "integrity": "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==", + "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -16360,8 +16250,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@types/ws": { "version": "8.18.1", @@ -16389,7 +16278,6 @@ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", "optional": true, - "peer": true, "dependencies": { "@types/node": "*" } @@ -17215,6 +17103,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -17342,6 +17231,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -17616,8 +17506,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/array-union": { "version": "2.1.0", @@ -17775,7 +17664,6 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, - "peer": true, "engines": { "node": "*" } @@ -17784,7 +17672,6 @@ "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "peer": true, "dependencies": { "tslib": "^2.0.1" }, @@ -17860,7 +17747,6 @@ "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.3.2.tgz", "integrity": "sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA==", "dev": true, - "peer": true, "dependencies": { "tslib": "^2.3.1" } @@ -17960,7 +17846,6 @@ "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.9.1.tgz", "integrity": "sha512-8PJDLJv7qTTMMwdnbMvrLYuvB47M81wRtxQmEdV5w4rgbTXTt+vtPkXwajOfOdSyv/wZICJOC+/UhXH4aQ/R+w==", "dev": true, - "peer": true, "dependencies": { "@babel/runtime": "^7.15.4", "is-retry-allowed": "^2.2.0" @@ -17981,8 +17866,7 @@ "node_modules/b4a": { "version": "1.6.7", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", - "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", - "peer": true + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==" }, "node_modules/babel-jest": { "version": "29.7.0", @@ -18353,15 +18237,13 @@ "version": "2.5.4", "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", - "optional": true, - "peer": true + "optional": true }, "node_modules/bare-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.1.5.tgz", "integrity": "sha512-1zccWBMypln0jEE05LzZt+V/8y8AQsQQqxtklqaIyg5nu6OAYFhZxPXinJTSG+kU5qyNmeLgcn9AW7eHiCHVLA==", "optional": true, - "peer": true, "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", @@ -18384,7 +18266,6 @@ "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.1.tgz", "integrity": "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==", "optional": true, - "peer": true, "engines": { "bare": ">=1.14.0" } @@ -18394,7 +18275,6 @@ "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", "optional": true, - "peer": true, "dependencies": { "bare-os": "^3.0.1" } @@ -18404,7 +18284,6 @@ "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.5.tgz", "integrity": "sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==", "optional": true, - "peer": true, "dependencies": { "streamx": "^2.21.0" }, @@ -18487,7 +18366,6 @@ "version": "5.0.5", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", - "peer": true, "engines": { "node": ">=10.0.0" } @@ -18834,6 +18712,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -19135,8 +19014,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/callsites": { "version": "3.1.0", @@ -19215,7 +19093,6 @@ "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", "dev": true, - "peer": true, "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.3", @@ -19234,7 +19111,6 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", "dev": true, - "peer": true, "engines": { "node": ">=4" } @@ -19284,7 +19160,6 @@ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", "dev": true, - "peer": true, "engines": { "node": "*" } @@ -19294,7 +19169,6 @@ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, - "peer": true, "dependencies": { "get-func-name": "^2.0.2" }, @@ -19312,6 +19186,7 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "devOptional": true, + "peer": true, "dependencies": { "readdirp": "^4.0.1" }, @@ -19343,7 +19218,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-5.1.0.tgz", "integrity": "sha512-9MSRhWRVoRPDG0TgzkHrshFSJJNZzfY5UFqUMuksg7zL1yoZIZ3jLB0YAgHclbiAxPI86pBnwDX1tbzoiV8aFw==", - "peer": true, "dependencies": { "mitt": "^3.0.1", "zod": "^3.24.1" @@ -19436,7 +19310,6 @@ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dev": true, - "peer": true, "dependencies": { "string-width": "^4.2.0" }, @@ -19451,15 +19324,13 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "peer": true + "dev": true }, "node_modules/cli-table3/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -19469,7 +19340,6 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -19805,7 +19675,6 @@ "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz", "integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==", "dev": true, - "peer": true, "dependencies": { "array-timsort": "^1.0.3", "core-util-is": "^1.0.3", @@ -20296,50 +20165,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, - "node_modules/create-jest/node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "optional": true, - "peer": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -20483,7 +20308,6 @@ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", "dev": true, - "peer": true, "engines": { "node": "*" } @@ -20500,8 +20324,7 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/cryptr/-/cryptr-6.3.0.tgz", "integrity": "sha512-TA4byAuorT8qooU9H8YJhBwnqD151i1rcauHfJ3Divg6HmukHB2AYMp0hmjv2873J2alr4t15QqC7zAnWFrtfQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/css-blank-pseudo": { "version": "3.0.3", @@ -20973,7 +20796,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", - "peer": true, "engines": { "node": ">= 14" } @@ -21053,8 +20875,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", - "optional": true, - "peer": true + "optional": true }, "node_modules/debounce": { "version": "1.2.1", @@ -21123,7 +20944,6 @@ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", "dev": true, - "peer": true, "dependencies": { "type-detect": "^4.0.0" }, @@ -21257,7 +21077,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "peer": true, "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", @@ -21341,7 +21160,6 @@ "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", "dev": true, - "peer": true, "dependencies": { "address": "^1.0.1", "debug": "4" @@ -21375,7 +21193,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -22475,6 +22292,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "peer": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -22580,7 +22398,6 @@ "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", "dev": true, "optional": true, - "peer": true, "dependencies": { "prr": "~1.0.1" }, @@ -22787,8 +22604,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", - "dev": true, - "peer": true + "dev": true }, "node_modules/esbuild": { "version": "0.25.4", @@ -22908,6 +22724,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "peer": true, "dependencies": { "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.4.3", @@ -23848,6 +23665,7 @@ "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "license": "MIT", + "peer": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -23961,6 +23779,7 @@ "version": "1.18.2", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.2.tgz", "integrity": "sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A==", + "peer": true, "dependencies": { "cookie": "0.7.2", "cookie-signature": "1.0.7", @@ -24110,8 +23929,7 @@ "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "peer": true + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" }, "node_modules/fast-glob": { "version": "3.3.3", @@ -24153,8 +23971,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/fast-uri": { "version": "3.0.6", @@ -24982,7 +24799,6 @@ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, - "peer": true, "engines": { "node": "*" } @@ -25150,7 +24966,6 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", - "peer": true, "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", @@ -25164,7 +24979,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -25579,7 +25393,6 @@ "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -25725,6 +25538,7 @@ "integrity": "sha512-Eaw2YTGM6WOxA6CXbckaEvslr2Ne4NFsKrvc0v97JD5awbmeBLO5w9Ho9L9kmKonrwF9RJlW6BxT1PVv/agBHQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=16.9.0" } @@ -26134,8 +25948,7 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/http2-wrapper": { "version": "1.0.3", @@ -26321,7 +26134,6 @@ "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", "dev": true, "optional": true, - "peer": true, "bin": { "image-size": "bin/image-size.js" }, @@ -26697,8 +26509,7 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true, - "peer": true + "dev": true }, "node_modules/is-bun-module": { "version": "2.0.0", @@ -27019,7 +26830,6 @@ "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", "dev": true, - "peer": true, "engines": { "node": ">=10" }, @@ -27408,7 +27218,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.0.1.tgz", "integrity": "sha512-w+JDABxQCkxbGGxg+a2hUVZyqUS2JKngvIyLGu/xiw2ZwgsoSB0iiecLQsQORSeaKQ6iGrCyWG86RfNDuoA7Lg==", - "dev": true + "dev": true, + "peer": true }, "node_modules/jasmine-spec-reporter": { "version": "5.0.2", @@ -27423,6 +27234,7 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -27621,50 +27433,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, - "node_modules/jest-cli/node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "optional": true, - "peer": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -27768,6 +27536,7 @@ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", "dev": true, + "peer": true, "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", @@ -28820,6 +28589,7 @@ "version": "1.21.7", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -28842,8 +28612,7 @@ "version": "3.7.7", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.7.tgz", "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/js-tokens": { "version": "4.0.0", @@ -29129,7 +28898,6 @@ "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.5.0.tgz", "integrity": "sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==", "dev": true, - "peer": true, "engines": { "node": "*" } @@ -29236,6 +29004,7 @@ "integrity": "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@colors/colors": "1.5.0", "body-parser": "^1.19.0", @@ -29663,7 +29432,6 @@ "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", "dev": true, - "peer": true, "dependencies": { "graceful-fs": "^4.1.9" } @@ -29714,6 +29482,7 @@ "resolved": "https://registry.npmjs.org/less/-/less-4.2.2.tgz", "integrity": "sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg==", "dev": true, + "peer": true, "dependencies": { "copy-anything": "^2.0.1", "parse-node-version": "^1.0.1", @@ -29767,7 +29536,6 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, "optional": true, - "peer": true, "bin": { "mime": "cli.js" }, @@ -29781,7 +29549,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "optional": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -30322,7 +30089,6 @@ "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, - "peer": true, "dependencies": { "get-func-name": "^2.0.1" } @@ -30388,7 +30154,6 @@ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, - "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -30591,7 +30356,6 @@ "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", "dev": true, - "peer": true, "dependencies": { "charenc": "0.0.2", "crypt": "0.0.2", @@ -30914,8 +30678,7 @@ "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", - "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", - "peer": true + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==" }, "node_modules/mkcert": { "version": "3.2.0", @@ -31141,7 +30904,6 @@ "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", "dev": true, - "peer": true, "bin": { "mustache": "bin/mustache" } @@ -31218,7 +30980,6 @@ "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", "dev": true, "optional": true, - "peer": true, "dependencies": { "iconv-lite": "^0.6.3", "sax": "^1.2.4" @@ -31236,7 +30997,6 @@ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "optional": true, - "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -31261,7 +31021,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "peer": true, "engines": { "node": ">= 0.4.0" } @@ -31270,8 +31029,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/neverthrow/-/neverthrow-3.2.0.tgz", "integrity": "sha512-AINA32QbYO83L+3CBI6I5lH4LpBSlLwWteJ+uI25s4AQy6g/xz3RZuedmuNo91lLw2rY+AbPEPQdxd7mg1rXoQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/next": { "version": "15.5.12", @@ -31436,7 +31194,6 @@ "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", "dev": true, - "peer": true, "dependencies": { "http2-client": "^1.2.5" }, @@ -31877,15 +31634,13 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/node-readfiles": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz", "integrity": "sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==", "dev": true, - "peer": true, "dependencies": { "es6-promise": "^3.2.1" } @@ -32664,7 +32419,6 @@ "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", "dev": true, - "peer": true, "dependencies": { "fast-safe-stringify": "^2.0.7" } @@ -32674,7 +32428,6 @@ "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz", "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==", "dev": true, - "peer": true, "dependencies": { "@exodus/schemasafe": "^1.0.0-rc.2", "should": "^13.2.1", @@ -32689,7 +32442,6 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, - "peer": true, "engines": { "node": ">= 6" } @@ -32699,7 +32451,6 @@ "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz", "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==", "dev": true, - "peer": true, "dependencies": { "node-fetch-h2": "^2.3.0", "oas-kit-common": "^1.0.8", @@ -32719,7 +32470,6 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, - "peer": true, "engines": { "node": ">= 6" } @@ -32729,7 +32479,6 @@ "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", "dev": true, - "peer": true, "funding": { "url": "https://github.com/Mermade/oas-kit?sponsor=1" } @@ -32739,7 +32488,6 @@ "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz", "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==", "dev": true, - "peer": true, "dependencies": { "call-me-maybe": "^1.0.1", "oas-kit-common": "^1.0.8", @@ -32759,7 +32507,6 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, - "peer": true, "engines": { "node": ">= 6" } @@ -33161,6 +32908,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.1.tgz", "integrity": "sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==", "dev": true, + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.33.1", "@typescript-eslint/types": "8.33.1", @@ -33369,6 +33117,7 @@ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -33491,6 +33240,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", @@ -33763,6 +33513,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -33778,6 +33529,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -33834,7 +33586,6 @@ "resolved": "https://registry.npmjs.org/office-addin-manifest-converter/-/office-addin-manifest-converter-0.4.1.tgz", "integrity": "sha512-2eOdCCYJ5bhCe2p9KKETdg1UNshsKaT0lDU/jNopAg3t7zC1WxwvofTSO/+4Log5L4Re+wUdV8MqrQikZBa7+Q==", "dev": true, - "peer": true, "dependencies": { "@xmldom/xmldom": "^0.8.5", "commander": "^9.0.0", @@ -33849,7 +33600,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "dev": true, - "peer": true, "engines": { "node": "^12.20.0 || >=14" } @@ -34001,7 +33751,6 @@ "resolved": "https://registry.npmjs.org/office-addin-project/-/office-addin-project-0.8.6.tgz", "integrity": "sha512-S93brHVDaMRZIIEibK12m6eTItoKqdy2Ep51qNhU7RaZTjH7n/C66AzdDai06UJb3I3AXfXHnKv/AJL2voGGWA==", "dev": true, - "peer": true, "dependencies": { "adm-zip": "0.5.12", "commander": "^6.2.1", @@ -34021,7 +33770,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", "dev": true, - "peer": true, "engines": { "node": ">= 6" } @@ -34031,7 +33779,6 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, - "peer": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -34046,7 +33793,6 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, - "peer": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -34056,7 +33802,6 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, - "peer": true, "engines": { "node": ">= 4.0.0" } @@ -34426,7 +34171,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", - "peer": true, "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.1.2", @@ -34445,7 +34189,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -34462,7 +34205,6 @@ "version": "8.0.5", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "peer": true, "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", @@ -34476,7 +34218,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", - "peer": true, "dependencies": { "degenerator": "^5.0.0", "netmask": "^2.0.2" @@ -34988,7 +34729,6 @@ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, - "peer": true, "engines": { "node": "*" } @@ -35244,6 +34984,7 @@ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", "license": "Apache-2.0", + "peer": true, "bin": { "playwright-core": "cli.js" }, @@ -35307,6 +35048,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -36171,6 +35913,7 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -36739,6 +36482,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz", "integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==", "dev": true, + "peer": true, "bin": { "prettier": "bin-prettier.js" }, @@ -36917,7 +36661,6 @@ "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", "dev": true, - "peer": true, "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", @@ -36928,8 +36671,7 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/protocols": { "version": "2.0.2", @@ -36953,7 +36695,6 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", - "peer": true, "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", @@ -36972,7 +36713,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -36989,7 +36729,6 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "peer": true, "engines": { "node": ">=12" } @@ -36998,7 +36737,6 @@ "version": "8.0.5", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "peer": true, "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", @@ -37018,8 +36756,7 @@ "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/psl": { "version": "1.15.0", @@ -37085,7 +36822,6 @@ "version": "24.10.0", "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.10.0.tgz", "integrity": "sha512-xX0QJRc8t19iAwRDsAOR38Q/Zx/W6WVzJCEhKCAwp2XMsaWqfNtQ+rBfQW9PlF+Op24d7c8Zlgq9YNmbnA7hdQ==", - "peer": true, "dependencies": { "@puppeteer/browsers": "2.10.5", "chromium-bidi": "5.1.0", @@ -37102,7 +36838,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -37119,7 +36854,6 @@ "version": "8.18.2", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -37340,6 +37074,7 @@ "version": "19.2.1", "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -37584,6 +37319,7 @@ "version": "19.2.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz", "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -37610,6 +37346,7 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -38294,6 +38031,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -38519,6 +38257,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "peer": true, "dependencies": { "@jest/core": "^27.5.1", "import-local": "^3.0.2", @@ -39619,50 +39358,6 @@ "node": ">=8" } }, - "node_modules/react-scripts/node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "optional": true, - "peer": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, "node_modules/react-scripts/node_modules/v8-to-istanbul": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", @@ -40303,7 +39998,6 @@ "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==", "dev": true, - "peer": true, "funding": { "url": "https://github.com/Mermade/oas-kit?sponsor=1" } @@ -40507,7 +40201,6 @@ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", "dev": true, - "peer": true, "engines": { "node": ">=0.10" } @@ -41021,6 +40714,7 @@ "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -41247,6 +40941,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -41641,7 +41336,6 @@ "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", "dev": true, - "peer": true, "dependencies": { "should-equal": "^2.0.0", "should-format": "^3.0.3", @@ -41655,7 +41349,6 @@ "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", "dev": true, - "peer": true, "dependencies": { "should-type": "^1.4.0" } @@ -41665,7 +41358,6 @@ "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", "dev": true, - "peer": true, "dependencies": { "should-type": "^1.3.0", "should-type-adaptors": "^1.0.1" @@ -41675,15 +41367,13 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/should-type-adaptors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", "dev": true, - "peer": true, "dependencies": { "should-type": "^1.3.0", "should-util": "^1.0.0" @@ -41693,8 +41383,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", - "dev": true, - "peer": true + "dev": true }, "node_modules/shx": { "version": "0.3.4", @@ -42457,7 +42146,6 @@ "version": "2.22.1", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.1.tgz", "integrity": "sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA==", - "peer": true, "dependencies": { "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" @@ -43240,7 +42928,6 @@ "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==", "dev": true, - "peer": true, "dependencies": { "call-me-maybe": "^1.0.1", "node-fetch": "^2.6.1", @@ -43268,7 +42955,6 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, - "peer": true, "engines": { "node": ">= 6" } @@ -43378,6 +43064,7 @@ "version": "3.4.17", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -43533,7 +43220,6 @@ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "optional": true, - "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -43576,8 +43262,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "optional": true, - "peer": true + "optional": true }, "node_modules/tapable": { "version": "2.3.0", @@ -43834,7 +43519,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", - "peer": true, "dependencies": { "b4a": "^1.6.4" } @@ -44160,6 +43844,7 @@ "integrity": "sha512-SaeUtjfpg9Uqu8IbeDKtdaS0g8lS6FT6OzM3ezrDfErPJPHNDo/Ey+VFGP1bQIDfagYDLyRpd7O15XpG1Es2Uw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "bs-logger": "^0.2.6", "fast-json-stable-stringify": "^2.1.0", @@ -44315,7 +44000,8 @@ "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "peer": true }, "node_modules/tsutils": { "version": "3.21.0", @@ -44674,6 +44360,7 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "peer": true, "engines": { "node": ">=10" }, @@ -44772,8 +44459,7 @@ "node_modules/typed-query-selector": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", - "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", - "peer": true + "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==" }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", @@ -44787,8 +44473,7 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/typedi/-/typedi-0.10.0.tgz", "integrity": "sha512-v3UJF8xm68BBj6AF4oQML3ikrfK2c9EmZUyLOfShpJuItAqVBHWP/KtpGinkSsIiP6EZyyb6Z3NXyW9dgS9X1w==", - "dev": true, - "peer": true + "dev": true }, "node_modules/typedoc": { "version": "0.24.8", @@ -44839,6 +44524,7 @@ "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -45008,8 +44694,7 @@ "version": "1.13.7", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", - "dev": true, - "peer": true + "dev": true }, "node_modules/undici": { "version": "7.20.0", @@ -45489,7 +45174,6 @@ "integrity": "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 0.10" } @@ -45986,7 +45670,6 @@ "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz", "integrity": "sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg==", "dev": true, - "peer": true, "engines": { "node": ">=8.0.0 || >=10.0.0" } @@ -46003,17 +45686,6 @@ "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", "dev": true }, - "node_modules/vue-template-compiler": { - "version": "2.7.16", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", - "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", - "optional": true, - "peer": true, - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } - }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -46110,6 +45782,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.2.tgz", "integrity": "sha512-dRXm0a2qcHPUBEzVk8uph0xWSjV/xZxenQQbLwnwP7caQCYpqG1qddwlyEkIDkYn0K8tvmcrZ+bOrzoQ3HxCDw==", "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -46327,6 +46000,7 @@ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.2.tgz", "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", "devOptional": true, + "peer": true, "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", @@ -46985,6 +46659,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -47059,6 +46734,7 @@ "version": "2.79.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", + "peer": true, "bin": { "rollup": "dist/bin/rollup" }, @@ -47500,7 +47176,8 @@ "resolved": "https://registry.npmjs.org/xterm/-/xterm-4.19.0.tgz", "integrity": "sha512-c3Cp4eOVsYY5Q839dR5IejghRPpxciGmLWWaP9g+ppfMeBChMeLa1DCA+pmX/jyDZ+zxFOmlJL/82qVdayVoGQ==", "deprecated": "This package is now deprecated. Move to @xterm/xterm instead.", - "dev": true + "dev": true, + "peer": true }, "node_modules/xterm-addon-fit": { "version": "0.5.0", @@ -47726,6 +47403,7 @@ "version": "3.25.75", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.75.tgz", "integrity": "sha512-OhpzAmVzabPOL6C3A3gpAifqr9MqihV/Msx3gor2b2kviCgcb+HM9SEOpMWwwNp9MRunWnhtAKUoo0AHhjyPPg==", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -47743,7 +47421,8 @@ "node_modules/zone.js": { "version": "0.15.1", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.1.tgz", - "integrity": "sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==" + "integrity": "sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==", + "peer": true }, "regression-tests/msal-node/client-credential": { "version": "1.0.0", @@ -47912,6 +47591,7 @@ "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-21.1.4.tgz", "integrity": "sha512-8xQ0Ylw7qqVyw4ZJ/Tyw/z5Mtqtp8AMj+R+Z1sCWcyxBgDU4+qfxteVYdiipWC3tX77A0FTsXqwvNP9WVY2/WA==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -48022,18 +47702,6 @@ } } }, - "samples/msal-angular-samples/angular-b2c-sample/node_modules/@angular/build/node_modules/@types/node": { - "version": "25.2.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.3.tgz", - "integrity": "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "undici-types": "~7.16.0" - } - }, "samples/msal-angular-samples/angular-b2c-sample/node_modules/@angular/build/node_modules/@vitejs/plugin-basic-ssl": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.1.0.tgz", @@ -48053,8 +47721,7 @@ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "samples/msal-angular-samples/angular-b2c-sample/node_modules/@angular/build/node_modules/vite": { "version": "7.3.0", @@ -48062,6 +47729,7 @@ "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -48136,6 +47804,7 @@ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-21.1.4.tgz", "integrity": "sha512-PElA4Ww4TIa3+B/ND+fm8ZPDKONTIqc9a/s0qNxhcAD9IpDqjaBVi/fyg+ZWBtS+x0DQgJtKeCsSZ6sr2aFQaQ==", "license": "MIT", + "peer": true, "dependencies": { "parse5": "^8.0.0", "tslib": "^2.3.0" @@ -48188,6 +47857,7 @@ "resolved": "https://registry.npmjs.org/@angular/common/-/common-21.1.4.tgz", "integrity": "sha512-1uOxPrHO9PFZBU/JavzYzjxAm+5x7vD2z6AeUndqdT4LjqOBIePswxFDRqM9dlfF8FIwnnfmNFipiC/yQjJSnA==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -48204,6 +47874,7 @@ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-21.1.4.tgz", "integrity": "sha512-H0qtASeqOTaS44ioF4DYE/yNqwzUmEJpMYrcNEUFEwA20/DkLzyoaEx4y1CjIxtXxuhtge95PNymDBOLWSjIdg==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -48217,6 +47888,7 @@ "integrity": "sha512-Uw8KmpVCo58/f5wf6pY8ZS5fodv65hn5jxms8Nv/K7/LVe3i1nNFrHyneBx5+a7qkz93nSV4rdwBVnMvjIyr+g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "7.28.5", "@jridgewell/sourcemap-codec": "^1.4.14", @@ -48249,6 +47921,7 @@ "resolved": "https://registry.npmjs.org/@angular/core/-/core-21.1.4.tgz", "integrity": "sha512-QBDO5SaVYTVQ0fIN9Qd7US9cUCgs2vM9x6K18PTUKmygIkHVHTFdzwm4MO5gpCOFzJseGbS+dNzqn+v0PaKf9g==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -48274,6 +47947,7 @@ "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-21.1.4.tgz", "integrity": "sha512-duVT/eOncmFNBYRlK/F7WDg6GD1vL1mxUrDdnp7M9J8JvNrKH0PvdfzuOAmjbB8/bsvUNTLFXCV4+43Mc2Hqsw==", "license": "MIT", + "peer": true, "dependencies": { "@standard-schema/spec": "^1.0.0", "tslib": "^2.3.0" @@ -48310,6 +47984,7 @@ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-21.1.4.tgz", "integrity": "sha512-S6Iw5CkORih5omh+MQY35w0bUBxdSFAPLDg386S6/9fEUjDClo61hvXNKxaNh9g7tnh1LD7zmTmKrqufnhnFDQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -48807,6 +48482,7 @@ "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@inquirer/checkbox": "^4.3.2", "@inquirer/confirm": "^5.1.21", @@ -49201,6 +48877,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.57.tgz", "integrity": "sha512-f3T4y6VU4fVQDKVqJV4Uppy8c1p/sVvS3peyqxyWnzkqXFJLRU7Y1Bl7rMS1Qe9z0v4M6McY0Fp9yBsgHJUsWQ==", "dev": true, + "peer": true, "dependencies": { "undici-types": "~6.19.2" } @@ -49379,6 +49056,7 @@ "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "readdirp": "^5.0.0" }, @@ -49762,6 +49440,7 @@ "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "cli-truncate": "^5.0.0", "colorette": "^2.0.20", @@ -50482,6 +50161,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -50714,6 +50394,7 @@ "version": "21.1.4", "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-21.1.4.tgz", "integrity": "sha512-8xQ0Ylw7qqVyw4ZJ/Tyw/z5Mtqtp8AMj+R+Z1sCWcyxBgDU4+qfxteVYdiipWC3tX77A0FTsXqwvNP9WVY2/WA==", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -50878,6 +50559,7 @@ "version": "21.1.4", "resolved": "https://registry.npmjs.org/@angular/common/-/common-21.1.4.tgz", "integrity": "sha512-1uOxPrHO9PFZBU/JavzYzjxAm+5x7vD2z6AeUndqdT4LjqOBIePswxFDRqM9dlfF8FIwnnfmNFipiC/yQjJSnA==", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -50893,6 +50575,7 @@ "version": "21.1.4", "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-21.1.4.tgz", "integrity": "sha512-H0qtASeqOTaS44ioF4DYE/yNqwzUmEJpMYrcNEUFEwA20/DkLzyoaEx4y1CjIxtXxuhtge95PNymDBOLWSjIdg==", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -50905,6 +50588,7 @@ "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-21.1.4.tgz", "integrity": "sha512-Uw8KmpVCo58/f5wf6pY8ZS5fodv65hn5jxms8Nv/K7/LVe3i1nNFrHyneBx5+a7qkz93nSV4rdwBVnMvjIyr+g==", "dev": true, + "peer": true, "dependencies": { "@babel/core": "7.28.5", "@jridgewell/sourcemap-codec": "^1.4.14", @@ -50936,6 +50620,7 @@ "version": "21.1.4", "resolved": "https://registry.npmjs.org/@angular/core/-/core-21.1.4.tgz", "integrity": "sha512-QBDO5SaVYTVQ0fIN9Qd7US9cUCgs2vM9x6K18PTUKmygIkHVHTFdzwm4MO5gpCOFzJseGbS+dNzqn+v0PaKf9g==", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -50960,6 +50645,7 @@ "version": "21.1.4", "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-21.1.4.tgz", "integrity": "sha512-duVT/eOncmFNBYRlK/F7WDg6GD1vL1mxUrDdnp7M9J8JvNrKH0PvdfzuOAmjbB8/bsvUNTLFXCV4+43Mc2Hqsw==", + "peer": true, "dependencies": { "@standard-schema/spec": "^1.0.0", "tslib": "^2.3.0" @@ -50994,6 +50680,7 @@ "version": "21.1.4", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-21.1.4.tgz", "integrity": "sha512-S6Iw5CkORih5omh+MQY35w0bUBxdSFAPLDg386S6/9fEUjDClo61hvXNKxaNh9g7tnh1LD7zmTmKrqufnhnFDQ==", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -51462,6 +51149,7 @@ "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", "dev": true, + "peer": true, "dependencies": { "@inquirer/checkbox": "^4.3.2", "@inquirer/confirm": "^5.1.21", @@ -52000,6 +51688,7 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", "dev": true, + "peer": true, "dependencies": { "readdirp": "^5.0.0" }, @@ -52309,7 +51998,8 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.5.0.tgz", "integrity": "sha512-9PMzyvhtocxb3aXJVOPqBDswdgyAeSB81QnLop4npOpbqnheaTEwPc9ZloQeVswugPManznQBjD8kWDTjlnHuw==", - "dev": true + "dev": true, + "peer": true }, "samples/msal-angular-samples/angular-modules-sample/node_modules/json-parse-even-better-errors": { "version": "5.0.0", @@ -52325,6 +52015,7 @@ "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz", "integrity": "sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==", "dev": true, + "peer": true, "dependencies": { "jasmine-core": "^4.1.0" }, @@ -52351,6 +52042,7 @@ "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", "dev": true, + "peer": true, "dependencies": { "cli-truncate": "^5.0.0", "colorette": "^2.0.20", @@ -53026,6 +52718,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -53072,6 +52765,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz", "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", "dev": true, + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -53325,6 +53019,7 @@ "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-21.1.4.tgz", "integrity": "sha512-8xQ0Ylw7qqVyw4ZJ/Tyw/z5Mtqtp8AMj+R+Z1sCWcyxBgDU4+qfxteVYdiipWC3tX77A0FTsXqwvNP9WVY2/WA==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -53493,6 +53188,7 @@ "resolved": "https://registry.npmjs.org/@angular/common/-/common-21.1.4.tgz", "integrity": "sha512-1uOxPrHO9PFZBU/JavzYzjxAm+5x7vD2z6AeUndqdT4LjqOBIePswxFDRqM9dlfF8FIwnnfmNFipiC/yQjJSnA==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -53509,6 +53205,7 @@ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-21.1.4.tgz", "integrity": "sha512-H0qtASeqOTaS44ioF4DYE/yNqwzUmEJpMYrcNEUFEwA20/DkLzyoaEx4y1CjIxtXxuhtge95PNymDBOLWSjIdg==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -53522,6 +53219,7 @@ "integrity": "sha512-Uw8KmpVCo58/f5wf6pY8ZS5fodv65hn5jxms8Nv/K7/LVe3i1nNFrHyneBx5+a7qkz93nSV4rdwBVnMvjIyr+g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "7.28.5", "@jridgewell/sourcemap-codec": "^1.4.14", @@ -53554,6 +53252,7 @@ "resolved": "https://registry.npmjs.org/@angular/core/-/core-21.1.4.tgz", "integrity": "sha512-QBDO5SaVYTVQ0fIN9Qd7US9cUCgs2vM9x6K18PTUKmygIkHVHTFdzwm4MO5gpCOFzJseGbS+dNzqn+v0PaKf9g==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -53579,6 +53278,7 @@ "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-21.1.4.tgz", "integrity": "sha512-duVT/eOncmFNBYRlK/F7WDg6GD1vL1mxUrDdnp7M9J8JvNrKH0PvdfzuOAmjbB8/bsvUNTLFXCV4+43Mc2Hqsw==", "license": "MIT", + "peer": true, "dependencies": { "@standard-schema/spec": "^1.0.0", "tslib": "^2.3.0" @@ -53615,6 +53315,7 @@ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-21.1.4.tgz", "integrity": "sha512-S6Iw5CkORih5omh+MQY35w0bUBxdSFAPLDg386S6/9fEUjDClo61hvXNKxaNh9g7tnh1LD7zmTmKrqufnhnFDQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -54112,6 +53813,7 @@ "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@inquirer/checkbox": "^4.3.2", "@inquirer/confirm": "^5.1.21", @@ -54720,6 +54422,7 @@ "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "readdirp": "^5.0.0" }, @@ -55094,6 +54797,7 @@ "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "cli-truncate": "^5.0.0", "colorette": "^2.0.20", @@ -55829,6 +55533,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -55879,6 +55584,7 @@ "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -56106,6 +55812,7 @@ "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -56286,6 +55993,7 @@ "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -57538,52 +57246,6 @@ "url": "https://opencollective.com/synckit" } }, - "samples/msal-browser-samples/ExpressSample/node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, "samples/msal-browser-samples/ExpressSample/node_modules/write-file-atomic": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", @@ -58085,6 +57747,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.110.tgz", "integrity": "sha512-WW2o4gTmREtSnqKty9nhqF/vA0GKd0V/rbC0OyjSk9Bz6bzlsXKT+i7WDdS/a0z74rfT2PO4dArVCSnapNLA5Q==", "dev": true, + "peer": true, "dependencies": { "undici-types": "~5.26.4" } @@ -58580,6 +58243,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.110.tgz", "integrity": "sha512-WW2o4gTmREtSnqKty9nhqF/vA0GKd0V/rbC0OyjSk9Bz6bzlsXKT+i7WDdS/a0z74rfT2PO4dArVCSnapNLA5Q==", "dev": true, + "peer": true, "dependencies": { "undici-types": "~5.26.4" } @@ -59184,6 +58848,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -59277,6 +58942,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.110.tgz", "integrity": "sha512-WW2o4gTmREtSnqKty9nhqF/vA0GKd0V/rbC0OyjSk9Bz6bzlsXKT+i7WDdS/a0z74rfT2PO4dArVCSnapNLA5Q==", "dev": true, + "peer": true, "dependencies": { "undici-types": "~5.26.4" } diff --git a/samples/e2eTestUtils/src/AppConfig.ts b/samples/e2eTestUtils/src/AppConfig.ts new file mode 100644 index 0000000000..51d4850b6b --- /dev/null +++ b/samples/e2eTestUtils/src/AppConfig.ts @@ -0,0 +1,31 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +/** + * Represents application configuration retrieved from Key Vault. + * This maps to the 'app' property in Key Vault secret JSON. + */ +export type AppConfig = { + /** The application (client) ID registered in Azure AD */ + appId?: string; + + /** The redirect URI configured for the application */ + redirectUri?: string; + + /** The authority URL (e.g., "https://login.microsoftonline.com/{tenantId}") */ + authority?: string; + + /** The default scopes for the application (space-separated) */ + defaultScopes?: string; + + /** The tenant ID where the application is registered */ + tenantId?: string; + + /** The Azure environment (e.g., "azurecloud", "azureusgovernment") */ + environment?: string; + + /** The name of the Key Vault secret containing the app's client secret */ + secretName?: string; +}; diff --git a/samples/e2eTestUtils/src/KeyVaultSecrets.ts b/samples/e2eTestUtils/src/KeyVaultSecrets.ts new file mode 100644 index 0000000000..a563a68918 --- /dev/null +++ b/samples/e2eTestUtils/src/KeyVaultSecrets.ts @@ -0,0 +1,47 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +/** + * Contains names of secrets stored in Azure Key Vault for lab configuration. + * These secrets contain JSON-serialized configuration objects for users, apps, and lab environments. + */ +export const KeyVaultSecrets = { + // Names of key vault secrets for user configuration JSONs + UserPublicCloud: "User-PublicCloud-Config", + UserFederated: "User-Federated-Config", + UserPublicCloud2: "MSAL-User-Default2-JSON", + UserB2C: "MSAL-USER-B2C-JSON", + UserB2CMSA: "MSAL-User-B2C-MSA-JSON", + UserArlington: "MSAL-USER-Arlington-JSON", + UserCiam: "MSAL-USER-CIAM-JSON", + UserPop: "MSAL-User-POP-JSON", + + // Names of key vault secrets for application configuration JSONs + // - Broad test scenarios + AppS2S: "App-S2S-Config", + AppPCAClient: "App-PCAClient-Config", + AppWebApi: "App-WebApi-Config", + AppWebApp: "App-WebApp-Config", + // - More specific test scenarios, edge cases, etc. + B2CAppIdLabsAppB2C: "MSAL-App-B2C-JSON", + ArlAppIdLabsApp: "MSAL-App-Arlington-JSON", + MsalAppCiam: "MSAL-App-CIAM-JSON", + MsalAppAzureAdMultipleOrgsRegional: + "MSAL-APP-AzureADMultipleOrgsRegional-JSON", + MsalAppArlingtonCCA: "MSAL-App-ArlingtonCCA-JSON", + + // B2C MSA app configuration (from MSID Lab Key Vault) + B2CMsaAppId: "MSIDLABB2C-MSAapp-AppID", + B2CMsaAppSecretName: "MSIDLABB2C-MSAapp-AppSecret", + + // Name of key vault secrets for specific test scenarios + MsalOboSecret: "IdentityDivisionDotNetOBOServiceSecret", + + // Name of key vault secrets for app secrets and certificates + DefaultAppSecret: "MSAL-App-Default", +} as const; + +export type KeyVaultSecretName = + (typeof KeyVaultSecrets)[keyof typeof KeyVaultSecrets]; diff --git a/samples/e2eTestUtils/src/KeyVaultSecretsProvider.ts b/samples/e2eTestUtils/src/KeyVaultSecretsProvider.ts new file mode 100644 index 0000000000..8c0e307e91 --- /dev/null +++ b/samples/e2eTestUtils/src/KeyVaultSecretsProvider.ts @@ -0,0 +1,313 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import { SecretClient, KeyVaultSecret } from "@azure/keyvault-secrets"; +import { ClientCertificateCredential } from "@azure/identity"; +import * as fs from "fs"; +import * as crypto from "crypto"; +import * as dotenv from "dotenv"; + +// Load environment variables from .env file +// Try 1p repo config first +dotenv.config({ path: __dirname + `/../../../../.env` }); +// If CLIENT_ID is not set, try the 3p repo for test env config +if (!process.env["AZURE_CLIENT_ID"]) { + dotenv.config({ path: __dirname + `/../../../.env` }); +} + +/** + * Key Vault URLs for lab infrastructure. + */ +export const KeyVaultInstance = { + /** + * This Key Vault is generally used for frequently rotated credentials (e.g., user passwords). + */ + MSIDLab: "https://msidlabs.vault.azure.net", + + /** + * This Key Vault is generally used for static configuration (user/app configs, app secrets). + */ + MsalTeam: "https://id4skeyvault.vault.azure.net", +} as const; + +/** + * Environment variable names for lab authentication. + */ +const EnvVariables = { + TENANT: "AZURE_TENANT_ID", + CLIENT_ID: "AZURE_CLIENT_ID", + CERTIFICATE_PATH: "AZURE_CLIENT_CERTIFICATE_PATH", +} as const; + +/** + * Certificate credential information that can be used for MSAL ConfidentialClientApplication. + */ +export type LabCertificateCredential = { + /** The client ID of the lab authentication app */ + clientId: string; + /** The tenant ID for lab authentication */ + tenantId: string; + /** The SHA-256 thumbprint of the certificate */ + thumbprintSha256: string; + /** The private key in PEM format */ + privateKey: string; + /** The certificate chain (x5c) in PEM format */ + x5c: string; +}; + +/** Cached lab credential (extracted once, reused across all tests) */ +let cachedLabCredential: LabCertificateCredential | null = null; + +/** Cached ClientCertificateCredential for Key Vault access */ +let cachedKeyVaultCredential: ClientCertificateCredential | null = null; + +/** + * Extracts certificate information from a PEM file containing both certificate and private key. + * @param pemContent - The PEM content as a string + * @returns Certificate credential information (thumbprint, privateKey, x5c) + */ +function extractCertificateInfoFromPem(pemContent: string): { + thumbprintSha256: string; + privateKey: string; + x5c: string; +} { + // Extract private key (supports both PKCS#8 and PKCS#1 formats) + const privateKeyMatch = pemContent.match( + /-----BEGIN PRIVATE KEY-----[\s\S]*?-----END PRIVATE KEY-----/ + ); + const rsaPrivateKeyMatch = pemContent.match( + /-----BEGIN RSA PRIVATE KEY-----[\s\S]*?-----END RSA PRIVATE KEY-----/ + ); + const privateKey = privateKeyMatch?.[0] || rsaPrivateKeyMatch?.[0]; + + if (!privateKey) { + throw new Error("No private key found in PEM content"); + } + + // Extract all certificates (there may be a chain) + const certMatches = pemContent.match( + /-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g + ); + + if (!certMatches || certMatches.length === 0) { + throw new Error("No certificate found in PEM content"); + } + + // The first certificate should be the leaf certificate + const leafCert = certMatches[0]; + const x5c = certMatches.join("\n"); + + // Calculate SHA-256 thumbprint from the leaf certificate + const certDer = Buffer.from( + leafCert + .replace(/-----BEGIN CERTIFICATE-----/g, "") + .replace(/-----END CERTIFICATE-----/g, "") + .replace(/\s/g, ""), + "base64" + ); + const thumbprintSha256 = crypto + .createHash("sha256") + .update(certDer) + .digest("hex") + .toUpperCase(); + + return { + thumbprintSha256, + privateKey, + x5c, + }; +} + +/** + * Gets the ClientCertificateCredential for authenticating with Azure Key Vault. + * Uses the certificate path from environment variables (expects PEM format). + * This follows the same pattern as LabClient. + * + * @returns ClientCertificateCredential for Key Vault access + * @throws Error if required environment variables are not set + */ +function getKeyVaultCredential(): ClientCertificateCredential { + if (cachedKeyVaultCredential) { + return cachedKeyVaultCredential; + } + + const tenant = process.env[EnvVariables.TENANT]; + const clientId = process.env[EnvVariables.CLIENT_ID]; + const certPath = process.env[EnvVariables.CERTIFICATE_PATH]; + + if (!tenant || !clientId || !certPath) { + throw new Error( + `Environment variables not set! Required: ${EnvVariables.TENANT}, ${EnvVariables.CLIENT_ID}, ${EnvVariables.CERTIFICATE_PATH}` + ); + } + + if (!fs.existsSync(certPath)) { + throw new Error(`Certificate file not found at ${certPath}`); + } + + cachedKeyVaultCredential = new ClientCertificateCredential( + tenant, + clientId, + certPath, + { + sendCertificateChain: true, + } + ); + + return cachedKeyVaultCredential; +} + +/** + * Provides access to Azure Key Vault secrets using certificate-based authentication. + * This class manages connections to Key Vault and provides methods to retrieve secrets. + * + * Authentication uses ClientCertificateCredential with a PEM certificate file, + * following the same pattern as LabClient in e2eTestUtils. + */ +export class KeyVaultSecretsProvider { + private secretClient: SecretClient; + private keyVaultAddress: string; + + /** + * Creates a new KeyVaultSecretsProvider instance. + * @param keyVaultAddress - The URL of the Key Vault (defaults to MSIDLab Key Vault) + */ + constructor(keyVaultAddress: string = KeyVaultInstance.MSIDLab) { + this.keyVaultAddress = keyVaultAddress; + const credential = getKeyVaultCredential(); + this.secretClient = new SecretClient(keyVaultAddress, credential); + } + + /** + * Gets the Key Vault address this provider is connected to. + */ + getKeyVaultAddress(): string { + return this.keyVaultAddress; + } + + /** + * Retrieves a secret from Key Vault by name. + * @param secretName - The name of the secret to retrieve + * @returns The Key Vault secret + */ + async getSecretByName(secretName: string): Promise { + return await this.secretClient.getSecret(secretName); + } + + /** + * Retrieves a secret from Key Vault by name and version. + * @param secretName - The name of the secret to retrieve + * @param secretVersion - The specific version of the secret + * @returns The Key Vault secret + */ + async getSecretByNameAndVersion( + secretName: string, + secretVersion: string + ): Promise { + return await this.secretClient.getSecret(secretName, { + version: secretVersion, + }); + } + + /** + * Retrieves the value of a secret from Key Vault. + * @param secretName - The name of the secret to retrieve + * @returns The secret value as a string + * @throws Error if the secret is not found or has no value + */ + async getSecretValue(secretName: string): Promise { + const secret = await this.getSecretByName(secretName); + if (!secret.value) { + throw new Error(`Secret '${secretName}' found but has no value`); + } + return secret.value; + } +} + +/** + * Singleton instances of KeyVaultSecretsProvider for each Key Vault. + * These are lazily initialized on first access. + */ +let msidLabProvider: KeyVaultSecretsProvider | null = null; +let msalTeamProvider: KeyVaultSecretsProvider | null = null; + +/** + * Gets a KeyVaultSecretsProvider instance for the MSID Lab Key Vault. + * This Key Vault is used for frequently rotated credentials and sensitive configuration. + */ +export function getMsidLabKeyVaultProvider(): KeyVaultSecretsProvider { + if (!msidLabProvider) { + msidLabProvider = new KeyVaultSecretsProvider(KeyVaultInstance.MSIDLab); + } + return msidLabProvider; +} + +/** + * Gets a KeyVaultSecretsProvider instance for the MSAL Team Key Vault. + * This Key Vault is used for static user/app configuration. + */ +export function getMsalTeamKeyVaultProvider(): KeyVaultSecretsProvider { + if (!msalTeamProvider) { + msalTeamProvider = new KeyVaultSecretsProvider( + KeyVaultInstance.MsalTeam + ); + } + return msalTeamProvider; +} + +/** + * Gets the lab certificate credential for use in tests. + * This credential can be used to create ConfidentialClientApplication instances. + * + * Reads the PEM certificate from the path specified in the AZURE_CLIENT_CERTIFICATE_PATH + * environment variable and extracts the thumbprint, private key, and certificate chain. + * + * The result is cached for subsequent calls. + * + * @returns Certificate credential with clientId, tenantId, thumbprintSha256, privateKey, and x5c + * @throws Error if required environment variables are not set or certificate file not found + */ +export function getLabCredential(): LabCertificateCredential { + // Return cached credential if available + if (cachedLabCredential) { + return cachedLabCredential; + } + + const tenant = process.env[EnvVariables.TENANT]; + const clientId = process.env[EnvVariables.CLIENT_ID]; + const certPath = process.env[EnvVariables.CERTIFICATE_PATH]; + + if (!tenant || !clientId || !certPath) { + throw new Error( + `Environment variables not set! Required: ${EnvVariables.TENANT}, ${EnvVariables.CLIENT_ID}, ${EnvVariables.CERTIFICATE_PATH}` + ); + } + + if (!fs.existsSync(certPath)) { + throw new Error(`Certificate file not found at ${certPath}`); + } + + const pemContent = fs.readFileSync(certPath, "utf-8"); + const certInfo = extractCertificateInfoFromPem(pemContent); + + cachedLabCredential = { + clientId, + tenantId: tenant, + thumbprintSha256: certInfo.thumbprintSha256, + privateKey: certInfo.privateKey, + x5c: certInfo.x5c, + }; + + return cachedLabCredential; +} + +/** + * Clears the cached credentials. + * Useful for testing or when you need to force a refresh. + */ +export function clearLabCredentialCache(): void { + cachedLabCredential = null; + cachedKeyVaultCredential = null; +} diff --git a/samples/e2eTestUtils/src/LabResponseHelper.ts b/samples/e2eTestUtils/src/LabResponseHelper.ts new file mode 100644 index 0000000000..d7068c9749 --- /dev/null +++ b/samples/e2eTestUtils/src/LabResponseHelper.ts @@ -0,0 +1,261 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import { + getMsidLabKeyVaultProvider, + getMsalTeamKeyVaultProvider, +} from "./KeyVaultSecretsProvider"; +import { UserConfig, LabUser } from "./UserConfig"; +import { AppConfig } from "./AppConfig"; + +/** + * Caches for configuration objects retrieved from Key Vault. + * Using Map for in-memory caching to avoid repeated Key Vault calls. + */ +const userConfigCache = new Map(); +const appConfigCache = new Map(); +const passwordCache = new Map(); + +/** + * Helper class for retrieving lab configuration from Azure Key Vault. + * Provides methods to fetch user configs, app configs, and passwords with caching. + */ +export class LabResponseHelper { + /** + * Retrieves user configuration from Key Vault with caching. + * @param secretName - The name of the Key Vault secret containing user configuration JSON. + * @returns A UserConfig object deserialized from the Key Vault secret. + */ + static async getUserConfig(secretName: string): Promise { + // Check cache first + const cached = userConfigCache.get(secretName); + if (cached) { + console.debug(`UserConfig '${secretName}' retrieved from cache`); + return cached; + } + + try { + const keyVaultProvider = getMsalTeamKeyVaultProvider(); + const secretValue = await keyVaultProvider.getSecretValue( + secretName + ); + + if (!secretValue) { + throw new Error(`KeyVault secret '${secretName}' is empty`); + } + + let userConfig: UserConfig; + try { + // Parse as JSON and extract the 'user' property + const jsonObject = JSON.parse(secretValue); + + // Look for 'user' property (case-insensitive) + const userKey = Object.keys(jsonObject).find( + (key) => key.toLowerCase() === "user" + ); + + if (!userKey) { + throw new Error( + `KeyVault '${secretName}': no 'user' property found in JSON` + ); + } + + userConfig = jsonObject[userKey] as UserConfig; + console.debug( + `KeyVault '${secretName}': ${ + userConfig.upn ?? "Unknown user" + }` + ); + } catch (parseError) { + if (parseError instanceof SyntaxError) { + throw new Error( + `KeyVault '${secretName}': invalid JSON - ${parseError.message}` + ); + } + throw parseError; + } + + // Cache the result + userConfigCache.set(secretName, userConfig); + return userConfig; + } catch (error) { + console.error(`KeyVault '${secretName}' failed:`, error); + throw new Error( + `Failed to retrieve or parse Key Vault secret '${secretName}'. ${ + error instanceof Error ? error.message : String(error) + }` + ); + } + } + + /** + * Retrieves user configuration as a LabUser instance with password retrieval capability. + * @param secretName - The name of the Key Vault secret containing user configuration JSON. + * @returns A LabUser object with password retrieval capability. + */ + static async getLabUser(secretName: string): Promise { + const config = await this.getUserConfig(secretName); + return new LabUser(config); + } + + /** + * Retrieves app configuration from Key Vault with caching. + * @param secretName - The name of the Key Vault secret containing app configuration JSON. + * @returns An AppConfig object deserialized from the Key Vault secret. + */ + static async getAppConfig(secretName: string): Promise { + // Check cache first + const cached = appConfigCache.get(secretName); + if (cached) { + console.debug(`AppConfig '${secretName}' retrieved from cache`); + return cached; + } + + try { + const keyVaultProvider = getMsalTeamKeyVaultProvider(); + const secretValue = await keyVaultProvider.getSecretValue( + secretName + ); + + if (!secretValue) { + throw new Error(`KeyVault secret '${secretName}' is empty`); + } + + let appConfig: AppConfig; + try { + // Parse as JSON and extract the 'app' property + const jsonObject = JSON.parse(secretValue); + + // Look for 'app' property (case-insensitive) + const appKey = Object.keys(jsonObject).find( + (key) => key.toLowerCase() === "app" + ); + + if (!appKey) { + throw new Error( + `KeyVault '${secretName}': no 'app' property found in JSON` + ); + } + + appConfig = jsonObject[appKey] as AppConfig; + console.debug( + `KeyVault '${secretName}': ${ + appConfig.appId ?? "Unknown app" + }` + ); + } catch (parseError) { + if (parseError instanceof SyntaxError) { + throw new Error( + `KeyVault '${secretName}': invalid JSON - ${parseError.message}` + ); + } + throw parseError; + } + + // Cache the result + appConfigCache.set(secretName, appConfig); + return appConfig; + } catch (error) { + console.error(`KeyVault '${secretName}' failed:`, error); + throw new Error( + `Failed to retrieve or parse Key Vault secret '${secretName}'. ${ + error instanceof Error ? error.message : String(error) + }` + ); + } + } + + /** + * Fetches user password from the MSID Lab Key Vault. + * Used internally by LabUser.getPassword(). + * @param userLabName - The lab name that serves as the secret name for the password. + * @returns The user's password. + */ + static async fetchUserPassword(userLabName: string): Promise { + if (!userLabName || userLabName.trim() === "") { + throw new Error( + "Password fetch failed: lab name is not set on user." + ); + } + + // Check cache first + const cached = passwordCache.get(userLabName); + if (cached) { + console.debug(`Password for '${userLabName}' retrieved from cache`); + return cached; + } + + const password = await this.getMsidLabSecret(userLabName); + + // Cache the result + passwordCache.set(userLabName, password); + console.debug( + `Password retrieved for ${userLabName} (${password.length} chars)` + ); + return password; + } + + /** + * Retrieves a secret from the MSAL Team Key Vault by name. + * Use for app secrets and other static configuration. + * @param secretName - The name of the secret to retrieve. + * @returns The secret value as a string. + */ + static async getSecret(secretName: string): Promise { + if (!secretName || secretName.trim() === "") { + throw new Error("Secret name cannot be empty."); + } + + const keyVaultProvider = getMsalTeamKeyVaultProvider(); + const secretValue = await keyVaultProvider.getSecretValue(secretName); + + if (!secretValue) { + throw new Error( + `Secret '${secretName}' found but was empty in Key Vault.` + ); + } + + console.debug( + `Secret retrieved: ${secretName} (${secretValue.length} chars)` + ); + return secretValue; + } + + /** + * Retrieves a secret from the MSID Lab Key Vault by name. + * Use for frequently rotated credentials like user passwords. + * @param secretName - The name of the secret to retrieve. + * @returns The secret value as a string. + */ + static async getMsidLabSecret(secretName: string): Promise { + if (!secretName || secretName.trim() === "") { + throw new Error("Secret name cannot be empty."); + } + + const keyVaultProvider = getMsidLabKeyVaultProvider(); + const secretValue = await keyVaultProvider.getSecretValue(secretName); + + if (!secretValue) { + throw new Error( + `Secret '${secretName}' found but was empty in Key Vault.` + ); + } + + console.debug( + `MSID Lab secret retrieved: ${secretName} (${secretValue.length} chars)` + ); + return secretValue; + } + + /** + * Clears all cached configurations. Useful for testing or forcing fresh data. + */ + static clearCache(): void { + userConfigCache.clear(); + appConfigCache.clear(); + passwordCache.clear(); + console.debug("LabResponseHelper cache cleared"); + } +} diff --git a/samples/e2eTestUtils/src/UserConfig.ts b/samples/e2eTestUtils/src/UserConfig.ts new file mode 100644 index 0000000000..7ff8ab3cc5 --- /dev/null +++ b/samples/e2eTestUtils/src/UserConfig.ts @@ -0,0 +1,82 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import { LabResponseHelper } from "./LabResponseHelper"; + +/** + * Represents user configuration retrieved from Key Vault. + * This maps to the 'user' property in Key Vault secret JSON. + */ +export type UserConfig = { + /** The object ID (GUID) of the user in Azure AD */ + objectId?: string; + + /** The type of user (e.g., "Cloud", "Federated", "B2C", "MSA") */ + userType?: string; + + /** The user principal name (email) for sign-in */ + upn?: string; + + /** The home UPN for guest users */ + homeUPN?: string; + + /** The B2C identity provider (e.g., "Local", "Facebook", "Google") */ + b2cProvider?: string; + + /** The name of the lab environment this user belongs to */ + labName?: string; + + /** The federation provider (e.g., "None", "ADFSv4") */ + federationProvider?: string; + + /** The tenant ID where the user resides */ + tenantId?: string; + + /** The application ID associated with this user config */ + appId?: string; + + /** The Azure environment (e.g., "azurecloud", "azureusgovernment") */ + azureEnvironment?: string; +}; + +/** + * Extended user config with password retrieval capability. + */ +export class LabUser implements UserConfig { + objectId?: string; + userType?: string; + upn?: string; + homeUPN?: string; + b2cProvider?: string; + labName?: string; + federationProvider?: string; + tenantId?: string; + appId?: string; + azureEnvironment?: string; + + private _password: string | null = null; + + constructor(config: UserConfig) { + Object.assign(this, config); + } + + /** + * Gets the user's password, fetching from Key Vault if not already cached. + * @returns The user's password + */ + async getPassword(): Promise { + if (this._password === null) { + if (!this.labName) { + throw new Error( + "Cannot fetch password: labName is not set on user config" + ); + } + this._password = await LabResponseHelper.fetchUserPassword( + this.labName + ); + } + return this._password; + } +} diff --git a/samples/e2eTestUtils/src/index.ts b/samples/e2eTestUtils/src/index.ts index 95120bf5f1..3ebea91864 100644 --- a/samples/e2eTestUtils/src/index.ts +++ b/samples/e2eTestUtils/src/index.ts @@ -53,3 +53,19 @@ export { enterCredentials as enterCredentialsElectron, retrieveAuthCodeUrlFromBrowserContext, } from "./ElectronPlaywrightTestUtils"; + +export type { AppConfig } from "./AppConfig"; +export type { UserConfig } from "./UserConfig"; +export { LabUser } from "./UserConfig"; +export { KeyVaultSecrets } from "./KeyVaultSecrets"; +export type { KeyVaultSecretName } from "./KeyVaultSecrets"; +export { + KeyVaultSecretsProvider, + KeyVaultInstance, + getMsidLabKeyVaultProvider, + getMsalTeamKeyVaultProvider, + getLabCredential, + clearLabCredentialCache, +} from "./KeyVaultSecretsProvider"; +export type { LabCertificateCredential } from "./KeyVaultSecretsProvider"; +export { LabResponseHelper } from "./LabResponseHelper"; diff --git a/samples/msal-node-samples/ElectronSystemBrowserTestApp/tests/electron-code-aad.spec.ts b/samples/msal-node-samples/ElectronSystemBrowserTestApp/tests/electron-code-aad.spec.ts index 35dc4b58a3..65339bcdbc 100644 --- a/samples/msal-node-samples/ElectronSystemBrowserTestApp/tests/electron-code-aad.spec.ts +++ b/samples/msal-node-samples/ElectronSystemBrowserTestApp/tests/electron-code-aad.spec.ts @@ -12,13 +12,10 @@ import { ScreenShotElectron, enterCredentialsElectron, retrieveAuthCodeUrlFromBrowserContext, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabApiQueryParams, - AppTypes, - AzureEnvironments, - LabClient, - setupCredentials, - SCREENSHOT_BASE_FOLDER_NAME, validateCacheLocation, } from "e2e-test-utils"; import * as path from "path"; @@ -27,10 +24,12 @@ let electronApp: ElectronApplication; let page: Page; let browser: Browser; let browserPage: Page; -let username: string; -let accountPwd: string; +let labUser: LabUser; -const screenshotFolder = path.join(__dirname, "screenshots/ElectronSystemBrowserTestApp"); +const screenshotFolder = path.join( + __dirname, + "screenshots/ElectronSystemBrowserTestApp" +); const TEST_CACHE_LOCATION = `${__dirname}/../data/aad.cache.json`; @@ -39,14 +38,9 @@ import config from "../src/config/AAD.json"; test.beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); - const labApiParams: LabApiQueryParams = { - azureEnvironment: AzureEnvironments.CLOUD, - appType: AppTypes.CLOUD, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment(labApiParams); - [username, accountPwd] = await setupCredentials(envResponse[0], labClient); + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserPublicCloud + ); electronApp = await electron.launch({ args: [ @@ -98,8 +92,8 @@ test.describe("Acquire token", () => { await enterCredentialsElectron( browserPage, screenshot, - username, - accountPwd + labUser.upn!, + await labUser.getPassword() ); const cachedTokens = await NodeCacheTestUtils.waitForTokens( TEST_CACHE_LOCATION, @@ -109,6 +103,8 @@ test.describe("Acquire token", () => { expect(cachedTokens.idTokens.length).toBe(1); expect(cachedTokens.refreshTokens.length).toBe(1); - await expect(page.locator(`text=${username}`).first()).toBeVisible(); + await expect( + page.locator(`text=${labUser.upn!}`).first() + ).toBeVisible(); }); }); diff --git a/samples/msal-node-samples/auth-code-cli-app/test/auth-code-cli.spec.ts b/samples/msal-node-samples/auth-code-cli-app/test/auth-code-cli.spec.ts index cbe2bce4a7..956f4a84a2 100644 --- a/samples/msal-node-samples/auth-code-cli-app/test/auth-code-cli.spec.ts +++ b/samples/msal-node-samples/auth-code-cli-app/test/auth-code-cli.spec.ts @@ -6,16 +6,14 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - setupCredentials, - RETRY_TIMES, enterCredentials, - validateCacheLocation, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - AppTypes, - AzureEnvironments, + validateCacheLocation, + createFolder, + RETRY_TIMES, } from "e2e-test-utils"; import path from "path"; @@ -37,10 +35,12 @@ describe("Auth Code CLI AAD Prod Tests", () => { let context: puppeteer.BrowserContext; let page: puppeteer.Page; - let username: string; - let accountPwd: string; + let labUser: LabUser; - const screenshotFolder = path.join(__dirname, "screenshots/auth-code-cli-app"); + const screenshotFolder = path.join( + __dirname, + "screenshots/auth-code-cli-app" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -49,18 +49,8 @@ describe("Auth Code CLI AAD Prod Tests", () => { createFolder(screenshotFolder); - const labApiParms: LabApiQueryParams = { - azureEnvironment: AzureEnvironments.CLOUD, - appType: AppTypes.CLOUD, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserPublicCloud ); }); @@ -91,7 +81,12 @@ describe("Auth Code CLI AAD Prod Tests", () => { page = await context.newPage(); page.setDefaultTimeout(5000); page.goto(url); - enterCredentials(page, screenshot, username, accountPwd); + enterCredentials( + page, + screenshot, + labUser.upn, + await labUser.getPassword() + ); }; const successMessage = "Success. You can close the browser now"; const result = @@ -102,7 +97,7 @@ describe("Auth Code CLI AAD Prod Tests", () => { }); expect(result.accessToken).toBeTruthy(); expect(result.idToken).toBeTruthy(); - expect(result.account.username).toEqual(username); + expect(result.account.username).toEqual(labUser.upn); try { expect( diff --git a/samples/msal-node-samples/auth-code/test/auth-code-aad-agc-confidential.spec.ts b/samples/msal-node-samples/auth-code/test/auth-code-aad-agc-confidential.spec.ts index 12bd85e9aa..d82130a5f5 100644 --- a/samples/msal-node-samples/auth-code/test/auth-code-aad-agc-confidential.spec.ts +++ b/samples/msal-node-samples/auth-code/test/auth-code-aad-agc-confidential.spec.ts @@ -6,14 +6,16 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - RETRY_TIMES, enterCredentials, - validateCacheLocation, SAMPLE_HOME_URL, + LabResponseHelper, + KeyVaultSecrets, + LabUser, + AppConfig, NodeCacheTestUtils, - getKeyVaultSecretClient, - getCredentials, + validateCacheLocation, + createFolder, + RETRY_TIMES, } from "e2e-test-utils"; import { ConfidentialClientApplication } from "@azure/msal-node"; import path from "path"; @@ -29,17 +31,6 @@ const cachePlugin = require("../../cachePlugin.js")(TEST_CACHE_LOCATION); // Load scenario configuration const config = require("../config/AAD-AGC-Confidential.json"); -config.authOptions = { - clientId: process.env.AZURE_CLIENT_ID, - clientSecret: process.env.AZURE_CLIENT_SECRET, - authority: `${process.env.AUTHORITY}/${process.env.AZURE_TENANT_ID}`, - knownAuthorities: [ - `${process.env.AUTHORITY}/${process.env.AZURE_TENANT_ID}`, - ], -}; -config.resourceApi = { - endpoint: `${process.env.GRAPH_URL}/v1.0/me`, -}; describe("Auth Code AAD AGC Confidential Tests", () => { jest.retryTimes(RETRY_TIMES); @@ -50,10 +41,13 @@ describe("Auth Code AAD AGC Confidential Tests", () => { let port: string; let homeRoute: string; - let username: string; - let password: string; + let labUser: LabUser; + let appConfig: AppConfig; - const screenshotFolder = path.join(__dirname, "screenshots/auth-code/aad-agc-confidential"); + const screenshotFolder = path.join( + __dirname, + "screenshots/auth-code/aad-agc-confidential" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -65,8 +59,36 @@ describe("Auth Code AAD AGC Confidential Tests", () => { createFolder(screenshotFolder); - const keyVaultSecretClient = await getKeyVaultSecretClient(); - [username, password] = await getCredentials(keyVaultSecretClient); + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserArlington + ); + appConfig = await LabResponseHelper.getAppConfig( + KeyVaultSecrets.MsalAppArlingtonCCA + ); + + // Get client secret from Key Vault + let clientSecret: string | undefined; + if (appConfig.secretName) { + clientSecret = await LabResponseHelper.getSecret( + appConfig.secretName + ); + } + + // Configure auth options from Key Vault app config + const authorityUrl = appConfig.authority + ? new URL(appConfig.authority) + : null; + config.authOptions = { + clientId: appConfig.appId, + clientSecret: clientSecret, + authority: appConfig.authority, + knownAuthorities: authorityUrl ? [authorityUrl.origin] : [], + }; + config.resourceApi = { + endpoint: authorityUrl + ? `${authorityUrl.origin}/v1.0/me` + : undefined, + }; }); afterAll(async () => { @@ -114,8 +136,9 @@ describe("Auth Code AAD AGC Confidential Tests", () => { it("Performs acquire token", async () => { const screenshot = new Screenshot(`${screenshotFolder}/BaseCase`); + const password = await labUser.getPassword(); await page.goto(homeRoute); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -132,8 +155,9 @@ describe("Auth Code AAD AGC Confidential Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/PromptLogin` ); + const password = await labUser.getPassword(); await page.goto(`${homeRoute}/?prompt=login`); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -151,8 +175,9 @@ describe("Auth Code AAD AGC Confidential Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/PromptConsent` ); + const password = await labUser.getPassword(); await page.goto(`${homeRoute}/?prompt=consent`); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -168,9 +193,10 @@ describe("Auth Code AAD AGC Confidential Tests", () => { it("Performs acquire token with prompt = 'none'", async () => { const screenshot = new Screenshot(`${screenshotFolder}/PromptNone`); + const password = await labUser.getPassword(); // First log the user in first await page.goto(`${homeRoute}/?prompt=login`); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -194,9 +220,10 @@ describe("Auth Code AAD AGC Confidential Tests", () => { it("Performs acquire token with state", async () => { const screenshot = new Screenshot(`${screenshotFolder}/WithState`); + const password = await labUser.getPassword(); const STATE_VALUE = "value_on_state"; await page.goto(`${homeRoute}/?prompt=login&state=${STATE_VALUE}`); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); diff --git a/samples/msal-node-samples/auth-code/test/auth-code-aad-agc-public.spec.ts b/samples/msal-node-samples/auth-code/test/auth-code-aad-agc-public.spec.ts index f398882a03..a7a50fc754 100644 --- a/samples/msal-node-samples/auth-code/test/auth-code-aad-agc-public.spec.ts +++ b/samples/msal-node-samples/auth-code/test/auth-code-aad-agc-public.spec.ts @@ -6,14 +6,16 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - RETRY_TIMES, enterCredentials, - validateCacheLocation, SAMPLE_HOME_URL, + LabResponseHelper, + KeyVaultSecrets, + LabUser, + AppConfig, NodeCacheTestUtils, - getKeyVaultSecretClient, - getCredentials, + validateCacheLocation, + createFolder, + RETRY_TIMES, } from "e2e-test-utils"; import { PublicClientApplication } from "@azure/msal-node"; import path from "path"; @@ -29,16 +31,6 @@ const cachePlugin = require("../../cachePlugin.js")(TEST_CACHE_LOCATION); // Load scenario configuration const config = require("../config/AAD-AGC-Public.json"); -config.authOptions = { - clientId: process.env.AZURE_CLIENT_ID, - authority: `${process.env.AUTHORITY}/${process.env.AZURE_TENANT_ID}`, - knownAuthorities: [ - `${process.env.AUTHORITY}/${process.env.AZURE_TENANT_ID}`, - ], -}; -config.resourceApi = { - endpoint: `${process.env.GRAPH_URL}/v1.0/me`, -}; describe("Auth Code AAD AGC Public Tests", () => { jest.retryTimes(RETRY_TIMES); @@ -49,10 +41,13 @@ describe("Auth Code AAD AGC Public Tests", () => { let port: string; let homeRoute: string; - let username: string; - let password: string; + let labUser: LabUser; + let appConfig: AppConfig; - const screenshotFolder = path.join(__dirname, "screenshots/auth-code/aad-agc-public"); + const screenshotFolder = path.join( + __dirname, + "screenshots/auth-code/aad-agc-public" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -64,8 +59,26 @@ describe("Auth Code AAD AGC Public Tests", () => { createFolder(screenshotFolder); - const keyVaultSecretClient = await getKeyVaultSecretClient(); - [username, password] = await getCredentials(keyVaultSecretClient); + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserArlington + ); + appConfig = await LabResponseHelper.getAppConfig( + KeyVaultSecrets.ArlAppIdLabsApp + ); + + // Configure auth options from Key Vault app config + config.authOptions = { + clientId: appConfig.appId, + authority: appConfig.authority, + knownAuthorities: appConfig.authority + ? [new URL(appConfig.authority).origin] + : [], + }; + config.resourceApi = { + endpoint: appConfig.authority + ? `${new URL(appConfig.authority).origin}/v1.0/me` + : undefined, + }; }); afterAll(async () => { @@ -109,8 +122,9 @@ describe("Auth Code AAD AGC Public Tests", () => { it("Performs acquire token", async () => { const screenshot = new Screenshot(`${screenshotFolder}/BaseCase`); + const password = await labUser.getPassword(); await page.goto(homeRoute); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -127,8 +141,9 @@ describe("Auth Code AAD AGC Public Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/PromptLogin` ); + const password = await labUser.getPassword(); await page.goto(`${homeRoute}/?prompt=login`); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -146,8 +161,9 @@ describe("Auth Code AAD AGC Public Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/PromptConsent` ); + const password = await labUser.getPassword(); await page.goto(`${homeRoute}/?prompt=consent`); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -163,9 +179,10 @@ describe("Auth Code AAD AGC Public Tests", () => { it("Performs acquire token with prompt = 'none'", async () => { const screenshot = new Screenshot(`${screenshotFolder}/PromptNone`); + const password = await labUser.getPassword(); // First log the user in first await page.goto(`${homeRoute}/?prompt=login`); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -189,9 +206,10 @@ describe("Auth Code AAD AGC Public Tests", () => { it("Performs acquire token with state", async () => { const screenshot = new Screenshot(`${screenshotFolder}/WithState`); + const password = await labUser.getPassword(); const STATE_VALUE = "value_on_state"; await page.goto(`${homeRoute}/?prompt=login&state=${STATE_VALUE}`); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); diff --git a/samples/msal-node-samples/auth-code/test/auth-code-aad.spec.ts b/samples/msal-node-samples/auth-code/test/auth-code-aad.spec.ts index 8506f17704..3f80830840 100644 --- a/samples/msal-node-samples/auth-code/test/auth-code-aad.spec.ts +++ b/samples/msal-node-samples/auth-code/test/auth-code-aad.spec.ts @@ -6,17 +6,15 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - setupCredentials, - RETRY_TIMES, enterCredentials, - validateCacheLocation, SAMPLE_HOME_URL, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - AppTypes, - AzureEnvironments, + validateCacheLocation, + createFolder, + RETRY_TIMES, } from "e2e-test-utils"; import path from "path"; @@ -43,8 +41,7 @@ describe("Auth Code AAD Prod Tests", () => { let port: string; let homeRoute: string; - let username: string; - let accountPwd: string; + let labUser: LabUser; const screenshotFolder = path.join(__dirname, "screenshots/auth-code/aad"); @@ -58,18 +55,8 @@ describe("Auth Code AAD Prod Tests", () => { createFolder(screenshotFolder); - const labApiParms: LabApiQueryParams = { - azureEnvironment: AzureEnvironments.CLOUD, - appType: AppTypes.CLOUD, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserPublicCloud ); }); @@ -114,8 +101,9 @@ describe("Auth Code AAD Prod Tests", () => { it("Performs acquire token", async () => { const screenshot = new Screenshot(`${screenshotFolder}/BaseCase`); + const accountPwd = await labUser.getPassword(); await page.goto(homeRoute); - await enterCredentials(page, screenshot, username, accountPwd); + await enterCredentials(page, screenshot, labUser.upn, accountPwd); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -132,8 +120,9 @@ describe("Auth Code AAD Prod Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/PromptLogin` ); + const accountPwd = await labUser.getPassword(); await page.goto(`${homeRoute}/?prompt=login`); - await enterCredentials(page, screenshot, username, accountPwd); + await enterCredentials(page, screenshot, labUser.upn, accountPwd); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -151,8 +140,9 @@ describe("Auth Code AAD Prod Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/PromptConsent` ); + const accountPwd = await labUser.getPassword(); await page.goto(`${homeRoute}/?prompt=consent`); - await enterCredentials(page, screenshot, username, accountPwd); + await enterCredentials(page, screenshot, labUser.upn, accountPwd); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -168,9 +158,10 @@ describe("Auth Code AAD Prod Tests", () => { it("Performs acquire token with prompt = 'none'", async () => { const screenshot = new Screenshot(`${screenshotFolder}/PromptNone`); + const accountPwd = await labUser.getPassword(); // First log the user in first await page.goto(`${homeRoute}/?prompt=login`); - await enterCredentials(page, screenshot, username, accountPwd); + await enterCredentials(page, screenshot, labUser.upn, accountPwd); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -194,9 +185,10 @@ describe("Auth Code AAD Prod Tests", () => { it("Performs acquire token with state", async () => { const screenshot = new Screenshot(`${screenshotFolder}/WithState`); + const accountPwd = await labUser.getPassword(); const STATE_VALUE = "value_on_state"; await page.goto(`${homeRoute}/?prompt=login&state=${STATE_VALUE}`); - await enterCredentials(page, screenshot, username, accountPwd); + await enterCredentials(page, screenshot, labUser.upn, accountPwd); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); diff --git a/samples/msal-node-samples/auth-code/test/auth-code-adfs.spec.ts b/samples/msal-node-samples/auth-code/test/auth-code-adfs.spec.ts index ef9c7c1bae..cdb4a840a3 100644 --- a/samples/msal-node-samples/auth-code/test/auth-code-adfs.spec.ts +++ b/samples/msal-node-samples/auth-code/test/auth-code-adfs.spec.ts @@ -1,19 +1,15 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - setupCredentials, - RETRY_TIMES, enterCredentialsADFS, enterCredentialsADFSWithConsent, SAMPLE_HOME_URL, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - AppTypes, - AzureEnvironments, - FederationProviders, - UserTypes, + createFolder, + RETRY_TIMES, } from "e2e-test-utils"; import { PublicClientApplication } from "@azure/msal-node"; import path from "path"; @@ -26,8 +22,7 @@ const cachePlugin = require("../../cachePlugin.js")(TEST_CACHE_LOCATION); const config = require("../config/ADFS.json"); -let username: string; -let accountPwd: string; +let labUser: LabUser; describe.skip("Auth Code ADFS 2019 Tests", () => { jest.retryTimes(RETRY_TIMES); @@ -47,20 +42,8 @@ describe.skip("Auth Code ADFS 2019 Tests", () => { homeRoute = `http://localhost:${port}`; createFolder(screenshotFolder); - const labApiParms: LabApiQueryParams = { - azureEnvironment: AzureEnvironments.CLOUD, - appType: AppTypes.CLOUD, - federationProvider: FederationProviders.ADFS2019, - userType: UserTypes.FEDERATED, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserFederated ); }); @@ -101,8 +84,14 @@ describe.skip("Auth Code ADFS 2019 Tests", () => { it("Performs acquire token", async () => { const screenshot = new Screenshot(`${screenshotFolder}/BaseCase`); + const accountPwd = await labUser.getPassword(); await page.goto(homeRoute); - await enterCredentialsADFS(page, screenshot, username, accountPwd); + await enterCredentialsADFS( + page, + screenshot, + labUser.upn, + accountPwd + ); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -119,8 +108,14 @@ describe.skip("Auth Code ADFS 2019 Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/PromptLogin` ); + const accountPwd = await labUser.getPassword(); await page.goto(`${homeRoute}/?prompt=login`); - await enterCredentialsADFS(page, screenshot, username, accountPwd); + await enterCredentialsADFS( + page, + screenshot, + labUser.upn, + accountPwd + ); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -137,11 +132,12 @@ describe.skip("Auth Code ADFS 2019 Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/PromptConsent` ); + const accountPwd = await labUser.getPassword(); await page.goto(`${homeRoute}/?prompt=consent`); await enterCredentialsADFSWithConsent( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForFunction( @@ -158,9 +154,15 @@ describe.skip("Auth Code ADFS 2019 Tests", () => { it("Performs acquire token with prompt = 'none'", async () => { const screenshot = new Screenshot(`${screenshotFolder}/PromptNone`); + const accountPwd = await labUser.getPassword(); // First login await page.goto(`${homeRoute}/?prompt=login`); - await enterCredentialsADFS(page, screenshot, username, accountPwd); + await enterCredentialsADFS( + page, + screenshot, + labUser.upn, + accountPwd + ); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -182,9 +184,15 @@ describe.skip("Auth Code ADFS 2019 Tests", () => { it("Performs acquire token with state", async () => { const screenshot = new Screenshot(`${screenshotFolder}/WithState`); + const accountPwd = await labUser.getPassword(); const STATE_VALUE = "value_on_state"; await page.goto(`${homeRoute}/?prompt=login&state=${STATE_VALUE}`); - await enterCredentialsADFS(page, screenshot, username, accountPwd); + await enterCredentialsADFS( + page, + screenshot, + labUser.upn, + accountPwd + ); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); diff --git a/samples/msal-node-samples/auth-code/test/auth-code-b2c-aad.spec.ts b/samples/msal-node-samples/auth-code/test/auth-code-b2c-aad.spec.ts index 738d90a51e..09129eefc5 100644 --- a/samples/msal-node-samples/auth-code/test/auth-code-b2c-aad.spec.ts +++ b/samples/msal-node-samples/auth-code/test/auth-code-b2c-aad.spec.ts @@ -6,17 +6,15 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - setupCredentials, b2cAadPpeAccountEnterCredentials, - RETRY_TIMES, - validateCacheLocation, SAMPLE_HOME_URL, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - AppTypes, - AzureEnvironments, + validateCacheLocation, + createFolder, + RETRY_TIMES, } from "e2e-test-utils"; import path from "path"; @@ -43,10 +41,12 @@ describe.skip("Auth Code B2C Tests (aad account)", () => { let port: number; let homeRoute: string; - let username: string; - let accountPwd: string; + let labUser: LabUser; - const screenshotFolder = path.join(__dirname, "screenshots/auth-code/b2c-aad"); + const screenshotFolder = path.join( + __dirname, + "screenshots/auth-code/b2c-aad" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -60,18 +60,8 @@ describe.skip("Auth Code B2C Tests (aad account)", () => { createFolder(screenshotFolder); - const labApiParms: LabApiQueryParams = { - azureEnvironment: AzureEnvironments.CLOUD, - appType: AppTypes.CLOUD, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserPublicCloud ); }); @@ -117,11 +107,12 @@ describe.skip("Auth Code B2C Tests (aad account)", () => { it("Performs acquire token", async () => { const screenshot = new Screenshot(`${screenshotFolder}/BaseCase`); + const accountPwd = await labUser.getPassword(); await page.goto(homeRoute); await b2cAadPpeAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForFunction( @@ -140,11 +131,12 @@ describe.skip("Auth Code B2C Tests (aad account)", () => { const screenshot = new Screenshot( `${screenshotFolder}/PromptLogin` ); + const accountPwd = await labUser.getPassword(); await page.goto(`${homeRoute}/?prompt=login`); await b2cAadPpeAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForFunction( @@ -164,11 +156,12 @@ describe.skip("Auth Code B2C Tests (aad account)", () => { const screenshot = new Screenshot( `${screenshotFolder}/PromptSelectAccount` ); + const accountPwd = await labUser.getPassword(); await page.goto(`${homeRoute}/?prompt=select_account`); await b2cAadPpeAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForFunction( @@ -186,12 +179,13 @@ describe.skip("Auth Code B2C Tests (aad account)", () => { it("Performs acquire token with prompt = 'none'", async () => { const screenshot = new Screenshot(`${screenshotFolder}/PromptNone`); + const accountPwd = await labUser.getPassword(); // First log the user in first await page.goto(`${homeRoute}/?prompt=login`); await b2cAadPpeAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForFunction( @@ -217,12 +211,13 @@ describe.skip("Auth Code B2C Tests (aad account)", () => { it("Performs acquire token with state", async () => { const screenshot = new Screenshot(`${screenshotFolder}/WithState`); + const accountPwd = await labUser.getPassword(); const STATE_VALUE = "value_on_state"; await page.goto(`${homeRoute}/?prompt=login&state=${STATE_VALUE}`); await b2cAadPpeAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForFunction( diff --git a/samples/msal-node-samples/auth-code/test/auth-code-b2c-local.spec.ts b/samples/msal-node-samples/auth-code/test/auth-code-b2c-local.spec.ts index ef3b8f23e2..cd967dbe1a 100644 --- a/samples/msal-node-samples/auth-code/test/auth-code-b2c-local.spec.ts +++ b/samples/msal-node-samples/auth-code/test/auth-code-b2c-local.spec.ts @@ -6,17 +6,15 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - setupCredentials, b2cLocalAccountEnterCredentials, - RETRY_TIMES, - validateCacheLocation, SAMPLE_HOME_URL, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - B2cProviders, - UserTypes, + validateCacheLocation, + createFolder, + RETRY_TIMES, } from "e2e-test-utils"; import path from "path"; @@ -43,10 +41,12 @@ describe("Auth Code B2C Tests (local account)", () => { let port: number; let homeRoute: string; - let username: string; - let accountPwd: string; + let labUser: LabUser; - const screenshotFolder = path.join(__dirname, "screenshots/auth-code/b2c-local"); + const screenshotFolder = path.join( + __dirname, + "screenshots/auth-code/b2c-local" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -60,19 +60,7 @@ describe("Auth Code B2C Tests (local account)", () => { createFolder(screenshotFolder); - const labApiParms: LabApiQueryParams = { - userType: UserTypes.B2C, - b2cProvider: B2cProviders.LOCAL, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient - ); + labUser = await LabResponseHelper.getLabUser(KeyVaultSecrets.UserB2C); }); afterAll(async () => { @@ -117,11 +105,12 @@ describe("Auth Code B2C Tests (local account)", () => { it("Performs acquire token", async () => { const screenshot = new Screenshot(`${screenshotFolder}/BaseCase`); + const accountPwd = await labUser.getPassword(); await page.goto(homeRoute); await b2cLocalAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForFunction( @@ -140,11 +129,12 @@ describe("Auth Code B2C Tests (local account)", () => { const screenshot = new Screenshot( `${screenshotFolder}/PromptLogin` ); + const accountPwd = await labUser.getPassword(); await page.goto(`${homeRoute}/?prompt=login`); await b2cLocalAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForFunction( @@ -164,11 +154,12 @@ describe("Auth Code B2C Tests (local account)", () => { const screenshot = new Screenshot( `${screenshotFolder}/PromptSelectAccount` ); + const accountPwd = await labUser.getPassword(); await page.goto(`${homeRoute}/?prompt=select_account`); await b2cLocalAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForFunction( @@ -186,12 +177,13 @@ describe("Auth Code B2C Tests (local account)", () => { it("Performs acquire token with prompt = 'none'", async () => { const screenshot = new Screenshot(`${screenshotFolder}/PromptNone`); + const accountPwd = await labUser.getPassword(); // First log the user in first await page.goto(`${homeRoute}/?prompt=login`); await b2cLocalAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForFunction( @@ -217,12 +209,13 @@ describe("Auth Code B2C Tests (local account)", () => { it("Performs acquire token with state", async () => { const screenshot = new Screenshot(`${screenshotFolder}/WithState`); + const accountPwd = await labUser.getPassword(); const STATE_VALUE = "value_on_state"; await page.goto(`${homeRoute}/?prompt=login&state=${STATE_VALUE}`); await b2cLocalAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForFunction( diff --git a/samples/msal-node-samples/auth-code/test/auth-code-b2c-msa.spec.ts b/samples/msal-node-samples/auth-code/test/auth-code-b2c-msa.spec.ts index 1e9c57250d..85ae199ea3 100644 --- a/samples/msal-node-samples/auth-code/test/auth-code-b2c-msa.spec.ts +++ b/samples/msal-node-samples/auth-code/test/auth-code-b2c-msa.spec.ts @@ -7,16 +7,14 @@ import * as puppeteer from "puppeteer"; import { Screenshot, createFolder, - setupCredentials, b2cMsaAccountEnterCredentials, RETRY_TIMES, validateCacheLocation, SAMPLE_HOME_URL, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - B2cProviders, - UserTypes, + LabResponseHelper, + KeyVaultSecrets, + LabUser, } from "e2e-test-utils"; import path from "path"; @@ -43,16 +41,18 @@ describe("Auth Code B2C Tests (msa account)", () => { let port: number; let homeRoute: string; - let username: string; - let accountPwd: string; + let labUser: LabUser; + let labPassword: string; - const screenshotFolder = path.join(__dirname, "screenshots/auth-code/b2c-msa"); + const screenshotFolder = path.join( + __dirname, + "screenshots/auth-code/b2c-msa" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); // @ts-ignore browser = await global.__BROWSER__; - // @ts-ignore // To run tests in parallel, each test needs to run on a unique port port = 3006; @@ -60,19 +60,9 @@ describe("Auth Code B2C Tests (msa account)", () => { createFolder(screenshotFolder); - const labApiParms: LabApiQueryParams = { - userType: UserTypes.B2C, - b2cProvider: B2cProviders.MICROSOFT, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient - ); + // Get B2C user configuration from Key Vault + labUser = await LabResponseHelper.getLabUser(KeyVaultSecrets.UserB2CMSA); + labPassword = await labUser.getPassword(); }); afterAll(async () => { @@ -121,8 +111,8 @@ describe("Auth Code B2C Tests (msa account)", () => { await b2cMsaAccountEnterCredentials( page, screenshot, - username, - accountPwd + labUser.upn, + labPassword ); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` @@ -144,8 +134,8 @@ describe("Auth Code B2C Tests (msa account)", () => { await b2cMsaAccountEnterCredentials( page, screenshot, - username, - accountPwd + labUser.upn, + labPassword ); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` @@ -168,8 +158,8 @@ describe("Auth Code B2C Tests (msa account)", () => { await b2cMsaAccountEnterCredentials( page, screenshot, - username, - accountPwd + labUser.upn, + labPassword ); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` @@ -191,8 +181,8 @@ describe("Auth Code B2C Tests (msa account)", () => { await b2cMsaAccountEnterCredentials( page, screenshot, - username, - accountPwd + labUser.upn, + labPassword ); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` @@ -222,8 +212,8 @@ describe("Auth Code B2C Tests (msa account)", () => { await b2cMsaAccountEnterCredentials( page, screenshot, - username, - accountPwd + labUser.upn, + labPassword ); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` diff --git a/samples/msal-node-samples/b2c-user-flows/test/user-flows-local.spec.ts b/samples/msal-node-samples/b2c-user-flows/test/user-flows-local.spec.ts index 605b1061bf..f6fb4d58e7 100644 --- a/samples/msal-node-samples/b2c-user-flows/test/user-flows-local.spec.ts +++ b/samples/msal-node-samples/b2c-user-flows/test/user-flows-local.spec.ts @@ -6,17 +6,15 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - setupCredentials, b2cLocalAccountEnterCredentials, - RETRY_TIMES, - validateCacheLocation, SAMPLE_HOME_URL, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - B2cProviders, - UserTypes, + validateCacheLocation, + createFolder, + RETRY_TIMES, } from "e2e-test-utils"; import path from "path"; @@ -43,12 +41,14 @@ describe("B2C User Flow Tests", () => { let port: string; let homeRoute: string; - let username: string; + let labUser: LabUser; let accountPwd: string; + let clientSecret: string; - let clientSecret: { secret: string; value: string }; - - const screenshotFolder = path.join(__dirname, "screenshots/b2c-user-flows/local"); + const screenshotFolder = path.join( + __dirname, + "screenshots/b2c-user-flows/local" + ); beforeAll(async () => { createFolder(screenshotFolder); @@ -60,20 +60,10 @@ describe("B2C User Flow Tests", () => { port = 3000; homeRoute = `http://localhost:${port}`; - const labApiParams: LabApiQueryParams = { - userType: UserTypes.B2C, - b2cProvider: B2cProviders.LOCAL, - }; - - const labClient = new LabClient(); - - clientSecret = await labClient.getSecret("MSIDLABB2C-MSAapp-AppSecret"); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParams - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient + labUser = await LabResponseHelper.getLabUser(KeyVaultSecrets.UserB2C); + accountPwd = await labUser.getPassword(); + clientSecret = await LabResponseHelper.getMsidLabSecret( + "MSIDLABB2C-MSAapp-AppSecret" ); }); @@ -89,7 +79,7 @@ describe("B2C User Flow Tests", () => { cca = new ConfidentialClientApplication({ auth: { clientId: config.authOptions.clientId, - clientSecret: clientSecret.value, + clientSecret: clientSecret, authority: config.policies.authorities.signUpSignIn.authority, knownAuthorities: [config.policies.authorityDomain], @@ -131,11 +121,15 @@ describe("B2C User Flow Tests", () => { ); let displayName = (Math.random() + 1).toString(36).substring(7); // generate a random string await page.goto(homeRoute); - await page.click("#signIn"); + await screenshot.takeScreenshot(page, "homePage"); + const [response] = await Promise.all([ + page.waitForNavigation(), + page.click("#signIn"), + ]); await b2cLocalAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForFunction( diff --git a/samples/msal-node-samples/b2c-user-flows/test/user-flows-msa.spec.ts b/samples/msal-node-samples/b2c-user-flows/test/user-flows-msa.spec.ts index 195ded932f..30c8d83733 100644 --- a/samples/msal-node-samples/b2c-user-flows/test/user-flows-msa.spec.ts +++ b/samples/msal-node-samples/b2c-user-flows/test/user-flows-msa.spec.ts @@ -7,16 +7,15 @@ import * as puppeteer from "puppeteer"; import { Screenshot, createFolder, - setupCredentials, b2cMsaAccountEnterCredentials, RETRY_TIMES, validateCacheLocation, SAMPLE_HOME_URL, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - B2cProviders, - UserTypes, + LabResponseHelper, + KeyVaultSecrets, + LabUser, + getMsidLabKeyVaultProvider, } from "e2e-test-utils"; import path from "path"; @@ -43,12 +42,14 @@ describe("B2C User Flow Tests", () => { let port: string; let homeRoute: string; - let username: string; - let accountPwd: string; + let labUser: LabUser; + let labPassword: string; + let clientSecret: string; - let clientSecret: { secret: string; value: string }; - - const screenshotFolder = path.join(__dirname, "screenshots/b2c-user-flows/msa"); + const screenshotFolder = path.join( + __dirname, + "screenshots/b2c-user-flows/msa" + ); beforeAll(async () => { createFolder(screenshotFolder); @@ -59,19 +60,16 @@ describe("B2C User Flow Tests", () => { port = 3001; homeRoute = `http://localhost:${port}`; - const labApiParams: LabApiQueryParams = { - userType: UserTypes.B2C, - b2cProvider: B2cProviders.MICROSOFT, - }; - - const labClient = new LabClient(); - clientSecret = await labClient.getSecret("MSIDLABB2C-MSAapp-AppSecret"); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParams + // Get B2C user configuration from Key Vault + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserB2CMSA ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient + labPassword = await labUser.getPassword(); + + // Get B2C MSA app secret from Key Vault + const kvProvider = getMsidLabKeyVaultProvider(); + clientSecret = await kvProvider.getSecretValue( + KeyVaultSecrets.B2CMsaAppSecretName ); }); @@ -87,7 +85,7 @@ describe("B2C User Flow Tests", () => { cca = new ConfidentialClientApplication({ auth: { clientId: config.authOptions.clientId, - clientSecret: clientSecret.value, + clientSecret: clientSecret, authority: config.policies.authorities.signUpSignIn.authority, knownAuthorities: [config.policies.authorityDomain], @@ -132,8 +130,8 @@ describe("B2C User Flow Tests", () => { await b2cMsaAccountEnterCredentials( page, screenshot, - username, - accountPwd + labUser.upn, + labPassword ); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` diff --git a/samples/msal-node-samples/client-credentials/test/client-credentials-aad.spec.ts b/samples/msal-node-samples/client-credentials/test/client-credentials-aad.spec.ts index 4357093aa0..1831eefb3d 100644 --- a/samples/msal-node-samples/client-credentials/test/client-credentials-aad.spec.ts +++ b/samples/msal-node-samples/client-credentials/test/client-credentials-aad.spec.ts @@ -1,13 +1,21 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * + * Client Credentials integration tests using Key Vault-based configuration. + * Tests use certificate-based authentication to acquire tokens. + */ + import { RETRY_TIMES, - retrieveAppConfiguration, validateCacheLocation, - LabApiQueryParams, NodeCacheTestUtils, - LabClient, + LabResponseHelper, + KeyVaultSecrets, + getLabCredential, + LabCertificateCredential, } from "e2e-test-utils"; import { ConfidentialClientApplication } from "@azure/msal-node"; -import config from "../config/AAD.json"; const TEST_CACHE_LOCATION = `${__dirname}/data/aad.cache.json`; @@ -15,42 +23,47 @@ const getClientCredentialsToken = require("../index"); const cachePlugin = require("../../cachePlugin.js")(TEST_CACHE_LOCATION); -let clientID; -let clientSecret; -let authority; - -const clientCredentialRequestScopes = ["https://graph.microsoft.com/.default"]; +const clientCredentialRequestScopes = ["https://vault.azure.net/.default"]; -describe("Client Credentials AAD Prod Tests", () => { +describe("Client Credentials AAD Tests", () => { jest.retryTimes(RETRY_TIMES); jest.setTimeout(90000); + // Lab certificate credential (used for both tests) + let labCredential: LabCertificateCredential; + + // App configs from Key Vault + let s2sAppId: string; + let s2sAuthority: string; + let regionalAppId: string; + let regionalAuthority: string; + beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); - const labApiParms: LabApiQueryParams = { - appType: "cloud", - publicClient: "no", - signInAudience: "azureadmyorg", - }; + // Get the lab certificate credential (same cert used for Key Vault auth) + labCredential = getLabCredential(); - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms + // Get standard S2S app configuration from Key Vault + const s2sAppConfig = await LabResponseHelper.getAppConfig( + KeyVaultSecrets.AppS2S ); - [clientID, clientSecret, authority] = await retrieveAppConfiguration( - envResponse[0], - labClient, - true + s2sAppId = s2sAppConfig.appId!; + s2sAuthority = s2sAppConfig.authority!; + + // Get regional app configuration from Key Vault + const regionalAppConfig = await LabResponseHelper.getAppConfig( + KeyVaultSecrets.MsalAppAzureAdMultipleOrgsRegional ); + regionalAppId = regionalAppConfig.appId!; + regionalAuthority = regionalAppConfig.authority!; - // Update the complete config - config.authOptions.clientId = clientID; - config.authOptions.clientSecret = clientSecret; - config.authOptions.authority = authority; + console.log( + `Test setup complete - S2S App ID: ${s2sAppId}, Regional App ID: ${regionalAppId}` + ); }); - describe("Acquire Token", () => { + describe("Acquire Token with Certificate", () => { let confidentialClientApplication: ConfidentialClientApplication; beforeAll(async () => { @@ -63,13 +76,23 @@ describe("Client Credentials AAD Prod Tests", () => { it("Performs acquire token", async () => { confidentialClientApplication = new ConfidentialClientApplication({ - auth: config.authOptions, + auth: { + clientId: s2sAppId, + authority: s2sAuthority, + clientCertificate: { + thumbprintSha256: labCredential.thumbprintSha256, + privateKey: labCredential.privateKey, + x5c: labCredential.x5c, + }, + }, cache: { cachePlugin }, }); + await getClientCredentialsToken( confidentialClientApplication, clientCredentialRequestScopes ); + const cachedTokens = await NodeCacheTestUtils.getTokens( TEST_CACHE_LOCATION ); @@ -78,14 +101,24 @@ describe("Client Credentials AAD Prod Tests", () => { it("Performs acquire token through regional authorities", async () => { confidentialClientApplication = new ConfidentialClientApplication({ - auth: config.authOptions, + auth: { + clientId: regionalAppId, + authority: regionalAuthority, + clientCertificate: { + thumbprintSha256: labCredential.thumbprintSha256, + privateKey: labCredential.privateKey, + x5c: labCredential.x5c, + }, + }, cache: { cachePlugin }, }); + await getClientCredentialsToken( confidentialClientApplication, clientCredentialRequestScopes, { region: "westus2" } ); + const cachedTokens = await NodeCacheTestUtils.getTokens( TEST_CACHE_LOCATION ); diff --git a/samples/msal-node-samples/device-code/test/device-code-aad-agc.spec.ts b/samples/msal-node-samples/device-code/test/device-code-aad-agc.spec.ts index b207061703..4cb2b28768 100644 --- a/samples/msal-node-samples/device-code/test/device-code-aad-agc.spec.ts +++ b/samples/msal-node-samples/device-code/test/device-code-aad-agc.spec.ts @@ -6,15 +6,17 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - RETRY_TIMES, approveRemoteConnect, enterCredentials, enterDeviceCode, - validateCacheLocation, + LabResponseHelper, + KeyVaultSecrets, + LabUser, + AppConfig, NodeCacheTestUtils, - getKeyVaultSecretClient, - getCredentials, + validateCacheLocation, + createFolder, + RETRY_TIMES, } from "e2e-test-utils"; import { Configuration, PublicClientApplication } from "@azure/msal-node"; import path from "path"; @@ -30,16 +32,6 @@ const cachePlugin = require("../../cachePlugin.js")(TEST_CACHE_LOCATION); // Load scenario configuration const config = require("../config/AAD-AGC.json"); -config.authOptions = { - clientId: process.env.AZURE_CLIENT_ID, - authority: `${process.env.AUTHORITY}/${process.env.AZURE_TENANT_ID}`, - knownAuthorities: [ - `${process.env.AUTHORITY}/${process.env.AZURE_TENANT_ID}`, - ], -}; -config.resourceApi = { - endpoint: `${process.env.GRAPH_URL}/v1.0/me`, -}; describe("Device Code AAD AGC Tests", () => { jest.setTimeout(45000); @@ -50,10 +42,13 @@ describe("Device Code AAD AGC Tests", () => { let publicClientApplication: PublicClientApplication; let clientConfig: Configuration; - let username: string; - let password: string; + let labUser: LabUser; + let appConfig: AppConfig; - const screenshotFolder = path.join(__dirname, "screenshots/device-code/aad-agc"); + const screenshotFolder = path.join( + __dirname, + "screenshots/device-code/aad-agc" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -61,8 +56,26 @@ describe("Device Code AAD AGC Tests", () => { browser = await global.__BROWSER__; createFolder(screenshotFolder); - const keyVaultSecretClient = await getKeyVaultSecretClient(); - [username, password] = await getCredentials(keyVaultSecretClient); + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserArlington + ); + appConfig = await LabResponseHelper.getAppConfig( + KeyVaultSecrets.ArlAppIdLabsApp + ); + + // Configure auth options from Key Vault app config + config.authOptions = { + clientId: appConfig.appId, + authority: appConfig.authority, + knownAuthorities: appConfig.authority + ? [new URL(appConfig.authority).origin] + : [], + }; + config.resourceApi = { + endpoint: appConfig.authority + ? `${new URL(appConfig.authority).origin}/v1.0/me` + : undefined, + }; }); afterAll(async () => { @@ -89,6 +102,7 @@ describe("Device Code AAD AGC Tests", () => { it("Performs acquire token with Device Code flow", async () => { const screenshot = new Screenshot(`${screenshotFolder}/BaseCase`); + const password = await labUser.getPassword(); const deviceCodeCallback = async (deviceCodeResponse: any) => { const { userCode, verificationUri } = deviceCodeResponse; @@ -99,7 +113,7 @@ describe("Device Code AAD AGC Tests", () => { verificationUri ); await approveRemoteConnect(page, screenshot); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForSelector("#message"); await screenshot.takeScreenshot( page, diff --git a/samples/msal-node-samples/device-code/test/device-code-aad.spec.ts b/samples/msal-node-samples/device-code/test/device-code-aad.spec.ts index 5be072f9b6..8660753193 100644 --- a/samples/msal-node-samples/device-code/test/device-code-aad.spec.ts +++ b/samples/msal-node-samples/device-code/test/device-code-aad.spec.ts @@ -6,18 +6,16 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - setupCredentials, - RETRY_TIMES, approveRemoteConnect, enterCredentials, enterDeviceCode, - validateCacheLocation, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - AppTypes, - AzureEnvironments, + validateCacheLocation, + createFolder, + RETRY_TIMES, } from "e2e-test-utils"; import { Configuration, PublicClientApplication } from "@azure/msal-node"; import path from "path"; @@ -43,10 +41,12 @@ describe("Device Code AAD Prod Tests", () => { let publicClientApplication: PublicClientApplication; let clientConfig: Configuration; - let username: string; - let accountPwd: string; + let labUser: LabUser; - const screenshotFolder = path.join(__dirname, "screenshots/device-code/aad"); + const screenshotFolder = path.join( + __dirname, + "screenshots/device-code/aad" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -54,19 +54,8 @@ describe("Device Code AAD Prod Tests", () => { browser = await global.__BROWSER__; createFolder(screenshotFolder); - // Configure Lab API Query Parameters - const labApiParms: LabApiQueryParams = { - azureEnvironment: AzureEnvironments.CLOUD, - appType: AppTypes.CLOUD, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserPublicCloud ); }); @@ -94,6 +83,7 @@ describe("Device Code AAD Prod Tests", () => { it("Performs acquire token with Device Code flow", async () => { const screenshot = new Screenshot(`${screenshotFolder}/BaseCase`); + const accountPwd = await labUser.getPassword(); const deviceCodeCallback = async (deviceCodeResponse: any) => { const { userCode, verificationUri } = deviceCodeResponse; @@ -104,7 +94,12 @@ describe("Device Code AAD Prod Tests", () => { verificationUri ); await approveRemoteConnect(page, screenshot); - await enterCredentials(page, screenshot, username, accountPwd); + await enterCredentials( + page, + screenshot, + labUser.upn, + accountPwd + ); await page.waitForSelector("#message"); await screenshot.takeScreenshot( page, diff --git a/samples/msal-node-samples/device-code/test/device-code-adfs.spec.ts b/samples/msal-node-samples/device-code/test/device-code-adfs.spec.ts index c93a958657..c2ee6e2f4e 100644 --- a/samples/msal-node-samples/device-code/test/device-code-adfs.spec.ts +++ b/samples/msal-node-samples/device-code/test/device-code-adfs.spec.ts @@ -6,19 +6,15 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - setupCredentials, - RETRY_TIMES, enterCredentialsADFSWithConsent, enterDeviceCode, - validateCacheLocation, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - AppTypes, - AzureEnvironments, - FederationProviders, - UserTypes, + validateCacheLocation, + createFolder, + RETRY_TIMES, } from "e2e-test-utils"; import path from "path"; import { Configuration, PublicClientApplication } from "@azure/msal-node"; @@ -44,10 +40,12 @@ describe.skip("Device Code ADFS 2019 Tests", () => { let publicClientApplication: PublicClientApplication; let clientConfig: Configuration; - let username: string; - let accountPwd: string; + let labUser: LabUser; - const screenshotFolder = path.join(__dirname, "screenshots/device-code/adfs"); + const screenshotFolder = path.join( + __dirname, + "screenshots/device-code/adfs" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -55,21 +53,8 @@ describe.skip("Device Code ADFS 2019 Tests", () => { browser = await global.__BROWSER__; createFolder(screenshotFolder); - // Configure Lab API Query Parameters - const labApiParms: LabApiQueryParams = { - azureEnvironment: AzureEnvironments.CLOUD, - appType: AppTypes.CLOUD, - federationProvider: FederationProviders.ADFS2019, - userType: UserTypes.FEDERATED, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserFederated ); }); @@ -97,6 +82,7 @@ describe.skip("Device Code ADFS 2019 Tests", () => { it("Performs acquire token with Device Code flow", async () => { const screenshot = new Screenshot(`${screenshotFolder}/BaseCase`); + const accountPwd = await labUser.getPassword(); const deviceCodeCallback = async (deviceCodeResponse: any) => { const { userCode, verificationUri } = deviceCodeResponse; @@ -109,7 +95,7 @@ describe.skip("Device Code ADFS 2019 Tests", () => { await enterCredentialsADFSWithConsent( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForSelector("#message"); diff --git a/samples/msal-node-samples/on-behalf-of/test/obo-aad.spec.ts b/samples/msal-node-samples/on-behalf-of/test/obo-aad.spec.ts index d2d3610629..9a2c0e1873 100644 --- a/samples/msal-node-samples/on-behalf-of/test/obo-aad.spec.ts +++ b/samples/msal-node-samples/on-behalf-of/test/obo-aad.spec.ts @@ -6,16 +6,14 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - setupCredentials, - enterCredentials - validateCacheLocation, + enterCredentials, SAMPLE_HOME_URL, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - AppTypes, - AzureEnvironments, + validateCacheLocation, + createFolder, } from "e2e-test-utils"; import { ConfidentialClientApplication, LogLevel } from "@azure/msal-node"; import path from "path"; @@ -56,10 +54,9 @@ describe("OBO AAD Tests", () => { let context: puppeteer.BrowserContext; let page: puppeteer.Page; - let username: string; - let accountPwd: string; + let labUser: LabUser; - const screenshotFolder = path.join(__dirname, "screenshots/on-behalf-of") + const screenshotFolder = path.join(__dirname, "screenshots/on-behalf-of"); beforeAll(async () => { await validateCacheLocation(WEB_APP_TEST_CACHE_LOCATION); @@ -69,18 +66,8 @@ describe("OBO AAD Tests", () => { createFolder(screenshotFolder); - const labApiParms: LabApiQueryParams = { - azureEnvironment: AzureEnvironments.CLOUD, - appType: AppTypes.CLOUD, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserPublicCloud ); }); @@ -164,8 +151,9 @@ describe("OBO AAD Tests", () => { it("Performs acquire token via OBO flow", async () => { const screenshot = new Screenshot(`${screenshotFolder}/BaseCase`); + const accountPwd = await labUser.getPassword(); await page.goto(HOME_ROUTE); - await enterCredentials(page, screenshot, username, accountPwd); + await enterCredentials(page, screenshot, labUser.upn, accountPwd); await page.waitForFunction( `window.location.href.startsWith("${SAMPLE_HOME_URL}")` ); @@ -184,7 +172,7 @@ describe("OBO AAD Tests", () => { expect(Object.keys(accounts).length).toBe(1); const account = Object.values(accounts)[0]; - expect(account.username).toEqual(username); + expect(account.username).toEqual(labUser.upn); }); }); }); diff --git a/samples/msal-node-samples/silent-flow/test/silent-flow-aad-agc-confidential.spec.ts b/samples/msal-node-samples/silent-flow/test/silent-flow-aad-agc-confidential.spec.ts index 1e1db4dfb9..ac7bf1f6df 100644 --- a/samples/msal-node-samples/silent-flow/test/silent-flow-aad-agc-confidential.spec.ts +++ b/samples/msal-node-samples/silent-flow/test/silent-flow-aad-agc-confidential.spec.ts @@ -6,19 +6,21 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - ONE_SECOND_IN_MS, - RETRY_TIMES, clickSignIn, enterCredentials, SAMPLE_HOME_URL, SUCCESSFUL_GRAPH_CALL_ID, SUCCESSFUL_GET_ALL_ACCOUNTS_ID, - validateCacheLocation, SUCCESSFUL_SILENT_TOKEN_ACQUISITION_ID, + LabResponseHelper, + KeyVaultSecrets, + LabUser, + AppConfig, NodeCacheTestUtils, - getKeyVaultSecretClient, - getCredentials, + validateCacheLocation, + createFolder, + RETRY_TIMES, + ONE_SECOND_IN_MS, } from "e2e-test-utils"; import { ConfidentialClientApplication, TokenCache } from "@azure/msal-node"; import path from "path"; @@ -34,18 +36,6 @@ const cachePlugin = require("../../cachePlugin.js")(TEST_CACHE_LOCATION); // Load scenario configuration const config = require("../config/AAD-AGC-Confidential.json"); -config.authOptions = { - ...config.authOptions, - clientId: process.env.AZURE_CLIENT_ID, - clientSecret: process.env.AZURE_CLIENT_SECRET, - authority: `${process.env.AUTHORITY}/${process.env.AZURE_TENANT_ID}`, - knownAuthorities: [ - `${process.env.AUTHORITY}/${process.env.AZURE_TENANT_ID}`, - ], -}; -config.resourceApi = { - endpoint: `${process.env.GRAPH_URL}/v1.0/me`, -}; describe("Silent Flow AAD AGC Confidential Tests", () => { jest.retryTimes(RETRY_TIMES); @@ -60,10 +50,13 @@ describe("Silent Flow AAD AGC Confidential Tests", () => { let msalTokenCache: TokenCache; let server: any; - let username: string; - let password: string; + let labUser: LabUser; + let appConfig: AppConfig; - const screenshotFolder = path.join(__dirname, "screenshots/silent-flow/aad-agc-confidential"); + const screenshotFolder = path.join( + __dirname, + "screenshots/silent-flow/aad-agc-confidential" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -74,8 +67,37 @@ describe("Silent Flow AAD AGC Confidential Tests", () => { createFolder(screenshotFolder); - const keyVaultSecretClient = await getKeyVaultSecretClient(); - [username, password] = await getCredentials(keyVaultSecretClient); + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserArlington + ); + appConfig = await LabResponseHelper.getAppConfig( + KeyVaultSecrets.MsalAppArlingtonCCA + ); + + // Get client secret from Key Vault + let clientSecret: string | undefined; + if (appConfig.secretName) { + clientSecret = await LabResponseHelper.getSecret( + appConfig.secretName + ); + } + + // Configure auth options from Key Vault app config + const authorityUrl = appConfig.authority + ? new URL(appConfig.authority) + : null; + config.authOptions = { + ...config.authOptions, + clientId: appConfig.appId, + clientSecret: clientSecret, + authority: appConfig.authority, + knownAuthorities: authorityUrl ? [authorityUrl.origin] : [], + }; + config.resourceApi = { + endpoint: authorityUrl + ? `${authorityUrl.origin}/v1.0/me` + : undefined, + }; confidentialClientApplication = new ConfidentialClientApplication({ auth: config.authOptions, @@ -116,8 +138,9 @@ describe("Silent Flow AAD AGC Confidential Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenAuthCode` ); + const password = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForSelector("#acquireTokenSilent"); await page.click("#acquireTokenSilent"); const cachedTokens = await NodeCacheTestUtils.waitForTokens( @@ -133,8 +156,9 @@ describe("Silent Flow AAD AGC Confidential Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenSilent` ); + const password = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForSelector("#acquireTokenSilent"); await screenshot.takeScreenshot(page, "ATS"); await page.click("#acquireTokenSilent"); @@ -155,8 +179,9 @@ describe("Silent Flow AAD AGC Confidential Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/RefreshExpiredToken` ); + const password = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForSelector("#acquireTokenSilent"); let tokens = await NodeCacheTestUtils.waitForTokens( @@ -218,8 +243,9 @@ describe("Silent Flow AAD AGC Confidential Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/GetAllAccounts` ); + const password = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForSelector("#getAllAccounts"); await page.click("#getAllAccounts"); await page.waitForSelector( diff --git a/samples/msal-node-samples/silent-flow/test/silent-flow-aad-agc-public.spec.ts b/samples/msal-node-samples/silent-flow/test/silent-flow-aad-agc-public.spec.ts index be82e71a53..5d5d8a2246 100644 --- a/samples/msal-node-samples/silent-flow/test/silent-flow-aad-agc-public.spec.ts +++ b/samples/msal-node-samples/silent-flow/test/silent-flow-aad-agc-public.spec.ts @@ -6,19 +6,21 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - ONE_SECOND_IN_MS, - RETRY_TIMES, clickSignIn, enterCredentials, SAMPLE_HOME_URL, SUCCESSFUL_GRAPH_CALL_ID, SUCCESSFUL_GET_ALL_ACCOUNTS_ID, - validateCacheLocation, SUCCESSFUL_SILENT_TOKEN_ACQUISITION_ID, + LabResponseHelper, + KeyVaultSecrets, + LabUser, + AppConfig, NodeCacheTestUtils, - getKeyVaultSecretClient, - getCredentials, + validateCacheLocation, + createFolder, + RETRY_TIMES, + ONE_SECOND_IN_MS, } from "e2e-test-utils"; import { PublicClientApplication, TokenCache } from "@azure/msal-node"; import path from "path"; @@ -34,17 +36,6 @@ const cachePlugin = require("../../cachePlugin.js")(TEST_CACHE_LOCATION); // Load scenario configuration const config = require("../config/AAD-AGC-Public.json"); -config.authOptions = { - ...config.authOptions, - clientId: process.env.AZURE_CLIENT_ID, - authority: `${process.env.AUTHORITY}/${process.env.AZURE_TENANT_ID}`, - knownAuthorities: [ - `${process.env.AUTHORITY}/${process.env.AZURE_TENANT_ID}`, - ], -}; -config.resourceApi = { - endpoint: `${process.env.AUTHORITY}/v1.0/me`, -}; describe("Silent Flow AAD AGC Public Tests", () => { jest.retryTimes(RETRY_TIMES); @@ -59,10 +50,13 @@ describe("Silent Flow AAD AGC Public Tests", () => { let msalTokenCache: TokenCache; let server: any; - let username: string; - let password: string; + let labUser: LabUser; + let appConfig: AppConfig; - const screenshotFolder = path.join(__dirname, "screenshots/silent-flow/aad-agc-public"); + const screenshotFolder = path.join( + __dirname, + "screenshots/silent-flow/aad-agc-public" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -73,8 +67,25 @@ describe("Silent Flow AAD AGC Public Tests", () => { createFolder(screenshotFolder); - const keyVaultSecretClient = await getKeyVaultSecretClient(); - [username, password] = await getCredentials(keyVaultSecretClient); + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserArlington + ); + appConfig = await LabResponseHelper.getAppConfig( + KeyVaultSecrets.ArlAppIdLabsApp + ); + + // Configure auth options from Key Vault app config + config.authOptions = { + ...config.authOptions, + clientId: appConfig.appId, + authority: appConfig.authority, + knownAuthorities: appConfig.authority + ? [new URL(appConfig.authority).origin] + : [], + }; + config.resourceApi = { + endpoint: `${new URL(appConfig.authority!).origin}/v1.0/me`, + }; publicClientApplication = new PublicClientApplication({ auth: config.authOptions, @@ -115,8 +126,9 @@ describe("Silent Flow AAD AGC Public Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenAuthCode` ); + const password = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForSelector("#acquireTokenSilent"); await page.click("#acquireTokenSilent"); const cachedTokens = await NodeCacheTestUtils.waitForTokens( @@ -132,8 +144,9 @@ describe("Silent Flow AAD AGC Public Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenSilent` ); + const password = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForSelector("#acquireTokenSilent"); await screenshot.takeScreenshot(page, "ATS"); await page.click("#acquireTokenSilent"); @@ -154,8 +167,9 @@ describe("Silent Flow AAD AGC Public Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenSilentFromPersistent` ); + const password = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForSelector("#acquireTokenSilent"); publicClientApplication.clearCache(); await screenshot.takeScreenshot(page, "ATS"); @@ -177,8 +191,9 @@ describe("Silent Flow AAD AGC Public Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/RefreshExpiredToken` ); + const password = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForSelector("#acquireTokenSilent"); let tokens = await NodeCacheTestUtils.waitForTokens( @@ -240,8 +255,9 @@ describe("Silent Flow AAD AGC Public Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/GetAllAccounts` ); + const password = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, password); + await enterCredentials(page, screenshot, labUser.upn, password); await page.waitForSelector("#getAllAccounts"); await page.click("#getAllAccounts"); await page.waitForSelector( diff --git a/samples/msal-node-samples/silent-flow/test/silent-flow-aad.spec.ts b/samples/msal-node-samples/silent-flow/test/silent-flow-aad.spec.ts index 74b8bddf17..289c8813c2 100644 --- a/samples/msal-node-samples/silent-flow/test/silent-flow-aad.spec.ts +++ b/samples/msal-node-samples/silent-flow/test/silent-flow-aad.spec.ts @@ -6,22 +6,20 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - setupCredentials, - ONE_SECOND_IN_MS, - RETRY_TIMES, clickSignIn, enterCredentials, SAMPLE_HOME_URL, SUCCESSFUL_GRAPH_CALL_ID, SUCCESSFUL_GET_ALL_ACCOUNTS_ID, - validateCacheLocation, SUCCESSFUL_SILENT_TOKEN_ACQUISITION_ID, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - AppTypes, - AzureEnvironments, + validateCacheLocation, + createFolder, + RETRY_TIMES, + ONE_SECOND_IN_MS, } from "e2e-test-utils"; import path from "path"; import { PublicClientApplication, TokenCache } from "@azure/msal-node"; @@ -51,10 +49,12 @@ describe("Silent Flow AAD Prod Tests", () => { let msalTokenCache: TokenCache; let server: any; - let username: string; - let accountPwd: string; + let labUser: LabUser; - const screenshotFolder = path.join(__dirname, "screenshots/silent-flow/aad"); + const screenshotFolder = path.join( + __dirname, + "screenshots/silent-flow/aad" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -65,19 +65,8 @@ describe("Silent Flow AAD Prod Tests", () => { createFolder(screenshotFolder); - const labApiParms: LabApiQueryParams = { - azureEnvironment: AzureEnvironments.CLOUD, - appType: AppTypes.CLOUD, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserPublicCloud ); publicClientApplication = new PublicClientApplication({ @@ -119,8 +108,9 @@ describe("Silent Flow AAD Prod Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenAuthCode` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, accountPwd); + await enterCredentials(page, screenshot, labUser.upn, accountPwd); await page.waitForSelector("#acquireTokenSilent"); await page.click("#acquireTokenSilent"); const cachedTokens = await NodeCacheTestUtils.waitForTokens( @@ -136,8 +126,9 @@ describe("Silent Flow AAD Prod Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenSilent` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, accountPwd); + await enterCredentials(page, screenshot, labUser.upn, accountPwd); await page.waitForSelector("#acquireTokenSilent"); await screenshot.takeScreenshot(page, "ATS"); await page.click("#acquireTokenSilent"); @@ -158,8 +149,9 @@ describe("Silent Flow AAD Prod Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenSilentFromPersistent` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, accountPwd); + await enterCredentials(page, screenshot, labUser.upn, accountPwd); await page.waitForSelector("#acquireTokenSilent"); await publicClientApplication.clearCache(); await screenshot.takeScreenshot(page, "ATS"); @@ -181,8 +173,9 @@ describe("Silent Flow AAD Prod Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/RefreshExpiredToken` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, accountPwd); + await enterCredentials(page, screenshot, labUser.upn, accountPwd); await page.waitForSelector("#acquireTokenSilent"); let tokens = await NodeCacheTestUtils.waitForTokens( @@ -244,8 +237,14 @@ describe("Silent Flow AAD Prod Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/GetAllAccounts` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentials(page, screenshot, username, accountPwd); + await enterCredentials( + page, + screenshot, + labUser.upn, + accountPwd + ); await page.waitForSelector("#getAllAccounts"); await page.click("#getAllAccounts"); await page.waitForSelector( diff --git a/samples/msal-node-samples/silent-flow/test/silent-flow-adfs.spec.ts b/samples/msal-node-samples/silent-flow/test/silent-flow-adfs.spec.ts index d92993f3a1..3c49eea951 100644 --- a/samples/msal-node-samples/silent-flow/test/silent-flow-adfs.spec.ts +++ b/samples/msal-node-samples/silent-flow/test/silent-flow-adfs.spec.ts @@ -6,24 +6,20 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - setupCredentials, - ONE_SECOND_IN_MS, - RETRY_TIMES, clickSignIn, enterCredentialsADFS, SAMPLE_HOME_URL, SUCCESSFUL_GRAPH_CALL_ID, SUCCESSFUL_GET_ALL_ACCOUNTS_ID, - validateCacheLocation, SUCCESSFUL_SILENT_TOKEN_ACQUISITION_ID, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - AppTypes, - AzureEnvironments, - FederationProviders, - UserTypes, + validateCacheLocation, + createFolder, + RETRY_TIMES, + ONE_SECOND_IN_MS, } from "e2e-test-utils"; import path from "path"; import { PublicClientApplication, TokenCache } from "@azure/msal-node"; @@ -53,10 +49,12 @@ describe.skip("Silent Flow ADFS 2019 Tests", () => { let msalTokenCache: TokenCache; let server: any; - let username: string; - let accountPwd: string; + let labUser: LabUser; - const screenshotFolder = path.join(__dirname, "screenshots/silent-flow/adfs"); + const screenshotFolder = path.join( + __dirname, + "screenshots/silent-flow/adfs" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -66,21 +64,9 @@ describe.skip("Silent Flow ADFS 2019 Tests", () => { homeRoute = `${SAMPLE_HOME_URL}:${port}`; createFolder(screenshotFolder); - const labApiParms: LabApiQueryParams = { - azureEnvironment: AzureEnvironments.CLOUD, - appType: AppTypes.CLOUD, - federationProvider: FederationProviders.ADFS2019, - userType: UserTypes.FEDERATED, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserFederated ); publicClientApplication = new PublicClientApplication({ @@ -122,8 +108,14 @@ describe.skip("Silent Flow ADFS 2019 Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenAuthCode` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentialsADFS(page, screenshot, username, accountPwd); + await enterCredentialsADFS( + page, + screenshot, + labUser.upn, + accountPwd + ); await page.waitForSelector("#acquireTokenSilent"); await page.click("#acquireTokenSilent"); const cachedTokens = await NodeCacheTestUtils.waitForTokens( @@ -139,8 +131,14 @@ describe.skip("Silent Flow ADFS 2019 Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenSilent` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentialsADFS(page, screenshot, username, accountPwd); + await enterCredentialsADFS( + page, + screenshot, + labUser.upn, + accountPwd + ); await page.waitForSelector("#acquireTokenSilent"); await page.click("#acquireTokenSilent"); await page.waitForSelector( @@ -158,8 +156,14 @@ describe.skip("Silent Flow ADFS 2019 Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenSilentFromPersistent` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentialsADFS(page, screenshot, username, accountPwd); + await enterCredentialsADFS( + page, + screenshot, + labUser.upn, + accountPwd + ); await page.waitForSelector("#acquireTokenSilent"); publicClientApplication.clearCache(); await page.click("#acquireTokenSilent"); @@ -178,8 +182,14 @@ describe.skip("Silent Flow ADFS 2019 Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/RefreshExpiredToken` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); - await enterCredentialsADFS(page, screenshot, username, accountPwd); + await enterCredentialsADFS( + page, + screenshot, + labUser.upn, + accountPwd + ); await page.waitForSelector("#acquireTokenSilent"); let tokens = await NodeCacheTestUtils.waitForTokens( @@ -241,11 +251,12 @@ describe.skip("Silent Flow ADFS 2019 Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/GetAllAccounts` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); await enterCredentialsADFS( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForSelector("#getAllAccounts"); diff --git a/samples/msal-node-samples/silent-flow/test/silent-flow-b2c-aad.spec.ts b/samples/msal-node-samples/silent-flow/test/silent-flow-b2c-aad.spec.ts index e574c77f4c..8765b4d043 100644 --- a/samples/msal-node-samples/silent-flow/test/silent-flow-b2c-aad.spec.ts +++ b/samples/msal-node-samples/silent-flow/test/silent-flow-b2c-aad.spec.ts @@ -6,20 +6,18 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - setupCredentials, b2cAadPpeAccountEnterCredentials, - ONE_SECOND_IN_MS, - RETRY_TIMES, clickSignIn, SAMPLE_HOME_URL, SUCCESSFUL_GET_ALL_ACCOUNTS_ID, - validateCacheLocation, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - AppTypes, - AzureEnvironments, + validateCacheLocation, + createFolder, + RETRY_TIMES, + ONE_SECOND_IN_MS, } from "e2e-test-utils"; import path from "path"; import { PublicClientApplication, TokenCache } from "@azure/msal-node"; @@ -49,10 +47,12 @@ describe.skip("Silent Flow B2C Tests (aad account)", () => { let msalTokenCache: TokenCache; let server: any; - let username: string; - let accountPwd: string; + let labUser: LabUser; - const screenshotFolder = path.join(__dirname, "screenshots/silent-flow/b2c-aad"); + const screenshotFolder = path.join( + __dirname, + "screenshots/silent-flow/b2c-aad" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -65,18 +65,8 @@ describe.skip("Silent Flow B2C Tests (aad account)", () => { createFolder(screenshotFolder); - const labApiParms: LabApiQueryParams = { - azureEnvironment: AzureEnvironments.CLOUD, - appType: AppTypes.CLOUD, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient + labUser = await LabResponseHelper.getLabUser( + KeyVaultSecrets.UserPublicCloud ); publicClientApplication = new PublicClientApplication({ @@ -119,11 +109,12 @@ describe.skip("Silent Flow B2C Tests (aad account)", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenAuthCode` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); await b2cAadPpeAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForSelector("#acquireTokenSilent"); @@ -141,11 +132,12 @@ describe.skip("Silent Flow B2C Tests (aad account)", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenSilent` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); await b2cAadPpeAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForSelector("#acquireTokenSilent"); @@ -164,11 +156,12 @@ describe.skip("Silent Flow B2C Tests (aad account)", () => { const screenshot = new Screenshot( `${screenshotFolder}/RefreshExpiredToken` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); await b2cAadPpeAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForSelector("#acquireTokenSilent"); @@ -228,11 +221,12 @@ describe.skip("Silent Flow B2C Tests (aad account)", () => { const screenshot = new Screenshot( `${screenshotFolder}/GetAllAccounts` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); await b2cAadPpeAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForSelector("#getAllAccounts"); diff --git a/samples/msal-node-samples/silent-flow/test/silent-flow-b2c-local.spec.ts b/samples/msal-node-samples/silent-flow/test/silent-flow-b2c-local.spec.ts index 8d7038ad47..d3112e92f0 100644 --- a/samples/msal-node-samples/silent-flow/test/silent-flow-b2c-local.spec.ts +++ b/samples/msal-node-samples/silent-flow/test/silent-flow-b2c-local.spec.ts @@ -6,20 +6,18 @@ import * as puppeteer from "puppeteer"; import { Screenshot, - createFolder, - setupCredentials, b2cLocalAccountEnterCredentials, - ONE_SECOND_IN_MS, - RETRY_TIMES, clickSignIn, SAMPLE_HOME_URL, SUCCESSFUL_GET_ALL_ACCOUNTS_ID, - validateCacheLocation, + LabResponseHelper, + KeyVaultSecrets, + LabUser, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - B2cProviders, - UserTypes, + validateCacheLocation, + createFolder, + RETRY_TIMES, + ONE_SECOND_IN_MS, } from "e2e-test-utils"; import { PublicClientApplication, TokenCache } from "@azure/msal-node"; import path from "path"; @@ -49,10 +47,12 @@ describe("Silent Flow B2C Tests", () => { let msalTokenCache: TokenCache; let server: any; - let username: string; - let accountPwd: string; + let labUser: LabUser; - const screenshotFolder = path.join(__dirname, "screenshots/silent-flow/b2c-local"); + const screenshotFolder = path.join( + __dirname, + "screenshots/silent-flow/b2c-local" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -65,19 +65,7 @@ describe("Silent Flow B2C Tests", () => { createFolder(screenshotFolder); - const labApiParms: LabApiQueryParams = { - userType: UserTypes.B2C, - b2cProvider: B2cProviders.LOCAL, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient - ); + labUser = await LabResponseHelper.getLabUser(KeyVaultSecrets.UserB2C); publicClientApplication = new PublicClientApplication({ auth: config.authOptions, @@ -119,11 +107,12 @@ describe("Silent Flow B2C Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenAuthCode` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); await b2cLocalAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForSelector("#acquireTokenSilent"); @@ -141,11 +130,12 @@ describe("Silent Flow B2C Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/AcquireTokenSilent` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); await b2cLocalAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForSelector("#acquireTokenSilent"); @@ -164,11 +154,12 @@ describe("Silent Flow B2C Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/RefreshExpiredToken` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); await b2cLocalAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForSelector("#acquireTokenSilent"); @@ -228,11 +219,12 @@ describe("Silent Flow B2C Tests", () => { const screenshot = new Screenshot( `${screenshotFolder}/GetAllAccounts` ); + const accountPwd = await labUser.getPassword(); await clickSignIn(page, screenshot); await b2cLocalAccountEnterCredentials( page, screenshot, - username, + labUser.upn, accountPwd ); await page.waitForSelector("#getAllAccounts"); diff --git a/samples/msal-node-samples/silent-flow/test/silent-flow-b2c-msa.spec.ts b/samples/msal-node-samples/silent-flow/test/silent-flow-b2c-msa.spec.ts index b1822fe5ba..95b1296732 100644 --- a/samples/msal-node-samples/silent-flow/test/silent-flow-b2c-msa.spec.ts +++ b/samples/msal-node-samples/silent-flow/test/silent-flow-b2c-msa.spec.ts @@ -7,7 +7,6 @@ import * as puppeteer from "puppeteer"; import { Screenshot, createFolder, - setupCredentials, b2cMsaAccountEnterCredentials, ONE_SECOND_IN_MS, RETRY_TIMES, @@ -16,10 +15,9 @@ import { SUCCESSFUL_GET_ALL_ACCOUNTS_ID, validateCacheLocation, NodeCacheTestUtils, - LabClient, - LabApiQueryParams, - B2cProviders, - UserTypes, + LabResponseHelper, + KeyVaultSecrets, + LabUser, } from "e2e-test-utils"; import path from "path"; import { PublicClientApplication, TokenCache } from "@azure/msal-node"; @@ -49,10 +47,13 @@ describe("Silent Flow B2C Tests (msa account)", () => { let msalTokenCache: TokenCache; let server: any; - let username: string; - let accountPwd: string; + let labUser: LabUser; + let labPassword: string; - const screenshotFolder = path.join(__dirname, "screenshots/silent-flow/b2c-msa"); + const screenshotFolder = path.join( + __dirname, + "screenshots/silent-flow/b2c-msa" + ); beforeAll(async () => { await validateCacheLocation(TEST_CACHE_LOCATION); @@ -65,19 +66,9 @@ describe("Silent Flow B2C Tests (msa account)", () => { createFolder(screenshotFolder); - const labApiParms: LabApiQueryParams = { - userType: UserTypes.B2C, - b2cProvider: B2cProviders.MICROSOFT, - }; - - const labClient = new LabClient(); - const envResponse = await labClient.getVarsByCloudEnvironment( - labApiParms - ); - [username, accountPwd] = await setupCredentials( - envResponse[0], - labClient - ); + // Get B2C user configuration from Key Vault + labUser = await LabResponseHelper.getLabUser(KeyVaultSecrets.UserB2CMSA); + labPassword = await labUser.getPassword(); publicClientApplication = new PublicClientApplication({ auth: config.authOptions, @@ -123,8 +114,8 @@ describe("Silent Flow B2C Tests (msa account)", () => { await b2cMsaAccountEnterCredentials( page, screenshot, - username, - accountPwd + labUser.upn, + labPassword ); await page.waitForSelector("#acquireTokenSilent"); await page.click("#acquireTokenSilent"); @@ -145,8 +136,8 @@ describe("Silent Flow B2C Tests (msa account)", () => { await b2cMsaAccountEnterCredentials( page, screenshot, - username, - accountPwd + labUser.upn, + labPassword ); await page.waitForSelector("#acquireTokenSilent"); await screenshot.takeScreenshot(page, "ATS"); @@ -168,8 +159,8 @@ describe("Silent Flow B2C Tests (msa account)", () => { await b2cMsaAccountEnterCredentials( page, screenshot, - username, - accountPwd + labUser.upn, + labPassword ); await page.waitForSelector("#acquireTokenSilent"); @@ -232,8 +223,8 @@ describe("Silent Flow B2C Tests (msa account)", () => { await b2cMsaAccountEnterCredentials( page, screenshot, - username, - accountPwd + labUser.upn, + labPassword ); await page.waitForSelector("#getAllAccounts"); await page.click("#getAllAccounts");