From c0fd7d0f2f30f5ec27f7e243846f3d8c2def32c7 Mon Sep 17 00:00:00 2001 From: shobhit upadhyay Date: Thu, 4 Sep 2025 13:08:51 +0530 Subject: [PATCH 1/8] feat: add build script and enhance OAuth token handling - Introduced a new build.sh script for region selection and OAuth login. - Added app.json to .gitignore and included manifest.json in API .gitignore. - Updated package dependencies for improved functionality. - Implemented saveOAuthToken endpoint for secure token handling. - Enhanced region configuration and API host management in constants. - Added error handling and logging improvements in auth service. --- .gitignore | 3 + .talismanrc | 6 + api/.gitignore | 4 +- api/package-lock.json | 1136 +++++++++++++++++++++++- api/package.json | 12 +- api/src/constants/index.ts | 15 + api/src/controllers/auth.controller.ts | 12 + api/src/models/types.ts | 7 + api/src/routes/auth.routes.ts | 11 + api/src/services/auth.service.ts | 214 ++++- api/sso.utils.js | 283 ++++++ build.sh | 94 ++ 12 files changed, 1719 insertions(+), 78 deletions(-) create mode 100644 api/sso.utils.js create mode 100755 build.sh diff --git a/.gitignore b/.gitignore index ffe1acc3d..6c9bb560f 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,9 @@ # Mono auto generated files mono_crash.* +#App JSON file +app.json + # Build results [Dd]ebug/ [Dd]ebugPublic/ diff --git a/.talismanrc b/.talismanrc index ce5b6fb4e..f2ea36823 100644 --- a/.talismanrc +++ b/.talismanrc @@ -76,4 +76,10 @@ fileignoreconfig: checksum: abae249cacfab5c67e2d18a645c852649da2339954f26ae0f88c8698bdc016e6 - filename: api/src/services/wordpress.service.ts checksum: 95e532836194547682e791d0a231fb70e402be99260ac234e808eddb6e80c6af +- filename: api/package-lock.json + checksum: 1a184f1e350c592460b8dc676c49b4ccc051ef0c230d9b96f8adbf8150c5e69d +- filename: api/src/services/auth.service.ts + checksum: d10881297b1c1e923811b8a5089183b59055cf68f206408c47467228352da0de +- filename: api/sso.utils.js + checksum: 6629ba2026ef40d7ac8aa351848041be46523990481f800afda0244abc7d9053 version: "1.0" \ No newline at end of file diff --git a/api/.gitignore b/api/.gitignore index a3563aa2f..7b7f6384c 100644 --- a/api/.gitignore +++ b/api/.gitignore @@ -366,4 +366,6 @@ database/ /cmsMigrationData /migration-data **/copy* -**copy.ts \ No newline at end of file +**copy.ts +#App manifest JSON file +manifest.json \ No newline at end of file diff --git a/api/package-lock.json b/api/package-lock.json index b15a41802..fd3019f72 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -10,14 +10,16 @@ "license": "ISC", "dependencies": { "@contentstack/cli": "^1.34.0", - "@contentstack/cli-utilities": "^1.12.0", + "@contentstack/cli-utilities": "^1.14.0", "@contentstack/json-rte-serializer": "^2.0.7", - "@contentstack/marketplace-sdk": "^1.2.4", - "axios": "^1.8.2", + "@contentstack/marketplace-sdk": "^1.4.0", + "api": "^6.1.3", + "axios": "^1.11.0", "chokidar": "^3.6.0", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.21.0", + "express-session": "^1.18.2", "express-validator": "^7.0.1", "express-winston": "^4.2.0", "fs-extra": "^11.2.0", @@ -41,6 +43,7 @@ "devDependencies": { "@types/cors": "^2.8.17", "@types/express": "^4.17.21", + "@types/express-session": "^1.18.2", "@types/fs-extra": "^11.0.4", "@types/fs-readdir-recursive": "^1.1.3", "@types/jsdom": "^21.1.7", @@ -75,6 +78,11 @@ "node": ">=6.0.0" } }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==" + }, "node_modules/@apollo/client": { "version": "3.13.8", "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.8.tgz", @@ -137,7 +145,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "peer": true, "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", @@ -288,7 +295,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -552,6 +558,14 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz", + "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", @@ -4478,11 +4492,11 @@ } }, "node_modules/@contentstack/cli-utilities": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@contentstack/cli-utilities/-/cli-utilities-1.12.0.tgz", - "integrity": "sha512-vFgC74Ebb07oKF5PO5Q6ToGcRh0ndVUBcPnKzqvnUmHNIN+RxvYkbgblPXLhZAQfsCsUnVhrxBULXqSV7TFafg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@contentstack/cli-utilities/-/cli-utilities-1.14.0.tgz", + "integrity": "sha512-dGTje9w6rGepJqJm8Fk8vIA8ja2x3AJFaNUTYIimdpMTBtA5N95STTUeV36sxKcjDaY/FmOsu0N/iZd0N2kZ5A==", "dependencies": { - "@contentstack/management": "~1.21.4", + "@contentstack/management": "~1.22.0", "@contentstack/marketplace-sdk": "^1.2.8", "@oclif/core": "^4.3.0", "axios": "^1.9.0", @@ -5001,9 +5015,9 @@ } }, "node_modules/@contentstack/management": { - "version": "1.21.6", - "resolved": "https://registry.npmjs.org/@contentstack/management/-/management-1.21.6.tgz", - "integrity": "sha512-d6ww6wTyXjX7lEma5JwqIWAXXYfu7UpF8zd3ChAD5Q4n1FH3yOEuV7puGCPx6mAZUP9NxRxWjPLavjpuj2oCUg==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@contentstack/management/-/management-1.22.0.tgz", + "integrity": "sha512-TmwCKhdZnmGpcTuXn5JWbvMqbu0PqEn8Z/oEUlCelAxpo9vSC2qS4aejJtLTqC3Gii/7cJwjqF1BoFpwSO5J9A==", "dependencies": { "assert": "^2.1.0", "axios": "^1.9.0", @@ -5019,11 +5033,11 @@ } }, "node_modules/@contentstack/marketplace-sdk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@contentstack/marketplace-sdk/-/marketplace-sdk-1.2.8.tgz", - "integrity": "sha512-qjPAN3kAWk21phmTgt7xAkT8cUuKw6gR9z0YlzavN4ZyqMHXHzXBS0/yuVnHC6D6MO0G8S//RvJ/F+1mTnbenQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@contentstack/marketplace-sdk/-/marketplace-sdk-1.4.0.tgz", + "integrity": "sha512-vUi9hoSh5ytr2KmuIKx+g7QDJqevIsM7UX12deCsCTdYH1q7eSrYwpv+jFH+TfrDQUYa71T/xrIF0QiTMUMqdA==", "dependencies": { - "axios": "^1.8.4" + "axios": "^1.11.0" } }, "node_modules/@contentstack/types-generator": { @@ -5735,6 +5749,11 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@exodus/schemasafe": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", + "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==" + }, "node_modules/@fast-csv/format": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/@fast-csv/format/-/format-4.3.5.tgz", @@ -5876,6 +5895,14 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@humanwhocodes/momoa": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@humanwhocodes/momoa/-/momoa-2.0.4.tgz", + "integrity": "sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==", + "engines": { + "node": ">=10.10.0" + } + }, "node_modules/@humanwhocodes/object-schema": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", @@ -6917,6 +6944,11 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -7137,6 +7169,122 @@ "url": "https://opencollective.com/pkgr" } }, + "node_modules/@readme/better-ajv-errors": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@readme/better-ajv-errors/-/better-ajv-errors-2.3.2.tgz", + "integrity": "sha512-T4GGnRAlY3C339NhoUpgJJFsMYko9vIgFAlhgV+/vEGFw66qEY4a4TRJIAZBcX/qT1pq5DvXSme+SQODHOoBrw==", + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/runtime": "^7.22.5", + "@humanwhocodes/momoa": "^2.0.3", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "ajv": "4.11.8 - 8" + } + }, + "node_modules/@readme/data-urls": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@readme/data-urls/-/data-urls-1.0.1.tgz", + "integrity": "sha512-FNP4ntG5rCgmrvQGoNH/Ljivc6jSWaaVeMuXneOyQ6oLuhm/NkysXJN3DnBrIsJUJbSae7qIs2QfPYnaropoHw==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@readme/http-status-codes": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@readme/http-status-codes/-/http-status-codes-7.2.0.tgz", + "integrity": "sha512-/dBh9qw3QhJYqlGwt2I+KUP/lQ6nytdCx3aq+GpMUhibLHF3O7fwoowNcTwlbnwtyJ+TJYTIIrp3oVUlRNx3fA==" + }, + "node_modules/@readme/json-schema-ref-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@readme/json-schema-ref-parser/-/json-schema-ref-parser-1.2.0.tgz", + "integrity": "sha512-Bt3QVovFSua4QmHa65EHUmh2xS0XJ3rgTEUPH998f4OW4VVJke3BuS16f+kM0ZLOGdvIrzrPRqwihuv5BAjtrA==", + "deprecated": "This package is no longer maintained. Please use `@apidevtools/json-schema-ref-parser` instead.", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "node_modules/@readme/oas-extensions": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@readme/oas-extensions/-/oas-extensions-17.0.1.tgz", + "integrity": "sha512-PCU7WLz8TkbdxsiE4eQGvJYDYZQPiyLhXme3SvLboSmH+8G6AJPJ5OymzSAdlf5sXpSSoD2q3dTIou3Cb2DirQ==", + "deprecated": "The functionality for this library has been moved into `oas`.", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "oas": "^20.0.0" + } + }, + "node_modules/@readme/oas-to-har": { + "version": "20.1.1", + "resolved": "https://registry.npmjs.org/@readme/oas-to-har/-/oas-to-har-20.1.1.tgz", + "integrity": "sha512-rz8YpdZw+Jqrd8VQhQaYrzctkCAYdBldoQ5qDQyF9vGvq2lpA1yMvQPgKCJXfPGXH8Cm+NjLbunxnYabKQeKeA==", + "dependencies": { + "@readme/data-urls": "^1.0.1", + "@readme/oas-extensions": "^17.0.1", + "oas": "^20.5.0", + "qs": "^6.10.5", + "remove-undefined-objects": "^2.0.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@readme/openapi-parser": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@readme/openapi-parser/-/openapi-parser-2.7.0.tgz", + "integrity": "sha512-P8WSr8WTOxilnT89tcCRKWYsG/II4sAwt1a/DIWub8xTtkrG9cCBBy/IUcvc5X8oGWN82MwcTA3uEkDrXZd/7A==", + "dependencies": { + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "@readme/better-ajv-errors": "^2.0.0", + "@readme/json-schema-ref-parser": "^1.2.0", + "@readme/openapi-schemas": "^3.1.0", + "ajv": "^8.12.0", + "ajv-draft-04": "^1.0.0", + "call-me-maybe": "^1.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@readme/openapi-schemas": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@readme/openapi-schemas/-/openapi-schemas-3.1.0.tgz", + "integrity": "sha512-9FC/6ho8uFa8fV50+FPy/ngWN53jaUu4GRXlAjcxIRrzhltJnpKkBG2Tp0IDraFJeWrOpk84RJ9EMEEYzaI1Bw==", + "engines": { + "node": ">=18" + } + }, + "node_modules/@readme/postman-to-openapi": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@readme/postman-to-openapi/-/postman-to-openapi-4.1.0.tgz", + "integrity": "sha512-VvV2Hzjskz01m8doSn7Ypt6cSZzgjnypVqXy1ipThbyYD6SGiM74VSePXykOODj/43Y2m6zeYedPk/ZLts/HvQ==", + "dependencies": { + "@readme/http-status-codes": "^7.2.0", + "js-yaml": "^4.1.0", + "jsonc-parser": "3.2.0", + "lodash.camelcase": "^4.3.0", + "marked": "^4.3.0", + "mustache": "^4.2.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/@rollup/plugin-commonjs": { "version": "28.0.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.3.tgz", @@ -7574,6 +7722,39 @@ "node": ">= 10" } }, + "node_modules/@ts-morph/common": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.18.1.tgz", + "integrity": "sha512-RVE+zSRICWRsfrkAw5qCAK+4ZH9kwEFv5h0+/YeHTLieWP7F4wWq4JsKFuNWG+fYh/KF+8rAtgdj5zb2mm+DVA==", + "dependencies": { + "fast-glob": "^3.2.12", + "minimatch": "^5.1.0", + "mkdirp": "^1.0.4", + "path-browserify": "^1.0.1" + } + }, + "node_modules/@ts-morph/common/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@ts-morph/common/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -7695,6 +7876,15 @@ "@types/send": "*" } }, + "node_modules/@types/express-session": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.2.tgz", + "integrity": "sha512-k+I0BxwVXsnEU2hV77cCobC08kIsn4y44C3gC0b46uxZVMaXA04lSPgRLR/bSL2w0t0ShJiG8o4jPzRG/nscFg==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/fs-extra": { "version": "11.0.4", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", @@ -7735,6 +7925,11 @@ "@types/node": "*" } }, + "node_modules/@types/har-format": { + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.16.tgz", + "integrity": "sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==" + }, "node_modules/@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", @@ -7778,8 +7973,7 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "node_modules/@types/json5": { "version": "0.0.29", @@ -8293,6 +8487,19 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/ajv-formats": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", @@ -8394,6 +8601,69 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/api": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/api/-/api-6.1.3.tgz", + "integrity": "sha512-a9Bk/CVzQUvGIDG8HR1sVyQdPd5gxzygoQEnzBhYWvSJOW5fIMGkGq+lXItM2vWAneJqWgFMqbBklYw9qMsz6A==", + "dependencies": { + "@readme/oas-to-har": "^20.0.2", + "@readme/openapi-parser": "^2.4.0", + "caseless": "^0.12.0", + "chalk": "^4.1.2", + "commander": "^10.0.0", + "datauri": "^4.1.0", + "execa": "^5.1.1", + "fetch-har": "^8.1.5", + "figures": "^3.2.0", + "find-cache-dir": "^3.3.1", + "form-data-encoder": "^1.7.2", + "formdata-node": "^4.3.2", + "get-stream": "^6.0.1", + "isomorphic-fetch": "^3.0.0", + "js-yaml": "^4.1.0", + "json-schema-to-ts": "^2.6.2-beta.0", + "json-schema-traverse": "^1.0.0", + "lodash": "^4.17.21", + "make-dir": "^3.1.0", + "node-abort-controller": "^3.1.1", + "oas": "^20.11.0", + "ora": "^5.4.1", + "prompts": "^2.4.2", + "remove-undefined-objects": "^2.0.2", + "semver": "^7.3.8", + "ssri": "^10.0.1", + "ts-morph": "^17.0.1", + "validate-npm-package-name": "^5.0.0" + }, + "bin": { + "api": "bin/api" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/api/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/api/node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -8673,12 +8943,12 @@ } }, "node_modules/axios": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", - "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", "dependencies": { "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", + "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, @@ -9125,6 +9395,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-me-maybe": { + "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==" + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -9173,6 +9448,11 @@ "cdl": "bin/cdl.js" } }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9409,6 +9689,11 @@ "node": ">= 0.12.0" } }, + "node_modules/code-block-writer": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-11.0.3.tgz", + "integrity": "sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw==" + }, "node_modules/code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -9507,11 +9792,40 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "engines": { + "node": ">=14" + } + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" }, + "node_modules/compute-gcd": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.1.tgz", + "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, + "node_modules/compute-lcm": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.2.tgz", + "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", + "dependencies": { + "compute-gcd": "^1.2.1", + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -9842,6 +10156,18 @@ "node": ">=0.4.0" } }, + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -9909,6 +10235,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/datauri": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/datauri/-/datauri-4.1.0.tgz", + "integrity": "sha512-y17kh32+I82G+ED9MNWFkZiP/Cq/vO1hN9+tSZsT9C9qn3NrvcBnh7crSepg0AQPge1hXx2Ca44s1FRdv0gFWA==", + "dependencies": { + "image-size": "1.0.0", + "mimer": "^2.0.2" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/date-fns": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", @@ -10513,11 +10851,59 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, "node_modules/es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" }, + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "node_modules/esbuild": { "version": "0.25.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", @@ -11182,6 +11568,20 @@ "node": "*" } }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -11264,11 +11664,19 @@ "node": ">= 0.6" } }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "peer": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -11291,7 +11699,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "peer": true, "dependencies": { "path-key": "^3.0.0" }, @@ -11302,8 +11709,7 @@ "node_modules/execa/node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "peer": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/exit": { "version": "0.1.2", @@ -11376,6 +11782,50 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express-session": { + "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==", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.7", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.1.0", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express-session/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/express-validator": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.2.1.tgz", @@ -11499,6 +11949,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dependencies": { + "type": "^2.7.2" + } + }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -11576,6 +12034,11 @@ "fastest-levenshtein": "^1.0.7" } }, + "node_modules/fast-safe-stringify": { + "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==" + }, "node_modules/fast-uri": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", @@ -11634,7 +12097,23 @@ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, - "node_modules/fetch-mock": { + "node_modules/fetch-har": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/fetch-har/-/fetch-har-8.1.5.tgz", + "integrity": "sha512-c9WDro4RWC+suOVRJFNW21cgqTOELRZpvFJgfENvOM7Yt/VA4QeFtRax795SyOpTisdpcl5XNQlQZdAE6HERDA==", + "dependencies": { + "@readme/data-urls": "^1.0.1", + "@types/har-format": "^1.2.8", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "formdata-node": "^4.3.2" + } + }, + "node_modules/fetch-mock": { "version": "12.5.2", "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-12.5.2.tgz", "integrity": "sha512-b5KGDFmdmado2MPQjZl6ix3dAG3iwCitb0XQwN72y2s9VnWZ3ObaGNy+bkpm1390foiLDybdJ7yjRGKD36kATw==", @@ -11753,6 +12232,44 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -11859,19 +12376,37 @@ } }, "node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" } }, + "node_modules/form-data-encoder": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.9.0.tgz", + "integrity": "sha512-rahaRMkN8P8d/tgK/BLPX+WBVM27NbvdXBxqQujBtkDAIFspaRqN7Od7lfdGQA6KAD+f82fYCLBq1ipvcu8qLw==" + }, + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "dependencies": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + }, + "engines": { + "node": ">= 12.20" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -12099,7 +12634,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "peer": true, "engines": { "node": ">=10" }, @@ -12489,6 +13023,11 @@ "node": ">= 14" } }, + "node_modules/http2-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", + "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==" + }, "node_modules/https-proxy-agent": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", @@ -12505,7 +13044,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "peer": true, "engines": { "node": ">=10.17.0" } @@ -12575,6 +13113,20 @@ "node": ">= 4" } }, + "node_modules/image-size": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.0.tgz", + "integrity": "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/immer": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", @@ -13810,6 +14362,15 @@ "node": ">=16" } }, + "node_modules/isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -16473,6 +17034,40 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "peer": true }, + "node_modules/json-schema-compare": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", + "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", + "dependencies": { + "lodash": "^4.17.4" + } + }, + "node_modules/json-schema-merge-allof": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/json-schema-merge-allof/-/json-schema-merge-allof-0.8.1.tgz", + "integrity": "sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w==", + "dependencies": { + "compute-lcm": "^1.1.2", + "json-schema-compare": "^0.2.2", + "lodash": "^4.17.20" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/json-schema-to-ts": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-2.12.0.tgz", + "integrity": "sha512-uTde38yBm5lzJSRPWRaasxZo72pb+JGE4iUksNdNfAkFaLhV4N9akeBxPPUpZy5onINt9Zo0oTLrAoEXyZESiQ==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@types/json-schema": "^7.0.9", + "ts-algebra": "^1.2.2" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -16511,6 +17106,11 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" + }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -16540,6 +17140,14 @@ "underscore": "1.12.1" } }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/jsonschema": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.5.0.tgz", @@ -16642,7 +17250,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "peer": true, "engines": { "node": ">=6" } @@ -16684,7 +17291,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "peer": true, "engines": { "node": ">=6" } @@ -17017,6 +17623,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -17363,6 +17974,14 @@ "yallist": "^3.0.2" } }, + "node_modules/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "dependencies": { + "es5-ext": "~0.10.2" + } + }, "node_modules/magic-string": { "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", @@ -17427,6 +18046,24 @@ "node": ">= 0.6" } }, + "node_modules/memoizee": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", + "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", + "dependencies": { + "d": "^1.0.2", + "es5-ext": "^0.10.64", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/merge": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", @@ -17443,8 +18080,7 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "peer": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/merge2": { "version": "1.4.1", @@ -17515,6 +18151,17 @@ "node": ">= 0.6" } }, + "node_modules/mimer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mimer/-/mimer-2.0.2.tgz", + "integrity": "sha512-izxvjsB7Ur5HrTbPu6VKTrzxSMBFBqyZQc6dWlZNQ4/wAvf886fD4lrjtFd8IQ8/WmZKdxKjUtqFFNaj3hQ52g==", + "bin": { + "mimer": "bin/mimer" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/mimic-fn": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", @@ -17610,6 +18257,14 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } + }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -17636,6 +18291,11 @@ "node": ">= 0.6" } }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -17666,6 +18326,30 @@ "node": ">= 10.13" } }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -17685,6 +18369,17 @@ } } }, + "node_modules/node-fetch-h2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", + "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", + "dependencies": { + "http2-client": "^1.2.5" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, "node_modules/node-fetch/node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -17715,6 +18410,19 @@ "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==" }, + "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==", + "dependencies": { + "es6-promise": "^3.2.1" + } + }, + "node_modules/node-readfiles/node_modules/es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==" + }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -20325,6 +21033,111 @@ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", "integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==" }, + "node_modules/oas": { + "version": "20.11.0", + "resolved": "https://registry.npmjs.org/oas/-/oas-20.11.0.tgz", + "integrity": "sha512-Eio2qil8z86PD8KJTdyGPN7hbcF3dV0gc5B6mkSQgL3MLMVFE/XyVAmq/9BRh51zkIXOPmZpSIF3nStADbnkHA==", + "dependencies": { + "@readme/json-schema-ref-parser": "^1.2.0", + "@types/json-schema": "^7.0.11", + "json-schema-merge-allof": "^0.8.1", + "jsonpath": "^1.1.1", + "jsonpointer": "^5.0.0", + "memoizee": "^0.4.14", + "oas-normalize": "^8.3.0", + "openapi-types": "^12.1.0", + "path-to-regexp": "^6.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/oas-kit-common": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", + "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/oas-linter": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz", + "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==", + "dependencies": { + "@exodus/schemasafe": "^1.0.0-rc.2", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-normalize": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/oas-normalize/-/oas-normalize-8.4.1.tgz", + "integrity": "sha512-cGODg+AntZteJRHBiYDWKtcO2svWGMXuFWYu2I8b4hOrNiwB3hgDs/ScX3O9mYm6RpLsUIftt6rDHGc8eYG8aA==", + "dependencies": { + "@readme/openapi-parser": "^2.5.0", + "@readme/postman-to-openapi": "^4.1.0", + "js-yaml": "^4.1.0", + "node-fetch": "^2.6.1", + "openapi-types": "^12.1.0", + "swagger2openapi": "^7.0.8" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/oas-resolver": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz", + "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==", + "dependencies": { + "node-fetch-h2": "^2.3.0", + "oas-kit-common": "^1.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "resolve": "resolve.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-schema-walker": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", + "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-validator": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz", + "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==", + "dependencies": { + "call-me-maybe": "^1.0.1", + "oas-kit-common": "^1.0.8", + "oas-linter": "^3.2.2", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "reftools": "^1.1.9", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas/node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -20484,6 +21297,14 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -20538,6 +21359,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==" + }, "node_modules/optimism": { "version": "0.18.1", "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.18.1.tgz", @@ -20789,6 +21615,11 @@ "cross-spawn": "^7.0.3" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -20857,8 +21688,7 @@ "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "peer": true + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "4.0.2", @@ -20884,7 +21714,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "peer": true, "dependencies": { "find-up": "^4.0.0" }, @@ -20896,7 +21725,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "peer": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -20909,7 +21737,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "peer": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -20921,7 +21748,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "peer": true, "dependencies": { "p-try": "^2.0.0" }, @@ -20936,7 +21762,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "peer": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -21217,7 +22042,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "peer": true, "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" @@ -21324,6 +22148,14 @@ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "dependencies": { + "inherits": "~2.0.3" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -21343,6 +22175,14 @@ } ] }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -21524,6 +22364,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/reftools": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", + "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -21568,6 +22416,14 @@ } } }, + "node_modules/remove-undefined-objects": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/remove-undefined-objects/-/remove-undefined-objects-2.0.2.tgz", + "integrity": "sha512-b6x4MUtR4YBW1aCoGx3tE4mA2PFjiXSmtSdNmLexQzUdZa4ybnJAItXLKpkcVgCUJIzJtk2DFG402sMSEMlonQ==", + "engines": { + "node": ">=14" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -22246,6 +23102,54 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dependencies": { + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==" + }, + "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==", + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==" + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -22369,8 +23273,7 @@ "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "peer": true + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, "node_modules/slash": { "version": "3.0.0", @@ -22660,6 +23563,25 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, + "node_modules/ssri": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", + "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ssri/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -22954,7 +23876,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "peer": true, "engines": { "node": ">=6" } @@ -23018,6 +23939,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swagger2openapi": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", + "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==", + "dependencies": { + "call-me-maybe": "^1.0.1", + "node-fetch": "^2.6.1", + "node-fetch-h2": "^2.3.0", + "node-readfiles": "^0.2.0", + "oas-kit-common": "^1.0.8", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "oas-validator": "^5.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "boast": "boast.js", + "oas-validate": "oas-validate.js", + "swagger2openapi": "swagger2openapi.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", @@ -23139,6 +24086,18 @@ "readable-stream": "2 || 3" } }, + "node_modules/timers-ext": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", + "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", + "dependencies": { + "es5-ext": "^0.10.64", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/tiny-warning": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", @@ -23234,6 +24193,11 @@ "node": ">= 14.0.0" } }, + "node_modules/ts-algebra": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.2.2.tgz", + "integrity": "sha512-kloPhf1hq3JbCPOTYoOWDKxebWjNb2o/LKnNfkWhxVVisFFmMJPPdJeGoGmM+iRLyoXAR61e08Pb+vUXINg8aA==" + }, "node_modules/ts-api-utils": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", @@ -23257,6 +24221,15 @@ "node": ">=8" } }, + "node_modules/ts-morph": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-17.0.1.tgz", + "integrity": "sha512-10PkHyXmrtsTvZSL+cqtJLTgFXkU43Gd0JCc0Rw6GchWbqKe0Rwgt1v3ouobTZwQzF1mGhDeAlWYBMGRV7y+3g==", + "dependencies": { + "@ts-morph/common": "~0.18.0", + "code-block-writer": "^11.0.3" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -23395,6 +24368,11 @@ "node": ">=6" } }, + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -23546,6 +24524,17 @@ "node": ">=14.17" } }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", @@ -23712,6 +24701,38 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/validate.io-array": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", + "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==" + }, + "node_modules/validate.io-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", + "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==" + }, + "node_modules/validate.io-integer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz", + "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", + "dependencies": { + "validate.io-number": "^1.0.3" + } + }, + "node_modules/validate.io-integer-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz", + "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-integer": "^1.0.4" + } + }, + "node_modules/validate.io-number": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", + "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==" + }, "node_modules/validator": { "version": "13.12.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", @@ -23764,6 +24785,14 @@ "defaults": "^1.0.3" } }, + "node_modules/web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "engines": { + "node": ">= 14" + } + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -23794,6 +24823,11 @@ "node": ">=0.10.0" } }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" + }, "node_modules/whatwg-mimetype": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", @@ -24092,6 +25126,14 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "peer": true }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/api/package.json b/api/package.json index f4c8e9ded..3c7552aa8 100644 --- a/api/package.json +++ b/api/package.json @@ -13,7 +13,6 @@ "lint:fix": "eslint --ext .ts --ignore-pattern './node_modules/' --ignore-pattern './dist/'", "precommit": "npm run prettify && npm run lint:fix" }, - "type": "module", "repository": { "type": "git", "url": "git+https://github.com/contentstack/migration-v2.git" @@ -26,14 +25,16 @@ "homepage": "https://github.com/contentstack/migration-v2.git#readme", "dependencies": { "@contentstack/cli": "^1.34.0", - "@contentstack/cli-utilities": "^1.12.0", + "@contentstack/cli-utilities": "^1.14.0", "@contentstack/json-rte-serializer": "^2.0.7", - "@contentstack/marketplace-sdk": "^1.2.4", - "axios": "^1.8.2", + "@contentstack/marketplace-sdk": "^1.4.0", + "api": "^6.1.3", + "axios": "^1.11.0", "chokidar": "^3.6.0", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.21.0", + "express-session": "^1.18.2", "express-validator": "^7.0.1", "express-winston": "^4.2.0", "fs-extra": "^11.2.0", @@ -57,6 +58,7 @@ "devDependencies": { "@types/cors": "^2.8.17", "@types/express": "^4.17.21", + "@types/express-session": "^1.18.2", "@types/fs-extra": "^11.0.4", "@types/fs-readdir-recursive": "^1.1.3", "@types/jsdom": "^21.1.7", @@ -78,4 +80,4 @@ "typescript": "^5.4.3" }, "keywords": [] -} \ No newline at end of file +} diff --git a/api/src/constants/index.ts b/api/src/constants/index.ts index b0efbcc78..ec509092a 100644 --- a/api/src/constants/index.ts +++ b/api/src/constants/index.ts @@ -6,6 +6,21 @@ export const DEVURLS: any = { AZURE_EU: "azure-eu-developerhub-api.contentstack.com", GCP_NA: "gcp-na-developerhub-api.contentstack.com", }; +export const CSAUTHHOST: any = { + NA:"https://app.contentstack.com/apps-api/token", + EU:"https://eu-app.contentstack.com/apps-api/token", + AZURE_NA:"https://azure-na-app.contentstack.com/apps-api/token", + AZURE_EU:"https://azure-eu-app.contentstack.com/apps-api/token", + GCP_NA:"https://gcp-na-app.contentstack.com/apps-api/token", +} + +export const regionalApiHosts = { + NA: 'api.contentstack.io', + EU: 'eu-api.contentstack.com', + AZURE_NA: 'azure-na-api.contentstack.com', + AZURE_EU: 'azure-eu-api.contentstack.com', + GCP_NA: 'gcp-na-api.contentstack.com' +}; export const CMS = { CONTENTFUL: "contentful", SITECORE_V8: "sitecore v8", diff --git a/api/src/controllers/auth.controller.ts b/api/src/controllers/auth.controller.ts index bdcbe1804..e2ecb530f 100644 --- a/api/src/controllers/auth.controller.ts +++ b/api/src/controllers/auth.controller.ts @@ -1,5 +1,6 @@ import { Request, Response } from "express"; import { authService } from "../services/auth.service.js"; +import { HTTP_CODES } from "../constants/index.js"; /** * Handles the login request. @@ -23,7 +24,18 @@ const RequestSms = async (req: Request, res: Response) => { res.status(resp.status).json(resp.data); }; + +/** + * Handles the secure, server-to-server POST request from our Launch proxy. + * This confirms to the proxy that the token was received. + */ +const saveOAuthToken = async (req: Request, res: Response) => { + await authService.saveOAuthToken(req); + res.status(HTTP_CODES.OK).json({ message: "Token received successfully." }); +}; + export const authController = { login, RequestSms, + saveOAuthToken, }; diff --git a/api/src/models/types.ts b/api/src/models/types.ts index 43e7eb049..5cd0c1ed8 100644 --- a/api/src/models/types.ts +++ b/api/src/models/types.ts @@ -45,4 +45,11 @@ export interface Locale { name: string; fallback_locale: string; uid: string; +} + +export interface RefreshTokenResponse { + access_token: string; + refresh_token?: string; + expires_in?: number; + token_type?: string; } \ No newline at end of file diff --git a/api/src/routes/auth.routes.ts b/api/src/routes/auth.routes.ts index 60b1755b9..131c26423 100644 --- a/api/src/routes/auth.routes.ts +++ b/api/src/routes/auth.routes.ts @@ -40,4 +40,15 @@ router.post( asyncRouter(authController.RequestSms) ); +/** + * The new secure endpoint that the Launch proxy will call with a POST request + * to deliver the final access token. This is NOT for browser access. + * @route POST /v2/auth/save-token + */ +router.get( + "/save-token", + asyncRouter(authController.saveOAuthToken) +); + + export default router; diff --git a/api/src/services/auth.service.ts b/api/src/services/auth.service.ts index cf512a621..f21b6d5c8 100644 --- a/api/src/services/auth.service.ts +++ b/api/src/services/auth.service.ts @@ -2,8 +2,8 @@ import { Request } from "express"; import { config } from "../config/index.js"; import { safePromise, getLogMessage } from "../utils/index.js"; import https from "../utils/https.utils.js"; -import { LoginServiceType, AppTokenPayload } from "../models/types.js"; -import { HTTP_CODES, HTTP_TEXTS } from "../constants/index.js"; +import { LoginServiceType, AppTokenPayload, RefreshTokenResponse } from "../models/types.js"; +import { HTTP_CODES, HTTP_TEXTS, CSAUTHHOST, regionalApiHosts } from "../constants/index.js"; import { generateToken } from "../utils/jwt.utils.js"; import { BadRequestError, @@ -12,23 +12,16 @@ import { } from "../utils/custom-errors.utils.js"; import AuthenticationModel from "../models/authentication.js"; import logger from "../utils/logger.js"; -// import * as configHandler from "@contentstack/cli-utilities"; +import path from "path"; +import fs from "fs"; +import axios from "axios"; +// import { createHash, randomBytes } from 'crypto'; /** - * Logs in a user with the provided request data. - * - * @param req - The request object containing user data. - * @returns A promise that resolves to a LoginServiceType object. - * @throws ExceptionFunction if an error occurs during the login process. + * Logs in a user with the provided request data. (No changes needed here) */ const login = async (req: Request): Promise => { const srcFun = "Login"; - /* - handles user authentication by making a request to an API, - performing various checks and validations, - updating a model, and generating a JWT token. - It also handles potential errors and logs appropriate messages. - */ try { const userData = req?.body; @@ -135,19 +128,10 @@ const login = async (req: Request): Promise => { }; /** - * Sends a request for SMS login token. - * @param req - The request object. - * @returns A promise that resolves to a LoginServiceType object. - * @throws {InternalServerError} If an error occurs while sending the request. + * Sends a request for SMS login token. (No changes needed here) */ const requestSms = async (req: Request): Promise => { const srcFun = "requestSms"; - - /* - handles the authentication process by making an HTTP POST request to an API endpoint, - handling any errors that occur, and returning the appropriate response or error data. - It also includes logging functionality to track the execution and potential errors. - */ try { const userData = req?.body; const [err, res] = await safePromise( @@ -187,7 +171,187 @@ const requestSms = async (req: Request): Promise => { } }; +const getAppConfig = () => { + const configPath = path.resolve(process.cwd(), '..', 'app.json'); + if (!fs.existsSync(configPath)) { + throw new InternalServerError("SSO is not configured. Please run the setup script first."); + } + const rawData = fs.readFileSync(configPath, 'utf-8'); + return JSON.parse(rawData); +}; + +/** + * Receives the final code to generate token, fetches user details, + * and saves/updates the user in the database. + */ +const saveOAuthToken = async (req: Request): Promise => { + const { code, region } = req.query; + + if (!code || !region) { + logger.error("Callback failed: Missing 'code' or 'region' in query parameters."); + throw new BadRequestError("Missing 'code' or 'region' in query parameters."); + } + + try { + // Exchange the code for access token + const appConfig = getAppConfig(); + const { client_id, client_secret, redirect_uri } = appConfig.oauthData; + const { code_verifier } = appConfig.pkce; + + const regionStr = Array.isArray(region) ? region[0] : region; + const tokenUrl = CSAUTHHOST[regionStr as keyof typeof CSAUTHHOST]; + const clientId = client_id + const clientSecret = client_secret + const redirectUri = `${redirect_uri}/v2/auth/save-token` + if (!tokenUrl || !clientId || !clientSecret) { + throw new InternalServerError(`Configuration missing for region: ${region}`); + } + + const formData = new URLSearchParams(); + formData.append('grant_type', 'authorization_code'); + formData.append('client_id', clientId); + formData.append('client_secret', clientSecret); + formData.append('redirect_uri', redirectUri); + formData.append('code', code as string); + formData.append('code_verifier', code_verifier); + const tokenResponse = await https({ + method: "POST", + url: tokenUrl, + data: formData, + headers: { 'Content-Type': 'application/x-www-form-urlencoded' } + }); + + delete (req.session as any).code_verifier; + + const { access_token, refresh_token, organization_uid } = tokenResponse.data; + + const apiHost = regionalApiHosts[region as keyof typeof regionalApiHosts]; + const [userErr, userRes] = await safePromise( + https({ + method: "GET", + url: `https://${apiHost}/v3/user`, + headers: { + 'authorization': `Bearer ${access_token}`, + }, + }) + ); + + if (userErr) { + logger.error("Error fetching user details with new token", userErr?.response?.data); + throw new InternalServerError(userErr); + } + + const csUser = userRes.data.user; + + const appTokenPayload = { + region: region as string, + user_id: csUser.uid, + }; + + await AuthenticationModel.read(); + const userIndex = AuthenticationModel.chain.get("users").findIndex({ user_id: csUser.uid }).value(); + + AuthenticationModel.update((data: any) => { + const userRecord = { + ...appTokenPayload, + email: csUser.email, + access_token: access_token, + refresh_token: refresh_token, + organization_uid: organization_uid, + updated_at: new Date().toISOString(), + }; + if (userIndex < 0) { + data.users.push({ ...userRecord, created_at: new Date().toISOString() }); + } else { + data.users[userIndex] = { ...data.users[userIndex], ...userRecord }; + } + }); + + logger.info(`Token and user data for ${csUser.email} (Region: ${region}) saved successfully.`); + + } catch (error) { + logger.error("An error occurred during token exchange and save:", error); + throw new InternalServerError("Failed to process OAuth callback."); + } +}; + +/** + * Generates a new access token using the refresh token. + * If the refresh token is not found, it throws an error. + * It updates the user record in the database with the new access token and refresh token. + * It returns the new access token. + */ +export const refreshOAuthToken = async (userId: string): Promise => { + try { + await AuthenticationModel.read(); + const userRecord = AuthenticationModel.chain.get("users").find({ user_id: userId }).value(); + + if (!userRecord) { + throw new Error(`User record not found for user_id: ${userId}`); + } + + if (!userRecord.refresh_token) { + throw new Error(`No refresh token available for user: ${userId}`); + } + + const appConfigPath = path.join(process.cwd(), "..", 'app.json'); + if (!fs.existsSync(appConfigPath)) { + throw new Error('app.json file not found - OAuth configuration required'); + } + + const appConfig = JSON.parse(fs.readFileSync(appConfigPath, 'utf8')); + const { client_id, client_secret, redirect_uri } = appConfig.oauthData; + + if (!client_id || !client_secret) { + throw new Error('OAuth client_id or client_secret not found in app.json'); + } + + console.info(`Refreshing token for user: ${userRecord.email} in region: ${userRecord.region}`); + + const appUrl = CSAUTHHOST[userRecord.region] || CSAUTHHOST['NA']; + const tokenEndpoint = `${appUrl}`; + + const formData = new URLSearchParams({ + grant_type: 'refresh_token', + client_id: client_id, + client_secret: client_secret, + redirect_uri: redirect_uri, + refresh_token: userRecord.refresh_token + }); + + const response = await axios.post(tokenEndpoint, formData, { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + timeout: 15000 + }); + + const { access_token, refresh_token } = response.data; + + AuthenticationModel.update((data: any) => { + const userIndex = data.users.findIndex((user: any) => user.user_id === userId); + if (userIndex >= 0) { + data.users[userIndex] = { + ...data.users[userIndex], + access_token: access_token, + refresh_token: refresh_token || userRecord.refresh_token, + updated_at: new Date().toISOString() + }; + } + }); + + console.info(`Token refreshed successfully for user: ${userRecord.email}`); + return access_token; + + } catch (error: any) { + console.error(`Token refresh failed for user ${userId}:`, error.response?.data || error.message); + throw new Error(`Failed to refresh token: ${error.response?.data?.error_description || error.message}`); + } +}; + export const authService = { login, requestSms, -}; + saveOAuthToken, + refreshOAuthToken, +}; \ No newline at end of file diff --git a/api/sso.utils.js b/api/sso.utils.js new file mode 100644 index 000000000..b32e49105 --- /dev/null +++ b/api/sso.utils.js @@ -0,0 +1,283 @@ +const contentstack = require("@contentstack/marketplace-sdk"); +const readline = require("readline"); +const { execSync } = require("child_process"); +const fs = require("fs"); +const crypto = require("crypto"); +const manifest = require("./manifest.json"); + + +const REGION_CONFIG = { + NA: { + name: "North America", + cma: "https://api.contentstack.io", + cda: "https://cdn.contentstack.io", + app: "https://app.contentstack.com", + developerHub: "https://developerhub-api.contentstack.com", + personalize: "https://personalize-api.contentstack.com", + launch: "https://launch-api.contentstack.com" + }, + EU: { + name: "Europe", + cma: "https://eu-api.contentstack.com", + cda: "https://eu-cdn.contentstack.com", + app: "https://eu-app.contentstack.com", + developerHub: "https://eu-developerhub-api.contentstack.com", + personalize: "https://eu-personalize-api.contentstack.com", + launch: "https://eu-launch-api.contentstack.com" + }, + "AZURE-NA": { + name: "Azure North America", + cma: "https://azure-na-api.contentstack.com", + cda: "https://azure-na-cdn.contentstack.com", + app: "https://azure-na-app.contentstack.com", + developerHub: "https://azure-na-developerhub-api.contentstack.com", + personalize: "https://azure-na-personalize-api.contentstack.com", + launch: "https://azure-na-launch-api.contentstack.com" + }, + "AZURE-EU": { + name: "Azure Europe", + cma: "https://azure-eu-api.contentstack.com", + cda: "https://azure-eu-cdn.contentstack.com", + app: "https://azure-eu-app.contentstack.com", + developerHub: "https://azure-eu-developerhub-api.contentstack.com", + personalize: "https://azure-eu-personalize-api.contentstack.com", + launch: "https://azure-eu-launch-api.contentstack.com" + }, + "GCP-NA": { + name: "GCP North America", + cma: "https://gcp-na-api.contentstack.com", + cda: "https://gcp-na-cdn.contentstack.com", + app: "https://gcp-na-app.contentstack.com", + developerHub: "https://gcp-na-developerhub-api.contentstack.com", + personalize: "https://gcp-na-personalize-api.contentstack.com", + launch: "https://gcp-na-launch-api.contentstack.com" + } +}; + +// Get region from CLI +function getCurrentRegion() { + try { + const regionOutput = execSync("csdx config:get:region", { encoding: "utf8" }).trim(); + console.log("Raw region from CSDX config:", regionOutput); + + const regionMatch = regionOutput.match(/\b(NA|EU|AZURE-NA|AZURE-EU|GCP-NA)\b/); + + if (regionMatch) { + const regionKey = regionMatch[1]; + console.log("Extracted region key:", regionKey); + return regionKey; + } + + console.warn("Could not extract region from:", regionOutput); + return "NA"; + } catch (error) { + console.warn("Could not get region from CSDX:", error.message); + return "NA"; + } +} + +module.exports = async ({ + migration, + stackSDKInstance, + managementAPIClient, +}) => { + const axiosInstance = managementAPIClient.axiosInstance; + + const regionKey = getCurrentRegion(); + const regionConfig = REGION_CONFIG[regionKey]; + + console.log(`\n=== USING REGION: ${regionConfig.name} (${regionKey}) ===`); + console.log(`CMA: ${regionConfig.cma}`); + console.log(`CDA: ${regionConfig.cda}`); + console.log(`App: ${regionConfig.app}`); + console.log("=".repeat(50)); + + try { + const user = await managementAPIClient.getUser(); + console.log(`āœ“ User: ${user.email} (${user.uid})`); + + if (!user.organizations || user.organizations.length === 0) { + console.log("āŒ No organizations found"); + return; + } + + console.log(`\n=== YOUR ORGANIZATIONS ===`); + user.organizations.forEach((org, index) => { + console.log(`${index + 1}. ${org.name} (${org.uid})`); + }); + + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + const selectedOrg = await new Promise((resolve) => { + rl.question(`\nSelect organization number: `, (answer) => { + rl.close(); + const index = parseInt(answer) - 1; + if (index >= 0 && index < user.organizations.length) { + resolve(user.organizations[index]); + } else { + console.log("āŒ Invalid selection"); + resolve(null); + } + }); + }); + + if (!selectedOrg) { + console.log("āŒ No organization selected. Exiting..."); + return; + } + + const headers = managementAPIClient.axiosInstance.defaults.headers; + const authtoken = headers.authtoken || headers.authorization; + + console.log(`\nāœ“ Selected: ${selectedOrg.name} (${selectedOrg.uid})`); + console.log(`šŸ”‘ Auth token: ${authtoken ? authtoken.substring(0, 20) + '...' : 'Not found'}`); + + const orgDetails = await managementAPIClient + .organization(selectedOrg.uid) + .fetch(); + + console.log(`āœ“ Organization details fetched: ${orgDetails.name}`); + + const regionMapping = { + 'NA': 'NA', + 'EU': 'EU', + 'AZURE-NA': 'AZURE_NA', + 'AZURE-EU': 'AZURE_EU', + 'GCP-NA': 'GCP_NA', + 'GCP-EU': 'GCP_EU' + }; + + const sdkRegion = regionMapping[regionKey]; + + let clientConfig = { + authorization: authtoken + }; + + + if (regionKey !== 'NA' && sdkRegion) { + + clientConfig.region = contentstack.Region[sdkRegion]; + console.log(`āœ“ Setting SDK region to: ${sdkRegion}`); + } + + const client = contentstack.client(clientConfig); + + console.log(`āœ“ Contentstack client configured for ${regionKey} region`); + + // Find or create app + let existingApp = null; + + try { + console.log("šŸ” Searching for existing app..."); + const allApps = await client.marketplace(selectedOrg.uid).findAllApps(); + existingApp = allApps?.items?.find((app) => app?.name === manifest?.name); + + if (!existingApp) { + console.log("šŸ“± Creating new app..."); + existingApp = await client + .marketplace(selectedOrg.uid) + .app() + .create(manifest); + console.log(`āœ“ App created: ${existingApp.name} (${existingApp.uid})`); + } else { + console.log(`āœ“ Found existing app: ${existingApp.name} (${existingApp.uid})`); + console.log("šŸ”„ Updating existing app with manifest..."); + + const updatedApp = await client + .marketplace(selectedOrg.uid) + .app(existingApp.uid) + .update(manifest); + + console.log(`āœ“ App updated: ${updatedApp.name} (${updatedApp.uid})`); + existingApp = updatedApp; + } + } catch (error) { + console.error("āŒ Error with app operations:", error.message); + if (error.status === 401) { + console.error(`\nšŸ’” Authentication Error - This usually means:`); + console.error(` • Your auth token is from a different region`); + console.error(` • Please logout and login again in the ${regionKey} region`); + console.error(` • Commands: csdx auth:logout → csdx auth:login`); + } + throw error; + } + + console.log("šŸ” Fetching OAuth configuration..."); + const oauthData = await client + .marketplace(selectedOrg.uid) + .app(existingApp?.uid) + .oauth() + .fetch(); + + + console.log("šŸ”’ Generating PKCE credentials..."); + const code_verifier = crypto.randomBytes(32).toString("hex"); + const code_challenge = crypto + .createHash("sha256") + .update(code_verifier) + .digest("base64") + .replace(/\+/g, "-") + .replace(/\//g, "_") + .replace(/=+$/, ""); + + + const appData = { + timestamp: new Date().toISOString(), + region: { + key: regionKey, + name: regionConfig.name, + endpoints: regionConfig + }, + user: { + email: user.email, + uid: user.uid + }, + organization: { + name: selectedOrg.name, + uid: selectedOrg.uid, + }, + app: { + name: existingApp?.name, + uid: existingApp?.uid, + manifest: manifest.name + }, + oauthData: oauthData, + pkce: { + code_verifier: code_verifier, + code_challenge: code_challenge, + }, + }; + + fs.writeFileSync("app.json", JSON.stringify(appData, null, 2)); + console.log("āœ“ OAuth data logged to app.json"); + + // Generate authorization URL + const authUrl = `${regionConfig.app}/#!/apps/${existingApp?.uid}/authorize?response_type=code&client_id=${oauthData?.client_id}&redirect_uri=${encodeURIComponent(oauthData?.redirect_uri)}&code_challenge=${code_challenge}&code_challenge_method=S256`; + + console.log(`\nšŸš€ Authorization URL for ${regionConfig.name}:`); + console.log(authUrl); + + + openBrowser(authUrl); + + console.log("\nNote: If the browser doesn't open automatically, please copy and paste the URL above into your browser."); + + } catch (error) { + console.error("āŒ Setup failed:"); + console.error("Error:", error.message); + + if (error.errorMessage) { + console.error("Details:", error.errorMessage); + } + + console.error(`\nšŸ” Debug Info:`); + console.error(`Region: ${regionKey} (${regionConfig?.name || 'Unknown'})`); + console.error(`Expected CMA: ${regionConfig?.cma || 'Unknown'}`); + console.error(`Management API URL: ${managementAPIClient.axiosInstance.defaults.baseURL}`); + + throw error; + } +}; \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 000000000..67d95ce3e --- /dev/null +++ b/build.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +# --- Function to get current region --- +get_current_region() { + local region=$(csdx config:get:region 2>/dev/null) + if [ $? -eq 0 ] && [ -n "$region" ]; then + echo "$region" + return 0 + else + echo "Not set" + return 1 + fi +} + +# --- Prompt for Region --- +echo "" +echo "Please select your region:" +echo "1. NA (North America)" +echo "2. EU (Europe)" +echo "3. AZURE-NA (Azure North America)" +echo "4. AZURE-EU (Azure Europe)" +echo "5. GCP-NA (GCP North America)" +read -p "Enter region number (default: 1): " REGION_CHOICE + +case $REGION_CHOICE in + 2) REGION="EU";; + 3) REGION="AZURE-NA";; + 4) REGION="AZURE-EU";; + 5) REGION="GCP-NA";; + *) REGION="NA";; +esac + +echo "Selected region: $REGION" + +# --- Set the Region in CSDX Config --- +echo "" +echo "Setting the region in CSDX..." +if ! csdx config:set:region "$REGION"; then + echo "Failed to set the region. Please check your CSDX installation." + exit 1 +fi +echo "āœ“ Region set to $REGION." + +# --- Get and Verify the Region --- +echo "" +echo "Verifying the region configuration..." +CURRENT_REGION=$(csdx config:get:region) +if [ $? -eq 0 ]; then + echo "āœ“ Current region is set to: $CURRENT_REGION" +else + echo "⚠ Could not retrieve current region configuration" +fi + +# --- OAuth Login (Always redirect after region selection) --- +echo "" +echo "Redirecting to OAuth login..." +echo "This will open your browser for authentication in the selected region ($REGION)." +if ! csdx auth:login --oauth; then + echo "OAuth login failed. Please try again." + exit 1 +fi +echo "āœ“ OAuth login successful for region: $REGION" + +# Update redirect_uri in manifest.json +JSON_FILE="api/manifest.json" +if [ -f "$JSON_FILE" ]; then + echo "" + read -p "Enter new redirect_uri or press enter to use default value: " NEW_URI + + #default value + if [ -z "$NEW_URI" ]; then + NEW_URI="http://localhost:5001" + fi + + sed -i '' "s|\"redirect_uri\"[[:space:]]*:[[:space:]]*\"[^\"]*\"|\"redirect_uri\": \"$NEW_URI\"|g" "$JSON_FILE" + echo "āœ“ redirect_uri updated to $NEW_URI in $JSON_FILE" +else + echo "⚠ manifest.json file not found at: $JSON_FILE" +fi + +# Run the Migration Script +echo "" +echo "Running the migration..." +SCRIPT_PATH="api/sso.utils.js" +if [ -f "$SCRIPT_PATH" ]; then + csdx cm:stacks:migration --file-path "$SCRIPT_PATH" +else + echo "Migration script not found at: $SCRIPT_PATH" + echo "Please update the script path in build.sh" + exit 1 +fi + +echo "" +echo "āœ“ Setup script finished." \ No newline at end of file From 12672d4bc8fdf333826a22672571fb6c5973205c Mon Sep 17 00:00:00 2001 From: shobhit upadhyay Date: Thu, 4 Sep 2025 15:28:28 +0530 Subject: [PATCH 2/8] refactor: streamline OAuth token handling and update package dependencies - Removed redundant variables for client_id and client_secret in saveOAuthToken function. - Updated logging to use a centralized logger instead of console methods. - Removed unnecessary deletion of code_verifier from the request session. - Updated package.json to remove outdated "api" dependency. --- .talismanrc | 6 ++++++ api/package.json | 1 - api/src/services/auth.service.ts | 17 ++++++----------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.talismanrc b/.talismanrc index b5bc1da80..6055ac3ad 100644 --- a/.talismanrc +++ b/.talismanrc @@ -119,4 +119,10 @@ fileignoreconfig: checksum: 8b78783b54935cc1e9721ab2b0b4daf768f5a1dbd96e6594e2eeb1d5fd45d90f - filename: api/src/services/taxonomy.service.ts checksum: 839f26a0ac2fe3515276011353a5e3eb288b29af87438dab6774b67857013461 +version: "1.0" + + +fileignoreconfig: +- filename: api/src/services/auth.service.ts + checksum: fb32356c34ba32440960c9c5be0b9ddf6fc48104128b985480ae9e455f94fe8c version: "1.0" \ No newline at end of file diff --git a/api/package.json b/api/package.json index 1d0b5c2e8..fca180401 100644 --- a/api/package.json +++ b/api/package.json @@ -28,7 +28,6 @@ "@contentstack/cli-utilities": "^1.12.0", "@contentstack/json-rte-serializer": "^2.0.7", "@contentstack/marketplace-sdk": "^1.4.0", - "api": "^6.1.3", "axios": "^1.11.0", "chokidar": "^3.6.0", "cors": "^2.8.5", diff --git a/api/src/services/auth.service.ts b/api/src/services/auth.service.ts index f21b6d5c8..596ae4e80 100644 --- a/api/src/services/auth.service.ts +++ b/api/src/services/auth.service.ts @@ -200,17 +200,14 @@ const saveOAuthToken = async (req: Request): Promise => { const regionStr = Array.isArray(region) ? region[0] : region; const tokenUrl = CSAUTHHOST[regionStr as keyof typeof CSAUTHHOST]; - const clientId = client_id - const clientSecret = client_secret const redirectUri = `${redirect_uri}/v2/auth/save-token` - if (!tokenUrl || !clientId || !clientSecret) { + if (!tokenUrl || !client_id || !client_secret) { throw new InternalServerError(`Configuration missing for region: ${region}`); } - const formData = new URLSearchParams(); formData.append('grant_type', 'authorization_code'); - formData.append('client_id', clientId); - formData.append('client_secret', clientSecret); + formData.append('client_id', client_id); + formData.append('client_secret', client_secret); formData.append('redirect_uri', redirectUri); formData.append('code', code as string); formData.append('code_verifier', code_verifier); @@ -221,8 +218,6 @@ const saveOAuthToken = async (req: Request): Promise => { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); - delete (req.session as any).code_verifier; - const { access_token, refresh_token, organization_uid } = tokenResponse.data; const apiHost = regionalApiHosts[region as keyof typeof regionalApiHosts]; @@ -306,7 +301,7 @@ export const refreshOAuthToken = async (userId: string): Promise => { throw new Error('OAuth client_id or client_secret not found in app.json'); } - console.info(`Refreshing token for user: ${userRecord.email} in region: ${userRecord.region}`); + logger.info(`Refreshing token for user: ${userRecord.email} in region: ${userRecord.region}`); const appUrl = CSAUTHHOST[userRecord.region] || CSAUTHHOST['NA']; const tokenEndpoint = `${appUrl}`; @@ -340,11 +335,11 @@ export const refreshOAuthToken = async (userId: string): Promise => { } }); - console.info(`Token refreshed successfully for user: ${userRecord.email}`); + logger.info(`Token refreshed successfully for user: ${userRecord.email}`); return access_token; } catch (error: any) { - console.error(`Token refresh failed for user ${userId}:`, error.response?.data || error.message); + logger.error(`Token refresh failed for user ${userId}:`, error.response?.data || error.message); throw new Error(`Failed to refresh token: ${error.response?.data?.error_description || error.message}`); } }; From 8d58e849d521a25bed78043c449cfb4be1e92726 Mon Sep 17 00:00:00 2001 From: shobhit upadhyay Date: Mon, 8 Sep 2025 10:46:12 +0530 Subject: [PATCH 3/8] fix: update redirect_uri in build script and auth service for OAuth flow - Modified build.sh to append '/v2/auth/save-token' to the redirect_uri. - Updated auth.service.ts to use the correct redirect_uri for token requests. - Ensured consistency in region configuration and API endpoint handling. --- api/src/services/auth.service.ts | 4 +- api/sso.utils.js | 160 ++++++++++++++++++------------- build.sh | 4 +- 3 files changed, 99 insertions(+), 69 deletions(-) diff --git a/api/src/services/auth.service.ts b/api/src/services/auth.service.ts index 596ae4e80..90bda5627 100644 --- a/api/src/services/auth.service.ts +++ b/api/src/services/auth.service.ts @@ -200,15 +200,15 @@ const saveOAuthToken = async (req: Request): Promise => { const regionStr = Array.isArray(region) ? region[0] : region; const tokenUrl = CSAUTHHOST[regionStr as keyof typeof CSAUTHHOST]; - const redirectUri = `${redirect_uri}/v2/auth/save-token` if (!tokenUrl || !client_id || !client_secret) { throw new InternalServerError(`Configuration missing for region: ${region}`); } + const formData = new URLSearchParams(); formData.append('grant_type', 'authorization_code'); formData.append('client_id', client_id); formData.append('client_secret', client_secret); - formData.append('redirect_uri', redirectUri); + formData.append('redirect_uri', redirect_uri); formData.append('code', code as string); formData.append('code_verifier', code_verifier); const tokenResponse = await https({ diff --git a/api/sso.utils.js b/api/sso.utils.js index b32e49105..1694958f1 100644 --- a/api/sso.utils.js +++ b/api/sso.utils.js @@ -4,7 +4,7 @@ const { execSync } = require("child_process"); const fs = require("fs"); const crypto = require("crypto"); const manifest = require("./manifest.json"); - +const { default: axios } = require("axios"); const REGION_CONFIG = { NA: { @@ -14,7 +14,7 @@ const REGION_CONFIG = { app: "https://app.contentstack.com", developerHub: "https://developerhub-api.contentstack.com", personalize: "https://personalize-api.contentstack.com", - launch: "https://launch-api.contentstack.com" + launch: "https://launch-api.contentstack.com", }, EU: { name: "Europe", @@ -23,7 +23,7 @@ const REGION_CONFIG = { app: "https://eu-app.contentstack.com", developerHub: "https://eu-developerhub-api.contentstack.com", personalize: "https://eu-personalize-api.contentstack.com", - launch: "https://eu-launch-api.contentstack.com" + launch: "https://eu-launch-api.contentstack.com", }, "AZURE-NA": { name: "Azure North America", @@ -32,7 +32,7 @@ const REGION_CONFIG = { app: "https://azure-na-app.contentstack.com", developerHub: "https://azure-na-developerhub-api.contentstack.com", personalize: "https://azure-na-personalize-api.contentstack.com", - launch: "https://azure-na-launch-api.contentstack.com" + launch: "https://azure-na-launch-api.contentstack.com", }, "AZURE-EU": { name: "Azure Europe", @@ -41,7 +41,7 @@ const REGION_CONFIG = { app: "https://azure-eu-app.contentstack.com", developerHub: "https://azure-eu-developerhub-api.contentstack.com", personalize: "https://azure-eu-personalize-api.contentstack.com", - launch: "https://azure-eu-launch-api.contentstack.com" + launch: "https://azure-eu-launch-api.contentstack.com", }, "GCP-NA": { name: "GCP North America", @@ -50,24 +50,28 @@ const REGION_CONFIG = { app: "https://gcp-na-app.contentstack.com", developerHub: "https://gcp-na-developerhub-api.contentstack.com", personalize: "https://gcp-na-personalize-api.contentstack.com", - launch: "https://gcp-na-launch-api.contentstack.com" - } + launch: "https://gcp-na-launch-api.contentstack.com", + }, }; -// Get region from CLI + function getCurrentRegion() { try { - const regionOutput = execSync("csdx config:get:region", { encoding: "utf8" }).trim(); + const regionOutput = execSync("csdx config:get:region", { + encoding: "utf8", + }).trim(); console.log("Raw region from CSDX config:", regionOutput); - - const regionMatch = regionOutput.match(/\b(NA|EU|AZURE-NA|AZURE-EU|GCP-NA)\b/); - + + const regionMatch = regionOutput.match( + /\b(NA|EU|AZURE-NA|AZURE-EU|GCP-NA)\b/ + ); + if (regionMatch) { const regionKey = regionMatch[1]; console.log("Extracted region key:", regionKey); return regionKey; } - + console.warn("Could not extract region from:", regionOutput); return "NA"; } catch (error) { @@ -83,9 +87,10 @@ module.exports = async ({ }) => { const axiosInstance = managementAPIClient.axiosInstance; + const regionKey = getCurrentRegion(); const regionConfig = REGION_CONFIG[regionKey]; - + console.log(`\n=== USING REGION: ${regionConfig.name} (${regionKey}) ===`); console.log(`CMA: ${regionConfig.cma}`); console.log(`CDA: ${regionConfig.cda}`); @@ -131,50 +136,52 @@ module.exports = async ({ const headers = managementAPIClient.axiosInstance.defaults.headers; const authtoken = headers.authtoken || headers.authorization; - + console.log(`\nāœ“ Selected: ${selectedOrg.name} (${selectedOrg.uid})`); - console.log(`šŸ”‘ Auth token: ${authtoken ? authtoken.substring(0, 20) + '...' : 'Not found'}`); + console.log( + `šŸ”‘ Auth token: ${ + authtoken ? authtoken.substring(0, 20) + "..." : "Not found" + }` + ); const orgDetails = await managementAPIClient .organization(selectedOrg.uid) .fetch(); - + console.log(`āœ“ Organization details fetched: ${orgDetails.name}`); const regionMapping = { - 'NA': 'NA', - 'EU': 'EU', - 'AZURE-NA': 'AZURE_NA', - 'AZURE-EU': 'AZURE_EU', - 'GCP-NA': 'GCP_NA', - 'GCP-EU': 'GCP_EU' + NA: "NA", + EU: "EU", + "AZURE-NA": "AZURE_NA", + "AZURE-EU": "AZURE_EU", + "GCP-NA": "GCP_NA", + "GCP-EU": "GCP_EU", }; - + const sdkRegion = regionMapping[regionKey]; - + let clientConfig = { - authorization: authtoken + authorization: authtoken, }; - - - if (regionKey !== 'NA' && sdkRegion) { + if (regionKey !== "NA" && sdkRegion) { clientConfig.region = contentstack.Region[sdkRegion]; console.log(`āœ“ Setting SDK region to: ${sdkRegion}`); } - + const client = contentstack.client(clientConfig); - + console.log(`āœ“ Contentstack client configured for ${regionKey} region`); // Find or create app let existingApp = null; - + try { console.log("šŸ” Searching for existing app..."); const allApps = await client.marketplace(selectedOrg.uid).findAllApps(); existingApp = allApps?.items?.find((app) => app?.name === manifest?.name); - + if (!existingApp) { console.log("šŸ“± Creating new app..."); existingApp = await client @@ -183,23 +190,46 @@ module.exports = async ({ .create(manifest); console.log(`āœ“ App created: ${existingApp.name} (${existingApp.uid})`); } else { - console.log(`āœ“ Found existing app: ${existingApp.name} (${existingApp.uid})`); + console.log( + `āœ“ Found existing app: ${existingApp.name} (${existingApp.uid})` + ); console.log("šŸ”„ Updating existing app with manifest..."); - - const updatedApp = await client - .marketplace(selectedOrg.uid) - .app(existingApp.uid) - .update(manifest); - - console.log(`āœ“ App updated: ${updatedApp.name} (${updatedApp.uid})`); - existingApp = updatedApp; + + // Update the existing app with the current manifest + const oauthUpdatePayload = { + redirect_uri: manifest?.oauth?.redirect_uri, + app_token_config: manifest?.oauth?.app_token_config || { + enabled: false, + scopes: [], + }, + user_token_config: manifest?.oauth?.user_token_config || { + enabled: true, + scopes: manifest?.oauth?.user_token_config?.scopes || [], + allow_pkce: true, + }, + }; + const updatedApp = await axios.put( + `${regionConfig.app}/apps-api/manifests/${existingApp?.uid}/oauth`, + oauthUpdatePayload, + { + headers: { + authorization: authtoken, + "Content-Type": "application/json", + organization_uid: selectedOrg.uid, + }, + } + ); + + console.log(`āœ“ App updated: ${existingApp.name} (${existingApp.uid})`); } } catch (error) { console.error("āŒ Error with app operations:", error.message); if (error.status === 401) { console.error(`\nšŸ’” Authentication Error - This usually means:`); console.error(` • Your auth token is from a different region`); - console.error(` • Please logout and login again in the ${regionKey} region`); + console.error( + ` • Please logout and login again in the ${regionKey} region` + ); console.error(` • Commands: csdx auth:logout → csdx auth:login`); } throw error; @@ -212,7 +242,6 @@ module.exports = async ({ .oauth() .fetch(); - console.log("šŸ”’ Generating PKCE credentials..."); const code_verifier = crypto.randomBytes(32).toString("hex"); const code_challenge = crypto @@ -223,17 +252,26 @@ module.exports = async ({ .replace(/\//g, "_") .replace(/=+$/, ""); + const authUrl = `${regionConfig.app}/#!/apps/${ + existingApp?.uid + }/authorize?response_type=code&client_id=${ + oauthData?.client_id + }&redirect_uri=${encodeURIComponent( + oauthData?.redirect_uri + )}&code_challenge=${code_challenge}&code_challenge_method=S256`; + console.log(`\nšŸš€ Authorization URL for ${regionConfig.name}:`); + console.log(authUrl); const appData = { timestamp: new Date().toISOString(), region: { key: regionKey, name: regionConfig.name, - endpoints: regionConfig + endpoints: regionConfig, }, user: { email: user.email, - uid: user.uid + uid: user.uid, }, organization: { name: selectedOrg.name, @@ -242,42 +280,34 @@ module.exports = async ({ app: { name: existingApp?.name, uid: existingApp?.uid, - manifest: manifest.name + manifest: manifest.name, }, oauthData: oauthData, pkce: { code_verifier: code_verifier, code_challenge: code_challenge, }, + authUrl: authUrl, }; fs.writeFileSync("app.json", JSON.stringify(appData, null, 2)); - console.log("āœ“ OAuth data logged to app.json"); - - // Generate authorization URL - const authUrl = `${regionConfig.app}/#!/apps/${existingApp?.uid}/authorize?response_type=code&client_id=${oauthData?.client_id}&redirect_uri=${encodeURIComponent(oauthData?.redirect_uri)}&code_challenge=${code_challenge}&code_challenge_method=S256`; - - console.log(`\nšŸš€ Authorization URL for ${regionConfig.name}:`); - console.log(authUrl); - - - openBrowser(authUrl); - - console.log("\nNote: If the browser doesn't open automatically, please copy and paste the URL above into your browser."); + console.log("āœ“ OAuth data & Auth URL logged to app.json"); } catch (error) { console.error("āŒ Setup failed:"); console.error("Error:", error.message); - + if (error.errorMessage) { console.error("Details:", error.errorMessage); } - + console.error(`\nšŸ” Debug Info:`); - console.error(`Region: ${regionKey} (${regionConfig?.name || 'Unknown'})`); - console.error(`Expected CMA: ${regionConfig?.cma || 'Unknown'}`); - console.error(`Management API URL: ${managementAPIClient.axiosInstance.defaults.baseURL}`); - + console.error(`Region: ${regionKey} (${regionConfig?.name || "Unknown"})`); + console.error(`Expected CMA: ${regionConfig?.cma || "Unknown"}`); + console.error( + `Management API URL: ${managementAPIClient.axiosInstance.defaults.baseURL}` + ); + throw error; } }; \ No newline at end of file diff --git a/build.sh b/build.sh index 67d95ce3e..4c2639826 100755 --- a/build.sh +++ b/build.sh @@ -72,8 +72,8 @@ if [ -f "$JSON_FILE" ]; then NEW_URI="http://localhost:5001" fi - sed -i '' "s|\"redirect_uri\"[[:space:]]*:[[:space:]]*\"[^\"]*\"|\"redirect_uri\": \"$NEW_URI\"|g" "$JSON_FILE" - echo "āœ“ redirect_uri updated to $NEW_URI in $JSON_FILE" + sed -i '' "s|\"redirect_uri\"[[:space:]]*:[[:space:]]*\"[^\"]*\"|\"redirect_uri\": \"${NEW_URI}/v2/auth/save-token\"|g" "$JSON_FILE" + echo "āœ“ redirect_uri updated to ${NEW_URI}/v2/auth/save-token in $JSON_FILE" else echo "⚠ manifest.json file not found at: $JSON_FILE" fi From 2127e90641b67100d5e705d7fee14d3290fe5cf7 Mon Sep 17 00:00:00 2001 From: shobhit upadhyay Date: Mon, 8 Sep 2025 10:46:45 +0530 Subject: [PATCH 4/8] talisman --- .talismanrc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.talismanrc b/.talismanrc index e70ba3579..0c798d31f 100644 --- a/.talismanrc +++ b/.talismanrc @@ -130,4 +130,9 @@ version: "1.0" fileignoreconfig: - filename: ui/src/components/DestinationStack/Actions/LoadLanguageMapper.tsx checksum: dde885393dfdd813f1dace88ce8ce79e3fb438801ee5e7bf19855fe1394cb78c +version: "1.0" + +fileignoreconfig: +- filename: api/sso.utils.js + checksum: 5d589c128c4b38f8aacd70e5d02ddd7fa8e93ff7897ca69a1258378139d1d616 version: "1.0" \ No newline at end of file From 3407f06cdc2e0c5e6e22dd876a7164ef4c663e2b Mon Sep 17 00:00:00 2001 From: shobhit upadhyay Date: Mon, 29 Sep 2025 14:27:03 +0530 Subject: [PATCH 5/8] refactor: enhance SSO functionality and update authentication flow - Added new endpoints for retrieving app configuration and checking SSO authentication status. - Updated authentication service to handle SSO tokens and access tokens more effectively. - Enhanced error handling for SSO-related operations. - Updated UI components to support SSO login and added corresponding styles. - Refactored API service calls to accommodate new SSO logic and improved token management. --- api/package-lock.json | 1694 +-------------------- api/package.json | 4 +- api/src/controllers/auth.controller.ts | 88 ++ api/src/models/authentication.ts | 1 + api/src/models/types.ts | 1 + api/src/routes/auth.routes.ts | 14 + api/src/services/auth.service.ts | 93 +- api/src/services/contentMapper.service.ts | 25 +- api/src/services/globalField.service.ts | 28 +- api/src/services/marketplace.service.ts | 19 +- api/src/services/migration.service.ts | 41 +- api/src/services/org.service.ts | 134 +- api/src/services/projects.service.ts | 36 +- api/src/services/runCli.service.ts | 20 +- api/src/services/taxonomy.service.ts | 31 +- api/src/services/user.service.ts | 17 +- api/src/utils/auth.utils.ts | 18 + api/src/utils/config-handler.util.ts | 26 + ui/src/pages/Login/index.scss | 46 + ui/src/pages/Login/index.tsx | 187 ++- ui/src/services/api/login.service.ts | 26 +- upload-api/src/config/index.ts | 4 +- 22 files changed, 816 insertions(+), 1737 deletions(-) create mode 100644 api/src/utils/config-handler.util.ts diff --git a/api/package-lock.json b/api/package-lock.json index 1f69f2351..36fc6d4e6 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -9,12 +9,11 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@contentstack/cli": "^1.34.0", - "@contentstack/cli-utilities": "^1.12.0", + "@contentstack/cli": "1.41.0", + "@contentstack/cli-utilities": "^1.14.2", "@contentstack/json-rte-serializer": "^2.0.7", "@contentstack/marketplace-sdk": "^1.4.0", - "api": "^6.1.3", - "axios": "^1.11.0", + "axios": "^1.12.2", "chokidar": "^3.6.0", "cors": "^2.8.5", "dotenv": "^16.3.1", @@ -65,19 +64,6 @@ "typescript": "^5.4.3" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@apollo/client": { "version": "3.13.9", "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.9.tgz", @@ -136,485 +122,6 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.3.tgz", - "integrity": "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.3.tgz", - "integrity": "sha512-hyrN8ivxfvJ4i0fIJuV4EOlV0WDMz5Ui4StRTgVaAvWeiRCilXgwVvxJKtFQ3TKtHgJscB2YiXKGNJuVwhQMtA==", - "peer": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.3", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.3", - "@babel/parser": "^7.27.3", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.27.3", - "@babel/types": "^7.27.3", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.3.tgz", - "integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==", - "peer": true, - "dependencies": { - "@babel/parser": "^7.27.3", - "@babel/types": "^7.27.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "peer": true, - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "peer": true, - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", - "peer": true, - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.3.tgz", - "integrity": "sha512-h/eKy9agOya1IGuLaZ9tEUgz+uIRXcbtOhRtUyyMf8JFmn1iT13vnl/IGVWSkdOCG/pC57U4S1jnAabAavTMwg==", - "peer": true, - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.3.tgz", - "integrity": "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==", - "peer": true, - "dependencies": { - "@babel/types": "^7.27.3" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.3.tgz", - "integrity": "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ==", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.3", - "@babel/parser": "^7.27.3", - "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz", - "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==", - "peer": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "peer": true - }, "node_modules/@colors/colors": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", @@ -2156,6 +1663,53 @@ "node": ">=14.0.0" } }, + "node_modules/@contentstack/cli-command/node_modules/@contentstack/cli-utilities": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@contentstack/cli-utilities/-/cli-utilities-1.13.2.tgz", + "integrity": "sha512-jOiX99fs4XD811ipPo3N0yj/QBN63m7AIq/egzddKt39xhRTmrzdmQ/jaQdZphcl/65W6OennDdt/ThgBBtQhQ==", + "dependencies": { + "@contentstack/management": "~1.22.0", + "@contentstack/marketplace-sdk": "^1.2.8", + "@oclif/core": "^4.3.0", + "axios": "^1.9.0", + "chalk": "^4.1.2", + "cli-cursor": "^3.1.0", + "cli-progress": "^3.12.0", + "cli-table": "^0.3.11", + "conf": "^10.2.0", + "dotenv": "^16.5.0", + "figures": "^3.2.0", + "inquirer": "8.2.6", + "inquirer-search-checkbox": "^1.0.0", + "inquirer-search-list": "^1.2.6", + "js-yaml": "^4.1.0", + "klona": "^2.0.6", + "lodash": "^4.17.21", + "mkdirp": "^1.0.4", + "open": "^8.4.2", + "ora": "^5.4.1", + "papaparse": "^5.5.3", + "recheck": "~4.4.5", + "rxjs": "^6.6.7", + "traverse": "^0.6.11", + "tty-table": "^4.2.3", + "unique-string": "^2.0.0", + "uuid": "^9.0.1", + "winston": "^3.17.0", + "xdg-basedir": "^4.0.0" + } + }, + "node_modules/@contentstack/cli-command/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@contentstack/cli-config": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@contentstack/cli-config/-/cli-config-1.12.1.tgz", @@ -2344,9 +1898,9 @@ } }, "node_modules/@contentstack/cli-utilities": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/@contentstack/cli-utilities/-/cli-utilities-1.13.1.tgz", - "integrity": "sha512-ybG+6AycUbVoDhIE9WF+aZkAlv4XA40E1X2B3etbgLk5oOZKRRXaZ3oZjToqF94sd2jFxu96sDDBs50DJcwaYA==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/@contentstack/cli-utilities/-/cli-utilities-1.14.2.tgz", + "integrity": "sha512-NcJj07TWAGYu30HvrQm3iICqa2OdGOQ/nXBZsZ+91HUDLqKiGlmeYrgj6IfvFJEXjdVM12dvs9EIQdLxG84L7Q==", "dependencies": { "@contentstack/management": "~1.22.0", "@contentstack/marketplace-sdk": "^1.2.8", @@ -2406,53 +1960,6 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/@contentstack/cli-utilities": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@contentstack/cli-utilities/-/cli-utilities-1.12.0.tgz", - "integrity": "sha512-vFgC74Ebb07oKF5PO5Q6ToGcRh0ndVUBcPnKzqvnUmHNIN+RxvYkbgblPXLhZAQfsCsUnVhrxBULXqSV7TFafg==", - "dependencies": { - "@contentstack/management": "~1.22.0", - "@contentstack/marketplace-sdk": "^1.2.8", - "@oclif/core": "^4.3.0", - "axios": "^1.9.0", - "chalk": "^4.1.2", - "cli-cursor": "^3.1.0", - "cli-progress": "^3.12.0", - "cli-table": "^0.3.11", - "conf": "^10.2.0", - "dotenv": "^16.5.0", - "figures": "^3.2.0", - "inquirer": "8.2.6", - "inquirer-search-checkbox": "^1.0.0", - "inquirer-search-list": "^1.2.6", - "js-yaml": "^4.1.0", - "klona": "^2.0.6", - "lodash": "^4.17.21", - "mkdirp": "^1.0.4", - "open": "^8.4.2", - "ora": "^5.4.1", - "papaparse": "^5.5.3", - "recheck": "~4.4.5", - "rxjs": "^6.6.7", - "traverse": "^0.6.11", - "tty-table": "^4.2.3", - "unique-string": "^2.0.0", - "uuid": "^9.0.1", - "winston": "^3.17.0", - "xdg-basedir": "^4.0.0" - } - }, - "node_modules/@contentstack/cli-variants/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@contentstack/cli/node_modules/@contentstack/cli-command": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@contentstack/cli-command/-/cli-command-1.5.1.tgz", @@ -3259,11 +2766,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@exodus/schemasafe": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", - "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==" - }, "node_modules/@fast-csv/format": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/@fast-csv/format/-/format-4.3.5.tgz", @@ -3359,14 +2861,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/momoa": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@humanwhocodes/momoa/-/momoa-2.0.4.tgz", - "integrity": "sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==", - "engines": { - "node": ">=10.10.0" - } - }, "node_modules/@humanwhocodes/object-schema": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", @@ -3810,11 +3304,6 @@ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==" }, - "node_modules/@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3930,18 +3419,6 @@ "node": ">=14" } }, - "node_modules/@pkgr/core": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz", - "integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==", - "peer": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/pkgr" - } - }, "node_modules/@rollup/plugin-commonjs": { "version": "28.0.6", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.6.tgz", @@ -4361,76 +3838,15 @@ }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "peer": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "peer": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "peer": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" }, - "node_modules/@types/babel__traverse": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", - "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", - "peer": true, - "dependencies": { - "@babel/types": "^7.20.7" + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "engines": { + "node": ">= 10" } }, "node_modules/@types/body-parser": { @@ -4520,20 +3936,6 @@ "@types/node": "*" } }, - "node_modules/@types/glob-to-regexp": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@types/glob-to-regexp/-/glob-to-regexp-0.4.4.tgz", - "integrity": "sha512-nDKoaKJYbnn1MZxUY0cA1bPmmgZbg0cTq7Rh13d0KWYNOiKbqoR+2d89SnRPszGh7ROzSwZ/GOjZ4jPbmmZ6Eg==" - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "peer": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", @@ -4553,7 +3955,8 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true }, "node_modules/@types/json5": { "version": "0.0.29", @@ -5047,19 +4450,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-draft-04": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", - "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", - "peerDependencies": { - "ajv": "^8.5.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, "node_modules/ajv-formats": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", @@ -5161,11 +4551,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -5384,6 +4769,14 @@ "dev": true, "peer": true }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", @@ -5435,9 +4828,9 @@ } }, "node_modules/axios": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", + "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", @@ -5715,11 +5108,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-me-maybe": { - "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==" - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -5748,11 +5136,6 @@ "cdl": "bin/cdl.js" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -5957,16 +5340,6 @@ "node": ">=0.8" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "peer": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, "node_modules/code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -6059,40 +5432,11 @@ "node": ">= 0.8" } }, - "node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "engines": { - "node": ">=14" - } - }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" }, - "node_modules/compute-gcd": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.1.tgz", - "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", - "dependencies": { - "validate.io-array": "^1.0.3", - "validate.io-function": "^1.0.2", - "validate.io-integer-array": "^1.0.0" - } - }, - "node_modules/compute-lcm": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.2.tgz", - "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", - "dependencies": { - "compute-gcd": "^1.2.1", - "validate.io-array": "^1.0.3", - "validate.io-function": "^1.0.2", - "validate.io-integer-array": "^1.0.0" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -6311,18 +5655,6 @@ "node": ">=0.4.0" } }, - "node_modules/d": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", - "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", - "dependencies": { - "es5-ext": "^0.10.64", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -6390,18 +5722,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/datauri": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/datauri/-/datauri-4.1.0.tgz", - "integrity": "sha512-y17kh32+I82G+ED9MNWFkZiP/Cq/vO1hN9+tSZsT9C9qn3NrvcBnh7crSepg0AQPge1hXx2Ca44s1FRdv0gFWA==", - "dependencies": { - "image-size": "1.0.0", - "mimer": "^2.0.2" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/date-fns": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", @@ -6940,59 +6260,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es5-ext": { - "version": "0.10.64", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", - "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", - "hasInstallScript": true, - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "esniff": "^2.0.1", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, "node_modules/es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" }, - "node_modules/es6-symbol": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", - "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", - "dependencies": { - "d": "^1.0.2", - "ext": "^1.7.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, "node_modules/esbuild": { "version": "0.25.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", @@ -7664,20 +6936,6 @@ "node": "*" } }, - "node_modules/esniff": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", - "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -7760,73 +7018,6 @@ "node": ">= 0.6" } }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "peer": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "peer": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/execa/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "peer": true - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "peer": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "30.0.0-beta.3", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.0-beta.3.tgz", - "integrity": "sha512-GvjGgmmu8jO6BdRAuGT9gJe/agQG+L8fZlbUEjZ5DICU11rYxT+IDzc/SCvvjFCnvfBg6EgLv7KpR0WvmgqS5Q==", - "peer": true, - "dependencies": { - "@jest/expect-utils": "30.0.0-beta.3", - "@jest/get-type": "30.0.0-beta.3", - "jest-matcher-utils": "30.0.0-beta.3", - "jest-message-util": "30.0.0-beta.3", - "jest-mock": "30.0.0-beta.3", - "jest-util": "30.0.0-beta.3" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || >=22.0.0" - } - }, "node_modules/express": { "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", @@ -8039,14 +7230,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dependencies": { - "type": "^2.7.2" - } - }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -8125,11 +7308,6 @@ "fastest-levenshtein": "^1.0.7" } }, - "node_modules/fast-safe-stringify": { - "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==" - }, "node_modules/fast-uri": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", @@ -8179,20 +7357,6 @@ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, - "node_modules/fetch-mock": { - "version": "12.5.2", - "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-12.5.2.tgz", - "integrity": "sha512-b5KGDFmdmado2MPQjZl6ix3dAG3iwCitb0XQwN72y2s9VnWZ3ObaGNy+bkpm1390foiLDybdJ7yjRGKD36kATw==", - "dependencies": { - "@types/glob-to-regexp": "^0.4.4", - "dequal": "^2.0.3", - "glob-to-regexp": "^0.4.1", - "regexparam": "^3.0.0" - }, - "engines": { - "node": ">=18.11.0" - } - }, "node_modules/figlet": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.8.1.tgz", @@ -8298,44 +7462,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-cache-dir/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-cache-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -8456,23 +7582,6 @@ "node": ">= 6" } }, - "node_modules/form-data-encoder": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.9.0.tgz", - "integrity": "sha512-rahaRMkN8P8d/tgK/BLPX+WBVM27NbvdXBxqQujBtkDAIFspaRqN7Od7lfdGQA6KAD+f82fYCLBq1ipvcu8qLw==" - }, - "node_modules/formdata-node": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", - "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", - "dependencies": { - "node-domexception": "1.0.0", - "web-streams-polyfill": "4.0.0-beta.3" - }, - "engines": { - "node": ">= 12.20" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -8683,18 +7792,6 @@ "node": ">= 0.4" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-symbol-description": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", @@ -9065,11 +8162,6 @@ "node": ">= 14" } }, - "node_modules/http2-client": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", - "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==" - }, "node_modules/https-proxy-agent": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", @@ -9082,20 +8174,6 @@ "node": ">= 14" } }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "peer": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/humps": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz", - "integrity": "sha512-E0eIbrFWUhwfXJmsbdjRQFQPrl5pTEoKlz163j1mTqqUnU9PgR4AgB8AIITzuB3vLBdxZXyZ9TDIrwB2OASz4g==" - }, "node_modules/husky": { "version": "9.1.7", "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", @@ -9149,20 +8227,6 @@ "node": ">= 4" } }, - "node_modules/image-size": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.0.tgz", - "integrity": "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==", - "dependencies": { - "queue": "6.0.2" - }, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/immer": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", @@ -10344,15 +9408,6 @@ "node": ">=16" } }, - "node_modules/isomorphic-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", - "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", - "dependencies": { - "node-fetch": "^2.6.1", - "whatwg-fetch": "^3.4.1" - } - }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -10488,12 +9543,6 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "peer": true - }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -10533,11 +9582,6 @@ "json5": "lib/cli.js" } }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" - }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -10567,14 +9611,6 @@ "underscore": "1.12.1" } }, - "node_modules/jsonpointer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/jsonschema": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.5.0.tgz", @@ -10673,15 +9709,6 @@ "json-buffer": "3.0.1" } }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/klona": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", @@ -10715,15 +9742,6 @@ "node": ">=0.10" } }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -11046,11 +10064,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" - }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -11387,14 +10400,6 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "dependencies": { - "es5-ext": "~0.10.2" - } - }, "node_modules/magic-string": { "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", @@ -11430,24 +10435,6 @@ "node": ">= 0.6" } }, - "node_modules/memoizee": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", - "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", - "dependencies": { - "d": "^1.0.2", - "es5-ext": "^0.10.64", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/merge": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", @@ -11461,12 +10448,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "peer": true - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -11528,23 +10509,12 @@ "node_modules/mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimer": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mimer/-/mimer-2.0.2.tgz", - "integrity": "sha512-izxvjsB7Ur5HrTbPu6VKTrzxSMBFBqyZQc6dWlZNQ4/wAvf886fD4lrjtFd8IQ8/WmZKdxKjUtqFFNaj3hQ52g==", - "bin": { - "mimer": "bin/mimer" + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" }, "engines": { - "node": ">= 12" + "node": ">= 0.6" } }, "node_modules/mimic-fn": { @@ -11637,14 +10607,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "bin": { - "mustache": "bin/mustache" - } - }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -11664,11 +10626,6 @@ "node": ">= 0.6" } }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" - }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -11699,30 +10656,6 @@ "node": ">= 10.13" } }, - "node_modules/node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "deprecated": "Use your platform's native DOMException instead", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -11742,17 +10675,6 @@ } } }, - "node_modules/node-fetch-h2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", - "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", - "dependencies": { - "http2-client": "^1.2.5" - }, - "engines": { - "node": "4.x || >=6.0.0" - } - }, "node_modules/node-fetch/node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -11777,12 +10699,6 @@ "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==" }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "peer": true - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -14316,111 +13232,6 @@ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", "integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==" }, - "node_modules/oas": { - "version": "20.11.0", - "resolved": "https://registry.npmjs.org/oas/-/oas-20.11.0.tgz", - "integrity": "sha512-Eio2qil8z86PD8KJTdyGPN7hbcF3dV0gc5B6mkSQgL3MLMVFE/XyVAmq/9BRh51zkIXOPmZpSIF3nStADbnkHA==", - "dependencies": { - "@readme/json-schema-ref-parser": "^1.2.0", - "@types/json-schema": "^7.0.11", - "json-schema-merge-allof": "^0.8.1", - "jsonpath": "^1.1.1", - "jsonpointer": "^5.0.0", - "memoizee": "^0.4.14", - "oas-normalize": "^8.3.0", - "openapi-types": "^12.1.0", - "path-to-regexp": "^6.2.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/oas-kit-common": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", - "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", - "dependencies": { - "fast-safe-stringify": "^2.0.7" - } - }, - "node_modules/oas-linter": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz", - "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==", - "dependencies": { - "@exodus/schemasafe": "^1.0.0-rc.2", - "should": "^13.2.1", - "yaml": "^1.10.0" - }, - "funding": { - "url": "https://github.com/Mermade/oas-kit?sponsor=1" - } - }, - "node_modules/oas-normalize": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/oas-normalize/-/oas-normalize-8.4.1.tgz", - "integrity": "sha512-cGODg+AntZteJRHBiYDWKtcO2svWGMXuFWYu2I8b4hOrNiwB3hgDs/ScX3O9mYm6RpLsUIftt6rDHGc8eYG8aA==", - "dependencies": { - "@readme/openapi-parser": "^2.5.0", - "@readme/postman-to-openapi": "^4.1.0", - "js-yaml": "^4.1.0", - "node-fetch": "^2.6.1", - "openapi-types": "^12.1.0", - "swagger2openapi": "^7.0.8" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/oas-resolver": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz", - "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==", - "dependencies": { - "node-fetch-h2": "^2.3.0", - "oas-kit-common": "^1.0.8", - "reftools": "^1.1.9", - "yaml": "^1.10.0", - "yargs": "^17.0.1" - }, - "bin": { - "resolve": "resolve.js" - }, - "funding": { - "url": "https://github.com/Mermade/oas-kit?sponsor=1" - } - }, - "node_modules/oas-schema-walker": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", - "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", - "funding": { - "url": "https://github.com/Mermade/oas-kit?sponsor=1" - } - }, - "node_modules/oas-validator": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz", - "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==", - "dependencies": { - "call-me-maybe": "^1.0.1", - "oas-kit-common": "^1.0.8", - "oas-linter": "^3.2.2", - "oas-resolver": "^2.5.6", - "oas-schema-walker": "^1.1.5", - "reftools": "^1.1.9", - "should": "^13.2.1", - "yaml": "^1.10.0" - }, - "funding": { - "url": "https://github.com/Mermade/oas-kit?sponsor=1" - } - }, - "node_modules/oas/node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==" - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -14642,11 +13453,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/openapi-types": { - "version": "12.1.3", - "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", - "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==" - }, "node_modules/optimism": { "version": "0.18.1", "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.18.1.tgz", @@ -14871,15 +13677,6 @@ "node": ">= 0.8" } }, - "node_modules/password-prompt": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/password-prompt/-/password-prompt-1.1.3.tgz", - "integrity": "sha512-HkrjG2aJlvF0t2BMH0e2LB/EHf3Lcq3fNMzy4GYHcQblAvOl+QQji1Lx7WRBMqpVK8p+KR7bCg7oqAMXtdgqyw==", - "dependencies": { - "ansi-escapes": "^4.3.2", - "cross-spawn": "^7.0.3" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -14942,12 +13739,6 @@ "node": ">=8" } }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "peer": true - }, "node_modules/picomatch": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", @@ -14959,79 +13750,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "peer": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "peer": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "peer": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "peer": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "peer": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "peer": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/pkg-up": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", @@ -15251,19 +13969,6 @@ "lodash": "^4.17.14" } }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "peer": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -15346,14 +14051,6 @@ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, - "node_modules/queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "dependencies": { - "inherits": "~2.0.3" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -15562,14 +14259,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/reftools": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", - "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==", - "funding": { - "url": "https://github.com/Mermade/oas-kit?sponsor=1" - } - }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -15606,14 +14295,6 @@ } } }, - "node_modules/remove-undefined-objects": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/remove-undefined-objects/-/remove-undefined-objects-2.0.2.tgz", - "integrity": "sha512-b6x4MUtR4YBW1aCoGx3tE4mA2PFjiXSmtSdNmLexQzUdZa4ybnJAItXLKpkcVgCUJIzJtk2DFG402sMSEMlonQ==", - "engines": { - "node": ">=14" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -16262,54 +14943,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/should": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", - "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", - "dependencies": { - "should-equal": "^2.0.0", - "should-format": "^3.0.3", - "should-type": "^1.4.0", - "should-type-adaptors": "^1.0.1", - "should-util": "^1.0.0" - } - }, - "node_modules/should-equal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", - "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", - "dependencies": { - "should-type": "^1.4.0" - } - }, - "node_modules/should-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", - "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", - "dependencies": { - "should-type": "^1.3.0", - "should-type-adaptors": "^1.0.1" - } - }, - "node_modules/should-type": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", - "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==" - }, - "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==", - "dependencies": { - "should-type": "^1.3.0", - "should-util": "^1.0.0" - } - }, - "node_modules/should-util": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", - "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==" - }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -16430,12 +15063,6 @@ "node": ">=8" } }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "peer": true - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -16711,11 +15338,6 @@ "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-1.0.0.tgz", "integrity": "sha512-lgxErLl/7A5+vgIIXsh9MbeukOaCb2axgQ+bKCdIE+ibNT4XNYGNCR1qFEGq6F+YDASXK3Fh/c5FgtZchFolxw==" }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -16963,15 +15585,6 @@ "node": ">=0.10.0" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -17009,32 +15622,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/swagger2openapi": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", - "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==", - "dependencies": { - "call-me-maybe": "^1.0.1", - "node-fetch": "^2.6.1", - "node-fetch-h2": "^2.3.0", - "node-readfiles": "^0.2.0", - "oas-kit-common": "^1.0.8", - "oas-resolver": "^2.5.6", - "oas-schema-walker": "^1.1.5", - "oas-validator": "^5.0.8", - "reftools": "^1.1.9", - "yaml": "^1.10.0", - "yargs": "^17.0.1" - }, - "bin": { - "boast": "boast.js", - "oas-validate": "oas-validate.js", - "swagger2openapi": "swagger2openapi.js" - }, - "funding": { - "url": "https://github.com/Mermade/oas-kit?sponsor=1" - } - }, "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", @@ -17100,18 +15687,6 @@ "readable-stream": "2 || 3" } }, - "node_modules/timers-ext": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", - "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", - "dependencies": { - "es5-ext": "^0.10.64", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/tiny-warning": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", @@ -17216,11 +15791,6 @@ "node": ">= 14.0.0" } }, - "node_modules/ts-algebra": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.2.2.tgz", - "integrity": "sha512-kloPhf1hq3JbCPOTYoOWDKxebWjNb2o/LKnNfkWhxVVisFFmMJPPdJeGoGmM+iRLyoXAR61e08Pb+vUXINg8aA==" - }, "node_modules/ts-api-utils": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", @@ -17244,56 +15814,6 @@ "node": ">=8" } }, - "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==", - "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/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -17359,11 +15879,6 @@ "node": ">=6" } }, - "node_modules/type": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", - "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -17643,38 +16158,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/validate.io-array": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", - "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==" - }, - "node_modules/validate.io-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", - "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==" - }, - "node_modules/validate.io-integer": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz", - "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", - "dependencies": { - "validate.io-number": "^1.0.3" - } - }, - "node_modules/validate.io-integer-array": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz", - "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", - "dependencies": { - "validate.io-array": "^1.0.3", - "validate.io-integer": "^1.0.4" - } - }, - "node_modules/validate.io-number": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", - "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==" - }, "node_modules/validator": { "version": "13.12.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", @@ -17718,14 +16201,6 @@ "defaults": "^1.0.3" } }, - "node_modules/web-streams-polyfill": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", - "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", - "engines": { - "node": ">= 14" - } - }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -17756,11 +16231,6 @@ "node": ">=0.10.0" } }, - "node_modules/whatwg-fetch": { - "version": "3.6.20", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", - "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" - }, "node_modules/whatwg-mimetype": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", @@ -18039,14 +16509,6 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" - } - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/api/package.json b/api/package.json index fca180401..87a0cb5cf 100644 --- a/api/package.json +++ b/api/package.json @@ -25,10 +25,10 @@ "homepage": "https://github.com/contentstack/migration-v2.git#readme", "dependencies": { "@contentstack/cli": "1.41.0", - "@contentstack/cli-utilities": "^1.12.0", + "@contentstack/cli-utilities": "^1.14.2", "@contentstack/json-rte-serializer": "^2.0.7", "@contentstack/marketplace-sdk": "^1.4.0", - "axios": "^1.11.0", + "axios": "^1.12.2", "chokidar": "^3.6.0", "cors": "^2.8.5", "dotenv": "^16.3.1", diff --git a/api/src/controllers/auth.controller.ts b/api/src/controllers/auth.controller.ts index e2ecb530f..fa7fcbdba 100644 --- a/api/src/controllers/auth.controller.ts +++ b/api/src/controllers/auth.controller.ts @@ -34,8 +34,96 @@ const saveOAuthToken = async (req: Request, res: Response) => { res.status(HTTP_CODES.OK).json({ message: "Token received successfully." }); }; + +/** + * Handles the request for getting the app configuration. + * + * @param req - The request object. + * @param res - The response object. + */ +export const getAppConfigHandler = async (req: Request, res: Response): Promise => { + try { + const appConfig = await authService.getAppData(); + res.status(200).json(appConfig); + + } catch (error: any) { + console.error('Error in getAppConfig controller:', error); + + if (error?.message?.includes('app.json file not found')) { + res.status(404).json({ + error: 'SSO configuration not found', + message: 'app.json file does not exist' + }); + return; + } + + if (error?.message?.includes('Invalid JSON format')) { + res.status(400).json({ + error: 'Invalid SSO configuration', + message: 'app.json contains invalid JSON' + }); + return; + } + + res.status(500).json({ + error: 'Server error', + message: 'Unable to read SSO configuration' + }); + } +}; + +/** + * Handles the request for checking the SSO authentication status. + * + * @param req - The request object. + * @param res - The response object. + */ +export const getSSOAuthStatus = async (req: Request, res: Response): Promise => { + try { + const { userId } = req.params; + + if (!userId) { + res.status(400).json({ + error: 'Missing user ID', + message: 'User ID parameter is required' + }); + return; + } + + const authStatus = await authService.checkSSOAuthStatus(userId); + + res.status(200).json(authStatus); + + } catch (error: any) { + console.error('Error in getSSOAuthStatus controller:', error); + + if (error?.message?.includes('User not found in authentication records')) { + res.status(404).json({ + error: 'User not found', + message: 'User not found in authentication records' + }); + return; + } + + if (error?.message?.includes('SSO authentication not completed')) { + res.status(202).json({ + authenticated: false, + message: 'SSO authentication not completed' + }); + return; + } + + res.status(500).json({ + error: 'Server error', + message: 'Unable to check SSO authentication status' + }); + } +}; + export const authController = { login, RequestSms, saveOAuthToken, + getAppConfigHandler, + getSSOAuthStatus }; diff --git a/api/src/models/authentication.ts b/api/src/models/authentication.ts index fcbefe733..48dc209f2 100644 --- a/api/src/models/authentication.ts +++ b/api/src/models/authentication.ts @@ -13,6 +13,7 @@ interface AuthenticationDocument { authtoken: string; created_at: string; updated_at: string; + access_token: string; }[]; } diff --git a/api/src/models/types.ts b/api/src/models/types.ts index 5cd0c1ed8..a8409efcf 100644 --- a/api/src/models/types.ts +++ b/api/src/models/types.ts @@ -19,6 +19,7 @@ export interface User { export interface AppTokenPayload { region: string; user_id: string; + is_sso: boolean; } /** diff --git a/api/src/routes/auth.routes.ts b/api/src/routes/auth.routes.ts index 131c26423..cc2f1077a 100644 --- a/api/src/routes/auth.routes.ts +++ b/api/src/routes/auth.routes.ts @@ -50,5 +50,19 @@ router.get( asyncRouter(authController.saveOAuthToken) ); +/** + * @route GET /api/app-config + * @desc Get app configuration from app.json + * @access Public + */ +router.get('/app-config', authController.getAppConfigHandler); + +/** + * @route GET /v2/auth/sso-status/:userId + * @desc Check SSO authentication status for a user + * @param userId - The user ID to check authentication status for + * @access Public + */ +router.get('/sso-status/:userId', authController.getSSOAuthStatus); export default router; diff --git a/api/src/services/auth.service.ts b/api/src/services/auth.service.ts index 90bda5627..6c087c01a 100644 --- a/api/src/services/auth.service.ts +++ b/api/src/services/auth.service.ts @@ -83,6 +83,7 @@ const login = async (req: Request): Promise => { const appTokenPayload: AppTokenPayload = { region: userData?.region, user_id: res?.data?.user.uid, + is_sso: false, }; // Saving auth info in the DB @@ -184,7 +185,7 @@ const getAppConfig = () => { * Receives the final code to generate token, fetches user details, * and saves/updates the user in the database. */ -const saveOAuthToken = async (req: Request): Promise => { +const saveOAuthToken = async (req: Request): Promise => { const { code, region } = req.query; if (!code || !region) { @@ -241,8 +242,10 @@ const saveOAuthToken = async (req: Request): Promise => { const appTokenPayload = { region: region as string, user_id: csUser.uid, + is_sso: true, }; + const appToken = generateToken(appTokenPayload); await AuthenticationModel.read(); const userIndex = AuthenticationModel.chain.get("users").findIndex({ user_id: csUser.uid }).value(); @@ -263,6 +266,13 @@ const saveOAuthToken = async (req: Request): Promise => { }); logger.info(`Token and user data for ${csUser.email} (Region: ${region}) saved successfully.`); + return { + data: { + message: HTTP_TEXTS.SUCCESS_LOGIN, + app_token: appToken, + }, + status: HTTP_CODES.OK, + } } catch (error) { logger.error("An error occurred during token exchange and save:", error); @@ -344,9 +354,90 @@ export const refreshOAuthToken = async (userId: string): Promise => { } }; +/** + * Check app.json file for SSO configuration. + * @returns The app configuration + */ +export const getAppData = async () => { + try { + const appConfigPath = path.join(process.cwd(), '..','app.json'); + + if (!fs.existsSync(appConfigPath)) { + throw new Error('app.json file not found - SSO configuration required'); + } + + const appConfigData = fs.readFileSync(appConfigPath, 'utf8'); + const appConfig: any = JSON.parse(appConfigData); + + return appConfig; + + } catch (error: any) { + if (error?.message?.includes('app.json file not found')) { + throw error; + } + if (error instanceof SyntaxError) { + throw new Error('Invalid JSON format in app.json file'); + } + throw new Error(`Failed to read app configuration: ${error?.message}`); + } +} + +/** + * Checks the status of the SSO authentication. + * @param userId - The user ID + * @returns The authentication status + */ +export const checkSSOAuthStatus = async (userId: string) => { + try { + await AuthenticationModel.read(); + const userRecord = AuthenticationModel.chain.get("users").find({ user_id: userId }).value(); + + if (!userRecord || !userRecord.access_token) { + throw new Error('SSO authentication not completed'); + } + + // Only consider tokens created in the last 10 minutes as "fresh" + const tokenAge = new Date()?.getTime() - new Date(userRecord.updated_at)?.getTime(); + const maxTokenAge = 10 * 60 * 1000; // 10 minutes in milliseconds + + if (tokenAge > maxTokenAge) { + throw new Error('SSO authentication not completed'); + } + + // Token is fresh, proceed with authentication + const appTokenPayload = { + region: userRecord.region, + user_id: userRecord.user_id, + is_sso: true, + }; + + const appToken = generateToken(appTokenPayload); + + return { + authenticated: true, + message: 'SSO authentication successful', + app_token: appToken, + user: { + email: userRecord.email, + uid: userRecord.user_id, + region: userRecord.region, + organization_uid: userRecord.organization_uid + } + }; + + } catch (error: any) { + if (error.message.includes('SSO authentication not completed')) { + throw error; + } + throw new Error(`Failed to check SSO authentication status: ${error.message}`); + } +}; + export const authService = { login, requestSms, saveOAuthToken, refreshOAuthToken, + getAppData, + checkSSOAuthStatus }; \ No newline at end of file diff --git a/api/src/services/contentMapper.service.ts b/api/src/services/contentMapper.service.ts index bccc9cba3..42706adfd 100644 --- a/api/src/services/contentMapper.service.ts +++ b/api/src/services/contentMapper.service.ts @@ -15,7 +15,7 @@ import { import logger from "../utils/logger.js"; import { config } from "../config/index.js"; import https from "../utils/https.utils.js"; -import getAuthtoken from "../utils/auth.utils.js"; +import getAuthtoken, { getAccessToken } from "../utils/auth.utils.js"; import getProjectUtil from "../utils/get-project.utils.js"; import fetchAllPaginatedData from "../utils/pagination.utils.js"; import ProjectModelLowdb from "../models/project-lowdb.js"; @@ -315,26 +315,29 @@ const getExistingContentTypes = async (req: Request) => { const { token_payload } = req.body; - const authtoken = await getAuthtoken( - token_payload?.region, - token_payload?.user_id - ); await ProjectModelLowdb.read(); const project = ProjectModelLowdb.chain .get("projects") .find({ id: projectId }) .value(); - const stackId = project?.destination_stack_id; const baseUrl = `${config.CS_API[ token_payload?.region as keyof typeof config.CS_API ]!}/content_types`; - - const headers = { - api_key: stackId, - authtoken, - }; + let headers: any = { + api_key: projectId?.destination_stack_id, + } + if(token_payload?.is_sso) { + const accessToken = await getAccessToken(token_payload?.region, token_payload?.user_id); + headers.authorization = `Bearer ${accessToken}`; + } else if (token_payload?.is_sso === false) { + const authtoken = await getAuthtoken( + token_payload?.region, + token_payload?.user_id + ); + headers.authtoken = authtoken; + } try { // Step 1: Fetch the updated list of all content types diff --git a/api/src/services/globalField.service.ts b/api/src/services/globalField.service.ts index 70611fc0d..ecc7264eb 100644 --- a/api/src/services/globalField.service.ts +++ b/api/src/services/globalField.service.ts @@ -1,11 +1,11 @@ import { getLogMessage, safePromise } from "../utils/index.js"; -import getAuthtoken from "../utils/auth.utils.js"; import { config } from "../config/index.js"; import https from "../utils/https.utils.js"; import fs from 'fs'; import { HTTP_TEXTS, MIGRATION_DATA_CONFIG} from "../constants/index.js"; import path from "path"; import logger from "../utils/logger.js"; +import AuthenticationModel from "../models/authentication.js"; const { GLOBAL_FIELDS_FILE_NAME, @@ -25,7 +25,26 @@ const createGlobalField = async ({ current_test_stack_id?: string; }) => { const srcFun = "createGlobalField"; - const authtoken = await getAuthtoken(region, user_id); + let headers: any = { + api_key : stackId, + } + let authtoken = ""; + await AuthenticationModel.read(); + const userIndex = AuthenticationModel.chain + .get('users') + .findIndex({ region, user_id: user_id }) + .value(); + + const userData = AuthenticationModel?.data?.users[userIndex]; + if(userData?.access_token) { + authtoken = `Bearer ${userData?.access_token}`; + headers.authorization = authtoken; + } else if(userData?.authtoken) { + authtoken = userData?.authtoken; + headers.authtoken = authtoken; + }else{ + throw new Error("No authentication token found"); + } try { const [err, res] = await safePromise( https({ @@ -33,10 +52,7 @@ const createGlobalField = async ({ url: `${config.CS_API[ region as keyof typeof config.CS_API ]!}/global_fields?include_global_field_schema=true`, - headers: { - api_key : stackId, - authtoken, - }, + headers: headers, }) ); const globalSave = path.join(MIGRATION_DATA_CONFIG.DATA, current_test_stack_id ?? '', GLOBAL_FIELDS_DIR_NAME); diff --git a/api/src/services/marketplace.service.ts b/api/src/services/marketplace.service.ts index e7f5301a1..056eaf605 100644 --- a/api/src/services/marketplace.service.ts +++ b/api/src/services/marketplace.service.ts @@ -1,9 +1,9 @@ import path from 'path'; import fs from 'fs'; -import getAuthtoken from "../utils/auth.utils.js"; import { MIGRATION_DATA_CONFIG, KEYTOREMOVE } from '../constants/index.js'; import { getAppManifestAndAppConfig } from '../utils/market-app.utils.js'; import { v4 as uuidv4 } from "uuid"; +import AuthenticationModel from "../models/authentication.js"; const { @@ -51,7 +51,22 @@ const writeManifestFile = async ({ destinationStackId, appManifest }: any) => { const createAppManifest = async ({ destinationStackId, region, userId, orgId }: any) => { - const authtoken = await getAuthtoken(region, userId); + let authtoken = ""; + await AuthenticationModel.read(); + const userIndex = AuthenticationModel.chain + .get('users') + .findIndex({ region, user_id: userId }) + .value(); + + const userData = AuthenticationModel?.data?.users[userIndex]; + if(userData?.access_token) { + + authtoken = `Bearer ${userData?.access_token}`; + } else if(userData?.authtoken) { + authtoken = userData?.authtoken; + }else{ + throw new Error("No authentication token found"); + } const marketPlacePath = path.join(MIGRATION_DATA_CONFIG.DATA, destinationStackId, EXTENSIONS_MAPPER_DIR_NAME); const AppMapper: any = await fs.promises.readFile(marketPlacePath, "utf-8").catch(async () => { }); if (AppMapper !== undefined) { diff --git a/api/src/services/migration.service.ts b/api/src/services/migration.service.ts index bb07b5775..027daf52d 100644 --- a/api/src/services/migration.service.ts +++ b/api/src/services/migration.service.ts @@ -5,7 +5,7 @@ import { config } from '../config/index.js'; import { safePromise, getLogMessage } from '../utils/index.js'; import https from '../utils/https.utils.js'; import { LoginServiceType } from '../models/types.js'; -import getAuthtoken from '../utils/auth.utils.js'; +import getAuthtoken, { getAccessToken } from '../utils/auth.utils.js'; import logger from '../utils/logger.js'; import { HTTP_TEXTS, @@ -52,11 +52,21 @@ const createTestStack = async (req: Request): Promise => { const testStackName = `${name}-Test`; try { + let headers: any = { + organization_uid: orgId, + } + if(token_payload?.is_sso) { + const accessToken = await getAccessToken(token_payload?.region, token_payload?.user_id); + headers.authorization = `Bearer ${accessToken}`; + } else if (token_payload?.is_sso === false) { const authtoken = await getAuthtoken( token_payload?.region, token_payload?.user_id ); - + headers.authtoken = authtoken; + } else { + throw new BadRequestError("No valid authentication token found or mismatch in is_sso flag"); + } await ProjectModelLowdb.read(); const projectData: any = ProjectModelLowdb.chain .get('projects') @@ -74,10 +84,7 @@ const createTestStack = async (req: Request): Promise => { url: `${config.CS_API[ token_payload?.region as keyof typeof config.CS_API ]!}/stacks`, - headers: { - organization_uid: orgId, - authtoken, - }, + headers: headers, data: { stack: { name: newName, @@ -155,10 +162,21 @@ const deleteTestStack = async (req: Request): Promise => { const { token_payload, stack_key } = req.body; try { + let headers: any = { + api_key: stack_key, + } + if(token_payload?.is_sso) { + const accessToken = await getAccessToken(token_payload?.region, token_payload?.user_id); + headers.authorization = `Bearer ${accessToken}`; + } else if (token_payload?.is_sso === false) { const authtoken = await getAuthtoken( - token_payload?.region, - token_payload?.user_id - ); + token_payload?.region, + token_payload?.user_id + ); + headers.authtoken = authtoken; + } else { + throw new BadRequestError("No valid authentication token found or mismatch in is_sso flag"); + } const [err, res] = await safePromise( https({ @@ -166,10 +184,7 @@ const deleteTestStack = async (req: Request): Promise => { url: `${config.CS_API[ token_payload?.region as keyof typeof config.CS_API ]!}/stacks`, - headers: { - api_key: stack_key, - authtoken, - }, + headers: headers, }) ); diff --git a/api/src/services/org.service.ts b/api/src/services/org.service.ts index 72fa72eaf..39e40a557 100644 --- a/api/src/services/org.service.ts +++ b/api/src/services/org.service.ts @@ -3,7 +3,7 @@ import { config } from "../config/index.js"; import { safePromise, getLogMessage } from "../utils/index.js"; import https from "../utils/https.utils.js"; import { LoginServiceType } from "../models/types.js"; -import getAuthtoken from "../utils/auth.utils.js"; +import getAuthtoken, { getAccessToken } from "../utils/auth.utils.js"; import logger from "../utils/logger.js"; import { HTTP_TEXTS, HTTP_CODES } from "../constants/index.js"; import { ExceptionFunction } from "../utils/custom-errors.utils.js"; @@ -22,10 +22,22 @@ const getAllStacks = async (req: Request): Promise => { const search: string = req?.params?.searchText?.toLowerCase(); try { - const authtoken = await getAuthtoken( - token_payload?.region, - token_payload?.user_id - ); + let headers: any = { + organization_uid: orgId, + "Content-Type": "application/json", + }; + if (token_payload?.is_sso) { + const accessToken = await getAccessToken(token_payload?.region, token_payload?.user_id); + headers.authorization = `Bearer ${accessToken}`; + } else if (token_payload?.is_sso === false) { + const authtoken = await getAuthtoken( + token_payload?.region, + token_payload?.user_id + ); + headers.authtoken = authtoken; + } else { + throw new BadRequestError("No valid authentication token found or mismatch in is_sso flag"); + } const [err, res] = await safePromise( https({ @@ -33,10 +45,7 @@ const getAllStacks = async (req: Request): Promise => { url: `${config.CS_API[ token_payload?.region as keyof typeof config.CS_API ]!}/stacks`, - headers: { - organization_uid: orgId, - authtoken, - }, + headers: headers, }) ); if (err) { @@ -109,10 +118,22 @@ const createStack = async (req: Request): Promise => { const { token_payload, name, description, master_locale } = req.body; try { - const authtoken = await getAuthtoken( - token_payload?.region, - token_payload?.user_id - ); + let headers: any = { + organization_uid: orgId, + "Content-Type": "application/json", + }; + if (token_payload?.is_sso) { + const accessToken = await getAccessToken(token_payload?.region, token_payload?.user_id); + headers.authorization = `Bearer ${accessToken}`; + } else if (token_payload?.is_sso === false) { + const authtoken = await getAuthtoken( + token_payload?.region, + token_payload?.user_id + ); + headers.authtoken = authtoken; + } else { + throw new BadRequestError("No valid authentication token found or mismatch in is_sso flag"); + } const [err, res] = await safePromise( https({ @@ -120,10 +141,7 @@ const createStack = async (req: Request): Promise => { url: `${config.CS_API[ token_payload?.region as keyof typeof config.CS_API ]!}/stacks`, - headers: { - organization_uid: orgId, - authtoken, - }, + headers: headers, data: { stack: { name, @@ -182,10 +200,18 @@ const getLocales = async (req: Request): Promise => { const { token_payload } = req.body; try { - const authtoken = await getAuthtoken( - token_payload?.region, - token_payload?.user_id - ); + let headers: any = { + "Content-Type": "application/json", + }; + if (token_payload?.is_sso) { + const accessToken = await getAccessToken(token_payload?.region, token_payload?.user_id); + headers.authorization = `Bearer ${accessToken}`; + } else if (token_payload?.is_sso === false) { + const authtoken = await getAuthtoken(token_payload?.region, token_payload?.user_id); + headers.authtoken = authtoken; + } else { + throw new BadRequestError("No valid authentication token found or mismatch in is_sso flag"); + } const [err, res] = await safePromise( https({ @@ -193,9 +219,7 @@ const getLocales = async (req: Request): Promise => { url: `${config.CS_API[ token_payload?.region as keyof typeof config.CS_API ]!}/locales?include_all=true`, - headers: { - authtoken, - }, + headers: headers, }) ); @@ -242,10 +266,22 @@ const getStackStatus = async (req: Request) => { const { token_payload, stack_api_key } = req.body; const srcFunc = "getStackStatus"; - const authtoken = await getAuthtoken( + let headers: any = { + organization_uid: orgId, + "Content-Type": "application/json", + }; + if (token_payload?.is_sso) { + const accessToken = await getAccessToken(token_payload?.region, token_payload?.user_id); + headers.authorization = `Bearer ${accessToken}`; + } else if (token_payload?.is_sso === false) { + const authtoken = await getAuthtoken( token_payload?.region, token_payload?.user_id - ); + ); + headers.authtoken = authtoken; + } else { + throw new BadRequestError("No valid authentication token found or mismatch in is_sso flag"); + } try { const [stackErr, stackRes] = await safePromise( @@ -254,10 +290,7 @@ const getStackStatus = async (req: Request) => { url: `${config.CS_API[ token_payload?.region as keyof typeof config.CS_API ]!}/stacks`, - headers: { - organization_uid: orgId, - authtoken, - }, + headers: headers, }) ); @@ -282,10 +315,7 @@ const getStackStatus = async (req: Request) => { url: `${config.CS_API[ token_payload?.region as keyof typeof config.CS_API ]!}/content_types?skip=0&limit=1&include_count=true`, - headers: { - api_key: stack_api_key, - authtoken, - }, + headers: headers, }) ); @@ -330,10 +360,16 @@ const getStackLocale = async (req: Request) => { const { token_payload, stack_api_key } = req.body; const srcFunc = "getStackStatus"; - const authtoken = await getAuthtoken( - token_payload?.region, - token_payload?.user_id - ); + let headers: any = { + api_key: stack_api_key, + } + if(token_payload?.is_sso) { + const accessToken = await getAccessToken(token_payload?.region, token_payload?.user_id); + headers.authorization = `Bearer ${accessToken}`; + } else if (token_payload?.is_sso === false) { + const authtoken = await getAuthtoken(token_payload?.region, token_payload?.user_id); + headers.authtoken = authtoken; + } try { const [stackErr, stackRes] = await safePromise( @@ -342,10 +378,7 @@ const getStackLocale = async (req: Request) => { url: `${config.CS_API[ token_payload?.region as keyof typeof config.CS_API ]!}/locales`, - headers: { - api_key: stack_api_key, - authtoken, - }, + headers: headers, }) ); @@ -388,10 +421,15 @@ const getOrgDetails = async (req: Request) => { const { token_payload } = req.body; const srcFunc = "getOrgDetails"; - const authtoken = await getAuthtoken( - token_payload?.region, - token_payload?.user_id - ); + let headers: any = {} + if(token_payload?.is_sso) { + const accessToken = await getAccessToken(token_payload?.region, token_payload?.user_id); + headers.authorization = `Bearer ${accessToken}`; + } else if (token_payload?.is_sso === false) { + const authtoken = await getAuthtoken(token_payload?.region, token_payload?.user_id); + headers.authtoken = authtoken; + } + try { const [stackErr, stackRes] = await safePromise( @@ -400,9 +438,7 @@ const getOrgDetails = async (req: Request) => { url: `${config.CS_API[ token_payload?.region as keyof typeof config.CS_API ]!}/organizations/${orgId}?include_plan=true`, - headers: { - authtoken, - }, + headers: headers, }) ); diff --git a/api/src/services/projects.service.ts b/api/src/services/projects.service.ts index 05d625e8e..d766e3f05 100644 --- a/api/src/services/projects.service.ts +++ b/api/src/services/projects.service.ts @@ -16,10 +16,11 @@ import { } from "../constants/index.js"; import { config } from "../config/index.js"; import { getLogMessage, isEmpty, safePromise } from "../utils/index.js"; -import getAuthtoken from "../utils/auth.utils.js"; +import getAuthtoken, { getAccessToken } from "../utils/auth.utils.js"; import https from "../utils/https.utils.js"; import getProjectUtil from "../utils/get-project.utils.js"; import logger from "../utils/logger.js"; +import AuthenticationModel from "../models/authentication.js"; // import { contentMapperService } from "./contentMapper.service.js"; import { v4 as uuidv4 } from "uuid"; @@ -88,7 +89,20 @@ const createProject = async (req: Request) => { const { name, description } = req.body; const decodedToken = req.body.token_payload; const { user_id = "", region = "" } = decodedToken; + let isSSO = false; const srcFunc = "createProject"; + await AuthenticationModel.read(); + const userIndex = AuthenticationModel.chain + .get("users") + .findIndex({ + user_id: user_id, + region: region, + }) + .value(); + const userRecord = AuthenticationModel.data.users[userIndex]; + if(userRecord?.access_token){ + isSSO = true; + } const projectData = { id: uuidv4(), region, @@ -129,6 +143,7 @@ const createProject = async (req: Request) => { isMigrationStarted: false, isMigrationCompleted:false, migration_execution:false, + isSSO: isSSO, }; try { @@ -588,11 +603,17 @@ const updateDestinationStack = async (req: Request) => { )) as number; const project = ProjectModelLowdb.data.projects[projectIndex]; + const headers :any = { + organization_uid: orgId, + } + if (project?.isSSO) { + const accessToken = await getAccessToken(token_payload?.region, token_payload?.user_id); + headers.authorization = `Bearer ${accessToken}`; + }else{ + headers.authtoken = await getAuthtoken(token_payload?.region, token_payload?.user_id); + } + - const authtoken = await getAuthtoken( - token_payload?.region, - token_payload?.user_id - ); if ( project.status === NEW_PROJECT_STATUS[4] || @@ -625,10 +646,7 @@ const updateDestinationStack = async (req: Request) => { url: `${config.CS_API[ token_payload?.region as keyof typeof config.CS_API ]!}/stacks`, - headers: { - organization_uid: orgId, - authtoken, - }, + headers: headers, }) ); diff --git a/api/src/services/runCli.service.ts b/api/src/services/runCli.service.ts index 956e01834..8568d829e 100644 --- a/api/src/services/runCli.service.ts +++ b/api/src/services/runCli.service.ts @@ -16,7 +16,7 @@ interface TestStack { stackUid: string; isMigrated: boolean; } -import utilitiesHandler from '@contentstack/cli-utilities'; +import { setBasicAuthConfig, setOAuthConfig } from '../utils/config-handler.util.js'; /** * Determines log level based on message content without removing ANSI codes @@ -150,27 +150,29 @@ export const runCli = async ( const regionPresent = CS_REGIONS.find((item) => item === rg) ?? 'NA'.replace(/_/g, '-'); const regionCli = regionPresent.replace(/_/g, '-'); - // Fetch user authentication data await AuthenticationModel.read(); const userData = AuthenticationModel.chain .get('users') .find({ region: regionPresent, user_id }) .value(); - - // Configure CLI with region settings await runCommand( 'npx', ['@contentstack/cli', 'config:set:region', `${regionCli}`], transformePath ); // Pass the log file path here - // Set up authentication configuration for CLI - utilitiesHandler.configHandler.set('authtoken', userData.authtoken); - utilitiesHandler.configHandler.set('email', userData.email); - utilitiesHandler.configHandler.set('authorisationType', 'BASIC'); + if(userData?.access_token){ + setOAuthConfig(userData); + + }else if(userData?.authtoken){ + setBasicAuthConfig(userData); + }else { + throw new Error("No authentication token found"); + } + - if (userData?.authtoken && stack_uid) { + if (userData?.authtoken && stack_uid || userData?.access_token && stack_uid) { // Set up paths for backup and source data const { BACKUP_DATA, diff --git a/api/src/services/taxonomy.service.ts b/api/src/services/taxonomy.service.ts index c2215fde5..0b43f2bab 100644 --- a/api/src/services/taxonomy.service.ts +++ b/api/src/services/taxonomy.service.ts @@ -6,6 +6,7 @@ import fs from 'fs'; import { HTTP_TEXTS, MIGRATION_DATA_CONFIG } from "../constants/index.js"; import path from "path"; import logger from "../utils/logger.js"; +import AuthenticationModel from "../models/authentication.js"; const { TAXONOMIES_DIR_NAME, @@ -142,21 +143,35 @@ const createTaxonomy = async ({stackId,region,userId,current_test_stack_id} : const srcFun = "createTaxonomy"; const taxonomiesPath = path.join(MIGRATION_DATA_CONFIG.DATA, current_test_stack_id, TAXONOMIES_DIR_NAME); await fs.promises.mkdir(taxonomiesPath, { recursive: true }); + let headers: any = { + api_key : stackId, + } + let authtoken = ""; + await AuthenticationModel.read(); + const userIndex = AuthenticationModel.chain + .get('users') + .findIndex({ region, user_id: userId }) + .value(); + + const userData = AuthenticationModel?.data?.users[userIndex]; + if(userData?.access_token) { + + authtoken = `Bearer ${userData?.access_token}`; + headers.authorization = authtoken; + } else if(userData?.authtoken) { + authtoken = userData?.authtoken; + headers.authtoken = authtoken; + }else{ + throw new Error("No authentication token found"); + } try { - const authtoken = await getAuthtoken( - region, - userId - ); const [err, res] = await safePromise( https({ method: "GET", url: `${config.CS_API[ region as keyof typeof config.CS_API ]!}/taxonomies?include_terms_count=true&include_count=true`, - headers: { - api_key : stackId, - authtoken, - }, + headers: headers, }) ); if (err) { diff --git a/api/src/services/user.service.ts b/api/src/services/user.service.ts index 86f1d336c..0c3463103 100644 --- a/api/src/services/user.service.ts +++ b/api/src/services/user.service.ts @@ -34,16 +34,25 @@ const getUserProfile = async (req: Request): Promise => { if (userIndex < 0) throw new BadRequestError(HTTP_TEXTS.NO_CS_USER); + const userRecord = AuthenticationModel.data.users[userIndex]; + let headers: any = { + "Content-Type": "application/json", + }; + if (appTokenPayload?.is_sso) { + headers.authorization = `Bearer ${userRecord.access_token}`; + } else if (appTokenPayload?.is_sso === false) { + headers.authtoken = userRecord.authtoken; + } else { + throw new BadRequestError("No valid authentication token found or mismatch in is_sso flag"); + } + const [err, res] = await safePromise( https({ method: "GET", url: `${config.CS_API[ appTokenPayload?.region as keyof typeof config.CS_API ]!}/user?include_orgs_roles=true`, - headers: { - "Content-Type": "application/json", - authtoken: AuthenticationModel.data.users[userIndex]?.authtoken, - }, + headers: headers, }) ); diff --git a/api/src/utils/auth.utils.ts b/api/src/utils/auth.utils.ts index 30df20752..e3d87d616 100644 --- a/api/src/utils/auth.utils.ts +++ b/api/src/utils/auth.utils.ts @@ -24,3 +24,21 @@ export default async (region: string, userId: string) => { return authToken; }; + + +export const getAccessToken = async (region: string, userId: string) => { + await AuthenticationModel.read(); + const userIndex = AuthenticationModel.chain + .get("users") + .findIndex({ + region: region, + user_id: userId, + }) + .value(); + + const accessToken = AuthenticationModel.data.users[userIndex]?.access_token; + + if (userIndex < 0 || !accessToken) throw new UnauthorizedError(); + + return accessToken; +}; \ No newline at end of file diff --git a/api/src/utils/config-handler.util.ts b/api/src/utils/config-handler.util.ts new file mode 100644 index 000000000..db789ebf0 --- /dev/null +++ b/api/src/utils/config-handler.util.ts @@ -0,0 +1,26 @@ +import { configHandler } from '@contentstack/cli-utilities'; + + +/** + * Sets the OAuth configuration for the CLI + * @param userData - The user data + */ +export const setOAuthConfig = (userData: any) => { + configHandler.set('oauthAccessToken', userData?.access_token); + configHandler.set('oauthRefreshToken', userData?.refresh_token); + configHandler.set('oauthDateTime', userData?.created_at); + configHandler.set('email', userData?.email); + configHandler.set('userUid', userData?.user_id); + configHandler.set('oauthOrgUid', userData?.organization_uid); + configHandler.set('authorisationType', 'OAUTH'); +} + +/** + * Sets the Basic Auth configuration for the CLI + * @param userData - The user data + */ +export const setBasicAuthConfig = (userData: any) => { + configHandler.set('authtoken', userData?.authtoken); + configHandler.set('email', userData?.email); + configHandler.set('authorisationType', 'BASIC'); +} \ No newline at end of file diff --git a/ui/src/pages/Login/index.scss b/ui/src/pages/Login/index.scss index 2c93376fd..56071c715 100644 --- a/ui/src/pages/Login/index.scss +++ b/ui/src/pages/Login/index.scss @@ -187,3 +187,49 @@ line-height: 1 !important; } } +// SSO Button specific styles +.AccountForm__actions__sso_button { + margin-bottom: 24px; +} + +// Divider styles +.flex { + display: flex; +} + +.items-center { + align-items: center; +} + +.flex-1 { + flex: 1; +} + +.border-t { + border-top: 1px solid; +} + +.border-gray-300 { + border-color: #d1d5db; +} + +.px-16 { + padding-left: 16px; + padding-right: 16px; +} + +.text-sm { + font-size: 14px; +} + +.text-gray-500 { + color: #6b7280; +} + +.bg-white { + background-color: white; +} + +.mb-24 { + margin-bottom: 24px; +} \ No newline at end of file diff --git a/ui/src/pages/Login/index.tsx b/ui/src/pages/Login/index.tsx index adebbcb48..ff9c01903 100644 --- a/ui/src/pages/Login/index.tsx +++ b/ui/src/pages/Login/index.tsx @@ -26,7 +26,7 @@ import { clearLocalStorage, failtureNotification, setDataInLocalStorage } from ' // API Service import { getCMSDataFromFile } from '../../cmsData/cmsSelector'; -import { userSession, requestSMSToken } from '../../services/api/login.service'; +import { userSession, requestSMSToken, getAppConfig, checkSSOAuthStatus } from '../../services/api/login.service'; // Interface import { IProps, IStates, defaultStates, User, UserRes, LoginType } from './login.interface'; @@ -243,6 +243,170 @@ const Login: FC = () => { }; }; + const handleSSOLogin = async () => { + setIsLoading(true); + try { + const currentRegion = region; + + await getAppConfig() + .then((res: any) => { + if (res?.status === 404) { + failtureNotification('Kindly setup the SSO first'); + setIsLoading(false); + return; + } + + if (res?.status === 400) { + failtureNotification('Something went wrong please try normal login method'); + setIsLoading(false); + return; + } + + if (res?.status === 500) { + failtureNotification('Something went wrong please try normal login method'); + setIsLoading(false); + return; + } + + const appConfig = res?.data; + + // Check if authUrl exists + if (!appConfig?.authUrl) { + failtureNotification('Something went wrong please try normal login method'); + setIsLoading(false); + return; + } + + // Checks if region matches + if (appConfig?.region?.key && appConfig.region.key !== currentRegion) { + failtureNotification('Kindly choose correct region as the SSO region'); + setIsLoading(false); + return; + } + + const authURL = appConfig.authUrl; + const ssoWindow = window.open(authURL, '_blank', 'noopener,noreferrer'); + + if (appConfig.user?.uid) { + startSSOPolling(appConfig.user.uid, ssoWindow); + } else { + failtureNotification('Missing user information in SSO configuration'); + setIsLoading(false); + } + + }) + .catch((err: any) => { + failtureNotification('Something went wrong please try normal login method'); + setIsLoading(false); + }); + + } catch (error) { + failtureNotification('Something went wrong please try normal login method'); + setIsLoading(false); + } + }; + + + const startSSOPolling = (userId: string, ssoWindow: Window | null) => { + const pollInterval = 2000; + const maxPollTime = 300000; + let pollCount = 0; + const maxPolls = maxPollTime / pollInterval; + const poll = async () => { + pollCount++ + + try { + if (ssoWindow?.closed) { + failtureNotification('SSO login was cancelled'); + setIsLoading(false); + return; + } + + await checkSSOAuthStatus(userId) + .then((authRes: any) => { + + if (authRes?.status === 200 && authRes?.data?.authenticated === true) { + + if (ssoWindow && !ssoWindow.closed) { + ssoWindow.close(); + } + + handleSuccessfulSSOLogin(authRes.data); + return; + } + + if (pollCount < maxPolls) { + setTimeout(poll, pollInterval); + } else { + failtureNotification('SSO authentication timed out. Please try again.'); + setIsLoading(false); + if (ssoWindow && !ssoWindow.closed) { + ssoWindow.close(); + } + } + }) + .catch((error: any) => { + + + if (pollCount < maxPolls) { + setTimeout(poll, pollInterval); + } else { + failtureNotification('Something went wrong please try normal login method'); + setIsLoading(false); + if (ssoWindow && !ssoWindow.closed) { + ssoWindow.close(); + } + } + }); + + } catch (error) { + failtureNotification('Something went wrong please try normal login method'); + setIsLoading(false); + if (ssoWindow && !ssoWindow.closed) { + ssoWindow.close(); + } + } + }; + + setTimeout(poll, pollInterval); + }; + + + const handleSuccessfulSSOLogin = (authData: any) => { + + try { + setIsLoading(false); + + setDataInLocalStorage('app_token', authData.app_token); + + localStorage?.removeItem('organization'); + dispatch(clearOrganisationData()); + + + const authenticationObj = { + authToken: authData.app_token, + isAuthenticated: true + }; + + const userObj = { + ...user, + region: region + }; + + dispatch(setUser(userObj)); + dispatch(setAuthToken(authenticationObj)); + setLoginStates((prev) => ({ ...prev, submitted: true })); + + dispatch(getUserDetails()); + + navigate(`/projects`, { replace: true }); + + } catch (error) { + console.error('Error processing SSO login success:', error); + failtureNotification('Login successful but navigation failed. Please refresh the page.'); + } + }; + // useEffect(()=>{ // const handlePopState = (event: PopStateEvent) => { // event.preventDefault(); @@ -286,7 +450,7 @@ const Login: FC = () => { {twoFactorAuthentication?.title && (

