diff --git a/.talismanrc b/.talismanrc index b7172be..5d4c472 100644 --- a/.talismanrc +++ b/.talismanrc @@ -3,7 +3,7 @@ fileignoreconfig: ignore_detectors: - filecontent - filename: package-lock.json - checksum: 59653dc17458f6bddffb6178bfb8f8191ad4715f41a788082a11d3b08e966b4c + checksum: 3f095735d07bd662952f037664e7ac61ce7841b5940ab16af4a3ef4ad9076d13 - filename: .husky/pre-commit checksum: 5baabd7d2c391648163f9371f0e5e9484f8fb90fa2284cfc378732ec3192c193 - filename: test/request.spec.ts diff --git a/package-lock.json b/package-lock.json index 8c42a23..f8dd5f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,17 @@ { "name": "@contentstack/core", - "version": "1.3.8", + "version": "1.3.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentstack/core", - "version": "1.3.8", + "version": "1.3.9", "license": "MIT", "dependencies": { - "axios": "^1.12.2", + "axios": "^1.13.4", "axios-mock-adapter": "^2.1.0", - "husky": "^9.1.7", - "lodash": "^4.17.21", + "lodash": "^4.17.23", "qs": "6.14.1", "tslib": "^2.8.1" }, @@ -42,7 +41,7 @@ "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-spellcheck": "^0.0.20", - "husky": "^8.0.3", + "husky": "^9.1.7", "jest": "28.1.3", "jest-environment-jsdom": "28.1.3", "jest-html-reporters": "^3.1.7", @@ -57,13 +56,13 @@ } }, "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==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", + "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -72,9 +71,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", - "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", + "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", "dev": true, "license": "MIT", "engines": { @@ -82,21 +81,21 @@ } }, "node_modules/@babel/core": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", - "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", + "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/code-frame": "^7.28.6", + "@babel/generator": "^7.28.6", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -113,14 +112,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", - "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", + "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -130,13 +129,13 @@ } }, "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==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", + "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -157,29 +156,29 @@ } }, "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==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -189,9 +188,9 @@ } }, "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==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true, "license": "MIT", "engines": { @@ -229,27 +228,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", + "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.5" + "@babel/types": "^7.28.6" }, "bin": { "parser": "bin/babel-parser.js" @@ -314,13 +313,13 @@ } }, "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==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -466,13 +465,13 @@ } }, "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==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -482,33 +481,33 @@ } }, "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==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", - "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", + "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", + "@babel/code-frame": "^7.28.6", + "@babel/generator": "^7.28.6", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.28.6", + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6", "debug": "^4.3.1" }, "engines": { @@ -516,9 +515,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", + "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", "dev": true, "license": "MIT", "dependencies": { @@ -1067,9 +1066,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-fullstack": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.7.tgz", - "integrity": "sha512-IxEk2YAwAJKYCUEgEeOg3QvTL4XLlyArJElFuMQevU1dPgHgzWElFevN5lsTFnvMFA1riYsVinqJJX0BanCFEg==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.8.tgz", + "integrity": "sha512-J6EeoeThvx/DFrcA2rJiCA6vfqwJMbkG0IcXhlsmRZmasIpanmxgt90OEaUazbZahFiuJT8wrhgQ1QgD1MsqBw==", "dev": true, "license": "MIT" }, @@ -1158,9 +1157,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.2.29", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.29.tgz", - "integrity": "sha512-ZAef8JpYmbuHFT1zekj/YyImLPvZevjECw663EmG5GPePyNo4AfH8Dd2fFhaOyQ3P5I5LrkAhGwypnOfUxcssw==", + "version": "5.2.31", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.31.tgz", + "integrity": "sha512-+HoFoFe53pL0wDuSHRs5L+CcDMaG5sLfjKLPT4H0VdwNzho3HLOohTCZr6cYt7OEbXf3xi4YXBkamCy38xOpjA==", "dev": true, "license": "MIT" }, @@ -2210,7 +2209,8 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", @@ -2332,6 +2332,7 @@ "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", @@ -2748,6 +2749,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2831,6 +2833,7 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -3223,10 +3226,11 @@ } }, "node_modules/axios": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", - "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.4.tgz", + "integrity": "sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==", "license": "MIT", + "peer": true, "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", @@ -3384,9 +3388,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.14", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz", - "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==", + "version": "2.9.18", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.18.tgz", + "integrity": "sha512-e23vBV1ZLfjb9apvfPk4rHVu2ry6RIr2Wfs+O324okSidrX7pTAnEJPCh/O5BtRlr7QtZI7ktOP3vsqr7Z5XoA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3456,6 +3460,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -3622,9 +3627,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001764", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz", - "integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==", + "version": "1.0.30001766", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz", + "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==", "dev": true, "funding": [ { @@ -3928,6 +3933,13 @@ "node": ">=10" } }, + "node_modules/commitizen/node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, "node_modules/commitizen/node_modules/minimist": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", @@ -4721,9 +4733,9 @@ } }, "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -4808,9 +4820,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.267", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "version": "1.5.279", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.279.tgz", + "integrity": "sha512-0bblUU5UNdOt5G7XqGiJtpZMONma6WAfq9vsFmtn9x1+joAObr6x1chfqyxFSDCAFwFhCQDrqeAr6MYdpwJ9Hg==", "dev": true, "license": "ISC" }, @@ -5103,6 +5115,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -5410,6 +5423,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -6787,16 +6801,16 @@ } }, "node_modules/husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, "license": "MIT", "bin": { - "husky": "lib/bin.js" + "husky": "bin.js" }, "engines": { - "node": ">=14" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/typicode" @@ -7746,6 +7760,7 @@ "integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/core": "^28.1.3", "@jest/types": "^28.1.3", @@ -8709,9 +8724,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "license": "MIT" }, "node_modules/lodash.camelcase": { @@ -9732,6 +9747,7 @@ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin-prettier.js" }, @@ -11113,9 +11129,9 @@ } }, "node_modules/terser": { - "version": "5.44.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", - "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", + "version": "5.46.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", + "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -11484,6 +11500,7 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -11730,6 +11747,7 @@ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -11931,9 +11949,9 @@ } }, "node_modules/watchpack": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.0.tgz", - "integrity": "sha512-e6vZvY6xboSwLz2GD36c16+O/2Z6fKvIf4pOXptw2rY9MVwE/TXc6RGqxD3I3x0a28lwBY7DE+76uTPSsBrrCA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, "license": "MIT", "dependencies": { @@ -11970,6 +11988,7 @@ "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -12269,9 +12288,9 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index b712672..1d6b5d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/core", - "version": "1.3.8", + "version": "1.3.9", "type": "commonjs", "main": "./dist/cjs/src/index.js", "types": "./dist/cjs/src/index.d.ts", @@ -33,10 +33,9 @@ "husky-check": "npx husky install && chmod +x .husky/pre-commit" }, "dependencies": { - "axios": "^1.12.2", + "axios": "^1.13.4", "axios-mock-adapter": "^2.1.0", - "husky": "^9.1.7", - "lodash": "^4.17.21", + "lodash": "^4.17.23", "qs": "6.14.1", "tslib": "^2.8.1" }, @@ -77,7 +76,7 @@ "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-spellcheck": "^0.0.20", - "husky": "^8.0.3", + "husky": "^9.1.7", "jest": "28.1.3", "jest-environment-jsdom": "28.1.3", "jest-html-reporters": "^3.1.7", diff --git a/src/lib/request.ts b/src/lib/request.ts index 4326c63..096056f 100644 --- a/src/lib/request.ts +++ b/src/lib/request.ts @@ -25,6 +25,27 @@ function buildFullUrl(baseURL: string | undefined, url: string, queryString: str return `${base}${url}?${queryString}`; } +/** + * Safely checks if a URL points to the preview endpoint by parsing the hostname + * This prevents substring matching vulnerabilities (e.g., evil.com/rest-preview.contentstack.com) + */ +function isPreviewEndpoint(url: string): boolean { + try { + // Ensure URL has a protocol for proper parsing + let urlToParse = url; + if (!url.startsWith('http://') && !url.startsWith('https://')) { + urlToParse = `https://${url}`; + } + + const parsedUrl = new URL(urlToParse); + // Check hostname exactly, not as substring + return parsedUrl.hostname === 'rest-preview.contentstack.com'; + } catch { + // If URL parsing fails, default to false for safety + return false; + } +} + /** * Makes the HTTP request with proper URL handling */ @@ -34,16 +55,26 @@ async function makeRequest( requestConfig: any, actualFullUrl: string ): Promise { + // Determine URL length threshold based on whether it's a preview endpoint + // rest-preview.contentstack.com has stricter limits, so use lower threshold + const isPreview = isPreviewEndpoint(actualFullUrl); + const urlLengthThreshold = isPreview ? 1500 : 2000; + // If URL is too long, use direct axios request with full URL - if (actualFullUrl.length > 2000) { + if (actualFullUrl.length > urlLengthThreshold) { + // Remove params from requestConfig since they're already in actualFullUrl + const { params, ...configWithoutParams } = requestConfig; return await instance.request({ method: 'get', url: actualFullUrl, headers: instance.defaults.headers, maxContentLength: Infinity, maxBodyLength: Infinity, + ...configWithoutParams, }); } else { + // For URLs under threshold, use normal get with params + // Axios will handle serialization correctly for both absolute and relative URLs return await instance.get(url, requestConfig); } } @@ -59,7 +90,7 @@ function handleRequestError(err: any): Error { export async function getData(instance: AxiosInstance, url: string, data?: any) { try { - if (instance.stackConfig && instance.stackConfig.live_preview) { + if (instance.stackConfig?.live_preview) { const livePreviewParams = instance.stackConfig.live_preview; if (livePreviewParams.enable) { @@ -90,7 +121,7 @@ export async function getData(instance: AxiosInstance, url: string, data?: any) const actualFullUrl = buildFullUrl(instance.defaults.baseURL, url, queryString); const response = await makeRequest(instance, url, requestConfig, actualFullUrl); - if (response && response.data) { + if (response?.data) { return response.data; } else { throw response; diff --git a/test/contentstack-core.spec.ts b/test/contentstack-core.spec.ts index c1bb031..0c4da51 100644 --- a/test/contentstack-core.spec.ts +++ b/test/contentstack-core.spec.ts @@ -165,7 +165,7 @@ describe('contentstackCore', () => { try { await instance.get('/'); } catch (error: unknown) { - expect(onError).toBeCalledWith(error); + expect(onError).toHaveBeenCalledWith(error); } consoleErrorSpy.mockRestore(); @@ -186,7 +186,7 @@ describe('contentstackCore', () => { await client.get('/'); - expect(client.httpClientParams.onError).not.toBeCalled(); + expect(client.httpClientParams.onError).not.toHaveBeenCalled(); }); }); diff --git a/test/esm-exports.spec.ts b/test/esm-exports.spec.ts index 40e7313..da07797 100644 --- a/test/esm-exports.spec.ts +++ b/test/esm-exports.spec.ts @@ -28,6 +28,7 @@ describe('ESM Exports Tests', () => { it('should re-export getData from ESM index.js', () => { const indexContent = fs.readFileSync(esmIndexPath, 'utf-8'); + // ESM builds include .js extension in import paths expect(indexContent).toContain("export * from './lib/request.js'"); }); diff --git a/test/request.spec.ts b/test/request.spec.ts index fb5f0f4..c41f6c7 100644 --- a/test/request.spec.ts +++ b/test/request.spec.ts @@ -22,7 +22,7 @@ describe('Request tests', () => { mockClient.onGet(url).reply(404, { error: errorMessage }); - await expect(getData(client, url)).rejects.toThrowError(errorMessage); + await expect(getData(client, url)).rejects.toThrow(errorMessage); }); it('should throw error when host is required for live preview', async () => { @@ -35,7 +35,7 @@ describe('Request tests', () => { live_preview: '', // this gets added via Delivery SDK; added here in core only for testing. }, }; - await expect(getData(client, url, {})).rejects.toThrowError('Host is required for live preview'); + await expect(getData(client, url, {})).rejects.toThrow('Host is required for live preview'); }); it('should handle live_preview with enable=true and live_preview=init', async () => { @@ -272,7 +272,7 @@ describe('Request tests', () => { throw customError; }); - await expect(getData(client, url)).rejects.toThrowError('Custom network error'); + await expect(getData(client, url)).rejects.toThrow('Custom network error'); }); it('should handle non-Error objects as errors when they have message property', async () => { @@ -372,6 +372,9 @@ describe('Request tests', () => { maxBodyLength: Infinity, }) ); + // Verify that params were removed from the request config (they're already in the URL) + const callConfig = requestSpy.mock.calls[0][0]; + expect(callConfig.params).toBeUndefined(); requestSpy.mockRestore(); }); @@ -525,8 +528,138 @@ describe('Request tests', () => { const callUrl = requestSpy.mock.calls[0][0].url; expect(callUrl).not.toContain('example.com:443/v3'); expect(callUrl).toContain('external-api.com'); + // Verify that params were removed from the request config + const callConfig = requestSpy.mock.calls[0][0]; + expect(callConfig.params).toBeUndefined(); requestSpy.mockRestore(); }); + + it('should remove params from requestConfig when absolute URL exceeds threshold', async () => { + const client = httpClient({ + defaultHostname: 'example.com', + }); + const absoluteUrl = 'https://external-api.com/api/endpoint'; + const mockResponse = { data: 'mocked' }; + + // Create params that will make URL exceed 2000 characters + const longParam = 'x'.repeat(2000); + const requestData = { params: { longParam, param2: 'y'.repeat(500) } }; + + // Mock instance.request since URL will exceed threshold + const requestSpy = jest.spyOn(client, 'request').mockResolvedValue({ data: mockResponse } as any); + + const result = await getData(client, absoluteUrl, requestData); + + expect(result).toEqual(mockResponse); + // Verify that request was called with full URL + expect(requestSpy).toHaveBeenCalled(); + // Verify that params were removed from the request config (they're in the URL) + const callConfig = requestSpy.mock.calls[0]?.[0]; + expect(callConfig?.params).toBeUndefined(); + + requestSpy.mockRestore(); + }); + + it('should use lower threshold (1500) for rest-preview.contentstack.com URLs', async () => { + const client = httpClient({ defaultHostname: 'example.com' }); + const url = '/content_types/blog/entries/entry123'; + const mockResponse = { entry: { uid: 'entry123', title: 'Test' } }; + + client.stackConfig = { + live_preview: { + enable: true, + preview_token: 'someToken', + live_preview: 'someHash', + host: 'rest-preview.contentstack.com', + }, + }; + + // Create include[] parameters that would exceed 1500 chars for Live Preview + // but would be under 2000 chars for regular requests + const manyIncludes = Array.from({ length: 100 }, (_, i) => `ref_field_${i}_with_long_name`); + const requestData = { params: { 'include[]': manyIncludes } }; + + // Mock instance.request since URL will exceed 1500 chars + const requestSpy = jest.spyOn(client, 'request').mockResolvedValue({ data: mockResponse } as any); + + const result = await getData(client, url, requestData); + + expect(result).toEqual(mockResponse); + // Verify that request was called (not get) because URL exceeded 1500 chars + expect(requestSpy).toHaveBeenCalled(); + const callUrl = requestSpy.mock.calls[0]?.[0]?.url; + expect(callUrl).toBeDefined(); + expect(callUrl).toContain('rest-preview.contentstack.com'); + expect(callUrl!.length).toBeGreaterThan(1500); + // Verify that params were removed from the request config + const callConfig = requestSpy.mock.calls[0]?.[0]; + expect(callConfig?.params).toBeUndefined(); + + requestSpy.mockRestore(); + }); + }); + + describe('URL length handling for includeReference parameters', () => { + it('should handle many include[] parameters without double serialization', async () => { + const client = httpClient({ defaultHostname: 'example.com' }); + const mock = new MockAdapter(client as any); + const url = '/content_types/blog/entries/entry123'; + const mockResponse = { entry: { uid: 'entry123', title: 'Test' } }; + + // Create many include[] parameters that would make URL long + const manyIncludes = Array.from({ length: 50 }, (_, i) => `ref_field_${i}`); + const requestData = { params: { 'include[]': manyIncludes } }; + + mock.onGet(url).reply((config) => { + // Verify params are present in config for relative URLs under threshold + expect(config.params).toBeDefined(); + return [200, mockResponse]; + }); + + const result = await getData(client, url, requestData); + expect(result).toEqual(mockResponse); + expect(mock.history.get.length).toBe(1); + }); + + it('should use instance.request for regular URLs exceeding 2000 characters', async () => { + const client = httpClient({ defaultHostname: 'example.com' }); + const url = '/content_types/blog/entries/entry123'; + const mockResponse = { entry: { uid: 'entry123', title: 'Test' } }; + + // Create many include[] parameters that will exceed 2000 characters + const manyIncludes = Array.from({ length: 200 }, (_, i) => `ref_field_${i}_with_very_long_name_to_make_url_long`); + const requestData = { params: { 'include[]': manyIncludes } }; + + // Mock instance.request since URL will exceed 2000 chars + const requestSpy = jest.spyOn(client, 'request').mockResolvedValue({ data: mockResponse } as any); + + const result = await getData(client, url, requestData); + + expect(result).toEqual(mockResponse); + expect(requestSpy).toHaveBeenCalled(); + // Verify that params were removed from the request config + const callConfig = requestSpy.mock.calls[0][0]; + expect(callConfig.params).toBeUndefined(); + + requestSpy.mockRestore(); + }); + + it('should use standard format when URL length is within threshold', async () => { + const client = httpClient({ defaultHostname: 'example.com' }); + const mock = new MockAdapter(client as any); + const url = '/content_types/blog/entries/entry123'; + const mockResponse = { entry: { uid: 'entry123', title: 'Test' } }; + + // Create a small number of includes that won't exceed threshold + const requestData = { params: { 'include[]': ['ref1', 'ref2', 'ref3'] } }; + + mock.onGet(url).reply(200, mockResponse); + + const result = await getData(client, url, requestData); + expect(result).toEqual(mockResponse); + // Verify the request was made successfully + expect(mock.history.get.length).toBe(1); + }); }); });