diff --git a/.github/.pre-commit-config.yaml b/.github/.pre-commit-config.yaml new file mode 100644 index 0000000000000..909f0c1cdca3c --- /dev/null +++ b/.github/.pre-commit-config.yaml @@ -0,0 +1,28 @@ +# 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. +--- +default_stages: [manual] +default_language_version: + python: python311 +minimum_pre_commit_version: '3.2.0' +repos: + - repo: https://github.com/eclipse-csi/octopin + rev: 21360742e352e87450f99e180fdfc2cf774a72a3 + hooks: + - id: pin-versions + name: Pin versions of dependencies in CI workflows (manual) + stages: ['manual'] diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bb5815dac0b84..69f10c58301a7 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -37,14 +37,14 @@ # Translation Owners (i18n) # Note: Non committer engaged translators are listed in comments prevent making file syntax invalid -# See: https://github.com/apache/airflow/blob/main/airflow-core/src/airflow/ui/src/i18n/README.md#43-engaged-translator -airflow-core/src/airflow/ui/src/i18n/locales/ar/ @shahar1 @hussein-awala # + @ahmadtfarhan -airflow-core/src/airflow/ui/src/i18n/locales/de/ @jscheffl # + @TJaniF @m1racoli -airflow-core/src/airflow/ui/src/i18n/locales/he/ @eladkal @shahar1 @romsharon98 # +@Dev-iL -airflow-core/src/airflow/ui/src/i18n/locales/nl/ @BasPH # + @DjVinnii -airflow-core/src/airflow/ui/src/i18n/locales/pl/ @potiuk @mobuchowski # + @kacpermuda -airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/ @Lee-W @jason810496 # + @RoyLee1224 @guan404ming -airflow-core/src/airflow/ui/src/i18n/locales/fr/ @pierrejeambrun @vincbeck +# See: https://github.com/apache/airflow/blob/main/airflow-core/src/airflow/ui/public/i18n/README.md#43-engaged-translator +airflow-core/src/airflow/ui/public/i18n/locales/ar/ @shahar1 @hussein-awala # + @ahmadtfarhan +airflow-core/src/airflow/ui/public/i18n/locales/de/ @jscheffl # + @TJaniF @m1racoli +airflow-core/src/airflow/ui/public/i18n/locales/he/ @eladkal @shahar1 @romsharon98 # +@Dev-iL +airflow-core/src/airflow/ui/public/i18n/locales/nl/ @BasPH # + @DjVinnii +airflow-core/src/airflow/ui/public/i18n/locales/pl/ @potiuk @mobuchowski # + @kacpermuda +airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/ @Lee-W @jason810496 # + @RoyLee1224 @guan404ming +airflow-core/src/airflow/ui/public/i18n/locales/fr/ @pierrejeambrun @vincbeck # Security/Permissions /airflow-core/src/airflow/security/permissions.py @vincbeck diff --git a/.github/ISSUE_TEMPLATE/4-airflow_helmchart_bug_report.yml b/.github/ISSUE_TEMPLATE/4-airflow_helmchart_bug_report.yml index 3c8b7e68a82bf..bb8abfe40a9ee 100644 --- a/.github/ISSUE_TEMPLATE/4-airflow_helmchart_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/4-airflow_helmchart_bug_report.yml @@ -28,7 +28,8 @@ body: What Apache Airflow Helm Chart version are you using? multiple: false options: - - "1.16.0 (latest released)" + - "1.17.0 (latest released)" + - "1.16.0" - "1.15.0" - "1.14.0" - "1.13.1" diff --git a/.github/actions/breeze/action.yml b/.github/actions/breeze/action.yml index 39e87cd7d8b52..3fef664b337fa 100644 --- a/.github/actions/breeze/action.yml +++ b/.github/actions/breeze/action.yml @@ -21,7 +21,7 @@ description: 'Sets up Python and Breeze' inputs: python-version: description: 'Python version to use' - default: "3.9" + default: "3.10" use-uv: description: 'Whether to use uv tool' required: true @@ -41,6 +41,8 @@ runs: - name: "Install Breeze" shell: bash run: ./scripts/ci/install_breeze.sh + env: + PYTHON_VERSION: "${{ inputs.python-version }}" - name: "Free space" shell: bash run: breeze ci free-space diff --git a/.github/actions/install-pre-commit/action.yml b/.github/actions/install-pre-commit/action.yml index 5289389930c15..ca6dd5da78194 100644 --- a/.github/actions/install-pre-commit/action.yml +++ b/.github/actions/install-pre-commit/action.yml @@ -21,16 +21,19 @@ description: 'Installs pre-commit and related packages' inputs: python-version: description: 'Python version to use' - default: "3.9" + default: "3.10" uv-version: description: 'uv version to use' - default: "0.7.8" # Keep this comment to allow automatic replacement of uv version + default: "0.7.17" # Keep this comment to allow automatic replacement of uv version pre-commit-version: description: 'pre-commit version to use' default: "4.2.0" # Keep this comment to allow automatic replacement of pre-commit version pre-commit-uv-version: description: 'pre-commit-uv version to use' default: "4.1.4" # Keep this comment to allow automatic replacement of pre-commit-uv version + skip-pre-commits: + description: "Skip some pre-commits from installation" + default: "" runs: using: "composite" steps: @@ -40,6 +43,7 @@ runs: UV_VERSION: ${{inputs.uv-version}} PRE_COMMIT_VERSION: ${{inputs.pre-commit-version}} PRE_COMMIT_UV_VERSION: ${{inputs.pre-commit-uv-version}} + SKIP: ${{ inputs.skip-pre-commits }} run: | pip install uv==${UV_VERSION} || true uv tool install pre-commit==${PRE_COMMIT_VERSION} --with uv==${UV_VERSION} \ @@ -86,3 +90,5 @@ runs: shell: bash run: pre-commit install-hooks || (cat ~/.cache/pre-commit/pre-commit.log && exit 1) working-directory: ${{ github.workspace }} + env: + SKIP: ${{ inputs.skip-pre-commits }} diff --git a/.github/actions/prepare_all_ci_images/action.yml b/.github/actions/prepare_all_ci_images/action.yml index 76c00a72a3998..f245d5081d5d8 100644 --- a/.github/actions/prepare_all_ci_images/action.yml +++ b/.github/actions/prepare_all_ci_images/action.yml @@ -34,14 +34,9 @@ runs: # TODO: Currently we cannot loop through the list of python versions and have dynamic list of # tasks. Instead we hardcode all possible python versions and they - but # this should be implemented in stash action as list of keys to download. - # That includes 3.8 - 3.12 as we are backporting it to v2-10-test branch + # That includes 3.9 - 3.12 as we are backporting it to v3-0-test branch # This is captured in https://github.com/apache/airflow/issues/45268 - - name: "Restore CI docker image ${{ inputs.platform }}:3.8" - uses: ./.github/actions/prepare_single_ci_image - with: - platform: ${{ inputs.platform }} - python: "3.8" - python-versions-list-as-string: ${{ inputs.python-versions-list-as-string }} + # So we actually need 3.9 even if 3.9 support on main is dropped! - name: "Restore CI docker image ${{ inputs.platform }}:3.9" uses: ./.github/actions/prepare_single_ci_image with: diff --git a/.github/boring-cyborg.yml b/.github/boring-cyborg.yml index 02954efbed283..9c5a437d3e07b 100644 --- a/.github/boring-cyborg.yml +++ b/.github/boring-cyborg.yml @@ -332,6 +332,24 @@ labelPRBasedOnFilePath: - .rat-excludes - .readthedocs.yml + # This should be copy of the "area:dev-tools" above and should be updated when we switch maintenance branch + backport-to-v3-0-test: + - scripts/**/* + - dev/**/* + - .github/**/* + - Dockerfile.ci + - CONTRIBUTING.rst + - contributing-docs/**/* + - yamllint-config.yml + - .asf.yaml + - .bash_completion + - .dockerignore + - .hadolint.yaml + - .pre-commit-config.yaml + - .rat-excludes + - .readthedocs.yml + + kind:documentation: - airflow-core/docs/**/* - chart/docs/**/* @@ -348,34 +366,34 @@ labelPRBasedOnFilePath: - airflow-core/src/airflow/ui/**/* area:translations: - - airflow-core/src/airflow/ui/src/i18n/**/* + - airflow-core/src/airflow/ui/public/i18n/**/* translation:default: - - airflow-core/src/airflow/ui/src/i18n/locales/en/* + - airflow-core/src/airflow/ui/public/i18n/locales/en/* translation:ar: - - airflow-core/src/airflow/ui/src/i18n/locales/ar/* + - airflow-core/src/airflow/ui/public/i18n/locales/ar/* translation:de: - - airflow-core/src/airflow/ui/src/i18n/locales/de/* + - airflow-core/src/airflow/ui/public/i18n/locales/de/* translation:fr: - - airflow-core/src/airflow/ui/src/i18n/locales/fr/* + - airflow-core/src/airflow/ui/public/i18n/locales/fr/* translation:he: - - airflow-core/src/airflow/ui/src/i18n/locales/he/* + - airflow-core/src/airflow/ui/public/i18n/locales/he/* translation:ko: - - airflow-core/src/airflow/ui/src/i18n/locales/ko/* + - airflow-core/src/airflow/ui/public/i18n/locales/ko/* translation:nl: - - airflow-core/src/airflow/ui/src/i18n/locales/nl/* + - airflow-core/src/airflow/ui/public/i18n/locales/nl/* translation:pl: - - airflow-core/src/airflow/ui/src/i18n/locales/pl/* + - airflow-core/src/airflow/ui/public/i18n/locales/pl/* translation:zh-TW: - - airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/* + - airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/* area:CLI: - airflow-core/src/airflow/cli/**/*.py diff --git a/.github/workflows/additional-ci-image-checks.yml b/.github/workflows/additional-ci-image-checks.yml index 9e7edaee0ee85..d78404dfef5b4 100644 --- a/.github/workflows/additional-ci-image-checks.yml +++ b/.github/workflows/additional-ci-image-checks.yml @@ -135,7 +135,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" diff --git a/.github/workflows/additional-prod-image-tests.yml b/.github/workflows/additional-prod-image-tests.yml index a2e9deed6df5c..d8e3180f883c9 100644 --- a/.github/workflows/additional-prod-image-tests.yml +++ b/.github/workflows/additional-prod-image-tests.yml @@ -107,7 +107,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 persist-credentials: false @@ -144,7 +144,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 persist-credentials: false diff --git a/.github/workflows/airflow-distributions-tests.yml b/.github/workflows/airflow-distributions-tests.yml index 8399839afd1d5..62d4ee1f6b420 100644 --- a/.github/workflows/airflow-distributions-tests.yml +++ b/.github/workflows/airflow-distributions-tests.yml @@ -61,11 +61,16 @@ on: # yamllint disable-line rule:truthy description: "Whether local venv should be used for tests (true/false)" required: true type: string + test-timeout: + required: false + type: number + default: 60 + permissions: contents: read jobs: distributions-tests: - timeout-minutes: 80 + timeout-minutes: ${{ fromJSON(inputs.test-timeout) }} name: ${{ inputs.distribution-name }}:P${{ matrix.python-version }} tests runs-on: ${{ fromJSON(inputs.runners) }} strategy: @@ -84,7 +89,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare breeze & CI image: ${{ matrix.python-version }}" diff --git a/.github/workflows/automatic-backport.yml b/.github/workflows/automatic-backport.yml index 4c72401a5d317..4f861ddd58118 100644 --- a/.github/workflows/automatic-backport.yml +++ b/.github/workflows/automatic-backport.yml @@ -37,7 +37,7 @@ jobs: - name: Find PR information id: pr-info - uses: actions/github-script@v7 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/backport-cli.yml b/.github/workflows/backport-cli.yml index 673607027496d..0ecdfb8e63e04 100644 --- a/.github/workflows/backport-cli.yml +++ b/.github/workflows/backport-cli.yml @@ -53,7 +53,7 @@ jobs: steps: - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" id: checkout-for-backport - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: true fetch-depth: 0 diff --git a/.github/workflows/basic-tests.yml b/.github/workflows/basic-tests.yml index 52983ad65d559..161ba36d58043 100644 --- a/.github/workflows/basic-tests.yml +++ b/.github/workflows/basic-tests.yml @@ -71,7 +71,7 @@ jobs: - name: "Cleanup repo" shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: # Need to fetch all history for selective checks tests fetch-depth: 0 @@ -94,7 +94,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" @@ -105,7 +105,7 @@ jobs: version: 9 run_install: false - name: "Setup node" - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 21 cache: 'pnpm' @@ -158,12 +158,13 @@ jobs: runs-on: ${{ fromJSON(inputs.runners) }} env: PYTHON_MAJOR_MINOR_VERSION: "${{ inputs.default-python-version }}" + SKIP: ${{ inputs.skip-pre-commits }} steps: - name: "Cleanup repo" shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Install Breeze" @@ -176,6 +177,7 @@ jobs: id: pre-commit with: python-version: ${{steps.breeze.outputs.host-python-version}} + skip-pre-commits: ${{ inputs.skip-pre-commits }} # Those checks are run if no image needs to be built for checks. This is for simple changes that # Do not touch any of the python code or any of the important files that might require building @@ -191,7 +193,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" @@ -205,9 +207,10 @@ jobs: uses: ./.github/actions/install-pre-commit id: pre-commit with: - python-version: ${{steps.breeze.outputs.host-python-version}} + python-version: ${{ steps.breeze.outputs.host-python-version }} + skip-pre-commits: ${{ inputs.skip-pre-commits }} - name: Fetch incoming commit ${{ github.sha }} with its parent - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.sha }} fetch-depth: 2 @@ -220,7 +223,7 @@ jobs: VERBOSE: "false" SKIP_BREEZE_PRE_COMMITS: "true" SKIP: ${{ inputs.skip-pre-commits }} - COLUMNS: "250" + COLUMNS: "202" test-git-clone-on-windows: timeout-minutes: 5 @@ -228,7 +231,7 @@ jobs: runs-on: ["windows-latest"] steps: - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 persist-credentials: false @@ -246,7 +249,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" @@ -261,6 +264,7 @@ jobs: id: pre-commit with: python-version: ${{steps.breeze.outputs.host-python-version}} + skip-pre-commits: ${{ inputs.skip-pre-commits }} - name: "Autoupdate all pre-commits" run: pre-commit autoupdate - name: "Run automated upgrade for black" @@ -319,7 +323,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" @@ -359,4 +363,5 @@ jobs: run: git fetch --tags >/dev/null 2>&1 || true - name: "Test airflow core issue generation automatically" run: | - breeze release-management generate-issue-content-core --limit-pr-count 25 --latest --verbose + breeze release-management generate-issue-content-core \ + --limit-pr-count 2 --previous-release 3.0.1 --current-release 3.0.2 --verbose diff --git a/.github/workflows/ci-amd.yml b/.github/workflows/ci-amd.yml index 8a8e654127ca9..05faec6423c44 100644 --- a/.github/workflows/ci-amd.yml +++ b/.github/workflows/ci-amd.yml @@ -135,13 +135,13 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" run: ./scripts/ci/prepare_and_cleanup_runner.sh - name: Fetch incoming commit ${{ github.sha }} with its parent - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.sha }} fetch-depth: 2 @@ -169,6 +169,37 @@ jobs: PR_LABELS: ${{ steps.source-run-info.outputs.pr-labels }} GITHUB_CONTEXT: ${{ toJson(github) }} + run-pin-versions-pre-commit: + name: "Run pin-versions pre-commit" + needs: [build-info] + runs-on: ${{ fromJSON(needs.build-info.outputs.amd-runners) }} + steps: + - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - name: "Install Python 3.11 as 3.11+ is needed by pin-versions pre-commit" + uses: actions/setup-python@7f4fc3e22c37d6ff65e88745f38bd3157c663f7c # v4.9.1 + with: + python-version: 3.11 + cache: "pip" + - name: Install pre-commit, uv, and pre-commit-uv + shell: bash + env: + UV_VERSION: "0.7.17" # Keep this comment to allow automatic replacement of uv version + PRE_COMMIT_VERSION: "4.2.0" # Keep this comment to allow automatic replacement of pre-commit version + PRE_COMMIT_UV_VERSION: "4.1.4" # Keep this comment to allow automatic replacement of pre-commit-uv version + run: | + pip install uv==${UV_VERSION} || true + uv tool install pre-commit==${PRE_COMMIT_VERSION} --with uv==${UV_VERSION} \ + --with pre-commit-uv==${PRE_COMMIT_UV_VERSION} + - name: "Run pin-versions pre-commit" + run: > + pre-commit run -c .github/.pre-commit-config.yaml --all-files --verbose --hook-stage manual + pin-versions + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + basic-tests: name: "Basic tests" needs: [build-info] @@ -217,7 +248,6 @@ jobs: contents: read packages: write id-token: write - if: needs.build-info.outputs.canary-run == 'true' with: runners: ${{ needs.build-info.outputs.amd-runners }} platform: "linux/amd64" @@ -244,6 +274,8 @@ jobs: runners: ${{ needs.build-info.outputs.amd-runners }} platform: "linux/amd64" python-versions-list-as-string: ${{ needs.build-info.outputs.python-versions-list-as-string }} + python-versions: ${{ needs.build-info.outputs.python-versions }} + generate-pypi-constraints: "true" # generate no providers constraints only in canary builds - they take quite some time to generate # they are not needed for regular builds, they are only needed to update constraints in canaries generate-no-providers-constraints: ${{ needs.build-info.outputs.canary-run }} @@ -753,6 +785,7 @@ jobs: distribution-cmd-format: "prepare-task-sdk-distributions" test-type: "task-sdk-tests" use-local-venv: 'false' + test-timeout: 20 if: > ( needs.build-info.outputs.run-task-sdk-tests == 'true' || needs.build-info.outputs.run-tests == 'true' && @@ -777,23 +810,30 @@ jobs: VERBOSE: "true" steps: - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false # keep this in sync with go.mod in go-sdk/ - name: Setup Go - uses: actions/setup-go@v5 + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version: 1.24 cache-dependency-path: go-sdk/go.sum + # keep this in sync with go.mod in go-sdk/ + - name: Setup Gotestsum + shell: bash + run: | + go install gotest.tools/gotestsum@ddd0b05a6878e2e8257a2abe6e7df66cebc53d0e # v1.12.3 + gotestsum --version + - name: "Cleanup dist files" run: rm -fv ./dist/* - name: Run Go tests working-directory: ./go-sdk - run: go test -v ./... + run: gotestsum --format testname ./... tests-airflow-ctl: name: "Airflow CTL tests" @@ -813,6 +853,7 @@ jobs: distribution-cmd-format: "prepare-airflow-ctl-distributions" test-type: "airflow-ctl-tests" use-local-venv: 'true' + test-timeout: 20 if: > ( needs.build-info.outputs.run-airflow-ctl-tests == 'true' || needs.build-info.outputs.run-tests == 'true' && @@ -901,7 +942,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" @@ -910,12 +951,12 @@ jobs: shell: bash run: ./scripts/tools/free_up_disk_space.sh - name: "Download all test warning artifacts from the current build" - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: path: ./artifacts pattern: test-warnings-* - name: "Setup python" - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: ${{ inputs.default-python-version }} - name: "Summarize all warnings" @@ -924,7 +965,7 @@ jobs: --pattern "**/warnings-*.txt" \ --output ./files - name: "Upload artifact for summarized warnings" - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: test-summarized-amd-runner-warnings path: ./files/warn-summary-*.txt diff --git a/.github/workflows/ci-arm.yml b/.github/workflows/ci-arm.yml index 0500106b94792..21dd5d75205ec 100644 --- a/.github/workflows/ci-arm.yml +++ b/.github/workflows/ci-arm.yml @@ -128,13 +128,13 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" run: ./scripts/ci/prepare_and_cleanup_runner.sh - name: Fetch incoming commit ${{ github.sha }} with its parent - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.sha }} fetch-depth: 2 @@ -210,7 +210,6 @@ jobs: contents: read packages: write id-token: write - if: needs.build-info.outputs.canary-run == 'true' with: runners: ${{ needs.build-info.outputs.arm-runners }} platform: "linux/arm64" @@ -237,13 +236,14 @@ jobs: runners: ${{ needs.build-info.outputs.arm-runners }} platform: "linux/arm64" python-versions-list-as-string: ${{ needs.build-info.outputs.python-versions-list-as-string }} + python-versions: ${{ needs.build-info.outputs.python-versions }} + generate-pypi-constraints: "true" # generate no providers constraints only in canary builds - they take quite some time to generate # they are not needed for regular builds, they are only needed to update constraints in canaries generate-no-providers-constraints: ${{ needs.build-info.outputs.canary-run }} debug-resources: ${{ needs.build-info.outputs.debug-resources }} use-uv: ${{ needs.build-info.outputs.use-uv }} - providers: name: "provider distributions tests" uses: ./.github/workflows/test-providers.yml @@ -527,13 +527,13 @@ jobs: VERBOSE: "true" steps: - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false # keep this in sync with go.mod in go-sdk/ - name: Setup Go - uses: actions/setup-go@v5 + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version: 1.24 cache-dependency-path: go-sdk/go.sum diff --git a/.github/workflows/ci-image-build.yml b/.github/workflows/ci-image-build.yml index b52fdb906fa2e..f58fe1946ca1f 100644 --- a/.github/workflows/ci-image-build.yml +++ b/.github/workflows/ci-image-build.yml @@ -117,7 +117,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout target branch" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" diff --git a/.github/workflows/ci-image-checks.yml b/.github/workflows/ci-image-checks.yml index 2cc5f690df83f..a3baab28f29bc 100644 --- a/.github/workflows/ci-image-checks.yml +++ b/.github/workflows/ci-image-checks.yml @@ -127,7 +127,7 @@ jobs: run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" if: inputs.canary-run == 'true' - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false if: inputs.canary-run == 'true' @@ -173,7 +173,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare breeze & CI image: ${{ inputs.default-python-version }}" @@ -193,7 +193,7 @@ jobs: env: VERBOSE: "false" SKIP: ${{ inputs.skip-pre-commits }} - COLUMNS: "250" + COLUMNS: "202" SKIP_GROUP_OUTPUT: "true" DEFAULT_BRANCH: ${{ inputs.branch }} RUFF_FORMAT: "github" @@ -216,7 +216,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare breeze & CI image: ${{ inputs.default-python-version }}" @@ -235,7 +235,7 @@ jobs: run: pre-commit run --color always --verbose --hook-stage manual "$MYPY_CHECK" --all-files env: VERBOSE: "false" - COLUMNS: "250" + COLUMNS: "202" SKIP_GROUP_OUTPUT: "true" DEFAULT_BRANCH: ${{ inputs.branch }} RUFF_FORMAT: "github" @@ -264,7 +264,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare breeze & CI image: ${{ inputs.default-python-version }}" @@ -295,7 +295,7 @@ jobs: # to be responsible for updating it. https://github.com/actions/upload-artifact/issues/506 if: steps.restore-docs-inventory-cache != 'true' && matrix.flag == '--docs-only' - name: "Upload build docs" - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: airflow-docs path: './generated/_build' @@ -327,7 +327,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare breeze & CI image: ${{ inputs.default-python-version }}" @@ -337,7 +337,7 @@ jobs: python: ${{ inputs.default-python-version }} use-uv: ${{ inputs.use-uv }} - name: "Download docs prepared as artifacts" - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: airflow-docs path: './generated/_build' @@ -402,12 +402,12 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 persist-credentials: false - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: "apache/airflow-client-python" fetch-depth: 1 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1fcf81a84fd5b..28c8cfae81a07 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -47,17 +47,17 @@ jobs: security-events: write steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@v3 + uses: github/codeql-action/autobuild@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0 diff --git a/.github/workflows/finalize-tests.yml b/.github/workflows/finalize-tests.yml index 6afcbd0812219..bab0d82bd7a3c 100644 --- a/.github/workflows/finalize-tests.yml +++ b/.github/workflows/finalize-tests.yml @@ -99,7 +99,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: # Needed to perform push action persist-credentials: false @@ -109,16 +109,16 @@ jobs: id: constraints-branch run: ./scripts/ci/constraints/ci_branch_constraints.sh >> ${GITHUB_OUTPUT} - name: Checkout ${{ steps.constraints-branch.outputs.branch }} - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: path: "constraints" ref: ${{ steps.constraints-branch.outputs.branch }} persist-credentials: true fetch-depth: 0 - name: "Download constraints from the constraints generated by build CI image" - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: - name: constraints + pattern: constraints-* path: ./files - name: "Diff in constraints for Python: ${{ inputs.python-versions-list-as-string }}" run: ./scripts/ci/constraints/ci_diff_constraints.sh @@ -132,6 +132,42 @@ jobs: run: git push + dependency-upgrade-summary: + runs-on: ${{ fromJSON(inputs.runners) }} + needs: [update-constraints] + if: inputs.upgrade-to-newer-dependencies == 'true' && inputs.platform == 'linux/amd64' + name: "Dependencies ${{ matrix.python-version }}:${{ matrix.constraints-mode }}" + strategy: + matrix: + python-version: ${{ fromJson(inputs.python-versions) }} + constraints-mode: ["constraints", "constraints-source-providers", "constraints-no-providers"] + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: "Cleanup repo" + shell: bash + run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" + - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - name: "Prepare breeze & CI image: ${{ matrix.python-version }}" + uses: ./.github/actions/prepare_breeze_and_image + with: + platform: ${{ inputs.platform }} + python: ${{ matrix.python-version }} + use-uv: ${{ inputs.use-uv }} + - name: "Dependency upgrade summary" + shell: bash + run: > + breeze run uv run /opt/airflow/dev/constraints-updated-version-check.py + --python-version "${MATRIX_PYTHON_VERSION}" + --airflow-constraints-mode "${MATRIX_CONSTRAINTS_MODE}" --explain-why + env: + MATRIX_PYTHON_VERSION: "${{ matrix.python-version }}" + MATRIX_CONSTRAINTS_MODE: "${{ matrix.constraints-mode }}" + VERBOSE: "false" + push-buildx-cache-to-github-registry: name: Push Regular Image Cache ${{ inputs.platform }} needs: [update-constraints] diff --git a/.github/workflows/generate-constraints.yml b/.github/workflows/generate-constraints.yml index 35b31db98e575..d2d0db0685a58 100644 --- a/.github/workflows/generate-constraints.yml +++ b/.github/workflows/generate-constraints.yml @@ -32,10 +32,18 @@ on: # yamllint disable-line rule:truthy description: "Stringified array of all Python versions to test - separated by spaces." required: true type: string + python-versions: + description: "JSON-formatted array of Python versions to generate constraints for" + required: true + type: string generate-no-providers-constraints: description: "Whether to generate constraints without providers (true/false)" required: true type: string + generate-pypi-constraints: + description: "Whether to generate PyPI constraints (true/false)" + required: true + type: string debug-resources: description: "Whether to run in debug mode (true/false)" required: true @@ -45,94 +53,86 @@ on: # yamllint disable-line rule:truthy required: true type: string jobs: - generate-constraints: + generate-constraints-matrix: permissions: contents: read timeout-minutes: 70 - name: Generate constraints ${{ inputs.python-versions-list-as-string }} + name: Generate constraints for ${{ matrix.python-version }} on ${{ inputs.platform }} runs-on: ${{ fromJSON(inputs.runners) }} + strategy: + matrix: + python-version: ${{ fromJson(inputs.python-versions) }} env: DEBUG_RESOURCES: ${{ inputs.debug-resources }} GITHUB_REPOSITORY: ${{ github.repository }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_USERNAME: ${{ github.actor }} INCLUDE_SUCCESS_OUTPUTS: "true" - PYTHON_VERSIONS: ${{ inputs.python-versions-list-as-string }} + PYTHON_VERSION: ${{ matrix.python-version }} VERBOSE: "true" steps: - name: "Cleanup repo" shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - name: "Prepare and cleanup runner" - run: ./scripts/ci/prepare_and_cleanup_runner.sh - shell: bash - - name: "Install Breeze" - uses: ./.github/actions/breeze - with: - use-uv: ${{ inputs.use-uv }} - id: breeze - - name: "Prepare all CI images: ${{ inputs.python-versions-list-as-string}}" - uses: ./.github/actions/prepare_all_ci_images + - name: "Prepare breeze & CI image: ${{ matrix.python-version }}" + uses: ./.github/actions/prepare_breeze_and_image with: platform: ${{ inputs.platform }} - python-versions-list-as-string: ${{ inputs.python-versions-list-as-string }} - docker-volume-location: "" # TODO(jscheffl): Understand why it fails here and fix it - - name: "Verify all CI images ${{ inputs.python-versions-list-as-string }}" - run: breeze ci-image verify --run-in-parallel + python: ${{ matrix.python-version }} + use-uv: ${{ inputs.use-uv }} - name: "Source constraints" shell: bash run: > - breeze release-management generate-constraints --run-in-parallel + breeze release-management generate-constraints --airflow-constraints-mode constraints-source-providers --answer yes + --python "${PYTHON_VERSION}" - name: "No providers constraints" shell: bash timeout-minutes: 25 run: > - breeze release-management generate-constraints --run-in-parallel - --airflow-constraints-mode constraints-no-providers --answer yes --parallelism 3 - # The no providers constraints are only needed when we want to update constraints (in canary builds) - # They slow down the start of PROD image builds so we want to only run them when needed. + breeze release-management generate-constraints + --airflow-constraints-mode constraints-no-providers --answer yes + --python "${PYTHON_VERSION}" if: inputs.generate-no-providers-constraints == 'true' - name: "Prepare updated provider distributions" - # In case of provider distributions which are not yet released, we build them from sources shell: bash run: > - breeze release-management prepare-provider-distributions --include-not-ready-providers - --distribution-format wheel + breeze release-management prepare-provider-distributions + --include-not-ready-providers --distribution-format wheel + if: inputs.generate-pypi-constraints == 'true' - name: "Prepare airflow distributions" shell: bash run: > breeze release-management prepare-airflow-distributions --distribution-format wheel + if: inputs.generate-pypi-constraints == 'true' - name: "Prepare task-sdk distribution" shell: bash run: > breeze release-management prepare-task-sdk-distributions --distribution-format wheel + if: inputs.generate-pypi-constraints == 'true' - name: "PyPI constraints" shell: bash timeout-minutes: 25 run: | - for PYTHON in $PYTHON_VERSIONS; do - breeze release-management generate-constraints --airflow-constraints-mode constraints \ - --answer yes --python "${PYTHON}" - done - - name: "Dependency upgrade summary" - shell: bash - env: - PYTHON_VERSIONS: ${{ env.PYTHON_VERSIONS }} - run: | - for PYTHON_VERSION in $PYTHON_VERSIONS; do - echo "Summarizing Python $PYTHON_VERSION" - cat "files/constraints-${PYTHON_VERSION}"/*.md >> $GITHUB_STEP_SUMMARY || true - df -H - done + breeze release-management generate-constraints --airflow-constraints-mode constraints \ + --answer yes --python "${PYTHON_VERSION}" + if: inputs.generate-pypi-constraints == 'true' - name: "Upload constraint artifacts" - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: - name: constraints - path: ./files/constraints-*/constraints-*.txt + name: constraints-${{ matrix.python-version }} + path: ./files/constraints-${{ matrix.python-version }}/constraints-*.txt retention-days: 7 if-no-files-found: error + - name: "Dependency upgrade summary" + shell: bash + env: + PYTHON_VERSION: ${{ matrix.python-version }} + run: | + echo "Summarizing Python $PYTHON_VERSION" + cat "files/constraints-${PYTHON_VERSION}"/*.md >> $GITHUB_STEP_SUMMARY || true + df -H diff --git a/.github/workflows/helm-tests.yml b/.github/workflows/helm-tests.yml index 26bf28cce1beb..e889e25160cea 100644 --- a/.github/workflows/helm-tests.yml +++ b/.github/workflows/helm-tests.yml @@ -68,7 +68,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare breeze & CI image: ${{ inputs.default-python-version }}" @@ -93,7 +93,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" @@ -130,13 +130,12 @@ jobs: SIGN_WITH: dev@airflow.apache.org - name: "Fetch Git Tags" run: git fetch --tags - - name: "Test helm chart issue generation automatically" - # Adding same tags for now, will address in a follow-up + - name: "Test helm chart issue generation" run: > - breeze release-management generate-issue-content-helm-chart --limit-pr-count 10 - --latest --verbose + breeze release-management generate-issue-content-helm-chart --limit-pr-count 2 + --previous-release helm-chart/1.15.0 --current-release helm-chart/1.16.0 --verbose - name: "Upload Helm artifacts" - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: Helm artifacts path: ./dist/airflow-* diff --git a/.github/workflows/integration-system-tests.yml b/.github/workflows/integration-system-tests.yml index bf75cc87f31a3..6619bedd7c65e 100644 --- a/.github/workflows/integration-system-tests.yml +++ b/.github/workflows/integration-system-tests.yml @@ -97,7 +97,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare breeze & CI image: ${{ inputs.default-python-version }}" @@ -146,7 +146,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare breeze & CI image: ${{ inputs.default-python-version }}" @@ -190,7 +190,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare breeze & CI image: ${{ inputs.default-python-version }}" diff --git a/.github/workflows/k8s-tests.yml b/.github/workflows/k8s-tests.yml index 6ed0c79d187c5..37aa3aa703ce1 100644 --- a/.github/workflows/k8s-tests.yml +++ b/.github/workflows/k8s-tests.yml @@ -80,7 +80,7 @@ jobs: echo "PYTHON_MAJOR_MINOR_VERSION=${KUBERNETES_COMBO}" | sed 's/-.*//' >> $GITHUB_ENV echo "KUBERNETES_VERSION=${KUBERNETES_COMBO}" | sed 's/=[^-]*-/=/' >> $GITHUB_ENV - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false # env.PYTHON_MAJOR_MINOR_VERSION, env.KUBERNETES_VERSION are set in the previous @@ -115,7 +115,7 @@ jobs: - name: "\ Upload KinD logs ${{ matrix.executor }}-${{ matrix.kubernetes-combo }}-\ ${{ matrix.use-standard-naming }}" - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: "\ kind-logs-${{ matrix.kubernetes-combo }}-${{ matrix.executor }}-\ diff --git a/.github/workflows/news-fragment.yml b/.github/workflows/news-fragment.yml index f6f68d1288a35..04e308c306138 100644 --- a/.github/workflows/news-fragment.yml +++ b/.github/workflows/news-fragment.yml @@ -30,7 +30,7 @@ jobs: if: "contains(github.event.pull_request.labels.*.name, 'airflow3.0:breaking')" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false # `towncrier check` runs `git diff --name-only origin/main...`, which diff --git a/.github/workflows/prod-image-build.yml b/.github/workflows/prod-image-build.yml index c5cf5cd5cef96..4819ee7be1470 100644 --- a/.github/workflows/prod-image-build.yml +++ b/.github/workflows/prod-image-build.yml @@ -124,7 +124,7 @@ jobs: run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" if: inputs.upload-package-artifact == 'true' - name: "Checkout target branch" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" @@ -171,7 +171,7 @@ jobs: breeze release-management prepare-airflow-ctl-distributions --distribution-format wheel if: inputs.upload-package-artifact == 'true' - name: "Upload prepared packages as artifacts" - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: prod-packages path: ./dist @@ -211,7 +211,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout target branch" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" @@ -224,16 +224,16 @@ jobs: shell: bash run: rm -fv ./dist/* ./docker-context-files/* - name: "Download packages prepared as artifacts" - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: prod-packages path: ./docker-context-files - name: "Show downloaded packages" run: ls -la ./docker-context-files - name: "Download constraints" - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: - name: constraints + pattern: constraints-* path: ./docker-context-files - name: "Show constraints" run: | diff --git a/.github/workflows/publish-docs-to-s3.yml b/.github/workflows/publish-docs-to-s3.yml index 22ba4b3e97af4..7d93753146458 100644 --- a/.github/workflows/publish-docs-to-s3.yml +++ b/.github/workflows/publish-docs-to-s3.yml @@ -118,7 +118,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_USERNAME: ${{ github.actor }} INCLUDE_SUCCESS_OUTPUTS: false - PYTHON_MAJOR_MINOR_VERSION: 3.9 + PYTHON_MAJOR_MINOR_VERSION: 3.10 VERBOSE: "true" EXTRA_BUILD_OPTIONS: ${{ needs.build-info.outputs.extra-build-options }} steps: @@ -127,7 +127,7 @@ jobs: run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" # Check out the repo first to run cleanup - in sub-folder - name: "Checkout current version first to clean-up stuff" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false path: current-version @@ -138,7 +138,7 @@ jobs: # This will take longer as we need to rebuild CI image and it will not use cache # but it will build the CI image from the version of Airflow that is used to check out things - name: "Checkout ${{ inputs.ref }} " - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false ref: ${{ inputs.ref }} @@ -167,7 +167,7 @@ jobs: run: > breeze release-management publish-docs --override-versioned --run-in-parallel ${INCLUDE_DOCS} - name: "Upload build docs" - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: airflow-docs path: /mnt/airflow-site @@ -187,7 +187,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_USERNAME: ${{ github.actor }} INCLUDE_SUCCESS_OUTPUTS: false - PYTHON_MAJOR_MINOR_VERSION: 3.9 + PYTHON_MAJOR_MINOR_VERSION: 3.10 VERBOSE: "true" steps: - name: "Cleanup repo" @@ -197,7 +197,7 @@ jobs: # This will take longer as we need to rebuild CI image and it will not use cache # but it will build the CI image from the version of Airflow that is used to check out things - name: "Checkout ${{ inputs.ref }} " - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" @@ -207,7 +207,7 @@ jobs: with: use-uv: ${{ inputs.use-uv }} - name: "Download docs prepared as artifacts" - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: airflow-docs path: /mnt/airflow-site diff --git a/.github/workflows/push-image-cache.yml b/.github/workflows/push-image-cache.yml index f2258c13b77a9..b523577b46c99 100644 --- a/.github/workflows/push-image-cache.yml +++ b/.github/workflows/push-image-cache.yml @@ -113,7 +113,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" @@ -184,7 +184,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" @@ -196,7 +196,7 @@ jobs: - name: "Cleanup dist and context file" run: rm -fv ./dist/* ./docker-context-files/* - name: "Download packages prepared as artifacts" - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: prod-packages path: ./docker-context-files diff --git a/.github/workflows/recheck-old-bug-report.yml b/.github/workflows/recheck-old-bug-report.yml index 217092b86f87e..c245f73923216 100644 --- a/.github/workflows/recheck-old-bug-report.yml +++ b/.github/workflows/recheck-old-bug-report.yml @@ -28,7 +28,7 @@ jobs: recheck-old-bug-report: runs-on: ["ubuntu-22.04"] steps: - - uses: actions/stale@v9 + - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 with: only-issue-labels: 'kind:bug' stale-issue-label: 'Stale Bug Report' diff --git a/.github/workflows/release_dockerhub_image.yml b/.github/workflows/release_dockerhub_image.yml index fe1ce300fbf4f..1ec9ec8f91be4 100644 --- a/.github/workflows/release_dockerhub_image.yml +++ b/.github/workflows/release_dockerhub_image.yml @@ -29,7 +29,7 @@ on: # yamllint disable-line rule:truthy default: false limitPythonVersions: type: string - description: 'Force python versions (e.g. "3.9 3.10")' + description: 'Force python versions (e.g. "3.10 3.11")' default: '' permissions: contents: read @@ -83,7 +83,7 @@ jobs: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" diff --git a/.github/workflows/release_single_dockerhub_image.yml b/.github/workflows/release_single_dockerhub_image.yml index 55a8c2cc00429..b308de93e72ee 100644 --- a/.github/workflows/release_single_dockerhub_image.yml +++ b/.github/workflows/release_single_dockerhub_image.yml @@ -29,7 +29,7 @@ on: # yamllint disable-line rule:truthy type: string required: true pythonVersion: - description: 'Python version (e.g. 3.8, 3.9, 3.10, 3.11)' + description: 'Python version (e.g. 3.10, 3.11)' type: string required: true skipLatest: @@ -76,7 +76,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" @@ -148,7 +148,7 @@ jobs: shell: bash run: find ./dist -name '*.json' - name: "Upload metadata artifact ${{ env.ARTIFACT_NAME }}" - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: ${{ env.ARTIFACT_NAME }} path: ./dist/metadata-* @@ -174,7 +174,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare and cleanup runner" @@ -197,7 +197,7 @@ jobs: ACTOR: ${{ github.actor }} run: echo "${GITHUB_TOKEN}" | docker login ghcr.io -u ${ACTOR} --password-stdin - name: "Download metadata artifacts" - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: path: ./dist pattern: metadata-${{ inputs.pythonVersion }}-* diff --git a/.github/workflows/run-unit-tests.yml b/.github/workflows/run-unit-tests.yml index 4b99ac6031137..035248113dac1 100644 --- a/.github/workflows/run-unit-tests.yml +++ b/.github/workflows/run-unit-tests.yml @@ -167,7 +167,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare breeze & CI image: ${{ matrix.python-version }}" diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 2e03e9f33b120..5724a17314aec 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -29,7 +29,7 @@ jobs: stale: runs-on: ["ubuntu-22.04"] steps: - - uses: actions/stale@v9 + - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 with: stale-pr-message: > This pull request has been automatically marked as stale because it has not had diff --git a/.github/workflows/test-providers.yml b/.github/workflows/test-providers.yml index 411b18daaa7b4..eec3c04722744 100644 --- a/.github/workflows/test-providers.yml +++ b/.github/workflows/test-providers.yml @@ -89,7 +89,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare breeze & CI image: ${{ inputs.default-python-version }}" @@ -126,10 +126,6 @@ jobs: breeze release-management generate-issue-content-providers --only-available-in-dist --disable-progress if: matrix.package-format == 'wheel' - - name: Remove Python 3.9-incompatible provider distributions - run: | - echo "Removing Python 3.9-incompatible provider: cloudant" - rm -vf dist/*cloudant* - name: "Generate source constraints from CI image" shell: bash run: > @@ -138,7 +134,8 @@ jobs: - name: "Install and verify wheel provider distributions" env: DISTRIBUTION_FORMAT: ${{ matrix.package-format }} - AIRFLOW_SKIP_CONSTRAINTS: "${{ inputs.upgrade-to-newer-dependencies }}" + # yamllint disable rule:line-length + INSTALL_AIRFLOW_WITH_CONSTRAINTS: "${{ inputs.upgrade-to-newer-dependencies == 'true' && 'false' || 'true' }}" run: > breeze release-management verify-provider-distributions --use-distributions-from-dist @@ -187,7 +184,7 @@ jobs: shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Prepare breeze & CI image: ${{ matrix.compat.python-version }}" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a76b5a0771861..15b5a3605d5ca 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,7 +18,7 @@ default_stages: [pre-commit, pre-push] default_language_version: python: python3 - node: 22.16.0 + node: 22.17.0 golang: 1.24.0 minimum_pre_commit_version: '3.2.0' exclude: ^.*/.*_vendor/ @@ -206,7 +206,11 @@ repos: entry: ./scripts/ci/pre_commit/update_installers_and_pre_commit.py stages: ['manual'] language: python - files: ^\.pre-commit-config\.yaml$|^scripts/ci/pre_commit/update_installers_and_pre_commit\.py$ + files: > + (?x) + ^\.pre-commit-config\.yaml$| + ^\.github/\.pre-commit-config\.yaml$| + ^scripts/ci/pre_commit/update_installers_and_pre_commit\.py$ pass_filenames: false require_serial: true additional_dependencies: ['pyyaml>=6.0.2', 'rich>=12.4.4', 'requests>=2.31.0'] @@ -233,8 +237,7 @@ repos: entry: ./scripts/ci/pre_commit/check_deferrable_default.py pass_filenames: false # libcst doesn't have source wheels for all PY except PY3.12, excluding it - # libcst 1.8.1 doesn't include typing-extensions which is needed for Python 3.9 - additional_dependencies: ['libcst>=1.1.0,!=1.8.0,!=1.8.1'] + additional_dependencies: ['libcst>=1.8.1'] files: ^(providers/.*/)?airflow/.*/(sensors|operators)/.*\.py$ - repo: https://github.com/asottile/blacken-docs rev: 1.19.1 @@ -243,7 +246,6 @@ repos: name: Run black on docs args: - --line-length=110 - - --target-version=py39 - --target-version=py310 - --target-version=py311 - --target-version=py312 @@ -285,7 +287,8 @@ repos: (?x) ^airflow-core/docs/img/.*\.dot$| ^dev/breeze/doc/images/output.*$| - ^.*/openapi-gen/.*$ + ^.*/openapi-gen/.*$| + ^airflow-ctl/docs/images/.*\.svg$ - id: fix-encoding-pragma name: Remove encoding header from Python files args: @@ -355,9 +358,7 @@ repos: ^.*/kinglear\.txt$| ^.*pnpm-lock\.yaml$| .*/dist/.*| - ^airflow-core/src/airflow/ui/src/i18n/locales/de/| - ^airflow-core/src/airflow/ui/src/i18n/locales/fr/| - ^airflow-core/src/airflow/ui/src/i18n/locales/pl/ + ^airflow-core/src/airflow/ui/public/i18n/locales/(?!en/).+/ args: - --ignore-words=docs/spelling_wordlist.txt - --skip=providers/.*/src/airflow/providers/*/*.rst,providers/*/docs/changelog.rst,docs/*/commits.rst,providers/*/docs/commits.rst,providers/*/*/docs/commits.rst,docs/apache-airflow/tutorial/pipeline_example.csv,*.min.js,*.lock,INTHEWILD.md,*.svg @@ -411,6 +412,13 @@ repos: ^airflow_breeze/templates/PROVIDER_README_TEMPLATE\.rst\.jinja2$ additional_dependencies: ['rich>=12.4.4','requests>=2.31.0'] require_serial: true + - id: check-airflow-v-imports-in-tests + name: Check AIRFLOW_V imports in tests + language: python + entry: ./scripts/ci/pre_commit/check_airflow_v_imports_in_tests.py + pass_filenames: true + files: ^providers/.*/tests/.+\.py$ + additional_dependencies: ['rich>=12.4.4'] - id: ruff name: Run 'ruff' for extremely fast Python linting description: "Run 'ruff' for extremely fast Python linting" @@ -419,7 +427,7 @@ repos: types_or: [python, pyi] args: [--fix] require_serial: true - additional_dependencies: ['ruff==0.11.13'] + additional_dependencies: ['ruff==0.12.1'] exclude: ^airflow-core/tests/unit/dags/test_imports\.py$|^performance/tests/test_.*\.py$ - id: ruff-format name: Run 'ruff format' @@ -429,7 +437,7 @@ repos: types_or: [python, pyi] args: [] require_serial: true - additional_dependencies: ['ruff==0.11.13'] + additional_dependencies: ['ruff==0.12.1'] exclude: ^airflow-core/tests/unit/dags/test_imports\.py$ - id: replace-bad-characters name: Replace bad characters @@ -539,6 +547,16 @@ repos: pass_filenames: false require_serial: true additional_dependencies: ['rich>=12.4.4'] + - id: prevent-deprecated-sqlalchemy-usage + name: Prevent deprecated sqlalchemy usage + entry: ./scripts/ci/pre_commit/prevent_deprecated_sqlalchemy_usage.py + language: python + additional_dependencies: ['rich>=12.4.4'] + files: > + (?x) + ^airflow-ctl.*\.py$| + ^task_sdk.*\.py$ + pass_filenames: true - id: update-supported-versions name: Updates supported versions in documentation entry: ./scripts/ci/pre_commit/supported_versions.py @@ -572,6 +590,60 @@ repos: entry: "pydevd.*settrace\\(" pass_filenames: true files: \.py$ + - id: check-pytest-mark-db-test-in-providers + language: pygrep + name: Check pytest.mark.db_test use in providers + entry: pytest\.mark\.db_test + pass_filenames: true + # Here we should add providers that are already free from the pytest.mark.db_test + # and we want to keep them clean and only use non-db-tests + files: > + (?x) + ^providers/airbyte/.*\.py$| + ^providers/apache/beam/.*\.py$| + ^providers/apache/flink/.*\.py$| + ^providers/apache/iceberg/.*\.py$| + ^providers/apache/kafka/.*\.py$| + ^providers/arangodb/.*\.py$| + ^providers/asana/.*\.py$| + ^providers/cloudant/.*\.py$| + ^providers/cohere/.*\.py$| + ^providers/common/compat/.*\.py$| + ^providers/common/messaging/.*\.py$| + ^providers/datadog/.*\.py$| + ^providers/dingding/.*\.py$| + ^providers/discord/.*\.py$| + ^providers/exasol/.*\.py$| + ^providers/facebook/.*\.py$| + ^providers/ftp/.*\.py$| + ^providers/grpc/.*\.py$| + ^providers/hashicorp/.*\.py$| + ^providers/imap/.*\.py$| + ^providers/influxdb/.*\.py$| + ^providers/jdbc/.*\.py$| + ^providers/jenkins/.*\.py$| + ^providers/mongo/.*\.py$| + ^providers/microsoft/psrp/.*\.py$| + ^providers/microsoft/winrm/.*\.py$| + ^providers/neo4j/.*\.py$| + ^providers/odbc/.*\.py$| + ^providers/openai/.*\.py$| + ^providers/openfaas/.*\.py$| + ^providers/oracle/.*\.py$| + ^providers/pagerduty/.*\.py$| + ^providers/pgvector/.*\.py$| + ^providers/pinecone/.*\.py$| + ^providers/postgres/.*\.py$| + ^providers/presto/.*\.py$| + ^providers/segment/.*\.py$| + ^providers/sendgrid/.*\.py$| + ^providers/singularity/.*\.py$| + ^providers/tableau/.*\.py$| + ^providers/teradata/.*\.py$| + ^providers/trino/.*\.py$| + ^providers/vertica/.*\.py$| + ^providers/yandex/.*\.py$| + ^providers/zendesk/.*\.py$ - id: check-links-to-example-dags-do-not-use-hardcoded-versions name: Verify no hard-coded version in example dags description: The links to example dags should use |version| as version specification @@ -637,7 +709,7 @@ repos: (?x) ^airflow-core/src/airflow/ui/src/i18n/config\.ts$| ^airflow-core/src/airflow/ui/openapi-gen/| - ^airflow-core/src/airflow/ui/src/i18n/locales/de/README\.md$| + ^airflow-core/src/airflow/ui/public/i18n/locales/de/README\.md$| ^airflow-core/src/airflow/cli/commands/local_commands/fastapi_api_command\.py$| ^airflow-core/src/airflow/config_templates/| ^airflow-core/src/airflow/models/baseoperator\.py$| @@ -688,6 +760,7 @@ repos: ^.*/conf_constants\.py$| ^.*/provider_conf\.py$| ^devel-common/src/sphinx_exts/removemarktransform\.py| + ^devel-common/src/tests_common/test_utils/db\.py| ^airflow-core/newsfragments/41761.significant\.rst$| ^scripts/ci/pre_commit/vendor_k8s_json_schema\.py$| ^scripts/ci/docker-compose/integration-keycloak\.yml$| @@ -801,12 +874,6 @@ repos: entry: "LoggingMixin\\(\\)" files: \.py$ pass_filenames: true - - id: check-daysago-import-from-utils - language: pygrep - name: days_ago imported from airflow.utils.dates - entry: "(airflow\\.){0,1}utils\\.dates\\.days_ago" - files: \.py$ - pass_filenames: true - id: check-start-date-not-used-in-defaults language: pygrep name: start_date not in default_args @@ -863,6 +930,13 @@ repos: files: ^chart require_serial: true additional_dependencies: ['rich>=12.4.4','requests>=2.31.0'] + - id: validate-chart-annotations + name: Validate chart annotations + entry: ./scripts/ci/pre_commit/validate_chart_annotations.py + language: python + pass_filenames: false + files: ^chart/Chart\.yaml$ + additional_dependencies: ['pyyaml>=6.0.2', 'rich>=12.4.4'] - id: kubeconform name: Kubeconform check on our helm chart entry: ./scripts/ci/pre_commit/check_kubeconform.py @@ -1263,14 +1337,6 @@ repos: files: ^airflow-core/src/airflow/migrations/versions/.*\.py$ exclude: airflow-core/src/airflow/migrations/versions/0028_3_0_0_drop_ab_user_id_foreign_key.py - - id: generate-airflowctl-help-images - name: Generate SVG from Airflow CTL Commands - entry: ./scripts/ci/pre_commit/capture_airflowctl_help.py - language: python - pass_filenames: false - files: - ^airflow-ctl/src/airflowctl/api/operations.py|airflow-ctl/src/airflowctl/cli/.*\.py$ - additional_dependencies: ['rich>=12.4.4'] - id: go-mockery name: Generate mocks for go entry: -w /src/go-sdk vektra/mockery:3 @@ -1279,7 +1345,7 @@ repos: types: [go] pass_filenames: false language: docker_image - - id: go-tidy + - id: go-mod-tidy name: Run go mod tidy entry: bash -c "cd go-sdk && go mod tidy" files: ^go-sdk/ @@ -1454,7 +1520,7 @@ repos: name: Check i18n files validity description: Check i18n files are valid json and have no TODOs language: python - files: ^airflow-core/src/airflow/ui/src/i18n/locales/.*\.json + files: ^airflow-core/src/airflow/ui/public/i18n/locales/.*\.json entry: ./scripts/ci/pre_commit/check_i18n_json.py additional_dependencies: ['rich>=12.4.4'] pass_filenames: false @@ -1524,7 +1590,7 @@ repos: name: Check imports in providers entry: ./scripts/ci/pre_commit/check_imports_in_providers.py language: python - additional_dependencies: ['rich>=12.4.4', 'ruff==0.11.13'] + additional_dependencies: ['rich>=12.4.4', 'ruff==0.12.1'] files: ^providers/.*/src/airflow/providers/.*version_compat.*\.py$ require_serial: true ## ONLY ADD PRE-COMMITS HERE THAT REQUIRE CI IMAGE diff --git a/.readthedocs.yml b/.readthedocs.yml index c276d282294ca..ddc2ffd3681fe 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -20,7 +20,7 @@ formats: [] sphinx: configuration: devel-common/src/docs/rtd-deprecation/conf.py python: - version: "3.9" + version: "3.10" install: - method: pip path: . diff --git a/AGENTS.md b/AGENTS.md index c49c534016767..724896d268710 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -34,7 +34,7 @@ how to set up the environment, run checks, build docs and follow the PR workflow ## Running tests -- [`03_contributors_quick_start.rst`](contributing-docs/03_contributors_quick_start.rst) shows running tests inside Breeze. Use `pytest` inside the container for individual files or invoke `breeze testing` commands to run full suites, e.g. `breeze --backend postgres --python 3.9 testing tests --test-type All`. +- [`03_contributors_quick_start.rst`](contributing-docs/03_contributors_quick_start.rst) shows running tests inside Breeze. Use `pytest` inside the container for individual files or invoke `breeze testing` commands to run full suites, e.g. `breeze --backend postgres --python 3.10 testing tests --test-type All`. ## Building documentation diff --git a/Dockerfile b/Dockerfile index 640c44396426f..194c27645d550 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,7 +48,7 @@ ARG AIRFLOW_USER_HOME_DIR=/home/airflow # latest released version here ARG AIRFLOW_VERSION="3.0.2" -ARG PYTHON_BASE_IMAGE="python:3.9-slim-bookworm" +ARG PYTHON_BASE_IMAGE="python:3.10-slim-bookworm" # You can swap comments between those two args to test pip from the main version @@ -56,8 +56,8 @@ ARG PYTHON_BASE_IMAGE="python:3.9-slim-bookworm" # Also use `force pip` label on your PR to swap all places we use `uv` to `pip` ARG AIRFLOW_PIP_VERSION=25.1.1 # ARG AIRFLOW_PIP_VERSION="git+https://github.com/pypa/pip.git@main" -ARG AIRFLOW_SETUPTOOLS_VERSION=80.8.0 -ARG AIRFLOW_UV_VERSION=0.7.8 +ARG AIRFLOW_SETUPTOOLS_VERSION=80.9.0 +ARG AIRFLOW_UV_VERSION=0.7.17 ARG AIRFLOW_USE_UV="false" ARG UV_HTTP_TIMEOUT="300" ARG AIRFLOW_IMAGE_REPOSITORY="https://github.com/apache/airflow" @@ -673,7 +673,7 @@ if [[ $(id -u) == "0" ]]; then echo echo "${COLOR_RED}You are running pip as root. Please use 'airflow' user to run pip!${COLOR_RESET}" echo - echo "${COLOR_YELLOW}See: https://airflow.apache.org/docs/docker-stack/build.html#adding-a-new-pypi-package${COLOR_RESET}" + echo "${COLOR_YELLOW}See: https://airflow.apache.org/docs/docker-stack/build.html#adding-new-pypi-packages-individually${COLOR_RESET}" echo exit 1 fi @@ -1313,7 +1313,7 @@ function check_uid_gid() { >&2 echo " This is to make sure you can run the image with an arbitrary UID in the future." >&2 echo >&2 echo " See more about it in the Airflow's docker image documentation" - >&2 echo " http://airflow.apache.org/docs/docker-stack/entrypoint" + >&2 echo " https://airflow.apache.org/docs/docker-stack/entrypoint.html" >&2 echo # We still allow the image to run with `airflow` user. return @@ -1327,7 +1327,7 @@ function check_uid_gid() { >&2 echo " This is to make sure you can run the image with an arbitrary UID." >&2 echo >&2 echo " See more about it in the Airflow's docker image documentation" - >&2 echo " http://airflow.apache.org/docs/docker-stack/entrypoint" + >&2 echo " https://airflow.apache.org/docs/docker-stack/entrypoint.html" # This will not work so we fail hard exit 1 fi diff --git a/Dockerfile.ci b/Dockerfile.ci index 8474f24855f73..6ba138121af1a 100644 --- a/Dockerfile.ci +++ b/Dockerfile.ci @@ -16,7 +16,7 @@ # # WARNING: THIS DOCKERFILE IS NOT INTENDED FOR PRODUCTION USE OR DEPLOYMENT. # -ARG PYTHON_BASE_IMAGE="python:3.9-slim-bookworm" +ARG PYTHON_BASE_IMAGE="python:3.10-slim-bookworm" ############################################################################################## # This is the script image where we keep all inlined bash scripts needed in other segments @@ -840,7 +840,7 @@ chmod 1777 /tmp AIRFLOW_SOURCES=$(cd "${IN_CONTAINER_DIR}/../.." || exit 1; pwd) -PYTHON_MAJOR_MINOR_VERSION=${PYTHON_MAJOR_MINOR_VERSION:=3.9} +PYTHON_MAJOR_MINOR_VERSION=${PYTHON_MAJOR_MINOR_VERSION:=3.10} export AIRFLOW_HOME=${AIRFLOW_HOME:=${HOME}} @@ -848,6 +848,10 @@ mkdir "${AIRFLOW_HOME}/sqlite" -p || true ASSET_COMPILATION_WAIT_MULTIPLIER=${ASSET_COMPILATION_WAIT_MULTIPLIER:=1} +if [[ "${CI=}" == "true" ]]; then + export COLUMNS="202" +fi + . "${IN_CONTAINER_DIR}/check_connectivity.sh" function wait_for_asset_compilation() { @@ -991,13 +995,13 @@ function handle_mount_sources() { echo echo "${COLOR_BLUE}Mounted sources are removed, cleaning up mounted dist-info files${COLOR_RESET}" echo - rm -rf /usr/local/lib/python${PYTHON_MAJOR_MINOR_VERSION}/site-packages/apache_airflow*.dist-info/ + rm -rf /usr/local/lib/python"${PYTHON_MAJOR_MINOR_VERSION}"/site-packages/apache_airflow*.dist-info/ fi } function determine_airflow_to_use() { USE_AIRFLOW_VERSION="${USE_AIRFLOW_VERSION:=""}" - if [[ ${USE_AIRFLOW_VERSION} == "" && ${USE_DISTRIBUTIONS_FROM_DIST=} != "true" ]]; then + if [[ "${USE_AIRFLOW_VERSION}" == "" && "${USE_DISTRIBUTIONS_FROM_DIST}" != "true" ]]; then export PYTHONPATH=${AIRFLOW_SOURCES} echo echo "${COLOR_BLUE}Using airflow version from current sources${COLOR_RESET}" @@ -1028,7 +1032,7 @@ function determine_airflow_to_use() { # for the use in parallel runs in docker containers--no-cache is needed - otherwise there is # possibility of overriding temporary environments by multiple parallel processes uv run --no-cache /opt/airflow/scripts/in_container/install_development_dependencies.py \ - --constraint https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-${PYTHON_MAJOR_MINOR_VERSION}.txt + --constraint https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-"${PYTHON_MAJOR_MINOR_VERSION}".txt # Some packages might leave legacy typing module which causes test issues # shellcheck disable=SC2086 ${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} typing || true @@ -1063,6 +1067,19 @@ function check_boto_upgrade() { set +x } +function check_upgrade_sqlalchemy() { + if [[ "${UPGRADE_SQLALCHEMY}" != "true" ]]; then + return + fi + echo + echo "${COLOR_BLUE}Upgrading sqlalchemy to the latest version to run tests with it${COLOR_RESET}" + echo + set -x + # shellcheck disable=SC2086 + ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade "sqlalchemy[asyncio]<2.1" "databricks-sqlalchemy>=2" + set +x +} + function check_downgrade_sqlalchemy() { if [[ ${DOWNGRADE_SQLALCHEMY=} != "true" ]]; then return @@ -1196,6 +1213,7 @@ handle_mount_sources determine_airflow_to_use environment_initialization check_boto_upgrade +check_upgrade_sqlalchemy check_downgrade_sqlalchemy check_downgrade_pendulum check_force_lowest_dependencies @@ -1232,7 +1250,7 @@ ARG AIRFLOW_IMAGE_REPOSITORY="https://github.com/apache/airflow" # NOTE! When you want to make sure dependencies are installed from scratch in your PR after removing # some dependencies, you also need to set "disable image cache" in your PR to make sure the image is # not built using the "main" version of those dependencies. -ARG DEPENDENCIES_EPOCH_NUMBER="14" +ARG DEPENDENCIES_EPOCH_NUMBER="15" # Make sure noninteractive debian install is used and language variables set ENV PYTHON_BASE_IMAGE=${PYTHON_BASE_IMAGE} \ @@ -1388,8 +1406,8 @@ COPY --from=scripts common.sh install_packaging_tools.sh install_additional_depe # Also use `force pip` label on your PR to swap all places we use `uv` to `pip` ARG AIRFLOW_PIP_VERSION=25.1.1 # ARG AIRFLOW_PIP_VERSION="git+https://github.com/pypa/pip.git@main" -ARG AIRFLOW_SETUPTOOLS_VERSION=80.8.0 -ARG AIRFLOW_UV_VERSION=0.7.8 +ARG AIRFLOW_SETUPTOOLS_VERSION=80.9.0 +ARG AIRFLOW_UV_VERSION=0.7.17 # TODO(potiuk): automate with upgrade check (possibly) ARG AIRFLOW_PRE_COMMIT_VERSION="4.2.0" ARG AIRFLOW_PRE_COMMIT_UV_VERSION="4.1.4" diff --git a/INSTALL b/INSTALL index b7a6a51602623..59e596ca79350 100644 --- a/INSTALL +++ b/INSTALL @@ -229,15 +229,15 @@ to avoid "works-for-me" syndrome, where you use different versions of dependenci that are used in main CI tests and by other contributors. There are different constraint files for different Python versions. For example, this command will install -all basic devel requirements and requirements of Google provider as last successfully tested for Python 3.9: +all basic devel requirements and requirements of Google provider as last successfully tested for Python 3.10: uv pip install -e ".[devel,google]"" \ - --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-3.9.txt" + --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-3.10.txt" Using the 'constraints-no-providers' constraint files, you can upgrade Airflow without paying attention to the provider's dependencies. This allows you to keep installed provider dependencies and install the latest supported ones using pure Airflow core. uv pip install -e ".[devel]" \ - --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-no-providers-3.9.txt" + --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-no-providers-3.10.txt" Note that you can also use `pip install` if you do not use `uv`. diff --git a/INTHEWILD.md b/INTHEWILD.md index 8e98bdf1000c0..630ea6542277a 100644 --- a/INTHEWILD.md +++ b/INTHEWILD.md @@ -392,6 +392,7 @@ Currently, **officially** using Airflow: 1. [Paradigma Digital](https://www.paradigmadigital.com/) [[@paradigmadigital](https://github.com/paradigmadigital)] 1. [Paraná Banco](https://paranabanco.com.br/) [[@lopesdiego12](https://github.com/lopesdiego12/)] 1. [Pathstream](https://pathstream.com) [[@pJackDanger](https://github.com/JackDanger)] +1. [Pattern](https://pattern.com) [[@patterninc](https://github.com/patterninc)] 1. [Paxful](https://paxful.com) [[@ne1r0n](https://github.com/ne1r0n)] 1. [PayFit](https://payfit.com) [[@pcorbel](https://github.com/pcorbel)] 1. [PAYMILL](https://www.paymill.com/) [[@paymill](https://github.com/paymill) & [@matthiashuschle](https://github.com/matthiashuschle)] diff --git a/README.md b/README.md index f58b2747e0642..84dc6c4f762dd 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ When workflows are defined as code, they become more maintainable, versionable, testable, and collaborative. -Use Airflow to author workflows as directed acyclic graphs (DAGs) of tasks. The Airflow scheduler executes your tasks on an array of workers while following the specified dependencies. Rich command line utilities make performing complex surgeries on DAGs a snap. The rich user interface makes it easy to visualize pipelines running in production, monitor progress, and troubleshoot issues when needed. +Use Airflow to author workflows (Dags) that orchestrate tasks. The Airflow scheduler executes your tasks on an array of workers while following the specified dependencies. Rich command line utilities make performing complex surgeries on DAGs a snap. The rich user interface makes it easy to visualize pipelines running in production, monitor progress, and troubleshoot issues when needed. @@ -101,7 +101,7 @@ Apache Airflow is tested with: | | Main version (dev) | Stable version (3.0.2) | |------------|------------------------|------------------------| -| Python | 3.9, 3.10, 3.11, 3.12 | 3.9, 3.10, 3.11, 3.12 | +| Python | 3.10, 3.11, 3.12 | 3.9, 3.10, 3.11, 3.12 | | Platform | AMD64/ARM64(\*) | AMD64/ARM64(\*) | | Kubernetes | 1.30, 1.31, 1.32, 1.33 | 1.30, 1.31, 1.32, 1.33 | | PostgreSQL | 13, 14, 15, 16, 17 | 13, 14, 15, 16, 17 | @@ -178,14 +178,14 @@ them to the appropriate format and workflow that your tool requires. ```bash pip install 'apache-airflow==3.0.2' \ - --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.0.2/constraints-3.9.txt" + --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.0.2/constraints-3.10.txt" ``` 2. Installing with extras (i.e., postgres, google) ```bash pip install 'apache-airflow[postgres,google]==3.0.2' \ - --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.0.2/constraints-3.9.txt" + --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.0.2/constraints-3.10.txt" ``` For information on installing provider distributions, check @@ -323,7 +323,7 @@ They are based on the official release schedule of Python and Kubernetes, nicely 1. We drop support for Python and Kubernetes versions when they reach EOL. Except for Kubernetes, a version stays supported by Airflow if two major cloud providers still provide support for it. We drop support for those EOL versions in main right after EOL date, and it is effectively removed when we release - the first new MINOR (Or MAJOR if there is no new MINOR version) of Airflow. For example, for Python 3.9 it + the first new MINOR (Or MAJOR if there is no new MINOR version) of Airflow. For example, for Python 3.10 it means that we will drop support in main right after 27.06.2023, and the first MAJOR or MINOR version of Airflow released after will not have it. diff --git a/airflow-core/docs/administration-and-deployment/dag-bundles.rst b/airflow-core/docs/administration-and-deployment/dag-bundles.rst index 7dc03ebab1451..057d354b1f523 100644 --- a/airflow-core/docs/administration-and-deployment/dag-bundles.rst +++ b/airflow-core/docs/administration-and-deployment/dag-bundles.rst @@ -83,6 +83,15 @@ For example, adding multiple dag bundles to your ``airflow.cfg`` file: You can also override the :ref:`config:dag_processor__refresh_interval` per dag bundle by passing it in kwargs. This controls how often the dag processor refreshes, or looks for new files, in the dag bundles. +Starting Airflow 3.0.2 git is pre installed in the base image. However, if you are using versions prior 3.0.2, you would need to install git in your docker image. + +.. code-block:: Dockerfile + + RUN apt-get update && apt-get install -y git + ENV GIT_PYTHON_GIT_EXECUTABLE=/usr/bin/git + ENV GIT_PYTHON_REFRESH=quiet + + Writing custom dag bundles -------------------------- diff --git a/airflow-core/docs/administration-and-deployment/logging-monitoring/logging-tasks.rst b/airflow-core/docs/administration-and-deployment/logging-monitoring/logging-tasks.rst index d506082aad996..2b827fe9cebcf 100644 --- a/airflow-core/docs/administration-and-deployment/logging-monitoring/logging-tasks.rst +++ b/airflow-core/docs/administration-and-deployment/logging-monitoring/logging-tasks.rst @@ -57,7 +57,7 @@ In addition, you can supply a remote location to store current logs and backups. Writing to task logs from your code ----------------------------------- -Airflow uses standard the Python `logging `_ framework to +Airflow uses the standard Python `logging `_ framework to write logs, and for the duration of a task, the root logger is configured to write to the task's log. Most operators will write logs to the task log automatically. This is because they @@ -113,7 +113,7 @@ When displaying the logs in web UI, the display of logs will be condensed: [2024-03-08, 23:30:18 CET] {logging_mixin.py:188} ⯈ Non important details [2024-03-08, 23:30:18 CET] {logging_mixin.py:188} INFO - Here is again some standard text. -If you click on the log text label, the detailed log lies will be displayed. +If you click on the log text label, the detailed log lines will be displayed. .. code-block:: text diff --git a/airflow-core/docs/administration-and-deployment/plugins.rst b/airflow-core/docs/administration-and-deployment/plugins.rst index 8747707b4a461..c0a1b5129db59 100644 --- a/airflow-core/docs/administration-and-deployment/plugins.rst +++ b/airflow-core/docs/administration-and-deployment/plugins.rst @@ -108,8 +108,10 @@ looks like: fastapi_apps = [] # A list of dictionaries containing FastAPI middleware factory objects and some metadata. See the example below. fastapi_root_middlewares = [] - # A list of dictionaries containing iframe views and some metadata. See the example below. - iframe_views = [] + # A list of dictionaries containing external views and some metadata. See the example below. + external_views = [] + # A list of dictionaries containing react apps and some metadata. See the example below. + react_apps = [] # A callback to perform actions when Airflow starts and the plugin is loaded. # NOTE: Ensure your plugin has *args, and **kwargs in the method definition @@ -194,19 +196,48 @@ definitions in Airflow. "name": "Name of the Middleware", } - # Creating a iframe view that will be rendered in the Airflow UI. - iframe_view_with_metadata = { - "name": "Name of the Iframe View as displayed in the UI", - # Source URL of the iframe. This URL can be templated using context variables, depending on the location where the iframe is rendered - # the context variables available will be different, i.e a subset of (DAG_ID, RUN_ID, TASK_ID, MAP_INDEX) - "src": "https://example.com/{DAG_ID}/{RUN_ID}/{TASK_ID}", - # Destination of the iframe view. This is used to determine where the iframe will be loaded in the UI. - # Supported locations are Literal["nav", "dag", "dag_run", "task", "task_instance"] + # Creating an external view that will be rendered in the Airflow UI. + external_view_with_metadata = { + # Name of the external view, this will be displayed in the UI. + "name": "Name of the External View", + # Source URL of the external view. This URL can be templated using context variables, depending on the location where the external view is rendered + # the context variables available will be different, i.e a subset of (DAG_ID, RUN_ID, TASK_ID, MAP_INDEX). + "href": "https://example.com/{DAG_ID}/{RUN_ID}/{TASK_ID}/{MAP_INDEX}", + # Destination of the external view. This is used to determine where the view will be loaded in the UI. + # Supported locations are Literal["nav", "dag", "dag_run", "task", "task_instance"], default to "nav". "destination": "dag_run", # Optional icon, url to an svg file. "icon": "https://example.com/icon.svg", - # Optional parameters, relative URL location when opening the iframe - "url_route": "/my_iframe_view", + # Optional dark icon for the dark theme, url to an svg file. If not provided, "icon" will be used for both light and dark themes. + "icon_dark_mode": "https://example.com/dark_icon.svg", + # Optional parameters, relative URL location for the External View rendering. If not provided, external view will be rendeded as an external link. If provided + # will be rendered inside an Iframe in the UI. Should not contain a leading slash. + "url_route": "my_external_view", + # Optional category, only relevant for destination "nav". This is used to group the external links in the navigation bar. We will match the existing + # menus of ["browse", "docs", "admin", "user"] and if there's no match then create a new menu. + "category": "browse", + } + + react_app_with_metadata = { + # Name of the React app, this will be displayed in the UI. + "name": "Name of the React App", + # Bundle URL of the React app. This is the URL where the React app is served from. It can be a static file or a CDN. + # This URL can be templated using context variables, depending on the location where the external view is rendered + # the context variables available will be different, i.e a subset of (DAG_ID, RUN_ID, TASK_ID, MAP_INDEX). + "bundle_url": "https://example.com/static/js/my_react_app.js", + # Destination of the react app. This is used to determine where the app will be loaded in the UI. + # Supported locations are Literal["nav", "dag", "dag_run", "task", "task_instance"], default to "nav". + # It can also be put inside of an existing page, the supported views are ["dashboard", "dag_overview", "task_overview"] + "destination": "dag_run", + # Optional icon, url to an svg file. + "icon": "https://example.com/icon.svg", + # Optional dark icon for the dark theme, url to an svg file. If not provided, "icon" will be used for both light and dark themes. + "icon_dark_mode": "https://example.com/dark_icon.svg", + # URL route for the React app, relative to the Airflow UI base URL. Should not contain a leading slash. + "url_route": "my_react_app", + # Optional category, only relevant for destination "nav". This is used to group the react apps in the navigation bar. We will match the existing + # menus of ["browse", "docs", "admin", "user"] and if there's no match then create a new menu. + "category": "browse", } @@ -216,7 +247,8 @@ definitions in Airflow. macros = [plugin_macro] fastapi_apps = [app_with_metadata] fastapi_root_middlewares = [middleware_with_metadata] - iframe_views = [iframe_view_with_metadata] + external_views = [external_view_with_metadata] + react_apps = [react_app_with_metadata] .. seealso:: :doc:`/howto/define-extra-link` diff --git a/airflow-core/docs/authoring-and-scheduling/assets.rst b/airflow-core/docs/authoring-and-scheduling/assets.rst index 4664c51d7f0e8..366a4069ca52b 100644 --- a/airflow-core/docs/authoring-and-scheduling/assets.rst +++ b/airflow-core/docs/authoring-and-scheduling/assets.rst @@ -229,6 +229,18 @@ The other way around also applies: def process_example_asset(example_asset): """Process inlet example_asset...""" +In addition, ``@asset`` can be used with ``@task`` to customize the task that generates the asset, +utilizing the modern TaskFlow approach described in :doc:`/tutorial/taskflow`. + +This combination allows you to set initial arguments for the task and to use various operators, such as the ``BashOperator``: + +.. code-block:: python + + @asset(schedule=None) + @task.bash(retries=3) + def example_asset(): + """Write to example_asset, from a Bash task with 3 retries...""" + return "echo 'run'" Output to multiple assets in one task ------------------------------------- diff --git a/airflow-core/docs/extra-packages-ref.rst b/airflow-core/docs/extra-packages-ref.rst index 7a13cc39dcc08..47106fab2ed8d 100644 --- a/airflow-core/docs/extra-packages-ref.rst +++ b/airflow-core/docs/extra-packages-ref.rst @@ -164,7 +164,7 @@ with a consistent set of dependencies based on constraint files provided by Airf :substitutions: pip install apache-airflow[google,amazon,apache-spark]==|version| \ - --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.9.txt" + --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.10.txt" Note, that this will install providers in the versions that were released at the time of Airflow |version| release. You can later upgrade those providers manually if you want to use latest versions of the providers. diff --git a/airflow-core/docs/howto/connection.rst b/airflow-core/docs/howto/connection.rst index c753e1342660f..84aa1648b8224 100644 --- a/airflow-core/docs/howto/connection.rst +++ b/airflow-core/docs/howto/connection.rst @@ -115,9 +115,16 @@ If serializing with Airflow URI: See :ref:`Connection URI format ` for more details on how to generate the a valid URI. -.. note:: +Visibility in UI and CLI +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Connections defined through environment variables are **not displayed** in the Airflow UI or listed using ``airflow connections list``. + +This is because these connections are **resolved dynamically at runtime**, typically on the **worker** process executing your task. They are not stored in the metadata database or loaded in the webserver or scheduler environment. + +This supports secure deployment patterns where environment-based secrets (e.g. via ``.env`` files, Docker, or Kubernetes secrets) are injected only into runtime components like workers — and not into components exposed to users, like the webserver. - Connections defined in environment variables will not show up in the Airflow UI or using ``airflow connections list``. +If you need connections to appear in the UI for visibility or editing, define them using the metadata database instead. Storing connections in a Secrets Backend diff --git a/airflow-core/docs/howto/custom-view-plugin.rst b/airflow-core/docs/howto/custom-view-plugin.rst index 28f413b9b54a2..38111354b9f5b 100644 --- a/airflow-core/docs/howto/custom-view-plugin.rst +++ b/airflow-core/docs/howto/custom-view-plugin.rst @@ -24,7 +24,7 @@ core UI using the Plugin manager. Plugins integrate with the Airflow core RestAPI. In this plugin, three object references are derived from the base class ``airflow.plugins_manager.AirflowPlugin``. -They are fastapi_apps, fastapi_root_middlewares and iframe_views. +They are fastapi_apps, fastapi_root_middlewares, external_views and react_apps. Using fastapi_apps in Airflow plugin, the core RestAPI can be extended to support extra endpoints to serve custom static file or any other json/application responses. @@ -37,12 +37,18 @@ functionality to the entire FastAPI application, including core endpoints. In this object reference, the list of dictionaries with Middleware factories object, initialization parameters and some metadata information like the name are passed on. -Using iframe_views in Airflow plugin, allows to register custom views that are rendered in iframes in -the Airflow UI. This is useful for integrating external applications or custom dashboards into the Airflow UI. -In this object reference, the list of dictionaries with the view name, iframe src (templatable), destination and +Using external_views in Airflow plugin, allows to register custom views that are rendered in iframes or external link +in the Airflow UI. This is useful for integrating external applications or custom dashboards into the Airflow UI. +In this object reference, the list of dictionaries with the view name, href (templatable), destination and optional parameters like the icon and url_route are passed on. -Information and code samples to register ``fastapi_apps``, ``fastapi_root_middlewares`` and ``iframe_views`` are +Using react_apps in Airflow plugin, allows to register custom React applications that can be rendered +in the Airflow UI. This is useful for integrating custom React components or applications into the Airflow UI. +In this object reference, the list of dictionaries with the app name, bundle_url (where to load the js assets, templatable), destination and +optional parameters like the icon and url_route are passed on. + + +Information and code samples to register ``fastapi_apps``, ``fastapi_root_middlewares``, ``external_views`` and ``react_apps`` are available in :doc:`plugin `. Support for Airflow 2 plugins diff --git a/airflow-core/docs/howto/docker-compose/docker-compose.yaml b/airflow-core/docs/howto/docker-compose/docker-compose.yaml index 17f2e93bf144b..1c298fc518865 100644 --- a/airflow-core/docs/howto/docker-compose/docker-compose.yaml +++ b/airflow-core/docs/howto/docker-compose/docker-compose.yaml @@ -87,7 +87,7 @@ x-airflow-common: services: postgres: - image: postgres:13 + image: postgres:16 environment: POSTGRES_USER: airflow POSTGRES_PASSWORD: airflow diff --git a/airflow-core/docs/howto/docker-compose/index.rst b/airflow-core/docs/howto/docker-compose/index.rst index 0d5e2a22bb62a..68c4d00998e61 100644 --- a/airflow-core/docs/howto/docker-compose/index.rst +++ b/airflow-core/docs/howto/docker-compose/index.rst @@ -211,7 +211,7 @@ In a second terminal you can check the condition of the containers and make sure 247ebe6cf87a apache/airflow:|version| "/usr/bin/dumb-init …" 3 minutes ago Up 3 minutes (healthy) 8080/tcp compose_airflow-worker_1 ed9b09fc84b1 apache/airflow:|version| "/usr/bin/dumb-init …" 3 minutes ago Up 3 minutes (healthy) 8080/tcp compose_airflow-scheduler_1 7cb1fb603a98 apache/airflow:|version| "/usr/bin/dumb-init …" 3 minutes ago Up 3 minutes (healthy) 0.0.0.0:8080->8080/tcp compose_airflow-api_server_1 - 74f3bbe506eb postgres:13 |version-spacepad| "docker-entrypoint.s…" 18 minutes ago Up 17 minutes (healthy) 5432/tcp compose_postgres_1 + 74f3bbe506eb postgres:16 |version-spacepad| "docker-entrypoint.s…" 18 minutes ago Up 17 minutes (healthy) 5432/tcp compose_postgres_1 0bd6576d23cb redis:latest |version-spacepad| "docker-entrypoint.s…" 10 hours ago Up 17 minutes (healthy) 0.0.0.0:6379->6379/tcp compose_redis_1 Accessing the environment diff --git a/airflow-core/docs/howto/variable.rst b/airflow-core/docs/howto/variable.rst index 20c36597c94e6..a07a04a154571 100644 --- a/airflow-core/docs/howto/variable.rst +++ b/airflow-core/docs/howto/variable.rst @@ -61,10 +61,20 @@ You can use them in your dags as: Single underscores surround ``VAR``. This is in contrast with the way ``airflow.cfg`` parameters are stored, where double underscores surround the config section name. - Variables set using Environment Variables would not appear in the Airflow UI but you will - be able to use them in your DAG file. Variables set using Environment Variables will also + Variables set using Environment Variables will also take precedence over variables defined in the Airflow UI. +Visibility in UI and CLI +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Variables defined through environment variables are **not displayed** in the Airflow UI or listed using ``airflow variables list``. + +This is because these variables are **resolved dynamically at runtime**, typically on the **worker** process executing your task. They are not stored in the metadata database or loaded in the webserver or scheduler environment. + +This supports secure deployment patterns where environment-based secrets (e.g. via ``.env`` files, Docker, or Kubernetes secrets) are injected only into runtime components like workers — and not into components exposed to users, like the webserver. + +If you want variables to appear in the UI for visibility or editing, define them in the metadata database instead. + Securing Variables ------------------ diff --git a/airflow-core/docs/img/airflow_erd.sha256 b/airflow-core/docs/img/airflow_erd.sha256 index 785d9c02a0e35..9f08be06aa704 100644 --- a/airflow-core/docs/img/airflow_erd.sha256 +++ b/airflow-core/docs/img/airflow_erd.sha256 @@ -1 +1 @@ -7e97c71ee6da77d758087a5d7129ac8d63b52dcc3bf4c46b7faf5977faa53ef4 \ No newline at end of file +538840eb3b7cd14f3a9434c10c6b34442a7059ac59100c6f9d4680f7974a1b03 \ No newline at end of file diff --git a/airflow-core/docs/img/airflow_erd.svg b/airflow-core/docs/img/airflow_erd.svg index 8e9d1c7a21606..50975d8288180 100644 --- a/airflow-core/docs/img/airflow_erd.svg +++ b/airflow-core/docs/img/airflow_erd.svg @@ -692,24 +692,24 @@ dagrun_asset_event - -dagrun_asset_event - -dag_run_id - - [INTEGER] - NOT NULL - -event_id - - [INTEGER] - NOT NULL + +dagrun_asset_event + +dag_run_id + + [INTEGER] + NOT NULL + +event_id + + [INTEGER] + NOT NULL asset_event--dagrun_asset_event - -0..N + +0..N 1 @@ -1358,30 +1358,30 @@ task_instance--rendered_task_instance_fields - -0..N -1 + +0..N +1 task_instance--rendered_task_instance_fields - -0..N -1 + +0..N +1 task_instance--rendered_task_instance_fields - -0..N -1 + +0..N +1 task_instance--rendered_task_instance_fields - -0..N -1 + +0..N +1 @@ -1524,88 +1524,42 @@ {0,1} - + dag--dag_schedule_asset_alias_reference 0..N 1 - + dag--dag_schedule_asset_reference 0..N 1 - + dag--task_outlet_asset_reference 0..N 1 - + dag--task_inlet_asset_reference 0..N 1 - + dag--asset_dag_run_queue 0..N 1 - - -dag_version - -dag_version - -id - - [UUID] - NOT NULL - -bundle_name - - [VARCHAR(250)] - -bundle_version - - [VARCHAR(250)] - -created_at - - [TIMESTAMP] - NOT NULL - -dag_id - - [VARCHAR(250)] - NOT NULL - -last_updated - - [TIMESTAMP] - NOT NULL - -version_number - - [INTEGER] - NOT NULL - - - -dag--dag_version - -0..N -1 - - + dag_schedule_asset_name_reference dag_schedule_asset_name_reference @@ -1626,14 +1580,14 @@ NOT NULL - + dag--dag_schedule_asset_name_reference 0..N 1 - + dag_schedule_asset_uri_reference dag_schedule_asset_uri_reference @@ -1654,12 +1608,58 @@ NOT NULL - + dag--dag_schedule_asset_uri_reference 0..N 1 + + +dag_version + +dag_version + +id + + [UUID] + NOT NULL + +bundle_name + + [VARCHAR(250)] + +bundle_version + + [VARCHAR(250)] + +created_at + + [TIMESTAMP] + NOT NULL + +dag_id + + [VARCHAR(250)] + NOT NULL + +last_updated + + [TIMESTAMP] + NOT NULL + +version_number + + [INTEGER] + NOT NULL + + + +dag--dag_version + +0..N +1 + dag_tag @@ -1747,41 +1747,41 @@ deadline - -deadline - -id - - [UUID] - NOT NULL - -callback - - [VARCHAR(500)] - NOT NULL - -callback_kwargs - - [JSON] - -dag_id - - [VARCHAR(250)] - -dagrun_id - - [INTEGER] - -deadline_time - - [TIMESTAMP] - NOT NULL + +deadline + +id + + [UUID] + NOT NULL + +callback + + [VARCHAR(500)] + NOT NULL + +callback_kwargs + + [JSON] + +dag_id + + [VARCHAR(250)] + +dagrun_id + + [INTEGER] + +deadline_time + + [TIMESTAMP] + NOT NULL dag--deadline - -0..N + +0..N {0,1} @@ -2018,71 +2018,71 @@ dag_run--dagrun_asset_event - -0..N -1 + +0..N +1 - + dag_run--task_instance 0..N 1 - + dag_run--task_instance 0..N 1 - + dag_run--deadline - -0..N -{0,1} + +0..N +{0,1} backfill_dag_run - -backfill_dag_run - -id - - [INTEGER] - NOT NULL - -backfill_id - - [INTEGER] - NOT NULL - -dag_run_id - - [INTEGER] - -exception_reason - - [VARCHAR(250)] - -logical_date - - [TIMESTAMP] - NOT NULL - -sort_ordinal - - [INTEGER] - NOT NULL + +backfill_dag_run + +id + + [INTEGER] + NOT NULL + +backfill_id + + [INTEGER] + NOT NULL + +dag_run_id + + [INTEGER] + +exception_reason + + [VARCHAR(250)] + +logical_date + + [TIMESTAMP] + NOT NULL + +sort_ordinal + + [INTEGER] + NOT NULL - + dag_run--backfill_dag_run - -0..N -{0,1} + +0..N +{0,1} @@ -2114,7 +2114,7 @@ [VARCHAR(128)] - + dag_run--dag_run_note 1 @@ -2222,9 +2222,9 @@ backfill--backfill_dag_run - -0..N -1 + +0..N +1 diff --git a/airflow-core/docs/img/diagram_auth_manager_airflow_architecture.md5sum b/airflow-core/docs/img/diagram_auth_manager_airflow_architecture.md5sum index ac3e24d8483b8..d108e6b94b972 100644 --- a/airflow-core/docs/img/diagram_auth_manager_airflow_architecture.md5sum +++ b/airflow-core/docs/img/diagram_auth_manager_airflow_architecture.md5sum @@ -1 +1 @@ -5b82cba489898a46dcfe5f458eeee33b +cdcfa104c489e0e679894e344084c061 diff --git a/airflow-core/docs/img/diagram_auth_manager_airflow_architecture.png b/airflow-core/docs/img/diagram_auth_manager_airflow_architecture.png index 35f3f418f2df4..2a677c0dc9b24 100644 Binary files a/airflow-core/docs/img/diagram_auth_manager_airflow_architecture.png and b/airflow-core/docs/img/diagram_auth_manager_airflow_architecture.png differ diff --git a/airflow-core/docs/img/diagram_auth_manager_airflow_architecture.py b/airflow-core/docs/img/diagram_auth_manager_airflow_architecture.py index 453d17267c8c6..b38c633cfde86 100644 --- a/airflow-core/docs/img/diagram_auth_manager_airflow_architecture.py +++ b/airflow-core/docs/img/diagram_auth_manager_airflow_architecture.py @@ -14,6 +14,13 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "rich>=12.4.4", +# "diagrams>=0.23.4", +# ] +# /// from __future__ import annotations from pathlib import Path @@ -25,7 +32,13 @@ MY_DIR = Path(__file__).parent MY_FILENAME = Path(__file__).with_suffix("").name -PYTHON_MULTIPROCESS_LOGO = MY_DIR.parents[1] / "diagrams" / "python_multiprocess_logo.png" +AIRFLOW_SOURCES_ROOT = MY_DIR.parents[2] +DIAGRAMS_DIR = AIRFLOW_SOURCES_ROOT / "devel-common" / "src" / "docs" / "diagrams" +PYTHON_MULTIPROCESS_LOGO = DIAGRAMS_DIR / "python_multiprocess_logo.png" +PACKAGES_IMAGE = DIAGRAMS_DIR / "packages.png" +DATABASE_IMAGE = DIAGRAMS_DIR / "database.png" +MULTIPLE_FILES_IMAGE = DIAGRAMS_DIR / "multiple_files.png" +CONFIG_FILE = DIAGRAMS_DIR / "config_file.png" console = Console(width=400, color_system="standard") diff --git a/airflow-core/docs/img/diagram_basic_airflow_architecture.md5sum b/airflow-core/docs/img/diagram_basic_airflow_architecture.md5sum index 810a76ed84d78..c0165abb926c3 100644 --- a/airflow-core/docs/img/diagram_basic_airflow_architecture.md5sum +++ b/airflow-core/docs/img/diagram_basic_airflow_architecture.md5sum @@ -1 +1 @@ -cc2aca72cb388d28842e539f599d373c +02bb21a66db61c0ea72aae788d1cd7da diff --git a/airflow-core/docs/img/diagram_basic_airflow_architecture.png b/airflow-core/docs/img/diagram_basic_airflow_architecture.png index 94a0590419f33..b027745363ca0 100644 Binary files a/airflow-core/docs/img/diagram_basic_airflow_architecture.png and b/airflow-core/docs/img/diagram_basic_airflow_architecture.png differ diff --git a/airflow-core/docs/img/diagram_basic_airflow_architecture.py b/airflow-core/docs/img/diagram_basic_airflow_architecture.py index 7d77cb321eee8..6f34fe19e02f5 100644 --- a/airflow-core/docs/img/diagram_basic_airflow_architecture.py +++ b/airflow-core/docs/img/diagram_basic_airflow_architecture.py @@ -14,6 +14,13 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "rich>=12.4.4", +# "diagrams>=0.23.4", +# ] +# /// from __future__ import annotations from pathlib import Path @@ -26,9 +33,13 @@ MY_DIR = Path(__file__).parent MY_FILENAME = Path(__file__).with_suffix("").name -PACKAGES_IMAGE = MY_DIR.parents[1] / "diagrams" / "packages.png" -DATABASE_IMAGE = MY_DIR.parents[1] / "diagrams" / "database.png" -MULTIPLE_FILES_IMAGE = MY_DIR.parents[1] / "diagrams" / "multiple_files.png" +AIRFLOW_SOURCES_ROOT = MY_DIR.parents[2] +DIAGRAMS_DIR = AIRFLOW_SOURCES_ROOT / "devel-common" / "src" / "docs" / "diagrams" +PYTHON_MULTIPROCESS_LOGO = DIAGRAMS_DIR / "python_multiprocess_logo.png" +PACKAGES_IMAGE = DIAGRAMS_DIR / "packages.png" +DATABASE_IMAGE = DIAGRAMS_DIR / "database.png" +MULTIPLE_FILES_IMAGE = DIAGRAMS_DIR / "multiple_files.png" +CONFIG_FILE = DIAGRAMS_DIR / "config_file.png" console = Console(width=400, color_system="standard") diff --git a/airflow-core/docs/img/diagram_dag_processor_airflow_architecture.md5sum b/airflow-core/docs/img/diagram_dag_processor_airflow_architecture.md5sum index 9b9ffcdc2a980..f14acf5c6c246 100644 --- a/airflow-core/docs/img/diagram_dag_processor_airflow_architecture.md5sum +++ b/airflow-core/docs/img/diagram_dag_processor_airflow_architecture.md5sum @@ -1 +1 @@ -00f67a1e0cd073ba521da168dc80ccaa +c5e05dafe7b9a39325835fd3a2b47d4d diff --git a/airflow-core/docs/img/diagram_dag_processor_airflow_architecture.png b/airflow-core/docs/img/diagram_dag_processor_airflow_architecture.png index 9d8773877835a..a13bc92586fc7 100644 Binary files a/airflow-core/docs/img/diagram_dag_processor_airflow_architecture.png and b/airflow-core/docs/img/diagram_dag_processor_airflow_architecture.png differ diff --git a/airflow-core/docs/img/diagram_dag_processor_airflow_architecture.py b/airflow-core/docs/img/diagram_dag_processor_airflow_architecture.py index 9a33c5af05a49..99091215128c9 100644 --- a/airflow-core/docs/img/diagram_dag_processor_airflow_architecture.py +++ b/airflow-core/docs/img/diagram_dag_processor_airflow_architecture.py @@ -14,6 +14,13 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "rich>=12.4.4", +# "diagrams>=0.23.4", +# ] +# /// from __future__ import annotations from pathlib import Path @@ -25,10 +32,13 @@ MY_DIR = Path(__file__).parent MY_FILENAME = Path(__file__).with_suffix("").name -PYTHON_MULTIPROCESS_LOGO = MY_DIR.parents[1] / "diagrams" / "python_multiprocess_logo.png" -PACKAGES_IMAGE = MY_DIR.parents[1] / "diagrams" / "packages.png" -DATABASE_IMAGE = MY_DIR.parents[1] / "diagrams" / "database.png" -MULTIPLE_FILES_IMAGE = MY_DIR.parents[1] / "diagrams" / "multiple_files.png" +AIRFLOW_SOURCES_ROOT = MY_DIR.parents[2] +DIAGRAMS_DIR = AIRFLOW_SOURCES_ROOT / "devel-common" / "src" / "docs" / "diagrams" +PYTHON_MULTIPROCESS_LOGO = DIAGRAMS_DIR / "python_multiprocess_logo.png" +PACKAGES_IMAGE = DIAGRAMS_DIR / "packages.png" +DATABASE_IMAGE = DIAGRAMS_DIR / "database.png" +MULTIPLE_FILES_IMAGE = DIAGRAMS_DIR / "multiple_files.png" +CONFIG_FILE = DIAGRAMS_DIR / "config_file.png" console = Console(width=400, color_system="standard") diff --git a/airflow-core/docs/img/diagram_distributed_airflow_architecture.md5sum b/airflow-core/docs/img/diagram_distributed_airflow_architecture.md5sum index f0df07cedd4b0..436ccc21c2c59 100644 --- a/airflow-core/docs/img/diagram_distributed_airflow_architecture.md5sum +++ b/airflow-core/docs/img/diagram_distributed_airflow_architecture.md5sum @@ -1 +1 @@ -887125381a232d742ab059c2049f3176 +c9291864de06bc4b09f3a0ed89609572 diff --git a/airflow-core/docs/img/diagram_distributed_airflow_architecture.png b/airflow-core/docs/img/diagram_distributed_airflow_architecture.png index b1b46d3d3c7cd..388d98138e226 100644 Binary files a/airflow-core/docs/img/diagram_distributed_airflow_architecture.png and b/airflow-core/docs/img/diagram_distributed_airflow_architecture.png differ diff --git a/airflow-core/docs/img/diagram_distributed_airflow_architecture.py b/airflow-core/docs/img/diagram_distributed_airflow_architecture.py index 831a9783a85e0..37521141462b2 100644 --- a/airflow-core/docs/img/diagram_distributed_airflow_architecture.py +++ b/airflow-core/docs/img/diagram_distributed_airflow_architecture.py @@ -14,6 +14,13 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "rich>=12.4.4", +# "diagrams>=0.23.4", +# ] +# /// from __future__ import annotations from pathlib import Path @@ -25,10 +32,13 @@ MY_DIR = Path(__file__).parent MY_FILENAME = Path(__file__).with_suffix("").name -PYTHON_MULTIPROCESS_LOGO = MY_DIR.parents[1] / "diagrams" / "python_multiprocess_logo.png" -PACKAGES_IMAGE = MY_DIR.parents[1] / "diagrams" / "packages.png" -DATABASE_IMAGE = MY_DIR.parents[1] / "diagrams" / "database.png" -MULTIPLE_FILES_IMAGE = MY_DIR.parents[1] / "diagrams" / "multiple_files.png" +AIRFLOW_SOURCES_ROOT = MY_DIR.parents[2] +DIAGRAMS_DIR = AIRFLOW_SOURCES_ROOT / "devel-common" / "src" / "docs" / "diagrams" +PYTHON_MULTIPROCESS_LOGO = DIAGRAMS_DIR / "python_multiprocess_logo.png" +PACKAGES_IMAGE = DIAGRAMS_DIR / "packages.png" +DATABASE_IMAGE = DIAGRAMS_DIR / "database.png" +MULTIPLE_FILES_IMAGE = DIAGRAMS_DIR / "multiple_files.png" +CONFIG_FILE = DIAGRAMS_DIR / "config_file.png" console = Console(width=400, color_system="standard") diff --git a/airflow-core/docs/img/diagram_multi_team_airflow_architecture.md5sum b/airflow-core/docs/img/diagram_multi_team_airflow_architecture.md5sum index 824f07b0e0157..b10d471780b21 100644 --- a/airflow-core/docs/img/diagram_multi_team_airflow_architecture.md5sum +++ b/airflow-core/docs/img/diagram_multi_team_airflow_architecture.md5sum @@ -1 +1 @@ -c50412b8cf43b84752d4acbf9d7a40ee +22f0feed88ad6a955d5bebba08469bf9 diff --git a/airflow-core/docs/img/diagram_multi_team_airflow_architecture.png b/airflow-core/docs/img/diagram_multi_team_airflow_architecture.png index 75ff970e95f12..2ce11092f59ec 100644 Binary files a/airflow-core/docs/img/diagram_multi_team_airflow_architecture.png and b/airflow-core/docs/img/diagram_multi_team_airflow_architecture.png differ diff --git a/airflow-core/docs/img/diagram_multi_team_airflow_architecture.py b/airflow-core/docs/img/diagram_multi_team_airflow_architecture.py index 43e2e62c0604f..ed25e5efbf4e1 100644 --- a/airflow-core/docs/img/diagram_multi_team_airflow_architecture.py +++ b/airflow-core/docs/img/diagram_multi_team_airflow_architecture.py @@ -14,6 +14,13 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "rich>=12.4.4", +# "diagrams>=0.23.4", +# ] +# /// from __future__ import annotations from pathlib import Path @@ -26,11 +33,13 @@ MY_DIR = Path(__file__).parent MY_FILENAME = Path(__file__).with_suffix("").name -PYTHON_MULTIPROCESS_LOGO = MY_DIR.parents[1] / "diagrams" / "python_multiprocess_logo.png" -PACKAGES_IMAGE = MY_DIR.parents[1] / "diagrams" / "packages.png" -DATABASE_IMAGE = MY_DIR.parents[1] / "diagrams" / "database.png" -MULTIPLE_FILES_IMAGE = MY_DIR.parents[1] / "diagrams" / "multiple_files.png" -CONFIG_FILE = MY_DIR.parents[1] / "diagrams" / "config_file.png" +AIRFLOW_SOURCES_ROOT = MY_DIR.parents[2] +DIAGRAMS_DIR = AIRFLOW_SOURCES_ROOT / "devel-common" / "src" / "docs" / "diagrams" +PYTHON_MULTIPROCESS_LOGO = DIAGRAMS_DIR / "python_multiprocess_logo.png" +PACKAGES_IMAGE = DIAGRAMS_DIR / "packages.png" +DATABASE_IMAGE = DIAGRAMS_DIR / "database.png" +MULTIPLE_FILES_IMAGE = DIAGRAMS_DIR / "multiple_files.png" +CONFIG_FILE = DIAGRAMS_DIR / "config_file.png" console = Console(width=400, color_system="standard") @@ -77,8 +86,6 @@ def generate_dag_processor_airflow_diagram(): "Common\nOrganization\nPlugins &\nPackages", PACKAGES_IMAGE.as_posix() ) - organization_config_file = Custom("Config\nFile\nCommon\nOrganization", CONFIG_FILE.as_posix()) - internal_api = Custom("Task SDK\nGRPC API", PYTHON_MULTIPROCESS_LOGO.as_posix()) ( internal_api @@ -104,7 +111,7 @@ def generate_dag_processor_airflow_diagram(): ) deployment_manager_1 = User("Deployment\nManager\nTeam 1") - dag_author_1 = User("DAG Author\nTeamt 1") + dag_author_1 = User("DAG Author\nTeam 1") with Cluster("Team 1 Airflow Deployment", graph_attr={"bgcolor": "#AAAABB", "fontsize": "22"}): with Cluster("No DB access"): @@ -113,9 +120,8 @@ def generate_dag_processor_airflow_diagram(): triggerer_1 = Custom("Triggerer(s)", PYTHON_MULTIPROCESS_LOGO.as_posix()) with Cluster("Parsing"): dag_processors_1 = Custom("DAG\nProcessor(s)", PYTHON_MULTIPROCESS_LOGO.as_posix()) - dag_files_1 = Custom("DAGS/Team 1", MULTIPLE_FILES_IMAGE.as_posix()) + dag_files_1 = Custom("DAG Bundles\nTeam 1", MULTIPLE_FILES_IMAGE.as_posix()) plugins_and_packages_1 = Custom("Plugins\n& Packages\nTenant 1", PACKAGES_IMAGE.as_posix()) - config_file_1 = Custom("Config\nFile\nTeam 1", CONFIG_FILE.as_posix()) operations_user_1 = User("Operations User\nTeam 1") deployment_manager_2 = User("Deployment\nManager\nTeam 2") @@ -128,9 +134,8 @@ def generate_dag_processor_airflow_diagram(): triggerer_2 = Custom("Triggerer(s)", PYTHON_MULTIPROCESS_LOGO.as_posix()) with Cluster("Parsing"): dag_processors_2 = Custom("DAG\nProcessor(s)", PYTHON_MULTIPROCESS_LOGO.as_posix()) - dag_files_2 = Custom("DAGS/Team 2", MULTIPLE_FILES_IMAGE.as_posix()) + dag_files_2 = Custom("DAG Bundles\nTeam 2", MULTIPLE_FILES_IMAGE.as_posix()) plugins_and_packages_2 = Custom("Plugins\n& Packages\nTeam 2", PACKAGES_IMAGE.as_posix()) - config_file_2 = Custom("Config\nFile\nTeam 2", CONFIG_FILE.as_posix()) operations_user_2 = User("Operations User\nTeam 2") ( @@ -154,12 +159,6 @@ def generate_dag_processor_airflow_diagram(): >> plugins_and_packages_1 ) - ( - deployment_manager_1 - >> Edge(color="blue", style="dashed", reverse=False, label="configure\n\n") - >> config_file_1 - ) - dag_author_2 >> Edge(color="brown", style="dashed", reverse=False, label="author\n\n") >> dag_files_2 ( deployment_manager_2 @@ -167,24 +166,12 @@ def generate_dag_processor_airflow_diagram(): >> plugins_and_packages_2 ) - ( - deployment_manager_2 - >> Edge(color="blue", style="solid", reverse=False, label="configure\n\n") - >> config_file_2 - ) - ( organization_plugins_and_packages - Edge(color="blue", style="solid", reverse=True, label="install\n\n") - organization_deployment_manager ) - ( - organization_config_file - - Edge(color="blue", style="solid", reverse=True, label="configure\n\n") - - organization_deployment_manager - ) - plugins_and_packages_1 >> Edge(style="invis") >> workers_1 plugins_and_packages_1 >> Edge(style="invis") >> dag_processors_1 plugins_and_packages_1 >> Edge(style="invis") >> triggerer_1 @@ -237,7 +224,6 @@ def generate_dag_processor_airflow_diagram(): dag_files_2 >> Edge(color="brown", style="solid", label="sync\n\n") >> triggerer_2 # This is for better layout. Invisible edges are used to align the nodes better - schedulers - Edge(style="invis") - organization_config_file schedulers - Edge(style="invis") - organization_plugins_and_packages metadata_db - Edge(style="invis") - executor_1 metadata_db - Edge(style="invis") - executor_2 diff --git a/airflow-core/docs/img/diagram_task_lifecycle.md5sum b/airflow-core/docs/img/diagram_task_lifecycle.md5sum index 5b00beaa9d888..a19ff4c1e4d6d 100644 --- a/airflow-core/docs/img/diagram_task_lifecycle.md5sum +++ b/airflow-core/docs/img/diagram_task_lifecycle.md5sum @@ -1 +1 @@ -ef689d2a19fcef658dca32076bb0bfd4 +2f0f0308c52315026f2ac50939247857 diff --git a/airflow-core/docs/img/diagram_task_lifecycle.png b/airflow-core/docs/img/diagram_task_lifecycle.png index 6f5f4e25a3026..837a9a7a06692 100644 Binary files a/airflow-core/docs/img/diagram_task_lifecycle.png and b/airflow-core/docs/img/diagram_task_lifecycle.png differ diff --git a/airflow-core/docs/img/diagram_task_lifecycle.py b/airflow-core/docs/img/diagram_task_lifecycle.py index 969a4fee324ec..3dc66c1635c35 100644 --- a/airflow-core/docs/img/diagram_task_lifecycle.py +++ b/airflow-core/docs/img/diagram_task_lifecycle.py @@ -14,6 +14,13 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "rich>=12.4.4", +# "diagrams>=0.23.4", +# ] +# /// from __future__ import annotations from pathlib import Path @@ -25,12 +32,21 @@ MY_DIR = Path(__file__).parent MY_FILENAME = Path(__file__).with_suffix("").name -COMPONENT_IMG = (MY_DIR.parents[1] / "diagrams" / "task_lifecycle" / "component.png").as_posix() -CONDITION_IMG = (MY_DIR.parents[1] / "diagrams" / "task_lifecycle" / "condition.png").as_posix() -SHARED_STATE_IMG = (MY_DIR.parents[1] / "diagrams" / "task_lifecycle" / "shared_state.png").as_posix() -TERMINAL_STATE_IMG = (MY_DIR.parents[1] / "diagrams" / "task_lifecycle" / "terminal_state.png").as_posix() -SENSOR_STATE_IMG = (MY_DIR.parents[1] / "diagrams" / "task_lifecycle" / "sensor_state.png").as_posix() -DEFERRABLE_STATE_IMG = (MY_DIR.parents[1] / "diagrams" / "task_lifecycle" / "deferrable_state.png").as_posix() +MY_DIR = Path(__file__).parent +MY_FILENAME = Path(__file__).with_suffix("").name +AIRFLOW_SOURCES_ROOT = MY_DIR.parents[2] +DIAGRAMS_DIR = AIRFLOW_SOURCES_ROOT / "devel-common" / "src" / "docs" / "diagrams" +PYTHON_MULTIPROCESS_LOGO = DIAGRAMS_DIR / "python_multiprocess_logo.png" +PACKAGES_IMAGE = DIAGRAMS_DIR / "packages.png" +DATABASE_IMAGE = DIAGRAMS_DIR / "database.png" +MULTIPLE_FILES_IMAGE = DIAGRAMS_DIR / "multiple_files.png" +CONFIG_FILE = DIAGRAMS_DIR / "config_file.png" +COMPONENT_IMG = (DIAGRAMS_DIR / "task_lifecycle" / "component.png").as_posix() +CONDITION_IMG = (DIAGRAMS_DIR / "task_lifecycle" / "condition.png").as_posix() +SHARED_STATE_IMG = (DIAGRAMS_DIR / "task_lifecycle" / "shared_state.png").as_posix() +TERMINAL_STATE_IMG = (DIAGRAMS_DIR / "task_lifecycle" / "terminal_state.png").as_posix() +SENSOR_STATE_IMG = (DIAGRAMS_DIR / "task_lifecycle" / "sensor_state.png").as_posix() +DEFERRABLE_STATE_IMG = (DIAGRAMS_DIR / "task_lifecycle" / "deferrable_state.png").as_posix() STATE_NODE_ATTRS = {"width": "4.16", "height": "1", "fontname": "Monospace", "fontsize": "20"} COMPONENT_NODE_ATTRS = { diff --git a/airflow-core/docs/installation/installing-from-pypi.rst b/airflow-core/docs/installation/installing-from-pypi.rst index 1a70723842a60..63bcee23e3244 100644 --- a/airflow-core/docs/installation/installing-from-pypi.rst +++ b/airflow-core/docs/installation/installing-from-pypi.rst @@ -40,7 +40,7 @@ Typical command to install Airflow from scratch in a reproducible way from PyPI .. code-block:: bash - pip install "apache-airflow[celery]==|version|" --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.9.txt" + pip install "apache-airflow[celery]==|version|" --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.10.txt" Typically, you can add other dependencies and providers as separate command after the reproducible @@ -105,14 +105,14 @@ You can create the URL to the file substituting the variables in the template be where: - ``AIRFLOW_VERSION`` - Airflow version (e.g. :subst-code:`|version|`) or ``main``, ``2-0``, for latest development version -- ``PYTHON_VERSION`` Python version e.g. ``3.9``, ``3.10`` +- ``PYTHON_VERSION`` Python version e.g. ``3.10``, ``3.11`` The examples below assume that you want to use install Airflow in a reproducible way with the ``celery`` extra, but you can pick your own set of extras and providers to install. .. code-block:: bash - pip install "apache-airflow[celery]==|version|" --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.9.txt" + pip install "apache-airflow[celery]==|version|" --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.10.txt" .. note:: @@ -143,7 +143,7 @@ performing dependency resolution. .. code-block:: bash - pip install "apache-airflow[celery]==|version|" --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.9.txt" + pip install "apache-airflow[celery]==|version|" --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.10.txt" pip install "apache-airflow==|version|" apache-airflow-providers-google==10.1.1 You can also downgrade or upgrade other dependencies this way - even if they are not compatible with @@ -151,7 +151,7 @@ those dependencies that are stored in the original constraints file: .. code-block:: bash - pip install "apache-airflow[celery]==|version|" --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.9.txt" + pip install "apache-airflow[celery]==|version|" --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.10.txt" pip install "apache-airflow[celery]==|version|" dbt-core==0.20.0 .. warning:: @@ -194,7 +194,7 @@ one provided by the community. .. code-block:: bash - pip install "apache-airflow[celery]==|version|" --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.9.txt" + pip install "apache-airflow[celery]==|version|" --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.10.txt" pip install "apache-airflow==|version|" dbt-core==0.20.0 pip freeze > my-constraints.txt @@ -321,9 +321,9 @@ dependencies compatible with just Airflow core at the moment Airflow was release AIRFLOW_VERSION=|version| PYTHON_VERSION="$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')" - # For example: 3.9 + # For example: 3.10 CONSTRAINT_URL="https://raw.githubusercontent.com/apache/airflow/constraints-${AIRFLOW_VERSION}/constraints-no-providers-${PYTHON_VERSION}.txt" - # For example: https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-no-providers-3.9.txt + # For example: https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-no-providers-3.10.txt pip install "apache-airflow==${AIRFLOW_VERSION}" --constraint "${CONSTRAINT_URL}" Troubleshooting @@ -347,7 +347,7 @@ Symbol not found: ``_Py_GetArgcArgv`` ===================================== If you see ``Symbol not found: _Py_GetArgcArgv`` while starting or importing ``airflow``, this may mean that you are using an incompatible version of Python. -For a homebrew installed version of Python, this is generally caused by using Python in ``/usr/local/opt/bin`` rather than the Frameworks installation (e.g. for ``python 3.9``: ``/usr/local/opt/python@3.9/Frameworks/Python.framework/Versions/3.9``). +For a homebrew installed version of Python, this is generally caused by using Python in ``/usr/local/opt/bin`` rather than the Frameworks installation (e.g. for ``python 3.10``: ``/usr/local/opt/python@3.10/Frameworks/Python.framework/Versions/3.10``). The crux of the issue is that a library Airflow depends on, ``setproctitle``, uses a non-public Python API which is not available from the standard installation ``/usr/local/opt/`` (which symlinks to a path under ``/usr/local/Cellar``). @@ -356,9 +356,9 @@ An easy fix is just to ensure you use a version of Python that has a dylib of th .. code-block:: bash - # Note: these instructions are for python3.9 but can be loosely modified for other versions - brew install python@3.9 - virtualenv -p /usr/local/opt/python@3.9/Frameworks/Python.framework/Versions/3.9/bin/python3 .toy-venv + # Note: these instructions are for python3.10 but can be loosely modified for other versions + brew install python@3.10 + virtualenv -p /usr/local/opt/python@3.10/Frameworks/Python.framework/Versions/3.10/bin/python3 .toy-venv source .toy-venv/bin/activate pip install apache-airflow python diff --git a/airflow-core/docs/installation/prerequisites.rst b/airflow-core/docs/installation/prerequisites.rst index 323af74f8e515..6859918d9c65c 100644 --- a/airflow-core/docs/installation/prerequisites.rst +++ b/airflow-core/docs/installation/prerequisites.rst @@ -20,7 +20,7 @@ Prerequisites Airflow® is tested with: -* Python: 3.9, 3.10, 3.11, 3.12 +* Python: 3.10, 3.11, 3.12 * Databases: diff --git a/airflow-core/docs/start.rst b/airflow-core/docs/start.rst index d0d0f1dd5f782..e992e94ac8f95 100644 --- a/airflow-core/docs/start.rst +++ b/airflow-core/docs/start.rst @@ -24,11 +24,11 @@ This quick start guide will help you bootstrap an Airflow standalone instance on .. note:: - Successful installation requires a Python 3 environment. Starting with Airflow 2.7.0, Airflow supports Python 3.9, 3.10, 3.11, and 3.12. + Successful installation requires a Python 3 environment. Starting with Airflow 3.1.0, Airflow supports Python 3.10, 3.11, and 3.12. Officially supported installation methods is with``pip`. - Run ``pip install apache-airflow[EXTRAS]==AIRFLOW_VERSION --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-AIRFLOW_VERSION/constraints-PYTHON_VERSION.txt"``, for example ``pip install "apache-airflow[celery]==3.0.0" --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.0.0/constraints-3.9.txt"`` to install Airflow in a reproducible way. + Run ``pip install apache-airflow[EXTRAS]==AIRFLOW_VERSION --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-AIRFLOW_VERSION/constraints-PYTHON_VERSION.txt"``, for example ``pip install "apache-airflow[celery]==3.0.0" --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-3.0.0/constraints-3.10.txt"`` to install Airflow in a reproducible way. @@ -75,7 +75,7 @@ This quick start guide will help you bootstrap an Airflow standalone instance on PYTHON_VERSION="$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')" CONSTRAINT_URL="https://raw.githubusercontent.com/apache/airflow/constraints-${AIRFLOW_VERSION}/constraints-${PYTHON_VERSION}.txt" - # For example this would install 3.0.0 with python 3.9: https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.9.txt + # For example this would install 3.0.0 with python 3.10: https://raw.githubusercontent.com/apache/airflow/constraints-|version|/constraints-3.10.txt uv pip install "apache-airflow==${AIRFLOW_VERSION}" --constraint "${CONSTRAINT_URL}" diff --git a/airflow-core/hatch_build.py b/airflow-core/hatch_build.py index 438767bcd9d5d..d691e6c25cd1d 100644 --- a/airflow-core/hatch_build.py +++ b/airflow-core/hatch_build.py @@ -19,10 +19,10 @@ import logging import os import shutil -from collections.abc import Iterable +from collections.abc import Callable, Iterable from pathlib import Path from subprocess import run -from typing import Any, Callable +from typing import Any from hatchling.builders.config import BuilderConfig from hatchling.builders.plugin.interface import BuilderInterface diff --git a/airflow-core/pyproject.toml b/airflow-core/pyproject.toml index 06e8f32bec991..d5d03e4021c02 100644 --- a/airflow-core/pyproject.toml +++ b/airflow-core/pyproject.toml @@ -35,7 +35,7 @@ name = "apache-airflow-core" description = "Core packages for Apache Airflow, schedule and API server" readme = { file = "README.md", content-type = "text/markdown" } license-files.globs = ["LICENSE", "3rd-party-licenses/*.txt", "NOTICE"] -requires-python = "~=3.9,<3.13" +requires-python = "~=3.10,<3.13" authors = [ { name = "Apache Software Foundation", email = "dev@airflow.apache.org" }, ] @@ -51,7 +51,6 @@ classifiers = [ "Intended Audience :: Developers", "Intended Audience :: System Administrators", "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -78,9 +77,6 @@ dependencies = [ "cryptography>=41.0.0", "deprecated>=1.2.13", "dill>=0.2.2", - # Required for python 3.9 to work with new annotations styles. Check package - # description on PyPI for more details: https://pypi.org/project/eval-type-backport/ - 'eval-type-backport>=0.2.0;python_version<"3.10"', # 0.115.10 fastapi was a bad release that broke our API's and static checks. # Related fastapi issue here: https://github.com/fastapi/fastapi/discussions/13431 "fastapi[standard]>=0.115.0,!=0.115.10", @@ -95,8 +91,7 @@ dependencies = [ "jinja2>=3.1.5", "jsonschema>=4.19.1", "lazy-object-proxy>=1.2.0", - 'libcst >=1.1.0,!=1.8.1;python_version<"3.10"', - 'libcst >=1.1.0;python_version>="3.10"', + 'libcst >=1.1.0', "linkify-it-py>=2.0.0", "lockfile>=0.12.2", "methodtools>=0.4.7", diff --git a/airflow-core/src/airflow/api_fastapi/app.py b/airflow-core/src/airflow/api_fastapi/app.py index 2d2afef0f2609..36b59630d0b65 100644 --- a/airflow-core/src/airflow/api_fastapi/app.py +++ b/airflow-core/src/airflow/api_fastapi/app.py @@ -170,7 +170,6 @@ def init_plugins(app: FastAPI) -> None: """Integrate FastAPI app, middlewares and UI plugins.""" from airflow import plugins_manager - plugins_manager.initialize_fastapi_plugins() plugins_manager.initialize_fastapi_plugins() # After calling initialize_fastapi_plugins, fastapi_apps cannot be None anymore. diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/package-lock.json b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/package-lock.json index 34694dc89ee12..b6ad85164832c 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/package-lock.json +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/package-lock.json @@ -8,43 +8,43 @@ "name": "simple-auth-manager-ui", "version": "0.0.0", "dependencies": { - "@chakra-ui/react": "^3.20.0", - "@tanstack/react-query": "^5.80.6", - "axios": "^1.9.0", + "@chakra-ui/react": "^3.21.0", + "@tanstack/react-query": "^5.81.2", + "axios": "^1.10.0", "next-themes": "^0.4.6", "react": "^19.1.0", "react-cookie": "^8.0.1", "react-dom": "^19.1.0", - "react-hook-form": "^7.57.0", + "react-hook-form": "^7.58.1", "react-router-dom": "^7.6.2" }, "devDependencies": { "@7nohe/openapi-react-query-codegen": "^1.6.2", - "@eslint/compat": "^1.2.9", - "@eslint/js": "^9.28.0", - "@stylistic/eslint-plugin": "^4.4.1", + "@eslint/compat": "^1.3.0", + "@eslint/js": "^9.29.0", + "@stylistic/eslint-plugin": "^5.0.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@trivago/prettier-plugin-sort-imports": "^5.2.2", - "@types/react": "^19.1.7", + "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", "@vitejs/plugin-react-swc": "^3.10.2", - "eslint": "^9.28.0", + "eslint": "^9.29.0", "eslint-config-prettier": "^10.1.5", "eslint-plugin-jsx-a11y": "^6.10.2", - "eslint-plugin-perfectionist": "^4.14.0", - "eslint-plugin-prettier": "^5.4.1", + "eslint-plugin-perfectionist": "^4.15.0", + "eslint-plugin-prettier": "^5.5.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-unicorn": "^59.0.1", - "happy-dom": "^17.6.3", - "prettier": "^3.5.3", + "happy-dom": "^18.0.1", + "prettier": "^3.6.0", "typescript": "~5.8.3", - "typescript-eslint": "^8.34.0", - "vite": "^6.3.5", + "typescript-eslint": "^8.35.0", + "vite": "^7.0.0", "vite-plugin-css-injected-by-js": "^3.5.2", - "vitest": "^3.2.3" + "vitest": "^3.2.4" } }, "node_modules/@7nohe/openapi-react-query-codegen": { @@ -97,69 +97,69 @@ } }, "node_modules/@ark-ui/react": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/@ark-ui/react/-/react-5.12.0.tgz", - "integrity": "sha512-UV89EqyESZoyr6rtvrbFJn/FejpswhvRVcfK44dZDU6h6UY8CxfR/6Ayvrq9UtFdD0dEawqwWrXS22l8Y05Nnw==", - "license": "MIT", - "dependencies": { - "@internationalized/date": "3.8.1", - "@zag-js/accordion": "1.15.0", - "@zag-js/anatomy": "1.15.0", - "@zag-js/angle-slider": "1.15.0", - "@zag-js/auto-resize": "1.15.0", - "@zag-js/avatar": "1.15.0", - "@zag-js/carousel": "1.15.0", - "@zag-js/checkbox": "1.15.0", - "@zag-js/clipboard": "1.15.0", - "@zag-js/collapsible": "1.15.0", - "@zag-js/collection": "1.15.0", - "@zag-js/color-picker": "1.15.0", - "@zag-js/color-utils": "1.15.0", - "@zag-js/combobox": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/date-picker": "1.15.0", - "@zag-js/date-utils": "1.15.0", - "@zag-js/dialog": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/editable": "1.15.0", - "@zag-js/file-upload": "1.15.0", - "@zag-js/file-utils": "1.15.0", - "@zag-js/floating-panel": "1.15.0", - "@zag-js/focus-trap": "1.15.0", - "@zag-js/highlight-word": "1.15.0", - "@zag-js/hover-card": "1.15.0", - "@zag-js/i18n-utils": "1.15.0", - "@zag-js/listbox": "1.15.0", - "@zag-js/menu": "1.15.0", - "@zag-js/number-input": "1.15.0", - "@zag-js/pagination": "1.15.0", - "@zag-js/password-input": "1.15.0", - "@zag-js/pin-input": "1.15.0", - "@zag-js/popover": "1.15.0", - "@zag-js/presence": "1.15.0", - "@zag-js/progress": "1.15.0", - "@zag-js/qr-code": "1.15.0", - "@zag-js/radio-group": "1.15.0", - "@zag-js/rating-group": "1.15.0", - "@zag-js/react": "1.15.0", - "@zag-js/select": "1.15.0", - "@zag-js/signature-pad": "1.15.0", - "@zag-js/slider": "1.15.0", - "@zag-js/splitter": "1.15.0", - "@zag-js/steps": "1.15.0", - "@zag-js/switch": "1.15.0", - "@zag-js/tabs": "1.15.0", - "@zag-js/tags-input": "1.15.0", - "@zag-js/time-picker": "1.15.0", - "@zag-js/timer": "1.15.0", - "@zag-js/toast": "1.15.0", - "@zag-js/toggle": "1.15.0", - "@zag-js/toggle-group": "1.15.0", - "@zag-js/tooltip": "1.15.0", - "@zag-js/tour": "1.15.0", - "@zag-js/tree-view": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@ark-ui/react/-/react-5.14.0.tgz", + "integrity": "sha512-7WWlCM3SowtF01e9NouuO4T6SYuKTM1dovR+2NZuuWTlqTBlvZ+1vPHS6BeqzXriwMLU7QUU+Y0i/TcI6/s/Sg==", + "license": "MIT", + "dependencies": { + "@internationalized/date": "3.8.2", + "@zag-js/accordion": "1.15.2", + "@zag-js/anatomy": "1.15.2", + "@zag-js/angle-slider": "1.15.2", + "@zag-js/auto-resize": "1.15.2", + "@zag-js/avatar": "1.15.2", + "@zag-js/carousel": "1.15.2", + "@zag-js/checkbox": "1.15.2", + "@zag-js/clipboard": "1.15.2", + "@zag-js/collapsible": "1.15.2", + "@zag-js/collection": "1.15.2", + "@zag-js/color-picker": "1.15.2", + "@zag-js/color-utils": "1.15.2", + "@zag-js/combobox": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/date-picker": "1.15.2", + "@zag-js/date-utils": "1.15.2", + "@zag-js/dialog": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/editable": "1.15.2", + "@zag-js/file-upload": "1.15.2", + "@zag-js/file-utils": "1.15.2", + "@zag-js/floating-panel": "1.15.2", + "@zag-js/focus-trap": "1.15.2", + "@zag-js/highlight-word": "1.15.2", + "@zag-js/hover-card": "1.15.2", + "@zag-js/i18n-utils": "1.15.2", + "@zag-js/listbox": "1.15.2", + "@zag-js/menu": "1.15.2", + "@zag-js/number-input": "1.15.2", + "@zag-js/pagination": "1.15.2", + "@zag-js/password-input": "1.15.2", + "@zag-js/pin-input": "1.15.2", + "@zag-js/popover": "1.15.2", + "@zag-js/presence": "1.15.2", + "@zag-js/progress": "1.15.2", + "@zag-js/qr-code": "1.15.2", + "@zag-js/radio-group": "1.15.2", + "@zag-js/rating-group": "1.15.2", + "@zag-js/react": "1.15.2", + "@zag-js/select": "1.15.2", + "@zag-js/signature-pad": "1.15.2", + "@zag-js/slider": "1.15.2", + "@zag-js/splitter": "1.15.2", + "@zag-js/steps": "1.15.2", + "@zag-js/switch": "1.15.2", + "@zag-js/tabs": "1.15.2", + "@zag-js/tags-input": "1.15.2", + "@zag-js/time-picker": "1.15.2", + "@zag-js/timer": "1.15.2", + "@zag-js/toast": "1.15.2", + "@zag-js/toggle": "1.15.2", + "@zag-js/toggle-group": "1.15.2", + "@zag-js/tooltip": "1.15.2", + "@zag-js/tour": "1.15.2", + "@zag-js/tree-view": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" }, "peerDependencies": { "react": ">=18.0.0", @@ -300,12 +300,12 @@ } }, "node_modules/@chakra-ui/react": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@chakra-ui/react/-/react-3.20.0.tgz", - "integrity": "sha512-zHYQAUqrT2pZZ/Xi+sskRC/An9q4ZelLPJkFHdobftTYkcFo1FtkMbBO0AEBZhb/6mZGyfw3JLflSawkuR++uQ==", + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/react/-/react-3.21.0.tgz", + "integrity": "sha512-Ajw6GuUhfNhMagTM9cO1Lg/w/HSQUwsv55j2QvvvPw/dk01wHiGi1aihfuCLpa6QY4ElLNs6SS3f78xI9Fwo6A==", "license": "MIT", "dependencies": { - "@ark-ui/react": "5.12.0", + "@ark-ui/react": "5.14.0", "@emotion/is-prop-valid": "1.3.1", "@emotion/serialize": "1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "1.2.0", @@ -902,9 +902,9 @@ } }, "node_modules/@eslint/compat": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.9.tgz", - "integrity": "sha512-gCdSY54n7k+driCadyMNv8JSPzYLeDVM/ikZRtvtROBpRdFSkS8W9A82MqsaY7lZuwL0wiapgD0NT1xT0hyJsA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.3.0.tgz", + "integrity": "sha512-ZBygRBqpDYiIHsN+d1WyHn3TYgzgpzLEcgJUxTATyiInQbKZz6wZb6+ljwdg8xeeOe4v03z6Uh6lELiw0/mVhQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -920,9 +920,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", - "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.1.tgz", + "integrity": "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -995,9 +995,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.28.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", - "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", + "version": "9.29.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.29.0.tgz", + "integrity": "sha512-3PIF4cBw/y+1u2EazflInpV+lYsSG0aByVIQzAgb1m1MhHFSbqTyNqtBKHgWf/9Ykud+DhILS9EGkmekVhbKoQ==", "dev": true, "license": "MIT", "engines": { @@ -1141,18 +1141,18 @@ } }, "node_modules/@internationalized/date": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.8.1.tgz", - "integrity": "sha512-PgVE6B6eIZtzf9Gu5HvJxRK3ufUFz9DhspELuhW/N0GuMGMTLvPQNRkHP2hTuP9lblOk+f+1xi96sPiPXANXAA==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.8.2.tgz", + "integrity": "sha512-/wENk7CbvLbkUvX1tu0mwq49CVkkWpkXubGel6birjRPyo6uQ4nQpnq5xZu823zRCwwn82zgHrvgF1vZyvmVgA==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" } }, "node_modules/@internationalized/number": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.2.tgz", - "integrity": "sha512-E5QTOlMg9wo5OrKdHD6edo1JJlIoOsylh0+mbf0evi1tHJwMZfJSaBpGtnJV9N7w3jeiioox9EG/EWRWPh82vg==", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.3.tgz", + "integrity": "sha512-p+Zh1sb6EfrfVaS86jlHGQ9HA66fJhV9x5LiE5vCbZtXEHAuhcmUZUdZ4WrFpUBfNalr2OkAJI5AcKEQF+Lebw==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -1577,15 +1577,16 @@ ] }, "node_modules/@stylistic/eslint-plugin": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.4.1.tgz", - "integrity": "sha512-CEigAk7eOLyHvdgmpZsKFwtiqS2wFwI1fn4j09IU9GmD4euFM4jEBAViWeCqaNLlbX2k2+A/Fq9cje4HQBXuJQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.0.0.tgz", + "integrity": "sha512-nVV2FSzeTJ3oFKw+3t9gQYQcrgbopgCASSY27QOtkhEGgSfdQQjDmzZd41NeT1myQ8Wc6l+pZllST9qIu4NKzg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.32.1", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/types": "^8.34.1", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, @@ -1845,9 +1846,9 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.80.6", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.80.6.tgz", - "integrity": "sha512-nl7YxT/TAU+VTf+e2zTkObGTyY8YZBMnbgeA1ee66lIVqzKlYursAII6z5t0e6rXgwUMJSV4dshBTNacNpZHbQ==", + "version": "5.81.2", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.81.2.tgz", + "integrity": "sha512-QLYkPdrudoMATDFa3MiLEwRhNnAlzHWDf0LKaXUqJd0/+QxN8uTPi7bahRlxoAyH0UbLMBdeDbYzWALj7THOtw==", "license": "MIT", "funding": { "type": "github", @@ -1855,12 +1856,12 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.80.6", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.80.6.tgz", - "integrity": "sha512-izX+5CnkpON3NQGcEm3/d7LfFQNo9ZpFtX2QsINgCYK9LT2VCIdi8D3bMaMSNhrAJCznRoAkFic76uvLroALBw==", + "version": "5.81.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.81.2.tgz", + "integrity": "sha512-pe8kFlTrL2zFLlcAj2kZk9UaYYHDk9/1hg9EBaoO3cxDhOZf1FRGJeziSXKrVZyxIfs7b3aoOj/bw7Lie0mDUg==", "license": "MIT", "dependencies": { - "@tanstack/query-core": "5.80.6" + "@tanstack/query-core": "5.81.2" }, "funding": { "type": "github", @@ -2094,6 +2095,16 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/node": { + "version": "20.19.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.1.tgz", + "integrity": "sha512-jJD50LtlD2dodAEO653i3YF04NWak6jN3ky+Ri3Em3mGR39/glWiboM/IePaRbgwSfqM1TpGXfAg8ohn/4dTgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", @@ -2101,9 +2112,9 @@ "peer": true }, "node_modules/@types/react": { - "version": "19.1.7", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.7.tgz", - "integrity": "sha512-BnsPLV43ddr05N71gaGzyZ5hzkCmGwhMvYc8zmvI8Ci1bRkkDSzDDVfAXfN2tk748OwI7ediiPX6PfT9p0QGVg==", + "version": "19.1.8", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz", + "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", "license": "MIT", "dependencies": { "csstype": "^3.0.2" @@ -2119,18 +2130,25 @@ "@types/react": "^19.0.0" } }, + "node_modules/@types/whatwg-mimetype": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz", + "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==", + "dev": true, + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.0.tgz", - "integrity": "sha512-QXwAlHlbcAwNlEEMKQS2RCgJsgXrTJdjXT08xEgbPFa2yYQgVjBymxP5DrfrE7X7iodSzd9qBUHUycdyVJTW1w==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.0.tgz", + "integrity": "sha512-ijItUYaiWuce0N1SoSMrEd0b6b6lYkYt99pqCPfybd+HKVXtEvYhICfLdwp42MhiI5mp0oq7PKEL+g1cNiz/Eg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.34.0", - "@typescript-eslint/type-utils": "8.34.0", - "@typescript-eslint/utils": "8.34.0", - "@typescript-eslint/visitor-keys": "8.34.0", + "@typescript-eslint/scope-manager": "8.35.0", + "@typescript-eslint/type-utils": "8.35.0", + "@typescript-eslint/utils": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -2144,7 +2162,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.34.0", + "@typescript-eslint/parser": "^8.35.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -2160,16 +2178,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.0.tgz", - "integrity": "sha512-vxXJV1hVFx3IXz/oy2sICsJukaBrtDEQSBiV48/YIV5KWjX1dO+bcIr/kCPrW6weKXvsaGKFNlwH0v2eYdRRbA==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.35.0.tgz", + "integrity": "sha512-6sMvZePQrnZH2/cJkwRpkT7DxoAWh+g6+GFRK6bV3YQo7ogi3SX5rgF6099r5Q53Ma5qeT7LGmOmuIutF4t3lA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.34.0", - "@typescript-eslint/types": "8.34.0", - "@typescript-eslint/typescript-estree": "8.34.0", - "@typescript-eslint/visitor-keys": "8.34.0", + "@typescript-eslint/scope-manager": "8.35.0", + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/typescript-estree": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0", "debug": "^4.3.4" }, "engines": { @@ -2185,14 +2203,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.34.0.tgz", - "integrity": "sha512-iEgDALRf970/B2YExmtPMPF54NenZUf4xpL3wsCRx/lgjz6ul/l13R81ozP/ZNuXfnLCS+oPmG7JIxfdNYKELw==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.35.0.tgz", + "integrity": "sha512-41xatqRwWZuhUMF/aZm2fcUsOFKNcG28xqRSS6ZVr9BVJtGExosLAm5A1OxTjRMagx8nJqva+P5zNIGt8RIgbQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.34.0", - "@typescript-eslint/types": "^8.34.0", + "@typescript-eslint/tsconfig-utils": "^8.35.0", + "@typescript-eslint/types": "^8.35.0", "debug": "^4.3.4" }, "engines": { @@ -2207,14 +2225,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.34.0.tgz", - "integrity": "sha512-9Ac0X8WiLykl0aj1oYQNcLZjHgBojT6cW68yAgZ19letYu+Hxd0rE0veI1XznSSst1X5lwnxhPbVdwjDRIomRw==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.35.0.tgz", + "integrity": "sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.34.0", - "@typescript-eslint/visitor-keys": "8.34.0" + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2225,9 +2243,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.0.tgz", - "integrity": "sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.0.tgz", + "integrity": "sha512-04k/7247kZzFraweuEirmvUj+W3bJLI9fX6fbo1Qm2YykuBvEhRTPl8tcxlYO8kZZW+HIXfkZNoasVb8EV4jpA==", "dev": true, "license": "MIT", "engines": { @@ -2242,14 +2260,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.34.0.tgz", - "integrity": "sha512-n7zSmOcUVhcRYC75W2pnPpbO1iwhJY3NLoHEtbJwJSNlVAZuwqu05zY3f3s2SDWWDSo9FdN5szqc73DCtDObAg==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.35.0.tgz", + "integrity": "sha512-ceNNttjfmSEoM9PW87bWLDEIaLAyR+E6BoYJQ5PfaDau37UGca9Nyq3lBk8Bw2ad0AKvYabz6wxc7DMTO2jnNA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.34.0", - "@typescript-eslint/utils": "8.34.0", + "@typescript-eslint/typescript-estree": "8.35.0", + "@typescript-eslint/utils": "8.35.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -2266,9 +2284,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.0.tgz", - "integrity": "sha512-9V24k/paICYPniajHfJ4cuAWETnt7Ssy+R0Rbcqo5sSFr3QEZ/8TSoUi9XeXVBGXCaLtwTOKSLGcInCAvyZeMA==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.35.0.tgz", + "integrity": "sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ==", "dev": true, "license": "MIT", "engines": { @@ -2280,16 +2298,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.34.0.tgz", - "integrity": "sha512-rOi4KZxI7E0+BMqG7emPSK1bB4RICCpF7QD3KCLXn9ZvWoESsOMlHyZPAHyG04ujVplPaHbmEvs34m+wjgtVtg==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.0.tgz", + "integrity": "sha512-F+BhnaBemgu1Qf8oHrxyw14wq6vbL8xwWKKMwTMwYIRmFFY/1n/9T/jpbobZL8vp7QyEUcC6xGrnAO4ua8Kp7w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.34.0", - "@typescript-eslint/tsconfig-utils": "8.34.0", - "@typescript-eslint/types": "8.34.0", - "@typescript-eslint/visitor-keys": "8.34.0", + "@typescript-eslint/project-service": "8.35.0", + "@typescript-eslint/tsconfig-utils": "8.35.0", + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2309,9 +2327,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2335,16 +2353,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.34.0.tgz", - "integrity": "sha512-8L4tWatGchV9A1cKbjaavS6mwYwp39jql8xUmIIKJdm+qiaeHy5KMKlBrf30akXAWBzn2SqKsNOtSENWUwg7XQ==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.35.0.tgz", + "integrity": "sha512-nqoMu7WWM7ki5tPgLVsmPM8CkqtoPUG6xXGeefM5t4x3XumOEKMoUZPdi+7F+/EotukN4R9OWdmDxN80fqoZeg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.34.0", - "@typescript-eslint/types": "8.34.0", - "@typescript-eslint/typescript-estree": "8.34.0" + "@typescript-eslint/scope-manager": "8.35.0", + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/typescript-estree": "8.35.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2359,14 +2377,14 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.34.0.tgz", - "integrity": "sha512-qHV7pW7E85A0x6qyrFn+O+q1k1p3tQCsqIZ1KZ5ESLXY57aTvUd3/a4rdPTeXisvhXn2VQG0VSKUqs8KHF2zcA==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.0.tgz", + "integrity": "sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.34.0", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.35.0", + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2391,15 +2409,15 @@ } }, "node_modules/@vitest/expect": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.3.tgz", - "integrity": "sha512-W2RH2TPWVHA1o7UmaFKISPvdicFJH+mjykctJFoAkUw+SPTJTGjUNdKscFBrqM7IPnCVu6zihtKYa7TkZS1dkQ==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.3", - "@vitest/utils": "3.2.3", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -2408,13 +2426,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.3.tgz", - "integrity": "sha512-cP6fIun+Zx8he4rbWvi+Oya6goKQDZK+Yq4hhlggwQBbrlOQ4qtZ+G4nxB6ZnzI9lyIb+JnvyiJnPC2AGbKSPA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.2.3", + "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -2435,9 +2453,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.3.tgz", - "integrity": "sha512-yFglXGkr9hW/yEXngO+IKMhP0jxyFw2/qys/CK4fFUZnSltD+MU7dVYGrH8rvPcK/O6feXQA+EU33gjaBBbAng==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dev": true, "license": "MIT", "dependencies": { @@ -2448,13 +2466,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.3.tgz", - "integrity": "sha512-83HWYisT3IpMaU9LN+VN+/nLHVBCSIUKJzGxC5RWUOsK1h3USg7ojL+UXQR3b4o4UBIWCYdD2fxuzM7PQQ1u8w==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.2.3", + "@vitest/utils": "3.2.4", "pathe": "^2.0.3", "strip-literal": "^3.0.0" }, @@ -2470,13 +2488,13 @@ "license": "MIT" }, "node_modules/@vitest/snapshot": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.3.tgz", - "integrity": "sha512-9gIVWx2+tysDqUmmM1L0hwadyumqssOL1r8KJipwLx5JVYyxvVRfxvMq7DaWbZZsCqZnu/dZedaZQh4iYTtneA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.3", + "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -2492,9 +2510,9 @@ "license": "MIT" }, "node_modules/@vitest/spy": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.3.tgz", - "integrity": "sha512-JHu9Wl+7bf6FEejTCREy+DmgWe+rQKbK+y32C/k5f4TBIAlijhJbRBIRIOCEpVevgRsCQR2iHRUH2/qKVM/plw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", "dev": true, "license": "MIT", "dependencies": { @@ -2505,14 +2523,14 @@ } }, "node_modules/@vitest/utils": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.3.tgz", - "integrity": "sha512-4zFBCU5Pf+4Z6v+rwnZ1HU1yzOKKvDkMXZrymE2PBlbjKJRlrOxbvpfPSvJTGRIwGoahaOGvp+kbCoxifhzJ1Q==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.3", - "loupe": "^3.1.3", + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" }, "funding": { @@ -2520,555 +2538,555 @@ } }, "node_modules/@zag-js/accordion": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/accordion/-/accordion-1.15.0.tgz", - "integrity": "sha512-EKNeuKx+lOQ/deCe/ApCjVPxpxpDwT2NXvMPL+YvqXmSv7hAnTLs9fDKjbDUQUMmsyx32BsBd8t6d17DL3rPXg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/accordion/-/accordion-1.15.2.tgz", + "integrity": "sha512-4ooxmmnEDeRLPLOCsrQeLHcTj+xTqBHm6pYEdho/pb67lHujAUSnbfEryorBSfvJEWdiUTYts96EfsLfbn5SYA==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/anatomy": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/anatomy/-/anatomy-1.15.0.tgz", - "integrity": "sha512-r0l5I7mSsF35HdwXm22TppNhfVftFuqvKfHvTUw+wQZhni4eUL93HypJD0Fl7mDhtP5zfVGfBwR048OzD0+tCw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/anatomy/-/anatomy-1.15.2.tgz", + "integrity": "sha512-GiWZk+fqO/W15FIRVhUL237xZmYMm/gcrp8b4VJGLpZE4qaQaBd4kSYObhIl/7AnLC45VjKbV7c8fLxZKd/5kA==", "license": "MIT" }, "node_modules/@zag-js/angle-slider": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/angle-slider/-/angle-slider-1.15.0.tgz", - "integrity": "sha512-xIZBa9V6d05uK7+XQVhfdsThqbZKimSYVxtMOWJfG0sKn63N9VGPxL1OtOMq7FA4IP3SyvlelsGt+3t82TUiyA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/angle-slider/-/angle-slider-1.15.2.tgz", + "integrity": "sha512-ItcDlKHJbPFfPGmmiCGcWcd0Y8xC+WH5Dji7+uzBl40L9hh8si7/FrY9EB2cX/qUTDppNyicLPIDnZRGkByTOA==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/rect-utils": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/rect-utils": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/aria-hidden": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/aria-hidden/-/aria-hidden-1.15.0.tgz", - "integrity": "sha512-3ogglAasycekTHI34ph16mqwM+VtHCOMtrFHWzPwB16itV5oDEeeMNdQXenHSSyQ/07nJ2QsRGFFjGhPm1kWNg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/aria-hidden/-/aria-hidden-1.15.2.tgz", + "integrity": "sha512-Uwt86QpEaI4qLFS/k4C7rwIfyiH8EdE5a4AWiQ26WsL8VOpjROn65rBEOJ8q3fG5CJXbdcqaYK3lg4ldqf9irQ==", "license": "MIT" }, "node_modules/@zag-js/auto-resize": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/auto-resize/-/auto-resize-1.15.0.tgz", - "integrity": "sha512-EXgrsU7OWxc7obSOt8Okh0144H8DQi1S84OsOUY04Uni11Dnp5/X8+t6mvBbkw4/Qyz5UBjChjocwBcO+HHV8w==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/auto-resize/-/auto-resize-1.15.2.tgz", + "integrity": "sha512-Mg3IN3eIP2wKBFRm5qti/rjKpTj7sfIVNfO9BgWdHDSzli1VwaBX7GaOE3nGc1tZ2nJ8n0SWRvRSzr3b57cwKw==", "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0" + "@zag-js/dom-query": "1.15.2" } }, "node_modules/@zag-js/avatar": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/avatar/-/avatar-1.15.0.tgz", - "integrity": "sha512-EHGxzXb1mLf3n6x0z/rqFl1mghDB/gyfPAeaFUoA/cacmmMk8YB3aDUXkS9pTgN9stYJBM5f6T4xB1ZUhrP8tg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/avatar/-/avatar-1.15.2.tgz", + "integrity": "sha512-4aG2ETJbdMTALyXwU/DeGfjs/dM0Kllje+t5ov52fQrtkY123JdrvKQkcvsc7Luph1kdN1tC1/2fe/pDMhycCg==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/carousel": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/carousel/-/carousel-1.15.0.tgz", - "integrity": "sha512-ZI9H34f2utdJ2Ek6GZa+iuRH4eC99GHD/VEOKLdGani8uadpT2v8M5kUwPGrlAJq9SiPbQ2UuXBmCkmurPQqdA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/carousel/-/carousel-1.15.2.tgz", + "integrity": "sha512-7bcyEtWIhv7kw+V4H+Fv5rE8I8lf0LQOj+m3HTYzWo+wiLybFfI8/bg1qywjSYKsgZr3gmGVCEZhfx3BSpP3eA==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/scroll-snap": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/scroll-snap": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/checkbox": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/checkbox/-/checkbox-1.15.0.tgz", - "integrity": "sha512-6lQvPQNJXt7R0xxdpOuh2qtmAkzdBdqSvFIH7fE6GJzJ/AWiRZh0X+9deLQ76CN4EDUdxizEe7MlQfTI3a56aw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/checkbox/-/checkbox-1.15.2.tgz", + "integrity": "sha512-Ay/+rpKbxL4jE1pwVw52h0t79PpiifA6QlYnV4E+hWl1yJBkMRIi76Ryhqvqp4yY+2Wyr9OfDA9eHmQjapG4VA==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/focus-visible": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/focus-visible": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/clipboard": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/clipboard/-/clipboard-1.15.0.tgz", - "integrity": "sha512-Q3kh0fHvOEAJUywQm3zAWyltrYyiI8OpeZQ18k5Mf3/M+bq3gSphZL0+AYsgGbKUg5O2+hJ1SfiErAjyhRtBQA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/clipboard/-/clipboard-1.15.2.tgz", + "integrity": "sha512-EE5OlsIYbBklo62qu3A7GiUnsgmoGaoDZvhpYvpNM8StWNeRREcJZXRIizv4aFC46e5eODzSNcebnMLYa8Wcgw==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/collapsible": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/collapsible/-/collapsible-1.15.0.tgz", - "integrity": "sha512-GX0kdMlKk4Yk5k/2wN0prudf21k+TfArGr4EHqimTDR0vQE3dSdb3pYyPjw20fLzceKHBBCLsoi2v+YnS75gHA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/collapsible/-/collapsible-1.15.2.tgz", + "integrity": "sha512-vvUXQMFgwsZJphE4Ml5ap4FVhtyLOqK2QXPbt2+F8X8SRwJ3/pqsSsLFdH+ALpNoCK6WF9j+8FZ4lyidr7XPDw==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/collection": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/collection/-/collection-1.15.0.tgz", - "integrity": "sha512-oC3i6c/oP/FuNPsfgoC1reSXbAvDBGXl0HU3CcvXiNLHbjg2ek8J7kbow6MNuXK6chiksiOHbzKxHl2Oo0Ox7A==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/collection/-/collection-1.15.2.tgz", + "integrity": "sha512-bJ9EtZ1Cpjh/rQFDMPTPrky/eSfaLpHWmMnk/S9b7wi+OhC0Hoqw38lcWzfc0AaE4bJsfru9/FLIsCDOLf7TSg==", "license": "MIT", "dependencies": { - "@zag-js/utils": "1.15.0" + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/color-picker": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/color-picker/-/color-picker-1.15.0.tgz", - "integrity": "sha512-DGujS24h1OWkYL+TWyd+xukOO8NBgcSfFCINffa4ivkHtNx3nC28qkwLPRASbl7AK69pbrcuO6bx1Sy/JQJw0Q==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/color-picker/-/color-picker-1.15.2.tgz", + "integrity": "sha512-UOYHECq+X6hSrgSxwBt5O4Y6f2IdOGMhe7P/LFev7Yn0x1F9fMxJZCIzvQGaQ2V/hR0eTatiKk5SmOp9+dJA/g==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/color-utils": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/color-utils": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dismissable": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/popper": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/color-utils": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/color-utils/-/color-utils-1.15.0.tgz", - "integrity": "sha512-SKo+p5Fu0TBtdDua8UHVjptOkwLLBFoD499Z1FER/gr0R/97L03Kdir0YTxvKn5pXWXYY1EQn4hpTuTITN16lQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/color-utils/-/color-utils-1.15.2.tgz", + "integrity": "sha512-c167QcxiVHgFZ7ca0PSQZ7skhbBOd6u1lIyWYzkZ2uPf0yJndqP9gFYPMbwK6d4WIM9k6y6mLdsWCGpqIJJsIg==", "license": "MIT", "dependencies": { - "@zag-js/utils": "1.15.0" + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/combobox": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/combobox/-/combobox-1.15.0.tgz", - "integrity": "sha512-HBck3wcEeIOa7IQMsUkUKbm9cAU7bjoklIyq2zFGn90k7DcDa++oXK9Z2pmcd4TPoBYiyVuuXucaCcjmLX8V/Q==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/combobox/-/combobox-1.15.2.tgz", + "integrity": "sha512-lZXW99NLnRfLLY1ZOE0oqo4wMDglkUjKV1UZaHyj+yqXsiMtWhKQFQW/JeVBRDe6RCv8wWPPHMycNANMw581gQ==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/aria-hidden": "1.15.0", - "@zag-js/collection": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/aria-hidden": "1.15.2", + "@zag-js/collection": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dismissable": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/popper": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/core": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/core/-/core-1.15.0.tgz", - "integrity": "sha512-P/8F3IXabMhpFnc6hC7GDg3rvUnvY27cuZU04hxjUqTH6+SfORIA/Uvqd4ekhC+dIprL9jicnFrmGgcyelyxfQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/core/-/core-1.15.2.tgz", + "integrity": "sha512-yUnh4I0nZ8rlszWgF402F5vGoYw7DNwStYz2TAO+4E08BpKBATw3FEdqAHPm+2xZm5qPqnPbM4iObwUlkBQUEw==", "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/dom-query": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/date-picker": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/date-picker/-/date-picker-1.15.0.tgz", - "integrity": "sha512-IZD0V9MAljp1QhxYbST80AonryuDnyx7hvEy/RrBY/VOx6I4STtKfcSJ5ZZgVIzJfH8Yyaed4+IwcenqG7W5YQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/date-picker/-/date-picker-1.15.2.tgz", + "integrity": "sha512-KElAFm3fW4GKGUNUe+jqqUX+P1H+Cigp/eGRgIl0dUjCwHocD1oN0ZCwNYmf7SJoWSgPRc1UJdA4XvpdU0IwPQ==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/date-utils": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/live-region": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/date-utils": "1.15.2", + "@zag-js/dismissable": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/live-region": "1.15.2", + "@zag-js/popper": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" }, "peerDependencies": { "@internationalized/date": ">=3.0.0" } }, "node_modules/@zag-js/date-utils": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/date-utils/-/date-utils-1.15.0.tgz", - "integrity": "sha512-FX9EesJRnUTYTpbXf5EVfCbsXW5vYtZfc635aQzojc9ekk1FGcHpqQs8ZKfCOTPuauZFOX9i6139A4KoPfQOiw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/date-utils/-/date-utils-1.15.2.tgz", + "integrity": "sha512-U+HtfdtHJ5ed2ys8izMhu8gY5jQigCd8ExPN5Cxg5CoIbSkho9NT8o/eO9OW71jc2F4kwBh+q0reyxxLJnTSbw==", "license": "MIT", "peerDependencies": { "@internationalized/date": ">=3.0.0" } }, "node_modules/@zag-js/dialog": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/dialog/-/dialog-1.15.0.tgz", - "integrity": "sha512-Vlt5vySs4u8c8xBEh2JMUvRfPc+aaVEIIUtFVxpc2ORWhBXs9glijyp1yf3rNHJhjj8gqqhF5sEvs3yUTTAk+Q==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/dialog/-/dialog-1.15.2.tgz", + "integrity": "sha512-LUF+tiiUJj7v24txhC0TOwEgsfj1GCogAmBaiJKxvqrDEDv1B91J0b6SUQ5TuTMLW+hlBEzXZw0QsTxa9OXBew==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/aria-hidden": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/focus-trap": "1.15.0", - "@zag-js/remove-scroll": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/aria-hidden": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dismissable": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/focus-trap": "1.15.2", + "@zag-js/remove-scroll": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/dismissable": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/dismissable/-/dismissable-1.15.0.tgz", - "integrity": "sha512-yv575KWy8gA1p4aajOiY5l/nBQ3Xw+Mrjpungp1+wiGd/98eNAIKJ6/adldfbE1Ygd/Q4Dx2VQ7D1AmiTdwUSw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/dismissable/-/dismissable-1.15.2.tgz", + "integrity": "sha512-+WY8a1L+L8hXPGmWKqOsSg2KCHabVWXEX8mewHamltpSb86+2WMmblpLNgTwbm6V0T6txf1N8lFuzWMojMEWSg==", "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0", - "@zag-js/interact-outside": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/dom-query": "1.15.2", + "@zag-js/interact-outside": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/dom-query": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.15.0.tgz", - "integrity": "sha512-z8H/j/Zs0eZEsGpbonScmlKSv0jEXKiAwUCrvQ9Mt6Gz9n0CQRM3MkFclSsM8aeiSv6qKLlhPfkzjl18OLkbgA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.15.2.tgz", + "integrity": "sha512-+r9Xj6hiQj9b2ZNkT3E/bDaXgigoAkhtikDXov9duAY14pFFJxazXr0NcVgacik8ytAEt6XOOshLcAftyalRKg==", "license": "MIT", "dependencies": { - "@zag-js/types": "1.15.0" + "@zag-js/types": "1.15.2" } }, "node_modules/@zag-js/editable": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/editable/-/editable-1.15.0.tgz", - "integrity": "sha512-F14HKZuDsfkpfIkaF/ZDYPkz/pFf6VHrvoV0rdhj8wb8QJQ4nB+lgBv2APSwkEaFb/gGrnE19v3Ojlt5tqpPsw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/editable/-/editable-1.15.2.tgz", + "integrity": "sha512-32v7DXDBnDX1CiFpGRh9uclu48UJQJT2QZPQ0Bys3ZOFgMxsWH6tCKDb7iQTcINIc/XIx/9nclWnV5egzimG9w==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/interact-outside": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/interact-outside": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/file-upload": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/file-upload/-/file-upload-1.15.0.tgz", - "integrity": "sha512-2hAlQr9qdT8EH4XnmkNkEIDCCsmp2SMoMAjq6nJKYO8UJNQGRanU2B5S8jV3quJBz0vIY43SwyvqiZ3+1VrJSg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/file-upload/-/file-upload-1.15.2.tgz", + "integrity": "sha512-Zgac/da5QrUlE0ItlNy1kyMXfTy4ynTWnq4aZ4wZ9eVHUFQhLXERv8l+hYJetImISnuclmNVxNKP8Xk+5t4+tA==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/file-utils": "1.15.0", - "@zag-js/i18n-utils": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/file-utils": "1.15.2", + "@zag-js/i18n-utils": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/file-utils": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/file-utils/-/file-utils-1.15.0.tgz", - "integrity": "sha512-tahJt3JmrXaOtGiknH5PxIiOyyNvroMfjiBqOqnNksIPzDoWmVNxHOEme/ts7dJlkRD8U2qm2NFC2VS0bKerzg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/file-utils/-/file-utils-1.15.2.tgz", + "integrity": "sha512-aNUEBJUeK6G3pyf+zYnIMg0GgJnInddjGRedFeTnfK1UmlSO8wTbxQTCvjWd4Nnr5eCTpQkRq6wTZy8JeIcOpw==", "license": "MIT", "dependencies": { - "@zag-js/i18n-utils": "1.15.0" + "@zag-js/i18n-utils": "1.15.2" } }, "node_modules/@zag-js/floating-panel": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/floating-panel/-/floating-panel-1.15.0.tgz", - "integrity": "sha512-AYYFseA1MeQUZl+zjNoKUu4j0kwz8EyJd4oJjs8uJIR6KG8u8QhpWYIBUny63M6AtZTCSYQAgBEcEh+mrbEyyQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/floating-panel/-/floating-panel-1.15.2.tgz", + "integrity": "sha512-8oG2MRXWWeXws7iVDmJFBqHLHYOGLvYe+vgXI3vgnLhmS4SeX9qAJj6qIOar7htOmEtp1p/KiBo2w2MYtzjuAw==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/rect-utils": "1.15.0", - "@zag-js/store": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dismissable": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/popper": "1.15.2", + "@zag-js/rect-utils": "1.15.2", + "@zag-js/store": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/focus-trap": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/focus-trap/-/focus-trap-1.15.0.tgz", - "integrity": "sha512-N8m/JpNe1gHUPJlr0hyGUdHg6pAuyJKkBaX0s38cyVntlo2CJhyAWZGuUdocpT2Q3HNPql666FNnH986rYPDKQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/focus-trap/-/focus-trap-1.15.2.tgz", + "integrity": "sha512-5EU5/Cg80oNO3z83A/33t9SOVYvLqLOuSPxt/7Xzy/L1Vj3vUj+s1ox6IpECmEFJcuql7X5yt6VIVitrLtgbFA==", "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0" + "@zag-js/dom-query": "1.15.2" } }, "node_modules/@zag-js/focus-visible": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.15.0.tgz", - "integrity": "sha512-TPXBf47tj6L0hhZNl9AWhuLoVzfPaNPM+/Gw8t9l9Whvy6v9rk/rqUCidY5LsrQuPiKTi7s5WI5J+Wod8ib3gw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.15.2.tgz", + "integrity": "sha512-zElE5T41p5QaB4856xK2SeERmHrKbA/UMzoyHzrAk/N1r6dNiMOOx1hMyHy7y6pEhC9kjJFwEpXi1QEel6/ELA==", "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0" + "@zag-js/dom-query": "1.15.2" } }, "node_modules/@zag-js/highlight-word": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/highlight-word/-/highlight-word-1.15.0.tgz", - "integrity": "sha512-Rwr/rRm8BaF2xW9BAEJeA2wpFVx6HzoezfYQX7GFPPgw3N8nBMAYNjx+i1YIwIEcNyad2rbaBB+pSd2fZLIniA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/highlight-word/-/highlight-word-1.15.2.tgz", + "integrity": "sha512-2a49h4k0ISIDydaZZDdASEHJpwxJeuZHSPCE7cM3/BWCR3H5galeC/jbNWRlTJVH4OQTYAR0I2wILQvOWLhSrw==", "license": "MIT" }, "node_modules/@zag-js/hover-card": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/hover-card/-/hover-card-1.15.0.tgz", - "integrity": "sha512-j6BsE+metdnv/C/Ls0TZzAMN78rtS2r8M1ccHY5FFTGyUvZnlE8BY/QPNyCSSSCUpynymzMYh3IMYlxbJgfpSQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/hover-card/-/hover-card-1.15.2.tgz", + "integrity": "sha512-FfNmhow8MPMp5RgTeC87x4EStFw+d1137w4QZ+fC5PystRzxGeiyDJyLRYGVeIQO2oP463az70vnxsbFAMu98A==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dismissable": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/popper": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/i18n-utils": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/i18n-utils/-/i18n-utils-1.15.0.tgz", - "integrity": "sha512-anxSbT8kLbJaFJFSb0Ork2j/Lp+XVfMNCIgiBR2BuqUlfX72k23TIJvRxAfwNIkUfs0L8ikaSgLss9OwS4mAnw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/i18n-utils/-/i18n-utils-1.15.2.tgz", + "integrity": "sha512-1RnqCaxe+l4UR1O3fhn04T+J62yw/SkCByhrhrPSis/H7a65nW0WsoWiJTIgWp/hN9HI2Y3dVFfMEwQUFFHG1g==", "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0" + "@zag-js/dom-query": "1.15.2" } }, "node_modules/@zag-js/interact-outside": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/interact-outside/-/interact-outside-1.15.0.tgz", - "integrity": "sha512-OwBf/iesQGU9Oq3xe/tcK7gu7xipiGWsmwl2CcScr0fTp3BIMbQywHS928IgPk1DxA8KTHodY8wBjoY1dskfRA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/interact-outside/-/interact-outside-1.15.2.tgz", + "integrity": "sha512-WbCICcMJHL6yS8vaou0FvKV6shl1Z+CefF7yzn5MEshPLbmy33WGQ2KBzodTkIQFM/C/zdVz5xKl8TbQmi7jUg==", "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/dom-query": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/listbox": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/listbox/-/listbox-1.15.0.tgz", - "integrity": "sha512-Gcg76uWZwUAyMFZzGWpHnFCU/aaquNbXmVnyzzBgE3Co2snkv02rK1yG9iBwemZe3e5+VBifMMAtLLPAQJdz+g==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/listbox/-/listbox-1.15.2.tgz", + "integrity": "sha512-V6Zbi8HTiyhsV4GhFaiFYL2bJo4lOt24/SA9M/T5D7ZH+bTm3itPUxYddIBi9w6yRTU0gsorosD2GyFkHjchvg==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/collection": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/focus-visible": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/collection": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/focus-visible": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/live-region": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/live-region/-/live-region-1.15.0.tgz", - "integrity": "sha512-Xy1PqLZD9AKzKuTKCMo9miL1Xizk/N8qFvj64iybBKUYnKr89/af3w7hRFqd2BDX+q3zrNxPp9rZ6L7MlOc7kA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/live-region/-/live-region-1.15.2.tgz", + "integrity": "sha512-dIrfDlKyNz99CQVeHu9RHe/x+yTBm3wFA7H655DXL7CugO9tpTlynkrTG9AB+0Z84JKZTeHh0vGVa2chTWKrNg==", "license": "MIT" }, "node_modules/@zag-js/menu": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/menu/-/menu-1.15.0.tgz", - "integrity": "sha512-GbEBVYu0w7+88xrGX2GrjXfnwWuX5jLhoLiEcuxvxJQal/nahKrH4AGXJvHXNaRbj+53V3nWAh3u70C9210PWw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/menu/-/menu-1.15.2.tgz", + "integrity": "sha512-54dGUChMLyTrkCGbKGh0R8l/cg0vPFnGZwMG96zYJhkmXdpDMECZgBrN3j7B6RtEIvlAR8fMH5Sya58Amb3lGg==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/rect-utils": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dismissable": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/popper": "1.15.2", + "@zag-js/rect-utils": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/number-input": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/number-input/-/number-input-1.15.0.tgz", - "integrity": "sha512-+kK8kyXJhIAbEUnswoMDR+DSJUmvDNIOW0ffuZ9pbfukN3p6zaA3/dCp2Dtg3bQS7hGrFWgtrdejJ8l+mVvUAA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/number-input/-/number-input-1.15.2.tgz", + "integrity": "sha512-qtDAVUdMXBhufBSwAgi8MXm7zHb36ujfWmxCJg6HbjKVF0BEAxeoye5VexgyYul7Hp8+Rr9LkW8X35W4amjJEQ==", "license": "MIT", "dependencies": { - "@internationalized/number": "3.6.2", - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@internationalized/number": "3.6.3", + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/pagination": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/pagination/-/pagination-1.15.0.tgz", - "integrity": "sha512-Z62Q41fQPWqk59QyJk+9J0Ad3H9DCqZ0zZutI6iH8DdzT0A0xxmT6zhup6DM/8C8h0OLlaHFTWQnj0RdRNrnXg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/pagination/-/pagination-1.15.2.tgz", + "integrity": "sha512-k1jT7UWDwgkYVsf83TTUhks6iZ7aQpcEjQ+iWI2LbZu98+bVhX9hpHfxdWbvTbueGk6WjB2xa1X0tsktII1mmQ==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/password-input": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/password-input/-/password-input-1.15.0.tgz", - "integrity": "sha512-oHuZKDRJIbycqWpTVznufy4L7K2g8kwcEaZ4runkwO2ocF00zP8HVmOZQzmhkUgTny0azErQydg8XE0VR5OfYg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/password-input/-/password-input-1.15.2.tgz", + "integrity": "sha512-9BpQ26Z9XoCiNAHOmx3zwa+62+C6358/az0h3N24P4qS1EdTVWkhG1tsyPhRElg4v1koavZ40RMUppJQBH+DmA==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/pin-input": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/pin-input/-/pin-input-1.15.0.tgz", - "integrity": "sha512-IykjogZBG+BfbFXymSa+KGpOi5CrV9kl8HRm6G2V2Sr3NA5jEwMFaGSd/QrcHS9vh23D1Smx/io4pvF7c3q0kg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/pin-input/-/pin-input-1.15.2.tgz", + "integrity": "sha512-1KjGGmyldtEb4RwwdBTKzbgAwpNT6CyY274LvQC8lTCEUYOBkUmS9OUaKUbwkoluCdmXrugpg/XMulisRmMtgg==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/popover": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/popover/-/popover-1.15.0.tgz", - "integrity": "sha512-cdzEed3zcGbjSgPQnQnrsuXo2hVVslmSNwQbU5dHcNzG1uxxmtPCIMVeBUmGyJbAFF5XQpKCq/7mIr26dT73vw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/popover/-/popover-1.15.2.tgz", + "integrity": "sha512-6cD4eTwwj/bkTCDWVk0dMFqg01iD7qJofRSU3da7nde1Y0TMz8gBlt++GASgCF4p/hPeGLD18GcIF8FKka9IlA==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/aria-hidden": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/focus-trap": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/remove-scroll": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/aria-hidden": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dismissable": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/focus-trap": "1.15.2", + "@zag-js/popper": "1.15.2", + "@zag-js/remove-scroll": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/popper": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/popper/-/popper-1.15.0.tgz", - "integrity": "sha512-Ra/0Ko423KN+8D4+mIFFkeTn9uaHfpxn6UUNIWwZKoiJQvED8DH4dPbLbmvGEoKp6qmisnRHAzi71NLgEhk0Mw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/popper/-/popper-1.15.2.tgz", + "integrity": "sha512-5uaFW9IU8bj3NdEiyuSp2eVJaPvWoA6/q7Fh423Va8booMYW4k1KFmz2BSxQ3JfK5lt3vPI0X2026gSxTx/vmg==", "license": "MIT", "dependencies": { "@floating-ui/dom": "1.7.1", - "@zag-js/dom-query": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/dom-query": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/presence": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/presence/-/presence-1.15.0.tgz", - "integrity": "sha512-hoxXis50pm79PpkY2kA1wdhh4AEo7t7pBv0VsQYZYjmzuFh4V5IMw9oa1EOfBlC6f/A+EMZ9E+xg+EVsB68a8w==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/presence/-/presence-1.15.2.tgz", + "integrity": "sha512-cNPJz3qeXdoYFEefxFixZoMDFzqfHsLgmi2ynmRrFlyHzHtFdvKjvS5ywo9YFGNgwKrEddS43n8gl3w3lgqBCA==", "license": "MIT", "dependencies": { - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0" + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2" } }, "node_modules/@zag-js/progress": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/progress/-/progress-1.15.0.tgz", - "integrity": "sha512-/Mz26GR2rOAuoErNOiSGRpvwckTmbCD5nWGDE/aYlVRID13HcsmN15Zk2Jfa4LadqK88aIN8Iy0Sk4elG0+Efw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/progress/-/progress-1.15.2.tgz", + "integrity": "sha512-VPunnrTYiJaHnnCKuh2ZARCnzgTtxYIiNKiUVPWlygsWy2AGg1K3AvVswF2CVfGpwbO4ioyBQO65EZkQiMN/Aw==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/qr-code": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/qr-code/-/qr-code-1.15.0.tgz", - "integrity": "sha512-GkGy5k5tk6DIui9lGjDO8+e8TsSVOxEGp1lblPiaRm1ggIh10GhIfCQWGe/x78ezdie8WzxlSrma89suTpaiAQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/qr-code/-/qr-code-1.15.2.tgz", + "integrity": "sha512-hFtwGGArxVJo7osbY3R73BHIX3Ldb8G4gtNDZ2fGcKAcp+SQg5GXUIBK17ncxJrOC7A1Wp7sdOoYNNOPWe2fYA==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0", + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2", "proxy-memoize": "3.0.1", "uqr": "0.1.2" } }, "node_modules/@zag-js/radio-group": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/radio-group/-/radio-group-1.15.0.tgz", - "integrity": "sha512-+KTebHUtMsE/YDyGE8wF5VnWfZQp+f2WoAwwzBjfhPpRxXbOUMDo0pZEEr3yxkSvQ9hgCcBhMKH8pEk0SPxvjQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/radio-group/-/radio-group-1.15.2.tgz", + "integrity": "sha512-+V9Y4EZuNITMbA9iJisysqWW+JB3YdlFF6dAomvXN8nuOuj8HE02JHndIeMflDtW6Tz99JcJLS7lNXN7G5uEuw==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/focus-visible": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/focus-visible": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/rating-group": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/rating-group/-/rating-group-1.15.0.tgz", - "integrity": "sha512-omGKN97FhplFwBX9J/Mj7BCZuwFXSXssSVTKU7Yp2d1Cmxhez4+Ju7KdSRNnIoWB4OxFCxwZyaAPTcg3E0Pjrg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/rating-group/-/rating-group-1.15.2.tgz", + "integrity": "sha512-g7F9NyB1MF6ydE9aEr9zLPXGKXZIH2ZsUBXEQ9u6apUhnchhCSHDw6xHVXI1hYGrJHnpf2xMw3Xu1opJge1DQg==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/react": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/react/-/react-1.15.0.tgz", - "integrity": "sha512-YSp9QBkdeBfZt4nVhJW+CUd5sNEEVAuwkmoZWDFUoDoWSAXwzSKuHCmTm5/8DaXg1IZD2bMrXgMNDqZv2x0hZw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/react/-/react-1.15.2.tgz", + "integrity": "sha512-T5QPiLbW4DoQ32NS5+Qu9NsIXKKz0d5MOpfEdXXuc6hKZdvV+V9d7EXeHBRohs3P6jqtf8FXpXDdK2trv37YlQ==", "license": "MIT", "dependencies": { - "@zag-js/core": "1.15.0", - "@zag-js/store": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/core": "1.15.2", + "@zag-js/store": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" }, "peerDependencies": { "react": ">=18.0.0", @@ -3076,288 +3094,289 @@ } }, "node_modules/@zag-js/rect-utils": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/rect-utils/-/rect-utils-1.15.0.tgz", - "integrity": "sha512-sjAn78x1t3XiDG3NT8SoFfyO0u7/SEJU5RKRhMgjTPoOLXTzZj+lu2d5N4cUw0uZTfeGb/ormObSchMQVhFgYQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/rect-utils/-/rect-utils-1.15.2.tgz", + "integrity": "sha512-wPsOM4qYncwOli20MNINgl0ZwmMY11RvrgPvjcMrkJ9dVqU/YrCcXV4rIg8Zig5jxCT+mf7rWQe9aQJlNTVipA==", "license": "MIT" }, "node_modules/@zag-js/remove-scroll": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/remove-scroll/-/remove-scroll-1.15.0.tgz", - "integrity": "sha512-vdWSAdgY8wJ7s4YeaKwTMwmZiRMBxCehmdktSxBWvwtAjU1cM3UWvjmZ9E6INJrQXxH9vDpe/rpFSyv1guIQIw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/remove-scroll/-/remove-scroll-1.15.2.tgz", + "integrity": "sha512-pXVuvFcAQND+C0KAzAve02hGaI/AgEhC7RpgpyUKaUzEccEsxLi40C88j1/2HCfta6GI7nd2e0QwPZiqngUIyA==", "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0" + "@zag-js/dom-query": "1.15.2" } }, "node_modules/@zag-js/scroll-snap": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/scroll-snap/-/scroll-snap-1.15.0.tgz", - "integrity": "sha512-/LfBlsjoR4tVL3Djus3k9jKLhwC2ApdHTACxEc72TAewoPe4M8icnSDLXmKHvwwOhzK0HlFz8wGm6ZncAbQbuA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/scroll-snap/-/scroll-snap-1.15.2.tgz", + "integrity": "sha512-RswpsMHg0aWHsx7xqybnPm8bTL9ow17z9GhYgxSWtIi2U9wgkUHDtEJQcRNUA9PQEGyVd29B39NM0ir64HAhNQ==", "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0" + "@zag-js/dom-query": "1.15.2" } }, "node_modules/@zag-js/select": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/select/-/select-1.15.0.tgz", - "integrity": "sha512-4urUBADzhrsGEO/UsqHdjsgmDdF15Zzeid3ejEbIMTrkt2/mMMcQ1CShuxtsWqm2EUBz/N1kOcZlE6Tq69n7Xg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/select/-/select-1.15.2.tgz", + "integrity": "sha512-Y07RlBIc8bVj2WklhS7tiVySZntBv9TE9sfiA8RcLU7KFFGTdS2XUoQV4fziJubUL8XFhNzEC92/bKeBLqpgDw==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/collection": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/collection": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dismissable": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/popper": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/signature-pad": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/signature-pad/-/signature-pad-1.15.0.tgz", - "integrity": "sha512-5Tj8vkrRxEkSV417oR2qdy+TRgDmS3W8dY7xsIjpbBf/kqkt/8Uo4JpaVH2vwQAFw9AwEFogBh9i6dHcXMy0rA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/signature-pad/-/signature-pad-1.15.2.tgz", + "integrity": "sha512-vw7oD7afBfGvUyotJrFl+PjPVYOYZLgQ1eVAosKj54phgKvxheBr8/ySq9vlyTkyvOMjJ8zIkkxlywuqoZzl8g==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0", + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2", "perfect-freehand": "^1.2.2" } }, "node_modules/@zag-js/slider": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/slider/-/slider-1.15.0.tgz", - "integrity": "sha512-NYIsn3GKXIoPmvkDXsQmw9wdYg3QHbYHXnZ8Ewl2fVubN7S5mDlHSZs2iDVsBvX+a4RChWFRO6JHX8E1+BncOg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/slider/-/slider-1.15.2.tgz", + "integrity": "sha512-Lcrm+h4Vx0stD0ybAqD5tA1qOnrKEfQP9ucQsPUy+fY2em19XC6raOVOhAc6ROx4X0neTI/yEc1ARJQSaxtRZw==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/splitter": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/splitter/-/splitter-1.15.0.tgz", - "integrity": "sha512-Xnedl+cpnD/hv9m+GOYCK5K2xRxbs4xuP/EajYtgVcDw8E1X5cBmxHa1hCrp7BMgb2xYCvZ5et4hnmZfb+1X9g==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/splitter/-/splitter-1.15.2.tgz", + "integrity": "sha512-LIuTTPRaw3inS64f2TLcFIlwjNe9Tx9mSE4VXf7wPhYitNKmyh7MeNE59na+wDzZisVwx9yBewAPfrZtbHDGBA==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/steps": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/steps/-/steps-1.15.0.tgz", - "integrity": "sha512-VoIDcDIEErZawmW2m0yTGlffqjfRuSwR37K9LdSRy8Q4Qzz3wV7jASaTjMhTya1hlreJ7tJg+Qbjqowvw9GndA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/steps/-/steps-1.15.2.tgz", + "integrity": "sha512-NnS3wYQrFWA5OXu+jnlnPpm49rGpzHCDbN2UuUcMGvbYVETKEXEO9fC1XWh7PstVuNi03E/CrZGHl5cEjf/j8w==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/store": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/store/-/store-1.15.0.tgz", - "integrity": "sha512-ecqjcy3b1GsULpsT8RVJV9KDaikajRN0XRg48HMvaGkaPIvxI6esyrE6RKnShuqr2eVXIPghgBnCnrJUev4UlA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/store/-/store-1.15.2.tgz", + "integrity": "sha512-oDJuRdu8SaGab06UycN96OgvNau1ynawDNNfQNhA7zoOIZlaJH6jP+5YaAPFila+wyjdw7svz5+4ejs8vXcjpw==", "license": "MIT", "dependencies": { "proxy-compare": "3.0.1" } }, "node_modules/@zag-js/switch": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/switch/-/switch-1.15.0.tgz", - "integrity": "sha512-2CaAUTi7jM4lJjCYoSE1HWlFPCifI5GR+hufWOCYKpanf8VA/LM+t/a2Aq5QoBsWdcQv3B9mHxF/aVTDbnCKPQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/switch/-/switch-1.15.2.tgz", + "integrity": "sha512-2aEm5HDP/ENcLvoP77CH7DQTPXIMUzVilefHlz6WT0tQxQzOw8uMhUOYYcuNmEq0FNRUOyuMEMyZnZFUYAxqvQ==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/focus-visible": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/focus-visible": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/tabs": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/tabs/-/tabs-1.15.0.tgz", - "integrity": "sha512-voHWpibC1TKLmbAJfixOesxrCio7wK+gdLRvh7Xh5u+3VSsT2fP2wEw3ySkJbpw3MpEE7R2OWkInbCV/SwPcsA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/tabs/-/tabs-1.15.2.tgz", + "integrity": "sha512-SJMR4K59sxvNZEIgnJfbweLzncmgxRWTBm+FamwMtP8DKQ3RETNdjrn4aA9qLUsCObapk06KT3iTeiCXzuBaFA==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/tags-input": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/tags-input/-/tags-input-1.15.0.tgz", - "integrity": "sha512-CB60z+/I/Nso1gwatTO1qrk4XITxDd4qtRD+l6fuuKyOkZGgKm0AP0W+/6qUuOvtWIuY6fas3yZHFmF2eEZ9vQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/tags-input/-/tags-input-1.15.2.tgz", + "integrity": "sha512-/mAuB8emhGoo3eoIgmlT/kQE27ukRlhghgwp3OjvEen+iTpz0XIWM+S+IV3QU6U4DlhwkadQaINht/c9ln6gxQ==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/auto-resize": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/interact-outside": "1.15.0", - "@zag-js/live-region": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/auto-resize": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/interact-outside": "1.15.2", + "@zag-js/live-region": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/time-picker": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/time-picker/-/time-picker-1.15.0.tgz", - "integrity": "sha512-4S02433X88X3MW/BxaFJiWna4BIRXsAdrmDcBb0PZ8dln29DUmpD8YHcFtONsKvmCAmrbO7Gr65n86nQwK8zeg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/time-picker/-/time-picker-1.15.2.tgz", + "integrity": "sha512-Aoe9GdbrvAMP1fdOEmzCESr/dO+cGnqhCoa0UkZB5wuB4dT3S02hRGSZsHO51Eon2NpzHPG9j+/alncwOe77Tw==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dismissable": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/popper": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" }, "peerDependencies": { "@internationalized/date": ">=3.0.0" } }, "node_modules/@zag-js/timer": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/timer/-/timer-1.15.0.tgz", - "integrity": "sha512-gDsYm4C9yju7g/r5u7n7mRQ2UY7diXXVbbLFr5Ja+0iUXgbD+uoSZEt9HypVc5TL9NWEEwn5/tut36owEeW4rw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/timer/-/timer-1.15.2.tgz", + "integrity": "sha512-v8RN3cwFuNXxuDMuxxfXKCSd+Z1UT6Ct+ueU3PRZqHqXU9u4k9Mm+vROIqnNzhCCdIHNxsqUt32/2zsRRaubbw==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/toast": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/toast/-/toast-1.15.0.tgz", - "integrity": "sha512-0RupMCXyGr7/La4Zlei7VqBF0VPNJelGd7zimLboe+IKZyy4Ypi/N2IX14rl8JZQDsDEgkLUl33xrSk/9RW2nQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/toast/-/toast-1.15.2.tgz", + "integrity": "sha512-OohJvGTy+J1MpydJ4eCV36picggfF9VbDW4nK97TT+4bIIRDgW+PGYgB4dd+PvEjRrk9194Kkm93lud95yOyZg==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dismissable": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/toggle": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/toggle/-/toggle-1.15.0.tgz", - "integrity": "sha512-mMSQ1+f1hOMp/7gLA7rTeiSNyeZxsCjRxP4XnTBY4BxJ5LswLuhem9CplBwaVthkhY1Y/5f3HHu80LBcfF+BVQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/toggle/-/toggle-1.15.2.tgz", + "integrity": "sha512-wtDeIRhDeVhaUboWQ2GrxlCC4+cLRyZzvZiN84tad7H/sUKq9hNDdROcCnIYBhEkb1Qf4sjR8KszY12YLtJx6A==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/toggle-group": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/toggle-group/-/toggle-group-1.15.0.tgz", - "integrity": "sha512-992vMz/2sriLrUKI3LpT/01kCGTbPGLgGLibiHRt562i0v9+2tV+GiY2jBctHZjJaKPrzBY3H0l8CCCvDj8gng==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/toggle-group/-/toggle-group-1.15.2.tgz", + "integrity": "sha512-JhWV0GY2NRgDhlzP73ADlG1E4NFXqv1h2q5+m3Rmos+Bi8soOV437jch/wy+M+xYN5vdZCczXJu9BumHNlknhA==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/tooltip": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/tooltip/-/tooltip-1.15.0.tgz", - "integrity": "sha512-sOpVECyfdS4RZBx46mSV+RPc9C5k9JvYQYUfoOVWh0E5RLSEz5bQm5xxctKOHfCOv+vJNTfG5gP596B1r2+Fkw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/tooltip/-/tooltip-1.15.2.tgz", + "integrity": "sha512-Spw5ewga3DNaT5H4AnrtsxJ6ebRoTxy+igwojGTYUCNUoxyQn6W3UpqZpgAAfw8B236bduTRh9MW9CsaM/hnmg==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/focus-visible": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/store": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/focus-visible": "1.15.2", + "@zag-js/popper": "1.15.2", + "@zag-js/store": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/tour": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/tour/-/tour-1.15.0.tgz", - "integrity": "sha512-EplcxoiE0z9vI0z6675+ABclQ9Mi1YUWhDZOHx7wfjRzpfawmJoBAlNDKzK3wc801d6OxgJx69SPj7ac0BwwwA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/tour/-/tour-1.15.2.tgz", + "integrity": "sha512-OW+autOwwsVMGwcYCxdCh3Hibeeag6Sg8w02XfmX7E+T2u9a+GGdLOrH7DPM2oHTbZV0iBUqIaKxGPKgRYZNng==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/focus-trap": "1.15.0", - "@zag-js/interact-outside": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dismissable": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/focus-trap": "1.15.2", + "@zag-js/interact-outside": "1.15.2", + "@zag-js/popper": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/tree-view": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/tree-view/-/tree-view-1.15.0.tgz", - "integrity": "sha512-wqdd+hu1bDOCWtnZ8MarRFHqbZF2t8qKBM3kO42IBq7jTI/93LCkHSlceEPft9dgZ6Ea9km0YJMHhoTqCPZ/fw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/tree-view/-/tree-view-1.15.2.tgz", + "integrity": "sha512-HWDHH3rpGEz3IN5bsj8EHZnU0ttk8uJwBOnH3reYcFQEQskA8cmyzd7y9hdBEn8PzAns+iOjUBj49IVmoYpOIg==", "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/collection": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.15.2", + "@zag-js/collection": "1.15.2", + "@zag-js/core": "1.15.2", + "@zag-js/dom-query": "1.15.2", + "@zag-js/types": "1.15.2", + "@zag-js/utils": "1.15.2" } }, "node_modules/@zag-js/types": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/types/-/types-1.15.0.tgz", - "integrity": "sha512-lV2ov2M07BlmjDUCSwBeHxPApHI3oAiLytG94AqcYvQ0BtsCRo5T60yRQ0syFc6fHf0e9+kwt89uoIgfGFYfmw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/types/-/types-1.15.2.tgz", + "integrity": "sha512-qEHNRA/uOYQjvXzI/ie6vuOD74/p7w6MA4X1VoZEYF2/sbIQjlRn6SzpeV3RyFZBzl6WBO6RqV/XEbgpvGSb5w==", "license": "MIT", "dependencies": { "csstype": "3.1.3" } }, "node_modules/@zag-js/utils": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/utils/-/utils-1.15.0.tgz", - "integrity": "sha512-XctFny5H8C00BsougV40Yp0qVEj9M2d/NRme7B33mon9wG+3hscZwP6miJmF6BYI5Pgu6e2P0Sv45FddQU1Tkg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@zag-js/utils/-/utils-1.15.2.tgz", + "integrity": "sha512-JdlyGT6yfG2ub2FftrB6BidIlvD04cSwdKYJGb/M+NJ7p7uxnZUZMxAjeBmTLhM1nWbtJPVq3oDTYz/cBBZLng==", "license": "MIT" }, "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -3640,9 +3659,9 @@ } }, "node_modules/axios": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", - "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -4653,19 +4672,19 @@ } }, "node_modules/eslint": { - "version": "9.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz", - "integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==", + "version": "9.29.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.29.0.tgz", + "integrity": "sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.0", + "@eslint/config-array": "^0.20.1", "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.28.0", + "@eslint/js": "9.29.0", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -4677,9 +4696,9 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -4770,14 +4789,14 @@ } }, "node_modules/eslint-plugin-perfectionist": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.14.0.tgz", - "integrity": "sha512-BkhiOqzdum8vQSFgj1/q5+6UUWPMn4GELdxuX7uIsGegmAeH/+LnWsiVxgMrxalD0p68sYfMeKaHF1NfrpI/mg==", + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.15.0.tgz", + "integrity": "sha512-pC7PgoXyDnEXe14xvRUhBII8A3zRgggKqJFx2a82fjrItDs1BSI7zdZnQtM2yQvcyod6/ujmzb7ejKPx8lZTnw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.33.1", - "@typescript-eslint/utils": "^8.33.1", + "@typescript-eslint/types": "^8.34.1", + "@typescript-eslint/utils": "^8.34.1", "natural-orderby": "^5.0.0" }, "engines": { @@ -4788,9 +4807,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz", - "integrity": "sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.0.tgz", + "integrity": "sha512-8qsOYwkkGrahrgoUv76NZi23koqXOGiiEzXMrT8Q7VcYaUISR+5MorIUxfWqYXN0fN/31WbSrxCxFkVQ43wwrA==", "dev": true, "license": "MIT", "dependencies": { @@ -4980,9 +4999,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -4997,9 +5016,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5037,15 +5056,15 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5653,13 +5672,14 @@ } }, "node_modules/happy-dom": { - "version": "17.6.3", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-17.6.3.tgz", - "integrity": "sha512-UVIHeVhxmxedbWPCfgS55Jg2rDfwf2BCKeylcPSqazLz5w3Kri7Q4xdBJubsr/+VUzFLh0VjIvh13RaDA2/Xug==", + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-18.0.1.tgz", + "integrity": "sha512-qn+rKOW7KWpVTtgIUi6RVmTBZJSe2k0Db0vh1f7CWrWclkkc7/Q+FrOfkZIb2eiErLyqu5AXEzE7XthO9JVxRA==", "dev": true, "license": "MIT", "dependencies": { - "webidl-conversions": "^7.0.0", + "@types/node": "^20.0.0", + "@types/whatwg-mimetype": "^3.0.2", "whatwg-mimetype": "^3.0.0" }, "engines": { @@ -6482,9 +6502,9 @@ } }, "node_modules/loupe": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.4.tgz", + "integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==", "dev": true, "license": "MIT" }, @@ -6686,9 +6706,9 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/nanoid": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.9.tgz", - "integrity": "sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { @@ -7174,9 +7194,9 @@ } }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -7194,7 +7214,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -7212,9 +7232,9 @@ } }, "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.0.tgz", + "integrity": "sha512-ujSB9uXHJKzM/2GBuE0hBOUgC77CN3Bnpqa+g80bkv3T3A93wL/xlzDATHhnhkzifz/UE2SNOvmbTz5hSkDlHw==", "dev": true, "license": "MIT", "bin": { @@ -7383,9 +7403,9 @@ } }, "node_modules/react-hook-form": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.57.0.tgz", - "integrity": "sha512-RbEks3+cbvTP84l/VXGUZ+JMrKOS8ykQCRYdm5aYsxnDquL0vspsyNhGRO7pcH6hsZqWlPOjLye7rJqdtdAmlg==", + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.58.1.tgz", + "integrity": "sha512-Lml/KZYEEFfPhUVgE0RdCVpnC4yhW+PndRhbiTtdvSlQTL8IfVR+iQkBjLIvmmc6+GGoVeM11z37ktKFPAb0FA==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -8324,9 +8344,9 @@ } }, "node_modules/tinypool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.0.tgz", - "integrity": "sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "dev": true, "license": "MIT", "engines": { @@ -8500,15 +8520,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.34.0.tgz", - "integrity": "sha512-MRpfN7uYjTrTGigFCt8sRyNqJFhjN0WwZecldaqhWm+wy0gaRt8Edb/3cuUy0zdq2opJWT6iXINKAtewnDOltQ==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.35.0.tgz", + "integrity": "sha512-uEnz70b7kBz6eg/j0Czy6K5NivaYopgxRjsnAJ2Fx5oTLo3wefTHIbL7AkQr1+7tJCRVpTs/wiM8JR/11Loq9A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.34.0", - "@typescript-eslint/parser": "8.34.0", - "@typescript-eslint/utils": "8.34.0" + "@typescript-eslint/eslint-plugin": "8.35.0", + "@typescript-eslint/parser": "8.35.0", + "@typescript-eslint/utils": "8.35.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -8560,6 +8580,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, "node_modules/universal-cookie": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-8.0.1.tgz", @@ -8617,24 +8644,24 @@ } }, "node_modules/vite": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", - "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.0.tgz", + "integrity": "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", - "fdir": "^6.4.4", + "fdir": "^6.4.6", "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" + "postcss": "^8.5.6", + "rollup": "^4.40.0", + "tinyglobby": "^0.2.14" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -8643,14 +8670,14 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", - "less": "*", + "less": "^4.0.0", "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" @@ -8692,9 +8719,9 @@ } }, "node_modules/vite-node": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.3.tgz", - "integrity": "sha512-gc8aAifGuDIpZHrPjuHyP4dpQmYXqWw7D1GmDnWeNWP654UEXzVfQ5IHPSK5HaHkwB/+p1atpYpSdw/2kOv8iQ==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", "dev": true, "license": "MIT", "dependencies": { @@ -8731,9 +8758,9 @@ } }, "node_modules/vite/node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -8759,20 +8786,20 @@ } }, "node_modules/vitest": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.3.tgz", - "integrity": "sha512-E6U2ZFXe3N/t4f5BwUaVCKRLHqUpk1CBWeMh78UT4VaTPH/2dyvH6ALl29JTovEPu9dVKr/K/J4PkXgrMbw4Ww==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/expect": "3.2.3", - "@vitest/mocker": "3.2.3", - "@vitest/pretty-format": "^3.2.3", - "@vitest/runner": "3.2.3", - "@vitest/snapshot": "3.2.3", - "@vitest/spy": "3.2.3", - "@vitest/utils": "3.2.3", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", @@ -8783,10 +8810,10 @@ "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", - "tinypool": "^1.1.0", + "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", - "vite-node": "3.2.3", + "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "bin": { @@ -8802,8 +8829,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.2.3", - "@vitest/ui": "3.2.3", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, @@ -8851,15 +8878,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/whatwg-mimetype": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/package.json b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/package.json index 00eaa21191f91..70c6470b6826f 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/package.json +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite --port 5174", + "dev": "vite --port 5174 --strictPort", "build": "vite build", "lint": "eslint --quiet && tsc --p tsconfig.app.json", "lint:fix": "eslint --fix && tsc --p tsconfig.app.json", @@ -15,42 +15,42 @@ "coverage": "vitest run --coverage" }, "dependencies": { - "@chakra-ui/react": "^3.20.0", - "@tanstack/react-query": "^5.80.6", - "axios": "^1.9.0", + "@chakra-ui/react": "^3.21.0", + "@tanstack/react-query": "^5.81.2", + "axios": "^1.10.0", "next-themes": "^0.4.6", "react": "^19.1.0", "react-cookie": "^8.0.1", "react-dom": "^19.1.0", - "react-hook-form": "^7.57.0", + "react-hook-form": "^7.58.1", "react-router-dom": "^7.6.2" }, "devDependencies": { "@7nohe/openapi-react-query-codegen": "^1.6.2", - "@eslint/compat": "^1.2.9", - "@eslint/js": "^9.28.0", - "@stylistic/eslint-plugin": "^4.4.1", + "@eslint/compat": "^1.3.0", + "@eslint/js": "^9.29.0", + "@stylistic/eslint-plugin": "^5.0.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@trivago/prettier-plugin-sort-imports": "^5.2.2", - "@types/react": "^19.1.7", + "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", "@vitejs/plugin-react-swc": "^3.10.2", - "eslint": "^9.28.0", + "eslint": "^9.29.0", "eslint-config-prettier": "^10.1.5", "eslint-plugin-jsx-a11y": "^6.10.2", - "eslint-plugin-perfectionist": "^4.14.0", - "eslint-plugin-prettier": "^5.4.1", + "eslint-plugin-perfectionist": "^4.15.0", + "eslint-plugin-prettier": "^5.5.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-unicorn": "^59.0.1", - "happy-dom": "^17.6.3", - "prettier": "^3.5.3", + "happy-dom": "^18.0.1", + "prettier": "^3.6.0", "typescript": "~5.8.3", - "typescript-eslint": "^8.34.0", - "vite": "^6.3.5", + "typescript-eslint": "^8.35.0", + "vite": "^7.0.0", "vite-plugin-css-injected-by-js": "^3.5.2", - "vitest": "^3.2.3" + "vitest": "^3.2.4" } } diff --git a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/pnpm-lock.yaml b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/pnpm-lock.yaml index 824b7750660ac..7a3af4dc5acfa 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/pnpm-lock.yaml +++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/pnpm-lock.yaml @@ -9,14 +9,14 @@ importers: .: dependencies: '@chakra-ui/react': - specifier: ^3.20.0 - version: 3.20.0(@emotion/react@11.14.0(@types/react@19.1.7)(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^3.21.0 + version: 3.21.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@tanstack/react-query': - specifier: ^5.80.6 - version: 5.80.6(react@19.1.0) + specifier: ^5.81.2 + version: 5.81.2(react@19.1.0) axios: - specifier: ^1.9.0 - version: 1.9.0 + specifier: ^1.10.0 + version: 1.10.0 next-themes: specifier: ^0.4.6 version: 0.4.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -30,8 +30,8 @@ importers: specifier: ^19.1.0 version: 19.1.0(react@19.1.0) react-hook-form: - specifier: ^7.57.0 - version: 7.57.0(react@19.1.0) + specifier: ^7.58.1 + version: 7.58.1(react@19.1.0) react-router-dom: specifier: ^7.6.2 version: 7.6.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -40,80 +40,80 @@ importers: specifier: ^1.6.2 version: 1.6.2(commander@12.1.0)(glob@10.4.5)(magicast@0.3.5)(ts-morph@22.0.0)(typescript@5.8.3) '@eslint/compat': - specifier: ^1.2.9 - version: 1.2.9(eslint@9.28.0(jiti@1.21.7)) + specifier: ^1.3.0 + version: 1.3.0(eslint@9.29.0(jiti@1.21.7)) '@eslint/js': - specifier: ^9.28.0 - version: 9.28.0 + specifier: ^9.29.0 + version: 9.29.0 '@stylistic/eslint-plugin': - specifier: ^4.4.1 - version: 4.4.1(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3) + specifier: ^5.0.0 + version: 5.0.0(eslint@9.29.0(jiti@1.21.7)) '@testing-library/jest-dom': specifier: ^6.6.3 version: 6.6.3 '@testing-library/react': specifier: ^16.3.0 - version: 16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@trivago/prettier-plugin-sort-imports': specifier: ^5.2.2 - version: 5.2.2(prettier@3.5.3) + version: 5.2.2(prettier@3.6.0) '@types/react': - specifier: ^19.1.7 - version: 19.1.7 + specifier: ^19.1.8 + version: 19.1.8 '@types/react-dom': specifier: ^19.1.6 - version: 19.1.6(@types/react@19.1.7) + version: 19.1.6(@types/react@19.1.8) '@vitejs/plugin-react-swc': specifier: ^3.10.2 - version: 3.10.2(@swc/helpers@0.5.17)(vite@6.3.5(jiti@1.21.7)) + version: 3.10.2(@swc/helpers@0.5.17)(vite@7.0.0(@types/node@20.19.1)(jiti@1.21.7)) eslint: - specifier: ^9.28.0 - version: 9.28.0(jiti@1.21.7) + specifier: ^9.29.0 + version: 9.29.0(jiti@1.21.7) eslint-config-prettier: specifier: ^10.1.5 - version: 10.1.5(eslint@9.28.0(jiti@1.21.7)) + version: 10.1.5(eslint@9.29.0(jiti@1.21.7)) eslint-plugin-jsx-a11y: specifier: ^6.10.2 - version: 6.10.2(eslint@9.28.0(jiti@1.21.7)) + version: 6.10.2(eslint@9.29.0(jiti@1.21.7)) eslint-plugin-perfectionist: - specifier: ^4.14.0 - version: 4.14.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3) + specifier: ^4.15.0 + version: 4.15.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3) eslint-plugin-prettier: - specifier: ^5.4.1 - version: 5.4.1(eslint-config-prettier@10.1.5(eslint@9.28.0(jiti@1.21.7)))(eslint@9.28.0(jiti@1.21.7))(prettier@3.5.3) + specifier: ^5.5.0 + version: 5.5.0(eslint-config-prettier@10.1.5(eslint@9.29.0(jiti@1.21.7)))(eslint@9.29.0(jiti@1.21.7))(prettier@3.6.0) eslint-plugin-react: specifier: ^7.37.5 - version: 7.37.5(eslint@9.28.0(jiti@1.21.7)) + version: 7.37.5(eslint@9.29.0(jiti@1.21.7)) eslint-plugin-react-hooks: specifier: ^5.2.0 - version: 5.2.0(eslint@9.28.0(jiti@1.21.7)) + version: 5.2.0(eslint@9.29.0(jiti@1.21.7)) eslint-plugin-react-refresh: specifier: ^0.4.20 - version: 0.4.20(eslint@9.28.0(jiti@1.21.7)) + version: 0.4.20(eslint@9.29.0(jiti@1.21.7)) eslint-plugin-unicorn: specifier: ^59.0.1 - version: 59.0.1(eslint@9.28.0(jiti@1.21.7)) + version: 59.0.1(eslint@9.29.0(jiti@1.21.7)) happy-dom: - specifier: ^17.6.3 - version: 17.6.3 + specifier: ^18.0.1 + version: 18.0.1 prettier: - specifier: ^3.5.3 - version: 3.5.3 + specifier: ^3.6.0 + version: 3.6.0 typescript: specifier: ~5.8.3 version: 5.8.3 typescript-eslint: - specifier: ^8.34.0 - version: 8.34.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3) + specifier: ^8.35.0 + version: 8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3) vite: - specifier: ^6.3.5 - version: 6.3.5(jiti@1.21.7) + specifier: ^7.0.0 + version: 7.0.0(@types/node@20.19.1)(jiti@1.21.7) vite-plugin-css-injected-by-js: specifier: ^3.5.2 - version: 3.5.2(vite@6.3.5(jiti@1.21.7)) + version: 3.5.2(vite@7.0.0(@types/node@20.19.1)(jiti@1.21.7)) vitest: - specifier: ^3.2.3 - version: 3.2.3(happy-dom@17.6.3)(jiti@1.21.7) + specifier: ^3.2.4 + version: 3.2.4(@types/node@20.19.1)(happy-dom@18.0.1)(jiti@1.21.7) packages: @@ -134,8 +134,8 @@ packages: resolution: {integrity: sha512-9K6xOqeevacvweLGik6LnZCb1fBtCOSIWQs8d096XGeqoLKC33UVMGz9+77Gw44KvbH4pKcQPWo4ZpxkXYj05w==} engines: {node: '>= 16'} - '@ark-ui/react@5.12.0': - resolution: {integrity: sha512-UV89EqyESZoyr6rtvrbFJn/FejpswhvRVcfK44dZDU6h6UY8CxfR/6Ayvrq9UtFdD0dEawqwWrXS22l8Y05Nnw==} + '@ark-ui/react@5.14.0': + resolution: {integrity: sha512-7WWlCM3SowtF01e9NouuO4T6SYuKTM1dovR+2NZuuWTlqTBlvZ+1vPHS6BeqzXriwMLU7QUU+Y0i/TcI6/s/Sg==} peerDependencies: react: '>=18.0.0' react-dom: '>=18.0.0' @@ -206,8 +206,8 @@ packages: resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} engines: {node: '>=6.9.0'} - '@chakra-ui/react@3.20.0': - resolution: {integrity: sha512-zHYQAUqrT2pZZ/Xi+sskRC/An9q4ZelLPJkFHdobftTYkcFo1FtkMbBO0AEBZhb/6mZGyfw3JLflSawkuR++uQ==} + '@chakra-ui/react@3.21.0': + resolution: {integrity: sha512-Ajw6GuUhfNhMagTM9cO1Lg/w/HSQUwsv55j2QvvvPw/dk01wHiGi1aihfuCLpa6QY4ElLNs6SS3f78xI9Fwo6A==} peerDependencies: '@emotion/react': '>=11' react: '>=18' @@ -257,152 +257,152 @@ packages: '@emotion/weak-memoize@0.4.0': resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - '@esbuild/aix-ppc64@0.25.4': - resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==} + '@esbuild/aix-ppc64@0.25.5': + resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.4': - resolution: {integrity: sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==} + '@esbuild/android-arm64@0.25.5': + resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.4': - resolution: {integrity: sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==} + '@esbuild/android-arm@0.25.5': + resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.4': - resolution: {integrity: sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==} + '@esbuild/android-x64@0.25.5': + resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.4': - resolution: {integrity: sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==} + '@esbuild/darwin-arm64@0.25.5': + resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.4': - resolution: {integrity: sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==} + '@esbuild/darwin-x64@0.25.5': + resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.4': - resolution: {integrity: sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==} + '@esbuild/freebsd-arm64@0.25.5': + resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.4': - resolution: {integrity: sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==} + '@esbuild/freebsd-x64@0.25.5': + resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.4': - resolution: {integrity: sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==} + '@esbuild/linux-arm64@0.25.5': + resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.4': - resolution: {integrity: sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==} + '@esbuild/linux-arm@0.25.5': + resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.4': - resolution: {integrity: sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==} + '@esbuild/linux-ia32@0.25.5': + resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.4': - resolution: {integrity: sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==} + '@esbuild/linux-loong64@0.25.5': + resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.4': - resolution: {integrity: sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==} + '@esbuild/linux-mips64el@0.25.5': + resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.4': - resolution: {integrity: sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==} + '@esbuild/linux-ppc64@0.25.5': + resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.4': - resolution: {integrity: sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==} + '@esbuild/linux-riscv64@0.25.5': + resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.4': - resolution: {integrity: sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==} + '@esbuild/linux-s390x@0.25.5': + resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.4': - resolution: {integrity: sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==} + '@esbuild/linux-x64@0.25.5': + resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.4': - resolution: {integrity: sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==} + '@esbuild/netbsd-arm64@0.25.5': + resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.4': - resolution: {integrity: sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==} + '@esbuild/netbsd-x64@0.25.5': + resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.4': - resolution: {integrity: sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==} + '@esbuild/openbsd-arm64@0.25.5': + resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.4': - resolution: {integrity: sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==} + '@esbuild/openbsd-x64@0.25.5': + resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.25.4': - resolution: {integrity: sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==} + '@esbuild/sunos-x64@0.25.5': + resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.4': - resolution: {integrity: sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==} + '@esbuild/win32-arm64@0.25.5': + resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.4': - resolution: {integrity: sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==} + '@esbuild/win32-ia32@0.25.5': + resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.4': - resolution: {integrity: sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==} + '@esbuild/win32-x64@0.25.5': + resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -417,8 +417,8 @@ packages: resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/compat@1.2.9': - resolution: {integrity: sha512-gCdSY54n7k+driCadyMNv8JSPzYLeDVM/ikZRtvtROBpRdFSkS8W9A82MqsaY7lZuwL0wiapgD0NT1xT0hyJsA==} + '@eslint/compat@1.3.0': + resolution: {integrity: sha512-ZBygRBqpDYiIHsN+d1WyHn3TYgzgpzLEcgJUxTATyiInQbKZz6wZb6+ljwdg8xeeOe4v03z6Uh6lELiw0/mVhQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^9.10.0 @@ -426,12 +426,12 @@ packages: eslint: optional: true - '@eslint/config-array@0.20.0': - resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} + '@eslint/config-array@0.20.1': + resolution: {integrity: sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.2.2': - resolution: {integrity: sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==} + '@eslint/config-helpers@0.2.3': + resolution: {integrity: sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/core@0.13.0': @@ -442,12 +442,16 @@ packages: resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.15.0': + resolution: {integrity: sha512-b7ePw78tEWWkpgZCDYkbqDOP8dmM6qe+AOC6iuJqlq1R/0ahMAeH3qynpnqKFGkMltrp44ohV4ubGyvLX28tzw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@3.3.1': resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.28.0': - resolution: {integrity: sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==} + '@eslint/js@9.29.0': + resolution: {integrity: sha512-3PIF4cBw/y+1u2EazflInpV+lYsSG0aByVIQzAgb1m1MhHFSbqTyNqtBKHgWf/9Ykud+DhILS9EGkmekVhbKoQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': @@ -458,8 +462,8 @@ packages: resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.3.1': - resolution: {integrity: sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==} + '@eslint/plugin-kit@0.3.2': + resolution: {integrity: sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@floating-ui/core@1.7.1': @@ -498,11 +502,11 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@internationalized/date@3.8.1': - resolution: {integrity: sha512-PgVE6B6eIZtzf9Gu5HvJxRK3ufUFz9DhspELuhW/N0GuMGMTLvPQNRkHP2hTuP9lblOk+f+1xi96sPiPXANXAA==} + '@internationalized/date@3.8.2': + resolution: {integrity: sha512-/wENk7CbvLbkUvX1tu0mwq49CVkkWpkXubGel6birjRPyo6uQ4nQpnq5xZu823zRCwwn82zgHrvgF1vZyvmVgA==} - '@internationalized/number@3.6.2': - resolution: {integrity: sha512-E5QTOlMg9wo5OrKdHD6edo1JJlIoOsylh0+mbf0evi1tHJwMZfJSaBpGtnJV9N7w3jeiioox9EG/EWRWPh82vg==} + '@internationalized/number@3.6.3': + resolution: {integrity: sha512-p+Zh1sb6EfrfVaS86jlHGQ9HA66fJhV9x5LiE5vCbZtXEHAuhcmUZUdZ4WrFpUBfNalr2OkAJI5AcKEQF+Lebw==} '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} @@ -555,108 +559,108 @@ packages: '@rolldown/pluginutils@1.0.0-beta.11': resolution: {integrity: sha512-L/gAA/hyCSuzTF1ftlzUSI/IKr2POHsv1Dd78GfqkR83KMNuswWD61JxGV2L7nRwBBBSDr6R1gCkdTmoN7W4ag==} - '@rollup/rollup-android-arm-eabi@4.40.2': - resolution: {integrity: sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==} + '@rollup/rollup-android-arm-eabi@4.44.0': + resolution: {integrity: sha512-xEiEE5oDW6tK4jXCAyliuntGR+amEMO7HLtdSshVuhFnKTYoeYMyXQK7pLouAJJj5KHdwdn87bfHAR2nSdNAUA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.40.2': - resolution: {integrity: sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==} + '@rollup/rollup-android-arm64@4.44.0': + resolution: {integrity: sha512-uNSk/TgvMbskcHxXYHzqwiyBlJ/lGcv8DaUfcnNwict8ba9GTTNxfn3/FAoFZYgkaXXAdrAA+SLyKplyi349Jw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.40.2': - resolution: {integrity: sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==} + '@rollup/rollup-darwin-arm64@4.44.0': + resolution: {integrity: sha512-VGF3wy0Eq1gcEIkSCr8Ke03CWT+Pm2yveKLaDvq51pPpZza3JX/ClxXOCmTYYq3us5MvEuNRTaeyFThCKRQhOA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.40.2': - resolution: {integrity: sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==} + '@rollup/rollup-darwin-x64@4.44.0': + resolution: {integrity: sha512-fBkyrDhwquRvrTxSGH/qqt3/T0w5Rg0L7ZIDypvBPc1/gzjJle6acCpZ36blwuwcKD/u6oCE/sRWlUAcxLWQbQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.40.2': - resolution: {integrity: sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==} + '@rollup/rollup-freebsd-arm64@4.44.0': + resolution: {integrity: sha512-u5AZzdQJYJXByB8giQ+r4VyfZP+walV+xHWdaFx/1VxsOn6eWJhK2Vl2eElvDJFKQBo/hcYIBg/jaKS8ZmKeNQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.40.2': - resolution: {integrity: sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==} + '@rollup/rollup-freebsd-x64@4.44.0': + resolution: {integrity: sha512-qC0kS48c/s3EtdArkimctY7h3nHicQeEUdjJzYVJYR3ct3kWSafmn6jkNCA8InbUdge6PVx6keqjk5lVGJf99g==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.40.2': - resolution: {integrity: sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==} + '@rollup/rollup-linux-arm-gnueabihf@4.44.0': + resolution: {integrity: sha512-x+e/Z9H0RAWckn4V2OZZl6EmV0L2diuX3QB0uM1r6BvhUIv6xBPL5mrAX2E3e8N8rEHVPwFfz/ETUbV4oW9+lQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.40.2': - resolution: {integrity: sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==} + '@rollup/rollup-linux-arm-musleabihf@4.44.0': + resolution: {integrity: sha512-1exwiBFf4PU/8HvI8s80icyCcnAIB86MCBdst51fwFmH5dyeoWVPVgmQPcKrMtBQ0W5pAs7jBCWuRXgEpRzSCg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.40.2': - resolution: {integrity: sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==} + '@rollup/rollup-linux-arm64-gnu@4.44.0': + resolution: {integrity: sha512-ZTR2mxBHb4tK4wGf9b8SYg0Y6KQPjGpR4UWwTFdnmjB4qRtoATZ5dWn3KsDwGa5Z2ZBOE7K52L36J9LueKBdOQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.40.2': - resolution: {integrity: sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==} + '@rollup/rollup-linux-arm64-musl@4.44.0': + resolution: {integrity: sha512-GFWfAhVhWGd4r6UxmnKRTBwP1qmModHtd5gkraeW2G490BpFOZkFtem8yuX2NyafIP/mGpRJgTJ2PwohQkUY/Q==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.40.2': - resolution: {integrity: sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==} + '@rollup/rollup-linux-loongarch64-gnu@4.44.0': + resolution: {integrity: sha512-xw+FTGcov/ejdusVOqKgMGW3c4+AgqrfvzWEVXcNP6zq2ue+lsYUgJ+5Rtn/OTJf7e2CbgTFvzLW2j0YAtj0Gg==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.40.2': - resolution: {integrity: sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==} + '@rollup/rollup-linux-powerpc64le-gnu@4.44.0': + resolution: {integrity: sha512-bKGibTr9IdF0zr21kMvkZT4K6NV+jjRnBoVMt2uNMG0BYWm3qOVmYnXKzx7UhwrviKnmK46IKMByMgvpdQlyJQ==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.40.2': - resolution: {integrity: sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==} + '@rollup/rollup-linux-riscv64-gnu@4.44.0': + resolution: {integrity: sha512-vV3cL48U5kDaKZtXrti12YRa7TyxgKAIDoYdqSIOMOFBXqFj2XbChHAtXquEn2+n78ciFgr4KIqEbydEGPxXgA==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.40.2': - resolution: {integrity: sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==} + '@rollup/rollup-linux-riscv64-musl@4.44.0': + resolution: {integrity: sha512-TDKO8KlHJuvTEdfw5YYFBjhFts2TR0VpZsnLLSYmB7AaohJhM8ctDSdDnUGq77hUh4m/djRafw+9zQpkOanE2Q==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.40.2': - resolution: {integrity: sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==} + '@rollup/rollup-linux-s390x-gnu@4.44.0': + resolution: {integrity: sha512-8541GEyktXaw4lvnGp9m84KENcxInhAt6vPWJ9RodsB/iGjHoMB2Pp5MVBCiKIRxrxzJhGCxmNzdu+oDQ7kwRA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.40.2': - resolution: {integrity: sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==} + '@rollup/rollup-linux-x64-gnu@4.44.0': + resolution: {integrity: sha512-iUVJc3c0o8l9Sa/qlDL2Z9UP92UZZW1+EmQ4xfjTc1akr0iUFZNfxrXJ/R1T90h/ILm9iXEY6+iPrmYB3pXKjw==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.40.2': - resolution: {integrity: sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==} + '@rollup/rollup-linux-x64-musl@4.44.0': + resolution: {integrity: sha512-PQUobbhLTQT5yz/SPg116VJBgz+XOtXt8D1ck+sfJJhuEsMj2jSej5yTdp8CvWBSceu+WW+ibVL6dm0ptG5fcA==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.40.2': - resolution: {integrity: sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==} + '@rollup/rollup-win32-arm64-msvc@4.44.0': + resolution: {integrity: sha512-M0CpcHf8TWn+4oTxJfh7LQuTuaYeXGbk0eageVjQCKzYLsajWS/lFC94qlRqOlyC2KvRT90ZrfXULYmukeIy7w==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.40.2': - resolution: {integrity: sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==} + '@rollup/rollup-win32-ia32-msvc@4.44.0': + resolution: {integrity: sha512-3XJ0NQtMAXTWFW8FqZKcw3gOQwBtVWP/u8TpHP3CRPXD7Pd6s8lLdH3sHWh8vqKCyyiI8xW5ltJScQmBU9j7WA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.40.2': - resolution: {integrity: sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==} + '@rollup/rollup-win32-x64-msvc@4.44.0': + resolution: {integrity: sha512-Q2Mgwt+D8hd5FIPUuPDsvPR7Bguza6yTkJxspDGkZj7tBRn2y4KSWYuIXpftFSjBra76TbKerCV7rgFPQrn+wQ==} cpu: [x64] os: [win32] - '@stylistic/eslint-plugin@4.4.1': - resolution: {integrity: sha512-CEigAk7eOLyHvdgmpZsKFwtiqS2wFwI1fn4j09IU9GmD4euFM4jEBAViWeCqaNLlbX2k2+A/Fq9cje4HQBXuJQ==} + '@stylistic/eslint-plugin@5.0.0': + resolution: {integrity: sha512-nVV2FSzeTJ3oFKw+3t9gQYQcrgbopgCASSY27QOtkhEGgSfdQQjDmzZd41NeT1myQ8Wc6l+pZllST9qIu4NKzg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=9.0.0' @@ -739,11 +743,11 @@ packages: '@swc/types@0.1.22': resolution: {integrity: sha512-D13mY/ZA4PPEFSy6acki9eBT/3WgjMoRqNcdpIvjaYLQ44Xk5BdaL7UkDxAh6Z9UOe7tCCp67BVmZCojYp9owg==} - '@tanstack/query-core@5.80.6': - resolution: {integrity: sha512-nl7YxT/TAU+VTf+e2zTkObGTyY8YZBMnbgeA1ee66lIVqzKlYursAII6z5t0e6rXgwUMJSV4dshBTNacNpZHbQ==} + '@tanstack/query-core@5.81.2': + resolution: {integrity: sha512-QLYkPdrudoMATDFa3MiLEwRhNnAlzHWDf0LKaXUqJd0/+QxN8uTPi7bahRlxoAyH0UbLMBdeDbYzWALj7THOtw==} - '@tanstack/react-query@5.80.6': - resolution: {integrity: sha512-izX+5CnkpON3NQGcEm3/d7LfFQNo9ZpFtX2QsINgCYK9LT2VCIdi8D3bMaMSNhrAJCznRoAkFic76uvLroALBw==} + '@tanstack/react-query@5.81.2': + resolution: {integrity: sha512-pe8kFlTrL2zFLlcAj2kZk9UaYYHDk9/1hg9EBaoO3cxDhOZf1FRGJeziSXKrVZyxIfs7b3aoOj/bw7Lie0mDUg==} peerDependencies: react: ^18 || ^19 @@ -798,9 +802,6 @@ packages: '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} - '@types/estree@1.0.7': - resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} - '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -810,6 +811,9 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/node@20.19.1': + resolution: {integrity: sha512-jJD50LtlD2dodAEO653i3YF04NWak6jN3ky+Ri3Em3mGR39/glWiboM/IePaRbgwSfqM1TpGXfAg8ohn/4dTgA==} + '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -818,103 +822,106 @@ packages: peerDependencies: '@types/react': ^19.0.0 - '@types/react@19.1.7': - resolution: {integrity: sha512-BnsPLV43ddr05N71gaGzyZ5hzkCmGwhMvYc8zmvI8Ci1bRkkDSzDDVfAXfN2tk748OwI7ediiPX6PfT9p0QGVg==} + '@types/react@19.1.8': + resolution: {integrity: sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==} - '@typescript-eslint/eslint-plugin@8.34.0': - resolution: {integrity: sha512-QXwAlHlbcAwNlEEMKQS2RCgJsgXrTJdjXT08xEgbPFa2yYQgVjBymxP5DrfrE7X7iodSzd9qBUHUycdyVJTW1w==} + '@types/whatwg-mimetype@3.0.2': + resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} + + '@typescript-eslint/eslint-plugin@8.35.0': + resolution: {integrity: sha512-ijItUYaiWuce0N1SoSMrEd0b6b6lYkYt99pqCPfybd+HKVXtEvYhICfLdwp42MhiI5mp0oq7PKEL+g1cNiz/Eg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.34.0 + '@typescript-eslint/parser': ^8.35.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/parser@8.34.0': - resolution: {integrity: sha512-vxXJV1hVFx3IXz/oy2sICsJukaBrtDEQSBiV48/YIV5KWjX1dO+bcIr/kCPrW6weKXvsaGKFNlwH0v2eYdRRbA==} + '@typescript-eslint/parser@8.35.0': + resolution: {integrity: sha512-6sMvZePQrnZH2/cJkwRpkT7DxoAWh+g6+GFRK6bV3YQo7ogi3SX5rgF6099r5Q53Ma5qeT7LGmOmuIutF4t3lA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/project-service@8.33.1': - resolution: {integrity: sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==} + '@typescript-eslint/project-service@8.34.1': + resolution: {integrity: sha512-nuHlOmFZfuRwLJKDGQOVc0xnQrAmuq1Mj/ISou5044y1ajGNp2BNliIqp7F2LPQ5sForz8lempMFCovfeS1XoA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/project-service@8.34.0': - resolution: {integrity: sha512-iEgDALRf970/B2YExmtPMPF54NenZUf4xpL3wsCRx/lgjz6ul/l13R81ozP/ZNuXfnLCS+oPmG7JIxfdNYKELw==} + '@typescript-eslint/project-service@8.35.0': + resolution: {integrity: sha512-41xatqRwWZuhUMF/aZm2fcUsOFKNcG28xqRSS6ZVr9BVJtGExosLAm5A1OxTjRMagx8nJqva+P5zNIGt8RIgbQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/scope-manager@8.33.1': - resolution: {integrity: sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==} + '@typescript-eslint/scope-manager@8.34.1': + resolution: {integrity: sha512-beu6o6QY4hJAgL1E8RaXNC071G4Kso2MGmJskCFQhRhg8VOH/FDbC8soP8NHN7e/Hdphwp8G8cE6OBzC8o41ZA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/scope-manager@8.34.0': - resolution: {integrity: sha512-9Ac0X8WiLykl0aj1oYQNcLZjHgBojT6cW68yAgZ19letYu+Hxd0rE0veI1XznSSst1X5lwnxhPbVdwjDRIomRw==} + '@typescript-eslint/scope-manager@8.35.0': + resolution: {integrity: sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.33.1': - resolution: {integrity: sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==} + '@typescript-eslint/tsconfig-utils@8.34.1': + resolution: {integrity: sha512-K4Sjdo4/xF9NEeA2khOb7Y5nY6NSXBnod87uniVYW9kHP+hNlDV8trUSFeynA2uxWam4gIWgWoygPrv9VMWrYg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/tsconfig-utils@8.34.0': - resolution: {integrity: sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA==} + '@typescript-eslint/tsconfig-utils@8.35.0': + resolution: {integrity: sha512-04k/7247kZzFraweuEirmvUj+W3bJLI9fX6fbo1Qm2YykuBvEhRTPl8tcxlYO8kZZW+HIXfkZNoasVb8EV4jpA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/type-utils@8.34.0': - resolution: {integrity: sha512-n7zSmOcUVhcRYC75W2pnPpbO1iwhJY3NLoHEtbJwJSNlVAZuwqu05zY3f3s2SDWWDSo9FdN5szqc73DCtDObAg==} + '@typescript-eslint/type-utils@8.35.0': + resolution: {integrity: sha512-ceNNttjfmSEoM9PW87bWLDEIaLAyR+E6BoYJQ5PfaDau37UGca9Nyq3lBk8Bw2ad0AKvYabz6wxc7DMTO2jnNA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/types@8.33.1': - resolution: {integrity: sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==} + '@typescript-eslint/types@8.34.1': + resolution: {integrity: sha512-rjLVbmE7HR18kDsjNIZQHxmv9RZwlgzavryL5Lnj2ujIRTeXlKtILHgRNmQ3j4daw7zd+mQgy+uyt6Zo6I0IGA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.34.0': - resolution: {integrity: sha512-9V24k/paICYPniajHfJ4cuAWETnt7Ssy+R0Rbcqo5sSFr3QEZ/8TSoUi9XeXVBGXCaLtwTOKSLGcInCAvyZeMA==} + '@typescript-eslint/types@8.35.0': + resolution: {integrity: sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.33.1': - resolution: {integrity: sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==} + '@typescript-eslint/typescript-estree@8.34.1': + resolution: {integrity: sha512-rjCNqqYPuMUF5ODD+hWBNmOitjBWghkGKJg6hiCHzUvXRy6rK22Jd3rwbP2Xi+R7oYVvIKhokHVhH41BxPV5mA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/typescript-estree@8.34.0': - resolution: {integrity: sha512-rOi4KZxI7E0+BMqG7emPSK1bB4RICCpF7QD3KCLXn9ZvWoESsOMlHyZPAHyG04ujVplPaHbmEvs34m+wjgtVtg==} + '@typescript-eslint/typescript-estree@8.35.0': + resolution: {integrity: sha512-F+BhnaBemgu1Qf8oHrxyw14wq6vbL8xwWKKMwTMwYIRmFFY/1n/9T/jpbobZL8vp7QyEUcC6xGrnAO4ua8Kp7w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/utils@8.33.1': - resolution: {integrity: sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==} + '@typescript-eslint/utils@8.34.1': + resolution: {integrity: sha512-mqOwUdZ3KjtGk7xJJnLbHxTuWVn3GO2WZZuM+Slhkun4+qthLdXx32C8xIXbO1kfCECb3jIs3eoxK3eryk7aoQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/utils@8.34.0': - resolution: {integrity: sha512-8L4tWatGchV9A1cKbjaavS6mwYwp39jql8xUmIIKJdm+qiaeHy5KMKlBrf30akXAWBzn2SqKsNOtSENWUwg7XQ==} + '@typescript-eslint/utils@8.35.0': + resolution: {integrity: sha512-nqoMu7WWM7ki5tPgLVsmPM8CkqtoPUG6xXGeefM5t4x3XumOEKMoUZPdi+7F+/EotukN4R9OWdmDxN80fqoZeg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/visitor-keys@8.33.1': - resolution: {integrity: sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==} + '@typescript-eslint/visitor-keys@8.34.1': + resolution: {integrity: sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.34.0': - resolution: {integrity: sha512-qHV7pW7E85A0x6qyrFn+O+q1k1p3tQCsqIZ1KZ5ESLXY57aTvUd3/a4rdPTeXisvhXn2VQG0VSKUqs8KHF2zcA==} + '@typescript-eslint/visitor-keys@8.35.0': + resolution: {integrity: sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@vitejs/plugin-react-swc@3.10.2': @@ -922,11 +929,11 @@ packages: peerDependencies: vite: ^4 || ^5 || ^6 || ^7.0.0-beta.0 - '@vitest/expect@3.2.3': - resolution: {integrity: sha512-W2RH2TPWVHA1o7UmaFKISPvdicFJH+mjykctJFoAkUw+SPTJTGjUNdKscFBrqM7IPnCVu6zihtKYa7TkZS1dkQ==} + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} - '@vitest/mocker@3.2.3': - resolution: {integrity: sha512-cP6fIun+Zx8he4rbWvi+Oya6goKQDZK+Yq4hhlggwQBbrlOQ4qtZ+G4nxB6ZnzI9lyIb+JnvyiJnPC2AGbKSPA==} + '@vitest/mocker@3.2.4': + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} peerDependencies: msw: ^2.4.9 vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 @@ -936,238 +943,238 @@ packages: vite: optional: true - '@vitest/pretty-format@3.2.3': - resolution: {integrity: sha512-yFglXGkr9hW/yEXngO+IKMhP0jxyFw2/qys/CK4fFUZnSltD+MU7dVYGrH8rvPcK/O6feXQA+EU33gjaBBbAng==} + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} - '@vitest/runner@3.2.3': - resolution: {integrity: sha512-83HWYisT3IpMaU9LN+VN+/nLHVBCSIUKJzGxC5RWUOsK1h3USg7ojL+UXQR3b4o4UBIWCYdD2fxuzM7PQQ1u8w==} + '@vitest/runner@3.2.4': + resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} - '@vitest/snapshot@3.2.3': - resolution: {integrity: sha512-9gIVWx2+tysDqUmmM1L0hwadyumqssOL1r8KJipwLx5JVYyxvVRfxvMq7DaWbZZsCqZnu/dZedaZQh4iYTtneA==} + '@vitest/snapshot@3.2.4': + resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} - '@vitest/spy@3.2.3': - resolution: {integrity: sha512-JHu9Wl+7bf6FEejTCREy+DmgWe+rQKbK+y32C/k5f4TBIAlijhJbRBIRIOCEpVevgRsCQR2iHRUH2/qKVM/plw==} + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} - '@vitest/utils@3.2.3': - resolution: {integrity: sha512-4zFBCU5Pf+4Z6v+rwnZ1HU1yzOKKvDkMXZrymE2PBlbjKJRlrOxbvpfPSvJTGRIwGoahaOGvp+kbCoxifhzJ1Q==} + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} - '@zag-js/accordion@1.15.0': - resolution: {integrity: sha512-EKNeuKx+lOQ/deCe/ApCjVPxpxpDwT2NXvMPL+YvqXmSv7hAnTLs9fDKjbDUQUMmsyx32BsBd8t6d17DL3rPXg==} + '@zag-js/accordion@1.15.2': + resolution: {integrity: sha512-4ooxmmnEDeRLPLOCsrQeLHcTj+xTqBHm6pYEdho/pb67lHujAUSnbfEryorBSfvJEWdiUTYts96EfsLfbn5SYA==} - '@zag-js/anatomy@1.15.0': - resolution: {integrity: sha512-r0l5I7mSsF35HdwXm22TppNhfVftFuqvKfHvTUw+wQZhni4eUL93HypJD0Fl7mDhtP5zfVGfBwR048OzD0+tCw==} + '@zag-js/anatomy@1.15.2': + resolution: {integrity: sha512-GiWZk+fqO/W15FIRVhUL237xZmYMm/gcrp8b4VJGLpZE4qaQaBd4kSYObhIl/7AnLC45VjKbV7c8fLxZKd/5kA==} - '@zag-js/angle-slider@1.15.0': - resolution: {integrity: sha512-xIZBa9V6d05uK7+XQVhfdsThqbZKimSYVxtMOWJfG0sKn63N9VGPxL1OtOMq7FA4IP3SyvlelsGt+3t82TUiyA==} + '@zag-js/angle-slider@1.15.2': + resolution: {integrity: sha512-ItcDlKHJbPFfPGmmiCGcWcd0Y8xC+WH5Dji7+uzBl40L9hh8si7/FrY9EB2cX/qUTDppNyicLPIDnZRGkByTOA==} - '@zag-js/aria-hidden@1.15.0': - resolution: {integrity: sha512-3ogglAasycekTHI34ph16mqwM+VtHCOMtrFHWzPwB16itV5oDEeeMNdQXenHSSyQ/07nJ2QsRGFFjGhPm1kWNg==} + '@zag-js/aria-hidden@1.15.2': + resolution: {integrity: sha512-Uwt86QpEaI4qLFS/k4C7rwIfyiH8EdE5a4AWiQ26WsL8VOpjROn65rBEOJ8q3fG5CJXbdcqaYK3lg4ldqf9irQ==} - '@zag-js/auto-resize@1.15.0': - resolution: {integrity: sha512-EXgrsU7OWxc7obSOt8Okh0144H8DQi1S84OsOUY04Uni11Dnp5/X8+t6mvBbkw4/Qyz5UBjChjocwBcO+HHV8w==} + '@zag-js/auto-resize@1.15.2': + resolution: {integrity: sha512-Mg3IN3eIP2wKBFRm5qti/rjKpTj7sfIVNfO9BgWdHDSzli1VwaBX7GaOE3nGc1tZ2nJ8n0SWRvRSzr3b57cwKw==} - '@zag-js/avatar@1.15.0': - resolution: {integrity: sha512-EHGxzXb1mLf3n6x0z/rqFl1mghDB/gyfPAeaFUoA/cacmmMk8YB3aDUXkS9pTgN9stYJBM5f6T4xB1ZUhrP8tg==} + '@zag-js/avatar@1.15.2': + resolution: {integrity: sha512-4aG2ETJbdMTALyXwU/DeGfjs/dM0Kllje+t5ov52fQrtkY123JdrvKQkcvsc7Luph1kdN1tC1/2fe/pDMhycCg==} - '@zag-js/carousel@1.15.0': - resolution: {integrity: sha512-ZI9H34f2utdJ2Ek6GZa+iuRH4eC99GHD/VEOKLdGani8uadpT2v8M5kUwPGrlAJq9SiPbQ2UuXBmCkmurPQqdA==} + '@zag-js/carousel@1.15.2': + resolution: {integrity: sha512-7bcyEtWIhv7kw+V4H+Fv5rE8I8lf0LQOj+m3HTYzWo+wiLybFfI8/bg1qywjSYKsgZr3gmGVCEZhfx3BSpP3eA==} - '@zag-js/checkbox@1.15.0': - resolution: {integrity: sha512-6lQvPQNJXt7R0xxdpOuh2qtmAkzdBdqSvFIH7fE6GJzJ/AWiRZh0X+9deLQ76CN4EDUdxizEe7MlQfTI3a56aw==} + '@zag-js/checkbox@1.15.2': + resolution: {integrity: sha512-Ay/+rpKbxL4jE1pwVw52h0t79PpiifA6QlYnV4E+hWl1yJBkMRIi76Ryhqvqp4yY+2Wyr9OfDA9eHmQjapG4VA==} - '@zag-js/clipboard@1.15.0': - resolution: {integrity: sha512-Q3kh0fHvOEAJUywQm3zAWyltrYyiI8OpeZQ18k5Mf3/M+bq3gSphZL0+AYsgGbKUg5O2+hJ1SfiErAjyhRtBQA==} + '@zag-js/clipboard@1.15.2': + resolution: {integrity: sha512-EE5OlsIYbBklo62qu3A7GiUnsgmoGaoDZvhpYvpNM8StWNeRREcJZXRIizv4aFC46e5eODzSNcebnMLYa8Wcgw==} - '@zag-js/collapsible@1.15.0': - resolution: {integrity: sha512-GX0kdMlKk4Yk5k/2wN0prudf21k+TfArGr4EHqimTDR0vQE3dSdb3pYyPjw20fLzceKHBBCLsoi2v+YnS75gHA==} + '@zag-js/collapsible@1.15.2': + resolution: {integrity: sha512-vvUXQMFgwsZJphE4Ml5ap4FVhtyLOqK2QXPbt2+F8X8SRwJ3/pqsSsLFdH+ALpNoCK6WF9j+8FZ4lyidr7XPDw==} - '@zag-js/collection@1.15.0': - resolution: {integrity: sha512-oC3i6c/oP/FuNPsfgoC1reSXbAvDBGXl0HU3CcvXiNLHbjg2ek8J7kbow6MNuXK6chiksiOHbzKxHl2Oo0Ox7A==} + '@zag-js/collection@1.15.2': + resolution: {integrity: sha512-bJ9EtZ1Cpjh/rQFDMPTPrky/eSfaLpHWmMnk/S9b7wi+OhC0Hoqw38lcWzfc0AaE4bJsfru9/FLIsCDOLf7TSg==} - '@zag-js/color-picker@1.15.0': - resolution: {integrity: sha512-DGujS24h1OWkYL+TWyd+xukOO8NBgcSfFCINffa4ivkHtNx3nC28qkwLPRASbl7AK69pbrcuO6bx1Sy/JQJw0Q==} + '@zag-js/color-picker@1.15.2': + resolution: {integrity: sha512-UOYHECq+X6hSrgSxwBt5O4Y6f2IdOGMhe7P/LFev7Yn0x1F9fMxJZCIzvQGaQ2V/hR0eTatiKk5SmOp9+dJA/g==} - '@zag-js/color-utils@1.15.0': - resolution: {integrity: sha512-SKo+p5Fu0TBtdDua8UHVjptOkwLLBFoD499Z1FER/gr0R/97L03Kdir0YTxvKn5pXWXYY1EQn4hpTuTITN16lQ==} + '@zag-js/color-utils@1.15.2': + resolution: {integrity: sha512-c167QcxiVHgFZ7ca0PSQZ7skhbBOd6u1lIyWYzkZ2uPf0yJndqP9gFYPMbwK6d4WIM9k6y6mLdsWCGpqIJJsIg==} - '@zag-js/combobox@1.15.0': - resolution: {integrity: sha512-HBck3wcEeIOa7IQMsUkUKbm9cAU7bjoklIyq2zFGn90k7DcDa++oXK9Z2pmcd4TPoBYiyVuuXucaCcjmLX8V/Q==} + '@zag-js/combobox@1.15.2': + resolution: {integrity: sha512-lZXW99NLnRfLLY1ZOE0oqo4wMDglkUjKV1UZaHyj+yqXsiMtWhKQFQW/JeVBRDe6RCv8wWPPHMycNANMw581gQ==} - '@zag-js/core@1.15.0': - resolution: {integrity: sha512-P/8F3IXabMhpFnc6hC7GDg3rvUnvY27cuZU04hxjUqTH6+SfORIA/Uvqd4ekhC+dIprL9jicnFrmGgcyelyxfQ==} + '@zag-js/core@1.15.2': + resolution: {integrity: sha512-yUnh4I0nZ8rlszWgF402F5vGoYw7DNwStYz2TAO+4E08BpKBATw3FEdqAHPm+2xZm5qPqnPbM4iObwUlkBQUEw==} - '@zag-js/date-picker@1.15.0': - resolution: {integrity: sha512-IZD0V9MAljp1QhxYbST80AonryuDnyx7hvEy/RrBY/VOx6I4STtKfcSJ5ZZgVIzJfH8Yyaed4+IwcenqG7W5YQ==} + '@zag-js/date-picker@1.15.2': + resolution: {integrity: sha512-KElAFm3fW4GKGUNUe+jqqUX+P1H+Cigp/eGRgIl0dUjCwHocD1oN0ZCwNYmf7SJoWSgPRc1UJdA4XvpdU0IwPQ==} peerDependencies: '@internationalized/date': '>=3.0.0' - '@zag-js/date-utils@1.15.0': - resolution: {integrity: sha512-FX9EesJRnUTYTpbXf5EVfCbsXW5vYtZfc635aQzojc9ekk1FGcHpqQs8ZKfCOTPuauZFOX9i6139A4KoPfQOiw==} + '@zag-js/date-utils@1.15.2': + resolution: {integrity: sha512-U+HtfdtHJ5ed2ys8izMhu8gY5jQigCd8ExPN5Cxg5CoIbSkho9NT8o/eO9OW71jc2F4kwBh+q0reyxxLJnTSbw==} peerDependencies: '@internationalized/date': '>=3.0.0' - '@zag-js/dialog@1.15.0': - resolution: {integrity: sha512-Vlt5vySs4u8c8xBEh2JMUvRfPc+aaVEIIUtFVxpc2ORWhBXs9glijyp1yf3rNHJhjj8gqqhF5sEvs3yUTTAk+Q==} + '@zag-js/dialog@1.15.2': + resolution: {integrity: sha512-LUF+tiiUJj7v24txhC0TOwEgsfj1GCogAmBaiJKxvqrDEDv1B91J0b6SUQ5TuTMLW+hlBEzXZw0QsTxa9OXBew==} - '@zag-js/dismissable@1.15.0': - resolution: {integrity: sha512-yv575KWy8gA1p4aajOiY5l/nBQ3Xw+Mrjpungp1+wiGd/98eNAIKJ6/adldfbE1Ygd/Q4Dx2VQ7D1AmiTdwUSw==} + '@zag-js/dismissable@1.15.2': + resolution: {integrity: sha512-+WY8a1L+L8hXPGmWKqOsSg2KCHabVWXEX8mewHamltpSb86+2WMmblpLNgTwbm6V0T6txf1N8lFuzWMojMEWSg==} - '@zag-js/dom-query@1.15.0': - resolution: {integrity: sha512-z8H/j/Zs0eZEsGpbonScmlKSv0jEXKiAwUCrvQ9Mt6Gz9n0CQRM3MkFclSsM8aeiSv6qKLlhPfkzjl18OLkbgA==} + '@zag-js/dom-query@1.15.2': + resolution: {integrity: sha512-+r9Xj6hiQj9b2ZNkT3E/bDaXgigoAkhtikDXov9duAY14pFFJxazXr0NcVgacik8ytAEt6XOOshLcAftyalRKg==} - '@zag-js/editable@1.15.0': - resolution: {integrity: sha512-F14HKZuDsfkpfIkaF/ZDYPkz/pFf6VHrvoV0rdhj8wb8QJQ4nB+lgBv2APSwkEaFb/gGrnE19v3Ojlt5tqpPsw==} + '@zag-js/editable@1.15.2': + resolution: {integrity: sha512-32v7DXDBnDX1CiFpGRh9uclu48UJQJT2QZPQ0Bys3ZOFgMxsWH6tCKDb7iQTcINIc/XIx/9nclWnV5egzimG9w==} - '@zag-js/file-upload@1.15.0': - resolution: {integrity: sha512-2hAlQr9qdT8EH4XnmkNkEIDCCsmp2SMoMAjq6nJKYO8UJNQGRanU2B5S8jV3quJBz0vIY43SwyvqiZ3+1VrJSg==} + '@zag-js/file-upload@1.15.2': + resolution: {integrity: sha512-Zgac/da5QrUlE0ItlNy1kyMXfTy4ynTWnq4aZ4wZ9eVHUFQhLXERv8l+hYJetImISnuclmNVxNKP8Xk+5t4+tA==} - '@zag-js/file-utils@1.15.0': - resolution: {integrity: sha512-tahJt3JmrXaOtGiknH5PxIiOyyNvroMfjiBqOqnNksIPzDoWmVNxHOEme/ts7dJlkRD8U2qm2NFC2VS0bKerzg==} + '@zag-js/file-utils@1.15.2': + resolution: {integrity: sha512-aNUEBJUeK6G3pyf+zYnIMg0GgJnInddjGRedFeTnfK1UmlSO8wTbxQTCvjWd4Nnr5eCTpQkRq6wTZy8JeIcOpw==} - '@zag-js/floating-panel@1.15.0': - resolution: {integrity: sha512-AYYFseA1MeQUZl+zjNoKUu4j0kwz8EyJd4oJjs8uJIR6KG8u8QhpWYIBUny63M6AtZTCSYQAgBEcEh+mrbEyyQ==} + '@zag-js/floating-panel@1.15.2': + resolution: {integrity: sha512-8oG2MRXWWeXws7iVDmJFBqHLHYOGLvYe+vgXI3vgnLhmS4SeX9qAJj6qIOar7htOmEtp1p/KiBo2w2MYtzjuAw==} - '@zag-js/focus-trap@1.15.0': - resolution: {integrity: sha512-N8m/JpNe1gHUPJlr0hyGUdHg6pAuyJKkBaX0s38cyVntlo2CJhyAWZGuUdocpT2Q3HNPql666FNnH986rYPDKQ==} + '@zag-js/focus-trap@1.15.2': + resolution: {integrity: sha512-5EU5/Cg80oNO3z83A/33t9SOVYvLqLOuSPxt/7Xzy/L1Vj3vUj+s1ox6IpECmEFJcuql7X5yt6VIVitrLtgbFA==} - '@zag-js/focus-visible@1.15.0': - resolution: {integrity: sha512-TPXBf47tj6L0hhZNl9AWhuLoVzfPaNPM+/Gw8t9l9Whvy6v9rk/rqUCidY5LsrQuPiKTi7s5WI5J+Wod8ib3gw==} + '@zag-js/focus-visible@1.15.2': + resolution: {integrity: sha512-zElE5T41p5QaB4856xK2SeERmHrKbA/UMzoyHzrAk/N1r6dNiMOOx1hMyHy7y6pEhC9kjJFwEpXi1QEel6/ELA==} - '@zag-js/highlight-word@1.15.0': - resolution: {integrity: sha512-Rwr/rRm8BaF2xW9BAEJeA2wpFVx6HzoezfYQX7GFPPgw3N8nBMAYNjx+i1YIwIEcNyad2rbaBB+pSd2fZLIniA==} + '@zag-js/highlight-word@1.15.2': + resolution: {integrity: sha512-2a49h4k0ISIDydaZZDdASEHJpwxJeuZHSPCE7cM3/BWCR3H5galeC/jbNWRlTJVH4OQTYAR0I2wILQvOWLhSrw==} - '@zag-js/hover-card@1.15.0': - resolution: {integrity: sha512-j6BsE+metdnv/C/Ls0TZzAMN78rtS2r8M1ccHY5FFTGyUvZnlE8BY/QPNyCSSSCUpynymzMYh3IMYlxbJgfpSQ==} + '@zag-js/hover-card@1.15.2': + resolution: {integrity: sha512-FfNmhow8MPMp5RgTeC87x4EStFw+d1137w4QZ+fC5PystRzxGeiyDJyLRYGVeIQO2oP463az70vnxsbFAMu98A==} - '@zag-js/i18n-utils@1.15.0': - resolution: {integrity: sha512-anxSbT8kLbJaFJFSb0Ork2j/Lp+XVfMNCIgiBR2BuqUlfX72k23TIJvRxAfwNIkUfs0L8ikaSgLss9OwS4mAnw==} + '@zag-js/i18n-utils@1.15.2': + resolution: {integrity: sha512-1RnqCaxe+l4UR1O3fhn04T+J62yw/SkCByhrhrPSis/H7a65nW0WsoWiJTIgWp/hN9HI2Y3dVFfMEwQUFFHG1g==} - '@zag-js/interact-outside@1.15.0': - resolution: {integrity: sha512-OwBf/iesQGU9Oq3xe/tcK7gu7xipiGWsmwl2CcScr0fTp3BIMbQywHS928IgPk1DxA8KTHodY8wBjoY1dskfRA==} + '@zag-js/interact-outside@1.15.2': + resolution: {integrity: sha512-WbCICcMJHL6yS8vaou0FvKV6shl1Z+CefF7yzn5MEshPLbmy33WGQ2KBzodTkIQFM/C/zdVz5xKl8TbQmi7jUg==} - '@zag-js/listbox@1.15.0': - resolution: {integrity: sha512-Gcg76uWZwUAyMFZzGWpHnFCU/aaquNbXmVnyzzBgE3Co2snkv02rK1yG9iBwemZe3e5+VBifMMAtLLPAQJdz+g==} + '@zag-js/listbox@1.15.2': + resolution: {integrity: sha512-V6Zbi8HTiyhsV4GhFaiFYL2bJo4lOt24/SA9M/T5D7ZH+bTm3itPUxYddIBi9w6yRTU0gsorosD2GyFkHjchvg==} - '@zag-js/live-region@1.15.0': - resolution: {integrity: sha512-Xy1PqLZD9AKzKuTKCMo9miL1Xizk/N8qFvj64iybBKUYnKr89/af3w7hRFqd2BDX+q3zrNxPp9rZ6L7MlOc7kA==} + '@zag-js/live-region@1.15.2': + resolution: {integrity: sha512-dIrfDlKyNz99CQVeHu9RHe/x+yTBm3wFA7H655DXL7CugO9tpTlynkrTG9AB+0Z84JKZTeHh0vGVa2chTWKrNg==} - '@zag-js/menu@1.15.0': - resolution: {integrity: sha512-GbEBVYu0w7+88xrGX2GrjXfnwWuX5jLhoLiEcuxvxJQal/nahKrH4AGXJvHXNaRbj+53V3nWAh3u70C9210PWw==} + '@zag-js/menu@1.15.2': + resolution: {integrity: sha512-54dGUChMLyTrkCGbKGh0R8l/cg0vPFnGZwMG96zYJhkmXdpDMECZgBrN3j7B6RtEIvlAR8fMH5Sya58Amb3lGg==} - '@zag-js/number-input@1.15.0': - resolution: {integrity: sha512-+kK8kyXJhIAbEUnswoMDR+DSJUmvDNIOW0ffuZ9pbfukN3p6zaA3/dCp2Dtg3bQS7hGrFWgtrdejJ8l+mVvUAA==} + '@zag-js/number-input@1.15.2': + resolution: {integrity: sha512-qtDAVUdMXBhufBSwAgi8MXm7zHb36ujfWmxCJg6HbjKVF0BEAxeoye5VexgyYul7Hp8+Rr9LkW8X35W4amjJEQ==} - '@zag-js/pagination@1.15.0': - resolution: {integrity: sha512-Z62Q41fQPWqk59QyJk+9J0Ad3H9DCqZ0zZutI6iH8DdzT0A0xxmT6zhup6DM/8C8h0OLlaHFTWQnj0RdRNrnXg==} + '@zag-js/pagination@1.15.2': + resolution: {integrity: sha512-k1jT7UWDwgkYVsf83TTUhks6iZ7aQpcEjQ+iWI2LbZu98+bVhX9hpHfxdWbvTbueGk6WjB2xa1X0tsktII1mmQ==} - '@zag-js/password-input@1.15.0': - resolution: {integrity: sha512-oHuZKDRJIbycqWpTVznufy4L7K2g8kwcEaZ4runkwO2ocF00zP8HVmOZQzmhkUgTny0azErQydg8XE0VR5OfYg==} + '@zag-js/password-input@1.15.2': + resolution: {integrity: sha512-9BpQ26Z9XoCiNAHOmx3zwa+62+C6358/az0h3N24P4qS1EdTVWkhG1tsyPhRElg4v1koavZ40RMUppJQBH+DmA==} - '@zag-js/pin-input@1.15.0': - resolution: {integrity: sha512-IykjogZBG+BfbFXymSa+KGpOi5CrV9kl8HRm6G2V2Sr3NA5jEwMFaGSd/QrcHS9vh23D1Smx/io4pvF7c3q0kg==} + '@zag-js/pin-input@1.15.2': + resolution: {integrity: sha512-1KjGGmyldtEb4RwwdBTKzbgAwpNT6CyY274LvQC8lTCEUYOBkUmS9OUaKUbwkoluCdmXrugpg/XMulisRmMtgg==} - '@zag-js/popover@1.15.0': - resolution: {integrity: sha512-cdzEed3zcGbjSgPQnQnrsuXo2hVVslmSNwQbU5dHcNzG1uxxmtPCIMVeBUmGyJbAFF5XQpKCq/7mIr26dT73vw==} + '@zag-js/popover@1.15.2': + resolution: {integrity: sha512-6cD4eTwwj/bkTCDWVk0dMFqg01iD7qJofRSU3da7nde1Y0TMz8gBlt++GASgCF4p/hPeGLD18GcIF8FKka9IlA==} - '@zag-js/popper@1.15.0': - resolution: {integrity: sha512-Ra/0Ko423KN+8D4+mIFFkeTn9uaHfpxn6UUNIWwZKoiJQvED8DH4dPbLbmvGEoKp6qmisnRHAzi71NLgEhk0Mw==} + '@zag-js/popper@1.15.2': + resolution: {integrity: sha512-5uaFW9IU8bj3NdEiyuSp2eVJaPvWoA6/q7Fh423Va8booMYW4k1KFmz2BSxQ3JfK5lt3vPI0X2026gSxTx/vmg==} - '@zag-js/presence@1.15.0': - resolution: {integrity: sha512-hoxXis50pm79PpkY2kA1wdhh4AEo7t7pBv0VsQYZYjmzuFh4V5IMw9oa1EOfBlC6f/A+EMZ9E+xg+EVsB68a8w==} + '@zag-js/presence@1.15.2': + resolution: {integrity: sha512-cNPJz3qeXdoYFEefxFixZoMDFzqfHsLgmi2ynmRrFlyHzHtFdvKjvS5ywo9YFGNgwKrEddS43n8gl3w3lgqBCA==} - '@zag-js/progress@1.15.0': - resolution: {integrity: sha512-/Mz26GR2rOAuoErNOiSGRpvwckTmbCD5nWGDE/aYlVRID13HcsmN15Zk2Jfa4LadqK88aIN8Iy0Sk4elG0+Efw==} + '@zag-js/progress@1.15.2': + resolution: {integrity: sha512-VPunnrTYiJaHnnCKuh2ZARCnzgTtxYIiNKiUVPWlygsWy2AGg1K3AvVswF2CVfGpwbO4ioyBQO65EZkQiMN/Aw==} - '@zag-js/qr-code@1.15.0': - resolution: {integrity: sha512-GkGy5k5tk6DIui9lGjDO8+e8TsSVOxEGp1lblPiaRm1ggIh10GhIfCQWGe/x78ezdie8WzxlSrma89suTpaiAQ==} + '@zag-js/qr-code@1.15.2': + resolution: {integrity: sha512-hFtwGGArxVJo7osbY3R73BHIX3Ldb8G4gtNDZ2fGcKAcp+SQg5GXUIBK17ncxJrOC7A1Wp7sdOoYNNOPWe2fYA==} - '@zag-js/radio-group@1.15.0': - resolution: {integrity: sha512-+KTebHUtMsE/YDyGE8wF5VnWfZQp+f2WoAwwzBjfhPpRxXbOUMDo0pZEEr3yxkSvQ9hgCcBhMKH8pEk0SPxvjQ==} + '@zag-js/radio-group@1.15.2': + resolution: {integrity: sha512-+V9Y4EZuNITMbA9iJisysqWW+JB3YdlFF6dAomvXN8nuOuj8HE02JHndIeMflDtW6Tz99JcJLS7lNXN7G5uEuw==} - '@zag-js/rating-group@1.15.0': - resolution: {integrity: sha512-omGKN97FhplFwBX9J/Mj7BCZuwFXSXssSVTKU7Yp2d1Cmxhez4+Ju7KdSRNnIoWB4OxFCxwZyaAPTcg3E0Pjrg==} + '@zag-js/rating-group@1.15.2': + resolution: {integrity: sha512-g7F9NyB1MF6ydE9aEr9zLPXGKXZIH2ZsUBXEQ9u6apUhnchhCSHDw6xHVXI1hYGrJHnpf2xMw3Xu1opJge1DQg==} - '@zag-js/react@1.15.0': - resolution: {integrity: sha512-YSp9QBkdeBfZt4nVhJW+CUd5sNEEVAuwkmoZWDFUoDoWSAXwzSKuHCmTm5/8DaXg1IZD2bMrXgMNDqZv2x0hZw==} + '@zag-js/react@1.15.2': + resolution: {integrity: sha512-T5QPiLbW4DoQ32NS5+Qu9NsIXKKz0d5MOpfEdXXuc6hKZdvV+V9d7EXeHBRohs3P6jqtf8FXpXDdK2trv37YlQ==} peerDependencies: react: '>=18.0.0' react-dom: '>=18.0.0' - '@zag-js/rect-utils@1.15.0': - resolution: {integrity: sha512-sjAn78x1t3XiDG3NT8SoFfyO0u7/SEJU5RKRhMgjTPoOLXTzZj+lu2d5N4cUw0uZTfeGb/ormObSchMQVhFgYQ==} + '@zag-js/rect-utils@1.15.2': + resolution: {integrity: sha512-wPsOM4qYncwOli20MNINgl0ZwmMY11RvrgPvjcMrkJ9dVqU/YrCcXV4rIg8Zig5jxCT+mf7rWQe9aQJlNTVipA==} - '@zag-js/remove-scroll@1.15.0': - resolution: {integrity: sha512-vdWSAdgY8wJ7s4YeaKwTMwmZiRMBxCehmdktSxBWvwtAjU1cM3UWvjmZ9E6INJrQXxH9vDpe/rpFSyv1guIQIw==} + '@zag-js/remove-scroll@1.15.2': + resolution: {integrity: sha512-pXVuvFcAQND+C0KAzAve02hGaI/AgEhC7RpgpyUKaUzEccEsxLi40C88j1/2HCfta6GI7nd2e0QwPZiqngUIyA==} - '@zag-js/scroll-snap@1.15.0': - resolution: {integrity: sha512-/LfBlsjoR4tVL3Djus3k9jKLhwC2ApdHTACxEc72TAewoPe4M8icnSDLXmKHvwwOhzK0HlFz8wGm6ZncAbQbuA==} + '@zag-js/scroll-snap@1.15.2': + resolution: {integrity: sha512-RswpsMHg0aWHsx7xqybnPm8bTL9ow17z9GhYgxSWtIi2U9wgkUHDtEJQcRNUA9PQEGyVd29B39NM0ir64HAhNQ==} - '@zag-js/select@1.15.0': - resolution: {integrity: sha512-4urUBADzhrsGEO/UsqHdjsgmDdF15Zzeid3ejEbIMTrkt2/mMMcQ1CShuxtsWqm2EUBz/N1kOcZlE6Tq69n7Xg==} + '@zag-js/select@1.15.2': + resolution: {integrity: sha512-Y07RlBIc8bVj2WklhS7tiVySZntBv9TE9sfiA8RcLU7KFFGTdS2XUoQV4fziJubUL8XFhNzEC92/bKeBLqpgDw==} - '@zag-js/signature-pad@1.15.0': - resolution: {integrity: sha512-5Tj8vkrRxEkSV417oR2qdy+TRgDmS3W8dY7xsIjpbBf/kqkt/8Uo4JpaVH2vwQAFw9AwEFogBh9i6dHcXMy0rA==} + '@zag-js/signature-pad@1.15.2': + resolution: {integrity: sha512-vw7oD7afBfGvUyotJrFl+PjPVYOYZLgQ1eVAosKj54phgKvxheBr8/ySq9vlyTkyvOMjJ8zIkkxlywuqoZzl8g==} - '@zag-js/slider@1.15.0': - resolution: {integrity: sha512-NYIsn3GKXIoPmvkDXsQmw9wdYg3QHbYHXnZ8Ewl2fVubN7S5mDlHSZs2iDVsBvX+a4RChWFRO6JHX8E1+BncOg==} + '@zag-js/slider@1.15.2': + resolution: {integrity: sha512-Lcrm+h4Vx0stD0ybAqD5tA1qOnrKEfQP9ucQsPUy+fY2em19XC6raOVOhAc6ROx4X0neTI/yEc1ARJQSaxtRZw==} - '@zag-js/splitter@1.15.0': - resolution: {integrity: sha512-Xnedl+cpnD/hv9m+GOYCK5K2xRxbs4xuP/EajYtgVcDw8E1X5cBmxHa1hCrp7BMgb2xYCvZ5et4hnmZfb+1X9g==} + '@zag-js/splitter@1.15.2': + resolution: {integrity: sha512-LIuTTPRaw3inS64f2TLcFIlwjNe9Tx9mSE4VXf7wPhYitNKmyh7MeNE59na+wDzZisVwx9yBewAPfrZtbHDGBA==} - '@zag-js/steps@1.15.0': - resolution: {integrity: sha512-VoIDcDIEErZawmW2m0yTGlffqjfRuSwR37K9LdSRy8Q4Qzz3wV7jASaTjMhTya1hlreJ7tJg+Qbjqowvw9GndA==} + '@zag-js/steps@1.15.2': + resolution: {integrity: sha512-NnS3wYQrFWA5OXu+jnlnPpm49rGpzHCDbN2UuUcMGvbYVETKEXEO9fC1XWh7PstVuNi03E/CrZGHl5cEjf/j8w==} - '@zag-js/store@1.15.0': - resolution: {integrity: sha512-ecqjcy3b1GsULpsT8RVJV9KDaikajRN0XRg48HMvaGkaPIvxI6esyrE6RKnShuqr2eVXIPghgBnCnrJUev4UlA==} + '@zag-js/store@1.15.2': + resolution: {integrity: sha512-oDJuRdu8SaGab06UycN96OgvNau1ynawDNNfQNhA7zoOIZlaJH6jP+5YaAPFila+wyjdw7svz5+4ejs8vXcjpw==} - '@zag-js/switch@1.15.0': - resolution: {integrity: sha512-2CaAUTi7jM4lJjCYoSE1HWlFPCifI5GR+hufWOCYKpanf8VA/LM+t/a2Aq5QoBsWdcQv3B9mHxF/aVTDbnCKPQ==} + '@zag-js/switch@1.15.2': + resolution: {integrity: sha512-2aEm5HDP/ENcLvoP77CH7DQTPXIMUzVilefHlz6WT0tQxQzOw8uMhUOYYcuNmEq0FNRUOyuMEMyZnZFUYAxqvQ==} - '@zag-js/tabs@1.15.0': - resolution: {integrity: sha512-voHWpibC1TKLmbAJfixOesxrCio7wK+gdLRvh7Xh5u+3VSsT2fP2wEw3ySkJbpw3MpEE7R2OWkInbCV/SwPcsA==} + '@zag-js/tabs@1.15.2': + resolution: {integrity: sha512-SJMR4K59sxvNZEIgnJfbweLzncmgxRWTBm+FamwMtP8DKQ3RETNdjrn4aA9qLUsCObapk06KT3iTeiCXzuBaFA==} - '@zag-js/tags-input@1.15.0': - resolution: {integrity: sha512-CB60z+/I/Nso1gwatTO1qrk4XITxDd4qtRD+l6fuuKyOkZGgKm0AP0W+/6qUuOvtWIuY6fas3yZHFmF2eEZ9vQ==} + '@zag-js/tags-input@1.15.2': + resolution: {integrity: sha512-/mAuB8emhGoo3eoIgmlT/kQE27ukRlhghgwp3OjvEen+iTpz0XIWM+S+IV3QU6U4DlhwkadQaINht/c9ln6gxQ==} - '@zag-js/time-picker@1.15.0': - resolution: {integrity: sha512-4S02433X88X3MW/BxaFJiWna4BIRXsAdrmDcBb0PZ8dln29DUmpD8YHcFtONsKvmCAmrbO7Gr65n86nQwK8zeg==} + '@zag-js/time-picker@1.15.2': + resolution: {integrity: sha512-Aoe9GdbrvAMP1fdOEmzCESr/dO+cGnqhCoa0UkZB5wuB4dT3S02hRGSZsHO51Eon2NpzHPG9j+/alncwOe77Tw==} peerDependencies: '@internationalized/date': '>=3.0.0' - '@zag-js/timer@1.15.0': - resolution: {integrity: sha512-gDsYm4C9yju7g/r5u7n7mRQ2UY7diXXVbbLFr5Ja+0iUXgbD+uoSZEt9HypVc5TL9NWEEwn5/tut36owEeW4rw==} + '@zag-js/timer@1.15.2': + resolution: {integrity: sha512-v8RN3cwFuNXxuDMuxxfXKCSd+Z1UT6Ct+ueU3PRZqHqXU9u4k9Mm+vROIqnNzhCCdIHNxsqUt32/2zsRRaubbw==} - '@zag-js/toast@1.15.0': - resolution: {integrity: sha512-0RupMCXyGr7/La4Zlei7VqBF0VPNJelGd7zimLboe+IKZyy4Ypi/N2IX14rl8JZQDsDEgkLUl33xrSk/9RW2nQ==} + '@zag-js/toast@1.15.2': + resolution: {integrity: sha512-OohJvGTy+J1MpydJ4eCV36picggfF9VbDW4nK97TT+4bIIRDgW+PGYgB4dd+PvEjRrk9194Kkm93lud95yOyZg==} - '@zag-js/toggle-group@1.15.0': - resolution: {integrity: sha512-992vMz/2sriLrUKI3LpT/01kCGTbPGLgGLibiHRt562i0v9+2tV+GiY2jBctHZjJaKPrzBY3H0l8CCCvDj8gng==} + '@zag-js/toggle-group@1.15.2': + resolution: {integrity: sha512-JhWV0GY2NRgDhlzP73ADlG1E4NFXqv1h2q5+m3Rmos+Bi8soOV437jch/wy+M+xYN5vdZCczXJu9BumHNlknhA==} - '@zag-js/toggle@1.15.0': - resolution: {integrity: sha512-mMSQ1+f1hOMp/7gLA7rTeiSNyeZxsCjRxP4XnTBY4BxJ5LswLuhem9CplBwaVthkhY1Y/5f3HHu80LBcfF+BVQ==} + '@zag-js/toggle@1.15.2': + resolution: {integrity: sha512-wtDeIRhDeVhaUboWQ2GrxlCC4+cLRyZzvZiN84tad7H/sUKq9hNDdROcCnIYBhEkb1Qf4sjR8KszY12YLtJx6A==} - '@zag-js/tooltip@1.15.0': - resolution: {integrity: sha512-sOpVECyfdS4RZBx46mSV+RPc9C5k9JvYQYUfoOVWh0E5RLSEz5bQm5xxctKOHfCOv+vJNTfG5gP596B1r2+Fkw==} + '@zag-js/tooltip@1.15.2': + resolution: {integrity: sha512-Spw5ewga3DNaT5H4AnrtsxJ6ebRoTxy+igwojGTYUCNUoxyQn6W3UpqZpgAAfw8B236bduTRh9MW9CsaM/hnmg==} - '@zag-js/tour@1.15.0': - resolution: {integrity: sha512-EplcxoiE0z9vI0z6675+ABclQ9Mi1YUWhDZOHx7wfjRzpfawmJoBAlNDKzK3wc801d6OxgJx69SPj7ac0BwwwA==} + '@zag-js/tour@1.15.2': + resolution: {integrity: sha512-OW+autOwwsVMGwcYCxdCh3Hibeeag6Sg8w02XfmX7E+T2u9a+GGdLOrH7DPM2oHTbZV0iBUqIaKxGPKgRYZNng==} - '@zag-js/tree-view@1.15.0': - resolution: {integrity: sha512-wqdd+hu1bDOCWtnZ8MarRFHqbZF2t8qKBM3kO42IBq7jTI/93LCkHSlceEPft9dgZ6Ea9km0YJMHhoTqCPZ/fw==} + '@zag-js/tree-view@1.15.2': + resolution: {integrity: sha512-HWDHH3rpGEz3IN5bsj8EHZnU0ttk8uJwBOnH3reYcFQEQskA8cmyzd7y9hdBEn8PzAns+iOjUBj49IVmoYpOIg==} - '@zag-js/types@1.15.0': - resolution: {integrity: sha512-lV2ov2M07BlmjDUCSwBeHxPApHI3oAiLytG94AqcYvQ0BtsCRo5T60yRQ0syFc6fHf0e9+kwt89uoIgfGFYfmw==} + '@zag-js/types@1.15.2': + resolution: {integrity: sha512-qEHNRA/uOYQjvXzI/ie6vuOD74/p7w6MA4X1VoZEYF2/sbIQjlRn6SzpeV3RyFZBzl6WBO6RqV/XEbgpvGSb5w==} - '@zag-js/utils@1.15.0': - resolution: {integrity: sha512-XctFny5H8C00BsougV40Yp0qVEj9M2d/NRme7B33mon9wG+3hscZwP6miJmF6BYI5Pgu6e2P0Sv45FddQU1Tkg==} + '@zag-js/utils@1.15.2': + resolution: {integrity: sha512-JdlyGT6yfG2ub2FftrB6BidIlvD04cSwdKYJGb/M+NJ7p7uxnZUZMxAjeBmTLhM1nWbtJPVq3oDTYz/cBBZLng==} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.14.1: - resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} hasBin: true @@ -1258,8 +1265,8 @@ packages: resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} engines: {node: '>=4'} - axios@1.9.0: - resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==} + axios@1.10.0: + resolution: {integrity: sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==} axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} @@ -1276,11 +1283,11 @@ packages: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -1538,8 +1545,8 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} - esbuild@0.25.4: - resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==} + esbuild@0.25.5: + resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} engines: {node: '>=18'} hasBin: true @@ -1567,14 +1574,14 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - eslint-plugin-perfectionist@4.14.0: - resolution: {integrity: sha512-BkhiOqzdum8vQSFgj1/q5+6UUWPMn4GELdxuX7uIsGegmAeH/+LnWsiVxgMrxalD0p68sYfMeKaHF1NfrpI/mg==} + eslint-plugin-perfectionist@4.15.0: + resolution: {integrity: sha512-pC7PgoXyDnEXe14xvRUhBII8A3zRgggKqJFx2a82fjrItDs1BSI7zdZnQtM2yQvcyod6/ujmzb7ejKPx8lZTnw==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: eslint: '>=8.45.0' - eslint-plugin-prettier@5.4.1: - resolution: {integrity: sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg==} + eslint-plugin-prettier@5.5.0: + resolution: {integrity: sha512-8qsOYwkkGrahrgoUv76NZi23koqXOGiiEzXMrT8Q7VcYaUISR+5MorIUxfWqYXN0fN/31WbSrxCxFkVQ43wwrA==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -1610,24 +1617,20 @@ packages: peerDependencies: eslint: '>=9.22.0' - eslint-scope@8.3.0: - resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint-visitor-keys@4.2.1: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.28.0: - resolution: {integrity: sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==} + eslint@9.29.0: + resolution: {integrity: sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -1636,8 +1639,8 @@ packages: jiti: optional: true - espree@10.3.0: - resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} esquery@1.6.0: @@ -1685,14 +1688,6 @@ packages: fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} - fdir@6.4.4: - resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==} - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - fdir@6.4.6: resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} peerDependencies: @@ -1744,8 +1739,8 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - form-data@4.0.2: - resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + form-data@4.0.3: + resolution: {integrity: sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==} engines: {node: '>= 6'} fs-minipass@2.1.0: @@ -1823,8 +1818,8 @@ packages: engines: {node: '>=0.4.7'} hasBin: true - happy-dom@17.6.3: - resolution: {integrity: sha512-UVIHeVhxmxedbWPCfgS55Jg2rDfwf2BCKeylcPSqazLz5w3Kri7Q4xdBJubsr/+VUzFLh0VjIvh13RaDA2/Xug==} + happy-dom@18.0.1: + resolution: {integrity: sha512-qn+rKOW7KWpVTtgIUi6RVmTBZJSe2k0Db0vh1f7CWrWclkkc7/Q+FrOfkZIb2eiErLyqu5AXEzE7XthO9JVxRA==} engines: {node: '>=20.0.0'} has-bigints@1.1.0: @@ -2083,8 +2078,8 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - loupe@3.1.3: - resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + loupe@3.1.4: + resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==} lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -2319,8 +2314,8 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} - postcss@8.5.3: - resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -2331,8 +2326,8 @@ packages: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} - prettier@3.5.3: - resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} + prettier@3.6.0: + resolution: {integrity: sha512-ujSB9uXHJKzM/2GBuE0hBOUgC77CN3Bnpqa+g80bkv3T3A93wL/xlzDATHhnhkzifz/UE2SNOvmbTz5hSkDlHw==} engines: {node: '>=14'} hasBin: true @@ -2372,8 +2367,8 @@ packages: peerDependencies: react: ^19.1.0 - react-hook-form@7.57.0: - resolution: {integrity: sha512-RbEks3+cbvTP84l/VXGUZ+JMrKOS8ykQCRYdm5aYsxnDquL0vspsyNhGRO7pcH6hsZqWlPOjLye7rJqdtdAmlg==} + react-hook-form@7.58.1: + resolution: {integrity: sha512-Lml/KZYEEFfPhUVgE0RdCVpnC4yhW+PndRhbiTtdvSlQTL8IfVR+iQkBjLIvmmc6+GGoVeM11z37ktKFPAb0FA==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 @@ -2446,8 +2441,8 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rollup@4.40.2: - resolution: {integrity: sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==} + rollup@4.44.0: + resolution: {integrity: sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2626,16 +2621,12 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - tinyglobby@0.2.13: - resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==} - engines: {node: '>=12.0.0'} - tinyglobby@0.2.14: resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} engines: {node: '>=12.0.0'} - tinypool@1.1.0: - resolution: {integrity: sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==} + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} engines: {node: ^18.0.0 || >=20.0.0} tinyrainbow@2.0.0: @@ -2682,8 +2673,8 @@ packages: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} - typescript-eslint@8.34.0: - resolution: {integrity: sha512-MRpfN7uYjTrTGigFCt8sRyNqJFhjN0WwZecldaqhWm+wy0gaRt8Edb/3cuUy0zdq2opJWT6iXINKAtewnDOltQ==} + typescript-eslint@8.35.0: + resolution: {integrity: sha512-uEnz70b7kBz6eg/j0Czy6K5NivaYopgxRjsnAJ2Fx5oTLo3wefTHIbL7AkQr1+7tJCRVpTs/wiM8JR/11Loq9A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -2706,6 +2697,9 @@ packages: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + universal-cookie@8.0.1: resolution: {integrity: sha512-B6ks9FLLnP1UbPPcveOidfvB9pHjP+wekP2uRYB9YDfKVpvcjKgy1W5Zj+cEXJ9KTPnqOKGfVDQBmn8/YCQfRg==} @@ -2721,8 +2715,8 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - vite-node@3.2.3: - resolution: {integrity: sha512-gc8aAifGuDIpZHrPjuHyP4dpQmYXqWw7D1GmDnWeNWP654UEXzVfQ5IHPSK5HaHkwB/+p1atpYpSdw/2kOv8iQ==} + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true @@ -2731,19 +2725,19 @@ packages: peerDependencies: vite: '>2.0.0-0' - vite@6.3.5: - resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vite@7.0.0: + resolution: {integrity: sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@types/node': ^20.19.0 || >=22.12.0 jiti: '>=1.21.0' - less: '*' + less: ^4.0.0 lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 terser: ^5.16.0 tsx: ^4.8.1 yaml: ^2.4.2 @@ -2771,16 +2765,16 @@ packages: yaml: optional: true - vitest@3.2.3: - resolution: {integrity: sha512-E6U2ZFXe3N/t4f5BwUaVCKRLHqUpk1CBWeMh78UT4VaTPH/2dyvH6ALl29JTovEPu9dVKr/K/J4PkXgrMbw4Ww==} + vitest@3.2.4: + resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/debug': ^4.1.12 '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.2.3 - '@vitest/ui': 3.2.3 + '@vitest/browser': 3.2.4 + '@vitest/ui': 3.2.4 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -2799,10 +2793,6 @@ packages: jsdom: optional: true - webidl-conversions@7.0.0: - resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} - engines: {node: '>=12'} - whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} engines: {node: '>=12'} @@ -2879,66 +2869,66 @@ snapshots: '@types/json-schema': 7.0.15 js-yaml: 4.1.0 - '@ark-ui/react@5.12.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': - dependencies: - '@internationalized/date': 3.8.1 - '@zag-js/accordion': 1.15.0 - '@zag-js/anatomy': 1.15.0 - '@zag-js/angle-slider': 1.15.0 - '@zag-js/auto-resize': 1.15.0 - '@zag-js/avatar': 1.15.0 - '@zag-js/carousel': 1.15.0 - '@zag-js/checkbox': 1.15.0 - '@zag-js/clipboard': 1.15.0 - '@zag-js/collapsible': 1.15.0 - '@zag-js/collection': 1.15.0 - '@zag-js/color-picker': 1.15.0 - '@zag-js/color-utils': 1.15.0 - '@zag-js/combobox': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/date-picker': 1.15.0(@internationalized/date@3.8.1) - '@zag-js/date-utils': 1.15.0(@internationalized/date@3.8.1) - '@zag-js/dialog': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/editable': 1.15.0 - '@zag-js/file-upload': 1.15.0 - '@zag-js/file-utils': 1.15.0 - '@zag-js/floating-panel': 1.15.0 - '@zag-js/focus-trap': 1.15.0 - '@zag-js/highlight-word': 1.15.0 - '@zag-js/hover-card': 1.15.0 - '@zag-js/i18n-utils': 1.15.0 - '@zag-js/listbox': 1.15.0 - '@zag-js/menu': 1.15.0 - '@zag-js/number-input': 1.15.0 - '@zag-js/pagination': 1.15.0 - '@zag-js/password-input': 1.15.0 - '@zag-js/pin-input': 1.15.0 - '@zag-js/popover': 1.15.0 - '@zag-js/presence': 1.15.0 - '@zag-js/progress': 1.15.0 - '@zag-js/qr-code': 1.15.0 - '@zag-js/radio-group': 1.15.0 - '@zag-js/rating-group': 1.15.0 - '@zag-js/react': 1.15.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@zag-js/select': 1.15.0 - '@zag-js/signature-pad': 1.15.0 - '@zag-js/slider': 1.15.0 - '@zag-js/splitter': 1.15.0 - '@zag-js/steps': 1.15.0 - '@zag-js/switch': 1.15.0 - '@zag-js/tabs': 1.15.0 - '@zag-js/tags-input': 1.15.0 - '@zag-js/time-picker': 1.15.0(@internationalized/date@3.8.1) - '@zag-js/timer': 1.15.0 - '@zag-js/toast': 1.15.0 - '@zag-js/toggle': 1.15.0 - '@zag-js/toggle-group': 1.15.0 - '@zag-js/tooltip': 1.15.0 - '@zag-js/tour': 1.15.0 - '@zag-js/tree-view': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@ark-ui/react@5.14.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@internationalized/date': 3.8.2 + '@zag-js/accordion': 1.15.2 + '@zag-js/anatomy': 1.15.2 + '@zag-js/angle-slider': 1.15.2 + '@zag-js/auto-resize': 1.15.2 + '@zag-js/avatar': 1.15.2 + '@zag-js/carousel': 1.15.2 + '@zag-js/checkbox': 1.15.2 + '@zag-js/clipboard': 1.15.2 + '@zag-js/collapsible': 1.15.2 + '@zag-js/collection': 1.15.2 + '@zag-js/color-picker': 1.15.2 + '@zag-js/color-utils': 1.15.2 + '@zag-js/combobox': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/date-picker': 1.15.2(@internationalized/date@3.8.2) + '@zag-js/date-utils': 1.15.2(@internationalized/date@3.8.2) + '@zag-js/dialog': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/editable': 1.15.2 + '@zag-js/file-upload': 1.15.2 + '@zag-js/file-utils': 1.15.2 + '@zag-js/floating-panel': 1.15.2 + '@zag-js/focus-trap': 1.15.2 + '@zag-js/highlight-word': 1.15.2 + '@zag-js/hover-card': 1.15.2 + '@zag-js/i18n-utils': 1.15.2 + '@zag-js/listbox': 1.15.2 + '@zag-js/menu': 1.15.2 + '@zag-js/number-input': 1.15.2 + '@zag-js/pagination': 1.15.2 + '@zag-js/password-input': 1.15.2 + '@zag-js/pin-input': 1.15.2 + '@zag-js/popover': 1.15.2 + '@zag-js/presence': 1.15.2 + '@zag-js/progress': 1.15.2 + '@zag-js/qr-code': 1.15.2 + '@zag-js/radio-group': 1.15.2 + '@zag-js/rating-group': 1.15.2 + '@zag-js/react': 1.15.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@zag-js/select': 1.15.2 + '@zag-js/signature-pad': 1.15.2 + '@zag-js/slider': 1.15.2 + '@zag-js/splitter': 1.15.2 + '@zag-js/steps': 1.15.2 + '@zag-js/switch': 1.15.2 + '@zag-js/tabs': 1.15.2 + '@zag-js/tags-input': 1.15.2 + '@zag-js/time-picker': 1.15.2(@internationalized/date@3.8.2) + '@zag-js/timer': 1.15.2 + '@zag-js/toast': 1.15.2 + '@zag-js/toggle': 1.15.2 + '@zag-js/toggle-group': 1.15.2 + '@zag-js/tooltip': 1.15.2 + '@zag-js/tour': 1.15.2 + '@zag-js/tree-view': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) @@ -3033,11 +3023,11 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@chakra-ui/react@3.20.0(@emotion/react@11.14.0(@types/react@19.1.7)(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@chakra-ui/react@3.21.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: - '@ark-ui/react': 5.12.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@ark-ui/react': 5.14.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@emotion/is-prop-valid': 1.3.1 - '@emotion/react': 11.14.0(@types/react@19.1.7)(react@19.1.0) + '@emotion/react': 11.14.0(@types/react@19.1.8)(react@19.1.0) '@emotion/serialize': 1.3.3 '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.1.0) '@emotion/utils': 1.4.2 @@ -3079,7 +3069,7 @@ snapshots: '@emotion/memoize@0.9.0': {} - '@emotion/react@11.14.0(@types/react@19.1.7)(react@19.1.0)': + '@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0)': dependencies: '@babel/runtime': 7.27.6 '@emotion/babel-plugin': 11.13.5 @@ -3091,7 +3081,7 @@ snapshots: hoist-non-react-statics: 3.3.2 react: 19.1.0 optionalDependencies: - '@types/react': 19.1.7 + '@types/react': 19.1.8 transitivePeerDependencies: - supports-color @@ -3115,93 +3105,93 @@ snapshots: '@emotion/weak-memoize@0.4.0': {} - '@esbuild/aix-ppc64@0.25.4': + '@esbuild/aix-ppc64@0.25.5': optional: true - '@esbuild/android-arm64@0.25.4': + '@esbuild/android-arm64@0.25.5': optional: true - '@esbuild/android-arm@0.25.4': + '@esbuild/android-arm@0.25.5': optional: true - '@esbuild/android-x64@0.25.4': + '@esbuild/android-x64@0.25.5': optional: true - '@esbuild/darwin-arm64@0.25.4': + '@esbuild/darwin-arm64@0.25.5': optional: true - '@esbuild/darwin-x64@0.25.4': + '@esbuild/darwin-x64@0.25.5': optional: true - '@esbuild/freebsd-arm64@0.25.4': + '@esbuild/freebsd-arm64@0.25.5': optional: true - '@esbuild/freebsd-x64@0.25.4': + '@esbuild/freebsd-x64@0.25.5': optional: true - '@esbuild/linux-arm64@0.25.4': + '@esbuild/linux-arm64@0.25.5': optional: true - '@esbuild/linux-arm@0.25.4': + '@esbuild/linux-arm@0.25.5': optional: true - '@esbuild/linux-ia32@0.25.4': + '@esbuild/linux-ia32@0.25.5': optional: true - '@esbuild/linux-loong64@0.25.4': + '@esbuild/linux-loong64@0.25.5': optional: true - '@esbuild/linux-mips64el@0.25.4': + '@esbuild/linux-mips64el@0.25.5': optional: true - '@esbuild/linux-ppc64@0.25.4': + '@esbuild/linux-ppc64@0.25.5': optional: true - '@esbuild/linux-riscv64@0.25.4': + '@esbuild/linux-riscv64@0.25.5': optional: true - '@esbuild/linux-s390x@0.25.4': + '@esbuild/linux-s390x@0.25.5': optional: true - '@esbuild/linux-x64@0.25.4': + '@esbuild/linux-x64@0.25.5': optional: true - '@esbuild/netbsd-arm64@0.25.4': + '@esbuild/netbsd-arm64@0.25.5': optional: true - '@esbuild/netbsd-x64@0.25.4': + '@esbuild/netbsd-x64@0.25.5': optional: true - '@esbuild/openbsd-arm64@0.25.4': + '@esbuild/openbsd-arm64@0.25.5': optional: true - '@esbuild/openbsd-x64@0.25.4': + '@esbuild/openbsd-x64@0.25.5': optional: true - '@esbuild/sunos-x64@0.25.4': + '@esbuild/sunos-x64@0.25.5': optional: true - '@esbuild/win32-arm64@0.25.4': + '@esbuild/win32-arm64@0.25.5': optional: true - '@esbuild/win32-ia32@0.25.4': + '@esbuild/win32-ia32@0.25.5': optional: true - '@esbuild/win32-x64@0.25.4': + '@esbuild/win32-x64@0.25.5': optional: true - '@eslint-community/eslint-utils@4.7.0(eslint@9.28.0(jiti@1.21.7))': + '@eslint-community/eslint-utils@4.7.0(eslint@9.29.0(jiti@1.21.7))': dependencies: - eslint: 9.28.0(jiti@1.21.7) + eslint: 9.29.0(jiti@1.21.7) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} - '@eslint/compat@1.2.9(eslint@9.28.0(jiti@1.21.7))': + '@eslint/compat@1.3.0(eslint@9.29.0(jiti@1.21.7))': optionalDependencies: - eslint: 9.28.0(jiti@1.21.7) + eslint: 9.29.0(jiti@1.21.7) - '@eslint/config-array@0.20.0': + '@eslint/config-array@0.20.1': dependencies: '@eslint/object-schema': 2.1.6 debug: 4.4.1 @@ -3209,7 +3199,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.2.2': {} + '@eslint/config-helpers@0.2.3': {} '@eslint/core@0.13.0': dependencies: @@ -3219,11 +3209,15 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 + '@eslint/core@0.15.0': + dependencies: + '@types/json-schema': 7.0.15 + '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 debug: 4.4.1 - espree: 10.3.0 + espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 @@ -3233,7 +3227,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.28.0': {} + '@eslint/js@9.29.0': {} '@eslint/object-schema@2.1.6': {} @@ -3242,9 +3236,9 @@ snapshots: '@eslint/core': 0.13.0 levn: 0.4.1 - '@eslint/plugin-kit@0.3.1': + '@eslint/plugin-kit@0.3.2': dependencies: - '@eslint/core': 0.14.0 + '@eslint/core': 0.15.0 levn: 0.4.1 '@floating-ui/core@1.7.1': @@ -3282,11 +3276,11 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@internationalized/date@3.8.1': + '@internationalized/date@3.8.2': dependencies: '@swc/helpers': 0.5.17 - '@internationalized/number@3.6.2': + '@internationalized/number@3.6.3': dependencies: '@swc/helpers': 0.5.17 @@ -3339,77 +3333,75 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.11': {} - '@rollup/rollup-android-arm-eabi@4.40.2': + '@rollup/rollup-android-arm-eabi@4.44.0': optional: true - '@rollup/rollup-android-arm64@4.40.2': + '@rollup/rollup-android-arm64@4.44.0': optional: true - '@rollup/rollup-darwin-arm64@4.40.2': + '@rollup/rollup-darwin-arm64@4.44.0': optional: true - '@rollup/rollup-darwin-x64@4.40.2': + '@rollup/rollup-darwin-x64@4.44.0': optional: true - '@rollup/rollup-freebsd-arm64@4.40.2': + '@rollup/rollup-freebsd-arm64@4.44.0': optional: true - '@rollup/rollup-freebsd-x64@4.40.2': + '@rollup/rollup-freebsd-x64@4.44.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.40.2': + '@rollup/rollup-linux-arm-gnueabihf@4.44.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.40.2': + '@rollup/rollup-linux-arm-musleabihf@4.44.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.40.2': + '@rollup/rollup-linux-arm64-gnu@4.44.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.40.2': + '@rollup/rollup-linux-arm64-musl@4.44.0': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.40.2': + '@rollup/rollup-linux-loongarch64-gnu@4.44.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.40.2': + '@rollup/rollup-linux-powerpc64le-gnu@4.44.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.40.2': + '@rollup/rollup-linux-riscv64-gnu@4.44.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.40.2': + '@rollup/rollup-linux-riscv64-musl@4.44.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.40.2': + '@rollup/rollup-linux-s390x-gnu@4.44.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.40.2': + '@rollup/rollup-linux-x64-gnu@4.44.0': optional: true - '@rollup/rollup-linux-x64-musl@4.40.2': + '@rollup/rollup-linux-x64-musl@4.44.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.40.2': + '@rollup/rollup-win32-arm64-msvc@4.44.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.40.2': + '@rollup/rollup-win32-ia32-msvc@4.44.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.40.2': + '@rollup/rollup-win32-x64-msvc@4.44.0': optional: true - '@stylistic/eslint-plugin@4.4.1(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3)': + '@stylistic/eslint-plugin@5.0.0(eslint@9.29.0(jiti@1.21.7))': dependencies: - '@typescript-eslint/utils': 8.33.1(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3) - eslint: 9.28.0(jiti@1.21.7) - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 + '@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0(jiti@1.21.7)) + '@typescript-eslint/types': 8.34.1 + eslint: 9.29.0(jiti@1.21.7) + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 estraverse: 5.3.0 picomatch: 4.0.2 - transitivePeerDependencies: - - supports-color - - typescript '@swc/core-darwin-arm64@1.11.31': optional: true @@ -3468,11 +3460,11 @@ snapshots: dependencies: '@swc/counter': 0.1.3 - '@tanstack/query-core@5.80.6': {} + '@tanstack/query-core@5.81.2': {} - '@tanstack/react-query@5.80.6(react@19.1.0)': + '@tanstack/react-query@5.81.2(react@19.1.0)': dependencies: - '@tanstack/query-core': 5.80.6 + '@tanstack/query-core': 5.81.2 react: 19.1.0 '@testing-library/dom@10.4.0': @@ -3496,17 +3488,17 @@ snapshots: lodash: 4.17.21 redent: 3.0.0 - '@testing-library/react@16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@testing-library/react@16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@babel/runtime': 7.27.1 '@testing-library/dom': 10.4.0 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.7 - '@types/react-dom': 19.1.6(@types/react@19.1.7) + '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) - '@trivago/prettier-plugin-sort-imports@5.2.2(prettier@3.5.3)': + '@trivago/prettier-plugin-sort-imports@5.2.2(prettier@3.6.0)': dependencies: '@babel/generator': 7.27.1 '@babel/parser': 7.27.1 @@ -3514,7 +3506,7 @@ snapshots: '@babel/types': 7.27.1 javascript-natural-sort: 0.7.1 lodash: 4.17.21 - prettier: 3.5.3 + prettier: 3.6.0 transitivePeerDependencies: - supports-color @@ -3533,36 +3525,40 @@ snapshots: '@types/deep-eql@4.0.2': {} - '@types/estree@1.0.7': {} - '@types/estree@1.0.8': {} '@types/hoist-non-react-statics@3.3.6': dependencies: - '@types/react': 19.1.7 + '@types/react': 19.1.8 hoist-non-react-statics: 3.3.2 '@types/json-schema@7.0.15': {} + '@types/node@20.19.1': + dependencies: + undici-types: 6.21.0 + '@types/parse-json@4.0.2': {} - '@types/react-dom@19.1.6(@types/react@19.1.7)': + '@types/react-dom@19.1.6(@types/react@19.1.8)': dependencies: - '@types/react': 19.1.7 + '@types/react': 19.1.8 - '@types/react@19.1.7': + '@types/react@19.1.8': dependencies: csstype: 3.1.3 - '@typescript-eslint/eslint-plugin@8.34.0(@typescript-eslint/parser@8.34.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3)': + '@types/whatwg-mimetype@3.0.2': {} + + '@typescript-eslint/eslint-plugin@8.35.0(@typescript-eslint/parser@8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.34.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/scope-manager': 8.34.0 - '@typescript-eslint/type-utils': 8.34.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/utils': 8.34.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.34.0 - eslint: 9.28.0(jiti@1.21.7) + '@typescript-eslint/parser': 8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.35.0 + '@typescript-eslint/type-utils': 8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/utils': 8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.35.0 + eslint: 9.29.0(jiti@1.21.7) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -3571,75 +3567,75 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.34.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3)': + '@typescript-eslint/parser@8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3)': dependencies: - '@typescript-eslint/scope-manager': 8.34.0 - '@typescript-eslint/types': 8.34.0 - '@typescript-eslint/typescript-estree': 8.34.0(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.34.0 + '@typescript-eslint/scope-manager': 8.35.0 + '@typescript-eslint/types': 8.35.0 + '@typescript-eslint/typescript-estree': 8.35.0(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.35.0 debug: 4.4.1 - eslint: 9.28.0(jiti@1.21.7) + eslint: 9.29.0(jiti@1.21.7) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.33.1(typescript@5.8.3)': + '@typescript-eslint/project-service@8.34.1(typescript@5.8.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.33.1(typescript@5.8.3) - '@typescript-eslint/types': 8.33.1 + '@typescript-eslint/tsconfig-utils': 8.34.1(typescript@5.8.3) + '@typescript-eslint/types': 8.34.1 debug: 4.4.1 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.34.0(typescript@5.8.3)': + '@typescript-eslint/project-service@8.35.0(typescript@5.8.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.34.0(typescript@5.8.3) - '@typescript-eslint/types': 8.34.0 + '@typescript-eslint/tsconfig-utils': 8.35.0(typescript@5.8.3) + '@typescript-eslint/types': 8.35.0 debug: 4.4.1 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.33.1': + '@typescript-eslint/scope-manager@8.34.1': dependencies: - '@typescript-eslint/types': 8.33.1 - '@typescript-eslint/visitor-keys': 8.33.1 + '@typescript-eslint/types': 8.34.1 + '@typescript-eslint/visitor-keys': 8.34.1 - '@typescript-eslint/scope-manager@8.34.0': + '@typescript-eslint/scope-manager@8.35.0': dependencies: - '@typescript-eslint/types': 8.34.0 - '@typescript-eslint/visitor-keys': 8.34.0 + '@typescript-eslint/types': 8.35.0 + '@typescript-eslint/visitor-keys': 8.35.0 - '@typescript-eslint/tsconfig-utils@8.33.1(typescript@5.8.3)': + '@typescript-eslint/tsconfig-utils@8.34.1(typescript@5.8.3)': dependencies: typescript: 5.8.3 - '@typescript-eslint/tsconfig-utils@8.34.0(typescript@5.8.3)': + '@typescript-eslint/tsconfig-utils@8.35.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 - '@typescript-eslint/type-utils@8.34.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3)': + '@typescript-eslint/type-utils@8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3)': dependencies: - '@typescript-eslint/typescript-estree': 8.34.0(typescript@5.8.3) - '@typescript-eslint/utils': 8.34.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.35.0(typescript@5.8.3) + '@typescript-eslint/utils': 8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3) debug: 4.4.1 - eslint: 9.28.0(jiti@1.21.7) + eslint: 9.29.0(jiti@1.21.7) ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.33.1': {} + '@typescript-eslint/types@8.34.1': {} - '@typescript-eslint/types@8.34.0': {} + '@typescript-eslint/types@8.35.0': {} - '@typescript-eslint/typescript-estree@8.33.1(typescript@5.8.3)': + '@typescript-eslint/typescript-estree@8.34.1(typescript@5.8.3)': dependencies: - '@typescript-eslint/project-service': 8.33.1(typescript@5.8.3) - '@typescript-eslint/tsconfig-utils': 8.33.1(typescript@5.8.3) - '@typescript-eslint/types': 8.33.1 - '@typescript-eslint/visitor-keys': 8.33.1 + '@typescript-eslint/project-service': 8.34.1(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.34.1(typescript@5.8.3) + '@typescript-eslint/types': 8.34.1 + '@typescript-eslint/visitor-keys': 8.34.1 debug: 4.4.1 fast-glob: 3.3.3 is-glob: 4.0.3 @@ -3650,12 +3646,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.34.0(typescript@5.8.3)': + '@typescript-eslint/typescript-estree@8.35.0(typescript@5.8.3)': dependencies: - '@typescript-eslint/project-service': 8.34.0(typescript@5.8.3) - '@typescript-eslint/tsconfig-utils': 8.34.0(typescript@5.8.3) - '@typescript-eslint/types': 8.34.0 - '@typescript-eslint/visitor-keys': 8.34.0 + '@typescript-eslint/project-service': 8.35.0(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.35.0(typescript@5.8.3) + '@typescript-eslint/types': 8.35.0 + '@typescript-eslint/visitor-keys': 8.35.0 debug: 4.4.1 fast-glob: 3.3.3 is-glob: 4.0.3 @@ -3666,592 +3662,592 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.33.1(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3)': + '@typescript-eslint/utils@8.34.1(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0(jiti@1.21.7)) - '@typescript-eslint/scope-manager': 8.33.1 - '@typescript-eslint/types': 8.33.1 - '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) - eslint: 9.28.0(jiti@1.21.7) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0(jiti@1.21.7)) + '@typescript-eslint/scope-manager': 8.34.1 + '@typescript-eslint/types': 8.34.1 + '@typescript-eslint/typescript-estree': 8.34.1(typescript@5.8.3) + eslint: 9.29.0(jiti@1.21.7) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.34.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3)': + '@typescript-eslint/utils@8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0(jiti@1.21.7)) - '@typescript-eslint/scope-manager': 8.34.0 - '@typescript-eslint/types': 8.34.0 - '@typescript-eslint/typescript-estree': 8.34.0(typescript@5.8.3) - eslint: 9.28.0(jiti@1.21.7) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0(jiti@1.21.7)) + '@typescript-eslint/scope-manager': 8.35.0 + '@typescript-eslint/types': 8.35.0 + '@typescript-eslint/typescript-estree': 8.35.0(typescript@5.8.3) + eslint: 9.29.0(jiti@1.21.7) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.33.1': + '@typescript-eslint/visitor-keys@8.34.1': dependencies: - '@typescript-eslint/types': 8.33.1 - eslint-visitor-keys: 4.2.0 + '@typescript-eslint/types': 8.34.1 + eslint-visitor-keys: 4.2.1 - '@typescript-eslint/visitor-keys@8.34.0': + '@typescript-eslint/visitor-keys@8.35.0': dependencies: - '@typescript-eslint/types': 8.34.0 + '@typescript-eslint/types': 8.35.0 eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-react-swc@3.10.2(@swc/helpers@0.5.17)(vite@6.3.5(jiti@1.21.7))': + '@vitejs/plugin-react-swc@3.10.2(@swc/helpers@0.5.17)(vite@7.0.0(@types/node@20.19.1)(jiti@1.21.7))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.11 '@swc/core': 1.11.31(@swc/helpers@0.5.17) - vite: 6.3.5(jiti@1.21.7) + vite: 7.0.0(@types/node@20.19.1)(jiti@1.21.7) transitivePeerDependencies: - '@swc/helpers' - '@vitest/expect@3.2.3': + '@vitest/expect@3.2.4': dependencies: '@types/chai': 5.2.2 - '@vitest/spy': 3.2.3 - '@vitest/utils': 3.2.3 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.3(vite@6.3.5(jiti@1.21.7))': + '@vitest/mocker@3.2.4(vite@7.0.0(@types/node@20.19.1)(jiti@1.21.7))': dependencies: - '@vitest/spy': 3.2.3 + '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.3.5(jiti@1.21.7) + vite: 7.0.0(@types/node@20.19.1)(jiti@1.21.7) - '@vitest/pretty-format@3.2.3': + '@vitest/pretty-format@3.2.4': dependencies: tinyrainbow: 2.0.0 - '@vitest/runner@3.2.3': + '@vitest/runner@3.2.4': dependencies: - '@vitest/utils': 3.2.3 + '@vitest/utils': 3.2.4 pathe: 2.0.3 strip-literal: 3.0.0 - '@vitest/snapshot@3.2.3': + '@vitest/snapshot@3.2.4': dependencies: - '@vitest/pretty-format': 3.2.3 + '@vitest/pretty-format': 3.2.4 magic-string: 0.30.17 pathe: 2.0.3 - '@vitest/spy@3.2.3': + '@vitest/spy@3.2.4': dependencies: tinyspy: 4.0.3 - '@vitest/utils@3.2.3': + '@vitest/utils@3.2.4': dependencies: - '@vitest/pretty-format': 3.2.3 - loupe: 3.1.3 + '@vitest/pretty-format': 3.2.4 + loupe: 3.1.4 tinyrainbow: 2.0.0 - '@zag-js/accordion@1.15.0': + '@zag-js/accordion@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/anatomy@1.15.0': {} + '@zag-js/anatomy@1.15.2': {} - '@zag-js/angle-slider@1.15.0': + '@zag-js/angle-slider@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/rect-utils': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/rect-utils': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/aria-hidden@1.15.0': {} + '@zag-js/aria-hidden@1.15.2': {} - '@zag-js/auto-resize@1.15.0': + '@zag-js/auto-resize@1.15.2': dependencies: - '@zag-js/dom-query': 1.15.0 + '@zag-js/dom-query': 1.15.2 - '@zag-js/avatar@1.15.0': + '@zag-js/avatar@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/carousel@1.15.0': + '@zag-js/carousel@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/scroll-snap': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/scroll-snap': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/checkbox@1.15.0': + '@zag-js/checkbox@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/focus-visible': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/focus-visible': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/clipboard@1.15.0': + '@zag-js/clipboard@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/collapsible@1.15.0': + '@zag-js/collapsible@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/collection@1.15.0': + '@zag-js/collection@1.15.2': dependencies: - '@zag-js/utils': 1.15.0 + '@zag-js/utils': 1.15.2 - '@zag-js/color-picker@1.15.0': + '@zag-js/color-picker@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/color-utils': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dismissable': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/popper': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/color-utils': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dismissable': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/popper': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/color-utils@1.15.0': + '@zag-js/color-utils@1.15.2': dependencies: - '@zag-js/utils': 1.15.0 + '@zag-js/utils': 1.15.2 - '@zag-js/combobox@1.15.0': + '@zag-js/combobox@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/aria-hidden': 1.15.0 - '@zag-js/collection': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dismissable': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/popper': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/aria-hidden': 1.15.2 + '@zag-js/collection': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dismissable': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/popper': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/core@1.15.0': + '@zag-js/core@1.15.2': dependencies: - '@zag-js/dom-query': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/dom-query': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/date-picker@1.15.0(@internationalized/date@3.8.1)': + '@zag-js/date-picker@1.15.2(@internationalized/date@3.8.2)': dependencies: - '@internationalized/date': 3.8.1 - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/date-utils': 1.15.0(@internationalized/date@3.8.1) - '@zag-js/dismissable': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/live-region': 1.15.0 - '@zag-js/popper': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@internationalized/date': 3.8.2 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/date-utils': 1.15.2(@internationalized/date@3.8.2) + '@zag-js/dismissable': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/live-region': 1.15.2 + '@zag-js/popper': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/date-utils@1.15.0(@internationalized/date@3.8.1)': + '@zag-js/date-utils@1.15.2(@internationalized/date@3.8.2)': dependencies: - '@internationalized/date': 3.8.1 + '@internationalized/date': 3.8.2 - '@zag-js/dialog@1.15.0': + '@zag-js/dialog@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/aria-hidden': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dismissable': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/focus-trap': 1.15.0 - '@zag-js/remove-scroll': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/aria-hidden': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dismissable': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/focus-trap': 1.15.2 + '@zag-js/remove-scroll': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/dismissable@1.15.0': + '@zag-js/dismissable@1.15.2': dependencies: - '@zag-js/dom-query': 1.15.0 - '@zag-js/interact-outside': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/dom-query': 1.15.2 + '@zag-js/interact-outside': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/dom-query@1.15.0': + '@zag-js/dom-query@1.15.2': dependencies: - '@zag-js/types': 1.15.0 + '@zag-js/types': 1.15.2 - '@zag-js/editable@1.15.0': + '@zag-js/editable@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/interact-outside': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/interact-outside': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/file-upload@1.15.0': + '@zag-js/file-upload@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/file-utils': 1.15.0 - '@zag-js/i18n-utils': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/file-utils': 1.15.2 + '@zag-js/i18n-utils': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/file-utils@1.15.0': + '@zag-js/file-utils@1.15.2': dependencies: - '@zag-js/i18n-utils': 1.15.0 + '@zag-js/i18n-utils': 1.15.2 - '@zag-js/floating-panel@1.15.0': + '@zag-js/floating-panel@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dismissable': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/popper': 1.15.0 - '@zag-js/rect-utils': 1.15.0 - '@zag-js/store': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dismissable': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/popper': 1.15.2 + '@zag-js/rect-utils': 1.15.2 + '@zag-js/store': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/focus-trap@1.15.0': + '@zag-js/focus-trap@1.15.2': dependencies: - '@zag-js/dom-query': 1.15.0 + '@zag-js/dom-query': 1.15.2 - '@zag-js/focus-visible@1.15.0': + '@zag-js/focus-visible@1.15.2': dependencies: - '@zag-js/dom-query': 1.15.0 + '@zag-js/dom-query': 1.15.2 - '@zag-js/highlight-word@1.15.0': {} + '@zag-js/highlight-word@1.15.2': {} - '@zag-js/hover-card@1.15.0': + '@zag-js/hover-card@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dismissable': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/popper': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dismissable': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/popper': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/i18n-utils@1.15.0': + '@zag-js/i18n-utils@1.15.2': dependencies: - '@zag-js/dom-query': 1.15.0 + '@zag-js/dom-query': 1.15.2 - '@zag-js/interact-outside@1.15.0': + '@zag-js/interact-outside@1.15.2': dependencies: - '@zag-js/dom-query': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/dom-query': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/listbox@1.15.0': + '@zag-js/listbox@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/collection': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/focus-visible': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/collection': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/focus-visible': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/live-region@1.15.0': {} + '@zag-js/live-region@1.15.2': {} - '@zag-js/menu@1.15.0': + '@zag-js/menu@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dismissable': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/popper': 1.15.0 - '@zag-js/rect-utils': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dismissable': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/popper': 1.15.2 + '@zag-js/rect-utils': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/number-input@1.15.0': + '@zag-js/number-input@1.15.2': dependencies: - '@internationalized/number': 3.6.2 - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@internationalized/number': 3.6.3 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/pagination@1.15.0': + '@zag-js/pagination@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/password-input@1.15.0': + '@zag-js/password-input@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/pin-input@1.15.0': + '@zag-js/pin-input@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/popover@1.15.0': + '@zag-js/popover@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/aria-hidden': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dismissable': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/focus-trap': 1.15.0 - '@zag-js/popper': 1.15.0 - '@zag-js/remove-scroll': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/aria-hidden': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dismissable': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/focus-trap': 1.15.2 + '@zag-js/popper': 1.15.2 + '@zag-js/remove-scroll': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/popper@1.15.0': + '@zag-js/popper@1.15.2': dependencies: '@floating-ui/dom': 1.7.1 - '@zag-js/dom-query': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/dom-query': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/presence@1.15.0': + '@zag-js/presence@1.15.2': dependencies: - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 - '@zag-js/progress@1.15.0': + '@zag-js/progress@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/qr-code@1.15.0': + '@zag-js/qr-code@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 proxy-memoize: 3.0.1 uqr: 0.1.2 - '@zag-js/radio-group@1.15.0': + '@zag-js/radio-group@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/focus-visible': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/focus-visible': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/rating-group@1.15.0': + '@zag-js/rating-group@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/react@1.15.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@zag-js/react@1.15.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: - '@zag-js/core': 1.15.0 - '@zag-js/store': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/core': 1.15.2 + '@zag-js/store': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - '@zag-js/rect-utils@1.15.0': {} + '@zag-js/rect-utils@1.15.2': {} - '@zag-js/remove-scroll@1.15.0': + '@zag-js/remove-scroll@1.15.2': dependencies: - '@zag-js/dom-query': 1.15.0 + '@zag-js/dom-query': 1.15.2 - '@zag-js/scroll-snap@1.15.0': + '@zag-js/scroll-snap@1.15.2': dependencies: - '@zag-js/dom-query': 1.15.0 + '@zag-js/dom-query': 1.15.2 - '@zag-js/select@1.15.0': + '@zag-js/select@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/collection': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dismissable': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/popper': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/collection': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dismissable': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/popper': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/signature-pad@1.15.0': + '@zag-js/signature-pad@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 perfect-freehand: 1.2.2 - '@zag-js/slider@1.15.0': + '@zag-js/slider@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/splitter@1.15.0': + '@zag-js/splitter@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/steps@1.15.0': + '@zag-js/steps@1.15.2': dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 - '@zag-js/store@1.15.0': + '@zag-js/store@1.15.2': dependencies: proxy-compare: 3.0.1 - '@zag-js/switch@1.15.0': - dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/focus-visible': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 - - '@zag-js/tabs@1.15.0': - dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 - - '@zag-js/tags-input@1.15.0': - dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/auto-resize': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/interact-outside': 1.15.0 - '@zag-js/live-region': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 - - '@zag-js/time-picker@1.15.0(@internationalized/date@3.8.1)': - dependencies: - '@internationalized/date': 3.8.1 - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dismissable': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/popper': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 - - '@zag-js/timer@1.15.0': - dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 - - '@zag-js/toast@1.15.0': - dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dismissable': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 - - '@zag-js/toggle-group@1.15.0': - dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 - - '@zag-js/toggle@1.15.0': - dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 - - '@zag-js/tooltip@1.15.0': - dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/focus-visible': 1.15.0 - '@zag-js/popper': 1.15.0 - '@zag-js/store': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 - - '@zag-js/tour@1.15.0': - dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dismissable': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/focus-trap': 1.15.0 - '@zag-js/interact-outside': 1.15.0 - '@zag-js/popper': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 - - '@zag-js/tree-view@1.15.0': - dependencies: - '@zag-js/anatomy': 1.15.0 - '@zag-js/collection': 1.15.0 - '@zag-js/core': 1.15.0 - '@zag-js/dom-query': 1.15.0 - '@zag-js/types': 1.15.0 - '@zag-js/utils': 1.15.0 - - '@zag-js/types@1.15.0': + '@zag-js/switch@1.15.2': + dependencies: + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/focus-visible': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 + + '@zag-js/tabs@1.15.2': + dependencies: + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 + + '@zag-js/tags-input@1.15.2': + dependencies: + '@zag-js/anatomy': 1.15.2 + '@zag-js/auto-resize': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/interact-outside': 1.15.2 + '@zag-js/live-region': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 + + '@zag-js/time-picker@1.15.2(@internationalized/date@3.8.2)': + dependencies: + '@internationalized/date': 3.8.2 + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dismissable': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/popper': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 + + '@zag-js/timer@1.15.2': + dependencies: + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 + + '@zag-js/toast@1.15.2': + dependencies: + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dismissable': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 + + '@zag-js/toggle-group@1.15.2': + dependencies: + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 + + '@zag-js/toggle@1.15.2': + dependencies: + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 + + '@zag-js/tooltip@1.15.2': + dependencies: + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/focus-visible': 1.15.2 + '@zag-js/popper': 1.15.2 + '@zag-js/store': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 + + '@zag-js/tour@1.15.2': + dependencies: + '@zag-js/anatomy': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dismissable': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/focus-trap': 1.15.2 + '@zag-js/interact-outside': 1.15.2 + '@zag-js/popper': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 + + '@zag-js/tree-view@1.15.2': + dependencies: + '@zag-js/anatomy': 1.15.2 + '@zag-js/collection': 1.15.2 + '@zag-js/core': 1.15.2 + '@zag-js/dom-query': 1.15.2 + '@zag-js/types': 1.15.2 + '@zag-js/utils': 1.15.2 + + '@zag-js/types@1.15.2': dependencies: csstype: 3.1.3 - '@zag-js/utils@1.15.0': {} + '@zag-js/utils@1.15.2': {} - acorn-jsx@5.3.2(acorn@8.14.1): + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: - acorn: 8.14.1 + acorn: 8.15.0 - acorn@8.14.1: {} + acorn@8.15.0: {} ajv@6.12.6: dependencies: @@ -4354,10 +4350,10 @@ snapshots: axe-core@4.10.3: {} - axios@1.9.0: + axios@1.10.0: dependencies: follow-redirects: 1.15.9 - form-data: 4.0.2 + form-data: 4.0.3 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug @@ -4374,12 +4370,12 @@ snapshots: binary-extensions@2.3.0: {} - brace-expansion@1.1.11: + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.0.1: + brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 @@ -4443,7 +4439,7 @@ snapshots: assertion-error: 2.0.1 check-error: 2.1.1 deep-eql: 5.0.2 - loupe: 3.1.3 + loupe: 3.1.4 pathval: 2.0.0 chalk@3.0.0: @@ -4704,33 +4700,33 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - esbuild@0.25.4: + esbuild@0.25.5: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.4 - '@esbuild/android-arm': 0.25.4 - '@esbuild/android-arm64': 0.25.4 - '@esbuild/android-x64': 0.25.4 - '@esbuild/darwin-arm64': 0.25.4 - '@esbuild/darwin-x64': 0.25.4 - '@esbuild/freebsd-arm64': 0.25.4 - '@esbuild/freebsd-x64': 0.25.4 - '@esbuild/linux-arm': 0.25.4 - '@esbuild/linux-arm64': 0.25.4 - '@esbuild/linux-ia32': 0.25.4 - '@esbuild/linux-loong64': 0.25.4 - '@esbuild/linux-mips64el': 0.25.4 - '@esbuild/linux-ppc64': 0.25.4 - '@esbuild/linux-riscv64': 0.25.4 - '@esbuild/linux-s390x': 0.25.4 - '@esbuild/linux-x64': 0.25.4 - '@esbuild/netbsd-arm64': 0.25.4 - '@esbuild/netbsd-x64': 0.25.4 - '@esbuild/openbsd-arm64': 0.25.4 - '@esbuild/openbsd-x64': 0.25.4 - '@esbuild/sunos-x64': 0.25.4 - '@esbuild/win32-arm64': 0.25.4 - '@esbuild/win32-ia32': 0.25.4 - '@esbuild/win32-x64': 0.25.4 + '@esbuild/aix-ppc64': 0.25.5 + '@esbuild/android-arm': 0.25.5 + '@esbuild/android-arm64': 0.25.5 + '@esbuild/android-x64': 0.25.5 + '@esbuild/darwin-arm64': 0.25.5 + '@esbuild/darwin-x64': 0.25.5 + '@esbuild/freebsd-arm64': 0.25.5 + '@esbuild/freebsd-x64': 0.25.5 + '@esbuild/linux-arm': 0.25.5 + '@esbuild/linux-arm64': 0.25.5 + '@esbuild/linux-ia32': 0.25.5 + '@esbuild/linux-loong64': 0.25.5 + '@esbuild/linux-mips64el': 0.25.5 + '@esbuild/linux-ppc64': 0.25.5 + '@esbuild/linux-riscv64': 0.25.5 + '@esbuild/linux-s390x': 0.25.5 + '@esbuild/linux-x64': 0.25.5 + '@esbuild/netbsd-arm64': 0.25.5 + '@esbuild/netbsd-x64': 0.25.5 + '@esbuild/openbsd-arm64': 0.25.5 + '@esbuild/openbsd-x64': 0.25.5 + '@esbuild/sunos-x64': 0.25.5 + '@esbuild/win32-arm64': 0.25.5 + '@esbuild/win32-ia32': 0.25.5 + '@esbuild/win32-x64': 0.25.5 escalade@3.2.0: {} @@ -4738,11 +4734,11 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.5(eslint@9.28.0(jiti@1.21.7)): + eslint-config-prettier@10.1.5(eslint@9.29.0(jiti@1.21.7)): dependencies: - eslint: 9.28.0(jiti@1.21.7) + eslint: 9.29.0(jiti@1.21.7) - eslint-plugin-jsx-a11y@6.10.2(eslint@9.28.0(jiti@1.21.7)): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.29.0(jiti@1.21.7)): dependencies: aria-query: 5.3.2 array-includes: 3.1.8 @@ -4752,7 +4748,7 @@ snapshots: axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 9.28.0(jiti@1.21.7) + eslint: 9.29.0(jiti@1.21.7) hasown: 2.0.2 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -4761,34 +4757,34 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-perfectionist@4.14.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3): + eslint-plugin-perfectionist@4.15.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3): dependencies: - '@typescript-eslint/types': 8.33.1 - '@typescript-eslint/utils': 8.33.1(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3) - eslint: 9.28.0(jiti@1.21.7) + '@typescript-eslint/types': 8.34.1 + '@typescript-eslint/utils': 8.34.1(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3) + eslint: 9.29.0(jiti@1.21.7) natural-orderby: 5.0.0 transitivePeerDependencies: - supports-color - typescript - eslint-plugin-prettier@5.4.1(eslint-config-prettier@10.1.5(eslint@9.28.0(jiti@1.21.7)))(eslint@9.28.0(jiti@1.21.7))(prettier@3.5.3): + eslint-plugin-prettier@5.5.0(eslint-config-prettier@10.1.5(eslint@9.29.0(jiti@1.21.7)))(eslint@9.29.0(jiti@1.21.7))(prettier@3.6.0): dependencies: - eslint: 9.28.0(jiti@1.21.7) - prettier: 3.5.3 + eslint: 9.29.0(jiti@1.21.7) + prettier: 3.6.0 prettier-linter-helpers: 1.0.0 synckit: 0.11.8 optionalDependencies: - eslint-config-prettier: 10.1.5(eslint@9.28.0(jiti@1.21.7)) + eslint-config-prettier: 10.1.5(eslint@9.29.0(jiti@1.21.7)) - eslint-plugin-react-hooks@5.2.0(eslint@9.28.0(jiti@1.21.7)): + eslint-plugin-react-hooks@5.2.0(eslint@9.29.0(jiti@1.21.7)): dependencies: - eslint: 9.28.0(jiti@1.21.7) + eslint: 9.29.0(jiti@1.21.7) - eslint-plugin-react-refresh@0.4.20(eslint@9.28.0(jiti@1.21.7)): + eslint-plugin-react-refresh@0.4.20(eslint@9.29.0(jiti@1.21.7)): dependencies: - eslint: 9.28.0(jiti@1.21.7) + eslint: 9.29.0(jiti@1.21.7) - eslint-plugin-react@7.37.5(eslint@9.28.0(jiti@1.21.7)): + eslint-plugin-react@7.37.5(eslint@9.29.0(jiti@1.21.7)): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 @@ -4796,7 +4792,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 9.28.0(jiti@1.21.7) + eslint: 9.29.0(jiti@1.21.7) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -4810,15 +4806,15 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-unicorn@59.0.1(eslint@9.28.0(jiti@1.21.7)): + eslint-plugin-unicorn@59.0.1(eslint@9.29.0(jiti@1.21.7)): dependencies: '@babel/helper-validator-identifier': 7.27.1 - '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0(jiti@1.21.7)) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0(jiti@1.21.7)) '@eslint/plugin-kit': 0.2.8 ci-info: 4.2.0 clean-regexp: 1.0.0 core-js-compat: 3.42.0 - eslint: 9.28.0(jiti@1.21.7) + eslint: 9.29.0(jiti@1.21.7) esquery: 1.6.0 find-up-simple: 1.0.1 globals: 16.1.0 @@ -4831,40 +4827,38 @@ snapshots: semver: 7.7.1 strip-indent: 4.0.0 - eslint-scope@8.3.0: + eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 eslint-visitor-keys@3.4.3: {} - eslint-visitor-keys@4.2.0: {} - eslint-visitor-keys@4.2.1: {} - eslint@9.28.0(jiti@1.21.7): + eslint@9.29.0(jiti@1.21.7): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0(jiti@1.21.7)) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0(jiti@1.21.7)) '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.20.0 - '@eslint/config-helpers': 0.2.2 + '@eslint/config-array': 0.20.1 + '@eslint/config-helpers': 0.2.3 '@eslint/core': 0.14.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.28.0 - '@eslint/plugin-kit': 0.3.1 + '@eslint/js': 9.29.0 + '@eslint/plugin-kit': 0.3.2 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.1 escape-string-regexp: 4.0.0 - eslint-scope: 8.3.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -4884,11 +4878,11 @@ snapshots: transitivePeerDependencies: - supports-color - espree@10.3.0: + espree@10.4.0: dependencies: - acorn: 8.14.1 - acorn-jsx: 5.3.2(acorn@8.14.1) - eslint-visitor-keys: 4.2.0 + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 esquery@1.6.0: dependencies: @@ -4930,10 +4924,6 @@ snapshots: dependencies: reusify: 1.1.0 - fdir@6.4.4(picomatch@4.0.2): - optionalDependencies: - picomatch: 4.0.2 - fdir@6.4.6(picomatch@4.0.2): optionalDependencies: picomatch: 4.0.2 @@ -4973,11 +4963,12 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - form-data@4.0.2: + form-data@4.0.3: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 es-set-tostringtag: 2.1.0 + hasown: 2.0.2 mime-types: 2.1.35 fs-minipass@2.1.0: @@ -5075,9 +5066,10 @@ snapshots: optionalDependencies: uglify-js: 3.19.3 - happy-dom@17.6.3: + happy-dom@18.0.1: dependencies: - webidl-conversions: 7.0.0 + '@types/node': 20.19.1 + '@types/whatwg-mimetype': 3.0.2 whatwg-mimetype: 3.0.0 has-bigints@1.1.0: {} @@ -5323,7 +5315,7 @@ snapshots: dependencies: js-tokens: 4.0.0 - loupe@3.1.3: {} + loupe@3.1.4: {} lru-cache@10.4.3: {} @@ -5359,11 +5351,11 @@ snapshots: minimatch@3.1.2: dependencies: - brace-expansion: 1.1.11 + brace-expansion: 1.1.12 minimatch@9.0.5: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimist@1.2.8: {} @@ -5386,7 +5378,7 @@ snapshots: mlly@1.7.4: dependencies: - acorn: 8.14.1 + acorn: 8.15.0 pathe: 2.0.3 pkg-types: 1.3.1 ufo: 1.5.4 @@ -5536,7 +5528,7 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss@8.5.3: + postcss@8.5.6: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 @@ -5548,7 +5540,7 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier@3.5.3: {} + prettier@3.6.0: {} pretty-format@27.5.1: dependencies: @@ -5591,7 +5583,7 @@ snapshots: react: 19.1.0 scheduler: 0.26.0 - react-hook-form@7.57.0(react@19.1.0): + react-hook-form@7.58.1(react@19.1.0): dependencies: react: 19.1.0 @@ -5666,30 +5658,30 @@ snapshots: reusify@1.1.0: {} - rollup@4.40.2: + rollup@4.44.0: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.40.2 - '@rollup/rollup-android-arm64': 4.40.2 - '@rollup/rollup-darwin-arm64': 4.40.2 - '@rollup/rollup-darwin-x64': 4.40.2 - '@rollup/rollup-freebsd-arm64': 4.40.2 - '@rollup/rollup-freebsd-x64': 4.40.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.40.2 - '@rollup/rollup-linux-arm-musleabihf': 4.40.2 - '@rollup/rollup-linux-arm64-gnu': 4.40.2 - '@rollup/rollup-linux-arm64-musl': 4.40.2 - '@rollup/rollup-linux-loongarch64-gnu': 4.40.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.40.2 - '@rollup/rollup-linux-riscv64-gnu': 4.40.2 - '@rollup/rollup-linux-riscv64-musl': 4.40.2 - '@rollup/rollup-linux-s390x-gnu': 4.40.2 - '@rollup/rollup-linux-x64-gnu': 4.40.2 - '@rollup/rollup-linux-x64-musl': 4.40.2 - '@rollup/rollup-win32-arm64-msvc': 4.40.2 - '@rollup/rollup-win32-ia32-msvc': 4.40.2 - '@rollup/rollup-win32-x64-msvc': 4.40.2 + '@rollup/rollup-android-arm-eabi': 4.44.0 + '@rollup/rollup-android-arm64': 4.44.0 + '@rollup/rollup-darwin-arm64': 4.44.0 + '@rollup/rollup-darwin-x64': 4.44.0 + '@rollup/rollup-freebsd-arm64': 4.44.0 + '@rollup/rollup-freebsd-x64': 4.44.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.44.0 + '@rollup/rollup-linux-arm-musleabihf': 4.44.0 + '@rollup/rollup-linux-arm64-gnu': 4.44.0 + '@rollup/rollup-linux-arm64-musl': 4.44.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.44.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.44.0 + '@rollup/rollup-linux-riscv64-gnu': 4.44.0 + '@rollup/rollup-linux-riscv64-musl': 4.44.0 + '@rollup/rollup-linux-s390x-gnu': 4.44.0 + '@rollup/rollup-linux-x64-gnu': 4.44.0 + '@rollup/rollup-linux-x64-musl': 4.44.0 + '@rollup/rollup-win32-arm64-msvc': 4.44.0 + '@rollup/rollup-win32-ia32-msvc': 4.44.0 + '@rollup/rollup-win32-x64-msvc': 4.44.0 fsevents: 2.3.3 run-parallel@1.2.0: @@ -5904,17 +5896,12 @@ snapshots: tinyexec@0.3.2: {} - tinyglobby@0.2.13: - dependencies: - fdir: 6.4.4(picomatch@4.0.2) - picomatch: 4.0.2 - tinyglobby@0.2.14: dependencies: fdir: 6.4.6(picomatch@4.0.2) picomatch: 4.0.2 - tinypool@1.1.0: {} + tinypool@1.1.1: {} tinyrainbow@2.0.0: {} @@ -5972,12 +5959,12 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.34.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3): + typescript-eslint@8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.34.0(@typescript-eslint/parser@8.34.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/parser': 8.34.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/utils': 8.34.0(eslint@9.28.0(jiti@1.21.7))(typescript@5.8.3) - eslint: 9.28.0(jiti@1.21.7) + '@typescript-eslint/eslint-plugin': 8.35.0(@typescript-eslint/parser@8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': 8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/utils': 8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3) + eslint: 9.29.0(jiti@1.21.7) typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -5996,6 +5983,8 @@ snapshots: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 + undici-types@6.21.0: {} + universal-cookie@8.0.1: dependencies: cookie: 1.0.2 @@ -6012,13 +6001,13 @@ snapshots: dependencies: punycode: 2.3.1 - vite-node@3.2.3(jiti@1.21.7): + vite-node@3.2.4(@types/node@20.19.1)(jiti@1.21.7): dependencies: cac: 6.7.14 debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(jiti@1.21.7) + vite: 7.0.0(@types/node@20.19.1)(jiti@1.21.7) transitivePeerDependencies: - '@types/node' - jiti @@ -6033,32 +6022,33 @@ snapshots: - tsx - yaml - vite-plugin-css-injected-by-js@3.5.2(vite@6.3.5(jiti@1.21.7)): + vite-plugin-css-injected-by-js@3.5.2(vite@7.0.0(@types/node@20.19.1)(jiti@1.21.7)): dependencies: - vite: 6.3.5(jiti@1.21.7) + vite: 7.0.0(@types/node@20.19.1)(jiti@1.21.7) - vite@6.3.5(jiti@1.21.7): + vite@7.0.0(@types/node@20.19.1)(jiti@1.21.7): dependencies: - esbuild: 0.25.4 - fdir: 6.4.4(picomatch@4.0.2) + esbuild: 0.25.5 + fdir: 6.4.6(picomatch@4.0.2) picomatch: 4.0.2 - postcss: 8.5.3 - rollup: 4.40.2 - tinyglobby: 0.2.13 + postcss: 8.5.6 + rollup: 4.44.0 + tinyglobby: 0.2.14 optionalDependencies: + '@types/node': 20.19.1 fsevents: 2.3.3 jiti: 1.21.7 - vitest@3.2.3(happy-dom@17.6.3)(jiti@1.21.7): + vitest@3.2.4(@types/node@20.19.1)(happy-dom@18.0.1)(jiti@1.21.7): dependencies: '@types/chai': 5.2.2 - '@vitest/expect': 3.2.3 - '@vitest/mocker': 3.2.3(vite@6.3.5(jiti@1.21.7)) - '@vitest/pretty-format': 3.2.3 - '@vitest/runner': 3.2.3 - '@vitest/snapshot': 3.2.3 - '@vitest/spy': 3.2.3 - '@vitest/utils': 3.2.3 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@7.0.0(@types/node@20.19.1)(jiti@1.21.7)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 chai: 5.2.0 debug: 4.4.1 expect-type: 1.2.1 @@ -6069,13 +6059,14 @@ snapshots: tinybench: 2.9.0 tinyexec: 0.3.2 tinyglobby: 0.2.14 - tinypool: 1.1.0 + tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.3.5(jiti@1.21.7) - vite-node: 3.2.3(jiti@1.21.7) + vite: 7.0.0(@types/node@20.19.1)(jiti@1.21.7) + vite-node: 3.2.4(@types/node@20.19.1)(jiti@1.21.7) why-is-node-running: 2.3.0 optionalDependencies: - happy-dom: 17.6.3 + '@types/node': 20.19.1 + happy-dom: 18.0.1 transitivePeerDependencies: - jiti - less @@ -6090,8 +6081,6 @@ snapshots: - tsx - yaml - webidl-conversions@7.0.0: {} - whatwg-mimetype@3.0.0: {} which-boxed-primitive@1.1.1: diff --git a/airflow-core/src/airflow/api_fastapi/auth/tokens.py b/airflow-core/src/airflow/api_fastapi/auth/tokens.py index d56678f052811..f80b7513d8ee8 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/tokens.py +++ b/airflow-core/src/airflow/api_fastapi/auth/tokens.py @@ -21,9 +21,9 @@ import time import uuid from base64 import urlsafe_b64encode -from collections.abc import Sequence +from collections.abc import Callable, Sequence from datetime import datetime -from typing import TYPE_CHECKING, Any, Callable, Literal, overload +from typing import TYPE_CHECKING, Any, Literal, overload import attrs import httpx diff --git a/airflow-core/src/airflow/api_fastapi/common/parameters.py b/airflow-core/src/airflow/api_fastapi/common/parameters.py index 7185fe6dafe47..14ab5efa8ef4d 100644 --- a/airflow-core/src/airflow/api_fastapi/common/parameters.py +++ b/airflow-core/src/airflow/api_fastapi/common/parameters.py @@ -18,26 +18,23 @@ from __future__ import annotations from abc import ABC, abstractmethod -from collections.abc import Iterable +from collections.abc import Callable, Iterable from datetime import datetime from enum import Enum from typing import ( TYPE_CHECKING, Annotated, Any, - Callable, Generic, Literal, - Optional, TypeVar, - Union, overload, ) from fastapi import Depends, HTTPException, Query, status from pendulum.parsing.exceptions import ParserError from pydantic import AfterValidator, BaseModel, NonNegativeInt -from sqlalchemy import Column, and_, case, or_ +from sqlalchemy import Column, and_, case, func, or_ from sqlalchemy.inspection import inspect from airflow.api_fastapi.core_api.base import OrmClause @@ -493,9 +490,12 @@ def depends_datetime( lower_bound: datetime | None = Query(alias=f"{filter_name}_gte", default=None), upper_bound: datetime | None = Query(alias=f"{filter_name}_lte", default=None), ) -> RangeFilter: + attr = getattr(model, attribute_name or filter_name) + if filter_name in ("start_date", "end_date"): + attr = func.coalesce(attr, func.now()) return RangeFilter( Range(lower_bound=lower_bound, upper_bound=upper_bound), - getattr(model, attribute_name or filter_name), + attr, ) return depends_datetime @@ -517,14 +517,14 @@ def depends_float( # Common Safe DateTime DateTimeQuery = Annotated[str, AfterValidator(_safe_parse_datetime)] -OptionalDateTimeQuery = Annotated[Union[str, None], AfterValidator(_safe_parse_datetime_optional)] +OptionalDateTimeQuery = Annotated[str | None, AfterValidator(_safe_parse_datetime_optional)] # DAG QueryLimit = Annotated[LimitFilter, Depends(LimitFilter.depends)] QueryOffset = Annotated[OffsetFilter, Depends(OffsetFilter.depends)] QueryPausedFilter = Annotated[ - FilterParam[Optional[bool]], - Depends(filter_param_factory(DagModel.is_paused, Optional[bool], filter_name="paused")), + FilterParam[bool | None], + Depends(filter_param_factory(DagModel.is_paused, bool | None, filter_name="paused")), ] QueryExcludeStaleFilter = Annotated[_ExcludeStaleFilter, Depends(_ExcludeStaleFilter.depends)] QueryDagIdPatternSearch = Annotated[ @@ -541,8 +541,8 @@ def depends_float( # DagRun QueryLastDagRunStateFilter = Annotated[ - FilterParam[Optional[DagRunState]], - Depends(filter_param_factory(DagRun.state, Optional[DagRunState], filter_name="last_dag_run_state")), + FilterParam[DagRunState | None], + Depends(filter_param_factory(DagRun.state, DagRunState | None, filter_name="last_dag_run_state")), ] @@ -610,7 +610,7 @@ def _transform_ti_states(states: list[str] | None) -> list[TaskInstanceState | N return None try: - return [None if s in ("none", None) else TaskInstanceState(s) for s in states] + return [None if s in ("no_status", "none", None) else TaskInstanceState(s) for s in states] except ValueError: raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, @@ -693,8 +693,8 @@ def _optional_boolean(value: bool | None) -> bool | None: return value if value is not None else False -QueryIncludeUpstream = Annotated[Union[bool], AfterValidator(_optional_boolean)] -QueryIncludeDownstream = Annotated[Union[bool], AfterValidator(_optional_boolean)] +QueryIncludeUpstream = Annotated[bool, AfterValidator(_optional_boolean)] +QueryIncludeDownstream = Annotated[bool, AfterValidator(_optional_boolean)] state_priority: list[None | TaskInstanceState] = [ TaskInstanceState.FAILED, diff --git a/airflow-core/src/airflow/api_fastapi/common/router.py b/airflow-core/src/airflow/api_fastapi/common/router.py index 12d9fca072459..e01b8462ba8bf 100644 --- a/airflow-core/src/airflow/api_fastapi/common/router.py +++ b/airflow-core/src/airflow/api_fastapi/common/router.py @@ -17,7 +17,8 @@ from __future__ import annotations -from typing import Any, Callable +from collections.abc import Callable +from typing import Any from fastapi import APIRouter from fastapi.types import DecoratedCallable diff --git a/airflow-core/src/airflow/api_fastapi/core_api/app.py b/airflow-core/src/airflow/api_fastapi/core_api/app.py index d378e009bc0c9..ad8938de994b6 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/app.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/app.py @@ -30,7 +30,6 @@ from starlette.templating import Jinja2Templates from airflow.api_fastapi.auth.tokens import get_signing_key -from airflow.api_fastapi.core_api.middleware import FlaskExceptionsMiddleware from airflow.exceptions import AirflowException from airflow.settings import AIRFLOW_PATH @@ -55,6 +54,13 @@ def init_views(app: FastAPI) -> None: templates = Jinja2Templates(directory=directory) + if dev_mode: + app.mount( + "/static/i18n/locales", + StaticFiles(directory=Path(AIRFLOW_PATH) / "airflow/ui/public/i18n/locales"), + name="dev_i18n_static", + ) + app.mount( "/static", StaticFiles( @@ -169,8 +175,9 @@ def init_error_handlers(app: FastAPI) -> None: def init_middlewares(app: FastAPI) -> None: from airflow.configuration import conf - app.add_middleware(FlaskExceptionsMiddleware) - if conf.getboolean("core", "simple_auth_manager_all_admins"): + if "SimpleAuthManager" in conf.get("core", "auth_manager") and conf.getboolean( + "core", "simple_auth_manager_all_admins" + ): from airflow.api_fastapi.auth.managers.simple.middleware import SimpleAllAdminMiddleware app.add_middleware(SimpleAllAdminMiddleware) diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py index fee330e1fd1d6..f2ac1f7a9403a 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py @@ -17,15 +17,12 @@ from __future__ import annotations -import json from collections import abc from typing import Annotated -from pydantic import Field, field_validator -from pydantic_core.core_schema import ValidationInfo +from pydantic import Field from airflow.api_fastapi.core_api.base import BaseModel, StrictBaseModel -from airflow.sdk.execution_time.secrets_masker import redact # Response Models @@ -42,26 +39,6 @@ class ConnectionResponse(BaseModel): password: str | None extra: str | None - @field_validator("password", mode="after") - @classmethod - def redact_password(cls, v: str | None, field_info: ValidationInfo) -> str | None: - if v is None: - return None - return redact(v, field_info.field_name) - - @field_validator("extra", mode="before") - @classmethod - def redact_extra(cls, v: str | None) -> str | None: - if v is None: - return None - try: - extra_dict = json.loads(v) - redacted_dict = redact(extra_dict) - return json.dumps(redacted_dict) - except json.JSONDecodeError: - # we can't redact fields in an unstructured `extra` - return v - class ConnectionCollectionResponse(BaseModel): """Connection Collection serializer for responses.""" diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dag_versions.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dag_versions.py index 6f255641aaa1c..09a18f8a4fc12 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dag_versions.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dag_versions.py @@ -41,7 +41,10 @@ class DagVersionResponse(BaseModel): @property def bundle_url(self) -> str | None: if self.bundle_name: - return DagBundlesManager().view_url(self.bundle_name, self.bundle_version) + try: + return DagBundlesManager().view_url(self.bundle_name, self.bundle_version) + except ValueError: + return None return None diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.py index 1801d03df7870..499b66c8e98be 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.py @@ -93,7 +93,7 @@ def get_owners(cls, v: Any) -> list[str] | None: if v is None: return [] if isinstance(v, str): - return v.split(",") + return [x.strip() for x in v.split(",")] return v @field_validator("timetable_summary", mode="before") diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/plugins.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/plugins.py index a1f51c04ab78d..92ad988b087fe 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/plugins.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/plugins.py @@ -19,7 +19,7 @@ from typing import Annotated, Any, Literal -from pydantic import BeforeValidator, ConfigDict, field_validator +from pydantic import BeforeValidator, ConfigDict, Field, field_validator, model_validator from airflow.api_fastapi.core_api.base import BaseModel from airflow.plugins_manager import AirflowPluginSource @@ -65,20 +65,37 @@ class AppBuilderMenuItemResponse(BaseModel): model_config = ConfigDict(extra="allow") name: str - href: str | None = None + href: str category: str | None = None -class IFrameViewsResponse(BaseModel): - """Serializer for IFrame Plugin responses.""" +class BaseUIResponse(BaseModel): + """Base serializer for UI Plugin responses.""" model_config = ConfigDict(extra="allow") name: str - src: str icon: str | None = None + icon_dark_mode: str | None = None url_route: str | None = None - destination: Literal["nav", "dag", "dag_run", "task", "task_instance"] | None = None + category: str | None = None + destination: Literal["nav", "dag", "dag_run", "task", "task_instance"] = "nav" + + +class ExternalViewResponse(BaseUIResponse): + """Serializer for External View Plugin responses.""" + + model_config = ConfigDict(extra="allow") + + href: str + + +class ReactAppResponse(BaseUIResponse): + """Serializer for React App Plugin responses.""" + + model_config = ConfigDict(extra="allow") + + bundle_url: str class PluginResponse(BaseModel): @@ -89,9 +106,14 @@ class PluginResponse(BaseModel): flask_blueprints: list[str] fastapi_apps: list[FastAPIAppResponse] fastapi_root_middlewares: list[FastAPIRootMiddlewareResponse] - iframe_views: list[IFrameViewsResponse] + external_views: list[ExternalViewResponse] = Field( + description="Aggregate all external views. Both 'external_views' and 'appbuilder_menu_items' are included here." + ) + react_apps: list[ReactAppResponse] appbuilder_views: list[AppBuilderViewResponse] - appbuilder_menu_items: list[AppBuilderMenuItemResponse] + appbuilder_menu_items: list[AppBuilderMenuItemResponse] = Field( + deprecated="Kept for backward compatibility, use `external_views` instead.", + ) global_operator_extra_links: list[str] operator_extra_links: list[str] source: Annotated[str, BeforeValidator(coerce_to_string)] @@ -105,6 +127,12 @@ def convert_source(cls, data: Any) -> Any: return str(data) return data + @model_validator(mode="before") + @classmethod + def convert_external_views(cls, data: Any) -> Any: + data["external_views"] = [*data["external_views"], *data["appbuilder_menu_items"]] + return data + class PluginCollectionResponse(BaseModel): """Plugin Collection serializer.""" diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/pools.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/pools.py index 2e7ae13cfcdb2..4342d04c1e125 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/pools.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/pools.py @@ -17,7 +17,8 @@ from __future__ import annotations -from typing import Annotated, Callable +from collections.abc import Callable +from typing import Annotated from pydantic import BeforeValidator, Field diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/common.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/common.py index cc4d7913b2244..0f315326194e5 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/common.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/common.py @@ -17,9 +17,14 @@ from __future__ import annotations +from datetime import datetime from typing import Generic, Literal, TypeVar +from pydantic import computed_field + from airflow.api_fastapi.core_api.base import BaseModel +from airflow.utils.state import TaskInstanceState +from airflow.utils.types import DagRunType class BaseEdgeResponse(BaseModel): @@ -52,8 +57,46 @@ class BaseNodeResponse(BaseModel): N = TypeVar("N", bound=BaseNodeResponse) +class GridNodeResponse(BaseModel): + """Base Node serializer for responses.""" + + id: str + label: str + children: list[GridNodeResponse] | None = None + is_mapped: bool | None + setup_teardown_type: Literal["setup", "teardown"] | None = None + + +class GridRunsResponse(BaseModel): + """Base Node serializer for responses.""" + + dag_id: str + run_id: str + queued_at: datetime | None + start_date: datetime | None + end_date: datetime | None + run_after: datetime + state: TaskInstanceState | None + run_type: DagRunType + + @computed_field + def duration(self) -> int | None: + if self.start_date and self.end_date: + return (self.end_date - self.start_date).seconds + return None + + class BaseGraphResponse(BaseModel, Generic[E, N]): """Base Graph serializer for responses.""" edges: list[E] nodes: list[N] + + +class LatestRunResponse(BaseModel): + """Base Node serializer for responses.""" + + id: int + dag_id: str + run_id: str + run_after: datetime diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/grid.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/grid.py index 822eb6f3e1a89..48ea0ece79495 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/grid.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/grid.py @@ -21,7 +21,6 @@ from pydantic import BaseModel, Field -from airflow.api_fastapi.core_api.datamodels.ui.structure import StructureDataResponse from airflow.utils.state import DagRunState, TaskInstanceState from airflow.utils.types import DagRunType @@ -40,6 +39,13 @@ class GridTaskInstanceSummary(BaseModel): note: str | None +class LightGridTaskInstanceSummary(BaseModel): + """Task Instance Summary model for the Grid UI.""" + + task_id: str + state: TaskInstanceState | None + + class GridDAGRunwithTIs(BaseModel): """DAG Run model for the Grid UI.""" @@ -57,8 +63,15 @@ class GridDAGRunwithTIs(BaseModel): task_instances: list[GridTaskInstanceSummary] +class GridTISummaries(BaseModel): + """DAG Run model for the Grid UI.""" + + run_id: str + dag_id: str + task_instances: list[LightGridTaskInstanceSummary] + + class GridResponse(BaseModel): """Response model for the Grid UI.""" dag_runs: list[GridDAGRunwithTIs] - structure: StructureDataResponse diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/variables.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/variables.py index 2905e752650cd..d60f052f77705 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/variables.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/variables.py @@ -46,7 +46,7 @@ def redact_val(self) -> Self: return self except json.JSONDecodeError: # value is not a serialized string representation of a dict. - self.val = redact(self.val, self.key) + self.val = str(redact(self.val, self.key)) return self diff --git a/airflow-core/src/airflow/api_fastapi/core_api/middleware.py b/airflow-core/src/airflow/api_fastapi/core_api/middleware.py deleted file mode 100644 index e88c9acc5438a..0000000000000 --- a/airflow-core/src/airflow/api_fastapi/core_api/middleware.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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. -from __future__ import annotations - -from fastapi import HTTPException, Request -from starlette.middleware.base import BaseHTTPMiddleware - - -# Custom Middleware Class -class FlaskExceptionsMiddleware(BaseHTTPMiddleware): - """Middleware that converts exceptions thrown in the Flask application to Fastapi exceptions.""" - - async def dispatch(self, request: Request, call_next): - response = await call_next(request) - - # Check if the WSGI response contains an error - if response.status_code >= 400 and response.media_type == "application/json": - body = await response.json() - if "error" in body: - # Transform the WSGI app's exception into a FastAPI HTTPException - raise HTTPException( - status_code=response.status_code, - detail=body["error"], - ) - return response diff --git a/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml b/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml index 660580cbe8400..ffb90dcf6e03f 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml +++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml @@ -604,6 +604,293 @@ paths: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' + /ui/grid/structure/{dag_id}: + get: + tags: + - Grid + summary: Get Dag Structure + description: Return dag structure for grid view. + operationId: get_dag_structure + security: + - OAuth2PasswordBearer: [] + parameters: + - name: dag_id + in: path + required: true + schema: + type: string + title: Dag Id + - name: offset + in: query + required: false + schema: + type: integer + minimum: 0 + default: 0 + title: Offset + - name: limit + in: query + required: false + schema: + type: integer + minimum: 0 + default: 50 + title: Limit + - name: order_by + in: query + required: false + schema: + type: string + default: id + title: Order By + - name: run_after_gte + in: query + required: false + schema: + anyOf: + - type: string + format: date-time + - type: 'null' + title: Run After Gte + - name: run_after_lte + in: query + required: false + schema: + anyOf: + - type: string + format: date-time + - type: 'null' + title: Run After Lte + responses: + '200': + description: Successful Response + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/GridNodeResponse' + title: Response Get Dag Structure + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Bad Request + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Not Found + '422': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' + /ui/grid/runs/{dag_id}: + get: + tags: + - Grid + summary: Get Grid Runs + description: Get info about a run for the grid. + operationId: get_grid_runs + security: + - OAuth2PasswordBearer: [] + parameters: + - name: dag_id + in: path + required: true + schema: + type: string + title: Dag Id + - name: offset + in: query + required: false + schema: + type: integer + minimum: 0 + default: 0 + title: Offset + - name: limit + in: query + required: false + schema: + type: integer + minimum: 0 + default: 50 + title: Limit + - name: order_by + in: query + required: false + schema: + type: string + default: id + title: Order By + - name: run_after_gte + in: query + required: false + schema: + anyOf: + - type: string + format: date-time + - type: 'null' + title: Run After Gte + - name: run_after_lte + in: query + required: false + schema: + anyOf: + - type: string + format: date-time + - type: 'null' + title: Run After Lte + responses: + '200': + description: Successful Response + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/GridRunsResponse' + title: Response Get Grid Runs + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Bad Request + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Not Found + '422': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' + /ui/grid/ti_summaries/{dag_id}/{run_id}: + get: + tags: + - Grid + summary: Get Grid Ti Summaries + description: 'Get states for TIs / "groups" of TIs. + + + Essentially this is to know what color to put in the squares in the grid. + + + The tricky part here is that we aggregate the state for groups and mapped + tasks. + + + We don''t add all the TIs for mapped TIs -- we only add one entry for the + mapped task and + + its state is an aggregate of its TI states. + + + And for task groups, we add a "task" for that which is not really a task but + is just + + an entry that represents the group (so that we can show a filled in box when + the group + + is not expanded) and its state is an agg of those within it.' + operationId: get_grid_ti_summaries + security: + - OAuth2PasswordBearer: [] + parameters: + - name: dag_id + in: path + required: true + schema: + type: string + title: Dag Id + - name: run_id + in: path + required: true + schema: + type: string + title: Run Id + responses: + '200': + description: Successful Response + content: + application/json: + schema: + $ref: '#/components/schemas/GridTISummaries' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Bad Request + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Not Found + '422': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' + /ui/grid/latest_run/{dag_id}: + get: + tags: + - Grid + summary: Get Latest Run + description: 'Get information about the latest dag run by run_after. + + + This is used by the UI to figure out if it needs to rerun queries and resume + auto refresh.' + operationId: get_latest_run + security: + - OAuth2PasswordBearer: [] + parameters: + - name: dag_id + in: path + required: true + schema: + type: string + title: Dag Id + responses: + '200': + description: Successful Response + content: + application/json: + schema: + anyOf: + - $ref: '#/components/schemas/LatestRunResponse' + - type: 'null' + title: Response Get Latest Run + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Bad Request + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Not Found + '422': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' components: schemas: BackfillCollectionResponse: @@ -1469,6 +1756,41 @@ components: - task_instances title: GridDAGRunwithTIs description: DAG Run model for the Grid UI. + GridNodeResponse: + properties: + id: + type: string + title: Id + label: + type: string + title: Label + children: + anyOf: + - items: + $ref: '#/components/schemas/GridNodeResponse' + type: array + - type: 'null' + title: Children + is_mapped: + anyOf: + - type: boolean + - type: 'null' + title: Is Mapped + setup_teardown_type: + anyOf: + - type: string + enum: + - setup + - teardown + - type: 'null' + title: Setup Teardown Type + type: object + required: + - id + - label + - is_mapped + title: GridNodeResponse + description: Base Node serializer for responses. GridResponse: properties: dag_runs: @@ -1476,14 +1798,86 @@ components: $ref: '#/components/schemas/GridDAGRunwithTIs' type: array title: Dag Runs - structure: - $ref: '#/components/schemas/StructureDataResponse' type: object required: - dag_runs - - structure title: GridResponse description: Response model for the Grid UI. + GridRunsResponse: + properties: + dag_id: + type: string + title: Dag Id + run_id: + type: string + title: Run Id + queued_at: + anyOf: + - type: string + format: date-time + - type: 'null' + title: Queued At + start_date: + anyOf: + - type: string + format: date-time + - type: 'null' + title: Start Date + end_date: + anyOf: + - type: string + format: date-time + - type: 'null' + title: End Date + run_after: + type: string + format: date-time + title: Run After + state: + anyOf: + - $ref: '#/components/schemas/TaskInstanceState' + - type: 'null' + run_type: + $ref: '#/components/schemas/DagRunType' + duration: + anyOf: + - type: integer + - type: 'null' + title: Duration + readOnly: true + type: object + required: + - dag_id + - run_id + - queued_at + - start_date + - end_date + - run_after + - state + - run_type + - duration + title: GridRunsResponse + description: Base Node serializer for responses. + GridTISummaries: + properties: + run_id: + type: string + title: Run Id + dag_id: + type: string + title: Dag Id + task_instances: + items: + $ref: '#/components/schemas/LightGridTaskInstanceSummary' + type: array + title: Task Instances + type: object + required: + - run_id + - dag_id + - task_instances + title: GridTISummaries + description: DAG Run model for the Grid UI. GridTaskInstanceSummary: properties: task_id: @@ -1579,6 +1973,44 @@ components: - task_instance_states title: HistoricalMetricDataResponse description: Historical Metric Data serializer for responses. + LatestRunResponse: + properties: + id: + type: integer + title: Id + dag_id: + type: string + title: Dag Id + run_id: + type: string + title: Run Id + run_after: + type: string + format: date-time + title: Run After + type: object + required: + - id + - dag_id + - run_id + - run_after + title: LatestRunResponse + description: Base Node serializer for responses. + LightGridTaskInstanceSummary: + properties: + task_id: + type: string + title: Task Id + state: + anyOf: + - $ref: '#/components/schemas/TaskInstanceState' + - type: 'null' + type: object + required: + - task_id + - state + title: LightGridTaskInstanceSummary + description: Task Instance Summary model for the Grid UI. MenuItem: type: string enum: diff --git a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml index c67a089b0623e..a3fd6d5cbd805 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml +++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml @@ -7029,9 +7029,7 @@ components: type: string title: Name href: - anyOf: - - type: string - - type: 'null' + type: string title: Href category: anyOf: @@ -7042,6 +7040,7 @@ components: type: object required: - name + - href title: AppBuilderMenuItemResponse description: Serializer for AppBuilder Menu Item responses. AppBuilderViewResponse: @@ -9293,6 +9292,51 @@ components: - url title: ExternalLogUrlResponse description: Response for the external log URL endpoint. + ExternalViewResponse: + properties: + name: + type: string + title: Name + icon: + anyOf: + - type: string + - type: 'null' + title: Icon + icon_dark_mode: + anyOf: + - type: string + - type: 'null' + title: Icon Dark Mode + url_route: + anyOf: + - type: string + - type: 'null' + title: Url Route + category: + anyOf: + - type: string + - type: 'null' + title: Category + destination: + type: string + enum: + - nav + - dag + - dag_run + - task + - task_instance + title: Destination + default: nav + href: + type: string + title: Href + additionalProperties: true + type: object + required: + - name + - href + title: ExternalViewResponse + description: Serializer for External View Plugin responses. ExtraLinkCollectionResponse: properties: extra_links: @@ -9386,42 +9430,6 @@ components: - triggerer title: HealthInfoResponse description: Health serializer for responses. - IFrameViewsResponse: - properties: - name: - type: string - title: Name - src: - type: string - title: Src - icon: - anyOf: - - type: string - - type: 'null' - title: Icon - url_route: - anyOf: - - type: string - - type: 'null' - title: Url Route - destination: - anyOf: - - type: string - enum: - - nav - - dag - - dag_run - - task - - task_instance - - type: 'null' - title: Destination - additionalProperties: true - type: object - required: - - name - - src - title: IFrameViewsResponse - description: Serializer for IFrame Plugin responses. ImportErrorCollectionResponse: properties: import_errors: @@ -9676,11 +9684,18 @@ components: $ref: '#/components/schemas/FastAPIRootMiddlewareResponse' type: array title: Fastapi Root Middlewares - iframe_views: + external_views: items: - $ref: '#/components/schemas/IFrameViewsResponse' + $ref: '#/components/schemas/ExternalViewResponse' type: array - title: Iframe Views + title: External Views + description: Aggregate all external views. Both 'external_views' and 'appbuilder_menu_items' + are included here. + react_apps: + items: + $ref: '#/components/schemas/ReactAppResponse' + type: array + title: React Apps appbuilder_views: items: $ref: '#/components/schemas/AppBuilderViewResponse' @@ -9691,6 +9706,7 @@ components: $ref: '#/components/schemas/AppBuilderMenuItemResponse' type: array title: Appbuilder Menu Items + deprecated: true global_operator_extra_links: items: type: string @@ -9721,7 +9737,8 @@ components: - flask_blueprints - fastapi_apps - fastapi_root_middlewares - - iframe_views + - external_views + - react_apps - appbuilder_views - appbuilder_menu_items - global_operator_extra_links @@ -9919,6 +9936,51 @@ components: - dag_display_name title: QueuedEventResponse description: Queued Event serializer for responses.. + ReactAppResponse: + properties: + name: + type: string + title: Name + icon: + anyOf: + - type: string + - type: 'null' + title: Icon + icon_dark_mode: + anyOf: + - type: string + - type: 'null' + title: Icon Dark Mode + url_route: + anyOf: + - type: string + - type: 'null' + title: Url Route + category: + anyOf: + - type: string + - type: 'null' + title: Category + destination: + type: string + enum: + - nav + - dag + - dag_run + - task + - task_instance + title: Destination + default: nav + bundle_url: + type: string + title: Bundle Url + additionalProperties: true + type: object + required: + - name + - bundle_url + title: ReactAppResponse + description: Serializer for React App Plugin responses. ReprocessBehavior: type: string enum: diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/import_error.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/import_error.py index feb475c91c3b0..a989a7eef168c 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/import_error.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/import_error.py @@ -22,7 +22,7 @@ from typing import Annotated from fastapi import Depends, HTTPException, status -from sqlalchemy import select +from sqlalchemy import and_, select from airflow.api_fastapi.app import get_auth_manager from airflow.api_fastapi.auth.managers.models.batch_apis import IsAuthorizedDagRequest @@ -163,8 +163,10 @@ def get_import_errors( select(ParseImportError, visible_files_cte.c.dag_id) .join( visible_files_cte, - ParseImportError.filename == visible_files_cte.c.relative_fileloc, - ParseImportError.bundle_name == visible_files_cte.c.bundle_name, + and_( + ParseImportError.filename == visible_files_cte.c.relative_fileloc, + ParseImportError.bundle_name == visible_files_cte.c.bundle_name, + ), ) .order_by(ParseImportError.id) ) diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py index 09409335c2c09..ce1a582a511f7 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py @@ -42,23 +42,35 @@ datetime_range_filter_factory, ) from airflow.api_fastapi.common.router import AirflowRouter +from airflow.api_fastapi.core_api.datamodels.ui.common import ( + GridNodeResponse, + GridRunsResponse, + LatestRunResponse, +) from airflow.api_fastapi.core_api.datamodels.ui.grid import ( GridDAGRunwithTIs, GridResponse, + GridTISummaries, ) from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc from airflow.api_fastapi.core_api.security import requires_access_dag from airflow.api_fastapi.core_api.services.ui.grid import ( + _find_aggregates, + _merge_node_dicts, fill_task_instance_summaries, get_child_task_map, - get_combined_structure, - get_structure_from_dag, get_task_group_map, ) -from airflow.models import DagRun, TaskInstance from airflow.models.dag_version import DagVersion +from airflow.models.dagrun import DagRun +from airflow.models.serialized_dag import SerializedDagModel +from airflow.models.taskinstance import TaskInstance from airflow.models.taskinstancehistory import TaskInstanceHistory from airflow.utils.state import TaskInstanceState +from airflow.utils.task_group import ( + get_task_group_children_getter, + task_group_to_dict_grid, +) log = structlog.get_logger(logger_name=__name__) grid_router = AirflowRouter(prefix="/grid", tags=["Grid"]) @@ -71,6 +83,7 @@ Depends(requires_access_dag(method="GET", access_entity=DagAccessEntity.TASK_INSTANCE)), Depends(requires_access_dag(method="GET", access_entity=DagAccessEntity.RUN)), ], + response_model_exclude_none=True, ) def grid_data( dag_id: str, @@ -124,11 +137,9 @@ def grid_data( ) dag_runs = list(session.scalars(dag_runs_select_filter).unique()) - # Check if there are any DAG Runs with given criteria to eliminate unnecessary queries/errors if not dag_runs: - structure = get_structure_from_dag(dag=dag) - return GridResponse(dag_runs=[], structure=structure) + return GridResponse(dag_runs=[]) # Retrieve, sort and encode the Task Instances tis_of_dag_runs, _ = paginated_select( @@ -257,8 +268,324 @@ def grid_data( ) for dag_run in dag_runs ] + return GridResponse(dag_runs=grid_dag_runs) + + +def _get_latest_serdag(dag_id, session): + serdag = session.scalar( + select(SerializedDagModel) + .where( + SerializedDagModel.dag_id == dag_id, + ) + .order_by(SerializedDagModel.id.desc()) + .limit(1) + ) + if not serdag: + raise HTTPException( + status.HTTP_404_NOT_FOUND, + f"Dag with id {dag_id} was not found", + ) + return serdag + + +def _get_serdag(dag_id, dag_version_id, session) -> SerializedDagModel | None: + # this is a simplification - we account for structure based on the first task + version = session.scalar(select(DagVersion).where(DagVersion.id == dag_version_id)) + if not version: + version = session.scalar( + select(DagVersion) + .where( + DagVersion.dag_id == dag_id, + ) + .order_by(DagVersion.id) # ascending cus this is mostly for pre-3.0 upgrade + .limit(1) + ) + if not (serdag := version.serialized_dag): + log.error( + "No serialized dag found", + dag_id=dag_id, + version_id=version.id, + version_number=version.version_number, + ) + return serdag + + +@grid_router.get( + "/structure/{dag_id}", + responses=create_openapi_http_exception_doc([status.HTTP_400_BAD_REQUEST, status.HTTP_404_NOT_FOUND]), + dependencies=[ + Depends(requires_access_dag(method="GET", access_entity=DagAccessEntity.TASK_INSTANCE)), + Depends(requires_access_dag(method="GET", access_entity=DagAccessEntity.RUN)), + ], + response_model_exclude_none=True, +) +def get_dag_structure( + dag_id: str, + session: SessionDep, + offset: QueryOffset, + limit: QueryLimit, + order_by: Annotated[ + SortParam, + Depends(SortParam(["run_after", "logical_date", "start_date", "end_date"], DagRun).dynamic_depends()), + ], + run_after: Annotated[RangeFilter, Depends(datetime_range_filter_factory("run_after", DagRun))], +) -> list[GridNodeResponse]: + """Return dag structure for grid view.""" + latest_serdag = _get_latest_serdag(dag_id, session) + latest_dag = latest_serdag.dag - flat_tis = itertools.chain.from_iterable(tis_by_run_id.values()) - structure = get_combined_structure(task_instances=flat_tis, session=session) + # Retrieve, sort the previous DAG Runs + base_query = select(DagRun.id).where(DagRun.dag_id == dag_id) + # This comparison is to fall back to DAG timetable when no order_by is provided + if order_by.value == order_by.get_primary_key_string(): + ordering = list(latest_dag.timetable.run_ordering) + order_by = SortParam( + allowed_attrs=ordering, + model=DagRun, + ).set_value(ordering[0]) + dag_runs_select_filter, _ = paginated_select( + statement=base_query, + order_by=order_by, + offset=offset, + filters=[run_after], + limit=limit, + ) + run_ids = list(session.scalars(dag_runs_select_filter)) + + task_group_sort = get_task_group_children_getter() + if not run_ids: + nodes = [task_group_to_dict_grid(x) for x in task_group_sort(latest_dag.task_group)] + return nodes - return GridResponse(dag_runs=grid_dag_runs, structure=structure) + serdags = session.scalars( + select(SerializedDagModel).where( + SerializedDagModel.dag_version_id.in_( + select(TaskInstance.dag_version_id) + .join(TaskInstance.dag_run) + .where( + DagRun.id.in_(run_ids), + SerializedDagModel.id != latest_serdag.id, + ) + ) + ) + ) + merged_nodes: list[GridNodeResponse] = [] + dags = [latest_dag] + for serdag in serdags: + if serdag: + dags.append(serdag.dag) + for dag in dags: + nodes = [task_group_to_dict_grid(x) for x in task_group_sort(dag.task_group)] + _merge_node_dicts(merged_nodes, nodes) + + return merged_nodes + + +@grid_router.get( + "/runs/{dag_id}", + responses=create_openapi_http_exception_doc( + [ + status.HTTP_400_BAD_REQUEST, + status.HTTP_404_NOT_FOUND, + ] + ), + dependencies=[ + Depends( + requires_access_dag( + method="GET", + access_entity=DagAccessEntity.TASK_INSTANCE, + ) + ), + Depends( + requires_access_dag( + method="GET", + access_entity=DagAccessEntity.RUN, + ) + ), + ], + response_model_exclude_none=True, +) +def get_grid_runs( + dag_id: str, + session: SessionDep, + offset: QueryOffset, + limit: QueryLimit, + order_by: Annotated[ + SortParam, + Depends( + SortParam( + [ + "run_after", + "logical_date", + "start_date", + "end_date", + ], + DagRun, + ).dynamic_depends() + ), + ], + run_after: Annotated[RangeFilter, Depends(datetime_range_filter_factory("run_after", DagRun))], +) -> list[GridRunsResponse]: + """Get info about a run for the grid.""" + # Retrieve, sort the previous DAG Runs + base_query = select( + DagRun.dag_id, + DagRun.run_id, + DagRun.queued_at, + DagRun.start_date, + DagRun.end_date, + DagRun.run_after, + DagRun.state, + DagRun.run_type, + ).where(DagRun.dag_id == dag_id) + + # This comparison is to fall back to DAG timetable when no order_by is provided + if order_by.value == order_by.get_primary_key_string(): + latest_serdag = _get_latest_serdag(dag_id, session) + latest_dag = latest_serdag.dag + ordering = list(latest_dag.timetable.run_ordering) + order_by = SortParam( + allowed_attrs=ordering, + model=DagRun, + ).set_value(ordering[0]) + dag_runs_select_filter, _ = paginated_select( + statement=base_query, + order_by=order_by, + offset=offset, + filters=[run_after], + limit=limit, + ) + return session.execute(dag_runs_select_filter) + + +@grid_router.get( + "/ti_summaries/{dag_id}/{run_id}", + responses=create_openapi_http_exception_doc( + [ + status.HTTP_400_BAD_REQUEST, + status.HTTP_404_NOT_FOUND, + ] + ), + dependencies=[ + Depends( + requires_access_dag( + method="GET", + access_entity=DagAccessEntity.TASK_INSTANCE, + ) + ), + Depends( + requires_access_dag( + method="GET", + access_entity=DagAccessEntity.RUN, + ) + ), + ], + response_model_exclude_none=True, +) +def get_grid_ti_summaries( + dag_id: str, + run_id: str, + session: SessionDep, +) -> GridTISummaries: + """ + Get states for TIs / "groups" of TIs. + + Essentially this is to know what color to put in the squares in the grid. + + The tricky part here is that we aggregate the state for groups and mapped tasks. + + We don't add all the TIs for mapped TIs -- we only add one entry for the mapped task and + its state is an aggregate of its TI states. + + And for task groups, we add a "task" for that which is not really a task but is just + an entry that represents the group (so that we can show a filled in box when the group + is not expanded) and its state is an agg of those within it. + """ + tis_of_dag_runs, _ = paginated_select( + statement=( + select( + TaskInstance.task_id, + TaskInstance.state, + TaskInstance.dag_version_id, + ) + .where(TaskInstance.dag_id == dag_id) + .where( + TaskInstance.run_id == run_id, + ) + ), + filters=[], + order_by=SortParam(allowed_attrs=["task_id", "run_id"], model=TaskInstance).set_value("task_id"), + limit=None, + return_total_entries=False, + ) + task_instances = list(session.execute(tis_of_dag_runs)) + task_id_states = collections.defaultdict(list) + for ti in task_instances: + task_id_states[ti.task_id].append(ti.state) + + serdag = _get_serdag( + dag_id=dag_id, + dag_version_id=task_instances[0].dag_version_id, + session=session, + ) + if not serdag: + raise HTTPException(status.HTTP_404_NOT_FOUND, f"Dag with id {dag_id} was not found") + tis = list( + _find_aggregates( + node=serdag.dag.task_group, + parent_node=None, + ti_states=task_id_states, + ) + ) + + return { # type: ignore[return-value] + "run_id": run_id, + "dag_id": dag_id, + "task_instances": list(tis), + } + + +@grid_router.get( + "/latest_run/{dag_id}", + responses=create_openapi_http_exception_doc( + [ + status.HTTP_400_BAD_REQUEST, + status.HTTP_404_NOT_FOUND, + ] + ), + dependencies=[ + Depends( + requires_access_dag( + method="GET", + access_entity=DagAccessEntity.TASK_INSTANCE, + ) + ), + Depends( + requires_access_dag( + method="GET", + access_entity=DagAccessEntity.RUN, + ) + ), + ], + response_model_exclude_none=True, +) +def get_latest_run( + dag_id: str, + session: SessionDep, +) -> LatestRunResponse | None: + """ + Get information about the latest dag run by run_after. + + This is used by the UI to figure out if it needs to rerun queries and resume auto refresh. + """ + return session.execute( + select( + DagRun.id, + DagRun.dag_id, + DagRun.run_id, + DagRun.run_after, + ) + .where(DagRun.dag_id == dag_id) + .order_by(DagRun.run_after.desc()) + .limit(1) + ).one_or_none() diff --git a/airflow-core/src/airflow/api_fastapi/core_api/security.py b/airflow-core/src/airflow/api_fastapi/core_api/security.py index be428124f9db6..5b3036de0d46e 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/security.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/security.py @@ -16,8 +16,9 @@ # under the License. from __future__ import annotations +from collections.abc import Callable from pathlib import Path -from typing import TYPE_CHECKING, Annotated, Callable +from typing import TYPE_CHECKING, Annotated from urllib.parse import ParseResult, urljoin, urlparse from fastapi import Depends, HTTPException, Request, status diff --git a/airflow-core/src/airflow/api_fastapi/core_api/services/ui/grid.py b/airflow-core/src/airflow/api_fastapi/core_api/services/ui/grid.py index 346676e14cd48..a69cafb7bbbda 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/services/ui/grid.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/services/ui/grid.py @@ -18,6 +18,8 @@ from __future__ import annotations import contextlib +from collections import Counter +from collections.abc import Iterable from uuid import UUID import structlog @@ -309,3 +311,61 @@ def _get_node_by_id(nodes, node_id): if node["id"] == node_id: return node return {} + + +def _is_task_node_mapped_task_group(task_node: BaseOperator | MappedTaskGroup | TaskMap | None) -> bool: + """Check if the Task Node is a Mapped Task Group.""" + return type(task_node) is MappedTaskGroup + + +def agg_state(states): + states = Counter(states) + for state in state_priority: + if state in states: + return state + return "no_status" + + +def _find_aggregates( + node: TaskGroup | BaseOperator | MappedTaskGroup | TaskMap, + parent_node: TaskGroup | BaseOperator | MappedTaskGroup | TaskMap | None, + ti_states: dict[str, list[str]], +) -> Iterable[dict]: + """Recursively fill the Task Group Map.""" + node_id = node.node_id + parent_id = parent_node.node_id if parent_node else None + + if node is None: + return + + if isinstance(node, MappedOperator): + yield { + "task_id": node_id, + "type": "mapped_task", + "parent_id": parent_id, + "state": agg_state(ti_states[node_id]), + } + + return + if isinstance(node, TaskGroup): + states = [] + for child in get_task_group_children_getter()(node): + for child_node in _find_aggregates(node=child, parent_node=node, ti_states=ti_states): + states.append(child_node["state"]) + yield child_node + if node_id: + yield { + "task_id": node_id, + "type": "group", + "parent_id": parent_id, + "state": agg_state(states), + } + return + if isinstance(node, BaseOperator): + yield { + "task_id": node_id, + "type": "task", + "parent_id": parent_id, + "state": agg_state(ti_states[node_id]), + } + return diff --git a/airflow-core/src/airflow/api_fastapi/execution_api/datamodels/taskinstance.py b/airflow-core/src/airflow/api_fastapi/execution_api/datamodels/taskinstance.py index c43c931f3e28a..5afc2e75a7193 100644 --- a/airflow-core/src/airflow/api_fastapi/execution_api/datamodels/taskinstance.py +++ b/airflow-core/src/airflow/api_fastapi/execution_api/datamodels/taskinstance.py @@ -19,7 +19,7 @@ import uuid from datetime import timedelta from enum import Enum -from typing import Annotated, Any, Literal, Union +from typing import Annotated, Any, Literal from pydantic import ( AwareDatetime, @@ -213,14 +213,12 @@ def ti_state_discriminator(v: dict[str, str] | StrictBaseModel) -> str: # It is called "_terminal_" to avoid future conflicts if we added an actual state named "terminal" # and "_other_" is a catch-all for all other states that are not covered by the other schemas. TIStateUpdate = Annotated[ - Union[ - Annotated[TITerminalStatePayload, Tag("_terminal_")], - Annotated[TISuccessStatePayload, Tag("success")], - Annotated[TITargetStatePayload, Tag("_other_")], - Annotated[TIDeferredStatePayload, Tag("deferred")], - Annotated[TIRescheduleStatePayload, Tag("up_for_reschedule")], - Annotated[TIRetryStatePayload, Tag("up_for_retry")], - ], + Annotated[TITerminalStatePayload, Tag("_terminal_")] + | Annotated[TISuccessStatePayload, Tag("success")] + | Annotated[TITargetStatePayload, Tag("_other_")] + | Annotated[TIDeferredStatePayload, Tag("deferred")] + | Annotated[TIRescheduleStatePayload, Tag("up_for_reschedule")] + | Annotated[TIRetryStatePayload, Tag("up_for_retry")], Discriminator(ti_state_discriminator), ] diff --git a/airflow-core/src/airflow/api_fastapi/execution_api/deps.py b/airflow-core/src/airflow/api_fastapi/execution_api/deps.py index c2161180dbb46..2648a64ffad7a 100644 --- a/airflow-core/src/airflow/api_fastapi/execution_api/deps.py +++ b/airflow-core/src/airflow/api_fastapi/execution_api/deps.py @@ -20,7 +20,7 @@ import sys import time -from typing import Any, Optional +from typing import Any import structlog import svcs @@ -55,8 +55,8 @@ class JWTBearer(HTTPBearer): def __init__( self, - path_param_name: Optional[str] = None, - required_claims: Optional[dict[str, Any]] = None, + path_param_name: str | None = None, + required_claims: dict[str, Any] | None = None, ): super().__init__(auto_error=False) self.path_param_name = path_param_name @@ -66,7 +66,7 @@ async def __call__( # type: ignore[override] self, request: Request, services=DepContainer, - ) -> Optional[TIToken]: + ) -> TIToken | None: creds = await super().__call__(request) if not creds: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Missing auth token") diff --git a/airflow-core/src/airflow/api_fastapi/execution_api/versions/v2025_05_20.py b/airflow-core/src/airflow/api_fastapi/execution_api/versions/v2025_05_20.py index f8039f0a4d3fb..d671c97dafd9e 100644 --- a/airflow-core/src/airflow/api_fastapi/execution_api/versions/v2025_05_20.py +++ b/airflow-core/src/airflow/api_fastapi/execution_api/versions/v2025_05_20.py @@ -17,8 +17,6 @@ from __future__ import annotations -from typing import Optional - from cadwyn import ResponseInfo, VersionChange, convert_response_to_previous_version_for, schema from airflow.api_fastapi.execution_api.datamodels.taskinstance import TIRunContext @@ -30,7 +28,7 @@ class DowngradeUpstreamMapIndexes(VersionChange): description = __doc__ instructions_to_migrate_to_previous_version = ( - schema(TIRunContext).field("upstream_map_indexes").had(type=Optional[dict[str, int]]), # type: ignore + schema(TIRunContext).field("upstream_map_indexes").had(type=dict[str, int] | None), # type: ignore ) @convert_response_to_previous_version_for(TIRunContext) # type: ignore[arg-type] diff --git a/airflow-core/src/airflow/callbacks/callback_requests.py b/airflow-core/src/airflow/callbacks/callback_requests.py index 8cf8c77035737..6c4c978b672de 100644 --- a/airflow-core/src/airflow/callbacks/callback_requests.py +++ b/airflow-core/src/airflow/callbacks/callback_requests.py @@ -16,7 +16,7 @@ # under the License. from __future__ import annotations -from typing import TYPE_CHECKING, Annotated, Literal, Union +from typing import TYPE_CHECKING, Annotated, Literal from pydantic import BaseModel, Field @@ -86,6 +86,6 @@ class DagCallbackRequest(BaseCallbackRequest): CallbackRequest = Annotated[ - Union[DagCallbackRequest, TaskCallbackRequest], + DagCallbackRequest | TaskCallbackRequest, Field(discriminator="type"), ] diff --git a/airflow-core/src/airflow/callbacks/pipe_callback_sink.py b/airflow-core/src/airflow/callbacks/pipe_callback_sink.py index 7f6a2883743df..f7aba11960c18 100644 --- a/airflow-core/src/airflow/callbacks/pipe_callback_sink.py +++ b/airflow-core/src/airflow/callbacks/pipe_callback_sink.py @@ -18,7 +18,8 @@ from __future__ import annotations import contextlib -from typing import TYPE_CHECKING, Callable +from collections.abc import Callable +from typing import TYPE_CHECKING from airflow.callbacks.base_callback_sink import BaseCallbackSink diff --git a/airflow-core/src/airflow/cli/cli_config.py b/airflow-core/src/airflow/cli/cli_config.py index 725fbe46a4330..31022e17219c4 100644 --- a/airflow-core/src/airflow/cli/cli_config.py +++ b/airflow-core/src/airflow/cli/cli_config.py @@ -24,8 +24,8 @@ import json import os import textwrap -from collections.abc import Iterable -from typing import Callable, NamedTuple, Union +from collections.abc import Callable, Iterable +from typing import NamedTuple import lazy_object_proxy @@ -932,7 +932,7 @@ class GroupCommand(NamedTuple): epilog: str | None = None -CLICommand = Union[ActionCommand, GroupCommand] +CLICommand = ActionCommand | GroupCommand ASSETS_COMMANDS = ( ActionCommand( diff --git a/airflow-core/src/airflow/cli/commands/daemon_utils.py b/airflow-core/src/airflow/cli/commands/daemon_utils.py index 409ff15e77fd8..c55c12b380461 100644 --- a/airflow-core/src/airflow/cli/commands/daemon_utils.py +++ b/airflow-core/src/airflow/cli/commands/daemon_utils.py @@ -18,7 +18,7 @@ import signal from argparse import Namespace -from typing import Callable +from collections.abc import Callable from daemon import daemon from daemon.pidfile import TimeoutPIDLockFile diff --git a/airflow-core/src/airflow/cli/commands/rotate_fernet_key_command.py b/airflow-core/src/airflow/cli/commands/rotate_fernet_key_command.py index b95e8f3752cc1..0d80cee446f99 100644 --- a/airflow-core/src/airflow/cli/commands/rotate_fernet_key_command.py +++ b/airflow-core/src/airflow/cli/commands/rotate_fernet_key_command.py @@ -71,10 +71,13 @@ def rotate_items_in_batches_v2(session, model_class, filter_condition=None, batc This function is taking advantage of yield_per available in SQLAlchemy 2.x. """ - while True: - query = select(model_class) - if filter_condition is not None: - query = query.where(filter_condition) + query = select(model_class) + if filter_condition is not None: + query = query.where(filter_condition) + + with session.no_autoflush: # Temporarily disable autoflush while iterating to prevent deadlocks. items = session.scalars(query).yield_per(batch_size) for item in items: item.rotate_fernet_key() + + # The dirty items will be flushed later by the session's transaction management. diff --git a/airflow-core/src/airflow/cli/commands/task_command.py b/airflow-core/src/airflow/cli/commands/task_command.py index 69859af3f5610..e6837f13fb15c 100644 --- a/airflow-core/src/airflow/cli/commands/task_command.py +++ b/airflow-core/src/airflow/cli/commands/task_command.py @@ -59,7 +59,6 @@ from sqlalchemy.orm.session import Session from airflow.models.operator import Operator - from airflow.typing_compat import Self CreateIfNecessary = Literal[False, "db", "memory"] @@ -448,53 +447,3 @@ def task_clear(args) -> None: only_running=args.only_running, confirm_prompt=not args.yes, ) - - -class LoggerMutationHelper: - """ - Helper for moving and resetting handlers and other logger attrs. - - :meta private: - """ - - def __init__(self, logger: logging.Logger) -> None: - self.handlers = logger.handlers[:] - self.level = logger.level - self.propagate = logger.propagate - self.source_logger = logger - - def apply(self, logger: logging.Logger, replace: bool = True) -> None: - """ - Set ``logger`` with attrs stored on instance. - - If ``logger`` is root logger, don't change propagate. - """ - if replace: - logger.handlers[:] = self.handlers - else: - for h in self.handlers: - if h not in logger.handlers: - logger.addHandler(h) - logger.level = self.level - if logger is not logging.getLogger(): - logger.propagate = self.propagate - - def move(self, logger: logging.Logger, replace: bool = True) -> None: - """ - Replace ``logger`` attrs with those from source. - - :param logger: target logger - :param replace: if True, remove all handlers from target first; otherwise add if not present. - """ - self.apply(logger, replace=replace) - self.source_logger.propagate = True - self.source_logger.handlers[:] = [] - - def reset(self) -> None: - self.apply(self.source_logger) - - def __enter__(self) -> Self: - return self - - def __exit__(self, exc_type, exc_val, exc_tb) -> None: - self.reset() diff --git a/airflow-core/src/airflow/cli/simple_table.py b/airflow-core/src/airflow/cli/simple_table.py index b8e4c6a7a41a0..53125e3f74830 100644 --- a/airflow-core/src/airflow/cli/simple_table.py +++ b/airflow-core/src/airflow/cli/simple_table.py @@ -18,8 +18,8 @@ import inspect import json -from collections.abc import Sequence -from typing import TYPE_CHECKING, Any, Callable +from collections.abc import Callable, Sequence +from typing import TYPE_CHECKING, Any from rich.box import ASCII_DOUBLE_HEAD from rich.console import Console diff --git a/airflow-core/src/airflow/config_templates/airflow_local_settings.py b/airflow-core/src/airflow/config_templates/airflow_local_settings.py index 3cade5678261c..cb1cc364e2ca6 100644 --- a/airflow-core/src/airflow/config_templates/airflow_local_settings.py +++ b/airflow-core/src/airflow/config_templates/airflow_local_settings.py @@ -250,7 +250,7 @@ **( { "base_log_folder": BASE_LOG_FOLDER, - "remote_base": remote_base_log_folder, + "remote_base": urlsplit(remote_base_log_folder).path, "delete_local_copy": delete_local_copy, } | remote_task_handler_kwargs diff --git a/airflow-core/src/airflow/configuration.py b/airflow-core/src/airflow/configuration.py index a32f119c744a6..d2f2cce2dfbc4 100644 --- a/airflow-core/src/airflow/configuration.py +++ b/airflow-core/src/airflow/configuration.py @@ -39,7 +39,7 @@ from io import StringIO from json.decoder import JSONDecodeError from re import Pattern -from typing import IO, TYPE_CHECKING, Any, Union +from typing import IO, TYPE_CHECKING, Any from urllib.parse import urlsplit from packaging.version import parse as parse_version @@ -64,9 +64,9 @@ _SQLITE3_VERSION_PATTERN = re.compile(r"(?P^\d+(?:\.\d+)*)\D?.*$") -ConfigType = Union[str, int, float, bool] +ConfigType = str | int | float | bool ConfigOptionsDictType = dict[str, ConfigType] -ConfigSectionSourcesType = dict[str, Union[str, tuple[str, str]]] +ConfigSectionSourcesType = dict[str, str | tuple[str, str]] ConfigSourcesType = dict[str, ConfigSectionSourcesType] ENV_VAR_PREFIX = "AIRFLOW__" diff --git a/airflow-core/src/airflow/dag_processing/manager.py b/airflow-core/src/airflow/dag_processing/manager.py index 36b1bf3e478b2..aebba824231e3 100644 --- a/airflow-core/src/airflow/dag_processing/manager.py +++ b/airflow-core/src/airflow/dag_processing/manager.py @@ -151,7 +151,7 @@ class DagFileProcessorManager(LoggingMixin): over again, but no more often than the specified interval. :param max_runs: The number of times to parse each file. -1 for unlimited. - :param bundles_names_to_parse: List of bundle names to parse. If None, all bundles are parsed. + :param bundle_names_to_parse: List of bundle names to parse. If None, all bundles are parsed. :param processor_timeout: How long to wait before timing out a DAG file processor """ diff --git a/airflow-core/src/airflow/dag_processing/processor.py b/airflow-core/src/airflow/dag_processing/processor.py index 011393f22c886..d626338482420 100644 --- a/airflow-core/src/airflow/dag_processing/processor.py +++ b/airflow-core/src/airflow/dag_processing/processor.py @@ -19,8 +19,9 @@ import os import sys import traceback +from collections.abc import Callable from pathlib import Path -from typing import TYPE_CHECKING, Annotated, BinaryIO, Callable, ClassVar, Literal, Union +from typing import TYPE_CHECKING, Annotated, BinaryIO, ClassVar, Literal import attrs from pydantic import BaseModel, Field, TypeAdapter @@ -88,12 +89,12 @@ class DagFileParsingResult(BaseModel): ToManager = Annotated[ - Union[DagFileParsingResult, GetConnection, GetVariable, PutVariable, DeleteVariable], + DagFileParsingResult | GetConnection | GetVariable | PutVariable | DeleteVariable, Field(discriminator="type"), ] ToDagProcessor = Annotated[ - Union[DagFileParseRequest, ConnectionResult, VariableResult, ErrorResponse, OKResponse], + DagFileParseRequest | ConnectionResult | VariableResult | ErrorResponse | OKResponse, Field(discriminator="type"), ] diff --git a/airflow-core/src/airflow/example_dags/example_time_delta_sensor_async.py b/airflow-core/src/airflow/example_dags/example_time_delta_sensor_async.py index 7b847e6871e37..726fa2cf5c5df 100644 --- a/airflow-core/src/airflow/example_dags/example_time_delta_sensor_async.py +++ b/airflow-core/src/airflow/example_dags/example_time_delta_sensor_async.py @@ -16,8 +16,7 @@ # specific language governing permissions and limitations # under the License. """ -Example DAG demonstrating ``TimeDeltaSensorAsync``, a drop in replacement for ``TimeDeltaSensor`` that -defers and doesn't occupy a worker slot while it waits +Example DAG demonstrating ``TimeDeltaSensor``, that defers and doesn't occupy a worker slot while it waits """ from __future__ import annotations @@ -27,7 +26,7 @@ import pendulum from airflow.providers.standard.operators.empty import EmptyOperator -from airflow.providers.standard.sensors.time_delta import TimeDeltaSensorAsync +from airflow.providers.standard.sensors.time_delta import TimeDeltaSensor from airflow.sdk import DAG with DAG( @@ -37,6 +36,6 @@ catchup=False, tags=["example"], ) as dag: - wait = TimeDeltaSensorAsync(task_id="wait", delta=datetime.timedelta(seconds=30)) + wait = TimeDeltaSensor(task_id="wait", delta=datetime.timedelta(seconds=30), deferrable=True) finish = EmptyOperator(task_id="finish") wait >> finish diff --git a/airflow-core/src/airflow/executors/base_executor.py b/airflow-core/src/airflow/executors/base_executor.py index a59231989ecbf..db42046d4cccf 100644 --- a/airflow-core/src/airflow/executors/base_executor.py +++ b/airflow-core/src/airflow/executors/base_executor.py @@ -23,7 +23,7 @@ from collections.abc import Sequence from dataclasses import dataclass, field from functools import cached_property -from typing import TYPE_CHECKING, Any, Optional +from typing import TYPE_CHECKING, Any import pendulum @@ -58,7 +58,7 @@ # Event_buffer dict value type # Tuple of: state, info - EventBufferValueType = tuple[Optional[str], Any] + EventBufferValueType = tuple[str | None, Any] log = logging.getLogger(__name__) @@ -342,9 +342,7 @@ def trigger_tasks(self, open_slots: int) -> None: # If it's None, then the span for the current TaskInstanceKey hasn't been started. if self.active_spans is not None and self.active_spans.get(key) is None: - from airflow.models.taskinstance import SimpleTaskInstance - - if isinstance(ti, (SimpleTaskInstance, workloads.TaskInstance)): + if isinstance(ti, workloads.TaskInstance): parent_context = Trace.extract(ti.parent_context_carrier) else: parent_context = Trace.extract(ti.dag_run.context_carrier) diff --git a/airflow-core/src/airflow/executors/local_executor.py b/airflow-core/src/airflow/executors/local_executor.py index 4c8ca1e73cb93..eabb921136978 100644 --- a/airflow-core/src/airflow/executors/local_executor.py +++ b/airflow-core/src/airflow/executors/local_executor.py @@ -31,7 +31,7 @@ import multiprocessing.sharedctypes import os from multiprocessing import Queue, SimpleQueue -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING from setproctitle import setproctitle @@ -43,7 +43,7 @@ if TYPE_CHECKING: from sqlalchemy.orm import Session - TaskInstanceStateType = tuple[workloads.TaskInstance, TaskInstanceState, Optional[Exception]] + TaskInstanceStateType = tuple[workloads.TaskInstance, TaskInstanceState, Exception | None] def _run_worker( diff --git a/airflow-core/src/airflow/executors/workloads.py b/airflow-core/src/airflow/executors/workloads.py index 3da9fe3cede39..c8d5f789d7112 100644 --- a/airflow-core/src/airflow/executors/workloads.py +++ b/airflow-core/src/airflow/executors/workloads.py @@ -20,7 +20,7 @@ import uuid from datetime import datetime from pathlib import Path -from typing import TYPE_CHECKING, Annotated, Literal, Union +from typing import TYPE_CHECKING, Annotated, Literal import structlog from pydantic import BaseModel, Field @@ -160,6 +160,6 @@ class RunTrigger(BaseModel): All = Annotated[ - Union[ExecuteTask, RunTrigger], + ExecuteTask | RunTrigger, Field(discriminator="type"), ] diff --git a/airflow-core/src/airflow/io/__init__.py b/airflow-core/src/airflow/io/__init__.py index 01e0cfaabe2d5..6bbea93e59ba3 100644 --- a/airflow-core/src/airflow/io/__init__.py +++ b/airflow-core/src/airflow/io/__init__.py @@ -18,11 +18,10 @@ import inspect import logging -from collections.abc import Mapping +from collections.abc import Callable, Mapping from functools import cache from typing import ( TYPE_CHECKING, - Callable, ) from fsspec.implementations.local import LocalFileSystem diff --git a/airflow-core/src/airflow/jobs/job.py b/airflow-core/src/airflow/jobs/job.py index 9c06552abca21..7cd2180bbd7bd 100644 --- a/airflow-core/src/airflow/jobs/job.py +++ b/airflow-core/src/airflow/jobs/job.py @@ -17,9 +17,10 @@ # under the License. from __future__ import annotations +from collections.abc import Callable from functools import cached_property, lru_cache from time import sleep -from typing import TYPE_CHECKING, Callable, NoReturn +from typing import TYPE_CHECKING, NoReturn from sqlalchemy import Column, Index, Integer, String, case, select from sqlalchemy.exc import OperationalError diff --git a/airflow-core/src/airflow/jobs/scheduler_job_runner.py b/airflow-core/src/airflow/jobs/scheduler_job_runner.py index 0cc71bf19b482..38e70b372ab1d 100644 --- a/airflow-core/src/airflow/jobs/scheduler_job_runner.py +++ b/airflow-core/src/airflow/jobs/scheduler_job_runner.py @@ -25,14 +25,14 @@ import sys import time from collections import Counter, defaultdict, deque -from collections.abc import Collection, Iterable, Iterator +from collections.abc import Callable, Collection, Iterable, Iterator from contextlib import ExitStack from datetime import date, timedelta from functools import lru_cache, partial from itertools import groupby -from typing import TYPE_CHECKING, Any, Callable +from typing import TYPE_CHECKING, Any -from sqlalchemy import and_, delete, exists, func, or_, select, text, tuple_, update +from sqlalchemy import and_, delete, desc, exists, func, or_, select, text, tuple_, update from sqlalchemy.exc import OperationalError from sqlalchemy.orm import joinedload, lazyload, load_only, make_transient, selectinload from sqlalchemy.sql import expression @@ -2028,19 +2028,34 @@ def _get_num_times_stuck_in_queued(self, ti: TaskInstance, session: Session = NE We can then use this information to determine whether to reschedule a task or fail it. """ - return ( - session.query(Log) + last_running_time = session.scalar( + select(Log.dttm) .where( - Log.task_id == ti.task_id, Log.dag_id == ti.dag_id, + Log.task_id == ti.task_id, Log.run_id == ti.run_id, Log.map_index == ti.map_index, Log.try_number == ti.try_number, - Log.event == TASK_STUCK_IN_QUEUED_RESCHEDULE_EVENT, + Log.event == "running", ) - .count() + .order_by(desc(Log.dttm)) + .limit(1) + ) + + query = session.query(Log).where( + Log.task_id == ti.task_id, + Log.dag_id == ti.dag_id, + Log.run_id == ti.run_id, + Log.map_index == ti.map_index, + Log.try_number == ti.try_number, + Log.event == TASK_STUCK_IN_QUEUED_RESCHEDULE_EVENT, ) + if last_running_time: + query = query.where(Log.dttm > last_running_time) + + return query.count() + previous_ti_running_metrics: dict[tuple[str, str, str], int] = {} @provide_session diff --git a/airflow-core/src/airflow/jobs/triggerer_job_runner.py b/airflow-core/src/airflow/jobs/triggerer_job_runner.py index adc87e802fa6f..2811dcf89f38b 100644 --- a/airflow-core/src/airflow/jobs/triggerer_job_runner.py +++ b/airflow-core/src/airflow/jobs/triggerer_job_runner.py @@ -30,7 +30,7 @@ from datetime import datetime from socket import socket from traceback import format_exception -from typing import TYPE_CHECKING, Annotated, Any, ClassVar, Literal, TypedDict, Union +from typing import TYPE_CHECKING, Annotated, Any, ClassVar, Literal, TypedDict import attrs import structlog @@ -210,18 +210,16 @@ class TriggerStateSync(BaseModel): ToTriggerRunner = Annotated[ - Union[ - messages.StartTriggerer, - messages.TriggerStateSync, - ConnectionResult, - VariableResult, - XComResult, - DagRunStateResult, - DRCount, - TICount, - TaskStatesResult, - ErrorResponse, - ], + messages.StartTriggerer + | messages.TriggerStateSync + | ConnectionResult + | VariableResult + | XComResult + | DagRunStateResult + | DRCount + | TICount + | TaskStatesResult + | ErrorResponse, Field(discriminator="type"), ] """ @@ -231,16 +229,14 @@ class TriggerStateSync(BaseModel): ToTriggerSupervisor = Annotated[ - Union[ - messages.TriggerStateChanges, - GetConnection, - GetVariable, - GetXCom, - GetTICount, - GetTaskStates, - GetDagRunState, - GetDRCount, - ], + messages.TriggerStateChanges + | GetConnection + | GetVariable + | GetXCom + | GetTICount + | GetTaskStates + | GetDagRunState + | GetDRCount, Field(discriminator="type"), ] """ @@ -713,11 +709,11 @@ def send(self, msg: ToTriggerSupervisor) -> ToTriggerRunner | None: async def _aread_frame(self): len_bytes = await self._async_reader.readexactly(4) - len = int.from_bytes(len_bytes, byteorder="big") - if len >= 2**32: - raise OverflowError(f"Refusing to receive messages larger than 4GiB {len=}") + length = int.from_bytes(len_bytes, byteorder="big") + if length >= 2**32: + raise OverflowError(f"Refusing to receive messages larger than 4GiB {length=}") - buffer = await self._async_reader.readexactly(len) + buffer = await self._async_reader.readexactly(length) return self.resp_decoder.decode(buffer) async def _aget_response(self, expect_id: int) -> ToTriggerRunner | None: diff --git a/airflow-core/src/airflow/lineage/hook.py b/airflow-core/src/airflow/lineage/hook.py index 9aeb65c277147..712b778aef6aa 100644 --- a/airflow-core/src/airflow/lineage/hook.py +++ b/airflow-core/src/airflow/lineage/hook.py @@ -20,7 +20,7 @@ import hashlib import json from collections import defaultdict -from typing import TYPE_CHECKING, Union +from typing import TYPE_CHECKING, TypeAlias import attr @@ -33,7 +33,7 @@ from airflow.sdk import ObjectStoragePath # Store context what sent lineage. - LineageContext = Union[BaseHook, ObjectStoragePath] + LineageContext: TypeAlias = BaseHook | ObjectStoragePath _hook_lineage_collector: HookLineageCollector | None = None diff --git a/airflow-core/src/airflow/metrics/otel_logger.py b/airflow-core/src/airflow/metrics/otel_logger.py index a8ad9d8ce2eb1..317b70a5ca29d 100644 --- a/airflow-core/src/airflow/metrics/otel_logger.py +++ b/airflow-core/src/airflow/metrics/otel_logger.py @@ -20,7 +20,8 @@ import logging import random import warnings -from typing import TYPE_CHECKING, Callable, Union +from collections.abc import Callable +from typing import TYPE_CHECKING from opentelemetry import metrics from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter @@ -47,7 +48,7 @@ log = logging.getLogger(__name__) -GaugeValues = Union[int, float] +GaugeValues = int | float DEFAULT_GAUGE_VALUE = 0.0 diff --git a/airflow-core/src/airflow/metrics/protocols.py b/airflow-core/src/airflow/metrics/protocols.py index 3c405aef37e7a..d170fe29ad9ba 100644 --- a/airflow-core/src/airflow/metrics/protocols.py +++ b/airflow-core/src/airflow/metrics/protocols.py @@ -19,12 +19,12 @@ import datetime import time -from typing import TYPE_CHECKING, Protocol, Union +from typing import TYPE_CHECKING, Protocol if TYPE_CHECKING: from airflow.typing_compat import Self -DeltaType = Union[int, float, datetime.timedelta] +DeltaType = int | float | datetime.timedelta class TimerProtocol(Protocol): diff --git a/airflow-core/src/airflow/metrics/statsd_logger.py b/airflow-core/src/airflow/metrics/statsd_logger.py index 8d47bc9ae132a..d952693eb230d 100644 --- a/airflow-core/src/airflow/metrics/statsd_logger.py +++ b/airflow-core/src/airflow/metrics/statsd_logger.py @@ -18,8 +18,9 @@ from __future__ import annotations import logging +from collections.abc import Callable from functools import wraps -from typing import TYPE_CHECKING, Callable, TypeVar, cast +from typing import TYPE_CHECKING, TypeVar, cast from airflow.configuration import conf from airflow.exceptions import AirflowConfigException diff --git a/airflow-core/src/airflow/metrics/validators.py b/airflow-core/src/airflow/metrics/validators.py index 85152426fdd17..252524455e022 100644 --- a/airflow-core/src/airflow/metrics/validators.py +++ b/airflow-core/src/airflow/metrics/validators.py @@ -24,10 +24,10 @@ import re import string import warnings -from collections.abc import Iterable +from collections.abc import Callable, Iterable from functools import partial, wraps from re import Pattern -from typing import Callable, cast +from typing import cast from airflow.configuration import conf from airflow.exceptions import InvalidStatsNameException diff --git a/airflow-core/src/airflow/migrations/versions/0036_3_0_0_add_name_field_to_dataset_model.py b/airflow-core/src/airflow/migrations/versions/0036_3_0_0_add_name_field_to_dataset_model.py index c7112f91b3c5e..b1f925dbffca2 100644 --- a/airflow-core/src/airflow/migrations/versions/0036_3_0_0_add_name_field_to_dataset_model.py +++ b/airflow-core/src/airflow/migrations/versions/0036_3_0_0_add_name_field_to_dataset_model.py @@ -48,7 +48,7 @@ _STRING_COLUMN_TYPE = sa.String(length=1500).with_variant( sa.String(length=1500, collation="latin1_general_cs"), - dialect_name="mysql", + "mysql", ) @@ -128,7 +128,7 @@ def downgrade(): "uri", type_=sa.String(length=3000).with_variant( sa.String(length=3000, collation="latin1_general_cs"), - dialect_name="mysql", + "mysql", ), nullable=False, ) diff --git a/airflow-core/src/airflow/migrations/versions/0038_3_0_0_add_asset_active.py b/airflow-core/src/airflow/migrations/versions/0038_3_0_0_add_asset_active.py index c924e0157bd5e..2a992cab4126e 100644 --- a/airflow-core/src/airflow/migrations/versions/0038_3_0_0_add_asset_active.py +++ b/airflow-core/src/airflow/migrations/versions/0038_3_0_0_add_asset_active.py @@ -39,7 +39,7 @@ _STRING_COLUMN_TYPE = sa.String(length=1500).with_variant( sa.String(length=1500, collation="latin1_general_cs"), - dialect_name="mysql", + "mysql", ) diff --git a/airflow-core/src/airflow/migrations/versions/0039_3_0_0_tweak_assetaliasmodel_to_match_asset.py b/airflow-core/src/airflow/migrations/versions/0039_3_0_0_tweak_assetaliasmodel_to_match_asset.py index 7cc2423590440..d0067f1288255 100644 --- a/airflow-core/src/airflow/migrations/versions/0039_3_0_0_tweak_assetaliasmodel_to_match_asset.py +++ b/airflow-core/src/airflow/migrations/versions/0039_3_0_0_tweak_assetaliasmodel_to_match_asset.py @@ -51,7 +51,7 @@ _STRING_COLUMN_TYPE = sa.String(length=1500).with_variant( sa.String(length=1500, collation="latin1_general_cs"), - dialect_name="mysql", + "mysql", ) @@ -77,7 +77,7 @@ def downgrade(): "name", type_=sa.String(length=3000).with_variant( sa.String(length=3000, collation="latin1_general_cs"), - dialect_name="mysql", + "mysql", ), nullable=False, ) diff --git a/airflow-core/src/airflow/models/base.py b/airflow-core/src/airflow/models/base.py index c146f4619efb3..0548e08a8f605 100644 --- a/airflow-core/src/airflow/models/base.py +++ b/airflow-core/src/airflow/models/base.py @@ -23,6 +23,7 @@ from sqlalchemy.orm import registry from airflow.configuration import conf +from airflow.utils.sqlalchemy import is_sqlalchemy_v1 SQL_ALCHEMY_SCHEMA = conf.get("database", "SQL_ALCHEMY_SCHEMA") @@ -52,6 +53,10 @@ def _get_schema(): Base = Any else: Base = mapper_registry.generate_base() + # TEMPORARY workaround to allow using unmapped (v1.4) models in SQLAlchemy 2.0. It is intended only to + # unblock the development of SQLA2 support. + if not is_sqlalchemy_v1(): + Base.__allow_unmapped__ = True ID_LEN = 250 diff --git a/airflow-core/src/airflow/models/connection.py b/airflow-core/src/airflow/models/connection.py index 02df02ddac2ca..a3ff23bbdea07 100644 --- a/airflow-core/src/airflow/models/connection.py +++ b/airflow-core/src/airflow/models/connection.py @@ -266,11 +266,20 @@ def get_uri(self) -> str: if self.host and "://" in self.host: protocol, host = self.host.split("://", 1) + # If the protocol in host matches the connection type, don't add it again + if protocol == self.conn_type: + host_to_use = self.host + protocol_to_add = None + else: + # Different protocol, add it to the URI + host_to_use = host + protocol_to_add = protocol else: - protocol, host = None, self.host + host_to_use = self.host + protocol_to_add = None - if protocol: - uri += f"{protocol}://" + if protocol_to_add: + uri += f"{protocol_to_add}://" authority_block = "" if self.login is not None: @@ -285,8 +294,8 @@ def get_uri(self) -> str: uri += authority_block host_block = "" - if host: - host_block += quote(host, safe="") + if host_to_use: + host_block += quote(host_to_use, safe="") if self.port: if host_block == "" and authority_block == "": diff --git a/airflow-core/src/airflow/models/dag.py b/airflow-core/src/airflow/models/dag.py index 80263b45ef8d2..2fe689e6168d5 100644 --- a/airflow-core/src/airflow/models/dag.py +++ b/airflow-core/src/airflow/models/dag.py @@ -22,13 +22,12 @@ import logging import re from collections import defaultdict -from collections.abc import Collection, Generator, Iterable, Sequence +from collections.abc import Callable, Collection, Generator, Iterable, Sequence from datetime import datetime, timedelta from functools import cache from typing import ( TYPE_CHECKING, Any, - Callable, TypeVar, Union, cast, @@ -122,14 +121,9 @@ TAG_MAX_LEN = 100 DagStateChangeCallback = Callable[[Context], None] -ScheduleInterval = Union[None, str, timedelta, relativedelta] +ScheduleInterval = None | str | timedelta | relativedelta -ScheduleArg = Union[ - ScheduleInterval, - Timetable, - BaseAsset, - Collection[Union["Asset", "AssetAlias"]], -] +ScheduleArg = ScheduleInterval | Timetable | BaseAsset | Collection[Union["Asset", "AssetAlias"]] class InconsistentDataInterval(AirflowException): @@ -227,13 +221,6 @@ def get_asset_triggered_next_run_info( } -def _triggerer_is_healthy(session: Session): - from airflow.jobs.triggerer_job_runner import TriggererJobRunner - - job = TriggererJobRunner.most_recent_job(session=session) - return job and job.is_alive() - - @provide_session def _create_orm_dagrun( *, @@ -716,15 +703,6 @@ def get_last_dagrun(self, session=NEW_SESSION, include_manually_triggered=False) self.dag_id, session=session, include_manually_triggered=include_manually_triggered ) - @provide_session - def has_dag_runs(self, session=NEW_SESSION, include_manually_triggered=True) -> bool: - return ( - get_last_dagrun( - self.dag_id, session=session, include_manually_triggered=include_manually_triggered - ) - is not None - ) - @property def dag_id(self) -> str: return self._dag_id @@ -1589,9 +1567,6 @@ def create_dagrun( # todo: AIP-78 add verification that if run type is backfill then we have a backfill id - if TYPE_CHECKING: - # TODO: Task-SDK: remove this assert - assert self.params # create a copy of params before validating copied_params = copy.deepcopy(self.params) if conf: diff --git a/airflow-core/src/airflow/models/dag_version.py b/airflow-core/src/airflow/models/dag_version.py index a1fa9cd3235fe..5c1068d6a9614 100644 --- a/airflow-core/src/airflow/models/dag_version.py +++ b/airflow-core/src/airflow/models/dag_version.py @@ -108,6 +108,7 @@ def write_dag( ) log.debug("Writing DagVersion %s to the DB", dag_version) session.add(dag_version) + session.commit() log.debug("DagVersion %s written to the DB", dag_version) return dag_version diff --git a/airflow-core/src/airflow/models/dagrun.py b/airflow-core/src/airflow/models/dagrun.py index 8dcd00fef0cbc..b6294aa3b0d17 100644 --- a/airflow-core/src/airflow/models/dagrun.py +++ b/airflow-core/src/airflow/models/dagrun.py @@ -21,14 +21,12 @@ import os import re from collections import defaultdict -from collections.abc import Iterable, Iterator, Sequence +from collections.abc import Callable, Iterable, Iterator, Sequence from typing import ( TYPE_CHECKING, Any, - Callable, NamedTuple, TypeVar, - Union, overload, ) @@ -58,7 +56,6 @@ from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.ext.mutable import MutableDict from sqlalchemy.orm import declared_attr, joinedload, relationship, synonym, validates -from sqlalchemy.sql.elements import Case from sqlalchemy.sql.expression import false, select from sqlalchemy.sql.functions import coalesce from sqlalchemy_utils import UUIDType @@ -390,16 +387,14 @@ def duration(cls, session: Session = NEW_SESSION) -> Case: dialect_name = session.bind.dialect.name if dialect_name == "mysql": return func.timestampdiff(text("SECOND"), cls.start_date, cls.end_date) - return case( - [ - ( - (cls.end_date != None) & (cls.start_date != None), # noqa: E711 - func.extract("epoch", cls.end_date - cls.start_date), - ) - ], - else_=None, + + when_condition = ( + (cls.end_date != None) & (cls.start_date != None), # noqa: E711 + func.extract("epoch", cls.end_date - cls.start_date), ) + return case(when_condition, else_=None) + @provide_session def check_version_id_exists_in_dr(self, dag_version_id: UUIDType, session: Session = NEW_SESSION): select_stmt = ( @@ -979,16 +974,9 @@ def set_dagrun_span_attrs(self, span: Span | EmptySpan): if self._state == DagRunState.FAILED: span.set_attribute("airflow.dag_run.error", True) - attribute_value_type = Union[ - str, - bool, - int, - float, - Sequence[str], - Sequence[bool], - Sequence[int], - Sequence[float], - ] + attribute_value_type = ( + str | bool | int | float | Sequence[str] | Sequence[bool] | Sequence[int] | Sequence[float] + ) # Explicitly set the value type to Union[...] to avoid a mypy error. attributes: dict[str, attribute_value_type] = { diff --git a/airflow-core/src/airflow/models/expandinput.py b/airflow-core/src/airflow/models/expandinput.py index b126c6f24b07f..803a8fe294c6d 100644 --- a/airflow-core/src/airflow/models/expandinput.py +++ b/airflow-core/src/airflow/models/expandinput.py @@ -20,7 +20,7 @@ import functools import operator from collections.abc import Iterable, Sized -from typing import TYPE_CHECKING, Any, ClassVar, Union +from typing import TYPE_CHECKING, Any, ClassVar import attrs @@ -138,7 +138,7 @@ def get_total_map_length(self, run_id: str, *, session: Session) -> int: "list-of-dicts": SchedulerListOfDictsExpandInput, } -SchedulerExpandInput = Union[SchedulerDictOfListsExpandInput, SchedulerListOfDictsExpandInput] +SchedulerExpandInput = SchedulerDictOfListsExpandInput | SchedulerListOfDictsExpandInput def create_expand_input(kind: str, value: Any) -> SchedulerExpandInput: diff --git a/airflow-core/src/airflow/models/operator.py b/airflow-core/src/airflow/models/operator.py index b42823e4c2189..a42b21b0a2544 100644 --- a/airflow-core/src/airflow/models/operator.py +++ b/airflow-core/src/airflow/models/operator.py @@ -17,12 +17,10 @@ # under the License. from __future__ import annotations -from typing import Union - from airflow.models.baseoperator import BaseOperator from airflow.models.mappedoperator import MappedOperator -Operator = Union[BaseOperator, MappedOperator] +Operator = BaseOperator | MappedOperator __all__ = ["Operator"] diff --git a/airflow-core/src/airflow/models/serialized_dag.py b/airflow-core/src/airflow/models/serialized_dag.py index 71722b54adee6..a05c4e6520415 100644 --- a/airflow-core/src/airflow/models/serialized_dag.py +++ b/airflow-core/src/airflow/models/serialized_dag.py @@ -21,9 +21,9 @@ import logging import zlib -from collections.abc import Iterable, Iterator, Sequence +from collections.abc import Callable, Iterable, Iterator, Sequence from datetime import timedelta -from typing import TYPE_CHECKING, Any, Callable, Literal +from typing import TYPE_CHECKING, Any, Literal import sqlalchemy_jsonfield import uuid6 diff --git a/airflow-core/src/airflow/models/taskinstance.py b/airflow-core/src/airflow/models/taskinstance.py index 21e20b32b9627..9044817c851c0 100644 --- a/airflow-core/src/airflow/models/taskinstance.py +++ b/airflow-core/src/airflow/models/taskinstance.py @@ -2510,97 +2510,6 @@ def _is_further_mapped_inside(operator: Operator, container: TaskGroup) -> bool: return False -# State of the task instance. -# Stores string version of the task state. -TaskInstanceStateType = tuple[TaskInstanceKey, TaskInstanceState] - - -class SimpleTaskInstance: - """ - Simplified Task Instance. - - Used to send data between processes via Queues. - """ - - def __init__( - self, - dag_id: str, - task_id: str, - run_id: str, - queued_dttm: datetime | None, - start_date: datetime | None, - end_date: datetime | None, - try_number: int, - map_index: int, - state: str, - executor: str | None, - executor_config: Any, - pool: str, - queue: str, - key: TaskInstanceKey, - run_as_user: str | None = None, - priority_weight: int | None = None, - parent_context_carrier: dict | None = None, - context_carrier: dict | None = None, - span_status: str | None = None, - ): - self.dag_id = dag_id - self.task_id = task_id - self.run_id = run_id - self.map_index = map_index - self.queued_dttm = queued_dttm - self.start_date = start_date - self.end_date = end_date - self.try_number = try_number - self.state = state - self.executor = executor - self.executor_config = executor_config - self.run_as_user = run_as_user - self.pool = pool - self.priority_weight = priority_weight - self.queue = queue - self.key = key - self.parent_context_carrier = parent_context_carrier - self.context_carrier = context_carrier - self.span_status = span_status - - def __repr__(self) -> str: - attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items()) - return f"SimpleTaskInstance({attrs})" - - def __eq__(self, other) -> bool: - if isinstance(other, self.__class__): - return self.__dict__ == other.__dict__ - return NotImplemented - - @classmethod - def from_ti(cls, ti: TaskInstance) -> SimpleTaskInstance: - return cls( - dag_id=ti.dag_id, - task_id=ti.task_id, - run_id=ti.run_id, - map_index=ti.map_index, - queued_dttm=ti.queued_dttm, - start_date=ti.start_date, - end_date=ti.end_date, - try_number=ti.try_number, - state=ti.state, - executor=ti.executor, - executor_config=ti.executor_config, - pool=ti.pool, - queue=ti.queue, - key=ti.key, - run_as_user=ti.run_as_user if hasattr(ti, "run_as_user") else None, - priority_weight=ti.priority_weight if hasattr(ti, "priority_weight") else None, - # Inspect the ti, to check if the 'dag_run' relationship is loaded. - parent_context_carrier=ti.dag_run.context_carrier - if "dag_run" not in inspect(ti).unloaded - else None, - context_carrier=ti.context_carrier if hasattr(ti, "context_carrier") else None, - span_status=ti.span_status, - ) - - class TaskInstanceNote(Base): """For storage of arbitrary notes concerning the task instance.""" diff --git a/airflow-core/src/airflow/models/variable.py b/airflow-core/src/airflow/models/variable.py index 5537e66e802f6..2c9138f7c695d 100644 --- a/airflow-core/src/airflow/models/variable.py +++ b/airflow-core/src/airflow/models/variable.py @@ -186,7 +186,7 @@ def set( """ Set a value for an Airflow Variable with a given Key. - This operation overwrites an existing variable. + This operation overwrites an existing variable using the session's dialect-specific upsert operation. :param key: Variable Key :param value: Value to set for the Variable @@ -231,9 +231,47 @@ def set( ctx = create_session() with ctx as session: - Variable.delete(key, session=session) - session.add(Variable(key=key, val=stored_value, description=description)) - session.flush() + new_variable = Variable(key=key, val=stored_value, description=description) + + val = new_variable._val + is_encrypted = new_variable.is_encrypted + + # Import dialect-specific insert function + if (dialect_name := session.get_bind().dialect.name) == "postgresql": + from sqlalchemy.dialects.postgresql import insert + elif dialect_name == "mysql": + from sqlalchemy.dialects.mysql import insert + else: + from sqlalchemy.dialects.sqlite import insert + + # Create the insert statement (common for all dialects) + stmt = insert(Variable).values( + key=key, + val=val, + description=description, + is_encrypted=is_encrypted, + ) + + # Apply dialect-specific upsert + if dialect_name == "mysql": + # MySQL: ON DUPLICATE KEY UPDATE + stmt = stmt.on_duplicate_key_update( + val=val, + description=description, + is_encrypted=is_encrypted, + ) + else: + # PostgreSQL and SQLite: ON CONFLICT DO UPDATE + stmt = stmt.on_conflict_do_update( + index_elements=["key"], + set_=dict( + val=val, + description=description, + is_encrypted=is_encrypted, + ), + ) + + session.execute(stmt) # invalidate key in cache for faster propagation # we cannot save the value set because it's possible that it's shadowed by a custom backend # (see call to check_for_write_conflict above) diff --git a/airflow-core/src/airflow/plugins_manager.py b/airflow-core/src/airflow/plugins_manager.py index 84cc92cd81723..2b0b324e9e352 100644 --- a/airflow-core/src/airflow/plugins_manager.py +++ b/airflow-core/src/airflow/plugins_manager.py @@ -69,7 +69,8 @@ flask_blueprints: list[Any] | None = None fastapi_apps: list[Any] | None = None fastapi_root_middlewares: list[Any] | None = None -iframe_views: list[Any] | None = None +external_views: list[Any] | None = None +react_apps: list[Any] | None = None menu_links: list[Any] | None = None flask_appbuilder_views: list[Any] | None = None flask_appbuilder_menu_links: list[Any] | None = None @@ -91,7 +92,8 @@ "flask_blueprints", "fastapi_apps", "fastapi_root_middlewares", - "iframe_views", + "external_views", + "react_apps", "menu_links", "appbuilder_views", "appbuilder_menu_items", @@ -156,7 +158,8 @@ class AirflowPlugin: flask_blueprints: list[Any] = [] fastapi_apps: list[Any] = [] fastapi_root_middlewares: list[Any] = [] - iframe_views: list[Any] = [] + external_views: list[Any] = [] + react_apps: list[Any] = [] menu_links: list[Any] = [] appbuilder_views: list[Any] = [] appbuilder_menu_items: list[Any] = [] @@ -371,9 +374,10 @@ def ensure_plugins_loaded(): def initialize_ui_plugins(): """Collect extension points for the UI.""" global plugins - global iframe_views + global external_views + global react_apps - if iframe_views is not None: + if external_views is not None and react_apps is not None: return ensure_plugins_loaded() @@ -383,10 +387,12 @@ def initialize_ui_plugins(): log.debug("Initialize UI plugin") - iframe_views = [] + external_views = [] + react_apps = [] for plugin in plugins: - iframe_views.extend(plugin.iframe_views) + external_views.extend(plugin.external_views) + react_apps.extend(plugin.react_apps) def initialize_flask_plugins(): diff --git a/airflow-core/src/airflow/providers_manager.py b/airflow-core/src/airflow/providers_manager.py index 81611c8205df7..757957ad5d039 100644 --- a/airflow-core/src/airflow/providers_manager.py +++ b/airflow-core/src/airflow/providers_manager.py @@ -26,18 +26,16 @@ import logging import traceback import warnings -from collections.abc import MutableMapping +from collections.abc import Callable, MutableMapping from dataclasses import dataclass from functools import wraps from importlib.resources import files as resource_files from time import perf_counter -from typing import TYPE_CHECKING, Any, Callable, NamedTuple, TypeVar +from typing import TYPE_CHECKING, Any, NamedTuple, TypeVar from packaging.utils import canonicalize_name from airflow.exceptions import AirflowOptionalProviderFeatureException -from airflow.providers.standard.hooks.filesystem import FSHook -from airflow.providers.standard.hooks.package_index import PackageIndexHook from airflow.typing_compat import ParamSpec from airflow.utils.entry_points import entry_points_with_dist from airflow.utils.log.logging_mixin import LoggingMixin @@ -395,8 +393,6 @@ def __init__(self): self._initialized_cache: dict[str, bool] = {} # Keeps dict of providers keyed by module name self._provider_dict: dict[str, ProviderInfo] = {} - # Keeps dict of hooks keyed by connection type - self._hooks_dict: dict[str, HookInfo] = {} self._fs_set: set[str] = set() self._asset_uri_handlers: dict[str, Callable[[SplitResult], SplitResult]] = {} self._asset_factories: dict[str, Callable[..., Asset]] = {} @@ -443,19 +439,17 @@ def _init_airflow_core_hooks(self): connection_type=None, connection_testable=False, ) - for cls in [FSHook, PackageIndexHook]: - package_name = cls.__module__ - hook_class_name = f"{cls.__module__}.{cls.__name__}" - hook_info = self._import_hook( + for conn_type, class_name in ( + ("fs", "airflow.providers.standard.hooks.filesystem.FSHook"), + ("package_index", "airflow.providers.standard.hooks.package_index.PackageIndexHook"), + ): + self._hooks_lazy_dict[conn_type] = functools.partial( + self._import_hook, connection_type=None, - provider_info=None, - hook_class_name=hook_class_name, - package_name=package_name, - ) - self._hook_provider_dict[hook_info.connection_type] = HookClassProvider( - hook_class_name=hook_class_name, package_name=package_name + package_name="apache-airflow-providers-standard", + hook_class_name=class_name, + provider_info=None, # type: ignore[argument] ) - self._hooks_lazy_dict[hook_info.connection_type] = hook_info @provider_info_cache("list") def initialize_providers_list(self): @@ -487,6 +481,7 @@ def _verify_all_providers_all_compatible(self): @provider_info_cache("hooks") def initialize_providers_hooks(self): """Lazy initialization of providers hooks.""" + self._init_airflow_core_hooks() self.initialize_providers_list() self._discover_hooks() self._hook_provider_dict = dict(sorted(self._hook_provider_dict.items())) @@ -1275,7 +1270,6 @@ def already_initialized_provider_configs(self) -> list[tuple[str, dict[str, Any] def _cleanup(self): self._initialized_cache.clear() self._provider_dict.clear() - self._hooks_dict.clear() self._fs_set.clear() self._taskflow_decorators.clear() self._hook_provider_dict.clear() diff --git a/airflow-core/src/airflow/sensors/__init__.py b/airflow-core/src/airflow/sensors/__init__.py index 62a4037df2f66..db378f4550324 100644 --- a/airflow-core/src/airflow/sensors/__init__.py +++ b/airflow-core/src/airflow/sensors/__init__.py @@ -26,8 +26,12 @@ from airflow.utils.deprecation_tools import add_deprecated_classes -# TODO: Add definition from Task SDK here and remove `base.py` file __deprecated_classes = { + "base": { + "BaseSensorOperator": "airflow.sdk.bases.sensor.BaseSensorOperator", + "PokeReturnValue": "airflow.sdk.bases.sensor.PokeReturnValue", + "poke_mode_only": "airflow.sdk.bases.sensor.poke_mode_only", + }, "python":{ "PythonSensor": "airflow.providers.standard.sensors.python.PythonSensor", }, diff --git a/airflow-core/src/airflow/serialization/enums.py b/airflow-core/src/airflow/serialization/enums.py index 1d04bee6f290d..11c37b3bd1a4e 100644 --- a/airflow-core/src/airflow/serialization/enums.py +++ b/airflow-core/src/airflow/serialization/enums.py @@ -62,17 +62,10 @@ class DagAttributeTypes(str, Enum): ASSET_REF = "asset_ref" ASSET_UNIQUE_KEY = "asset_unique_key" ASSET_ALIAS_UNIQUE_KEY = "asset_alias_unique_key" - SIMPLE_TASK_INSTANCE = "simple_task_instance" - BASE_JOB = "Job" - TASK_INSTANCE = "task_instance" - DAG_RUN = "dag_run" - DAG_MODEL = "dag_model" - LOG_TEMPLATE = "log_template" CONNECTION = "connection" TASK_CONTEXT = "task_context" ARG_NOT_SET = "arg_not_set" TASK_CALLBACK_REQUEST = "task_callback_request" DAG_CALLBACK_REQUEST = "dag_callback_request" TASK_INSTANCE_KEY = "task_instance_key" - TRIGGER = "trigger" DEADLINE_ALERT = "deadline_alert" diff --git a/airflow-core/src/airflow/serialization/serde.py b/airflow-core/src/airflow/serialization/serde.py index 0268ad91206d8..664a8d7cd5657 100644 --- a/airflow-core/src/airflow/serialization/serde.py +++ b/airflow-core/src/airflow/serialization/serde.py @@ -26,7 +26,7 @@ from fnmatch import fnmatch from importlib import import_module from re import Pattern -from typing import TYPE_CHECKING, Any, TypeVar, Union, cast +from typing import TYPE_CHECKING, Any, TypeVar, cast import attr @@ -56,8 +56,8 @@ DEFAULT_VERSION = 0 T = TypeVar("T", bool, float, int, dict, list, str, tuple, set) -U = Union[bool, float, int, dict, list, str, tuple, set] -S = Union[list, tuple, set] +U = bool | float | int | dict | list | str | tuple | set +S = list | tuple | set _serializers: dict[str, ModuleType] = {} _deserializers: dict[str, ModuleType] = {} diff --git a/airflow-core/src/airflow/serialization/serialized_objects.py b/airflow-core/src/airflow/serialization/serialized_objects.py index 3859c535d1828..1db0a91236199 100644 --- a/airflow-core/src/airflow/serialization/serialized_objects.py +++ b/airflow-core/src/airflow/serialization/serialized_objects.py @@ -47,7 +47,6 @@ from airflow.models.expandinput import ( create_expand_input, ) -from airflow.models.taskinstance import SimpleTaskInstance, TaskInstance from airflow.models.taskinstancekey import TaskInstanceKey from airflow.models.xcom import XComModel from airflow.models.xcom_arg import SchedulerXComArg, deserialize_xcom_arg @@ -101,6 +100,7 @@ from airflow.models import DagRun from airflow.models.expandinput import SchedulerExpandInput + from airflow.models.taskinstance import TaskInstance from airflow.sdk import BaseOperatorLink from airflow.sdk.definitions._internal.node import DAGNode from airflow.sdk.types import Operator @@ -520,20 +520,13 @@ def deref(self, dag: DAG) -> SchedulerXComArg: # the type declarations in expandinput.py so we always remember to update # serialization logic when adding new ExpandInput variants. If you add things to # the unions, be sure to update _ExpandInputRef to match. -_ExpandInputOriginalValue = Union[ - # For .expand(**kwargs). - Mapping[str, Any], - # For expand_kwargs(arg). - XComArg, - Collection[Union[XComArg, Mapping[str, Any]]], -] -_ExpandInputSerializedValue = Union[ - # For .expand(**kwargs). - Mapping[str, Any], - # For expand_kwargs(arg). - _XComRef, - Collection[Union[_XComRef, Mapping[str, Any]]], -] +# Mapping[str, Any], For .expand(**kwargs). +# XComArg # For expand_kwargs(arg). +_ExpandInputOriginalValue = Mapping[str, Any] | XComArg | Collection[XComArg | Mapping[str, Any]] + +# Mapping[str, Any], For .expand(**kwargs). +# _XComRef For expand_kwargs(arg). +_ExpandInputSerializedValue = Mapping[str, Any] | _XComRef | Collection[_XComRef | Mapping[str, Any]] class _ExpandInputRef(NamedTuple): @@ -822,11 +815,6 @@ def serialize( return cls._encode(serialized_asset, type_=serialized_asset.pop("__type")) elif isinstance(var, AssetRef): return cls._encode(attrs.asdict(var), type_=DAT.ASSET_REF) - elif isinstance(var, SimpleTaskInstance): - return cls._encode( - cls.serialize(var.__dict__, strict=strict), - type_=DAT.SIMPLE_TASK_INSTANCE, - ) elif isinstance(var, Connection): return cls._encode(var.to_dict(validate=True), type_=DAT.CONNECTION) elif isinstance(var, TaskCallbackRequest): @@ -939,8 +927,6 @@ def deserialize(cls, encoded_var: Any) -> Any: return AssetAll(*(decode_asset_condition(x) for x in var["objects"])) elif type_ == DAT.ASSET_REF: return Asset.ref(**var) - elif type_ == DAT.SIMPLE_TASK_INSTANCE: - return SimpleTaskInstance(**cls.deserialize(var)) elif type_ == DAT.CONNECTION: return Connection(**var) elif type_ == DAT.TASK_CALLBACK_REQUEST: diff --git a/airflow-core/src/airflow/serialization/serializers/numpy.py b/airflow-core/src/airflow/serialization/serializers/numpy.py index 603f4df44a44c..1e32f90a081aa 100644 --- a/airflow-core/src/airflow/serialization/serializers/numpy.py +++ b/airflow-core/src/airflow/serialization/serializers/numpy.py @@ -55,28 +55,24 @@ def serialize(o: object) -> tuple[U, str, int, bool]: name = qualname(o) if isinstance( o, - ( - np.int_, - np.intc, - np.intp, - np.int8, - np.int16, - np.int32, - np.int64, - np.uint8, - np.uint16, - np.uint32, - np.uint64, - ), + np.int_ + | np.intc + | np.intp + | np.int8 + | np.int16 + | np.int32 + | np.int64 + | np.uint8 + | np.uint16 + | np.uint32 + | np.uint64, ): return int(o), name, __version__, True if isinstance(o, np.bool_): - return bool(np), name, __version__, True + return bool(o), name, __version__, True - if isinstance( - o, (np.float_, np.float16, np.float32, np.float64, np.complex_, np.complex64, np.complex128) - ): + if isinstance(o, (np.float16, np.float32, np.float64, np.complex64, np.complex128)): return float(o), name, __version__, True return "", "", 0, False diff --git a/airflow-core/src/airflow/settings.py b/airflow-core/src/airflow/settings.py index 08d7ac7af5ba7..689ce2e4e6819 100644 --- a/airflow-core/src/airflow/settings.py +++ b/airflow-core/src/airflow/settings.py @@ -25,8 +25,9 @@ import platform import sys import warnings +from collections.abc import Callable from importlib import metadata -from typing import TYPE_CHECKING, Any, Callable +from typing import TYPE_CHECKING, Any import pluggy from packaging.version import Version diff --git a/airflow-core/src/airflow/stats.py b/airflow-core/src/airflow/stats.py index 569bce480653c..6cb9229ab7388 100644 --- a/airflow-core/src/airflow/stats.py +++ b/airflow-core/src/airflow/stats.py @@ -19,7 +19,8 @@ import logging import socket -from typing import TYPE_CHECKING, Callable +from collections.abc import Callable +from typing import TYPE_CHECKING from airflow.configuration import conf from airflow.metrics.base_stats_logger import NoStatsLogger diff --git a/airflow-core/src/airflow/timetables/interval.py b/airflow-core/src/airflow/timetables/interval.py index f0de30e76de6e..7e68b9a01e624 100644 --- a/airflow-core/src/airflow/timetables/interval.py +++ b/airflow-core/src/airflow/timetables/interval.py @@ -17,7 +17,7 @@ from __future__ import annotations import datetime -from typing import TYPE_CHECKING, Any, Union +from typing import TYPE_CHECKING, Any from dateutil.relativedelta import relativedelta from pendulum import DateTime @@ -30,7 +30,7 @@ if TYPE_CHECKING: from airflow.timetables.base import TimeRestriction -Delta = Union[datetime.timedelta, relativedelta] +Delta = datetime.timedelta | relativedelta class _DataIntervalTimetable(Timetable): diff --git a/airflow-core/src/airflow/traces/otel_tracer.py b/airflow-core/src/airflow/traces/otel_tracer.py index d5e71e3f47e05..34ee543a56d6a 100644 --- a/airflow-core/src/airflow/traces/otel_tracer.py +++ b/airflow-core/src/airflow/traces/otel_tracer.py @@ -19,6 +19,7 @@ import logging import random +from contextlib import AbstractContextManager from typing import TYPE_CHECKING from opentelemetry import trace @@ -247,7 +248,7 @@ def _new_span( links=None, start_time=None, start_as_current: bool = True, - ): + ) -> AbstractContextManager[trace.span.Span] | trace.span.Span: if component is None: component = self.otel_service @@ -260,24 +261,24 @@ def _new_span( links = [] if start_as_current: - span = tracer.start_as_current_span( - name=span_name, - context=parent_context, - links=links, - start_time=datetime_to_nano(start_time), - ) - else: - span = tracer.start_span( + return tracer.start_as_current_span( name=span_name, context=parent_context, links=links, start_time=datetime_to_nano(start_time), ) - current_span_ctx = trace.set_span_in_context(NonRecordingSpan(span.get_span_context())) - # We have to manually make the span context as the active context. - # If the span needs to be injected into the carrier, then this is needed to make sure - # that the injected context will point to the span context that was just created. - attach(current_span_ctx) + + span = tracer.start_span( + name=span_name, + context=parent_context, + links=links, + start_time=datetime_to_nano(start_time), + ) + current_span_ctx = trace.set_span_in_context(NonRecordingSpan(span.get_span_context())) + # We have to manually make the span context as the active context. + # If the span needs to be injected into the carrier, then this is needed to make sure + # that the injected context will point to the span context that was just created. + attach(current_span_ctx) return span def inject(self) -> dict: diff --git a/airflow-core/src/airflow/traces/tracer.py b/airflow-core/src/airflow/traces/tracer.py index 45ed924deda85..7ac1ea3abeaab 100644 --- a/airflow-core/src/airflow/traces/tracer.py +++ b/airflow-core/src/airflow/traces/tracer.py @@ -19,8 +19,9 @@ import logging import socket +from collections.abc import Callable from functools import wraps -from typing import TYPE_CHECKING, Any, Callable, Protocol +from typing import TYPE_CHECKING, Any, Protocol from airflow.configuration import conf diff --git a/airflow-core/src/airflow/triggers/base.py b/airflow-core/src/airflow/triggers/base.py index 2dfe6880786f6..490423da5fda2 100644 --- a/airflow-core/src/airflow/triggers/base.py +++ b/airflow-core/src/airflow/triggers/base.py @@ -21,7 +21,7 @@ from collections.abc import AsyncIterator from dataclasses import dataclass from datetime import timedelta -from typing import Annotated, Any, Union +from typing import Annotated, Any import structlog from pydantic import ( @@ -229,11 +229,9 @@ def trigger_event_discriminator(v): DiscrimatedTriggerEvent = Annotated[ - Union[ - Annotated[TriggerEvent, Tag("_event_")], - Annotated[TaskSuccessEvent, Tag(TaskInstanceState.SUCCESS)], - Annotated[TaskFailedEvent, Tag(TaskInstanceState.FAILED)], - Annotated[TaskSkippedEvent, Tag(TaskInstanceState.SKIPPED)], - ], + Annotated[TriggerEvent, Tag("_event_")] + | Annotated[TaskSuccessEvent, Tag(TaskInstanceState.SUCCESS)] + | Annotated[TaskFailedEvent, Tag(TaskInstanceState.FAILED)] + | Annotated[TaskSkippedEvent, Tag(TaskInstanceState.SKIPPED)], Discriminator(trigger_event_discriminator), ] diff --git a/airflow-core/src/airflow/typing_compat.py b/airflow-core/src/airflow/typing_compat.py index 91a37ae020fec..283537e7e07b4 100644 --- a/airflow-core/src/airflow/typing_compat.py +++ b/airflow-core/src/airflow/typing_compat.py @@ -37,12 +37,9 @@ if sys.version_info >= (3, 10, 1) or (3, 9, 8) <= sys.version_info < (3, 10): from typing import Literal else: - from typing_extensions import Literal # type: ignore[assignment] + from typing import Literal # type: ignore[assignment] -if sys.version_info >= (3, 10): - from typing import ParamSpec, TypeAlias, TypeGuard -else: - from typing_extensions import ParamSpec, TypeAlias, TypeGuard +from typing import ParamSpec, TypeAlias, TypeGuard if sys.version_info >= (3, 11): from typing import Self diff --git a/airflow-core/src/airflow/ui/.prettierignore b/airflow-core/src/airflow/ui/.prettierignore index f013813d71866..b90ad27ecef3d 100644 --- a/airflow-core/src/airflow/ui/.prettierignore +++ b/airflow-core/src/airflow/ui/.prettierignore @@ -5,5 +5,5 @@ dist/ *.yaml coverage/* .pnpm-store -src/i18n/locales/* +public/i18n/locales/* openapi-gen/ diff --git a/airflow-core/src/airflow/ui/CONTRIBUTING.md b/airflow-core/src/airflow/ui/CONTRIBUTING.md index 43f5ac043be42..a7a2ae9831e1d 100644 --- a/airflow-core/src/airflow/ui/CONTRIBUTING.md +++ b/airflow-core/src/airflow/ui/CONTRIBUTING.md @@ -26,7 +26,7 @@ With Breeze: Manually: -- Have the `dev-mode` environment variable enabled +- Have the `DEV_MODE` environment variable set to `true` when starting airflow api-server - Run `pnpm install && pnpm dev` - Note: Make sure to access the UI via the Airflow localhost port (8080 or 28080) and not the vite port (5173) diff --git a/airflow-core/src/airflow/ui/eslint.config.js b/airflow-core/src/airflow/ui/eslint.config.js index e9edfa5ace783..c7d2363724a95 100644 --- a/airflow-core/src/airflow/ui/eslint.config.js +++ b/airflow-core/src/airflow/ui/eslint.config.js @@ -23,6 +23,7 @@ import { coreRules } from "./rules/core.js"; import { i18nRules } from "./rules/i18n.js"; import { i18nextRules } from "./rules/i18next.js"; +import { jsoncRules } from "./rules/jsonc.js"; import { perfectionistRules } from "./rules/perfectionist.js"; import { prettierRules } from "./rules/prettier.js"; import { reactRules } from "./rules/react.js"; @@ -36,7 +37,7 @@ import { unicornRules } from "./rules/unicorn.js"; */ export default /** @type {const} @satisfies {ReadonlyArray} */ ([ // Global ignore of dist directory - { ignores: ["**/dist/", "**coverage/"] }, + { ignores: ["**/dist/", "**coverage/", "**/openapi-gen/"] }, // Base rules coreRules, typescriptRules, @@ -48,4 +49,5 @@ export default /** @type {const} @satisfies {ReadonlyArray} * unicornRules, i18nextRules, i18nRules, + jsoncRules, ]); diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts index 4c187c5575a21..d538e3e617596 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts @@ -669,6 +669,41 @@ export const UseGridServiceGridDataKeyFn = ({ dagId, includeDownstream, includeU runType?: string[]; state?: string[]; }, queryKey?: Array) => [useGridServiceGridDataKey, ...(queryKey ?? [{ dagId, includeDownstream, includeUpstream, limit, logicalDateGte, logicalDateLte, offset, orderBy, root, runAfterGte, runAfterLte, runType, state }])]; +export type GridServiceGetDagStructureDefaultResponse = Awaited>; +export type GridServiceGetDagStructureQueryResult = UseQueryResult; +export const useGridServiceGetDagStructureKey = "GridServiceGetDagStructure"; +export const UseGridServiceGetDagStructureKeyFn = ({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }: { + dagId: string; + limit?: number; + offset?: number; + orderBy?: string; + runAfterGte?: string; + runAfterLte?: string; +}, queryKey?: Array) => [useGridServiceGetDagStructureKey, ...(queryKey ?? [{ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }])]; +export type GridServiceGetGridRunsDefaultResponse = Awaited>; +export type GridServiceGetGridRunsQueryResult = UseQueryResult; +export const useGridServiceGetGridRunsKey = "GridServiceGetGridRuns"; +export const UseGridServiceGetGridRunsKeyFn = ({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }: { + dagId: string; + limit?: number; + offset?: number; + orderBy?: string; + runAfterGte?: string; + runAfterLte?: string; +}, queryKey?: Array) => [useGridServiceGetGridRunsKey, ...(queryKey ?? [{ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }])]; +export type GridServiceGetGridTiSummariesDefaultResponse = Awaited>; +export type GridServiceGetGridTiSummariesQueryResult = UseQueryResult; +export const useGridServiceGetGridTiSummariesKey = "GridServiceGetGridTiSummaries"; +export const UseGridServiceGetGridTiSummariesKeyFn = ({ dagId, runId }: { + dagId: string; + runId: string; +}, queryKey?: Array) => [useGridServiceGetGridTiSummariesKey, ...(queryKey ?? [{ dagId, runId }])]; +export type GridServiceGetLatestRunDefaultResponse = Awaited>; +export type GridServiceGetLatestRunQueryResult = UseQueryResult; +export const useGridServiceGetLatestRunKey = "GridServiceGetLatestRun"; +export const UseGridServiceGetLatestRunKeyFn = ({ dagId }: { + dagId: string; +}, queryKey?: Array) => [useGridServiceGetLatestRunKey, ...(queryKey ?? [{ dagId }])]; export type AssetServiceCreateAssetEventMutationResult = Awaited>; export type AssetServiceMaterializeAssetMutationResult = Awaited>; export type BackfillServiceCreateBackfillMutationResult = Awaited>; diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts index a82b28a403ac2..5ba5f5f3620c7 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts @@ -1259,3 +1259,82 @@ export const ensureUseGridServiceGridDataData = (queryClient: QueryClient, { dag runType?: string[]; state?: string[]; }) => queryClient.ensureQueryData({ queryKey: Common.UseGridServiceGridDataKeyFn({ dagId, includeDownstream, includeUpstream, limit, logicalDateGte, logicalDateLte, offset, orderBy, root, runAfterGte, runAfterLte, runType, state }), queryFn: () => GridService.gridData({ dagId, includeDownstream, includeUpstream, limit, logicalDateGte, logicalDateLte, offset, orderBy, root, runAfterGte, runAfterLte, runType, state }) }); +/** +* Get Dag Structure +* Return dag structure for grid view. +* @param data The data for the request. +* @param data.dagId +* @param data.offset +* @param data.limit +* @param data.orderBy +* @param data.runAfterGte +* @param data.runAfterLte +* @returns GridNodeResponse Successful Response +* @throws ApiError +*/ +export const ensureUseGridServiceGetDagStructureData = (queryClient: QueryClient, { dagId, limit, offset, orderBy, runAfterGte, runAfterLte }: { + dagId: string; + limit?: number; + offset?: number; + orderBy?: string; + runAfterGte?: string; + runAfterLte?: string; +}) => queryClient.ensureQueryData({ queryKey: Common.UseGridServiceGetDagStructureKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }), queryFn: () => GridService.getDagStructure({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) }); +/** +* Get Grid Runs +* Get info about a run for the grid. +* @param data The data for the request. +* @param data.dagId +* @param data.offset +* @param data.limit +* @param data.orderBy +* @param data.runAfterGte +* @param data.runAfterLte +* @returns GridRunsResponse Successful Response +* @throws ApiError +*/ +export const ensureUseGridServiceGetGridRunsData = (queryClient: QueryClient, { dagId, limit, offset, orderBy, runAfterGte, runAfterLte }: { + dagId: string; + limit?: number; + offset?: number; + orderBy?: string; + runAfterGte?: string; + runAfterLte?: string; +}) => queryClient.ensureQueryData({ queryKey: Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }), queryFn: () => GridService.getGridRuns({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) }); +/** +* Get Grid Ti Summaries +* Get states for TIs / "groups" of TIs. +* +* Essentially this is to know what color to put in the squares in the grid. +* +* The tricky part here is that we aggregate the state for groups and mapped tasks. +* +* We don't add all the TIs for mapped TIs -- we only add one entry for the mapped task and +* its state is an aggregate of its TI states. +* +* And for task groups, we add a "task" for that which is not really a task but is just +* an entry that represents the group (so that we can show a filled in box when the group +* is not expanded) and its state is an agg of those within it. +* @param data The data for the request. +* @param data.dagId +* @param data.runId +* @returns GridTISummaries Successful Response +* @throws ApiError +*/ +export const ensureUseGridServiceGetGridTiSummariesData = (queryClient: QueryClient, { dagId, runId }: { + dagId: string; + runId: string; +}) => queryClient.ensureQueryData({ queryKey: Common.UseGridServiceGetGridTiSummariesKeyFn({ dagId, runId }), queryFn: () => GridService.getGridTiSummaries({ dagId, runId }) }); +/** +* Get Latest Run +* Get information about the latest dag run by run_after. +* +* This is used by the UI to figure out if it needs to rerun queries and resume auto refresh. +* @param data The data for the request. +* @param data.dagId +* @returns unknown Successful Response +* @throws ApiError +*/ +export const ensureUseGridServiceGetLatestRunData = (queryClient: QueryClient, { dagId }: { + dagId: string; +}) => queryClient.ensureQueryData({ queryKey: Common.UseGridServiceGetLatestRunKeyFn({ dagId }), queryFn: () => GridService.getLatestRun({ dagId }) }); diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts index 041d8282ecf64..f878624e22eb4 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts @@ -1259,3 +1259,82 @@ export const prefetchUseGridServiceGridData = (queryClient: QueryClient, { dagId runType?: string[]; state?: string[]; }) => queryClient.prefetchQuery({ queryKey: Common.UseGridServiceGridDataKeyFn({ dagId, includeDownstream, includeUpstream, limit, logicalDateGte, logicalDateLte, offset, orderBy, root, runAfterGte, runAfterLte, runType, state }), queryFn: () => GridService.gridData({ dagId, includeDownstream, includeUpstream, limit, logicalDateGte, logicalDateLte, offset, orderBy, root, runAfterGte, runAfterLte, runType, state }) }); +/** +* Get Dag Structure +* Return dag structure for grid view. +* @param data The data for the request. +* @param data.dagId +* @param data.offset +* @param data.limit +* @param data.orderBy +* @param data.runAfterGte +* @param data.runAfterLte +* @returns GridNodeResponse Successful Response +* @throws ApiError +*/ +export const prefetchUseGridServiceGetDagStructure = (queryClient: QueryClient, { dagId, limit, offset, orderBy, runAfterGte, runAfterLte }: { + dagId: string; + limit?: number; + offset?: number; + orderBy?: string; + runAfterGte?: string; + runAfterLte?: string; +}) => queryClient.prefetchQuery({ queryKey: Common.UseGridServiceGetDagStructureKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }), queryFn: () => GridService.getDagStructure({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) }); +/** +* Get Grid Runs +* Get info about a run for the grid. +* @param data The data for the request. +* @param data.dagId +* @param data.offset +* @param data.limit +* @param data.orderBy +* @param data.runAfterGte +* @param data.runAfterLte +* @returns GridRunsResponse Successful Response +* @throws ApiError +*/ +export const prefetchUseGridServiceGetGridRuns = (queryClient: QueryClient, { dagId, limit, offset, orderBy, runAfterGte, runAfterLte }: { + dagId: string; + limit?: number; + offset?: number; + orderBy?: string; + runAfterGte?: string; + runAfterLte?: string; +}) => queryClient.prefetchQuery({ queryKey: Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }), queryFn: () => GridService.getGridRuns({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) }); +/** +* Get Grid Ti Summaries +* Get states for TIs / "groups" of TIs. +* +* Essentially this is to know what color to put in the squares in the grid. +* +* The tricky part here is that we aggregate the state for groups and mapped tasks. +* +* We don't add all the TIs for mapped TIs -- we only add one entry for the mapped task and +* its state is an aggregate of its TI states. +* +* And for task groups, we add a "task" for that which is not really a task but is just +* an entry that represents the group (so that we can show a filled in box when the group +* is not expanded) and its state is an agg of those within it. +* @param data The data for the request. +* @param data.dagId +* @param data.runId +* @returns GridTISummaries Successful Response +* @throws ApiError +*/ +export const prefetchUseGridServiceGetGridTiSummaries = (queryClient: QueryClient, { dagId, runId }: { + dagId: string; + runId: string; +}) => queryClient.prefetchQuery({ queryKey: Common.UseGridServiceGetGridTiSummariesKeyFn({ dagId, runId }), queryFn: () => GridService.getGridTiSummaries({ dagId, runId }) }); +/** +* Get Latest Run +* Get information about the latest dag run by run_after. +* +* This is used by the UI to figure out if it needs to rerun queries and resume auto refresh. +* @param data The data for the request. +* @param data.dagId +* @returns unknown Successful Response +* @throws ApiError +*/ +export const prefetchUseGridServiceGetLatestRun = (queryClient: QueryClient, { dagId }: { + dagId: string; +}) => queryClient.prefetchQuery({ queryKey: Common.UseGridServiceGetLatestRunKeyFn({ dagId }), queryFn: () => GridService.getLatestRun({ dagId }) }); diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts index ca8a496c167e7..3e3ba37467f1c 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts @@ -1260,6 +1260,85 @@ export const useGridServiceGridData = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseGridServiceGridDataKeyFn({ dagId, includeDownstream, includeUpstream, limit, logicalDateGte, logicalDateLte, offset, orderBy, root, runAfterGte, runAfterLte, runType, state }, queryKey), queryFn: () => GridService.gridData({ dagId, includeDownstream, includeUpstream, limit, logicalDateGte, logicalDateLte, offset, orderBy, root, runAfterGte, runAfterLte, runType, state }) as TData, ...options }); /** +* Get Dag Structure +* Return dag structure for grid view. +* @param data The data for the request. +* @param data.dagId +* @param data.offset +* @param data.limit +* @param data.orderBy +* @param data.runAfterGte +* @param data.runAfterLte +* @returns GridNodeResponse Successful Response +* @throws ApiError +*/ +export const useGridServiceGetDagStructure = = unknown[]>({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }: { + dagId: string; + limit?: number; + offset?: number; + orderBy?: string; + runAfterGte?: string; + runAfterLte?: string; +}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseGridServiceGetDagStructureKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }, queryKey), queryFn: () => GridService.getDagStructure({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) as TData, ...options }); +/** +* Get Grid Runs +* Get info about a run for the grid. +* @param data The data for the request. +* @param data.dagId +* @param data.offset +* @param data.limit +* @param data.orderBy +* @param data.runAfterGte +* @param data.runAfterLte +* @returns GridRunsResponse Successful Response +* @throws ApiError +*/ +export const useGridServiceGetGridRuns = = unknown[]>({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }: { + dagId: string; + limit?: number; + offset?: number; + orderBy?: string; + runAfterGte?: string; + runAfterLte?: string; +}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }, queryKey), queryFn: () => GridService.getGridRuns({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) as TData, ...options }); +/** +* Get Grid Ti Summaries +* Get states for TIs / "groups" of TIs. +* +* Essentially this is to know what color to put in the squares in the grid. +* +* The tricky part here is that we aggregate the state for groups and mapped tasks. +* +* We don't add all the TIs for mapped TIs -- we only add one entry for the mapped task and +* its state is an aggregate of its TI states. +* +* And for task groups, we add a "task" for that which is not really a task but is just +* an entry that represents the group (so that we can show a filled in box when the group +* is not expanded) and its state is an agg of those within it. +* @param data The data for the request. +* @param data.dagId +* @param data.runId +* @returns GridTISummaries Successful Response +* @throws ApiError +*/ +export const useGridServiceGetGridTiSummaries = = unknown[]>({ dagId, runId }: { + dagId: string; + runId: string; +}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseGridServiceGetGridTiSummariesKeyFn({ dagId, runId }, queryKey), queryFn: () => GridService.getGridTiSummaries({ dagId, runId }) as TData, ...options }); +/** +* Get Latest Run +* Get information about the latest dag run by run_after. +* +* This is used by the UI to figure out if it needs to rerun queries and resume auto refresh. +* @param data The data for the request. +* @param data.dagId +* @returns unknown Successful Response +* @throws ApiError +*/ +export const useGridServiceGetLatestRun = = unknown[]>({ dagId }: { + dagId: string; +}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseGridServiceGetLatestRunKeyFn({ dagId }, queryKey), queryFn: () => GridService.getLatestRun({ dagId }) as TData, ...options }); +/** * Create Asset Event * Create asset events. * @param data The data for the request. diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts index 17e46fa8bb18f..2ebe843edb37e 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts @@ -1259,3 +1259,82 @@ export const useGridServiceGridDataSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseGridServiceGridDataKeyFn({ dagId, includeDownstream, includeUpstream, limit, logicalDateGte, logicalDateLte, offset, orderBy, root, runAfterGte, runAfterLte, runType, state }, queryKey), queryFn: () => GridService.gridData({ dagId, includeDownstream, includeUpstream, limit, logicalDateGte, logicalDateLte, offset, orderBy, root, runAfterGte, runAfterLte, runType, state }) as TData, ...options }); +/** +* Get Dag Structure +* Return dag structure for grid view. +* @param data The data for the request. +* @param data.dagId +* @param data.offset +* @param data.limit +* @param data.orderBy +* @param data.runAfterGte +* @param data.runAfterLte +* @returns GridNodeResponse Successful Response +* @throws ApiError +*/ +export const useGridServiceGetDagStructureSuspense = = unknown[]>({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }: { + dagId: string; + limit?: number; + offset?: number; + orderBy?: string; + runAfterGte?: string; + runAfterLte?: string; +}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseGridServiceGetDagStructureKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }, queryKey), queryFn: () => GridService.getDagStructure({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) as TData, ...options }); +/** +* Get Grid Runs +* Get info about a run for the grid. +* @param data The data for the request. +* @param data.dagId +* @param data.offset +* @param data.limit +* @param data.orderBy +* @param data.runAfterGte +* @param data.runAfterLte +* @returns GridRunsResponse Successful Response +* @throws ApiError +*/ +export const useGridServiceGetGridRunsSuspense = = unknown[]>({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }: { + dagId: string; + limit?: number; + offset?: number; + orderBy?: string; + runAfterGte?: string; + runAfterLte?: string; +}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }, queryKey), queryFn: () => GridService.getGridRuns({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) as TData, ...options }); +/** +* Get Grid Ti Summaries +* Get states for TIs / "groups" of TIs. +* +* Essentially this is to know what color to put in the squares in the grid. +* +* The tricky part here is that we aggregate the state for groups and mapped tasks. +* +* We don't add all the TIs for mapped TIs -- we only add one entry for the mapped task and +* its state is an aggregate of its TI states. +* +* And for task groups, we add a "task" for that which is not really a task but is just +* an entry that represents the group (so that we can show a filled in box when the group +* is not expanded) and its state is an agg of those within it. +* @param data The data for the request. +* @param data.dagId +* @param data.runId +* @returns GridTISummaries Successful Response +* @throws ApiError +*/ +export const useGridServiceGetGridTiSummariesSuspense = = unknown[]>({ dagId, runId }: { + dagId: string; + runId: string; +}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseGridServiceGetGridTiSummariesKeyFn({ dagId, runId }, queryKey), queryFn: () => GridService.getGridTiSummaries({ dagId, runId }) as TData, ...options }); +/** +* Get Latest Run +* Get information about the latest dag run by run_after. +* +* This is used by the UI to figure out if it needs to rerun queries and resume auto refresh. +* @param data The data for the request. +* @param data.dagId +* @returns unknown Successful Response +* @throws ApiError +*/ +export const useGridServiceGetLatestRunSuspense = = unknown[]>({ dagId }: { + dagId: string; +}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseGridServiceGetLatestRunKeyFn({ dagId }, queryKey), queryFn: () => GridService.getLatestRun({ dagId }) as TData, ...options }); diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts index 93814056bb09c..ef5a2f6a57ea6 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts @@ -7,14 +7,7 @@ export const $AppBuilderMenuItemResponse = { title: 'Name' }, href: { - anyOf: [ - { - type: 'string' - }, - { - type: 'null' - } - ], + type: 'string', title: 'Href' }, category: { @@ -31,7 +24,7 @@ export const $AppBuilderMenuItemResponse = { }, additionalProperties: true, type: 'object', - required: ['name'], + required: ['name', 'href'], title: 'AppBuilderMenuItemResponse', description: 'Serializer for AppBuilder Menu Item responses.' } as const; @@ -3269,6 +3262,74 @@ export const $ExternalLogUrlResponse = { description: 'Response for the external log URL endpoint.' } as const; +export const $ExternalViewResponse = { + properties: { + name: { + type: 'string', + title: 'Name' + }, + icon: { + anyOf: [ + { + type: 'string' + }, + { + type: 'null' + } + ], + title: 'Icon' + }, + icon_dark_mode: { + anyOf: [ + { + type: 'string' + }, + { + type: 'null' + } + ], + title: 'Icon Dark Mode' + }, + url_route: { + anyOf: [ + { + type: 'string' + }, + { + type: 'null' + } + ], + title: 'Url Route' + }, + category: { + anyOf: [ + { + type: 'string' + }, + { + type: 'null' + } + ], + title: 'Category' + }, + destination: { + type: 'string', + enum: ['nav', 'dag', 'dag_run', 'task', 'task_instance'], + title: 'Destination', + default: 'nav' + }, + href: { + type: 'string', + title: 'Href' + } + }, + additionalProperties: true, + type: 'object', + required: ['name', 'href'], + title: 'ExternalViewResponse', + description: 'Serializer for External View Plugin responses.' +} as const; + export const $ExtraLinkCollectionResponse = { properties: { extra_links: { @@ -3399,58 +3460,6 @@ export const $HealthInfoResponse = { description: 'Health serializer for responses.' } as const; -export const $IFrameViewsResponse = { - properties: { - name: { - type: 'string', - title: 'Name' - }, - src: { - type: 'string', - title: 'Src' - }, - icon: { - anyOf: [ - { - type: 'string' - }, - { - type: 'null' - } - ], - title: 'Icon' - }, - url_route: { - anyOf: [ - { - type: 'string' - }, - { - type: 'null' - } - ], - title: 'Url Route' - }, - destination: { - anyOf: [ - { - type: 'string', - enum: ['nav', 'dag', 'dag_run', 'task', 'task_instance'] - }, - { - type: 'null' - } - ], - title: 'Destination' - } - }, - additionalProperties: true, - type: 'object', - required: ['name', 'src'], - title: 'IFrameViewsResponse', - description: 'Serializer for IFrame Plugin responses.' -} as const; - export const $ImportErrorCollectionResponse = { properties: { import_errors: { @@ -3830,12 +3839,20 @@ export const $PluginResponse = { type: 'array', title: 'Fastapi Root Middlewares' }, - iframe_views: { + external_views: { + items: { + '$ref': '#/components/schemas/ExternalViewResponse' + }, + type: 'array', + title: 'External Views', + description: "Aggregate all external views. Both 'external_views' and 'appbuilder_menu_items' are included here." + }, + react_apps: { items: { - '$ref': '#/components/schemas/IFrameViewsResponse' + '$ref': '#/components/schemas/ReactAppResponse' }, type: 'array', - title: 'Iframe Views' + title: 'React Apps' }, appbuilder_views: { items: { @@ -3849,7 +3866,8 @@ export const $PluginResponse = { '$ref': '#/components/schemas/AppBuilderMenuItemResponse' }, type: 'array', - title: 'Appbuilder Menu Items' + title: 'Appbuilder Menu Items', + deprecated: true }, global_operator_extra_links: { items: { @@ -3885,7 +3903,7 @@ export const $PluginResponse = { } }, type: 'object', - required: ['name', 'macros', 'flask_blueprints', 'fastapi_apps', 'fastapi_root_middlewares', 'iframe_views', 'appbuilder_views', 'appbuilder_menu_items', 'global_operator_extra_links', 'operator_extra_links', 'source', 'listeners', 'timetables'], + required: ['name', 'macros', 'flask_blueprints', 'fastapi_apps', 'fastapi_root_middlewares', 'external_views', 'react_apps', 'appbuilder_views', 'appbuilder_menu_items', 'global_operator_extra_links', 'operator_extra_links', 'source', 'listeners', 'timetables'], title: 'PluginResponse', description: 'Plugin serializer.' } as const; @@ -4141,6 +4159,74 @@ export const $QueuedEventResponse = { description: 'Queued Event serializer for responses..' } as const; +export const $ReactAppResponse = { + properties: { + name: { + type: 'string', + title: 'Name' + }, + icon: { + anyOf: [ + { + type: 'string' + }, + { + type: 'null' + } + ], + title: 'Icon' + }, + icon_dark_mode: { + anyOf: [ + { + type: 'string' + }, + { + type: 'null' + } + ], + title: 'Icon Dark Mode' + }, + url_route: { + anyOf: [ + { + type: 'string' + }, + { + type: 'null' + } + ], + title: 'Url Route' + }, + category: { + anyOf: [ + { + type: 'string' + }, + { + type: 'null' + } + ], + title: 'Category' + }, + destination: { + type: 'string', + enum: ['nav', 'dag', 'dag_run', 'task', 'task_instance'], + title: 'Destination', + default: 'nav' + }, + bundle_url: { + type: 'string', + title: 'Bundle Url' + } + }, + additionalProperties: true, + type: 'object', + required: ['name', 'bundle_url'], + title: 'ReactAppResponse', + description: 'Serializer for React App Plugin responses.' +} as const; + export const $ReprocessBehavior = { type: 'string', enum: ['failed', 'completed', 'none'], @@ -6721,6 +6807,60 @@ export const $GridDAGRunwithTIs = { description: 'DAG Run model for the Grid UI.' } as const; +export const $GridNodeResponse = { + properties: { + id: { + type: 'string', + title: 'Id' + }, + label: { + type: 'string', + title: 'Label' + }, + children: { + anyOf: [ + { + items: { + '$ref': '#/components/schemas/GridNodeResponse' + }, + type: 'array' + }, + { + type: 'null' + } + ], + title: 'Children' + }, + is_mapped: { + anyOf: [ + { + type: 'boolean' + }, + { + type: 'null' + } + ], + title: 'Is Mapped' + }, + setup_teardown_type: { + anyOf: [ + { + type: 'string', + enum: ['setup', 'teardown'] + }, + { + type: 'null' + } + ], + title: 'Setup Teardown Type' + } + }, + type: 'object', + required: ['id', 'label', 'is_mapped'], + title: 'GridNodeResponse', + description: 'Base Node serializer for responses.' +} as const; + export const $GridResponse = { properties: { dag_runs: { @@ -6729,17 +6869,121 @@ export const $GridResponse = { }, type: 'array', title: 'Dag Runs' - }, - structure: { - '$ref': '#/components/schemas/StructureDataResponse' } }, type: 'object', - required: ['dag_runs', 'structure'], + required: ['dag_runs'], title: 'GridResponse', description: 'Response model for the Grid UI.' } as const; +export const $GridRunsResponse = { + properties: { + dag_id: { + type: 'string', + title: 'Dag Id' + }, + run_id: { + type: 'string', + title: 'Run Id' + }, + queued_at: { + anyOf: [ + { + type: 'string', + format: 'date-time' + }, + { + type: 'null' + } + ], + title: 'Queued At' + }, + start_date: { + anyOf: [ + { + type: 'string', + format: 'date-time' + }, + { + type: 'null' + } + ], + title: 'Start Date' + }, + end_date: { + anyOf: [ + { + type: 'string', + format: 'date-time' + }, + { + type: 'null' + } + ], + title: 'End Date' + }, + run_after: { + type: 'string', + format: 'date-time', + title: 'Run After' + }, + state: { + anyOf: [ + { + '$ref': '#/components/schemas/TaskInstanceState' + }, + { + type: 'null' + } + ] + }, + run_type: { + '$ref': '#/components/schemas/DagRunType' + }, + duration: { + anyOf: [ + { + type: 'integer' + }, + { + type: 'null' + } + ], + title: 'Duration', + readOnly: true + } + }, + type: 'object', + required: ['dag_id', 'run_id', 'queued_at', 'start_date', 'end_date', 'run_after', 'state', 'run_type', 'duration'], + title: 'GridRunsResponse', + description: 'Base Node serializer for responses.' +} as const; + +export const $GridTISummaries = { + properties: { + run_id: { + type: 'string', + title: 'Run Id' + }, + dag_id: { + type: 'string', + title: 'Dag Id' + }, + task_instances: { + items: { + '$ref': '#/components/schemas/LightGridTaskInstanceSummary' + }, + type: 'array', + title: 'Task Instances' + } + }, + type: 'object', + required: ['run_id', 'dag_id', 'task_instances'], + title: 'GridTISummaries', + description: 'DAG Run model for the Grid UI.' +} as const; + export const $GridTaskInstanceSummary = { properties: { task_id: { @@ -6850,6 +7094,55 @@ export const $HistoricalMetricDataResponse = { description: 'Historical Metric Data serializer for responses.' } as const; +export const $LatestRunResponse = { + properties: { + id: { + type: 'integer', + title: 'Id' + }, + dag_id: { + type: 'string', + title: 'Dag Id' + }, + run_id: { + type: 'string', + title: 'Run Id' + }, + run_after: { + type: 'string', + format: 'date-time', + title: 'Run After' + } + }, + type: 'object', + required: ['id', 'dag_id', 'run_id', 'run_after'], + title: 'LatestRunResponse', + description: 'Base Node serializer for responses.' +} as const; + +export const $LightGridTaskInstanceSummary = { + properties: { + task_id: { + type: 'string', + title: 'Task Id' + }, + state: { + anyOf: [ + { + '$ref': '#/components/schemas/TaskInstanceState' + }, + { + type: 'null' + } + ] + } + }, + type: 'object', + required: ['task_id', 'state'], + title: 'LightGridTaskInstanceSummary', + description: 'Task Instance Summary model for the Grid UI.' +} as const; + export const $MenuItem = { type: 'string', enum: ['Assets', 'Audit Log', 'Config', 'Connections', 'Dags', 'Docs', 'Plugins', 'Pools', 'Providers', 'Variables', 'XComs'], diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts index 08ae1f9bb0052..02acbbca34361 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts @@ -3,7 +3,7 @@ import type { CancelablePromise } from './core/CancelablePromise'; import { OpenAPI } from './core/OpenAPI'; import { request as __request } from './core/request'; -import type { GetAssetsData, GetAssetsResponse, GetAssetAliasesData, GetAssetAliasesResponse, GetAssetAliasData, GetAssetAliasResponse, GetAssetEventsData, GetAssetEventsResponse, CreateAssetEventData, CreateAssetEventResponse, MaterializeAssetData, MaterializeAssetResponse, GetAssetQueuedEventsData, GetAssetQueuedEventsResponse, DeleteAssetQueuedEventsData, DeleteAssetQueuedEventsResponse, GetAssetData, GetAssetResponse, GetDagAssetQueuedEventsData, GetDagAssetQueuedEventsResponse, DeleteDagAssetQueuedEventsData, DeleteDagAssetQueuedEventsResponse, GetDagAssetQueuedEventData, GetDagAssetQueuedEventResponse, DeleteDagAssetQueuedEventData, DeleteDagAssetQueuedEventResponse, NextRunAssetsData, NextRunAssetsResponse, ListBackfillsData, ListBackfillsResponse, CreateBackfillData, CreateBackfillResponse, GetBackfillData, GetBackfillResponse, PauseBackfillData, PauseBackfillResponse, UnpauseBackfillData, UnpauseBackfillResponse, CancelBackfillData, CancelBackfillResponse, CreateBackfillDryRunData, CreateBackfillDryRunResponse, ListBackfillsUiData, ListBackfillsUiResponse, DeleteConnectionData, DeleteConnectionResponse, GetConnectionData, GetConnectionResponse, PatchConnectionData, PatchConnectionResponse, GetConnectionsData, GetConnectionsResponse, PostConnectionData, PostConnectionResponse, BulkConnectionsData, BulkConnectionsResponse, TestConnectionData, TestConnectionResponse, CreateDefaultConnectionsResponse, HookMetaDataResponse, GetDagRunData, GetDagRunResponse, DeleteDagRunData, DeleteDagRunResponse, PatchDagRunData, PatchDagRunResponse, GetUpstreamAssetEventsData, GetUpstreamAssetEventsResponse, ClearDagRunData, ClearDagRunResponse, GetDagRunsData, GetDagRunsResponse, TriggerDagRunData, TriggerDagRunResponse, GetListDagRunsBatchData, GetListDagRunsBatchResponse, GetDagSourceData, GetDagSourceResponse, GetDagStatsData, GetDagStatsResponse, GetDagReportsData, GetDagReportsResponse, GetConfigData, GetConfigResponse, GetConfigValueData, GetConfigValueResponse, GetConfigsResponse, ListDagWarningsData, ListDagWarningsResponse, GetDagsData, GetDagsResponse, PatchDagsData, PatchDagsResponse, GetDagData, GetDagResponse, PatchDagData, PatchDagResponse, DeleteDagData, DeleteDagResponse, GetDagDetailsData, GetDagDetailsResponse, GetDagTagsData, GetDagTagsResponse, GetDagsUiData, GetDagsUiResponse, GetEventLogData, GetEventLogResponse, GetEventLogsData, GetEventLogsResponse, GetExtraLinksData, GetExtraLinksResponse, GetTaskInstanceData, GetTaskInstanceResponse, PatchTaskInstanceData, PatchTaskInstanceResponse, DeleteTaskInstanceData, DeleteTaskInstanceResponse, GetMappedTaskInstancesData, GetMappedTaskInstancesResponse, GetTaskInstanceDependenciesByMapIndexData, GetTaskInstanceDependenciesByMapIndexResponse, GetTaskInstanceDependenciesData, GetTaskInstanceDependenciesResponse, GetTaskInstanceTriesData, GetTaskInstanceTriesResponse, GetMappedTaskInstanceTriesData, GetMappedTaskInstanceTriesResponse, GetMappedTaskInstanceData, GetMappedTaskInstanceResponse, PatchTaskInstanceByMapIndexData, PatchTaskInstanceByMapIndexResponse, GetTaskInstancesData, GetTaskInstancesResponse, BulkTaskInstancesData, BulkTaskInstancesResponse, GetTaskInstancesBatchData, GetTaskInstancesBatchResponse, GetTaskInstanceTryDetailsData, GetTaskInstanceTryDetailsResponse, GetMappedTaskInstanceTryDetailsData, GetMappedTaskInstanceTryDetailsResponse, PostClearTaskInstancesData, PostClearTaskInstancesResponse, PatchTaskInstanceDryRunByMapIndexData, PatchTaskInstanceDryRunByMapIndexResponse, PatchTaskInstanceDryRunData, PatchTaskInstanceDryRunResponse, GetLogData, GetLogResponse, GetExternalLogUrlData, GetExternalLogUrlResponse, GetImportErrorData, GetImportErrorResponse, GetImportErrorsData, GetImportErrorsResponse, GetJobsData, GetJobsResponse, GetPluginsData, GetPluginsResponse, ImportErrorsResponse, DeletePoolData, DeletePoolResponse, GetPoolData, GetPoolResponse, PatchPoolData, PatchPoolResponse, GetPoolsData, GetPoolsResponse, PostPoolData, PostPoolResponse, BulkPoolsData, BulkPoolsResponse, GetProvidersData, GetProvidersResponse, GetXcomEntryData, GetXcomEntryResponse, UpdateXcomEntryData, UpdateXcomEntryResponse, GetXcomEntriesData, GetXcomEntriesResponse, CreateXcomEntryData, CreateXcomEntryResponse, GetTasksData, GetTasksResponse, GetTaskData, GetTaskResponse, DeleteVariableData, DeleteVariableResponse, GetVariableData, GetVariableResponse, PatchVariableData, PatchVariableResponse, GetVariablesData, GetVariablesResponse, PostVariableData, PostVariableResponse, BulkVariablesData, BulkVariablesResponse, ReparseDagFileData, ReparseDagFileResponse, GetDagVersionData, GetDagVersionResponse, GetDagVersionsData, GetDagVersionsResponse, GetHealthResponse, GetVersionResponse, LoginData, LoginResponse, LogoutData, LogoutResponse, GetAuthMenusResponse, GetDependenciesData, GetDependenciesResponse, HistoricalMetricsData, HistoricalMetricsResponse, DagStatsResponse2, StructureDataData, StructureDataResponse2, GridDataData, GridDataResponse } from './types.gen'; +import type { GetAssetsData, GetAssetsResponse, GetAssetAliasesData, GetAssetAliasesResponse, GetAssetAliasData, GetAssetAliasResponse, GetAssetEventsData, GetAssetEventsResponse, CreateAssetEventData, CreateAssetEventResponse, MaterializeAssetData, MaterializeAssetResponse, GetAssetQueuedEventsData, GetAssetQueuedEventsResponse, DeleteAssetQueuedEventsData, DeleteAssetQueuedEventsResponse, GetAssetData, GetAssetResponse, GetDagAssetQueuedEventsData, GetDagAssetQueuedEventsResponse, DeleteDagAssetQueuedEventsData, DeleteDagAssetQueuedEventsResponse, GetDagAssetQueuedEventData, GetDagAssetQueuedEventResponse, DeleteDagAssetQueuedEventData, DeleteDagAssetQueuedEventResponse, NextRunAssetsData, NextRunAssetsResponse, ListBackfillsData, ListBackfillsResponse, CreateBackfillData, CreateBackfillResponse, GetBackfillData, GetBackfillResponse, PauseBackfillData, PauseBackfillResponse, UnpauseBackfillData, UnpauseBackfillResponse, CancelBackfillData, CancelBackfillResponse, CreateBackfillDryRunData, CreateBackfillDryRunResponse, ListBackfillsUiData, ListBackfillsUiResponse, DeleteConnectionData, DeleteConnectionResponse, GetConnectionData, GetConnectionResponse, PatchConnectionData, PatchConnectionResponse, GetConnectionsData, GetConnectionsResponse, PostConnectionData, PostConnectionResponse, BulkConnectionsData, BulkConnectionsResponse, TestConnectionData, TestConnectionResponse, CreateDefaultConnectionsResponse, HookMetaDataResponse, GetDagRunData, GetDagRunResponse, DeleteDagRunData, DeleteDagRunResponse, PatchDagRunData, PatchDagRunResponse, GetUpstreamAssetEventsData, GetUpstreamAssetEventsResponse, ClearDagRunData, ClearDagRunResponse, GetDagRunsData, GetDagRunsResponse, TriggerDagRunData, TriggerDagRunResponse, GetListDagRunsBatchData, GetListDagRunsBatchResponse, GetDagSourceData, GetDagSourceResponse, GetDagStatsData, GetDagStatsResponse, GetDagReportsData, GetDagReportsResponse, GetConfigData, GetConfigResponse, GetConfigValueData, GetConfigValueResponse, GetConfigsResponse, ListDagWarningsData, ListDagWarningsResponse, GetDagsData, GetDagsResponse, PatchDagsData, PatchDagsResponse, GetDagData, GetDagResponse, PatchDagData, PatchDagResponse, DeleteDagData, DeleteDagResponse, GetDagDetailsData, GetDagDetailsResponse, GetDagTagsData, GetDagTagsResponse, GetDagsUiData, GetDagsUiResponse, GetEventLogData, GetEventLogResponse, GetEventLogsData, GetEventLogsResponse, GetExtraLinksData, GetExtraLinksResponse, GetTaskInstanceData, GetTaskInstanceResponse, PatchTaskInstanceData, PatchTaskInstanceResponse, DeleteTaskInstanceData, DeleteTaskInstanceResponse, GetMappedTaskInstancesData, GetMappedTaskInstancesResponse, GetTaskInstanceDependenciesByMapIndexData, GetTaskInstanceDependenciesByMapIndexResponse, GetTaskInstanceDependenciesData, GetTaskInstanceDependenciesResponse, GetTaskInstanceTriesData, GetTaskInstanceTriesResponse, GetMappedTaskInstanceTriesData, GetMappedTaskInstanceTriesResponse, GetMappedTaskInstanceData, GetMappedTaskInstanceResponse, PatchTaskInstanceByMapIndexData, PatchTaskInstanceByMapIndexResponse, GetTaskInstancesData, GetTaskInstancesResponse, BulkTaskInstancesData, BulkTaskInstancesResponse, GetTaskInstancesBatchData, GetTaskInstancesBatchResponse, GetTaskInstanceTryDetailsData, GetTaskInstanceTryDetailsResponse, GetMappedTaskInstanceTryDetailsData, GetMappedTaskInstanceTryDetailsResponse, PostClearTaskInstancesData, PostClearTaskInstancesResponse, PatchTaskInstanceDryRunByMapIndexData, PatchTaskInstanceDryRunByMapIndexResponse, PatchTaskInstanceDryRunData, PatchTaskInstanceDryRunResponse, GetLogData, GetLogResponse, GetExternalLogUrlData, GetExternalLogUrlResponse, GetImportErrorData, GetImportErrorResponse, GetImportErrorsData, GetImportErrorsResponse, GetJobsData, GetJobsResponse, GetPluginsData, GetPluginsResponse, ImportErrorsResponse, DeletePoolData, DeletePoolResponse, GetPoolData, GetPoolResponse, PatchPoolData, PatchPoolResponse, GetPoolsData, GetPoolsResponse, PostPoolData, PostPoolResponse, BulkPoolsData, BulkPoolsResponse, GetProvidersData, GetProvidersResponse, GetXcomEntryData, GetXcomEntryResponse, UpdateXcomEntryData, UpdateXcomEntryResponse, GetXcomEntriesData, GetXcomEntriesResponse, CreateXcomEntryData, CreateXcomEntryResponse, GetTasksData, GetTasksResponse, GetTaskData, GetTaskResponse, DeleteVariableData, DeleteVariableResponse, GetVariableData, GetVariableResponse, PatchVariableData, PatchVariableResponse, GetVariablesData, GetVariablesResponse, PostVariableData, PostVariableResponse, BulkVariablesData, BulkVariablesResponse, ReparseDagFileData, ReparseDagFileResponse, GetDagVersionData, GetDagVersionResponse, GetDagVersionsData, GetDagVersionsResponse, GetHealthResponse, GetVersionResponse, LoginData, LoginResponse, LogoutData, LogoutResponse, GetAuthMenusResponse, GetDependenciesData, GetDependenciesResponse, HistoricalMetricsData, HistoricalMetricsResponse, DagStatsResponse2, StructureDataData, StructureDataResponse2, GridDataData, GridDataResponse, GetDagStructureData, GetDagStructureResponse, GetGridRunsData, GetGridRunsResponse, GetGridTiSummariesData, GetGridTiSummariesResponse, GetLatestRunData, GetLatestRunResponse } from './types.gen'; export class AssetService { /** @@ -3481,4 +3481,135 @@ export class GridService { }); } + /** + * Get Dag Structure + * Return dag structure for grid view. + * @param data The data for the request. + * @param data.dagId + * @param data.offset + * @param data.limit + * @param data.orderBy + * @param data.runAfterGte + * @param data.runAfterLte + * @returns GridNodeResponse Successful Response + * @throws ApiError + */ + public static getDagStructure(data: GetDagStructureData): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/ui/grid/structure/{dag_id}', + path: { + dag_id: data.dagId + }, + query: { + offset: data.offset, + limit: data.limit, + order_by: data.orderBy, + run_after_gte: data.runAfterGte, + run_after_lte: data.runAfterLte + }, + errors: { + 400: 'Bad Request', + 404: 'Not Found', + 422: 'Validation Error' + } + }); + } + + /** + * Get Grid Runs + * Get info about a run for the grid. + * @param data The data for the request. + * @param data.dagId + * @param data.offset + * @param data.limit + * @param data.orderBy + * @param data.runAfterGte + * @param data.runAfterLte + * @returns GridRunsResponse Successful Response + * @throws ApiError + */ + public static getGridRuns(data: GetGridRunsData): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/ui/grid/runs/{dag_id}', + path: { + dag_id: data.dagId + }, + query: { + offset: data.offset, + limit: data.limit, + order_by: data.orderBy, + run_after_gte: data.runAfterGte, + run_after_lte: data.runAfterLte + }, + errors: { + 400: 'Bad Request', + 404: 'Not Found', + 422: 'Validation Error' + } + }); + } + + /** + * Get Grid Ti Summaries + * Get states for TIs / "groups" of TIs. + * + * Essentially this is to know what color to put in the squares in the grid. + * + * The tricky part here is that we aggregate the state for groups and mapped tasks. + * + * We don't add all the TIs for mapped TIs -- we only add one entry for the mapped task and + * its state is an aggregate of its TI states. + * + * And for task groups, we add a "task" for that which is not really a task but is just + * an entry that represents the group (so that we can show a filled in box when the group + * is not expanded) and its state is an agg of those within it. + * @param data The data for the request. + * @param data.dagId + * @param data.runId + * @returns GridTISummaries Successful Response + * @throws ApiError + */ + public static getGridTiSummaries(data: GetGridTiSummariesData): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/ui/grid/ti_summaries/{dag_id}/{run_id}', + path: { + dag_id: data.dagId, + run_id: data.runId + }, + errors: { + 400: 'Bad Request', + 404: 'Not Found', + 422: 'Validation Error' + } + }); + } + + /** + * Get Latest Run + * Get information about the latest dag run by run_after. + * + * This is used by the UI to figure out if it needs to rerun queries and resume auto refresh. + * @param data The data for the request. + * @param data.dagId + * @returns unknown Successful Response + * @throws ApiError + */ + public static getLatestRun(data: GetLatestRunData): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/ui/grid/latest_run/{dag_id}', + path: { + dag_id: data.dagId + }, + errors: { + 400: 'Bad Request', + 404: 'Not Found', + 422: 'Validation Error' + } + }); + } + } \ No newline at end of file diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts index 92dee7ed04011..e22e3cb52f714 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts @@ -5,7 +5,7 @@ */ export type AppBuilderMenuItemResponse = { name: string; - href?: string | null; + href: string; category?: string | null; [key: string]: unknown | string; }; @@ -871,6 +871,22 @@ export type ExternalLogUrlResponse = { url: string; }; +/** + * Serializer for External View Plugin responses. + */ +export type ExternalViewResponse = { + name: string; + icon?: string | null; + icon_dark_mode?: string | null; + url_route?: string | null; + category?: string | null; + destination?: 'nav' | 'dag' | 'dag_run' | 'task' | 'task_instance'; + href: string; + [key: string]: unknown | string; +}; + +export type destination = 'nav' | 'dag' | 'dag_run' | 'task' | 'task_instance'; + /** * Extra Links Response. */ @@ -923,18 +939,6 @@ export type HealthInfoResponse = { dag_processor?: DagProcessorInfoResponse | null; }; -/** - * Serializer for IFrame Plugin responses. - */ -export type IFrameViewsResponse = { - name: string; - src: string; - icon?: string | null; - url_route?: string | null; - destination?: 'nav' | 'dag' | 'dag_run' | 'task' | 'task_instance' | null; - [key: string]: unknown | string; -}; - /** * Import Error Collection Response. */ @@ -1034,8 +1038,15 @@ export type PluginResponse = { flask_blueprints: Array<(string)>; fastapi_apps: Array; fastapi_root_middlewares: Array; - iframe_views: Array; + /** + * Aggregate all external views. Both 'external_views' and 'appbuilder_menu_items' are included here. + */ + external_views: Array; + react_apps: Array; appbuilder_views: Array; + /** + * @deprecated + */ appbuilder_menu_items: Array; global_operator_extra_links: Array<(string)>; operator_extra_links: Array<(string)>; @@ -1123,6 +1134,20 @@ export type QueuedEventResponse = { dag_display_name: string; }; +/** + * Serializer for React App Plugin responses. + */ +export type ReactAppResponse = { + name: string; + icon?: string | null; + icon_dark_mode?: string | null; + url_route?: string | null; + category?: string | null; + destination?: 'nav' | 'dag' | 'dag_run' | 'task' | 'task_instance'; + bundle_url: string; + [key: string]: unknown | string; +}; + /** * Internal enum for setting reprocess behavior in a backfill. * @@ -1703,12 +1728,46 @@ export type GridDAGRunwithTIs = { task_instances: Array; }; +/** + * Base Node serializer for responses. + */ +export type GridNodeResponse = { + id: string; + label: string; + children?: Array | null; + is_mapped: boolean | null; + setup_teardown_type?: 'setup' | 'teardown' | null; +}; + /** * Response model for the Grid UI. */ export type GridResponse = { dag_runs: Array; - structure: StructureDataResponse; +}; + +/** + * Base Node serializer for responses. + */ +export type GridRunsResponse = { + dag_id: string; + run_id: string; + queued_at: string | null; + start_date: string | null; + end_date: string | null; + run_after: string; + state: TaskInstanceState | null; + run_type: DagRunType; + readonly duration: number | null; +}; + +/** + * DAG Run model for the Grid UI. + */ +export type GridTISummaries = { + run_id: string; + dag_id: string; + task_instances: Array; }; /** @@ -1737,6 +1796,24 @@ export type HistoricalMetricDataResponse = { task_instance_states: TaskInstanceStateCount; }; +/** + * Base Node serializer for responses. + */ +export type LatestRunResponse = { + id: number; + dag_id: string; + run_id: string; + run_after: string; +}; + +/** + * Task Instance Summary model for the Grid UI. + */ +export type LightGridTaskInstanceSummary = { + task_id: string; + state: TaskInstanceState | null; +}; + /** * Define all menu items defined in the menu. */ @@ -2816,6 +2893,41 @@ export type GridDataData = { export type GridDataResponse = GridResponse; +export type GetDagStructureData = { + dagId: string; + limit?: number; + offset?: number; + orderBy?: string; + runAfterGte?: string | null; + runAfterLte?: string | null; +}; + +export type GetDagStructureResponse = Array; + +export type GetGridRunsData = { + dagId: string; + limit?: number; + offset?: number; + orderBy?: string; + runAfterGte?: string | null; + runAfterLte?: string | null; +}; + +export type GetGridRunsResponse = Array; + +export type GetGridTiSummariesData = { + dagId: string; + runId: string; +}; + +export type GetGridTiSummariesResponse = GridTISummaries; + +export type GetLatestRunData = { + dagId: string; +}; + +export type GetLatestRunResponse = LatestRunResponse | null; + export type $OpenApiTs = { '/api/v2/assets': { get: { @@ -5747,4 +5859,96 @@ export type $OpenApiTs = { }; }; }; + '/ui/grid/structure/{dag_id}': { + get: { + req: GetDagStructureData; + res: { + /** + * Successful Response + */ + 200: Array; + /** + * Bad Request + */ + 400: HTTPExceptionResponse; + /** + * Not Found + */ + 404: HTTPExceptionResponse; + /** + * Validation Error + */ + 422: HTTPValidationError; + }; + }; + }; + '/ui/grid/runs/{dag_id}': { + get: { + req: GetGridRunsData; + res: { + /** + * Successful Response + */ + 200: Array; + /** + * Bad Request + */ + 400: HTTPExceptionResponse; + /** + * Not Found + */ + 404: HTTPExceptionResponse; + /** + * Validation Error + */ + 422: HTTPValidationError; + }; + }; + }; + '/ui/grid/ti_summaries/{dag_id}/{run_id}': { + get: { + req: GetGridTiSummariesData; + res: { + /** + * Successful Response + */ + 200: GridTISummaries; + /** + * Bad Request + */ + 400: HTTPExceptionResponse; + /** + * Not Found + */ + 404: HTTPExceptionResponse; + /** + * Validation Error + */ + 422: HTTPValidationError; + }; + }; + }; + '/ui/grid/latest_run/{dag_id}': { + get: { + req: GetLatestRunData; + res: { + /** + * Successful Response + */ + 200: LatestRunResponse | null; + /** + * Bad Request + */ + 400: HTTPExceptionResponse; + /** + * Not Found + */ + 404: HTTPExceptionResponse; + /** + * Validation Error + */ + 422: HTTPValidationError; + }; + }; + }; }; \ No newline at end of file diff --git a/airflow-core/src/airflow/ui/package.json b/airflow-core/src/airflow/ui/package.json index 7c6871eb433c8..6835f54581f1d 100644 --- a/airflow-core/src/airflow/ui/package.json +++ b/airflow-core/src/airflow/ui/package.json @@ -5,7 +5,7 @@ "type": "module", "homepage": "/ui", "scripts": { - "dev": "vite", + "dev": "vite --port 5173 --strictPort", "build": "vite build", "lint": "eslint --quiet && tsc --p tsconfig.app.json", "lint:fix": "eslint --fix && tsc --p tsconfig.app.json", @@ -39,6 +39,7 @@ "html-to-image": "^1.11.13", "i18next": "^25.1.2", "i18next-browser-languagedetector": "^8.1.0", + "i18next-http-backend": "^3.0.2", "next-themes": "^0.3.0", "react": "^18.3.1", "react-chartjs-2": "^5.3.0", @@ -76,6 +77,7 @@ "eslint": "^9.25.1", "eslint-config-prettier": "^10.1.2", "eslint-plugin-i18next": "^6.1.1", + "eslint-plugin-jsonc": "^2.20.1", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-perfectionist": "^4.12.3", "eslint-plugin-prettier": "^5.2.6", @@ -85,6 +87,7 @@ "eslint-plugin-unicorn": "^55.0.0", "globals": "^15.15.0", "happy-dom": "^17.4.6", + "jsonc-eslint-parser": "^2.4.0", "msw": "^2.7.5", "openapi-merge-cli": "^1.3.2", "prettier": "^3.5.3", diff --git a/airflow-core/src/airflow/ui/pnpm-lock.yaml b/airflow-core/src/airflow/ui/pnpm-lock.yaml index c7b0c7e6eebc2..8e0903acea395 100644 --- a/airflow-core/src/airflow/ui/pnpm-lock.yaml +++ b/airflow-core/src/airflow/ui/pnpm-lock.yaml @@ -77,6 +77,9 @@ importers: i18next-browser-languagedetector: specifier: ^8.1.0 version: 8.1.0 + i18next-http-backend: + specifier: ^3.0.2 + version: 3.0.2 next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -183,6 +186,9 @@ importers: eslint-plugin-i18next: specifier: ^6.1.1 version: 6.1.1 + eslint-plugin-jsonc: + specifier: ^2.20.1 + version: 2.20.1(eslint@9.26.0(jiti@1.21.7)) eslint-plugin-jsx-a11y: specifier: ^6.10.2 version: 6.10.2(eslint@9.26.0(jiti@1.21.7)) @@ -210,6 +216,9 @@ importers: happy-dom: specifier: ^17.4.6 version: 17.4.6 + jsonc-eslint-parser: + specifier: ^2.4.0 + version: 2.4.0 msw: specifier: ^2.7.5 version: 2.7.6(@types/node@22.15.14)(typescript@5.8.3) @@ -2072,6 +2081,9 @@ packages: cross-fetch@3.2.0: resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} + cross-fetch@4.0.0: + resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -2334,16 +2346,39 @@ packages: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} + eslint-compat-utils@0.6.5: + resolution: {integrity: sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + eslint-config-prettier@10.1.2: resolution: {integrity: sha512-Epgp/EofAUeEpIdZkW60MHKvPyru1ruQJxPL+WIycnaPApuseK0Zpkrh/FwL9oIpQvIhJwV7ptOy0DWUjTlCiA==} hasBin: true peerDependencies: eslint: '>=7.0.0' + eslint-json-compat-utils@0.2.1: + resolution: {integrity: sha512-YzEodbDyW8DX8bImKhAcCeu/L31Dd/70Bidx2Qex9OFUtgzXLqtfWL4Hr5fM/aCCB8QUZLuJur0S9k6UfgFkfg==} + engines: {node: '>=12'} + peerDependencies: + '@eslint/json': '*' + eslint: '*' + jsonc-eslint-parser: ^2.4.0 + peerDependenciesMeta: + '@eslint/json': + optional: true + eslint-plugin-i18next@6.1.1: resolution: {integrity: sha512-/Vy6BfX44njxpRnbJm7bbph0KaNJF2eillqN5W+u03hHuxmh9BjtjdPSrI9HPtyoEbG4j5nBn9gXm/dg99mz3Q==} engines: {node: '>=0.10.0'} + eslint-plugin-jsonc@2.20.1: + resolution: {integrity: sha512-gUzIwQHXx7ZPypUoadcyRi4WbHW2TPixDr0kqQ4miuJBU0emJmyGTlnaT3Og9X2a8R1CDayN9BFSq5weGWbTng==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + eslint-plugin-jsx-a11y@6.10.2: resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} engines: {node: '>=4.0'} @@ -2419,6 +2454,10 @@ packages: resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} @@ -2742,6 +2781,9 @@ packages: i18next-browser-languagedetector@8.1.0: resolution: {integrity: sha512-mHZxNx1Lq09xt5kCauZ/4bsXOEA2pfpwSoU11/QTJB+pD94iONFwp+ohqi///PwiFvjFOxe1akYCdHyFo1ng5Q==} + i18next-http-backend@3.0.2: + resolution: {integrity: sha512-PdlvPnvIp4E1sYi46Ik4tBYh/v/NbYfFFgTjkwFl0is8A18s7/bx9aXqsrOax9WUbeNS6mD2oix7Z0yGGf6m5g==} + i18next@25.1.2: resolution: {integrity: sha512-SP63m8LzdjkrAjruH7SCI3ndPSgjt4/wX7ouUUOzCW/eY+HzlIo19IQSfYA9X3qRiRP1SYtaTsg/Oz/PGsfD8w==} peerDependencies: @@ -3013,6 +3055,10 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + jsonc-eslint-parser@2.4.0: + resolution: {integrity: sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + jsonpointer@5.0.1: resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} engines: {node: '>=0.10.0'} @@ -4063,6 +4109,10 @@ packages: resolution: {integrity: sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ==} engines: {node: ^14.18.0 || >=16.0.0} + synckit@0.11.8: + resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==} + engines: {node: ^14.18.0 || >=16.0.0} + tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} @@ -7051,6 +7101,12 @@ snapshots: transitivePeerDependencies: - encoding + cross-fetch@4.0.0: + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -7376,15 +7432,40 @@ snapshots: escape-string-regexp@5.0.0: {} + eslint-compat-utils@0.6.5(eslint@9.26.0(jiti@1.21.7)): + dependencies: + eslint: 9.26.0(jiti@1.21.7) + semver: 7.7.1 + eslint-config-prettier@10.1.2(eslint@9.26.0(jiti@1.21.7)): dependencies: eslint: 9.26.0(jiti@1.21.7) + eslint-json-compat-utils@0.2.1(eslint@9.26.0(jiti@1.21.7))(jsonc-eslint-parser@2.4.0): + dependencies: + eslint: 9.26.0(jiti@1.21.7) + esquery: 1.6.0 + jsonc-eslint-parser: 2.4.0 + eslint-plugin-i18next@6.1.1: dependencies: lodash: 4.17.21 requireindex: 1.1.0 + eslint-plugin-jsonc@2.20.1(eslint@9.26.0(jiti@1.21.7)): + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@1.21.7)) + eslint: 9.26.0(jiti@1.21.7) + eslint-compat-utils: 0.6.5(eslint@9.26.0(jiti@1.21.7)) + eslint-json-compat-utils: 0.2.1(eslint@9.26.0(jiti@1.21.7))(jsonc-eslint-parser@2.4.0) + espree: 10.3.0 + graphemer: 1.4.0 + jsonc-eslint-parser: 2.4.0 + natural-compare: 1.4.0 + synckit: 0.11.8 + transitivePeerDependencies: + - '@eslint/json' + eslint-plugin-jsx-a11y@6.10.2(eslint@9.26.0(jiti@1.21.7)): dependencies: aria-query: 5.3.2 @@ -7532,6 +7613,12 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.14.1) eslint-visitor-keys: 4.2.0 + espree@9.6.1: + dependencies: + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + eslint-visitor-keys: 3.4.3 + esprima@4.0.1: {} esquery@1.6.0: @@ -7919,6 +8006,12 @@ snapshots: dependencies: '@babel/runtime': 7.26.10 + i18next-http-backend@3.0.2: + dependencies: + cross-fetch: 4.0.0 + transitivePeerDependencies: + - encoding + i18next@25.1.2(typescript@5.8.3): dependencies: '@babel/runtime': 7.26.10 @@ -8179,6 +8272,13 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + jsonc-eslint-parser@2.4.0: + dependencies: + acorn: 8.14.1 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + semver: 7.7.1 + jsonpointer@5.0.1: {} jsx-ast-utils@3.3.5: @@ -9568,6 +9668,10 @@ snapshots: '@pkgr/core': 0.2.4 tslib: 2.8.1 + synckit@0.11.8: + dependencies: + '@pkgr/core': 0.2.4 + tar@6.2.1: dependencies: chownr: 2.0.0 diff --git a/airflow-core/src/airflow/ui/src/i18n/README.md b/airflow-core/src/airflow/ui/public/i18n/README.md similarity index 95% rename from airflow-core/src/airflow/ui/src/i18n/README.md rename to airflow-core/src/airflow/ui/public/i18n/README.md index 190ba07fbfdf2..4fa50122cf7a4 100644 --- a/airflow-core/src/airflow/ui/src/i18n/README.md +++ b/airflow-core/src/airflow/ui/public/i18n/README.md @@ -28,7 +28,7 @@ This policy aims to avoid inconsistencies, maintenance issues, unclear ownership This policy applies to: -- Each supported locale included in `airflow-core/src/airflow/ui/src/i18n/locales`. +- Each supported locale included in `airflow-core/src/airflow/ui/public/i18n/locales`. - Contributors making changes in the default locale (English). - Contributors suggesting new locales to be added to the codebase. - Maintainers of supported locales in any role defined below. @@ -42,7 +42,7 @@ This policy applies to: **Internationalization (i18n)** - The process of designing a software application so that it can be adapted to various languages and regions without engineering changes (see also the [Wikipedia article](https://en.wikipedia.org/wiki/Internationalization_and_localization)). -**Supported locale** - An officially accepted locale in `airflow-core/src/airflow/ui/src/i18n/locales`. +**Supported locale** - An officially accepted locale in `airflow-core/src/airflow/ui/public/i18n/locales`. **Default locale** - English (`en`), the primary locale and fallback for all other locales. @@ -175,7 +175,7 @@ Translation conflicts MUST be resolved according to the procedures outlined in s The following steps outline the process for approving a new locale to be added to the supported locales: - Creating a PR for adding the suggested locale to the codebase ([see example](https://github.com/apache/airflow/pull/51258/files)), which includes: - - The locale files (translated according to the guidelines) in the `airflow-core/src/airflow/ui/src/i18n/locales/` directory, where `` is the code of the language according to ISO 639-1 standard (e.g., `fr` for French). Languages with regional variants should be handled in separate directories, where the name is suffixed with `-`, and `` is the variant that follows ISO 3166-1 or UN M.49 codes in lowercase (e.g., `zh-tw` for Taiwanese Mandarin). + - The locale files (translated according to the guidelines) in the `airflow-core/src/airflow/ui/public/i18n/locales/` directory, where `` is the code of the language according to ISO 639-1 standard (e.g., `fr` for French). Languages with regional variants should be handled in separate directories, where the name is suffixed with `-`, and `` is the variant that follows ISO 3166-1 or UN M.49 codes in lowercase (e.g., `zh-tw` for Taiwanese Mandarin). - Making the required modifications in `airflow-core/src/airflow/ui/src/i18n/config.ts` ([see example](https://github.com/apache/airflow/pull/51258/files#diff-bfb4d5fafd26d206fb4a545a41ba303f33d15a479d21e0a726fd743bdf9717ff)). - Changes to the `.github/CODEOWNERS` file to include the designated code owner(s) and translation owner(s) for the new locale, considering the following: - A code owner who is also a translation sponsor should be indicated in a comment as well. @@ -234,13 +234,13 @@ Language proficiency for translation owners can be demonstrated through any of t All files: ```bash -uv run ./check_translations_completeness.py +uv run dev/i18n/check_translations_completeness.py ``` Files for specific languages: ```bash -uv run ./check_translations_completeness.py --language +uv run dev/i18n/check_translations_completeness.py --language ``` Where `` is the code of the language you want to check, e.g., `en`, `fr`, `de`, etc. @@ -248,7 +248,7 @@ Where `` is the code of the language you want to check, e.g., `en Adding missing translations (with `TODO: translate` prefix): ```bash -uv run ./check_translations_completeness.py --language --add-missing +uv run dev/i18n/check_translations_completeness.py --language --add-missing ``` ## 9. Compliance & enforcement diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/ar/admin.json b/airflow-core/src/airflow/ui/public/i18n/locales/ar/admin.json similarity index 54% rename from airflow-core/src/airflow/ui/src/i18n/locales/ar/admin.json rename to airflow-core/src/airflow/ui/public/i18n/locales/ar/admin.json index ab5e6126974c1..ae32f5ccd8266 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/ar/admin.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/ar/admin.json @@ -1,74 +1,76 @@ { + "columns": { + "description": "الوصف", + "key": "المفتاح", + "name": "الاسم", + "value": "القيمة" + }, + "config": { "columns": { - "description": "الوصف", - "key": "المفتاح", - "name": "الاسم", - "value": "القيمة" + "section": "القسم" }, - "config": { - "columns": { - "section": "القسم" - }, - "title": "Airflow إعدادات" + "title": "Airflow إعدادات" + }, + "connections": { + "add": "إضافة موَّصل", + "columns": { + "connectionId": "معرِّف الموَّصل", + "connectionType": "نوع الموَّصل", + "host": "المضيف", + "port": "المنفذ" }, - "connections": { - "add": "إضافة موَّصل", - "columns": { - "connectionId": "معرِّف الموَّصل", - "connectionType": "نوع الموَّصل", - "host": "المضيف", - "port": "المنفذ" - }, - "connection_one": "موَّصل", - "connection_other": "موَّصلات", - "delete": { - "deleteConnection_one": "حذف موَّصل واحد", - "deleteConnection_other": "موَّصلات {{count}} حذف", - "firstConfirmMessage_one": ":أنت على وشك حذف الموَّصل التالي", - "firstConfirmMessage_other": ":أنت على وشك حذف الموَّصلات التالية", - "title": "حذف الموَّصل" - }, - "edit": "تعديل الموَّصل", - "form": { - "connectionIdRequired": "مطلوب معرِّف الموَّصل", - "connectionIdRequirement": "لا يمكن أن يحتوي معرِّف الموَّصل على مسافات فقط", - "connectionTypeRequired": "مطلوب نوع الموَّصل", - "extraFields": "حقول إضافية", - "extraFieldsJson": "JSON حقول إضافية بصيغة", - "helperText": "نوع الموَّصل مفقود؟ تأكد من تثبيت حزمة Airflow المناسبة.", - "selectConnectionType": "اختر نوع الموَّصل", - "standardFields": "حقول قياسية" - }, - "noRowMessage": "لا توجد موَّصلات متاحة", - "searchPlaceholder": "البحث عن موَّصلات", - "test": "اختبار الموَّصل", - "testDisabled": "اختبار الموَّصل معطل. تواصل مع المسؤول لتفعيله.", - "typeMeta": { - "error": "فشل في استرداد نوع الموَّصل", - "standardFields": { - "description": "الوصف", - "host": "المضيف", - "login": "معرف الدخول", - "password": "كلمة المرور", - "port": "المنفذ", - "url_schema": "المخطط" - } - } + "connection_one": "موَّصل", + "connection_other": "موَّصلات", + "delete": { + "deleteConnection_one": "حذف موَّصل واحد", + "deleteConnection_other": "موَّصلات {{count}} حذف", + "firstConfirmMessage_one": ":أنت على وشك حذف الموَّصل التالي", + "firstConfirmMessage_other": ":أنت على وشك حذف الموَّصلات التالية", + "title": "حذف الموَّصل" }, - "deleteActions": { - "button": "حذف", - "modal": { - "confirmButton": "نعم، حذف الموَّصلات", - "secondConfirmMessage": "هذا الإجراء دائم و لا يمكن التراجع عنه.", - "thirdConfirmMessage": "هل أنت متأكد أنك تريد المواصلة؟" - }, - "selected": "المحدد", - "tooltip": "حذف الموَّصلات المحددة" + "edit": "تعديل الموَّصل", + "form": { + "connectionIdRequired": "مطلوب معرِّف الموَّصل", + "connectionIdRequirement": "لا يمكن أن يحتوي معرِّف الموَّصل على مسافات فقط", + "connectionTypeRequired": "مطلوب نوع الموَّصل", + "extraFields": "حقول إضافية", + "extraFieldsJson": "JSON حقول إضافية بصيغة", + "helperText": "نوع الموَّصل مفقود؟ تأكد من تثبيت حزمة Airflow المناسبة.", + "selectConnectionType": "اختر نوع الموَّصل", + "standardFields": "حقول قياسية" }, - "formActions": { - "reset": "إعادة تعيين", - "save": "حفظ" + "nothingFound": { + "title": "لا توجد موَّصلات متاحة" }, + "searchPlaceholder": "البحث عن موَّصلات", + "test": "اختبار الموَّصل", + "testDisabled": "اختبار الموَّصل معطل. تواصل مع المسؤول لتفعيله.", + "typeMeta": { + "error": "فشل في استرداد نوع الموَّصل", + "standardFields": { + "description": "الوصف", + "host": "المضيف", + "login": "معرف الدخول", + "password": "كلمة المرور", + "port": "المنفذ", + "url_schema": "المخطط" + } + } + }, + "deleteActions": { + "button": "حذف", + "modal": { + "confirmButton": "نعم، حذف الموَّصلات", + "secondConfirmMessage": "هذا الإجراء دائم و لا يمكن التراجع عنه.", + "thirdConfirmMessage": "هل أنت متأكد أنك تريد المواصلة؟" + }, + "selected": "المحدد", + "tooltip": "حذف الموَّصلات المحددة" + }, + "formActions": { + "reset": "إعادة تعيين", + "save": "حفظ" + }, "plugins": { "columns": { "source": "المصدر" @@ -80,7 +82,7 @@ "pools": { "add": "إضافة حصص", "deferredSlotsIncluded": "شمل الحصص المؤجلة", - "delete":{ + "delete": { "title": "حذف مجموعة", "warning": "هذا الإجراء سيؤدي إلى حذف المجموعة المحددة و من الممكن أن يؤثر على المهام الجارية." }, @@ -122,7 +124,7 @@ "title": "حذف المتغير", "tooltip": "حذف المتغيرات المحددة" }, - "edit": "تعديل المتغير", + "edit": "تعديل المتغير", "export": "تصدير", "exportTooltip": "تصدير المتغيرات المحددة", "form": { diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/ar/assets.json b/airflow-core/src/airflow/ui/public/i18n/locales/ar/assets.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/ar/assets.json rename to airflow-core/src/airflow/ui/public/i18n/locales/ar/assets.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/ar/browse.json b/airflow-core/src/airflow/ui/public/i18n/locales/ar/browse.json similarity index 87% rename from airflow-core/src/airflow/ui/src/i18n/locales/ar/browse.json rename to airflow-core/src/airflow/ui/public/i18n/locales/ar/browse.json index ff6abf0b81777..775230d598cc5 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/ar/browse.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/ar/browse.json @@ -1,10 +1,10 @@ { - "auditLog":{ + "auditLog": { "actions": { "collapseAllExtra": "طي جميع الJSON الإضافية", "expandAllExtra": "توسيع جميع الJSON الإضافية" }, - "columns":{ + "columns": { "event": "اصل", "extra": "إضافي", "user": "مستخدم", @@ -12,8 +12,8 @@ }, "title": "سجل المراجعة" }, - "xcom":{ - "columns":{ + "xcom": { + "columns": { "dag": "Dag", "key": "مفتاح", "value": "قيمة" diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/ar/common.json b/airflow-core/src/airflow/ui/public/i18n/locales/ar/common.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/ar/common.json rename to airflow-core/src/airflow/ui/public/i18n/locales/ar/common.json diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ar/components.json b/airflow-core/src/airflow/ui/public/i18n/locales/ar/components.json new file mode 100644 index 0000000000000..7764a53c62edf --- /dev/null +++ b/airflow-core/src/airflow/ui/public/i18n/locales/ar/components.json @@ -0,0 +1,131 @@ +{ + "backfill": { + "affected_one": "مهمة واحدة ستُشغّل.", + "affected_other": "{{count}} مهام ستُشغّل.", + "affectedNone": "لا توجد مهام تطابق المعايير المحددة.", + "backwards": "تشغيل رجعي", + "dateRange": "نطاق التاريخ", + "dateRangeFrom": "من", + "dateRangeTo": "إلى", + "errorStartDateBeforeEndDate": "يجب أن يكون تاريخ البدء قبل تاريخ الانتهاء", + "maxRuns": "الحد الأقصى للتشغيلات النشطة", + "reprocessBehavior": "اعادة معالجة السلوك", + "run": "تشغيل التعبئة الرجعية", + "selectDescription": "تشغيل هذا DAG لنطاق من التواريخ", + "selectLabel": "تعبئة رجعية", + "title": "تشغيل التعبئة الرجعية", + "toaster": { + "success": { + "description": "تم تشغيل مهام التعبئة الرجعية بنجاح.", + "title": "تم إنشاء التعبئة الرجعية" + } + }, + "tooltip": "التعبئة الرجعية تتطلب جدول زمني", + "unpause": "إلغاء إيقاف {{dag_display_name}} عند التشغيل", + "validation": { + "datesRequired": "يجب توفير بيانات كل من تاريخ بدء فترة وتاريخ الانتهاء.", + "startBeforeEnd": "بيانات فترة تاريخ البدء يجب ان تكون من او قبل تاريخ الانتهاء. " + } + }, + "banner": { + "backfillInProgress": "التعبئة الرجعية قيد التنفيذ", + "cancel": "إلغاء التعبئة الرجعية", + "pause": "إيقاف التعبئة الرجعية", + "unpause": "إلغاء إيقاف التعبئة الرجعية" + }, + "clipboard": { + "copy": "نسخ" + }, + "close": "إغلاق", + "configForm": { + "advancedOptions": "خيارات متقدمة", + "configJson": "تكوين JSON", + "invalidJson": "تنسيق JSON غير صالح: {{errorMessage}}" + }, + "dagWarnings": { + "error_one": "1 خطأ", + "errorAndWarning": "1 خطأ و{{warningText}}", + "warning_one": "1 تحذير", + "warning_other": "{{count}} تحذيرات" + }, + "durationChart": { + "duration": "المدة (بالثواني)", + "lastDagRun_one": "آخر تشغيل DAG", + "lastDagRun_other": "آخر {{count}} تشغيلات DAG", + "lastTaskInstance_one": "آخر مثيل مهمة", + "lastTaskInstance_other": "آخر {{count}} مثيلات المهام", + "queuedDuration": "مدة الانتظار في الطابور", + "runAfter": "تشغيل بعد", + "runDuration": "مدة التشغيل" + }, + "fileUpload": { + "files_other": "{{count}} ملفات" + }, + "flexibleForm": { + "placeholder": "اختر قيمة", + "placeholderArray": "أدخل كل سلسلة في سطر جديد", + "placeholderExamples": "ابدأ الكتابة لرؤية الخيارات", + "placeholderMulti": "اختر قيمة أو أكثر", + "validationErrorArrayNotArray": "القيمة يجب أن تكون مصفوفة.", + "validationErrorArrayNotNumbers": "جميع العناصر في المصفوفة يجب أن تكون أرقامًا.", + "validationErrorArrayNotObject": "جميع العناصر في المصفوفة يجب أن تكون كائنات.", + "validationErrorRequired": "هذا الحقل مطلوب" + }, + "graph": { + "directionDown": "من الأعلى إلى الأسفل", + "directionLeft": "من اليمين إلى اليسار", + "directionRight": "من اليسار إلى اليمين", + "directionUp": "من الأسفل إلى الأعلى", + "downloadImage": "تحميل صورة الرسم البياني", + "downloadImageError": "فشل تحميل صورة الرسم البياني.", + "downloadImageErrorTitle": "فشل التحميل", + "otherDagRuns": "+تشغيلات DAG أخرى", + "taskCount_one": "{{count}} مهمة", + "taskCount_other": "{{count}} مهام", + "taskGroup": "مجموعة المهام" + }, + "limitedList": "+{{count}} المزيد", + "logs": { + "file": "ملف", + "location": "سطر {{line}} في {{name}}" + }, + "reparseDag": "إعادة تحليل DAG", + "sortedAscending": "الترتيب تصاعدي", + "sortedDescending": "الترتيب تنازلي", + "sortedUnsorted": "غير مرتب", + "taskTries": "محاولات المهمة", + "toggleCardView": "عرض البطاقة", + "toggleTableView": "عرض الجدول", + "triggerDag": { + "button": "تشغيل", + "loading": "جارٍ تحميل معلومات DAG...", + "loadingFailed": "فشل تحميل معلومات DAG. يرجى المحاولة مرة أخرى.", + "runIdHelp": "اختياري - سيتم توليده تلقائيًا إذا لم يتم توفيره.", + "selectDescription": "تشغيل عملية واحدة من هذا DAG", + "selectLabel": "تشغيلة واحدة", + "title": "تشغيل DAG", + "toaster": { + "success": { + "description": "تم تشغيل عملية DAG بنجاح.", + "title": "تم تشغيل DAG" + } + }, + "unpause": "إلغاء إيقاف {{dagDisplayName}} عند التشغيل" + }, + "trimText": { + "details": "التفاصيل", + "empty": "فارغ", + "noContent": "لا توجد محتويات متاحة." + }, + "versionDetails": { + "bundleLink": "رابط الحزمة", + "bundleName": "اسم الحزمة", + "bundleVersion": "إصدار الحزمة", + "createdAt": "تاريخ الإنشاء", + "versionId": "معرف الإصدار" + }, + "versionSelect": { + "dagVersion": "إصدار DAG", + "versionCode": "v{{versionCode}}" + } +} diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/ar/dag.json b/airflow-core/src/airflow/ui/public/i18n/locales/ar/dag.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/ar/dag.json rename to airflow-core/src/airflow/ui/public/i18n/locales/ar/dag.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/ar/dags.json b/airflow-core/src/airflow/ui/public/i18n/locales/ar/dags.json similarity index 88% rename from airflow-core/src/airflow/ui/src/i18n/locales/ar/dags.json rename to airflow-core/src/airflow/ui/public/i18n/locales/ar/dags.json index 20964aff8e539..e535ee03ec670 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/ar/dags.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/ar/dags.json @@ -52,18 +52,18 @@ "downstream": "المهام اللاحقة", "existingTasks": "مسح المهام الحالية", "future": "المستقبل", - "onlyFailed": "مسح المهام الفاشلة فقط", - "past": "الماضي", - "queueNew": "إضافة مهام جديدة للانتظار", - "upstream": "المهام السابقة" + "onlyFailed": "مسح المهام الفاشلة فقط", + "past": "الماضي", + "queueNew": "إضافة مهام جديدة للانتظار", + "upstream": "المهام السابقة" } }, "search": { - "advanced": "بحث متقدم", - "clear": " مسح", - "dags": "ابحث عن Dags", - "hotkey": "+K", - "tasks": "ابحث عن مهام" + "advanced": "بحث متقدم", + "clear": " مسح", + "dags": "ابحث عن Dags", + "hotkey": "+K", + "tasks": "ابحث عن مهام" }, "sort": { "displayName": { diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/ar/dashboard.json b/airflow-core/src/airflow/ui/public/i18n/locales/ar/dashboard.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/ar/dashboard.json rename to airflow-core/src/airflow/ui/public/i18n/locales/ar/dashboard.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/de/README.md b/airflow-core/src/airflow/ui/public/i18n/locales/de/README.md similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/de/README.md rename to airflow-core/src/airflow/ui/public/i18n/locales/de/README.md diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/de/admin.json b/airflow-core/src/airflow/ui/public/i18n/locales/de/admin.json similarity index 92% rename from airflow-core/src/airflow/ui/src/i18n/locales/de/admin.json rename to airflow-core/src/airflow/ui/public/i18n/locales/de/admin.json index f8d2194b0b571..d2d8cf7d0d8db 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/de/admin.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/de/admin.json @@ -39,7 +39,12 @@ "selectConnectionType": "Verbindungstyp auswählen", "standardFields": "Standardfelder" }, - "noRowMessage": "Keine Verbindungen gefunden", + "nothingFound": { + "description": "Verbindungen, die durch Secret-Managers oder Umgebungsvariablen definiert sind werden hier nicht gelistet.", + "documentationLink": "Mehr Details sind in der Airflow-Dokumentation beschrieben.", + "learnMore": "Diese Verbindungen werden erst eingelesen, wenn ein Task, der sie verwendet ausgeführt wird und sie sind daher in dieser Ansicht nicht sichtbar.", + "title": "Keine Verbindungen gefunden!" + }, "searchPlaceholder": "Verbindungen suchen", "test": "Verbindung testen", "testDisabled": "Das Testen von Verbindungen ist deaktiviert. Der Administrator kann via Konfiguration das Testen freischalten.", diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/de/assets.json b/airflow-core/src/airflow/ui/public/i18n/locales/de/assets.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/de/assets.json rename to airflow-core/src/airflow/ui/public/i18n/locales/de/assets.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/de/browse.json b/airflow-core/src/airflow/ui/public/i18n/locales/de/browse.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/de/browse.json rename to airflow-core/src/airflow/ui/public/i18n/locales/de/browse.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/de/common.json b/airflow-core/src/airflow/ui/public/i18n/locales/de/common.json similarity index 96% rename from airflow-core/src/airflow/ui/src/i18n/locales/de/common.json rename to airflow-core/src/airflow/ui/public/i18n/locales/de/common.json index da82650f85671..f657e7e5d6af2 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/de/common.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/de/common.json @@ -17,6 +17,7 @@ "auditLog": "Prüf-Log", "xcoms": "Task Kommunikation (XComs)" }, + "collapseDetailsPanel": "Detailansicht ausblenden", "createdAssetEvent_one": "Erstelltes Ereignis zu Datenset (Asset)", "createdAssetEvent_other": "Erstellte Ereignisse zu Datensets (Assets)", "dag_one": "Dag", @@ -128,6 +129,13 @@ "manual": "Manuell", "scheduled": "Geplant" }, + "scroll": { + "direction": { + "bottom": "unten", + "top": "oben" + }, + "tooltip": "Tastenkombination {{hotkey}} zum scrollen nach {{direction}}" + }, "seconds": "{{count}}s", "security": { "actions": "Aktionen", @@ -137,6 +145,7 @@ "users": "Benutzer" }, "selectLanguage": "Sprache wählen", + "showDetailsPanel": "Detailansicht einblenden", "sourceAssetEvent_one": "Urspung des Datenset (Asset) Ereignisses", "sourceAssetEvent_other": "Urspung der Datenset (Asset) Ereignisse", "startDate": "Startdatum", diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/de/components.json b/airflow-core/src/airflow/ui/public/i18n/locales/de/components.json similarity index 98% rename from airflow-core/src/airflow/ui/src/i18n/locales/de/components.json rename to airflow-core/src/airflow/ui/public/i18n/locales/de/components.json index 3f4a1bf6e3bbe..765fb85ae73bd 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/de/components.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/de/components.json @@ -44,6 +44,7 @@ }, "dagWarnings": { "error_one": "1 Fehler", + "error_other": "{{count}} Fehler", "errorAndWarning": "1 Fehler und {{warningText}}", "warning_one": "1 Warnung", "warning_other": "{{count}} Warnungen" @@ -59,6 +60,7 @@ "runDuration": "Laufzeit" }, "fileUpload": { + "files_one": "1 Datei", "files_other": "{{count}} Dateien" }, "flexibleForm": { diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/de/dag.json b/airflow-core/src/airflow/ui/public/i18n/locales/de/dag.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/de/dag.json rename to airflow-core/src/airflow/ui/public/i18n/locales/de/dag.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/de/dags.json b/airflow-core/src/airflow/ui/public/i18n/locales/de/dags.json similarity index 92% rename from airflow-core/src/airflow/ui/src/i18n/locales/de/dags.json rename to airflow-core/src/airflow/ui/public/i18n/locales/de/dags.json index 06e96c85cd90a..d79a944687da3 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/de/dags.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/de/dags.json @@ -23,7 +23,7 @@ }, "clear": { "button": "{{type}} zurücksetzen", - "buttonTooltip": "STRG+C zum Zurücksetzen tippen", + "buttonTooltip": "Umschalttaste+C zum Zurücksetzen tippen", "error": "Fehler beim Zurücksetzen von {{type}}", "title": "{{type}} bereinigen und neu planen" }, @@ -43,8 +43,8 @@ "markAs": { "button": "{{type}} markieren...", "buttonTooltip": { - "failed": "STRG+F tippen um als fehlgeschlagen zu markieren", - "success": "STRG+S tippen um als erfolgreich zu markieren" + "failed": "Umschalttaste+F tippen um als fehlgeschlagen zu markieren", + "success": "Umschalttaste+S tippen um als erfolgreich zu markieren" }, "title": "{{type}} auf den Status {{state}} setzen" }, diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/de/dashboard.json b/airflow-core/src/airflow/ui/public/i18n/locales/de/dashboard.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/de/dashboard.json rename to airflow-core/src/airflow/ui/public/i18n/locales/de/dashboard.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/admin.json b/airflow-core/src/airflow/ui/public/i18n/locales/en/admin.json similarity index 93% rename from airflow-core/src/airflow/ui/src/i18n/locales/en/admin.json rename to airflow-core/src/airflow/ui/public/i18n/locales/en/admin.json index aeb93b92c76fd..5012117276db9 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/en/admin.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/en/admin.json @@ -39,7 +39,12 @@ "selectConnectionType": "Select Connection Type", "standardFields": "Standard Fields" }, - "noRowMessage": "No connections found", + "nothingFound": { + "description": "Connections defined via environment variables or secrets managers are not listed here.", + "documentationLink": "Learn more in the Airflow documentation.", + "learnMore": "These are resolved at runtime and are not visible in the UI.", + "title": "No connection found!" + }, "searchPlaceholder": "Search Connections", "test": "Test Connection", "testDisabled": "Test connection feature is disabled. Please contact an administrator to enable it.", diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/assets.json b/airflow-core/src/airflow/ui/public/i18n/locales/en/assets.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/en/assets.json rename to airflow-core/src/airflow/ui/public/i18n/locales/en/assets.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/browse.json b/airflow-core/src/airflow/ui/public/i18n/locales/en/browse.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/en/browse.json rename to airflow-core/src/airflow/ui/public/i18n/locales/en/browse.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/common.json b/airflow-core/src/airflow/ui/public/i18n/locales/en/common.json similarity index 96% rename from airflow-core/src/airflow/ui/src/i18n/locales/en/common.json rename to airflow-core/src/airflow/ui/public/i18n/locales/en/common.json index 6cebff264bdd7..6d1c8cc4d8244 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/en/common.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/en/common.json @@ -17,6 +17,7 @@ "auditLog": "Audit Log", "xcoms": "XComs" }, + "collapseDetailsPanel": "Collapse Details Panel", "createdAssetEvent_one": "Created Asset Event", "createdAssetEvent_other": "Created Asset Events", "dag_one": "Dag", @@ -128,6 +129,13 @@ "manual": "Manual", "scheduled": "Scheduled" }, + "scroll": { + "direction": { + "bottom": "bottom", + "top": "top" + }, + "tooltip": "Press {{hotkey}} to scroll to {{direction}}" + }, "seconds": "{{count}}s", "security": { "actions": "Actions", @@ -137,6 +145,7 @@ "users": "Users" }, "selectLanguage": "Select Language", + "showDetailsPanel": "Show Details Panel", "sourceAssetEvent_one": "Source Asset Event", "sourceAssetEvent_other": "Source Asset Events", "startDate": "Start Date", diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/components.json b/airflow-core/src/airflow/ui/public/i18n/locales/en/components.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/en/components.json rename to airflow-core/src/airflow/ui/public/i18n/locales/en/components.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/dag.json b/airflow-core/src/airflow/ui/public/i18n/locales/en/dag.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/en/dag.json rename to airflow-core/src/airflow/ui/public/i18n/locales/en/dag.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/dags.json b/airflow-core/src/airflow/ui/public/i18n/locales/en/dags.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/en/dags.json rename to airflow-core/src/airflow/ui/public/i18n/locales/en/dags.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/dashboard.json b/airflow-core/src/airflow/ui/public/i18n/locales/en/dashboard.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/en/dashboard.json rename to airflow-core/src/airflow/ui/public/i18n/locales/en/dashboard.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/fr/admin.json b/airflow-core/src/airflow/ui/public/i18n/locales/fr/admin.json similarity index 94% rename from airflow-core/src/airflow/ui/src/i18n/locales/fr/admin.json rename to airflow-core/src/airflow/ui/public/i18n/locales/fr/admin.json index 3626a7a2f1904..2c0592320df9c 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/fr/admin.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/fr/admin.json @@ -1,19 +1,19 @@ { - "columns":{ + "columns": { "description": "Description", "key": "Clé", "name": "Nom", "value": "Valeur" }, - "config":{ - "columns":{ + "config": { + "columns": { "section": "Section" }, "title": "Configuration d'Airflow" }, - "connections":{ - "add":"Ajouter une Connexion", - "columns":{ + "connections": { + "add": "Ajouter une Connexion", + "columns": { "connectionId": "ID de la connexion", "connectionType": "Type de la connexion", "host": "Hôte", @@ -21,7 +21,7 @@ }, "connection_one": "Connexion", "connection_other": "Connexions", - "delete":{ + "delete": { "deleteConnection_one": "Supprimer 1 connexion", "deleteConnection_other": "Supprimer {{count}} connexions", "firstConfirmMessage_one": "Vous êtes sur le point de supprimer la connexion suivante :", @@ -29,7 +29,7 @@ "title": "Supprimer la Connexion" }, "edit": "Modifier la Connexion", - "form":{ + "form": { "connectionIdRequired": "L'ID de la connexion est requis", "connectionIdRequirement": "L'ID de la connexion ne peut pas contenir uniquement des espaces", "connectionTypeRequired": "Le type de la connexion est requis", @@ -39,7 +39,9 @@ "selectConnectionType": "Sélectionner le Type de Connexion", "standardFields": "Champs Standards" }, - "noRowMessage": "Aucune connexion trouvée", + "nothingFound": { + "title": "Aucune connexion trouvée!" + }, "searchPlaceholder": "Rechercher les connexions", "test": "Test la connexion", "testDisabled": "Le test de connexion est désactivé. Veuillez contacter un administrateur pour l'activer.", @@ -55,9 +57,9 @@ } } }, - "deleteActions":{ + "deleteActions": { "button": "Supprimer", - "modal":{ + "modal": { "confirmButton": "Oui, Supprimer", "secondConfirmMessage": "Cette action est irréversible.", "thirdConfirmMessage": " Êtes-vous sûr de vouloir continuer ?" @@ -65,7 +67,7 @@ "selected": "Sélectionné", "tooltip": "Supprimer les connexions sélectionnées" }, - "formActions":{ + "formActions": { "reset": "Réinitialiser", "save": "Sauvegarder" }, @@ -80,7 +82,7 @@ "pools": { "add": "Ajouter un Pool", "deferredSlotsIncluded": "Slots Différés Inclus", - "delete":{ + "delete": { "title": "Supprimer le Pool", "warning": "Cela supprimera toutes les métadonnées liées au pool et peut affecter les tâches utilisant ce pool." }, @@ -122,7 +124,7 @@ "title": "Supprimer la Variable", "tooltip": "Supprimer les variables sélectionnées" }, - "edit": "Modifier la Variable", + "edit": "Modifier la Variable", "export": "Exporter", "exportTooltip": "Exporter les variables sélectionnées", "form": { diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/fr/assets.json b/airflow-core/src/airflow/ui/public/i18n/locales/fr/assets.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/fr/assets.json rename to airflow-core/src/airflow/ui/public/i18n/locales/fr/assets.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/fr/browse.json b/airflow-core/src/airflow/ui/public/i18n/locales/fr/browse.json similarity index 86% rename from airflow-core/src/airflow/ui/src/i18n/locales/fr/browse.json rename to airflow-core/src/airflow/ui/public/i18n/locales/fr/browse.json index 7aad5959a653f..09b7d3de68768 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/fr/browse.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/fr/browse.json @@ -1,10 +1,10 @@ { - "auditLog":{ + "auditLog": { "actions": { "collapseAllExtra": "Réduire tous les extra json", "expandAllExtra": "Ouvrir tous les extra json" }, - "columns":{ + "columns": { "event": "Événement", "extra": "Extra", "user": "Utilisateur", @@ -12,8 +12,8 @@ }, "title": "Journal d'Audit" }, - "xcom":{ - "columns":{ + "xcom": { + "columns": { "dag": "Dag", "key": "Clé", "value": "Valeur" diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/fr/common.json b/airflow-core/src/airflow/ui/public/i18n/locales/fr/common.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/fr/common.json rename to airflow-core/src/airflow/ui/public/i18n/locales/fr/common.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/fr/components.json b/airflow-core/src/airflow/ui/public/i18n/locales/fr/components.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/fr/components.json rename to airflow-core/src/airflow/ui/public/i18n/locales/fr/components.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/fr/dag.json b/airflow-core/src/airflow/ui/public/i18n/locales/fr/dag.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/fr/dag.json rename to airflow-core/src/airflow/ui/public/i18n/locales/fr/dag.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/fr/dags.json b/airflow-core/src/airflow/ui/public/i18n/locales/fr/dags.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/fr/dags.json rename to airflow-core/src/airflow/ui/public/i18n/locales/fr/dags.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/fr/dashboard.json b/airflow-core/src/airflow/ui/public/i18n/locales/fr/dashboard.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/fr/dashboard.json rename to airflow-core/src/airflow/ui/public/i18n/locales/fr/dashboard.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/he/admin.json b/airflow-core/src/airflow/ui/public/i18n/locales/he/admin.json similarity index 98% rename from airflow-core/src/airflow/ui/src/i18n/locales/he/admin.json rename to airflow-core/src/airflow/ui/public/i18n/locales/he/admin.json index 30bc908225b07..adadffd1961e3 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/he/admin.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/he/admin.json @@ -39,7 +39,9 @@ "selectConnectionType": "בחר סוג חיבור", "standardFields": "שדות סטנדרטיים" }, - "noRowMessage": "לא נמצאו חיבורים", + "nothingFound": { + "title": "לא נמצאו חיבורים" + }, "searchPlaceholder": "חפש חיבורים", "test": "בדוק חיבור", "testDisabled": "אפשרות זו אינה זמינה. פנו למנהל המערכת להפעלתה", diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/he/assets.json b/airflow-core/src/airflow/ui/public/i18n/locales/he/assets.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/he/assets.json rename to airflow-core/src/airflow/ui/public/i18n/locales/he/assets.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/he/browse.json b/airflow-core/src/airflow/ui/public/i18n/locales/he/browse.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/he/browse.json rename to airflow-core/src/airflow/ui/public/i18n/locales/he/browse.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/he/common.json b/airflow-core/src/airflow/ui/public/i18n/locales/he/common.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/he/common.json rename to airflow-core/src/airflow/ui/public/i18n/locales/he/common.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/he/components.json b/airflow-core/src/airflow/ui/public/i18n/locales/he/components.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/he/components.json rename to airflow-core/src/airflow/ui/public/i18n/locales/he/components.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/he/dag.json b/airflow-core/src/airflow/ui/public/i18n/locales/he/dag.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/he/dag.json rename to airflow-core/src/airflow/ui/public/i18n/locales/he/dag.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/he/dags.json b/airflow-core/src/airflow/ui/public/i18n/locales/he/dags.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/he/dags.json rename to airflow-core/src/airflow/ui/public/i18n/locales/he/dags.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/he/dashboard.json b/airflow-core/src/airflow/ui/public/i18n/locales/he/dashboard.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/he/dashboard.json rename to airflow-core/src/airflow/ui/public/i18n/locales/he/dashboard.json diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ko/admin.json b/airflow-core/src/airflow/ui/public/i18n/locales/ko/admin.json new file mode 100644 index 0000000000000..f3d960db72002 --- /dev/null +++ b/airflow-core/src/airflow/ui/public/i18n/locales/ko/admin.json @@ -0,0 +1,166 @@ +{ + "columns": { + "description": "설명", + "key": "키", + "name": "이름", + "value": "값" + }, + "config": { + "columns": { + "section": "섹션" + }, + "title": "Airflow 구성" + }, + "connections": { + "add": "커넥션 추가", + "columns": { + "connectionId": "커넥션 ID", + "connectionType": "커넥션 유형", + "host": "호스트", + "port": "포트" + }, + "connection_one": "커넥션", + "connection_other": "커넥션들", + "delete": { + "deleteConnection_one": "커넥션 1개 삭제", + "deleteConnection_other": "커넥션 {{count}}개 삭제", + "firstConfirmMessage_one": "다음 커넥션을 삭제하려고 합니다:", + "firstConfirmMessage_other": "다음 커넥션들을 삭제하려고 합니다:", + "title": "커넥션 삭제" + }, + "edit": "커넥션 편집", + "form": { + "connectionIdRequired": "커넥션 ID는 필수 항목입니다", + "connectionIdRequirement": "커넥션 ID는 공백만으로 구성될 수 없습니다", + "connectionTypeRequired": "커넥션 유형은 필수 항목입니다", + "extraFields": "추가 필드", + "extraFieldsJson": "추가 필드 JSON", + "helperText": "커넥션 유형이 보이지 않나요? 해당 Airflow Provider 패키지가 설치되어 있는지 확인하세요.", + "selectConnectionType": "커넥션 유형 선택", + "standardFields": "기본 필드" + }, + "nothingFound": { + "description": "환경 변수나 시크릿 매니저를 통해 정의된 커넥션은 여기에 표시되지 않습니다.", + "documentationLink": "자세한 내용은 Airflow 문서를 참고하세요.", + "learnMore": "이러한 커넥션은 런타임 시점에 해결되며 UI에는 표시되지 않습니다.", + "title": "커넥션을 찾을 수 없습니다." + }, + "searchPlaceholder": "커넥션 검색", + "test": "커넥션 테스트", + "testDisabled": "커넥션 테스트 기능이 비활성화되어 있습니다. 관리자에게 활성화를 요청하세요.", + "typeMeta": { + "error": "커넥션 유형 메타 정보를 가져오지 못했습니다", + "standardFields": { + "description": "설명", + "host": "호스트", + "login": "로그인", + "password": "비밀번호", + "port": "포트", + "url_schema": "스키마" + } + } + }, + "deleteActions": { + "button": "삭제", + "modal": { + "confirmButton": "네, 삭제합니다", + "secondConfirmMessage": "이 작업은 영구적으로 삭제되며 되돌릴 수 없습니다.", + "thirdConfirmMessage": "정말로 계속하시겠습니까?" + }, + "selected": "선택됨", + "tooltip": "선택된 커넥션들 삭제" + }, + "formActions": { + "reset": "초기화", + "save": "저장" + }, + "plugins": { + "columns": { + "source": "소스" + }, + "importError_one": "플러그인 가져오기 오류", + "importError_other": "플러그인 가져오기 오류들", + "searchPlaceholder": "파일로 검색" + }, + "pools": { + "add": "풀 추가", + "deferredSlotsIncluded": "연기된 슬롯 포함됨", + "delete": { + "title": "풀 삭제", + "warning": "이 작업은 풀과 관련된 모든 메타데이터를 제거하며, 해당 풀을 사용하는 태스크에 영향을 줄 수 있습니다." + }, + "edit": "풀 편집", + "form": { + "checkbox": "열린 풀 슬롯 게산시 연기된 작업 포함", + "description": "설명", + "includeDeferred": "연기됨 포함", + "nameMaxLength": "이름은 최대 256자까지 입력할 수 있습니다", + "nameRequired": "이름은 필수입니다", + "slots": "슬롯" + }, + "noPoolsFound": "풀을 찾을 수 없습니다", + "pool_one": "풀", + "pool_other": "풀", + "searchPlaceholder": "풀 검색", + "sort": { + "asc": "이름 (A-Z)", + "desc": "이름 (Z-A)", + "placeholder": "정렬 기준" + } + }, + "providers": { + "columns": { + "packageName": "패키지 이름", + "version": "버전" + } + }, + "variables": { + "add": "변수 추가", + "columns": { + "isEncrypted": "암호화됨 여부" + }, + "delete": { + "deleteVariable_one": "변수 1개 삭제", + "deleteVariable_other": "변수 {{count}}개 삭제", + "firstConfirmMessage_one": "다음 변수를 삭제하려고 합니다:", + "firstConfirmMessage_other": "다음 변수들을 삭제하려고 합니다:", + "title": "변수 삭제", + "tooltip": "선택된 변수들 삭제" + }, + "edit": "변수 편집", + "export": "내보내기", + "exportTooltip": "선택된 변수들 내보내기", + "form": { + "invalidJson": "유효하지 않은 JSON입니다", + "keyMaxLength": "키는 최대 250자까지 입력할 수 있습니다", + "keyRequired": "키는 필수입니다", + "valueRequired": "값은 필수입니다" + }, + "import": { + "button": "가져오기", + "conflictResolution": "변수 충돌 해결 방법 선택", + "errorParsingJsonFile": "JSON 파일 구문 분석 오류: 변수들이 포함된 JSON 파일을 업로드하세요 (예: {\"key\": \"value\", ...}).", + "options": { + "fail": { + "description": "기존 변수가 존재하는 경우 가져오기를 실패합니다.", + "title": "실패" + }, + "overwrite": { + "description": "충돌 시 해당 변수를 덮어씁니다.", + "title": "덮어쓰기" + }, + "skip": { + "description": "이미 존재하는 변수는 가져오기를 건너뜁니다.", + "title": "건너뛰기" + } + }, + "title": "변수 가져오기", + "upload": "JSON 파일 업로드", + "uploadPlaceholder": "변수를 포함한 JSON 파일 업로드 (e.g., {\"key\": \"value\", ...})" + }, + "noRowsMessage": "변수를 찾을 수 없습니다", + "searchPlaceholder": "키 검색", + "variable_one": "변수", + "variable_other": "변수들" + } +} diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ko/assets.json b/airflow-core/src/airflow/ui/public/i18n/locales/ko/assets.json new file mode 100644 index 0000000000000..629cae2480498 --- /dev/null +++ b/airflow-core/src/airflow/ui/public/i18n/locales/ko/assets.json @@ -0,0 +1,29 @@ +{ + "consumingDags": "사용 중인 Dags", + "createEvent": { + "button": "이벤트 생성", + "manual": { + "description": "에셋 이벤트를 수동으로 생성", + "extra": "에셋 이벤트 추가 정보", + "label": "수동 생성" + }, + "materialize": { + "description": "이 에셋의 상위 Dag을 트리거합니다", + "descriptionWithDag": "이 에셋의 상위 Dag을 트리거합니다: {{dagName}}", + "label": "구체화", + "unpauseDag": "트리거 시 {{dagName}}의 일시중지를 해제합니다" + }, + "success": { + "manualDescription": "에셋 이벤트가 성공적으로 수동 생성되었습니다.", + "manualTitle": "에셋 이벤트 생성 완료", + "materializeDescription": "상위 Dag {{dagId}}가 성공적으로 트리거되었습니다.", + "materializeTitle": "에셋 구체화 중" + }, + "title": "{{name}}에 대한 에셋 이벤트 생성" + }, + "group": "그룹", + "lastAssetEvent": "마지막 에셋 이벤트", + "name": "이름", + "producingTasks": "생성하는 태스크", + "searchPlaceholder": "에셋 검색" +} diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ko/browse.json b/airflow-core/src/airflow/ui/public/i18n/locales/ko/browse.json new file mode 100644 index 0000000000000..ee5f1b9d1e405 --- /dev/null +++ b/airflow-core/src/airflow/ui/public/i18n/locales/ko/browse.json @@ -0,0 +1,23 @@ +{ + "auditLog": { + "actions": { + "collapseAllExtra": "모든 추가 JSON 접기", + "expandAllExtra": "모든 추가 JSON 펼치기" + }, + "columns": { + "event": "이벤트", + "extra": "추가 정보", + "user": "사용자", + "when": "시점" + }, + "title": "감사 로그" + }, + "xcom": { + "columns": { + "dag": "Dag", + "key": "키", + "value": "값" + }, + "title": "XCom" + } +} diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ko/common.json b/airflow-core/src/airflow/ui/public/i18n/locales/ko/common.json new file mode 100644 index 0000000000000..9e56b91799e09 --- /dev/null +++ b/airflow-core/src/airflow/ui/public/i18n/locales/ko/common.json @@ -0,0 +1,280 @@ +{ + "admin": { + "Config": "설정", + "Connections": "커넥션들", + "Plugins": "플러그인들", + "Pools": "풀들", + "Providers": "제공자들", + "Variables": "변수들" + }, + "asset_one": "에셋", + "asset_other": "에셋들", + "assetEvent_one": "에셋 이벤트", + "assetEvent_other": "에셋 이벤트들", + "backfill_one": "백필", + "backfill_other": "백필들", + "browse": { + "auditLog": "감사 로그", + "xcoms": "XComs" + }, + "collapseDetailsPanel": "세부 정보 패널 접기", + "createdAssetEvent_one": "생성된 에셋 이벤트", + "createdAssetEvent_other": "생성된 에셋 이벤트들", + "dag_one": "Dag", + "dag_other": "Dags", + "dagDetails": { + "catchup": "캐치업", + "concurrency": "동시 샐행 수", + "dagRunTimeout": "Dag 실행 제한 시간", + "defaultArgs": "기본 인자", + "description": "설명", + "documentation": "Dag 문서", + "fileLocation": "파일 위치", + "hasTaskConcurrencyLimits": "태스크 동시성 제한 존재 여부", + "lastExpired": "마지막 만료 시점", + "lastParsed": "마지막 파싱 시점", + "latestDagVersion": "최신 Dag 버전", + "latestRun": "최근 실행", + "maxActiveRuns": "최대 활성 실행 수", + "maxActiveTasks": "최대 활성 태스크 수", + "maxConsecutiveFailedDagRuns": "연속 실패한 Dag 실행 최대 횟수", + "nextRun": "다음 실행", + "owner": "소유자", + "params": "매개변수", + "schedule": "스케줄", + "tags": "태그" + }, + "dagId": "Dag ID", + "dagRun": { + "conf": "구성", + "dagVersions": "Dag 버전", + "dataIntervalEnd": "데이터 구간 종료", + "dataIntervalStart": "데이터 구간 시작", + "lastSchedulingDecision": "마지막 스케줄링 결정", + "queuedAt": "대기열에 추가된 시간", + "runAfter": "다음 실행", + "runType": "실행 유형", + "sourceAssetEvent": "소스 에셋 이벤트", + "triggeredBy": "실행 주체" + }, + "dagRun_one": "Dag 실행", + "dagRun_other": "Dag 실행들", + "dagWarnings": "Dag 경고/오류", + "defaultToGraphView": "그래프 뷰 기본 보기", + "defaultToGridView": "그리드 뷰 기본 보기", + "direction": "방향", + "docs": { + "documentation": "문서", + "githubRepo": "GitHub 저장소", + "restApiReference": "REST API 참조" + }, + "duration": "기간", + "endDate": "종료일", + "error": { + "back": "뒤로", + "defaultMessage": "예기치 않은 오류가 발생했습니다.", + "home": "홈", + "notFound": "페이지를 찾을 수 없습니다.", + "title": "오류" + }, + "expression": { + "all": "모두", + "and": "그리고", + "any": "모든", + "or": "또는" + }, + "logicalDate": "논리적 날짜", + "logout": "로그아웃", + "logoutConfirmation": "애플리케이션에서 로그아웃하시겠습니까?", + "mapIndex": "맵 인덱스", + "modal": { + "cancel": "취소", + "confirm": "확인", + "delete": { + "button": "삭제", + "confirmation": "{{resourceName}}을(를) 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다." + } + }, + "nav": { + "admin": "관리자", + "assets": "에셋", + "browse": "탐색", + "dags": "Dags", + "docs": "문서", + "home": "홈", + "plugins": "플러그인", + "security": "보안" + }, + "noItemsFound": "{{modelName}} 을(를) 찾을 수 없음", + "note": { + "add": "메모 추가", + "dagRun": "Dag 실행 메모", + "label": "메모", + "placeholder": "메모 추가...", + "taskInstance": "작업 인스턴스 메모" + }, + "pools": { + "deferred": "연기됨", + "open": "열림", + "pools_one": "풀", + "pools_other": "풀", + "queued": "대기 중", + "running": "실행 중", + "scheduled": "예약됨" + }, + "runId": "실행 ID", + "runTypes": { + "asset_triggered": "에셋 트리거", + "backfill": "백필", + "manual": "수동", + "scheduled": "예정됨" + }, + "scroll": { + "direction": { + "bottom": "아래", + "top": "위" + }, + "tooltip": "{{hotkey}}를 눌러 {{direction}}로 스크롤" + }, + "seconds": "{{count}}초", + "security": { + "actions": "작업", + "permissions": "권한", + "resources": "리소스", + "roles": "역할", + "users": "사용자" + }, + "selectLanguage": "언어 선택", + "showDetailsPanel": "세부 정보 패널 펼치기", + "sourceAssetEvent_one": "소스 에셋 이벤트", + "sourceAssetEvent_other": "소스 에셋 이벤트", + "startDate": "시작일", + "state": "상태", + "states": { + "deferred": "연기됨", + "failed": "실패", + "no_status": "상태 없음", + "none": "상태 없음", + "queued": "대기 중", + "removed": "제거됨", + "restarting": "다시 시작 중", + "running": "실행 중", + "scheduled": "예약됨", + "skipped": "건너뜀", + "success": "성공", + "up_for_reschedule": "재예약 대기 중", + "up_for_retry": "재시도 대기 중", + "upstream_failed": "업스트림 실패" + }, + "switchToDarkMode": "다크 모드로 전환", + "switchToLightMode": "라이트 모드로 전환", + "table": { + "completedAt": "완료 시간", + "createdAt": "생성 시간", + "filterByTag": "태그로 Dag 필터링", + "filterColumns": "테이블 열 필터링", + "filterReset_one": "필터 초기화", + "filterReset_other": "필터 초기화", + "from": "시작", + "maxActiveRuns": "최대 활성 실행 수", + "noTagsFound": "태그를 찾을 수 없습니다.", + "tagMode": { + "all": "모두", + "any": "모든" + }, + "tagPlaceholder": "태그로 필터링", + "to": "종료" + }, + "task": { + "documentation": "작업 문서", + "lastInstance": "마지막 인스턴스", + "operator": "연산자", + "triggerRule": "트리거 규칙" + }, + "task_one": "작업", + "task_other": "작업들", + "taskId": "작업 ID", + "taskInstance": { + "dagVersion": "Dag 버전", + "executor": "실행기", + "executorConfig": "실행기 구성", + "hostname": "호스트 이름", + "maxTries": "최대 시도 횟수", + "pid": "PID", + "pool": "풀", + "poolSlots": "풀 슬롯", + "priorityWeight": "우선순위 가중치", + "queue": "큐", + "queuedWhen": "대기열에 추가된 시간", + "scheduledWhen": "예정된 시간", + "triggerer": { + "assigned": "할당된 트리거", + "class": "트리거 클래스", + "createdAt": "트리거 생성 시간", + "id": "트리거 ID", + "latestHeartbeat": "최신 트리거 상태", + "title": "트리거 정보" + }, + "unixname": "유닉스 이름" + }, + "taskInstance_one": "작업 인스턴스", + "taskInstance_other": "작업 인스턴스들", + "timeRange": { + "last12Hours": "지난 12 시간", + "last24Hours": "지난 24 시간", + "lastHour": "지난 1시간", + "pastWeek": "지난 주" + }, + "timezone": "시간대", + "timezoneModal": { + "current-timezone": "현재 시간:", + "placeholder": "시간대 선택", + "title": "시간대 선택", + "utc": "UTC (협정 세계시)" + }, + "toaster": { + "bulkDelete": { + "error": "대량 삭제 {{resourceName}} 요청 실패", + "success": { + "description": "{{count}}개 {{resourceName}}이(가) 성공적으로 삭제되었습니다. 키: {{keys}}", + "title": "대량 삭제 {{resourceName}} 요청 제출됨" + } + }, + "create": { + "error": "생성 {{resourceName}} 요청 실패", + "success": { + "description": "{{resourceName}}이(가) 성공적으로 생성되었습니다.", + "title": "생성 {{resourceName}} 요청 제출됨" + } + }, + "delete": { + "error": "삭제 {{resourceName}} 요청 실패", + "success": { + "description": "{{resourceName}}이(가) 성공적으로 삭제되었습니다.", + "title": "삭제 {{resourceName}} 요청 제출됨" + } + }, + "import": { + "error": "가져오기 {{resourceName}} 요청 실패", + "success": { + "description": "{{count}}개 {{resourceName}}이(가) 성공적으로 가져와졌습니다.", + "title": "가져오기 {{resourceName}} 요청 제출됨" + } + }, + "update": { + "error": "업데이트 {{resourceName}} 요청 실패", + "success": { + "description": "{{resourceName}}이(가) 성공적으로 업데이트되었습니다.", + "title": "업데이트 {{resourceName}} 요청 제출됨" + } + } + }, + "triggered": "트리거됨", + "tryNumber": "시도 횟수", + "user": "사용자", + "wrap": { + "tooltip": "{{hotkey}}를 눌러 텍스트 줄바꿈 토글", + "unwrap": "줄바꿈 해제", + "wrap": "줄바꿈" + } +} diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ko/components.json b/airflow-core/src/airflow/ui/public/i18n/locales/ko/components.json new file mode 100644 index 0000000000000..79c1b7a1ccecd --- /dev/null +++ b/airflow-core/src/airflow/ui/public/i18n/locales/ko/components.json @@ -0,0 +1,131 @@ +{ + "backfill": { + "affected_one": "1개의 실행이 트리거됩니다.", + "affected_other": "{{count}}개의 실행이 트리거됩니다.", + "affectedNone": "선택한 조건과 일치하는 실행이 없습니다.", + "backwards": "거꾸로 실행", + "dateRange": "날짜 범위", + "dateRangeFrom": "시작", + "dateRangeTo": "종료", + "errorStartDateBeforeEndDate": "시작일은 종료일보다 빨라야 합니다.", + "maxRuns": "최대 활성 실행 수", + "reprocessBehavior": "재처리 동작", + "run": "백필 실행", + "selectDescription": "이 Dag을(를) 특정 날짜 범위에 대해 실행합니다.", + "selectLabel": "백필", + "title": "백필 실행", + "toaster": { + "success": { + "description": "백필 작업이 성공적으로 트리거되었습니다.", + "title": "백필 생성됨" + } + }, + "tooltip": "백필에는 일정이 필요합니다.", + "unpause": "트리거 시 {{dag_display_name}} 일시 중지 해제", + "validation": { + "datesRequired": "데이터 구간 시작일과 종료일이 모두 제공되어야 합니다.", + "startBeforeEnd": "데이터 구간 시작일은 데이터 구간 종료일보다 작거나 같아야 합니다." + } + }, + "banner": { + "backfillInProgress": "백필 진행 중", + "cancel": "백필 취소", + "pause": "백필 일시 중지", + "unpause": "백필 일시 중지 해제" + }, + "clipboard": { + "copy": "복사" + }, + "close": "닫기", + "configForm": { + "advancedOptions": "고급 옵션", + "configJson": "구성 JSON", + "invalidJson": "잘못된 JSON 형식: {{errorMessage}}" + }, + "dagWarnings": { + "error_one": "오류 1개", + "errorAndWarning": "오류 1개 및 {{warningText}}", + "warning_one": "경고 1개", + "warning_other": "경고 {{count}}개" + }, + "durationChart": { + "duration": "기간 (초)", + "lastDagRun_one": "마지막 Dag 실행", + "lastDagRun_other": "마지막 {{count}}개 Dag 실행", + "lastTaskInstance_one": "마지막 작업 인스턴스", + "lastTaskInstance_other": "마지막 {{count}}개 작업 인스턴스", + "queuedDuration": "대기열 대기 시간", + "runAfter": "실행 후", + "runDuration": "실행 기간" + }, + "fileUpload": { + "files_other": "{{count}}개 파일" + }, + "flexibleForm": { + "placeholder": "값 선택", + "placeholderArray": "각 문자열을 새 줄에 입력하세요.", + "placeholderExamples": "입력하여 옵션 보기", + "placeholderMulti": "하나 또는 여러 값 선택", + "validationErrorArrayNotArray": "값은 배열이어야 합니다.", + "validationErrorArrayNotNumbers": "배열의 모든 요소는 숫자여야 합니다.", + "validationErrorArrayNotObject": "배열의 모든 요소는 객체여야 합니다.", + "validationErrorRequired": "이 필드는 필수입니다." + }, + "graph": { + "directionDown": "위에서 아래로", + "directionLeft": "오른쪽에서 왼쪽으로", + "directionRight": "왼쪽에서 오른쪽으로", + "directionUp": "아래에서 위로", + "downloadImage": "그래프 이미지 다운로드", + "downloadImageError": "그래프 이미지를 다운로드하지 못했습니다.", + "downloadImageErrorTitle": "다운로드 실패", + "otherDagRuns": "+다른 Dag 실행", + "taskCount_one": "{{count}}개 작업", + "taskCount_other": "{{count}}개 작업", + "taskGroup": "작업 그룹" + }, + "limitedList": "+{{count}}개 더 보기", + "logs": { + "file": "파일", + "location": "{{name}}의 {{line}}번째 줄" + }, + "reparseDag": "Dag 재구문 분석", + "sortedAscending": "오름차순 정렬됨", + "sortedDescending": "내림차순 정렬됨", + "sortedUnsorted": "정렬되지 않음", + "taskTries": "작업 시도 횟수", + "toggleCardView": "카드 보기 표시", + "toggleTableView": "테이블 보기 표시", + "triggerDag": { + "button": "트리거", + "loading": "DAG 정보 로드 중...", + "loadingFailed": "DAG 정보를 로드하지 못했습니다. 다시 시도해주세요.", + "runIdHelp": "선택 사항 - 제공되지 않으면 생성됩니다.", + "selectDescription": "이 Dag을(를) 단일 실행 트리거", + "selectLabel": "단일 실행", + "title": "Dag 트리거", + "toaster": { + "success": { + "description": "Dag 실행이 성공적으로 트리거되었습니다.", + "title": "Dag 실행 트리거됨" + } + }, + "unpause": "트리거 시 {{dagDisplayName}} 일시 중지 해제" + }, + "trimText": { + "details": "세부 정보", + "empty": "비어 있음", + "noContent": "내용 없음." + }, + "versionDetails": { + "bundleLink": "번들 링크", + "bundleName": "번들 이름", + "bundleVersion": "번들 버전", + "createdAt": "생성 시간", + "versionId": "버전 ID" + }, + "versionSelect": { + "dagVersion": "Dag 버전", + "versionCode": "v{{versionCode}}" + } +} diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ko/dag.json b/airflow-core/src/airflow/ui/public/i18n/locales/ko/dag.json new file mode 100644 index 0000000000000..a8a295e88720d --- /dev/null +++ b/airflow-core/src/airflow/ui/public/i18n/locales/ko/dag.json @@ -0,0 +1,110 @@ +{ + "allRuns": "모든 실행", + "blockingDeps": { + "dependency": "종속성", + "reason": "이유", + "title": "작업 스케줄링을 막는 종속성" + }, + "code": { + "bundleUrl": "번들 URL", + "noCode": "코드를 찾을 수 없습니다.", + "parsedAt": "구문 분석 시간:" + }, + "extraLinks": "추가 링크", + "grid": { + "buttons": { + "resetToLatest": "최신 버전으로 재설정", + "toggleGroup": "그룹 토글" + } + }, + "header": { + "buttons": { + "dagDocs": "Dag 문서" + } + }, + "logs": { + "noTryNumber": "시도 횟수 없음", + "viewInExternal": "{{name}}에서 로그 보기 (시도 {{attempt}})" + }, + "overview": { + "buttons": { + "failedRun_one": "실패한 실행", + "failedRun_other": "실패한 실행", + "failedTask_one": "실패한 작업", + "failedTask_other": "실패한 작업", + "failedTaskInstance_one": "실패한 작업 인스턴스", + "failedTaskInstance_other": "실패한 작업 인스턴스" + }, + "charts": { + "assetEvent_one": "생성된 에셋 이벤트", + "assetEvent_other": "생성된 에셋 이벤트" + }, + "failedLogs": { + "title": "최근 실패한 작업 로그", + "viewFullLogs": "전체 로그 보기" + } + }, + "panel": { + "buttons": { + "options": "옵션", + "showGraph": "그래프 보기", + "showGrid": "그리드 보기" + }, + "dagRuns": { + "label": "Dag 실행 수" + }, + "dependencies": { + "label": "종속성", + "options": { + "allDagDependencies": "모든 Dag 종속성", + "externalConditions": "외부 조건", + "onlyTasks": "작업만" + }, + "placeholder": "종속성" + }, + "graphDirection": { + "label": "그래프 방향" + } + }, + "paramsFailed": "매개변수 로드 실패", + "parse": { + "toaster": { + "error": { + "description": "Dag 구문 분석 요청에 실패했습니다. 처리되지 않은 보류 중인 구문 분석 요청이 있을 수 있습니다.", + "title": "Dag 재구문 분석 실패" + }, + "success": { + "description": "Dag이(가) 곧 재구문 분석될 예정입니다.", + "title": "재구문 분석 요청이 성공적으로 제출되었습니다." + } + } + }, + "tabs": { + "assetEvents": "에셋 이벤트", + "auditLog": "감사 로그", + "backfills": "백필", + "code": "코드", + "details": "세부 정보", + "logs": "로그", + "mappedTaskInstances_one": "작업 인스턴스 [{{count}}]", + "mappedTaskInstances_other": "작업 인스턴스 [{{count}}]", + "overview": "개요", + "renderedTemplates": "렌더링된 템플릿", + "runs": "실행", + "taskInstances": "작업 인스턴스", + "tasks": "작업", + "xcom": "XCom" + }, + "taskGroups": { + "collapseAll": "모든 작업 그룹 접기", + "expandAll": "모든 작업 그룹 확장" + }, + "taskLogs": { + "allLogLevels": "모든 로그 레벨", + "allSources": "모든 소스", + "fullscreen": { + "button": "전체 화면", + "tooltip": "전체 화면을 보려면 {{hotkey}}를 누르세요." + } + } +} diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ko/dags.json b/airflow-core/src/airflow/ui/public/i18n/locales/ko/dags.json new file mode 100644 index 0000000000000..665294e4a01de --- /dev/null +++ b/airflow-core/src/airflow/ui/public/i18n/locales/ko/dags.json @@ -0,0 +1,87 @@ +{ + "assetSchedule": "{{total}}개 에셋 중 {{count}}개 업데이트됨", + "dagActions": { + "delete": { + "button": "Dag 삭제", + "warning": "실행 및 작업를 포함하여 Dag과(와) 관련된 모든 메타데이터가 제거됩니다." + } + }, + "filters": { + "allRunTypes": "모든 실행 유형", + "allStates": "모든 상태", + "paused": { + "active": "활성", + "all": "모두", + "paused": "일시 중지됨" + } + }, + "ownerLink": "{{owner}}의 소유자 링크", + "runAndTaskActions": { + "affectedTasks": { + "noItemsFound": "작업를 찾을 수 없습니다.", + "title": "영향을 받는 작업: {{count}}" + }, + "clear": { + "button": "{{type}} 지우기", + "buttonTooltip": "Shift+C를 눌러 지우기", + "error": "{{type}}을(를) 지우지 못했습니다.", + "title": "{{type}} 지우기" + }, + "delete": { + "button": "{{type}} 삭제", + "dialog": { + "resourceName": "{{type}} {{id}}", + "title": "{{type}} 삭제", + "warning": "{{type}}과(와) 관련된 모든 메타데이터가 제거됩니다." + }, + "error": "{{type}} 삭제 오류", + "success": { + "description": "{{type}} 삭제 요청이 성공했습니다.", + "title": "{{type}} 삭제 완료" + } + }, + "markAs": { + "button": "{{type}}을(를) ...으로 표시", + "buttonTooltip": { + "failed": "Shift+F를 눌러 실패로 표시", + "success": "Shift+S를 눌러 성공으로 표시" + }, + "title": "{{type}}을(를) {{state}}으로 표시" + }, + "options": { + "downstream": "다운스트림", + "existingTasks": "기존 작업 지우기", + "future": "미래", + "onlyFailed": "실패한 작업만 지우기", + "past": "과거", + "queueNew": "새 작업 대기열에 추가", + "upstream": "업스트림" + } + }, + "search": { + "advanced": "고급 검색", + "clear": "검색 지우기", + "dags": "Dag 검색", + "hotkey": "+K", + "tasks": "작업 검색" + }, + "sort": { + "displayName": { + "asc": "표시 이름으로 정렬 (A-Z)", + "desc": "표시 이름으로 정렬 (Z-A)" + }, + "lastRunStartDate": { + "asc": "최신 실행 시작 날짜로 정렬 (이전-최신)", + "desc": "최신 실행 시작 날짜로 정렬 (최신-이전)" + }, + "lastRunState": { + "asc": "최신 실행 상태로 정렬 (A-Z)", + "desc": "최신 실행 상태로 정렬 (Z-A)" + }, + "nextDagRun": { + "asc": "다음 Dag 실행으로 정렬 (이전-최신)", + "desc": "다음 Dag 실행으로 정렬 (최신-이전)" + }, + "placeholder": "정렬 기준" + } +} diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/ko/dashboard.json b/airflow-core/src/airflow/ui/public/i18n/locales/ko/dashboard.json similarity index 87% rename from airflow-core/src/airflow/ui/src/i18n/locales/ko/dashboard.json rename to airflow-core/src/airflow/ui/public/i18n/locales/ko/dashboard.json index c8f200c8eafbe..84e3529ca5cbb 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/ko/dashboard.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/ko/dashboard.json @@ -18,9 +18,9 @@ "searchByFile": "파일로 검색", "timestamp": "타임스탬프" }, - "managePools": "Pools 관리", - "noAssetEvents": "자산 이벤트를 찾을 수 없습니다.", - "poolSlots": "Pool 슬롯", + "managePools": "풀 관리", + "noAssetEvents": "에셋 이벤트를 찾을 수 없습니다.", + "poolSlots": "풀 슬롯", "sortBy": { "newestFirst": "최신순", "oldestFirst": "오래된 순" diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/nl/common.json b/airflow-core/src/airflow/ui/public/i18n/locales/nl/common.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/nl/common.json rename to airflow-core/src/airflow/ui/public/i18n/locales/nl/common.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/nl/dashboard.json b/airflow-core/src/airflow/ui/public/i18n/locales/nl/dashboard.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/nl/dashboard.json rename to airflow-core/src/airflow/ui/public/i18n/locales/nl/dashboard.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/pl/admin.json b/airflow-core/src/airflow/ui/public/i18n/locales/pl/admin.json similarity index 81% rename from airflow-core/src/airflow/ui/src/i18n/locales/pl/admin.json rename to airflow-core/src/airflow/ui/public/i18n/locales/pl/admin.json index 909a37c294d37..009d178b16202 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/pl/admin.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/pl/admin.json @@ -19,11 +19,17 @@ "host": "Host", "port": "Port" }, + "connection_few": "Połączenia", + "connection_many": "Połączeń", "connection_one": "Połączenie", "connection_other": "Połączenia", "delete": { + "deleteConnection_few": "Usuń {{count}} połączenia", + "deleteConnection_many": "Usuń {{count}} połączeń", "deleteConnection_one": "Usuń 1 połączenie", "deleteConnection_other": "Usuń {{count}} połączenia", + "firstConfirmMessage_few": "Zamierzasz usunąć następujące połączenia:", + "firstConfirmMessage_many": "Zamierzasz usunąć następujące połączenia:", "firstConfirmMessage_one": "Zamierzasz usunąć następujące połączenie:", "firstConfirmMessage_other": "Zamierzasz usunąć następujące połączenia:", "title": "Usuń połączenie" @@ -39,7 +45,12 @@ "selectConnectionType": "Wybierz typ połączenia", "standardFields": "Standardowe pola" }, - "noRowMessage": "Nie znaleziono połączeń", + "nothingFound": { + "description": "Połączenia zdefiniowane za pomocą zmiennych środowiskowych lub menedżerów sekretów nie są tutaj wyświetlane.", + "documentationLink": "Dowiedz się więcej w dokumentacji Airflow.", + "learnMore": "Są one rozwiązywane w czasie wykonywania i nie są widoczne w interfejsie użytkownika.", + "title": "Nie znaleziono połączeń!" + }, "searchPlaceholder": "Szukaj połączeń", "test": "Test połączenia", "testDisabled": "Testowanie połączeń wyłączone. Skontaktuj się z administratorem, aby je włączyć.", @@ -73,6 +84,8 @@ "columns": { "source": "Źródło" }, + "importError_few": "Błędy importu wtyczek", + "importError_many": "Błędów importu wtyczek", "importError_one": "Błąd importu wtyczki", "importError_other": "Błędy importu wtyczek", "searchPlaceholder": "Szukaj po pliku" @@ -94,6 +107,8 @@ "slots": "Miejsca" }, "noPoolsFound": "Nie znaleziono pul", + "pool_few": "Pule", + "pool_many": "Puli", "pool_one": "Pula", "pool_other": "Pule", "searchPlaceholder": "Szukaj pul", @@ -115,8 +130,12 @@ "isEncrypted": "Zaszyfrowana" }, "delete": { + "deleteVariable_few": "Usuń {{count}} zmienne", + "deleteVariable_many": "Usuń {{count}} zmiennych", "deleteVariable_one": "Usuń 1 zmienną", "deleteVariable_other": "Usuń {{count}} zmienne", + "firstConfirmMessage_few": "Zamierzasz usunąć następujące zmienne:", + "firstConfirmMessage_many": "Zamierzasz usunąć następujące zmienne:", "firstConfirmMessage_one": "Zamierzasz usunąć następującą zmienną:", "firstConfirmMessage_other": "Zamierzasz usunąć następujące zmienne:", "title": "Usuń zmienną", @@ -155,6 +174,8 @@ }, "noRowsMessage": "Nie znaleziono zmiennych", "searchPlaceholder": "Szukaj kluczy", + "variable_few": "Zmienne", + "variable_many": "Zmiennych", "variable_one": "Zmienna", "variable_other": "Zmienne" } diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/pl/assets.json b/airflow-core/src/airflow/ui/public/i18n/locales/pl/assets.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/pl/assets.json rename to airflow-core/src/airflow/ui/public/i18n/locales/pl/assets.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/pl/browse.json b/airflow-core/src/airflow/ui/public/i18n/locales/pl/browse.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/pl/browse.json rename to airflow-core/src/airflow/ui/public/i18n/locales/pl/browse.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/pl/common.json b/airflow-core/src/airflow/ui/public/i18n/locales/pl/common.json similarity index 88% rename from airflow-core/src/airflow/ui/src/i18n/locales/pl/common.json rename to airflow-core/src/airflow/ui/public/i18n/locales/pl/common.json index 46eaf9e09b955..103192006f10d 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/pl/common.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/pl/common.json @@ -7,18 +7,29 @@ "Providers": "Providery", "Variables": "Zmienne" }, + "asset_few": "Zasoby", + "asset_many": "Zasobów", "asset_one": "Zasób", "asset_other": "Zasoby", + "assetEvent_few": "Zdarzenia zasobów", + "assetEvent_many": "Zdarzeń zasobów", "assetEvent_one": "Zdarzenie Zasobu", "assetEvent_other": "Zdarzenia Zasobów", + "backfill_few": "Wypełnienia wsteczne", + "backfill_many": "Wypełnień wstecznych", "backfill_one": "Wypełnienie wsteczne", "backfill_other": "Wypełnienia wsteczne", "browse": { "auditLog": "Log audytu", "xcoms": "XComy" }, + "collapseDetailsPanel": "Zwiń panel szczegółów", + "createdAssetEvent_few": "Utworzone zdarzenia zasobów", + "createdAssetEvent_many": "Utworzonych zdarzeń zasobów", "createdAssetEvent_one": "Utworzone zdarzenie zasobu", "createdAssetEvent_other": "Utworzone zdarzenia zasobów", + "dag_few": "Dagi", + "dag_many": "Dagów", "dag_one": "Dag", "dag_other": "Dagi", "dagDetails": { @@ -56,6 +67,8 @@ "sourceAssetEvent": "Zdarzenie źródłowego zasobu", "triggeredBy": "Uruchomiony przez" }, + "dagRun_few": "Wykonania Dagów", + "dagRun_many": "Wykonań Dagów", "dagRun_one": "Wykonanie Daga", "dagRun_other": "Wykonania Dagów", "dagWarnings": "Ostrzeżenia/Błędy Daga", @@ -63,7 +76,7 @@ "defaultToGridView": "Domyślnie widok siatki", "direction": "Kierunek", "docs": { - "documentation": "Documentacja", + "documentation": "Dokumentacja", "githubRepo": "Repozytorium GitHub", "restApiReference": "Dokuentacja REST API" }, @@ -115,6 +128,8 @@ "pools": { "deferred": "Odłożone", "open": "Otwarte", + "pools_few": "Pule", + "pools_many": "Puli", "pools_one": "Pula", "pools_other": "Pule", "queued": "W kolejce", @@ -128,6 +143,13 @@ "manual": "Ręcznie", "scheduled": "Według harmonogramu" }, + "scroll": { + "direction": { + "bottom": "dół", + "top": "góra" + }, + "tooltip": "Naciśnij {{hotkey}}, aby przewinąć do {{direction}}" + }, "seconds": "{{count}}s", "security": { "actions": "Akcje", @@ -137,6 +159,9 @@ "users": "Użytkownicy" }, "selectLanguage": "Wybierz język", + "showDetailsPanel": "Pokaż panel szczegółów", + "sourceAssetEvent_few": "Zdarzenia źródłowych zasobów", + "sourceAssetEvent_many": "Zdarzeń źródłowych zasobów", "sourceAssetEvent_one": "Zdarzenie źródłowego zasobu", "sourceAssetEvent_other": "Zdarzenia źródłowych zasobów", "startDate": "Data rozpoczęcia", @@ -164,6 +189,8 @@ "createdAt": "Utworzono o", "filterByTag": "Filtruj Dagi według tagu", "filterColumns": "Filtruj kolumny tabeli", + "filterReset_few": "Resetuj filtry", + "filterReset_many": "Resetuj filtry", "filterReset_one": "Resetuj filtr", "filterReset_other": "Resetuj filtry", "from": "Od", @@ -182,6 +209,8 @@ "operator": "Operator", "triggerRule": "Reguła zależności" }, + "task_few": "Zadania", + "task_many": "Zadań", "task_one": "Zadanie", "task_other": "Zadania", "taskId": "Identifikator Zadania", @@ -208,6 +237,8 @@ }, "unixname": "Nazwa użytkownika systemu Unix" }, + "taskInstance_few": "Instancje Zadań", + "taskInstance_many": "Instancji Zadań", "taskInstance_one": "Instancja Zadania", "taskInstance_other": "Instancje Zadań", "timeRange": { diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/pl/components.json b/airflow-core/src/airflow/ui/public/i18n/locales/pl/components.json similarity index 86% rename from airflow-core/src/airflow/ui/src/i18n/locales/pl/components.json rename to airflow-core/src/airflow/ui/public/i18n/locales/pl/components.json index 533960245ab0e..dc412a3d19121 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/pl/components.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/pl/components.json @@ -1,5 +1,7 @@ { "backfill": { + "affected_few": "{{count}} wykonania zostaną uruchomione.", + "affected_many": "{{count}} wykonań zostanie uruchomionych.", "affected_one": "Dotyczy 1 wykonania.", "affected_other": "Dotyczy {{count}} wykonań.", "affectedNone": "Brak wykonań spełniających wybrane kryteria.", @@ -43,15 +45,24 @@ "invalidJson": "Nieprawidłowy format JSON: {{errorMessage}}" }, "dagWarnings": { - "error_one": "1 Błąd", + "error_few": "Błędy", + "error_many": "Błędów", + "error_one": "Błąd", + "error_other": "Błedy", "errorAndWarning": "1 Błąd i {{warningText}}", + "warning_few": "{{count}} Ostrzeżenia", + "warning_many": "{{count}} Ostrzeżeń", "warning_one": "1 Ostrzeżenie", "warning_other": "{{count}} Ostrzeżenia" }, "durationChart": { "duration": "Czas trwania (sekundy)", + "lastDagRun_few": "Ostatnie {{count}} wykonania Daga", + "lastDagRun_many": "Ostatnich {{count}} wykonań Daga", "lastDagRun_one": "Ostatnie wykonanie Daga", "lastDagRun_other": "Ostatnie {{count}} wykonania Daga", + "lastTaskInstance_few": "Ostatnie {{count}} instancje zadania", + "lastTaskInstance_many": "Ostatnich {{count}} instancji zadania", "lastTaskInstance_one": "Ostatnia instancja zadania", "lastTaskInstance_other": "Ostatnie {{count}} instancje zadania", "queuedDuration": "Czas oczekiwania", @@ -59,6 +70,9 @@ "runDuration": "Czas trwania wykonania" }, "fileUpload": { + "files_few": "{{count}} pliki", + "files_many": "{{count}} plików", + "files_one": "{{count}} plik", "files_other": "{{count}} plików" }, "flexibleForm": { @@ -80,6 +94,8 @@ "downloadImageError": "Nie udało się pobrać obrazu grafu.", "downloadImageErrorTitle": "Pobieranie nieudane", "otherDagRuns": "+Inne wykonania Daga", + "taskCount_few": "{{count}} Zadania", + "taskCount_many": "{{count}} Zadań", "taskCount_one": "{{count}} Zadanie", "taskCount_other": "{{count}} Zadań", "taskGroup": "Grupa zadań" diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/pl/dag.json b/airflow-core/src/airflow/ui/public/i18n/locales/pl/dag.json similarity index 85% rename from airflow-core/src/airflow/ui/src/i18n/locales/pl/dag.json rename to airflow-core/src/airflow/ui/public/i18n/locales/pl/dag.json index fde6f90fd8824..8e271d983561b 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/pl/dag.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/pl/dag.json @@ -28,14 +28,22 @@ }, "overview": { "buttons": { + "failedRun_few": "Nieudane wykonania", + "failedRun_many": "Nieudanych wykonań", "failedRun_one": "Nieudane wykonanie", "failedRun_other": "Nieudane wykonania", + "failedTask_few": "Nieudane zadania", + "failedTask_many": "Nieudanych zadań", "failedTask_one": "Nieudane zadanie", "failedTask_other": "Nieudane zadania", + "failedTaskInstance_few": "Nieudane instancje zadań", + "failedTaskInstance_many": "Nieudanych instancji zadań", "failedTaskInstance_one": "Nieudana instancja zadania", "failedTaskInstance_other": "Nieudane instancje zadań" }, "charts": { + "assetEvent_few": "Utworzone zdarzenia zasobów", + "assetEvent_many": "Utworzonych zdarzeń zasobów", "assetEvent_one": "Utworzone zdarzenie zasobu", "assetEvent_other": "Utworzone zdarzenia zasobów" }, @@ -86,6 +94,8 @@ "code": "Kod", "details": "Szczegóły", "logs": "Logi", + "mappedTaskInstances_few": "Instancje zadań [{{count}}]", + "mappedTaskInstances_many": "Instancji zadań [{{count}}]", "mappedTaskInstances_one": "Instancja zadania [{{count}}]", "mappedTaskInstances_other": "Instancje zadań [{{count}}]", "overview": "Przegląd", diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/pl/dags.json b/airflow-core/src/airflow/ui/public/i18n/locales/pl/dags.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/pl/dags.json rename to airflow-core/src/airflow/ui/public/i18n/locales/pl/dags.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/pl/dashboard.json b/airflow-core/src/airflow/ui/public/i18n/locales/pl/dashboard.json similarity index 90% rename from airflow-core/src/airflow/ui/src/i18n/locales/pl/dashboard.json rename to airflow-core/src/airflow/ui/public/i18n/locales/pl/dashboard.json index 1291b73f193a5..72c58e1db72f8 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/pl/dashboard.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/pl/dashboard.json @@ -13,6 +13,8 @@ }, "history": "Historia", "importErrors": { + "dagImportError_few": "Błędy importu Dagów", + "dagImportError_many": "Błędów importu Dagów", "dagImportError_one": "Błąd importu Daga", "dagImportError_other": "Błędy importu Dagów", "searchByFile": "Szukaj według plików", diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/admin.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/admin.json similarity index 98% rename from airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/admin.json rename to airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/admin.json index e64f103e5bd33..c8b9242d12179 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/admin.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/admin.json @@ -39,7 +39,9 @@ "selectConnectionType": "選擇連線類型", "standardFields": "標準欄位" }, - "noRowMessage": "找不到連線", + "nothingFound": { + "title": "找不到連線" + }, "searchPlaceholder": "搜尋連線", "test": "測試連線", "testDisabled": "測試連線功能已停用。請聯繫管理員以啟用。", diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/assets.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/assets.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/assets.json rename to airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/assets.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/browse.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/browse.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/browse.json rename to airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/browse.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/common.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/common.json similarity index 96% rename from airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/common.json rename to airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/common.json index 1b94813361e1a..8ffe50696d106 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/common.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/common.json @@ -17,6 +17,7 @@ "auditLog": "審計日誌", "xcoms": "XComs" }, + "collapseDetailsPanel": "收起詳細資訊", "createdAssetEvent_one": "已建立資源事件", "createdAssetEvent_other": "已建立資源事件", "dag_one": "Dag", @@ -128,6 +129,13 @@ "manual": "手動觸發", "scheduled": "已排程" }, + "scroll": { + "direction": { + "bottom": "最下方", + "top": "最上方" + }, + "tooltip": "按 {{hotkey}} 捲動到{{direction}}" + }, "seconds": "{{count}} 秒", "security": { "actions": "操作", @@ -137,6 +145,7 @@ "users": "使用者" }, "selectLanguage": "選擇語言", + "showDetailsPanel": "顯示詳細資訊", "sourceAssetEvent_one": "來源資源事件", "sourceAssetEvent_other": "來源資源事件", "startDate": "開始日期", @@ -223,7 +232,7 @@ "title": "選擇時區", "utc": "UTC" }, - "toaster": { + "toaster": { "bulkDelete": { "error": "批次刪除 {{resourceName}} 請求失敗", "success": { diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/components.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/components.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/components.json rename to airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/components.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/dag.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dag.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/dag.json rename to airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dag.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/dags.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dags.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/dags.json rename to airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dags.json diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/dashboard.json b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dashboard.json similarity index 100% rename from airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/dashboard.json rename to airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/dashboard.json diff --git a/airflow-core/src/airflow/ui/rules/i18n.js b/airflow-core/src/airflow/ui/rules/i18n.js index f96e71b37b7d4..309e7e65eaada 100644 --- a/airflow-core/src/airflow/ui/rules/i18n.js +++ b/airflow-core/src/airflow/ui/rules/i18n.js @@ -20,12 +20,12 @@ /* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ +import jsoncParser from "jsonc-eslint-parser"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; export const i18nNamespace = "i18n"; - /** * Extract all nested keys from translation object * @param {Record} obj @@ -50,7 +50,7 @@ const getKeys = (obj, prefix = "") => { }; // Path to locales directory -const localesDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../src/i18n/locales"); +const localesDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../public/i18n/locales"); // Default language (English) as reference const defaultLanguage = "en"; @@ -72,7 +72,7 @@ fs.readdirSync(defaultLanguageDir) }); export const i18nPlugin = { - files: ["**/i18n/locales/**/*.json"], + files: ["public/i18n/locales/**/*.json"], rules: { "check-translation-completeness": { /** @param {import('@typescript-eslint/utils').TSESLint.RuleContext<'missingKeys' | 'fileError', []>} context */ @@ -155,13 +155,17 @@ export const i18nPlugin = { /** @type {import("@typescript-eslint/utils/ts-eslint").FlatConfig.Config} */ export const i18nRules = { - files: ["**/i18n/locales/**/*.json"], + files: ["public/i18n/locales/**/*.json"], + languageOptions: { + parser: jsoncParser, + parserOptions: { + extraFileExtensions: [".json"], + }, + }, plugins: { [i18nNamespace]: i18nPlugin, }, rules: { - "@typescript-eslint/no-unused-expressions": "off", [`${i18nNamespace}/check-translation-completeness`]: "warn", - "no-unused-expressions": "off", }, }; diff --git a/airflow-core/src/airflow/ui/rules/jsonc.js b/airflow-core/src/airflow/ui/rules/jsonc.js new file mode 100644 index 0000000000000..a39418eb31ce6 --- /dev/null +++ b/airflow-core/src/airflow/ui/rules/jsonc.js @@ -0,0 +1,45 @@ +/*! + * 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 jsonc from "eslint-plugin-jsonc"; + +import { ERROR } from "./levels.js"; + +export const jsoncNamespace = "jsonc"; + +/** @type {import("@typescript-eslint/utils/ts-eslint").FlatConfig.Config} */ +export const jsoncRules = { + files: ["public/i18n/locales/**/*.json"], + plugins: { + [jsoncNamespace]: jsonc, + }, + rules: { + /** + * Enforce sorted keys. + * + * @see [jsonc/sort-keys](https://ota-meshi.github.io/eslint-plugin-jsonc/rules/sort-keys.html) + */ + [`${jsoncNamespace}/sort-keys`]: [ + ERROR, + "asc", + { + natural: true, + }, + ], + }, +}; diff --git a/airflow-core/src/airflow/ui/rules/typescript.js b/airflow-core/src/airflow/ui/rules/typescript.js index 2583b602e7264..ed05e15089799 100644 --- a/airflow-core/src/airflow/ui/rules/typescript.js +++ b/airflow-core/src/airflow/ui/rules/typescript.js @@ -38,6 +38,7 @@ export const typescriptNamespace = "@typescript-eslint"; * @see [@typescript-eslint/eslint-plugin](https://typescript-eslint.io/rules/) */ export const typescriptRules = /** @type {const} @satisfies {FlatConfig.Config} */ ({ + files: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"], languageOptions: { parser: typescriptParser, parserOptions: { diff --git a/airflow-core/src/airflow/ui/src/components/Clear/TaskInstance/ClearTaskInstanceDialog.tsx b/airflow-core/src/airflow/ui/src/components/Clear/TaskInstance/ClearTaskInstanceDialog.tsx index a26f276601d67..7458b20489896 100644 --- a/airflow-core/src/airflow/ui/src/components/Clear/TaskInstance/ClearTaskInstanceDialog.tsx +++ b/airflow-core/src/airflow/ui/src/components/Clear/TaskInstance/ClearTaskInstanceDialog.tsx @@ -110,6 +110,7 @@ const ClearTaskInstanceDialog = ({ onClose, open, taskInstance }: Props) => { { return values === undefined ? 0 : values.reduce((initial, next) => initial + next, 0) / values.length; }; -type RunResponse = DAGRunResponse | TaskInstanceResponse; +type RunResponse = GridRunsResponse | TaskInstanceResponse; const getDuration = (start: string, end: string | null) => dayjs.duration(dayjs(end).diff(start)).asSeconds(); @@ -115,7 +115,7 @@ export const DurationChart = ({ data: entries.map((entry: RunResponse) => { switch (kind) { case "Dag Run": { - const run = entry as DAGRunResponse; + const run = entry as GridRunsResponse; return run.queued_at !== null && run.start_date !== null && run.queued_at < run.start_date ? Number(getDuration(run.queued_at, run.start_date)) @@ -158,18 +158,19 @@ export const DurationChart = ({ return; } - const entry = entries[element.index]; - const baseUrl = `/dags/${entry?.dag_id}/runs/${entry?.dag_run_id}`; - switch (kind) { case "Dag Run": { + const entry = entries[element.index] as GridRunsResponse | undefined; + const baseUrl = `/dags/${entry?.dag_id}/runs/${entry?.run_id}`; + navigate(baseUrl); break; } case "Task Instance": { - const taskInstance = entry as TaskInstanceResponse; + const entry = entries[element.index] as TaskInstanceResponse | undefined; + const baseUrl = `/dags/${entry?.dag_id}/runs/${entry?.dag_run_id}`; - navigate(`${baseUrl}/tasks/${taskInstance.task_id}`); + navigate(`${baseUrl}/tasks/${entry?.task_id}`); break; } default: diff --git a/airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldRow.tsx b/airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldRow.tsx index f2596b9ac734e..3125201ceb176 100644 --- a/airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldRow.tsx +++ b/airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldRow.tsx @@ -38,8 +38,6 @@ export const FieldRow = ({ name, onUpdate: rowOnUpdate }: FlexibleFormElementPro ); const [isValid, setIsValid] = useState(!(isRequired(param) && param.value === null)); - // console.log(param); - const onUpdate = (value?: string, _error?: unknown) => { if (Boolean(_error)) { setIsValid(false); diff --git a/airflow-core/src/airflow/ui/src/components/MarkAs/TaskInstance/MarkTaskInstanceAsDialog.tsx b/airflow-core/src/airflow/ui/src/components/MarkAs/TaskInstance/MarkTaskInstanceAsDialog.tsx index afde1862458f0..c95e27013a8a7 100644 --- a/airflow-core/src/airflow/ui/src/components/MarkAs/TaskInstance/MarkTaskInstanceAsDialog.tsx +++ b/airflow-core/src/airflow/ui/src/components/MarkAs/TaskInstance/MarkTaskInstanceAsDialog.tsx @@ -107,6 +107,7 @@ const MarkTaskInstanceAsDialog = ({ onClose, open, state, taskInstance }: Props) lang.code), }); diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/ar/components.json b/airflow-core/src/airflow/ui/src/i18n/locales/ar/components.json deleted file mode 100644 index b5b9c1b43b372..0000000000000 --- a/airflow-core/src/airflow/ui/src/i18n/locales/ar/components.json +++ /dev/null @@ -1,131 +0,0 @@ -{ - "backfill": { - "affected_one": "مهمة واحدة ستُشغّل.", - "affected_other": "{{count}} مهام ستُشغّل.", - "affectedNone": "لا توجد مهام تطابق المعايير المحددة.", - "backwards": "تشغيل رجعي", - "dateRange": "نطاق التاريخ", - "dateRangeFrom": "من", - "dateRangeTo": "إلى", - "errorStartDateBeforeEndDate": "يجب أن يكون تاريخ البدء قبل تاريخ الانتهاء", - "maxRuns": "الحد الأقصى للتشغيلات النشطة", - "reprocessBehavior": "اعادة معالجة السلوك", - "run": "تشغيل التعبئة الرجعية", - "selectDescription": "تشغيل هذا DAG لنطاق من التواريخ", - "selectLabel": "تعبئة رجعية", - "title": "تشغيل التعبئة الرجعية", - "toaster": { - "success": { - "description": "تم تشغيل مهام التعبئة الرجعية بنجاح.", - "title": "تم إنشاء التعبئة الرجعية" - } - }, - "tooltip": "التعبئة الرجعية تتطلب جدول زمني", - "unpause": "إلغاء إيقاف {{dag_display_name}} عند التشغيل", - "validation": { - "datesRequired": "يجب توفير بيانات كل من تاريخ بدء فترة وتاريخ الانتهاء.", - "startBeforeEnd": "بيانات فترة تاريخ البدء يجب ان تكون من او قبل تاريخ الانتهاء. " - } - }, - "banner": { - "backfillInProgress": "التعبئة الرجعية قيد التنفيذ", - "cancel": "إلغاء التعبئة الرجعية", - "pause": "إيقاف التعبئة الرجعية", - "unpause": "إلغاء إيقاف التعبئة الرجعية" - }, - "clipboard": { - "copy": "نسخ" - }, - "close": "إغلاق", - "configForm": { - "advancedOptions": "خيارات متقدمة", - "configJson": "تكوين JSON", - "invalidJson": "تنسيق JSON غير صالح: {{errorMessage}}" - }, - "dagWarnings": { - "error_one": "1 خطأ", - "errorAndWarning": "1 خطأ و{{warningText}}", - "warning_one": "1 تحذير", - "warning_other": "{{count}} تحذيرات" - }, - "durationChart": { - "duration": "المدة (بالثواني)", - "lastDagRun_one": "آخر تشغيل DAG", - "lastDagRun_other": "آخر {{count}} تشغيلات DAG", - "lastTaskInstance_one": "آخر مثيل مهمة", - "lastTaskInstance_other": "آخر {{count}} مثيلات المهام", - "queuedDuration": "مدة الانتظار في الطابور", - "runAfter": "تشغيل بعد", - "runDuration": "مدة التشغيل" - }, - "fileUpload": { - "files_other": "{{count}} ملفات" - }, - "flexibleForm": { - "placeholder": "اختر قيمة", - "placeholderArray": "أدخل كل سلسلة في سطر جديد", - "placeholderExamples": "ابدأ الكتابة لرؤية الخيارات", - "placeholderMulti": "اختر قيمة أو أكثر", - "validationErrorArrayNotArray": "القيمة يجب أن تكون مصفوفة.", - "validationErrorArrayNotNumbers": "جميع العناصر في المصفوفة يجب أن تكون أرقامًا.", - "validationErrorArrayNotObject": "جميع العناصر في المصفوفة يجب أن تكون كائنات.", - "validationErrorRequired": "هذا الحقل مطلوب" - }, - "graph": { - "directionDown": "من الأعلى إلى الأسفل", - "directionLeft": "من اليمين إلى اليسار", - "directionRight": "من اليسار إلى اليمين", - "directionUp": "من الأسفل إلى الأعلى", - "downloadImage": "تحميل صورة الرسم البياني", - "downloadImageError": "فشل تحميل صورة الرسم البياني.", - "downloadImageErrorTitle": "فشل التحميل", - "otherDagRuns": "+تشغيلات DAG أخرى", - "taskCount_one": "{{count}} مهمة", - "taskCount_other": "{{count}} مهام", - "taskGroup": "مجموعة المهام" - }, - "limitedList": "+{{count}} المزيد", - "logs": { - "file": "ملف", - "location": "سطر {{line}} في {{name}}" - }, - "reparseDag": "إعادة تحليل DAG", - "sortedAscending": "الترتيب تصاعدي", - "sortedDescending": "الترتيب تنازلي", - "sortedUnsorted": "غير مرتب", - "taskTries": "محاولات المهمة", - "toggleCardView": "عرض البطاقة", - "toggleTableView": "عرض الجدول", - "triggerDag": { - "button": "تشغيل", - "loading": "جارٍ تحميل معلومات DAG...", - "loadingFailed": "فشل تحميل معلومات DAG. يرجى المحاولة مرة أخرى.", - "runIdHelp": "اختياري - سيتم توليده تلقائيًا إذا لم يتم توفيره.", - "selectDescription": "تشغيل عملية واحدة من هذا DAG", - "selectLabel": "تشغيلة واحدة", - "title": "تشغيل DAG", - "toaster": { - "success": { - "description": "تم تشغيل عملية DAG بنجاح.", - "title": "تم تشغيل DAG" - } - }, - "unpause": "إلغاء إيقاف {{dagDisplayName}} عند التشغيل" - }, - "trimText": { - "details": "التفاصيل", - "empty": "فارغ", - "noContent": "لا توجد محتويات متاحة." - }, - "versionDetails": { - "bundleLink": "رابط الحزمة", - "bundleName": "اسم الحزمة", - "bundleVersion": "إصدار الحزمة", - "createdAt": "تاريخ الإنشاء", - "versionId": "معرف الإصدار" - }, - "versionSelect": { - "dagVersion": "إصدار DAG", - "versionCode": "v{{versionCode}}" - } -} diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/ko/common.json b/airflow-core/src/airflow/ui/src/i18n/locales/ko/common.json deleted file mode 100644 index dc4217be1eb34..0000000000000 --- a/airflow-core/src/airflow/ui/src/i18n/locales/ko/common.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "admin": { - "Config": "설정", - "Connections": "연결들", - "Plugins": "플러그인들", - "Pools": "Pools", - "Providers": "제공자들", - "Variables": "변수들" - }, - "assetEvent_one": "에셋 이벤트", - "assetEvent_other": "에셋 이벤트들", - "browse": { - "auditLog": "감사 로그", - "xcoms": "XComs" - }, - "dagRun_one": "Dag 실행", - "dagRun_other": "Dag 실행들", - "defaultToGraphView": "그래프 뷰 기본 보기", - "defaultToGridView": "그리드 뷰 기본 보기", - "docs": { - "documentation": "문서", - "githubRepo": "GitHub 저장소", - "restApiReference": "REST API 참조" - }, - "duration": "지속 시간", - "logout": "로그아웃", - "nav": { - "admin": "관리자", - "assets": "에셋", - "browse": "탐색", - "docs": "문서", - "home": "홈", - "plugins": "플러그인" - }, - "noItemsFound": "{{modelName}} 을(를) 찾을 수 없음", - "pools": { - "deferred": "연기됨", - "open": "열림", - "pools_one": "pool", - "pools_other": "pools", - "queued": "대기 중", - "running": "실행 중", - "scheduled": "예약됨" - }, - "selectLanguage": "언어 선택", - "states": { - "deferred": "연기됨", - "failed": "실패", - "no_status": "상태 없음", - "queued": "대기 중", - "removed": "제거됨", - "restarting": "다시 시작 중", - "running": "실행 중", - "scheduled": "예약됨", - "skipped": "건너뜀", - "success": "성공", - "up_for_reschedule": "재예약 대기 중", - "up_for_retry": "재시도 대기 중", - "upstream_failed": "업스트림 실패" - }, - "switchToDarkMode": "다크 모드로 전환", - "switchToLightMode": "라이트 모드로 전환", - "taskInstance_one": "작업 인스턴스", - "taskInstance_other": "작업 인스턴스들", - "timeRange": { - "last12Hours": "지난 12 시간", - "last24Hours": "지난 24 시간", - "lastHour": "지난 1시간", - "pastWeek": "지난 주" - }, - "timezone": "시간대", - "triggered": "트리거됨", - "user": "사용자" -} diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/DagRunSelect.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/DagRunSelect.tsx index f73d9c3d49a2e..459a281ae70d2 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/DagRunSelect.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Details/DagRunSelect.tsx @@ -21,13 +21,13 @@ import { forwardRef, useMemo } from "react"; import { useTranslation } from "react-i18next"; import { useNavigate, useParams } from "react-router-dom"; -import type { GridDAGRunwithTIs } from "openapi/requests/types.gen"; +import type { GridRunsResponse } from "openapi/requests/types.gen"; import { StateBadge } from "src/components/StateBadge"; import Time from "src/components/Time"; -import { useGrid } from "src/queries/useGrid"; +import { useGridRuns } from "src/queries/useGridRuns.ts"; type DagRunSelected = { - run: GridDAGRunwithTIs; + run: GridRunsResponse; value: string; }; @@ -40,34 +40,33 @@ export const DagRunSelect = forwardRef(({ lim const { t: translate } = useTranslation(["dag", "common"]); const navigate = useNavigate(); - const { data, isLoading } = useGrid(limit); - + const { data: gridRuns, isLoading } = useGridRuns({ limit }); const runOptions = useMemo( () => createListCollection({ - items: (data?.dag_runs ?? []).map((dr: GridDAGRunwithTIs) => ({ + items: (gridRuns ?? []).map((dr: GridRunsResponse) => ({ run: dr, - value: dr.dag_run_id, + value: dr.run_id, })), }), - [data], + [gridRuns], ); const selectDagRun = ({ items }: SelectValueChangeDetails) => { - const run = items.length > 0 ? `/runs/${items[0]?.run.dag_run_id}` : ""; + const runPartialPath = items.length > 0 ? `/runs/${items[0]?.run.run_id}` : ""; navigate({ - pathname: `/dags/${dagId}${run}/${taskId === undefined ? "" : `tasks/${taskId}`}`, + pathname: `/dags/${dagId}${runPartialPath}/${taskId === undefined ? "" : `tasks/${taskId}`}`, }); }; - const selectedRun = (data?.dag_runs ?? []).find((dr) => dr.dag_run_id === runId); + const selectedRun = (gridRuns ?? []).find((dr) => dr.run_id === runId); return ( { dagId, }); const { onClose, onOpen, open } = useDisclosure(); + const [isRightPanelCollapsed, setIsRightPanelCollapsed] = useState(false); return ( @@ -79,6 +82,25 @@ export const DetailsLayout = ({ children, error, isLoading, tabs }: Props) => { + {isRightPanelCollapsed ? ( + + setIsRightPanelCollapsed(false)} + position="absolute" + right={0} + size="sm" + top="50%" + zIndex={10} + > + + + + ) : undefined} @@ -92,50 +114,78 @@ export const DetailsLayout = ({ children, error, isLoading, tabs }: Props) => { {dagView === "graph" ? : } - { - if (!isDragging) { - const zoom = getZoom(); + {!isRightPanelCollapsed && ( + { + if (!isDragging) { + const zoom = getZoom(); - void fitView({ maxZoom: zoom, minZoom: zoom }); - } - }} - > - - - - - {children} - {Boolean(error) || (warningData?.dag_warnings.length ?? 0) > 0 ? ( - <> - } - margin="2" - marginBottom="-1" - onClick={onOpen} - rounded="full" - text={String(warningData?.total_entries ?? 0 + Number(error))} - variant="solid" - /> + void fitView({ maxZoom: zoom, minZoom: zoom }); + } + }} + > + + + setIsRightPanelCollapsed(true)} + size="xs" + zIndex={2} + > + + + + + + )} + {!isRightPanelCollapsed && ( + + + {children} + {Boolean(error) || (warningData?.dag_warnings.length ?? 0) > 0 ? ( + <> + } + margin="2" + marginBottom="-1" + onClick={onOpen} + rounded="full" + text={String(warningData?.total_entries ?? 0 + Number(error))} + variant="solid" + /> - - - ) : undefined} - - - - + + + ) : undefined} + + + + + - - + + )} diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Bar.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Bar.tsx index 90480f8f79221..dbcc965c61f74 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Bar.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Bar.tsx @@ -19,27 +19,30 @@ import { Flex, Box } from "@chakra-ui/react"; import { useParams, useSearchParams } from "react-router-dom"; +import type { GridRunsResponse } from "openapi/requests"; import { RunTypeIcon } from "src/components/RunTypeIcon"; +import { useGridTiSummaries } from "src/queries/useGridTISummaries.ts"; import { GridButton } from "./GridButton"; import { TaskInstancesColumn } from "./TaskInstancesColumn"; -import type { GridTask, RunWithDuration } from "./utils"; +import type { GridTask } from "./utils"; const BAR_HEIGHT = 100; type Props = { readonly max: number; readonly nodes: Array; - readonly run: RunWithDuration; + readonly run: GridRunsResponse; }; export const Bar = ({ max, nodes, run }: Props) => { const { dagId = "", runId } = useParams(); const [searchParams] = useSearchParams(); - const isSelected = runId === run.dag_run_id; + const isSelected = runId === run.run_id; const search = searchParams.toString(); + const { data: gridTISummaries } = useGridTiSummaries(run); return ( { color="white" dagId={dagId} flexDir="column" - height={`${(run.duration / max) * BAR_HEIGHT}px`} + height={`${((run.duration ?? 0) / max) * BAR_HEIGHT}px`} justifyContent="flex-end" label={run.run_after} minHeight="14px" - runId={run.dag_run_id} + runId={run.run_id} searchParams={search} state={run.state} zIndex={1} @@ -74,7 +77,11 @@ export const Bar = ({ max, nodes, run }: Props) => { {run.run_type !== "scheduled" && } - + ); }; diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx index 5a407c355e4b3..59b8d250c6407 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx @@ -19,19 +19,22 @@ import { Box, Flex, IconButton } from "@chakra-ui/react"; import dayjs from "dayjs"; import dayjsDuration from "dayjs/plugin/duration"; -import { useMemo } from "react"; +import { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { FiChevronsRight } from "react-icons/fi"; import { Link, useParams } from "react-router-dom"; +import type { GridRunsResponse } from "openapi/requests"; import { useOpenGroups } from "src/context/openGroups"; -import { useGrid } from "src/queries/useGrid"; +import { useGridRuns } from "src/queries/useGridRuns.ts"; +import { useGridStructure } from "src/queries/useGridStructure.ts"; +import { isStatePending } from "src/utils"; import { Bar } from "./Bar"; import { DurationAxis } from "./DurationAxis"; import { DurationTick } from "./DurationTick"; import { TaskNames } from "./TaskNames"; -import { flattenNodes, type RunWithDuration } from "./utils"; +import { flattenNodes } from "./utils"; dayjs.extend(dayjsDuration); @@ -41,36 +44,47 @@ type Props = { export const Grid = ({ limit }: Props) => { const { t: translate } = useTranslation("dag"); + + const [selectedIsVisible, setSelectedIsVisible] = useState(); + const [hasActiveRun, setHasActiveRun] = useState(); const { openGroupIds } = useOpenGroups(); - const { dagId = "" } = useParams(); + const { dagId = "", runId = "" } = useParams(); - const { data: gridData, isLoading, runAfter } = useGrid(limit); + const { data: gridRuns, isLoading } = useGridRuns({ limit }); - const runs: Array = useMemo( - () => - (gridData?.dag_runs ?? []).map((run) => { - const duration = dayjs - .duration(dayjs(run.end_date ?? undefined).diff(run.start_date ?? undefined)) - .asSeconds(); + // Check if the selected dag run is inside of the grid response, if not, we'll update the grid filters + // Eventually we should redo the api endpoint to make this work better + useEffect(() => { + if (gridRuns && runId) { + const run = gridRuns.find((dr: GridRunsResponse) => dr.run_id === runId); - return { - ...run, - duration, - }; - }), - [gridData?.dag_runs], - ); + if (!run) { + setSelectedIsVisible(false); + } + } + }, [runId, gridRuns, selectedIsVisible, setSelectedIsVisible]); + + useEffect(() => { + if (gridRuns) { + const run = gridRuns.some((dr: GridRunsResponse) => isStatePending(dr.state)); + if (!run) { + setHasActiveRun(false); + } + } + }, [gridRuns, setHasActiveRun]); + + const { data: dagStructure } = useGridStructure({ hasActiveRun, limit }); // calculate dag run bar heights relative to max const max = Math.max.apply( undefined, - runs.map((dr) => dr.duration), - ); - - const { flatNodes } = useMemo( - () => flattenNodes(gridData === undefined ? [] : gridData.structure.nodes, openGroupIds), - [gridData, openGroupIds], + gridRuns === undefined + ? [] + : gridRuns + .map((dr: GridRunsResponse) => dr.duration) + .filter((duration: number | null): duration is number => duration !== null), ); + const { flatNodes } = useMemo(() => flattenNodes(dagStructure, openGroupIds), [dagStructure, openGroupIds]); return ( @@ -83,7 +97,7 @@ export const Grid = ({ limit }: Props) => { - {Boolean(runs.length) && ( + {Boolean(gridRuns?.length) && ( <> @@ -92,11 +106,11 @@ export const Grid = ({ limit }: Props) => { )} - {runs.map((dr) => ( - + {gridRuns?.map((dr: GridRunsResponse) => ( + ))} - {runAfter === undefined ? undefined : ( + {selectedIsVisible === undefined || !selectedIsVisible ? undefined : ( ; readonly runId: string; - readonly taskInstances: Array; + readonly taskInstances: Array; }; export const TaskInstancesColumn = ({ nodes, runId, taskInstances }: Props) => { @@ -37,6 +37,7 @@ export const TaskInstancesColumn = ({ nodes, runId, taskInstances }: Props) => { const search = searchParams.toString(); return nodes.map((node) => { + // todo: how does this work with mapped? same task id for multiple tis const taskInstance = taskInstances.find((ti) => ti.task_id === node.id); if (!taskInstance) { diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/utils.ts b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/utils.ts index 4b17098faff63..d278597267a14 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/utils.ts +++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/utils.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import type { GridDAGRunwithTIs, NodeResponse } from "openapi/requests/types.gen"; +import type { GridDAGRunwithTIs, GridNodeResponse } from "openapi/requests/types.gen"; export type RunWithDuration = { duration: number; @@ -26,31 +26,33 @@ export type GridTask = { depth: number; isGroup?: boolean; isOpen?: boolean; -} & NodeResponse; +} & GridNodeResponse; -export const flattenNodes = (nodes: Array, openGroupIds: Array, depth: number = 0) => { +export const flattenNodes = ( + nodes: Array | undefined, + openGroupIds: Array, + depth: number = 0, +) => { let flatNodes: Array = []; let allGroupIds: Array = []; - nodes.forEach((node) => { - if (node.type === "task") { - if (node.children) { - const { children, ...rest } = node; - - flatNodes.push({ ...rest, depth, isGroup: true, isOpen: openGroupIds.includes(node.id) }); - allGroupIds.push(node.id); - - const { allGroupIds: childGroupIds, flatNodes: childNodes } = flattenNodes( - children, - openGroupIds, - depth + 1, - ); - - flatNodes = [...flatNodes, ...(openGroupIds.includes(node.id) ? childNodes : [])]; - allGroupIds = [...allGroupIds, ...childGroupIds]; - } else { - flatNodes.push({ ...node, depth }); - } + nodes?.forEach((node) => { + if (node.children) { + const { children, ...rest } = node; + + flatNodes.push({ ...rest, depth, isGroup: true, isOpen: openGroupIds.includes(node.id) }); + allGroupIds.push(node.id); + + const { allGroupIds: childGroupIds, flatNodes: childNodes } = flattenNodes( + children, + openGroupIds, + depth + 1, + ); + + flatNodes = [...flatNodes, ...(openGroupIds.includes(node.id) ? childNodes : [])]; + allGroupIds = [...allGroupIds, ...childGroupIds]; + } else { + flatNodes.push({ ...node, depth }); } }); diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/ToggleGroups.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/ToggleGroups.tsx index a412a99af2e95..69ffc13866a2f 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/ToggleGroups.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Details/ToggleGroups.tsx @@ -21,23 +21,22 @@ import { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { MdExpand, MdCompress } from "react-icons/md"; import { useParams } from "react-router-dom"; +import { useLocalStorage } from "usehooks-ts"; -import { useStructureServiceStructureData } from "openapi/queries"; import { useOpenGroups } from "src/context/openGroups"; +import { useGridStructure } from "src/queries/useGridStructure.ts"; import { flattenNodes } from "./Grid/utils"; export const ToggleGroups = (props: ButtonGroupProps) => { const { t: translate } = useTranslation(); - const { dagId = "" } = useParams(); - const { data: structure } = useStructureServiceStructureData({ - dagId, - }); const { openGroupIds, setOpenGroupIds } = useOpenGroups(); - + const { dagId = "" } = useParams(); + const [limit] = useLocalStorage(`dag_runs_limit-${dagId}`, 10); + const { data: dagStructure } = useGridStructure({ limit }); const { allGroupIds } = useMemo( - () => flattenNodes(structure?.nodes ?? [], openGroupIds), - [structure?.nodes, openGroupIds], + () => flattenNodes(dagStructure, openGroupIds), + [dagStructure, openGroupIds], ); // Don't show button if the DAG has no task groups diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/NavButton.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/NavButton.tsx index 23f837cd7c62f..6c0eec7f18e7f 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/NavButton.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/NavButton.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Box, Button, type ButtonProps } from "@chakra-ui/react"; +import { Box, Button, Link, type ButtonProps } from "@chakra-ui/react"; import type { ReactElement } from "react"; import { NavLink } from "react-router-dom"; @@ -33,16 +33,24 @@ const styles = { type NavButtonProps = { readonly icon: ReactElement; + readonly isExternal?: boolean; readonly title?: string; readonly to?: string; } & ButtonProps; -export const NavButton = ({ icon, title, to, ...rest }: NavButtonProps) => +export const NavButton = ({ icon, isExternal = false, title, to, ...rest }: NavButtonProps) => to === undefined ? ( + ) : isExternal ? ( + + + ) : ( {({ isActive }: { readonly isActive: boolean }) => ( diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenuItem.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenuItem.tsx new file mode 100644 index 0000000000000..28b777570501d --- /dev/null +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenuItem.tsx @@ -0,0 +1,92 @@ +/*! + * 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 { Box, Link, Image } from "@chakra-ui/react"; +import { LuPlug } from "react-icons/lu"; +import { Link as RouterLink } from "react-router-dom"; + +import type { ExternalViewResponse } from "openapi/requests/types.gen"; + +import { NavButton } from "./NavButton"; + +type Props = { readonly topLevel?: boolean } & ExternalViewResponse; + +export const PluginMenuItem = ({ href, icon, name, topLevel = false, url_route: urlRoute }: Props) => { + // External Link + if (urlRoute === undefined || urlRoute === null) { + return topLevel ? ( + + ) : ( + + ) + } + isExternal={true} + key={name} + title={name} + to={href} + /> + ) : ( + + + {name} + + + ); + } + + // Embedded External Link via iframes + if (topLevel) { + return ( + + ) : ( + + ) + } + key={name} + title={name} + to={`plugin/${urlRoute}`} + /> + ); + } + + return ( + + + {typeof icon === "string" ? ( + + ) : ( + + )} + {name} + + + ); +}; diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenus.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenus.tsx index 7ff5c58d3bbb7..13fde6fa66371 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenus.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/PluginMenus.tsx @@ -16,98 +16,65 @@ * specific language governing permissions and limitations * under the License. */ -import { Box, Link, Image } from "@chakra-ui/react"; +import { Box } from "@chakra-ui/react"; import { useTranslation } from "react-i18next"; import { FiChevronRight } from "react-icons/fi"; import { LuPlug } from "react-icons/lu"; -import { Link as RouterLink } from "react-router-dom"; import { usePluginServiceGetPlugins } from "openapi/queries"; -import type { AppBuilderMenuItemResponse } from "openapi/requests/types.gen"; +import type { ExternalViewResponse } from "openapi/requests/types.gen"; import { Menu } from "src/components/ui"; import { NavButton } from "./NavButton"; +import { PluginMenuItem } from "./PluginMenuItem"; export const PluginMenus = () => { const { t: translate } = useTranslation("common"); const { data } = usePluginServiceGetPlugins(); - const menuPlugins = data?.plugins.filter((plugin) => plugin.appbuilder_menu_items.length > 0); - const iframePlugins = - data?.plugins.flatMap((plugin) => plugin.iframe_views).filter((view) => view.destination === "nav") ?? []; + const menuPlugins = + data?.plugins.flatMap((plugin) => plugin.external_views).filter((view) => view.destination === "nav") ?? + []; - // Only show iframe plugins in menu if there are more than 2 - const menuIframePlugins = iframePlugins.length > 2 ? iframePlugins : []; - const directIframePlugins = iframePlugins.length <= 2 ? iframePlugins : []; + // Only show external plugins in menu if there are more than 2 + const menuExternalViews = menuPlugins.length > 2 ? menuPlugins : []; + const directExternalViews = menuPlugins.length <= 2 ? menuPlugins : []; - if (data === undefined || (menuPlugins === undefined && iframePlugins.length === 0)) { + if (data === undefined || menuPlugins.length === 0) { return undefined; } - const categories: Record> = {}; - const buttons: Array = []; + const categories: Record> = {}; + const buttons: Array = []; - menuPlugins?.forEach((plugin) => { - plugin.appbuilder_menu_items.forEach((mi) => { - if (mi.category !== null && mi.category !== undefined) { - categories[mi.category] = [...(categories[mi.category] ?? []), mi]; - } else { - buttons.push(mi); - } - }); + menuPlugins.forEach((externalView) => { + if (externalView.category !== null && externalView.category !== undefined) { + categories[externalView.category] = [...(categories[externalView.category] ?? []), externalView]; + } else { + buttons.push(externalView); + } }); - if (!buttons.length && !Object.keys(categories).length && iframePlugins.length === 0) { + if (!buttons.length && !Object.keys(categories).length && menuPlugins.length === 0) { return undefined; } return ( <> - {directIframePlugins.map((plugin) => ( - - ) : ( - - ) - } - key={plugin.name} - title={plugin.name} - to={`plugin/${plugin.url_route ?? plugin.name.toLowerCase().replace(" ", "-")}`} - /> + {directExternalViews.map((externalView) => ( + ))} - {(menuIframePlugins.length > 0 || buttons.length > 0 || Object.keys(categories).length > 0) && ( + {menuExternalViews.length > 0 && ( } title={translate("nav.plugins")} /> - {menuIframePlugins.map((plugin) => ( - - - {typeof plugin.icon === "string" ? ( - - ) : ( - - )} - - {plugin.name} - - + {buttons.map((externalView) => ( + + ))} - {buttons.map(({ href, name }) => - href !== null && href !== undefined ? ( - - - {name} - - - ) : undefined, - )} {Object.entries(categories).map(([key, menuButtons]) => ( @@ -115,15 +82,11 @@ export const PluginMenus = () => { - {menuButtons.map(({ href, name }) => - href !== undefined && href !== null ? ( - - - {name} - - - ) : undefined, - )} + {menuButtons.map((externalView) => ( + + + + ))} ))} diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/TimezoneSelector.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/TimezoneSelector.tsx index 8be9fd9a650b7..7a458f668c3a2 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/TimezoneSelector.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/TimezoneSelector.tsx @@ -21,7 +21,7 @@ import { Select, type SingleValue } from "chakra-react-select"; import dayjs from "dayjs"; import timezone from "dayjs/plugin/timezone"; import utc from "dayjs/plugin/utc"; -import React, { useMemo } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { useTimezone } from "src/context/timezone"; @@ -33,6 +33,8 @@ dayjs.extend(timezone); const TimezoneSelector: React.FC = () => { const { selectedTimezone, setSelectedTimezone } = useTimezone(); const { t: translate } = useTranslation("common"); + const [currentTime, setCurrentTime] = useState(""); + const timezones = useMemo>(() => { const tzList = Intl.supportedValuesOf("timeZone"); const guessedTz = dayjs.tz.guess(); @@ -56,7 +58,17 @@ const TimezoneSelector: React.FC = () => { } }; - const currentTime = dayjs().tz(selectedTimezone).format("YYYY-MM-DD HH:mm:ss"); + useEffect(() => { + const updateTime = () => { + setCurrentTime(dayjs().tz(selectedTimezone).format("YYYY-MM-DD HH:mm:ss")); + }; + + updateTime(); + + const interval = setInterval(updateTime, 1000); + + return () => clearInterval(interval); + }, [selectedTimezone]); return ( diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx index 4eca5ea77d8c5..3b9321525ad58 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx @@ -20,7 +20,7 @@ import { useDisclosure } from "@chakra-ui/react"; import dayjs from "dayjs"; import timezone from "dayjs/plugin/timezone"; import utc from "dayjs/plugin/utc"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { FiClock, FiGrid, FiLogOut, FiMoon, FiSun, FiUser, FiGlobe } from "react-icons/fi"; import { MdOutlineAccountTree } from "react-icons/md"; @@ -49,8 +49,20 @@ export const UserSettingsButton = () => { const [time, setTime] = useState(dayjs()); + useEffect(() => { + const updateTime = () => { + setTime(dayjs()); + }; + + updateTime(); + + const interval = setInterval(updateTime, 1000); + + return () => clearInterval(interval); + }, [selectedTimezone]); + return ( - setTime(dayjs())} positioning={{ placement: "right" }}> + } title={translate("user")} /> diff --git a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx index bf921a1de3c99..9e4e38647eaf4 100644 --- a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx @@ -57,7 +57,7 @@ const ConnectionForm = ({ const { conf: extra, setConf } = useParamStore(); const { control, - formState: { isValid }, + formState: { isDirty, isValid }, handleSubmit, reset, watch, @@ -94,6 +94,14 @@ const ConnectionForm = ({ mutateConnection(data); }; + const hasChanges = () => { + if (isDirty) { + return true; + } + + return JSON.stringify(JSON.parse(extra)) !== JSON.stringify(JSON.parse(initialConnection.extra)); + }; + const validateAndPrettifyJson = (value: string) => { try { const parsedJson = JSON.parse(value) as JSON; @@ -234,7 +242,7 @@ const ConnectionForm = ({