{twoFactorAuthentication?.title}

)} - + ( @@ -466,10 +630,9 @@ const Login: FC = () => { }} - +
- {/* disabled={errors && Object.keys(errors).length ? true : false} */}
+
+ +
diff --git a/ui/src/services/api/login.service.ts b/ui/src/services/api/login.service.ts index acf3300a3..fe9be1a20 100644 --- a/ui/src/services/api/login.service.ts +++ b/ui/src/services/api/login.service.ts @@ -1,7 +1,7 @@ import { AUTH_ROUTES } from '../../utilities/constants'; import { User, SmsToken } from '../../pages/Login/login.interface'; -import { postCall } from './service'; +import { postCall, getCall } from './service'; export const userSession = (data: User) => { try { @@ -26,3 +26,27 @@ export const requestSMSToken = (data: SmsToken) => { } } }; + +export const getAppConfig = () => { + try { + return getCall(`${AUTH_ROUTES}/app-config`); + } catch (error) { + if (error instanceof Error) { + throw new Error(`Error in getAppConfig: ${error.message}`); + } else { + throw new Error('Unknown error in getAppConfig'); + } + } +}; + +export const checkSSOAuthStatus = (userId: string) => { + try { + return getCall(`${AUTH_ROUTES}/sso-status/${userId}`); + } catch (error) { + if (error instanceof Error) { + throw new Error(`Error in checkSSOAuthStatus: ${error.message}`); + } else { + throw new Error('Unknown error in checkSSOAuthStatus'); + } + } +}; \ No newline at end of file diff --git a/upload-api/src/config/index.ts b/upload-api/src/config/index.ts index ca683e8b0..6b1b06da8 100644 --- a/upload-api/src/config/index.ts +++ b/upload-api/src/config/index.ts @@ -2,7 +2,7 @@ export default { plan: { dropdown: { optionLimit: 100 } }, - cmsType: process.env.CMS_TYPE || 'cmsType', + cmsType: process.env.CMS_TYPE || 'wordpress', isLocalPath: true, awsData: { awsRegion: 'us-east-2', @@ -12,5 +12,5 @@ export default { bucketName: '', bucketKey: '' }, - localPath: process.env.CONTAINER_PATH || 'your-local-legacy-cms-path', + localPath: process.env.CONTAINER_PATH || '/Users/shobhit.upadhyay/Downloads/sitetitle (1).xml', }; \ No newline at end of file From 450bb90af6a13b4355d0f55f64d9357662a0f052 Mon Sep 17 00:00:00 2001 From: shobhit upadhyay Date: Mon, 29 Sep 2025 14:28:36 +0530 Subject: [PATCH 6/8] talisman --- .talismanrc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.talismanrc b/.talismanrc index 770e17cd7..cb3a98f94 100644 --- a/.talismanrc +++ b/.talismanrc @@ -119,4 +119,21 @@ fileignoreconfig: fileignoreconfig: - filename: api/sso.utils.js checksum: 5d589c128c4b38f8aacd70e5d02ddd7fa8e93ff7897ca69a1258378139d1d616 +version: "1.0" + +fileignoreconfig: +- filename: api/package-lock.json + checksum: 4d2fd1905b5933e1d2c4d178e1536422d4aac84caa9640149eab0432a75b712d +- filename: api/src/services/migration.service.ts + checksum: 1fdf5423840e170709c7c677c3a6a7c6ae61f373948c2ef295aa645a859c1af5 +- filename: api/src/services/contentMapper.service.ts + checksum: 03d5dcc31b38fd435f6a4389d6891c7fc1ba27b32dc2b382b91173d84f4565f7 +- filename: api/src/services/globalField.service.ts + checksum: b808815c7372f68fe9a5904d23be50cb0ec066592328ec1721dc3c395cbe3a2c +- filename: api/src/services/taxonomy.service.ts + checksum: 840ab11838ebf08df44ada0a3674dad8cc124bc8bcbc5dfd1d9c585a34e4aeda +- filename: api/src/services/org.service.ts + checksum: 0a50297164d7845d889fc78097164c4794a3f9cd7314c06365c8426a2a6ee52a +- filename: ui/src/pages/Login/index.tsx + checksum: 7f7c008586db60f1cc8df625b88bfdc5c3bb861c21e40a55fc763f0ac4a6a8d2 version: "1.0" \ No newline at end of file From 8d39b125c570d98d55e5c5620c0a57a9a1ee0ae5 Mon Sep 17 00:00:00 2001 From: shobhit upadhyay Date: Tue, 30 Sep 2025 11:47:09 +0530 Subject: [PATCH 7/8] copilot comments resolve --- .talismanrc | 5 +++++ api/src/services/contentMapper.service.ts | 2 +- ui/src/pages/Login/index.tsx | 2 +- upload-api/src/config/index.ts | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.talismanrc b/.talismanrc index cb3a98f94..fafa16819 100644 --- a/.talismanrc +++ b/.talismanrc @@ -136,4 +136,9 @@ fileignoreconfig: checksum: 0a50297164d7845d889fc78097164c4794a3f9cd7314c06365c8426a2a6ee52a - filename: ui/src/pages/Login/index.tsx checksum: 7f7c008586db60f1cc8df625b88bfdc5c3bb861c21e40a55fc763f0ac4a6a8d2 +version: "1.0" + +fileignoreconfig: +- filename: api/src/services/contentMapper.service.ts + checksum: 924b124214a93a7bec4c471304f5b270d5e735d506644180273b7118f3d37dd2 version: "1.0" \ No newline at end of file diff --git a/api/src/services/contentMapper.service.ts b/api/src/services/contentMapper.service.ts index 42706adfd..9a7a022b6 100644 --- a/api/src/services/contentMapper.service.ts +++ b/api/src/services/contentMapper.service.ts @@ -326,7 +326,7 @@ const getExistingContentTypes = async (req: Request) => { token_payload?.region as keyof typeof config.CS_API ]!}/content_types`; let headers: any = { - api_key: projectId?.destination_stack_id, + api_key: project?.destination_stack_id, } if(token_payload?.is_sso) { const accessToken = await getAccessToken(token_payload?.region, token_payload?.user_id); diff --git a/ui/src/pages/Login/index.tsx b/ui/src/pages/Login/index.tsx index ff9c01903..42d0eef78 100644 --- a/ui/src/pages/Login/index.tsx +++ b/ui/src/pages/Login/index.tsx @@ -313,7 +313,7 @@ const Login: FC = () => { let pollCount = 0; const maxPolls = maxPollTime / pollInterval; const poll = async () => { - pollCount++ + pollCount++; try { if (ssoWindow?.closed) { diff --git a/upload-api/src/config/index.ts b/upload-api/src/config/index.ts index 6b1b06da8..051930f18 100644 --- a/upload-api/src/config/index.ts +++ b/upload-api/src/config/index.ts @@ -12,5 +12,5 @@ export default { bucketName: '', bucketKey: '' }, - localPath: process.env.CONTAINER_PATH || '/Users/shobhit.upadhyay/Downloads/sitetitle (1).xml', + localPath: process.env.CONTAINER_PATH || 'your-local-legacy-cms-path', }; \ No newline at end of file From d90b34576f26566d1f55c11318f836dc90aefe3d Mon Sep 17 00:00:00 2001 From: shobhit upadhyay Date: Tue, 30 Sep 2025 15:16:09 +0530 Subject: [PATCH 8/8] comments resolve --- .talismanrc | 5 +++ api/src/controllers/auth.controller.ts | 5 +-- api/src/routes/auth.routes.ts | 5 +-- api/src/services/auth.service.ts | 42 ++++++++++++------------ api/src/services/user.service.ts | 10 +++--- api/src/utils/auth.utils.ts | 4 +-- api/sso.utils.js | 44 +++++++++++++++++--------- ui/src/pages/Login/index.tsx | 14 ++++---- 8 files changed, 75 insertions(+), 54 deletions(-) diff --git a/.talismanrc b/.talismanrc index fafa16819..57928c220 100644 --- a/.talismanrc +++ b/.talismanrc @@ -141,4 +141,9 @@ version: "1.0" fileignoreconfig: - filename: api/src/services/contentMapper.service.ts checksum: 924b124214a93a7bec4c471304f5b270d5e735d506644180273b7118f3d37dd2 +version: "1.0" + +fileignoreconfig: +- filename: ui/src/pages/Login/index.tsx + checksum: 213c6441dc87d82ce6b97679d457ae56c6e40ef13a89bddd4f21afcf566b5576 version: "1.0" \ No newline at end of file diff --git a/api/src/controllers/auth.controller.ts b/api/src/controllers/auth.controller.ts index fa7fcbdba..abf01775d 100644 --- a/api/src/controllers/auth.controller.ts +++ b/api/src/controllers/auth.controller.ts @@ -26,8 +26,9 @@ const RequestSms = async (req: Request, res: Response) => { /** - * Handles the secure, server-to-server POST request from our Launch proxy. - * This confirms to the proxy that the token was received. + * Generates the OAuth token and saves it to the database. + * @param req - The request object. Sends the code and region. + * @param res - The response object. Sends the message "Token received successfully." */ const saveOAuthToken = async (req: Request, res: Response) => { await authService.saveOAuthToken(req); diff --git a/api/src/routes/auth.routes.ts b/api/src/routes/auth.routes.ts index cc2f1077a..322243aac 100644 --- a/api/src/routes/auth.routes.ts +++ b/api/src/routes/auth.routes.ts @@ -41,8 +41,9 @@ router.post( ); /** - * The new secure endpoint that the Launch proxy will call with a POST request - * to deliver the final access token. This is NOT for browser access. + * Generates the OAuth token and saves it to the database. + * @param req - The request object. Sends the code and region. + * @param res - The response object. Sends the message "Token received successfully." * @route POST /v2/auth/save-token */ router.get( diff --git a/api/src/services/auth.service.ts b/api/src/services/auth.service.ts index 6c087c01a..3310e3854 100644 --- a/api/src/services/auth.service.ts +++ b/api/src/services/auth.service.ts @@ -237,22 +237,22 @@ const saveOAuthToken = async (req: Request): Promise => { throw new InternalServerError(userErr); } - const csUser = userRes.data.user; + const csUser = userRes?.data?.user; const appTokenPayload = { region: region as string, - user_id: csUser.uid, + user_id: csUser?.uid, is_sso: true, }; const appToken = generateToken(appTokenPayload); await AuthenticationModel.read(); - const userIndex = AuthenticationModel.chain.get("users").findIndex({ user_id: csUser.uid }).value(); + const userIndex = AuthenticationModel.chain.get("users").findIndex({ user_id: csUser?.uid }).value(); AuthenticationModel.update((data: any) => { const userRecord = { ...appTokenPayload, - email: csUser.email, + email: csUser?.email, access_token: access_token, refresh_token: refresh_token, organization_uid: organization_uid, @@ -295,7 +295,7 @@ export const refreshOAuthToken = async (userId: string): Promise => { throw new Error(`User record not found for user_id: ${userId}`); } - if (!userRecord.refresh_token) { + if (!userRecord?.refresh_token) { throw new Error(`No refresh token available for user: ${userId}`); } @@ -311,7 +311,7 @@ export const refreshOAuthToken = async (userId: string): Promise => { throw new Error('OAuth client_id or client_secret not found in app.json'); } - logger.info(`Refreshing token for user: ${userRecord.email} in region: ${userRecord.region}`); + logger.info(`Refreshing token for user: ${userRecord?.email} in region: ${userRecord?.region}`); const appUrl = CSAUTHHOST[userRecord.region] || CSAUTHHOST['NA']; const tokenEndpoint = `${appUrl}`; @@ -321,7 +321,7 @@ export const refreshOAuthToken = async (userId: string): Promise => { client_id: client_id, client_secret: client_secret, redirect_uri: redirect_uri, - refresh_token: userRecord.refresh_token + refresh_token: userRecord?.refresh_token }); const response = await axios.post(tokenEndpoint, formData, { @@ -331,13 +331,13 @@ export const refreshOAuthToken = async (userId: string): Promise => { timeout: 15000 }); - const { access_token, refresh_token } = response.data; + const { access_token, refresh_token } = response?.data; AuthenticationModel.update((data: any) => { - const userIndex = data.users.findIndex((user: any) => user.user_id === userId); + const userIndex = data?.users?.findIndex((user: any) => user?.user_id === userId); if (userIndex >= 0) { data.users[userIndex] = { - ...data.users[userIndex], + ...data?.users[userIndex], access_token: access_token, refresh_token: refresh_token || userRecord.refresh_token, updated_at: new Date().toISOString() @@ -345,11 +345,11 @@ export const refreshOAuthToken = async (userId: string): Promise => { } }); - logger.info(`Token refreshed successfully for user: ${userRecord.email}`); + logger.info(`Token refreshed successfully for user: ${userRecord?.email}`); return access_token; } catch (error: any) { - logger.error(`Token refresh failed for user ${userId}:`, error.response?.data || error.message); + logger.error(`Token refresh failed for user ${userId}:`, error?.response?.data || error?.message); throw new Error(`Failed to refresh token: ${error.response?.data?.error_description || error.message}`); } }; @@ -392,12 +392,12 @@ export const checkSSOAuthStatus = async (userId: string) => { await AuthenticationModel.read(); const userRecord = AuthenticationModel.chain.get("users").find({ user_id: userId }).value(); - if (!userRecord || !userRecord.access_token) { + if (!userRecord || !userRecord?.access_token) { throw new Error('SSO authentication not completed'); } // Only consider tokens created in the last 10 minutes as "fresh" - const tokenAge = new Date()?.getTime() - new Date(userRecord.updated_at)?.getTime(); + const tokenAge = new Date()?.getTime() - new Date(userRecord?.updated_at)?.getTime(); const maxTokenAge = 10 * 60 * 1000; // 10 minutes in milliseconds if (tokenAge > maxTokenAge) { @@ -406,7 +406,7 @@ export const checkSSOAuthStatus = async (userId: string) => { // Token is fresh, proceed with authentication const appTokenPayload = { - region: userRecord.region, + region: userRecord?.region, user_id: userRecord.user_id, is_sso: true, }; @@ -418,18 +418,18 @@ export const checkSSOAuthStatus = async (userId: string) => { message: 'SSO authentication successful', app_token: appToken, user: { - email: userRecord.email, - uid: userRecord.user_id, - region: userRecord.region, - organization_uid: userRecord.organization_uid + email: userRecord?.email, + uid: userRecord?.user_id, + region: userRecord?.region, + organization_uid: userRecord?.organization_uid } }; } catch (error: any) { - if (error.message.includes('SSO authentication not completed')) { + if (error?.message?.includes('SSO authentication not completed')) { throw error; } - throw new Error(`Failed to check SSO authentication status: ${error.message}`); + throw new Error(`Failed to check SSO authentication status: ${error?.message}`); } }; diff --git a/api/src/services/user.service.ts b/api/src/services/user.service.ts index 0c3463103..53f1333ce 100644 --- a/api/src/services/user.service.ts +++ b/api/src/services/user.service.ts @@ -34,14 +34,14 @@ const getUserProfile = async (req: Request): Promise => { if (userIndex < 0) throw new BadRequestError(HTTP_TEXTS.NO_CS_USER); - const userRecord = AuthenticationModel.data.users[userIndex]; + const userRecord = AuthenticationModel?.data?.users[userIndex]; let headers: any = { "Content-Type": "application/json", }; if (appTokenPayload?.is_sso) { - headers.authorization = `Bearer ${userRecord.access_token}`; + headers.authorization = `Bearer ${userRecord?.access_token}`; } else if (appTokenPayload?.is_sso === false) { - headers.authtoken = userRecord.authtoken; + headers.authtoken = userRecord?.authtoken; } else { throw new BadRequestError("No valid authentication token found or mismatch in is_sso flag"); } @@ -75,7 +75,7 @@ const getUserProfile = async (req: Request): Promise => { if (!res?.data?.user) throw new BadRequestError(HTTP_TEXTS.NO_CS_USER); const orgs = (res?.data?.user?.organizations || []) - ?.filter((org: any) => org?.org_roles?.some((item: any) => item.admin)) + ?.filter((org: any) => org?.org_roles?.some((item: any) => item?.admin)) ?.map(({ uid, name }: any) => ({ org_id: uid, org_name: name })); const ownerOrgs = (res?.data?.user?.organizations || [])?.filter((org:any)=> org?.is_owner) @@ -91,7 +91,7 @@ const getUserProfile = async (req: Request): Promise => { orgs: allOrgs, }, }, - status: res.status, + status: res?.status, }; } catch (error: any) { logger.error( diff --git a/api/src/utils/auth.utils.ts b/api/src/utils/auth.utils.ts index e3d87d616..1d933ba0f 100644 --- a/api/src/utils/auth.utils.ts +++ b/api/src/utils/auth.utils.ts @@ -30,11 +30,11 @@ export const getAccessToken = async (region: string, userId: string) => { await AuthenticationModel.read(); const userIndex = AuthenticationModel.chain .get("users") - .findIndex({ + ?.findIndex({ region: region, user_id: userId, }) - .value(); + ?.value(); const accessToken = AuthenticationModel.data.users[userIndex]?.access_token; diff --git a/api/sso.utils.js b/api/sso.utils.js index 1694958f1..2a1c2b600 100644 --- a/api/sso.utils.js +++ b/api/sso.utils.js @@ -6,6 +6,7 @@ const crypto = require("crypto"); const manifest = require("./manifest.json"); const { default: axios } = require("axios"); +// Region configuration const REGION_CONFIG = { NA: { name: "North America", @@ -55,6 +56,10 @@ const REGION_CONFIG = { }; +/** + * Gets the current region from the CSDX config. + * @returns The current region. + */ function getCurrentRegion() { try { const regionOutput = execSync("csdx config:get:region", { @@ -80,6 +85,12 @@ function getCurrentRegion() { } } +/** + * Sets the OAuth configuration for the CLI. + * @param migration - The migration object. + * @param stackSDKInstance - The stack SDK instance. + * @param managementAPIClient - The management API client. + */ module.exports = async ({ migration, stackSDKInstance, @@ -237,21 +248,22 @@ module.exports = async ({ console.log("šŸ” Fetching OAuth configuration..."); const oauthData = await client - .marketplace(selectedOrg.uid) - .app(existingApp?.uid) - .oauth() - .fetch(); + ?.marketplace(selectedOrg?.uid) + ?.app(existingApp?.uid) + ?.oauth() + ?.fetch(); console.log("šŸ”’ Generating PKCE credentials..."); - const code_verifier = crypto.randomBytes(32).toString("hex"); + const code_verifier = crypto?.randomBytes(32).toString("hex"); const code_challenge = crypto - .createHash("sha256") - .update(code_verifier) - .digest("base64") - .replace(/\+/g, "-") - .replace(/\//g, "_") - .replace(/=+$/, ""); - + ?.createHash("sha256") + ?.update(code_verifier) + ?.digest("base64") + ?.replace(/\+/g, "-") + ?.replace(/\//g, "_") + ?.replace(/=+$/, ""); + + // Generates the authorization URL for the app const authUrl = `${regionConfig.app}/#!/apps/${ existingApp?.uid }/authorize?response_type=code&client_id=${ @@ -262,6 +274,8 @@ module.exports = async ({ console.log(`\nšŸš€ Authorization URL for ${regionConfig.name}:`); console.log(authUrl); + + // Formats the app data for the app.json file const appData = { timestamp: new Date().toISOString(), region: { @@ -295,10 +309,10 @@ module.exports = async ({ } catch (error) { console.error("āŒ Setup failed:"); - console.error("Error:", error.message); + console.error("Error:", error?.message); - if (error.errorMessage) { - console.error("Details:", error.errorMessage); + if (error?.errorMessage) { + console.error("Details:", error?.errorMessage); } console.error(`\nšŸ” Debug Info:`); diff --git a/ui/src/pages/Login/index.tsx b/ui/src/pages/Login/index.tsx index 42d0eef78..d589ce36c 100644 --- a/ui/src/pages/Login/index.tsx +++ b/ui/src/pages/Login/index.tsx @@ -278,17 +278,17 @@ const Login: FC = () => { } // Checks if region matches - if (appConfig?.region?.key && appConfig.region.key !== currentRegion) { + if (appConfig?.region?.key && appConfig?.region?.key !== currentRegion) { failtureNotification('Kindly choose correct region as the SSO region'); setIsLoading(false); return; } - const authURL = appConfig.authUrl; + const authURL = appConfig?.authUrl; const ssoWindow = window.open(authURL, '_blank', 'noopener,noreferrer'); - if (appConfig.user?.uid) { - startSSOPolling(appConfig.user.uid, ssoWindow); + if (appConfig?.user?.uid) { + startSSOPolling(appConfig?.user?.uid, ssoWindow); } else { failtureNotification('Missing user information in SSO configuration'); setIsLoading(false); @@ -331,7 +331,7 @@ const Login: FC = () => { ssoWindow.close(); } - handleSuccessfulSSOLogin(authRes.data); + handleSuccessfulSSOLogin(authRes?.data); return; } @@ -377,14 +377,14 @@ const Login: FC = () => { try { setIsLoading(false); - setDataInLocalStorage('app_token', authData.app_token); + setDataInLocalStorage('app_token', authData?.app_token); localStorage?.removeItem('organization'); dispatch(clearOrganisationData()); const authenticationObj = { - authToken: authData.app_token, + authToken: authData?.app_token, isAuthenticated: true };