diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 90619df78630..a1bdbdd92e93 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -139,6 +139,9 @@ updates: - package-ecosystem: "npm" directory: "/superset-frontend/plugins/plugin-chart-pivot-table/" + ignore: + # TODO: remove below entries until React >= 19.0.0 + - dependency-name: "react-icons" schedule: interval: "daily" labels: @@ -189,6 +192,9 @@ updates: - package-ecosystem: "npm" directory: "/superset-frontend/plugins/plugin-chart-table/" + ignore: + # TODO: remove below entries until React >= 19.0.0 + - dependency-name: "react-icons" schedule: interval: "daily" labels: diff --git a/docs/package.json b/docs/package.json index 064b49d14983..484432a7666d 100644 --- a/docs/package.json +++ b/docs/package.json @@ -83,7 +83,7 @@ "remark-import-partial": "^0.0.2", "reselect": "^5.1.1", "storybook": "^8.6.17", - "swagger-ui-react": "^5.31.1", + "swagger-ui-react": "^5.31.2", "swc-loader": "^0.2.7", "tinycolor2": "^1.4.2", "unist-util-visit": "^5.1.0" diff --git a/docs/yarn.lock b/docs/yarn.lock index aad4838432f4..a232ce5c2bb6 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -3567,26 +3567,26 @@ "@svgr/plugin-jsx" "8.1.0" "@svgr/plugin-svgo" "8.1.0" -"@swagger-api/apidom-ast@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ast/-/apidom-ast-1.5.0.tgz#328fe6ffe2e0516b06f3c47af496c4d3fe3765d6" - integrity sha512-sSfoHE1Bb/FM4//sqsU9VN1refIRGd/RlIwsWJ132TJyEtMAw/Blo68hl4zTGh6ob89OZSKqQ0oZNmwickYhxA== +"@swagger-api/apidom-ast@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ast/-/apidom-ast-1.5.1.tgz#d6f91755110c175ae9f59d625c5a9ce83974d7b3" + integrity sha512-BtaUaWXE0zzosuy6d1UFZp8wQZlqXapolTNF5f/3kzzZPLdDDWZeFyvvGww3Jt0Bwcw5rzavqD/lrTZp3j2qTQ== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-error" "^1.5.0" + "@swagger-api/apidom-error" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" unraw "^3.0.0" -"@swagger-api/apidom-core@^1.3.0", "@swagger-api/apidom-core@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-core/-/apidom-core-1.5.0.tgz#85f10da227e54c02948a88c3cbb31efc278412c1" - integrity sha512-esQ++pv78gCr8ZDdM9dfEjrOymcELzFmJCe5i3q8Q2pQSSkW+FUsUCaSP6mdB+HHqz4H9L+Jy9N7h4e/uVsCVQ== +"@swagger-api/apidom-core@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-core/-/apidom-core-1.5.1.tgz#2191d47d7f11a20422f9a2b5c4f8f42403d1e4d6" + integrity sha512-vjP+HhbIN2D+Z8qsq57Ab2z0CpxCTD177Zd8mbUEKpOFYtc9qoizv6bAXTmhZGfVLxBsw+iGzFVH/z6DvuD3ag== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-ast" "^1.5.0" - "@swagger-api/apidom-error" "^1.5.0" + "@swagger-api/apidom-ast" "^1.5.1" + "@swagger-api/apidom-error" "^1.5.1" "@types/ramda" "~0.30.0" minim "~0.23.8" ramda "~0.30.0" @@ -3594,396 +3594,396 @@ short-unique-id "^5.3.2" ts-mixer "^6.0.3" -"@swagger-api/apidom-error@^1.3.0", "@swagger-api/apidom-error@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-error/-/apidom-error-1.5.0.tgz#576b42ba3dfe2fb18c6713e5a01be0d23dde09fb" - integrity sha512-lSc/7wS/t4y6KmueouAopzZnm1r1/5QzcOUPmwQcDrnoLLqtfd2Hkp+v3a0vqHbbyUi+lHYmCA0JoITzbJYcgQ== +"@swagger-api/apidom-error@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-error/-/apidom-error-1.5.1.tgz#34268b5df902d46e3d6330a3848edf8477e7ee4e" + integrity sha512-R0BSvVgKVNNxnC8S4uJVf4JwWCFNI1ktpLbML6UbzXBPquHfM0gjv+WQgKApMAYw809rtaVIF9ADoUtL/c6+uQ== dependencies: "@babel/runtime-corejs3" "^7.20.7" -"@swagger-api/apidom-json-pointer@^1.3.0", "@swagger-api/apidom-json-pointer@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-1.5.0.tgz#6f36c42fc67ab732e5c45f8b591c67e782694c7d" - integrity sha512-YiRA7n6aOnXD6ZrZcp6avZiVz55rihye5gp4QB3+qEtfcOvFIG6jYRRawXO/1dj9haZvq/2gQys+kJSEQEhMhg== +"@swagger-api/apidom-json-pointer@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-1.5.1.tgz#f5d0f84d1c9e502bad4a359c57edb0d01052a60d" + integrity sha512-EFJzHgHbs5AIPSRowuc02WjbQY5bbFvijQuFIkHSKCsPOQ8VX+h8xOe3dxRjgnCAJ33nk+VOYiaZTy48BK2bfw== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-error" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-error" "^1.5.1" "@swaggerexpert/json-pointer" "^2.10.1" -"@swagger-api/apidom-ns-api-design-systems@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-api-design-systems/-/apidom-ns-api-design-systems-1.5.0.tgz#2fbefee01991f61d18a715d6e34c51d762ae9a3d" - integrity sha512-jt8hCcN/NhmZPMMGy7DNbw1LHu7gUqcNkG840aC2OUVj+qHp7CDG7wing0F2zIW3+fDfw+UIiVzFy7oVbiiheg== +"@swagger-api/apidom-ns-api-design-systems@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-api-design-systems/-/apidom-ns-api-design-systems-1.5.1.tgz#1ebab1c006c3d65d16b435dab84e78d4d6c245c6" + integrity sha512-YQJdNb6TJQ8lNa1o8ThfT0P7DY/cGhnI4Se8YiGIsdTPSBOiPtTY72+lfsM1O+3bOeAy7n/MvWRXrJuiKGf7Pg== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-error" "^1.5.0" - "@swagger-api/apidom-ns-openapi-3-1" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-error" "^1.5.1" + "@swagger-api/apidom-ns-openapi-3-1" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" ts-mixer "^6.0.3" -"@swagger-api/apidom-ns-arazzo-1@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-arazzo-1/-/apidom-ns-arazzo-1-1.5.0.tgz#305f41d7cb8aab5cf0682f1c5ece259f45d978ec" - integrity sha512-ATkcwJfyu3rhwLwicCmARhfQM6/KRGZ2+Y5HuG5smPxzzDdgb0o5/VP9goSvxgfAveIJsEWFbP6CMm/LW4Gy3A== +"@swagger-api/apidom-ns-arazzo-1@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-arazzo-1/-/apidom-ns-arazzo-1-1.5.1.tgz#e43e6a85e30075a1357652e1b350d1421b1f7c28" + integrity sha512-hC/AD9TG3DMex+UAlYmg3fKcbmgrLGyZ3Fm2KqJfaC3CkiYE6SdVtfCBK9mPOcArPVa2RfzSgU4aRYzClDmvNQ== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-json-schema-2020-12" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-json-schema-2020-12" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" ts-mixer "^6.0.3" -"@swagger-api/apidom-ns-asyncapi-2@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-asyncapi-2/-/apidom-ns-asyncapi-2-1.5.0.tgz#bfd1d78570f1f3294d6600c122ba8710467a26ec" - integrity sha512-luYRreqMhHRSGQWEOt8I8Pd12Up2tl66w1oCBBJHwzc97j8a9sN6S0s6FuJS+LLajJgyDwwL6msgP5r92W9Ppw== +"@swagger-api/apidom-ns-asyncapi-2@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-asyncapi-2/-/apidom-ns-asyncapi-2-1.5.1.tgz#ea69d970f81ca137183137a42599a3f161fbfd70" + integrity sha512-9k97IdvSde7OaGwE8opX9psjmhsRYkuKm5eCmM3n6WOZkwdJFD73bCtYVqCuDCVRzJwT9xMras4fVG5Zn1Vhcw== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-json-schema-draft-7" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-json-schema-draft-7" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" ts-mixer "^6.0.3" -"@swagger-api/apidom-ns-asyncapi-3@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-asyncapi-3/-/apidom-ns-asyncapi-3-1.5.0.tgz#85d8c76f104e37606355f8a733a97a363c432ecc" - integrity sha512-Xvj6tAVchSkki9rWb5d9KzHbr7f0EmO8tZ6rfqEQHlx+XGAOoMzlRrwjvPvrn/8+wOI8E/AxVw25TuRfxiHMAQ== +"@swagger-api/apidom-ns-asyncapi-3@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-asyncapi-3/-/apidom-ns-asyncapi-3-1.5.1.tgz#f818337f88562fbc9a63f8e0b25415e737b2c694" + integrity sha512-EQGnSP93yB8ZDhaESqtavnynySH/hjkdkb4tInRoKYN3j3WU+in6Bvxwq2qCkyH9ACaSbW2HFlT2qIRBcLW+oA== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-asyncapi-2" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-asyncapi-2" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" ts-mixer "^6.0.3" -"@swagger-api/apidom-ns-json-schema-2019-09@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-json-schema-2019-09/-/apidom-ns-json-schema-2019-09-1.5.0.tgz#0fea21e17839eea0815ff1206b59270ba744d602" - integrity sha512-xd4Fhs3YSqKNDO7yhs7u+mcrEi9gBIo2i1NjUDAX4YLs4QPwACq4ruEp1VihSrgunv/A1dQvmQcLpjpTsoqtIg== +"@swagger-api/apidom-ns-json-schema-2019-09@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-json-schema-2019-09/-/apidom-ns-json-schema-2019-09-1.5.1.tgz#a3c23aa09b52cce54292c26e3bb2a651dd523035" + integrity sha512-peszjtx5OPUYsvl/t4XTRVt0vY0WfR7jBpcmq3/ioqAaddhfbnb4i3PPWWhAIzzeKAiFHc/m4E5HCMMdDF2wDA== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-error" "^1.5.0" - "@swagger-api/apidom-ns-json-schema-draft-7" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-error" "^1.5.1" + "@swagger-api/apidom-ns-json-schema-draft-7" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" ts-mixer "^6.0.4" -"@swagger-api/apidom-ns-json-schema-2020-12@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-json-schema-2020-12/-/apidom-ns-json-schema-2020-12-1.5.0.tgz#6ba01d6b7c21d85441556106867108bfc1cf6f84" - integrity sha512-+WdWwrLpdZaEDqS5uzVUJ34emCZSNOzqs2AfrxopOenbQM/Th29lHrTt2Zu6L4xhlp8HTUaqIb8nnkjVd/wheg== +"@swagger-api/apidom-ns-json-schema-2020-12@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-json-schema-2020-12/-/apidom-ns-json-schema-2020-12-1.5.1.tgz#0149439f0d16fbef2a8aba8cd92344363a61ece6" + integrity sha512-4L6X5SxkXCD4W7O0KI8e3kc0Q8TkVg0kPSNOWYosGAHOk9g5KyMIbACDjZhJ2q+uPlyLFCLAPY93aOVaVZ+nsA== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-error" "^1.5.0" - "@swagger-api/apidom-ns-json-schema-2019-09" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-error" "^1.5.1" + "@swagger-api/apidom-ns-json-schema-2019-09" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" ts-mixer "^6.0.4" -"@swagger-api/apidom-ns-json-schema-draft-4@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-1.5.0.tgz#d77b7e04e544985676480340245ec566097f710b" - integrity sha512-YxGZcTjXuKOPX2DHhSM3SBtxzriXs/8blNIBouIxqtalythud+nyi2sx1pQllBraBDsqQl3q5nCNXufum+TrNw== +"@swagger-api/apidom-ns-json-schema-draft-4@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-1.5.1.tgz#7be28fed4470ce292db34820e9311f4d6fc4582b" + integrity sha512-vdc+vVLwf4JwDeK4mPfZqyVHG5gJc766GkqH522VRTh1XWJPlW674lIJuhqo5HLzXLm4zV4alI/QJMR3fRWFIQ== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-ast" "^1.5.0" - "@swagger-api/apidom-core" "^1.5.0" + "@swagger-api/apidom-ast" "^1.5.1" + "@swagger-api/apidom-core" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" ts-mixer "^6.0.4" -"@swagger-api/apidom-ns-json-schema-draft-6@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-json-schema-draft-6/-/apidom-ns-json-schema-draft-6-1.5.0.tgz#06997b77debab77d4cc8841b2a8a2fd50d860da0" - integrity sha512-OOzP1Xi/GETOQ4qEksoESsq7CV7mW51aYk8T7yKArWocT3dJ9pn6smmpNmd3MnGVXJFumscKHCQzYrjnCQE6/A== +"@swagger-api/apidom-ns-json-schema-draft-6@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-json-schema-draft-6/-/apidom-ns-json-schema-draft-6-1.5.1.tgz#6900ebb8c04ee83c316a54f733f2c9f2d63221dc" + integrity sha512-sNRDQybpzl16HwktI0by0nWj85Rpmx/K1Qc6e4uQRmpPeozJTi8hAdyxw9ays1WJI+Bao9YEz+xJNAqNIE5xlg== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-error" "^1.5.0" - "@swagger-api/apidom-ns-json-schema-draft-4" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-error" "^1.5.1" + "@swagger-api/apidom-ns-json-schema-draft-4" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" ts-mixer "^6.0.4" -"@swagger-api/apidom-ns-json-schema-draft-7@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-json-schema-draft-7/-/apidom-ns-json-schema-draft-7-1.5.0.tgz#61cea5d602904a4ded624a1c3cadbc6dc4dad154" - integrity sha512-lL8S8Qmm5gc386bYfO4ptL1BVlN5Htg3QITXew8y6EItAo8syXCPkWy7h8JXC76vGVMNLr1KAISuZ0dzqz3Yow== +"@swagger-api/apidom-ns-json-schema-draft-7@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-json-schema-draft-7/-/apidom-ns-json-schema-draft-7-1.5.1.tgz#68b70a698eff3fdbfd34222127dae3e41f656137" + integrity sha512-hdgYjOzZCN866F/BP5tuReZmVTZF2NTNykOwILhR/uoDR2YvgvwvHbnifsywLhreZOkhf3HIbfvCkQnIopkluw== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-error" "^1.5.0" - "@swagger-api/apidom-ns-json-schema-draft-6" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-error" "^1.5.1" + "@swagger-api/apidom-ns-json-schema-draft-6" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" ts-mixer "^6.0.4" -"@swagger-api/apidom-ns-openapi-2@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-openapi-2/-/apidom-ns-openapi-2-1.5.0.tgz#2a486b1d8c646ba19343816ffba4e143e36dcd14" - integrity sha512-i8quM2983OaWJf4/44CeFwzZI0Kr0W4i54lfbKw88kcZWgYB5OXqdUcbOX9g15z2bd+IpmLzmeWjY5O0WiXWKg== +"@swagger-api/apidom-ns-openapi-2@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-openapi-2/-/apidom-ns-openapi-2-1.5.1.tgz#96c090e7397592d9ec146dadda5d1741bb1b0497" + integrity sha512-KnFYGqvlHBeczLs5P1R1dCfDGW3O7LaLu/AmFLRvt0ya8AXwkF4gd5gHsXKn0lXBeAc3kEwHAValtg6WNR8keQ== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-error" "^1.5.0" - "@swagger-api/apidom-ns-json-schema-draft-4" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-error" "^1.5.1" + "@swagger-api/apidom-ns-json-schema-draft-4" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" ts-mixer "^6.0.3" -"@swagger-api/apidom-ns-openapi-3-0@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-1.5.0.tgz#dcb184aeaa0a78c780ce9dfaebcf60f730737fd4" - integrity sha512-P+97SVL+uomuO1lmByBcXZLkZjHJCZ/7hTPbMmmm40f0J6Se46tRuakImaQLtZld5X067aSxYVo9/npm+VecMQ== +"@swagger-api/apidom-ns-openapi-3-0@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-1.5.1.tgz#fe40bf412b7e1cd3881e176c8bf522041f5b9ca2" + integrity sha512-n3KaIh7dVkINDC7g8osBpxvYCZnsDHHg8rOvOYy1kKlZHi7xd3Ui83rDnKCsOsdsKlFdIdd6isBcBEBQazgwPA== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-error" "^1.5.0" - "@swagger-api/apidom-ns-json-schema-draft-4" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-error" "^1.5.1" + "@swagger-api/apidom-ns-json-schema-draft-4" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" ts-mixer "^6.0.3" -"@swagger-api/apidom-ns-openapi-3-1@^1.3.0", "@swagger-api/apidom-ns-openapi-3-1@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-1.5.0.tgz#76dadf14e37fdfb25e185168f3e99b60af891cd9" - integrity sha512-8tIL0Kz+3FYelW+zoWd8/5Pj5neDOD4nOV4GJbmLntfQRjboi1ki/eoKqHJvhBBrMSzgBZidgBauzK7HipTZ8A== +"@swagger-api/apidom-ns-openapi-3-1@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-1.5.1.tgz#593a8e5d101e3cf477b25bf6e03912de4eb6fe8d" + integrity sha512-rJPZH969I67snT6ux3Dve5QXaHCfm/phv20kAojR50fW5FPbR+nn4a9FIi59F3OrD69zQascKUrJb24ieFVHIw== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-ast" "^1.5.0" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-json-pointer" "^1.5.0" - "@swagger-api/apidom-ns-json-schema-2020-12" "^1.5.0" - "@swagger-api/apidom-ns-openapi-3-0" "^1.5.0" + "@swagger-api/apidom-ast" "^1.5.1" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-json-pointer" "^1.5.1" + "@swagger-api/apidom-ns-json-schema-2020-12" "^1.5.1" + "@swagger-api/apidom-ns-openapi-3-0" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" ts-mixer "^6.0.3" -"@swagger-api/apidom-parser-adapter-api-design-systems-json@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-api-design-systems-json/-/apidom-parser-adapter-api-design-systems-json-1.5.0.tgz#50c098a19520290f16288d4a8cb7b2373e1f107e" - integrity sha512-BeX09CAvJYuwwg6uxtHBWOdrviF7Q0ylve2Qc4U5M8TST5Cff2X8H6y26WU6ss6te/VsFYMtkZw6uYf78m9kXA== +"@swagger-api/apidom-parser-adapter-api-design-systems-json@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-api-design-systems-json/-/apidom-parser-adapter-api-design-systems-json-1.5.1.tgz#95f5c4d4939f6456e2e1160b0e95f5270f735d8f" + integrity sha512-XomzUhgy+w1toxJMjN1mXKITl88QPiug4e9eyNWSEQkoCD1ko0MEVZYA6/6mjwlTW2DQ4qg+XF+TFmOPlkQWeA== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-api-design-systems" "^1.5.0" - "@swagger-api/apidom-parser-adapter-json" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-api-design-systems" "^1.5.1" + "@swagger-api/apidom-parser-adapter-json" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-api-design-systems-yaml@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/-/apidom-parser-adapter-api-design-systems-yaml-1.5.0.tgz#8ee3406106e81c6678d795ba462894610e7a1891" - integrity sha512-OBP/ccJLkZA0TEgzZvzuVOnv/2ic1Q3xW1BkTEGUapAqG0qBuUFNVjiIBVWKbPA88BP4vamvTxtT/nhnraC04w== +"@swagger-api/apidom-parser-adapter-api-design-systems-yaml@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/-/apidom-parser-adapter-api-design-systems-yaml-1.5.1.tgz#ec40c54fd9bcb389ef79cf84d8ed5e3c259e9607" + integrity sha512-pfa+iQwMLhDcE4CYi4pUHraAOUUo2DNeRRWZGhregWZoZPo5gVZ8w9NwSowLE19zf922A9RfzBkouI969j27QQ== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-api-design-systems" "^1.5.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-api-design-systems" "^1.5.1" + "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-arazzo-json-1@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-arazzo-json-1/-/apidom-parser-adapter-arazzo-json-1-1.5.0.tgz#f64679ed650fda1a9df9f2e4585dceed5b9aad56" - integrity sha512-mpJoq0zhvweYoctl8IfjcmYPQVWaFptEpNq0AtjXYvHp1bNNTLV/Q+oRKOO4odSPTyoHVzJjahtwgxP1DqXBag== +"@swagger-api/apidom-parser-adapter-arazzo-json-1@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-arazzo-json-1/-/apidom-parser-adapter-arazzo-json-1-1.5.1.tgz#e0d05b7278382efde19bbcb8b97aef1d2686917e" + integrity sha512-pJrlCospvJDvh8mqLjyb0ILRPuD3rYaZlTRs340W2ADgn6m+ClrDBQwXCod5QrKmcjYqAhtLZXwnwSuZStaj+Q== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-arazzo-1" "^1.5.0" - "@swagger-api/apidom-parser-adapter-json" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-arazzo-1" "^1.5.1" + "@swagger-api/apidom-parser-adapter-json" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-arazzo-yaml-1@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-arazzo-yaml-1/-/apidom-parser-adapter-arazzo-yaml-1-1.5.0.tgz#819b6ca62399d8459ceaeb82fdd09edc7493a658" - integrity sha512-WNC4C8U+cb8kprYFWziMtnO+9/mZuJ5BYXCe79vCH9G9CTDcmoDD1HeYkpAon4BKAI4jNbsZ4boF09ineAHFSQ== +"@swagger-api/apidom-parser-adapter-arazzo-yaml-1@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-arazzo-yaml-1/-/apidom-parser-adapter-arazzo-yaml-1-1.5.1.tgz#995bef03e90d5004d994afb13d5853dad27b36b7" + integrity sha512-Q/EZ9BGnBlj4TiEQ+Q4k/pdgZ/Le+/ppZSfcc22umnKujDNyBLGB5L0sSfTOEjANRYNo+UtPYnkctwTkJu3/ZQ== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-arazzo-1" "^1.5.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-arazzo-1" "^1.5.1" + "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-asyncapi-json-2@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-asyncapi-json-2/-/apidom-parser-adapter-asyncapi-json-2-1.5.0.tgz#833d5ad846fde1561615bc40ca39c198ab247399" - integrity sha512-9xL8PTHqBv1oBZpTlST596n/TBAuHRa+t41OrThQIg+6mqkQFy6jqf/nFFe4B6MQyOURNLcII4VNcdBVwvHSpQ== +"@swagger-api/apidom-parser-adapter-asyncapi-json-2@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-asyncapi-json-2/-/apidom-parser-adapter-asyncapi-json-2-1.5.1.tgz#54accbfb97aa85fc9df46ec215f31b49ffa69d23" + integrity sha512-GRM5iCz9eRMiTSV4iAlpuWM6q3SBndSmEMhgjDuclWiC3HF78CCNuT9KwYNFMAx1bEe5Fr8c8Gs8KNckdeCU4g== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-asyncapi-2" "^1.5.0" - "@swagger-api/apidom-parser-adapter-json" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-asyncapi-2" "^1.5.1" + "@swagger-api/apidom-parser-adapter-json" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-asyncapi-json-3@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-asyncapi-json-3/-/apidom-parser-adapter-asyncapi-json-3-1.5.0.tgz#4a44a1a20879eafb8f1759c4b7e05ae69746b151" - integrity sha512-ySX+YuSMiJUR5CMox3GBotiT9vtA7jdZz+ZD7XC2zb4RGfayGtHX02QBqBarlgoZIVorP4+ps6ol0+Zg55vbYA== +"@swagger-api/apidom-parser-adapter-asyncapi-json-3@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-asyncapi-json-3/-/apidom-parser-adapter-asyncapi-json-3-1.5.1.tgz#5258b13a6107a209afd4f6d73f1ee1086fc21651" + integrity sha512-TCMm7Ce9PwzTQw2SnRYR0smCnrE6bmGbVsjqVz4d+tQy8h6ZNkfjAqOtBasKr/KpEywpLCRgWC2YRNAHGKLndw== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-asyncapi-3" "^1.5.0" - "@swagger-api/apidom-parser-adapter-json" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-asyncapi-3" "^1.5.1" + "@swagger-api/apidom-parser-adapter-json" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/-/apidom-parser-adapter-asyncapi-yaml-2-1.5.0.tgz#bcb0a9f444820e48f95af1afee022193ce5cf9ba" - integrity sha512-E+SY7E1nE4A40fgrZvKy0U0nXYAWk4sHTCIp0uxpfkzBXq5wp7IU+wr6E56THzuNF0HaNMzzSfi6agNad30bPg== +"@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/-/apidom-parser-adapter-asyncapi-yaml-2-1.5.1.tgz#6069c15ab5d08615bed5d2fc044b737d45b14aa4" + integrity sha512-sZQ/7kOs7+apKq22uyhF3jmhPTzt7y8Xy8cGPIp1b0PnQhbm7rT1/rrOl9qh9MqCdUip2Dx0Y+WTyyET0faZ4g== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-asyncapi-2" "^1.5.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-asyncapi-2" "^1.5.1" + "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-asyncapi-yaml-3@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-asyncapi-yaml-3/-/apidom-parser-adapter-asyncapi-yaml-3-1.5.0.tgz#6b688b797bfcda9e5ce59c0637833d0900101d02" - integrity sha512-NCwY+ZcmEjwabbDp1/uQtnNWfSd1KI9ikM6McM4aOWHp4b24AdClbTl1W5QXskM2f9g45TadmWR8Ol7yex6H3g== +"@swagger-api/apidom-parser-adapter-asyncapi-yaml-3@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-asyncapi-yaml-3/-/apidom-parser-adapter-asyncapi-yaml-3-1.5.1.tgz#910200002c2c619c113f2a59533295a52fbef90f" + integrity sha512-bYoyX/qP9SmGF6DKohPO1Fguz8/8uHF8ieSo04jrQblHbEeDVcTBG6oTFVNcpG2ZxnqaoNF2/KY4/fUSKMH/4g== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-asyncapi-3" "^1.5.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-asyncapi-3" "^1.5.1" + "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-json@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-json/-/apidom-parser-adapter-json-1.5.0.tgz#1b7f228bdf8bb806b4cf78ef8190e844e02a8704" - integrity sha512-pSavF+9zuaaEoQ5lHqfYoHpo4sKBAnZGQcLAGI6ZhpNOHkxFkcmDd/hNYI0gM9g7NuwX6+xFBZi29OYsA4qtlw== +"@swagger-api/apidom-parser-adapter-json@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-json/-/apidom-parser-adapter-json-1.5.1.tgz#6cb79641f78389d4a7af916ae284092f0dc8b8c1" + integrity sha512-zYXchiHC5wsvCImr4lgrhwuLWDH3EDz4L4KJbp8ltO1Y+3PRwPYNruKVppHdIC6d+eTBy4e110a4629rl6LQTg== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-ast" "^1.5.0" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-error" "^1.5.0" + "@swagger-api/apidom-ast" "^1.5.1" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-error" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" - tree-sitter "=0.22.4" + tree-sitter "=0.21.1" tree-sitter-json "=0.24.8" web-tree-sitter "=0.24.5" -"@swagger-api/apidom-parser-adapter-openapi-json-2@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-json-2/-/apidom-parser-adapter-openapi-json-2-1.5.0.tgz#1588a73503d51ddffd4ae5a36dfd4586818884a7" - integrity sha512-O9ndJK/oOiPnY0UmrqIDYFAL4bODT3PJFa8bVVORKr+ZdUPg/xRZL/kgWgA8uOBfTuKU57sQvFvTOV8omyeURQ== +"@swagger-api/apidom-parser-adapter-openapi-json-2@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-json-2/-/apidom-parser-adapter-openapi-json-2-1.5.1.tgz#d46b74ab848563462433149d8587c7a9b5936103" + integrity sha512-05SXfF5ate18FKlPBg4YEfyS6Sr4lmu+gppxMQ202x172ejBQjAU37iZeSKfKw1egXngAmm6OZqWGKn36WD/fw== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-openapi-2" "^1.5.0" - "@swagger-api/apidom-parser-adapter-json" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-openapi-2" "^1.5.1" + "@swagger-api/apidom-parser-adapter-json" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-openapi-json-3-0@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-json-3-0/-/apidom-parser-adapter-openapi-json-3-0-1.5.0.tgz#2bb0718005d9b658a350480cb4fbbee7df617993" - integrity sha512-qxh/sV54E6Y8VknvzAu/21r8ElxB1N3mmCnxTh1q6AUo6MX0SWCmnL1E2v3/2/HlJAA6yHW4RjwdKAv90Wklxw== +"@swagger-api/apidom-parser-adapter-openapi-json-3-0@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-json-3-0/-/apidom-parser-adapter-openapi-json-3-0-1.5.1.tgz#8fe6b58ecad4182998dd1afe752b48ba9c9dd697" + integrity sha512-AG68rFxilJwQuwgYUlbSX89j96CzFwm7MLsMbd1Pe2k8bsZJF41bxYEWLck08hQ0v8HikZ7igJLGvkwm9Fk6EQ== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-openapi-3-0" "^1.5.0" - "@swagger-api/apidom-parser-adapter-json" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-openapi-3-0" "^1.5.1" + "@swagger-api/apidom-parser-adapter-json" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-openapi-json-3-1@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-json-3-1/-/apidom-parser-adapter-openapi-json-3-1-1.5.0.tgz#3d57fa9327caa58919bbbaab46d6435d76238460" - integrity sha512-DAMwQlrZj8b9lBj4G4huWLPoOHmOASe0JFFfhu18kmcCFtUSOR5UsCTvbJDyOuztOyKCT/HIMXp3/OEKbU8y6w== +"@swagger-api/apidom-parser-adapter-openapi-json-3-1@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-json-3-1/-/apidom-parser-adapter-openapi-json-3-1-1.5.1.tgz#4e91a8af381cf8ac27f515c2fe7b3c69ce4e2bef" + integrity sha512-UYuaUegcqsR8DbqUS9gJnzdV/g7P61HfgjO620soSHwvDRlHCdgxd71dnaBZWT22+as8vuZABAzjQuKrtiej2g== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-openapi-3-1" "^1.5.0" - "@swagger-api/apidom-parser-adapter-json" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-openapi-3-1" "^1.5.1" + "@swagger-api/apidom-parser-adapter-json" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-openapi-yaml-2@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-yaml-2/-/apidom-parser-adapter-openapi-yaml-2-1.5.0.tgz#25fc96b4799e110805cbf26b36ed0bb194be6cfe" - integrity sha512-KHPrgAY1g5Fucy+BFDdzUrGaFaVr86d3IgWFvifnKUQGpz96zMMaGG+IWsUoSfoAQaJSHpz+SVnNFaIF2sLOfQ== +"@swagger-api/apidom-parser-adapter-openapi-yaml-2@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-yaml-2/-/apidom-parser-adapter-openapi-yaml-2-1.5.1.tgz#6d3acbe72527dcfd8e9f6d093295229dacc35dd2" + integrity sha512-d64JVYhBa5O6Kz2H/Wr1gLf5la0T1gZ22XIf2ABPTHga8fKQjEFDhFifxVS65NX9cOglcXQo9sRvD4AZkRMEkQ== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-openapi-2" "^1.5.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-openapi-2" "^1.5.1" + "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/-/apidom-parser-adapter-openapi-yaml-3-0-1.5.0.tgz#271317818c550a4e04bac262069faea75fd76b55" - integrity sha512-owFoZyqiRsSUtDEuSafLGWHwupVeh+pcspfnQy2sl7bmYmsi73NMJpsdIMcizlyeOqav0MWQ7FNrBZOSctiPIQ== +"@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/-/apidom-parser-adapter-openapi-yaml-3-0-1.5.1.tgz#fdf3a2db31886ac341d31dee386f199a018d1e28" + integrity sha512-MgyCo6rz+jH1cR5CpKleT1HOXOLoK2LuP7CrEGsuRNCA4nR6w/H4T75XYxUCWO/9T3870vkxDM8hp8IRW5xtQg== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-openapi-3-0" "^1.5.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-openapi-3-0" "^1.5.1" + "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/-/apidom-parser-adapter-openapi-yaml-3-1-1.5.0.tgz#861cd60bc20dcaead77cbf0cb69c066632d36d58" - integrity sha512-9NcPLDbXZTftx9cMDh9iW+nXLeFFFTCuRyXKvtV+tu3PEiACMUIi0ij5J6+NZ3sBQVaEp7qF7nqzPIT2JRZHzw== +"@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/-/apidom-parser-adapter-openapi-yaml-3-1-1.5.1.tgz#a80ce67e2220c7bf9f64495246bf29b981e03018" + integrity sha512-9ED9pmYqCfKqfeeDtGrXU7+gISjt6bh93XO5qCexwfHCbzrTdjiMcWMTCnaRjXvgv819LAKUDIDnnn88EGpUNg== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-ns-openapi-3-1" "^1.5.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-ns-openapi-3-1" "^1.5.1" + "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" ramda-adjunct "^5.0.0" -"@swagger-api/apidom-parser-adapter-yaml-1-2@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-yaml-1-2/-/apidom-parser-adapter-yaml-1-2-1.5.0.tgz#bd3d0a802ba9307dfeb2fe445f4fcf8de5712262" - integrity sha512-TBpyfwQ0aFWmVlpI4aKMVwoPM3bLxtc9MzDchjo5BXWLfpYIXNbI72VzzeEeUnauC9I5kTomT4xQKZQzNtEGnw== +"@swagger-api/apidom-parser-adapter-yaml-1-2@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-yaml-1-2/-/apidom-parser-adapter-yaml-1-2-1.5.1.tgz#42e856ec5be1c5b2f4a3a79db60c7836d66f8189" + integrity sha512-jMZUwbS7P2n/3BG+w0Mg+G2m6tY1zuDCACTpVh3UjIMl15k+6VIyB49kKIs1q9BZRX8rbnJmmzpYcjhjDOgaqA== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-ast" "^1.5.0" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-error" "^1.5.0" + "@swagger-api/apidom-ast" "^1.5.1" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-error" "^1.5.1" "@tree-sitter-grammars/tree-sitter-yaml" "=0.7.1" "@types/ramda" "~0.30.0" ramda "~0.30.0" @@ -3991,43 +3991,42 @@ tree-sitter "=0.22.4" web-tree-sitter "=0.24.5" -"@swagger-api/apidom-reference@^1.3.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-reference/-/apidom-reference-1.5.0.tgz#e6c8e4f83582eee97ddb78883d159080177bce44" - integrity sha512-6PrvPqAecUcYkMlJGK4g7wEcpSAMTAOysxGAxfF42JRD6pAkAqAiGAzCGrucZXzK9UyRqfchloUlv/5fqnQ+CQ== +"@swagger-api/apidom-reference@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swagger-api/apidom-reference/-/apidom-reference-1.5.1.tgz#2b7b6a041fb0ad4636a347bfebcd9d796bc86a94" + integrity sha512-KppyiuQ8EY1vnhb2RsCty60DKYP1jszmxNKHAAGaMgKOmTcoGCvPNDl0Fn6IPlEfXsy3yqYn1CsEePC3BcGtHg== dependencies: "@babel/runtime-corejs3" "^7.26.10" - "@swagger-api/apidom-core" "^1.5.0" - "@swagger-api/apidom-error" "^1.5.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-error" "^1.5.1" "@types/ramda" "~0.30.0" axios "^1.12.2" - minimatch "^7.4.3" - process "^0.11.10" + minimatch "^10.2.1" ramda "~0.30.0" ramda-adjunct "^5.0.0" optionalDependencies: - "@swagger-api/apidom-json-pointer" "^1.5.0" - "@swagger-api/apidom-ns-arazzo-1" "^1.5.0" - "@swagger-api/apidom-ns-asyncapi-2" "^1.5.0" - "@swagger-api/apidom-ns-openapi-2" "^1.5.0" - "@swagger-api/apidom-ns-openapi-3-0" "^1.5.0" - "@swagger-api/apidom-ns-openapi-3-1" "^1.5.0" - "@swagger-api/apidom-parser-adapter-api-design-systems-json" "^1.5.0" - "@swagger-api/apidom-parser-adapter-api-design-systems-yaml" "^1.5.0" - "@swagger-api/apidom-parser-adapter-arazzo-json-1" "^1.5.0" - "@swagger-api/apidom-parser-adapter-arazzo-yaml-1" "^1.5.0" - "@swagger-api/apidom-parser-adapter-asyncapi-json-2" "^1.5.0" - "@swagger-api/apidom-parser-adapter-asyncapi-json-3" "^1.5.0" - "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2" "^1.5.0" - "@swagger-api/apidom-parser-adapter-asyncapi-yaml-3" "^1.5.0" - "@swagger-api/apidom-parser-adapter-json" "^1.5.0" - "@swagger-api/apidom-parser-adapter-openapi-json-2" "^1.5.0" - "@swagger-api/apidom-parser-adapter-openapi-json-3-0" "^1.5.0" - "@swagger-api/apidom-parser-adapter-openapi-json-3-1" "^1.5.0" - "@swagger-api/apidom-parser-adapter-openapi-yaml-2" "^1.5.0" - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0" "^1.5.0" - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1" "^1.5.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.0" + "@swagger-api/apidom-json-pointer" "^1.5.1" + "@swagger-api/apidom-ns-arazzo-1" "^1.5.1" + "@swagger-api/apidom-ns-asyncapi-2" "^1.5.1" + "@swagger-api/apidom-ns-openapi-2" "^1.5.1" + "@swagger-api/apidom-ns-openapi-3-0" "^1.5.1" + "@swagger-api/apidom-ns-openapi-3-1" "^1.5.1" + "@swagger-api/apidom-parser-adapter-api-design-systems-json" "^1.5.1" + "@swagger-api/apidom-parser-adapter-api-design-systems-yaml" "^1.5.1" + "@swagger-api/apidom-parser-adapter-arazzo-json-1" "^1.5.1" + "@swagger-api/apidom-parser-adapter-arazzo-yaml-1" "^1.5.1" + "@swagger-api/apidom-parser-adapter-asyncapi-json-2" "^1.5.1" + "@swagger-api/apidom-parser-adapter-asyncapi-json-3" "^1.5.1" + "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2" "^1.5.1" + "@swagger-api/apidom-parser-adapter-asyncapi-yaml-3" "^1.5.1" + "@swagger-api/apidom-parser-adapter-json" "^1.5.1" + "@swagger-api/apidom-parser-adapter-openapi-json-2" "^1.5.1" + "@swagger-api/apidom-parser-adapter-openapi-json-3-0" "^1.5.1" + "@swagger-api/apidom-parser-adapter-openapi-json-3-1" "^1.5.1" + "@swagger-api/apidom-parser-adapter-openapi-yaml-2" "^1.5.1" + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0" "^1.5.1" + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1" "^1.5.1" + "@swagger-api/apidom-parser-adapter-yaml-1-2" "^1.5.1" "@swaggerexpert/cookie@^2.0.2": version "2.0.2" @@ -5511,6 +5510,11 @@ balanced-match@^1.0.0: resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +balanced-match@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-4.0.3.tgz#6337a2f23e0604a30481423432f99eac603599f9" + integrity sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g== + base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" @@ -5622,6 +5626,13 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" +brace-expansion@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-5.0.2.tgz#b6c16d0791087af6c2bc463f52a8142046c06b6f" + integrity sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw== + dependencies: + balanced-match "^4.0.2" + braces@^3.0.3, braces@~3.0.2: version "3.0.3" resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" @@ -10783,6 +10794,13 @@ minimatch@3.1.2, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +minimatch@^10.2.1: + version "10.2.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.2.2.tgz#361603ee323cfb83496fea2ae17cc44ea4e1f99f" + integrity sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw== + dependencies: + brace-expansion "^5.0.2" + minimatch@^5.0.1: version "5.1.6" resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz" @@ -10790,13 +10808,6 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^7.4.3: - version "7.4.6" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz" - integrity sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw== - dependencies: - brace-expansion "^2.0.1" - minimatch@^9.0.5: version "9.0.5" resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" @@ -10914,7 +10925,7 @@ node-addon-api@^7.0.0: resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz" integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== -node-addon-api@^8.2.2, node-addon-api@^8.3.0, node-addon-api@^8.3.1: +node-addon-api@^8.0.0, node-addon-api@^8.2.2, node-addon-api@^8.3.0, node-addon-api@^8.3.1: version "8.5.0" resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz" integrity sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A== @@ -10961,7 +10972,7 @@ node-forge@^1: resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz" integrity sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw== -node-gyp-build@^4.8.2, node-gyp-build@^4.8.4: +node-gyp-build@^4.8.0, node-gyp-build@^4.8.2, node-gyp-build@^4.8.4: version "4.8.4" resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz" integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== @@ -14015,18 +14026,18 @@ svgo@^3.0.2, svgo@^3.2.0: csso "^5.0.5" picocolors "^1.0.0" -swagger-client@^3.36.1: - version "3.36.1" - resolved "https://registry.yarnpkg.com/swagger-client/-/swagger-client-3.36.1.tgz#f3b5b1a727d0210bc94adddb9ea28a1c75cdb122" - integrity sha512-bcYpeN4P3sOoKi22zsxIlL9lSgouBAmQmL5hH4g5yeOvyTUvq1+OFtGTs0l1C5Dkb0ZN+2vNgp0FBAFulmUklA== +swagger-client@^3.36.2: + version "3.36.2" + resolved "https://registry.yarnpkg.com/swagger-client/-/swagger-client-3.36.2.tgz#e54e1d9a51036d01e6fb394ab8200b083966aa76" + integrity sha512-M+m0TpZTWtVMvd0Qiq5W2ABLmY6w8PnnqnMIKgT/nYS/w6hZ4s1sBCCS/w4SOjmAyy0QT/kl3tNh2jPWIkaI3A== dependencies: "@babel/runtime-corejs3" "^7.22.15" "@scarf/scarf" "=1.4.0" - "@swagger-api/apidom-core" "^1.3.0" - "@swagger-api/apidom-error" "^1.3.0" - "@swagger-api/apidom-json-pointer" "^1.3.0" - "@swagger-api/apidom-ns-openapi-3-1" "^1.3.0" - "@swagger-api/apidom-reference" "^1.3.0" + "@swagger-api/apidom-core" "^1.5.1" + "@swagger-api/apidom-error" "^1.5.1" + "@swagger-api/apidom-json-pointer" "^1.5.1" + "@swagger-api/apidom-ns-openapi-3-1" "^1.5.1" + "@swagger-api/apidom-reference" "^1.5.1" "@swaggerexpert/cookie" "^2.0.2" deepmerge "~4.3.0" fast-json-patch "^3.0.0-1" @@ -14039,10 +14050,10 @@ swagger-client@^3.36.1: ramda "^0.30.1" ramda-adjunct "^5.1.0" -swagger-ui-react@^5.31.1: - version "5.31.1" - resolved "https://registry.yarnpkg.com/swagger-ui-react/-/swagger-ui-react-5.31.1.tgz#7603c365eed5e9819036aa05bcf26ae6a3fb20cc" - integrity sha512-4SLhM7Ofq3e28wceOHGQRUpwIs5emUH1b0iYWaIPlDcTc8HFxvLYR2ft+/1CdLO7mXcFcDvnNI5Z/nGKNcZ0Lg== +swagger-ui-react@^5.31.2: + version "5.31.2" + resolved "https://registry.yarnpkg.com/swagger-ui-react/-/swagger-ui-react-5.31.2.tgz#535ef6bf994231f9417420eecf56ad881a79522f" + integrity sha512-0BwMRS07mJ30rPSZrjAsZP/vJxWTvIjxiRCm7GAoLQ/0259vy2uHtz+GtVuAbohOpmziE/F4l6QQLf0w34MuQw== dependencies: "@babel/runtime-corejs3" "^7.27.1" "@scarf/scarf" "=1.4.0" @@ -14073,7 +14084,7 @@ swagger-ui-react@^5.31.1: reselect "^5.1.1" serialize-error "^8.1.0" sha.js "^2.4.12" - swagger-client "^3.36.1" + swagger-client "^3.36.2" url-parse "^1.5.10" xml "=1.0.1" xml-but-prettier "^1.0.1" @@ -14265,6 +14276,14 @@ tree-sitter-json@=0.24.8: node-addon-api "^8.2.2" node-gyp-build "^4.8.2" +tree-sitter@=0.21.1: + version "0.21.1" + resolved "https://registry.yarnpkg.com/tree-sitter/-/tree-sitter-0.21.1.tgz#fbb34c09056700814af0e1e37688e06463ba04c4" + integrity sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ== + dependencies: + node-addon-api "^8.0.0" + node-gyp-build "^4.8.0" + tree-sitter@=0.22.4: version "0.22.4" resolved "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.22.4.tgz" diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index e6b6f27aa5f3..511f15e2e297 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -266,7 +266,7 @@ "lightningcss": "^1.31.1", "mini-css-extract-plugin": "^2.10.0", "open-cli": "^8.0.0", - "oxlint": "^1.48.0", + "oxlint": "^1.49.0", "po2json": "^0.4.5", "prettier": "3.8.1", "prettier-plugin-packagejson": "^3.0.0", @@ -3944,9 +3944,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -9039,9 +9039,9 @@ } }, "node_modules/@oxlint/binding-android-arm-eabi": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.48.0.tgz", - "integrity": "sha512-1Pz/stJvveO9ZO7ll4ZoEY3f6j2FiUgBLBcCRCiW6ylId9L9UKs+gn3X28m3eTnoiFCkhKwmJJ+VO6vwsu7Qtg==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.49.0.tgz", + "integrity": "sha512-2WPoh/2oK9r/i2R4o4J18AOrm3HVlWiHZ8TnuCaS4dX8m5ZzRmHW0I3eLxEurQLHWVruhQN7fHgZnah+ag5iQg==", "cpu": [ "arm" ], @@ -9056,9 +9056,9 @@ } }, "node_modules/@oxlint/binding-android-arm64": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.48.0.tgz", - "integrity": "sha512-Zc42RWGE8huo6Ht0lXKjd0NH2lWNmimQHUmD0JFcvShLOuwN+RSEE/kRakc2/0LIgOUuU/R7PaDMCOdQlPgNUQ==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.49.0.tgz", + "integrity": "sha512-YqJAGvNB11EzoKm1euVhZntb79alhMvWW/j12bYqdvVxn6xzEQWrEDCJg9BPo3A3tBCSUBKH7bVkAiCBqK/L1w==", "cpu": [ "arm64" ], @@ -9073,9 +9073,9 @@ } }, "node_modules/@oxlint/binding-darwin-arm64": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.48.0.tgz", - "integrity": "sha512-jgZs563/4vaG5jH2RSt2TSh8A2jwsFdmhLXrElMdm3Mmto0HPf85FgInLSNi9HcwzQFvkYV8JofcoUg2GH1HTA==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.49.0.tgz", + "integrity": "sha512-WFocCRlvVkMhChCJ2qpJfp1Gj/IjvyjuifH9Pex8m8yHonxxQa3d8DZYreuDQU3T4jvSY8rqhoRqnpc61Nlbxw==", "cpu": [ "arm64" ], @@ -9090,9 +9090,9 @@ } }, "node_modules/@oxlint/binding-darwin-x64": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.48.0.tgz", - "integrity": "sha512-kvo87BujEUjCJREuWDC4aPh1WoXCRFFWE4C7uF6wuoMw2f6N2hypA/cHHcYn9DdL8R2RrgUZPefC8JExyeIMKA==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.49.0.tgz", + "integrity": "sha512-BN0KniwvehbUfYztOMwEDkYoojGm/narf5oJf+/ap+6PnzMeWLezMaVARNIS0j3OdMkjHTEP8s3+GdPJ7WDywQ==", "cpu": [ "x64" ], @@ -9107,9 +9107,9 @@ } }, "node_modules/@oxlint/binding-freebsd-x64": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.48.0.tgz", - "integrity": "sha512-eyzzPaHQKn0RIM+ueDfgfJF2RU//Wp4oaKs2JVoVYcM5HjbCL36+O0S3wO5Xe1NWpcZIG3cEHc/SuOCDRqZDSg==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.49.0.tgz", + "integrity": "sha512-SnkAc/DPIY6joMCiP/+53Q+N2UOGMU6ULvbztpmvPJNF/jYPGhNbKtN982uj2Gs6fpbxYkmyj08QnpkD4fbHJA==", "cpu": [ "x64" ], @@ -9124,9 +9124,9 @@ } }, "node_modules/@oxlint/binding-linux-arm-gnueabihf": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.48.0.tgz", - "integrity": "sha512-p3kSloztK7GRO7FyO3u38UCjZxQTl92VaLDsMQAq0eGoiNmeeEF1KPeE4+Fr+LSkQhF8WvJKSuls6TwOlurdPA==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.49.0.tgz", + "integrity": "sha512-6Z3EzRvpQVIpO7uFhdiGhdE8Mh3S2VWKLL9xuxVqD6fzPhyI3ugthpYXlCChXzO8FzcYIZ3t1+Kau+h2NY1hqA==", "cpu": [ "arm" ], @@ -9141,9 +9141,9 @@ } }, "node_modules/@oxlint/binding-linux-arm-musleabihf": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.48.0.tgz", - "integrity": "sha512-uWM+wiTqLW/V0ZmY/eyTWs8ykhIkzU+K2tz/8m35YepYEzohiUGRbnkpAFXj2ioXpQL+GUe5vmM3SLH6ozlfFw==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.49.0.tgz", + "integrity": "sha512-wdjXaQYAL/L25732mLlngfst4Jdmi/HLPVHb3yfCoP5mE3lO/pFFrmOJpqWodgv29suWY74Ij+RmJ/YIG5VuzQ==", "cpu": [ "arm" ], @@ -9158,9 +9158,9 @@ } }, "node_modules/@oxlint/binding-linux-arm64-gnu": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.48.0.tgz", - "integrity": "sha512-OhQNPjs/OICaYqxYJjKKMaIY7p3nJ9IirXcFoHKD+CQE1BZFCeUUAknMzUeLclDCfudH9Vb/UgjFm8+ZM5puAg==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.49.0.tgz", + "integrity": "sha512-oSHpm8zmSvAG1BWUumbDRSg7moJbnwoEXKAkwDf/xTQJOzvbUknq95NVQdw/AduZr5dePftalB8rzJNGBogUMg==", "cpu": [ "arm64" ], @@ -9175,9 +9175,9 @@ } }, "node_modules/@oxlint/binding-linux-arm64-musl": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.48.0.tgz", - "integrity": "sha512-adu5txuwGvQ4C4fjYHJD+vnY+OCwCixBzn7J3KF3iWlVHBBImcosSv+Ye+fbMMJui4HGjifNXzonjKm9pXmOiw==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.49.0.tgz", + "integrity": "sha512-xeqkMOARgGBlEg9BQuPDf6ZW711X6BT5qjDyeM5XNowCJeTSdmMhpePJjTEiVbbr3t21sIlK8RE6X5bc04nWyQ==", "cpu": [ "arm64" ], @@ -9192,9 +9192,9 @@ } }, "node_modules/@oxlint/binding-linux-ppc64-gnu": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.48.0.tgz", - "integrity": "sha512-inlQQRUnHCny/7b7wA6NjEoJSSZPNea4qnDhWyeqBYWx8ukf2kzNDSiamfhOw6bfAYPm/PVlkVRYaNXQbkLeTQ==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.49.0.tgz", + "integrity": "sha512-uvcqRO6PnlJGbL7TeePhTK5+7/JXbxGbN+C6FVmfICDeeRomgQqrfVjf0lUrVpUU8ii8TSkIbNdft3M+oNlOsQ==", "cpu": [ "ppc64" ], @@ -9209,9 +9209,9 @@ } }, "node_modules/@oxlint/binding-linux-riscv64-gnu": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.48.0.tgz", - "integrity": "sha512-YiJx6sW6bYebQDZRVWLKm/Drswx/hcjIgbLIhULSn0rRcBKc7d9V6mkqPjKDbhcxJgQD5Zi0yVccJiOdF40AWA==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.49.0.tgz", + "integrity": "sha512-Dw1HkdXAwHNH+ZDserHP2RzXQmhHtpsYYI0hf8fuGAVCIVwvS6w1+InLxpPMY25P8ASRNiFN3hADtoh6lI+4lg==", "cpu": [ "riscv64" ], @@ -9226,9 +9226,9 @@ } }, "node_modules/@oxlint/binding-linux-riscv64-musl": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.48.0.tgz", - "integrity": "sha512-zwSqxMgmb2ITamNfDv9Q9EKBc/4ZhCBP9gkg2hhcgR6sEVGPUDl1AKPC89CBKMxkmPUi3685C38EvqtZn5OtHw==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.49.0.tgz", + "integrity": "sha512-EPlMYaA05tJ9km/0dI9K57iuMq3Tw+nHst7TNIegAJZrBPtsOtYaMFZEaWj02HA8FI5QvSnRHMt+CI+RIhXJBQ==", "cpu": [ "riscv64" ], @@ -9243,9 +9243,9 @@ } }, "node_modules/@oxlint/binding-linux-s390x-gnu": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.48.0.tgz", - "integrity": "sha512-c/+2oUWAOsQB5JTem0rW8ODlZllF6pAtGSGXoLSvPTonKI1vAwaKhD9Qw1X36jRbcI3Etkpu/9z/RRjMba8vFQ==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.49.0.tgz", + "integrity": "sha512-yZiQL9qEwse34aMbnMb5VqiAWfDY+fLFuoJbHOuzB1OaJZbN1MRF9Nk+W89PIpGr5DNPDipwjZb8+Q7wOywoUQ==", "cpu": [ "s390x" ], @@ -9260,9 +9260,9 @@ } }, "node_modules/@oxlint/binding-linux-x64-gnu": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.48.0.tgz", - "integrity": "sha512-PhauDqeFW5DGed6QxCY5lXZYKSlcBdCXJnH03ZNU6QmDZ0BFM/zSy1oPT2MNb1Afx1G6yOOVk8ErjWsQ7c59ng==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.49.0.tgz", + "integrity": "sha512-CcCDwMMXSchNkhdgvhVn3DLZ4EnBXAD8o8+gRzahg+IdSt/72y19xBgShJgadIRF0TsRcV/MhDUMwL5N/W54aQ==", "cpu": [ "x64" ], @@ -9277,9 +9277,9 @@ } }, "node_modules/@oxlint/binding-linux-x64-musl": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.48.0.tgz", - "integrity": "sha512-6d7LIFFZGiavbHndhf1cK9kG9qmy2Dmr37sV9Ep7j3H+ciFdKSuOzdLh85mEUYMih+b+esMDlF5DU0WQRZPQjw==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.49.0.tgz", + "integrity": "sha512-u3HfKV8BV6t6UCCbN0RRiyqcymhrnpunVmLFI8sEa5S/EBu+p/0bJ3D7LZ2KT6PsBbrB71SWq4DeFrskOVgIZg==", "cpu": [ "x64" ], @@ -9294,9 +9294,9 @@ } }, "node_modules/@oxlint/binding-openharmony-arm64": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.48.0.tgz", - "integrity": "sha512-r+0KK9lK6vFp3tXAgDMOW32o12dxvKS3B9La1uYMGdWAMoSeu2RzG34KmzSpXu6MyLDl4aSVyZLFM8KGdEjwaw==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.49.0.tgz", + "integrity": "sha512-dRDpH9fw+oeUMpM4br0taYCFpW6jQtOuEIec89rOgDA1YhqwmeRcx0XYeCv7U48p57qJ1XZHeMGM9LdItIjfzA==", "cpu": [ "arm64" ], @@ -9311,9 +9311,9 @@ } }, "node_modules/@oxlint/binding-win32-arm64-msvc": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.48.0.tgz", - "integrity": "sha512-Nkw/MocyT3HSp0OJsKPXrcbxZqSPMTYnLLfsqsoiFKoL1ppVNL65MFa7vuTxJehPlBkjy+95gUgacZtuNMECrg==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.49.0.tgz", + "integrity": "sha512-6rrKe/wL9tn0qnOy76i1/0f4Dc3dtQnibGlU4HqR/brVHlVjzLSoaH0gAFnLnznh9yQ6gcFTBFOPrcN/eKPDGA==", "cpu": [ "arm64" ], @@ -9328,9 +9328,9 @@ } }, "node_modules/@oxlint/binding-win32-ia32-msvc": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.48.0.tgz", - "integrity": "sha512-reO1SpefvRmeZSP+WeyWkQd1ArxxDD1MyKgMUKuB8lNuUoxk9QEohYtKnsfsxJuFwMT0JTr7p9wZjouA85GzGQ==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.49.0.tgz", + "integrity": "sha512-CXHLWAtLs2xG/aVy1OZiYJzrULlq0QkYpI6cd7VKMrab+qur4fXVE/B1Bp1m0h1qKTj5/FTGg6oU4qaXMjS/ug==", "cpu": [ "ia32" ], @@ -9345,9 +9345,9 @@ } }, "node_modules/@oxlint/binding-win32-x64-msvc": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.48.0.tgz", - "integrity": "sha512-T6zwhfcsrorqAybkOglZdPkTLlEwipbtdO1qjE+flbawvwOMsISoyiuaa7vM7zEyfq1hmDvMq1ndvkYFioranA==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.49.0.tgz", + "integrity": "sha512-VteIelt78kwzSglOozaQcs6BCS4Lk0j+QA+hGV0W8UeyaqQ3XpbZRhDU55NW1PPvCy1tg4VXsTlEaPovqto7nQ==", "cpu": [ "x64" ], @@ -9846,15 +9846,6 @@ "integrity": "sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==", "license": "MIT" }, - "node_modules/@react-icons/all-files": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@react-icons/all-files/-/all-files-4.1.0.tgz", - "integrity": "sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ==", - "license": "MIT", - "peerDependencies": { - "react": "*" - } - }, "node_modules/@react-spring/animated": { "version": "9.7.5", "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.5.tgz", @@ -11773,9 +11764,9 @@ } }, "node_modules/@storybook/react-webpack5/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -17904,9 +17895,9 @@ } }, "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -25330,9 +25321,9 @@ } }, "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -26639,9 +26630,9 @@ } }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -39360,9 +39351,9 @@ } }, "node_modules/oxlint": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.48.0.tgz", - "integrity": "sha512-m5vyVBgPtPhVCJc3xI//8je9lRc8bYuYB4R/1PH3VPGOjA4vjVhkHtyJukdEjYEjwrw4Qf1eIf+pP9xvfhfMow==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.49.0.tgz", + "integrity": "sha512-YZffp0gM+63CJoRhHjtjRnwKtAgUnXM6j63YQ++aigji2NVvLGsUlrXo9gJUXZOdcbfShLYtA6RuTu8GZ4lzOQ==", "dev": true, "license": "MIT", "bin": { @@ -39375,28 +39366,28 @@ "url": "https://github.com/sponsors/Boshen" }, "optionalDependencies": { - "@oxlint/binding-android-arm-eabi": "1.48.0", - "@oxlint/binding-android-arm64": "1.48.0", - "@oxlint/binding-darwin-arm64": "1.48.0", - "@oxlint/binding-darwin-x64": "1.48.0", - "@oxlint/binding-freebsd-x64": "1.48.0", - "@oxlint/binding-linux-arm-gnueabihf": "1.48.0", - "@oxlint/binding-linux-arm-musleabihf": "1.48.0", - "@oxlint/binding-linux-arm64-gnu": "1.48.0", - "@oxlint/binding-linux-arm64-musl": "1.48.0", - "@oxlint/binding-linux-ppc64-gnu": "1.48.0", - "@oxlint/binding-linux-riscv64-gnu": "1.48.0", - "@oxlint/binding-linux-riscv64-musl": "1.48.0", - "@oxlint/binding-linux-s390x-gnu": "1.48.0", - "@oxlint/binding-linux-x64-gnu": "1.48.0", - "@oxlint/binding-linux-x64-musl": "1.48.0", - "@oxlint/binding-openharmony-arm64": "1.48.0", - "@oxlint/binding-win32-arm64-msvc": "1.48.0", - "@oxlint/binding-win32-ia32-msvc": "1.48.0", - "@oxlint/binding-win32-x64-msvc": "1.48.0" - }, - "peerDependencies": { - "oxlint-tsgolint": ">=0.12.2" + "@oxlint/binding-android-arm-eabi": "1.49.0", + "@oxlint/binding-android-arm64": "1.49.0", + "@oxlint/binding-darwin-arm64": "1.49.0", + "@oxlint/binding-darwin-x64": "1.49.0", + "@oxlint/binding-freebsd-x64": "1.49.0", + "@oxlint/binding-linux-arm-gnueabihf": "1.49.0", + "@oxlint/binding-linux-arm-musleabihf": "1.49.0", + "@oxlint/binding-linux-arm64-gnu": "1.49.0", + "@oxlint/binding-linux-arm64-musl": "1.49.0", + "@oxlint/binding-linux-ppc64-gnu": "1.49.0", + "@oxlint/binding-linux-riscv64-gnu": "1.49.0", + "@oxlint/binding-linux-riscv64-musl": "1.49.0", + "@oxlint/binding-linux-s390x-gnu": "1.49.0", + "@oxlint/binding-linux-x64-gnu": "1.49.0", + "@oxlint/binding-linux-x64-musl": "1.49.0", + "@oxlint/binding-openharmony-arm64": "1.49.0", + "@oxlint/binding-win32-arm64-msvc": "1.49.0", + "@oxlint/binding-win32-ia32-msvc": "1.49.0", + "@oxlint/binding-win32-x64-msvc": "1.49.0" + }, + "peerDependencies": { + "oxlint-tsgolint": ">=0.14.1" }, "peerDependenciesMeta": { "oxlint-tsgolint": { @@ -42435,6 +42426,15 @@ "react": ">=16.4.1" } }, + "node_modules/react-icons": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.4.0.tgz", + "integrity": "sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-intersection-observer": { "version": "10.0.3", "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-10.0.3.tgz", @@ -51830,7 +51830,6 @@ "license": "Apache-2.0", "dependencies": { "@apache-superset/core": "*", - "@react-icons/all-files": "^4.1.0", "@types/react": "*", "lodash": "^4.17.23" }, @@ -53009,63 +53008,6 @@ "url": "https://opencollective.com/unified" } }, - "packages/superset-ui-demo": { - "name": "@superset-ui/demo", - "version": "0.20.0", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@emotion/cache": "^11.14.0", - "@emotion/react": "^11.14.0", - "@emotion/styled": "^11.14.1", - "@mihkeleidast/storybook-addon-source": "^1.0.1", - "@react-icons/all-files": "^4.1.0", - "@storybook/addon-actions": "^8.6.15", - "@storybook/addon-controls": "^8.6.15", - "@storybook/addon-links": "^8.6.15", - "@storybook/react": "^8.6.15", - "@storybook/types": "^8.6.15", - "@types/react-loadable": "^5.5.11", - "core-js": "3.48.0", - "gh-pages": "^6.3.0", - "jquery": "^4.0.0", - "memoize-one": "^6.0.0", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "react-loadable": "^5.5.0", - "react-resizable": "^3.1.3" - }, - "devDependencies": { - "@babel/core": "^7.29.0", - "@babel/preset-env": "^7.29.0", - "@babel/preset-react": "^7.28.5", - "@babel/preset-typescript": "^7.28.5", - "@storybook/react-webpack5": "^8.6.15", - "babel-loader": "^10.0.0", - "fork-ts-checker-webpack-plugin": "^9.1.0", - "ts-loader": "^9.5.4", - "typescript": "^5.9.3" - }, - "peerDependencies": { - "@apache-superset/core": "*", - "@superset-ui/core": "*", - "@superset-ui/legacy-plugin-chart-calendar": "*", - "@superset-ui/legacy-plugin-chart-chord": "*", - "@superset-ui/legacy-plugin-chart-country-map": "*", - "@superset-ui/legacy-plugin-chart-horizon": "*", - "@superset-ui/legacy-plugin-chart-map-box": "*", - "@superset-ui/legacy-plugin-chart-paired-t-test": "*", - "@superset-ui/legacy-plugin-chart-parallel-coordinates": "*", - "@superset-ui/legacy-plugin-chart-partition": "*", - "@superset-ui/legacy-plugin-chart-rose": "*", - "@superset-ui/legacy-plugin-chart-world-map": "*", - "@superset-ui/legacy-preset-chart-deckgl": "*", - "@superset-ui/legacy-preset-chart-nvd3": "*", - "@superset-ui/plugin-chart-echarts": "*", - "@superset-ui/plugin-chart-table": "*", - "@superset-ui/plugin-chart-word-cloud": "*" - } - }, "packages/superset-ui-switchboard": { "name": "@superset-ui/switchboard", "version": "0.20.3", @@ -53451,7 +53393,6 @@ "version": "0.20.3", "license": "Apache-2.0", "dependencies": { - "@react-icons/all-files": "^4.1.0", "@types/d3-array": "^3.2.2", "@types/react-table": "^7.7.20", "classnames": "^2.5.1", @@ -53606,13 +53547,13 @@ "peerDependencies": { "@ant-design/icons": "^5.2.6", "@apache-superset/core": "*", - "@react-icons/all-files": "^4.1.0", "@superset-ui/chart-controls": "*", "@superset-ui/core": "*", "lodash": "^4.17.11", "prop-types": "*", "react": "^17.0.2", - "react-dom": "^17.0.2" + "react-dom": "^17.0.2", + "react-icons": "5.4.0" } }, "plugins/plugin-chart-table": { @@ -53620,13 +53561,13 @@ "version": "0.20.3", "license": "Apache-2.0", "dependencies": { - "@react-icons/all-files": "^4.1.0", "@types/d3-array": "^3.2.2", "@types/react-table": "^7.7.20", "classnames": "^2.5.1", "d3-array": "^3.2.4", "lodash": "^4.17.23", "memoize-one": "^5.2.1", + "react-icons": "5.4.0", "react-table": "^7.8.0", "regenerator-runtime": "^0.14.1", "xss": "^1.0.15" diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 965f6d347abb..17ddace909ea 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -347,7 +347,7 @@ "lightningcss": "^1.31.1", "mini-css-extract-plugin": "^2.10.0", "open-cli": "^8.0.0", - "oxlint": "^1.48.0", + "oxlint": "^1.49.0", "po2json": "^0.4.5", "prettier": "3.8.1", "prettier-plugin-packagejson": "^3.0.0", diff --git a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/package-lock.erb b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/package-lock.erb index 56df41714ad3..a4530edb1419 100644 --- a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/package-lock.erb +++ b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/package-lock.erb @@ -4144,15 +4144,6 @@ "node": ">= 8" } }, - "node_modules/@react-icons/all-files": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@react-icons/all-files/-/all-files-4.1.0.tgz", - "integrity": "sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ==", - "peer": true, - "peerDependencies": { - "react": "*" - } - }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -4186,7 +4177,6 @@ "integrity": "sha512-zi2DJ2cTpgR1HugPX3yBHJAaBo7XYhodgZqj0BsKNMoexrLvHyPYsN+cw5xXFE1Q1ZyeKtQBB5m41+CKKfwQYw==", "peer": true, "dependencies": { - "@react-icons/all-files": "^4.1.0", "@superset-ui/core": "0.18.25", "lodash": "^4.17.15", "prop-types": "^15.7.2" @@ -21330,13 +21320,6 @@ "fastq": "^1.6.0" } }, - "@react-icons/all-files": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@react-icons/all-files/-/all-files-4.1.0.tgz", - "integrity": "sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ==", - "peer": true, - "requires": {} - }, "@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -21367,7 +21350,6 @@ "integrity": "sha512-zi2DJ2cTpgR1HugPX3yBHJAaBo7XYhodgZqj0BsKNMoexrLvHyPYsN+cw5xXFE1Q1ZyeKtQBB5m41+CKKfwQYw==", "peer": true, "requires": { - "@react-icons/all-files": "^4.1.0", "@superset-ui/core": "0.18.25", "lodash": "^4.17.15", "prop-types": "^15.7.2" diff --git a/superset-frontend/packages/superset-core/src/ui/theme/utils/themeUtils.ts b/superset-frontend/packages/superset-core/src/ui/theme/utils/themeUtils.ts index 041f9a728447..809e7f1a35c4 100644 --- a/superset-frontend/packages/superset-core/src/ui/theme/utils/themeUtils.ts +++ b/superset-frontend/packages/superset-core/src/ui/theme/utils/themeUtils.ts @@ -47,6 +47,15 @@ export function getFontSize(theme: SupersetTheme, size?: FontSizeKey): string { return String(theme[key] || theme.fontSize); } +/** + * Check if the current theme is dark mode based on background color + * @param theme - Theme tokens from useTheme() + * @returns true if theme is dark, false if light + */ +export function isThemeDark(theme: SupersetTheme): boolean { + return tinycolor(theme.colorBgContainer).isDark(); +} + /** * Get color variants for a given color type from theme tokens * @param theme - Theme tokens from useTheme() @@ -111,15 +120,6 @@ export function getColorVariants( }; } -/** - * Check if the current theme is dark mode based on background color - * @param theme - Theme tokens from useTheme() - * @returns true if theme is dark, false if light - */ -export function isThemeDark(theme: SupersetTheme): boolean { - return tinycolor(theme.colorBgContainer).isDark(); -} - /** * Check if a theme configuration results in a dark theme * @param config - The theme configuration to check diff --git a/superset-frontend/packages/superset-ui-chart-controls/package.json b/superset-frontend/packages/superset-ui-chart-controls/package.json index 061eba7bd4aa..a9eb07107a1b 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/package.json +++ b/superset-frontend/packages/superset-ui-chart-controls/package.json @@ -25,7 +25,6 @@ ], "dependencies": { "@apache-superset/core": "*", - "@react-icons/all-files": "^4.1.0", "@types/react": "*", "lodash": "^4.17.23" }, diff --git a/superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts b/superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts index a2eb7979c4ee..bcf843556657 100644 --- a/superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts +++ b/superset-frontend/packages/superset-ui-core/src/query/types/Dashboard.ts @@ -240,4 +240,33 @@ export type DashboardComponentMetadata = { dataMask: DataMaskStateWithId; }; +export interface LegacyChartCustomizationDataset { + value: number | string; + label: string; + table_name?: string; +} + +export interface LegacyChartCustomizationConfig { + name: string; + dataset: string | number | LegacyChartCustomizationDataset | null; + column: string | string[] | null; + sortAscending?: boolean; + sortMetric?: string; + canSelectMultiple?: boolean; + defaultDataMask?: DataMask; + controlValues?: { + enableEmptyFilter?: boolean; + [key: string]: any; + }; + description?: string; +} + +export interface LegacyChartCustomizationItem { + id: string; + title?: string; + removed?: boolean; + chartId?: number; + customization: LegacyChartCustomizationConfig; +} + export default {}; diff --git a/superset-frontend/plugins/legacy-plugin-chart-rose/src/Rose.ts b/superset-frontend/plugins/legacy-plugin-chart-rose/src/Rose.ts index 4ead29792ce0..c356ce9cf2bc 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-rose/src/Rose.ts +++ b/superset-frontend/plugins/legacy-plugin-chart-rose/src/Rose.ts @@ -17,7 +17,7 @@ * under the License. */ // @ts-nocheck -/* eslint no-use-before-define: ["error", { "functions": false }] */ +/* oxlint-disable no-use-before-define: ["error", { "functions": false }] */ /* eslint-disable no-restricted-syntax */ /* eslint-disable react/sort-prop-types */ import d3 from 'd3'; diff --git a/superset-frontend/plugins/plugin-chart-ag-grid-table/package.json b/superset-frontend/plugins/plugin-chart-ag-grid-table/package.json index 6d23f8bd2411..0be899eeaba5 100644 --- a/superset-frontend/plugins/plugin-chart-ag-grid-table/package.json +++ b/superset-frontend/plugins/plugin-chart-ag-grid-table/package.json @@ -24,7 +24,6 @@ "lib" ], "dependencies": { - "@react-icons/all-files": "^4.1.0", "@types/d3-array": "^3.2.2", "@types/react-table": "^7.7.20", "classnames": "^2.5.1", diff --git a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/components/CustomPopover.tsx b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/components/CustomPopover.tsx index 0fe0bc7474fd..e630986bf69a 100644 --- a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/components/CustomPopover.tsx +++ b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/components/CustomPopover.tsx @@ -36,6 +36,16 @@ const CustomPopover: React.FC = ({ const triggerRef = useRef(null); const popoverRef = useRef(null); + const handleClickOutside = (event: MouseEvent) => { + if ( + popoverRef.current && + !popoverRef.current.contains(event.target as Node) && + !triggerRef.current?.contains(event.target as Node) + ) { + onClose(); + } + }; + useEffect(() => { const updatePosition = () => { const rect = triggerRef.current?.getBoundingClientRect(); @@ -73,16 +83,6 @@ const CustomPopover: React.FC = ({ }; }, [isOpen]); - const handleClickOutside = (event: MouseEvent) => { - if ( - popoverRef.current && - !popoverRef.current.contains(event.target as Node) && - !triggerRef.current?.contains(event.target as Node) - ) { - onClose(); - } - }; - return ( {cloneElement(children, { ref: triggerRef })} diff --git a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/agGridFilterConverter.ts b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/agGridFilterConverter.ts index 5fe226ef84d9..6389f61ca8e9 100644 --- a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/agGridFilterConverter.ts +++ b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/agGridFilterConverter.ts @@ -246,6 +246,47 @@ function formatValueForOperator( return value; } +/** + * Format a date string to ISO format expected by Superset, preserving local timezone + */ +export function formatDateForSuperset(dateStr: string): string { + // AG Grid typically provides dates in format: "YYYY-MM-DD HH:MM:SS" + // Superset expects: "YYYY-MM-DDTHH:MM:SS" in local timezone (not UTC) + const date = new Date(dateStr); + if (Number.isNaN(date.getTime())) { + return dateStr; // Return as-is if invalid + } + + // Format date in local timezone, not UTC + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); + + const formatted = `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`; + return formatted; +} + +/** + * Get the start of day (00:00:00) for a given date string + */ +export function getStartOfDay(dateStr: string): string { + const date = new Date(dateStr); + date.setHours(0, 0, 0, 0); + return formatDateForSuperset(date.toISOString()); +} + +/** + * Get the end of day (23:59:59) for a given date string + */ +export function getEndOfDay(dateStr: string): string { + const date = new Date(dateStr); + date.setHours(23, 59, 59, 999); + return formatDateForSuperset(date.toISOString()); +} + /** * Convert a date filter to a WHERE clause * @param columnName - Column name @@ -418,47 +459,6 @@ function compoundFilterToWhereClause( return result; } -/** - * Format a date string to ISO format expected by Superset, preserving local timezone - */ -export function formatDateForSuperset(dateStr: string): string { - // AG Grid typically provides dates in format: "YYYY-MM-DD HH:MM:SS" - // Superset expects: "YYYY-MM-DDTHH:MM:SS" in local timezone (not UTC) - const date = new Date(dateStr); - if (Number.isNaN(date.getTime())) { - return dateStr; // Return as-is if invalid - } - - // Format date in local timezone, not UTC - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); - const hours = String(date.getHours()).padStart(2, '0'); - const minutes = String(date.getMinutes()).padStart(2, '0'); - const seconds = String(date.getSeconds()).padStart(2, '0'); - - const formatted = `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`; - return formatted; -} - -/** - * Get the start of day (00:00:00) for a given date string - */ -export function getStartOfDay(dateStr: string): string { - const date = new Date(dateStr); - date.setHours(0, 0, 0, 0); - return formatDateForSuperset(date.toISOString()); -} - -/** - * Get the end of day (23:59:59) for a given date string - */ -export function getEndOfDay(dateStr: string): string { - const date = new Date(dateStr); - date.setHours(23, 59, 59, 999); - return formatDateForSuperset(date.toISOString()); -} - // Converts date filters to TEMPORAL_RANGE format for Superset backend function convertDateFilter( columnName: string, diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts index f8384bfbe785..2d5f4d9c2f0a 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts @@ -89,6 +89,18 @@ function getYAxisFormatter( return yAxis.axisLabel!.formatter!; } +const queriesData: ChartDataResponseResult[] = [ + createTestQueryData( + createTestData( + [ + { 'San Francisco': 1, 'New York': 2 }, + { 'San Francisco': 3, 'New York': 4 }, + ], + { intervalMs: 300000000 }, + ), + ), +]; + /** * Creates a properly typed EchartsTimeseriesChartProps for testing. * Uses shared createEchartsTimeseriesTestChartProps with Timeseries defaults. @@ -128,17 +140,7 @@ const formData: SqlaFormData = { groupby: ['foo', 'bar'], viz_type: 'my_viz', }; -const queriesData: ChartDataResponseResult[] = [ - createTestQueryData( - createTestData( - [ - { 'San Francisco': 1, 'New York': 2 }, - { 'San Francisco': 3, 'New York': 4 }, - ], - { intervalMs: 300000000 }, - ), - ), -]; + describe('EchartsTimeseries transformProps', () => { test('should transform chart props for viz', () => { const chartProps = createTestChartProps({}); diff --git a/superset-frontend/plugins/plugin-chart-pivot-table/package.json b/superset-frontend/plugins/plugin-chart-pivot-table/package.json index b20f5970919e..15658cf96130 100644 --- a/superset-frontend/plugins/plugin-chart-pivot-table/package.json +++ b/superset-frontend/plugins/plugin-chart-pivot-table/package.json @@ -27,7 +27,7 @@ "access": "public" }, "peerDependencies": { - "@react-icons/all-files": "^4.1.0", + "react-icons": "5.4.0", "@apache-superset/core": "*", "@ant-design/icons": "^5.2.6", "@superset-ui/chart-controls": "*", diff --git a/superset-frontend/plugins/plugin-chart-pivot-table/src/react-pivottable/TableRenderers.tsx b/superset-frontend/plugins/plugin-chart-pivot-table/src/react-pivottable/TableRenderers.tsx index 15d258279634..3d5f29631e0f 100644 --- a/superset-frontend/plugins/plugin-chart-pivot-table/src/react-pivottable/TableRenderers.tsx +++ b/superset-frontend/plugins/plugin-chart-pivot-table/src/react-pivottable/TableRenderers.tsx @@ -21,9 +21,9 @@ import { Component, ReactNode, MouseEvent } from 'react'; import { safeHtmlSpan } from '@superset-ui/core'; import { t } from '@apache-superset/core/ui'; import PropTypes from 'prop-types'; -import { FaSort } from '@react-icons/all-files/fa/FaSort'; -import { FaSortDown as FaSortDesc } from '@react-icons/all-files/fa/FaSortDown'; -import { FaSortUp as FaSortAsc } from '@react-icons/all-files/fa/FaSortUp'; +import { FaSort } from 'react-icons/fa'; +import { FaSortDown as FaSortDesc } from 'react-icons/fa'; +import { FaSortUp as FaSortAsc } from 'react-icons/fa'; import { PivotData, flatKey } from './utilities'; import { Styles } from './Styles'; diff --git a/superset-frontend/plugins/plugin-chart-table/package.json b/superset-frontend/plugins/plugin-chart-table/package.json index 27b073ec388f..3d9798b6783a 100644 --- a/superset-frontend/plugins/plugin-chart-table/package.json +++ b/superset-frontend/plugins/plugin-chart-table/package.json @@ -24,7 +24,7 @@ "lib" ], "dependencies": { - "@react-icons/all-files": "^4.1.0", + "react-icons": "5.4.0", "@types/d3-array": "^3.2.2", "@types/react-table": "^7.7.20", "classnames": "^2.5.1", diff --git a/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx b/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx index e95387049d94..d05193edbc3f 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx +++ b/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx @@ -35,9 +35,9 @@ import { Row, } from 'react-table'; import { extent as d3Extent, max as d3Max } from 'd3-array'; -import { FaSort } from '@react-icons/all-files/fa/FaSort'; -import { FaSortDown as FaSortDesc } from '@react-icons/all-files/fa/FaSortDown'; -import { FaSortUp as FaSortAsc } from '@react-icons/all-files/fa/FaSortUp'; +import { FaSort } from 'react-icons/fa'; +import { FaSortDown as FaSortDesc } from 'react-icons/fa'; +import { FaSortUp as FaSortAsc } from 'react-icons/fa'; import cx from 'classnames'; import { DataRecord, diff --git a/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts b/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts index 358181e46dee..08e832fce67f 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts @@ -569,6 +569,29 @@ const transformProps = ( return { arrow, arrowColor, backgroundColor }; }; + const nonCustomNorInheritShifts = ensureIsArray(formData.time_compare).filter( + (shift: string) => shift !== 'custom' && shift !== 'inherit', + ); + const customOrInheritShifts = ensureIsArray(formData.time_compare).filter( + (shift: string) => shift === 'custom' || shift === 'inherit', + ); + + let timeOffsets: string[] = []; + + if (isUsingTimeComparison && !isEmpty(nonCustomNorInheritShifts)) { + timeOffsets = nonCustomNorInheritShifts; + } + + // Shifts for custom or inherit time comparison + if (isUsingTimeComparison && !isEmpty(customOrInheritShifts)) { + if (customOrInheritShifts.includes('custom')) { + timeOffsets = timeOffsets.concat([formData.start_date_offset]); + } + if (customOrInheritShifts.includes('inherit')) { + timeOffsets = timeOffsets.concat(['inherit']); + } + } + const getBasicColorFormatter = memoizeOne(function getBasicColorFormatter( originalData: DataRecord[] | undefined, originalColumns: DataColumnMeta[], @@ -653,28 +676,6 @@ const transformProps = ( const timeGrain = extractTimegrain(formData); - const nonCustomNorInheritShifts = ensureIsArray(formData.time_compare).filter( - (shift: string) => shift !== 'custom' && shift !== 'inherit', - ); - const customOrInheritShifts = ensureIsArray(formData.time_compare).filter( - (shift: string) => shift === 'custom' || shift === 'inherit', - ); - - let timeOffsets: string[] = []; - - if (isUsingTimeComparison && !isEmpty(nonCustomNorInheritShifts)) { - timeOffsets = nonCustomNorInheritShifts; - } - - // Shifts for custom or inherit time comparison - if (isUsingTimeComparison && !isEmpty(customOrInheritShifts)) { - if (customOrInheritShifts.includes('custom')) { - timeOffsets = timeOffsets.concat([formData.start_date_offset]); - } - if (customOrInheritShifts.includes('inherit')) { - timeOffsets = timeOffsets.concat(['inherit']); - } - } const comparisonSuffix = isUsingTimeComparison ? ensureIsArray(timeOffsets)[0] : ''; diff --git a/superset-frontend/src/components/Chart/Chart.test.tsx b/superset-frontend/src/components/Chart/Chart.test.tsx new file mode 100644 index 000000000000..53028d2d1e94 --- /dev/null +++ b/superset-frontend/src/components/Chart/Chart.test.tsx @@ -0,0 +1,88 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { render, screen } from 'spec/helpers/testing-library'; +import '@testing-library/jest-dom'; +import { PLACEHOLDER_DATASOURCE } from 'src/dashboard/constants'; +import { ResourceStatus } from 'src/hooks/apiResources/apiResources'; +import Chart from './Chart'; +import type { Actions } from './Chart'; + +const mockActions: Actions = { + logEvent: jest.fn() as unknown as Actions['logEvent'], + chartRenderingFailed: jest.fn() as unknown as Actions['chartRenderingFailed'], + chartRenderingSucceeded: + jest.fn() as unknown as Actions['chartRenderingSucceeded'], + postChartFormData: jest.fn() as unknown as Actions['postChartFormData'], +}; + +const baseProps = { + chartId: 1, + width: 800, + height: 600, + actions: mockActions, + formData: { datasource: '1__table', viz_type: 'table' }, + vizType: 'table', + setControlValue: jest.fn(), +}; + +test('shows backend error instead of loading spinner when datasource is still a placeholder', () => { + render( + , + ); + + expect( + screen.getByText(/Your default credentials were not found/), + ).toBeInTheDocument(); +}); + +test('shows loading spinner for client-side errors without errors array when datasource is still a placeholder', () => { + render( + , + ); + + expect(screen.getByRole('status')).toBeInTheDocument(); + expect(screen.queryByText(/Some client-side error/)).not.toBeInTheDocument(); +}); diff --git a/superset-frontend/src/components/Chart/Chart.tsx b/superset-frontend/src/components/Chart/Chart.tsx index 9a05bb270fbf..7ab23a2260d2 100644 --- a/superset-frontend/src/components/Chart/Chart.tsx +++ b/superset-frontend/src/components/Chart/Chart.tsx @@ -168,6 +168,11 @@ const LoadingDiv = styled.div` transform: translate(-50%, -50%); `; +const ErrorContainer = styled.div<{ height: number }>` + height: ${p => p.height}px; + overflow: auto; +`; + const MessageSpan = styled.span` display: block; text-align: center; @@ -261,7 +266,10 @@ class Chart extends PureComponent { const message = chartAlert || queryResponse?.message; // if datasource is still loading, don't render JS errors + // but always show backend API errors (which have an errors array) + // so users can see real issues like auth failures if ( + !error && chartAlert !== undefined && chartAlert !== NONEXISTENT_DATASET && datasource === PLACEHOLDER_DATASOURCE && @@ -353,8 +361,12 @@ class Chart extends PureComponent { const isLoading = chartStatus === 'loading'; if (chartStatus === 'failed') { - return queriesResponse?.map(item => - this.renderErrorMessage(item as ChartErrorType), + return ( + + {queriesResponse?.map(item => + this.renderErrorMessage(item as ChartErrorType), + )} + ); } diff --git a/superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx b/superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx index 58c15ddcb28e..f5592a2c645b 100644 --- a/superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx +++ b/superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx @@ -497,6 +497,14 @@ function CollectionTabTitle({ ); } +function FormContainer({ children }: FormContainerProps): JSX.Element { + return ( + + {children} + + ); +} + function ColumnCollectionTable({ columns, datasource, @@ -766,14 +774,6 @@ function StackedField({ label, formElement }: StackedFieldProps): JSX.Element { ); } -function FormContainer({ children }: FormContainerProps): JSX.Element { - return ( - - {children} - - ); -} - function OwnersSelector({ datasource, onChange, diff --git a/superset-frontend/src/components/JsonModal/index.tsx b/superset-frontend/src/components/JsonModal/index.tsx index f108c3dc19b1..cc38d28454d5 100644 --- a/superset-frontend/src/components/JsonModal/index.tsx +++ b/superset-frontend/src/components/JsonModal/index.tsx @@ -17,32 +17,23 @@ * under the License. */ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ import { FC, useMemo } from 'react'; import { JSONTree } from 'react-json-tree'; +import { styled } from '@apache-superset/core/ui'; import { useJsonTreeTheme } from 'src/hooks/useJsonTreeTheme'; import { Button, ModalTrigger } from '@superset-ui/core/components'; import { CopyToClipboard } from '../CopyToClipboard'; import { convertBigIntStrToNumber } from './utils'; import type { JsonModalProps } from './types'; +/** + * Preserve line breaks for multiline cell content (e.g. stack traces) + * while keeping the change scoped to this component only. + */ +const PreWrap = styled.span` + white-space: pre-wrap; +`; + function renderBigIntStrToNumber(value: string | number) { return <>{convertBigIntStrToNumber(value)}; } @@ -53,6 +44,7 @@ export const JsonModal: FC = ({ jsonValue, }) => { const jsonTreeTheme = useJsonTreeTheme(); + const content = useMemo( () => typeof jsonValue === 'object' ? JSON.stringify(jsonValue) : jsonValue, @@ -74,7 +66,7 @@ export const JsonModal: FC = ({ } modalTitle={modalTitle} - triggerNode={<>{content}} + triggerNode={{content}} /> ); }; diff --git a/superset-frontend/src/dashboard/actions/hydrate.ts b/superset-frontend/src/dashboard/actions/hydrate.ts index 5bcb85744351..46396c336e8c 100644 --- a/superset-frontend/src/dashboard/actions/hydrate.ts +++ b/superset-frontend/src/dashboard/actions/hydrate.ts @@ -60,6 +60,7 @@ import { ResourceStatus } from 'src/hooks/apiResources/apiResources'; import type { DashboardChartStates } from 'src/dashboard/types/chartState'; import extractUrlParams from '../util/extractUrlParams'; import updateComponentParentsList from '../util/updateComponentParentsList'; +import { migrateChartCustomizationArray } from '../util/migrateChartCustomization'; import { DashboardLayout, FilterBarOrientation, @@ -291,8 +292,13 @@ export const hydrateDashboard = directPathToChild.push(directLinkComponentId); } - const chartCustomizations = + const rawChartCustomizations = (metadata?.chart_customization_config as JsonObject[]) || []; + + const chartCustomizations = migrateChartCustomizationArray( + rawChartCustomizations, + ); + const filters = (metadata?.native_filter_configuration as JsonObject[]) || []; const combinedFilters = [...filters, ...chartCustomizations]; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx index 545496aec345..49ebc4b58663 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx @@ -279,10 +279,14 @@ const FilterControls: FC = ({ /> ); } + const filterWithDataMask = addDataMaskToCustomization( + item, + dataMaskSelected, + ); return ( handleChartCustomizationChange(item, dataMask) diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts index 1191edf5e69d..ed6a7634f180 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts @@ -30,6 +30,7 @@ import { ChartsState, RootState } from 'src/dashboard/types'; import { NATIVE_FILTER_PREFIX, CHART_CUSTOMIZATION_PREFIX, + LEGACY_GROUPBY_PREFIX, isNativeFilter, } from '../FiltersConfigModal/utils'; import { useFilterConfiguration } from '../state'; @@ -87,7 +88,8 @@ export const useAllAppliedDataMask = () => { const id = String(item.id); return ( id.startsWith(NATIVE_FILTER_PREFIX) || - id.startsWith(CHART_CUSTOMIZATION_PREFIX) + id.startsWith(CHART_CUSTOMIZATION_PREFIX) || + id.startsWith(LEGACY_GROUPBY_PREFIX) ); }) .reduce( @@ -108,10 +110,10 @@ export const useFilterUpdates = ( const dataMaskApplied = useNativeFiltersDataMask(); useEffect(() => { Object.keys(dataMaskSelected).forEach(selectedId => { - const isChartCustomization = String(selectedId).startsWith( - CHART_CUSTOMIZATION_PREFIX, - ); - if (!isChartCustomization && !filters[selectedId]) { + const isChartCustomizationItem = + String(selectedId).startsWith(CHART_CUSTOMIZATION_PREFIX) || + String(selectedId).startsWith(LEGACY_GROUPBY_PREFIX); + if (!isChartCustomizationItem && !filters[selectedId]) { setDataMaskSelected(draft => { delete draft[selectedId]; }); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts index 199d464a559d..c69bf4243035 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts @@ -310,9 +310,11 @@ export const createHandleCustomizationSave = export const CHART_CUSTOMIZATION_PREFIX = 'CHART_CUSTOMIZATION-'; export const CHART_CUSTOMIZATION_DIVIDER_PREFIX = 'CHART_CUSTOMIZATION_DIVIDER-'; +export const LEGACY_GROUPBY_PREFIX = 'groupby_'; export const isChartCustomization = (id: string): boolean => - id.startsWith(CHART_CUSTOMIZATION_PREFIX); + id.startsWith(CHART_CUSTOMIZATION_PREFIX) || + id.startsWith(LEGACY_GROUPBY_PREFIX); export const isChartCustomizationDivider = (id: string): boolean => id.startsWith(CHART_CUSTOMIZATION_DIVIDER_PREFIX); @@ -337,7 +339,8 @@ export const isFilterId = (id: string): boolean => export const isChartCustomizationId = (id: string): boolean => id.startsWith(CHART_CUSTOMIZATION_PREFIX) || - id.startsWith(CHART_CUSTOMIZATION_DIVIDER_PREFIX); + id.startsWith(CHART_CUSTOMIZATION_DIVIDER_PREFIX) || + id.startsWith(LEGACY_GROUPBY_PREFIX); export const getItemType = (id: string): ItemType => { if (isFilterId(id)) return 'filter'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/state.ts index ecbb56e47a06..11034ab1da05 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/state.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/state.ts @@ -32,6 +32,10 @@ import { FilterElement } from './FilterBar/FilterControls/types'; import { ActiveTabs, DashboardLayout, RootState } from '../../types'; import { CHART_TYPE, TAB_TYPE } from '../../util/componentTypes'; import { isChartCustomizationId } from './FiltersConfigModal/utils'; +import { + migrateChartCustomizationArray, + isLegacyChartCustomizationFormat, +} from '../../util/migrateChartCustomization'; const EMPTY_ARRAY: ChartCustomizationConfiguration = []; const defaultFilterConfiguration: (Filter | Divider)[] = []; @@ -93,11 +97,19 @@ const selectDashboardChartIds = createSelector( const selectChartCustomizationConfiguration = createSelector( [ (state: RootState) => - state.dashboardInfo.metadata?.chart_customization_config || EMPTY_ARRAY, + state.dashboardInfo?.metadata?.chart_customization_config || EMPTY_ARRAY, selectDashboardChartIds, ], - (allCustomizations, dashboardChartIds): ChartCustomizationConfiguration => - allCustomizations.filter(customization => { + (allCustomizations, dashboardChartIds): ChartCustomizationConfiguration => { + const hasLegacyFormat = allCustomizations.some(item => + isLegacyChartCustomizationFormat(item), + ); + + const migratedCustomizations = hasLegacyFormat + ? migrateChartCustomizationArray(allCustomizations) + : (allCustomizations as ChartCustomizationConfiguration); + + return migratedCustomizations.filter(customization => { if ( !customization.chartsInScope || customization.chartsInScope.length === 0 @@ -108,7 +120,8 @@ const selectChartCustomizationConfiguration = createSelector( return customization.chartsInScope.some((chartId: number) => dashboardChartIds.has(chartId), ); - }), + }); + }, ); export function useChartCustomizationConfiguration() { @@ -270,10 +283,20 @@ export function useIsCustomizationInScope() { (customization: ChartCustomization | ChartCustomizationDivider) => { if ('title' in customization) return true; - const isChartInScope = + const hasChartsInScope = Array.isArray(customization.chartsInScope) && - customization.chartsInScope.length > 0 && - customization.chartsInScope.some((chartId: number) => { + customization.chartsInScope.length > 0; + const hasTabsInScope = + Array.isArray(customization.tabsInScope) && + customization.tabsInScope.length > 0; + + if (!hasChartsInScope && !hasTabsInScope) { + return true; + } + + const isChartInScope = + hasChartsInScope && + customization.chartsInScope!.some((chartId: number) => { const tabParents = selectChartTabParents(chartId); // Note: every() returns true for empty arrays, so length check is unnecessary return ( @@ -281,9 +304,9 @@ export function useIsCustomizationInScope() { ); }); - const isCustomizationInActiveTab = customization.tabsInScope?.some(tab => - activeTabs.includes(tab), - ); + const isCustomizationInActiveTab = + hasTabsInScope && + customization.tabsInScope!.some(tab => activeTabs.includes(tab)); return isChartInScope || isCustomizationInActiveTab; }, diff --git a/superset-frontend/src/dashboard/util/migrateChartCustomization.test.ts b/superset-frontend/src/dashboard/util/migrateChartCustomization.test.ts new file mode 100644 index 000000000000..28784c7378a2 --- /dev/null +++ b/superset-frontend/src/dashboard/util/migrateChartCustomization.test.ts @@ -0,0 +1,490 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { ChartCustomizationType } from '@superset-ui/core'; +import { ChartCustomizationPlugins } from 'src/constants'; +import { + isLegacyChartCustomizationFormat, + migrateChartCustomization, + migrateChartCustomizationArray, +} from './migrateChartCustomization'; +import { DASHBOARD_ROOT_ID } from './constants'; + +test('isLegacyChartCustomizationFormat detects legacy format', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: 1, + column: 'country', + }, + }; + expect(isLegacyChartCustomizationFormat(legacy)).toBe(true); +}); + +test('isLegacyChartCustomizationFormat rejects new format', () => { + const newFormat = { + id: 'CUSTOMIZATION-1', + type: ChartCustomizationType.ChartCustomization, + name: 'Test', + filterType: ChartCustomizationPlugins.DynamicGroupBy, + targets: [], + }; + expect(isLegacyChartCustomizationFormat(newFormat)).toBe(false); +}); + +test('isLegacyChartCustomizationFormat rejects null', () => { + expect(isLegacyChartCustomizationFormat(null)).toBe(false); +}); + +test('isLegacyChartCustomizationFormat rejects undefined', () => { + expect(isLegacyChartCustomizationFormat(undefined)).toBe(false); +}); + +test('isLegacyChartCustomizationFormat rejects string', () => { + expect(isLegacyChartCustomizationFormat('string')).toBe(false); +}); + +test('isLegacyChartCustomizationFormat rejects empty object', () => { + expect(isLegacyChartCustomizationFormat({})).toBe(false); +}); + +test('migrateChartCustomization handles basic legacy format', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + chartId: 123, + customization: { + name: 'Country Filter', + dataset: 1, + column: 'country', + sortAscending: true, + sortMetric: 'count', + canSelectMultiple: true, + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.id).toBe('CUSTOMIZATION-1'); + expect(result.type).toBe(ChartCustomizationType.ChartCustomization); + expect(result.name).toBe('Country Filter'); + expect(result.filterType).toBe(ChartCustomizationPlugins.DynamicGroupBy); + expect(result.targets).toEqual([ + { + datasetId: 1, + column: { name: 'country' }, + }, + ]); + expect(result.scope).toEqual({ + rootPath: [DASHBOARD_ROOT_ID], + excluded: [], + }); + expect(result.chartsInScope).toEqual([123]); + expect(result.tabsInScope).toBeUndefined(); + expect(result.cascadeParentIds).toEqual([]); + expect(result.controlValues).toEqual({ + sortAscending: true, + sortMetric: 'count', + canSelectMultiple: true, + }); +}); + +test('migrateChartCustomization handles dataset as string', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: '42', + column: 'country', + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.targets[0].datasetId).toBe(42); +}); + +test('migrateChartCustomization handles dataset as object', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: { + value: 42, + label: 'My Dataset', + table_name: 'my_table', + }, + column: 'country', + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.targets[0].datasetId).toBe(42); +}); + +test('migrateChartCustomization handles dataset object with string value', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: { + value: '99', + label: 'My Dataset', + }, + column: 'country', + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.targets[0].datasetId).toBe(99); +}); + +test('migrateChartCustomization handles column as array', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: 1, + column: ['country', 'region'], + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.targets[0].column?.name).toBe('country'); +}); + +test('migrateChartCustomization handles empty column array', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: 1, + column: [], + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.targets[0].column?.name).toBe(''); +}); + +test('migrateChartCustomization handles missing chartId', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: 1, + column: 'country', + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.chartsInScope).toBeUndefined(); +}); + +test('migrateChartCustomization uses title as fallback for name', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + title: 'Fallback Title', + customization: { + name: '', + dataset: 1, + column: 'country', + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.name).toBe('Fallback Title'); +}); + +test('migrateChartCustomization prefers customization.name over title', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + title: 'Fallback Title', + customization: { + name: 'Primary Name', + dataset: 1, + column: 'country', + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.name).toBe('Primary Name'); +}); + +test('migrateChartCustomization enhances defaultDataMask with groupby', () => { + const dataMask = { + extraFormData: { filters: [] }, + filterState: { value: ['USA'] }, + }; + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: 1, + column: 'country', + defaultDataMask: dataMask, + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.defaultDataMask).toEqual({ + extraFormData: { + filters: [], + custom_form_data: { + groupby: ['USA'], + }, + }, + filterState: { + value: ['USA'], + label: 'USA', + }, + }); +}); + +test('migrateChartCustomization provides default dataMask when missing', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: 1, + column: 'country', + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.defaultDataMask).toEqual({ + extraFormData: {}, + filterState: {}, + }); +}); + +test('migrateChartCustomization merges controlValues', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: 1, + column: 'country', + sortAscending: false, + controlValues: { + enableEmptyFilter: true, + customSetting: 'value', + }, + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.controlValues).toEqual({ + sortAscending: false, + sortMetric: undefined, + canSelectMultiple: undefined, + enableEmptyFilter: true, + customSetting: 'value', + }); +}); + +test('migrateChartCustomization preserves removed flag', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + removed: true, + customization: { + name: 'Test', + dataset: 1, + column: 'country', + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.removed).toBe(true); +}); + +test('migrateChartCustomization preserves description', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: 1, + column: 'country', + description: 'Filter by country', + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.description).toBe('Filter by country'); +}); + +test('migrateChartCustomization handles null dataset', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: null, + column: 'country', + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.targets[0].datasetId).toBe(0); +}); + +test('migrateChartCustomization handles null column', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: 1, + column: null, + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.targets[0].column?.name).toBe(''); +}); + +test('migrateChartCustomization handles non-numeric string dataset', () => { + const legacy = { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Test', + dataset: 'not-a-number', + column: 'country', + }, + }; + + const result = migrateChartCustomization(legacy); + + expect(result.targets[0].datasetId).toBe(0); +}); + +test('migrateChartCustomizationArray migrates mixed array', () => { + const items = [ + { + id: 'CUSTOMIZATION-1', + customization: { + name: 'Legacy', + dataset: 1, + column: 'country', + }, + }, + { + id: 'CUSTOMIZATION-2', + type: ChartCustomizationType.ChartCustomization, + name: 'Already Migrated', + filterType: ChartCustomizationPlugins.DynamicGroupBy, + targets: [{ datasetId: 2, column: { name: 'region' } }], + scope: { rootPath: [DASHBOARD_ROOT_ID], excluded: [] }, + chartsInScope: [], + tabsInScope: [], + cascadeParentIds: [], + defaultDataMask: { extraFormData: {}, filterState: {} }, + controlValues: {}, + }, + ]; + + const result = migrateChartCustomizationArray(items); + + expect(result).toHaveLength(2); + expect(result[0].type).toBe(ChartCustomizationType.ChartCustomization); + expect(result[0].name).toBe('Legacy'); + expect(result[1].name).toBe('Already Migrated'); +}); + +test('migrateChartCustomizationArray handles empty array', () => { + const result = migrateChartCustomizationArray([]); + expect(result).toEqual([]); +}); + +test('migrateChartCustomizationArray handles all legacy items', () => { + const items = [ + { + id: 'CUSTOMIZATION-1', + customization: { + name: 'First', + dataset: 1, + column: 'col1', + }, + }, + { + id: 'CUSTOMIZATION-2', + customization: { + name: 'Second', + dataset: 2, + column: 'col2', + }, + }, + ]; + + const result = migrateChartCustomizationArray(items); + + expect(result).toHaveLength(2); + expect(result[0].type).toBe(ChartCustomizationType.ChartCustomization); + expect(result[1].type).toBe(ChartCustomizationType.ChartCustomization); + expect(result[0].name).toBe('First'); + expect(result[1].name).toBe('Second'); +}); + +test('migrateChartCustomizationArray handles all new format items', () => { + const items = [ + { + id: 'CUSTOMIZATION-1', + type: ChartCustomizationType.ChartCustomization, + name: 'First', + filterType: ChartCustomizationPlugins.DynamicGroupBy, + targets: [{ datasetId: 1, column: { name: 'col1' } }], + scope: { rootPath: [DASHBOARD_ROOT_ID], excluded: [] }, + chartsInScope: [], + tabsInScope: [], + cascadeParentIds: [], + defaultDataMask: { extraFormData: {}, filterState: {} }, + controlValues: {}, + }, + { + id: 'CUSTOMIZATION-2', + type: ChartCustomizationType.ChartCustomization, + name: 'Second', + filterType: ChartCustomizationPlugins.DynamicGroupBy, + targets: [{ datasetId: 2, column: { name: 'col2' } }], + scope: { rootPath: [DASHBOARD_ROOT_ID], excluded: [] }, + chartsInScope: [], + tabsInScope: [], + cascadeParentIds: [], + defaultDataMask: { extraFormData: {}, filterState: {} }, + controlValues: {}, + }, + ]; + + const result = migrateChartCustomizationArray(items); + + expect(result).toHaveLength(2); + expect(result[0].name).toBe('First'); + expect(result[1].name).toBe('Second'); +}); diff --git a/superset-frontend/src/dashboard/util/migrateChartCustomization.ts b/superset-frontend/src/dashboard/util/migrateChartCustomization.ts new file mode 100644 index 000000000000..e658c57c0f4a --- /dev/null +++ b/superset-frontend/src/dashboard/util/migrateChartCustomization.ts @@ -0,0 +1,155 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { + ChartCustomization, + ChartCustomizationType, + LegacyChartCustomizationItem, + LegacyChartCustomizationDataset, +} from '@superset-ui/core'; +import { ChartCustomizationPlugins } from 'src/constants'; +import { DASHBOARD_ROOT_ID } from './constants'; + +export function isLegacyChartCustomizationFormat( + item: unknown, +): item is LegacyChartCustomizationItem { + return ( + typeof item === 'object' && + item !== null && + 'customization' in item && + !('type' in item) + ); +} + +function extractDatasetId( + dataset: string | number | LegacyChartCustomizationDataset | null, +): number { + if (dataset === null) { + return 0; + } + if (typeof dataset === 'number') { + return dataset; + } + if (typeof dataset === 'string') { + const parsed = Number.parseInt(dataset, 10); + return Number.isNaN(parsed) ? 0 : parsed; + } + if (typeof dataset === 'object') { + const { value } = dataset; + return typeof value === 'number' + ? value + : Number.parseInt(String(value), 10) || 0; + } + return 0; +} + +function extractColumnName(column: string | string[] | null): string { + if (column === null) { + return ''; + } + if (Array.isArray(column)) { + return column[0] || ''; + } + return column; +} + +export function migrateChartCustomization( + legacy: LegacyChartCustomizationItem, +): ChartCustomization { + const { customization } = legacy; + const datasetId = extractDatasetId(customization.dataset); + const columnName = extractColumnName(customization.column); + + const controlValues: ChartCustomization['controlValues'] = { + sortAscending: customization.sortAscending, + sortMetric: customization.sortMetric, + canSelectMultiple: customization.canSelectMultiple, + }; + + if (customization.controlValues) { + Object.assign(controlValues, customization.controlValues); + } + + let defaultDataMask = customization.defaultDataMask || { + extraFormData: {}, + filterState: {}, + }; + + const filterStateValue = defaultDataMask.filterState?.value; + if (filterStateValue) { + const groupbyValue = Array.isArray(filterStateValue) + ? filterStateValue + : [filterStateValue]; + + defaultDataMask = { + ...defaultDataMask, + extraFormData: { + ...defaultDataMask.extraFormData, + custom_form_data: { + ...((defaultDataMask.extraFormData as Record) + ?.custom_form_data as Record), + groupby: groupbyValue, + }, + }, + filterState: { + ...defaultDataMask.filterState, + label: defaultDataMask.filterState?.label || groupbyValue.join(', '), + value: filterStateValue, + }, + }; + } + + const migrated: ChartCustomization = { + id: legacy.id, + type: ChartCustomizationType.ChartCustomization, + name: customization.name || legacy.title || '', + filterType: ChartCustomizationPlugins.DynamicGroupBy, + targets: [ + { + datasetId, + column: { + name: columnName, + }, + }, + ], + scope: { + rootPath: [DASHBOARD_ROOT_ID], + excluded: [], + }, + chartsInScope: legacy.chartId ? [legacy.chartId] : undefined, + tabsInScope: undefined, + cascadeParentIds: [], + defaultDataMask, + controlValues, + description: customization.description, + removed: legacy.removed, + }; + + return migrated; +} + +export function migrateChartCustomizationArray( + items: unknown[], +): ChartCustomization[] { + return items.map(item => { + if (isLegacyChartCustomizationFormat(item)) { + return migrateChartCustomization(item); + } + return item as ChartCustomization; + }); +} diff --git a/superset-frontend/src/dataMask/reducer.ts b/superset-frontend/src/dataMask/reducer.ts index b049c0efde2b..011cc49440c1 100644 --- a/superset-frontend/src/dataMask/reducer.ts +++ b/superset-frontend/src/dataMask/reducer.ts @@ -37,6 +37,10 @@ import { } from 'src/dashboard/components/nativeFilters/FiltersConfigModal/utils'; import { HYDRATE_DASHBOARD } from 'src/dashboard/actions/hydrate'; import { SaveFilterChangesType } from 'src/dashboard/components/nativeFilters/FiltersConfigModal/types'; +import { + migrateChartCustomizationArray, + isLegacyChartCustomizationFormat, +} from 'src/dashboard/util/migrateChartCustomization'; import { isEqual } from 'lodash'; import { AnyDataMaskAction, @@ -222,9 +226,17 @@ const dataMaskReducer = produce( loadedDataMask, ); - const chartCustomizationConfig = + const rawChartCustomizationConfig = metadata?.chart_customization_config || []; + const hasLegacyFormat = rawChartCustomizationConfig.some(item => + isLegacyChartCustomizationFormat(item), + ); + + const chartCustomizationConfig = hasLegacyFormat + ? migrateChartCustomizationArray(rawChartCustomizationConfig) + : (rawChartCustomizationConfig as ChartCustomization[]); + chartCustomizationConfig.forEach(item => { if (!isChartCustomizationItem(item)) { return; diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx index 5509eae785b5..7a7069673883 100644 --- a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx +++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx @@ -51,16 +51,6 @@ interface ColumnSelectPopoverTriggerProps { selectedMetrics?: QueryFormMetric[]; } -const ColumnSelectPopoverTriggerWrapper = ( - props: ColumnSelectPopoverTriggerProps, -) => { - const datasource = useSelector( - (state: any) => state?.explore?.datasource || null, - ); - - return ; -}; - interface ColumnSelectPopoverTriggerInnerProps extends ColumnSelectPopoverTriggerProps { datasource?: any; } @@ -217,4 +207,14 @@ const ColumnSelectPopoverTriggerInner = ({ ); }; +const ColumnSelectPopoverTriggerWrapper = ( + props: ColumnSelectPopoverTriggerProps, +) => { + const datasource = useSelector( + (state: any) => state?.explore?.datasource || null, + ); + + return ; +}; + export default ColumnSelectPopoverTriggerWrapper; diff --git a/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetric.ts b/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetric.ts index 7bd04bd0f184..68c1d2875c8c 100644 --- a/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetric.ts +++ b/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetric.ts @@ -87,33 +87,6 @@ function inferSqlExpressionAggregate( return null; } -/** - * Adapter function to create an AdhocMetric instance from a core AdhocMetric type. - * This bridges the type gap between @superset-ui/core's AdhocMetric and the local class. - */ -export function fromCoreAdhocMetric(metric: CoreAdhocMetric): AdhocMetric { - return new AdhocMetric(metric as AdhocMetricInput); -} - -/** - * Type guard to check if an object can be used to construct an AdhocMetric. - * Returns true for plain objects that have metric-like properties. - */ -export function isDictionaryForAdhocMetric( - value: unknown, -): value is AdhocMetricInput { - return ( - typeof value === 'object' && - value !== null && - !(value instanceof AdhocMetric) && - ('expressionType' in value || - 'column' in value || - 'aggregate' in value || - 'sqlExpression' in value || - 'metric_name' in value) - ); -} - export default class AdhocMetric { expressionType: string; column?: ColumnType | null; @@ -224,3 +197,30 @@ export default class AdhocMetric { return inferSqlExpressionColumn(this as unknown as AdhocMetricInput); } } + +/** + * Type guard to check if an object can be used to construct an AdhocMetric. + * Returns true for plain objects that have metric-like properties. + */ +export function isDictionaryForAdhocMetric( + value: unknown, +): value is AdhocMetricInput { + return ( + typeof value === 'object' && + value !== null && + !(value instanceof AdhocMetric) && + ('expressionType' in value || + 'column' in value || + 'aggregate' in value || + 'sqlExpression' in value || + 'metric_name' in value) + ); +} + +/** + * Adapter function to create an AdhocMetric instance from a core AdhocMetric type. + * This bridges the type gap between @superset-ui/core's AdhocMetric and the local class. + */ +export function fromCoreAdhocMetric(metric: CoreAdhocMetric): AdhocMetric { + return new AdhocMetric(metric as AdhocMetricInput); +} diff --git a/superset-frontend/src/explore/components/controls/TextAreaControl.tsx b/superset-frontend/src/explore/components/controls/TextAreaControl.tsx index f8365029ae37..6b5c8a86b198 100644 --- a/superset-frontend/src/explore/components/controls/TextAreaControl.tsx +++ b/superset-frontend/src/explore/components/controls/TextAreaControl.tsx @@ -141,21 +141,44 @@ class TextAreaControl extends Component { } renderEditor(inModal = false) { - const minLines = inModal ? 40 : this.props.minLines || 12; - if (this.props.language) { + // Exclude props that shouldn't be passed to TextAreaEditor: + // - theme: TextAreaEditor expects theme as a string, not the theme object from withTheme HOC + // - height: ReactAce expects string, we pass number (height is controlled via minLines/maxLines) + // - other control-specific props and explicitly-set props to avoid duplicate/conflicting assignments + const { + theme, + height, + offerEditInModal, + aboveEditorSection, + resize, + textAreaStyles, + tooltipOptions, + hotkeys, + debounceDelay, + language, + initialValue, + readOnly, + name, + onChange, + minLines: minLinesProp, + maxLines: maxLinesProp, + ...editorProps + } = this.props; + const minLines = inModal ? 40 : minLinesProp || 12; + if (language) { const style: React.CSSProperties = { - border: this.props.theme?.colorBorder - ? `1px solid ${this.props.theme.colorBorder}` + border: theme?.colorBorder + ? `1px solid ${theme.colorBorder}` : undefined, minHeight: `${minLines}em`, width: 'auto', - ...this.props.textAreaStyles, + ...textAreaStyles, }; - if (this.props.resize) { - style.resize = this.props.resize; + if (resize) { + style.resize = resize; } - if (this.props.readOnly) { - style.backgroundColor = this.props.theme?.colorBgMask; + if (readOnly) { + style.backgroundColor = theme?.colorBgMask; } const onEditorLoad = (editor: { commands: { @@ -166,7 +189,7 @@ class TextAreaControl extends Component { }) => void; }; }) => { - this.props.hotkeys?.forEach(keyConfig => { + hotkeys?.forEach(keyConfig => { editor.commands.addCommand({ name: keyConfig.name, bindKey: { win: keyConfig.key, mac: keyConfig.key }, @@ -177,23 +200,23 @@ class TextAreaControl extends Component { const codeEditor = (
); - if (this.props.tooltipOptions) { - return {codeEditor}; + if (tooltipOptions) { + return {codeEditor}; } return codeEditor; } diff --git a/superset-frontend/src/features/alerts/AlertReportModal.tsx b/superset-frontend/src/features/alerts/AlertReportModal.tsx index fa25c7c75fd3..39c15b18aedf 100644 --- a/superset-frontend/src/features/alerts/AlertReportModal.tsx +++ b/superset-frontend/src/features/alerts/AlertReportModal.tsx @@ -610,6 +610,20 @@ const AlertReportModal: FunctionComponent = ({ const [emailSubject, setEmailSubject] = useState(''); const [emailError, setEmailError] = useState(false); + const allowedNotificationMethodsCount = useMemo( + () => + allowedNotificationMethods.reduce((accum: string[], setting: string) => { + if ( + accum.some(nm => nm.includes('slack')) && + setting.toLowerCase().includes('slack') + ) { + return accum; + } + return [...accum, setting.toLowerCase()]; + }, []).length, + [allowedNotificationMethods], + ); + const onNotificationAdd = () => { setNotificationSettings([ ...notificationSettings, @@ -2013,20 +2027,6 @@ const AlertReportModal: FunctionComponent = ({ enforceValidation(); }, [validationStatus]); - const allowedNotificationMethodsCount = useMemo( - () => - allowedNotificationMethods.reduce((accum: string[], setting: string) => { - if ( - accum.some(nm => nm.includes('slack')) && - setting.toLowerCase().includes('slack') - ) { - return accum; - } - return [...accum, setting.toLowerCase()]; - }, []).length, - [allowedNotificationMethods], - ); - // Show/hide if (isHidden && show) { setIsHidden(false); diff --git a/superset-frontend/src/features/databases/DatabaseModal/index.tsx b/superset-frontend/src/features/databases/DatabaseModal/index.tsx index bbb4dd6bf5cf..7b0834077e52 100644 --- a/superset-frontend/src/features/databases/DatabaseModal/index.tsx +++ b/superset-frontend/src/features/databases/DatabaseModal/index.tsx @@ -712,6 +712,12 @@ const DatabaseModal: FunctionComponent = ({ ) || {}; + const handleClearValidationErrors = useCallback(() => { + setValidationErrors(null); + setHasValidated(false); + clearError(); + }, [setValidationErrors, setHasValidated, clearError]); + // Test Connection logic const testConnection = () => { handleClearValidationErrors(); @@ -773,12 +779,6 @@ const DatabaseModal: FunctionComponent = ({ [], ); - const handleClearValidationErrors = useCallback(() => { - setValidationErrors(null); - setHasValidated(false); - clearError(); - }, [setValidationErrors, setHasValidated, clearError]); - const handleParametersChange = useCallback( ({ target }: { target: HTMLInputElement }) => { onChange(ActionType.ParametersChange, { diff --git a/superset-frontend/src/pages/UserInfo/index.tsx b/superset-frontend/src/pages/UserInfo/index.tsx index 8f1138a6d64a..4c5bdea5faca 100644 --- a/superset-frontend/src/pages/UserInfo/index.tsx +++ b/superset-frontend/src/pages/UserInfo/index.tsx @@ -94,10 +94,6 @@ export function UserInfo({ user }: { user: UserWithPermissionsAndRoles }) { const { addDangerToast } = useToasts(); const [userDetails, setUserDetails] = useState(user); - useEffect(() => { - getUserDetails(); - }, []); - const getUserDetails = useCallback(() => { SupersetClient.get({ endpoint: '/api/v1/me/' }) .then(({ json }) => { @@ -113,6 +109,10 @@ export function UserInfo({ user }: { user: UserWithPermissionsAndRoles }) { }); }, [userDetails]); + useEffect(() => { + getUserDetails(); + }, []); + const SubMenuButtons: SubMenuProps['buttons'] = [ { name: ( diff --git a/superset/db_engine_specs/gsheets.py b/superset/db_engine_specs/gsheets.py index 780f92cc750f..9692db9d9a65 100644 --- a/superset/db_engine_specs/gsheets.py +++ b/superset/db_engine_specs/gsheets.py @@ -203,13 +203,18 @@ def needs_oauth2(cls, ex: Exception) -> bool: In case the token was manually revoked on Google side, `google-auth` will try to automatically refresh credentials, but it fails since it only has the access token. This override catches this scenario as well. + + Also catches the case where no credentials are configured at all + (missing Application Default Credentials). """ + error_message = str(ex).lower() return ( g and hasattr(g, "user") and ( isinstance(ex, cls.oauth2_exception) - or "credentials do not contain the necessary fields" in str(ex) + or "credentials do not contain the necessary fields" in error_message + or "default credentials were not found" in error_message ) ) diff --git a/superset/models/helpers.py b/superset/models/helpers.py index 754956cbc2fa..a1c92adaa146 100644 --- a/superset/models/helpers.py +++ b/superset/models/helpers.py @@ -2800,6 +2800,21 @@ def get_sqla_query( # pylint: disable=too-many-arguments,too-many-locals,too-ma col = self.convert_tbl_column_to_sqla_col( columns_by_name[col], template_processor=template_processor ) + elif isinstance(col, str) and columns: + # Check if this is a label reference to an adhoc column + adhoc_col = next( + ( + c + for c in columns + if utils.is_adhoc_column(c) and c.get("label") == col + ), + None, + ) + if adhoc_col: + col = self.adhoc_column_to_sqla( + col=adhoc_col, + template_processor=template_processor, + ) if isinstance(col, ColumnElement): orderby_exprs.append(col) diff --git a/superset/utils/encrypt.py b/superset/utils/encrypt.py index ab05e455a380..b833fc79de8b 100644 --- a/superset/utils/encrypt.py +++ b/superset/utils/encrypt.py @@ -54,7 +54,7 @@ def create( **kwargs: Optional[dict[str, Any]], ) -> TypeDecorator: if app_config: - return EncryptedType(*args, app_config["SECRET_KEY"], **kwargs) + return EncryptedType(*args, lambda: app_config["SECRET_KEY"], **kwargs) raise Exception( # pylint: disable=broad-exception-raised "Missing app_config kwarg" diff --git a/tests/integration_tests/utils/encrypt_tests.py b/tests/integration_tests/utils/encrypt_tests.py index 4f48f6691323..95279ee607ed 100644 --- a/tests/integration_tests/utils/encrypt_tests.py +++ b/tests/integration_tests/utils/encrypt_tests.py @@ -16,6 +16,7 @@ # under the License. from typing import Any, Optional +import pytest from sqlalchemy import String, TypeDecorator from sqlalchemy_utils import EncryptedType from sqlalchemy_utils.types.encrypted.encrypted_type import StringEncryptedType @@ -54,7 +55,8 @@ def setUp(self) -> None: def test_create_field(self): field = encrypted_field_factory.create(String(1024)) assert isinstance(field, EncryptedType) - assert self.app.config["SECRET_KEY"] == field.key + assert callable(field.key) + assert self.app.config["SECRET_KEY"] == field.key() def test_custom_adapter(self): self.app.config["SQLALCHEMY_ENCRYPTED_FIELD_TYPE_ADAPTER"] = ( @@ -86,3 +88,75 @@ def test_ensure_encrypted_field_factory_is_used(self): " was not created using the" " encrypted_field_factory" ) + + def test_lazy_key_resolution(self): + """ + Verify that the encryption key is resolved lazily at runtime, + not captured statically at field creation time. + """ + original_key = self.app.config["SECRET_KEY"] + field = encrypted_field_factory.create(String(1024)) + + # Key should initially resolve to the current SECRET_KEY + assert callable(field.key) + assert field.key() == original_key + + # Simulate a key change (e.g. config override, env var update) + new_key = "ROTATED_TEST_KEY_12345" + self.app.config["SECRET_KEY"] = new_key + + # The field's key should now resolve to the new value + assert field.key() == new_key + + # Restore original key + self.app.config["SECRET_KEY"] = original_key + assert field.key() == original_key + + def test_secret_key_rotation(self): + """ + End-to-end test: encrypt data with KEY_A, rotate to KEY_B, + run re-encryption, and verify data is accessible under KEY_B. + """ + from sqlalchemy.engine import make_url + + key_a = self.app.config["SECRET_KEY"] + key_b = "NEW_ROTATION_TEST_KEY_67890" + test_value = "super_secret_password_123" + + field = encrypted_field_factory.create(String(1024)) + dialect = make_url("sqlite://").get_dialect() + + # Step 1: Encrypt with KEY_A + encrypted_a = field.process_bind_param(test_value, dialect) + assert encrypted_a is not None + assert encrypted_a != test_value + + # Step 2: Verify decryption with KEY_A works + decrypted = field.process_result_value(encrypted_a, dialect) + assert decrypted == test_value + + # Step 3: Rotate key to KEY_B + self.app.config["SECRET_KEY"] = key_b + + # Step 4: Re-encrypt with KEY_B (simulating SecretsMigrator logic) + # Decrypt using previous key + previous_field = EncryptedType(type_in=field.underlying_type, key=key_a) + decrypted_with_prev = previous_field.process_result_value(encrypted_a, dialect) + assert decrypted_with_prev == test_value + + # Re-encrypt using current key (KEY_B, resolved via lambda) + encrypted_b = field.process_bind_param(decrypted_with_prev, dialect) + assert encrypted_b is not None + assert encrypted_b != encrypted_a # Different ciphertext + + # Step 5: Verify decryption with KEY_B works + decrypted_b = field.process_result_value(encrypted_b, dialect) + assert decrypted_b == test_value + + # Step 6: Verify KEY_A can no longer decrypt the new ciphertext + self.app.config["SECRET_KEY"] = key_a + with pytest.raises(ValueError, match="Invalid decryption key"): + field.process_result_value(encrypted_b, dialect) + + # Restore original key + self.app.config["SECRET_KEY"] = key_a diff --git a/tests/unit_tests/db_engine_specs/test_gsheets.py b/tests/unit_tests/db_engine_specs/test_gsheets.py index a2406c18fc32..aac67ea1fe24 100644 --- a/tests/unit_tests/db_engine_specs/test_gsheets.py +++ b/tests/unit_tests/db_engine_specs/test_gsheets.py @@ -757,6 +757,26 @@ def test_needs_oauth2_with_credentials_error(mocker: MockerFixture) -> None: assert GSheetsEngineSpec.needs_oauth2(ex) is True +def test_needs_oauth2_with_default_credentials_not_found( + mocker: MockerFixture, +) -> None: + """ + Test that needs_oauth2 returns True when Application Default Credentials + are not configured. + """ + from superset.db_engine_specs.gsheets import GSheetsEngineSpec + + g = mocker.patch("superset.db_engine_specs.gsheets.g") + g.user = mocker.MagicMock() + + ex = Exception( + "Your default credentials were not found. To set up Application Default " + "Credentials, see https://cloud.google.com/docs/authentication/external/" + "set-up-adc for more information." + ) + assert GSheetsEngineSpec.needs_oauth2(ex) is True + + def test_needs_oauth2_with_other_error(mocker: MockerFixture) -> None: """ Test that needs_oauth2 returns False for other errors. diff --git a/tests/unit_tests/models/helpers_test.py b/tests/unit_tests/models/helpers_test.py index e913526975fb..e5a177285e80 100644 --- a/tests/unit_tests/models/helpers_test.py +++ b/tests/unit_tests/models/helpers_test.py @@ -1703,3 +1703,43 @@ def test_adhoc_column_with_spaces_in_full_query(database: Database) -> None: # Verify SELECT and FROM clauses are present assert "SELECT" in sql assert "FROM" in sql + + +def test_orderby_adhoc_column(database: Database) -> None: + """ + Test that orderby works with adhoc column labels. + + When orderby contains a string that matches the label of an adhoc column + in the columns list, it should correctly convert to a SQLAlchemy column + instead of raising QueryObjectValidationError. + """ + from superset.connectors.sqla.models import SqlaTable, TableColumn + + table = SqlaTable( + database=database, + schema=None, + table_name="t", + columns=[ + TableColumn(column_name="a"), + TableColumn(column_name="b"), + ], + ) + + # Should not raise QueryObjectValidationError + result = table.get_sqla_query( + columns=[ + {"expressionType": "SQL", "label": "custom_col", "sqlExpression": "a + 1"}, + "b", + ], + orderby=[("custom_col", False)], # Order by adhoc column label + metrics=[], + extras={}, + filter=[], + granularity=None, + is_timeseries=False, + ) + assert result is not None + + # Verify the SQL contains the expression from the adhoc column + sql = str(result.sqla_query) + assert "ORDER BY" in sql.upper()