From e0dd33fdc9e6b495e50cd73d70a7a249639bd425 Mon Sep 17 00:00:00 2001 From: schutzbot Date: Wed, 20 Aug 2025 08:35:04 +0000 Subject: [PATCH 01/16] Post release version bump [skip ci] --- cockpit/cockpit-image-builder.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cockpit/cockpit-image-builder.spec b/cockpit/cockpit-image-builder.spec index 213d9af1..85988df4 100644 --- a/cockpit/cockpit-image-builder.spec +++ b/cockpit/cockpit-image-builder.spec @@ -1,5 +1,5 @@ Name: cockpit-image-builder -Version: 74 +Version: 75 Release: 1%{?dist} Summary: Image builder plugin for Cockpit From 0e7f5d9e7baecf016ee3b28a34fa614d27d67062 Mon Sep 17 00:00:00 2001 From: Sanne Raymaekers Date: Thu, 14 Aug 2025 13:17:31 +0200 Subject: [PATCH 02/16] plans: add gating tests This tmt[0] test runs the playwright tests as gating tests. Having the gating tests upstream avoids duplication across fedora and centos dist-git repositories, and running them upstream should keep them in working order. Only add x86_64 for now, the aarch runners seem to be a bit too slow. [0]: https://tmt.readthedocs.io/en/stable/index.html --- .fmf/version | 1 + packit.yaml | 10 +++++++++- plans/all.fmf | 14 ++++++++++++++ schutzbot/playwright.fmf | 8 ++++++++ schutzbot/playwright_tests.sh | 35 +++++++++++++++++++---------------- 5 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 .fmf/version create mode 100644 plans/all.fmf create mode 100644 schutzbot/playwright.fmf diff --git a/.fmf/version b/.fmf/version new file mode 100644 index 00000000..d00491fd --- /dev/null +++ b/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/packit.yaml b/packit.yaml index bd019940..2cbf432b 100644 --- a/packit.yaml +++ b/packit.yaml @@ -16,6 +16,15 @@ srpm_build_deps: - npm jobs: + - job: tests + identifier: self + trigger: pull_request + tmt_plan: /plans/all/main + targets: + - centos-stream-10 + - fedora-41 + - fedora-42 + - job: copr_build trigger: pull_request targets: &build_targets @@ -24,7 +33,6 @@ jobs: - centos-stream-10 - centos-stream-10-aarch64 - fedora-all - - fedora-all-aarch64 - job: copr_build trigger: commit diff --git a/plans/all.fmf b/plans/all.fmf new file mode 100644 index 00000000..66deae89 --- /dev/null +++ b/plans/all.fmf @@ -0,0 +1,14 @@ +summary: cockpit-image-builder playwright tests +prepare: + how: install + package: + - cockpit-image-builder +discover: + how: fmf +execute: + how: tmt + +/main: + summary: playwright tests + discover+: + test: /schutzbot/playwright diff --git a/schutzbot/playwright.fmf b/schutzbot/playwright.fmf new file mode 100644 index 00000000..bbc5721a --- /dev/null +++ b/schutzbot/playwright.fmf @@ -0,0 +1,8 @@ +summary: run playwright tests +test: ./playwright_tests.sh +require: + - cockpit-image-builder + - podman + - nodejs + - nodejs-npm +duration: 30m diff --git a/schutzbot/playwright_tests.sh b/schutzbot/playwright_tests.sh index d6a5a87f..2ad039e4 100755 --- a/schutzbot/playwright_tests.sh +++ b/schutzbot/playwright_tests.sh @@ -1,16 +1,16 @@ #!/bin/bash set -euo pipefail -# As playwright isn't supported on fedora/el, install dependencies -# beforehand. -sudo dnf install -y \ - alsa-lib \ - libXrandr-devel \ - libXdamage-devel \ - libXcomposite-devel \ - at-spi2-atk-devel \ - cups \ - atk +TMT_SOURCE_DIR=${TMT_SOURCE_DIR:-} +if [ -n "$TMT_SOURCE_DIR" ]; then + # Move to the directory with sources + cd "${TMT_SOURCE_DIR}/cockpit-image-builder" + npm ci +elif [ "${CI:-}" != "true" ]; then + # packit drops us into the schutzbot directory + cd ../ + npm ci +fi sudo systemctl enable --now cockpit.socket @@ -19,10 +19,13 @@ sudo usermod -aG wheel admin echo "admin ALL=(ALL:ALL) NOPASSWD: ALL" | sudo tee "/etc/sudoers.d/admin-nopasswd" function upload_artifacts { - mkdir -p /tmp/artifacts/extra-screenshots - USER="$(whoami)" - sudo chown -R "$USER:$USER" playwright-report - mv playwright-report /tmp/artifacts/ + if [ -n "${TMT_TEST_DATA:-}" ]; then + mv playwright-report "$TMT_TEST_DATA"/playwright-report + else + USER="$(whoami)" + sudo chown -R "$USER:$USER" playwright-report + mv playwright-report /tmp/artifacts/ + fi } trap upload_artifacts EXIT @@ -73,8 +76,8 @@ sudo podman run \ -e "CI=true" \ -e "PLAYWRIGHT_USER=admin" \ -e "PLAYWRIGHT_PASSWORD=foobar" \ - -e "CURRENTS_PROJECT_ID=$CURRENTS_PROJECT_ID" \ - -e "CURRENTS_RECORD_KEY=$CURRENTS_RECORD_KEY" \ + -e "CURRENTS_PROJECT_ID=${CURRENTS_PROJECT_ID:-}" \ + -e "CURRENTS_RECORD_KEY=${CURRENTS_RECORD_KEY:-}" \ --net=host \ -v "$PWD:/tests" \ -v '/etc:/etc' \ From fa0560ac4d9216ce87dc700288201b7414d97488 Mon Sep 17 00:00:00 2001 From: Sanne Raymaekers Date: Tue, 19 Aug 2025 12:46:50 +0200 Subject: [PATCH 03/16] playwright: wait until distro and arch have been initialized On-prem the distro and architecture are set after the wizard has been opened. This triggers a reload of the image types and makes the tests very flaky. --- playwright/helpers/helpers.ts | 43 ++++++++++++++++++++++++++++++++ playwright/helpers/navHelpers.ts | 11 ++++++-- schutzbot/playwright_tests.sh | 1 + 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/playwright/helpers/helpers.ts b/playwright/helpers/helpers.ts index 33291ac0..9b086de7 100644 --- a/playwright/helpers/helpers.ts +++ b/playwright/helpers/helpers.ts @@ -1,3 +1,6 @@ +import { execSync } from 'child_process'; +import { readFileSync } from 'node:fs'; + import { expect, type Page } from '@playwright/test'; export const togglePreview = async (page: Page) => { @@ -42,3 +45,43 @@ export const closePopupsIfExist = async (page: Page) => { }); } }; + +// copied over from constants +const ON_PREM_RELEASES = new Map([ + ['centos-10', 'CentOS Stream 10'], + ['fedora-41', 'Fedora Linux 41'], + ['fedora-42', 'Fedora Linux 42'], + ['rhel-10', 'Red Hat Enterprise Linux (RHEL) 10'], +]); + +/* eslint-disable @typescript-eslint/no-explicit-any */ +export const getHostDistroName = (): string => { + const osRelData = readFileSync('/etc/os-release'); + const lines = osRelData + .toString('utf-8') + .split('\n') + .filter((l) => l !== ''); + const osRel = {}; + + for (const l of lines) { + const lineData = l.split('='); + (osRel as any)[lineData[0]] = lineData[1].replace(/"/g, ''); + } + + // strip minor version from rhel + const distro = ON_PREM_RELEASES.get( + `${(osRel as any)['ID']}-${(osRel as any)['VERSION_ID'].split('.')[0]}`, + ); + + if (distro === undefined) { + /* eslint-disable no-console */ + console.error('getHostDistroName failed, os-release config:', osRel); + throw new Error('getHostDistroName failed, distro undefined'); + } + + return distro; +}; + +export const getHostArch = (): string => { + return execSync('uname -m').toString('utf-8').replace(/\s/g, ''); +}; diff --git a/playwright/helpers/navHelpers.ts b/playwright/helpers/navHelpers.ts index 40c1007c..0fa6fe1d 100644 --- a/playwright/helpers/navHelpers.ts +++ b/playwright/helpers/navHelpers.ts @@ -1,6 +1,6 @@ -import type { FrameLocator, Page } from '@playwright/test'; +import { expect, FrameLocator, Page } from '@playwright/test'; -import { isHosted } from './helpers'; +import { getHostArch, getHostDistroName, isHosted } from './helpers'; /** * Opens the wizard, fills out the "Image Output" step, and navigates to the optional steps @@ -8,6 +8,13 @@ import { isHosted } from './helpers'; */ export const navigateToOptionalSteps = async (page: Page | FrameLocator) => { await page.getByRole('button', { name: 'Create image blueprint' }).click(); + if (!isHosted()) { + // wait until the distro and architecture aligns with the host + await expect(page.getByTestId('release_select')).toHaveText( + getHostDistroName(), + ); + await expect(page.getByTestId('arch_select')).toHaveText(getHostArch()); + } await page.getByRole('checkbox', { name: 'Virtualization' }).click(); await page.getByRole('button', { name: 'Next' }).click(); }; diff --git a/schutzbot/playwright_tests.sh b/schutzbot/playwright_tests.sh index 2ad039e4..052faed2 100755 --- a/schutzbot/playwright_tests.sh +++ b/schutzbot/playwright_tests.sh @@ -81,6 +81,7 @@ sudo podman run \ --net=host \ -v "$PWD:/tests" \ -v '/etc:/etc' \ + -v '/etc/os-release:/etc/os-release' \ --privileged \ --rm \ --init \ From 957700adccb3a9dff131172ee1eb7a95cc34e52f Mon Sep 17 00:00:00 2001 From: Sanne Raymaekers Date: Tue, 19 Aug 2025 16:16:36 +0200 Subject: [PATCH 04/16] .gitlab-ci.yml: switch to rhel-10.1 nightly --- .gitlab-ci.yml | 3 +-- schutzbot/terraform | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0948c85c..9cbc9f7a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -32,8 +32,7 @@ test: - RUNNER: - aws/fedora-41-x86_64 - aws/fedora-42-x86_64 - - aws/rhel-9.6-nightly-x86_64 - - aws/rhel-10.0-nightly-x86_64 + - aws/rhel-10.1-nightly-x86_64 INTERNAL_NETWORK: ["true"] finish: diff --git a/schutzbot/terraform b/schutzbot/terraform index 9a64fd4c..a3ddc921 100644 --- a/schutzbot/terraform +++ b/schutzbot/terraform @@ -1 +1 @@ -7b4735d287dd0950e0a6f47dde65b62b0f239da1 +cf0a810fd3b75fa27139746c4dfe72222e13dcba From 0d917c3cd81f93e54bc672f75ab98c70f2c276ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Aug 2025 06:54:49 +0000 Subject: [PATCH 05/16] build(deps-dev): bump @types/node from 24.1.0 to 24.3.0 Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.1.0 to 24.3.0. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 24.3.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 30 +++++++++++++++--------------- package.json | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 19bf3fde..f4c24492 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,7 +49,7 @@ "@testing-library/jest-dom": "6.6.4", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", - "@types/node": "24.1.0", + "@types/node": "24.3.0", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", "@types/react-redux": "7.1.34", @@ -5577,12 +5577,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz", - "integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==", + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz", + "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==", "license": "MIT", "dependencies": { - "undici-types": "~7.8.0" + "undici-types": "~7.10.0" } }, "node_modules/@types/node-forge": { @@ -19390,9 +19390,9 @@ } }, "node_modules/undici-types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", - "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -23977,11 +23977,11 @@ "dev": true }, "@types/node": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz", - "integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==", + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz", + "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==", "requires": { - "undici-types": "~7.8.0" + "undici-types": "~7.10.0" } }, "@types/node-forge": { @@ -32748,9 +32748,9 @@ } }, "undici-types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", - "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==" + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==" }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.1", diff --git a/package.json b/package.json index 171dba95..1ddc2ef3 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@testing-library/jest-dom": "6.6.4", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", - "@types/node": "24.1.0", + "@types/node": "24.3.0", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", "@types/react-redux": "7.1.34", From 0b96c64c930b23a592d69537108d9d3dcb7ad19d Mon Sep 17 00:00:00 2001 From: Gianluca Zuccarelli Date: Wed, 20 Aug 2025 14:20:07 +0100 Subject: [PATCH 06/16] devDeps: Bump typescript deps This bumps @typescript-eslint/eslint-plugin and @typescript-eslint/parser from 8.40.0 to 8.40.0. These need to be bumped in tandem. --- package-lock.json | 995 ++-------------------------------------------- package.json | 4 +- 2 files changed, 45 insertions(+), 954 deletions(-) diff --git a/package-lock.json b/package-lock.json index f4c24492..d593079a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,8 +54,8 @@ "@types/react-dom": "18.3.1", "@types/react-redux": "7.1.34", "@types/uuid": "10.0.0", - "@typescript-eslint/eslint-plugin": "8.39.1", - "@typescript-eslint/parser": "8.39.1", + "@typescript-eslint/eslint-plugin": "8.40.0", + "@typescript-eslint/parser": "8.40.0", "@vitejs/plugin-react": "4.7.0", "@vitest/coverage-v8": "3.2.4", "babel-loader": "10.0.0", @@ -5712,17 +5712,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.1.tgz", - "integrity": "sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz", + "integrity": "sha512-w/EboPlBwnmOBtRbiOvzjD+wdiZdgFeo17lkltrtn7X37vagKKWJABvyfsJXTlHe6XBzugmYgd4A4nW+k8Mixw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.39.1", - "@typescript-eslint/type-utils": "8.39.1", - "@typescript-eslint/utils": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", + "@typescript-eslint/scope-manager": "8.40.0", + "@typescript-eslint/type-utils": "8.40.0", + "@typescript-eslint/utils": "8.40.0", + "@typescript-eslint/visitor-keys": "8.40.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -5736,166 +5736,11 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.39.1", + "@typescript-eslint/parser": "^8.40.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/project-service": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", - "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.39.1", - "@typescript-eslint/types": "^8.39.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", - "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", - "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", - "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", - "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.39.1", - "@typescript-eslint/tsconfig-utils": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", - "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/typescript-estree": "8.39.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", - "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.39.1", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-visitor-keys": { - "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": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", @@ -5906,19 +5751,6 @@ "node": ">= 4" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -5933,16 +5765,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.39.1.tgz", - "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.40.0.tgz", + "integrity": "sha512-jCNyAuXx8dr5KJMkecGmZ8KI61KBUhkCob+SD+C+I5+Y1FWI2Y3QmY4/cxMCC5WAsZqoEtEETVhUiUMIGCf6Bw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/typescript-estree": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", + "@typescript-eslint/scope-manager": "8.40.0", + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/typescript-estree": "8.40.0", + "@typescript-eslint/visitor-keys": "8.40.0", "debug": "^4.3.4" }, "engines": { @@ -5957,163 +5789,6 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/project-service": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", - "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.39.1", - "@typescript-eslint/types": "^8.39.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", - "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", - "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", - "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", - "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.39.1", - "@typescript-eslint/tsconfig-utils": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", - "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.39.1", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { - "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": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, "node_modules/@typescript-eslint/project-service": { "version": "8.40.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.40.0.tgz", @@ -6172,15 +5847,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.39.1.tgz", - "integrity": "sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.40.0.tgz", + "integrity": "sha512-eE60cK4KzAc6ZrzlJnflXdrMqOBaugeukWICO2rB0KNvwdIMaEaYiywwHMzA1qFpTxrLhN9Lp4E/00EgWcD3Ow==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/typescript-estree": "8.39.1", - "@typescript-eslint/utils": "8.39.1", + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/typescript-estree": "8.40.0", + "@typescript-eslint/utils": "8.40.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -6196,174 +5871,6 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/project-service": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", - "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.39.1", - "@typescript-eslint/types": "^8.39.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", - "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", - "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", - "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", - "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.39.1", - "@typescript-eslint/tsconfig-utils": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", - "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/typescript-estree": "8.39.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", - "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.39.1", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": { - "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": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/type-utils/node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -19262,109 +18769,6 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz", - "integrity": "sha512-w/EboPlBwnmOBtRbiOvzjD+wdiZdgFeo17lkltrtn7X37vagKKWJABvyfsJXTlHe6XBzugmYgd4A4nW+k8Mixw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.40.0", - "@typescript-eslint/type-utils": "8.40.0", - "@typescript-eslint/utils": "8.40.0", - "@typescript-eslint/visitor-keys": "8.40.0", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.40.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.40.0.tgz", - "integrity": "sha512-jCNyAuXx8dr5KJMkecGmZ8KI61KBUhkCob+SD+C+I5+Y1FWI2Y3QmY4/cxMCC5WAsZqoEtEETVhUiUMIGCf6Bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.40.0", - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/typescript-estree": "8.40.0", - "@typescript-eslint/visitor-keys": "8.40.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.40.0.tgz", - "integrity": "sha512-eE60cK4KzAc6ZrzlJnflXdrMqOBaugeukWICO2rB0KNvwdIMaEaYiywwHMzA1qFpTxrLhN9Lp4E/00EgWcD3Ow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/typescript-estree": "8.40.0", - "@typescript-eslint/utils": "8.40.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/typescript-eslint/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/typescript-eslint/node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, "node_modules/ufo": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", @@ -24095,114 +23499,28 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.1.tgz", - "integrity": "sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz", + "integrity": "sha512-w/EboPlBwnmOBtRbiOvzjD+wdiZdgFeo17lkltrtn7X37vagKKWJABvyfsJXTlHe6XBzugmYgd4A4nW+k8Mixw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.39.1", - "@typescript-eslint/type-utils": "8.39.1", - "@typescript-eslint/utils": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", + "@typescript-eslint/scope-manager": "8.40.0", + "@typescript-eslint/type-utils": "8.40.0", + "@typescript-eslint/utils": "8.40.0", + "@typescript-eslint/visitor-keys": "8.40.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "dependencies": { - "@typescript-eslint/project-service": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", - "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", - "dev": true, - "requires": { - "@typescript-eslint/tsconfig-utils": "^8.39.1", - "@typescript-eslint/types": "^8.39.1", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", - "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1" - } - }, - "@typescript-eslint/tsconfig-utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", - "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", - "dev": true, - "requires": {} - }, - "@typescript-eslint/types": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", - "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", - "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", - "dev": true, - "requires": { - "@typescript-eslint/project-service": "8.39.1", - "@typescript-eslint/tsconfig-utils": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - } - }, - "@typescript-eslint/utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", - "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/typescript-estree": "8.39.1" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", - "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.39.1", - "eslint-visitor-keys": "^4.2.1" - } - }, - "eslint-visitor-keys": { - "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 - }, "ignore": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", "dev": true }, - "semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true - }, "ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -24213,99 +23531,16 @@ } }, "@typescript-eslint/parser": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.39.1.tgz", - "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.40.0.tgz", + "integrity": "sha512-jCNyAuXx8dr5KJMkecGmZ8KI61KBUhkCob+SD+C+I5+Y1FWI2Y3QmY4/cxMCC5WAsZqoEtEETVhUiUMIGCf6Bw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/typescript-estree": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", + "@typescript-eslint/scope-manager": "8.40.0", + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/typescript-estree": "8.40.0", + "@typescript-eslint/visitor-keys": "8.40.0", "debug": "^4.3.4" - }, - "dependencies": { - "@typescript-eslint/project-service": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", - "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", - "dev": true, - "requires": { - "@typescript-eslint/tsconfig-utils": "^8.39.1", - "@typescript-eslint/types": "^8.39.1", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", - "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1" - } - }, - "@typescript-eslint/tsconfig-utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", - "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", - "dev": true, - "requires": {} - }, - "@typescript-eslint/types": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", - "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", - "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", - "dev": true, - "requires": { - "@typescript-eslint/project-service": "8.39.1", - "@typescript-eslint/tsconfig-utils": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", - "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.39.1", - "eslint-visitor-keys": "^4.2.1" - } - }, - "eslint-visitor-keys": { - "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 - }, - "semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true - }, - "ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "dev": true, - "requires": {} - } } }, "@typescript-eslint/project-service": { @@ -24337,104 +23572,18 @@ "requires": {} }, "@typescript-eslint/type-utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.39.1.tgz", - "integrity": "sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.40.0.tgz", + "integrity": "sha512-eE60cK4KzAc6ZrzlJnflXdrMqOBaugeukWICO2rB0KNvwdIMaEaYiywwHMzA1qFpTxrLhN9Lp4E/00EgWcD3Ow==", "dev": true, "requires": { - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/typescript-estree": "8.39.1", - "@typescript-eslint/utils": "8.39.1", + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/typescript-estree": "8.40.0", + "@typescript-eslint/utils": "8.40.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "dependencies": { - "@typescript-eslint/project-service": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", - "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", - "dev": true, - "requires": { - "@typescript-eslint/tsconfig-utils": "^8.39.1", - "@typescript-eslint/types": "^8.39.1", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", - "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1" - } - }, - "@typescript-eslint/tsconfig-utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", - "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", - "dev": true, - "requires": {} - }, - "@typescript-eslint/types": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", - "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", - "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", - "dev": true, - "requires": { - "@typescript-eslint/project-service": "8.39.1", - "@typescript-eslint/tsconfig-utils": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - } - }, - "@typescript-eslint/utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", - "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/typescript-estree": "8.39.1" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", - "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.39.1", - "eslint-visitor-keys": "^4.2.1" - } - }, - "eslint-visitor-keys": { - "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 - }, - "semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true - }, "ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -32671,64 +31820,6 @@ "@typescript-eslint/parser": "8.40.0", "@typescript-eslint/typescript-estree": "8.40.0", "@typescript-eslint/utils": "8.40.0" - }, - "dependencies": { - "@typescript-eslint/eslint-plugin": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz", - "integrity": "sha512-w/EboPlBwnmOBtRbiOvzjD+wdiZdgFeo17lkltrtn7X37vagKKWJABvyfsJXTlHe6XBzugmYgd4A4nW+k8Mixw==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.40.0", - "@typescript-eslint/type-utils": "8.40.0", - "@typescript-eslint/utils": "8.40.0", - "@typescript-eslint/visitor-keys": "8.40.0", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" - } - }, - "@typescript-eslint/parser": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.40.0.tgz", - "integrity": "sha512-jCNyAuXx8dr5KJMkecGmZ8KI61KBUhkCob+SD+C+I5+Y1FWI2Y3QmY4/cxMCC5WAsZqoEtEETVhUiUMIGCf6Bw==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "8.40.0", - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/typescript-estree": "8.40.0", - "@typescript-eslint/visitor-keys": "8.40.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/type-utils": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.40.0.tgz", - "integrity": "sha512-eE60cK4KzAc6ZrzlJnflXdrMqOBaugeukWICO2rB0KNvwdIMaEaYiywwHMzA1qFpTxrLhN9Lp4E/00EgWcD3Ow==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/typescript-estree": "8.40.0", - "@typescript-eslint/utils": "8.40.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" - } - }, - "ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true - }, - "ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "dev": true, - "requires": {} - } } }, "ufo": { diff --git a/package.json b/package.json index 1ddc2ef3..6ab83430 100644 --- a/package.json +++ b/package.json @@ -52,8 +52,8 @@ "@types/react-dom": "18.3.1", "@types/react-redux": "7.1.34", "@types/uuid": "10.0.0", - "@typescript-eslint/eslint-plugin": "8.39.1", - "@typescript-eslint/parser": "8.39.1", + "@typescript-eslint/eslint-plugin": "8.40.0", + "@typescript-eslint/parser": "8.40.0", "@vitejs/plugin-react": "4.7.0", "@vitest/coverage-v8": "3.2.4", "babel-loader": "10.0.0", From 4d783537fb3cfe1176c439a7a7c2f7cbf9875c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anna=20V=C3=ADtov=C3=A1?= Date: Wed, 20 Aug 2025 11:29:17 +0200 Subject: [PATCH 07/16] Launch: implement guidance for Oracle (HMS-9004) This commit adds launch modal for guiding users through launching a Oracle instance from their image. It provides a link to Oracle's cloud and a link for importing the image on the user's side. --- src/Components/ImagesTable/ImagesTable.tsx | 9 +- src/Components/Launch/OciLaunchModal.tsx | 139 +++++++++++++++++++++ 2 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 src/Components/Launch/OciLaunchModal.tsx diff --git a/src/Components/ImagesTable/ImagesTable.tsx b/src/Components/ImagesTable/ImagesTable.tsx index 32782d3a..09e4b8d7 100644 --- a/src/Components/ImagesTable/ImagesTable.tsx +++ b/src/Components/ImagesTable/ImagesTable.tsx @@ -26,6 +26,7 @@ import { } from '@patternfly/react-table'; import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; import { ChromeUser } from '@redhat-cloud-services/types'; +import { useFlag } from '@unleash/proxy-client-react'; import { useDispatch } from 'react-redux'; import { NavigateFunction, useNavigate } from 'react-router-dom'; @@ -87,6 +88,7 @@ import { timestampToDisplayString, timestampToDisplayStringDetailed, } from '../../Utilities/time'; +import { OciLaunchModal } from '../Launch/OciLaunchModal'; const ImagesTable = () => { const [page, setPage] = useState(1); @@ -403,13 +405,18 @@ type OciRowPropTypes = { }; const OciRow = ({ compose, rowIndex }: OciRowPropTypes) => { + const launchEofFlag = useFlag('image-builder.launcheof'); const daysToExpiration = Math.floor( computeHoursToExpiration(compose.created_at) / 24, ); const isExpired = daysToExpiration >= OCI_STORAGE_EXPIRATION_TIME_IN_DAYS; const details = ; - const instance = ; + const instance = launchEofFlag ? ( + + ) : ( + + ); const status = ( { + const [isModalOpen, setIsModalOpen] = useState(false); + const { data, isSuccess, isFetching } = useGetComposeStatusQuery({ + composeId: compose.id, + }); + + const navigate = useNavigate(); + if (!isSuccess) { + return ; + } + + const options = data?.image_status.upload_status?.options; + + if (options && !isOciUploadStatus(options)) { + throw TypeError( + `Error: options must be of type OciUploadStatus, not ${typeof options}.`, + ); + } + + if (isExpired) { + return ( + + ); + } + + const handleModalToggle = () => { + setIsModalOpen(!isModalOpen); + }; + + return ( + + + + + + + + Navigate to the{' '} + {' '} + page. + + + Select{' '} + Import image, + and enter the Object Storage URL of the image. + {!isFetching && ( + + {options?.url || ''} + + )} + {isFetching && } + + + After the image is available, click on{' '} + Create instance. + + + + + + + + + ); +}; From 44c3674072f3d0d4fe147c374b63e3dcabcc0a80 Mon Sep 17 00:00:00 2001 From: Gianluca Zuccarelli Date: Wed, 20 Aug 2025 14:51:52 +0100 Subject: [PATCH 08/16] devDeps: Bump msw from 2.10.4 to 2.10.5 This bumps msw from 2.10.4 to 2.10.5 --- package-lock.json | 14 +++++++------- package.json | 2 +- src/mockServiceWorker.js | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index d593079a..c8b41f90 100644 --- a/package-lock.json +++ b/package-lock.json @@ -83,7 +83,7 @@ "madge": "8.0.0", "mini-css-extract-plugin": "2.9.2", "moment": "2.30.1", - "msw": "2.10.4", + "msw": "2.10.5", "npm-run-all": "4.1.5", "path-browserify": "1.0.1", "postcss-scss": "4.0.9", @@ -13730,9 +13730,9 @@ "license": "MIT" }, "node_modules/msw": { - "version": "2.10.4", - "resolved": "https://registry.npmjs.org/msw/-/msw-2.10.4.tgz", - "integrity": "sha512-6R1or/qyele7q3RyPwNuvc0IxO8L8/Aim6Sz5ncXEgcWUNxSKE+udriTOWHtpMwmfkLYlacA2y7TIx4cL5lgHA==", + "version": "2.10.5", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.10.5.tgz", + "integrity": "sha512-0EsQCrCI1HbhpBWd89DvmxY6plmvrM96b0sCIztnvcNHQbXn5vqwm1KlXslo6u4wN9LFGLC1WFjjgljcQhe40A==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -28622,9 +28622,9 @@ "version": "2.1.3" }, "msw": { - "version": "2.10.4", - "resolved": "https://registry.npmjs.org/msw/-/msw-2.10.4.tgz", - "integrity": "sha512-6R1or/qyele7q3RyPwNuvc0IxO8L8/Aim6Sz5ncXEgcWUNxSKE+udriTOWHtpMwmfkLYlacA2y7TIx4cL5lgHA==", + "version": "2.10.5", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.10.5.tgz", + "integrity": "sha512-0EsQCrCI1HbhpBWd89DvmxY6plmvrM96b0sCIztnvcNHQbXn5vqwm1KlXslo6u4wN9LFGLC1WFjjgljcQhe40A==", "dev": true, "requires": { "@bundled-es-modules/cookie": "^2.0.1", diff --git a/package.json b/package.json index 6ab83430..a262b49f 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "madge": "8.0.0", "mini-css-extract-plugin": "2.9.2", "moment": "2.30.1", - "msw": "2.10.4", + "msw": "2.10.5", "npm-run-all": "4.1.5", "path-browserify": "1.0.1", "postcss-scss": "4.0.9", diff --git a/src/mockServiceWorker.js b/src/mockServiceWorker.js index be4527c7..723b0714 100644 --- a/src/mockServiceWorker.js +++ b/src/mockServiceWorker.js @@ -7,7 +7,7 @@ * - Please do NOT modify this file. */ -const PACKAGE_VERSION = '2.10.4' +const PACKAGE_VERSION = '2.10.5' const INTEGRITY_CHECKSUM = 'f5825c521429caf22a4dd13b66e243af' const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') const activeClientIds = new Set() From a5aa15cbcb711c10d472cf348eca4ed41e2554c4 Mon Sep 17 00:00:00 2001 From: Michal Gold Date: Mon, 28 Jul 2025 11:40:26 +0300 Subject: [PATCH 09/16] Wizard: Resolve row reordering issue on selection and expansion - Fix issue when clicking the expandable arrow or selecting a package checkbox in the Packages step it caused unexpected row reordering. - Updated sorting logic to ensure that selecting a package with a specific stream groups all related module streams together at the top. - Ensured that rows expand in place and selection does not affect row position. - Add unit test as well --- .../steps/Packages/Packages.tsx | 129 +++++++++--------- .../steps/Packages/Packages.test.tsx | 117 ++++++++++++++++ src/test/fixtures/packages.ts | 58 ++++++++ 3 files changed, 239 insertions(+), 65 deletions(-) diff --git a/src/Components/CreateImageWizard/steps/Packages/Packages.tsx b/src/Components/CreateImageWizard/steps/Packages/Packages.tsx index f067d16c..8106fd4b 100644 --- a/src/Components/CreateImageWizard/steps/Packages/Packages.tsx +++ b/src/Components/CreateImageWizard/steps/Packages/Packages.tsx @@ -50,6 +50,7 @@ import { Thead, Tr, } from '@patternfly/react-table'; +import { orderBy } from 'lodash'; import { useDispatch } from 'react-redux'; import CustomHelperText from './components/CustomHelperText'; @@ -66,7 +67,6 @@ import { } from '../../../../constants'; import { useGetArchitecturesQuery } from '../../../../store/backendApi'; import { - ApiPackageSourcesResponse, ApiRepositoryResponseRead, ApiSearchRpmResponse, useCreateRepositoryMutation, @@ -700,7 +700,7 @@ const Packages = () => { ); } - const unpackedData: IBPackageWithRepositoryInfo[] = + let unpackedData: IBPackageWithRepositoryInfo[] = combinedPackageData.flatMap((item) => { // Spread modules into separate rows by application stream if (item.sources) { @@ -724,13 +724,16 @@ const Packages = () => { }); // group by name, but sort by application stream in descending order - unpackedData.sort((a, b) => { - if (a.name === b.name) { - return (b.stream ?? '').localeCompare(a.stream ?? ''); - } else { - return a.name.localeCompare(b.name); - } - }); + unpackedData = orderBy( + unpackedData, + [ + 'name', + (pkg) => pkg.stream || '', + (pkg) => pkg.repository || '', + (pkg) => pkg.module_name || '', + ], + ['asc', 'desc', 'asc', 'asc'], + ); if (toggleSelected === 'toggle-available') { if (activeTabKey === Repos.INCLUDED) { @@ -866,8 +869,6 @@ const Packages = () => { dispatch(addPackage(pkg)); if (pkg.type === 'module') { setActiveStream(pkg.stream || ''); - setActiveSortIndex(2); - setPage(1); dispatch( addModule({ name: pkg.module_name || '', @@ -993,7 +994,18 @@ const Packages = () => { } }; - const initialExpandedPkgs: IBPackageWithRepositoryInfo[] = []; + const getPackageUniqueKey = (pkg: IBPackageWithRepositoryInfo): string => { + try { + if (!pkg || !pkg.name) { + return `invalid_${Date.now()}`; + } + return `${pkg.name}_${pkg.stream || 'none'}_${pkg.module_name || 'none'}_${pkg.repository || 'unknown'}`; + } catch { + return `error_${Date.now()}`; + } + }; + + const initialExpandedPkgs: string[] = []; const [expandedPkgs, setExpandedPkgs] = useState(initialExpandedPkgs); const setPkgExpanded = ( @@ -1001,12 +1013,13 @@ const Packages = () => { isExpanding: boolean, ) => setExpandedPkgs((prevExpanded) => { - const otherExpandedPkgs = prevExpanded.filter((p) => p.name !== pkg.name); - return isExpanding ? [...otherExpandedPkgs, pkg] : otherExpandedPkgs; + const pkgKey = getPackageUniqueKey(pkg); + const otherExpandedPkgs = prevExpanded.filter((key) => key !== pkgKey); + return isExpanding ? [...otherExpandedPkgs, pkgKey] : otherExpandedPkgs; }); const isPkgExpanded = (pkg: IBPackageWithRepositoryInfo) => - expandedPkgs.includes(pkg); + expandedPkgs.includes(getPackageUniqueKey(pkg)); const initialExpandedGroups: GroupWithRepositoryInfo['name'][] = []; const [expandedGroups, setExpandedGroups] = useState(initialExpandedGroups); @@ -1030,51 +1043,37 @@ const Packages = () => { 'asc' | 'desc' >('asc'); - const getSortableRowValues = ( - pkg: IBPackageWithRepositoryInfo, - ): (string | number | ApiPackageSourcesResponse[] | undefined)[] => { - return [pkg.name, pkg.summary, pkg.stream, pkg.end_date, pkg.repository]; - }; + const sortedPackages = useMemo(() => { + if (!transformedPackages || !Array.isArray(transformedPackages)) { + return []; + } - let sortedPackages = transformedPackages; - sortedPackages = transformedPackages.sort((a, b) => { - const aValue = getSortableRowValues(a)[activeSortIndex]; - const bValue = getSortableRowValues(b)[activeSortIndex]; - if (typeof aValue === 'number') { - // Numeric sort - if (activeSortDirection === 'asc') { - return (aValue as number) - (bValue as number); - } - return (bValue as number) - (aValue as number); - } - // String sort - // if active stream is set, sort it to the top - if (aValue === activeStream) { - return -1; - } - if (bValue === activeStream) { - return 1; - } - if (activeSortDirection === 'asc') { - // handle packages with undefined stream - if (!aValue) { - return -1; - } - if (!bValue) { - return 1; - } - return (aValue as string).localeCompare(bValue as string); - } else { - // handle packages with undefined stream - if (!aValue) { - return 1; - } - if (!bValue) { - return -1; - } - return (bValue as string).localeCompare(aValue as string); - } - }); + return orderBy( + transformedPackages, + [ + // Active stream packages first (if activeStream is set) + (pkg) => (activeStream && pkg.stream === activeStream ? 0 : 1), + // Then by name + 'name', + // Then by stream version (descending) + (pkg) => { + if (!pkg.stream) return ''; + const parts = pkg.stream + .split('.') + .map((part) => parseInt(part, 10) || 0); + // Convert to string with zero-padding for proper sorting + return parts.map((p) => p.toString().padStart(10, '0')).join('.'); + }, + // Then by end date (nulls last) + (pkg) => pkg.end_date || '9999-12-31', + // Then by repository + (pkg) => pkg.repository || '', + // Finally by module name + (pkg) => pkg.module_name || '', + ], + ['asc', 'asc', 'desc', 'asc', 'asc', 'asc'], + ); + }, [transformedPackages, activeStream]); const getSortParams = (columnIndex: number) => ({ sortBy: { @@ -1100,14 +1099,14 @@ const Packages = () => { (module) => module.name === pkg.name, ); isSelected = - packages.some((p) => p.name === pkg.name) && !isModuleWithSameName; + packages.some((p) => p.name === pkg.name && p.stream === pkg.stream) && + !isModuleWithSameName; } if (pkg.type === 'module') { - // the package is selected if it's added to the packages state - // and its module stream matches one in enabled_modules + // the package is selected if its module stream matches one in enabled_modules isSelected = - packages.some((p) => p.name === pkg.name) && + packages.some((p) => p.name === pkg.name && p.stream === pkg.stream) && modules.some( (m) => m.name === pkg.module_name && m.stream === pkg.stream, ); @@ -1208,7 +1207,7 @@ const Packages = () => { .slice(computeStart(), computeEnd()) .map((grp, rowIndex) => ( @@ -1308,7 +1307,7 @@ const Packages = () => { .slice(computeStart(), computeEnd()) .map((pkg, rowIndex) => ( diff --git a/src/test/Components/CreateImageWizard/steps/Packages/Packages.test.tsx b/src/test/Components/CreateImageWizard/steps/Packages/Packages.test.tsx index 85a2a12e..42fecc29 100644 --- a/src/test/Components/CreateImageWizard/steps/Packages/Packages.test.tsx +++ b/src/test/Components/CreateImageWizard/steps/Packages/Packages.test.tsx @@ -513,6 +513,123 @@ describe('Step Packages', () => { expect(secondAppStreamRow).toBeDisabled(); expect(secondAppStreamRow).not.toBeChecked(); }); + + test('module selection sorts selected stream to top while maintaining alphabetical order', async () => { + const user = userEvent.setup(); + + await renderCreateMode(); + await goToPackagesStep(); + await typeIntoSearchBox('sortingTest'); + + await screen.findAllByText('alphaModule'); + await screen.findAllByText('betaModule'); + await screen.findAllByText('gammaModule'); + + let rows = await screen.findAllByRole('row'); + rows.shift(); + expect(rows).toHaveLength(6); + + expect(rows[0]).toHaveTextContent('alphaModule'); + expect(rows[0]).toHaveTextContent('3.0'); + expect(rows[1]).toHaveTextContent('alphaModule'); + expect(rows[1]).toHaveTextContent('2.0'); + expect(rows[2]).toHaveTextContent('betaModule'); + expect(rows[2]).toHaveTextContent('4.0'); + expect(rows[3]).toHaveTextContent('betaModule'); + expect(rows[3]).toHaveTextContent('2.0'); + + // Select betaModule with stream 2.0 (row index 3) + const betaModule20Checkbox = await screen.findByRole('checkbox', { + name: /select row 3/i, + }); + + await waitFor(() => user.click(betaModule20Checkbox)); + expect(betaModule20Checkbox).toBeChecked(); + + // After selection, the active stream (2.0) should be prioritized + // All modules with stream 2.0 should move to the top, maintaining alphabetical order + rows = await screen.findAllByRole('row'); + rows.shift(); + expect(rows[0]).toHaveTextContent('alphaModule'); + expect(rows[0]).toHaveTextContent('2.0'); + expect(rows[1]).toHaveTextContent('betaModule'); + expect(rows[1]).toHaveTextContent('2.0'); + expect(rows[2]).toHaveTextContent('gammaModule'); + expect(rows[2]).toHaveTextContent('2.0'); + expect(rows[3]).toHaveTextContent('alphaModule'); + expect(rows[3]).toHaveTextContent('3.0'); + expect(rows[4]).toHaveTextContent('betaModule'); + expect(rows[4]).toHaveTextContent('4.0'); + expect(rows[5]).toHaveTextContent('gammaModule'); + expect(rows[5]).toHaveTextContent('1.5'); + + // Verify that only the selected module is checked + const updatedBetaModule20Checkbox = await screen.findByRole('checkbox', { + name: /select row 1/i, // betaModule 2.0 is now at position 1 + }); + expect(updatedBetaModule20Checkbox).toBeChecked(); + + // Verify that only one checkbox is checked + const allCheckboxes = await screen.findAllByRole('checkbox', { + name: /select row [0-9]/i, + }); + const checkedCheckboxes = allCheckboxes.filter( + (cb) => (cb as HTMLInputElement).checked, + ); + expect(checkedCheckboxes).toHaveLength(1); + expect(checkedCheckboxes[0]).toBe(updatedBetaModule20Checkbox); + }); + + test('unselecting a module does not cause jumping but may reset sort to default', async () => { + const user = userEvent.setup(); + + await renderCreateMode(); + await goToPackagesStep(); + await selectCustomRepo(); + await typeIntoSearchBox('sortingTest'); + await screen.findAllByText('betaModule'); + const betaModule20Checkbox = await screen.findByRole('checkbox', { + name: /select row 3/i, + }); + await waitFor(() => user.click(betaModule20Checkbox)); + expect(betaModule20Checkbox).toBeChecked(); + let rows = await screen.findAllByRole('row'); + rows.shift(); + expect(rows[0]).toHaveTextContent('alphaModule'); + expect(rows[0]).toHaveTextContent('2.0'); + expect(rows[1]).toHaveTextContent('betaModule'); + expect(rows[1]).toHaveTextContent('2.0'); + + const updatedBetaModule20Checkbox = await screen.findByRole('checkbox', { + name: /select row 1/i, + }); + await waitFor(() => user.click(updatedBetaModule20Checkbox)); + expect(updatedBetaModule20Checkbox).not.toBeChecked(); + + // After unselection, the sort may reset to default or stay the same + // The important thing is that we don't get jumping/reordering during the interaction + rows = await screen.findAllByRole('row'); + rows.shift(); // Remove header row + const allCheckboxes = await screen.findAllByRole('checkbox', { + name: /select row [0-9]/i, + }); + const checkedCheckboxes = allCheckboxes.filter( + (cb) => (cb as HTMLInputElement).checked, + ); + expect(checkedCheckboxes).toHaveLength(0); + + // The key test: the table should have a consistent, predictable order + // Either the original alphabetical order OR the stream-sorted order + // What we don't want is jumping around during the selection/unselection process + expect(rows).toHaveLength(6); // Still have all 6 modules + const moduleNames = rows.map((row) => { + const match = row.textContent?.match(/(\w+Module)/); + return match ? match[1] : ''; + }); + expect(moduleNames).toContain('alphaModule'); + expect(moduleNames).toContain('betaModule'); + expect(moduleNames).toContain('gammaModule'); + }); }); }); diff --git a/src/test/fixtures/packages.ts b/src/test/fixtures/packages.ts index 0f494415..08aefb20 100644 --- a/src/test/fixtures/packages.ts +++ b/src/test/fixtures/packages.ts @@ -75,6 +75,64 @@ export const mockSourcesPackagesResults = ( }, ]; } + if (search === 'sortingTest') { + return [ + { + package_name: 'alphaModule', + summary: 'Alpha module for sorting tests', + package_sources: [ + { + name: 'alphaModule', + type: 'module', + stream: '2.0', + end_date: '2025-12-01', + }, + { + name: 'alphaModule', + type: 'module', + stream: '3.0', + end_date: '2027-12-01', + }, + ], + }, + { + package_name: 'betaModule', + summary: 'Beta module for sorting tests', + package_sources: [ + { + name: 'betaModule', + type: 'module', + stream: '2.0', + end_date: '2025-06-01', + }, + { + name: 'betaModule', + type: 'module', + stream: '4.0', + end_date: '2028-06-01', + }, + ], + }, + { + package_name: 'gammaModule', + summary: 'Gamma module for sorting tests', + package_sources: [ + { + name: 'gammaModule', + type: 'module', + stream: '2.0', + end_date: '2025-08-01', + }, + { + name: 'gammaModule', + type: 'module', + stream: '1.5', + end_date: '2026-08-01', + }, + ], + }, + ]; + } if (search === 'mock') { return [ { From e61cb99f1bc96ce3e3af1f0f9abc756c5a287f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anna=20V=C3=ADtov=C3=A1?= Date: Mon, 11 Aug 2025 16:06:21 +0200 Subject: [PATCH 10/16] Launch: implement guidance for Azure (HMS-9003) This commit adds launch modal for guiding users through launching an Azure instance from their image. As the launch service will be decommissioned, the flag shall be turned on, the code will later be cleaned up and the Provisioning wizard removed. --- src/Components/ImagesTable/ImagesTable.tsx | 9 +- src/Components/Launch/AzureLaunchModal.tsx | 116 +++++++++++++++++++++ src/Components/Launch/OciLaunchModal.tsx | 2 +- 3 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 src/Components/Launch/AzureLaunchModal.tsx diff --git a/src/Components/ImagesTable/ImagesTable.tsx b/src/Components/ImagesTable/ImagesTable.tsx index 09e4b8d7..8c9118a1 100644 --- a/src/Components/ImagesTable/ImagesTable.tsx +++ b/src/Components/ImagesTable/ImagesTable.tsx @@ -88,6 +88,7 @@ import { timestampToDisplayString, timestampToDisplayStringDetailed, } from '../../Utilities/time'; +import { AzureLaunchModal } from '../Launch/AzureLaunchModal'; import { OciLaunchModal } from '../Launch/OciLaunchModal'; const ImagesTable = () => { @@ -384,8 +385,14 @@ type AzureRowPropTypes = { }; const AzureRow = ({ compose, rowIndex }: AzureRowPropTypes) => { + const launchEofFlag = useFlag('image-builder.launcheof'); + const details = ; - const instance = ; + const instance = launchEofFlag ? ( + + ) : ( + + ); const status = ; return ( diff --git a/src/Components/Launch/AzureLaunchModal.tsx b/src/Components/Launch/AzureLaunchModal.tsx new file mode 100644 index 00000000..8cfba072 --- /dev/null +++ b/src/Components/Launch/AzureLaunchModal.tsx @@ -0,0 +1,116 @@ +import React, { Fragment, useState } from 'react'; + +import { + Button, + List, + ListComponent, + ListItem, + Modal, + ModalBody, + ModalFooter, + ModalHeader, + ModalVariant, + OrderType, + Skeleton, +} from '@patternfly/react-core'; +import { ExternalLinkAltIcon } from '@patternfly/react-icons'; + +import { + ComposesResponseItem, + useGetComposeStatusQuery, +} from '../../store/imageBuilderApi'; +import { isAzureUploadStatus } from '../../store/typeGuards'; + +type LaunchProps = { + compose: ComposesResponseItem; +}; + +export const AzureLaunchModal = ({ compose }: LaunchProps) => { + const [isModalOpen, setIsModalOpen] = useState(false); + const { data, isSuccess, isFetching } = useGetComposeStatusQuery({ + composeId: compose.id, + }); + + if (!isSuccess) { + return ; + } + + const options = data?.image_status.upload_status?.options; + + if (options && !isAzureUploadStatus(options)) { + throw TypeError( + `Error: options must be of type AzureUploadStatus, not ${typeof options}.`, + ); + } + + const handleModalToggle = (_event: KeyboardEvent | React.MouseEvent) => { + setIsModalOpen(!isModalOpen); + }; + + return ( + + + + + + + + + Locate{' '} + {!isFetching && ( + + {options?.image_name}{' '} + + )} + {isFetching && } + in the{' '} + + . + + + Create a Virtual Machine (VM) by using the image. +
+ Note: Review the{' '} + + Availability Zone + {' '} + and the Size to + meet your requirements. Adjust these settings as needed. +
+
+
+ + + +
+
+ ); +}; diff --git a/src/Components/Launch/OciLaunchModal.tsx b/src/Components/Launch/OciLaunchModal.tsx index 8d9f93d6..fa129be3 100644 --- a/src/Components/Launch/OciLaunchModal.tsx +++ b/src/Components/Launch/OciLaunchModal.tsx @@ -72,7 +72,7 @@ export const OciLaunchModal = ({ isExpired, compose }: LaunchProps) => {