mirror of
https://github.com/apache/superset.git
synced 2026-06-17 05:29:21 +00:00
Compare commits
19 Commits
enxdev/cha
...
chore/sqla
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
024aac2152 | ||
|
|
3e2174b50f | ||
|
|
5b66443d48 | ||
|
|
2ea7585490 | ||
|
|
eeac76146c | ||
|
|
6a1091d576 | ||
|
|
8e82b6b2c3 | ||
|
|
b0c5f99007 | ||
|
|
f1ae683923 | ||
|
|
d51d98891e | ||
|
|
44f0667a55 | ||
|
|
1f95a6c486 | ||
|
|
e93cbd6c38 | ||
|
|
dca8af770c | ||
|
|
81c1181519 | ||
|
|
387c62919e | ||
|
|
77d7483f27 | ||
|
|
1a8d08152d | ||
|
|
257dafeec5 |
@@ -109,7 +109,7 @@
|
||||
"globals": "^17.6.0",
|
||||
"prettier": "^3.8.3",
|
||||
"typescript": "~6.0.3",
|
||||
"typescript-eslint": "^8.60.1",
|
||||
"typescript-eslint": "^8.61.0",
|
||||
"webpack": "^5.107.2"
|
||||
},
|
||||
"browserslist": {
|
||||
|
||||
@@ -7235,10 +7235,10 @@
|
||||
"pypi_packages": [
|
||||
"oracledb"
|
||||
],
|
||||
"connection_string": "oracle://{username}:{password}@{hostname}:{port}",
|
||||
"connection_string": "oracle+oracledb://{username}:{password}@{hostname}:{port}",
|
||||
"default_port": 1521,
|
||||
"notes": "Previously used cx_Oracle, now uses oracledb.",
|
||||
"docs_url": "https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html",
|
||||
"docs_url": "https://python-oracledb.readthedocs.io/en/latest/user_guide/installation.html",
|
||||
"category": "Other Databases"
|
||||
},
|
||||
"engine": "oracle",
|
||||
|
||||
127
docs/yarn.lock
127
docs/yarn.lock
@@ -4922,32 +4922,21 @@
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@8.60.1", "@typescript-eslint/eslint-plugin@^8.59.3":
|
||||
version "8.60.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.1.tgz#c1060bb8fa4be80624d3f3dec8dd9caca373af76"
|
||||
integrity sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==
|
||||
"@typescript-eslint/eslint-plugin@8.61.0", "@typescript-eslint/eslint-plugin@^8.59.3":
|
||||
version "8.61.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz#db20271974b94a3a54d3b9544e5f5b3481448400"
|
||||
integrity sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.12.2"
|
||||
"@typescript-eslint/scope-manager" "8.60.1"
|
||||
"@typescript-eslint/type-utils" "8.60.1"
|
||||
"@typescript-eslint/utils" "8.60.1"
|
||||
"@typescript-eslint/visitor-keys" "8.60.1"
|
||||
"@typescript-eslint/scope-manager" "8.61.0"
|
||||
"@typescript-eslint/type-utils" "8.61.0"
|
||||
"@typescript-eslint/utils" "8.61.0"
|
||||
"@typescript-eslint/visitor-keys" "8.61.0"
|
||||
ignore "^7.0.5"
|
||||
natural-compare "^1.4.0"
|
||||
ts-api-utils "^2.5.0"
|
||||
|
||||
"@typescript-eslint/parser@8.60.1":
|
||||
version "8.60.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.60.1.tgz#a9d7f30850384d34b41f4687dd8944823c09e289"
|
||||
integrity sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "8.60.1"
|
||||
"@typescript-eslint/types" "8.60.1"
|
||||
"@typescript-eslint/typescript-estree" "8.60.1"
|
||||
"@typescript-eslint/visitor-keys" "8.60.1"
|
||||
debug "^4.4.3"
|
||||
|
||||
"@typescript-eslint/parser@^8.61.0":
|
||||
"@typescript-eslint/parser@8.61.0", "@typescript-eslint/parser@^8.61.0":
|
||||
version "8.61.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.61.0.tgz#1afe73c9ccce16b7a26d6b95f9400b0ccc34af87"
|
||||
integrity sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==
|
||||
@@ -4958,15 +4947,6 @@
|
||||
"@typescript-eslint/visitor-keys" "8.61.0"
|
||||
debug "^4.4.3"
|
||||
|
||||
"@typescript-eslint/project-service@8.60.1":
|
||||
version "8.60.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.60.1.tgz#eb29712f58d72c222fc727162e92f2ab4670971b"
|
||||
integrity sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==
|
||||
dependencies:
|
||||
"@typescript-eslint/tsconfig-utils" "^8.60.1"
|
||||
"@typescript-eslint/types" "^8.60.1"
|
||||
debug "^4.4.3"
|
||||
|
||||
"@typescript-eslint/project-service@8.61.0":
|
||||
version "8.61.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.61.0.tgz#417a2feac32e8ebd336d63f068c3b42b736ea1ac"
|
||||
@@ -4976,14 +4956,6 @@
|
||||
"@typescript-eslint/types" "^8.61.0"
|
||||
debug "^4.4.3"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.60.1":
|
||||
version "8.60.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.60.1.tgz#2f875962eaad0a0789cc3c36aea9b4ddeb2dd9c8"
|
||||
integrity sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.60.1"
|
||||
"@typescript-eslint/visitor-keys" "8.60.1"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.61.0":
|
||||
version "8.61.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz#93c2520d05653fe65eb9ee98efc74fd0134a7852"
|
||||
@@ -4992,12 +4964,7 @@
|
||||
"@typescript-eslint/types" "8.61.0"
|
||||
"@typescript-eslint/visitor-keys" "8.61.0"
|
||||
|
||||
"@typescript-eslint/tsconfig-utils@8.60.1":
|
||||
version "8.60.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.1.tgz#bee8b942a13679a878101c9c74577d732062ed93"
|
||||
integrity sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==
|
||||
|
||||
"@typescript-eslint/tsconfig-utils@8.61.0", "@typescript-eslint/tsconfig-utils@^8.60.1":
|
||||
"@typescript-eslint/tsconfig-utils@8.61.0":
|
||||
version "8.61.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz#05d6e3ff20001674ebcd22d03dac29ee448043ba"
|
||||
integrity sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==
|
||||
@@ -5007,47 +4974,27 @@
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.1.tgz#ca88080e0cf191d49516d7f300b67aa090d2254f"
|
||||
integrity sha512-UN/H4di+OO7EWx2ovME+8t31YO+KVnK0RRKEHR3kOt21/Ay8BOq3M1OMvWs5vNiqcFCYGYoxK3MXPZzmMUE+yg==
|
||||
|
||||
"@typescript-eslint/type-utils@8.60.1":
|
||||
version "8.60.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.60.1.tgz#1ae45f0f2a701354beea4a58c2161e40a5e3c379"
|
||||
integrity sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==
|
||||
"@typescript-eslint/type-utils@8.61.0":
|
||||
version "8.61.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz#50219b57e6b89cecfb1a15f093b15ec9ee019974"
|
||||
integrity sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.60.1"
|
||||
"@typescript-eslint/typescript-estree" "8.60.1"
|
||||
"@typescript-eslint/utils" "8.60.1"
|
||||
"@typescript-eslint/types" "8.61.0"
|
||||
"@typescript-eslint/typescript-estree" "8.61.0"
|
||||
"@typescript-eslint/utils" "8.61.0"
|
||||
debug "^4.4.3"
|
||||
ts-api-utils "^2.5.0"
|
||||
|
||||
"@typescript-eslint/types@8.60.1":
|
||||
version "8.60.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.60.1.tgz#ccdc482ba9e17f9723a10ce240b5e67dad3046c4"
|
||||
integrity sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==
|
||||
|
||||
"@typescript-eslint/types@8.61.0":
|
||||
version "8.61.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.61.0.tgz#0ddb46e012a4288292950bdd253db42f278ce64d"
|
||||
integrity sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==
|
||||
|
||||
"@typescript-eslint/types@^8.60.1", "@typescript-eslint/types@^8.61.0":
|
||||
"@typescript-eslint/types@^8.61.0":
|
||||
version "8.61.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.61.1.tgz#0c51f518e4e6848371a1c988e859d59eb7522d5a"
|
||||
integrity sha512-G+CRlPqLv7Bz1IZVs03x5K59F1veqL0EJUROAdGhKsEq8qOiRiZbI+HUojPq5l0fEGOKModD9br6lObhB8zkoA==
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.60.1":
|
||||
version "8.60.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.1.tgz#016630b119228bf483ddc652703a6a038f3fdd74"
|
||||
integrity sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==
|
||||
dependencies:
|
||||
"@typescript-eslint/project-service" "8.60.1"
|
||||
"@typescript-eslint/tsconfig-utils" "8.60.1"
|
||||
"@typescript-eslint/types" "8.60.1"
|
||||
"@typescript-eslint/visitor-keys" "8.60.1"
|
||||
debug "^4.4.3"
|
||||
minimatch "^10.2.2"
|
||||
semver "^7.7.3"
|
||||
tinyglobby "^0.2.15"
|
||||
ts-api-utils "^2.5.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.61.0":
|
||||
version "8.61.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz#98ca47260bbf627fc28f018b3a0abf00e3090690"
|
||||
@@ -5063,23 +5010,15 @@
|
||||
tinyglobby "^0.2.15"
|
||||
ts-api-utils "^2.5.0"
|
||||
|
||||
"@typescript-eslint/utils@8.60.1":
|
||||
version "8.60.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.60.1.tgz#31cf566095602d9fe8ad91837d2eb520b8de762b"
|
||||
integrity sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==
|
||||
"@typescript-eslint/utils@8.61.0":
|
||||
version "8.61.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.61.0.tgz#ed3546a052787e84ea6c5064d0919fc5eea8522f"
|
||||
integrity sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.9.1"
|
||||
"@typescript-eslint/scope-manager" "8.60.1"
|
||||
"@typescript-eslint/types" "8.60.1"
|
||||
"@typescript-eslint/typescript-estree" "8.60.1"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.60.1":
|
||||
version "8.60.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.1.tgz#165d1d8901137b944efaf18f00ab5ecb57f06995"
|
||||
integrity sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.60.1"
|
||||
eslint-visitor-keys "^5.0.0"
|
||||
"@typescript-eslint/scope-manager" "8.61.0"
|
||||
"@typescript-eslint/types" "8.61.0"
|
||||
"@typescript-eslint/typescript-estree" "8.61.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.61.0":
|
||||
version "8.61.0"
|
||||
@@ -14560,15 +14499,15 @@ types-ramda@^0.30.1:
|
||||
dependencies:
|
||||
ts-toolbelt "^9.6.0"
|
||||
|
||||
typescript-eslint@^8.60.1:
|
||||
version "8.60.1"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.60.1.tgz#13db05c6eabb89669deec44545b788a0e9aee640"
|
||||
integrity sha512-6m5hkkRAp8lKvhVpcprAIn5KkehQEh+47oHH2VGnExEh7dhNxXlg6GPAOIu6TxbVQxhebrJDvjl3020ooiWCMA==
|
||||
typescript-eslint@^8.61.0:
|
||||
version "8.61.0"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.61.0.tgz#6927fb94f5f29623e370d33fd9fa61f15d6d996b"
|
||||
integrity sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==
|
||||
dependencies:
|
||||
"@typescript-eslint/eslint-plugin" "8.60.1"
|
||||
"@typescript-eslint/parser" "8.60.1"
|
||||
"@typescript-eslint/typescript-estree" "8.60.1"
|
||||
"@typescript-eslint/utils" "8.60.1"
|
||||
"@typescript-eslint/eslint-plugin" "8.61.0"
|
||||
"@typescript-eslint/parser" "8.61.0"
|
||||
"@typescript-eslint/typescript-estree" "8.61.0"
|
||||
"@typescript-eslint/utils" "8.61.0"
|
||||
|
||||
typescript@~6.0.3:
|
||||
version "6.0.3"
|
||||
|
||||
@@ -29,7 +29,7 @@ maintainers:
|
||||
- name: craig-rueda
|
||||
email: craig@craigrueda.com
|
||||
url: https://github.com/craig-rueda
|
||||
version: 0.16.0 # See [README](https://github.com/apache/superset/blob/master/helm/superset/README.md#versioning) for version details.
|
||||
version: 0.16.1 # See [README](https://github.com/apache/superset/blob/master/helm/superset/README.md#versioning) for version details.
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
version: 16.7.27
|
||||
|
||||
@@ -23,7 +23,7 @@ NOTE: This file is generated by helm-docs: https://github.com/norwoodj/helm-docs
|
||||
|
||||
# superset
|
||||
|
||||

