From e1cb3f24c8d67e18791ca7bd79a02f5c625c280c Mon Sep 17 00:00:00 2001 From: Stanislav Jakuschevskij Date: Thu, 23 Apr 2026 13:18:26 +0200 Subject: [PATCH] feat: add Function Edit Page File tree browser and code editor for viewing and editing function source code on GitHub. Files load from the Git Data API, the handler file is auto-selected based on func.yaml runtime. Save & Deploy pushes changes back via updateRepo, which caches the last commit SHA to handle GitHub's eventually consistent ref storage. Migrate test runner from Jest to Vitest with MSW 2.x for GitHub API mocking. Merge RepoInfo and SourceRepo into single RepoMetadata type. Extract shared utils (parseNamespaceAndRuntime, getLanguageFromPath, handlerMap). Add CSP connect-src for GitHub API in dev mode. Co-Authored-By: Claude Signed-off-by: Stanislav Jakuschevskij --- AGENTS.md | 6 + docs/ARCHITECTURE.md | 18 +- docs/STYLEGUIDE.md | 6 + docs/WORKFLOW.md | 2 +- docs/claude-progress.txt | 21 + docs/features.json | 44 +- .../completed/016-feat-function-edit-page.md | 86 + docs/potential-features.json | 11 + jest.config.ts | 14 - .../en/plugin__console-functions-plugin.json | 12 +- package.json | 15 +- src/components/CreateFunctionForm.test.tsx | 8 +- src/components/EmptyState.test.tsx | 4 +- src/components/FileTreeView.test.tsx | 190 + src/components/FileTreeView.tsx | 165 + src/components/FunctionTable.test.tsx | 28 +- src/components/UserAvatar.test.tsx | 12 +- src/components/UserAvatar.tsx | 2 +- .../cluster/useClusterService.test.tsx | 8 +- src/services/function/FunctionService.test.ts | 12 +- .../source-control/GithubService.test.ts | 398 ++ src/services/source-control/GithubService.ts | 124 +- .../SourceControlService.test.ts | 157 - .../source-control/SourceControlService.ts | 12 +- src/services/types.ts | 8 +- src/test-setup.ts | 1 - src/utils/errorMessage.ts | 3 - src/utils/utils.test.ts | 20 + src/utils/utils.ts | 55 + src/views/FunctionCreatePage.test.tsx | 26 +- src/views/FunctionCreatePage.tsx | 4 +- src/views/FunctionEditPage.test.tsx | 199 + src/views/FunctionEditPage.tsx | 355 +- src/views/FunctionsListPage.test.tsx | 52 +- src/views/FunctionsListPage.tsx | 48 +- start-console.sh | 4 + testing/msw/handlers.ts | 16 + testing/msw/server.ts | 4 + testing/setup.ts | 6 + tsconfig.json | 5 +- vitest.config.ts | 10 + yarn.lock | 3593 +++++++---------- 42 files changed, 3292 insertions(+), 2472 deletions(-) create mode 100644 docs/plans/completed/016-feat-function-edit-page.md delete mode 100644 jest.config.ts create mode 100644 src/components/FileTreeView.test.tsx create mode 100644 src/components/FileTreeView.tsx create mode 100644 src/services/source-control/GithubService.test.ts delete mode 100644 src/services/source-control/SourceControlService.test.ts delete mode 100644 src/test-setup.ts delete mode 100644 src/utils/errorMessage.ts create mode 100644 src/utils/utils.test.ts create mode 100644 src/utils/utils.ts create mode 100644 src/views/FunctionEditPage.test.tsx create mode 100644 testing/msw/handlers.ts create mode 100644 testing/msw/server.ts create mode 100644 testing/setup.ts create mode 100644 vitest.config.ts diff --git a/AGENTS.md b/AGENTS.md index 052bb77..226a93f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,6 +7,12 @@ This is the project map. Read this first, every session. FaaS PoC UI for OpenShift Console — React + TypeScript + Webpack + PatternFly 6 + OCP Dynamic Plugin SDK. See `docs/design/` for full design specs. +## Communication + +- Ask before staring modifications of code. +- Ask before starting a new task or making a design decision. +- Once actively implementing, keep going without asking. Only stop to ask when blocked by sandbox, permissions, or ambiguous requirements. + ## Writing Style No em dashes (`—`). Use commas, periods, or parentheses instead. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index a61e8bc..3fb68c5 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -39,13 +39,23 @@ Arrows mean "imports / depends on." - Services never import Components or Views - No circular dependencies -## Page / Component / Hook Rules +## React -**Components are simple** — they receive data via props, render it, and call callbacks to return data to the parent (or use context). No logic at the top of a component. +### Page / Component / Hook Rules -**Pages are smart** — they use central hooks (e.g. `useClusterService`, `useSourceControl`) to fetch, prepare, and transform all data needed for downstream components. +**Components are simple by default** — they receive data via props, render it, and call callbacks. No logic at the top of a component. -**Extract logic into hooks** — if a page or component has any logic (state management, data transformation, side effects), extract it into a co-named hook: `FunctionTable.tsx` → `useFunctionTable.ts`, `FunctionsListPage.tsx` → `useFunctionsListPage.ts`. If there is no logic, no hook is needed. +**A component may own its own data and state when it encapsulates a self-contained capability that is not specific to any one page** (e.g., forge connection, auth flows, notification subscriptions). The component becomes the single owner of that concern. Pages consume it without orchestrating its internals. + +**Pages are smart for page-specific data** — they use central hooks (e.g. `useClusterService`, `useSourceControl`) to fetch, prepare, and transform all data needed for downstream components. + +**Extract logic into hooks** — if a page or component has any logic (state management, data transformation, side effects), extract it into a custom hook. If the hook is reused by multiple components, put it in a separate file: `useFunctionTable.ts`. If the hook is only used by one component, keep it in the same file, do not export it. If there is no logic, no hook is needed. + +**File ordering** — within a file, put the exported component at the top, then its hook below, then helper functions at the bottom. Readers see the main thing first and can drill down. + +### Performance + +- **No speculative memoization**: Do not wrap every function in `useCallback` or every value in `useMemo` as a habit. Use them when there is a concrete reason: a `React.memo` child that depends on a stable reference, or a known re-render path (e.g., a sibling component re-rendering on every keystroke). Plain functions and derived values are the default. ## Architectural Guidance diff --git a/docs/STYLEGUIDE.md b/docs/STYLEGUIDE.md index 60820f2..caab021 100644 --- a/docs/STYLEGUIDE.md +++ b/docs/STYLEGUIDE.md @@ -17,11 +17,17 @@ - **No `any` type**: Use proper TypeScript types. - **No `console.log`**: Use structured approach if logging needed. - **Naming**: `use*` for hooks, `*Service` for services, PascalCase for components/types. +- **Co-locate helper functions**: Keep helper functions in the same file as the component or hook that uses them. Test them indirectly through the consumer's tests. Only extract to `utils/` when shared across multiple unrelated modules. ## Documentation - **No em dashes (`—`)**. Use commas, periods, or parentheses instead. +## CSS + +- **PatternFly first**: Use PatternFly component props for all layout and spacing. Only fall back to custom CSS when PatternFly does not cover the need. +- **Relative units only**: When custom CSS is necessary, use `rem` and `em` for all sizing. Never use `px`. + ## OCP Plugin Styling Constraints The `.stylelintrc.yaml` enforces strict rules to prevent breaking the OpenShift Console: diff --git a/docs/WORKFLOW.md b/docs/WORKFLOW.md index 67c6751..9ec8524 100644 --- a/docs/WORKFLOW.md +++ b/docs/WORKFLOW.md @@ -17,7 +17,7 @@ Every session, before doing any work: After [Startup Sequence](#startup-sequence), work through the picked feature: 1. **Plan** — read `docs/ARCHITECTURE.md` + `docs/STYLEGUIDE.md` + `docs/TESTING.md`, then use `/brainstorming` to design the chosen feature from `docs/features.json`, then use `/writing-plans` to create implementation plan → `docs/plans/active/--.md` -2. **Branch** — create feature branch per [Branching](#branching) convention +2. **Branch** — create feature branch per [Branching](#branching) convention. Immediately push and open a **draft PR** (`gh pr create --draft`) to reserve the PR number for other contributors' branch numbering. 3. **Implement** — using `/executing-plans` skill 4. **Review** — code review using `/requesting-code-review` skill, fix found issues 5. **Manual Test** — use browser automation and validate it works in the browser diff --git a/docs/claude-progress.txt b/docs/claude-progress.txt index cfe2b2f..f4e0d4b 100644 --- a/docs/claude-progress.txt +++ b/docs/claude-progress.txt @@ -1,6 +1,27 @@ # Claude Progress Log # Newest entries first. Agents: append your entry at the top after the header. +--- +## 2026-04-28 | Session: Function Edit Page +Worked on: Full Function Edit Page feature (plan 016) +Completed: +- Function Edit Page with FileTreeView file browser and SDK CodeEditor +- FileTreeView component: loading spinner state, empty placeholder, directories-before-files sorting, dirty dot indicators, fixed width with horizontal scroll +- SDK CodeEditor with empty state (code icon, "Start editing"), language label, auto-selected handler file based on func.yaml runtime +- EditToolbar with Back link (unsaved changes modal), Save & Deploy (success alert with 2s auto-dismiss, danger alert on error) +- SourceControlService: fetch(repo) via git.getTree recursive + blob fetches, updateRepo(repo) with local commit SHA cache for GitHub's eventual consistency +- Decomposed push() into push() (initial commits) and updateRepo() (subsequent commits) +- Migrated test runner from Jest to Vitest with MSW 2.x for GitHub API mocking +- Merged RepoInfo + SourceRepo into single RepoMetadata type +- Extracted parseNamespaceAndRuntime, getLanguageFromPath, handlerMap into shared utils +- Added CSP connect-src for GitHub API in dev mode (start-console.sh) +- Removed navigation state passing between pages (each page loads own data from URL params) +- Added CSS, co-location, React performance rules to style guide and architecture docs +- Added communication rules and draft PR step to workflow docs +- 12 test suites, 89 tests, all passing, zero lint errors +Left off: PR #16 ready for review. Missing test coverage for dirty tracking, save error alert, modal interactions, file selection. +Blockers: None + --- ## 2026-04-28 | Session: Runtime PAT entry and user avatar Worked on: Replace compile-time PAT injection with runtime modal entry, add user avatar to page headers diff --git a/docs/features.json b/docs/features.json index 1eae9b9..26bb702 100644 --- a/docs/features.json +++ b/docs/features.json @@ -96,6 +96,19 @@ ], "passes": true }, + { + "category": "technical", + "description": "CI/CD: GitHub Actions pipelines for PR checks and master publish to GHCR, plus lint fixes and README deployment instructions", + "steps": [ + "PR pipeline (.github/workflows/pr.yml): triggers on pull_request to master, runs yarn install --immutable, yarn lint, yarn test — branch cannot merge without passing checks and an approval", + "Publish pipeline (.github/workflows/publish.yml): triggers on push to master (merged PRs), runs yarn install --immutable, yarn lint, yarn test, then builds multi-arch container image via docker/build-push-action using existing Dockerfile and pushes to ghcr.io/twogiants/console-functions-plugin with :latest and :sha- tags", + "Both pipelines use actions/setup-node@v4 with node-version 22, corepack enable, and cache: yarn for Yarn install caching (GitHub runners ship Node 20 by default with corepack disabled)", + "Both pipelines authenticate to GHCR using GITHUB_TOKEN secret with packages:write permission (token added to repo's Actions secrets)", + "Add yarn lint script to package.json if missing, run it, and fix all lint errors in the codebase", + "Update README.md deployment section (lines 96-117) — replace generic Helm boilerplate, placeholder commands, and obsolete OCP 4.10 / i18n notes with concrete instructions: oc new-project console-functions-plugin, helm upgrade -i console-functions-plugin charts/openshift-console-plugin -n console-functions-plugin --create-namespace --set plugin.image=ghcr.io/twogiants/console-functions-plugin:latest@sha256:" + ], + "passes": true + }, { "category": "functional", "description": "GitHub PAT Avatar: session-wide PAT entry via modal + avatar component showing authenticated GitHub user", @@ -126,19 +139,6 @@ ], "passes": false }, - { - "category": "technical", - "description": "CI/CD: GitHub Actions pipelines for PR checks and master publish to GHCR, plus lint fixes and README deployment instructions", - "steps": [ - "PR pipeline (.github/workflows/pr.yml): triggers on pull_request to master, runs yarn install --immutable, yarn lint, yarn test — branch cannot merge without passing checks and an approval", - "Publish pipeline (.github/workflows/publish.yml): triggers on push to master (merged PRs), runs yarn install --immutable, yarn lint, yarn test, then builds multi-arch container image via docker/build-push-action using existing Dockerfile and pushes to ghcr.io/twogiants/console-functions-plugin with :latest and :sha- tags", - "Both pipelines use actions/setup-node@v4 with node-version 22, corepack enable, and cache: yarn for Yarn install caching (GitHub runners ship Node 20 by default with corepack disabled)", - "Both pipelines authenticate to GHCR using GITHUB_TOKEN secret with packages:write permission (token added to repo's Actions secrets)", - "Add yarn lint script to package.json if missing, run it, and fix all lint errors in the codebase", - "Update README.md deployment section (lines 96-117) — replace generic Helm boilerplate, placeholder commands, and obsolete OCP 4.10 / i18n notes with concrete instructions: oc new-project console-functions-plugin, helm upgrade -i console-functions-plugin charts/openshift-console-plugin -n console-functions-plugin --create-namespace --set plugin.image=ghcr.io/twogiants/console-functions-plugin:latest@sha256:" - ], - "passes": true - }, { "category": "functional", "description": "Set GitHub Secret (KUBECONFIG) on created function repos so GH Actions can deploy to the cluster", @@ -149,5 +149,23 @@ "GH Actions workflow can authenticate to the cluster and run func deploy" ], "passes": false + }, + { + "category": "functional", + "description": "Function Edit Page with TreeView file browser and CodeEditor for editing and deploying function code", + "steps": [ + "SourceControlService extended with fetch(repo) and updateRepo(repo) methods. fetch retrieves full repo tree via git.getTree recursive + blob fetches. updateRepo commits on existing branches with local commit SHA cache for GitHub's eventual consistency", + "Navigate to /faas/edit/:name loads files from GitHub via listFunctionRepos + fetch (each page loads its own data from URL params)", + "Page layout: toolbar at top (Back link left, success/danger Alert center, Save & Deploy button right), FileTreeView fixed-width left panel (16rem, horizontally scrollable), SDK CodeEditor fills remaining width (70vh height)", + "FileTreeView builds nested tree from flat FileEntry[] paths with loading spinner state, empty placeholder state, directories expand/collapse only, files are selectable and update CodeEditor content", + "SDK CodeEditor with empty state (code icon + 'Start editing' message) when no file selected, language label visible in header", + "CodeEditor language auto-detected from file extension via getLanguageFromPath utility", + "Handler file auto-selected on load based on runtime from func.yaml (no fallback selection if handler not found)", + "Modified files indicated in tree with dot indicator after filename, dirty state derived by comparing working content against original per file on every onChange", + "Save & Deploy button pushes all files to GitHub via updateRepo, resets dirty state on success, shows spinner and disables button during push, shows success alert with auto-dismiss after 2 seconds", + "Back to Functions link navigates to /faas directly if clean, shows unsaved changes confirmation modal if dirty", + "Empty tree with 'No files' placeholder and disabled Save & Deploy when repo not found, back link always visible" + ], + "passes": true } ] diff --git a/docs/plans/completed/016-feat-function-edit-page.md b/docs/plans/completed/016-feat-function-edit-page.md new file mode 100644 index 0000000..fb3ecbf --- /dev/null +++ b/docs/plans/completed/016-feat-function-edit-page.md @@ -0,0 +1,86 @@ +# Function Edit Page Implementation Plan + +**Status:** COMPLETED + +**Goal:** Build the Function Edit Page with a TreeView file browser and CodeEditor for editing and deploying function code to GitHub. + +**Architecture:** The page follows the project's layered architecture. A `useFunctionEditPage` hook (co-located in the view file, unexported) handles data loading, state management, and save logic. A `FileTreeView` component with a co-located `useFileTreeView` hook renders the file tree. An `EditToolbar` component with `useEditToolbar` hook manages save flow and navigation. The `SourceControlService` interface is extended with `fetch()` and `updateRepo()`. + +**Tech Stack:** React, PatternFly 6 (TreeView, Toolbar, Modal, Button, Alert, EmptyState), OCP Dynamic Plugin SDK (CodeEditor, DocumentTitle, ListPageHeader), Vitest + React Testing Library + MSW + +**Testing approach:** MSW for all GitHub API interactions. `vi.mock` only for `react-i18next` and OCP SDK components. + +--- + +## Completed Tasks + +### Task 1: Add fetch() to SourceControlService and GithubService + +- Added `fetch(repo)` using `git.getTree({ recursive: '1' })` + per-file `git.getBlob` +- Migrated all GithubService tests from `vi.mock('@octokit/rest')` to MSW handlers +- Renamed test file to `GithubService.test.ts` +- Merged `RepoInfo` + `SourceRepo` into single `RepoMetadata` type +- Added test for `fetchFileContent` error path + +### Task 2: Decompose push() into push() and updateRepo() + +- `push()` for initial commits (createRef, no parents) +- `updateRepo()` for subsequent commits with local commit SHA cache +- Cache handles GitHub's eventually consistent ref storage (stale getRef on rapid saves) +- Cache clears only on "not a fast forward" errors (external push), not on network errors +- 5 updateRepo tests: first push, second from cache, third from cache, stale cache recovery, network error preserves cache + +### Task 3: Add getLanguageFromPath utility + +- Maps file extensions and special filenames (Dockerfile, Makefile) to Monaco Language enum +- Extracted to shared `src/utils/utils.ts` along with `parseNamespaceAndRuntime` and `handlerMap` + +### Tasks 4+5: FileTreeView component + +- Builds `TreeViewDataItem[]` directly from flat `FileEntry[]` paths (no intermediate type) +- Separate handling for root files and nested files +- Directories render before files, sorted alphabetically +- Loading state with spinner and "Loading source..." text +- Empty state with "No files" placeholder (not clickable) +- Dirty indicator after filename (`func.yaml ●`) +- `React.memo` with `useMemo` (justified: parent re-renders on every CodeEditor keystroke) +- Fixed width (16rem) with horizontal scroll, vertical scroll for long file lists +- 11 test cases using realistic Node function file structure from knative/func templates + +### Task 6: FunctionEditPage view and hooks + +- Page component: toolbar + flex layout (FileTreeView left, SDK CodeEditor right) +- `Flex` with `direction: row`, `flexWrap: nowrap`, `alignItems: stretch` (fixes baseline alignment stacking issue) +- SDK CodeEditor with `height="70vh"`, empty state (code icon + "Start editing"), language label visible +- Handler file auto-selected based on runtime from func.yaml (function.go for Go, index.js for Node, function/func.py for Python) +- Each page loads its own data from URL params (no navigation state passing between pages) +- `resolveRepoContent` extracts API calls from state management +- Repo metadata stored in state after load for save without re-fetching + +### EditToolbar component + +- Back link (left), success/danger Alert (center), Save & Deploy button (right) +- `useEditToolbar` hook: save flow with isSaving/error/success state +- Success alert "Pushed to GitHub. Deployment running..." with 2-second auto-dismiss (tested with `vi.useFakeTimers`) +- Unsaved changes confirmation modal (LeaveModal) on back navigation when dirty +- Save & Deploy disabled when no changes + +### Infrastructure changes + +- Migrated from Jest to Vitest with MSW 2.x +- Custom jsdom environment removed (Vitest handles globals natively) +- CSP connect-src for GitHub API added to start-console.sh for dev mode +- Added CSS, co-location, React performance rules to style guide and architecture docs +- Added communication rules and draft PR step to workflow docs + +--- + +## Deviations from original plan + +- Used SDK CodeEditor instead of PatternFly CodeEditor (CSP blob URL issues with Monaco workers in OCP Console) +- Removed navigation state passing between list and edit page (each page is self-contained) +- Split `push()` into `push()` + `updateRepo()` (clearer separation of initial vs subsequent commits) +- Added local commit SHA cache (GitHub eventual consistency workaround) +- Added success alert after save (not in original plan) +- Editor empty state with code icon (not in original plan) +- `autoSelectHandler` renamed to `determineHandler` (pure function, returns path instead of calling setState) diff --git a/docs/potential-features.json b/docs/potential-features.json index ab8d84b..1e8985f 100644 --- a/docs/potential-features.json +++ b/docs/potential-features.json @@ -22,5 +22,16 @@ "Namespace column visible in admin perspective, hidden in dev perspective (redundant with project selector)" ], "passes": false + }, + { + "category": "technical", + "description": "Replace per-file blob fetching in GithubService.fetch() with single archive download (downloadTarballArchive) and extraction for better performance", + "steps": [ + "Download repo as tarball via octokit.repos.downloadTarballArchive()", + "Decompress gzip with DecompressionStream, parse tar format", + "Strip the prefix directory from extracted paths", + "Return FileEntry[] from extracted contents instead of N+1 getBlob calls" + ], + "passes": false } ] diff --git a/jest.config.ts b/jest.config.ts deleted file mode 100644 index 7893a2e..0000000 --- a/jest.config.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { Config } from 'jest'; - -const config: Config = { - testEnvironment: 'jsdom', - transform: { - '^.+\\.tsx?$': 'ts-jest', - }, - moduleNameMapper: { - '\\.css$': 'identity-obj-proxy', - }, - setupFilesAfterEnv: ['./src/test-setup.ts'], -}; - -export default config; diff --git a/locales/en/plugin__console-functions-plugin.json b/locales/en/plugin__console-functions-plugin.json index 5a1d2af..8541f68 100644 --- a/locales/en/plugin__console-functions-plugin.json +++ b/locales/en/plugin__console-functions-plugin.json @@ -13,6 +13,7 @@ "Delete": "Delete", "Edit": "Edit", "Enter your GitHub Personal Access Token to connect your repositories.": "Enter your GitHub Personal Access Token to connect your repositories.", + "Edit function": "Edit function", "Error creating function": "Error creating function", "Function Settings": "Function Settings", "FaaS": "FaaS", @@ -25,6 +26,7 @@ "No functions found": "No functions found", "Owner": "Owner", "Personal Access Token": "Personal Access Token", + "Pushed to GitHub. Deployment running...": "Pushed to GitHub. Deployment running...", "Registry": "Registry", "Replicas": "Replicas", "Repository": "Repository", @@ -32,5 +34,13 @@ "Serverless functions in your repository and deployed to your cluster. Manage lifecycle, monitor status, and scale on demand.": "Serverless functions in your repository and deployed to your cluster. Manage lifecycle, monitor status, and scale on demand.", "Status": "Status", "URL": "URL", - "Undeploy": "Undeploy" + "Undeploy": "Undeploy", + "Back to Functions": "Back to Functions", + "Save & Deploy": "Save & Deploy", + "Select a file from the tree view to start editing.": "Select a file from the tree view to start editing.", + "Start editing": "Start editing", + "Unsaved changes": "Unsaved changes", + "You have unsaved changes. Leave anyway?": "You have unsaved changes. Leave anyway?", + "Stay": "Stay", + "Leave": "Leave" } diff --git a/package.json b/package.json index a117f7c..6ade408 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "build-dev": "yarn clean && yarn webpack", "start": "yarn webpack serve --progress", "start-console": "./start-console.sh", - "test": "jest", + "test": "vitest run", "i18n": "./i18n-scripts/build-i18n.sh && node ./i18n-scripts/set-english-defaults.js", "lint": "yarn eslint src integration-tests --fix && stylelint 'src/**/*.css' --allow-empty-input --fix", "test-cypress": "cd integration-tests && cypress open", @@ -37,11 +37,10 @@ "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^12.1.5", "@testing-library/user-event": "^14.6.1", - "@types/identity-obj-proxy": "^3", - "@types/jest": "^30.0.0", "@types/node": "^22.0.0", "@types/react": "^17.0.37", "@types/react-router-dom": "^5.3.3", + "@vitest/coverage-v8": "^4.1.5", "babel-loader": "^10.1.0", "copy-webpack-plugin": "^14.0.0", "css-loader": "^7.1.4", @@ -56,13 +55,12 @@ "globals": "^17.4.0", "i18next": "^23.11.5", "i18next-parser": "^9.4.0", - "identity-obj-proxy": "^3.0.0", - "jest": "^30.3.0", - "jest-environment-jsdom": "^30.3.0", + "jsdom": "^29.0.2", "mocha": "^11.7.5", "mocha-junit-reporter": "^2.2.1", "mochawesome": "^7.1.4", "mochawesome-merge": "^5.1.1", + "msw": "^2.13.6", "pluralize": "^8.0.0", "prettier": "^3.8.1", "prettier-stylelint": "^0.4.2", @@ -75,11 +73,11 @@ "style-loader": "^4.0.0", "stylelint": "^17.4.0", "stylelint-config-standard": "^40.0.0", - "ts-jest": "^29.4.6", "ts-loader": "^9.5.4", "ts-node": "^10.9.2", "typescript": "^5.9.3", "typescript-eslint": "^8.56.1", + "vitest": "^4.1.5", "webpack": "^5.100.0", "webpack-cli": "^6.0.1", "webpack-dev-server": "^5.2.3" @@ -100,6 +98,7 @@ }, "packageManager": "yarn@4.13.0", "dependencies": { - "@octokit/rest": "^22.0.1" + "@octokit/rest": "^22.0.1", + "@patternfly/react-code-editor": "^6.4.3" } } diff --git a/src/components/CreateFunctionForm.test.tsx b/src/components/CreateFunctionForm.test.tsx index 91e74cd..8d8be42 100644 --- a/src/components/CreateFunctionForm.test.tsx +++ b/src/components/CreateFunctionForm.test.tsx @@ -2,17 +2,17 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { CreateFunctionForm } from './CreateFunctionForm'; -jest.mock('react-i18next', () => ({ +vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string) => key }), })); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); describe('CreateFunctionForm', () => { - const onSubmit = jest.fn(); - const onCancel = jest.fn(); + const onSubmit = vi.fn(); + const onCancel = vi.fn(); beforeEach(() => { onSubmit.mockClear(); diff --git a/src/components/EmptyState.test.tsx b/src/components/EmptyState.test.tsx index f516404..ebd26f2 100644 --- a/src/components/EmptyState.test.tsx +++ b/src/components/EmptyState.test.tsx @@ -2,12 +2,12 @@ import { render, screen } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom-v5-compat'; import { FunctionsEmptyState } from './EmptyState'; -jest.mock('react-i18next', () => ({ +vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string) => key }), })); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); describe('FunctionsEmptyState', () => { diff --git a/src/components/FileTreeView.test.tsx b/src/components/FileTreeView.test.tsx new file mode 100644 index 0000000..32c5f9a --- /dev/null +++ b/src/components/FileTreeView.test.tsx @@ -0,0 +1,190 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { FileTreeView } from './FileTreeView'; +import { FileEntry } from '../services/types'; + +const nodeFuncFiles: FileEntry[] = [ + { path: '.github/workflows/func-deploy.yaml', mode: '100644', content: '', type: 'blob' }, + { path: '.gitignore', mode: '100644', content: '', type: 'blob' }, + { path: 'README.md', mode: '100644', content: '', type: 'blob' }, + { path: 'func.yaml', mode: '100644', content: '', type: 'blob' }, + { path: 'index.js', mode: '100644', content: '', type: 'blob' }, + { path: 'package.json', mode: '100644', content: '', type: 'blob' }, + { path: 'test/integration.js', mode: '100644', content: '', type: 'blob' }, + { path: 'test/unit.js', mode: '100644', content: '', type: 'blob' }, +]; + +describe('FileTreeView', () => { + it('renders all file and directory names', () => { + render( + , + ); + + expect(screen.getByText('.github')).toBeInTheDocument(); + expect(screen.getByText('test')).toBeInTheDocument(); + expect(screen.getByText('func.yaml')).toBeInTheDocument(); + expect(screen.getByText('index.js')).toBeInTheDocument(); + expect(screen.getByText('package.json')).toBeInTheDocument(); + }); + + it('renders directories before files', () => { + render( + , + ); + + const allText = document.body.textContent ?? ''; + const githubPos = allText.indexOf('.github'); + const testPos = allText.indexOf('test'); + const gitignorePos = allText.indexOf('.gitignore'); + + expect(githubPos).toBeLessThan(gitignorePos); + expect(testPos).toBeLessThan(gitignorePos); + }); + + it('renders nested files under their parent directory', () => { + render( + , + ); + + const testDir = screen.getByText('test').closest('[role="treeitem"]'); + const nestedItems = testDir?.querySelectorAll('[role="treeitem"]'); + const nestedNames = Array.from(nestedItems ?? []).map((el) => el.textContent?.trim()); + + expect(nestedNames).toContain('integration.js'); + expect(nestedNames).toContain('unit.js'); + }); + + it('renders deeply nested paths as nested directories', () => { + render( + , + ); + + expect(screen.getByText('.github')).toBeInTheDocument(); + expect(screen.getByText('workflows')).toBeInTheDocument(); + expect(screen.getByText('func-deploy.yaml')).toBeInTheDocument(); + }); + + it('renders multiple files under the same directory', () => { + render( + , + ); + + const testDir = screen.getByText('test'); + const testGroup = testDir.closest('[role="treeitem"]'); + const nested = testGroup?.querySelectorAll('[role="treeitem"]'); + + expect(nested?.length).toBe(2); + }); + + it('shows placeholder when no files provided', () => { + render( + , + ); + + expect(screen.getByText('No files')).toBeInTheDocument(); + expect(screen.getAllByRole('treeitem')).toHaveLength(1); + }); + + it('does not call onSelect when placeholder is clicked', async () => { + const user = userEvent.setup(); + const onSelect = vi.fn(); + + render( + , + ); + + await user.click(screen.getByText('No files')); + + expect(onSelect).not.toHaveBeenCalled(); + }); + + it('calls onSelect when a file is clicked', async () => { + const user = userEvent.setup(); + const onSelect = vi.fn(); + + render( + , + ); + + await user.click(screen.getByText('func.yaml')); + + expect(onSelect).toHaveBeenCalledWith('func.yaml'); + }); + + it('does not call onSelect when a directory is clicked', async () => { + const user = userEvent.setup(); + const onSelect = vi.fn(); + + render( + , + ); + + await user.click(screen.getByText('test')); + + expect(onSelect).not.toHaveBeenCalled(); + }); + + it('shows loading state with spinner', () => { + render( + , + ); + + expect(screen.getByText('Loading source...')).toBeInTheDocument(); + expect(screen.queryByText('No files')).not.toBeInTheDocument(); + }); + + it('shows dirty indicator for modified files', () => { + render( + , + ); + + expect(screen.getByText(/func\.yaml \u25CF/)).toBeInTheDocument(); + expect(screen.queryByText(/index\.js \u25CF/)).not.toBeInTheDocument(); + }); +}); diff --git a/src/components/FileTreeView.tsx b/src/components/FileTreeView.tsx new file mode 100644 index 0000000..29ceabb --- /dev/null +++ b/src/components/FileTreeView.tsx @@ -0,0 +1,165 @@ +import { useMemo } from 'react'; +import { Spinner, TreeView, TreeViewDataItem } from '@patternfly/react-core'; +import { FileEntry } from '../services/types'; +import * as React from 'react'; + +const emptyTreeData: TreeViewDataItem[] = [{ id: '__empty__', name: 'No files' }]; +const loadingTreeData: TreeViewDataItem[] = [ + { + id: '__loading__', + name: ( + <> + Loading source... + + ), + }, +]; + +interface FileTreeViewProps { + files: FileEntry[]; + selectedPath: string | null; + dirtyPaths: Set; + isLoading?: boolean; + onSelect: (path: string) => void; +} + +export const FileTreeView = React.memo(function FileTreeView({ + files, + selectedPath, + dirtyPaths, + isLoading = false, + onSelect, +}: FileTreeViewProps) { + const { treeData, activeItems, handleSelect, selectable } = useFileTreeView( + files, + selectedPath, + dirtyPaths, + isLoading, + onSelect, + ); + + return ( + + ); +}); + +// --- hook --- + +function useFileTreeView( + files: FileEntry[], + selectedPath: string | null, + dirtyPaths: Set, + isLoading: boolean = false, + onSelect: (path: string) => void, +): { + treeData: TreeViewDataItem[]; + activeItems: TreeViewDataItem[]; + handleSelect: (_: React.MouseEvent, item: TreeViewDataItem) => void; + selectable: boolean; +} { + const treeData = useMemo(() => buildFileTree(files, dirtyPaths), [files, dirtyPaths]); + + const activeItems = useMemo(() => { + if (!selectedPath) return []; + return findItemByPath(treeData, selectedPath); + }, [treeData, selectedPath]); + + const handleSelect = (_: React.MouseEvent, item: TreeViewDataItem) => { + if (!item.children) { + onSelect(item.id!); + } + }; + + let data: TreeViewDataItem[]; + if (isLoading) data = loadingTreeData; + else if (treeData.length > 0) data = treeData; + else data = emptyTreeData; + + const selectable = !isLoading && treeData.length > 0; + + return { treeData: data, activeItems, handleSelect, selectable }; +} + +// --- helpers --- +function findItemByPath(items: TreeViewDataItem[], path: string): TreeViewDataItem[] { + for (const item of items) { + if (item.id === path) return [item]; + if (item.children) { + const found = findItemByPath(item.children, path); + if (found.length > 0) return [item, ...found]; + } + } + return []; +} + +function buildFileTree(files: FileEntry[], dirtyPaths: Set): TreeViewDataItem[] { + const root: TreeViewDataItem[] = []; + + for (const file of files) { + if (isRootFile(file)) handleRootFile(file); + else handleNestedFile(file); + } + + sortTree(root); + return root; + + function isRootFile(file: FileEntry): boolean { + return file.path.split('/').length === 1; + } + + function handleRootFile(file: FileEntry) { + if (!root.find((item) => item.id === file.path)) createItem(file.path, file.path, root); + } + + function handleNestedFile(file: FileEntry) { + let items = root; + const filePathParts = file.path.split('/'); + for (let i = 0; i < filePathParts.length; i++) { + // e.g. with ['test/unit.js'] filePathPart is first 'test', then 'unit.js' + const filePathPart = filePathParts[i]; + // fullPath is used as id + const fullPath = filePathParts.slice(0, i + 1).join('/'); + // tells us if filePathPart we're working with is a dir or a file + const isDir = i < filePathParts.length - 1; + + const existing = items.find((item) => item.id === fullPath); + if (existing) { + // only true when it's a directory and then we step into it + items = existing.children!; + continue; + } + + createItem(fullPath, filePathPart, items, isDir); + if (isDir) items = items[items.length - 1].children!; + } + } + + function createItem(id: string, name: string, items: TreeViewDataItem[], isDir = false) { + const item: TreeViewDataItem = { + id, + name: dirtyPaths.has(id) ? `${name} \u25CF` : name, + defaultExpanded: true, + }; + if (isDir) item.children = []; + items.push(item); + } + + function sortTree(items: TreeViewDataItem[]) { + items.sort((a, b) => { + const aIsDir = !!a.children; + const bIsDir = !!b.children; + if (aIsDir && !bIsDir) return -1; + if (!aIsDir && bIsDir) return 1; + return String(a.name).localeCompare(String(b.name)); + }); + for (const item of items) { + if (item.children) sortTree(item.children); + } + } +} diff --git a/src/components/FunctionTable.test.tsx b/src/components/FunctionTable.test.tsx index d33cc58..684a3ce 100644 --- a/src/components/FunctionTable.test.tsx +++ b/src/components/FunctionTable.test.tsx @@ -3,13 +3,13 @@ import userEvent from '@testing-library/user-event'; import { MemoryRouter } from 'react-router-dom-v5-compat'; import { FunctionTable, FunctionTableItem } from './FunctionTable'; -jest.mock('react-i18next', () => ({ +vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string) => key }), })); -const mockUseDeleteModal = jest.fn().mockReturnValue(jest.fn()); +const mockUseDeleteModal = vi.fn().mockReturnValue(vi.fn()); -jest.mock('@openshift-console/dynamic-plugin-sdk', () => ({ +vi.mock('@openshift-console/dynamic-plugin-sdk', () => ({ SuccessStatus: ({ title }: { title: string }) => `Success: ${title}`, ProgressStatus: ({ title }: { title: string }) => `Progress: ${title}`, ErrorStatus: ({ title }: { title: string }) => `Error: ${title}`, @@ -18,14 +18,14 @@ jest.mock('@openshift-console/dynamic-plugin-sdk', () => ({ useDeleteModal: (...args: unknown[]) => mockUseDeleteModal(...args), })); -jest.mock('@patternfly/react-icons', () => ({ +vi.mock('@patternfly/react-icons', () => ({ ExclamationTriangleIcon: () => 'WarningIcon', PencilAltIcon: () => 'EditIcon', TrashIcon: () => 'DeleteIcon', })); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); const mockDeployment = { @@ -61,7 +61,7 @@ describe('FunctionTable', () => { it('renders a row for each function', () => { render( - + , ); @@ -72,7 +72,7 @@ describe('FunctionTable', () => { it('renders namespace with dash for empty value', () => { render( - + , ); @@ -84,7 +84,7 @@ describe('FunctionTable', () => { it('renders SuccessStatus for Running functions', () => { render( - + , ); @@ -94,7 +94,7 @@ describe('FunctionTable', () => { it('renders InfoStatus for NotDeployed functions', () => { render( - + , ); @@ -104,7 +104,7 @@ describe('FunctionTable', () => { it('displays hostname-only link for URL', () => { render( - + , ); @@ -114,7 +114,7 @@ describe('FunctionTable', () => { }); it('calls onEdit when edit button is clicked', async () => { - const onEdit = jest.fn(); + const onEdit = vi.fn(); const user = userEvent.setup(); render( @@ -128,13 +128,13 @@ describe('FunctionTable', () => { }); it('launches delete modal when delete button is clicked', async () => { - const mockLauncher = jest.fn(); + const mockLauncher = vi.fn(); mockUseDeleteModal.mockReturnValue(mockLauncher); const user = userEvent.setup(); render( - + , ); @@ -151,7 +151,7 @@ describe('FunctionTable', () => { it('disables delete button for NotDeployed functions', () => { render( - + , ); diff --git a/src/components/UserAvatar.test.tsx b/src/components/UserAvatar.test.tsx index 017f29b..b817361 100644 --- a/src/components/UserAvatar.test.tsx +++ b/src/components/UserAvatar.test.tsx @@ -5,12 +5,12 @@ import { PAT_KEY, USER_KEY } from '../services/types'; import { ForgeConnectionContext } from '../context/ForgeConnectionProvider'; import { ReactNode } from 'react'; -jest.mock('react-i18next', () => ({ +vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string) => key }), })); -const mockFetchUserInfo = jest.fn(); -jest.mock('../services/source-control/useSourceControlService', () => ({ +const mockFetchUserInfo = vi.fn(); +vi.mock('../services/source-control/useSourceControlService', () => ({ useSourceControlService: () => ({ fetchUserInfo: mockFetchUserInfo, }), @@ -20,7 +20,7 @@ const testUser = { name: 'twoGiants' }; function renderWithContext( ui: ReactNode, - contextValue = { isActive: false, connectToForge: jest.fn() }, + contextValue = { isActive: false, connectToForge: vi.fn() }, ) { return render( {ui}, @@ -33,7 +33,7 @@ describe('UserAvatar', () => { }); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); afterAll(() => { @@ -114,7 +114,7 @@ describe('UserAvatar', () => { it('calls fetchUserInfo with PAT and updates UI on successful connect', async () => { const user = userEvent.setup(); - const connectToForge = jest.fn(); + const connectToForge = vi.fn(); mockFetchUserInfo.mockResolvedValue(testUser); renderWithContext(, { isActive: false, connectToForge }); diff --git a/src/components/UserAvatar.tsx b/src/components/UserAvatar.tsx index b44ccbd..8f4b63e 100644 --- a/src/components/UserAvatar.tsx +++ b/src/components/UserAvatar.tsx @@ -15,7 +15,7 @@ import { ForgeUser, PAT_KEY, USER_KEY } from '../services/types'; import { useContext, useState } from 'react'; import { ForgeConnectionContext } from '../context/ForgeConnectionProvider'; import { useSourceControlService } from '../services/source-control/useSourceControlService'; -import { errorMessage } from '../utils/errorMessage'; +import { errorMessage } from '../utils/utils'; interface UserAvatarProps { enableReconnect: boolean; diff --git a/src/services/cluster/useClusterService.test.tsx b/src/services/cluster/useClusterService.test.tsx index e7b6215..6f5b115 100644 --- a/src/services/cluster/useClusterService.test.tsx +++ b/src/services/cluster/useClusterService.test.tsx @@ -1,16 +1,16 @@ import { render, screen } from '@testing-library/react'; import { useClusterService } from './useClusterService'; -const mockUseK8sWatchResource = jest.fn(); -const mockUseActiveNamespace = jest.fn(); +const mockUseK8sWatchResource = vi.fn(); +const mockUseActiveNamespace = vi.fn(); -jest.mock('@openshift-console/dynamic-plugin-sdk', () => ({ +vi.mock('@openshift-console/dynamic-plugin-sdk', () => ({ useK8sWatchResource: (...args: unknown[]) => mockUseK8sWatchResource(...args), useActiveNamespace: () => mockUseActiveNamespace(), })); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); const mockDeployment = { diff --git a/src/services/function/FunctionService.test.ts b/src/services/function/FunctionService.test.ts index a7b5739..4ff63b2 100644 --- a/src/services/function/FunctionService.test.ts +++ b/src/services/function/FunctionService.test.ts @@ -2,14 +2,14 @@ import { consoleFetchJSON } from '@openshift-console/dynamic-plugin-sdk'; import { FunctionBackendService } from './FunctionBackendService'; import { FileEntry, FunctionConfig } from '../types'; -jest.mock('@openshift-console/dynamic-plugin-sdk', () => ({ +vi.mock('@openshift-console/dynamic-plugin-sdk', () => ({ consoleFetchJSON: { - post: jest.fn(), + post: vi.fn(), }, })); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); const config: FunctionConfig = { @@ -27,7 +27,7 @@ const files: FileEntry[] = [ describe('FunctionBackendService', () => { it('calls consoleFetchJSON.post with the proxy URL and returns generated files', async () => { - (consoleFetchJSON.post as jest.Mock).mockResolvedValue(files); + vi.mocked(consoleFetchJSON.post).mockResolvedValue(files); const service = new FunctionBackendService(); const result = await service.generateFunction(config); @@ -40,9 +40,7 @@ describe('FunctionBackendService', () => { }); it('throws when consoleFetchJSON.post rejects', async () => { - (consoleFetchJSON.post as jest.Mock).mockRejectedValue( - new Error('failed to initialize function'), - ); + vi.mocked(consoleFetchJSON.post).mockRejectedValue(new Error('failed to initialize function')); const service = new FunctionBackendService(); diff --git a/src/services/source-control/GithubService.test.ts b/src/services/source-control/GithubService.test.ts new file mode 100644 index 0000000..2f3ae41 --- /dev/null +++ b/src/services/source-control/GithubService.test.ts @@ -0,0 +1,398 @@ +import { http, HttpResponse } from 'msw'; +import { server } from '../../../testing/msw/server'; +import { GithubService } from './GithubService'; +import { FileEntry, RepoMetadata } from '../types'; + +const GITHUB_API = 'https://api.github.com'; +const GH_SEARCH_REPOS = `${GITHUB_API}/search/repositories`; + +describe('GithubService', () => { + describe('listFunctionRepos', () => { + it('lists function repos tagged with serverless-function topic', async () => { + setupGithubSearchReposResponse(); + + const svc = new GithubService(() => 'pat'); + const repos: RepoMetadata[] = await svc.listFunctionRepos(); + + expect(repos).toEqual([ + { + owner: 'twoGiants', + name: 'my-func', + url: 'https://github.com/twoGiants/my-func', + defaultBranch: 'main', + }, + ]); + + function setupGithubSearchReposResponse() { + server.use( + http.get(GH_SEARCH_REPOS, ({ request }) => { + const url = new URL(request.url); + expect(url.searchParams.get('q')).toBe('topic:serverless-function user:twoGiants'); + return HttpResponse.json({ + total_count: 1, + items: [ + { + owner: { login: 'twoGiants' }, + name: 'my-func', + html_url: 'https://github.com/twoGiants/my-func', + default_branch: 'main', + }, + ], + }); + }), + ); + } + }); + }); + + describe('fetchFileContent', () => { + it('fetches file content from a repo', async () => { + setupFileContentResponse(); + + const svc = new GithubService(() => 'pat'); + const content = await svc.fetchFileContent( + { + owner: 'twoGiants', + name: 'my-func', + url: 'https://github.com/twoGiants/my-func', + defaultBranch: 'main', + }, + 'func.yaml', + ); + + expect(content).toBe('name: my-func\nruntime: go\n'); + + function setupFileContentResponse() { + server.use( + http.get(`${GITHUB_API}/repos/twoGiants/my-func/contents/func.yaml`, () => + HttpResponse.json({ + content: btoa('name: my-func\nruntime: go\n'), + encoding: 'base64', + }), + ), + ); + } + }); + + it('throws when path is not a file', async () => { + setupDirectoryResponse(); + + const svc = new GithubService(() => 'pat'); + + await expect( + svc.fetchFileContent( + { owner: 'twoGiants', name: 'my-func', url: '', defaultBranch: 'main' }, + 'src', + ), + ).rejects.toThrow('src is not a file'); + + function setupDirectoryResponse() { + server.use( + http.get(`${GITHUB_API}/repos/twoGiants/my-func/contents/src`, () => + HttpResponse.json([{ name: 'index.js', type: 'file' }]), + ), + ); + } + }); + }); + + describe('push', () => { + const repoInfo: RepoMetadata = { + owner: 'twoGiants', + name: 'my-func', + url: '', + defaultBranch: 'main', + }; + const files: FileEntry[] = [ + { path: 'func.yaml', mode: '100644', content: 'name: my-func', type: 'blob' }, + ]; + + it('creates a new branch ref when branch does not exist', async () => { + const { refCreated } = setupPushHandlers(); + + const svc = new GithubService(() => 'pat'); + await svc.push(repoInfo, files, 'Initial commit'); + + expect(refCreated()).toBe(true); + }); + + it('throws when the API fails', async () => { + setupPushHandlers({ treeError: true }); + + const svc = new GithubService(() => 'pat'); + + await expect(svc.push(repoInfo, files, 'Fail')).rejects.toThrow(); + }); + + function setupPushHandlers({ treeError = false }: { treeError?: boolean } = {}) { + let _refCreated = false; + + server.use( + http.post(`${GITHUB_API}/repos/twoGiants/my-func/git/blobs`, () => + HttpResponse.json({ sha: 'blob-sha' }), + ), + http.post(`${GITHUB_API}/repos/twoGiants/my-func/git/trees`, () => + treeError + ? HttpResponse.json({ message: 'Validation Failed' }, { status: 422 }) + : HttpResponse.json({ sha: 'tree-sha' }), + ), + http.post(`${GITHUB_API}/repos/twoGiants/my-func/git/commits`, () => + HttpResponse.json({ sha: 'commit-sha' }), + ), + http.post(`${GITHUB_API}/repos/twoGiants/my-func/git/refs`, () => { + _refCreated = true; + return HttpResponse.json({}); + }), + ); + + return { refCreated: () => _refCreated }; + } + }); + + describe('updateRepo', () => { + const repoInfo: RepoMetadata = { + owner: 'twoGiants', + name: 'my-func', + url: '', + defaultBranch: 'main', + }; + const files: FileEntry[] = [ + { path: 'func.yaml', mode: '100644', content: 'name: my-func', type: 'blob' }, + ]; + + it('updates existing branch ref first time by loading last commit sha from GitHub', async () => { + const result = setupUpdateRepoHandlers({ commitSha: 'commit-1' }); + + const svc = new GithubService(() => 'pat'); + await svc.updateRepo(repoInfo, files, 'Update'); + + expect(result.updateRefSha()).toBe('commit-1'); + expect(result.getRefCalled()).toBe(true); + }); + + function setupUpdateRepoHandlers({ + commitSha, + updateRefError, + }: { + commitSha: string; + updateRefError?: string; + }) { + let _updateRefSha = ''; + let _getRefCalled = false; + + server.use( + // createBlob + http.post(`${GITHUB_API}/repos/twoGiants/my-func/git/blobs`, () => + HttpResponse.json({ sha: 'blob-sha' }), + ), + // getRef + http.get(`${GITHUB_API}/repos/twoGiants/my-func/git/ref/:ref+`, () => { + _getRefCalled = true; + return HttpResponse.json({ object: { sha: 'head-sha' } }); + }), + // getCommit + http.get(`${GITHUB_API}/repos/twoGiants/my-func/git/commits/:sha`, () => + HttpResponse.json({ tree: { sha: 'tree-sha' } }), + ), + // createTree + http.post(`${GITHUB_API}/repos/twoGiants/my-func/git/trees`, () => + HttpResponse.json({ sha: 'new-tree-sha' }), + ), + // createCommit + http.post(`${GITHUB_API}/repos/twoGiants/my-func/git/commits`, () => + HttpResponse.json({ sha: commitSha }), + ), + // updateRef + http.patch(`${GITHUB_API}/repos/twoGiants/my-func/git/refs/:ref+`, async ({ request }) => { + if (updateRefError === 'fast forward') + return HttpResponse.json({ message: 'Update is not a fast forward' }, { status: 422 }); + + if (updateRefError === 'network') + return HttpResponse.json({ message: 'Server Error' }, { status: 500 }); + + const body = (await request.json()) as { sha: string }; + _updateRefSha = body.sha; + + return HttpResponse.json({}); + }), + ); + + return { getRefCalled: () => _getRefCalled, updateRefSha: () => _updateRefSha }; + } + + it('updates existing branch ref second time by loading last commit sha from cache', async () => { + let result = setupUpdateRepoHandlers({ commitSha: 'commit-1' }); + + const svc = new GithubService(() => 'pat'); + await svc.updateRepo(repoInfo, files, 'First update'); + + expect(result.updateRefSha()).toBe('commit-1'); + expect(result.getRefCalled()).toBe(true); + + result = setupUpdateRepoHandlers({ commitSha: 'commit-2' }); + await svc.updateRepo(repoInfo, files, 'Second update'); + + expect(result.updateRefSha()).toBe('commit-2'); + expect(result.getRefCalled()).toBe(false); + }); + + it('updates existing branch ref third time by loading last commit sha from cache', async () => { + let result = setupUpdateRepoHandlers({ commitSha: 'commit-1' }); + + const svc = new GithubService(() => 'pat'); + await svc.updateRepo(repoInfo, files, 'First update'); + + expect(result.updateRefSha()).toBe('commit-1'); + expect(result.getRefCalled()).toBe(true); + + result = setupUpdateRepoHandlers({ commitSha: 'commit-2' }); + await svc.updateRepo(repoInfo, files, 'Second update'); + + expect(result.updateRefSha()).toBe('commit-2'); + expect(result.getRefCalled()).toBe(false); + + result = setupUpdateRepoHandlers({ commitSha: 'commit-3' }); + await svc.updateRepo(repoInfo, files, 'Third update'); + + expect(result.updateRefSha()).toBe('commit-3'); + expect(result.getRefCalled()).toBe(false); + }); + + it('fails to update existing branch ref because of a stale sha, cleans cache and throws error', async () => { + // GIVEN: first commit succeeds + let result = setupUpdateRepoHandlers({ + commitSha: 'commit-1', + }); + const svc = new GithubService(() => 'pat'); + + // WHEN + await svc.updateRepo(repoInfo, files, 'First update'); + + // THEN + expect(result.updateRefSha()).toBe('commit-1'); + expect(result.getRefCalled()).toBe(true); + + // GIVEN: second commit fails because of a stale sha => clears cache entry + result = setupUpdateRepoHandlers({ + commitSha: 'commit-2', + updateRefError: 'fast forward', + }); + + await expect( + // WHEN + svc.updateRepo(repoInfo, files, 'Stale (Second) update'), + // THEN + ).rejects.toThrow(); + expect(result.getRefCalled()).toBe(false); + expect(result.updateRefSha()).toBe(''); + + // GIVEN: third commit succeeds and goes through getRef because cache was cleared + result = setupUpdateRepoHandlers({ + commitSha: 'commit-3', + }); + + // WHEN + await svc.updateRepo(repoInfo, files, 'Third update'); + + // THEN + expect(result.updateRefSha()).toBe('commit-3'); + expect(result.getRefCalled()).toBe(true); + }); + + it('fails to update existing branch ref because of a network error, does not clean cache and throws error', async () => { + // GIVEN: first commit succeeds + let result = setupUpdateRepoHandlers({ + commitSha: 'commit-1', + }); + const svc = new GithubService(() => 'pat'); + + // WHEN + await svc.updateRepo(repoInfo, files, 'First update'); + + // THEN + expect(result.updateRefSha()).toBe('commit-1'); + expect(result.getRefCalled()).toBe(true); + + // GIVEN: second commit fails because of a network error -> cache NOT cleared + result = setupUpdateRepoHandlers({ + commitSha: 'commit-2', + updateRefError: 'network', + }); + + await expect( + // WHEN + svc.updateRepo(repoInfo, files, 'Network fail (Second) update'), + // THEN + ).rejects.toThrow(); + expect(result.getRefCalled()).toBe(false); + expect(result.updateRefSha()).toBe(''); + + // GIVEN: third commit succeeds and goes through cache + result = setupUpdateRepoHandlers({ + commitSha: 'commit-3', + }); + + // WHEN + await svc.updateRepo(repoInfo, files, 'Third update'); + + // THEN + expect(result.updateRefSha()).toBe('commit-3'); + expect(result.getRefCalled()).toBe(false); + }); + }); + + describe('fetch', () => { + const repo: RepoMetadata = { + owner: 'twoGiants', + name: 'my-func', + url: 'https://github.com/twoGiants/my-func', + defaultBranch: 'main', + }; + + it('fetches all files from a repo', async () => { + setupRepoTreeAndBlobs(); + + const svc = new GithubService(() => 'pat'); + const files = await svc.fetch(repo); + + expect(files).toEqual([ + { + path: 'func.yaml', + mode: '100644', + content: 'name: my-func\nruntime: node', + type: 'blob', + }, + { path: 'index.js', mode: '100644', content: 'module.exports = {}', type: 'blob' }, + ]); + + function setupRepoTreeAndBlobs() { + server.use( + http.get(`${GITHUB_API}/repos/twoGiants/my-func/git/trees/main`, ({ request }) => { + const url = new URL(request.url); + expect(url.searchParams.get('recursive')).toBe('1'); + return HttpResponse.json({ + sha: 'tree-sha', + tree: [ + { path: 'src', type: 'tree', mode: '040000', sha: 'dir-sha' }, + { path: 'func.yaml', type: 'blob', mode: '100644', sha: 'blob-1' }, + { path: 'index.js', type: 'blob', mode: '100644', sha: 'blob-2' }, + ], + }); + }), + http.get(`${GITHUB_API}/repos/twoGiants/my-func/git/blobs/blob-1`, () => + HttpResponse.json({ + content: btoa('name: my-func\nruntime: node'), + encoding: 'base64', + }), + ), + http.get(`${GITHUB_API}/repos/twoGiants/my-func/git/blobs/blob-2`, () => + HttpResponse.json({ + content: btoa('module.exports = {}'), + encoding: 'base64', + }), + ), + ); + } + }); + }); +}); diff --git a/src/services/source-control/GithubService.ts b/src/services/source-control/GithubService.ts index 3133af9..9410582 100644 --- a/src/services/source-control/GithubService.ts +++ b/src/services/source-control/GithubService.ts @@ -1,11 +1,12 @@ import { Octokit } from '@octokit/rest'; -import { FileEntry, ForgeUser, RepoInfo, SourceRepo } from '../types'; +import { FileEntry, ForgeUser, RepoMetadata } from '../types'; import { SourceControlService } from './SourceControlService'; export class GithubService implements SourceControlService { private getToken: () => string; private cachedOctokit: Octokit | null = null; private cachedToken: string = ''; + private lastCommitSha = new Map(); constructor(getToken: () => string) { this.getToken = getToken; @@ -26,7 +27,7 @@ export class GithubService implements SourceControlService { return { name: data.login }; } - async listFunctionRepos(): Promise { + async listFunctionRepos(): Promise { const { data: user } = await this.octokit.users.getAuthenticated(); const { data } = await this.octokit.search.repos({ @@ -41,8 +42,8 @@ export class GithubService implements SourceControlService { })); } - async push(repo: RepoInfo, files: FileEntry[], message: string): Promise { - const { owner, repo: repoName, branch } = repo; + async push(repo: RepoMetadata, files: FileEntry[], message: string): Promise { + const { owner, name: repoName, defaultBranch: branch } = repo; const treeEntries = await Promise.all( files.map(async (file) => { @@ -83,7 +84,110 @@ export class GithubService implements SourceControlService { }); } - async fetchFileContent(repo: SourceRepo, path: string): Promise { + async updateRepo(repo: RepoMetadata, files: FileEntry[], message: string): Promise { + const { owner, name: repoName, defaultBranch: branch } = repo; + const refKey = `${owner}/${repoName}/${branch}`; + + const treeEntries = await Promise.all( + files.map(async (file) => { + const { data: blob } = await this.octokit.git.createBlob({ + owner, + repo: repoName, + content: file.content, + encoding: 'utf-8', + }); + return { + path: file.path, + mode: file.mode, + type: file.type as 'blob', + sha: blob.sha, + }; + }), + ); + + // GitHub's ref storage is eventually consistent. After a successful + // updateRef, a subsequent getRef may return a stale SHA. Use the + // locally cached commit SHA from the previous push when available. + // Fall back to getRef only on first push or if the cache is stale + // (someone else pushed, causing a "not a fast forward" error). + let parentCommitSha = this.lastCommitSha.get(refKey); + if (!parentCommitSha) { + const { data: ref } = await this.octokit.git.getRef({ + owner, + repo: repoName, + ref: `heads/${branch}`, + }); + parentCommitSha = ref.object.sha; + } + + const { data: parentCommit } = await this.octokit.git.getCommit({ + owner, + repo: repoName, + commit_sha: parentCommitSha, + }); + + const { data: tree } = await this.octokit.git.createTree({ + owner, + repo: repoName, + tree: treeEntries, + base_tree: parentCommit.tree.sha, + }); + + const { data: commit } = await this.octokit.git.createCommit({ + owner, + repo: repoName, + message, + tree: tree.sha, + parents: [parentCommitSha], + }); + + try { + await this.octokit.git.updateRef({ + owner, + repo: repoName, + ref: `heads/${branch}`, + sha: commit.sha, + }); + this.lastCommitSha.set(refKey, commit.sha); + } catch (err) { + // If cache was stale (someone else pushed). Clear and let next + // attempt use getRef for the fresh SHA. + const isStaleRef = err instanceof Error && err.message.includes('fast forward'); + if (isStaleRef) this.lastCommitSha.delete(refKey); + throw err; + } + } + + async fetch(repo: RepoMetadata): Promise { + const { data: repoContent } = await this.octokit.git.getTree({ + owner: repo.owner, + repo: repo.name, + tree_sha: repo.defaultBranch, + recursive: '1', + }); + + const filesAsBlobs = repoContent.tree.filter((entry) => entry.type === 'blob'); + + const files = await Promise.all( + filesAsBlobs.map(async (fileAsBlob) => { + const { data: file } = await this.octokit.git.getBlob({ + owner: repo.owner, + repo: repo.name, + file_sha: fileAsBlob.sha!, + }); + return { + path: fileAsBlob.path!, + mode: (fileAsBlob.mode ?? '100644') as FileEntry['mode'], + content: base64ToUtf8(file.content), + type: 'blob' as const, + }; + }), + ); + + return files; + } + + async fetchFileContent(repo: RepoMetadata, path: string): Promise { const { data } = await this.octokit.repos.getContent({ owner: repo.owner, repo: repo.name, @@ -93,6 +197,14 @@ export class GithubService implements SourceControlService { if (!('content' in data)) { throw new Error(`${path} is not a file`); } - return atob(data.content); + return base64ToUtf8(data.content); } } + +/** + * Decodes base64 to UTF-8. Unlike plain atob, handles multi-byte characters. + */ +function base64ToUtf8(base64: string): string { + const bytes = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0)); + return new TextDecoder().decode(bytes); +} diff --git a/src/services/source-control/SourceControlService.test.ts b/src/services/source-control/SourceControlService.test.ts deleted file mode 100644 index 33a8037..0000000 --- a/src/services/source-control/SourceControlService.test.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { GithubService } from './GithubService'; -import { FileEntry, RepoInfo, SourceRepo } from '../types'; - -const mockGetAuthenticated = jest.fn(); -const mockSearch = jest.fn(); -const mockGetContent = jest.fn(); -const mockCreateBlob = jest.fn(); -const mockCreateTree = jest.fn(); -const mockCreateCommit = jest.fn(); -const mockCreateRef = jest.fn(); - -jest.mock('@octokit/rest', () => ({ - Octokit: jest.fn().mockImplementation(() => ({ - users: { getAuthenticated: mockGetAuthenticated }, - search: { repos: mockSearch }, - repos: { getContent: mockGetContent }, - git: { - createBlob: mockCreateBlob, - createTree: mockCreateTree, - createCommit: mockCreateCommit, - createRef: mockCreateRef, - }, - })), -})); - -afterEach(() => { - jest.restoreAllMocks(); -}); - -describe('GithubService', () => { - beforeEach(() => { - mockGetAuthenticated.mockResolvedValue({ - data: { login: 'twoGiants', avatar_url: 'https://avatars.githubusercontent.com/u/123' }, - }); - }); - - it('lists function repos tagged with serverless-function topic', async () => { - mockSearch.mockResolvedValue({ - data: { - items: [ - { - owner: { login: 'twoGiants' }, - name: 'my-func', - html_url: 'https://github.com/twoGiants/my-func', - default_branch: 'main', - }, - ], - }, - }); - - const svc = new GithubService(() => 'fake-token'); - const repos: SourceRepo[] = await svc.listFunctionRepos(); - - expect(repos).toEqual([ - { - owner: 'twoGiants', - name: 'my-func', - url: 'https://github.com/twoGiants/my-func', - defaultBranch: 'main', - }, - ]); - expect(mockSearch).toHaveBeenCalledWith({ q: 'topic:serverless-function user:twoGiants' }); - }); - - it('fetches file content from a repo', async () => { - mockGetContent.mockResolvedValue({ - data: { content: btoa('name: my-func\nruntime: go\n'), encoding: 'base64' }, - }); - - const svc = new GithubService(() => 'fake-token'); - const content = await svc.fetchFileContent( - { - owner: 'twoGiants', - name: 'my-func', - url: 'https://github.com/twoGiants/my-func', - defaultBranch: 'main', - }, - 'func.yaml', - ); - - expect(content).toBe('name: my-func\nruntime: go\n'); - expect(mockGetContent).toHaveBeenCalledWith({ - owner: 'twoGiants', - repo: 'my-func', - path: 'func.yaml', - }); - }); - - describe('push', () => { - const repoInfo: RepoInfo = { owner: 'twoGiants', repo: 'my-func', branch: 'main' }; - const files: FileEntry[] = [ - { path: 'func.yaml', mode: '100644', content: 'name: my-func', type: 'blob' }, - ]; - - beforeEach(() => { - mockCreateBlob.mockResolvedValue({ data: { sha: 'blob-sha-123' } }); - mockCreateTree.mockResolvedValue({ data: { sha: 'tree-sha-123' } }); - mockCreateCommit.mockResolvedValue({ data: { sha: 'commit-sha-123' } }); - mockCreateRef.mockResolvedValue({}); - }); - - it('creates an initial commit with the provided files', async () => { - const svc = new GithubService(() => 'fake-token'); - await svc.push(repoInfo, files, 'Initialize function'); - - expect(mockCreateBlob).toHaveBeenCalledWith({ - owner: 'twoGiants', - repo: 'my-func', - content: 'name: my-func', - encoding: 'utf-8', - }); - expect(mockCreateTree).toHaveBeenCalledWith({ - owner: 'twoGiants', - repo: 'my-func', - tree: [{ path: 'func.yaml', mode: '100644', type: 'blob', sha: 'blob-sha-123' }], - }); - expect(mockCreateCommit).toHaveBeenCalledWith({ - owner: 'twoGiants', - repo: 'my-func', - message: 'Initialize function', - tree: 'tree-sha-123', - parents: [], - }); - expect(mockCreateRef).toHaveBeenCalledWith({ - owner: 'twoGiants', - repo: 'my-func', - ref: 'refs/heads/main', - sha: 'commit-sha-123', - }); - }); - - it('propagates errors from intermediate API calls', async () => { - mockCreateTree.mockRejectedValue(new Error('Validation Failed')); - const svc = new GithubService(() => 'fake-token'); - - await expect(svc.push(repoInfo, files, 'Initialize function')).rejects.toThrow( - 'Validation Failed', - ); - }); - }); - - describe('fetchUserInfo', () => { - it('returns ForgeUser on valid token', async () => { - const svc = new GithubService(() => ''); - const user = await svc.fetchUserInfo('valid-token'); - - expect(user).toEqual({ name: 'twoGiants' }); - }); - - it('throws on invalid token', async () => { - mockGetAuthenticated.mockRejectedValue(new Error('Bad credentials')); - const svc = new GithubService(() => ''); - - await expect(svc.fetchUserInfo('bad-token')).rejects.toThrow('Bad credentials'); - }); - }); -}); diff --git a/src/services/source-control/SourceControlService.ts b/src/services/source-control/SourceControlService.ts index c7555d8..6264d42 100644 --- a/src/services/source-control/SourceControlService.ts +++ b/src/services/source-control/SourceControlService.ts @@ -1,8 +1,10 @@ -import { FileEntry, ForgeUser as ForgeUserInfo, RepoInfo, SourceRepo } from '../types'; +import { FileEntry, ForgeUser, RepoMetadata } from '../types'; export interface SourceControlService { - listFunctionRepos(): Promise; - fetchFileContent(repo: SourceRepo, path: string): Promise; - push(repo: RepoInfo, files: FileEntry[], message: string): Promise; - fetchUserInfo(pat: string): Promise; + listFunctionRepos(): Promise; + fetchFileContent(repo: RepoMetadata, path: string): Promise; + push(repo: RepoMetadata, files: FileEntry[], message: string): Promise; + updateRepo(repo: RepoMetadata, files: FileEntry[], message: string): Promise; + fetch(repo: RepoMetadata): Promise; + fetchUserInfo(pat: string): Promise; } diff --git a/src/services/types.ts b/src/services/types.ts index f7cb21d..27802ed 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -18,13 +18,7 @@ export interface FunctionConfig { export type FunctionRuntime = 'node' | 'python' | 'go' | 'quarkus'; -export interface RepoInfo { - owner: string; - repo: string; - branch: string; -} - -export interface SourceRepo { +export interface RepoMetadata { owner: string; name: string; url: string; diff --git a/src/test-setup.ts b/src/test-setup.ts deleted file mode 100644 index 7b0828b..0000000 --- a/src/test-setup.ts +++ /dev/null @@ -1 +0,0 @@ -import '@testing-library/jest-dom'; diff --git a/src/utils/errorMessage.ts b/src/utils/errorMessage.ts deleted file mode 100644 index 7db4add..0000000 --- a/src/utils/errorMessage.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function errorMessage(err: unknown): string { - return err instanceof Error ? err.message : String(err); -} diff --git a/src/utils/utils.test.ts b/src/utils/utils.test.ts new file mode 100644 index 0000000..1156f31 --- /dev/null +++ b/src/utils/utils.test.ts @@ -0,0 +1,20 @@ +import { getLanguageFromPath } from './utils'; + +describe('getLanguageFromPath', () => { + it.each([ + ['index.js', 'javascript'], + ['handler.ts', 'typescript'], + ['main.go', 'go'], + ['app.py', 'python'], + ['func.yaml', 'yaml'], + ['config.yml', 'yaml'], + ['package.json', 'json'], + ['README.md', 'markdown'], + ['Dockerfile', 'dockerfile'], + ['.gitignore', 'plaintext'], + ['Makefile', 'plaintext'], + ['', 'plaintext'], + ])('returns correct language for %s', (path, expected) => { + expect(getLanguageFromPath(path)).toBe(expected); + }); +}); diff --git a/src/utils/utils.ts b/src/utils/utils.ts new file mode 100644 index 0000000..99bae26 --- /dev/null +++ b/src/utils/utils.ts @@ -0,0 +1,55 @@ +import { Language } from '@patternfly/react-code-editor'; + +const extensionMap: Record = { + js: 'javascript', + jsx: 'javascript', + ts: 'typescript', + tsx: 'typescript', + go: 'go', + py: 'python', + yaml: 'yaml', + yml: 'yaml', + json: 'json', + md: 'markdown', + sh: 'shell', + bash: 'shell', + html: 'html', + css: 'css', + xml: 'xml', + toml: 'plaintext', + txt: 'plaintext', +}; + +const filenameMap: Record = { + Dockerfile: 'dockerfile', + Makefile: 'plaintext', +}; + +export function getLanguageFromPath(path: string): Language { + const filename = path.split('/').pop() ?? ''; + if (filenameMap[filename]) return filenameMap[filename] as Language; + + const ext = filename.split('.').pop() ?? ''; + return (extensionMap[ext] as Language) ?? Language.plaintext; +} + +export function parseNamespaceAndRuntime(funcYaml: string): { + namespace: string; + runtime: string; +} { + const runtimeMatch = funcYaml.match(/^runtime:\s*(.+)$/m); + const namespaceMatch = funcYaml.match(/^namespace:\s*(.+)$/m); + if (!runtimeMatch) throw new Error(`func.yaml missing runtime field`); + return { namespace: namespaceMatch?.[1]?.trim() ?? '', runtime: runtimeMatch[1].trim() }; +} + +export const handlerMap: Record = { + node: 'index.js', + python: 'function/func.py', + go: 'handle.go', + quarkus: 'src/main/java/functions/Function.java', +}; + +export function errorMessage(err: unknown): string { + return err instanceof Error ? err.message : String(err); +} diff --git a/src/views/FunctionCreatePage.test.tsx b/src/views/FunctionCreatePage.test.tsx index 7d57ffe..d7ace7a 100644 --- a/src/views/FunctionCreatePage.test.tsx +++ b/src/views/FunctionCreatePage.test.tsx @@ -4,15 +4,15 @@ import { MemoryRouter } from 'react-router-dom'; import FunctionCreatePage from './FunctionCreatePage'; import { PAT_KEY } from '../services/types'; -const mockGenerateFunction = jest.fn(); -const mockPush = jest.fn(); -const mockNavigate = jest.fn(); +const mockGenerateFunction = vi.fn(); +const mockPush = vi.fn(); +const mockNavigate = vi.fn(); -jest.mock('react-i18next', () => ({ +vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string) => key }), })); -jest.mock('@openshift-console/dynamic-plugin-sdk', () => ({ +vi.mock('@openshift-console/dynamic-plugin-sdk', () => ({ DocumentTitle: ({ children }: { children: string }) => children, ListPageHeader: ({ title, children }: { title: string; children?: React.ReactNode }) => ( <> @@ -22,23 +22,23 @@ jest.mock('@openshift-console/dynamic-plugin-sdk', () => ({ ), })); -jest.mock('../services/function/useFunctionService', () => ({ +vi.mock('../services/function/useFunctionService', () => ({ useFunctionService: () => ({ generateFunction: mockGenerateFunction }), })); -jest.mock('../services/source-control/useSourceControlService', () => ({ +vi.mock('../services/source-control/useSourceControlService', () => ({ useSourceControlService: () => ({ push: mockPush, - listFunctionRepos: jest.fn(), - fetchFileContent: jest.fn(), + listFunctionRepos: vi.fn(), + fetchFileContent: vi.fn(), }), })); -jest.mock('react-router-dom-v5-compat', () => ({ +vi.mock('react-router-dom-v5-compat', () => ({ useNavigate: () => mockNavigate, })); -jest.mock('../components/UserAvatar', () => ({ +vi.mock('../components/UserAvatar', () => ({ UserAvatar: ({ enableReconnect }: { enableReconnect: boolean }) => ( {enableReconnect ? 'reconnect' : 'no-reconnect'} ), @@ -49,7 +49,7 @@ beforeEach(() => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); afterAll(() => { @@ -107,7 +107,7 @@ describe('FunctionCreatePage', () => { await waitFor(() => { expect(mockPush).toHaveBeenCalledWith( - { owner: 'testuser', repo: 'my-repo', branch: 'main' }, + { owner: 'testuser', name: 'my-repo', url: '', defaultBranch: 'main' }, files, 'Initialize Knative function project', ); diff --git a/src/views/FunctionCreatePage.tsx b/src/views/FunctionCreatePage.tsx index f35b75d..87d65d8 100644 --- a/src/views/FunctionCreatePage.tsx +++ b/src/views/FunctionCreatePage.tsx @@ -8,7 +8,7 @@ import { useFunctionService } from '../services/function/useFunctionService'; import { useSourceControlService } from '../services/source-control/useSourceControlService'; import { UserAvatar } from '../components/UserAvatar'; import { PAT_KEY } from '../services/types'; -import { errorMessage } from '../utils/errorMessage'; +import { errorMessage } from '../utils/utils'; export default function FunctionCreatePage() { const { t } = useTranslation('plugin__console-functions-plugin'); @@ -70,7 +70,7 @@ function useFunctionCreatePage() { }); await sourceControl.push( - { owner: data.owner, repo: data.repo, branch: data.branch }, + { owner: data.owner, name: data.repo, url: '', defaultBranch: data.branch }, files, 'Initialize Knative function project', ); diff --git a/src/views/FunctionEditPage.test.tsx b/src/views/FunctionEditPage.test.tsx new file mode 100644 index 0000000..65bd644 --- /dev/null +++ b/src/views/FunctionEditPage.test.tsx @@ -0,0 +1,199 @@ +import { act, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { http, HttpResponse, delay } from 'msw'; +import { server } from '../../testing/msw/server'; +import { MemoryRouter, Route, Routes } from 'react-router-dom-v5-compat'; +import FunctionEditPage from './FunctionEditPage'; + +const GITHUB_API = 'https://api.github.com'; + +vi.mock('react-i18next', () => ({ + useTranslation: () => ({ t: (key: string) => key }), +})); + +let mockOnChange: ((value: string) => void) | undefined; + +vi.mock('@openshift-console/dynamic-plugin-sdk', () => ({ + DocumentTitle: ({ children }: { children: string }) => children, + ListPageHeader: ({ title }: { title: string }) => title, + CodeEditor: ({ onChange }: { onChange?: (value: string) => void }) => { + mockOnChange = onChange; + return 'CodeEditor'; + }, +})); + +function renderEditPage(name: string) { + return render( + + + } /> + + , + ); +} + +function setupSearchReposHandler() { + server.use( + http.get(`${GITHUB_API}/search/repositories`, () => + HttpResponse.json({ + total_count: 1, + items: [ + { + owner: { login: 'twoGiants' }, + name: 'my-func', + html_url: '', + default_branch: 'main', + }, + ], + }), + ), + ); +} + +function setupFetchHandlers() { + setupSearchReposHandler(); + server.use( + http.get(`${GITHUB_API}/repos/twoGiants/my-func/git/trees/main`, () => + HttpResponse.json({ + sha: 'tree-sha', + tree: [ + { path: 'func.yaml', type: 'blob', mode: '100644', sha: 'blob-1' }, + { path: 'index.js', type: 'blob', mode: '100644', sha: 'blob-2' }, + ], + }), + ), + http.get(`${GITHUB_API}/repos/twoGiants/my-func/git/blobs/blob-1`, () => + HttpResponse.json({ + content: btoa('name: my-func\nruntime: node'), + encoding: 'base64', + }), + ), + http.get(`${GITHUB_API}/repos/twoGiants/my-func/git/blobs/blob-2`, () => + HttpResponse.json({ + content: btoa('module.exports = {}'), + encoding: 'base64', + }), + ), + ); +} + +describe('FunctionEditPage', () => { + beforeAll(() => { + sessionStorage.setItem('func-console-pat', 'test-pat'); + }); + + afterAll(() => { + sessionStorage.clear(); + }); + + it('shows loading state in tree while fetching files', () => { + setupSearchReposHandler(); + server.use( + http.get(`${GITHUB_API}/repos/twoGiants/my-func/git/trees/main`, async () => { + await delay('infinite'); + return HttpResponse.json({}); + }), + ); + + renderEditPage('my-func'); + + expect(screen.getByText('Loading source...')).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /Save & Deploy/ })).toBeDisabled(); + }); + + it('loads files from GitHub', async () => { + setupFetchHandlers(); + + renderEditPage('my-func'); + + await waitFor(() => { + expect(screen.getByText('func.yaml')).toBeInTheDocument(); + expect(screen.getByText('index.js')).toBeInTheDocument(); + }); + }); + + it('shows empty tree and disabled save when repo not found', async () => { + renderEditPage('nonexistent'); + + await waitFor(() => { + expect(screen.getByText('No files')).toBeInTheDocument(); + }); + expect(screen.getByRole('button', { name: /Save & Deploy/ })).toBeDisabled(); + expect(screen.getByRole('button', { name: /Back to Functions/ })).toBeInTheDocument(); + }); + + it('auto-selects handler file based on runtime from func.yaml', async () => { + setupFetchHandlers(); + + renderEditPage('my-func'); + + await waitFor(() => { + const indexItem = screen.getByText('index.js').closest('[role="treeitem"]'); + expect(indexItem).toHaveAttribute('aria-selected', 'true'); + }); + }); + + it('navigates back without modal when no changes made', async () => { + setupFetchHandlers(); + + renderEditPage('my-func'); + + await waitFor(() => { + expect(screen.getByText('func.yaml')).toBeInTheDocument(); + }); + + await userEvent.setup().click(screen.getByRole('button', { name: /Back to Functions/ })); + + expect(screen.queryByText('Unsaved changes')).not.toBeInTheDocument(); + }); + + it('shows success message after save and hides it after 2 seconds', async () => { + vi.useFakeTimers({ shouldAdvanceTime: true }); + setupFetchHandlers(); + setupPushHandlers(); + + renderEditPage('my-func'); + + await waitFor(() => { + expect(screen.getByText('func.yaml')).toBeInTheDocument(); + }); + + act(() => mockOnChange?.('edited content')); + + await userEvent.setup().click(screen.getByRole('button', { name: /Save & Deploy/ })); + + await waitFor(() => { + expect(screen.getByText('Pushed to GitHub. Deployment running...')).toBeInTheDocument(); + }); + + vi.advanceTimersByTime(2000); + + await waitFor(() => { + expect(screen.queryByText('Pushed to GitHub. Deployment running...')).not.toBeInTheDocument(); + }); + + vi.useRealTimers(); + }); +}); + +function setupPushHandlers() { + setupSearchReposHandler(); + server.use( + http.get(`${GITHUB_API}/repos/twoGiants/my-func/git/ref/:ref+`, () => + HttpResponse.json({ object: { sha: 'head-sha' } }), + ), + http.get(`${GITHUB_API}/repos/twoGiants/my-func/git/commits/head-sha`, () => + HttpResponse.json({ tree: { sha: 'parent-tree-sha' } }), + ), + http.post(`${GITHUB_API}/repos/twoGiants/my-func/git/blobs`, () => + HttpResponse.json({ sha: 'blob-sha' }), + ), + http.post(`${GITHUB_API}/repos/twoGiants/my-func/git/trees`, () => + HttpResponse.json({ sha: 'tree-sha' }), + ), + http.post(`${GITHUB_API}/repos/twoGiants/my-func/git/commits`, () => + HttpResponse.json({ sha: 'commit-sha' }), + ), + http.patch(`${GITHUB_API}/repos/twoGiants/my-func/git/refs/:ref+`, () => HttpResponse.json({})), + ); +} diff --git a/src/views/FunctionEditPage.tsx b/src/views/FunctionEditPage.tsx index 7d901e2..0da5c9e 100644 --- a/src/views/FunctionEditPage.tsx +++ b/src/views/FunctionEditPage.tsx @@ -1,20 +1,363 @@ -import { DocumentTitle, ListPageHeader } from '@openshift-console/dynamic-plugin-sdk'; -import { PageSection } from '@patternfly/react-core'; +import { CodeEditor, DocumentTitle, ListPageHeader } from '@openshift-console/dynamic-plugin-sdk'; +import { Language } from '@patternfly/react-code-editor'; +import { + Alert, + Button, + EmptyState, + EmptyStateBody, + Flex, + FlexItem, + Modal, + ModalBody, + ModalFooter, + ModalHeader, + PageSection, + Toolbar, + ToolbarContent, + ToolbarGroup, + ToolbarItem, +} from '@patternfly/react-core'; +import { ArrowLeftIcon, CodeIcon } from '@patternfly/react-icons'; +import { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useParams } from 'react-router-dom-v5-compat'; +import { useNavigate, useParams } from 'react-router-dom-v5-compat'; +import { FileTreeView } from '../components/FileTreeView'; import { UserAvatar } from '../components/UserAvatar'; +import { SourceControlService } from '../services/source-control/SourceControlService'; +import { useSourceControlService } from '../services/source-control/useSourceControlService'; +import { FileEntry, RepoMetadata } from '../services/types'; +import { getLanguageFromPath, handlerMap, parseNamespaceAndRuntime } from '../utils/utils'; + +// --- page component --- export default function FunctionEditPage() { const { t } = useTranslation('plugin__console-functions-plugin'); - const { name } = useParams<{ name: string }>(); + const state = useFunctionEditPage(); return ( <> {t('Edit function')} - + - {t('Coming soon.')} + + + + + + + + + + {t('Select a file from the tree view to start editing.')} + + + } + isLanguageLabelVisible + /> + + + + + ); +} + +// --- page hook --- + +interface FunctionEditPageState { + files: FileEntry[]; + selectedPath: string | null; + selectedContent: string; + selectedLanguage: Language; + dirtyPaths: Set; + hasChanges: boolean; + isLoading: boolean; + repoMetadata: RepoMetadata | undefined; + onFileSelect: (path: string) => void; + onFileChange: (content: string) => void; + saveFiles: () => Promise; +} + +function useFunctionEditPage(): FunctionEditPageState { + const sourceControl = useSourceControlService(); + const { name: repoName } = useParams<{ name: string }>(); + + const [files, setFiles] = useState([]); + const [originalFiles, setOriginalFiles] = useState([]); + const [repoMetadata, setRepoMetadata] = useState(); + const [selectedPath, setSelectedPath] = useState(''); + const [isLoading, setIsLoading] = useState(true); + + const dirtyFiles = new Set( + files + // Guard: originalFiles is empty during initial render before fetch completes. + .filter((f, i) => originalFiles[i] && f.content !== originalFiles[i].content) + .map((f) => f.path), + ); + const hasChanges = dirtyFiles.size > 0; + + const selectedFile = files.find((f) => f.path === selectedPath); + const selectedContent = selectedFile?.content ?? ''; + const selectedLanguage = getLanguageFromPath(selectedPath); + + useEffect(() => { + let ignore = false; + + async function loadFiles() { + let repo: { content: FileEntry[]; metadata: RepoMetadata }; + try { + // we ignore the error and show an empty tree if repo is not found + repo = await resolveRepoContent(repoName!, sourceControl); + } catch { + if (!ignore) setIsLoading(false); + return; + } + if (ignore) return; + + if (repo.content.length === 0) { + setIsLoading(false); + return; + } + + setFiles(repo.content); + // Shallow copy each entry so files and originalFiles hold + // different object references. When onFileChange updates a + // file's content via setFiles, the corresponding originalFiles + // entry stays unchanged, enabling dirty comparison. + setOriginalFiles(repo.content.map((f) => ({ ...f }))); + setRepoMetadata(repo.metadata); + setSelectedPath(determineHandler(repo.content)); + setIsLoading(false); + } + + loadFiles(); + return () => { + ignore = true; + }; + }, [repoName, sourceControl]); + + const onFileSelect = (path: string) => { + setSelectedPath(path); + }; + + const onFileChange = (content: string) => { + if (!selectedPath) return; + setFiles((prev) => prev.map((f) => (f.path === selectedPath ? { ...f, content } : f))); + }; + + const saveFiles = async () => { + if (!repoMetadata) return; + await sourceControl.updateRepo(repoMetadata, files, 'Update function files'); + setOriginalFiles(files.map((f) => ({ ...f }))); + }; + + return { + files, + selectedPath, + selectedContent, + selectedLanguage, + dirtyPaths: dirtyFiles, + hasChanges, + isLoading, + repoMetadata, + onFileSelect, + onFileChange, + saveFiles, + }; +} + +async function resolveRepoContent( + repoName: string, + sourceControl: SourceControlService, +): Promise<{ content: FileEntry[]; metadata: RepoMetadata }> { + const repos = await sourceControl.listFunctionRepos(); + + const repoMetadata = repos.find((r) => r.name === repoName); + if (!repoMetadata) throw new Error(`repository ${repoName} not found`); + + return { + content: await sourceControl.fetch(repoMetadata), + metadata: repoMetadata, + }; +} + +function determineHandler(loadedFiles: FileEntry[]): string { + const funcYaml = loadedFiles.find((f) => f.path === 'func.yaml'); + if (!funcYaml) return ''; + + const { runtime } = parseNamespaceAndRuntime(funcYaml.content); + + const handlerPath = handlerMap[runtime]; + if (loadedFiles.find((f) => f.path === handlerPath)) return handlerPath; + return ''; +} + +// --- toolbar component --- + +interface EditToolbarProps { + hasChanges: boolean; + onSave: () => Promise; +} + +function EditToolbar({ hasChanges, onSave }: EditToolbarProps) { + const { t } = useTranslation('plugin__console-functions-plugin'); + const { + isSaving, + errorMsg, + successMsg, + showLeaveModal, + handleSave, + handleBack, + onLeaveConfirm, + onLeaveCancel, + } = useEditToolbar(hasChanges, onSave); + + return ( + <> + + + + + + + + {errorMsg && } + {successMsg && } + + + + + + + + + + ); } + +function useEditToolbar( + hasChanges: boolean, + onSave: () => Promise, +): { + isSaving: boolean; + errorMsg: string; + successMsg: string; + showLeaveModal: boolean; + handleSave: () => Promise; + handleBack: () => void; + onLeaveConfirm: () => void; + onLeaveCancel: () => void; +} { + const navigate = useNavigate(); + const [isSaving, setIsSaving] = useState(false); + const [errorMsg, setErrorMsg] = useState(''); + const [successMsg, setSuccessMsg] = useState(''); + const [showLeaveModal, setShowLeaveModal] = useState(false); + + // Cleared on unmount to prevent state updates after navigation. + const dismissTimer = useRef>(); + + useEffect(() => { + return () => clearTimeout(dismissTimer.current); + }, []); + + const handleSave = async () => { + setIsSaving(true); + setErrorMsg(''); + setSuccessMsg(''); + try { + await onSave(); + setSuccessMsg('Pushed to GitHub. Deployment running...'); + dismissTimer.current = setTimeout(() => setSuccessMsg(''), 2000); + } catch (err) { + setErrorMsg(err instanceof Error ? err.message : String(err)); + } finally { + setIsSaving(false); + } + }; + + const handleBack = () => { + if (hasChanges) setShowLeaveModal(true); + else navigate('/faas'); + }; + + const onLeaveConfirm = () => { + setShowLeaveModal(false); + navigate('/faas'); + }; + + const onLeaveCancel = () => { + setShowLeaveModal(false); + }; + + return { + isSaving, + errorMsg, + successMsg, + showLeaveModal, + handleSave, + handleBack, + onLeaveConfirm, + onLeaveCancel, + }; +} + +// --- leave modal component --- + +function LeaveModal({ + isOpen, + onStay, + onLeave, +}: { + isOpen: boolean; + onStay: () => void; + onLeave: () => void; +}) { + const { t } = useTranslation('plugin__console-functions-plugin'); + + return ( + + + {t('You have unsaved changes. Leave anyway?')} + + + + + + ); +} diff --git a/src/views/FunctionsListPage.test.tsx b/src/views/FunctionsListPage.test.tsx index 108bd63..21024b1 100644 --- a/src/views/FunctionsListPage.test.tsx +++ b/src/views/FunctionsListPage.test.tsx @@ -3,11 +3,11 @@ import { MemoryRouter } from 'react-router-dom-v5-compat'; import FunctionsListPage from './FunctionsListPage'; import { PAT_KEY } from '../services/types'; -jest.mock('react-i18next', () => ({ +vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string) => key }), })); -jest.mock('@openshift-console/dynamic-plugin-sdk', () => ({ +vi.mock('@openshift-console/dynamic-plugin-sdk', () => ({ DocumentTitle: ({ children }: { children: string }) => children, ListPageHeader: ({ title, children }: { title: string; children?: React.ReactNode }) => ( <> @@ -17,22 +17,22 @@ jest.mock('@openshift-console/dynamic-plugin-sdk', () => ({ ), })); -const mockUseSourceControl = jest.fn(); -jest.mock('../services/source-control/useSourceControlService', () => ({ +const mockUseSourceControl = vi.fn(); +vi.mock('../services/source-control/useSourceControlService', () => ({ useSourceControlService: () => mockUseSourceControl(), })); -const mockUseClusterService = jest.fn(); -jest.mock('../services/cluster/useClusterService', () => ({ +const mockUseClusterService = vi.fn(); +vi.mock('../services/cluster/useClusterService', () => ({ useClusterService: () => mockUseClusterService(), })); -jest.mock('../components/FunctionTable', () => ({ +vi.mock('../components/FunctionTable', () => ({ FunctionTable: ({ functions }: { functions: { name: string }[] }) => functions.map((f) => f.name).join(','), })); -jest.mock('../components/UserAvatar', () => ({ +vi.mock('../components/UserAvatar', () => ({ UserAvatar: ({ enableReconnect }: { enableReconnect: boolean }) => ( {enableReconnect ? 'reconnect' : 'no-reconnect'} ), @@ -48,7 +48,7 @@ describe('FunctionsListPage', () => { }); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); afterAll(() => { @@ -58,8 +58,8 @@ describe('FunctionsListPage', () => { it('renders a spinner while loading', () => { renderAuthenticated(); mockUseSourceControl.mockReturnValue({ - listFunctionRepos: jest.fn().mockResolvedValue([]), - fetchFileContent: jest.fn(), + listFunctionRepos: vi.fn().mockResolvedValue([]), + fetchFileContent: vi.fn(), }); mockUseClusterService.mockReturnValue({ deployments: [], loaded: false, error: null }); @@ -75,8 +75,8 @@ describe('FunctionsListPage', () => { it('renders the empty state when loaded with no functions', async () => { renderAuthenticated(); mockUseSourceControl.mockReturnValue({ - listFunctionRepos: jest.fn().mockResolvedValue([]), - fetchFileContent: jest.fn(), + listFunctionRepos: vi.fn().mockResolvedValue([]), + fetchFileContent: vi.fn(), }); mockUseClusterService.mockReturnValue({ deployments: [], loaded: true, error: null }); @@ -92,7 +92,7 @@ describe('FunctionsListPage', () => { it('renders table when functions are loaded', async () => { renderAuthenticated(); mockUseSourceControl.mockReturnValue({ - listFunctionRepos: jest.fn().mockResolvedValue([ + listFunctionRepos: vi.fn().mockResolvedValue([ { owner: 'twoGiants', name: 'my-func', @@ -100,9 +100,7 @@ describe('FunctionsListPage', () => { defaultBranch: 'main', }, ]), - fetchFileContent: jest - .fn() - .mockResolvedValue('name: my-func\nruntime: go\nnamespace: demo\n'), + fetchFileContent: vi.fn().mockResolvedValue('name: my-func\nruntime: go\nnamespace: demo\n'), }); mockUseClusterService.mockReturnValue({ deployments: [ @@ -134,7 +132,7 @@ describe('FunctionsListPage', () => { it('shows NotDeployed status for repos without cluster deployment', async () => { renderAuthenticated(); mockUseSourceControl.mockReturnValue({ - listFunctionRepos: jest.fn().mockResolvedValue([ + listFunctionRepos: vi.fn().mockResolvedValue([ { owner: 'twoGiants', name: 'orphan-func', @@ -142,7 +140,7 @@ describe('FunctionsListPage', () => { defaultBranch: 'main', }, ]), - fetchFileContent: jest + fetchFileContent: vi .fn() .mockResolvedValue('name: orphan-func\nruntime: node\nnamespace: demo\n'), }); @@ -160,8 +158,8 @@ describe('FunctionsListPage', () => { it('renders empty state when GitHub API fails', async () => { renderAuthenticated(); mockUseSourceControl.mockReturnValue({ - listFunctionRepos: jest.fn().mockRejectedValue(new Error('Requires authentication')), - fetchFileContent: jest.fn(), + listFunctionRepos: vi.fn().mockRejectedValue(new Error('Requires authentication')), + fetchFileContent: vi.fn(), }); mockUseClusterService.mockReturnValue({ deployments: [], loaded: true, error: null }); @@ -175,10 +173,10 @@ describe('FunctionsListPage', () => { }); it('does not call listFunctionRepos when not authenticated', async () => { - const mockListRepos = jest.fn().mockResolvedValue([]); + const mockListRepos = vi.fn().mockResolvedValue([]); mockUseSourceControl.mockReturnValue({ listFunctionRepos: mockListRepos, - fetchFileContent: jest.fn(), + fetchFileContent: vi.fn(), }); mockUseClusterService.mockReturnValue({ deployments: [], loaded: true, error: null }); @@ -196,8 +194,8 @@ describe('FunctionsListPage', () => { it('renders UserAvatar in header', () => { renderAuthenticated(); mockUseSourceControl.mockReturnValue({ - listFunctionRepos: jest.fn().mockResolvedValue([]), - fetchFileContent: jest.fn(), + listFunctionRepos: vi.fn().mockResolvedValue([]), + fetchFileContent: vi.fn(), }); mockUseClusterService.mockReturnValue({ deployments: [], loaded: true, error: null }); @@ -212,8 +210,8 @@ describe('FunctionsListPage', () => { it('empty state receives hint and isCreateDisabled when not authenticated', async () => { mockUseSourceControl.mockReturnValue({ - listFunctionRepos: jest.fn().mockResolvedValue([]), - fetchFileContent: jest.fn(), + listFunctionRepos: vi.fn().mockResolvedValue([]), + fetchFileContent: vi.fn(), }); mockUseClusterService.mockReturnValue({ deployments: [], loaded: true, error: null }); diff --git a/src/views/FunctionsListPage.tsx b/src/views/FunctionsListPage.tsx index e6e6018..f8b0c02 100644 --- a/src/views/FunctionsListPage.tsx +++ b/src/views/FunctionsListPage.tsx @@ -16,6 +16,8 @@ import { ForgeConnectionContext, } from '../context/ForgeConnectionProvider'; import { UserAvatar } from '../components/UserAvatar'; +import { RepoMetadata } from '../services/types'; +import { parseNamespaceAndRuntime } from '../utils/utils'; export default function FunctionsListPage() { return ( @@ -103,23 +105,28 @@ function useFunctionListPage(): { let ignore = false; async function loadFunctionTableItems() { - const repos = await sourceControl.listFunctionRepos(); - const items = await Promise.all( - repos.map(async (repo) => { - const funcYaml = await sourceControl.fetchFileContent(repo, 'func.yaml'); - const { namespace, runtime } = parseNamespaceAndRuntime(funcYaml, repo.name); - return newItem(repo.name, namespace, runtime); - }), - ); - if (!ignore) { - setFunctionItems(items); - setReposLoaded(true); + let repos: RepoMetadata[]; + let items: FunctionTableItem[]; + try { + repos = await sourceControl.listFunctionRepos(); + items = await Promise.all( + repos.map(async (repo) => { + const funcYaml = await sourceControl.fetchFileContent(repo, 'func.yaml'); + const { namespace, runtime } = parseNamespaceAndRuntime(funcYaml); + return newItem(repo.name, namespace, runtime); + }), + ); + } catch { + if (!ignore) setReposLoaded(true); + return; } + if (ignore) return; + + setFunctionItems(items); + setReposLoaded(true); } - loadFunctionTableItems().catch(() => { - if (!ignore) setReposLoaded(true); - }); + loadFunctionTableItems(); return () => { ignore = true; }; @@ -142,19 +149,6 @@ function useFunctionListPage(): { return { functions, loaded, onEdit, isConnectedToForge }; } -function parseNamespaceAndRuntime( - funcYaml: string, - repoName: string, -): { - namespace: string; - runtime: string; -} { - const runtimeMatch = funcYaml.match(/^runtime:\s*(.+)$/m); - const namespaceMatch = funcYaml.match(/^namespace:\s*(.+)$/m); - if (!runtimeMatch) throw new Error(`func.yaml in ${repoName} missing runtime field`); - return { namespace: namespaceMatch?.[1]?.trim() ?? '', runtime: runtimeMatch[1].trim() }; -} - function newItem(repoName: string, namespace: string, runtime: string): FunctionTableItem { return { name: repoName, diff --git a/start-console.sh b/start-console.sh index f6b49a7..1172604 100755 --- a/start-console.sh +++ b/start-console.sh @@ -59,6 +59,10 @@ fi BRIDGE_PLUGINS="${PLUGIN_NAME}=http://${PLUGIN_HOST}:9001" BRIDGE_PLUGIN_PROXY='{"services":[{"consoleAPIPath":"/api/proxy/plugin/'"${PLUGIN_NAME}"'/backend/","endpoint":"http://'"${PLUGIN_HOST}"':8080","authorize":false}]}' +# Allow browser to connect to GitHub API (CSP connect-src). +# Production uses ConsolePlugin.spec.contentSecurityPolicy instead. +BRIDGE_CONTENT_SECURITY_POLICY="connect-src=https://api.github.com" + echo "BRIDGE_PLUGINS=$BRIDGE_PLUGINS" echo "BRIDGE_PLUGIN_PROXY=$BRIDGE_PLUGIN_PROXY" diff --git a/testing/msw/handlers.ts b/testing/msw/handlers.ts new file mode 100644 index 0000000..c08266b --- /dev/null +++ b/testing/msw/handlers.ts @@ -0,0 +1,16 @@ +import { http, HttpResponse } from 'msw'; + +const GITHUB_API = 'https://api.github.com'; + +/** Default GitHub API handlers. Override per test by using server.use(). */ +export const handlers = [ + // GET /user - authenticated user + http.get(`${GITHUB_API}/user`, () => + HttpResponse.json({ login: 'twoGiants' }), + ), + + // GET /search/repositories - search for function repos + http.get(`${GITHUB_API}/search/repositories`, () => + HttpResponse.json({ total_count: 0, items: [] }), + ), +]; diff --git a/testing/msw/server.ts b/testing/msw/server.ts new file mode 100644 index 0000000..e52fee0 --- /dev/null +++ b/testing/msw/server.ts @@ -0,0 +1,4 @@ +import { setupServer } from 'msw/node'; +import { handlers } from './handlers'; + +export const server = setupServer(...handlers); diff --git a/testing/setup.ts b/testing/setup.ts new file mode 100644 index 0000000..acb4c21 --- /dev/null +++ b/testing/setup.ts @@ -0,0 +1,6 @@ +import '@testing-library/jest-dom/vitest'; +import { server } from '../testing/msw/server'; + +beforeAll(() => server.listen({ onUnhandledRequest: 'error' })); +afterEach(() => server.resetHandlers()); +afterAll(() => server.close()); diff --git a/tsconfig.json b/tsconfig.json index 1573d16..efe5d45 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,9 +8,10 @@ "jsx": "react-jsx", "allowJs": true, "strict": true, - "noUnusedLocals": true + "noUnusedLocals": true, + "types": ["vitest/globals"] }, - "include": ["src"], + "include": ["src", "testing"], "exclude": ["node_modules"], "ts-node": { "files": true, diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..f211d59 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + environment: 'jsdom', + globals: true, + setupFiles: ['./testing/setup.ts'], + css: false, + }, +}); diff --git a/yarn.lock b/yarn.lock index 5367c1f..5d2e818 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,20 +12,47 @@ __metadata: languageName: node linkType: hard -"@asamuzakjp/css-color@npm:^3.2.0": - version: 3.2.0 - resolution: "@asamuzakjp/css-color@npm:3.2.0" +"@asamuzakjp/css-color@npm:^5.1.5": + version: 5.1.11 + resolution: "@asamuzakjp/css-color@npm:5.1.11" + dependencies: + "@asamuzakjp/generational-cache": "npm:^1.0.1" + "@csstools/css-calc": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^4.1.0" + "@csstools/css-parser-algorithms": "npm:^4.0.0" + "@csstools/css-tokenizer": "npm:^4.0.0" + checksum: 10c0/32720bdff8daea6a8847aba6cdfae55baa3b4a2690b51d21db7f0382bbd183f3d9f2d5126df50afd889062635684b2819e47113629ee2e80c99389e75f48d060 + languageName: node + linkType: hard + +"@asamuzakjp/dom-selector@npm:^7.0.6": + version: 7.1.1 + resolution: "@asamuzakjp/dom-selector@npm:7.1.1" dependencies: - "@csstools/css-calc": "npm:^2.1.3" - "@csstools/css-color-parser": "npm:^3.0.9" - "@csstools/css-parser-algorithms": "npm:^3.0.4" - "@csstools/css-tokenizer": "npm:^3.0.3" - lru-cache: "npm:^10.4.3" - checksum: 10c0/a4bf1c831751b1fae46b437e37e8a38c0b5bd58d23230157ae210bd1e905fe509b89b7c243e63d1522d852668a6292ed730a160e21342772b4e5b7b8ea14c092 + "@asamuzakjp/generational-cache": "npm:^1.0.1" + "@asamuzakjp/nwsapi": "npm:^2.3.9" + bidi-js: "npm:^1.0.3" + css-tree: "npm:^3.2.1" + is-potential-custom-element-name: "npm:^1.0.1" + checksum: 10c0/8cec1c618781c94de5836a215bbe5aafb4d8b835b18c51faf8547f4574afa39f92def3951e40123860062467613dd825f1e1600ff32e8045cc099a91796dcfb8 + languageName: node + linkType: hard + +"@asamuzakjp/generational-cache@npm:^1.0.1": + version: 1.0.1 + resolution: "@asamuzakjp/generational-cache@npm:1.0.1" + checksum: 10c0/1de62de43764e13fca3b9a31b7ea9b1bf0780fe053d266e40378a19ff8c66b543e011e6a0df02d410cd59bf981126706f176cdbb938985165202c4a079fe1057 + languageName: node + linkType: hard + +"@asamuzakjp/nwsapi@npm:^2.3.9": + version: 2.3.9 + resolution: "@asamuzakjp/nwsapi@npm:2.3.9" + checksum: 10c0/869b81382e775499c96c45c6dbe0d0766a6da04bcf0abb79f5333535c4e19946851acaa43398f896e2ecc5a1de9cf3db7cf8c4b1afac1ee3d15e21584546d74d languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": version: 7.29.0 resolution: "@babel/code-frame@npm:7.29.0" dependencies: @@ -43,7 +70,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.23.9, @babel/core@npm:^7.24.4, @babel/core@npm:^7.27.4, @babel/core@npm:^7.29.0": +"@babel/core@npm:^7.24.4, @babel/core@npm:^7.29.0": version: 7.29.0 resolution: "@babel/core@npm:7.29.0" dependencies: @@ -66,7 +93,7 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.27.5, @babel/generator@npm:^7.29.0": +"@babel/generator@npm:^7.29.0": version: 7.29.1 resolution: "@babel/generator@npm:7.29.1" dependencies: @@ -195,7 +222,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.28.6, @babel/helper-plugin-utils@npm:^7.8.0": +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-plugin-utils@npm:7.28.6" checksum: 10c0/3f5f8acc152fdbb69a84b8624145ff4f9b9f6e776cb989f9f968f8606eb7185c5c3cfcf3ba08534e37e1e0e1c118ac67080610333f56baa4f7376c99b5f1143d @@ -280,17 +307,6 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9": - version: 7.29.2 - resolution: "@babel/parser@npm:7.29.2" - dependencies: - "@babel/types": "npm:^7.29.0" - bin: - parser: ./bin/babel-parser.js - checksum: 10c0/e5a4e69e3ac7acdde995f37cf299a68458cfe7009dff66bd0962fd04920bef287201169006af365af479c08ff216bfefbb595e331f87f6ae7283858aebbc3317 - languageName: node - linkType: hard - "@babel/parser@npm:^7.24.4, @babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": version: 7.29.0 resolution: "@babel/parser@npm:7.29.0" @@ -370,50 +386,6 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-async-generators@npm:^7.8.4": - version: 7.8.4 - resolution: "@babel/plugin-syntax-async-generators@npm:7.8.4" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/d13efb282838481348c71073b6be6245b35d4f2f964a8f71e4174f235009f929ef7613df25f8d2338e2d3e44bc4265a9f8638c6aaa136d7a61fe95985f9725c8 - languageName: node - linkType: hard - -"@babel/plugin-syntax-bigint@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-bigint@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/686891b81af2bc74c39013655da368a480f17dd237bf9fbc32048e5865cb706d5a8f65438030da535b332b1d6b22feba336da8fa931f663b6b34e13147d12dde - languageName: node - linkType: hard - -"@babel/plugin-syntax-class-properties@npm:^7.12.13": - version: 7.12.13 - resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.12.13" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/95168fa186416195280b1264fb18afcdcdcea780b3515537b766cb90de6ce042d42dd6a204a39002f794ae5845b02afb0fd4861a3308a861204a55e68310a120 - languageName: node - linkType: hard - -"@babel/plugin-syntax-class-static-block@npm:^7.14.5": - version: 7.14.5 - resolution: "@babel/plugin-syntax-class-static-block@npm:7.14.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/4464bf9115f4a2d02ce1454411baf9cfb665af1da53709c5c56953e5e2913745b0fcce82982a00463d6facbdd93445c691024e310b91431a1e2f024b158f6371 - languageName: node - linkType: hard - "@babel/plugin-syntax-import-assertions@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-syntax-import-assertions@npm:7.28.6" @@ -425,7 +397,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-import-attributes@npm:^7.24.7, @babel/plugin-syntax-import-attributes@npm:^7.28.6": +"@babel/plugin-syntax-import-attributes@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-syntax-import-attributes@npm:7.28.6" dependencies: @@ -436,138 +408,6 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-import-meta@npm:^7.10.4": - version: 7.10.4 - resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.10.4" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/0b08b5e4c3128523d8e346f8cfc86824f0da2697b1be12d71af50a31aff7a56ceb873ed28779121051475010c28d6146a6bfea8518b150b71eeb4e46190172ee - languageName: node - linkType: hard - -"@babel/plugin-syntax-json-strings@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-json-strings@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/e98f31b2ec406c57757d115aac81d0336e8434101c224edd9a5c93cefa53faf63eacc69f3138960c8b25401315af03df37f68d316c151c4b933136716ed6906e - languageName: node - linkType: hard - -"@babel/plugin-syntax-jsx@npm:^7.27.1": - version: 7.28.6 - resolution: "@babel/plugin-syntax-jsx@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/b98fc3cd75e4ca3d5ca1162f610c286e14ede1486e0d297c13a5eb0ac85680ac9656d17d348bddd9160a54d797a08cea5eaac02b9330ddebb7b26732b7b99fb5 - languageName: node - linkType: hard - -"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": - version: 7.10.4 - resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.10.4" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/2594cfbe29411ad5bc2ad4058de7b2f6a8c5b86eda525a993959438615479e59c012c14aec979e538d60a584a1a799b60d1b8942c3b18468cb9d99b8fd34cd0b - languageName: node - linkType: hard - -"@babel/plugin-syntax-nullish-coalescing-operator@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-nullish-coalescing-operator@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/2024fbb1162899094cfc81152449b12bd0cc7053c6d4bda8ac2852545c87d0a851b1b72ed9560673cbf3ef6248257262c3c04aabf73117215c1b9cc7dd2542ce - languageName: node - linkType: hard - -"@babel/plugin-syntax-numeric-separator@npm:^7.10.4": - version: 7.10.4 - resolution: "@babel/plugin-syntax-numeric-separator@npm:7.10.4" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.10.4" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/c55a82b3113480942c6aa2fcbe976ff9caa74b7b1109ff4369641dfbc88d1da348aceb3c31b6ed311c84d1e7c479440b961906c735d0ab494f688bf2fd5b9bb9 - languageName: node - linkType: hard - -"@babel/plugin-syntax-object-rest-spread@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-object-rest-spread@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/ee1eab52ea6437e3101a0a7018b0da698545230015fc8ab129d292980ec6dff94d265e9e90070e8ae5fed42f08f1622c14c94552c77bcac784b37f503a82ff26 - languageName: node - linkType: hard - -"@babel/plugin-syntax-optional-catch-binding@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-optional-catch-binding@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/27e2493ab67a8ea6d693af1287f7e9acec206d1213ff107a928e85e173741e1d594196f99fec50e9dde404b09164f39dec5864c767212154ffe1caa6af0bc5af - languageName: node - linkType: hard - -"@babel/plugin-syntax-optional-chaining@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-optional-chaining@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/46edddf2faa6ebf94147b8e8540dfc60a5ab718e2de4d01b2c0bdf250a4d642c2bd47cbcbb739febcb2bf75514dbcefad3c52208787994b8d0f8822490f55e81 - languageName: node - linkType: hard - -"@babel/plugin-syntax-private-property-in-object@npm:^7.14.5": - version: 7.14.5 - resolution: "@babel/plugin-syntax-private-property-in-object@npm:7.14.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/69822772561706c87f0a65bc92d0772cea74d6bc0911537904a676d5ff496a6d3ac4e05a166d8125fce4a16605bace141afc3611074e170a994e66e5397787f3 - languageName: node - linkType: hard - -"@babel/plugin-syntax-top-level-await@npm:^7.14.5": - version: 7.14.5 - resolution: "@babel/plugin-syntax-top-level-await@npm:7.14.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/14bf6e65d5bc1231ffa9def5f0ef30b19b51c218fcecaa78cd1bdf7939dfdf23f90336080b7f5196916368e399934ce5d581492d8292b46a2fb569d8b2da106f - languageName: node - linkType: hard - -"@babel/plugin-syntax-typescript@npm:^7.27.1": - version: 7.28.6 - resolution: "@babel/plugin-syntax-typescript@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/b0c392a35624883ac480277401ac7d92d8646b66e33639f5d350de7a6723924265985ae11ab9ebd551740ded261c443eaa9a87ea19def9763ca1e0d78c97dea8 - languageName: node - linkType: hard - "@babel/plugin-syntax-unicode-sets-regex@npm:^7.18.6": version: 7.18.6 resolution: "@babel/plugin-syntax-unicode-sets-regex@npm:7.18.6" @@ -1314,7 +1154,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.5, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.4.4": +"@babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.5, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.4.4": version: 7.29.0 resolution: "@babel/types@npm:7.29.0" dependencies: @@ -1324,10 +1164,21 @@ __metadata: languageName: node linkType: hard -"@bcoe/v8-coverage@npm:^0.2.3": - version: 0.2.3 - resolution: "@bcoe/v8-coverage@npm:0.2.3" - checksum: 10c0/6b80ae4cb3db53f486da2dc63b6e190a74c8c3cca16bb2733f234a0b6a9382b09b146488ae08e2b22cf00f6c83e20f3e040a2f7894f05c045c946d6a090b1d52 +"@bcoe/v8-coverage@npm:^1.0.2": + version: 1.0.2 + resolution: "@bcoe/v8-coverage@npm:1.0.2" + checksum: 10c0/1eb1dc93cc17fb7abdcef21a6e7b867d6aa99a7ec88ec8207402b23d9083ab22a8011213f04b2cf26d535f1d22dc26139b7929e6c2134c254bd1e14ba5e678c3 + languageName: node + linkType: hard + +"@bramus/specificity@npm:^2.4.2": + version: 2.4.2 + resolution: "@bramus/specificity@npm:2.4.2" + dependencies: + css-tree: "npm:^3.0.0" + bin: + specificity: bin/cli.js + checksum: 10c0/c5f4e04e0bca0d2202598207a5eb0733c8109d12a68a329caa26373bec598d99db5bb785b8865fefa00fc01b08c6068138807ceb11a948fe15e904ed6cf4ba72 languageName: node linkType: hard @@ -1362,20 +1213,10 @@ __metadata: languageName: node linkType: hard -"@csstools/color-helpers@npm:^5.1.0": - version: 5.1.0 - resolution: "@csstools/color-helpers@npm:5.1.0" - checksum: 10c0/b7f99d2e455cf1c9b41a67a5327d5d02888cd5c8802a68b1887dffef537d9d4bc66b3c10c1e62b40bbed638b6c1d60b85a232f904ed7b39809c4029cb36567db - languageName: node - linkType: hard - -"@csstools/css-calc@npm:^2.1.3, @csstools/css-calc@npm:^2.1.4": - version: 2.1.4 - resolution: "@csstools/css-calc@npm:2.1.4" - peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.5 - "@csstools/css-tokenizer": ^3.0.4 - checksum: 10c0/42ce5793e55ec4d772083808a11e9fb2dfe36db3ec168713069a276b4c3882205b3507c4680224c28a5d35fe0bc2d308c77f8f2c39c7c09aad8747708eb8ddd8 +"@csstools/color-helpers@npm:^6.0.2": + version: 6.0.2 + resolution: "@csstools/color-helpers@npm:6.0.2" + checksum: 10c0/4c66574563d7c960010c11e41c2673675baff07c427cca6e8dddffa5777de45770d13ff3efce1c0642798089ad55de52870d9d8141f78db3fa5bba012f2d3789 languageName: node linkType: hard @@ -1389,25 +1230,26 @@ __metadata: languageName: node linkType: hard -"@csstools/css-color-parser@npm:^3.0.9": - version: 3.1.0 - resolution: "@csstools/css-color-parser@npm:3.1.0" - dependencies: - "@csstools/color-helpers": "npm:^5.1.0" - "@csstools/css-calc": "npm:^2.1.4" +"@csstools/css-calc@npm:^3.2.0": + version: 3.2.0 + resolution: "@csstools/css-calc@npm:3.2.0" peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.5 - "@csstools/css-tokenizer": ^3.0.4 - checksum: 10c0/0e0c670ad54ec8ec4d9b07568b80defd83b9482191f5e8ca84ab546b7be6db5d7cc2ba7ac9fae54488b129a4be235d6183d3aab4416fec5e89351f73af4222c5 + "@csstools/css-parser-algorithms": ^4.0.0 + "@csstools/css-tokenizer": ^4.0.0 + checksum: 10c0/a4dffeef3cb8ec9e8c1e44fa68c7634033050be52ea0b56ba6ac3815b635b587c6f3a8f8cd7b8f53881c2dd0ab9ec0af77227c532ed81b8e24a05aa997d22337 languageName: node linkType: hard -"@csstools/css-parser-algorithms@npm:^3.0.4": - version: 3.0.5 - resolution: "@csstools/css-parser-algorithms@npm:3.0.5" +"@csstools/css-color-parser@npm:^4.1.0": + version: 4.1.0 + resolution: "@csstools/css-color-parser@npm:4.1.0" + dependencies: + "@csstools/color-helpers": "npm:^6.0.2" + "@csstools/css-calc": "npm:^3.2.0" peerDependencies: - "@csstools/css-tokenizer": ^3.0.4 - checksum: 10c0/d9a1c888bd43849ae3437ca39251d5c95d2c8fd6b5ccdb7c45491dfd2c1cbdc3075645e80901d120e4d2c1993db9a5b2d83793b779dbbabcfb132adb142eb7f7 + "@csstools/css-parser-algorithms": ^4.0.0 + "@csstools/css-tokenizer": ^4.0.0 + checksum: 10c0/b5b8a697b4c1b22dd535b4d93b2ffce338d38e587ac1ab20b781c08328bfa99e5f763a99d990983560df543862fa9bd578ee966c18f9d3381c8e33c641d32a0e languageName: node linkType: hard @@ -1427,10 +1269,15 @@ __metadata: languageName: node linkType: hard -"@csstools/css-tokenizer@npm:^3.0.3": - version: 3.0.4 - resolution: "@csstools/css-tokenizer@npm:3.0.4" - checksum: 10c0/3b589f8e9942075a642213b389bab75a2d50d05d203727fcdac6827648a5572674caff07907eff3f9a2389d86a4ee47308fafe4f8588f4a77b7167c588d2559f +"@csstools/css-syntax-patches-for-csstree@npm:^1.1.1": + version: 1.1.3 + resolution: "@csstools/css-syntax-patches-for-csstree@npm:1.1.3" + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true + checksum: 10c0/3b8a686710a46bb460f9d560d52ce0de315828e6d452002b692013e95fbf53669d7a71e28c9b6b1333fa9f37f058fad93e5db3b8516444907713cb9aad299ce1 languageName: node linkType: hard @@ -1545,31 +1392,31 @@ __metadata: languageName: node linkType: hard -"@emnapi/core@npm:^1.4.3": - version: 1.9.1 - resolution: "@emnapi/core@npm:1.9.1" +"@emnapi/core@npm:1.10.0": + version: 1.10.0 + resolution: "@emnapi/core@npm:1.10.0" dependencies: - "@emnapi/wasi-threads": "npm:1.2.0" + "@emnapi/wasi-threads": "npm:1.2.1" tslib: "npm:^2.4.0" - checksum: 10c0/00e7a99a2bc3ad908ca8272ba861a934da87dffa8797a41316c4a3b571a1e4d2743e2fa14b1a0f131fa4a3c2018ddb601cd2a8cb7f574fa940af696df3c2fe8d + checksum: 10c0/f51d08227857b60632de7714d708124f0e100a1462dde6df8221760939aa3204a73193830371830fac0716f3ccd2129f2cac1b17cd7d7958bc4da9018a296edb languageName: node linkType: hard -"@emnapi/runtime@npm:^1.4.3": - version: 1.9.1 - resolution: "@emnapi/runtime@npm:1.9.1" +"@emnapi/runtime@npm:1.10.0": + version: 1.10.0 + resolution: "@emnapi/runtime@npm:1.10.0" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/750edca117e0363ab2de10622f8ee60e57d8690c2f29c49704813da5cd627c641798d7f3cb0d953c62fdc71688e02e333ddbf2c1204f38b47e3e40657332a6f5 + checksum: 10c0/953f14991d1aefb92ee6f8eb27dea725e484791a53a0cb5f47d9e0087b9a2c929ff2e92adf95af15d6ad456db6300c6b761ebf72b50a875b874a83520b3ba093 languageName: node linkType: hard -"@emnapi/wasi-threads@npm:1.2.0": - version: 1.2.0 - resolution: "@emnapi/wasi-threads@npm:1.2.0" +"@emnapi/wasi-threads@npm:1.2.1": + version: 1.2.1 + resolution: "@emnapi/wasi-threads@npm:1.2.1" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/1e3724b5814b06c14782fda87eee9b9aa68af01576c81ffeaefdf621ddb74386e419d5b3b1027b6a8172397729d95a92f814fc4b8d3c224376428faa07a6a01a + checksum: 10c0/32fcfa81ab396533b2ec1f4082b1ff779a05d9c836bbbd3f4398405b0e6814c0d9503b7993130e37bc6941dbc1ded49f55e9700ae9ca4e803bab2b5bc5deb331 languageName: node linkType: hard @@ -1843,6 +1690,18 @@ __metadata: languageName: node linkType: hard +"@exodus/bytes@npm:^1.11.0, @exodus/bytes@npm:^1.15.0, @exodus/bytes@npm:^1.6.0": + version: 1.15.0 + resolution: "@exodus/bytes@npm:1.15.0" + peerDependencies: + "@noble/hashes": ^1.8.0 || ^2.0.0 + peerDependenciesMeta: + "@noble/hashes": + optional: true + checksum: 10c0/b48aad9729653385d6ed055c28cfcf0b1b1481cf5d83f4375c12abd7988f1d20f69c80b5f95d4a1cc24d9abe32b9efc352a812d53884c26efea172aca8b6356d + languageName: node + linkType: hard + "@gar/promise-retry@npm:^1.0.0": version: 1.0.2 resolution: "@gar/promise-retry@npm:1.0.2" @@ -1892,6 +1751,67 @@ __metadata: languageName: node linkType: hard +"@inquirer/ansi@npm:^2.0.5": + version: 2.0.5 + resolution: "@inquirer/ansi@npm:2.0.5" + checksum: 10c0/ad61532e5bb47473e3d987c32d4015499a8ce5f4f86e46467e8e672fc52670beb303905d6b324e453935a61671f59f3b9b1b6a1edbbe1f64085e2bb87735e295 + languageName: node + linkType: hard + +"@inquirer/confirm@npm:^6.0.11": + version: 6.0.12 + resolution: "@inquirer/confirm@npm:6.0.12" + dependencies: + "@inquirer/core": "npm:^11.1.9" + "@inquirer/type": "npm:^4.0.5" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/36e9b1ef60e08562f07bcbcd78ba0a681b2fa3e5f54fa5e12303fc5982e8ba875ed782c24161e2295028b2b404ba690e841837303d16eeeb28df7aa9eb8aa835 + languageName: node + linkType: hard + +"@inquirer/core@npm:^11.1.9": + version: 11.1.9 + resolution: "@inquirer/core@npm:11.1.9" + dependencies: + "@inquirer/ansi": "npm:^2.0.5" + "@inquirer/figures": "npm:^2.0.5" + "@inquirer/type": "npm:^4.0.5" + cli-width: "npm:^4.1.0" + fast-wrap-ansi: "npm:^0.2.0" + mute-stream: "npm:^3.0.0" + signal-exit: "npm:^4.1.0" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/f7b162ce5f67fb75aab00a3668fdd8c8629aec790087840ea66ee8ead6009ab2066bec9cbf5bcc394ccdf130e6139051d6bace334b3a66c4f05349585213172c + languageName: node + linkType: hard + +"@inquirer/figures@npm:^2.0.5": + version: 2.0.5 + resolution: "@inquirer/figures@npm:2.0.5" + checksum: 10c0/139671b88f33f059aec85ed3fdf464999115573350c6dea61141adc1cfd43d14742b6cb68150c2ca9baf5a1bae618f990ed89b4430ae768d415bbd19944c56df + languageName: node + linkType: hard + +"@inquirer/type@npm:^4.0.5": + version: 4.0.5 + resolution: "@inquirer/type@npm:4.0.5" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/390edb0fd1f027f9c8dc26bac28486d38bbde6c19974ef1588ea187f54a2cb58db639ebca31fa81a8fe4a4e84c2f0953ab3f5a6768ba86649368c5e806148a6f + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -1915,372 +1835,67 @@ __metadata: languageName: node linkType: hard -"@istanbuljs/load-nyc-config@npm:^1.0.0": - version: 1.1.0 - resolution: "@istanbuljs/load-nyc-config@npm:1.1.0" +"@jridgewell/gen-mapping@npm:^0.3.12, @jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.13 + resolution: "@jridgewell/gen-mapping@npm:0.3.13" dependencies: - camelcase: "npm:^5.3.1" - find-up: "npm:^4.1.0" - get-package-type: "npm:^0.1.0" - js-yaml: "npm:^3.13.1" - resolve-from: "npm:^5.0.0" - checksum: 10c0/dd2a8b094887da5a1a2339543a4933d06db2e63cbbc2e288eb6431bd832065df0c099d091b6a67436e71b7d6bf85f01ce7c15f9253b4cbebcc3b9a496165ba42 + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/9a7d65fb13bd9aec1fbab74cda08496839b7e2ceb31f5ab922b323e94d7c481ce0fc4fd7e12e2610915ed8af51178bdc61e168e92a8c8b8303b030b03489b13b languageName: node linkType: hard -"@istanbuljs/schema@npm:^0.1.2, @istanbuljs/schema@npm:^0.1.3": - version: 0.1.3 - resolution: "@istanbuljs/schema@npm:0.1.3" - checksum: 10c0/61c5286771676c9ca3eb2bd8a7310a9c063fb6e0e9712225c8471c582d157392c88f5353581c8c9adbe0dff98892317d2fdfc56c3499aa42e0194405206a963a +"@jridgewell/remapping@npm:^2.3.5": + version: 2.3.5 + resolution: "@jridgewell/remapping@npm:2.3.5" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/3de494219ffeb2c5c38711d0d7bb128097edf91893090a2dbc8ee0b55d092bb7347b1fd0f478486c5eab010e855c73927b1666f2107516d472d24a73017d1194 languageName: node linkType: hard -"@jest/console@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/console@npm:30.3.0" - dependencies: - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - jest-message-util: "npm:30.3.0" - jest-util: "npm:30.3.0" - slash: "npm:^3.0.0" - checksum: 10c0/5458f26b0591b847b719a707cbd1d6b2b99960784a1480a28d19200a807b6092f066c1bd1810df8c6adebf934a64de7b6022dc35082cd7c8f09f35940da104d9 +"@jridgewell/resolve-uri@npm:^3.0.3, @jridgewell/resolve-uri@npm:^3.1.0": + version: 3.1.2 + resolution: "@jridgewell/resolve-uri@npm:3.1.2" + checksum: 10c0/d502e6fb516b35032331406d4e962c21fe77cdf1cbdb49c6142bcbd9e30507094b18972778a6e27cbad756209cfe34b1a27729e6fa08a2eb92b33943f680cf1e languageName: node linkType: hard -"@jest/core@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/core@npm:30.3.0" +"@jridgewell/source-map@npm:^0.3.3": + version: 0.3.11 + resolution: "@jridgewell/source-map@npm:0.3.11" dependencies: - "@jest/console": "npm:30.3.0" - "@jest/pattern": "npm:30.0.1" - "@jest/reporters": "npm:30.3.0" - "@jest/test-result": "npm:30.3.0" - "@jest/transform": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - ansi-escapes: "npm:^4.3.2" - chalk: "npm:^4.1.2" - ci-info: "npm:^4.2.0" - exit-x: "npm:^0.2.2" - graceful-fs: "npm:^4.2.11" - jest-changed-files: "npm:30.3.0" - jest-config: "npm:30.3.0" - jest-haste-map: "npm:30.3.0" - jest-message-util: "npm:30.3.0" - jest-regex-util: "npm:30.0.1" - jest-resolve: "npm:30.3.0" - jest-resolve-dependencies: "npm:30.3.0" - jest-runner: "npm:30.3.0" - jest-runtime: "npm:30.3.0" - jest-snapshot: "npm:30.3.0" - jest-util: "npm:30.3.0" - jest-validate: "npm:30.3.0" - jest-watcher: "npm:30.3.0" - pretty-format: "npm:30.3.0" - slash: "npm:^3.0.0" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - checksum: 10c0/1735f2263cca10c6cae4e1dbde9c3ccb36e2cbd1cc10bac6fc45e187b06c4e33a6a029f9a6444a3cd43a2a44ffaec3b686d94f70965cebf2b885b198c8615322 + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.25" + checksum: 10c0/50a4fdafe0b8f655cb2877e59fe81320272eaa4ccdbe6b9b87f10614b2220399ae3e05c16137a59db1f189523b42c7f88bd097ee991dbd7bc0e01113c583e844 languageName: node linkType: hard -"@jest/diff-sequences@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/diff-sequences@npm:30.3.0" - checksum: 10c0/8922c16a869b839b6c05f677023b3e5a9aa1610ad78a9c5ec8bd6654e35e8136ea1c7b60ad561910e2ad964bfdb0b09b0254ff8dcfacd4562095766f60c63d76 +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0, @jridgewell/sourcemap-codec@npm:^1.5.5": + version: 1.5.5 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" + checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 languageName: node linkType: hard -"@jest/environment-jsdom-abstract@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/environment-jsdom-abstract@npm:30.3.0" +"@jridgewell/trace-mapping@npm:0.3.9": + version: 0.3.9 + resolution: "@jridgewell/trace-mapping@npm:0.3.9" dependencies: - "@jest/environment": "npm:30.3.0" - "@jest/fake-timers": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/jsdom": "npm:^21.1.7" - "@types/node": "npm:*" - jest-mock: "npm:30.3.0" - jest-util: "npm:30.3.0" - peerDependencies: - canvas: ^3.0.0 - jsdom: "*" - peerDependenciesMeta: - canvas: - optional: true - checksum: 10c0/95ec44bc3cc4cf91660acd4bf7da547414a1d797a32442dd6c4f6d47c82bb4b6eb2ee6b7a5d177d0827378793433a743462d24f5e445075b69edfbc28ab5ca40 + "@jridgewell/resolve-uri": "npm:^3.0.3" + "@jridgewell/sourcemap-codec": "npm:^1.4.10" + checksum: 10c0/fa425b606d7c7ee5bfa6a31a7b050dd5814b4082f318e0e4190f991902181b4330f43f4805db1dd4f2433fd0ed9cc7a7b9c2683f1deeab1df1b0a98b1e24055b languageName: node linkType: hard -"@jest/environment@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/environment@npm:30.3.0" +"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.28, @jridgewell/trace-mapping@npm:^0.3.31": + version: 0.3.31 + resolution: "@jridgewell/trace-mapping@npm:0.3.31" dependencies: - "@jest/fake-timers": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - jest-mock: "npm:30.3.0" - checksum: 10c0/4068ccc2e4761e52909239c21e71f73b57ad087bd120b75d3232c68d911686d68fd0fb20e19725517a624b0aa9d45431b00503bd1d5ab2f4958e1a18d265d8d5 - languageName: node - linkType: hard - -"@jest/expect-utils@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/expect-utils@npm:30.3.0" - dependencies: - "@jest/get-type": "npm:30.1.0" - checksum: 10c0/4bb60fb434cb8ed325735bd39171b61621e110502ecc502089805d203ecb17b9fc5a400aeffb83b41fabcc819628a9c38c955f90a716d6aaff193d10926fc854 - languageName: node - linkType: hard - -"@jest/expect@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/expect@npm:30.3.0" - dependencies: - expect: "npm:30.3.0" - jest-snapshot: "npm:30.3.0" - checksum: 10c0/1e052975fdf2b977a63dc9f3db1de56be9dce8e5cd660d9c72cc25093324b990b3e93318cd0c1ff9df7cb30ec7eef71331bc7e19d39700eb3f4498e17ee4c9e0 - languageName: node - linkType: hard - -"@jest/fake-timers@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/fake-timers@npm:30.3.0" - dependencies: - "@jest/types": "npm:30.3.0" - "@sinonjs/fake-timers": "npm:^15.0.0" - "@types/node": "npm:*" - jest-message-util: "npm:30.3.0" - jest-mock: "npm:30.3.0" - jest-util: "npm:30.3.0" - checksum: 10c0/114855ca14d6b34c886855445852a5b960bc3df0ef97c4b971b375747fe0206b3111ec60efc6e658565677022f0d790acd7e232e478f3390ea854d04dea0c4d8 - languageName: node - linkType: hard - -"@jest/get-type@npm:30.1.0": - version: 30.1.0 - resolution: "@jest/get-type@npm:30.1.0" - checksum: 10c0/3e65fd5015f551c51ec68fca31bbd25b466be0e8ee8075d9610fa1c686ea1e70a942a0effc7b10f4ea9a338c24337e1ad97ff69d3ebacc4681b7e3e80d1b24ac - languageName: node - linkType: hard - -"@jest/globals@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/globals@npm:30.3.0" - dependencies: - "@jest/environment": "npm:30.3.0" - "@jest/expect": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - jest-mock: "npm:30.3.0" - checksum: 10c0/013554dcbf75867e715801e98a5c6eefbea67cb388efd019be9e0d83979d7354874c4b33bbabc95de698215f5b891e921c26a284841504f9825fd789432b1cd0 - languageName: node - linkType: hard - -"@jest/pattern@npm:30.0.1": - version: 30.0.1 - resolution: "@jest/pattern@npm:30.0.1" - dependencies: - "@types/node": "npm:*" - jest-regex-util: "npm:30.0.1" - checksum: 10c0/32c5a7bfb6c591f004dac0ed36d645002ed168971e4c89bd915d1577031672870032594767557b855c5bc330aa1e39a2f54bf150d2ee88a7a0886e9cb65318bc - languageName: node - linkType: hard - -"@jest/reporters@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/reporters@npm:30.3.0" - dependencies: - "@bcoe/v8-coverage": "npm:^0.2.3" - "@jest/console": "npm:30.3.0" - "@jest/test-result": "npm:30.3.0" - "@jest/transform": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@jridgewell/trace-mapping": "npm:^0.3.25" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - collect-v8-coverage: "npm:^1.0.2" - exit-x: "npm:^0.2.2" - glob: "npm:^10.5.0" - graceful-fs: "npm:^4.2.11" - istanbul-lib-coverage: "npm:^3.0.0" - istanbul-lib-instrument: "npm:^6.0.0" - istanbul-lib-report: "npm:^3.0.0" - istanbul-lib-source-maps: "npm:^5.0.0" - istanbul-reports: "npm:^3.1.3" - jest-message-util: "npm:30.3.0" - jest-util: "npm:30.3.0" - jest-worker: "npm:30.3.0" - slash: "npm:^3.0.0" - string-length: "npm:^4.0.2" - v8-to-istanbul: "npm:^9.0.1" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - checksum: 10c0/e1b6fb13df94435d4b8e6f4d4bd1c27dfc572ca7393b0a95d14c98013abe3c962aa28e2c56864f3ddd0894834d21c9a67485d11e6c31532aaaeea66ca6a2a026 - languageName: node - linkType: hard - -"@jest/schemas@npm:30.0.5": - version: 30.0.5 - resolution: "@jest/schemas@npm:30.0.5" - dependencies: - "@sinclair/typebox": "npm:^0.34.0" - checksum: 10c0/449dcd7ec5c6505e9ac3169d1143937e67044ae3e66a729ce4baf31812dfd30535f2b3b2934393c97cfdf5984ff581120e6b38f62b8560c8b5b7cc07f4175f65 - languageName: node - linkType: hard - -"@jest/snapshot-utils@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/snapshot-utils@npm:30.3.0" - dependencies: - "@jest/types": "npm:30.3.0" - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - natural-compare: "npm:^1.4.0" - checksum: 10c0/ba4fea05a418b257d128d8f9eb7672a9004952563a45ad577bed80e5b2ea2ec6e6d3a24535781cc6530d9904d8fda7b27d15952d079ccdbe88f87a5e71112df0 - languageName: node - linkType: hard - -"@jest/source-map@npm:30.0.1": - version: 30.0.1 - resolution: "@jest/source-map@npm:30.0.1" - dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.25" - callsites: "npm:^3.1.0" - graceful-fs: "npm:^4.2.11" - checksum: 10c0/e7bda2786fc9f483d9dd7566c58c4bd948830997be862dfe80a3ae5550ff3f84753abb52e705d02ebe9db9f34ba7ebec4c2db11882048cdeef7a66f6332b3897 - languageName: node - linkType: hard - -"@jest/test-result@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/test-result@npm:30.3.0" - dependencies: - "@jest/console": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/istanbul-lib-coverage": "npm:^2.0.6" - collect-v8-coverage: "npm:^1.0.2" - checksum: 10c0/67bcd405d0a1ac85b55afabf26e0ee0f184f9cfe0e659a44e0e4a4456c1c7fed9d2288f0116b017eaddfa49ded8c44426b8694c44f9a8a2af35be9202b8a9165 - languageName: node - linkType: hard - -"@jest/test-sequencer@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/test-sequencer@npm:30.3.0" - dependencies: - "@jest/test-result": "npm:30.3.0" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.3.0" - slash: "npm:^3.0.0" - checksum: 10c0/698be35e7145e79ea9d66071d4ec255f6cef4b5972b5142d299f3edbcbc0428cadf8ddecc6d21e938c98ed72b73b15a6d5f81e7b8b370aaa130d2f6b26fd017c - languageName: node - linkType: hard - -"@jest/transform@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/transform@npm:30.3.0" - dependencies: - "@babel/core": "npm:^7.27.4" - "@jest/types": "npm:30.3.0" - "@jridgewell/trace-mapping": "npm:^0.3.25" - babel-plugin-istanbul: "npm:^7.0.1" - chalk: "npm:^4.1.2" - convert-source-map: "npm:^2.0.0" - fast-json-stable-stringify: "npm:^2.1.0" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.3.0" - jest-regex-util: "npm:30.0.1" - jest-util: "npm:30.3.0" - pirates: "npm:^4.0.7" - slash: "npm:^3.0.0" - write-file-atomic: "npm:^5.0.1" - checksum: 10c0/5ad0b5361910680b5160e3dc347c0beb75b4edc35a165ef4fc55837d01365179c276dd6f9cc80f7db94048c641b0c188757e1c98c6d4e9b55577956efbc00574 - languageName: node - linkType: hard - -"@jest/types@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/types@npm:30.3.0" - dependencies: - "@jest/pattern": "npm:30.0.1" - "@jest/schemas": "npm:30.0.5" - "@types/istanbul-lib-coverage": "npm:^2.0.6" - "@types/istanbul-reports": "npm:^3.0.4" - "@types/node": "npm:*" - "@types/yargs": "npm:^17.0.33" - chalk: "npm:^4.1.2" - checksum: 10c0/c3e3f4de0b77a7ced345f47d3687b1094c1b6c1521529a7ca66a76f9a80194f79179a1dbc32d6761a5b67914a8f78be1e65d1408107efcb1f252c4a63b5ddd92 - languageName: node - linkType: hard - -"@jridgewell/gen-mapping@npm:^0.3.12, @jridgewell/gen-mapping@npm:^0.3.5": - version: 0.3.13 - resolution: "@jridgewell/gen-mapping@npm:0.3.13" - dependencies: - "@jridgewell/sourcemap-codec": "npm:^1.5.0" - "@jridgewell/trace-mapping": "npm:^0.3.24" - checksum: 10c0/9a7d65fb13bd9aec1fbab74cda08496839b7e2ceb31f5ab922b323e94d7c481ce0fc4fd7e12e2610915ed8af51178bdc61e168e92a8c8b8303b030b03489b13b - languageName: node - linkType: hard - -"@jridgewell/remapping@npm:^2.3.5": - version: 2.3.5 - resolution: "@jridgewell/remapping@npm:2.3.5" - dependencies: - "@jridgewell/gen-mapping": "npm:^0.3.5" - "@jridgewell/trace-mapping": "npm:^0.3.24" - checksum: 10c0/3de494219ffeb2c5c38711d0d7bb128097edf91893090a2dbc8ee0b55d092bb7347b1fd0f478486c5eab010e855c73927b1666f2107516d472d24a73017d1194 - languageName: node - linkType: hard - -"@jridgewell/resolve-uri@npm:^3.0.3, @jridgewell/resolve-uri@npm:^3.1.0": - version: 3.1.2 - resolution: "@jridgewell/resolve-uri@npm:3.1.2" - checksum: 10c0/d502e6fb516b35032331406d4e962c21fe77cdf1cbdb49c6142bcbd9e30507094b18972778a6e27cbad756209cfe34b1a27729e6fa08a2eb92b33943f680cf1e - languageName: node - linkType: hard - -"@jridgewell/source-map@npm:^0.3.3": - version: 0.3.11 - resolution: "@jridgewell/source-map@npm:0.3.11" - dependencies: - "@jridgewell/gen-mapping": "npm:^0.3.5" - "@jridgewell/trace-mapping": "npm:^0.3.25" - checksum: 10c0/50a4fdafe0b8f655cb2877e59fe81320272eaa4ccdbe6b9b87f10614b2220399ae3e05c16137a59db1f189523b42c7f88bd097ee991dbd7bc0e01113c583e844 - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0": - version: 1.5.5 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" - checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:0.3.9": - version: 0.3.9 - resolution: "@jridgewell/trace-mapping@npm:0.3.9" - dependencies: - "@jridgewell/resolve-uri": "npm:^3.0.3" - "@jridgewell/sourcemap-codec": "npm:^1.4.10" - checksum: 10c0/fa425b606d7c7ee5bfa6a31a7b050dd5814b4082f318e0e4190f991902181b4330f43f4805db1dd4f2433fd0ed9cc7a7b9c2683f1deeab1df1b0a98b1e24055b - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.28": - version: 0.3.31 - resolution: "@jridgewell/trace-mapping@npm:0.3.31" - dependencies: - "@jridgewell/resolve-uri": "npm:^3.1.0" - "@jridgewell/sourcemap-codec": "npm:^1.4.14" - checksum: 10c0/4b30ec8cd56c5fd9a661f088230af01e0c1a3888d11ffb6b47639700f71225be21d1f7e168048d6d4f9449207b978a235c07c8f15c07705685d16dc06280e9d9 + "@jridgewell/resolve-uri": "npm:^3.1.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.14" + checksum: 10c0/4b30ec8cd56c5fd9a661f088230af01e0c1a3888d11ffb6b47639700f71225be21d1f7e168048d6d4f9449207b978a235c07c8f15c07705685d16dc06280e9d9 languageName: node linkType: hard @@ -2379,14 +1994,51 @@ __metadata: languageName: node linkType: hard -"@napi-rs/wasm-runtime@npm:^0.2.11": - version: 0.2.12 - resolution: "@napi-rs/wasm-runtime@npm:0.2.12" +"@monaco-editor/loader@npm:^1.5.0": + version: 1.7.0 + resolution: "@monaco-editor/loader@npm:1.7.0" + dependencies: + state-local: "npm:^1.0.6" + checksum: 10c0/1fd3579cb09b669493cf553dfc0723a93483140a44353ce9a739827edfa7b2c6541b254024d15c48176ece749ef666b6d16cce6cf0e4396c7fa1c5a48012d08a + languageName: node + linkType: hard + +"@monaco-editor/react@npm:^4.6.0": + version: 4.7.0 + resolution: "@monaco-editor/react@npm:4.7.0" dependencies: - "@emnapi/core": "npm:^1.4.3" - "@emnapi/runtime": "npm:^1.4.3" - "@tybys/wasm-util": "npm:^0.10.0" - checksum: 10c0/6d07922c0613aab30c6a497f4df297ca7c54e5b480e00035e0209b872d5c6aab7162fc49477267556109c2c7ed1eb9c65a174e27e9b87568106a87b0a6e3ca7d + "@monaco-editor/loader": "npm:^1.5.0" + peerDependencies: + monaco-editor: ">= 0.25.0 < 1" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + checksum: 10c0/a4e91c6eda1a71f5fd23871bd801de435490ccbc43934d23cba65cefe2be7e9d02c9a57c4ef80fc9fe99e4d4deea51e5db19cb4e0ecf3f51818dda0eb9cdbf12 + languageName: node + linkType: hard + +"@mswjs/interceptors@npm:^0.41.3": + version: 0.41.6 + resolution: "@mswjs/interceptors@npm:0.41.6" + dependencies: + "@open-draft/deferred-promise": "npm:^2.2.0" + "@open-draft/logger": "npm:^0.3.0" + "@open-draft/until": "npm:^2.0.0" + is-node-process: "npm:^1.2.0" + outvariant: "npm:^1.4.3" + strict-event-emitter: "npm:^0.5.1" + checksum: 10c0/abedbd64c7602dd358ded2a92e0a84b0d21cc0d15cb9d6a8d73283f46938f2a5adb69d9be8124c5c5c3394cc980e758a34bd77de1aa2677b7b2b399d34c148ce + languageName: node + linkType: hard + +"@napi-rs/wasm-runtime@npm:^1.1.4": + version: 1.1.4 + resolution: "@napi-rs/wasm-runtime@npm:1.1.4" + dependencies: + "@tybys/wasm-util": "npm:^0.10.1" + peerDependencies: + "@emnapi/core": ^1.7.1 + "@emnapi/runtime": ^1.7.1 + checksum: 10c0/2e88e1955258949ccf2d18c79975821ad38071b465ef126a5e14110977b97868867b016c1ad046e963cccc42c0bd9db6c8ff5fd1ebb61b87bb3487f339041658 languageName: node linkType: hard @@ -2571,6 +2223,37 @@ __metadata: languageName: node linkType: hard +"@open-draft/deferred-promise@npm:^2.2.0": + version: 2.2.0 + resolution: "@open-draft/deferred-promise@npm:2.2.0" + checksum: 10c0/eafc1b1d0fc8edb5e1c753c5e0f3293410b40dde2f92688211a54806d4136887051f39b98c1950370be258483deac9dfd17cf8b96557553765198ef2547e4549 + languageName: node + linkType: hard + +"@open-draft/deferred-promise@npm:^3.0.0": + version: 3.0.0 + resolution: "@open-draft/deferred-promise@npm:3.0.0" + checksum: 10c0/4dd697e55495e436be9536413cc9975e792e9ca7472e81e3d3d69e9b65cb678465aac90b463ac02f2b490c0581c4e9aa8a33d2a5857decbe2c6d9ffb310f8e1f + languageName: node + linkType: hard + +"@open-draft/logger@npm:^0.3.0": + version: 0.3.0 + resolution: "@open-draft/logger@npm:0.3.0" + dependencies: + is-node-process: "npm:^1.2.0" + outvariant: "npm:^1.4.0" + checksum: 10c0/90010647b22e9693c16258f4f9adb034824d1771d3baa313057b9a37797f571181005bc50415a934eaf7c891d90ff71dcd7a9d5048b0b6bb438f31bef2c7c5c1 + languageName: node + linkType: hard + +"@open-draft/until@npm:^2.0.0": + version: 2.1.0 + resolution: "@open-draft/until@npm:2.1.0" + checksum: 10c0/61d3f99718dd86bb393fee2d7a785f961dcaf12f2055f0c693b27f4d0cd5f7a03d498a6d9289773b117590d794a43cd129366fd8e99222e4832f67b1653d54cf + languageName: node + linkType: hard + "@openshift-console/dynamic-plugin-sdk-webpack@npm:4.21-latest": version: 4.21.0 resolution: "@openshift-console/dynamic-plugin-sdk-webpack@npm:4.21.0" @@ -2640,6 +2323,30 @@ __metadata: languageName: node linkType: hard +"@oxc-project/types@npm:=0.127.0": + version: 0.127.0 + resolution: "@oxc-project/types@npm:0.127.0" + checksum: 10c0/52c0947ac64a9ca119fe971f947e784a35ecd14a072fa3f542a58a5f6c42010b53f2bf92731e39b9899b83c990a9517bbd29d1e5a5b7b489e52616685c6a9278 + languageName: node + linkType: hard + +"@patternfly/react-code-editor@npm:^6.4.3": + version: 6.4.3 + resolution: "@patternfly/react-code-editor@npm:6.4.3" + dependencies: + "@monaco-editor/react": "npm:^4.6.0" + "@patternfly/react-core": "npm:^6.4.3" + "@patternfly/react-icons": "npm:^6.4.0" + "@patternfly/react-styles": "npm:^6.4.0" + react-dropzone: "npm:14.3.5" + tslib: "npm:^2.8.1" + peerDependencies: + react: ^17 || ^18 || ^19 + react-dom: ^17 || ^18 || ^19 + checksum: 10c0/5ff88454edff81fb5c85003793e3ad883f23ba263e73faece8a663d29704b809d167369b422455e113dcdff38e836d5fa62faf182698c1b4d7c8941a9c8b4723 + languageName: node + linkType: hard + "@patternfly/react-core@npm:^6.0.0, @patternfly/react-core@npm:^6.2.2": version: 6.4.0 resolution: "@patternfly/react-core@npm:6.4.0" @@ -2657,6 +2364,23 @@ __metadata: languageName: node linkType: hard +"@patternfly/react-core@npm:^6.4.3": + version: 6.4.3 + resolution: "@patternfly/react-core@npm:6.4.3" + dependencies: + "@patternfly/react-icons": "npm:^6.4.0" + "@patternfly/react-styles": "npm:^6.4.0" + "@patternfly/react-tokens": "npm:^6.4.0" + focus-trap: "npm:7.6.4" + react-dropzone: "npm:^14.3.5" + tslib: "npm:^2.8.1" + peerDependencies: + react: ^17 || ^18 || ^19 + react-dom: ^17 || ^18 || ^19 + checksum: 10c0/c9f6b50b146a6acec22ab05c81916593a90a7d02436a89096b26e6e8880253cdcb90d2086951daac609006a80676db4dc3af7057a509084bc6cdb8d2aecd5bb6 + languageName: node + linkType: hard + "@patternfly/react-icons@npm:^6.0.0, @patternfly/react-icons@npm:^6.2.2, @patternfly/react-icons@npm:^6.4.0": version: 6.4.0 resolution: "@patternfly/react-icons@npm:6.4.0" @@ -2888,35 +2612,133 @@ __metadata: languageName: node linkType: hard -"@sinclair/typebox@npm:^0.34.0": - version: 0.34.49 - resolution: "@sinclair/typebox@npm:0.34.49" - checksum: 10c0/16b7d87f039a49b68c10bb4cdcae2ce5242b2472228851fd6483731616aba4ef977690aa517b230a8d20da8185bb416eb34e326f30568b3963c1cf26b05d1ad8 +"@rolldown/binding-android-arm64@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-android-arm64@npm:1.0.0-rc.17" + conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@sindresorhus/merge-streams@npm:^4.0.0": - version: 4.0.0 - resolution: "@sindresorhus/merge-streams@npm:4.0.0" - checksum: 10c0/482ee543629aa1933b332f811a1ae805a213681ecdd98c042b1c1b89387df63e7812248bb4df3910b02b3cc5589d3d73e4393f30e197c9dde18046ccd471fc6b +"@rolldown/binding-darwin-arm64@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-darwin-arm64@npm:1.0.0-rc.17" + conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@sinonjs/commons@npm:^3.0.1": - version: 3.0.1 - resolution: "@sinonjs/commons@npm:3.0.1" - dependencies: - type-detect: "npm:4.0.8" - checksum: 10c0/1227a7b5bd6c6f9584274db996d7f8cee2c8c350534b9d0141fc662eaf1f292ea0ae3ed19e5e5271c8fd390d27e492ca2803acd31a1978be2cdc6be0da711403 +"@rolldown/binding-darwin-x64@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-darwin-x64@npm:1.0.0-rc.17" + conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@sinonjs/fake-timers@npm:^15.0.0": - version: 15.1.1 - resolution: "@sinonjs/fake-timers@npm:15.1.1" +"@rolldown/binding-freebsd-x64@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-freebsd-x64@npm:1.0.0-rc.17" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-rc.17" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@rolldown/binding-linux-arm64-gnu@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-arm64-gnu@npm:1.0.0-rc.17" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rolldown/binding-linux-arm64-musl@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-arm64-musl@npm:1.0.0-rc.17" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rolldown/binding-linux-ppc64-gnu@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-ppc64-gnu@npm:1.0.0-rc.17" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rolldown/binding-linux-s390x-gnu@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-s390x-gnu@npm:1.0.0-rc.17" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@rolldown/binding-linux-x64-gnu@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-x64-gnu@npm:1.0.0-rc.17" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rolldown/binding-linux-x64-musl@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-linux-x64-musl@npm:1.0.0-rc.17" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rolldown/binding-openharmony-arm64@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-openharmony-arm64@npm:1.0.0-rc.17" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@rolldown/binding-wasm32-wasi@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-wasm32-wasi@npm:1.0.0-rc.17" dependencies: - "@sinonjs/commons": "npm:^3.0.1" - checksum: 10c0/8eaaa1c9db91256dfe31f3503cdd844ea031ffd16276b3bcd95457432d666d6d027453af5f884e010dba4ebe264b50ac0aac049e192c5f370158da9b291206b9 + "@emnapi/core": "npm:1.10.0" + "@emnapi/runtime": "npm:1.10.0" + "@napi-rs/wasm-runtime": "npm:^1.1.4" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@rolldown/binding-win32-arm64-msvc@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-win32-arm64-msvc@npm:1.0.0-rc.17" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rolldown/binding-win32-x64-msvc@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/binding-win32-x64-msvc@npm:1.0.0-rc.17" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@rolldown/pluginutils@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "@rolldown/pluginutils@npm:1.0.0-rc.17" + checksum: 10c0/5e840b20cc531910c093c1ca36e550952cf4936465a50d89f0a98fc9d0dfd7d319d06a10a5f4376209d89e9bf4d60af6cc8363ebf0dcc5e60842f7fef438b2f0 + languageName: node + linkType: hard + +"@sindresorhus/merge-streams@npm:^4.0.0": + version: 4.0.0 + resolution: "@sindresorhus/merge-streams@npm:4.0.0" + checksum: 10c0/482ee543629aa1933b332f811a1ae805a213681ecdd98c042b1c1b89387df63e7812248bb4df3910b02b3cc5589d3d73e4393f30e197c9dde18046ccd471fc6b + languageName: node + linkType: hard + +"@standard-schema/spec@npm:^1.1.0": + version: 1.1.0 + resolution: "@standard-schema/spec@npm:1.1.0" + checksum: 10c0/d90f55acde4b2deb983529c87e8025fa693de1a5e8b49ecc6eb84d1fd96328add0e03d7d551442156c7432fd78165b2c26ff561b970a9a881f046abb78d6a526 languageName: node linkType: hard @@ -3001,7 +2823,7 @@ __metadata: languageName: node linkType: hard -"@tybys/wasm-util@npm:^0.10.0": +"@tybys/wasm-util@npm:^0.10.1": version: 0.10.1 resolution: "@tybys/wasm-util@npm:0.10.1" dependencies: @@ -3017,47 +2839,6 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.20.5": - version: 7.20.5 - resolution: "@types/babel__core@npm:7.20.5" - dependencies: - "@babel/parser": "npm:^7.20.7" - "@babel/types": "npm:^7.20.7" - "@types/babel__generator": "npm:*" - "@types/babel__template": "npm:*" - "@types/babel__traverse": "npm:*" - checksum: 10c0/bdee3bb69951e833a4b811b8ee9356b69a61ed5b7a23e1a081ec9249769117fa83aaaf023bb06562a038eb5845155ff663e2d5c75dd95c1d5ccc91db012868ff - languageName: node - linkType: hard - -"@types/babel__generator@npm:*": - version: 7.27.0 - resolution: "@types/babel__generator@npm:7.27.0" - dependencies: - "@babel/types": "npm:^7.0.0" - checksum: 10c0/9f9e959a8792df208a9d048092fda7e1858bddc95c6314857a8211a99e20e6830bdeb572e3587ae8be5429e37f2a96fcf222a9f53ad232f5537764c9e13a2bbd - languageName: node - linkType: hard - -"@types/babel__template@npm:*": - version: 7.4.4 - resolution: "@types/babel__template@npm:7.4.4" - dependencies: - "@babel/parser": "npm:^7.1.0" - "@babel/types": "npm:^7.0.0" - checksum: 10c0/cc84f6c6ab1eab1427e90dd2b76ccee65ce940b778a9a67be2c8c39e1994e6f5bbc8efa309f6cea8dc6754994524cd4d2896558df76d92e7a1f46ecffee7112b - languageName: node - linkType: hard - -"@types/babel__traverse@npm:*": - version: 7.28.0 - resolution: "@types/babel__traverse@npm:7.28.0" - dependencies: - "@babel/types": "npm:^7.28.2" - checksum: 10c0/b52d7d4e8fc6a9018fe7361c4062c1c190f5778cf2466817cb9ed19d69fbbb54f9a85ffedeb748ed8062d2cf7d4cc088ee739848f47c57740de1c48cbf0d0994 - languageName: node - linkType: hard - "@types/body-parser@npm:*": version: 1.19.2 resolution: "@types/body-parser@npm:1.19.2" @@ -3077,6 +2858,16 @@ __metadata: languageName: node linkType: hard +"@types/chai@npm:^5.2.2": + version: 5.2.3 + resolution: "@types/chai@npm:5.2.3" + dependencies: + "@types/deep-eql": "npm:*" + assertion-error: "npm:^2.0.1" + checksum: 10c0/e0ef1de3b6f8045a5e473e867c8565788c444271409d155588504840ad1a53611011f85072188c2833941189400228c1745d78323dac13fcede9c2b28bacfb2f + languageName: node + linkType: hard + "@types/connect-history-api-fallback@npm:^1.5.4": version: 1.5.4 resolution: "@types/connect-history-api-fallback@npm:1.5.4" @@ -3375,6 +3166,13 @@ __metadata: languageName: node linkType: hard +"@types/deep-eql@npm:*": + version: 4.0.2 + resolution: "@types/deep-eql@npm:4.0.2" + checksum: 10c0/bf3f811843117900d7084b9d0c852da9a044d12eb40e6de73b552598a6843c21291a8a381b0532644574beecd5e3491c5ff3a0365ab86b15d59862c025384844 + languageName: node + linkType: hard + "@types/eslint-scope@npm:^3.7.7": version: 3.7.7 resolution: "@types/eslint-scope@npm:3.7.7" @@ -3395,7 +3193,7 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:*, @types/estree@npm:^1.0.6, @types/estree@npm:^1.0.8": +"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.6, @types/estree@npm:^1.0.8": version: 1.0.8 resolution: "@types/estree@npm:1.0.8" checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5 @@ -3467,59 +3265,6 @@ __metadata: languageName: node linkType: hard -"@types/identity-obj-proxy@npm:^3": - version: 3.0.2 - resolution: "@types/identity-obj-proxy@npm:3.0.2" - checksum: 10c0/9277c7bf75aaf3688b659ad86f33eb57bd9fab9a5ed342adfbab6b6a804b8f7ce2f0a9ce0394dc6e73b3128d61920c5d35d71b825b84bfe28a97f86f5360c7e3 - languageName: node - linkType: hard - -"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.1, @types/istanbul-lib-coverage@npm:^2.0.6": - version: 2.0.6 - resolution: "@types/istanbul-lib-coverage@npm:2.0.6" - checksum: 10c0/3948088654f3eeb45363f1db158354fb013b362dba2a5c2c18c559484d5eb9f6fd85b23d66c0a7c2fcfab7308d0a585b14dadaca6cc8bf89ebfdc7f8f5102fb7 - languageName: node - linkType: hard - -"@types/istanbul-lib-report@npm:*": - version: 3.0.3 - resolution: "@types/istanbul-lib-report@npm:3.0.3" - dependencies: - "@types/istanbul-lib-coverage": "npm:*" - checksum: 10c0/247e477bbc1a77248f3c6de5dadaae85ff86ac2d76c5fc6ab1776f54512a745ff2a5f791d22b942e3990ddbd40f3ef5289317c4fca5741bedfaa4f01df89051c - languageName: node - linkType: hard - -"@types/istanbul-reports@npm:^3.0.4": - version: 3.0.4 - resolution: "@types/istanbul-reports@npm:3.0.4" - dependencies: - "@types/istanbul-lib-report": "npm:*" - checksum: 10c0/1647fd402aced5b6edac87274af14ebd6b3a85447ef9ad11853a70fd92a98d35f81a5d3ea9fcb5dbb5834e800c6e35b64475e33fcae6bfa9acc70d61497c54ee - languageName: node - linkType: hard - -"@types/jest@npm:^30.0.0": - version: 30.0.0 - resolution: "@types/jest@npm:30.0.0" - dependencies: - expect: "npm:^30.0.0" - pretty-format: "npm:^30.0.0" - checksum: 10c0/20c6ce574154bc16f8dd6a97afacca4b8c4921a819496a3970382031c509ebe87a1b37b152a1b8475089b82d8ca951a9e95beb4b9bf78fbf579b1536f0b65969 - languageName: node - linkType: hard - -"@types/jsdom@npm:^21.1.7": - version: 21.1.7 - resolution: "@types/jsdom@npm:21.1.7" - dependencies: - "@types/node": "npm:*" - "@types/tough-cookie": "npm:*" - parse5: "npm:^7.0.0" - checksum: 10c0/c0c0025adc2b193e85453eeeea168bb909f0ebad08d6552be7474a407e9c163db8f696dcf1e3cbe8cb9c9d970ba45f4386171794509c1a0fe5d1fed72c91679d - languageName: node - linkType: hard - "@types/json-schema@npm:*, @types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" @@ -3709,6 +3454,15 @@ __metadata: languageName: node linkType: hard +"@types/set-cookie-parser@npm:^2.4.10": + version: 2.4.10 + resolution: "@types/set-cookie-parser@npm:2.4.10" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/010b0c582ea70a2088618b4725808e80c30cce296c19ec58e51d94e0fd1038201b7b99238bf3ea74e1894163c8037d10a4f1729de62b2801ce240ff070f43e76 + languageName: node + linkType: hard + "@types/sinonjs__fake-timers@npm:8.1.1": version: 8.1.1 resolution: "@types/sinonjs__fake-timers@npm:8.1.1" @@ -3732,10 +3486,10 @@ __metadata: languageName: node linkType: hard -"@types/stack-utils@npm:^2.0.3": - version: 2.0.3 - resolution: "@types/stack-utils@npm:2.0.3" - checksum: 10c0/1f4658385ae936330581bcb8aa3a066df03867d90281cdf89cc356d404bd6579be0f11902304e1f775d92df22c6dd761d4451c804b0a4fba973e06211e9bd77c +"@types/statuses@npm:^2.0.6": + version: 2.0.6 + resolution: "@types/statuses@npm:2.0.6" + checksum: 10c0/dd88c220b0e2c6315686289525fd61472d2204d2e4bef4941acfb76bda01d3066f749ac74782aab5b537a45314fcd7d6261eefa40b6ec872691f5803adaa608d languageName: node linkType: hard @@ -3753,13 +3507,6 @@ __metadata: languageName: node linkType: hard -"@types/tough-cookie@npm:*": - version: 4.0.5 - resolution: "@types/tough-cookie@npm:4.0.5" - checksum: 10c0/68c6921721a3dcb40451543db2174a145ef915bc8bcbe7ad4e59194a0238e776e782b896c7a59f4b93ac6acefca9161fccb31d1ce3b3445cb6faa467297fb473 - languageName: node - linkType: hard - "@types/unist@npm:^2.0.0": version: 2.0.11 resolution: "@types/unist@npm:2.0.11" @@ -3776,22 +3523,6 @@ __metadata: languageName: node linkType: hard -"@types/yargs-parser@npm:*": - version: 21.0.3 - resolution: "@types/yargs-parser@npm:21.0.3" - checksum: 10c0/e71c3bd9d0b73ca82e10bee2064c384ab70f61034bbfb78e74f5206283fc16a6d85267b606b5c22cb2a3338373586786fed595b2009825d6a9115afba36560a0 - languageName: node - linkType: hard - -"@types/yargs@npm:^17.0.33": - version: 17.0.35 - resolution: "@types/yargs@npm:17.0.35" - dependencies: - "@types/yargs-parser": "npm:*" - checksum: 10c0/609557826a6b85e73ccf587923f6429850d6dc70e420b455bab4601b670bfadf684b09ae288bccedab042c48ba65f1666133cf375814204b544009f57d6eef63 - languageName: node - linkType: hard - "@types/yauzl@npm:^2.9.1": version: 2.10.0 resolution: "@types/yauzl@npm:2.10.0" @@ -3881,200 +3612,164 @@ __metadata: peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/66517aed5059ef4a29605d06a510582f934d5789ae40ad673f1f0421f8aa13ec9ba7b8caab57ae9f270afacbf13ec5359cedfe74f21ae77e9a2364929f7e7cee - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:8.56.1, @typescript-eslint/types@npm:^8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/types@npm:8.56.1" - checksum: 10c0/e5a0318abddf0c4f98da3039cb10b3c0601c8601f7a9f7043630f0d622dabfe83a4cd833545ad3531fc846e46ca2874377277b392c2490dffec279d9242d827b - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/typescript-estree@npm:8.56.1" - dependencies: - "@typescript-eslint/project-service": "npm:8.56.1" - "@typescript-eslint/tsconfig-utils": "npm:8.56.1" - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/visitor-keys": "npm:8.56.1" - debug: "npm:^4.4.3" - minimatch: "npm:^10.2.2" - semver: "npm:^7.7.3" - tinyglobby: "npm:^0.2.15" - ts-api-utils: "npm:^2.4.0" - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/92f4421dac41be289761200dc2ed85974fa451deacb09490ae1870a25b71b97218e609a90d4addba9ded5b2abdebc265c9db7f6e9ce6d29ed20e89b8487e9618 - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/utils@npm:8.56.1" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.9.1" - "@typescript-eslint/scope-manager": "npm:8.56.1" - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/typescript-estree": "npm:8.56.1" - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/d9ffd9b2944a2c425e0532f71dc61e61d0a923d1a17733cf2777c2a4ae638307d12d44f63b33b6b3dc62f02f47db93ec49344ecefe17b76ee3e4fb0833325be3 - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/visitor-keys@npm:8.56.1" - dependencies: - "@typescript-eslint/types": "npm:8.56.1" - eslint-visitor-keys: "npm:^5.0.0" - checksum: 10c0/86d97905dec1af964cc177c185933d040449acf6006096497f2e0093c6a53eb92b3ac1db9eb40a5a2e8d91160f558c9734331a9280797f09f284c38978b22190 - languageName: node - linkType: hard - -"@ungap/structured-clone@npm:^1.3.0": - version: 1.3.0 - resolution: "@ungap/structured-clone@npm:1.3.0" - checksum: 10c0/0fc3097c2540ada1fc340ee56d58d96b5b536a2a0dab6e3ec17d4bfc8c4c86db345f61a375a8185f9da96f01c69678f836a2b57eeaa9e4b8eeafd26428e57b0a - languageName: node - linkType: hard - -"@unrs/resolver-binding-android-arm-eabi@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.11.1" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@unrs/resolver-binding-android-arm64@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-android-arm64@npm:1.11.1" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@unrs/resolver-binding-darwin-arm64@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.11.1" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@unrs/resolver-binding-darwin-x64@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-darwin-x64@npm:1.11.1" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@unrs/resolver-binding-freebsd-x64@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.11.1" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1" - conditions: os=linux & cpu=arm + checksum: 10c0/66517aed5059ef4a29605d06a510582f934d5789ae40ad673f1f0421f8aa13ec9ba7b8caab57ae9f270afacbf13ec5359cedfe74f21ae77e9a2364929f7e7cee languageName: node linkType: hard -"@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1" - conditions: os=linux & cpu=arm64 & libc=glibc +"@typescript-eslint/types@npm:8.56.1, @typescript-eslint/types@npm:^8.56.1": + version: 8.56.1 + resolution: "@typescript-eslint/types@npm:8.56.1" + checksum: 10c0/e5a0318abddf0c4f98da3039cb10b3c0601c8601f7a9f7043630f0d622dabfe83a4cd833545ad3531fc846e46ca2874377277b392c2490dffec279d9242d827b languageName: node linkType: hard -"@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1" - conditions: os=linux & cpu=arm64 & libc=musl +"@typescript-eslint/typescript-estree@npm:8.56.1": + version: 8.56.1 + resolution: "@typescript-eslint/typescript-estree@npm:8.56.1" + dependencies: + "@typescript-eslint/project-service": "npm:8.56.1" + "@typescript-eslint/tsconfig-utils": "npm:8.56.1" + "@typescript-eslint/types": "npm:8.56.1" + "@typescript-eslint/visitor-keys": "npm:8.56.1" + debug: "npm:^4.4.3" + minimatch: "npm:^10.2.2" + semver: "npm:^7.7.3" + tinyglobby: "npm:^0.2.15" + ts-api-utils: "npm:^2.4.0" + peerDependencies: + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/92f4421dac41be289761200dc2ed85974fa451deacb09490ae1870a25b71b97218e609a90d4addba9ded5b2abdebc265c9db7f6e9ce6d29ed20e89b8487e9618 languageName: node linkType: hard -"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1" - conditions: os=linux & cpu=ppc64 & libc=glibc +"@typescript-eslint/utils@npm:8.56.1": + version: 8.56.1 + resolution: "@typescript-eslint/utils@npm:8.56.1" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.9.1" + "@typescript-eslint/scope-manager": "npm:8.56.1" + "@typescript-eslint/types": "npm:8.56.1" + "@typescript-eslint/typescript-estree": "npm:8.56.1" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/d9ffd9b2944a2c425e0532f71dc61e61d0a923d1a17733cf2777c2a4ae638307d12d44f63b33b6b3dc62f02f47db93ec49344ecefe17b76ee3e4fb0833325be3 languageName: node linkType: hard -"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1" - conditions: os=linux & cpu=riscv64 & libc=glibc +"@typescript-eslint/visitor-keys@npm:8.56.1": + version: 8.56.1 + resolution: "@typescript-eslint/visitor-keys@npm:8.56.1" + dependencies: + "@typescript-eslint/types": "npm:8.56.1" + eslint-visitor-keys: "npm:^5.0.0" + checksum: 10c0/86d97905dec1af964cc177c185933d040449acf6006096497f2e0093c6a53eb92b3ac1db9eb40a5a2e8d91160f558c9734331a9280797f09f284c38978b22190 languageName: node linkType: hard -"@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1" - conditions: os=linux & cpu=riscv64 & libc=musl +"@vitest/coverage-v8@npm:^4.1.5": + version: 4.1.5 + resolution: "@vitest/coverage-v8@npm:4.1.5" + dependencies: + "@bcoe/v8-coverage": "npm:^1.0.2" + "@vitest/utils": "npm:4.1.5" + ast-v8-to-istanbul: "npm:^1.0.0" + istanbul-lib-coverage: "npm:^3.2.2" + istanbul-lib-report: "npm:^3.0.1" + istanbul-reports: "npm:^3.2.0" + magicast: "npm:^0.5.2" + obug: "npm:^2.1.1" + std-env: "npm:^4.0.0-rc.1" + tinyrainbow: "npm:^3.1.0" + peerDependencies: + "@vitest/browser": 4.1.5 + vitest: 4.1.5 + peerDependenciesMeta: + "@vitest/browser": + optional: true + checksum: 10c0/71bf669cc1714611855caef5e89b4f3e405e410bdb34e4b2f6fbc9dc5e50dd9e09e73068c1750f6bfa03f0cd9209a2b6e03665c3bdbd34e0adff1ca65c482b7b languageName: node linkType: hard -"@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1" - conditions: os=linux & cpu=s390x & libc=glibc +"@vitest/expect@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/expect@npm:4.1.5" + dependencies: + "@standard-schema/spec": "npm:^1.1.0" + "@types/chai": "npm:^5.2.2" + "@vitest/spy": "npm:4.1.5" + "@vitest/utils": "npm:4.1.5" + chai: "npm:^6.2.2" + tinyrainbow: "npm:^3.1.0" + checksum: 10c0/5184682304db471aa20024c1154210ad3d6d590afb61646201ce1a15297259f9a35f92f8fad4435bc8a82135e307ddd27c8495f72417d72d9aa139eb281d9e06 languageName: node linkType: hard -"@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1" - conditions: os=linux & cpu=x64 & libc=glibc +"@vitest/mocker@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/mocker@npm:4.1.5" + dependencies: + "@vitest/spy": "npm:4.1.5" + estree-walker: "npm:^3.0.3" + magic-string: "npm:^0.30.21" + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + checksum: 10c0/bcfe97700476130933c7ea33fa670c8d2768a81de5325ce407f901e55c2f66cabbb88a7b6cffb46ddf33dff7d8fc209d769fb298f568e310fbeead9b36f6fdb9 languageName: node linkType: hard -"@unrs/resolver-binding-linux-x64-musl@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.11.1" - conditions: os=linux & cpu=x64 & libc=musl +"@vitest/pretty-format@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/pretty-format@npm:4.1.5" + dependencies: + tinyrainbow: "npm:^3.1.0" + checksum: 10c0/42b5e9b75e87c0a884d36bee364e2d07ee45e96f413377737a74993e077d90c3a12aa36743855aee5e4e28b78fae20e3e6de5eef8d5344b9aba2bc1e1d5537a1 languageName: node linkType: hard -"@unrs/resolver-binding-wasm32-wasi@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.11.1" +"@vitest/runner@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/runner@npm:4.1.5" dependencies: - "@napi-rs/wasm-runtime": "npm:^0.2.11" - conditions: cpu=wasm32 + "@vitest/utils": "npm:4.1.5" + pathe: "npm:^2.0.3" + checksum: 10c0/6a03b313a121155f6dd9e32eeb103c0e12440f586bc4ba1f0d77444e44c6df4652a44443718552037463115635b8378e11f35902d90ce1326f77743219fca056 languageName: node linkType: hard -"@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1" - conditions: os=win32 & cpu=arm64 +"@vitest/snapshot@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/snapshot@npm:4.1.5" + dependencies: + "@vitest/pretty-format": "npm:4.1.5" + "@vitest/utils": "npm:4.1.5" + magic-string: "npm:^0.30.21" + pathe: "npm:^2.0.3" + checksum: 10c0/e11bf50d06702331290750a40eaef86078c108df3cd9a52bb1be7b84250048790163f36827525be6a383a4bb1994fc35e6d0c24239a41688b0bb68a1d15d172f languageName: node linkType: hard -"@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1" - conditions: os=win32 & cpu=ia32 +"@vitest/spy@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/spy@npm:4.1.5" + checksum: 10c0/fda6b1ee0a2fec1a152d8041aba7a79744c3876863b244d1ed406d02b36e8ccc997edb2e3963d1027d728d3dc5a33813e11bef53a0a14fc7de4de5e721d0f591 languageName: node linkType: hard -"@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1" - conditions: os=win32 & cpu=x64 +"@vitest/utils@npm:4.1.5": + version: 4.1.5 + resolution: "@vitest/utils@npm:4.1.5" + dependencies: + "@vitest/pretty-format": "npm:4.1.5" + convert-source-map: "npm:^2.0.0" + tinyrainbow: "npm:^3.1.0" + checksum: 10c0/72409717e68018e5fe42fa173cc4eff6def8c35bd52013f86ddb414cd28d73fcc425ac62968e01a52371b3fd5a7a775536283d2f1d64432753f628712a6a4908 languageName: node linkType: hard @@ -4418,7 +4113,7 @@ __metadata: languageName: node linkType: hard -"ansi-escapes@npm:^4.3.0, ansi-escapes@npm:^4.3.2": +"ansi-escapes@npm:^4.3.0": version: 4.3.2 resolution: "ansi-escapes@npm:4.3.2" dependencies: @@ -4489,7 +4184,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^5.0.0, ansi-styles@npm:^5.2.0": +"ansi-styles@npm:^5.0.0": version: 5.2.0 resolution: "ansi-styles@npm:5.2.0" checksum: 10c0/9c4ca80eb3c2fb7b33841c210d2f20807f40865d27008d7c3f707b7f95cab7d67462a565e2388ac3285b71cb3d9bb2173de8da37c57692a362885ec34d6e27df @@ -4733,6 +4428,24 @@ __metadata: languageName: node linkType: hard +"assertion-error@npm:^2.0.1": + version: 2.0.1 + resolution: "assertion-error@npm:2.0.1" + checksum: 10c0/bbbcb117ac6480138f8c93cf7f535614282dea9dc828f540cdece85e3c665e8f78958b96afac52f29ff883c72638e6a87d469ecc9fe5bc902df03ed24a55dba8 + languageName: node + linkType: hard + +"ast-v8-to-istanbul@npm:^1.0.0": + version: 1.0.0 + resolution: "ast-v8-to-istanbul@npm:1.0.0" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.31" + estree-walker: "npm:^3.0.3" + js-tokens: "npm:^10.0.0" + checksum: 10c0/35e57b754ba63287358094d4f7ae8de2de27286fb4e76a1fbf28b2e67e3b670b59c3f511882473d0fd2cdbaa260062e3cd4f216b724c70032e2b09e5cebbd618 + languageName: node + linkType: hard + "astral-regex@npm:^2.0.0": version: 2.0.0 resolution: "astral-regex@npm:2.0.0" @@ -4826,23 +4539,6 @@ __metadata: languageName: node linkType: hard -"babel-jest@npm:30.3.0": - version: 30.3.0 - resolution: "babel-jest@npm:30.3.0" - dependencies: - "@jest/transform": "npm:30.3.0" - "@types/babel__core": "npm:^7.20.5" - babel-plugin-istanbul: "npm:^7.0.1" - babel-preset-jest: "npm:30.3.0" - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - slash: "npm:^3.0.0" - peerDependencies: - "@babel/core": ^7.11.0 || ^8.0.0-0 - checksum: 10c0/5e41e124a404ddb78aa37a20336d7c883feab5ad9c4f4c72ae26db71be2fcca345874b9a7fef97d9c5f64f144a264b247ebde8acfe493578320f314ca581bac3 - languageName: node - linkType: hard - "babel-loader@npm:^10.1.0": version: 10.1.0 resolution: "babel-loader@npm:10.1.0" @@ -4861,28 +4557,6 @@ __metadata: languageName: node linkType: hard -"babel-plugin-istanbul@npm:^7.0.1": - version: 7.0.1 - resolution: "babel-plugin-istanbul@npm:7.0.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.0.0" - "@istanbuljs/load-nyc-config": "npm:^1.0.0" - "@istanbuljs/schema": "npm:^0.1.3" - istanbul-lib-instrument: "npm:^6.0.2" - test-exclude: "npm:^6.0.0" - checksum: 10c0/92975e3df12503b168695463b451468da0c20e117807221652eb8e33a26c160f3b9d4c5c4e65495657420e871c6a54e5e31f539e2e1da37ef2261d7ddd4b1dfd - languageName: node - linkType: hard - -"babel-plugin-jest-hoist@npm:30.3.0": - version: 30.3.0 - resolution: "babel-plugin-jest-hoist@npm:30.3.0" - dependencies: - "@types/babel__core": "npm:^7.20.5" - checksum: 10c0/5e15900a6487356131e084970f4a9ebe24b702d74930f786e897d4fab90b0987054f66661a3570ea692f429dcd158c2214c97ecf08f7356cbc60029d7b277c74 - languageName: node - linkType: hard - "babel-plugin-polyfill-corejs2@npm:^0.4.15": version: 0.4.15 resolution: "babel-plugin-polyfill-corejs2@npm:0.4.15" @@ -4919,43 +4593,6 @@ __metadata: languageName: node linkType: hard -"babel-preset-current-node-syntax@npm:^1.2.0": - version: 1.2.0 - resolution: "babel-preset-current-node-syntax@npm:1.2.0" - dependencies: - "@babel/plugin-syntax-async-generators": "npm:^7.8.4" - "@babel/plugin-syntax-bigint": "npm:^7.8.3" - "@babel/plugin-syntax-class-properties": "npm:^7.12.13" - "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" - "@babel/plugin-syntax-import-attributes": "npm:^7.24.7" - "@babel/plugin-syntax-import-meta": "npm:^7.10.4" - "@babel/plugin-syntax-json-strings": "npm:^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" - "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" - "@babel/plugin-syntax-object-rest-spread": "npm:^7.8.3" - "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" - "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" - "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" - "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0 || ^8.0.0-0 - checksum: 10c0/94a4f81cddf9b051045d08489e4fff7336292016301664c138cfa3d9ffe3fe2ba10a24ad6ae589fd95af1ac72ba0216e1653555c187e694d7b17be0c002bea10 - languageName: node - linkType: hard - -"babel-preset-jest@npm:30.3.0": - version: 30.3.0 - resolution: "babel-preset-jest@npm:30.3.0" - dependencies: - babel-plugin-jest-hoist: "npm:30.3.0" - babel-preset-current-node-syntax: "npm:^1.2.0" - peerDependencies: - "@babel/core": ^7.11.0 || ^8.0.0-beta.1 - checksum: 10c0/a6839a1527d254bf04e82c0cf61a6a2aa283123a74f0a552e6fce462cb990abebab75a13ec3e9c58b09a865d4d2dfbac710c2d3975ae3ce6f2707cb314915c66 - languageName: node - linkType: hard - "bail@npm:^1.0.0": version: 1.0.5 resolution: "bail@npm:1.0.5" @@ -5028,6 +4665,15 @@ __metadata: languageName: node linkType: hard +"bidi-js@npm:^1.0.3": + version: 1.0.3 + resolution: "bidi-js@npm:1.0.3" + dependencies: + require-from-string: "npm:^2.0.2" + checksum: 10c0/fdddea4aa4120a34285486f2267526cd9298b6e8b773ad25e765d4f104b6d7437ab4ba542e6939e3ac834a7570bcf121ee2cf6d3ae7cd7082c4b5bedc8f271e1 + languageName: node + linkType: hard + "binary-extensions@npm:^2.0.0": version: 2.2.0 resolution: "binary-extensions@npm:2.2.0" @@ -5241,24 +4887,6 @@ __metadata: languageName: node linkType: hard -"bs-logger@npm:^0.2.6": - version: 0.2.6 - resolution: "bs-logger@npm:0.2.6" - dependencies: - fast-json-stable-stringify: "npm:2.x" - checksum: 10c0/80e89aaaed4b68e3374ce936f2eb097456a0dddbf11f75238dbd53140b1e39259f0d248a5089ed456f1158984f22191c3658d54a713982f676709fbe1a6fa5a0 - languageName: node - linkType: hard - -"bser@npm:2.1.1": - version: 2.1.1 - resolution: "bser@npm:2.1.1" - dependencies: - node-int64: "npm:^0.4.0" - checksum: 10c0/24d8dfb7b6d457d73f32744e678a60cc553e4ec0e9e1a01cf614b44d85c3c87e188d3cc78ef0442ce5032ee6818de20a0162ba1074725c0d08908f62ea979227 - languageName: node - linkType: hard - "buffer-crc32@npm:~0.2.3": version: 0.2.13 resolution: "buffer-crc32@npm:0.2.13" @@ -5387,7 +5015,7 @@ __metadata: languageName: node linkType: hard -"callsites@npm:^3.0.0, callsites@npm:^3.1.0": +"callsites@npm:^3.0.0": version: 3.1.0 resolution: "callsites@npm:3.1.0" checksum: 10c0/fff92277400eb06c3079f9e74f3af120db9f8ea03bad0e84d9aede54bbe2d44a56cccb5f6cf12211f93f52306df87077ecec5b712794c5a9b5dac6d615a3f301 @@ -5429,14 +5057,7 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^5.3.1": - version: 5.3.1 - resolution: "camelcase@npm:5.3.1" - checksum: 10c0/92ff9b443bfe8abb15f2b1513ca182d16126359ad4f955ebc83dc4ddcc4ef3fdd2c078bc223f2673dc223488e75c99b16cc4d056624374b799e6a1555cf61b23 - languageName: node - linkType: hard - -"camelcase@npm:^6.0.0, camelcase@npm:^6.3.0": +"camelcase@npm:^6.0.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" checksum: 10c0/0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 @@ -5471,6 +5092,13 @@ __metadata: languageName: node linkType: hard +"chai@npm:^6.2.2": + version: 6.2.2 + resolution: "chai@npm:6.2.2" + checksum: 10c0/e6c69e5f0c11dffe6ea13d0290936ebb68fcc1ad688b8e952e131df6a6d5797d5e860bc55cef1aca2e950c3e1f96daf79e9d5a70fb7dbaab4e46355e2635ed53 + languageName: node + linkType: hard + "chalk@npm:2.4.x, chalk@npm:^2.0.1, chalk@npm:^2.1.0, chalk@npm:^2.4.1": version: 2.4.2 resolution: "chalk@npm:2.4.2" @@ -5505,13 +5133,6 @@ __metadata: languageName: node linkType: hard -"char-regex@npm:^1.0.2": - version: 1.0.2 - resolution: "char-regex@npm:1.0.2" - checksum: 10c0/57a09a86371331e0be35d9083ba429e86c4f4648ecbe27455dbfb343037c16ee6fdc7f6b61f433a57cc5ded5561d71c56a150e018f40c2ffb7bc93a26dae341e - languageName: node - linkType: hard - "character-entities-html4@npm:^1.0.0": version: 1.1.4 resolution: "character-entities-html4@npm:1.1.4" @@ -5636,13 +5257,6 @@ __metadata: languageName: node linkType: hard -"ci-info@npm:^4.2.0": - version: 4.4.0 - resolution: "ci-info@npm:4.4.0" - checksum: 10c0/44156201545b8dde01aa8a09ee2fe9fc7a73b1bef9adbd4606c9f61c8caeeb73fb7a575c88b0443f7b4edb5ee45debaa59ed54ba5f99698339393ca01349eb3a - languageName: node - linkType: hard - "circular-json@npm:^0.3.1": version: 0.3.3 resolution: "circular-json@npm:0.3.3" @@ -5650,13 +5264,6 @@ __metadata: languageName: node linkType: hard -"cjs-module-lexer@npm:^2.1.0": - version: 2.2.0 - resolution: "cjs-module-lexer@npm:2.2.0" - checksum: 10c0/aec4ca58f87145fac221386790ecaae8b012f2e2359a45acb61d8c75ea4fa84f6ea869f17abc1a7e91a808eff0fed581209632f03540de16f72f0a28f5fd35ac - languageName: node - linkType: hard - "clean-stack@npm:^2.0.0": version: 2.2.0 resolution: "clean-stack@npm:2.2.0" @@ -5703,6 +5310,13 @@ __metadata: languageName: node linkType: hard +"cli-width@npm:^4.1.0": + version: 4.1.0 + resolution: "cli-width@npm:4.1.0" + checksum: 10c0/1fbd56413578f6117abcaf858903ba1f4ad78370a4032f916745fa2c7e390183a9d9029cf837df320b0fdce8137668e522f60a30a5f3d6529ff3872d265a955f + languageName: node + linkType: hard + "cliui@npm:^8.0.1": version: 8.0.1 resolution: "cliui@npm:8.0.1" @@ -5742,13 +5356,6 @@ __metadata: languageName: node linkType: hard -"co@npm:^4.6.0": - version: 4.6.0 - resolution: "co@npm:4.6.0" - checksum: 10c0/c0e85ea0ca8bf0a50cbdca82efc5af0301240ca88ebe3644a6ffb8ffe911f34d40f8fbcf8f1d52c5ddd66706abd4d3bfcd64259f1e8e2371d4f47573b0dc8c28 - languageName: node - linkType: hard - "collapse-white-space@npm:^1.0.2": version: 1.0.6 resolution: "collapse-white-space@npm:1.0.6" @@ -5756,13 +5363,6 @@ __metadata: languageName: node linkType: hard -"collect-v8-coverage@npm:^1.0.2": - version: 1.0.3 - resolution: "collect-v8-coverage@npm:1.0.3" - checksum: 10c0/bc62ba251bcce5e3354a8f88fa6442bee56e3e612fec08d4dfcf66179b41ea0bf544b0f78c4ebc0f8050871220af95bb5c5578a6aef346feea155640582f09dc - languageName: node - linkType: hard - "color-convert@npm:^1.9.0": version: 1.9.3 resolution: "color-convert@npm:1.9.3" @@ -5935,6 +5535,7 @@ __metadata: "@octokit/rest": "npm:^22.0.1" "@openshift-console/dynamic-plugin-sdk": "npm:4.21-latest" "@openshift-console/dynamic-plugin-sdk-webpack": "npm:4.21-latest" + "@patternfly/react-code-editor": "npm:^6.4.3" "@patternfly/react-core": "npm:^6.2.2" "@patternfly/react-icons": "npm:^6.2.2" "@patternfly/react-table": "npm:^6.2.2" @@ -5942,11 +5543,10 @@ __metadata: "@testing-library/jest-dom": "npm:^6.9.1" "@testing-library/react": "npm:^12.1.5" "@testing-library/user-event": "npm:^14.6.1" - "@types/identity-obj-proxy": "npm:^3" - "@types/jest": "npm:^30.0.0" "@types/node": "npm:^22.0.0" "@types/react": "npm:^17.0.37" "@types/react-router-dom": "npm:^5.3.3" + "@vitest/coverage-v8": "npm:^4.1.5" babel-loader: "npm:^10.1.0" copy-webpack-plugin: "npm:^14.0.0" css-loader: "npm:^7.1.4" @@ -5961,13 +5561,12 @@ __metadata: globals: "npm:^17.4.0" i18next: "npm:^23.11.5" i18next-parser: "npm:^9.4.0" - identity-obj-proxy: "npm:^3.0.0" - jest: "npm:^30.3.0" - jest-environment-jsdom: "npm:^30.3.0" + jsdom: "npm:^29.0.2" mocha: "npm:^11.7.5" mocha-junit-reporter: "npm:^2.2.1" mochawesome: "npm:^7.1.4" mochawesome-merge: "npm:^5.1.1" + msw: "npm:^2.13.6" pluralize: "npm:^8.0.0" prettier: "npm:^3.8.1" prettier-stylelint: "npm:^0.4.2" @@ -5980,11 +5579,11 @@ __metadata: style-loader: "npm:^4.0.0" stylelint: "npm:^17.4.0" stylelint-config-standard: "npm:^40.0.0" - ts-jest: "npm:^29.4.6" ts-loader: "npm:^9.5.4" ts-node: "npm:^10.9.2" typescript: "npm:^5.9.3" typescript-eslint: "npm:^8.56.1" + vitest: "npm:^4.1.5" webpack: "npm:^5.100.0" webpack-cli: "npm:^6.0.1" webpack-dev-server: "npm:^5.2.3" @@ -6021,6 +5620,13 @@ __metadata: languageName: node linkType: hard +"cookie@npm:^1.1.1": + version: 1.1.1 + resolution: "cookie@npm:1.1.1" + checksum: 10c0/79c4ddc0fcad9c4f045f826f42edf54bcc921a29586a4558b0898277fa89fb47be95bc384c2253f493af7b29500c830da28341274527328f18eba9f58afa112c + languageName: node + linkType: hard + "cookie@npm:~0.7.1": version: 0.7.2 resolution: "cookie@npm:0.7.2" @@ -6191,6 +5797,16 @@ __metadata: languageName: node linkType: hard +"css-tree@npm:^3.0.0, css-tree@npm:^3.2.1": + version: 3.2.1 + resolution: "css-tree@npm:3.2.1" + dependencies: + mdn-data: "npm:2.27.1" + source-map-js: "npm:^1.2.1" + checksum: 10c0/1f65e9ccaa56112a4706d6f003dd43d777f0dbcf848e66fd320f823192533581f8dd58daa906cb80622658332d50284d6be13b87a6ab4556cbbfe9ef535bbf7e + languageName: node + linkType: hard + "css-tree@npm:^3.1.0": version: 3.1.0 resolution: "css-tree@npm:3.1.0" @@ -6224,16 +5840,6 @@ __metadata: languageName: node linkType: hard -"cssstyle@npm:^4.2.1": - version: 4.6.0 - resolution: "cssstyle@npm:4.6.0" - dependencies: - "@asamuzakjp/css-color": "npm:^3.2.0" - rrweb-cssom: "npm:^0.8.0" - checksum: 10c0/71add1b0ffafa1bedbef6855db6189b9523d3320e015a0bf3fbd504760efb9a81e1f1a225228d5fa892ee58e56d06994ca372e7f4e461cda7c4c9985fe075f65 - languageName: node - linkType: hard - "csstype@npm:^3.0.2": version: 3.0.9 resolution: "csstype@npm:3.0.9" @@ -6690,13 +6296,13 @@ __metadata: languageName: node linkType: hard -"data-urls@npm:^5.0.0": - version: 5.0.0 - resolution: "data-urls@npm:5.0.0" +"data-urls@npm:^7.0.0": + version: 7.0.0 + resolution: "data-urls@npm:7.0.0" dependencies: - whatwg-mimetype: "npm:^4.0.0" - whatwg-url: "npm:^14.0.0" - checksum: 10c0/1b894d7d41c861f3a4ed2ae9b1c3f0909d4575ada02e36d3d3bc584bdd84278e20709070c79c3b3bff7ac98598cb191eb3e86a89a79ea4ee1ef360e1694f92ad + whatwg-mimetype: "npm:^5.0.0" + whatwg-url: "npm:^16.0.0" + checksum: 10c0/08d88ef50d8966a070ffdaa703e1e4b29f01bb2da364dfbc1612b1c2a4caa8045802c9532d81347b21781100132addb36a585071c8323b12cce97973961dee9f languageName: node linkType: hard @@ -6801,25 +6407,13 @@ __metadata: languageName: node linkType: hard -"decimal.js@npm:^10.5.0": +"decimal.js@npm:^10.6.0": version: 10.6.0 resolution: "decimal.js@npm:10.6.0" checksum: 10c0/07d69fbcc54167a340d2d97de95f546f9ff1f69d2b45a02fd7a5292412df3cd9eb7e23065e532a318f5474a2e1bccf8392fdf0443ef467f97f3bf8cb0477e5aa languageName: node linkType: hard -"dedent@npm:^1.6.0": - version: 1.7.2 - resolution: "dedent@npm:1.7.2" - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - checksum: 10c0/acaff07cac355b93f17b1b17ebbb84d3cc55af6ab4b7814c3f505e061903e168bc6bf9ddce331552d64dee1525f0b4c549c9ade46aebfac6f69caaed74e90751 - languageName: node - linkType: hard - "deep-equal@npm:^2.0.5": version: 2.2.3 resolution: "deep-equal@npm:2.2.3" @@ -6860,13 +6454,6 @@ __metadata: languageName: node linkType: hard -"deepmerge@npm:^4.3.1": - version: 4.3.1 - resolution: "deepmerge@npm:4.3.1" - checksum: 10c0/e53481aaf1aa2c4082b5342be6b6d8ad9dfe387bc92ce197a66dea08bd4265904a087e75e464f14d1347cf2ac8afe1e4c16b266e0561cc5df29382d3c5f80044 - languageName: node - linkType: hard - "default-browser-id@npm:^5.0.0": version: 5.0.1 resolution: "default-browser-id@npm:5.0.1" @@ -6950,10 +6537,10 @@ __metadata: languageName: node linkType: hard -"detect-newline@npm:^3.1.0": - version: 3.1.0 - resolution: "detect-newline@npm:3.1.0" - checksum: 10c0/c38cfc8eeb9fda09febb44bcd85e467c970d4e3bf526095394e5a4f18bc26dd0cf6b22c69c1fa9969261521c593836db335c2795218f6d781a512aea2fb8209d +"detect-libc@npm:^2.0.3": + version: 2.1.2 + resolution: "detect-libc@npm:2.1.2" + checksum: 10c0/acc675c29a5649fa1fb6e255f993b8ee829e510b6b56b0910666949c80c364738833417d0edb5f90e4e46be17228b0f2b66a010513984e18b15deeeac49369c4 languageName: node linkType: hard @@ -7167,13 +6754,6 @@ __metadata: languageName: node linkType: hard -"emittery@npm:^0.13.1": - version: 0.13.1 - resolution: "emittery@npm:0.13.1" - checksum: 10c0/1573d0ae29ab34661b6c63251ff8f5facd24ccf6a823f19417ae8ba8c88ea450325788c67f16c99edec8de4b52ce93a10fe441ece389fd156e88ee7dab9bfa35 - languageName: node - linkType: hard - "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -7268,6 +6848,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:^8.0.0": + version: 8.0.0 + resolution: "entities@npm:8.0.0" + checksum: 10c0/938e631664c19451823344a351aeeafd74fae2d5fa51e4d5b6ff635afaefd4bacf0f609989888c04c42733f46ffdac15211608267ebb02488005891a4793e94d + languageName: node + linkType: hard + "env-paths@npm:^2.2.0, env-paths@npm:^2.2.1": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -7575,13 +7162,6 @@ __metadata: languageName: node linkType: hard -"escape-string-regexp@npm:^2.0.0": - version: 2.0.0 - resolution: "escape-string-regexp@npm:2.0.0" - checksum: 10c0/2530479fe8db57eace5e8646c9c2a9c80fa279614986d16dcc6bcaceb63ae77f05a851ba6c43756d816c61d7f4534baf56e3c705e3e0d884818a46808811c507 - languageName: node - linkType: hard - "escape-string-regexp@npm:^4.0.0": version: 4.0.0 resolution: "escape-string-regexp@npm:4.0.0" @@ -7817,6 +7397,15 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^3.0.3": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": "npm:^1.0.0" + checksum: 10c0/c12e3c2b2642d2bcae7d5aa495c60fa2f299160946535763969a1c83fc74518ffa9c2cd3a8b69ac56aea547df6a8aac25f729a342992ef0bbac5f1c73e78995d + languageName: node + linkType: hard + "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -7893,23 +7482,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^5.1.1": - version: 5.1.1 - resolution: "execa@npm:5.1.1" - dependencies: - cross-spawn: "npm:^7.0.3" - get-stream: "npm:^6.0.0" - human-signals: "npm:^2.1.0" - is-stream: "npm:^2.0.0" - merge-stream: "npm:^2.0.0" - npm-run-path: "npm:^4.0.1" - onetime: "npm:^5.1.2" - signal-exit: "npm:^3.0.3" - strip-final-newline: "npm:^2.0.0" - checksum: 10c0/c8e615235e8de4c5addf2fa4c3da3e3aa59ce975a3e83533b4f6a71750fb816a2e79610dc5f1799b6e28976c9ae86747a36a606655bf8cb414a74d8d507b304f - languageName: node - linkType: hard - "execall@npm:^1.0.0": version: 1.0.0 resolution: "execall@npm:1.0.0" @@ -7928,13 +7500,6 @@ __metadata: languageName: node linkType: hard -"exit-x@npm:^0.2.2": - version: 0.2.2 - resolution: "exit-x@npm:0.2.2" - checksum: 10c0/212a7a095ca5540e9581f1ef2d1d6a40df7a6027c8cc96e78ce1d16b86d1a88326d4a0eff8dff2b5ec1e68bb0c1edd5d0dfdde87df1869bf7514d4bc6a5cbd72 - languageName: node - linkType: hard - "expand-brackets@npm:^0.1.4": version: 0.1.5 resolution: "expand-brackets@npm:0.1.5" @@ -7953,17 +7518,10 @@ __metadata: languageName: node linkType: hard -"expect@npm:30.3.0, expect@npm:^30.0.0": - version: 30.3.0 - resolution: "expect@npm:30.3.0" - dependencies: - "@jest/expect-utils": "npm:30.3.0" - "@jest/get-type": "npm:30.1.0" - jest-matcher-utils: "npm:30.3.0" - jest-message-util: "npm:30.3.0" - jest-mock: "npm:30.3.0" - jest-util: "npm:30.3.0" - checksum: 10c0/a07a157a0c8b3f1e29bfe5ccbf03a3add2c69fe60d1af8a0980053bb6403d721d5f5e4616f1ea5833b747913f8c880c79ce4d98c23a71a2f0c27cf7273892576 +"expect-type@npm:^1.3.0": + version: 1.3.0 + resolution: "expect-type@npm:1.3.0" + checksum: 10c0/8412b3fe4f392c420ab41dae220b09700e4e47c639a29ba7ba2e83cc6cffd2b4926f7ac9e47d7e277e8f4f02acda76fd6931cb81fd2b382fa9477ef9ada953fd languageName: node linkType: hard @@ -8101,7 +7659,7 @@ __metadata: languageName: node linkType: hard -"fast-json-stable-stringify@npm:2.x, fast-json-stable-stringify@npm:^2.0.0, fast-json-stable-stringify@npm:^2.1.0": +"fast-json-stable-stringify@npm:^2.0.0": version: 2.1.0 resolution: "fast-json-stable-stringify@npm:2.1.0" checksum: 10c0/7f081eb0b8a64e0057b3bb03f974b3ef00135fbf36c1c710895cd9300f13c94ba809bb3a81cf4e1b03f6e5285610a61abbd7602d0652de423144dfee5a389c9b @@ -8115,6 +7673,22 @@ __metadata: languageName: node linkType: hard +"fast-string-truncated-width@npm:^3.0.2": + version: 3.0.3 + resolution: "fast-string-truncated-width@npm:3.0.3" + checksum: 10c0/043b8663397d14a3880ce4f3407bcda60b40db9bbeafe62863a35d1f9c69ea17c8da3fcd72de235553e6c9cd053128cde9e24ca0d4a7463208f48db3cd23d981 + languageName: node + linkType: hard + +"fast-string-width@npm:^3.0.2": + version: 3.0.2 + resolution: "fast-string-width@npm:3.0.2" + dependencies: + fast-string-truncated-width: "npm:^3.0.2" + checksum: 10c0/c8822d175315bb353ebe782b65214ac53b13e3bf704e03b132ea7bdfa8de6a636375b3ab7a4097545393d109381c37c4f387c72a462c90b61412dbc4632f39a7 + languageName: node + linkType: hard + "fast-uri@npm:^3.0.1": version: 3.1.0 resolution: "fast-uri@npm:3.1.0" @@ -8122,6 +7696,15 @@ __metadata: languageName: node linkType: hard +"fast-wrap-ansi@npm:^0.2.0": + version: 0.2.0 + resolution: "fast-wrap-ansi@npm:0.2.0" + dependencies: + fast-string-width: "npm:^3.0.2" + checksum: 10c0/c0eb6debee565c5dbb9132dddff5c4d4aba5eb02185ae4dab285acd6186018cffca04264e92f373cbf592a9bcd1c33d65dba036030a8f3baeff1169969a1b59b + languageName: node + linkType: hard + "fastest-levenshtein@npm:^1.0.12, fastest-levenshtein@npm:^1.0.16": version: 1.0.16 resolution: "fastest-levenshtein@npm:1.0.16" @@ -8147,15 +7730,6 @@ __metadata: languageName: node linkType: hard -"fb-watchman@npm:^2.0.2": - version: 2.0.2 - resolution: "fb-watchman@npm:2.0.2" - dependencies: - bser: "npm:2.1.1" - checksum: 10c0/feae89ac148adb8f6ae8ccd87632e62b13563e6fb114cacb5265c51f585b17e2e268084519fb2edd133872f1d47a18e6bfd7e5e08625c0d41b93149694187581 - languageName: node - linkType: hard - "fd-slicer@npm:~1.1.0": version: 1.1.0 resolution: "fd-slicer@npm:1.1.0" @@ -8267,7 +7841,7 @@ __metadata: languageName: node linkType: hard -"find-up@npm:4.x, find-up@npm:^4.0.0, find-up@npm:^4.1.0": +"find-up@npm:4.x, find-up@npm:^4.0.0": version: 4.1.0 resolution: "find-up@npm:4.1.0" dependencies: @@ -8540,16 +8114,6 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:^2.3.3": - version: 2.3.3 - resolution: "fsevents@npm:2.3.3" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 - conditions: os=darwin - languageName: node - linkType: hard - "fsevents@npm:~2.3.2": version: 2.3.2 resolution: "fsevents@npm:2.3.2" @@ -8560,11 +8124,12 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A^2.3.3#optional!builtin": +"fsevents@npm:~2.3.3": version: 2.3.3 - resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" + resolution: "fsevents@npm:2.3.3" dependencies: node-gyp: "npm:latest" + checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 conditions: os=darwin languageName: node linkType: hard @@ -8578,6 +8143,15 @@ __metadata: languageName: node linkType: hard +"fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: "npm:latest" + conditions: os=darwin + languageName: node + linkType: hard + "fsu@npm:^1.1.1": version: 1.1.1 resolution: "fsu@npm:1.1.1" @@ -8662,13 +8236,6 @@ __metadata: languageName: node linkType: hard -"get-package-type@npm:^0.1.0": - version: 0.1.0 - resolution: "get-package-type@npm:0.1.0" - checksum: 10c0/e34cdf447fdf1902a1f6d5af737eaadf606d2ee3518287abde8910e04159368c268568174b2e71102b87b26c2020486f126bfca9c4fb1ceb986ff99b52ecd1be - languageName: node - linkType: hard - "get-proto@npm:^1.0.0, get-proto@npm:^1.0.1": version: 1.0.1 resolution: "get-proto@npm:1.0.1" @@ -8709,13 +8276,6 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^6.0.0": - version: 6.0.1 - resolution: "get-stream@npm:6.0.1" - checksum: 10c0/49825d57d3fd6964228e6200a58169464b8e8970489b3acdc24906c782fb7f01f9f56f8e6653c4a50713771d6658f7cfe051e5eb8c12e334138c9c918b296341 - languageName: node - linkType: hard - "get-symbol-description@npm:^1.1.0": version: 1.1.0 resolution: "get-symbol-description@npm:1.1.0" @@ -8805,7 +8365,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:7.x, glob@npm:^7.0.3, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4": +"glob@npm:7.x, glob@npm:^7.0.3, glob@npm:^7.1.2, glob@npm:^7.1.3": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -8819,7 +8379,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.4.5, glob@npm:^10.5.0": +"glob@npm:^10.4.5": version: 10.5.0 resolution: "glob@npm:10.5.0" dependencies: @@ -9000,6 +8560,13 @@ __metadata: languageName: node linkType: hard +"graphql@npm:^16.13.2": + version: 16.13.2 + resolution: "graphql@npm:16.13.2" + checksum: 10c0/64e822a0a0e4398781e4bc9765b88d370c08261498b517add4b878038ef7be2005b6b394a79a5102b9379d57052f60bc7f23fec8f39808d101984a74772ebd9d + languageName: node + linkType: hard + "gulp-sort@npm:^2.0.0": version: 2.0.0 resolution: "gulp-sort@npm:2.0.0" @@ -9016,31 +8583,6 @@ __metadata: languageName: node linkType: hard -"handlebars@npm:^4.7.8": - version: 4.7.9 - resolution: "handlebars@npm:4.7.9" - dependencies: - minimist: "npm:^1.2.5" - neo-async: "npm:^2.6.2" - source-map: "npm:^0.6.1" - uglify-js: "npm:^3.1.4" - wordwrap: "npm:^1.0.0" - dependenciesMeta: - uglify-js: - optional: true - bin: - handlebars: bin/handlebars - checksum: 10c0/22f8105a7e68e81aff2662bb434edf05f757d21d850731d71cec886d69c10cd33d3c43e34b2892968ec62de8241611851d3d0674c8ef324ea3e01dc66262faa9 - languageName: node - linkType: hard - -"harmony-reflect@npm:^1.4.6": - version: 1.6.2 - resolution: "harmony-reflect@npm:1.6.2" - checksum: 10c0/fa5b251fbeff0e2d925f0bfb5ffe39e0627639e998c453562d6a39e41789c15499649dc022178c807cf99bfb97e7b974bbbc031ba82078a26be7b098b9bc2b1a - languageName: node - linkType: hard - "has-ansi@npm:^2.0.0": version: 2.0.0 resolution: "has-ansi@npm:2.0.0" @@ -9163,6 +8705,16 @@ __metadata: languageName: node linkType: hard +"headers-polyfill@npm:^5.0.1": + version: 5.0.1 + resolution: "headers-polyfill@npm:5.0.1" + dependencies: + "@types/set-cookie-parser": "npm:^2.4.10" + set-cookie-parser: "npm:^3.0.1" + checksum: 10c0/c269730a88a12c88718037aa71f178601f2b193ba8a37e276b6ced6b8f7e06fc1ac051f2a7acb0a8b4cc878407066555fdcdbb270e90374baaa472cb26af0c30 + languageName: node + linkType: hard + "heimdalljs-logger@npm:^0.1.10, heimdalljs-logger@npm:^0.1.7": version: 0.1.10 resolution: "heimdalljs-logger@npm:0.1.10" @@ -9256,12 +8808,12 @@ __metadata: languageName: node linkType: hard -"html-encoding-sniffer@npm:^4.0.0": - version: 4.0.0 - resolution: "html-encoding-sniffer@npm:4.0.0" +"html-encoding-sniffer@npm:^6.0.0": + version: 6.0.0 + resolution: "html-encoding-sniffer@npm:6.0.0" dependencies: - whatwg-encoding: "npm:^3.1.1" - checksum: 10c0/523398055dc61ac9b34718a719cb4aa691e4166f29187e211e1607de63dc25ac7af52ca7c9aead0c4b3c0415ffecb17326396e1202e2e86ff4bca4c0ee4c6140 + "@exodus/bytes": "npm:^1.6.0" + checksum: 10c0/66dc3f6f5539cc3beb814fcbfae7eacf4ec38cf824d6e1425b72039b51a40f4456bd8541ba66f4f4fe09cdf885ab5cd5bae6ec6339d6895a930b2fdb83c53025 languageName: node linkType: hard @@ -9367,7 +8919,7 @@ __metadata: languageName: node linkType: hard -"http-proxy-agent@npm:^7.0.0, http-proxy-agent@npm:^7.0.2": +"http-proxy-agent@npm:^7.0.0": version: 7.0.2 resolution: "http-proxy-agent@npm:7.0.2" dependencies: @@ -9417,7 +8969,7 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.6": +"https-proxy-agent@npm:^7.0.1": version: 7.0.6 resolution: "https-proxy-agent@npm:7.0.6" dependencies: @@ -9434,13 +8986,6 @@ __metadata: languageName: node linkType: hard -"human-signals@npm:^2.1.0": - version: 2.1.0 - resolution: "human-signals@npm:2.1.0" - checksum: 10c0/695edb3edfcfe9c8b52a76926cd31b36978782062c0ed9b1192b36bebc75c4c87c82e178dfcb0ed0fc27ca59d434198aac0bd0be18f5781ded775604db22304a - languageName: node - linkType: hard - "hyperdyperid@npm:^1.2.0": version: 1.2.0 resolution: "hyperdyperid@npm:1.2.0" @@ -9534,15 +9079,6 @@ __metadata: languageName: node linkType: hard -"identity-obj-proxy@npm:^3.0.0": - version: 3.0.0 - resolution: "identity-obj-proxy@npm:3.0.0" - dependencies: - harmony-reflect: "npm:^1.4.6" - checksum: 10c0/a3fc4de0042d7b45bf8652d5596c80b42139d8625c9cd6a8834e29e1b6dce8fccabd1228e08744b78677a19ceed7201a32fed8ca3dc3e4852e8fee24360a6cfc - languageName: node - linkType: hard - "ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": version: 1.2.1 resolution: "ieee754@npm:1.2.1" @@ -9619,18 +9155,6 @@ __metadata: languageName: node linkType: hard -"import-local@npm:^3.2.0": - version: 3.2.0 - resolution: "import-local@npm:3.2.0" - dependencies: - pkg-dir: "npm:^4.2.0" - resolve-cwd: "npm:^3.0.0" - bin: - import-local-fixture: fixtures/cli.js - checksum: 10c0/94cd6367a672b7e0cb026970c85b76902d2710a64896fa6de93bd5c571dd03b228c5759308959de205083e3b1c61e799f019c9e36ee8e9c523b993e1057f0433 - languageName: node - linkType: hard - "import-meta-resolve@npm:^4.2.0": version: 4.2.0 resolution: "import-meta-resolve@npm:4.2.0" @@ -9997,13 +9521,6 @@ __metadata: languageName: node linkType: hard -"is-generator-fn@npm:^2.1.0": - version: 2.1.0 - resolution: "is-generator-fn@npm:2.1.0" - checksum: 10c0/2957cab387997a466cd0bf5c1b6047bd21ecb32bdcfd8996b15747aa01002c1c88731802f1b3d34ac99f4f6874b626418bd118658cf39380fe5fff32a3af9c4d - languageName: node - linkType: hard - "is-generator-function@npm:^1.0.10": version: 1.1.2 resolution: "is-generator-function@npm:1.1.2" @@ -10101,6 +9618,13 @@ __metadata: languageName: node linkType: hard +"is-node-process@npm:^1.2.0": + version: 1.2.0 + resolution: "is-node-process@npm:1.2.0" + checksum: 10c0/5b24fda6776d00e42431d7bcd86bce81cb0b6cabeb944142fe7b077a54ada2e155066ad06dbe790abdb397884bdc3151e04a9707b8cd185099efbc79780573ed + languageName: node + linkType: hard + "is-npm@npm:^1.0.0": version: 1.0.0 resolution: "is-npm@npm:1.0.0" @@ -10436,558 +9960,100 @@ __metadata: "isarray@npm:^2.0.5": version: 2.0.5 - resolution: "isarray@npm:2.0.5" - checksum: 10c0/4199f14a7a13da2177c66c31080008b7124331956f47bca57dd0b6ea9f11687aa25e565a2c7a2b519bc86988d10398e3049a1f5df13c9f6b7664154690ae79fd - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d - languageName: node - linkType: hard - -"isexe@npm:^4.0.0": - version: 4.0.0 - resolution: "isexe@npm:4.0.0" - checksum: 10c0/5884815115bceac452877659a9c7726382531592f43dc29e5d48b7c4100661aed54018cb90bd36cb2eaeba521092570769167acbb95c18d39afdccbcca06c5ce - languageName: node - linkType: hard - -"isobject@npm:^2.0.0": - version: 2.1.0 - resolution: "isobject@npm:2.1.0" - dependencies: - isarray: "npm:1.0.0" - checksum: 10c0/c4cafec73b3b2ee11be75dff8dafd283b5728235ac099b07d7873d5182553a707768e208327bbc12931b9422d8822280bf88d894a0024ff5857b3efefb480e7b - languageName: node - linkType: hard - -"isobject@npm:^3.0.1": - version: 3.0.1 - resolution: "isobject@npm:3.0.1" - checksum: 10c0/03344f5064a82f099a0cd1a8a407f4c0d20b7b8485e8e816c39f249e9416b06c322e8dec5b842b6bb8a06de0af9cb48e7bc1b5352f0fadc2f0abac033db3d4db - languageName: node - linkType: hard - -"isstream@npm:~0.1.2": - version: 0.1.2 - resolution: "isstream@npm:0.1.2" - checksum: 10c0/a6686a878735ca0a48e0d674dd6d8ad31aedfaf70f07920da16ceadc7577b46d67179a60b313f2e6860cb097a2c2eb3cbd0b89e921ae89199a59a17c3273d66f - languageName: node - linkType: hard - -"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0": - version: 3.2.2 - resolution: "istanbul-lib-coverage@npm:3.2.2" - checksum: 10c0/6c7ff2106769e5f592ded1fb418f9f73b4411fd5a084387a5410538332b6567cd1763ff6b6cadca9b9eb2c443cce2f7ea7d7f1b8d315f9ce58539793b1e0922b - languageName: node - linkType: hard - -"istanbul-lib-instrument@npm:^6.0.0, istanbul-lib-instrument@npm:^6.0.2": - version: 6.0.3 - resolution: "istanbul-lib-instrument@npm:6.0.3" - dependencies: - "@babel/core": "npm:^7.23.9" - "@babel/parser": "npm:^7.23.9" - "@istanbuljs/schema": "npm:^0.1.3" - istanbul-lib-coverage: "npm:^3.2.0" - semver: "npm:^7.5.4" - checksum: 10c0/a1894e060dd2a3b9f046ffdc87b44c00a35516f5e6b7baf4910369acca79e506fc5323a816f811ae23d82334b38e3ddeb8b3b331bd2c860540793b59a8689128 - languageName: node - linkType: hard - -"istanbul-lib-report@npm:^3.0.0": - version: 3.0.1 - resolution: "istanbul-lib-report@npm:3.0.1" - dependencies: - istanbul-lib-coverage: "npm:^3.0.0" - make-dir: "npm:^4.0.0" - supports-color: "npm:^7.1.0" - checksum: 10c0/84323afb14392de8b6a5714bd7e9af845cfbd56cfe71ed276cda2f5f1201aea673c7111901227ee33e68e4364e288d73861eb2ed48f6679d1e69a43b6d9b3ba7 - languageName: node - linkType: hard - -"istanbul-lib-source-maps@npm:^5.0.0": - version: 5.0.6 - resolution: "istanbul-lib-source-maps@npm:5.0.6" - dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.23" - debug: "npm:^4.1.1" - istanbul-lib-coverage: "npm:^3.0.0" - checksum: 10c0/ffe75d70b303a3621ee4671554f306e0831b16f39ab7f4ab52e54d356a5d33e534d97563e318f1333a6aae1d42f91ec49c76b6cd3f3fb378addcb5c81da0255f - languageName: node - linkType: hard - -"istanbul-reports@npm:^3.1.3": - version: 3.2.0 - resolution: "istanbul-reports@npm:3.2.0" - dependencies: - html-escaper: "npm:^2.0.0" - istanbul-lib-report: "npm:^3.0.0" - checksum: 10c0/d596317cfd9c22e1394f22a8d8ba0303d2074fe2e971887b32d870e4b33f8464b10f8ccbe6847808f7db485f084eba09e6c2ed706b3a978e4b52f07085b8f9bc - languageName: node - linkType: hard - -"iterator.prototype@npm:^1.1.5": - version: 1.1.5 - resolution: "iterator.prototype@npm:1.1.5" - dependencies: - define-data-property: "npm:^1.1.4" - es-object-atoms: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.6" - get-proto: "npm:^1.0.0" - has-symbols: "npm:^1.1.0" - set-function-name: "npm:^2.0.2" - checksum: 10c0/f7a262808e1b41049ab55f1e9c29af7ec1025a000d243b83edf34ce2416eedd56079b117fa59376bb4a724110690f13aa8427f2ee29a09eec63a7e72367626d0 - languageName: node - linkType: hard - -"jackspeak@npm:^3.1.2": - version: 3.4.3 - resolution: "jackspeak@npm:3.4.3" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 - languageName: node - linkType: hard - -"jest-changed-files@npm:30.3.0": - version: 30.3.0 - resolution: "jest-changed-files@npm:30.3.0" - dependencies: - execa: "npm:^5.1.1" - jest-util: "npm:30.3.0" - p-limit: "npm:^3.1.0" - checksum: 10c0/5a2f9790f8ab7f5804ebbf0fcdd908c40286d602d76abbecc6bea72e7f3c60b77dc8a3d3f5acdddd11653b2574f471a5c126ceda0734bc6a7d607cf145843525 - languageName: node - linkType: hard - -"jest-circus@npm:30.3.0": - version: 30.3.0 - resolution: "jest-circus@npm:30.3.0" - dependencies: - "@jest/environment": "npm:30.3.0" - "@jest/expect": "npm:30.3.0" - "@jest/test-result": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - co: "npm:^4.6.0" - dedent: "npm:^1.6.0" - is-generator-fn: "npm:^2.1.0" - jest-each: "npm:30.3.0" - jest-matcher-utils: "npm:30.3.0" - jest-message-util: "npm:30.3.0" - jest-runtime: "npm:30.3.0" - jest-snapshot: "npm:30.3.0" - jest-util: "npm:30.3.0" - p-limit: "npm:^3.1.0" - pretty-format: "npm:30.3.0" - pure-rand: "npm:^7.0.0" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.6" - checksum: 10c0/a3a0eb973699b400fb6de4207a7fbc5b33f51523e5e94f954d0e6e60418ea95099883614495fce54d805a321cb65e883592048b73203a59b8f4e53d1bb975a07 - languageName: node - linkType: hard - -"jest-cli@npm:30.3.0": - version: 30.3.0 - resolution: "jest-cli@npm:30.3.0" - dependencies: - "@jest/core": "npm:30.3.0" - "@jest/test-result": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - chalk: "npm:^4.1.2" - exit-x: "npm:^0.2.2" - import-local: "npm:^3.2.0" - jest-config: "npm:30.3.0" - jest-util: "npm:30.3.0" - jest-validate: "npm:30.3.0" - yargs: "npm:^17.7.2" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - bin: - jest: ./bin/jest.js - checksum: 10c0/764d77551e0fb6d666212e89d01be6f7bb1a2b3adb918bba7c5c37593a11b01cf2af645506c2b6438335cfc79bfcf41bfd4680958d8ca751851752a7c66269d3 - languageName: node - linkType: hard - -"jest-config@npm:30.3.0": - version: 30.3.0 - resolution: "jest-config@npm:30.3.0" - dependencies: - "@babel/core": "npm:^7.27.4" - "@jest/get-type": "npm:30.1.0" - "@jest/pattern": "npm:30.0.1" - "@jest/test-sequencer": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - babel-jest: "npm:30.3.0" - chalk: "npm:^4.1.2" - ci-info: "npm:^4.2.0" - deepmerge: "npm:^4.3.1" - glob: "npm:^10.5.0" - graceful-fs: "npm:^4.2.11" - jest-circus: "npm:30.3.0" - jest-docblock: "npm:30.2.0" - jest-environment-node: "npm:30.3.0" - jest-regex-util: "npm:30.0.1" - jest-resolve: "npm:30.3.0" - jest-runner: "npm:30.3.0" - jest-util: "npm:30.3.0" - jest-validate: "npm:30.3.0" - parse-json: "npm:^5.2.0" - pretty-format: "npm:30.3.0" - slash: "npm:^3.0.0" - strip-json-comments: "npm:^3.1.1" - peerDependencies: - "@types/node": "*" - esbuild-register: ">=3.4.0" - ts-node: ">=9.0.0" - peerDependenciesMeta: - "@types/node": - optional: true - esbuild-register: - optional: true - ts-node: - optional: true - checksum: 10c0/157607e5ac5e83924df97d992fbd40a1540af07c5a7be296fae49455b3729687847304f3b4a9112e7da17593b76cec3453cd55c1ecd4334f7318f2489d7d10a1 - languageName: node - linkType: hard - -"jest-diff@npm:30.3.0": - version: 30.3.0 - resolution: "jest-diff@npm:30.3.0" - dependencies: - "@jest/diff-sequences": "npm:30.3.0" - "@jest/get-type": "npm:30.1.0" - chalk: "npm:^4.1.2" - pretty-format: "npm:30.3.0" - checksum: 10c0/573a2a1a155b95fbde547d8ee33a5375179a8d03d4586025478dac16d695e4614aef075c3afa57e0f3a96cea8f638fa68a55c1e625f6e86b4f5b9e5850311ffb - languageName: node - linkType: hard - -"jest-docblock@npm:30.2.0": - version: 30.2.0 - resolution: "jest-docblock@npm:30.2.0" - dependencies: - detect-newline: "npm:^3.1.0" - checksum: 10c0/2578366604eef1b36d59ffe1fc52a710995571535d437f83d94ff94756a83f78e699c1ba004c38a34c01859d669fd6c64e865c23c5a7d5bf4837cfca4bef3dda - languageName: node - linkType: hard - -"jest-each@npm:30.3.0": - version: 30.3.0 - resolution: "jest-each@npm:30.3.0" - dependencies: - "@jest/get-type": "npm:30.1.0" - "@jest/types": "npm:30.3.0" - chalk: "npm:^4.1.2" - jest-util: "npm:30.3.0" - pretty-format: "npm:30.3.0" - checksum: 10c0/d23d2b43b3ea42beaf99648e2cf1c74b8a13c3e45c7c882979171471c225f7d666cb4a0d5f1ff9031b4504866fa3badc7266ffd885d3d8035420c559a31501e1 - languageName: node - linkType: hard - -"jest-environment-jsdom@npm:^30.3.0": - version: 30.3.0 - resolution: "jest-environment-jsdom@npm:30.3.0" - dependencies: - "@jest/environment": "npm:30.3.0" - "@jest/environment-jsdom-abstract": "npm:30.3.0" - jsdom: "npm:^26.1.0" - peerDependencies: - canvas: ^3.0.0 - peerDependenciesMeta: - canvas: - optional: true - checksum: 10c0/1d9a288c847dc7d3fe0ac4bd494fa5f78581d5f7f1f28fd1f58073634f139b6e4d13d1ea1bbed8e68693f45b74279fb7ea002dd453faa98ab6ab657c443cc0ce - languageName: node - linkType: hard - -"jest-environment-node@npm:30.3.0": - version: 30.3.0 - resolution: "jest-environment-node@npm:30.3.0" - dependencies: - "@jest/environment": "npm:30.3.0" - "@jest/fake-timers": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - jest-mock: "npm:30.3.0" - jest-util: "npm:30.3.0" - jest-validate: "npm:30.3.0" - checksum: 10c0/2a4be80861e569fa11456d89ff2aaedd71726ae02ade8f2cc6fbc86ba8749e24c37864676c4718fc08a40f6e6d2b2b51bc48d715b09b1e93e15e42e4a10f7b5b - languageName: node - linkType: hard - -"jest-haste-map@npm:30.3.0": - version: 30.3.0 - resolution: "jest-haste-map@npm:30.3.0" - dependencies: - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - anymatch: "npm:^3.1.3" - fb-watchman: "npm:^2.0.2" - fsevents: "npm:^2.3.3" - graceful-fs: "npm:^4.2.11" - jest-regex-util: "npm:30.0.1" - jest-util: "npm:30.3.0" - jest-worker: "npm:30.3.0" - picomatch: "npm:^4.0.3" - walker: "npm:^1.0.8" - dependenciesMeta: - fsevents: - optional: true - checksum: 10c0/b9ef350082b15d4c119d6188f781024d859d6cfb17ae25d15c90c3a373234e16109afbeffdcf1af4baf6a85eb0cbbab00439c981ad43037c0f05d89ff98bd1af - languageName: node - linkType: hard - -"jest-leak-detector@npm:30.3.0": - version: 30.3.0 - resolution: "jest-leak-detector@npm:30.3.0" - dependencies: - "@jest/get-type": "npm:30.1.0" - pretty-format: "npm:30.3.0" - checksum: 10c0/a648c082b74e6c7d0c2e890002094ba97b108398fa3d0316958fc74321aa7b0824507a685d261a463856f219a724b86a6073bac86d351cf0675ecf962c1ee0ca - languageName: node - linkType: hard - -"jest-matcher-utils@npm:30.3.0": - version: 30.3.0 - resolution: "jest-matcher-utils@npm:30.3.0" - dependencies: - "@jest/get-type": "npm:30.1.0" - chalk: "npm:^4.1.2" - jest-diff: "npm:30.3.0" - pretty-format: "npm:30.3.0" - checksum: 10c0/4c5f4b6435964110e64c4b5b42e3553fffe303ecdd68021147a7bcc72914aec3a899867c50db22b250c72aded53e3f7a9f64d83c9dca2e65ce27f36d23c6ca78 - languageName: node - linkType: hard - -"jest-message-util@npm:30.3.0": - version: 30.3.0 - resolution: "jest-message-util@npm:30.3.0" - dependencies: - "@babel/code-frame": "npm:^7.27.1" - "@jest/types": "npm:30.3.0" - "@types/stack-utils": "npm:^2.0.3" - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - picomatch: "npm:^4.0.3" - pretty-format: "npm:30.3.0" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.6" - checksum: 10c0/6ce611caef76394872b23a111286b48e56f42655d14a5fbd0629d9b7437ed892e85ad96b15864bc22185c24ef670afb6665c57b9729458a36d50ffe8310f0926 + resolution: "isarray@npm:2.0.5" + checksum: 10c0/4199f14a7a13da2177c66c31080008b7124331956f47bca57dd0b6ea9f11687aa25e565a2c7a2b519bc86988d10398e3049a1f5df13c9f6b7664154690ae79fd languageName: node linkType: hard -"jest-mock@npm:30.3.0": - version: 30.3.0 - resolution: "jest-mock@npm:30.3.0" - dependencies: - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - jest-util: "npm:30.3.0" - checksum: 10c0/9d95d550c6c998a85887c48ff5ee26de4bca18be91462ea8a8135d6023d591132465756f74981ca39b60f8708dfe38213a55bd4b619798a7b9438ca10d718099 +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d languageName: node linkType: hard -"jest-pnp-resolver@npm:^1.2.3": - version: 1.2.3 - resolution: "jest-pnp-resolver@npm:1.2.3" - peerDependencies: - jest-resolve: "*" - peerDependenciesMeta: - jest-resolve: - optional: true - checksum: 10c0/86eec0c78449a2de733a6d3e316d49461af6a858070e113c97f75fb742a48c2396ea94150cbca44159ffd4a959f743a47a8b37a792ef6fdad2cf0a5cba973fac +"isexe@npm:^4.0.0": + version: 4.0.0 + resolution: "isexe@npm:4.0.0" + checksum: 10c0/5884815115bceac452877659a9c7726382531592f43dc29e5d48b7c4100661aed54018cb90bd36cb2eaeba521092570769167acbb95c18d39afdccbcca06c5ce languageName: node linkType: hard -"jest-regex-util@npm:30.0.1": - version: 30.0.1 - resolution: "jest-regex-util@npm:30.0.1" - checksum: 10c0/f30c70524ebde2d1012afe5ffa5691d5d00f7d5ba9e43d588f6460ac6fe96f9e620f2f9b36a02d0d3e7e77bc8efb8b3450ae3b80ac53c8be5099e01bf54f6728 +"isobject@npm:^2.0.0": + version: 2.1.0 + resolution: "isobject@npm:2.1.0" + dependencies: + isarray: "npm:1.0.0" + checksum: 10c0/c4cafec73b3b2ee11be75dff8dafd283b5728235ac099b07d7873d5182553a707768e208327bbc12931b9422d8822280bf88d894a0024ff5857b3efefb480e7b languageName: node linkType: hard -"jest-resolve-dependencies@npm:30.3.0": - version: 30.3.0 - resolution: "jest-resolve-dependencies@npm:30.3.0" - dependencies: - jest-regex-util: "npm:30.0.1" - jest-snapshot: "npm:30.3.0" - checksum: 10c0/25dde0c8c050bc3437332f37ab87484f597596b80ece77a93e4da2b466b42e45cc5ad748270c1477587536de15eea1ffe83a32638e824b120830c3a87c9a5b71 +"isobject@npm:^3.0.1": + version: 3.0.1 + resolution: "isobject@npm:3.0.1" + checksum: 10c0/03344f5064a82f099a0cd1a8a407f4c0d20b7b8485e8e816c39f249e9416b06c322e8dec5b842b6bb8a06de0af9cb48e7bc1b5352f0fadc2f0abac033db3d4db languageName: node linkType: hard -"jest-resolve@npm:30.3.0": - version: 30.3.0 - resolution: "jest-resolve@npm:30.3.0" - dependencies: - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.3.0" - jest-pnp-resolver: "npm:^1.2.3" - jest-util: "npm:30.3.0" - jest-validate: "npm:30.3.0" - slash: "npm:^3.0.0" - unrs-resolver: "npm:^1.7.11" - checksum: 10c0/540f59f160c232c1b922b111a93f24ef5202d75e00f2e994de976badf6e88879893b474320ff363a6b97259a7a208b6a4f5eeabede787eea9b7912a12ac64b1b +"isstream@npm:~0.1.2": + version: 0.1.2 + resolution: "isstream@npm:0.1.2" + checksum: 10c0/a6686a878735ca0a48e0d674dd6d8ad31aedfaf70f07920da16ceadc7577b46d67179a60b313f2e6860cb097a2c2eb3cbd0b89e921ae89199a59a17c3273d66f languageName: node linkType: hard -"jest-runner@npm:30.3.0": - version: 30.3.0 - resolution: "jest-runner@npm:30.3.0" - dependencies: - "@jest/console": "npm:30.3.0" - "@jest/environment": "npm:30.3.0" - "@jest/test-result": "npm:30.3.0" - "@jest/transform": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - emittery: "npm:^0.13.1" - exit-x: "npm:^0.2.2" - graceful-fs: "npm:^4.2.11" - jest-docblock: "npm:30.2.0" - jest-environment-node: "npm:30.3.0" - jest-haste-map: "npm:30.3.0" - jest-leak-detector: "npm:30.3.0" - jest-message-util: "npm:30.3.0" - jest-resolve: "npm:30.3.0" - jest-runtime: "npm:30.3.0" - jest-util: "npm:30.3.0" - jest-watcher: "npm:30.3.0" - jest-worker: "npm:30.3.0" - p-limit: "npm:^3.1.0" - source-map-support: "npm:0.5.13" - checksum: 10c0/6fb205f48541658f0b23b6c9a6730f0133f07c994a22ef506ebfcded5bbb444b655ac828074157e6579e664609a46f6a5bf3d366b694c6c8b523b5207a70499c - languageName: node - linkType: hard - -"jest-runtime@npm:30.3.0": - version: 30.3.0 - resolution: "jest-runtime@npm:30.3.0" - dependencies: - "@jest/environment": "npm:30.3.0" - "@jest/fake-timers": "npm:30.3.0" - "@jest/globals": "npm:30.3.0" - "@jest/source-map": "npm:30.0.1" - "@jest/test-result": "npm:30.3.0" - "@jest/transform": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - cjs-module-lexer: "npm:^2.1.0" - collect-v8-coverage: "npm:^1.0.2" - glob: "npm:^10.5.0" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.3.0" - jest-message-util: "npm:30.3.0" - jest-mock: "npm:30.3.0" - jest-regex-util: "npm:30.0.1" - jest-resolve: "npm:30.3.0" - jest-snapshot: "npm:30.3.0" - jest-util: "npm:30.3.0" - slash: "npm:^3.0.0" - strip-bom: "npm:^4.0.0" - checksum: 10c0/79c486157a926d5be5c66356ad26cc3792cca1afb1490e255a550f52784b6c92eea42f1cb3b2c7565650ea777cf17ffc3f8e305d6b97888e7d273f6d7f282686 - languageName: node - linkType: hard - -"jest-snapshot@npm:30.3.0": - version: 30.3.0 - resolution: "jest-snapshot@npm:30.3.0" - dependencies: - "@babel/core": "npm:^7.27.4" - "@babel/generator": "npm:^7.27.5" - "@babel/plugin-syntax-jsx": "npm:^7.27.1" - "@babel/plugin-syntax-typescript": "npm:^7.27.1" - "@babel/types": "npm:^7.27.3" - "@jest/expect-utils": "npm:30.3.0" - "@jest/get-type": "npm:30.1.0" - "@jest/snapshot-utils": "npm:30.3.0" - "@jest/transform": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - babel-preset-current-node-syntax: "npm:^1.2.0" - chalk: "npm:^4.1.2" - expect: "npm:30.3.0" - graceful-fs: "npm:^4.2.11" - jest-diff: "npm:30.3.0" - jest-matcher-utils: "npm:30.3.0" - jest-message-util: "npm:30.3.0" - jest-util: "npm:30.3.0" - pretty-format: "npm:30.3.0" - semver: "npm:^7.7.2" - synckit: "npm:^0.11.8" - checksum: 10c0/c1dd295d9d4962f2504c965575212fc62a358a849c66ab96b2f6e608ebdf6a6029ca505bb0693664a54a534e581883665d404a59976a5b46b1a1f88b537e96c5 +"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.2": + version: 3.2.2 + resolution: "istanbul-lib-coverage@npm:3.2.2" + checksum: 10c0/6c7ff2106769e5f592ded1fb418f9f73b4411fd5a084387a5410538332b6567cd1763ff6b6cadca9b9eb2c443cce2f7ea7d7f1b8d315f9ce58539793b1e0922b languageName: node linkType: hard -"jest-util@npm:30.3.0": - version: 30.3.0 - resolution: "jest-util@npm:30.3.0" +"istanbul-lib-report@npm:^3.0.0, istanbul-lib-report@npm:^3.0.1": + version: 3.0.1 + resolution: "istanbul-lib-report@npm:3.0.1" dependencies: - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - ci-info: "npm:^4.2.0" - graceful-fs: "npm:^4.2.11" - picomatch: "npm:^4.0.3" - checksum: 10c0/eea6f39e52a8cb2b1a28bb315a90dc6a8e450fffed73bb5ef4489d02d86f7d91be600d83f1dcba22956b8ac5fefa8f1b250e636c8402d3e8b50a5eec8b5963b2 + istanbul-lib-coverage: "npm:^3.0.0" + make-dir: "npm:^4.0.0" + supports-color: "npm:^7.1.0" + checksum: 10c0/84323afb14392de8b6a5714bd7e9af845cfbd56cfe71ed276cda2f5f1201aea673c7111901227ee33e68e4364e288d73861eb2ed48f6679d1e69a43b6d9b3ba7 languageName: node linkType: hard -"jest-validate@npm:30.3.0": - version: 30.3.0 - resolution: "jest-validate@npm:30.3.0" +"istanbul-reports@npm:^3.2.0": + version: 3.2.0 + resolution: "istanbul-reports@npm:3.2.0" dependencies: - "@jest/get-type": "npm:30.1.0" - "@jest/types": "npm:30.3.0" - camelcase: "npm:^6.3.0" - chalk: "npm:^4.1.2" - leven: "npm:^3.1.0" - pretty-format: "npm:30.3.0" - checksum: 10c0/645629e9ae0926252dee26b0ad71b9f0392daa896328393479c63b1b13d2a70df4dac8b5053227c64e0120e930db1242897898c40706f135f20f73ef77fcf4f5 + html-escaper: "npm:^2.0.0" + istanbul-lib-report: "npm:^3.0.0" + checksum: 10c0/d596317cfd9c22e1394f22a8d8ba0303d2074fe2e971887b32d870e4b33f8464b10f8ccbe6847808f7db485f084eba09e6c2ed706b3a978e4b52f07085b8f9bc languageName: node linkType: hard -"jest-watcher@npm:30.3.0": - version: 30.3.0 - resolution: "jest-watcher@npm:30.3.0" +"iterator.prototype@npm:^1.1.5": + version: 1.1.5 + resolution: "iterator.prototype@npm:1.1.5" dependencies: - "@jest/test-result": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - "@types/node": "npm:*" - ansi-escapes: "npm:^4.3.2" - chalk: "npm:^4.1.2" - emittery: "npm:^0.13.1" - jest-util: "npm:30.3.0" - string-length: "npm:^4.0.2" - checksum: 10c0/2631be5cc122fbf14cb0bb7566cdea6d6c432b984d8ef3c6385254bb6c378342e0754cbd2dfe094d80762d44bd1c7015de2ec2100eb6f192906619d8b229e1a5 + define-data-property: "npm:^1.1.4" + es-object-atoms: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.6" + get-proto: "npm:^1.0.0" + has-symbols: "npm:^1.1.0" + set-function-name: "npm:^2.0.2" + checksum: 10c0/f7a262808e1b41049ab55f1e9c29af7ec1025a000d243b83edf34ce2416eedd56079b117fa59376bb4a724110690f13aa8427f2ee29a09eec63a7e72367626d0 languageName: node linkType: hard -"jest-worker@npm:30.3.0": - version: 30.3.0 - resolution: "jest-worker@npm:30.3.0" +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" dependencies: - "@types/node": "npm:*" - "@ungap/structured-clone": "npm:^1.3.0" - jest-util: "npm:30.3.0" - merge-stream: "npm:^2.0.0" - supports-color: "npm:^8.1.1" - checksum: 10c0/25dfb1bc43d389e1daf8baad0ef7964249f001a7da7d92c61e398840424ca13fb1fb6242f6e021f0cbb37952f90371fb8be1ef0183b5d04ef161fdb8f09ee78e + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 languageName: node linkType: hard @@ -11002,25 +10068,6 @@ __metadata: languageName: node linkType: hard -"jest@npm:^30.3.0": - version: 30.3.0 - resolution: "jest@npm:30.3.0" - dependencies: - "@jest/core": "npm:30.3.0" - "@jest/types": "npm:30.3.0" - import-local: "npm:^3.2.0" - jest-cli: "npm:30.3.0" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - bin: - jest: ./bin/jest.js - checksum: 10c0/1f940424b741d1541c3d71e311f77c3cfaf31cff9ab2d53180333f00a31f157790a8d3d413b72b8dd2bb191aa75769fa741d9bc9085df779cd59689559a65815 - languageName: node - linkType: hard - "js-base64@npm:^2.1.9": version: 2.6.4 resolution: "js-base64@npm:2.6.4" @@ -11028,6 +10075,13 @@ __metadata: languageName: node linkType: hard +"js-tokens@npm:^10.0.0": + version: 10.0.0 + resolution: "js-tokens@npm:10.0.0" + checksum: 10c0/a93498747812ba3e0c8626f95f75ab29319f2a13613a0de9e610700405760931624433a0de59eb7c27ff8836e526768fb20783861b86ef89be96676f2c996b64 + languageName: node + linkType: hard + "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -11035,18 +10089,6 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^3.13.1": - version: 3.14.2 - resolution: "js-yaml@npm:3.14.2" - dependencies: - argparse: "npm:^1.0.7" - esprima: "npm:^4.0.0" - bin: - js-yaml: bin/js-yaml.js - checksum: 10c0/3261f25912f5dd76605e5993d0a126c2b6c346311885d3c483706cd722efe34f697ea0331f654ce27c00a42b426e524518ec89d65ed02ea47df8ad26dcc8ce69 - languageName: node - linkType: hard - "js-yaml@npm:^3.9.0": version: 3.14.1 resolution: "js-yaml@npm:3.14.1" @@ -11077,36 +10119,37 @@ __metadata: languageName: node linkType: hard -"jsdom@npm:^26.1.0": - version: 26.1.0 - resolution: "jsdom@npm:26.1.0" +"jsdom@npm:^29.0.2": + version: 29.0.2 + resolution: "jsdom@npm:29.0.2" dependencies: - cssstyle: "npm:^4.2.1" - data-urls: "npm:^5.0.0" - decimal.js: "npm:^10.5.0" - html-encoding-sniffer: "npm:^4.0.0" - http-proxy-agent: "npm:^7.0.2" - https-proxy-agent: "npm:^7.0.6" + "@asamuzakjp/css-color": "npm:^5.1.5" + "@asamuzakjp/dom-selector": "npm:^7.0.6" + "@bramus/specificity": "npm:^2.4.2" + "@csstools/css-syntax-patches-for-csstree": "npm:^1.1.1" + "@exodus/bytes": "npm:^1.15.0" + css-tree: "npm:^3.2.1" + data-urls: "npm:^7.0.0" + decimal.js: "npm:^10.6.0" + html-encoding-sniffer: "npm:^6.0.0" is-potential-custom-element-name: "npm:^1.0.1" - nwsapi: "npm:^2.2.16" - parse5: "npm:^7.2.1" - rrweb-cssom: "npm:^0.8.0" + lru-cache: "npm:^11.2.7" + parse5: "npm:^8.0.0" saxes: "npm:^6.0.0" symbol-tree: "npm:^3.2.4" - tough-cookie: "npm:^5.1.1" + tough-cookie: "npm:^6.0.1" + undici: "npm:^7.24.5" w3c-xmlserializer: "npm:^5.0.0" - webidl-conversions: "npm:^7.0.0" - whatwg-encoding: "npm:^3.1.1" - whatwg-mimetype: "npm:^4.0.0" - whatwg-url: "npm:^14.1.1" - ws: "npm:^8.18.0" + webidl-conversions: "npm:^8.0.1" + whatwg-mimetype: "npm:^5.0.0" + whatwg-url: "npm:^16.0.1" xml-name-validator: "npm:^5.0.0" peerDependencies: canvas: ^3.0.0 peerDependenciesMeta: canvas: optional: true - checksum: 10c0/5b14a5bc32ce077a06fb42d1ab95b1191afa5cbbce8859e3b96831c5143becbbcbf0511d4d4934e922d2901443ced2cdc3b734c1cf30b5f73b3e067ce457d0f4 + checksum: 10c0/a325324117932de83d13f00c74ff91a5f6b4bbbf11f45e7e31189fea06d007f764aac286dad80f643430c81b618b9fb20eac1ef03f120cec4c68df271e7547e2 languageName: node linkType: hard @@ -11305,13 +10348,6 @@ __metadata: languageName: node linkType: hard -"leven@npm:^3.1.0": - version: 3.1.0 - resolution: "leven@npm:3.1.0" - checksum: 10c0/cd778ba3fbab0f4d0500b7e87d1f6e1f041507c56fdcd47e8256a3012c98aaee371d4c15e0a76e0386107af2d42e2b7466160a2d80688aaa03e66e49949f42df - languageName: node - linkType: hard - "levn@npm:^0.4.1": version: 0.4.1 resolution: "levn@npm:0.4.1" @@ -11322,6 +10358,126 @@ __metadata: languageName: node linkType: hard +"lightningcss-android-arm64@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-android-arm64@npm:1.32.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-darwin-arm64@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-darwin-arm64@npm:1.32.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-darwin-x64@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-darwin-x64@npm:1.32.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"lightningcss-freebsd-x64@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-freebsd-x64@npm:1.32.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"lightningcss-linux-arm-gnueabihf@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-arm-gnueabihf@npm:1.32.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"lightningcss-linux-arm64-gnu@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-arm64-gnu@npm:1.32.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"lightningcss-linux-arm64-musl@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-arm64-musl@npm:1.32.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"lightningcss-linux-x64-gnu@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-x64-gnu@npm:1.32.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"lightningcss-linux-x64-musl@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-x64-musl@npm:1.32.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"lightningcss-win32-arm64-msvc@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-win32-arm64-msvc@npm:1.32.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-win32-x64-msvc@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-win32-x64-msvc@npm:1.32.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"lightningcss@npm:^1.32.0": + version: 1.32.0 + resolution: "lightningcss@npm:1.32.0" + dependencies: + detect-libc: "npm:^2.0.3" + lightningcss-android-arm64: "npm:1.32.0" + lightningcss-darwin-arm64: "npm:1.32.0" + lightningcss-darwin-x64: "npm:1.32.0" + lightningcss-freebsd-x64: "npm:1.32.0" + lightningcss-linux-arm-gnueabihf: "npm:1.32.0" + lightningcss-linux-arm64-gnu: "npm:1.32.0" + lightningcss-linux-arm64-musl: "npm:1.32.0" + lightningcss-linux-x64-gnu: "npm:1.32.0" + lightningcss-linux-x64-musl: "npm:1.32.0" + lightningcss-win32-arm64-msvc: "npm:1.32.0" + lightningcss-win32-x64-msvc: "npm:1.32.0" + dependenciesMeta: + lightningcss-android-arm64: + optional: true + lightningcss-darwin-arm64: + optional: true + lightningcss-darwin-x64: + optional: true + lightningcss-freebsd-x64: + optional: true + lightningcss-linux-arm-gnueabihf: + optional: true + lightningcss-linux-arm64-gnu: + optional: true + lightningcss-linux-arm64-musl: + optional: true + lightningcss-linux-x64-gnu: + optional: true + lightningcss-linux-x64-musl: + optional: true + lightningcss-win32-arm64-msvc: + optional: true + lightningcss-win32-x64-msvc: + optional: true + checksum: 10c0/70945bd55097af46fc9fab7f5ed09cd5869d85940a2acab7ee06d0117004a1d68155708a2d462531cea2fc3c67aefc9333a7068c80b0b78dd404c16838809e03 + languageName: node + linkType: hard + "lilconfig@npm:^3.1.3": version: 3.1.3 resolution: "lilconfig@npm:3.1.3" @@ -11459,13 +10615,6 @@ __metadata: languageName: node linkType: hard -"lodash.memoize@npm:^4.1.2": - version: 4.1.2 - resolution: "lodash.memoize@npm:4.1.2" - checksum: 10c0/c8713e51eccc650422716a14cece1809cfe34bc5ab5e242b7f8b4e2241c2483697b971a604252807689b9dd69bfe3a98852e19a5b89d506b000b4187a1285df8 - languageName: node - linkType: hard - "lodash.merge@npm:^4.6.2": version: 4.6.2 resolution: "lodash.merge@npm:4.6.2" @@ -11560,7 +10709,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.2.0, lru-cache@npm:^10.4.3": +"lru-cache@npm:^10.2.0": version: 10.4.3 resolution: "lru-cache@npm:10.4.3" checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb @@ -11574,6 +10723,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^11.2.7": + version: 11.3.5 + resolution: "lru-cache@npm:11.3.5" + checksum: 10c0/5b54ef7b88afb4bd25b7a778f1b2b1cde32d9770913e530da34ab203cf0442413bcaa6e372800cbab9562557a4480e4d8bf32e3a368bb5a91b12218eca085c66 + languageName: node + linkType: hard + "lru-cache@npm:^4.0.1": version: 4.1.5 resolution: "lru-cache@npm:4.1.5" @@ -11602,6 +10758,26 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.21": + version: 0.30.21 + resolution: "magic-string@npm:0.30.21" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.5" + checksum: 10c0/299378e38f9a270069fc62358522ddfb44e94244baa0d6a8980ab2a9b2490a1d03b236b447eee309e17eb3bddfa482c61259d47960eb018a904f0ded52780c4a + languageName: node + linkType: hard + +"magicast@npm:^0.5.2": + version: 0.5.2 + resolution: "magicast@npm:0.5.2" + dependencies: + "@babel/parser": "npm:^7.29.0" + "@babel/types": "npm:^7.29.0" + source-map-js: "npm:^1.2.1" + checksum: 10c0/924af677643c5a0a7d6cdb3247c0eb96fa7611b2ba6a5e720d35d81c503d3d9f5948eb5227f80f90f82ea3e7d38cffd10bb988f3fc09020db428e14f26e960d7 + languageName: node + linkType: hard + "make-dir@npm:^1.0.0": version: 1.3.0 resolution: "make-dir@npm:1.3.0" @@ -11620,7 +10796,7 @@ __metadata: languageName: node linkType: hard -"make-error@npm:^1.1.1, make-error@npm:^1.3.6": +"make-error@npm:^1.1.1": version: 1.3.6 resolution: "make-error@npm:1.3.6" checksum: 10c0/171e458d86854c6b3fc46610cfacf0b45149ba043782558c6875d9f42f222124384ad0b468c92e996d815a8a2003817a710c0a160e49c1c394626f76fa45396f @@ -11646,15 +10822,6 @@ __metadata: languageName: node linkType: hard -"makeerror@npm:1.0.12": - version: 1.0.12 - resolution: "makeerror@npm:1.0.12" - dependencies: - tmpl: "npm:1.0.5" - checksum: 10c0/b0e6e599780ce6bab49cc413eba822f7d1f0dfebd1c103eaa3785c59e43e22c59018323cf9e1708f0ef5329e94a745d163fcbb6bff8e4c6742f9be9e86f3500c - languageName: node - linkType: hard - "map-obj@npm:^1.0.0, map-obj@npm:^1.0.1": version: 1.0.1 resolution: "map-obj@npm:1.0.1" @@ -11748,6 +10915,13 @@ __metadata: languageName: node linkType: hard +"mdn-data@npm:2.27.1": + version: 2.27.1 + resolution: "mdn-data@npm:2.27.1" + checksum: 10c0/eb8abf5d22e4d1e090346f5e81b67d23cef14c83940e445da5c44541ad874dc8fb9f6ca236e8258c3a489d9fb5884188a4d7d58773adb9089ac2c0b966796393 + languageName: node + linkType: hard + "media-typer@npm:0.3.0": version: 0.3.0 resolution: "media-typer@npm:0.3.0" @@ -12233,6 +11407,39 @@ __metadata: languageName: node linkType: hard +"msw@npm:^2.13.6": + version: 2.13.6 + resolution: "msw@npm:2.13.6" + dependencies: + "@inquirer/confirm": "npm:^6.0.11" + "@mswjs/interceptors": "npm:^0.41.3" + "@open-draft/deferred-promise": "npm:^3.0.0" + "@types/statuses": "npm:^2.0.6" + cookie: "npm:^1.1.1" + graphql: "npm:^16.13.2" + headers-polyfill: "npm:^5.0.1" + is-node-process: "npm:^1.2.0" + outvariant: "npm:^1.4.3" + path-to-regexp: "npm:^6.3.0" + picocolors: "npm:^1.1.1" + rettime: "npm:^0.11.7" + statuses: "npm:^2.0.2" + strict-event-emitter: "npm:^0.5.1" + tough-cookie: "npm:^6.0.1" + type-fest: "npm:^5.5.0" + until-async: "npm:^3.0.2" + yargs: "npm:^17.7.2" + peerDependencies: + typescript: ">= 4.8.x" + peerDependenciesMeta: + typescript: + optional: true + bin: + msw: cli/index.js + checksum: 10c0/33f4c3b16aa290d2820cb2f0b33e05d414516b6a6e2cc15f7a8068e3b61247992985371719a9fb75a433c2b6455cb2d0a1d93446b8610a17601ab28cd3a8a9a2 + languageName: node + linkType: hard + "multicast-dns@npm:^7.2.5": version: 7.2.5 resolution: "multicast-dns@npm:7.2.5" @@ -12245,6 +11452,13 @@ __metadata: languageName: node linkType: hard +"mute-stream@npm:^3.0.0": + version: 3.0.0 + resolution: "mute-stream@npm:3.0.0" + checksum: 10c0/12cdb36a101694c7a6b296632e6d93a30b74401873cf7507c88861441a090c71c77a58f213acadad03bc0c8fa186639dec99d68a14497773a8744320c136e701 + languageName: node + linkType: hard + "nanoclone@npm:^0.2.1": version: 0.2.1 resolution: "nanoclone@npm:0.2.1" @@ -12261,15 +11475,6 @@ __metadata: languageName: node linkType: hard -"napi-postinstall@npm:^0.3.0": - version: 0.3.4 - resolution: "napi-postinstall@npm:0.3.4" - bin: - napi-postinstall: lib/cli.js - checksum: 10c0/b33d64150828bdade3a5d07368a8b30da22ee393f8dd8432f1b9e5486867be21c84ec443dd875dd3ef3c7401a079a7ab7e2aa9d3538a889abbcd96495d5104fe - languageName: node - linkType: hard - "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -12337,13 +11542,6 @@ __metadata: languageName: node linkType: hard -"node-int64@npm:^0.4.0": - version: 0.4.0 - resolution: "node-int64@npm:0.4.0" - checksum: 10c0/a6a4d8369e2f2720e9c645255ffde909c0fbd41c92ea92a5607fc17055955daac99c1ff589d421eee12a0d24e99f7bfc2aabfeb1a4c14742f6c099a51863f31a - languageName: node - linkType: hard - "node-releases@npm:^2.0.27": version: 2.0.27 resolution: "node-releases@npm:2.0.27" @@ -12422,7 +11620,7 @@ __metadata: languageName: node linkType: hard -"npm-run-path@npm:^4.0.0, npm-run-path@npm:^4.0.1": +"npm-run-path@npm:^4.0.0": version: 4.0.1 resolution: "npm-run-path@npm:4.0.1" dependencies: @@ -12447,13 +11645,6 @@ __metadata: languageName: node linkType: hard -"nwsapi@npm:^2.2.16": - version: 2.2.23 - resolution: "nwsapi@npm:2.2.23" - checksum: 10c0/e44bfc9246baf659581206ed716d291a1905185247795fb8a302cb09315c943a31023b4ac4d026a5eaf32b2def51d77b3d0f9ebf4f3d35f70e105fcb6447c76e - languageName: node - linkType: hard - "object-assign@npm:^4.0.1, object-assign@npm:^4.1.0, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" @@ -12552,6 +11743,13 @@ __metadata: languageName: node linkType: hard +"obug@npm:^2.1.1": + version: 2.1.1 + resolution: "obug@npm:2.1.1" + checksum: 10c0/59dccd7de72a047e08f8649e94c1015ec72f94eefb6ddb57fb4812c4b425a813bc7e7cd30c9aca20db3c59abc3c85cc7a62bb656a968741d770f4e8e02bc2e78 + languageName: node + linkType: hard + "on-finished@npm:^2.4.1, on-finished@npm:~2.4.1": version: 2.4.1 resolution: "on-finished@npm:2.4.1" @@ -12577,7 +11775,7 @@ __metadata: languageName: node linkType: hard -"onetime@npm:^5.1.0, onetime@npm:^5.1.2": +"onetime@npm:^5.1.0": version: 5.1.2 resolution: "onetime@npm:5.1.2" dependencies: @@ -12628,6 +11826,13 @@ __metadata: languageName: node linkType: hard +"outvariant@npm:^1.4.0, outvariant@npm:^1.4.3": + version: 1.4.3 + resolution: "outvariant@npm:1.4.3" + checksum: 10c0/5976ca7740349cb8c71bd3382e2a762b1aeca6f33dc984d9d896acdf3c61f78c3afcf1bfe9cc633a7b3c4b295ec94d292048f83ea2b2594fae4496656eba992c + languageName: node + linkType: hard + "own-keys@npm:^1.0.1": version: 1.0.1 resolution: "own-keys@npm:1.0.1" @@ -12664,7 +11869,7 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^3.0.2, p-limit@npm:^3.1.0": +"p-limit@npm:^3.0.2": version: 3.1.0 resolution: "p-limit@npm:3.1.0" dependencies: @@ -12854,7 +12059,7 @@ __metadata: languageName: node linkType: hard -"parse5@npm:^7.0.0, parse5@npm:^7.2.1, parse5@npm:^7.3.0": +"parse5@npm:^7.0.0, parse5@npm:^7.3.0": version: 7.3.0 resolution: "parse5@npm:7.3.0" dependencies: @@ -12863,6 +12068,15 @@ __metadata: languageName: node linkType: hard +"parse5@npm:^8.0.0": + version: 8.0.1 + resolution: "parse5@npm:8.0.1" + dependencies: + entities: "npm:^8.0.0" + checksum: 10c0/c3c1c5aab55f6e4be5245599790e56e64be7764a4a0edd7f98db4fe3bb380f63add752fa047dff0496446c25f4104f0c7c1967723de640bde92306a7bb67ed2f + languageName: node + linkType: hard + "parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" @@ -12964,6 +12178,13 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:^6.3.0": + version: 6.3.0 + resolution: "path-to-regexp@npm:6.3.0" + checksum: 10c0/73b67f4638b41cde56254e6354e46ae3a2ebc08279583f6af3d96fe4664fc75788f74ed0d18ca44fa4a98491b69434f9eee73b97bb5314bd1b5adb700f5c18d6 + languageName: node + linkType: hard + "path-to-regexp@npm:~0.1.12": version: 0.1.12 resolution: "path-to-regexp@npm:0.1.12" @@ -12991,6 +12212,13 @@ __metadata: languageName: node linkType: hard +"pathe@npm:^2.0.3": + version: 2.0.3 + resolution: "pathe@npm:2.0.3" + checksum: 10c0/c118dc5a8b5c4166011b2b70608762e260085180bb9e33e80a50dcdb1e78c010b1624f4280c492c92b05fc276715a4c357d1f9edc570f8f1b3d90b6839ebaca1 + languageName: node + linkType: hard + "pend@npm:~1.2.0": version: 1.2.0 resolution: "pend@npm:1.2.0" @@ -13026,6 +12254,13 @@ __metadata: languageName: node linkType: hard +"picomatch@npm:^4.0.4": + version: 4.0.4 + resolution: "picomatch@npm:4.0.4" + checksum: 10c0/e2c6023372cc7b5764719a5ffb9da0f8e781212fa7ca4bd0562db929df8e117460f00dff3cb7509dacfc06b86de924b247f504d0ce1806a37fac4633081466b0 + languageName: node + linkType: hard + "pify@npm:^2.0.0, pify@npm:^2.2.0": version: 2.3.0 resolution: "pify@npm:2.3.0" @@ -13051,15 +12286,8 @@ __metadata: "pinkie@npm:^2.0.0": version: 2.0.4 - resolution: "pinkie@npm:2.0.4" - checksum: 10c0/25228b08b5597da42dc384221aa0ce56ee0fbf32965db12ba838e2a9ca0193c2f0609c45551ee077ccd2060bf109137fdb185b00c6d7e0ed7e35006d20fdcbc6 - languageName: node - linkType: hard - -"pirates@npm:^4.0.7": - version: 4.0.7 - resolution: "pirates@npm:4.0.7" - checksum: 10c0/a51f108dd811beb779d58a76864bbd49e239fa40c7984cd11596c75a121a8cc789f1c8971d8bb15f0dbf9d48b76c05bb62fcbce840f89b688c0fa64b37e8478a + resolution: "pinkie@npm:2.0.4" + checksum: 10c0/25228b08b5597da42dc384221aa0ce56ee0fbf32965db12ba838e2a9ca0193c2f0609c45551ee077ccd2060bf109137fdb185b00c6d7e0ed7e35006d20fdcbc6 languageName: node linkType: hard @@ -13326,6 +12554,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:^8.5.10": + version: 8.5.10 + resolution: "postcss@npm:8.5.10" + dependencies: + nanoid: "npm:^3.3.11" + picocolors: "npm:^1.1.1" + source-map-js: "npm:^1.2.1" + checksum: 10c0/c592dffa0c4873b401f01955b265538d9942f425040df5e2b8f0ad34c83773a792ea0fa5859ccc99cfb5b955b4ebff118ab7056315388dc83b107b0fa8313576 + languageName: node + linkType: hard + "prelude-ls@npm:^1.2.1": version: 1.2.1 resolution: "prelude-ls@npm:1.2.1" @@ -13405,17 +12644,6 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:30.3.0, pretty-format@npm:^30.0.0": - version: 30.3.0 - resolution: "pretty-format@npm:30.3.0" - dependencies: - "@jest/schemas": "npm:30.0.5" - ansi-styles: "npm:^5.2.0" - react-is: "npm:^18.3.1" - checksum: 10c0/719b27d70cd8b01013485054c5d094e1fe85e093b09ee73553e3b19302da3cf54fbd6a7ea9577d6471aeff8d372200e56979ffc4c831e2133520bd18060895fb - languageName: node - linkType: hard - "pretty-format@npm:^27.0.2": version: 27.5.1 resolution: "pretty-format@npm:27.5.1" @@ -13521,13 +12749,6 @@ __metadata: languageName: node linkType: hard -"pure-rand@npm:^7.0.0": - version: 7.0.1 - resolution: "pure-rand@npm:7.0.1" - checksum: 10c0/9cade41030f5ec95f5d55a11a71404cd6f46b69becaad892097cd7f58e2c6248cd0a933349ca7d21336ab629f1da42ffe899699b671bc4651600eaf6e57f837e - languageName: node - linkType: hard - "pvtsutils@npm:^1.3.6": version: 1.3.6 resolution: "pvtsutils@npm:1.3.6" @@ -13653,7 +12874,7 @@ __metadata: languageName: node linkType: hard -"react-dropzone@npm:^14.3.5": +"react-dropzone@npm:14.3.5, react-dropzone@npm:^14.3.5": version: 14.3.5 resolution: "react-dropzone@npm:14.3.5" dependencies: @@ -13698,13 +12919,6 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^18.3.1": - version: 18.3.1 - resolution: "react-is@npm:18.3.1" - checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072 - languageName: node - linkType: hard - "react-redux@npm:7.2.9": version: 7.2.9 resolution: "react-redux@npm:7.2.9" @@ -14330,6 +13544,13 @@ __metadata: languageName: node linkType: hard +"rettime@npm:^0.11.7": + version: 0.11.8 + resolution: "rettime@npm:0.11.8" + checksum: 10c0/a0e53133e5d3345a60ca4a86f29e5b67715ce6de61427eb5bdd223c41e80789f62a926f9efd9524dee38d3ab968444096564e29263a9abd61f1695fdd1114867 + languageName: node + linkType: hard + "reusify@npm:^1.0.4": version: 1.0.4 resolution: "reusify@npm:1.0.4" @@ -14384,10 +13605,61 @@ __metadata: languageName: node linkType: hard -"rrweb-cssom@npm:^0.8.0": - version: 0.8.0 - resolution: "rrweb-cssom@npm:0.8.0" - checksum: 10c0/56f2bfd56733adb92c0b56e274c43f864b8dd48784d6fe946ef5ff8d438234015e59ad837fc2ad54714b6421384141c1add4eb569e72054e350d1f8a50b8ac7b +"rolldown@npm:1.0.0-rc.17": + version: 1.0.0-rc.17 + resolution: "rolldown@npm:1.0.0-rc.17" + dependencies: + "@oxc-project/types": "npm:=0.127.0" + "@rolldown/binding-android-arm64": "npm:1.0.0-rc.17" + "@rolldown/binding-darwin-arm64": "npm:1.0.0-rc.17" + "@rolldown/binding-darwin-x64": "npm:1.0.0-rc.17" + "@rolldown/binding-freebsd-x64": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-arm-gnueabihf": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-arm64-gnu": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-arm64-musl": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-ppc64-gnu": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-s390x-gnu": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-x64-gnu": "npm:1.0.0-rc.17" + "@rolldown/binding-linux-x64-musl": "npm:1.0.0-rc.17" + "@rolldown/binding-openharmony-arm64": "npm:1.0.0-rc.17" + "@rolldown/binding-wasm32-wasi": "npm:1.0.0-rc.17" + "@rolldown/binding-win32-arm64-msvc": "npm:1.0.0-rc.17" + "@rolldown/binding-win32-x64-msvc": "npm:1.0.0-rc.17" + "@rolldown/pluginutils": "npm:1.0.0-rc.17" + dependenciesMeta: + "@rolldown/binding-android-arm64": + optional: true + "@rolldown/binding-darwin-arm64": + optional: true + "@rolldown/binding-darwin-x64": + optional: true + "@rolldown/binding-freebsd-x64": + optional: true + "@rolldown/binding-linux-arm-gnueabihf": + optional: true + "@rolldown/binding-linux-arm64-gnu": + optional: true + "@rolldown/binding-linux-arm64-musl": + optional: true + "@rolldown/binding-linux-ppc64-gnu": + optional: true + "@rolldown/binding-linux-s390x-gnu": + optional: true + "@rolldown/binding-linux-x64-gnu": + optional: true + "@rolldown/binding-linux-x64-musl": + optional: true + "@rolldown/binding-openharmony-arm64": + optional: true + "@rolldown/binding-wasm32-wasi": + optional: true + "@rolldown/binding-win32-arm64-msvc": + optional: true + "@rolldown/binding-win32-x64-msvc": + optional: true + bin: + rolldown: bin/cli.mjs + checksum: 10c0/bb99abc62ece4e34edd06d2b8eb9ffb7194dc2f0465a4329bb106cbde3006a10f1575e3580b198b793341109a2109581aed623c537c12b0c3a4ba0d72169b2fb languageName: node linkType: hard @@ -14567,7 +13839,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.3, semver@npm:^7.7.2, semver@npm:^7.7.3": +"semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.3, semver@npm:^7.6.3, semver@npm:^7.7.3": version: 7.7.4 resolution: "semver@npm:7.7.4" bin: @@ -14640,6 +13912,13 @@ __metadata: languageName: node linkType: hard +"set-cookie-parser@npm:^3.0.1": + version: 3.1.0 + resolution: "set-cookie-parser@npm:3.1.0" + checksum: 10c0/7465e389ff9fb7ff243fd55f0f48b5648d53a560903db170a7f766c2b82f22f4242c4d366fcdf12afdd376496f84058025d889e718459256ecbfc9a5fe7755f5 + languageName: node + linkType: hard + "set-function-length@npm:^1.2.2": version: 1.2.2 resolution: "set-function-length@npm:1.2.2" @@ -14787,14 +14066,21 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3": +"siginfo@npm:^2.0.0": + version: 2.0.0 + resolution: "siginfo@npm:2.0.0" + checksum: 10c0/3def8f8e516fbb34cb6ae415b07ccc5d9c018d85b4b8611e3dc6f8be6d1899f693a4382913c9ed51a06babb5201639d76453ab297d1c54a456544acf5c892e34 + languageName: node + linkType: hard + +"signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" checksum: 10c0/25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912 languageName: node linkType: hard -"signal-exit@npm:^4.0.1": +"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": version: 4.1.0 resolution: "signal-exit@npm:4.1.0" checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 @@ -14808,13 +14094,6 @@ __metadata: languageName: node linkType: hard -"slash@npm:^3.0.0": - version: 3.0.0 - resolution: "slash@npm:3.0.0" - checksum: 10c0/e18488c6a42bdfd4ac5be85b2ced3ccd0224773baae6ad42cfbb9ec74fc07f9fa8396bd35ee638084ead7a2a0818eb5e7151111544d4731ce843019dab4be47b - languageName: node - linkType: hard - "slash@npm:^5.1.0": version: 5.1.0 resolution: "slash@npm:5.1.0" @@ -14908,16 +14187,6 @@ __metadata: languageName: node linkType: hard -"source-map-support@npm:0.5.13": - version: 0.5.13 - resolution: "source-map-support@npm:0.5.13" - dependencies: - buffer-from: "npm:^1.0.0" - source-map: "npm:^0.6.0" - checksum: 10c0/137539f8c453fa0f496ea42049ab5da4569f96781f6ac8e5bfda26937be9494f4e8891f523c5f98f0e85f71b35d74127a00c46f83f6a4f54672b58d53202565e - languageName: node - linkType: hard - "source-map-support@npm:~0.5.20": version: 0.5.20 resolution: "source-map-support@npm:0.5.20" @@ -15063,12 +14332,17 @@ __metadata: languageName: node linkType: hard -"stack-utils@npm:^2.0.6": - version: 2.0.6 - resolution: "stack-utils@npm:2.0.6" - dependencies: - escape-string-regexp: "npm:^2.0.0" - checksum: 10c0/651c9f87667e077584bbe848acaecc6049bc71979f1e9a46c7b920cad4431c388df0f51b8ad7cfd6eed3db97a2878d0fc8b3122979439ea8bac29c61c95eec8a +"stackback@npm:0.0.2": + version: 0.0.2 + resolution: "stackback@npm:0.0.2" + checksum: 10c0/89a1416668f950236dd5ac9f9a6b2588e1b9b62b1b6ad8dff1bfc5d1a15dbf0aafc9b52d2226d00c28dffff212da464eaeebfc6b7578b9d180cef3e3782c5983 + languageName: node + linkType: hard + +"state-local@npm:^1.0.6": + version: 1.0.7 + resolution: "state-local@npm:1.0.7" + checksum: 10c0/8dc7daeac71844452fafb514a6d6b6f40d7e2b33df398309ea1c7b3948d6110c57f112b7196500a10c54fdde40291488c52c875575670fb5c819602deca48bd9 languageName: node linkType: hard @@ -15086,13 +14360,20 @@ __metadata: languageName: node linkType: hard -"statuses@npm:~2.0.1, statuses@npm:~2.0.2": +"statuses@npm:^2.0.2, statuses@npm:~2.0.1, statuses@npm:~2.0.2": version: 2.0.2 resolution: "statuses@npm:2.0.2" checksum: 10c0/a9947d98ad60d01f6b26727570f3bcceb6c8fa789da64fe6889908fe2e294d57503b14bf2b5af7605c2d36647259e856635cd4c49eab41667658ec9d0080ec3f languageName: node linkType: hard +"std-env@npm:^4.0.0-rc.1": + version: 4.1.0 + resolution: "std-env@npm:4.1.0" + checksum: 10c0/2e14b6b490db34cb969a48d9cf7c35bca4a47653914aac2814221baae7b867a5b15940d133625c391621971f98cd2266a5dc7036669960e883f1081db2a56558 + languageName: node + linkType: hard + "stop-iteration-iterator@npm:^1.0.0, stop-iteration-iterator@npm:^1.1.0": version: 1.1.0 resolution: "stop-iteration-iterator@npm:1.1.0" @@ -15123,13 +14404,10 @@ __metadata: languageName: node linkType: hard -"string-length@npm:^4.0.2": - version: 4.0.2 - resolution: "string-length@npm:4.0.2" - dependencies: - char-regex: "npm:^1.0.2" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/1cd77409c3d7db7bc59406f6bcc9ef0783671dcbabb23597a1177c166906ef2ee7c8290f78cae73a8aec858768f189d2cb417797df5e15ec4eb5e16b3346340c +"strict-event-emitter@npm:^0.5.1": + version: 0.5.1 + resolution: "strict-event-emitter@npm:0.5.1" + checksum: 10c0/f5228a6e6b6393c57f52f62e673cfe3be3294b35d6f7842fc24b172ae0a6e6c209fa83241d0e433fc267c503bc2f4ffdbe41a9990ff8ffd5ac425ec0489417f7 languageName: node linkType: hard @@ -15317,13 +14595,6 @@ __metadata: languageName: node linkType: hard -"strip-bom@npm:^4.0.0": - version: 4.0.0 - resolution: "strip-bom@npm:4.0.0" - checksum: 10c0/26abad1172d6bc48985ab9a5f96c21e440f6e7e476686de49be813b5a59b3566dccb5c525b831ec54fe348283b47f3ffb8e080bc3f965fde12e84df23f6bb7ef - languageName: node - linkType: hard - "strip-eof@npm:^1.0.0": version: 1.0.0 resolution: "strip-eof@npm:1.0.0" @@ -15608,7 +14879,7 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.11.12, synckit@npm:^0.11.8": +"synckit@npm:^0.11.12": version: 0.11.12 resolution: "synckit@npm:0.11.12" dependencies: @@ -15661,6 +14932,13 @@ __metadata: languageName: node linkType: hard +"tagged-tag@npm:^1.0.0": + version: 1.0.0 + resolution: "tagged-tag@npm:1.0.0" + checksum: 10c0/91d25c9ffb86a91f20522cefb2cbec9b64caa1febe27ad0df52f08993ff60888022d771e868e6416cf2e72dab68449d2139e8709ba009b74c6c7ecd4000048d1 + languageName: node + linkType: hard + "tapable@npm:^2.3.0": version: 2.3.0 resolution: "tapable@npm:2.3.0" @@ -15781,17 +15059,6 @@ __metadata: languageName: node linkType: hard -"test-exclude@npm:^6.0.0": - version: 6.0.0 - resolution: "test-exclude@npm:6.0.0" - dependencies: - "@istanbuljs/schema": "npm:^0.1.2" - glob: "npm:^7.1.4" - minimatch: "npm:^3.0.4" - checksum: 10c0/019d33d81adff3f9f1bfcff18125fb2d3c65564f437d9be539270ee74b994986abb8260c7c2ce90e8f30162178b09dbbce33c6389273afac4f36069c48521f57 - languageName: node - linkType: hard - "text-decoder@npm:^1.1.0": version: 1.2.3 resolution: "text-decoder@npm:1.2.3" @@ -15862,6 +15129,20 @@ __metadata: languageName: node linkType: hard +"tinybench@npm:^2.9.0": + version: 2.9.0 + resolution: "tinybench@npm:2.9.0" + checksum: 10c0/c3500b0f60d2eb8db65250afe750b66d51623057ee88720b7f064894a6cb7eb93360ca824a60a31ab16dab30c7b1f06efe0795b352e37914a9d4bad86386a20c + languageName: node + linkType: hard + +"tinyexec@npm:^1.0.2": + version: 1.1.1 + resolution: "tinyexec@npm:1.1.1" + checksum: 10c0/48433cb32573a767e2b63bb92343cbbae4240d05a19a63f7869f9447491305e7bd82d11daccb79b2628b596ad703a25798226c50bfd1d8e63477fb42af6a5b35 + languageName: node + linkType: hard + "tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" @@ -15872,6 +15153,23 @@ __metadata: languageName: node linkType: hard +"tinyglobby@npm:^0.2.16": + version: 0.2.16 + resolution: "tinyglobby@npm:0.2.16" + dependencies: + fdir: "npm:^6.5.0" + picomatch: "npm:^4.0.4" + checksum: 10c0/f2e09fd93dd95c41e522113b686ff6f7c13020962f8698a864a257f3d7737599afc47722b7ab726e12f8a813f779906187911ff8ee6701ede65072671a7e934b + languageName: node + linkType: hard + +"tinyrainbow@npm:^3.1.0": + version: 3.1.0 + resolution: "tinyrainbow@npm:3.1.0" + checksum: 10c0/f11cf387a26c5c9255bec141a90ac511b26172981b10c3e50053bc6700ea7d2336edcc4a3a21dbb8412fe7c013477d2ba4d7e4877800f3f8107be5105aad6511 + languageName: node + linkType: hard + "tldts-core@npm:^6.1.86": version: 6.1.86 resolution: "tldts-core@npm:6.1.86" @@ -15879,6 +15177,13 @@ __metadata: languageName: node linkType: hard +"tldts-core@npm:^7.0.28": + version: 7.0.28 + resolution: "tldts-core@npm:7.0.28" + checksum: 10c0/1fde2a2806c758d13c7eb2bd285a9482bf905829b38c060d66127e9e0682a103c42e181509f0d3c6da046e9aa2f71fe9d61afadb1b85a6b6c557cb98d6b7dede + languageName: node + linkType: hard + "tldts@npm:^6.1.32": version: 6.1.86 resolution: "tldts@npm:6.1.86" @@ -15890,6 +15195,17 @@ __metadata: languageName: node linkType: hard +"tldts@npm:^7.0.5": + version: 7.0.28 + resolution: "tldts@npm:7.0.28" + dependencies: + tldts-core: "npm:^7.0.28" + bin: + tldts: bin/cli.js + checksum: 10c0/37f92481bc7276f60f06d93d2671a67fd94dc8e245c232a50c69b8704d34c908658968f7298810e1b4df68a84be9ff6248867981d1cc7ddb08755565edd3f496 + languageName: node + linkType: hard + "tmp@npm:~0.2.4": version: 0.2.5 resolution: "tmp@npm:0.2.5" @@ -15897,13 +15213,6 @@ __metadata: languageName: node linkType: hard -"tmpl@npm:1.0.5": - version: 1.0.5 - resolution: "tmpl@npm:1.0.5" - checksum: 10c0/f935537799c2d1922cb5d6d3805f594388f75338fe7a4a9dac41504dd539704ca4db45b883b52e7b0aa5b2fd5ddadb1452bf95cd23a69da2f793a843f9451cc9 - languageName: node - linkType: hard - "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -15936,7 +15245,7 @@ __metadata: languageName: node linkType: hard -"tough-cookie@npm:^5.0.0, tough-cookie@npm:^5.1.1": +"tough-cookie@npm:^5.0.0": version: 5.1.2 resolution: "tough-cookie@npm:5.1.2" dependencies: @@ -15945,12 +15254,21 @@ __metadata: languageName: node linkType: hard -"tr46@npm:^5.1.0": - version: 5.1.1 - resolution: "tr46@npm:5.1.1" +"tough-cookie@npm:^6.0.1": + version: 6.0.1 + resolution: "tough-cookie@npm:6.0.1" + dependencies: + tldts: "npm:^7.0.5" + checksum: 10c0/ec70bd6b1215efe4ed31a158f0be3e4c9088fcbd8620edc23a5860d4f3d85c757b77e274baaa700f7b25e409f4181552ed189603c2b2e1a9f88104da3a61a37d + languageName: node + linkType: hard + +"tr46@npm:^6.0.0": + version: 6.0.0 + resolution: "tr46@npm:6.0.0" dependencies: punycode: "npm:^2.3.1" - checksum: 10c0/ae270e194d52ec67ebd695c1a42876e0f19b96e4aca2ab464ab1d9d17dc3acd3e18764f5034c93897db73421563be27c70c98359c4501136a497e46deda5d5ec + checksum: 10c0/83130df2f649228aa91c17754b66248030a3af34911d713b5ea417066fa338aa4bc8668d06bd98aa21a2210f43fc0a3db8b9099e7747fb5830e40e39a6a1058e languageName: node linkType: hard @@ -16016,46 +15334,6 @@ __metadata: languageName: node linkType: hard -"ts-jest@npm:^29.4.6": - version: 29.4.6 - resolution: "ts-jest@npm:29.4.6" - dependencies: - bs-logger: "npm:^0.2.6" - fast-json-stable-stringify: "npm:^2.1.0" - handlebars: "npm:^4.7.8" - json5: "npm:^2.2.3" - lodash.memoize: "npm:^4.1.2" - make-error: "npm:^1.3.6" - semver: "npm:^7.7.3" - type-fest: "npm:^4.41.0" - yargs-parser: "npm:^21.1.1" - peerDependencies: - "@babel/core": ">=7.0.0-beta.0 <8" - "@jest/transform": ^29.0.0 || ^30.0.0 - "@jest/types": ^29.0.0 || ^30.0.0 - babel-jest: ^29.0.0 || ^30.0.0 - jest: ^29.0.0 || ^30.0.0 - jest-util: ^29.0.0 || ^30.0.0 - typescript: ">=4.3 <6" - peerDependenciesMeta: - "@babel/core": - optional: true - "@jest/transform": - optional: true - "@jest/types": - optional: true - babel-jest: - optional: true - esbuild: - optional: true - jest-util: - optional: true - bin: - ts-jest: cli.js - checksum: 10c0/013dda99ac938cd4b94bae9323ed1b633cd295976c256d596d01776866188078fe7b82b8b3ebd05deb401b27b5618d9d76208eded2568661240ecf9694a5c933 - languageName: node - linkType: hard - "ts-loader@npm:^9.5.4": version: 9.5.4 resolution: "ts-loader@npm:9.5.4" @@ -16158,13 +15436,6 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:4.0.8": - version: 4.0.8 - resolution: "type-detect@npm:4.0.8" - checksum: 10c0/8fb9a51d3f365a7de84ab7f73b653534b61b622aa6800aecdb0f1095a4a646d3f5eb295322127b6573db7982afcd40ab492d038cf825a42093a58b1e1353e0bd - languageName: node - linkType: hard - "type-fest@npm:^0.21.3": version: 0.21.3 resolution: "type-fest@npm:0.21.3" @@ -16186,10 +15457,12 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^4.41.0": - version: 4.41.0 - resolution: "type-fest@npm:4.41.0" - checksum: 10c0/f5ca697797ed5e88d33ac8f1fec21921839871f808dc59345c9cf67345bfb958ce41bd821165dbf3ae591cedec2bf6fe8882098dfdd8dc54320b859711a2c1e4 +"type-fest@npm:^5.5.0": + version: 5.6.0 + resolution: "type-fest@npm:5.6.0" + dependencies: + tagged-tag: "npm:^1.0.0" + checksum: 10c0/5468a8ffda7f3904e6f7bbd8069eb8b6dd4bd9156e206df7a01d09a73e28cd1afedf74ead9d0fc12841c8c90074194859feca240511c50800962fde1bd9ddcbc languageName: node linkType: hard @@ -16298,15 +15571,6 @@ __metadata: languageName: node linkType: hard -"uglify-js@npm:^3.1.4": - version: 3.19.3 - resolution: "uglify-js@npm:3.19.3" - bin: - uglifyjs: bin/uglifyjs - checksum: 10c0/83b0a90eca35f778e07cad9622b80c448b6aad457c9ff8e568afed978212b42930a95f9e1be943a1ffa4258a3340fbb899f41461131c05bb1d0a9c303aed8479 - languageName: node - linkType: hard - "unbox-primitive@npm:^1.1.0": version: 1.1.0 resolution: "unbox-primitive@npm:1.1.0" @@ -16343,6 +15607,13 @@ __metadata: languageName: node linkType: hard +"undici@npm:^7.24.5": + version: 7.25.0 + resolution: "undici@npm:7.25.0" + checksum: 10c0/02a0b45dc14eb91bc488948750232450fe52f27a6b08086d6ac6736bb47908d600fe3a96d346f12eab24729c782e5c2f693bc8e8eca6696d4e4c09b1ed4cb4ec + languageName: node + linkType: hard + "unherit@npm:^1.0.4": version: 1.1.3 resolution: "unherit@npm:1.1.3" @@ -16517,70 +15788,10 @@ __metadata: languageName: node linkType: hard -"unrs-resolver@npm:^1.7.11": - version: 1.11.1 - resolution: "unrs-resolver@npm:1.11.1" - dependencies: - "@unrs/resolver-binding-android-arm-eabi": "npm:1.11.1" - "@unrs/resolver-binding-android-arm64": "npm:1.11.1" - "@unrs/resolver-binding-darwin-arm64": "npm:1.11.1" - "@unrs/resolver-binding-darwin-x64": "npm:1.11.1" - "@unrs/resolver-binding-freebsd-x64": "npm:1.11.1" - "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.11.1" - "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.11.1" - "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-arm64-musl": "npm:1.11.1" - "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-riscv64-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-riscv64-musl": "npm:1.11.1" - "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-x64-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-x64-musl": "npm:1.11.1" - "@unrs/resolver-binding-wasm32-wasi": "npm:1.11.1" - "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.11.1" - "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.11.1" - "@unrs/resolver-binding-win32-x64-msvc": "npm:1.11.1" - napi-postinstall: "npm:^0.3.0" - dependenciesMeta: - "@unrs/resolver-binding-android-arm-eabi": - optional: true - "@unrs/resolver-binding-android-arm64": - optional: true - "@unrs/resolver-binding-darwin-arm64": - optional: true - "@unrs/resolver-binding-darwin-x64": - optional: true - "@unrs/resolver-binding-freebsd-x64": - optional: true - "@unrs/resolver-binding-linux-arm-gnueabihf": - optional: true - "@unrs/resolver-binding-linux-arm-musleabihf": - optional: true - "@unrs/resolver-binding-linux-arm64-gnu": - optional: true - "@unrs/resolver-binding-linux-arm64-musl": - optional: true - "@unrs/resolver-binding-linux-ppc64-gnu": - optional: true - "@unrs/resolver-binding-linux-riscv64-gnu": - optional: true - "@unrs/resolver-binding-linux-riscv64-musl": - optional: true - "@unrs/resolver-binding-linux-s390x-gnu": - optional: true - "@unrs/resolver-binding-linux-x64-gnu": - optional: true - "@unrs/resolver-binding-linux-x64-musl": - optional: true - "@unrs/resolver-binding-wasm32-wasi": - optional: true - "@unrs/resolver-binding-win32-arm64-msvc": - optional: true - "@unrs/resolver-binding-win32-ia32-msvc": - optional: true - "@unrs/resolver-binding-win32-x64-msvc": - optional: true - checksum: 10c0/c91b112c71a33d6b24e5c708dab43ab80911f2df8ee65b87cd7a18fb5af446708e98c4b415ca262026ad8df326debcc7ca6a801b2935504d87fd6f0b9d70dce1 +"until-async@npm:^3.0.2": + version: 3.0.2 + resolution: "until-async@npm:3.0.2" + checksum: 10c0/61c8b03895dbe18fe3d90316d0a1894e0c131ea4b1673f6ce78eed993d0bb81bbf4b7adf8477e9ff7725782a76767eed9d077561cfc9f89b4a1ebe61f7c9828e languageName: node linkType: hard @@ -16687,17 +15898,6 @@ __metadata: languageName: node linkType: hard -"v8-to-istanbul@npm:^9.0.1": - version: 9.3.0 - resolution: "v8-to-istanbul@npm:9.3.0" - dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.12" - "@types/istanbul-lib-coverage": "npm:^2.0.1" - convert-source-map: "npm:^2.0.0" - checksum: 10c0/968bcf1c7c88c04df1ffb463c179558a2ec17aa49e49376120504958239d9e9dad5281aa05f2a78542b8557f2be0b0b4c325710262f3b838b40d703d5ed30c23 - languageName: node - linkType: hard - "validate-npm-package-license@npm:^3.0.1": version: 3.0.4 resolution: "validate-npm-package-license@npm:3.0.4" @@ -16826,6 +16026,131 @@ __metadata: languageName: node linkType: hard +"vite@npm:^6.0.0 || ^7.0.0 || ^8.0.0": + version: 8.0.10 + resolution: "vite@npm:8.0.10" + dependencies: + fsevents: "npm:~2.3.3" + lightningcss: "npm:^1.32.0" + picomatch: "npm:^4.0.4" + postcss: "npm:^8.5.10" + rolldown: "npm:1.0.0-rc.17" + tinyglobby: "npm:^0.2.16" + peerDependencies: + "@types/node": ^20.19.0 || >=22.12.0 + "@vitejs/devtools": ^0.1.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: ">=1.21.0" + less: ^4.0.0 + 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 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + "@vitejs/devtools": + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + bin: + vite: bin/vite.js + checksum: 10c0/92188b82654f856dbe562a1b679de695bb6ca18c0f43c4c276f84a869fb78e22dedb7c2df83b5617d6afdca979c059d654b5f61a0936a45f49917f352b9325ca + languageName: node + linkType: hard + +"vitest@npm:^4.1.5": + version: 4.1.5 + resolution: "vitest@npm:4.1.5" + dependencies: + "@vitest/expect": "npm:4.1.5" + "@vitest/mocker": "npm:4.1.5" + "@vitest/pretty-format": "npm:4.1.5" + "@vitest/runner": "npm:4.1.5" + "@vitest/snapshot": "npm:4.1.5" + "@vitest/spy": "npm:4.1.5" + "@vitest/utils": "npm:4.1.5" + es-module-lexer: "npm:^2.0.0" + expect-type: "npm:^1.3.0" + magic-string: "npm:^0.30.21" + obug: "npm:^2.1.1" + pathe: "npm:^2.0.3" + picomatch: "npm:^4.0.3" + std-env: "npm:^4.0.0-rc.1" + tinybench: "npm:^2.9.0" + tinyexec: "npm:^1.0.2" + tinyglobby: "npm:^0.2.15" + tinyrainbow: "npm:^3.1.0" + vite: "npm:^6.0.0 || ^7.0.0 || ^8.0.0" + why-is-node-running: "npm:^2.3.0" + peerDependencies: + "@edge-runtime/vm": "*" + "@opentelemetry/api": ^1.9.0 + "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 + "@vitest/browser-playwright": 4.1.5 + "@vitest/browser-preview": 4.1.5 + "@vitest/browser-webdriverio": 4.1.5 + "@vitest/coverage-istanbul": 4.1.5 + "@vitest/coverage-v8": 4.1.5 + "@vitest/ui": 4.1.5 + happy-dom: "*" + jsdom: "*" + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@opentelemetry/api": + optional: true + "@types/node": + optional: true + "@vitest/browser-playwright": + optional: true + "@vitest/browser-preview": + optional: true + "@vitest/browser-webdriverio": + optional: true + "@vitest/coverage-istanbul": + optional: true + "@vitest/coverage-v8": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vite: + optional: false + bin: + vitest: vitest.mjs + checksum: 10c0/196eaf5e95b45a3f6d3001a2408d7dc6f146c29c873ed4e42e1ad4c9327122934fb3793a12b6ce3b7c25d355e738b20123acc0894ce30358c3370b15f4bd0865 + languageName: node + linkType: hard + "void-elements@npm:3.1.0": version: 3.1.0 resolution: "void-elements@npm:3.1.0" @@ -16854,15 +16179,6 @@ __metadata: languageName: node linkType: hard -"walker@npm:^1.0.8": - version: 1.0.8 - resolution: "walker@npm:1.0.8" - dependencies: - makeerror: "npm:1.0.12" - checksum: 10c0/a17e037bccd3ca8a25a80cb850903facdfed0de4864bd8728f1782370715d679fa72e0a0f5da7c1c1379365159901e5935f35be531229da53bbfc0efdabdb48e - languageName: node - linkType: hard - "watchpack@npm:^2.5.1": version: 2.5.1 resolution: "watchpack@npm:2.5.1" @@ -16894,10 +16210,10 @@ __metadata: languageName: node linkType: hard -"webidl-conversions@npm:^7.0.0": - version: 7.0.0 - resolution: "webidl-conversions@npm:7.0.0" - checksum: 10c0/228d8cb6d270c23b0720cb2d95c579202db3aaf8f633b4e9dd94ec2000a04e7e6e43b76a94509cdb30479bd00ae253ab2371a2da9f81446cc313f89a4213a2c4 +"webidl-conversions@npm:^8.0.1": + version: 8.0.1 + resolution: "webidl-conversions@npm:8.0.1" + checksum: 10c0/3f6f327ca5fa0c065ed8ed0ef3b72f33623376e68f958e9b7bd0df49fdb0b908139ac2338d19fb45bd0e05595bda96cb6d1622222a8b413daa38a17aacc4dd46 languageName: node linkType: hard @@ -17085,13 +16401,21 @@ __metadata: languageName: node linkType: hard -"whatwg-url@npm:^14.0.0, whatwg-url@npm:^14.1.1": - version: 14.2.0 - resolution: "whatwg-url@npm:14.2.0" +"whatwg-mimetype@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-mimetype@npm:5.0.0" + checksum: 10c0/eead164fe73a00dd82f817af6fc0bd22e9c273e1d55bf4bc6bdf2da7ad8127fca82ef00ea6a37892f5f5641f8e34128e09508f92126086baba126b9e0d57feb4 + languageName: node + linkType: hard + +"whatwg-url@npm:^16.0.0, whatwg-url@npm:^16.0.1": + version: 16.0.1 + resolution: "whatwg-url@npm:16.0.1" dependencies: - tr46: "npm:^5.1.0" - webidl-conversions: "npm:^7.0.0" - checksum: 10c0/f746fc2f4c906607d09537de1227b13f9494c171141e5427ed7d2c0dd0b6a48b43d8e71abaae57d368d0c06b673fd8ec63550b32ad5ed64990c7b0266c2b4272 + "@exodus/bytes": "npm:^1.11.0" + tr46: "npm:^6.0.0" + webidl-conversions: "npm:^8.0.1" + checksum: 10c0/e75565566abf3a2cdbd9f06c965dbcccee6ec4e9f0d3728ad5e08ceb9944279848bcaa211d35a29cb6d2df1e467dd05cfb59fbddf8a0adcd7d0bce9ffb703fd2 languageName: node linkType: hard @@ -17189,6 +16513,18 @@ __metadata: languageName: node linkType: hard +"why-is-node-running@npm:^2.3.0": + version: 2.3.0 + resolution: "why-is-node-running@npm:2.3.0" + dependencies: + siginfo: "npm:^2.0.0" + stackback: "npm:0.0.2" + bin: + why-is-node-running: cli.js + checksum: 10c0/1cde0b01b827d2cf4cb11db962f3958b9175d5d9e7ac7361d1a7b0e2dc6069a263e69118bd974c4f6d0a890ef4eedfe34cf3d5167ec14203dbc9a18620537054 + languageName: node + linkType: hard + "widest-line@npm:^2.0.0": version: 2.0.1 resolution: "widest-line@npm:2.0.1" @@ -17212,13 +16548,6 @@ __metadata: languageName: node linkType: hard -"wordwrap@npm:^1.0.0": - version: 1.0.0 - resolution: "wordwrap@npm:1.0.0" - checksum: 10c0/7ed2e44f3c33c5c3e3771134d2b0aee4314c9e49c749e37f464bf69f2bcdf0cbf9419ca638098e2717cff4875c47f56a007532f6111c3319f557a2ca91278e92 - languageName: node - linkType: hard - "workerpool@npm:^9.2.0": version: 9.3.4 resolution: "workerpool@npm:9.3.4" @@ -17277,16 +16606,6 @@ __metadata: languageName: node linkType: hard -"write-file-atomic@npm:^5.0.1": - version: 5.0.1 - resolution: "write-file-atomic@npm:5.0.1" - dependencies: - imurmurhash: "npm:^0.1.4" - signal-exit: "npm:^4.0.1" - checksum: 10c0/e8c850a8e3e74eeadadb8ad23c9d9d63e4e792bd10f4836ed74189ef6e996763959f1249c5650e232f3c77c11169d239cbfc8342fc70f3fe401407d23810505d - languageName: node - linkType: hard - "write-file-atomic@npm:^7.0.0": version: 7.0.1 resolution: "write-file-atomic@npm:7.0.1"