|
||||

|
||||
|
||||
Apache Superset is a modern, enterprise-ready business intelligence web application
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ spec:
|
||||
{{- if .Values.init.initContainers }}
|
||||
initContainers: {{- tpl (toYaml .Values.init.initContainers) . | nindent 6 }}
|
||||
{{- end }}
|
||||
{{- with .Values.hostAliases }}
|
||||
hostAliases: {{- toYaml . | nindent 6 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: {{ template "superset.name" . }}-init-db
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
|
||||
@@ -43,7 +43,7 @@ dependencies = [
|
||||
"click-option-group",
|
||||
"colorama",
|
||||
"flask-cors>=6.0.0, <7.0",
|
||||
"croniter>=0.3.28",
|
||||
"croniter>=6.2.2",
|
||||
"cron-descriptor",
|
||||
"cryptography>=42.0.4, <47.0.0",
|
||||
"deprecation>=2.1.0, <2.2.0",
|
||||
@@ -53,7 +53,7 @@ dependencies = [
|
||||
"flask-compress>=1.13, <2.0",
|
||||
"flask-talisman>=1.0.0, <2.0",
|
||||
"flask-login>=0.6.0, < 1.0",
|
||||
"flask-migrate>=3.1.0, <5.0",
|
||||
"flask-migrate>=4.1.0, <5.0",
|
||||
"flask-session>=0.4.0, <1.0",
|
||||
"flask-wtf>=1.3.0, <2.0",
|
||||
"geopy",
|
||||
@@ -97,9 +97,9 @@ dependencies = [
|
||||
"selenium>=4.44.0, <5.0",
|
||||
"shillelagh[gsheetsapi]>=1.4.4, <2.0",
|
||||
"sshtunnel>=0.4.0, <0.5",
|
||||
"simplejson>=3.15.0",
|
||||
"simplejson>=4.1.1",
|
||||
"slack_sdk>=3.19.0, <4",
|
||||
"sqlalchemy>=1.4, <2",
|
||||
"sqlalchemy>=1.4.43, <2", # 1.4.43 adds the python-oracledb (oracle+oracledb) dialect
|
||||
"sqlalchemy-utils>=0.38.0, <0.43", # expanding lowerbound to work with pydoris
|
||||
"sqlglot>=30.8.0, <31",
|
||||
# newer pandas needs 0.9+
|
||||
@@ -177,7 +177,7 @@ ocient = [
|
||||
"shapely",
|
||||
"geojson",
|
||||
]
|
||||
oracle = ["cx-Oracle>8.0.0, <8.4"]
|
||||
oracle = ["oracledb>=2.0.0, <5"]
|
||||
parseable = ["sqlalchemy-parseable>=0.1.3,<0.2.0"]
|
||||
pinot = ["pinotdb>=5.0.0, <10.0.0"]
|
||||
playwright = ["playwright>=1.60.0, <2"]
|
||||
|
||||
@@ -84,7 +84,7 @@ colorama==0.4.6
|
||||
# flask-appbuilder
|
||||
cron-descriptor==1.4.5
|
||||
# via apache-superset (pyproject.toml)
|
||||
croniter==6.0.0
|
||||
croniter==6.2.2
|
||||
# via apache-superset (pyproject.toml)
|
||||
cryptography==46.0.7
|
||||
# via
|
||||
@@ -141,7 +141,7 @@ flask-login==0.6.3
|
||||
# via
|
||||
# apache-superset (pyproject.toml)
|
||||
# flask-appbuilder
|
||||
flask-migrate==3.1.0
|
||||
flask-migrate==4.1.0
|
||||
# via apache-superset (pyproject.toml)
|
||||
flask-session==0.8.0
|
||||
# via apache-superset (pyproject.toml)
|
||||
@@ -384,7 +384,7 @@ setuptools==80.9.0
|
||||
# via -r requirements/base.in
|
||||
shillelagh==1.4.4
|
||||
# via apache-superset (pyproject.toml)
|
||||
simplejson==3.20.1
|
||||
simplejson==4.1.1
|
||||
# via apache-superset (pyproject.toml)
|
||||
six==1.17.0
|
||||
# via
|
||||
|
||||
@@ -174,7 +174,7 @@ cron-descriptor==1.4.5
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
croniter==6.0.0
|
||||
croniter==6.2.2
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
@@ -293,7 +293,7 @@ flask-login==0.6.3
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
flask-migrate==3.1.0
|
||||
flask-migrate==4.1.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
@@ -939,7 +939,7 @@ shillelagh==1.4.4
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
simplejson==3.20.1
|
||||
simplejson==4.1.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
|
||||
40
superset-frontend/package-lock.json
generated
40
superset-frontend/package-lock.json
generated
@@ -95,7 +95,7 @@
|
||||
"echarts": "^5.6.0",
|
||||
"fast-glob": "^3.3.2",
|
||||
"fs-extra": "^11.3.5",
|
||||
"fuse.js": "^7.4.1",
|
||||
"fuse.js": "^7.4.2",
|
||||
"geolib": "^3.3.14",
|
||||
"geostyler": "^18.6.0",
|
||||
"geostyler-data": "^1.1.0",
|
||||
@@ -178,7 +178,7 @@
|
||||
"@babel/types": "^7.29.7",
|
||||
"@emotion/babel-plugin": "^11.13.5",
|
||||
"@emotion/jest": "^11.14.2",
|
||||
"@formatjs/intl-durationformat": "^0.10.13",
|
||||
"@formatjs/intl-durationformat": "^0.10.14",
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
"@playwright/test": "^1.60.0",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.6.2",
|
||||
@@ -3955,38 +3955,38 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/bigdecimal": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/bigdecimal/-/bigdecimal-0.2.5.tgz",
|
||||
"integrity": "sha512-2XTKNrZRaCUyXK2976wfutqxMBuPO/S/zbJnQdysLI2Zy5mWPVNVEkE6tsTcSVWSE7DgO88t8DtBy+uf3I8bxg==",
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/bigdecimal/-/bigdecimal-0.2.6.tgz",
|
||||
"integrity": "sha512-aPzKsGQOkQRHUEbyO/ZtYfr4EqaBQnSs6U4tzTla1xBnIdEHgY2GqEqso28UMwWRkzKqqTj5+/6BmuOsRkfn2A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@formatjs/fast-memoize": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-3.1.5.tgz",
|
||||
"integrity": "sha512-KLi3fan6WnCHmigd9pmEEN8Hid0v4wiFBW576M/d07KMWYecf1CvyMI3n34vCmHT4AoVqG2n702kiHbXjzZX2A==",
|
||||
"version": "3.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-3.1.6.tgz",
|
||||
"integrity": "sha512-H5aexk1Le7T9TPmscacZ+1pR6CTa2n1wq+HDVGXhH8TzUlQQpeXzZs91dRtmFHrbeNbjPFPfQujUqm7MHgVoXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@formatjs/intl-durationformat": {
|
||||
"version": "0.10.13",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/intl-durationformat/-/intl-durationformat-0.10.13.tgz",
|
||||
"integrity": "sha512-A1dBcOh1YrcRf/AbmZHFVXgIYkpAaFgyGaYavO/KutbqEXY3HI63o2E1ctmxmllfg3qn3TZGtZux42EFwHNTbg==",
|
||||
"version": "0.10.14",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/intl-durationformat/-/intl-durationformat-0.10.14.tgz",
|
||||
"integrity": "sha512-qVrbKGJZwoGFLmQyMBn4Pk44WCpBKINwLf+isrEd4RpvKs5nChRofHanWJqSu8TjuKJjk1qJjDIFkA/hJX/a9Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/bigdecimal": "0.2.5",
|
||||
"@formatjs/intl-localematcher": "0.8.9"
|
||||
"@formatjs/bigdecimal": "0.2.6",
|
||||
"@formatjs/intl-localematcher": "0.8.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/intl-localematcher": {
|
||||
"version": "0.8.9",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.8.9.tgz",
|
||||
"integrity": "sha512-GmB0F/gYh4Hdl4rLWjgDsgT+x4pB54fkJeRh8kAZ4XFzKeCK8dGs+SBJWXO42QZtOUni+IDWKNuCw6wiL4lTvw==",
|
||||
"version": "0.8.10",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.8.10.tgz",
|
||||
"integrity": "sha512-P/IC3qws3jH+1fEs+o0RIFgXKRaQlFehjS5W0FPAqdo6hgzawLl+eD0q0JjheQ3XtoOe5n8WSYfX06KQZI/QJA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/fast-memoize": "3.1.5"
|
||||
"@formatjs/fast-memoize": "3.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@gar/promise-retry": {
|
||||
@@ -20911,9 +20911,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/fuse.js": {
|
||||
"version": "7.4.1",
|
||||
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.4.1.tgz",
|
||||
"integrity": "sha512-AY7lKAXK71hi3WgUvDy6oZL67UEHOOtvCAwVdOXHyJd6ZzftBy7QqxuXt4HxmmAhYjmp/YCuOELZtIvAdlZ+fw==",
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.4.2.tgz",
|
||||
"integrity": "sha512-LVbzjD4WA6UP5B1UnP8wuaXJiLnqMdM/E4fiJXTJ5haJ5b/MBNsK29h2fm6swEoQaVQjvYFWKLE2RanyZIoRVQ==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
"echarts": "^5.6.0",
|
||||
"fast-glob": "^3.3.2",
|
||||
"fs-extra": "^11.3.5",
|
||||
"fuse.js": "^7.4.1",
|
||||
"fuse.js": "^7.4.2",
|
||||
"geolib": "^3.3.14",
|
||||
"geostyler": "^18.6.0",
|
||||
"geostyler-data": "^1.1.0",
|
||||
@@ -261,7 +261,7 @@
|
||||
"@babel/types": "^7.29.7",
|
||||
"@emotion/babel-plugin": "^11.13.5",
|
||||
"@emotion/jest": "^11.14.2",
|
||||
"@formatjs/intl-durationformat": "^0.10.13",
|
||||
"@formatjs/intl-durationformat": "^0.10.14",
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
"@playwright/test": "^1.60.0",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.6.2",
|
||||
|
||||
@@ -45,6 +45,7 @@ import TextControl from 'src/explore/components/controls/TextControl';
|
||||
import CheckboxControl from 'src/explore/components/controls/CheckboxControl';
|
||||
import PopoverSection from '@superset-ui/core/components/PopoverSection';
|
||||
import ControlHeader from 'src/explore/components/ControlHeader';
|
||||
import { ensureAppRoot } from 'src/utils/pathUtils';
|
||||
import {
|
||||
ANNOTATION_SOURCE_TYPES,
|
||||
ANNOTATION_TYPES,
|
||||
@@ -145,7 +146,7 @@ const NotFoundContent = () => (
|
||||
<span>
|
||||
{t('Add an annotation layer')}{' '}
|
||||
<a
|
||||
href="/annotationlayer/list"
|
||||
href={ensureAppRoot('/annotationlayer/list')}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
|
||||
@@ -29,8 +29,8 @@ import {
|
||||
DatasetObject,
|
||||
} from 'src/features/datasets/AddDataset/types';
|
||||
import { Table } from 'src/hooks/apiResources';
|
||||
import { Typography } from '@superset-ui/core/components/Typography';
|
||||
import { ensureAppRoot } from 'src/utils/pathUtils';
|
||||
import { Typography } from '@superset-ui/core/components/Typography';
|
||||
|
||||
interface LeftPanelProps {
|
||||
setDataset: Dispatch<SetStateAction<object>>;
|
||||
|
||||
@@ -218,10 +218,10 @@ export function Menu({
|
||||
const path = location.pathname;
|
||||
switch (true) {
|
||||
case path.startsWith(Paths.Dashboard):
|
||||
setActiveTabs(['Dashboards']);
|
||||
setActiveTabs([t('Dashboards')]);
|
||||
break;
|
||||
case path.startsWith(Paths.Chart) || path.startsWith(Paths.Explore):
|
||||
setActiveTabs(['Charts']);
|
||||
setActiveTabs([t('Charts')]);
|
||||
break;
|
||||
case path.startsWith(Paths.Datasets):
|
||||
setActiveTabs([datasetsLabel()]);
|
||||
@@ -263,9 +263,10 @@ export function Menu({
|
||||
|
||||
const childItems: MenuItem[] = [];
|
||||
childs?.forEach((child: MenuObjectChildProps | string, index1: number) => {
|
||||
if (typeof child === 'string' && child === '-' && label !== 'Data') {
|
||||
if (typeof child === 'string' && child === '-' && label !== t('Data')) {
|
||||
childItems.push({ type: 'divider', key: `divider-${index1}` });
|
||||
} else if (typeof child !== 'string') {
|
||||
Object.assign(child, { label: t(child.label) });
|
||||
childItems.push({
|
||||
key: `${child.label}`,
|
||||
label: child.isFrontendRoute ? (
|
||||
@@ -366,6 +367,7 @@ export function Menu({
|
||||
items={menu.map(item => {
|
||||
const props = {
|
||||
...item,
|
||||
label: t(item.label),
|
||||
isFrontendRoute: isFrontendRoute(item.url),
|
||||
childs: item.childs?.map(c => {
|
||||
if (typeof c === 'string') {
|
||||
@@ -429,15 +431,16 @@ export default function MenuWrapper({ data, ...rest }: MenuProps) {
|
||||
// Apply any label override for this item (keyed by FAB internal name).
|
||||
...(item.name && labelOverrides[item.name]
|
||||
? { label: labelOverrides[item.name]() }
|
||||
: {}),
|
||||
: { label: t(item.label) }),
|
||||
};
|
||||
|
||||
// Filter childs
|
||||
if (item.childs) {
|
||||
item.childs.forEach((child: MenuObjectChildProps | string) => {
|
||||
if (typeof child === 'string') {
|
||||
children.push(child);
|
||||
children.push(t(child));
|
||||
} else if ((child as MenuObjectChildProps).label) {
|
||||
Object.assign(child, { label: t(child.label) });
|
||||
children.push(child);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -110,6 +110,34 @@ describe('getBootstrapData and helpers', () => {
|
||||
expect(staticAssetsPrefix()).toEqual(expectedStaticPrefix);
|
||||
});
|
||||
|
||||
test.each([
|
||||
['//evil.example.com', 'protocol-relative URL'],
|
||||
// eslint-disable-next-line no-script-url -- intentional unsafe value under test
|
||||
['javascript:alert(1)', 'javascript scheme'],
|
||||
['https://evil.example.com', 'absolute URL'],
|
||||
['/foo"><img src=x>', 'path with HTML meta-characters'],
|
||||
])(
|
||||
'should fall back to the default root when application_root is %s (%s)',
|
||||
async unsafeRoot => {
|
||||
const customData = {
|
||||
common: {
|
||||
application_root: unsafeRoot,
|
||||
static_assets_prefix: '/custom-static/',
|
||||
},
|
||||
};
|
||||
document.body.innerHTML = `<div id="app" data-bootstrap='${JSON.stringify(customData)}'></div>`;
|
||||
|
||||
jest.resetModules();
|
||||
const { default: getBootstrapData, applicationRoot } =
|
||||
await import('./getBootstrapData');
|
||||
getBootstrapData();
|
||||
|
||||
const expectedAppRoot =
|
||||
DEFAULT_BOOTSTRAP_DATA.common.application_root.replace(/\/$/, '');
|
||||
expect(applicationRoot()).toEqual(expectedAppRoot);
|
||||
},
|
||||
);
|
||||
|
||||
test('should defaults without trailing slashes when #app element does not include application_root or static_assets_prefix', async () => {
|
||||
// Set up the fake #app element
|
||||
const customData = {
|
||||
|
||||
@@ -38,7 +38,34 @@ const normalizePathWithFallback = (
|
||||
fallback: string,
|
||||
): string => (path ?? fallback).replace(/\/$/, '');
|
||||
|
||||
const APPLICATION_ROOT_NO_TRAILING_SLASH = normalizePathWithFallback(
|
||||
/**
|
||||
* Matches a plain absolute path prefix (e.g. "" for root deployments or
|
||||
* "/analytics" for a subdirectory). The character after the leading slash must
|
||||
* not be another slash, so protocol-relative URLs ("//host") and scheme-bearing
|
||||
* values ("javascript:...") do not qualify.
|
||||
*/
|
||||
const SAFE_APPLICATION_ROOT_RE = /^(\/[\w\-.][\w\-./]*)?$/;
|
||||
|
||||
/**
|
||||
* The application root (SUPERSET_APP_ROOT) is reflected into links and
|
||||
* navigation, so constrain it to a plain absolute path before use. Anything
|
||||
* that isn't a simple "/path" prefix falls back to the default root so a
|
||||
* malformed value can't be reinterpreted as HTML or redirect off-origin. This
|
||||
* also keeps the bootstrap-derived value from being treated as a tainted href
|
||||
* source by static analysis.
|
||||
*/
|
||||
const sanitizeApplicationRoot = (
|
||||
path: string | undefined,
|
||||
fallback: string,
|
||||
): string => {
|
||||
const normalizedFallback = normalizePathWithFallback(fallback, fallback);
|
||||
const normalized = normalizePathWithFallback(path, fallback);
|
||||
return SAFE_APPLICATION_ROOT_RE.test(normalized)
|
||||
? normalized
|
||||
: normalizedFallback;
|
||||
};
|
||||
|
||||
const APPLICATION_ROOT_NO_TRAILING_SLASH = sanitizeApplicationRoot(
|
||||
getBootstrapData().common.application_root,
|
||||
DEFAULT_BOOTSTRAP_DATA.common.application_root,
|
||||
);
|
||||
|
||||
512
superset-websocket/package-lock.json
generated
512
superset-websocket/package-lock.json
generated
@@ -10,7 +10,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"cookie": "^1.1.1",
|
||||
"hot-shots": "^15.0.0",
|
||||
"hot-shots": "^16.0.0",
|
||||
"ioredis": "^5.11.1",
|
||||
"jsonwebtoken": "^9.0.3",
|
||||
"lodash": "^4.18.1",
|
||||
@@ -37,7 +37,7 @@
|
||||
"ts-node": "^10.9.2",
|
||||
"tscw-config": "^1.1.2",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.60.1"
|
||||
"typescript-eslint": "^8.61.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^24.16.0",
|
||||
@@ -1844,17 +1844,17 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.1.tgz",
|
||||
"integrity": "sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz",
|
||||
"integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.12.2",
|
||||
"@typescript-eslint/scope-manager": "8.60.1",
|
||||
"@typescript-eslint/type-utils": "8.60.1",
|
||||
"@typescript-eslint/utils": "8.60.1",
|
||||
"@typescript-eslint/visitor-keys": "8.60.1",
|
||||
"@typescript-eslint/scope-manager": "8.61.0",
|
||||
"@typescript-eslint/type-utils": "8.61.0",
|
||||
"@typescript-eslint/utils": "8.61.0",
|
||||
"@typescript-eslint/visitor-keys": "8.61.0",
|
||||
"ignore": "^7.0.5",
|
||||
"natural-compare": "^1.4.0",
|
||||
"ts-api-utils": "^2.5.0"
|
||||
@@ -1867,7 +1867,7 @@
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@typescript-eslint/parser": "^8.60.1",
|
||||
"@typescript-eslint/parser": "^8.61.0",
|
||||
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
|
||||
"typescript": ">=4.8.4 <6.1.0"
|
||||
}
|
||||
@@ -1907,7 +1907,7 @@
|
||||
"typescript": ">=4.8.4 <6.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/project-service": {
|
||||
"node_modules/@typescript-eslint/project-service": {
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.0.tgz",
|
||||
"integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==",
|
||||
@@ -1929,7 +1929,7 @@
|
||||
"typescript": ">=4.8.4 <6.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz",
|
||||
"integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==",
|
||||
@@ -1947,7 +1947,7 @@
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/tsconfig-utils": {
|
||||
"node_modules/@typescript-eslint/tsconfig-utils": {
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz",
|
||||
"integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==",
|
||||
@@ -1964,185 +1964,16 @@
|
||||
"typescript": ">=4.8.4 <6.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz",
|
||||
"integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz",
|
||||
"integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/project-service": "8.61.0",
|
||||
"@typescript-eslint/tsconfig-utils": "8.61.0",
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"@typescript-eslint/visitor-keys": "8.61.0",
|
||||
"debug": "^4.4.3",
|
||||
"minimatch": "^10.2.2",
|
||||
"semver": "^7.7.3",
|
||||
"tinyglobby": "^0.2.15",
|
||||
"ts-api-utils": "^2.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=4.8.4 <6.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz",
|
||||
"integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"eslint-visitor-keys": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/balanced-match": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/brace-expansion": {
|
||||
"version": "5.0.6",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
|
||||
"integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
|
||||
"integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/minimatch": {
|
||||
"version": "10.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
|
||||
"integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^5.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/project-service": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.60.1.tgz",
|
||||
"integrity": "sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/tsconfig-utils": "^8.60.1",
|
||||
"@typescript-eslint/types": "^8.60.1",
|
||||
"debug": "^4.4.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=4.8.4 <6.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.60.1.tgz",
|
||||
"integrity": "sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/visitor-keys": "8.60.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/tsconfig-utils": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.1.tgz",
|
||||
"integrity": "sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=4.8.4 <6.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.60.1.tgz",
|
||||
"integrity": "sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz",
|
||||
"integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/typescript-estree": "8.60.1",
|
||||
"@typescript-eslint/utils": "8.60.1",
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"@typescript-eslint/typescript-estree": "8.61.0",
|
||||
"@typescript-eslint/utils": "8.61.0",
|
||||
"debug": "^4.4.3",
|
||||
"ts-api-utils": "^2.5.0"
|
||||
},
|
||||
@@ -2159,9 +1990,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.60.1.tgz",
|
||||
"integrity": "sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz",
|
||||
"integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -2173,16 +2004,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.1.tgz",
|
||||
"integrity": "sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz",
|
||||
"integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/project-service": "8.60.1",
|
||||
"@typescript-eslint/tsconfig-utils": "8.60.1",
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/visitor-keys": "8.60.1",
|
||||
"@typescript-eslint/project-service": "8.61.0",
|
||||
"@typescript-eslint/tsconfig-utils": "8.61.0",
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"@typescript-eslint/visitor-keys": "8.61.0",
|
||||
"debug": "^4.4.3",
|
||||
"minimatch": "^10.2.2",
|
||||
"semver": "^7.7.3",
|
||||
@@ -2240,16 +2071,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.60.1.tgz",
|
||||
"integrity": "sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.0.tgz",
|
||||
"integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.9.1",
|
||||
"@typescript-eslint/scope-manager": "8.60.1",
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/typescript-estree": "8.60.1"
|
||||
"@typescript-eslint/scope-manager": "8.61.0",
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"@typescript-eslint/typescript-estree": "8.61.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -2264,13 +2095,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.1.tgz",
|
||||
"integrity": "sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz",
|
||||
"integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"eslint-visitor-keys": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -3634,9 +3465,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/hot-shots": {
|
||||
"version": "15.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-15.0.0.tgz",
|
||||
"integrity": "sha512-89EmKbvjVbDdFmUcvMl1x9XaKdEzg1VDLElbKaQCPC88wrus6O5XlCyZ+KbwZk9Dy4BNcsyfEHMfSkUtRZHBQg==",
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-16.0.0.tgz",
|
||||
"integrity": "sha512-1WHuq7vv0Hj6wiSmR89XpxxiNnw9s1W50yGJExC3/PSqVv+Kr7GSk3rz0jsTWjhIkF1c5Nz9mpLdzJ+CqKKwMg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
@@ -6357,41 +6188,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript-eslint": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.60.1.tgz",
|
||||
"integrity": "sha512-6m5hkkRAp8lKvhVpcprAIn5KkehQEh+47oHH2VGnExEh7dhNxXlg6GPAOIu6TxbVQxhebrJDvjl3020ooiWCMA==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.61.0.tgz",
|
||||
"integrity": "sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "8.60.1",
|
||||
"@typescript-eslint/parser": "8.60.1",
|
||||
"@typescript-eslint/typescript-estree": "8.60.1",
|
||||
"@typescript-eslint/utils": "8.60.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
|
||||
"typescript": ">=4.8.4 <6.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.60.1.tgz",
|
||||
"integrity": "sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.60.1",
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/typescript-estree": "8.60.1",
|
||||
"@typescript-eslint/visitor-keys": "8.60.1",
|
||||
"debug": "^4.4.3"
|
||||
"@typescript-eslint/eslint-plugin": "8.61.0",
|
||||
"@typescript-eslint/parser": "8.61.0",
|
||||
"@typescript-eslint/typescript-estree": "8.61.0",
|
||||
"@typescript-eslint/utils": "8.61.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -8121,16 +7927,16 @@
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.1.tgz",
|
||||
"integrity": "sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz",
|
||||
"integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint-community/regexpp": "^4.12.2",
|
||||
"@typescript-eslint/scope-manager": "8.60.1",
|
||||
"@typescript-eslint/type-utils": "8.60.1",
|
||||
"@typescript-eslint/utils": "8.60.1",
|
||||
"@typescript-eslint/visitor-keys": "8.60.1",
|
||||
"@typescript-eslint/scope-manager": "8.61.0",
|
||||
"@typescript-eslint/type-utils": "8.61.0",
|
||||
"@typescript-eslint/utils": "8.61.0",
|
||||
"@typescript-eslint/visitor-keys": "8.61.0",
|
||||
"ignore": "^7.0.5",
|
||||
"natural-compare": "^1.4.0",
|
||||
"ts-api-utils": "^2.5.0"
|
||||
@@ -8155,158 +7961,65 @@
|
||||
"@typescript-eslint/typescript-estree": "8.61.0",
|
||||
"@typescript-eslint/visitor-keys": "8.61.0",
|
||||
"debug": "^4.4.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@typescript-eslint/project-service": {
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.0.tgz",
|
||||
"integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/tsconfig-utils": "^8.61.0",
|
||||
"@typescript-eslint/types": "^8.61.0",
|
||||
"debug": "^4.4.3"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz",
|
||||
"integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"@typescript-eslint/visitor-keys": "8.61.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/tsconfig-utils": {
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz",
|
||||
"integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@typescript-eslint/types": {
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz",
|
||||
"integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz",
|
||||
"integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/project-service": "8.61.0",
|
||||
"@typescript-eslint/tsconfig-utils": "8.61.0",
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"@typescript-eslint/visitor-keys": "8.61.0",
|
||||
"debug": "^4.4.3",
|
||||
"minimatch": "^10.2.2",
|
||||
"semver": "^7.7.3",
|
||||
"tinyglobby": "^0.2.15",
|
||||
"ts-api-utils": "^2.5.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/visitor-keys": {
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz",
|
||||
"integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"eslint-visitor-keys": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "5.0.6",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
|
||||
"integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
|
||||
"integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
|
||||
"dev": true
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "10.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
|
||||
"integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^5.0.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/project-service": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.60.1.tgz",
|
||||
"integrity": "sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.0.tgz",
|
||||
"integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/tsconfig-utils": "^8.60.1",
|
||||
"@typescript-eslint/types": "^8.60.1",
|
||||
"@typescript-eslint/tsconfig-utils": "^8.61.0",
|
||||
"@typescript-eslint/types": "^8.61.0",
|
||||
"debug": "^4.4.3"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.60.1.tgz",
|
||||
"integrity": "sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz",
|
||||
"integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/visitor-keys": "8.60.1"
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"@typescript-eslint/visitor-keys": "8.61.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/tsconfig-utils": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.1.tgz",
|
||||
"integrity": "sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz",
|
||||
"integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@typescript-eslint/type-utils": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.60.1.tgz",
|
||||
"integrity": "sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz",
|
||||
"integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/typescript-estree": "8.60.1",
|
||||
"@typescript-eslint/utils": "8.60.1",
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"@typescript-eslint/typescript-estree": "8.61.0",
|
||||
"@typescript-eslint/utils": "8.61.0",
|
||||
"debug": "^4.4.3",
|
||||
"ts-api-utils": "^2.5.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/types": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.60.1.tgz",
|
||||
"integrity": "sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz",
|
||||
"integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.1.tgz",
|
||||
"integrity": "sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz",
|
||||
"integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/project-service": "8.60.1",
|
||||
"@typescript-eslint/tsconfig-utils": "8.60.1",
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/visitor-keys": "8.60.1",
|
||||
"@typescript-eslint/project-service": "8.61.0",
|
||||
"@typescript-eslint/tsconfig-utils": "8.61.0",
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"@typescript-eslint/visitor-keys": "8.61.0",
|
||||
"debug": "^4.4.3",
|
||||
"minimatch": "^10.2.2",
|
||||
"semver": "^7.7.3",
|
||||
@@ -8341,24 +8054,24 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/utils": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.60.1.tgz",
|
||||
"integrity": "sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.0.tgz",
|
||||
"integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint-community/eslint-utils": "^4.9.1",
|
||||
"@typescript-eslint/scope-manager": "8.60.1",
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/typescript-estree": "8.60.1"
|
||||
"@typescript-eslint/scope-manager": "8.61.0",
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"@typescript-eslint/typescript-estree": "8.61.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/visitor-keys": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.1.tgz",
|
||||
"integrity": "sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz",
|
||||
"integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/types": "8.61.0",
|
||||
"eslint-visitor-keys": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -9307,9 +9020,9 @@
|
||||
}
|
||||
},
|
||||
"hot-shots": {
|
||||
"version": "15.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-15.0.0.tgz",
|
||||
"integrity": "sha512-89EmKbvjVbDdFmUcvMl1x9XaKdEzg1VDLElbKaQCPC88wrus6O5XlCyZ+KbwZk9Dy4BNcsyfEHMfSkUtRZHBQg==",
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-16.0.0.tgz",
|
||||
"integrity": "sha512-1WHuq7vv0Hj6wiSmR89XpxxiNnw9s1W50yGJExC3/PSqVv+Kr7GSk3rz0jsTWjhIkF1c5Nz9mpLdzJ+CqKKwMg==",
|
||||
"requires": {
|
||||
"unix-dgram": "2.x"
|
||||
}
|
||||
@@ -11308,30 +11021,15 @@
|
||||
"dev": true
|
||||
},
|
||||
"typescript-eslint": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.60.1.tgz",
|
||||
"integrity": "sha512-6m5hkkRAp8lKvhVpcprAIn5KkehQEh+47oHH2VGnExEh7dhNxXlg6GPAOIu6TxbVQxhebrJDvjl3020ooiWCMA==",
|
||||
"version": "8.61.0",
|
||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.61.0.tgz",
|
||||
"integrity": "sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/eslint-plugin": "8.60.1",
|
||||
"@typescript-eslint/parser": "8.60.1",
|
||||
"@typescript-eslint/typescript-estree": "8.60.1",
|
||||
"@typescript-eslint/utils": "8.60.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.60.1.tgz",
|
||||
"integrity": "sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/scope-manager": "8.60.1",
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/typescript-estree": "8.60.1",
|
||||
"@typescript-eslint/visitor-keys": "8.60.1",
|
||||
"debug": "^4.4.3"
|
||||
}
|
||||
}
|
||||
"@typescript-eslint/eslint-plugin": "8.61.0",
|
||||
"@typescript-eslint/parser": "8.61.0",
|
||||
"@typescript-eslint/typescript-estree": "8.61.0",
|
||||
"@typescript-eslint/utils": "8.61.0"
|
||||
}
|
||||
},
|
||||
"uglify-js": {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"cookie": "^1.1.1",
|
||||
"hot-shots": "^15.0.0",
|
||||
"hot-shots": "^16.0.0",
|
||||
"ioredis": "^5.11.1",
|
||||
"jsonwebtoken": "^9.0.3",
|
||||
"lodash": "^4.18.1",
|
||||
@@ -45,7 +45,7 @@
|
||||
"ts-node": "^10.9.2",
|
||||
"tscw-config": "^1.1.2",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.60.1"
|
||||
"typescript-eslint": "^8.61.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^24.16.0",
|
||||
|
||||
@@ -39,14 +39,14 @@ logger = logging.getLogger(__name__)
|
||||
@click.command()
|
||||
@with_appcontext
|
||||
@transaction()
|
||||
@click.option("--database_name", "-d", help="Database name to change")
|
||||
@click.option("--uri", "-u", help="Database URI to change")
|
||||
@click.option("--database_name", "-d", required=True, help="Database name to change")
|
||||
@click.option("--uri", "-u", required=True, help="Database URI to change")
|
||||
@click.option(
|
||||
"--skip_create",
|
||||
"-s",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
help="Create the DB if it doesn't exist",
|
||||
help="Don't create the DB if it doesn't exist",
|
||||
)
|
||||
def set_database_uri(database_name: str, uri: str, skip_create: bool) -> None:
|
||||
"""Updates a database connection URI"""
|
||||
|
||||
@@ -36,10 +36,10 @@ class OracleEngineSpec(BaseEngineSpec):
|
||||
DatabaseCategory.PROPRIETARY,
|
||||
],
|
||||
"pypi_packages": ["oracledb"],
|
||||
"connection_string": "oracle://{username}:{password}@{hostname}:{port}",
|
||||
"connection_string": "oracle+oracledb://{username}:{password}@{hostname}:{port}",
|
||||
"default_port": 1521,
|
||||
"notes": "Previously used cx_Oracle, now uses oracledb.",
|
||||
"docs_url": "https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html",
|
||||
"docs_url": "https://python-oracledb.readthedocs.io/en/latest/user_guide/installation.html",
|
||||
}
|
||||
force_column_alias_quotes = True
|
||||
max_column_name_length = 128
|
||||
|
||||
@@ -3138,7 +3138,10 @@ class ExploreMixin: # pylint: disable=too-many-public-methods
|
||||
for orig_col, ascending in orderby: # noqa: B007
|
||||
col: Union[AdhocMetric, ColumnElement] = orig_col
|
||||
if isinstance(col, dict):
|
||||
col = cast(AdhocMetric, col)
|
||||
# process a copy, as the dict is shared with `QueryObject.orderby`
|
||||
# and `QueryContext.cache_values`; writing the processed expression
|
||||
# back would change the cache key of a rehydrated query context
|
||||
col = cast(AdhocMetric, dict(col))
|
||||
if col.get("sqlExpression"):
|
||||
col["sqlExpression"] = self._process_orderby_expression(
|
||||
expression=col["sqlExpression"],
|
||||
|
||||
@@ -592,6 +592,84 @@ class SQLStatement(BaseSQLStatement[exp.Expression]):
|
||||
This class is used for all engines with dialects that can be parsed using sqlglot.
|
||||
"""
|
||||
|
||||
# Function names that mutate server-side state but appear in the AST as
|
||||
# plain function calls inside a non-mutating wrapper. Used by
|
||||
# ``is_mutating()`` to classify e.g. PostgreSQL large-object writers.
|
||||
# Names are uppercased for comparison.
|
||||
_MUTATING_FUNCTION_NAMES: frozenset[str] = frozenset(
|
||||
{
|
||||
"LO_FROM_BYTEA",
|
||||
"LO_EXPORT",
|
||||
"LO_IMPORT",
|
||||
"LO_PUT",
|
||||
"LO_CREATE",
|
||||
"LOWRITE",
|
||||
"LO_UNLINK",
|
||||
# PostgreSQL sequence mutators. `SELECT setval('seq', N)` and
|
||||
# `SELECT nextval('seq')` look like reads but change sequence state
|
||||
# for every subsequent caller. (`currval` only reads the session's
|
||||
# last value, so it is intentionally not listed.)
|
||||
"SETVAL",
|
||||
"NEXTVAL",
|
||||
}
|
||||
)
|
||||
|
||||
# PostgreSQL constructs that sqlglot represents as an opaque ``exp.Command``
|
||||
# (no structured AST). Each can mutate server state or wrap a DML body that
|
||||
# would otherwise be detected by node-type matching. Used by
|
||||
# ``is_mutating()``.
|
||||
_POSTGRES_MUTATING_COMMAND_NAMES: frozenset[str] = frozenset(
|
||||
{
|
||||
"DO", # PL/pgSQL anonymous block
|
||||
"PREPARE", # PREPARE u AS UPDATE ... ; EXECUTE u
|
||||
"EXECUTE", # body is the prepared DML
|
||||
"CALL", # procedure body may mutate
|
||||
"COPY", # server-side file ingest into a table
|
||||
"GRANT",
|
||||
"REVOKE",
|
||||
# Only the command-fallback forms (e.g. SET ROLE / SET SESSION
|
||||
# AUTHORIZATION, which change the effective user) reach here as an
|
||||
# exp.Command. Structured `SET search_path = ...` /
|
||||
# `SET statement_timeout = ...` parse as exp.Set and are NOT matched
|
||||
# by this command-name path.
|
||||
"SET",
|
||||
"RESET", # RESET ROLE / RESET ALL reverts SET; same class as SET
|
||||
"REFRESH", # REFRESH MATERIALIZED VIEW
|
||||
"REINDEX",
|
||||
"VACUUM",
|
||||
# DDL head-tokens that sqlglot falls back to exp.Command for
|
||||
# whenever the body uses syntax it does not model
|
||||
# (CREATE EXTENSION/FUNCTION...LANGUAGE C/PUBLICATION/etc.,
|
||||
# ALTER ROLE/SYSTEM/..., DROP EXTENSION/RULE/...). Well-formed
|
||||
# CREATE TABLE/ALTER TABLE/DROP TABLE are already caught by the
|
||||
# node-type tuple; these entries close the fallback path.
|
||||
"CREATE",
|
||||
"ALTER",
|
||||
"DROP",
|
||||
"LOAD", # LOAD '/path/lib.so' dlopens a shared library on the PG host
|
||||
# NOTE: `SHOW` is intentionally NOT included. It is a read (mutates
|
||||
# nothing), so classifying it as mutating would be wrong for every
|
||||
# is_mutating()/has_mutation() consumer (the commit decision, the
|
||||
# "only SELECT allowed" validators, limit handling), not just the
|
||||
# read-only gate. Gating information-disclosure reads such as
|
||||
# `SHOW server_version` belongs in a denylist (DISALLOWED_SQL_FUNCTIONS
|
||||
# already blocks version()/pg_read_file), not in the mutation check.
|
||||
}
|
||||
)
|
||||
|
||||
# Dialects where `SELECT ... INTO target` is CTAS (creates a table, and so
|
||||
# mutates schema). Elsewhere the same syntax assigns into a variable and is
|
||||
# a read: Oracle PL/SQL `SELECT ... INTO v` and MySQL `SELECT ... INTO @v`
|
||||
# parse into an identical `exp.Select` with an `into` arg, so the dialect is
|
||||
# the only signal that distinguishes the mutating form from the read form.
|
||||
_SELECT_INTO_CTAS_DIALECTS: frozenset[Dialects] = frozenset(
|
||||
{
|
||||
Dialects.POSTGRES,
|
||||
Dialects.REDSHIFT,
|
||||
Dialects.TSQL,
|
||||
}
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
statement: str | None = None,
|
||||
@@ -725,25 +803,67 @@ class SQLStatement(BaseSQLStatement[exp.Expression]):
|
||||
exp.Drop,
|
||||
exp.TruncateTable,
|
||||
exp.Alter,
|
||||
# sqlglot has structured nodes for these DML/DCL forms in
|
||||
# PostgreSQL and other dialects; without them an opaque exp.Command
|
||||
# check would still miss the structured-parse path.
|
||||
exp.Copy, # COPY <table> FROM/TO (server-side file ingest)
|
||||
exp.Grant,
|
||||
exp.Revoke,
|
||||
# COMMENT ON TABLE/COLUMN/etc. writes to system catalog pg_description.
|
||||
exp.Comment,
|
||||
)
|
||||
|
||||
for node_type in mutating_nodes:
|
||||
if self._parsed.find(node_type):
|
||||
return True
|
||||
if self._parsed.find(*mutating_nodes):
|
||||
return True
|
||||
|
||||
# `SELECT ... INTO new_table FROM ...` parses as `exp.Select` with an
|
||||
# `into` arg (Postgres-style CTAS variant). It creates a new table and
|
||||
# therefore mutates schema. Only treat it as mutating for dialects where
|
||||
# the syntax is CTAS; elsewhere it assigns into a variable (a read).
|
||||
if (
|
||||
self._dialect in self._SELECT_INTO_CTAS_DIALECTS
|
||||
and isinstance(self._parsed, exp.Select)
|
||||
and self._parsed.args.get("into")
|
||||
):
|
||||
return True
|
||||
|
||||
# Function calls that mutate server-side state without an enclosing
|
||||
# mutating AST node. Notable example: PostgreSQL large-object writers
|
||||
# (`lo_export` writes to the server filesystem, `lo_from_bytea`/
|
||||
# `lo_create`/`lo_put`/`lo_import`/`lowrite` mutate the pg_largeobject
|
||||
# catalog). These appear as plain function calls inside an `exp.Select`
|
||||
# and would otherwise pass the read-only gate. Every name in
|
||||
# _MUTATING_FUNCTION_NAMES is PostgreSQL-specific, so the walk is gated
|
||||
# on the dialect: other engines may expose read-only functions/UDFs with
|
||||
# the same names, and flagging those would wrongly block read-only
|
||||
# queries. Each parses as an `exp.Anonymous`, whose `.name` is the bare
|
||||
# function identifier. The walk is restricted to `exp.Anonymous` rather
|
||||
# than the broader `exp.Func`, because for built-in function nodes (e.g.
|
||||
# `exp.Upper`) `.name` returns the first argument's text, not the
|
||||
# function name, so `SELECT upper('lo_export')` would otherwise be
|
||||
# misclassified as mutating.
|
||||
if self._dialect == Dialects.POSTGRES and any(
|
||||
function.name.upper() in self._MUTATING_FUNCTION_NAMES
|
||||
for function in self._parsed.find_all(exp.Anonymous)
|
||||
):
|
||||
return True
|
||||
|
||||
# depending on the dialect (Oracle, MS SQL) the `ALTER` is parsed as a
|
||||
# command, not an expression - check at root level
|
||||
if isinstance(self._parsed, exp.Command) and self._parsed.name == "ALTER":
|
||||
return True # pragma: no cover
|
||||
|
||||
# PostgreSQL constructs that sqlglot represents as an opaque
|
||||
# `exp.Command` rather than a structured AST. Each of these can mutate
|
||||
# state or wrap a DML body that would otherwise be detected. The
|
||||
# `.name` attribute on `exp.Command` preserves the source-case of the
|
||||
# head keyword (so `create extension ...` would yield `'create'`),
|
||||
# which means the set lookup must be case-insensitive.
|
||||
if (
|
||||
self._dialect == Dialects.POSTGRES
|
||||
and isinstance(self._parsed, exp.Command)
|
||||
and self._parsed.name == "DO"
|
||||
and self._parsed.name.upper() in self._POSTGRES_MUTATING_COMMAND_NAMES
|
||||
):
|
||||
# anonymous blocks can be written in many different languages (the default
|
||||
# is PL/pgSQL), so parsing them it out of scope of this class; we just
|
||||
# assume the anonymous block is mutating
|
||||
return True
|
||||
|
||||
# Postgres runs DMLs prefixed by `EXPLAIN ANALYZE`, see
|
||||
@@ -864,6 +984,13 @@ class SQLStatement(BaseSQLStatement[exp.Expression]):
|
||||
else:
|
||||
present.add(function.name.upper())
|
||||
|
||||
# MySQL `@@<name>` syntax (also Oracle/SQL-Server `@@name`) parses as
|
||||
# `exp.SessionParameter`, which is *not* a subclass of `exp.Func`, so
|
||||
# the walk above misses it. Include those names so denylist entries
|
||||
# like `version` or `hostname` match `SELECT @@version`.
|
||||
for param in self._parsed.find_all(exp.SessionParameter):
|
||||
present.add(param.name.upper())
|
||||
|
||||
return any(function.upper() in present for function in functions)
|
||||
|
||||
def check_tables_present(self, tables: set[str]) -> bool:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
from contextlib import contextmanager
|
||||
from typing import cast, TYPE_CHECKING
|
||||
from unittest.mock import patch
|
||||
@@ -30,7 +31,7 @@ from sqlalchemy.orm.session import Session
|
||||
from sqlalchemy.pool import StaticPool
|
||||
from sqlalchemy.sql.elements import ColumnElement
|
||||
|
||||
from superset.superset_typing import AdhocColumn
|
||||
from superset.superset_typing import AdhocColumn, AdhocMetric, OrderBy
|
||||
from superset.utils.core import GenericDataType
|
||||
from tests.unit_tests.conftest import with_feature_flags
|
||||
|
||||
@@ -925,6 +926,118 @@ def test_process_orderby_expression_with_template_processor(
|
||||
assert result == "processed_column DESC"
|
||||
|
||||
|
||||
def _assert_get_sqla_query_does_not_mutate_orderby(
|
||||
database: Database,
|
||||
sql_expression: str,
|
||||
expected_sql_fragment: str,
|
||||
) -> None:
|
||||
"""
|
||||
Order a query by an ad-hoc SQL metric and assert the caller's orderby
|
||||
dicts are left untouched.
|
||||
|
||||
The processed (Jinja-rendered, sqlglot-normalized) expression must not be
|
||||
written back into the shared dict, which would change the cache key of a
|
||||
rehydrated query context (see issue #37114). ``expected_sql_fragment`` is
|
||||
matched against the whitespace-stripped SQL, as sqlglot may normalize the
|
||||
output slightly.
|
||||
"""
|
||||
from superset.connectors.sqla.models import SqlaTable, TableColumn
|
||||
|
||||
table = SqlaTable(
|
||||
database=database,
|
||||
schema=None,
|
||||
table_name="t",
|
||||
columns=[TableColumn(column_name="a", type="INTEGER")],
|
||||
)
|
||||
|
||||
adhoc_metric: AdhocMetric = {
|
||||
"expressionType": "SQL",
|
||||
"sqlExpression": sql_expression,
|
||||
"label": "my metric",
|
||||
"hasCustomLabel": True,
|
||||
}
|
||||
orderby: list[OrderBy] = [(copy.deepcopy(adhoc_metric), False)]
|
||||
original_orderby = copy.deepcopy(orderby)
|
||||
|
||||
query = table.get_sqla_query(
|
||||
metrics=[adhoc_metric],
|
||||
orderby=orderby,
|
||||
is_timeseries=False,
|
||||
row_limit=10,
|
||||
)
|
||||
|
||||
with database.get_sqla_engine() as engine:
|
||||
sql = str(
|
||||
query.sqla_query.compile(
|
||||
dialect=engine.dialect, compile_kwargs={"literal_binds": True}
|
||||
)
|
||||
)
|
||||
|
||||
assert expected_sql_fragment in sql.replace(" ", "")
|
||||
assert orderby == original_orderby
|
||||
assert cast(AdhocMetric, orderby[0][0])["sqlExpression"] == sql_expression
|
||||
|
||||
|
||||
def test_get_sqla_query_does_not_mutate_adhoc_orderby(database: Database) -> None:
|
||||
"""
|
||||
Test that `get_sqla_query` does not mutate ad-hoc ORDER BY entries.
|
||||
"""
|
||||
_assert_get_sqla_query_does_not_mutate_orderby(
|
||||
database,
|
||||
"SUM(CASE \r\n WHEN a > 0\r\n THEN 1\r\n END)",
|
||||
"ORDERBY",
|
||||
)
|
||||
|
||||
|
||||
@with_feature_flags(ENABLE_TEMPLATE_PROCESSING=True)
|
||||
def test_get_sqla_query_does_not_mutate_adhoc_orderby_with_jinja(
|
||||
database: Database,
|
||||
) -> None:
|
||||
"""
|
||||
Test that Jinja in an ad-hoc ORDER BY entry is not rendered back.
|
||||
"""
|
||||
_assert_get_sqla_query_does_not_mutate_orderby(
|
||||
database,
|
||||
"SUM(CASE WHEN a > {{ 1 + 1 }} THEN 1 END)",
|
||||
"a>2",
|
||||
)
|
||||
|
||||
|
||||
def test_cache_key_stable_across_query_build(database: Database) -> None:
|
||||
"""
|
||||
Test that `QueryObject.cache_key()` is unchanged by building the query.
|
||||
"""
|
||||
from superset.common.query_object import QueryObject
|
||||
from superset.connectors.sqla.models import SqlaTable, TableColumn
|
||||
|
||||
table = SqlaTable(
|
||||
database=database,
|
||||
schema=None,
|
||||
table_name="t",
|
||||
columns=[TableColumn(column_name="a", type="INTEGER")],
|
||||
)
|
||||
|
||||
adhoc_metric: AdhocMetric = {
|
||||
"expressionType": "SQL",
|
||||
"sqlExpression": "SUM(CASE \r\n WHEN a > 0\r\n THEN a\r\nEND)",
|
||||
"label": "my metric",
|
||||
"hasCustomLabel": True,
|
||||
}
|
||||
query_obj = QueryObject(
|
||||
datasource=table,
|
||||
columns=[],
|
||||
metrics=[adhoc_metric],
|
||||
orderby=[(copy.deepcopy(adhoc_metric), False)],
|
||||
is_timeseries=False,
|
||||
row_limit=10,
|
||||
)
|
||||
|
||||
cache_key_before = query_obj.cache_key()
|
||||
table.get_query_str_extended(query_obj.to_dict())
|
||||
|
||||
assert query_obj.cache_key() == cache_key_before
|
||||
|
||||
|
||||
def test_process_select_expression_basic(
|
||||
mocker: MockerFixture,
|
||||
database: Database,
|
||||
|
||||
@@ -1143,7 +1143,14 @@ def test_split_kql(kql: str, expected: list[str]) -> None:
|
||||
("postgresql", "DROP TABLE foo", True),
|
||||
("postgresql", "EXPLAIN ANALYZE SELECT * FROM foo", False),
|
||||
("postgresql", "EXPLAIN ANALYZE DELETE FROM foo", True),
|
||||
# SHOW reads server configuration; it mutates nothing, so it is NOT
|
||||
# classified as mutating (that would be wrong for the commit/limit/
|
||||
# "only SELECT" consumers of has_mutation()). Gating disclosure reads
|
||||
# belongs in DISALLOWED_SQL_FUNCTIONS, not the mutation check.
|
||||
("postgresql", "SHOW search_path", False),
|
||||
# SET search_path parses as exp.Set (a structured node), not
|
||||
# exp.Command, so the SET-in-mutating-commands rule does NOT
|
||||
# catch it. Pure GUC reads/writes stay non-mutating.
|
||||
("postgresql", "SET search_path TO public", False),
|
||||
(
|
||||
"postgres",
|
||||
@@ -1388,6 +1395,9 @@ def test_custom_dialect(app: None) -> None:
|
||||
("SELECT 1", False),
|
||||
("with source as ( select 1 as one ) select * from source", False),
|
||||
("ALTER TABLE foo ADD COLUMN bar INT", True),
|
||||
# COMMENT ON parses as a typed exp.Comment node across dialects; it
|
||||
# writes to the catalog (pg_description on Postgres) so it is gated.
|
||||
("COMMENT ON TABLE t IS 'note'", True),
|
||||
],
|
||||
)
|
||||
def test_is_mutating(sql: str, engine: str, expected: bool) -> None:
|
||||
@@ -1434,6 +1444,222 @@ def test_is_mutating_anonymous_block(sql: str, expected: bool) -> None:
|
||||
assert SQLStatement(sql, "postgresql").is_mutating() == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"sql, expected",
|
||||
[
|
||||
# PostgreSQL large-object writers: each mutates server state. The bare
|
||||
# SELECT wrapper is irrelevant because the function call itself is the
|
||||
# side effect.
|
||||
("SELECT lo_from_bytea(0, decode('deadbeef', 'hex'))", True),
|
||||
("SELECT lo_export(12345, '/tmp/payload.bin')", True),
|
||||
("SELECT lo_import('/etc/passwd')", True),
|
||||
("SELECT lo_put(12345, 0, decode('00', 'hex'))", True),
|
||||
("SELECT lo_create(0)", True),
|
||||
("SELECT lowrite(12345, decode('00', 'hex'))", True),
|
||||
# lo_unlink deletes a large object outright.
|
||||
("SELECT lo_unlink(12345)", True),
|
||||
# PostgreSQL sequence mutators. setval()/nextval() look like reads but
|
||||
# advance sequence state for every subsequent caller.
|
||||
("SELECT setval('public.my_seq', 1000)", True),
|
||||
("SELECT SETVAL('public.my_seq', 1)", True),
|
||||
("SELECT nextval('public.my_seq')", True),
|
||||
# currval() only reads the session's last value, so it is not mutating.
|
||||
("SELECT currval('public.my_seq')", False),
|
||||
# Read-side large-object functions are intentionally NOT classified
|
||||
# as mutating here. They are still blocked via the function denylist
|
||||
# (see DISALLOWED_SQL_FUNCTIONS) but they do not write state.
|
||||
("SELECT lo_get(12345)", False),
|
||||
("SELECT loread(12345, 1024)", False),
|
||||
# Case-insensitive matching: the AST stores the raw casing for
|
||||
# anonymous functions, the check uppercases both sides.
|
||||
("SELECT LO_EXPORT(12345, '/tmp/x')", True),
|
||||
# `SELECT INTO new_table FROM existing` creates a new relation; treat
|
||||
# as mutating even though sqlglot parses it as exp.Select.
|
||||
("SELECT * INTO new_table FROM existing_table", True),
|
||||
("SELECT col INTO TEMP new_table FROM existing_table", True),
|
||||
# A built-in function whose first string argument happens to match a
|
||||
# mutating name must NOT be flagged. sqlglot parses these into dedicated
|
||||
# nodes (e.g. exp.Upper) whose `.name` is the argument text, not the
|
||||
# function name, so the walk is restricted to exp.Anonymous to avoid a
|
||||
# false positive on this read-only query.
|
||||
("SELECT upper('lo_export')", False),
|
||||
("SELECT length('setval')", False),
|
||||
# Plain SELECT must remain non-mutating.
|
||||
("SELECT 1", False),
|
||||
("SELECT * FROM users WHERE id = 1", False),
|
||||
],
|
||||
)
|
||||
def test_is_mutating_postgres_function_and_select_into(
|
||||
sql: str, expected: bool
|
||||
) -> None:
|
||||
"""
|
||||
`is_mutating` must catch mutating function calls (PostgreSQL large-object
|
||||
writers) and `SELECT ... INTO new_table` even though the wrapping AST
|
||||
node is a plain `exp.Select`.
|
||||
"""
|
||||
assert SQLStatement(sql, "postgresql").is_mutating() == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"engine, sql",
|
||||
[
|
||||
# `SELECT ... INTO new_table` is CTAS only in Postgres/Redshift/T-SQL.
|
||||
# In Oracle PL/SQL and MySQL the same syntax assigns into a variable
|
||||
# and is a read, so it must NOT be classified as mutating.
|
||||
("oracle", "SELECT col INTO v FROM existing_table"),
|
||||
("mysql", "SELECT col INTO @v FROM existing_table"),
|
||||
],
|
||||
)
|
||||
def test_is_mutating_select_into_variable_is_read(engine: str, sql: str) -> None:
|
||||
"""
|
||||
`SELECT ... INTO target` is only CTAS (mutating) for dialects where the
|
||||
syntax creates a table. On Oracle/MySQL it assigns into a variable and is
|
||||
a read, so `is_mutating` must return False there.
|
||||
"""
|
||||
assert SQLStatement(sql, engine).is_mutating() is False
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"engine, sql",
|
||||
[
|
||||
# `SELECT ... INTO new_table` is CTAS on Redshift and T-SQL just as it
|
||||
# is on Postgres, so each dialect in _SELECT_INTO_CTAS_DIALECTS must
|
||||
# classify the statement as mutating.
|
||||
("redshift", "SELECT * INTO new_table FROM existing_table"),
|
||||
("redshift", "SELECT col INTO new_table FROM existing_table"),
|
||||
("mssql", "SELECT * INTO new_table FROM existing_table"),
|
||||
("mssql", "SELECT col INTO new_table FROM existing_table"),
|
||||
],
|
||||
)
|
||||
def test_is_mutating_select_into_ctas_dialects(engine: str, sql: str) -> None:
|
||||
"""
|
||||
`SELECT ... INTO new_table` creates a table on the CTAS dialects beyond
|
||||
Postgres (Redshift, T-SQL), so `is_mutating` must return True there.
|
||||
"""
|
||||
assert SQLStatement(sql, engine).is_mutating() is True
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"engine, sql",
|
||||
[
|
||||
# The mutating-function names are PostgreSQL built-ins. On other engines
|
||||
# a same-named read-only function or UDF must NOT be flagged as
|
||||
# mutating, otherwise read-only queries get wrongly blocked.
|
||||
("mysql", "SELECT setval(my_col)"),
|
||||
("mysql", "SELECT lo_export(id, path) FROM t"),
|
||||
("base", "SELECT setval(my_col)"),
|
||||
("trino", "SELECT lowrite(x)"),
|
||||
],
|
||||
)
|
||||
def test_is_mutating_function_names_scoped_to_postgres(engine: str, sql: str) -> None:
|
||||
"""
|
||||
`_MUTATING_FUNCTION_NAMES` is PostgreSQL-specific, so the function-name walk
|
||||
only runs for the Postgres dialect; same-named functions on other engines
|
||||
must stay non-mutating.
|
||||
"""
|
||||
assert SQLStatement(sql, engine).is_mutating() is False
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"sql, expected",
|
||||
[
|
||||
# PostgreSQL constructs that sqlglot parses as opaque exp.Command.
|
||||
# Each can wrap a DML body or change effective server state.
|
||||
("PREPARE u AS UPDATE t SET x = 1", True),
|
||||
("PREPARE i AS INSERT INTO t VALUES (1)", True),
|
||||
("EXECUTE my_plan", True),
|
||||
("CALL my_writing_procedure()", True),
|
||||
("COPY t FROM '/tmp/data.csv'", True),
|
||||
("GRANT SELECT ON t TO public", True),
|
||||
("REVOKE SELECT ON t FROM public", True),
|
||||
("SET ROLE other_role", True),
|
||||
("REFRESH MATERIALIZED VIEW mv", True),
|
||||
("REINDEX TABLE t", True),
|
||||
("VACUUM t", True),
|
||||
# SHOW commands are reads (they mutate nothing), so they are NOT
|
||||
# classified as mutating. Gating information-disclosure reads such as
|
||||
# SHOW server_version belongs in DISALLOWED_SQL_FUNCTIONS (which already
|
||||
# blocks pg_read_file, version(), etc.), not in the mutation check.
|
||||
("SHOW search_path", False),
|
||||
("SHOW all", False),
|
||||
("SHOW server_version", False),
|
||||
# RESET reverts a prior SET (e.g. RESET ROLE backs out SET ROLE).
|
||||
("RESET ROLE", True),
|
||||
# DDL head-tokens that sqlglot falls back to exp.Command for when the
|
||||
# body uses syntax it does not model. One representative per
|
||||
# head-token branch (CREATE/ALTER/DROP); they all hit the same
|
||||
# set-lookup so additional CREATE PUBLICATION/SUBSCRIPTION/etc.
|
||||
# cases would not add coverage.
|
||||
(
|
||||
"CREATE FUNCTION x() RETURNS int AS '/tmp/x.so', 'i' LANGUAGE C",
|
||||
True,
|
||||
),
|
||||
("CREATE EXTENSION pg_trgm", True), # non-FUNCTION DDL via Command
|
||||
("ALTER SYSTEM SET wal_level = 'logical'", True),
|
||||
("DROP EXTENSION pg_trgm", True),
|
||||
# LOAD dlopens a shared library on the PG host. Same RCE primitive
|
||||
# as `CREATE FUNCTION ... LANGUAGE C` if the library path is
|
||||
# attacker-controlled (e.g. via a prior COPY-to-program foothold).
|
||||
("LOAD '/tmp/x.so'", True),
|
||||
# Case-insensitive: sqlglot preserves source case on Command.name,
|
||||
# so the set lookup must normalise. Regression for the original
|
||||
# bug where a lowercase head-token bypassed the gate.
|
||||
("create extension pg_trgm", True),
|
||||
("load '/tmp/x.so'", True),
|
||||
# Pre-existing positive controls
|
||||
("DO $$ BEGIN UPDATE t SET x = 1; END $$", True),
|
||||
("EXPLAIN ANALYZE UPDATE t SET x = 1", True),
|
||||
],
|
||||
)
|
||||
def test_is_mutating_postgres_command_constructs(sql: str, expected: bool) -> None:
|
||||
"""
|
||||
Several PostgreSQL constructs are represented by sqlglot as opaque
|
||||
`exp.Command` nodes (no structured AST). `is_mutating` recognises them
|
||||
by command name so they cannot slip past the read-only gate.
|
||||
"""
|
||||
assert SQLStatement(sql, "postgresql").is_mutating() == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"sql, engine, functions, expected",
|
||||
[
|
||||
# MySQL `@@<name>` syntax parses as exp.SessionParameter, which is
|
||||
# not a subclass of exp.Func. The walker must include it so the
|
||||
# denylist entry for `version` still catches `SELECT @@version`.
|
||||
("SELECT @@version", "mysql", {"version"}, True),
|
||||
("SELECT @@global.version", "mysql", {"version"}, True),
|
||||
("SELECT @@hostname", "mysql", {"hostname"}, True),
|
||||
("SELECT @@datadir", "mysql", {"datadir"}, True),
|
||||
# Negative control: a session parameter not in the denylist must
|
||||
# not match.
|
||||
("SELECT @@autocommit", "mysql", {"version", "hostname"}, False),
|
||||
# A plain SELECT does not introduce session-parameter names.
|
||||
("SELECT 1", "mysql", {"version"}, False),
|
||||
# The pre-existing exp.Func walk still works for normal calls.
|
||||
("SELECT version()", "mysql", {"version"}, True),
|
||||
# PostgreSQL large-object functions are exp.Anonymous calls. The
|
||||
# walk includes them; the denylist entry catches them.
|
||||
("SELECT lo_export(12345, '/tmp/x')", "postgresql", {"lo_export"}, True),
|
||||
(
|
||||
"SELECT lo_from_bytea(0, decode('00','hex'))",
|
||||
"postgresql",
|
||||
{"lo_from_bytea"},
|
||||
True,
|
||||
),
|
||||
("SELECT loread(12345, 1024)", "postgresql", {"loread"}, True),
|
||||
],
|
||||
)
|
||||
def test_check_functions_present_session_parameter(
|
||||
sql: str, engine: str, functions: set[str], expected: bool
|
||||
) -> None:
|
||||
"""
|
||||
`check_functions_present` must visit `exp.SessionParameter` so that
|
||||
denylist entries for names like `version` or `hostname` also match
|
||||
`SELECT @@version` / `SELECT @@hostname` in MySQL.
|
||||
"""
|
||||
assert SQLScript(sql, engine).check_functions_present(functions) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"sql, expected",
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user