diff --git a/CNAME b/CNAME
deleted file mode 100644
index b35b671..0000000
--- a/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-dropout.hydroroll.team
diff --git a/README.CN.md b/README.CN.md
new file mode 100644
index 0000000..ff5cdd4
--- /dev/null
+++ b/README.CN.md
@@ -0,0 +1,142 @@
+# Drop*O*ut
+
+[](https://app.fossa.com/projects/git%2Bgithub.com%2FHsiangNianian%2FDropOut?ref=badge_small)
+[](https://github.com/pre-commit/pre-commit)
+[](https://results.pre-commit.ci/latest/github/HsiangNianian/DropOut/main)
+[](https://github.com/astral-sh/ruff)
+[](https://github.com/HydroRoll-Team/DropOut/actions/workflows/codeql.yml)
+[](https://github.com/HydroRoll-Team/DropOut/actions/workflows/dependabot/dependabot-updates)
+[](https://github.com/HydroRoll-Team/DropOut/actions/workflows/release.yml)
+[](https://github.com/HydroRoll-Team/DropOut/actions/workflows/test.yml)
+
+DropOut 是一个现代的、可重现的、开发者级别的 Minecraft 启动器。
+它不仅仅是为了启动 Minecraft 而设计的,而是将 Minecraft 环境作为确定性的、版本化的工作空间进行管理。
+
+使用 Tauri v2 和 Rust 构建,DropOut 提供原生性能和最小资源使用,并配有现代响应式 Web UI(目前使用 Svelte 5,正在迁移到 React)。
+
+> Minecraft 环境是一个复杂的系统。
+> DropOut 将它们视为软件项目。
+
+
+

+
+
+## 为什么选择 DropOut?
+
+大多数 Minecraft 启动器专注于让你进入游戏。
+DropOut 专注于保持你的游戏稳定、可调试和可重现。
+
+- 整合包昨天还能游玩,今天却坏了?
+→ DropOut 让它可追溯。
+
+- 分享模组包意味着压缩数 GB 的文件?
+→ DropOut 分享精确的依赖清单。
+
+- Java、加载器、模组、配置不同步?
+→ DropOut 将它们锁定在一起。
+
+这个启动器是为重视控制、透明度和长期稳定性的玩家构建的。
+
+## 功能特性
+
+- **高性能**:使用 Rust 和 Tauri 构建,实现最小资源使用和快速启动时间。
+- **现代工业 UI**:使用 **Svelte 5** 和 **Tailwind CSS 4** 设计的干净、无干扰界面。
+- **Microsoft 认证**:通过官方 Xbox Live 和 Microsoft OAuth 流程(设备代码流程)提供安全登录支持。
+- **模组加载器支持**:
+ - **Fabric**:内置安装程序和版本管理。
+ - **Forge**:支持安装和启动 Forge 版本。
+- **Java 管理**:
+ - 自动检测已安装的 Java 版本。
+ - 内置 Adoptium JDK/JRE 下载器。
+- **GitHub 集成**:直接从启动器主页查看最新的项目更新和变更日志。
+- **游戏管理**:
+ - 完整的版本隔离。
+ - 高效的并发资产和库下载。
+ - 可自定义的内存分配和分辨率设置。
+
+## 路线图
+
+- [X] **账户持久化** — 在会话之间保存登录状态
+- [X] **令牌刷新** — 自动刷新过期的 Microsoft 令牌
+- [X] **JVM 参数解析** — 完全支持 `arguments.jvm` 和 `arguments.game` 解析
+- [X] **Java 自动检测和下载** — 扫描系统并下载 Java 运行时
+- [X] **Fabric 加载器支持** — 使用 Fabric 安装和启动
+- [X] **Forge 加载器支持** — 使用 Forge 安装和启动
+- [X] **GitHub 发布集成** — 在应用内查看变更日志
+- [ ] **实例/配置文件系统** — 多个隔离的游戏目录,具有不同的版本/模组
+- [ ] **多账户支持** — 在多个账户之间无缝切换
+- [ ] **自定义游戏目录** — 允许用户选择游戏文件位置
+- [ ] **启动器自动更新** — 通过 Tauri 更新插件的自更新机制
+- [ ] **模组管理器** — 直接在启动器中启用/禁用模组
+- [ ] **从其他启动器导入** — MultiMC/Prism 配置的迁移工具
+
+## 安装
+
+从 [Releases](https://github.com/HsiangNianian/DropOut/releases) 页面下载适用于您平台的最新版本。
+
+| 平台 | 文件 |
+| -------------- | ----------------------- |
+| Linux x86_64 | `.deb`, `.AppImage` |
+| Linux ARM64 | `.deb`, `.AppImage` |
+| macOS ARM64 | `.dmg` |
+| Windows x86_64 | `.msi`, `.exe` |
+| Windows ARM64 | `.msi`, `.exe` |
+
+## 从源码构建
+
+### 先决条件
+
+1. **Rust**:从 [rustup.rs](https://rustup.rs/) 安装。
+2. **Node.js** 和 **pnpm**:用于前端依赖。
+3. **系统依赖**:按照您的操作系统遵循 [Tauri 先决条件](https://v2.tauri.app/start/prerequisites/)。
+
+### 步骤
+
+1. **克隆仓库**
+
+ ```bash
+ git clone https://github.com/HsiangNianian/DropOut.git
+ cd DropOut
+ ```
+2. **安装前端依赖**
+
+ ```bash
+ cd ui
+ pnpm install
+ cd ..
+ ```
+3. **运行开发模式**
+
+ ```bash
+ # 这将启动前端服务器和 Tauri 应用窗口
+ cargo tauri dev
+ ```
+4. **构建发布版本**
+
+ ```bash
+ cargo tauri build
+ ```
+
+ 可执行文件将位于 `src-tauri/target/release/`。
+
+## 贡献
+
+DropOut 以长期可维护性为目标构建。
+欢迎贡献,尤其在这些领域:
+- 实例系统设计
+- 模组兼容性工具
+- UI/UX 改进
+- 跨启动器迁移工具
+
+标准的 GitHub 工作流程适用:
+fork → 功能分支 → 拉取请求。
+
+
+## 许可证
+
+[](https://app.fossa.com/projects/git%2Bgithub.com%2FHsiangNianian%2FDropOut?ref=badge_shield&issueType=license)
+[](https://app.fossa.com/projects/git%2Bgithub.com%2FHsiangNianian%2FDropOut?ref=badge_shield&issueType=security)
+
+[](https://app.fossa.com/projects/git%2Bgithub.com%2FHsiangNianian%2FDropOut?ref=badge_large)
+
+根据 MIT 许可证分发。有关更多信息,请参见 `LICENSE`。
diff --git a/packages/docs/.gitignore b/packages/docs/.gitignore
new file mode 100644
index 0000000..8fa7200
--- /dev/null
+++ b/packages/docs/.gitignore
@@ -0,0 +1,7 @@
+.DS_Store
+/node_modules/
+
+# React Router
+/.react-router/
+/build/
+.source
diff --git a/packages/docs/README.md b/packages/docs/README.md
new file mode 100644
index 0000000..2b4c09a
--- /dev/null
+++ b/packages/docs/README.md
@@ -0,0 +1,14 @@
+# docs
+
+This is a React Router application generated with
+[Create Fumadocs](https://github.com/fuma-nama/fumadocs).
+
+Run development server:
+
+```bash
+npm run dev
+# or
+pnpm dev
+# or
+yarn dev
+```
diff --git a/packages/docs/app/app.css b/packages/docs/app/app.css
new file mode 100644
index 0000000..50b3bc2
--- /dev/null
+++ b/packages/docs/app/app.css
@@ -0,0 +1,3 @@
+@import 'tailwindcss';
+@import 'fumadocs-ui/css/neutral.css';
+@import 'fumadocs-ui/css/preset.css';
diff --git a/packages/docs/app/docs/page.tsx b/packages/docs/app/docs/page.tsx
new file mode 100644
index 0000000..2618989
--- /dev/null
+++ b/packages/docs/app/docs/page.tsx
@@ -0,0 +1,51 @@
+import type { Route } from './+types/page';
+import { DocsLayout } from 'fumadocs-ui/layouts/docs';
+import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page';
+import { source } from '@/lib/source';
+import defaultMdxComponents from 'fumadocs-ui/mdx';
+import browserCollections from 'fumadocs-mdx:collections/browser';
+import { baseOptions } from '@/lib/layout.shared';
+import { useFumadocsLoader } from 'fumadocs-core/source/client';
+
+export async function loader({ params }: Route.LoaderArgs) {
+ const slugs = params['*'].split('/').filter((v) => v.length > 0);
+ const page = source.getPage(slugs);
+ if (!page) throw new Response('Not found', { status: 404 });
+
+ return {
+ path: page.path,
+ pageTree: await source.serializePageTree(source.getPageTree()),
+ };
+}
+
+const clientLoader = browserCollections.docs.createClientLoader({
+ component(
+ { toc, frontmatter, default: Mdx },
+ // you can define props for the `` component
+ props?: {
+ className?: string;
+ },
+ ) {
+ return (
+
+ {frontmatter.title}
+
+ {frontmatter.title}
+ {frontmatter.description}
+
+
+
+
+ );
+ },
+});
+
+export default function Page({ loaderData }: Route.ComponentProps) {
+ const { path, pageTree } = useFumadocsLoader(loaderData);
+
+ return (
+
+ {clientLoader.useContent(path)}
+
+ );
+}
diff --git a/packages/docs/app/docs/search.ts b/packages/docs/app/docs/search.ts
new file mode 100644
index 0000000..9603c72
--- /dev/null
+++ b/packages/docs/app/docs/search.ts
@@ -0,0 +1,12 @@
+import type { Route } from './+types/search';
+import { createFromSource } from 'fumadocs-core/search/server';
+import { source } from '@/lib/source';
+
+const server = createFromSource(source, {
+ // https://docs.orama.com/docs/orama-js/supported-languages
+ language: 'english',
+});
+
+export async function loader({ request }: Route.LoaderArgs) {
+ return server.GET(request);
+}
diff --git a/packages/docs/app/lib/layout.shared.tsx b/packages/docs/app/lib/layout.shared.tsx
new file mode 100644
index 0000000..af2b6f0
--- /dev/null
+++ b/packages/docs/app/lib/layout.shared.tsx
@@ -0,0 +1,9 @@
+import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
+
+export function baseOptions(): BaseLayoutProps {
+ return {
+ nav: {
+ title: 'React Router',
+ },
+ };
+}
diff --git a/packages/docs/app/lib/source.ts b/packages/docs/app/lib/source.ts
new file mode 100644
index 0000000..97cf767
--- /dev/null
+++ b/packages/docs/app/lib/source.ts
@@ -0,0 +1,7 @@
+import { loader } from 'fumadocs-core/source';
+import { docs } from 'fumadocs-mdx:collections/server';
+
+export const source = loader({
+ source: docs.toFumadocsSource(),
+ baseUrl: '/docs',
+});
diff --git a/packages/docs/app/root.tsx b/packages/docs/app/root.tsx
new file mode 100644
index 0000000..08b8aa8
--- /dev/null
+++ b/packages/docs/app/root.tsx
@@ -0,0 +1,73 @@
+import {
+ isRouteErrorResponse,
+ Links,
+ Meta,
+ Outlet,
+ Scripts,
+ ScrollRestoration,
+} from 'react-router';
+import { RootProvider } from 'fumadocs-ui/provider/react-router';
+import type { Route } from './+types/root';
+import './app.css';
+
+export const links: Route.LinksFunction = () => [
+ { rel: 'preconnect', href: 'https://fonts.googleapis.com' },
+ {
+ rel: 'preconnect',
+ href: 'https://fonts.gstatic.com',
+ crossOrigin: 'anonymous',
+ },
+ {
+ rel: 'stylesheet',
+ href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
+ },
+];
+
+export function Layout({ children }: { children: React.ReactNode }) {
+ return (
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+ );
+}
+
+export default function App() {
+ return ;
+}
+
+export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
+ let message = 'Oops!';
+ let details = 'An unexpected error occurred.';
+ let stack: string | undefined;
+
+ if (isRouteErrorResponse(error)) {
+ message = error.status === 404 ? '404' : 'Error';
+ details =
+ error.status === 404 ? 'The requested page could not be found.' : error.statusText || details;
+ } else if (import.meta.env.DEV && error && error instanceof Error) {
+ details = error.message;
+ stack = error.stack;
+ }
+
+ return (
+
+ {message}
+ {details}
+ {stack && (
+
+ {stack}
+
+ )}
+
+ );
+}
diff --git a/packages/docs/app/routes.ts b/packages/docs/app/routes.ts
new file mode 100644
index 0000000..60dd630
--- /dev/null
+++ b/packages/docs/app/routes.ts
@@ -0,0 +1,7 @@
+import { index, route, type RouteConfig } from '@react-router/dev/routes';
+
+export default [
+ index('routes/home.tsx'),
+ route('docs/*', 'docs/page.tsx'),
+ route('api/search', 'docs/search.ts'),
+] satisfies RouteConfig;
diff --git a/packages/docs/app/routes/home.tsx b/packages/docs/app/routes/home.tsx
new file mode 100644
index 0000000..7f03ba9
--- /dev/null
+++ b/packages/docs/app/routes/home.tsx
@@ -0,0 +1,30 @@
+import type { Route } from './+types/home';
+import { HomeLayout } from 'fumadocs-ui/layouts/home';
+import { Link } from 'react-router';
+import { baseOptions } from '@/lib/layout.shared';
+
+export function meta({}: Route.MetaArgs) {
+ return [
+ { title: 'New React Router App' },
+ { name: 'description', content: 'Welcome to React Router!' },
+ ];
+}
+
+export default function Home() {
+ return (
+
+
+
Fumadocs on React Router.
+
+ The truly flexible docs framework on React.js.
+
+
+ Open Docs
+
+
+
+ );
+}
diff --git a/packages/docs/biome.json b/packages/docs/biome.json
new file mode 100644
index 0000000..a637e58
--- /dev/null
+++ b/packages/docs/biome.json
@@ -0,0 +1,37 @@
+{
+ "$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
+ "vcs": {
+ "enabled": true,
+ "clientKind": "git",
+ "useIgnoreFile": true
+ },
+ "files": {
+ "ignoreUnknown": true,
+ "includes": [
+ "**",
+ "!node_modules",
+ "!.source"
+ ]
+ },
+ "formatter": {
+ "enabled": true,
+ "indentStyle": "space",
+ "indentWidth": 2
+ },
+ "linter": {
+ "enabled": true,
+ "rules": {
+ "recommended": true
+ },
+ "domains": {
+ "react": "recommended"
+ }
+ },
+ "assist": {
+ "actions": {
+ "source": {
+ "organizeImports": "on"
+ }
+ }
+ }
+}
diff --git a/packages/docs/content/docs/index.mdx b/packages/docs/content/docs/index.mdx
new file mode 100644
index 0000000..6c2e629
--- /dev/null
+++ b/packages/docs/content/docs/index.mdx
@@ -0,0 +1,32 @@
+---
+title: Hello World
+description: |
+ Your first `document`
+ You'll love it!
+---
+
+Hey there! Fumadocs is the docs framework that also works on React Router!
+
+## Heading
+
+Hello World
+
+
+
+
+
+
+```ts
+console.log('I love React!');
+```
+
+### Heading
+
+#### Heading
+
+| Head | Description |
+| ------------------------------- | ----------------------------------- |
+| `hello` | Hello World |
+| very **important** | Hey |
+| _Surprisingly_ | Fumadocs |
+| very long text that looks weird | hello world hello world hello world |
diff --git a/packages/docs/content/docs/meta.json b/packages/docs/content/docs/meta.json
new file mode 100644
index 0000000..bc00362
--- /dev/null
+++ b/packages/docs/content/docs/meta.json
@@ -0,0 +1,3 @@
+{
+ "pages": ["index", "..."]
+}
diff --git a/packages/docs/content/docs/test.mdx b/packages/docs/content/docs/test.mdx
new file mode 100644
index 0000000..cac4d26
--- /dev/null
+++ b/packages/docs/content/docs/test.mdx
@@ -0,0 +1,24 @@
+---
+title: Test
+description: A document to test Fumadocs
+---
+
+Hey there!
+
+## Cards
+
+
+
+
+
+
+### CodeBlock
+
+```js
+console.log('Hello World');
+```
+
+#### List
+
+- Hello
+- World
diff --git a/packages/docs/package.json b/packages/docs/package.json
new file mode 100644
index 0000000..18a5bf3
--- /dev/null
+++ b/packages/docs/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "@dropout/docs",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "build": "react-router build",
+ "dev": "react-router dev",
+ "start": "react-router-serve ./build/server/index.js",
+ "types:check": "react-router typegen && fumadocs-mdx && tsc --noEmit",
+ "postinstall": "fumadocs-mdx",
+ "lint": "biome check",
+ "format": "biome format --write"
+ },
+ "dependencies": {
+ "@react-router/node": "^7.12.0",
+ "@react-router/serve": "^7.12.0",
+ "fumadocs-core": "16.4.7",
+ "fumadocs-mdx": "14.2.6",
+ "fumadocs-ui": "16.4.7",
+ "isbot": "^5.1.32",
+ "react": "^19.2.3",
+ "react-dom": "^19.2.3",
+ "react-router": "^7.12.0"
+ },
+ "devDependencies": {
+ "@react-router/dev": "^7.12.0",
+ "@tailwindcss/vite": "^4.1.18",
+ "@types/mdx": "^2.0.13",
+ "@types/node": "^25.0.5",
+ "@types/react": "^19.2.8",
+ "@types/react-dom": "^19.2.3",
+ "react-router-devtools": "^6.1.0",
+ "tailwindcss": "^4.1.18",
+ "typescript": "^5.9.3",
+ "vite": "^7.3.1",
+ "vite-tsconfig-paths": "^6.0.4",
+ "@biomejs/biome": "^2.3.11"
+ }
+}
diff --git a/packages/docs/public/favicon.ico b/packages/docs/public/favicon.ico
new file mode 100644
index 0000000..5dbdfcd
Binary files /dev/null and b/packages/docs/public/favicon.ico differ
diff --git a/packages/docs/react-router.config.ts b/packages/docs/react-router.config.ts
new file mode 100644
index 0000000..cfcfbe4
--- /dev/null
+++ b/packages/docs/react-router.config.ts
@@ -0,0 +1,23 @@
+import type { Config } from '@react-router/dev/config';
+import { glob } from 'node:fs/promises';
+import { createGetUrl, getSlugs } from 'fumadocs-core/source';
+
+const getUrl = createGetUrl('/docs');
+
+export default {
+ ssr: true,
+ async prerender({ getStaticPaths }) {
+ const paths: string[] = [];
+ const excluded: string[] = ['/api/search'];
+
+ for (const path of getStaticPaths()) {
+ if (!excluded.includes(path)) paths.push(path);
+ }
+
+ for await (const entry of glob('**/*.mdx', { cwd: 'content/docs' })) {
+ paths.push(getUrl(getSlugs(entry)));
+ }
+
+ return paths;
+ },
+} satisfies Config;
diff --git a/packages/docs/source.config.ts b/packages/docs/source.config.ts
new file mode 100644
index 0000000..0564068
--- /dev/null
+++ b/packages/docs/source.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig, defineDocs } from 'fumadocs-mdx/config';
+
+export const docs = defineDocs({
+ dir: 'content/docs',
+});
+
+export default defineConfig();
diff --git a/packages/docs/tsconfig.json b/packages/docs/tsconfig.json
new file mode 100644
index 0000000..717253d
--- /dev/null
+++ b/packages/docs/tsconfig.json
@@ -0,0 +1,23 @@
+{
+ "include": ["**/*", "**/.server/**/*", "**/.client/**/*", ".react-router/types/**/*"],
+ "compilerOptions": {
+ "lib": ["DOM", "DOM.Iterable", "ES2022"],
+ "types": ["node", "vite/client"],
+ "target": "esnext",
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "jsx": "react-jsx",
+ "rootDirs": [".", "./.react-router/types"],
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./app/*"],
+ "fumadocs-mdx:collections/*": [".source/*"]
+ },
+ "esModuleInterop": true,
+ "verbatimModuleSyntax": true,
+ "noEmit": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "strict": true
+ }
+}
diff --git a/packages/docs/vite.config.ts b/packages/docs/vite.config.ts
new file mode 100644
index 0000000..f408dc5
--- /dev/null
+++ b/packages/docs/vite.config.ts
@@ -0,0 +1,17 @@
+import { reactRouter } from '@react-router/dev/vite';
+import tailwindcss from '@tailwindcss/vite';
+import { defineConfig } from 'vite';
+import tsconfigPaths from 'vite-tsconfig-paths';
+import mdx from 'fumadocs-mdx/vite';
+import * as MdxConfig from './source.config';
+
+export default defineConfig({
+ plugins: [
+ mdx(MdxConfig),
+ tailwindcss(),
+ reactRouter(),
+ tsconfigPaths({
+ root: __dirname,
+ }),
+ ],
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5a86e4c..66255bd 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -34,6 +34,73 @@ importers:
specifier: ^4.21.0
version: 4.21.0
+ packages/docs:
+ dependencies:
+ '@react-router/node':
+ specifier: ^7.12.0
+ version: 7.12.0(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)
+ '@react-router/serve':
+ specifier: ^7.12.0
+ version: 7.12.0(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)
+ fumadocs-core:
+ specifier: 16.4.7
+ version: 16.4.7(@types/react@19.2.8)(lucide-react@0.562.0(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.3.5)
+ fumadocs-mdx:
+ specifier: 14.2.6
+ version: 14.2.6(@types/react@19.2.8)(fumadocs-core@16.4.7(@types/react@19.2.8)(lucide-react@0.562.0(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.3.5))(react@19.2.3)(rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0))
+ fumadocs-ui:
+ specifier: 16.4.7
+ version: 16.4.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(fumadocs-core@16.4.7(@types/react@19.2.8)(lucide-react@0.562.0(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.3.5))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)
+ isbot:
+ specifier: ^5.1.32
+ version: 5.1.33
+ react:
+ specifier: ^19.2.3
+ version: 19.2.3
+ react-dom:
+ specifier: ^19.2.3
+ version: 19.2.3(react@19.2.3)
+ react-router:
+ specifier: ^7.12.0
+ version: 7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ devDependencies:
+ '@biomejs/biome':
+ specifier: ^2.3.11
+ version: 2.3.11
+ '@react-router/dev':
+ specifier: ^7.12.0
+ version: 7.12.0(@react-router/serve@7.12.0(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3))(@types/node@25.0.9)(jiti@2.6.1)(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0))(tsx@4.21.0)(typescript@5.9.3)
+ '@tailwindcss/vite':
+ specifier: ^4.1.18
+ version: 4.1.18(rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0))
+ '@types/mdx':
+ specifier: ^2.0.13
+ version: 2.0.13
+ '@types/node':
+ specifier: ^25.0.5
+ version: 25.0.9
+ '@types/react':
+ specifier: ^19.2.8
+ version: 19.2.8
+ '@types/react-dom':
+ specifier: ^19.2.3
+ version: 19.2.3(@types/react@19.2.8)
+ react-router-devtools:
+ specifier: ^6.1.0
+ version: 6.2.0(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0))(solid-js@1.9.10)
+ tailwindcss:
+ specifier: ^4.1.18
+ version: 4.1.18
+ typescript:
+ specifier: ^5.9.3
+ version: 5.9.3
+ vite:
+ specifier: npm:rolldown-vite@^7
+ version: rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0)
+ vite-tsconfig-paths:
+ specifier: ^6.0.4
+ version: 6.0.4(rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0))(typescript@5.9.3)
+
packages/ui:
dependencies:
'@tauri-apps/api':
@@ -151,9 +218,6 @@ importers:
clsx:
specifier: ^2.1.1
version: 2.1.1
- dompurify:
- specifier: ^2.4.0
- version: 2.5.8
lucide-react:
specifier: ^0.562.0
version: 0.562.0(react@19.2.3)
@@ -231,14 +295,28 @@ packages:
resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-annotate-as-pure@7.27.3':
+ resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-compilation-targets@7.28.6':
resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-create-class-features-plugin@7.28.6':
+ resolution: {integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/helper-globals@7.28.0':
resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-member-expression-to-functions@7.28.5':
+ resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-module-imports@7.28.6':
resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==}
engines: {node: '>=6.9.0'}
@@ -249,10 +327,24 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/helper-optimise-call-expression@7.27.1':
+ resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-plugin-utils@7.28.6':
resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-replace-supers@7.28.6':
+ resolution: {integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
+ resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-string-parser@7.27.1':
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
engines: {node: '>=6.9.0'}
@@ -274,6 +366,24 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
+ '@babel/plugin-syntax-jsx@7.28.6':
+ resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-typescript@7.28.6':
+ resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-modules-commonjs@7.28.6':
+ resolution: {integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-react-jsx-self@7.27.1':
resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==}
engines: {node: '>=6.9.0'}
@@ -286,6 +396,22 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-typescript@7.28.6':
+ resolution: {integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/preset-typescript@7.28.5':
+ resolution: {integrity: sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/runtime@7.28.6':
+ resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==}
+ engines: {node: '>=6.9.0'}
+
'@babel/template@7.28.6':
resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
engines: {node: '>=6.9.0'}
@@ -351,6 +477,12 @@ packages:
cpu: [x64]
os: [win32]
+ '@bkrem/react-transition-group@1.3.5':
+ resolution: {integrity: sha512-lbBYhC42sxAeFEopxzd9oWdkkV0zirO5E9WyeOBxOrpXsf7m30Aj8vnbayZxFOwD9pvUQ2Pheb1gO79s0Qap3Q==}
+ peerDependencies:
+ react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
'@emnapi/core@1.8.1':
resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==}
@@ -531,6 +663,29 @@ packages:
'@floating-ui/utils@0.2.10':
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
+ '@formatjs/fast-memoize@3.0.3':
+ resolution: {integrity: sha512-CArYtQKGLAOruCMeq5/RxCg6vUXFx3OuKBdTm30Wn/+gCefehmZ8Y2xSMxMrO2iel7hRyE3HKfV56t3vAU6D4Q==}
+
+ '@formatjs/intl-localematcher@0.7.5':
+ resolution: {integrity: sha512-7/nd90cn5CT7SVF71/ybUKAcnvBlr9nZlJJp8O8xIZHXFgYOC4SXExZlSdgHv2l6utjw1byidL06QzChvQMHwA==}
+
+ '@fumadocs/ui@16.4.7':
+ resolution: {integrity: sha512-NnkMIN5BzBRh2OzA9rp2SgbGEkEwfCfq0sE4vq2n+GkIDIggicGYUNgSl2gtIBQsKYKP/a4/0wrkQKdq4eUJlw==}
+ peerDependencies:
+ '@types/react': '*'
+ fumadocs-core: 16.4.7
+ next: 16.x.x
+ react: ^19.2.0
+ react-dom: ^19.2.0
+ tailwindcss: ^4.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ next:
+ optional: true
+ tailwindcss:
+ optional: true
+
'@isaacs/balanced-match@4.0.1':
resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
engines: {node: 20 || >=22}
@@ -560,9 +715,19 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+ '@mdx-js/mdx@3.1.1':
+ resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==}
+
+ '@mjackson/node-fetch-server@0.2.0':
+ resolution: {integrity: sha512-EMlH1e30yzmTpGLQjlFmaDAjyOeZhng1/XCd7DExR8PNAnG/G1tyruZxEoUe11ClnwGhGrtsdnyyUx1frSzjng==}
+
'@napi-rs/wasm-runtime@1.1.1':
resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==}
+ '@orama/orama@3.1.18':
+ resolution: {integrity: sha512-a61ljmRVVyG5MC/698C8/FfFDw5a8LOIvyOLW5fztgUXqUpc1jOfQzOitSCbge657OgXXThmY3Tk8fpiDb4UcA==}
+ engines: {node: '>= 20.0.0'}
+
'@oxc-project/runtime@0.97.0':
resolution: {integrity: sha512-yH0zw7z+jEws4dZ4IUKoix5Lh3yhqIJWF9Dc8PWvhpo7U7O+lJrv7ZZL4BeRO0la8LBQFwcCewtLBnVV7hPe/w==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -656,6 +821,19 @@ packages:
'@radix-ui/primitive@1.1.3':
resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==}
+ '@radix-ui/react-accordion@1.2.12':
+ resolution: {integrity: sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-arrow@1.1.7':
resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==}
peerDependencies:
@@ -682,6 +860,19 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-collapsible@1.1.12':
+ resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-collection@1.1.7':
resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==}
peerDependencies:
@@ -792,6 +983,32 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-navigation-menu@1.2.14':
+ resolution: {integrity: sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-popover@1.1.15':
+ resolution: {integrity: sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-popper@1.2.8':
resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==}
peerDependencies:
@@ -1041,6 +1258,61 @@ packages:
'@radix-ui/rect@1.1.1':
resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==}
+ '@react-router/dev@7.12.0':
+ resolution: {integrity: sha512-5GpwXgq4pnOVeG7l6ADkCHA1rthJus1q/A3NRYJAIypclUQDYAzg1/fDNjvaKuTSrq+Nr3u6aj2v+oC+47MX6g==}
+ engines: {node: '>=20.0.0'}
+ hasBin: true
+ peerDependencies:
+ '@react-router/serve': ^7.12.0
+ '@vitejs/plugin-rsc': ~0.5.7
+ react-router: ^7.12.0
+ react-server-dom-webpack: ^19.2.3
+ typescript: ^5.1.0
+ vite: ^5.1.0 || ^6.0.0 || ^7.0.0
+ wrangler: ^3.28.2 || ^4.0.0
+ peerDependenciesMeta:
+ '@react-router/serve':
+ optional: true
+ '@vitejs/plugin-rsc':
+ optional: true
+ react-server-dom-webpack:
+ optional: true
+ typescript:
+ optional: true
+ wrangler:
+ optional: true
+
+ '@react-router/express@7.12.0':
+ resolution: {integrity: sha512-uAK+zF93M6XauGeXLh/UBh+3HrwiA/9lUS+eChjQ0a5FzjLpsc6ciUqF5oHh3lwWzLU7u7tj4qoeucUn6SInTw==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ express: ^4.17.1 || ^5
+ react-router: 7.12.0
+ typescript: ^5.1.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ '@react-router/node@7.12.0':
+ resolution: {integrity: sha512-o/t10Cse4LK8kFefqJ8JjC6Ng6YuKD2I87S2AiJs17YAYtXU5W731ZqB73AWyCDd2G14R0dSuqXiASRNK/xLjg==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ react-router: 7.12.0
+ typescript: ^5.1.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ '@react-router/serve@7.12.0':
+ resolution: {integrity: sha512-j1ltgU7s3wAwOosZ5oxgHSsmVyK706gY/yIs8qVmC239wQ3zr3eqaXk3TVVLMeRy+eDgPNmgc6oNJv2o328VgA==}
+ engines: {node: '>=20.0.0'}
+ hasBin: true
+ peerDependencies:
+ react-router: 7.12.0
+
+ '@remix-run/node-fetch-server@0.9.0':
+ resolution: {integrity: sha512-SoLMv7dbH+njWzXnOY6fI08dFMI5+/dQ+vY3n8RnnbdG7MdJEgiP28Xj/xWlnRnED/aB6SFw56Zop+LbmaaKqA==}
+
'@rolldown/binding-android-arm64@1.0.0-beta.50':
resolution: {integrity: sha512-XlEkrOIHLyGT3avOgzfTFSjG+f+dZMw+/qd+Y3HLN86wlndrB/gSimrJCk4gOhr1XtRtEKfszpadI3Md4Z4/Ag==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1130,10 +1402,80 @@ packages:
'@rolldown/pluginutils@1.0.0-beta.53':
resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==}
+ '@rollup/rollup-darwin-arm64@4.55.2':
+ resolution: {integrity: sha512-UCbaTklREjrc5U47ypLulAgg4njaqfOVLU18VrCrI+6E5MQjuG0lSWaqLlAJwsD7NpFV249XgB0Bi37Zh5Sz4g==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-linux-x64-gnu@4.55.2':
+ resolution: {integrity: sha512-1e30XAuaBP1MAizaOBApsgeGZge2/Byd6wV4a8oa6jPdHELbRHBiw7wvo4dp7Ie2PE8TZT4pj9RLGZv9N4qwlw==}
+ cpu: [x64]
+ os: [linux]
+
+ '@shikijs/core@3.21.0':
+ resolution: {integrity: sha512-AXSQu/2n1UIQekY8euBJlvFYZIw0PHY63jUzGbrOma4wPxzznJXTXkri+QcHeBNaFxiiOljKxxJkVSoB3PjbyA==}
+
+ '@shikijs/engine-javascript@3.21.0':
+ resolution: {integrity: sha512-ATwv86xlbmfD9n9gKRiwuPpWgPENAWCLwYCGz9ugTJlsO2kOzhOkvoyV/UD+tJ0uT7YRyD530x6ugNSffmvIiQ==}
+
+ '@shikijs/engine-oniguruma@3.21.0':
+ resolution: {integrity: sha512-OYknTCct6qiwpQDqDdf3iedRdzj6hFlOPv5hMvI+hkWfCKs5mlJ4TXziBG9nyabLwGulrUjHiCq3xCspSzErYQ==}
+
+ '@shikijs/langs@3.21.0':
+ resolution: {integrity: sha512-g6mn5m+Y6GBJ4wxmBYqalK9Sp0CFkUqfNzUy2pJglUginz6ZpWbaWjDB4fbQ/8SHzFjYbtU6Ddlp1pc+PPNDVA==}
+
+ '@shikijs/rehype@3.21.0':
+ resolution: {integrity: sha512-fTQvwsZL67QdosMFdTgQ5SNjW3nxaPplRy//312hqOctRbIwviTV0nAbhv3NfnztHXvFli2zLYNKsTz/f9tbpQ==}
+
+ '@shikijs/themes@3.21.0':
+ resolution: {integrity: sha512-BAE4cr9EDiZyYzwIHEk7JTBJ9CzlPuM4PchfcA5ao1dWXb25nv6hYsoDiBq2aZK9E3dlt3WB78uI96UESD+8Mw==}
+
+ '@shikijs/transformers@3.21.0':
+ resolution: {integrity: sha512-CZwvCWWIiRRiFk9/JKzdEooakAP8mQDtBOQ1TKiCaS2E1bYtyBCOkUzS8akO34/7ufICQ29oeSfkb3tT5KtrhA==}
+
+ '@shikijs/types@3.21.0':
+ resolution: {integrity: sha512-zGrWOxZ0/+0ovPY7PvBU2gIS9tmhSUUt30jAcNV0Bq0gb2S98gwfjIs1vxlmH5zM7/4YxLamT6ChlqqAJmPPjA==}
+
+ '@shikijs/vscode-textmate@10.0.2':
+ resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
+
'@sindresorhus/is@4.6.0':
resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
engines: {node: '>=10'}
+ '@solid-primitives/event-listener@2.4.3':
+ resolution: {integrity: sha512-h4VqkYFv6Gf+L7SQj+Y6puigL/5DIi7x5q07VZET7AWcS+9/G3WfIE9WheniHWJs51OEkRB43w6lDys5YeFceg==}
+ peerDependencies:
+ solid-js: ^1.6.12
+
+ '@solid-primitives/keyboard@1.3.3':
+ resolution: {integrity: sha512-9dQHTTgLBqyAI7aavtO+HnpTVJgWQA1ghBSrmLtMu1SMxLPDuLfuNr+Tk5udb4AL4Ojg7h9JrKOGEEDqsJXWJA==}
+ peerDependencies:
+ solid-js: ^1.6.12
+
+ '@solid-primitives/resize-observer@2.1.3':
+ resolution: {integrity: sha512-zBLje5E06TgOg93S7rGPldmhDnouNGhvfZVKOp+oG2XU8snA+GoCSSCz1M+jpNAg5Ek2EakU5UVQqL152WmdXQ==}
+ peerDependencies:
+ solid-js: ^1.6.12
+
+ '@solid-primitives/rootless@1.5.2':
+ resolution: {integrity: sha512-9HULb0QAzL2r47CCad0M+NKFtQ+LrGGNHZfteX/ThdGvKIg2o2GYhBooZubTCd/RTu2l2+Nw4s+dEfiDGvdrrQ==}
+ peerDependencies:
+ solid-js: ^1.6.12
+
+ '@solid-primitives/static-store@0.1.2':
+ resolution: {integrity: sha512-ReK+5O38lJ7fT+L6mUFvUr6igFwHBESZF+2Ug842s7fvlVeBdIVEdTCErygff6w7uR6+jrr7J8jQo+cYrEq4Iw==}
+ peerDependencies:
+ solid-js: ^1.6.12
+
+ '@solid-primitives/utils@6.3.2':
+ resolution: {integrity: sha512-hZ/M/qr25QOCcwDPOHtGjxTD8w2mNyVAYvcfgwzBHq2RwNqHNdDNsMZYap20+ruRwW4A3Cdkczyoz0TSxLCAPQ==}
+ peerDependencies:
+ solid-js: ^1.6.12
+
+ '@standard-schema/spec@1.1.0':
+ resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
+
'@sveltejs/acorn-typescript@1.0.8':
resolution: {integrity: sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA==}
peerDependencies:
@@ -1244,6 +1586,45 @@ packages:
peerDependencies:
vite: ^5.2.0 || ^6 || ^7
+ '@tanstack/devtools-client@0.0.5':
+ resolution: {integrity: sha512-hsNDE3iu4frt9cC2ppn1mNRnLKo2uc1/1hXAyY9z4UYb+o40M2clFAhiFoo4HngjfGJDV3x18KVVIq7W4Un+zA==}
+ engines: {node: '>=18'}
+
+ '@tanstack/devtools-event-bus@0.4.0':
+ resolution: {integrity: sha512-1t+/csFuDzi+miDxAOh6Xv7VDE80gJEItkTcAZLjV5MRulbO/W8ocjHLI2Do/p2r2/FBU0eKCRTpdqvXaYoHpQ==}
+ engines: {node: '>=18'}
+
+ '@tanstack/devtools-event-client@0.4.0':
+ resolution: {integrity: sha512-RPfGuk2bDZgcu9bAJodvO2lnZeHuz4/71HjZ0bGb/SPg8+lyTA+RLSKQvo7fSmPSi8/vcH3aKQ8EM9ywf1olaw==}
+ engines: {node: '>=18'}
+
+ '@tanstack/devtools-ui@0.4.4':
+ resolution: {integrity: sha512-5xHXFyX3nom0UaNfiOM92o6ziaHjGo3mcSGe2HD5Xs8dWRZNpdZ0Smd0B9ddEhy0oB+gXyMzZgUJb9DmrZV0Mg==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ solid-js: '>=1.9.7'
+
+ '@tanstack/devtools-vite@0.4.1':
+ resolution: {integrity: sha512-PkMOomcWnl/pUkCqIjqL/csjPHtkMVBirDpJVOZR7XJZDxo5CuD7B+3KsujFCF4Dsn6QYlae97gCZvxi/CB76Q==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ vite: ^6.0.0 || ^7.0.0
+
+ '@tanstack/devtools@0.10.3':
+ resolution: {integrity: sha512-M2HnKtaNf3Z8JDTNDq+X7/1gwOqSwTnCyC0GR+TYiRZM9mkY9GpvTqp6p6bx3DT8onu2URJiVxgHD9WK2e3MNQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ solid-js: '>=1.9.7'
+
+ '@tanstack/react-devtools@0.9.2':
+ resolution: {integrity: sha512-JNXvBO3jgq16GzTVm7p65n5zHNfMhnqF6Bm7CawjoqZrjEakxbM6Yvy63aKSIpbrdf+Wun2Xn8P0qD+vp56e1g==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@types/react': '>=16.8'
+ '@types/react-dom': '>=16.8'
+ react: '>=16.8'
+ react-dom: '>=16.8'
+
'@tauri-apps/api@2.9.1':
resolution: {integrity: sha512-IGlhP6EivjXHepbBic618GOmiWe4URJiIeZFlB7x3czM0yDHHYviH1Xvoiv4FefdkQtn6v7TuwWCRfOGdnVUGw==}
@@ -1345,12 +1726,36 @@ packages:
'@types/babel__traverse@7.28.0':
resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
+ '@types/d3-hierarchy@1.1.11':
+ resolution: {integrity: sha512-lnQiU7jV+Gyk9oQYk0GGYccuexmQPTp08E0+4BidgFdiJivjEvf+esPSdZqCZ2C7UwTWejWpqetVaU8A+eX3FA==}
+
+ '@types/debug@4.1.12':
+ resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
+
+ '@types/estree-jsx@1.0.5':
+ resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
+
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+ '@types/hast@3.0.4':
+ resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
+
+ '@types/mdast@4.0.4':
+ resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
+
+ '@types/mdx@2.0.13':
+ resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==}
+
+ '@types/ms@2.1.0':
+ resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
+
'@types/node@24.10.9':
resolution: {integrity: sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==}
+ '@types/node@25.0.9':
+ resolution: {integrity: sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==}
+
'@types/prismjs@1.26.5':
resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==}
@@ -1362,17 +1767,41 @@ packages:
'@types/react@19.2.8':
resolution: {integrity: sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==}
+ '@types/unist@2.0.11':
+ resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
+
+ '@types/unist@3.0.3':
+ resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
+
+ '@ungap/structured-clone@1.3.0':
+ resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
+
'@vitejs/plugin-react@5.1.2':
resolution: {integrity: sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==}
engines: {node: ^20.19.0 || >=22.12.0}
peerDependencies:
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
+ accepts@1.3.8:
+ resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
+ engines: {node: '>= 0.6'}
+
+ acorn-jsx@5.3.2:
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+
acorn@8.15.0:
resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
engines: {node: '>=0.4.0'}
hasBin: true
+ arg@5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+
+ argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
aria-hidden@1.2.6:
resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==}
engines: {node: '>=10'}
@@ -1381,6 +1810,13 @@ packages:
resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
engines: {node: '>= 0.4'}
+ array-flatten@1.1.1:
+ resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
+
+ astring@1.9.0:
+ resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
+ hasBin: true
+
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
@@ -1401,45 +1837,127 @@ packages:
resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
engines: {node: '>= 0.4'}
+ babel-dead-code-elimination@1.0.12:
+ resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==}
+
+ bail@2.0.2:
+ resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
+
baseline-browser-mapping@2.9.15:
resolution: {integrity: sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg==}
hasBin: true
+ basic-auth@2.0.1:
+ resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==}
+ engines: {node: '>= 0.8'}
+
+ body-parser@1.20.4:
+ resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==}
+ engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
+
browserslist@4.28.1:
resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
+ buffer-from@1.1.2:
+ resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+
+ bytes@3.1.2:
+ resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
+ engines: {node: '>= 0.8'}
+
+ cac@6.7.14:
+ resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
+ engines: {node: '>=8'}
+
call-bind-apply-helpers@1.0.2:
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
engines: {node: '>= 0.4'}
+ call-bound@1.0.4:
+ resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
+ engines: {node: '>= 0.4'}
+
caniuse-lite@1.0.30001764:
resolution: {integrity: sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==}
+ ccount@2.0.1:
+ resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
+
+ chain-function@1.0.1:
+ resolution: {integrity: sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg==}
+
+ chalk@5.6.2:
+ resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
+ engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+
char-regex@1.0.2:
resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
engines: {node: '>=10'}
+ character-entities-html4@2.1.0:
+ resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
+
+ character-entities-legacy@3.0.0:
+ resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
+
+ character-entities@2.0.2:
+ resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
+
+ character-reference-invalid@2.0.1:
+ resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
+
chokidar@4.0.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
+ chokidar@5.0.0:
+ resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
+ engines: {node: '>= 20.19.0'}
+
class-variance-authority@0.7.1:
resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
+ classnames@2.5.1:
+ resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==}
+
clone@1.0.4:
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
engines: {node: '>=0.8'}
+ clone@2.1.2:
+ resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==}
+ engines: {node: '>=0.8'}
+
clsx@2.1.1:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
+ collapse-white-space@2.1.0:
+ resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==}
+
combined-stream@1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
+ comma-separated-tokens@2.0.3:
+ resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
+
+ compressible@2.0.18:
+ resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==}
+ engines: {node: '>= 0.6'}
+
+ compression@1.8.1:
+ resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==}
+ engines: {node: '>= 0.8.0'}
+
+ compute-scroll-into-view@3.1.1:
+ resolution: {integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==}
+
+ confbox@0.2.2:
+ resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==}
+
consola@3.4.2:
resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
engines: {node: ^14.18.0 || >=16.10.0}
@@ -1448,16 +1966,91 @@ packages:
resolution: {integrity: sha512-dPyZofqggxuvSf7WXvNjuRfnsOk1YazkVP8FdxH4tcH2c37wc79/Yl6Bhr7Lsu00KMgy2ql/qCMuNu8xctZM8g==}
engines: {node: '> 0.10'}
- convert-source-map@2.0.0:
+ content-disposition@0.5.4:
+ resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
+ engines: {node: '>= 0.6'}
+
+ content-type@1.0.5:
+ resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
+ engines: {node: '>= 0.6'}
+
+ convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ cookie-signature@1.0.7:
+ resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==}
+
+ cookie@0.7.2:
+ resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
+ engines: {node: '>= 0.6'}
+
cookie@1.1.1:
resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==}
engines: {node: '>=18'}
+ cssesc@3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+ d3-color@3.1.0:
+ resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
+ engines: {node: '>=12'}
+
+ d3-dispatch@3.0.1:
+ resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==}
+ engines: {node: '>=12'}
+
+ d3-drag@3.0.0:
+ resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==}
+ engines: {node: '>=12'}
+
+ d3-ease@3.0.1:
+ resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
+ engines: {node: '>=12'}
+
+ d3-hierarchy@1.1.9:
+ resolution: {integrity: sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==}
+
+ d3-interpolate@3.0.1:
+ resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
+ engines: {node: '>=12'}
+
+ d3-path@1.0.9:
+ resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==}
+
+ d3-selection@3.0.0:
+ resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==}
+ engines: {node: '>=12'}
+
+ d3-shape@1.3.7:
+ resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==}
+
+ d3-timer@3.0.1:
+ resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
+ engines: {node: '>=12'}
+
+ d3-transition@3.0.1:
+ resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==}
+ engines: {node: '>=12'}
+ peerDependencies:
+ d3-selection: 2 - 3
+
+ d3-zoom@3.0.0:
+ resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==}
+ engines: {node: '>=12'}
+
+ debug@2.6.9:
+ resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
@@ -1467,6 +2060,17 @@ packages:
supports-color:
optional: true
+ decode-named-character-reference@1.3.0:
+ resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==}
+
+ dedent@1.7.1:
+ resolution: {integrity: sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==}
+ peerDependencies:
+ babel-plugin-macros: ^3.1.0
+ peerDependenciesMeta:
+ babel-plugin-macros:
+ optional: true
+
deepmerge@4.3.1:
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
engines: {node: '>=0.10.0'}
@@ -1478,6 +2082,18 @@ packages:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
+ depd@2.0.0:
+ resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
+ engines: {node: '>= 0.8'}
+
+ dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+
+ destroy@1.2.0:
+ resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
+ engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
+
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
@@ -1488,8 +2104,11 @@ packages:
devalue@5.6.2:
resolution: {integrity: sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==}
- dompurify@2.5.8:
- resolution: {integrity: sha512-o1vSNgrmYMQObbSSvF/1brBYEQPHhV1+gsmrusO7/GXtp1T9rCS8cXFqVxK/9crT1jA6Ccv+5MTSjBNqr7Sovw==}
+ devlop@1.1.0:
+ resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+
+ dom-helpers@3.4.0:
+ resolution: {integrity: sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==}
dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
@@ -1498,12 +2117,19 @@ packages:
easy-table@1.1.0:
resolution: {integrity: sha512-oq33hWOSSnl2Hoh00tZWaIPi1ievrD9aFG82/IgjlycAnW9hHx5PkJiXpxPsgEE+H7BsbVQXFVFST8TEXS6/pA==}
+ ee-first@1.1.1:
+ resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
+
electron-to-chromium@1.5.267:
resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==}
emojilib@2.4.0:
resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==}
+ encodeurl@2.0.0:
+ resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
+ engines: {node: '>= 0.8'}
+
enhanced-resolve@5.18.4:
resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==}
engines: {node: '>=10.13.0'}
@@ -1516,6 +2142,9 @@ packages:
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
engines: {node: '>= 0.4'}
+ es-module-lexer@1.7.0:
+ resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
+
es-object-atoms@1.1.1:
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
engines: {node: '>= 0.4'}
@@ -1524,6 +2153,12 @@ packages:
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
engines: {node: '>= 0.4'}
+ esast-util-from-estree@2.0.0:
+ resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==}
+
+ esast-util-from-js@2.0.1:
+ resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==}
+
esbuild@0.27.2:
resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==}
engines: {node: '>=18'}
@@ -1533,12 +2168,61 @@ packages:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
+ escape-html@1.0.3:
+ resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+
+ escape-string-regexp@5.0.0:
+ resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
+ engines: {node: '>=12'}
+
esm-env@1.2.2:
resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==}
esrap@2.2.1:
resolution: {integrity: sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg==}
+ estree-util-attach-comments@3.0.0:
+ resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==}
+
+ estree-util-build-jsx@3.0.1:
+ resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==}
+
+ estree-util-is-identifier-name@3.0.0:
+ resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
+
+ estree-util-scope@1.0.0:
+ resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==}
+
+ estree-util-to-js@2.0.0:
+ resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==}
+
+ estree-util-value-to-estree@3.5.0:
+ resolution: {integrity: sha512-aMV56R27Gv3QmfmF1MY12GWkGzzeAezAX+UplqHVASfjc9wNzI/X6hC0S9oxq61WT4aQesLGslWP9tKk6ghRZQ==}
+
+ estree-util-visit@2.0.0:
+ resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==}
+
+ estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+
+ etag@1.8.1:
+ resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
+ engines: {node: '>= 0.6'}
+
+ exit-hook@2.2.1:
+ resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==}
+ engines: {node: '>=6'}
+
+ express@4.22.1:
+ resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==}
+ engines: {node: '>= 0.10.0'}
+
+ exsolve@1.0.8:
+ resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
+
+ extend@3.0.2:
+ resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+
fdir@6.5.0:
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
engines: {node: '>=12.0.0'}
@@ -1548,6 +2232,10 @@ packages:
picomatch:
optional: true
+ finalhandler@1.3.2:
+ resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==}
+ engines: {node: '>= 0.8'}
+
follow-redirects@1.15.11:
resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==}
engines: {node: '>=4.0'}
@@ -1561,14 +2249,119 @@ packages:
resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==}
engines: {node: '>= 6'}
+ forwarded@0.2.0:
+ resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
+ engines: {node: '>= 0.6'}
+
fraction.js@5.3.4:
resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
+ framer-motion@12.27.1:
+ resolution: {integrity: sha512-cEAqO69kcZt3gL0TGua8WTgRQfv4J57nqt1zxHtLKwYhAwA0x9kDS/JbMa1hJbwkGY74AGJKvZ9pX/IqWZtZWQ==}
+ peerDependencies:
+ '@emotion/is-prop-valid': '*'
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@emotion/is-prop-valid':
+ optional: true
+ react:
+ optional: true
+ react-dom:
+ optional: true
+
+ fresh@0.5.2:
+ resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
+ engines: {node: '>= 0.6'}
+
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
+ fumadocs-core@16.4.7:
+ resolution: {integrity: sha512-oEsoha5EjyQnhRb6s5tNYEM+AiDA4BN80RyevRohsKPXGRQ2K3ddMaFAQq5kBaqA/Xxb+vqrElyRtzmdif7w2A==}
+ peerDependencies:
+ '@mixedbread/sdk': ^0.46.0
+ '@orama/core': 1.x.x
+ '@oramacloud/client': 2.x.x
+ '@tanstack/react-router': 1.x.x
+ '@types/react': '*'
+ algoliasearch: 5.x.x
+ lucide-react: '*'
+ next: 16.x.x
+ react: ^19.2.0
+ react-dom: ^19.2.0
+ react-router: 7.x.x
+ waku: ^0.26.0 || ^0.27.0
+ zod: 4.x.x
+ peerDependenciesMeta:
+ '@mixedbread/sdk':
+ optional: true
+ '@orama/core':
+ optional: true
+ '@oramacloud/client':
+ optional: true
+ '@tanstack/react-router':
+ optional: true
+ '@types/react':
+ optional: true
+ algoliasearch:
+ optional: true
+ lucide-react:
+ optional: true
+ next:
+ optional: true
+ react:
+ optional: true
+ react-dom:
+ optional: true
+ react-router:
+ optional: true
+ waku:
+ optional: true
+ zod:
+ optional: true
+
+ fumadocs-mdx@14.2.6:
+ resolution: {integrity: sha512-T8i5IllZ6OGaZ3/4Wwjl1zovvypSsr6Cco9ZACvoABLqpqTQ2TDfrW1nBt1o9YUKyfzkwDnjKdrnrq/nDexfcg==}
+ hasBin: true
+ peerDependencies:
+ '@fumadocs/mdx-remote': ^1.4.0
+ '@types/react': '*'
+ fumadocs-core: ^15.0.0 || ^16.0.0
+ next: ^15.3.0 || ^16.0.0
+ react: '*'
+ vite: 6.x.x || 7.x.x
+ peerDependenciesMeta:
+ '@fumadocs/mdx-remote':
+ optional: true
+ '@types/react':
+ optional: true
+ next:
+ optional: true
+ react:
+ optional: true
+ vite:
+ optional: true
+
+ fumadocs-ui@16.4.7:
+ resolution: {integrity: sha512-ShEftF54mj89EW7Wll2wwGcH6bNTmPrPtUUmO+ThakK13skJmY7GSBH3Ft51TzQNLhN3kBKEQipIlJWc7LT5NQ==}
+ peerDependencies:
+ '@types/react': '*'
+ fumadocs-core: 16.4.7
+ next: 16.x.x
+ react: ^19.2.0
+ react-dom: ^19.2.0
+ tailwindcss: ^4.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ next:
+ optional: true
+ tailwindcss:
+ optional: true
+
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
@@ -1584,6 +2377,10 @@ packages:
resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
engines: {node: '>=6'}
+ get-port@5.1.1:
+ resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==}
+ engines: {node: '>=8'}
+
get-proto@1.0.1:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'}
@@ -1591,6 +2388,9 @@ packages:
get-tsconfig@4.13.0:
resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==}
+ github-slugger@2.0.0:
+ resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==}
+
glob@13.0.0:
resolution: {integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==}
engines: {node: 20 || >=22}
@@ -1599,6 +2399,14 @@ packages:
resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==}
engines: {node: '>=18'}
+ globrex@0.1.2:
+ resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
+
+ goober@2.1.18:
+ resolution: {integrity: sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==}
+ peerDependencies:
+ csstype: ^3.0.10
+
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
@@ -1618,9 +2426,70 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
+ hast-util-to-estree@3.1.3:
+ resolution: {integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==}
+
+ hast-util-to-html@9.0.5:
+ resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}
+
+ hast-util-to-jsx-runtime@2.3.6:
+ resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
+
+ hast-util-to-string@3.0.1:
+ resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==}
+
+ hast-util-whitespace@3.0.0:
+ resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+
+ html-void-elements@3.0.0:
+ resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
+
+ http-errors@2.0.1:
+ resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
+ engines: {node: '>= 0.8'}
+
+ iconv-lite@0.4.24:
+ resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
+ engines: {node: '>=0.10.0'}
+
+ image-size@2.0.2:
+ resolution: {integrity: sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==}
+ engines: {node: '>=16.x'}
+ hasBin: true
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+ inline-style-parser@0.2.7:
+ resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
+
+ ipaddr.js@1.9.1:
+ resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
+ engines: {node: '>= 0.10'}
+
+ is-alphabetical@2.0.1:
+ resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
+
+ is-alphanumerical@2.0.1:
+ resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
+
+ is-decimal@2.0.1:
+ resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
+
+ is-hexadecimal@2.0.1:
+ resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
+
+ is-plain-obj@4.1.0:
+ resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
+ engines: {node: '>=12'}
+
is-reference@3.0.3:
resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==}
+ isbot@5.1.33:
+ resolution: {integrity: sha512-P4Hgb5NqswjkI0J1CM6XKXon/sxKY1SuowE7Qx2hrBhIwICFyXy54mfgB5eMHXsbe/eStzzpbIGNOvGmz+dlKg==}
+ engines: {node: '>=18'}
+
jiti@2.6.1:
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
hasBin: true
@@ -1628,8 +2497,12 @@ packages:
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
- jsesc@3.1.0:
- resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+ js-yaml@4.1.1:
+ resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
+ hasBin: true
+
+ jsesc@3.0.2:
+ resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==}
engines: {node: '>=6'}
hasBin: true
@@ -1638,6 +2511,9 @@ packages:
engines: {node: '>=6'}
hasBin: true
+ launch-editor@2.12.0:
+ resolution: {integrity: sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==}
+
lightningcss-android-arm64@1.30.2:
resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
engines: {node: '>= 12.0.0'}
@@ -1711,6 +2587,16 @@ packages:
locate-character@3.0.0:
resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==}
+ lodash@4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+
+ longest-streak@3.1.0:
+ resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
+
+ loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+
lru-cache@11.2.4:
resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==}
engines: {node: 20 || >=22}
@@ -1731,6 +2617,13 @@ packages:
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+ markdown-extensions@2.0.0:
+ resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==}
+ engines: {node: '>=16'}
+
+ markdown-table@3.0.4:
+ resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
+
marked@17.0.1:
resolution: {integrity: sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==}
engines: {node: '>= 20'}
@@ -1740,6 +2633,170 @@ packages:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
+ mdast-util-find-and-replace@3.0.2:
+ resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
+
+ mdast-util-from-markdown@2.0.2:
+ resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==}
+
+ mdast-util-gfm-autolink-literal@2.0.1:
+ resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==}
+
+ mdast-util-gfm-footnote@2.1.0:
+ resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==}
+
+ mdast-util-gfm-strikethrough@2.0.0:
+ resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}
+
+ mdast-util-gfm-table@2.0.0:
+ resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}
+
+ mdast-util-gfm-task-list-item@2.0.0:
+ resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}
+
+ mdast-util-gfm@3.1.0:
+ resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==}
+
+ mdast-util-mdx-expression@2.0.1:
+ resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
+
+ mdast-util-mdx-jsx@3.2.0:
+ resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
+
+ mdast-util-mdx@3.0.0:
+ resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==}
+
+ mdast-util-mdxjs-esm@2.0.1:
+ resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
+
+ mdast-util-phrasing@4.1.0:
+ resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
+
+ mdast-util-to-hast@13.2.1:
+ resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==}
+
+ mdast-util-to-markdown@2.1.2:
+ resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}
+
+ mdast-util-to-string@4.0.0:
+ resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
+
+ media-typer@0.3.0:
+ resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
+ engines: {node: '>= 0.6'}
+
+ merge-descriptors@1.0.3:
+ resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==}
+
+ methods@1.1.2:
+ resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
+ engines: {node: '>= 0.6'}
+
+ micromark-core-commonmark@2.0.3:
+ resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
+
+ micromark-extension-gfm-autolink-literal@2.1.0:
+ resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==}
+
+ micromark-extension-gfm-footnote@2.1.0:
+ resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==}
+
+ micromark-extension-gfm-strikethrough@2.1.0:
+ resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==}
+
+ micromark-extension-gfm-table@2.1.1:
+ resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==}
+
+ micromark-extension-gfm-tagfilter@2.0.0:
+ resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}
+
+ micromark-extension-gfm-task-list-item@2.1.0:
+ resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==}
+
+ micromark-extension-gfm@3.0.0:
+ resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
+
+ micromark-extension-mdx-expression@3.0.1:
+ resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==}
+
+ micromark-extension-mdx-jsx@3.0.2:
+ resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==}
+
+ micromark-extension-mdx-md@2.0.0:
+ resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==}
+
+ micromark-extension-mdxjs-esm@3.0.0:
+ resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==}
+
+ micromark-extension-mdxjs@3.0.0:
+ resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==}
+
+ micromark-factory-destination@2.0.1:
+ resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
+
+ micromark-factory-label@2.0.1:
+ resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
+
+ micromark-factory-mdx-expression@2.0.3:
+ resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==}
+
+ micromark-factory-space@2.0.1:
+ resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
+
+ micromark-factory-title@2.0.1:
+ resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==}
+
+ micromark-factory-whitespace@2.0.1:
+ resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==}
+
+ micromark-util-character@2.1.1:
+ resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
+
+ micromark-util-chunked@2.0.1:
+ resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==}
+
+ micromark-util-classify-character@2.0.1:
+ resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==}
+
+ micromark-util-combine-extensions@2.0.1:
+ resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==}
+
+ micromark-util-decode-numeric-character-reference@2.0.2:
+ resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==}
+
+ micromark-util-decode-string@2.0.1:
+ resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==}
+
+ micromark-util-encode@2.0.1:
+ resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
+
+ micromark-util-events-to-acorn@2.0.3:
+ resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==}
+
+ micromark-util-html-tag-name@2.0.1:
+ resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
+
+ micromark-util-normalize-identifier@2.0.1:
+ resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==}
+
+ micromark-util-resolve-all@2.0.1:
+ resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==}
+
+ micromark-util-sanitize-uri@2.0.1:
+ resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
+
+ micromark-util-subtokenize@2.1.0:
+ resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==}
+
+ micromark-util-symbol@2.0.1:
+ resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
+
+ micromark-util-types@2.0.2:
+ resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
+
+ micromark@4.0.2:
+ resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}
+
mime-db@1.52.0:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
@@ -1748,6 +2805,11 @@ packages:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
+ mime@1.6.0:
+ resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
+ engines: {node: '>=4'}
+ hasBin: true
+
minimatch@10.1.1:
resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==}
engines: {node: 20 || >=22}
@@ -1756,10 +2818,23 @@ packages:
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'}
+ morgan@1.10.1:
+ resolution: {integrity: sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==}
+ engines: {node: '>= 0.8.0'}
+
+ motion-dom@12.27.1:
+ resolution: {integrity: sha512-V/53DA2nBqKl9O2PMJleSUb/G0dsMMeZplZwgIQf5+X0bxIu7Q1cTv6DrjvTTGYRm3+7Y5wMlRZ1wT61boU/bQ==}
+
+ motion-utils@12.24.10:
+ resolution: {integrity: sha512-x5TFgkCIP4pPsRLpKoI86jv/q8t8FQOiM/0E8QKBzfMozWHfkKap2gA1hOki+B5g3IsBNpxbUnfOum1+dgvYww==}
+
mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
+ ms@2.0.0:
+ resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
+
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@@ -1768,6 +2843,18 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
+ negotiator@0.6.3:
+ resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
+ engines: {node: '>= 0.6'}
+
+ negotiator@0.6.4:
+ resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==}
+ engines: {node: '>= 0.6'}
+
+ negotiator@1.0.0:
+ resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
+ engines: {node: '>= 0.6'}
+
next-themes@0.4.6:
resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==}
peerDependencies:
@@ -1781,9 +2868,39 @@ packages:
node-releases@2.0.27:
resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
+ npm-to-yarn@3.0.1:
+ resolution: {integrity: sha512-tt6PvKu4WyzPwWUzy/hvPFqn+uwXO0K1ZHka8az3NnrhWJDmSqI8ncWq0fkL0k/lmmi5tAC11FXwXuh0rFbt1A==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ object-inspect@1.13.4:
+ resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
+ engines: {node: '>= 0.4'}
+
obug@2.1.1:
resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
+ on-finished@2.3.0:
+ resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==}
+ engines: {node: '>= 0.8'}
+
+ on-finished@2.4.1:
+ resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
+ engines: {node: '>= 0.8'}
+
+ on-headers@1.1.0:
+ resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==}
+ engines: {node: '>= 0.8'}
+
+ oniguruma-parser@0.12.1:
+ resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==}
+
+ oniguruma-to-es@4.3.4:
+ resolution: {integrity: sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==}
+
oxfmt@0.24.0:
resolution: {integrity: sha512-UjeM3Peez8Tl7IJ9s5UwAoZSiDRMww7BEc21gDYxLq3S3/KqJnM3mjNxsoSHgmBvSeX6RBhoVc2MfC/+96RdSw==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1799,13 +2916,36 @@ packages:
oxlint-tsgolint:
optional: true
+ p-map@7.0.4:
+ resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==}
+ engines: {node: '>=18'}
+
package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
- path-scurry@2.0.1:
- resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==}
+ parse-entities@4.0.2:
+ resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
+
+ parseurl@1.3.3:
+ resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
+ engines: {node: '>= 0.8'}
+
+ path-scurry@2.0.1:
+ resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==}
engines: {node: 20 || >=22}
+ path-to-regexp@0.1.12:
+ resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==}
+
+ path-to-regexp@8.3.0:
+ resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==}
+
+ pathe@1.1.2:
+ resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
+
+ pathe@2.0.3:
+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -1813,6 +2953,13 @@ packages:
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
engines: {node: '>=12'}
+ pkg-types@2.3.0:
+ resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==}
+
+ postcss-selector-parser@7.1.1:
+ resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==}
+ engines: {node: '>=4'}
+
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
@@ -1820,18 +2967,73 @@ packages:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
+ prettier@3.8.0:
+ resolution: {integrity: sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==}
+ engines: {node: '>=14'}
+ hasBin: true
+
prismjs@1.30.0:
resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
engines: {node: '>=6'}
+ prop-types@15.8.1:
+ resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+
+ property-information@7.1.0:
+ resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
+
+ proxy-addr@2.0.7:
+ resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
+ engines: {node: '>= 0.10'}
+
proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+ qs@6.14.1:
+ resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==}
+ engines: {node: '>=0.6'}
+
+ range-parser@1.2.1:
+ resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
+ engines: {node: '>= 0.6'}
+
+ raw-body@2.5.3:
+ resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==}
+ engines: {node: '>= 0.8'}
+
+ react-d3-tree@3.6.6:
+ resolution: {integrity: sha512-E9ByUdeqvlxLlF9BSL7KWQH3ikYHtHO+g1rAPcVgj6mu92tjRUCan2AWxoD4eTSzzAATf8BZtf+CXGSoSd6ioQ==}
+ peerDependencies:
+ react: 16.x || 17.x || 18.x || 19.x
+ react-dom: 16.x || 17.x || 18.x || 19.x
+
react-dom@19.2.3:
resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==}
peerDependencies:
react: ^19.2.3
+ react-hotkeys-hook@5.2.3:
+ resolution: {integrity: sha512-Q27F8EuImYJOVSXAjSQrQPj9cx4GSNY+WdSdk5tSNN085H8/a00W6LZp0PrytEDwF6iT0pGTJeVEDKPRpEK2Bg==}
+ peerDependencies:
+ react: '>=16.8.0'
+ react-dom: '>=16.8.0'
+
+ react-is@16.13.1:
+ resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
+
+ react-lifecycles-compat@3.0.4:
+ resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==}
+
+ react-medium-image-zoom@5.4.0:
+ resolution: {integrity: sha512-BsE+EnFVQzFIlyuuQrZ9iTwyKpKkqdFZV1ImEQN573QPqGrIUuNni7aF+sZwDcxlsuOMayCr6oO/PZR/yJnbRg==}
+ peerDependencies:
+ 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
+
+ react-refresh@0.14.2:
+ resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
+ engines: {node: '>=0.10.0'}
+
react-refresh@0.18.0:
resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==}
engines: {node: '>=0.10.0'}
@@ -1856,6 +3058,16 @@ packages:
'@types/react':
optional: true
+ react-router-devtools@6.2.0:
+ resolution: {integrity: sha512-YzaFAyKZEtTmWzBF/moKuMtEa8Hd/xhTtUCKarrhAbZMyR8S0OpCpN0pyKrNGNz7ueOc4jvvKdE9S6Q3UTotDg==}
+ peerDependencies:
+ '@types/react': '>=17'
+ '@types/react-dom': '>=17'
+ react: '>=17'
+ react-dom: '>=17'
+ react-router: '>=7.0.0'
+ vite: '>=5.0.0 || >=6.0.0'
+
react-router@7.12.0:
resolution: {integrity: sha512-kTPDYPFzDVGIIGNLS5VJykK0HfHLY5MF3b+xj0/tTyNYL1gF1qs7u67Z9jEhQk2sQ98SUaHxlG31g1JtF7IfVw==}
engines: {node: '>=20.0.0'}
@@ -1876,6 +3088,12 @@ packages:
'@types/react':
optional: true
+ react-tooltip@5.30.0:
+ resolution: {integrity: sha512-Yn8PfbgQ/wmqnL7oBpz1QiDaLKrzZMdSUUdk7nVeGTwzbxCAJiJzR4VSYW+eIO42F1INt57sPUmpgKv0KwJKtg==}
+ peerDependencies:
+ react: '>=16.14.0'
+ react-dom: '>=16.14.0'
+
react@19.2.3:
resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==}
engines: {node: '>=0.10.0'}
@@ -1884,6 +3102,54 @@ packages:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
+ readdirp@5.0.0:
+ resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
+ engines: {node: '>= 20.19.0'}
+
+ recma-build-jsx@1.0.0:
+ resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==}
+
+ recma-jsx@1.0.1:
+ resolution: {integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+
+ recma-parse@1.0.0:
+ resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==}
+
+ recma-stringify@1.0.0:
+ resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==}
+
+ regex-recursion@6.0.2:
+ resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}
+
+ regex-utilities@2.3.0:
+ resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==}
+
+ regex@6.1.0:
+ resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==}
+
+ rehype-recma@1.0.0:
+ resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==}
+
+ remark-gfm@4.0.1:
+ resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
+
+ remark-mdx@3.1.1:
+ resolution: {integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==}
+
+ remark-parse@11.0.0:
+ resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
+
+ remark-rehype@11.1.2:
+ resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
+
+ remark-stringify@11.0.0:
+ resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
+
+ remark@15.0.1:
+ resolution: {integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==}
+
resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
@@ -1941,20 +3207,84 @@ packages:
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
engines: {node: '>=6'}
+ safe-buffer@5.1.2:
+ resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
+
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
+ safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
+ scroll-into-view-if-needed@3.1.0:
+ resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==}
+
semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
+ semver@7.7.3:
+ resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ send@0.19.2:
+ resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==}
+ engines: {node: '>= 0.8.0'}
+
+ seroval-plugins@1.3.3:
+ resolution: {integrity: sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ seroval: ^1.0
+
+ seroval@1.3.2:
+ resolution: {integrity: sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==}
+ engines: {node: '>=10'}
+
+ serve-static@1.16.3:
+ resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==}
+ engines: {node: '>= 0.8.0'}
+
set-cookie-parser@2.7.2:
resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
+ setprototypeof@1.2.0:
+ resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
+
+ shell-quote@1.8.3:
+ resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==}
+ engines: {node: '>= 0.4'}
+
+ shiki@3.21.0:
+ resolution: {integrity: sha512-N65B/3bqL/TI2crrXr+4UivctrAGEjmsib5rPMMPpFp1xAx/w03v8WZ9RDDFYteXoEgY7qZ4HGgl5KBIu1153w==}
+
+ side-channel-list@1.0.0:
+ resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-map@1.0.1:
+ resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-weakmap@1.0.2:
+ resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
+ engines: {node: '>= 0.4'}
+
+ side-channel@1.1.0:
+ resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
+ engines: {node: '>= 0.4'}
+
skin-tone@2.0.0:
resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==}
engines: {node: '>=8'}
+ solid-js@1.9.10:
+ resolution: {integrity: sha512-Coz956cos/EPDlhs6+jsdTxKuJDPT7B5SVIWgABwROyxjY7Xbr8wkzD68Et+NxnV7DLJ3nJdAC2r9InuV/4Jew==}
+
sonner@2.0.7:
resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==}
peerDependencies:
@@ -1965,6 +3295,33 @@ packages:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
+ source-map-support@0.5.21:
+ resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+
+ source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+
+ source-map@0.7.6:
+ resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
+ engines: {node: '>= 12'}
+
+ space-separated-tokens@2.0.2:
+ resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
+
+ statuses@2.0.2:
+ resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
+ engines: {node: '>= 0.8'}
+
+ stringify-entities@4.0.4:
+ resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
+
+ style-to-js@1.1.21:
+ resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==}
+
+ style-to-object@1.0.14:
+ resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
+
svelte-check@4.3.5:
resolution: {integrity: sha512-e4VWZETyXaKGhpkxOXP+B/d0Fp/zKViZoJmneZWe/05Y2aqSKj3YN2nLfYPJBQ87WEiY4BQCQ9hWGu9mPT1a1Q==}
engines: {node: '>= 18.0.0'}
@@ -1987,6 +3344,10 @@ packages:
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
engines: {node: '>=6'}
+ tinyexec@1.0.2:
+ resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==}
+ engines: {node: '>=18'}
+
tinyglobby@0.2.15:
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
engines: {node: '>=12.0.0'}
@@ -1995,9 +3356,29 @@ packages:
resolution: {integrity: sha512-/RX9RzeH2xU5ADE7n2Ykvmi9ED3FBGPAjw9u3zucrNNaEBIO0HPSYgL0NT7+3p147ojeSdaVu08F6hjpv31HJg==}
engines: {node: ^20.0.0 || >=22.0.0}
+ toidentifier@1.0.1:
+ resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
+ engines: {node: '>=0.6'}
+
toml@3.0.0:
resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==}
+ trim-lines@3.0.1:
+ resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
+
+ trough@2.2.0:
+ resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
+
+ tsconfck@3.1.6:
+ resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==}
+ engines: {node: ^18 || >=20}
+ hasBin: true
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@@ -2013,6 +3394,10 @@ packages:
tw-animate-css@1.4.0:
resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==}
+ type-is@1.6.18:
+ resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
+ engines: {node: '>= 0.6'}
+
typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
@@ -2025,6 +3410,34 @@ packages:
resolution: {integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==}
engines: {node: '>=4'}
+ unified@11.0.5:
+ resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
+
+ unist-util-is@6.0.1:
+ resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
+
+ unist-util-position-from-estree@2.0.0:
+ resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==}
+
+ unist-util-position@5.0.0:
+ resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
+
+ unist-util-remove-position@5.0.0:
+ resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==}
+
+ unist-util-stringify-position@4.0.0:
+ resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+
+ unist-util-visit-parents@6.0.2:
+ resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
+
+ unist-util-visit@5.0.0:
+ resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
+
+ unpipe@1.0.0:
+ resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
+ engines: {node: '>= 0.8'}
+
update-browserslist-db@1.2.3:
resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
hasBin: true
@@ -2051,6 +3464,48 @@ packages:
'@types/react':
optional: true
+ util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+ utils-merge@1.0.1:
+ resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
+ engines: {node: '>= 0.4.0'}
+
+ uuid@8.3.2:
+ resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
+ hasBin: true
+
+ valibot@1.2.0:
+ resolution: {integrity: sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==}
+ peerDependencies:
+ typescript: '>=5'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ vary@1.1.2:
+ resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
+ engines: {node: '>= 0.8'}
+
+ vfile-message@4.0.3:
+ resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
+
+ vfile@6.0.3:
+ resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
+
+ vite-node@3.2.4:
+ resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+
+ vite-tsconfig-paths@6.0.4:
+ resolution: {integrity: sha512-iIsEJ+ek5KqRTK17pmxtgIxXtqr3qDdE6OxrP9mVeGhVDNXRJTKN/l9oMbujTQNzMLe6XZ8qmpztfbkPu2TiFQ==}
+ peerDependencies:
+ vite: '*'
+ peerDependenciesMeta:
+ vite:
+ optional: true
+
vitefu@1.1.1:
resolution: {integrity: sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==}
peerDependencies:
@@ -2059,15 +3514,33 @@ packages:
vite:
optional: true
+ warning@3.0.0:
+ resolution: {integrity: sha512-jMBt6pUrKn5I+OGgtQ4YZLdhIeJmObddh6CsibPxyQ5yPZm1XExSyzC1LCNX7BzhxWgiHmizBWJTHJIjMjTQYQ==}
+
wcwidth@1.0.1:
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
+ ws@8.19.0:
+ resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
zimmerframe@1.1.4:
resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==}
+ zod@4.3.5:
+ resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==}
+
zustand@5.0.10:
resolution: {integrity: sha512-U1AiltS1O9hSy3rul+Ub82ut2fqIAefiSuwECWt6jlMVUGejvf+5omLcRBSzqbRagSM3hQZbtzdeRc6QVScXTg==}
engines: {node: '>=12.20.0'}
@@ -2086,6 +3559,9 @@ packages:
use-sync-external-store:
optional: true
+ zwitch@2.0.4:
+ resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
+
snapshots:
'@babel/code-frame@7.28.6':
@@ -2122,7 +3598,11 @@ snapshots:
'@babel/types': 7.28.6
'@jridgewell/gen-mapping': 0.3.13
'@jridgewell/trace-mapping': 0.3.31
- jsesc: 3.1.0
+ jsesc: 3.0.2
+
+ '@babel/helper-annotate-as-pure@7.27.3':
+ dependencies:
+ '@babel/types': 7.28.6
'@babel/helper-compilation-targets@7.28.6':
dependencies:
@@ -2132,8 +3612,28 @@ snapshots:
lru-cache: 5.1.1
semver: 6.3.1
+ '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/helper-member-expression-to-functions': 7.28.5
+ '@babel/helper-optimise-call-expression': 7.27.1
+ '@babel/helper-replace-supers': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+ '@babel/traverse': 7.28.6
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/helper-globals@7.28.0': {}
+ '@babel/helper-member-expression-to-functions@7.28.5':
+ dependencies:
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/helper-module-imports@7.28.6':
dependencies:
'@babel/traverse': 7.28.6
@@ -2150,8 +3650,28 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/helper-optimise-call-expression@7.27.1':
+ dependencies:
+ '@babel/types': 7.28.6
+
'@babel/helper-plugin-utils@7.28.6': {}
+ '@babel/helper-replace-supers@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-member-expression-to-functions': 7.28.5
+ '@babel/helper-optimise-call-expression': 7.27.1
+ '@babel/traverse': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
+ dependencies:
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/helper-string-parser@7.27.1': {}
'@babel/helper-validator-identifier@7.28.5': {}
@@ -2167,6 +3687,24 @@ snapshots:
dependencies:
'@babel/types': 7.28.6
+ '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.6)':
dependencies:
'@babel/core': 7.28.6
@@ -2177,6 +3715,30 @@ snapshots:
'@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.28.6
+ '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+ '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/preset-typescript@7.28.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-validator-option': 7.27.1
+ '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/runtime@7.28.6': {}
+
'@babel/template@7.28.6':
dependencies:
'@babel/code-frame': 7.28.6
@@ -2235,6 +3797,17 @@ snapshots:
'@biomejs/cli-win32-x64@2.3.11':
optional: true
+ '@bkrem/react-transition-group@1.3.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ chain-function: 1.0.1
+ dom-helpers: 3.4.0
+ loose-envify: 1.4.0
+ prop-types: 15.8.1
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ react-lifecycles-compat: 3.0.4
+ warning: 3.0.0
+
'@emnapi/core@1.8.1':
dependencies:
'@emnapi/wasi-threads': 1.1.0
@@ -2346,6 +3919,27 @@ snapshots:
'@floating-ui/utils@0.2.10': {}
+ '@formatjs/fast-memoize@3.0.3':
+ dependencies:
+ tslib: 2.8.1
+
+ '@formatjs/intl-localematcher@0.7.5':
+ dependencies:
+ '@formatjs/fast-memoize': 3.0.3
+ tslib: 2.8.1
+
+ '@fumadocs/ui@16.4.7(@types/react@19.2.8)(fumadocs-core@16.4.7(@types/react@19.2.8)(lucide-react@0.562.0(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.3.5))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)':
+ dependencies:
+ fumadocs-core: 16.4.7(@types/react@19.2.8)(lucide-react@0.562.0(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.3.5)
+ next-themes: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ postcss-selector-parser: 7.1.1
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ tailwind-merge: 3.4.0
+ optionalDependencies:
+ '@types/react': 19.2.8
+ tailwindcss: 4.1.18
+
'@isaacs/balanced-match@4.0.1': {}
'@isaacs/brace-expansion@5.0.0':
@@ -2381,6 +3975,38 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
+ '@mdx-js/mdx@3.1.1':
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdx': 2.0.13
+ acorn: 8.15.0
+ collapse-white-space: 2.1.0
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ estree-util-scope: 1.0.0
+ estree-walker: 3.0.3
+ hast-util-to-jsx-runtime: 2.3.6
+ markdown-extensions: 2.0.0
+ recma-build-jsx: 1.0.0
+ recma-jsx: 1.0.1(acorn@8.15.0)
+ recma-stringify: 1.0.0
+ rehype-recma: 1.0.0
+ remark-mdx: 3.1.1
+ remark-parse: 11.0.0
+ remark-rehype: 11.1.2
+ source-map: 0.7.6
+ unified: 11.0.5
+ unist-util-position-from-estree: 2.0.0
+ unist-util-stringify-position: 4.0.0
+ unist-util-visit: 5.0.0
+ vfile: 6.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@mjackson/node-fetch-server@0.2.0': {}
+
'@napi-rs/wasm-runtime@1.1.1':
dependencies:
'@emnapi/core': 1.8.1
@@ -2388,6 +4014,8 @@ snapshots:
'@tybys/wasm-util': 0.10.1
optional: true
+ '@orama/orama@3.1.18': {}
+
'@oxc-project/runtime@0.97.0': {}
'@oxc-project/types@0.97.0': {}
@@ -2444,6 +4072,23 @@ snapshots:
'@radix-ui/primitive@1.1.3': {}
+ '@radix-ui/react-accordion@1.2.12(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
'@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
dependencies:
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -2469,19 +4114,35 @@ snapshots:
'@types/react': 19.2.8
'@types/react-dom': 19.2.3(@types/react@19.2.8)
- '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
dependencies:
+ '@radix-ui/primitive': 1.1.3
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
'@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-slot': 1.2.3(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
optionalDependencies:
'@types/react': 19.2.8
'@types/react-dom': 19.2.3(@types/react@19.2.8)
- '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.8)(react@19.2.3)':
+ '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-slot': 1.2.3(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.8)(react@19.2.3)':
dependencies:
react: 19.2.3
optionalDependencies:
@@ -2567,6 +4228,51 @@ snapshots:
'@types/react': 19.2.8
'@types/react-dom': 19.2.3(@types/react@19.2.8)
+ '@radix-ui/react-navigation-menu@1.2.14(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-slot': 1.2.3(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3)
+ aria-hidden: 1.2.6
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ react-remove-scroll: 2.7.2(@types/react@19.2.8)(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
'@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
dependencies:
'@floating-ui/react-dom': 2.1.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -2805,6 +4511,88 @@ snapshots:
'@radix-ui/rect@1.1.1': {}
+ '@react-router/dev@7.12.0(@react-router/serve@7.12.0(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3))(@types/node@25.0.9)(jiti@2.6.1)(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0))(tsx@4.21.0)(typescript@5.9.3)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.28.6)
+ '@babel/preset-typescript': 7.28.5(@babel/core@7.28.6)
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ '@react-router/node': 7.12.0(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)
+ '@remix-run/node-fetch-server': 0.9.0
+ arg: 5.0.2
+ babel-dead-code-elimination: 1.0.12
+ chokidar: 4.0.3
+ dedent: 1.7.1
+ es-module-lexer: 1.7.0
+ exit-hook: 2.2.1
+ isbot: 5.1.33
+ jsesc: 3.0.2
+ lodash: 4.17.21
+ p-map: 7.0.4
+ pathe: 1.1.2
+ picocolors: 1.1.1
+ pkg-types: 2.3.0
+ prettier: 3.8.0
+ react-refresh: 0.14.2
+ react-router: 7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ semver: 7.7.3
+ tinyglobby: 0.2.15
+ valibot: 1.2.0(typescript@5.9.3)
+ vite: rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0)
+ vite-node: 3.2.4(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0)
+ optionalDependencies:
+ '@react-router/serve': 7.12.0(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - '@types/node'
+ - babel-plugin-macros
+ - esbuild
+ - jiti
+ - less
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
+ '@react-router/express@7.12.0(express@4.22.1)(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)':
+ dependencies:
+ '@react-router/node': 7.12.0(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)
+ express: 4.22.1
+ react-router: 7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ optionalDependencies:
+ typescript: 5.9.3
+
+ '@react-router/node@7.12.0(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)':
+ dependencies:
+ '@mjackson/node-fetch-server': 0.2.0
+ react-router: 7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ optionalDependencies:
+ typescript: 5.9.3
+
+ '@react-router/serve@7.12.0(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)':
+ dependencies:
+ '@mjackson/node-fetch-server': 0.2.0
+ '@react-router/express': 7.12.0(express@4.22.1)(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)
+ '@react-router/node': 7.12.0(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)
+ compression: 1.8.1
+ express: 4.22.1
+ get-port: 5.1.1
+ morgan: 1.10.1
+ react-router: 7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ source-map-support: 0.5.21
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+
+ '@remix-run/node-fetch-server@0.9.0': {}
+
'@rolldown/binding-android-arm64@1.0.0-beta.50':
optional: true
@@ -2853,8 +4641,97 @@ snapshots:
'@rolldown/pluginutils@1.0.0-beta.53': {}
+ '@rollup/rollup-darwin-arm64@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.55.2':
+ optional: true
+
+ '@shikijs/core@3.21.0':
+ dependencies:
+ '@shikijs/types': 3.21.0
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+ hast-util-to-html: 9.0.5
+
+ '@shikijs/engine-javascript@3.21.0':
+ dependencies:
+ '@shikijs/types': 3.21.0
+ '@shikijs/vscode-textmate': 10.0.2
+ oniguruma-to-es: 4.3.4
+
+ '@shikijs/engine-oniguruma@3.21.0':
+ dependencies:
+ '@shikijs/types': 3.21.0
+ '@shikijs/vscode-textmate': 10.0.2
+
+ '@shikijs/langs@3.21.0':
+ dependencies:
+ '@shikijs/types': 3.21.0
+
+ '@shikijs/rehype@3.21.0':
+ dependencies:
+ '@shikijs/types': 3.21.0
+ '@types/hast': 3.0.4
+ hast-util-to-string: 3.0.1
+ shiki: 3.21.0
+ unified: 11.0.5
+ unist-util-visit: 5.0.0
+
+ '@shikijs/themes@3.21.0':
+ dependencies:
+ '@shikijs/types': 3.21.0
+
+ '@shikijs/transformers@3.21.0':
+ dependencies:
+ '@shikijs/core': 3.21.0
+ '@shikijs/types': 3.21.0
+
+ '@shikijs/types@3.21.0':
+ dependencies:
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+
+ '@shikijs/vscode-textmate@10.0.2': {}
+
'@sindresorhus/is@4.6.0': {}
+ '@solid-primitives/event-listener@2.4.3(solid-js@1.9.10)':
+ dependencies:
+ '@solid-primitives/utils': 6.3.2(solid-js@1.9.10)
+ solid-js: 1.9.10
+
+ '@solid-primitives/keyboard@1.3.3(solid-js@1.9.10)':
+ dependencies:
+ '@solid-primitives/event-listener': 2.4.3(solid-js@1.9.10)
+ '@solid-primitives/rootless': 1.5.2(solid-js@1.9.10)
+ '@solid-primitives/utils': 6.3.2(solid-js@1.9.10)
+ solid-js: 1.9.10
+
+ '@solid-primitives/resize-observer@2.1.3(solid-js@1.9.10)':
+ dependencies:
+ '@solid-primitives/event-listener': 2.4.3(solid-js@1.9.10)
+ '@solid-primitives/rootless': 1.5.2(solid-js@1.9.10)
+ '@solid-primitives/static-store': 0.1.2(solid-js@1.9.10)
+ '@solid-primitives/utils': 6.3.2(solid-js@1.9.10)
+ solid-js: 1.9.10
+
+ '@solid-primitives/rootless@1.5.2(solid-js@1.9.10)':
+ dependencies:
+ '@solid-primitives/utils': 6.3.2(solid-js@1.9.10)
+ solid-js: 1.9.10
+
+ '@solid-primitives/static-store@0.1.2(solid-js@1.9.10)':
+ dependencies:
+ '@solid-primitives/utils': 6.3.2(solid-js@1.9.10)
+ solid-js: 1.9.10
+
+ '@solid-primitives/utils@6.3.2(solid-js@1.9.10)':
+ dependencies:
+ solid-js: 1.9.10
+
+ '@standard-schema/spec@1.1.0': {}
+
'@sveltejs/acorn-typescript@1.0.8(acorn@8.15.0)':
dependencies:
acorn: 8.15.0
@@ -2944,6 +4821,81 @@ snapshots:
tailwindcss: 4.1.18
vite: rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(tsx@4.21.0)
+ '@tailwindcss/vite@4.1.18(rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0))':
+ dependencies:
+ '@tailwindcss/node': 4.1.18
+ '@tailwindcss/oxide': 4.1.18
+ tailwindcss: 4.1.18
+ vite: rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0)
+
+ '@tanstack/devtools-client@0.0.5':
+ dependencies:
+ '@tanstack/devtools-event-client': 0.4.0
+
+ '@tanstack/devtools-event-bus@0.4.0':
+ dependencies:
+ ws: 8.19.0
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+
+ '@tanstack/devtools-event-client@0.4.0': {}
+
+ '@tanstack/devtools-ui@0.4.4(csstype@3.2.3)(solid-js@1.9.10)':
+ dependencies:
+ clsx: 2.1.1
+ goober: 2.1.18(csstype@3.2.3)
+ solid-js: 1.9.10
+ transitivePeerDependencies:
+ - csstype
+
+ '@tanstack/devtools-vite@0.4.1(rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0))':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ '@tanstack/devtools-client': 0.0.5
+ '@tanstack/devtools-event-bus': 0.4.0
+ chalk: 5.6.2
+ launch-editor: 2.12.0
+ picomatch: 4.0.3
+ vite: rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0)
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ '@tanstack/devtools@0.10.3(csstype@3.2.3)(solid-js@1.9.10)':
+ dependencies:
+ '@solid-primitives/event-listener': 2.4.3(solid-js@1.9.10)
+ '@solid-primitives/keyboard': 1.3.3(solid-js@1.9.10)
+ '@solid-primitives/resize-observer': 2.1.3(solid-js@1.9.10)
+ '@tanstack/devtools-client': 0.0.5
+ '@tanstack/devtools-event-bus': 0.4.0
+ '@tanstack/devtools-ui': 0.4.4(csstype@3.2.3)(solid-js@1.9.10)
+ clsx: 2.1.1
+ goober: 2.1.18(csstype@3.2.3)
+ solid-js: 1.9.10
+ transitivePeerDependencies:
+ - bufferutil
+ - csstype
+ - utf-8-validate
+
+ '@tanstack/react-devtools@0.9.2(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10)':
+ dependencies:
+ '@tanstack/devtools': 0.10.3(csstype@3.2.3)(solid-js@1.9.10)
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ transitivePeerDependencies:
+ - bufferutil
+ - csstype
+ - solid-js
+ - utf-8-validate
+
'@tauri-apps/api@2.9.1': {}
'@tauri-apps/cli-darwin-arm64@2.9.6':
@@ -3033,12 +4985,38 @@ snapshots:
dependencies:
'@babel/types': 7.28.6
+ '@types/d3-hierarchy@1.1.11': {}
+
+ '@types/debug@4.1.12':
+ dependencies:
+ '@types/ms': 2.1.0
+
+ '@types/estree-jsx@1.0.5':
+ dependencies:
+ '@types/estree': 1.0.8
+
'@types/estree@1.0.8': {}
+ '@types/hast@3.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
+ '@types/mdast@4.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
+ '@types/mdx@2.0.13': {}
+
+ '@types/ms@2.1.0': {}
+
'@types/node@24.10.9':
dependencies:
undici-types: 7.16.0
+ '@types/node@25.0.9':
+ dependencies:
+ undici-types: 7.16.0
+
'@types/prismjs@1.26.5': {}
'@types/react-dom@19.2.3(@types/react@19.2.8)':
@@ -3049,6 +5027,12 @@ snapshots:
dependencies:
csstype: 3.2.3
+ '@types/unist@2.0.11': {}
+
+ '@types/unist@3.0.3': {}
+
+ '@ungap/structured-clone@1.3.0': {}
+
'@vitejs/plugin-react@5.1.2(rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(tsx@4.21.0))':
dependencies:
'@babel/core': 7.28.6
@@ -3061,14 +5045,31 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ accepts@1.3.8:
+ dependencies:
+ mime-types: 2.1.35
+ negotiator: 0.6.3
+
+ acorn-jsx@5.3.2(acorn@8.15.0):
+ dependencies:
+ acorn: 8.15.0
+
acorn@8.15.0: {}
+ arg@5.0.2: {}
+
+ argparse@2.0.1: {}
+
aria-hidden@1.2.6:
dependencies:
tslib: 2.8.1
aria-query@5.3.2: {}
+ array-flatten@1.1.1: {}
+
+ astring@1.9.0: {}
+
asynckit@0.4.0: {}
autoprefixer@10.4.23(postcss@8.5.6):
@@ -3094,8 +5095,40 @@ snapshots:
axobject-query@4.1.0: {}
+ babel-dead-code-elimination@1.0.12:
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ bail@2.0.2: {}
+
baseline-browser-mapping@2.9.15: {}
+ basic-auth@2.0.1:
+ dependencies:
+ safe-buffer: 5.1.2
+
+ body-parser@1.20.4:
+ dependencies:
+ bytes: 3.1.2
+ content-type: 1.0.5
+ debug: 2.6.9
+ depd: 2.0.0
+ destroy: 1.2.0
+ http-errors: 2.0.1
+ iconv-lite: 0.4.24
+ on-finished: 2.4.1
+ qs: 6.14.1
+ raw-body: 2.5.3
+ type-is: 1.6.18
+ unpipe: 1.0.0
+ transitivePeerDependencies:
+ - supports-color
+
browserslist@4.28.1:
dependencies:
baseline-browser-mapping: 2.9.15
@@ -3104,48 +5137,171 @@ snapshots:
node-releases: 2.0.27
update-browserslist-db: 1.2.3(browserslist@4.28.1)
+ buffer-from@1.1.2: {}
+
+ bytes@3.1.2: {}
+
+ cac@6.7.14: {}
+
call-bind-apply-helpers@1.0.2:
dependencies:
es-errors: 1.3.0
function-bind: 1.1.2
+ call-bound@1.0.4:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ get-intrinsic: 1.3.0
+
caniuse-lite@1.0.30001764: {}
+ ccount@2.0.1: {}
+
+ chain-function@1.0.1: {}
+
+ chalk@5.6.2: {}
+
char-regex@1.0.2: {}
+ character-entities-html4@2.1.0: {}
+
+ character-entities-legacy@3.0.0: {}
+
+ character-entities@2.0.2: {}
+
+ character-reference-invalid@2.0.1: {}
+
chokidar@4.0.3:
dependencies:
readdirp: 4.1.2
+ chokidar@5.0.0:
+ dependencies:
+ readdirp: 5.0.0
+
class-variance-authority@0.7.1:
dependencies:
clsx: 2.1.1
+ classnames@2.5.1: {}
+
clone@1.0.4:
optional: true
+ clone@2.1.2: {}
+
clsx@2.1.1: {}
+ collapse-white-space@2.1.0: {}
+
combined-stream@1.0.8:
dependencies:
delayed-stream: 1.0.0
+ comma-separated-tokens@2.0.3: {}
+
+ compressible@2.0.18:
+ dependencies:
+ mime-db: 1.52.0
+
+ compression@1.8.1:
+ dependencies:
+ bytes: 3.1.2
+ compressible: 2.0.18
+ debug: 2.6.9
+ negotiator: 0.6.4
+ on-headers: 1.1.0
+ safe-buffer: 5.2.1
+ vary: 1.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ compute-scroll-into-view@3.1.1: {}
+
+ confbox@0.2.2: {}
+
consola@3.4.2: {}
console.table@0.10.0:
dependencies:
easy-table: 1.1.0
+ content-disposition@0.5.4:
+ dependencies:
+ safe-buffer: 5.2.1
+
+ content-type@1.0.5: {}
+
convert-source-map@2.0.0: {}
+ cookie-signature@1.0.7: {}
+
+ cookie@0.7.2: {}
+
cookie@1.1.1: {}
+ cssesc@3.0.0: {}
+
csstype@3.2.3: {}
+ d3-color@3.1.0: {}
+
+ d3-dispatch@3.0.1: {}
+
+ d3-drag@3.0.0:
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-selection: 3.0.0
+
+ d3-ease@3.0.1: {}
+
+ d3-hierarchy@1.1.9: {}
+
+ d3-interpolate@3.0.1:
+ dependencies:
+ d3-color: 3.1.0
+
+ d3-path@1.0.9: {}
+
+ d3-selection@3.0.0: {}
+
+ d3-shape@1.3.7:
+ dependencies:
+ d3-path: 1.0.9
+
+ d3-timer@3.0.1: {}
+
+ d3-transition@3.0.1(d3-selection@3.0.0):
+ dependencies:
+ d3-color: 3.1.0
+ d3-dispatch: 3.0.1
+ d3-ease: 3.0.1
+ d3-interpolate: 3.0.1
+ d3-selection: 3.0.0
+ d3-timer: 3.0.1
+
+ d3-zoom@3.0.0:
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-drag: 3.0.0
+ d3-interpolate: 3.0.1
+ d3-selection: 3.0.0
+ d3-transition: 3.0.1(d3-selection@3.0.0)
+
+ debug@2.6.9:
+ dependencies:
+ ms: 2.0.0
+
debug@4.4.3:
dependencies:
ms: 2.1.3
+ decode-named-character-reference@1.3.0:
+ dependencies:
+ character-entities: 2.0.2
+
+ dedent@1.7.1: {}
+
deepmerge@4.3.1: {}
defaults@1.0.4:
@@ -3155,13 +5311,25 @@ snapshots:
delayed-stream@1.0.0: {}
+ depd@2.0.0: {}
+
+ dequal@2.0.3: {}
+
+ destroy@1.2.0: {}
+
detect-libc@2.1.2: {}
detect-node-es@1.1.0: {}
devalue@5.6.2: {}
- dompurify@2.5.8: {}
+ devlop@1.1.0:
+ dependencies:
+ dequal: 2.0.3
+
+ dom-helpers@3.4.0:
+ dependencies:
+ '@babel/runtime': 7.28.6
dunder-proto@1.0.1:
dependencies:
@@ -3173,10 +5341,14 @@ snapshots:
optionalDependencies:
wcwidth: 1.0.1
+ ee-first@1.1.1: {}
+
electron-to-chromium@1.5.267: {}
emojilib@2.4.0: {}
+ encodeurl@2.0.0: {}
+
enhanced-resolve@5.18.4:
dependencies:
graceful-fs: 4.2.11
@@ -3186,6 +5358,8 @@ snapshots:
es-errors@1.3.0: {}
+ es-module-lexer@1.7.0: {}
+
es-object-atoms@1.1.1:
dependencies:
es-errors: 1.3.0
@@ -3197,6 +5371,20 @@ snapshots:
has-tostringtag: 1.0.2
hasown: 2.0.2
+ esast-util-from-estree@2.0.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ devlop: 1.1.0
+ estree-util-visit: 2.0.0
+ unist-util-position-from-estree: 2.0.0
+
+ esast-util-from-js@2.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ acorn: 8.15.0
+ esast-util-from-estree: 2.0.0
+ vfile-message: 4.0.3
+
esbuild@0.27.2:
optionalDependencies:
'@esbuild/aix-ppc64': 0.27.2
@@ -3228,16 +5416,113 @@ snapshots:
escalade@3.2.0: {}
+ escape-html@1.0.3: {}
+
+ escape-string-regexp@5.0.0: {}
+
esm-env@1.2.2: {}
esrap@2.2.1:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
+ estree-util-attach-comments@3.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+
+ estree-util-build-jsx@3.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ estree-walker: 3.0.3
+
+ estree-util-is-identifier-name@3.0.0: {}
+
+ estree-util-scope@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+ devlop: 1.1.0
+
+ estree-util-to-js@2.0.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ astring: 1.9.0
+ source-map: 0.7.6
+
+ estree-util-value-to-estree@3.5.0:
+ dependencies:
+ '@types/estree': 1.0.8
+
+ estree-util-visit@2.0.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/unist': 3.0.3
+
+ estree-walker@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.8
+
+ etag@1.8.1: {}
+
+ exit-hook@2.2.1: {}
+
+ express@4.22.1:
+ dependencies:
+ accepts: 1.3.8
+ array-flatten: 1.1.1
+ body-parser: 1.20.4
+ content-disposition: 0.5.4
+ content-type: 1.0.5
+ cookie: 0.7.2
+ cookie-signature: 1.0.7
+ debug: 2.6.9
+ depd: 2.0.0
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ etag: 1.8.1
+ finalhandler: 1.3.2
+ fresh: 0.5.2
+ http-errors: 2.0.1
+ merge-descriptors: 1.0.3
+ methods: 1.1.2
+ on-finished: 2.4.1
+ parseurl: 1.3.3
+ path-to-regexp: 0.1.12
+ proxy-addr: 2.0.7
+ qs: 6.14.1
+ range-parser: 1.2.1
+ safe-buffer: 5.2.1
+ send: 0.19.2
+ serve-static: 1.16.3
+ setprototypeof: 1.2.0
+ statuses: 2.0.2
+ type-is: 1.6.18
+ utils-merge: 1.0.1
+ vary: 1.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ exsolve@1.0.8: {}
+
+ extend@3.0.2: {}
+
fdir@6.5.0(picomatch@4.0.3):
optionalDependencies:
picomatch: 4.0.3
+ finalhandler@1.3.2:
+ dependencies:
+ debug: 2.6.9
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ on-finished: 2.4.1
+ parseurl: 1.3.3
+ statuses: 2.0.2
+ unpipe: 1.0.0
+ transitivePeerDependencies:
+ - supports-color
+
follow-redirects@1.15.11: {}
form-data@4.0.5:
@@ -3248,11 +5533,109 @@ snapshots:
hasown: 2.0.2
mime-types: 2.1.35
+ forwarded@0.2.0: {}
+
fraction.js@5.3.4: {}
+ framer-motion@12.27.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ dependencies:
+ motion-dom: 12.27.1
+ motion-utils: 12.24.10
+ tslib: 2.8.1
+ optionalDependencies:
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+
+ fresh@0.5.2: {}
+
fsevents@2.3.3:
optional: true
+ fumadocs-core@16.4.7(@types/react@19.2.8)(lucide-react@0.562.0(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.3.5):
+ dependencies:
+ '@formatjs/intl-localematcher': 0.7.5
+ '@orama/orama': 3.1.18
+ '@shikijs/rehype': 3.21.0
+ '@shikijs/transformers': 3.21.0
+ estree-util-value-to-estree: 3.5.0
+ github-slugger: 2.0.0
+ hast-util-to-estree: 3.1.3
+ hast-util-to-jsx-runtime: 2.3.6
+ image-size: 2.0.2
+ negotiator: 1.0.0
+ npm-to-yarn: 3.0.1
+ path-to-regexp: 8.3.0
+ remark: 15.0.1
+ remark-gfm: 4.0.1
+ remark-rehype: 11.1.2
+ scroll-into-view-if-needed: 3.1.0
+ shiki: 3.21.0
+ tinyglobby: 0.2.15
+ unist-util-visit: 5.0.0
+ optionalDependencies:
+ '@types/react': 19.2.8
+ lucide-react: 0.562.0(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ react-router: 7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ zod: 4.3.5
+ transitivePeerDependencies:
+ - supports-color
+
+ fumadocs-mdx@14.2.6(@types/react@19.2.8)(fumadocs-core@16.4.7(@types/react@19.2.8)(lucide-react@0.562.0(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.3.5))(react@19.2.3)(rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0)):
+ dependencies:
+ '@mdx-js/mdx': 3.1.1
+ '@standard-schema/spec': 1.1.0
+ chokidar: 5.0.0
+ esbuild: 0.27.2
+ estree-util-value-to-estree: 3.5.0
+ fumadocs-core: 16.4.7(@types/react@19.2.8)(lucide-react@0.562.0(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.3.5)
+ js-yaml: 4.1.1
+ mdast-util-to-markdown: 2.1.2
+ picocolors: 1.1.1
+ picomatch: 4.0.3
+ remark-mdx: 3.1.1
+ tinyexec: 1.0.2
+ tinyglobby: 0.2.15
+ unified: 11.0.5
+ unist-util-remove-position: 5.0.0
+ unist-util-visit: 5.0.0
+ vfile: 6.0.3
+ zod: 4.3.5
+ optionalDependencies:
+ '@types/react': 19.2.8
+ react: 19.2.3
+ vite: rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0)
+ transitivePeerDependencies:
+ - supports-color
+
+ fumadocs-ui@16.4.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(fumadocs-core@16.4.7(@types/react@19.2.8)(lucide-react@0.562.0(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.3.5))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18):
+ dependencies:
+ '@fumadocs/ui': 16.4.7(@types/react@19.2.8)(fumadocs-core@16.4.7(@types/react@19.2.8)(lucide-react@0.562.0(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.3.5))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)
+ '@radix-ui/react-accordion': 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-navigation-menu': 1.2.14(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-popover': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-scroll-area': 1.2.10(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-slot': 1.2.4(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ class-variance-authority: 0.7.1
+ fumadocs-core: 16.4.7(@types/react@19.2.8)(lucide-react@0.562.0(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(zod@4.3.5)
+ lucide-react: 0.562.0(react@19.2.3)
+ next-themes: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ react-medium-image-zoom: 5.4.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ scroll-into-view-if-needed: 3.1.0
+ optionalDependencies:
+ '@types/react': 19.2.8
+ tailwindcss: 4.1.18
+ transitivePeerDependencies:
+ - '@types/react-dom'
+
function-bind@1.1.2: {}
gensync@1.0.0-beta.2: {}
@@ -3272,6 +5655,8 @@ snapshots:
get-nonce@1.0.1: {}
+ get-port@5.1.1: {}
+
get-proto@1.0.1:
dependencies:
dunder-proto: 1.0.1
@@ -3281,6 +5666,8 @@ snapshots:
dependencies:
resolve-pkg-maps: 1.0.0
+ github-slugger@2.0.0: {}
+
glob@13.0.0:
dependencies:
minimatch: 10.1.1
@@ -3289,6 +5676,12 @@ snapshots:
globals@16.5.0: {}
+ globrex@0.1.2: {}
+
+ goober@2.1.18(csstype@3.2.3):
+ dependencies:
+ csstype: 3.2.3
+
gopd@1.2.0: {}
graceful-fs@4.2.11: {}
@@ -3303,18 +5696,127 @@ snapshots:
dependencies:
function-bind: 1.1.2
+ hast-util-to-estree@3.1.3:
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ comma-separated-tokens: 2.0.3
+ devlop: 1.1.0
+ estree-util-attach-comments: 3.0.0
+ estree-util-is-identifier-name: 3.0.0
+ hast-util-whitespace: 3.0.0
+ mdast-util-mdx-expression: 2.0.1
+ mdast-util-mdx-jsx: 3.2.0
+ mdast-util-mdxjs-esm: 2.0.1
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ style-to-js: 1.1.21
+ unist-util-position: 5.0.0
+ zwitch: 2.0.4
+ transitivePeerDependencies:
+ - supports-color
+
+ hast-util-to-html@9.0.5:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ ccount: 2.0.1
+ comma-separated-tokens: 2.0.3
+ hast-util-whitespace: 3.0.0
+ html-void-elements: 3.0.0
+ mdast-util-to-hast: 13.2.1
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ stringify-entities: 4.0.4
+ zwitch: 2.0.4
+
+ hast-util-to-jsx-runtime@2.3.6:
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ comma-separated-tokens: 2.0.3
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ hast-util-whitespace: 3.0.0
+ mdast-util-mdx-expression: 2.0.1
+ mdast-util-mdx-jsx: 3.2.0
+ mdast-util-mdxjs-esm: 2.0.1
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ style-to-js: 1.1.21
+ unist-util-position: 5.0.0
+ vfile-message: 4.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ hast-util-to-string@3.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+
+ hast-util-whitespace@3.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+
+ html-void-elements@3.0.0: {}
+
+ http-errors@2.0.1:
+ dependencies:
+ depd: 2.0.0
+ inherits: 2.0.4
+ setprototypeof: 1.2.0
+ statuses: 2.0.2
+ toidentifier: 1.0.1
+
+ iconv-lite@0.4.24:
+ dependencies:
+ safer-buffer: 2.1.2
+
+ image-size@2.0.2: {}
+
+ inherits@2.0.4: {}
+
+ inline-style-parser@0.2.7: {}
+
+ ipaddr.js@1.9.1: {}
+
+ is-alphabetical@2.0.1: {}
+
+ is-alphanumerical@2.0.1:
+ dependencies:
+ is-alphabetical: 2.0.1
+ is-decimal: 2.0.1
+
+ is-decimal@2.0.1: {}
+
+ is-hexadecimal@2.0.1: {}
+
+ is-plain-obj@4.1.0: {}
+
is-reference@3.0.3:
dependencies:
'@types/estree': 1.0.8
+ isbot@5.1.33: {}
+
jiti@2.6.1: {}
js-tokens@4.0.0: {}
- jsesc@3.1.0: {}
+ js-yaml@4.1.1:
+ dependencies:
+ argparse: 2.0.1
+
+ jsesc@3.0.2: {}
json5@2.2.3: {}
+ launch-editor@2.12.0:
+ dependencies:
+ picocolors: 1.1.1
+ shell-quote: 1.8.3
+
lightningcss-android-arm64@1.30.2:
optional: true
@@ -3366,6 +5868,14 @@ snapshots:
locate-character@3.0.0: {}
+ lodash@4.17.21: {}
+
+ longest-streak@3.1.0: {}
+
+ loose-envify@1.4.0:
+ dependencies:
+ js-tokens: 4.0.0
+
lru-cache@11.2.4: {}
lru-cache@5.1.1:
@@ -3384,28 +5894,491 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
+ markdown-extensions@2.0.0: {}
+
+ markdown-table@3.0.4: {}
+
marked@17.0.1: {}
math-intrinsics@1.1.0: {}
+ mdast-util-find-and-replace@3.0.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ escape-string-regexp: 5.0.0
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
+ mdast-util-from-markdown@2.0.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ decode-named-character-reference: 1.3.0
+ devlop: 1.1.0
+ mdast-util-to-string: 4.0.0
+ micromark: 4.0.2
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-decode-string: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ unist-util-stringify-position: 4.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-autolink-literal@2.0.1:
+ dependencies:
+ '@types/mdast': 4.0.4
+ ccount: 2.0.1
+ devlop: 1.1.0
+ mdast-util-find-and-replace: 3.0.2
+ micromark-util-character: 2.1.1
+
+ mdast-util-gfm-footnote@2.1.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ micromark-util-normalize-identifier: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-strikethrough@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-table@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ markdown-table: 3.0.4
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-task-list-item@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm@3.1.0:
+ dependencies:
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-gfm-autolink-literal: 2.0.1
+ mdast-util-gfm-footnote: 2.1.0
+ mdast-util-gfm-strikethrough: 2.0.0
+ mdast-util-gfm-table: 2.0.0
+ mdast-util-gfm-task-list-item: 2.0.0
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx-expression@2.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx-jsx@3.2.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ ccount: 2.0.1
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ parse-entities: 4.0.2
+ stringify-entities: 4.0.4
+ unist-util-stringify-position: 4.0.0
+ vfile-message: 4.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx@3.0.0:
+ dependencies:
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-mdx-expression: 2.0.1
+ mdast-util-mdx-jsx: 3.2.0
+ mdast-util-mdxjs-esm: 2.0.1
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdxjs-esm@2.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-phrasing@4.1.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ unist-util-is: 6.0.1
+
+ mdast-util-to-hast@13.2.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@ungap/structured-clone': 1.3.0
+ devlop: 1.1.0
+ micromark-util-sanitize-uri: 2.0.1
+ trim-lines: 3.0.1
+ unist-util-position: 5.0.0
+ unist-util-visit: 5.0.0
+ vfile: 6.0.3
+
+ mdast-util-to-markdown@2.1.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ longest-streak: 3.1.0
+ mdast-util-phrasing: 4.1.0
+ mdast-util-to-string: 4.0.0
+ micromark-util-classify-character: 2.0.1
+ micromark-util-decode-string: 2.0.1
+ unist-util-visit: 5.0.0
+ zwitch: 2.0.4
+
+ mdast-util-to-string@4.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+
+ media-typer@0.3.0: {}
+
+ merge-descriptors@1.0.3: {}
+
+ methods@1.1.2: {}
+
+ micromark-core-commonmark@2.0.3:
+ dependencies:
+ decode-named-character-reference: 1.3.0
+ devlop: 1.1.0
+ micromark-factory-destination: 2.0.1
+ micromark-factory-label: 2.0.1
+ micromark-factory-space: 2.0.1
+ micromark-factory-title: 2.0.1
+ micromark-factory-whitespace: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-chunked: 2.0.1
+ micromark-util-classify-character: 2.0.1
+ micromark-util-html-tag-name: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-subtokenize: 2.1.0
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-autolink-literal@2.1.0:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-footnote@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-core-commonmark: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-strikethrough@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-chunked: 2.0.1
+ micromark-util-classify-character: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-table@2.1.1:
+ dependencies:
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-tagfilter@2.0.0:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-task-list-item@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm@3.0.0:
+ dependencies:
+ micromark-extension-gfm-autolink-literal: 2.1.0
+ micromark-extension-gfm-footnote: 2.1.0
+ micromark-extension-gfm-strikethrough: 2.1.0
+ micromark-extension-gfm-table: 2.1.1
+ micromark-extension-gfm-tagfilter: 2.0.0
+ micromark-extension-gfm-task-list-item: 2.1.0
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-mdx-expression@3.0.1:
+ dependencies:
+ '@types/estree': 1.0.8
+ devlop: 1.1.0
+ micromark-factory-mdx-expression: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-events-to-acorn: 2.0.3
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-mdx-jsx@3.0.2:
+ dependencies:
+ '@types/estree': 1.0.8
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ micromark-factory-mdx-expression: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-events-to-acorn: 2.0.3
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ vfile-message: 4.0.3
+
+ micromark-extension-mdx-md@2.0.0:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-extension-mdxjs-esm@3.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+ devlop: 1.1.0
+ micromark-core-commonmark: 2.0.3
+ micromark-util-character: 2.1.1
+ micromark-util-events-to-acorn: 2.0.3
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ unist-util-position-from-estree: 2.0.0
+ vfile-message: 4.0.3
+
+ micromark-extension-mdxjs@3.0.0:
+ dependencies:
+ acorn: 8.15.0
+ acorn-jsx: 5.3.2(acorn@8.15.0)
+ micromark-extension-mdx-expression: 3.0.1
+ micromark-extension-mdx-jsx: 3.0.2
+ micromark-extension-mdx-md: 2.0.0
+ micromark-extension-mdxjs-esm: 3.0.0
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-destination@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-label@2.0.1:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-mdx-expression@2.0.3:
+ dependencies:
+ '@types/estree': 1.0.8
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-events-to-acorn: 2.0.3
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ unist-util-position-from-estree: 2.0.0
+ vfile-message: 4.0.3
+
+ micromark-factory-space@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-title@2.0.1:
+ dependencies:
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-whitespace@2.0.1:
+ dependencies:
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-character@2.1.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-chunked@2.0.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-classify-character@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-combine-extensions@2.0.1:
+ dependencies:
+ micromark-util-chunked: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-decode-numeric-character-reference@2.0.2:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-decode-string@2.0.1:
+ dependencies:
+ decode-named-character-reference: 1.3.0
+ micromark-util-character: 2.1.1
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-encode@2.0.1: {}
+
+ micromark-util-events-to-acorn@2.0.3:
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/unist': 3.0.3
+ devlop: 1.1.0
+ estree-util-visit: 2.0.0
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ vfile-message: 4.0.3
+
+ micromark-util-html-tag-name@2.0.1: {}
+
+ micromark-util-normalize-identifier@2.0.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-resolve-all@2.0.1:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-util-sanitize-uri@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-encode: 2.0.1
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-subtokenize@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-chunked: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-symbol@2.0.1: {}
+
+ micromark-util-types@2.0.2: {}
+
+ micromark@4.0.2:
+ dependencies:
+ '@types/debug': 4.1.12
+ debug: 4.4.3
+ decode-named-character-reference: 1.3.0
+ devlop: 1.1.0
+ micromark-core-commonmark: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-chunked: 2.0.1
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-encode: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-subtokenize: 2.1.0
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
mime-db@1.52.0: {}
mime-types@2.1.35:
dependencies:
mime-db: 1.52.0
+ mime@1.6.0: {}
+
minimatch@10.1.1:
dependencies:
'@isaacs/brace-expansion': 5.0.0
minipass@7.1.2: {}
+ morgan@1.10.1:
+ dependencies:
+ basic-auth: 2.0.1
+ debug: 2.6.9
+ depd: 2.0.0
+ on-finished: 2.3.0
+ on-headers: 1.1.0
+ transitivePeerDependencies:
+ - supports-color
+
+ motion-dom@12.27.1:
+ dependencies:
+ motion-utils: 12.24.10
+
+ motion-utils@12.24.10: {}
+
mri@1.2.0: {}
+ ms@2.0.0: {}
+
ms@2.1.3: {}
nanoid@3.3.11: {}
+ negotiator@0.6.3: {}
+
+ negotiator@0.6.4: {}
+
+ negotiator@1.0.0: {}
+
next-themes@0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
react: 19.2.3
@@ -3420,8 +6393,32 @@ snapshots:
node-releases@2.0.27: {}
+ npm-to-yarn@3.0.1: {}
+
+ object-assign@4.1.1: {}
+
+ object-inspect@1.13.4: {}
+
obug@2.1.1: {}
+ on-finished@2.3.0:
+ dependencies:
+ ee-first: 1.1.1
+
+ on-finished@2.4.1:
+ dependencies:
+ ee-first: 1.1.1
+
+ on-headers@1.1.0: {}
+
+ oniguruma-parser@0.12.1: {}
+
+ oniguruma-to-es@4.3.4:
+ dependencies:
+ oniguruma-parser: 0.12.1
+ regex: 6.1.0
+ regex-recursion: 6.0.2
+
oxfmt@0.24.0:
dependencies:
tinypool: 2.0.0
@@ -3446,17 +6443,50 @@ snapshots:
'@oxlint/win32-arm64': 1.39.0
'@oxlint/win32-x64': 1.39.0
+ p-map@7.0.4: {}
+
package-json-from-dist@1.0.1: {}
+ parse-entities@4.0.2:
+ dependencies:
+ '@types/unist': 2.0.11
+ character-entities-legacy: 3.0.0
+ character-reference-invalid: 2.0.1
+ decode-named-character-reference: 1.3.0
+ is-alphanumerical: 2.0.1
+ is-decimal: 2.0.1
+ is-hexadecimal: 2.0.1
+
+ parseurl@1.3.3: {}
+
path-scurry@2.0.1:
dependencies:
lru-cache: 11.2.4
minipass: 7.1.2
+ path-to-regexp@0.1.12: {}
+
+ path-to-regexp@8.3.0: {}
+
+ pathe@1.1.2: {}
+
+ pathe@2.0.3: {}
+
picocolors@1.1.1: {}
picomatch@4.0.3: {}
+ pkg-types@2.3.0:
+ dependencies:
+ confbox: 0.2.2
+ exsolve: 1.0.8
+ pathe: 2.0.3
+
+ postcss-selector-parser@7.1.1:
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+
postcss-value-parser@4.2.0: {}
postcss@8.5.6:
@@ -3465,15 +6495,73 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
+ prettier@3.8.0: {}
+
prismjs@1.30.0: {}
+ prop-types@15.8.1:
+ dependencies:
+ loose-envify: 1.4.0
+ object-assign: 4.1.1
+ react-is: 16.13.1
+
+ property-information@7.1.0: {}
+
+ proxy-addr@2.0.7:
+ dependencies:
+ forwarded: 0.2.0
+ ipaddr.js: 1.9.1
+
proxy-from-env@1.1.0: {}
+ qs@6.14.1:
+ dependencies:
+ side-channel: 1.1.0
+
+ range-parser@1.2.1: {}
+
+ raw-body@2.5.3:
+ dependencies:
+ bytes: 3.1.2
+ http-errors: 2.0.1
+ iconv-lite: 0.4.24
+ unpipe: 1.0.0
+
+ react-d3-tree@3.6.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ dependencies:
+ '@bkrem/react-transition-group': 1.3.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@types/d3-hierarchy': 1.1.11
+ clone: 2.1.2
+ d3-hierarchy: 1.1.9
+ d3-selection: 3.0.0
+ d3-shape: 1.3.7
+ d3-zoom: 3.0.0
+ dequal: 2.0.3
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ uuid: 8.3.2
+
react-dom@19.2.3(react@19.2.3):
dependencies:
react: 19.2.3
scheduler: 0.27.0
+ react-hotkeys-hook@5.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+
+ react-is@16.13.1: {}
+
+ react-lifecycles-compat@3.0.4: {}
+
+ react-medium-image-zoom@5.4.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+
+ react-refresh@0.14.2: {}
+
react-refresh@0.18.0: {}
react-remove-scroll-bar@2.3.8(@types/react@19.2.8)(react@19.2.3):
@@ -3495,6 +6583,43 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.8
+ react-router-devtools@6.2.0(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0))(solid-js@1.9.10):
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ '@radix-ui/react-accordion': 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@tanstack/devtools-client': 0.0.5
+ '@tanstack/devtools-event-client': 0.4.0
+ '@tanstack/devtools-vite': 0.4.1(rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0))
+ '@tanstack/react-devtools': 0.9.2(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10)
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+ chalk: 5.6.2
+ clsx: 2.1.1
+ framer-motion: 12.27.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ goober: 2.1.18(csstype@3.2.3)
+ react: 19.2.3
+ react-d3-tree: 3.6.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ react-dom: 19.2.3(react@19.2.3)
+ react-hotkeys-hook: 5.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ react-router: 7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ react-tooltip: 5.30.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ vite: rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0)
+ optionalDependencies:
+ '@biomejs/cli-darwin-arm64': 2.3.11
+ '@rollup/rollup-darwin-arm64': 4.55.2
+ '@rollup/rollup-linux-x64-gnu': 4.55.2
+ transitivePeerDependencies:
+ - '@emotion/is-prop-valid'
+ - bufferutil
+ - csstype
+ - solid-js
+ - supports-color
+ - utf-8-validate
+
react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
cookie: 1.1.1
@@ -3511,10 +6636,116 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.8
+ react-tooltip@5.30.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ dependencies:
+ '@floating-ui/dom': 1.7.4
+ classnames: 2.5.1
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+
react@19.2.3: {}
readdirp@4.1.2: {}
+ readdirp@5.0.0: {}
+
+ recma-build-jsx@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+ estree-util-build-jsx: 3.0.1
+ vfile: 6.0.3
+
+ recma-jsx@1.0.1(acorn@8.15.0):
+ dependencies:
+ acorn: 8.15.0
+ acorn-jsx: 5.3.2(acorn@8.15.0)
+ estree-util-to-js: 2.0.0
+ recma-parse: 1.0.0
+ recma-stringify: 1.0.0
+ unified: 11.0.5
+
+ recma-parse@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+ esast-util-from-js: 2.0.1
+ unified: 11.0.5
+ vfile: 6.0.3
+
+ recma-stringify@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+ estree-util-to-js: 2.0.0
+ unified: 11.0.5
+ vfile: 6.0.3
+
+ regex-recursion@6.0.2:
+ dependencies:
+ regex-utilities: 2.3.0
+
+ regex-utilities@2.3.0: {}
+
+ regex@6.1.0:
+ dependencies:
+ regex-utilities: 2.3.0
+
+ rehype-recma@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/hast': 3.0.4
+ hast-util-to-estree: 3.1.3
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-gfm@4.0.1:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-gfm: 3.1.0
+ micromark-extension-gfm: 3.0.0
+ remark-parse: 11.0.0
+ remark-stringify: 11.0.0
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-mdx@3.1.1:
+ dependencies:
+ mdast-util-mdx: 3.0.0
+ micromark-extension-mdxjs: 3.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-parse@11.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-from-markdown: 2.0.2
+ micromark-util-types: 2.0.2
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-rehype@11.1.2:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ mdast-util-to-hast: 13.2.1
+ unified: 11.0.5
+ vfile: 6.0.3
+
+ remark-stringify@11.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-to-markdown: 2.1.2
+ unified: 11.0.5
+
+ remark@15.0.1:
+ dependencies:
+ '@types/mdast': 4.0.4
+ remark-parse: 11.0.0
+ remark-stringify: 11.0.0
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
resolve-pkg-maps@1.0.0: {}
rimraf@6.1.2:
@@ -3537,6 +6768,21 @@ snapshots:
jiti: 2.6.1
tsx: 4.21.0
+ rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0):
+ dependencies:
+ '@oxc-project/runtime': 0.97.0
+ fdir: 6.5.0(picomatch@4.0.3)
+ lightningcss: 1.30.2
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rolldown: 1.0.0-beta.50
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 25.0.9
+ fsevents: 2.3.3
+ jiti: 2.6.1
+ tsx: 4.21.0
+
rolldown@1.0.0-beta.50:
dependencies:
'@oxc-project/types': 0.97.0
@@ -3561,16 +6807,110 @@ snapshots:
dependencies:
mri: 1.2.0
+ safe-buffer@5.1.2: {}
+
+ safe-buffer@5.2.1: {}
+
+ safer-buffer@2.1.2: {}
+
scheduler@0.27.0: {}
+ scroll-into-view-if-needed@3.1.0:
+ dependencies:
+ compute-scroll-into-view: 3.1.1
+
semver@6.3.1: {}
+ semver@7.7.3: {}
+
+ send@0.19.2:
+ dependencies:
+ debug: 2.6.9
+ depd: 2.0.0
+ destroy: 1.2.0
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ etag: 1.8.1
+ fresh: 0.5.2
+ http-errors: 2.0.1
+ mime: 1.6.0
+ ms: 2.1.3
+ on-finished: 2.4.1
+ range-parser: 1.2.1
+ statuses: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ seroval-plugins@1.3.3(seroval@1.3.2):
+ dependencies:
+ seroval: 1.3.2
+
+ seroval@1.3.2: {}
+
+ serve-static@1.16.3:
+ dependencies:
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ parseurl: 1.3.3
+ send: 0.19.2
+ transitivePeerDependencies:
+ - supports-color
+
set-cookie-parser@2.7.2: {}
+ setprototypeof@1.2.0: {}
+
+ shell-quote@1.8.3: {}
+
+ shiki@3.21.0:
+ dependencies:
+ '@shikijs/core': 3.21.0
+ '@shikijs/engine-javascript': 3.21.0
+ '@shikijs/engine-oniguruma': 3.21.0
+ '@shikijs/langs': 3.21.0
+ '@shikijs/themes': 3.21.0
+ '@shikijs/types': 3.21.0
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+
+ side-channel-list@1.0.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-map@1.0.1:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-weakmap@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-map: 1.0.1
+
+ side-channel@1.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-list: 1.0.0
+ side-channel-map: 1.0.1
+ side-channel-weakmap: 1.0.2
+
skin-tone@2.0.0:
dependencies:
unicode-emoji-modifier-base: 1.0.0
+ solid-js@1.9.10:
+ dependencies:
+ csstype: 3.2.3
+ seroval: 1.3.2
+ seroval-plugins: 1.3.3(seroval@1.3.2)
+
sonner@2.0.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
react: 19.2.3
@@ -3578,6 +6918,32 @@ snapshots:
source-map-js@1.2.1: {}
+ source-map-support@0.5.21:
+ dependencies:
+ buffer-from: 1.1.2
+ source-map: 0.6.1
+
+ source-map@0.6.1: {}
+
+ source-map@0.7.6: {}
+
+ space-separated-tokens@2.0.2: {}
+
+ statuses@2.0.2: {}
+
+ stringify-entities@4.0.4:
+ dependencies:
+ character-entities-html4: 2.1.0
+ character-entities-legacy: 3.0.0
+
+ style-to-js@1.1.21:
+ dependencies:
+ style-to-object: 1.0.14
+
+ style-to-object@1.0.14:
+ dependencies:
+ inline-style-parser: 0.2.7
+
svelte-check@4.3.5(picomatch@4.0.3)(svelte@5.46.4)(typescript@5.9.3):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
@@ -3614,6 +6980,8 @@ snapshots:
tapable@2.3.0: {}
+ tinyexec@1.0.2: {}
+
tinyglobby@0.2.15:
dependencies:
fdir: 6.5.0(picomatch@4.0.3)
@@ -3621,8 +6989,18 @@ snapshots:
tinypool@2.0.0: {}
+ toidentifier@1.0.1: {}
+
toml@3.0.0: {}
+ trim-lines@3.0.1: {}
+
+ trough@2.2.0: {}
+
+ tsconfck@3.1.6(typescript@5.9.3):
+ optionalDependencies:
+ typescript: 5.9.3
+
tslib@2.8.1: {}
tsx@4.21.0:
@@ -3636,12 +7014,61 @@ snapshots:
tw-animate-css@1.4.0: {}
+ type-is@1.6.18:
+ dependencies:
+ media-typer: 0.3.0
+ mime-types: 2.1.35
+
typescript@5.9.3: {}
undici-types@7.16.0: {}
unicode-emoji-modifier-base@1.0.0: {}
+ unified@11.0.5:
+ dependencies:
+ '@types/unist': 3.0.3
+ bail: 2.0.2
+ devlop: 1.1.0
+ extend: 3.0.2
+ is-plain-obj: 4.1.0
+ trough: 2.2.0
+ vfile: 6.0.3
+
+ unist-util-is@6.0.1:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-position-from-estree@2.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-position@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-remove-position@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-visit: 5.0.0
+
+ unist-util-stringify-position@4.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-visit-parents@6.0.2:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+
+ unist-util-visit@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
+ unpipe@1.0.0: {}
+
update-browserslist-db@1.2.3(browserslist@4.28.1):
dependencies:
browserslist: 4.28.1
@@ -3663,20 +7090,84 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.8
+ util-deprecate@1.0.2: {}
+
+ utils-merge@1.0.1: {}
+
+ uuid@8.3.2: {}
+
+ valibot@1.2.0(typescript@5.9.3):
+ optionalDependencies:
+ typescript: 5.9.3
+
+ vary@1.1.2: {}
+
+ vfile-message@4.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-stringify-position: 4.0.0
+
+ vfile@6.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ vfile-message: 4.0.3
+
+ vite-node@3.2.4(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0):
+ dependencies:
+ cac: 6.7.14
+ debug: 4.4.3
+ es-module-lexer: 1.7.0
+ pathe: 2.0.3
+ vite: rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0)
+ transitivePeerDependencies:
+ - '@types/node'
+ - esbuild
+ - jiti
+ - less
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
+ vite-tsconfig-paths@6.0.4(rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0))(typescript@5.9.3):
+ dependencies:
+ debug: 4.4.3
+ globrex: 0.1.2
+ tsconfck: 3.1.6(typescript@5.9.3)
+ optionalDependencies:
+ vite: rolldown-vite@7.2.5(@types/node@25.0.9)(jiti@2.6.1)(tsx@4.21.0)
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+
vitefu@1.1.1(rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(tsx@4.21.0)):
optionalDependencies:
vite: rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(tsx@4.21.0)
+ warning@3.0.0:
+ dependencies:
+ loose-envify: 1.4.0
+
wcwidth@1.0.1:
dependencies:
defaults: 1.0.4
optional: true
+ ws@8.19.0: {}
+
yallist@3.1.1: {}
zimmerframe@1.1.4: {}
+ zod@4.3.5: {}
+
zustand@5.0.10(@types/react@19.2.8)(react@19.2.3):
optionalDependencies:
'@types/react': 19.2.8
react: 19.2.3
+
+ zwitch@2.0.4: {}
diff --git a/src-tauri/src/core/instance.rs b/src-tauri/src/core/instance.rs
index e7746b2..e842ec9 100644
--- a/src-tauri/src/core/instance.rs
+++ b/src-tauri/src/core/instance.rs
@@ -34,6 +34,7 @@ pub struct Instance {
pub jvm_args_override: Option, // JVM参数覆盖(可选)
#[serde(default)]
pub memory_override: Option, // 内存设置覆盖(可选)
+ pub java_path_override: Option, // 实例级Java路径覆盖(可选)
}
/// Memory settings override for an instance
@@ -127,6 +128,7 @@ impl InstanceState {
mod_loader_version: None,
jvm_args_override: None,
memory_override: None,
+ java_path_override: None,
};
let mut config = self.instances.lock().unwrap();
@@ -283,6 +285,7 @@ impl InstanceState {
last_played: None,
jvm_args_override: source_instance.jvm_args_override.clone(),
memory_override: source_instance.memory_override.clone(),
+ java_path_override: source_instance.java_path_override.clone(),
};
self.update_instance(new_instance.clone())?;
diff --git a/src-tauri/src/core/java.rs b/src-tauri/src/core/java.rs
deleted file mode 100644
index 12a6d56..0000000
--- a/src-tauri/src/core/java.rs
+++ /dev/null
@@ -1,1117 +0,0 @@
-use serde::{Deserialize, Serialize};
-#[cfg(target_os = "windows")]
-use std::os::windows::process::CommandExt;
-use std::path::PathBuf;
-use std::process::Command;
-use tauri::AppHandle;
-use tauri::Emitter;
-use tauri::Manager;
-use ts_rs::TS;
-
-use crate::core::downloader::{self, DownloadQueue, JavaDownloadProgress, PendingJavaDownload};
-use crate::utils::zip;
-
-const ADOPTIUM_API_BASE: &str = "https://api.adoptium.net/v3";
-const CACHE_DURATION_SECS: u64 = 24 * 60 * 60; // 24 hours
-
-/// Helper to strip UNC prefix on Windows (\\?\)
-fn strip_unc_prefix(path: PathBuf) -> PathBuf {
- #[cfg(target_os = "windows")]
- {
- let s = path.to_string_lossy().to_string();
- if s.starts_with(r"\\?\") {
- return PathBuf::from(&s[4..]);
- }
- }
- path
-}
-
-#[derive(Debug, Clone, Serialize, Deserialize, TS)]
-#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/java.ts")]
-pub struct JavaInstallation {
- pub path: String,
- pub version: String,
- pub is_64bit: bool,
-}
-
-/// Java image type: JRE or JDK
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, TS)]
-#[ts(
- export,
- rename_all = "lowercase",
- export_to = "../../packages/ui-new/src/types/bindings/java.ts"
-)]
-#[serde(rename_all = "lowercase")]
-pub enum ImageType {
- Jre,
- Jdk,
-}
-
-impl Default for ImageType {
- fn default() -> Self {
- Self::Jre
- }
-}
-
-impl std::fmt::Display for ImageType {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Self::Jre => write!(f, "jre"),
- Self::Jdk => write!(f, "jdk"),
- }
- }
-}
-
-/// Java release information for UI display
-#[derive(Debug, Clone, Serialize, Deserialize, TS)]
-#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/java.ts")]
-pub struct JavaReleaseInfo {
- pub major_version: u32,
- pub image_type: String,
- pub version: String,
- pub release_name: String,
- pub release_date: Option,
- pub file_size: u64,
- pub checksum: Option,
- pub download_url: String,
- pub is_lts: bool,
- pub is_available: bool,
- pub architecture: String,
-}
-
-/// Java catalog containing all available versions
-#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)]
-#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/java.ts")]
-pub struct JavaCatalog {
- pub releases: Vec,
- pub available_major_versions: Vec,
- pub lts_versions: Vec,
- pub cached_at: u64,
-}
-
-/// Adoptium `/v3/assets/latest/{version}/hotspot` API response structures
-#[derive(Debug, Clone, Deserialize)]
-pub struct AdoptiumAsset {
- pub binary: AdoptiumBinary,
- pub release_name: String,
- pub version: AdoptiumVersionData,
-}
-
-#[derive(Debug, Clone, Deserialize)]
-#[allow(dead_code)]
-pub struct AdoptiumBinary {
- pub os: String,
- pub architecture: String,
- pub image_type: String,
- pub package: AdoptiumPackage,
- #[serde(default)]
- pub updated_at: Option,
-}
-
-#[derive(Debug, Clone, Deserialize)]
-pub struct AdoptiumPackage {
- pub name: String,
- pub link: String,
- pub size: u64,
- pub checksum: Option, // SHA256
-}
-
-#[derive(Debug, Clone, Deserialize)]
-#[allow(dead_code)]
-pub struct AdoptiumVersionData {
- pub major: u32,
- pub minor: u32,
- pub security: u32,
- pub semver: String,
- pub openjdk_version: String,
-}
-
-/// Adoptium available releases response
-#[derive(Debug, Clone, Deserialize)]
-#[allow(dead_code)]
-pub struct AvailableReleases {
- pub available_releases: Vec,
- pub available_lts_releases: Vec,
- pub most_recent_lts: Option,
- pub most_recent_feature_release: Option,
-}
-
-/// Java download information from Adoptium
-#[derive(Debug, Clone, Serialize, TS)]
-#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/java.ts")]
-pub struct JavaDownloadInfo {
- pub version: String,
- pub release_name: String,
- pub download_url: String,
- pub file_name: String,
- pub file_size: u64,
- pub checksum: Option,
- pub image_type: String,
-}
-
-/// Get the Adoptium OS name for the current platform
-pub fn get_adoptium_os() -> &'static str {
- #[cfg(target_os = "linux")]
- {
- // Check if Alpine Linux (musl libc)
- if std::path::Path::new("/etc/alpine-release").exists() {
- return "alpine-linux";
- }
- "linux"
- }
- #[cfg(target_os = "macos")]
- {
- "mac"
- }
- #[cfg(target_os = "windows")]
- {
- "windows"
- }
- #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
- {
- "linux" // fallback
- }
-}
-
-/// Get the Adoptium Architecture name for the current architecture
-pub fn get_adoptium_arch() -> &'static str {
- #[cfg(target_arch = "x86_64")]
- {
- "x64"
- }
- #[cfg(target_arch = "aarch64")]
- {
- "aarch64"
- }
- #[cfg(target_arch = "x86")]
- {
- "x86"
- }
- #[cfg(target_arch = "arm")]
- {
- "arm"
- }
- #[cfg(not(any(
- target_arch = "x86_64",
- target_arch = "aarch64",
- target_arch = "x86",
- target_arch = "arm"
- )))]
- {
- "x64" // fallback
- }
-}
-
-/// Get the default Java installation directory for DropOut
-pub fn get_java_install_dir(app_handle: &AppHandle) -> PathBuf {
- app_handle.path().app_data_dir().unwrap().join("java")
-}
-
-/// Get the cache file path for Java catalog
-fn get_catalog_cache_path(app_handle: &AppHandle) -> PathBuf {
- app_handle
- .path()
- .app_data_dir()
- .unwrap()
- .join("java_catalog_cache.json")
-}
-
-/// Load cached Java catalog if not expired
-pub fn load_cached_catalog(app_handle: &AppHandle) -> Option {
- let cache_path = get_catalog_cache_path(app_handle);
- if !cache_path.exists() {
- return None;
- }
-
- let content = std::fs::read_to_string(&cache_path).ok()?;
- let catalog: JavaCatalog = serde_json::from_str(&content).ok()?;
-
- let now = std::time::SystemTime::now()
- .duration_since(std::time::UNIX_EPOCH)
- .unwrap()
- .as_secs();
-
- if now - catalog.cached_at < CACHE_DURATION_SECS {
- Some(catalog)
- } else {
- None
- }
-}
-
-/// Save Java catalog to cache
-pub fn save_catalog_cache(app_handle: &AppHandle, catalog: &JavaCatalog) -> Result<(), String> {
- let cache_path = get_catalog_cache_path(app_handle);
- let content = serde_json::to_string_pretty(catalog).map_err(|e| e.to_string())?;
- std::fs::write(&cache_path, content).map_err(|e| e.to_string())?;
- Ok(())
-}
-
-/// Clear Java catalog cache
-#[allow(dead_code)]
-pub fn clear_catalog_cache(app_handle: &AppHandle) -> Result<(), String> {
- let cache_path = get_catalog_cache_path(app_handle);
- if cache_path.exists() {
- std::fs::remove_file(&cache_path).map_err(|e| e.to_string())?;
- }
- Ok(())
-}
-
-/// Fetch complete Java catalog from Adoptium API with platform availability check
-pub async fn fetch_java_catalog(
- app_handle: &AppHandle,
- force_refresh: bool,
-) -> Result {
- // Check cache first unless force refresh
- if !force_refresh {
- if let Some(cached) = load_cached_catalog(app_handle) {
- return Ok(cached);
- }
- }
-
- let os = get_adoptium_os();
- let arch = get_adoptium_arch();
- let client = reqwest::Client::new();
-
- // 1. Fetch available releases
- let releases_url = format!("{}/info/available_releases", ADOPTIUM_API_BASE);
- let available: AvailableReleases = client
- .get(&releases_url)
- .header("Accept", "application/json")
- .send()
- .await
- .map_err(|e| format!("Failed to fetch available releases: {}", e))?
- .json()
- .await
- .map_err(|e| format!("Failed to parse available releases: {}", e))?;
-
- let mut releases = Vec::new();
-
- // 2. Fetch details for each major version
- for major_version in &available.available_releases {
- for image_type in &["jre", "jdk"] {
- let url = format!(
- "{}/assets/latest/{}/hotspot?os={}&architecture={}&image_type={}",
- ADOPTIUM_API_BASE, major_version, os, arch, image_type
- );
-
- match client
- .get(&url)
- .header("Accept", "application/json")
- .send()
- .await
- {
- Ok(response) => {
- if response.status().is_success() {
- if let Ok(assets) = response.json::>().await {
- if let Some(asset) = assets.into_iter().next() {
- let release_date = asset.binary.updated_at.clone();
- releases.push(JavaReleaseInfo {
- major_version: *major_version,
- image_type: image_type.to_string(),
- version: asset.version.semver.clone(),
- release_name: asset.release_name.clone(),
- release_date,
- file_size: asset.binary.package.size,
- checksum: asset.binary.package.checksum,
- download_url: asset.binary.package.link,
- is_lts: available
- .available_lts_releases
- .contains(major_version),
- is_available: true,
- architecture: asset.binary.architecture.clone(),
- });
- }
- }
- } else {
- // Platform not available for this version/type
- releases.push(JavaReleaseInfo {
- major_version: *major_version,
- image_type: image_type.to_string(),
- version: format!("{}.x", major_version),
- release_name: format!("jdk-{}", major_version),
- release_date: None,
- file_size: 0,
- checksum: None,
- download_url: String::new(),
- is_lts: available.available_lts_releases.contains(major_version),
- is_available: false,
- architecture: arch.to_string(),
- });
- }
- }
- Err(_) => {
- // Network error, mark as unavailable
- releases.push(JavaReleaseInfo {
- major_version: *major_version,
- image_type: image_type.to_string(),
- version: format!("{}.x", major_version),
- release_name: format!("jdk-{}", major_version),
- release_date: None,
- file_size: 0,
- checksum: None,
- download_url: String::new(),
- is_lts: available.available_lts_releases.contains(major_version),
- is_available: false,
- architecture: arch.to_string(),
- });
- }
- }
- }
- }
-
- let now = std::time::SystemTime::now()
- .duration_since(std::time::UNIX_EPOCH)
- .unwrap()
- .as_secs();
-
- let catalog = JavaCatalog {
- releases,
- available_major_versions: available.available_releases,
- lts_versions: available.available_lts_releases,
- cached_at: now,
- };
-
- // Save to cache
- let _ = save_catalog_cache(app_handle, &catalog);
-
- Ok(catalog)
-}
-
-/// Get Adoptium API download info for a specific Java version and image type
-///
-/// # Arguments
-/// * `major_version` - Java major version (e.g., 8, 11, 17)
-/// * `image_type` - JRE or JDK
-///
-/// # Returns
-/// * `Ok(JavaDownloadInfo)` - Download information
-/// * `Err(String)` - Error message
-pub async fn fetch_java_release(
- major_version: u32,
- image_type: ImageType,
-) -> Result {
- let os = get_adoptium_os();
- let arch = get_adoptium_arch();
-
- let url = format!(
- "{}/assets/latest/{}/hotspot?os={}&architecture={}&image_type={}",
- ADOPTIUM_API_BASE, major_version, os, arch, image_type
- );
-
- let client = reqwest::Client::new();
- let response = client
- .get(&url)
- .header("Accept", "application/json")
- .send()
- .await
- .map_err(|e| format!("Network request failed: {}", e))?;
-
- if !response.status().is_success() {
- return Err(format!(
- "Adoptium API returned error: {} - The version/platform might be unavailable",
- response.status()
- ));
- }
-
- let assets: Vec = response
- .json()
- .await
- .map_err(|e| format!("Failed to parse API response: {}", e))?;
-
- let asset = assets
- .into_iter()
- .next()
- .ok_or_else(|| format!("Java {} {} download not found", major_version, image_type))?;
-
- Ok(JavaDownloadInfo {
- version: asset.version.semver.clone(),
- release_name: asset.release_name,
- download_url: asset.binary.package.link,
- file_name: asset.binary.package.name,
- file_size: asset.binary.package.size,
- checksum: asset.binary.package.checksum,
- image_type: asset.binary.image_type,
- })
-}
-
-/// Fetch available Java versions from Adoptium API
-pub async fn fetch_available_versions() -> Result, String> {
- let url = format!("{}/info/available_releases", ADOPTIUM_API_BASE);
-
- let response = reqwest::get(url)
- .await
- .map_err(|e| format!("Network request failed: {}", e))?;
-
- #[derive(Deserialize)]
- struct AvailableReleases {
- available_releases: Vec,
- }
-
- let releases: AvailableReleases = response
- .json()
- .await
- .map_err(|e| format!("Failed to parse response: {}", e))?;
-
- Ok(releases.available_releases)
-}
-
-/// Download and install Java with resume support and progress events
-///
-/// # Arguments
-/// * `app_handle` - Tauri app handle for accessing app directories
-/// * `major_version` - Java major version (e.g., 8, 11, 17)
-/// * `image_type` - JRE or JDK
-/// * `custom_path` - Optional custom installation path
-///
-/// # Returns
-/// * `Ok(JavaInstallation)` - Information about the successfully installed Java
-pub async fn download_and_install_java(
- app_handle: &AppHandle,
- major_version: u32,
- image_type: ImageType,
- custom_path: Option,
-) -> Result {
- // 1. Fetch download information
- let info = fetch_java_release(major_version, image_type).await?;
- let file_name = info.file_name.clone();
-
- // 2. Prepare installation directory
- let install_base = custom_path.unwrap_or_else(|| get_java_install_dir(app_handle));
- let version_dir = install_base.join(format!("temurin-{}-{}", major_version, image_type));
-
- std::fs::create_dir_all(&install_base)
- .map_err(|e| format!("Failed to create installation directory: {}", e))?;
-
- // 3. Add to download queue for persistence
- let mut queue = DownloadQueue::load(app_handle);
- queue.add(PendingJavaDownload {
- major_version,
- image_type: image_type.to_string(),
- download_url: info.download_url.clone(),
- file_name: info.file_name.clone(),
- file_size: info.file_size,
- checksum: info.checksum.clone(),
- install_path: install_base.to_string_lossy().to_string(),
- created_at: std::time::SystemTime::now()
- .duration_since(std::time::UNIX_EPOCH)
- .unwrap()
- .as_secs(),
- });
- queue.save(app_handle)?;
-
- // 4. Download the archive with resume support
- let archive_path = install_base.join(&info.file_name);
-
- // Check if we need to download
- let need_download = if archive_path.exists() {
- if let Some(expected_checksum) = &info.checksum {
- let data = std::fs::read(&archive_path)
- .map_err(|e| format!("Failed to read downloaded file: {}", e))?;
- !downloader::verify_checksum(&data, Some(expected_checksum), None)
- } else {
- false
- }
- } else {
- true
- };
-
- if need_download {
- // Use resumable download
- downloader::download_with_resume(
- app_handle,
- &info.download_url,
- &archive_path,
- info.checksum.as_deref(),
- info.file_size,
- )
- .await?;
- }
-
- // 5. Emit extracting status
- let _ = app_handle.emit(
- "java-download-progress",
- JavaDownloadProgress {
- file_name: file_name.clone(),
- downloaded_bytes: info.file_size,
- total_bytes: info.file_size,
- speed_bytes_per_sec: 0,
- eta_seconds: 0,
- status: "Extracting".to_string(),
- percentage: 100.0,
- },
- );
-
- // 6. Extract
- // If the target directory exists, remove it first
- if version_dir.exists() {
- std::fs::remove_dir_all(&version_dir)
- .map_err(|e| format!("Failed to remove old version directory: {}", e))?;
- }
-
- std::fs::create_dir_all(&version_dir)
- .map_err(|e| format!("Failed to create version directory: {}", e))?;
-
- let top_level_dir = if info.file_name.ends_with(".tar.gz") || info.file_name.ends_with(".tgz") {
- zip::extract_tar_gz(&archive_path, &version_dir)?
- } else if info.file_name.ends_with(".zip") {
- zip::extract_zip(&archive_path, &version_dir)?;
- // Find the top-level directory inside the extracted folder
- find_top_level_dir(&version_dir)?
- } else {
- return Err(format!("Unsupported archive format: {}", info.file_name));
- };
-
- // 7. Clean up downloaded archive
- let _ = std::fs::remove_file(&archive_path);
-
- // 8. Locate java executable
- // macOS has a different structure: jdk-xxx/Contents/Home/bin/java
- // Linux/Windows: jdk-xxx/bin/java
- let java_home = version_dir.join(&top_level_dir);
- let java_bin = if cfg!(target_os = "macos") {
- java_home
- .join("Contents")
- .join("Home")
- .join("bin")
- .join("java")
- } else if cfg!(windows) {
- java_home.join("bin").join("java.exe")
- } else {
- java_home.join("bin").join("java")
- };
-
- if !java_bin.exists() {
- return Err(format!(
- "Installation completed but Java executable not found: {}",
- java_bin.display()
- ));
- }
-
- // Resolve symlinks and strip UNC prefix to ensure clean path
- let java_bin = std::fs::canonicalize(&java_bin).map_err(|e| e.to_string())?;
- let java_bin = strip_unc_prefix(java_bin);
-
- // 9. Verify installation
- let installation = check_java_installation(&java_bin)
- .ok_or_else(|| "Failed to verify Java installation".to_string())?;
-
- // 10. Remove from download queue
- queue.remove(major_version, &image_type.to_string());
- queue.save(app_handle)?;
-
- // 11. Emit completed status
- let _ = app_handle.emit(
- "java-download-progress",
- JavaDownloadProgress {
- file_name,
- downloaded_bytes: info.file_size,
- total_bytes: info.file_size,
- speed_bytes_per_sec: 0,
- eta_seconds: 0,
- status: "Completed".to_string(),
- percentage: 100.0,
- },
- );
-
- Ok(installation)
-}
-
-/// Find the top-level directory inside the extracted folder
-fn find_top_level_dir(extract_dir: &PathBuf) -> Result {
- let entries: Vec<_> = std::fs::read_dir(extract_dir)
- .map_err(|e| format!("Failed to read directory: {}", e))?
- .filter_map(|e| e.ok())
- .filter(|e| e.path().is_dir())
- .collect();
-
- if entries.len() == 1 {
- Ok(entries[0].file_name().to_string_lossy().to_string())
- } else {
- // No single top-level directory, return empty string
- Ok(String::new())
- }
-}
-
-/// Detect Java installations on the system
-pub fn detect_java_installations() -> Vec {
- let mut installations = Vec::new();
- let candidates = get_java_candidates();
-
- for candidate in candidates {
- if let Some(java) = check_java_installation(&candidate) {
- // Avoid duplicates
- if !installations
- .iter()
- .any(|j: &JavaInstallation| j.path == java.path)
- {
- installations.push(java);
- }
- }
- }
-
- // Sort by version (newer first)
- installations.sort_by(|a, b| {
- let v_a = parse_java_version(&a.version);
- let v_b = parse_java_version(&b.version);
- v_b.cmp(&v_a)
- });
-
- installations
-}
-
-/// Get list of candidate Java paths to check
-fn get_java_candidates() -> Vec {
- let mut candidates = Vec::new();
-
- // Check PATH first
- let mut cmd = Command::new(if cfg!(windows) { "where" } else { "which" });
- cmd.arg("java");
- #[cfg(target_os = "windows")]
- cmd.creation_flags(0x08000000);
-
- if let Ok(output) = cmd.output() {
- if output.status.success() {
- let paths = String::from_utf8_lossy(&output.stdout);
- for line in paths.lines() {
- let path = PathBuf::from(line.trim());
- if path.exists() {
- // Resolve symlinks (important for Windows javapath wrapper)
- let resolved = std::fs::canonicalize(&path).unwrap_or(path);
- // Strip UNC prefix if present to keep paths clean
- let final_path = strip_unc_prefix(resolved);
- candidates.push(final_path);
- }
- }
- }
- }
-
- #[cfg(target_os = "linux")]
- {
- // Common Linux Java paths
- let linux_paths = [
- "/usr/lib/jvm",
- "/usr/java",
- "/opt/java",
- "/opt/jdk",
- "/opt/openjdk",
- ];
-
- for base in &linux_paths {
- if let Ok(entries) = std::fs::read_dir(base) {
- for entry in entries.flatten() {
- let java_path = entry.path().join("bin/java");
- if java_path.exists() {
- candidates.push(java_path);
- }
- }
- }
- }
-
- // Flatpak / Snap locations
- let home = std::env::var("HOME").unwrap_or_default();
- let snap_java = PathBuf::from(&home).join(".sdkman/candidates/java");
- if snap_java.exists() {
- if let Ok(entries) = std::fs::read_dir(&snap_java) {
- for entry in entries.flatten() {
- let java_path = entry.path().join("bin/java");
- if java_path.exists() {
- candidates.push(java_path);
- }
- }
- }
- }
- }
-
- #[cfg(target_os = "macos")]
- {
- // macOS Java paths
- let mac_paths = [
- "/Library/Java/JavaVirtualMachines",
- "/System/Library/Java/JavaVirtualMachines",
- "/usr/local/opt/openjdk/bin/java",
- "/opt/homebrew/opt/openjdk/bin/java",
- ];
-
- for path in &mac_paths {
- let p = PathBuf::from(path);
- if p.is_dir() {
- if let Ok(entries) = std::fs::read_dir(&p) {
- for entry in entries.flatten() {
- let java_path = entry.path().join("Contents/Home/bin/java");
- if java_path.exists() {
- candidates.push(java_path);
- }
- }
- }
- } else if p.exists() {
- candidates.push(p);
- }
- }
-
- // Homebrew ARM64
- let homebrew_arm = PathBuf::from("/opt/homebrew/Cellar/openjdk");
- if homebrew_arm.exists() {
- if let Ok(entries) = std::fs::read_dir(&homebrew_arm) {
- for entry in entries.flatten() {
- let java_path = entry
- .path()
- .join("libexec/openjdk.jdk/Contents/Home/bin/java");
- if java_path.exists() {
- candidates.push(java_path);
- }
- }
- }
- }
- }
-
- #[cfg(target_os = "windows")]
- {
- // Windows Java paths
- let program_files =
- std::env::var("ProgramFiles").unwrap_or_else(|_| "C:\\Program Files".to_string());
- let program_files_x86 = std::env::var("ProgramFiles(x86)")
- .unwrap_or_else(|_| "C:\\Program Files (x86)".to_string());
- let local_app_data = std::env::var("LOCALAPPDATA").unwrap_or_default();
-
- let win_paths = [
- format!("{}\\Java", program_files),
- format!("{}\\Java", program_files_x86),
- format!("{}\\Eclipse Adoptium", program_files),
- format!("{}\\AdoptOpenJDK", program_files),
- format!("{}\\Microsoft\\jdk", program_files),
- format!("{}\\Zulu", program_files),
- format!("{}\\Amazon Corretto", program_files),
- format!("{}\\BellSoft\\LibericaJDK", program_files),
- format!("{}\\Programs\\Eclipse Adoptium", local_app_data),
- ];
-
- for base in &win_paths {
- let base_path = PathBuf::from(base);
- if base_path.exists() {
- if let Ok(entries) = std::fs::read_dir(&base_path) {
- for entry in entries.flatten() {
- let java_path = entry.path().join("bin\\java.exe");
- if java_path.exists() {
- candidates.push(java_path);
- }
- }
- }
- }
- }
-
- // Also check JAVA_HOME
- if let Ok(java_home) = std::env::var("JAVA_HOME") {
- let java_path = PathBuf::from(&java_home).join("bin\\java.exe");
- if java_path.exists() {
- candidates.push(java_path);
- }
- }
- }
-
- // JAVA_HOME environment variable (cross-platform)
- if let Ok(java_home) = std::env::var("JAVA_HOME") {
- let bin_name = if cfg!(windows) { "java.exe" } else { "java" };
- let java_path = PathBuf::from(&java_home).join("bin").join(bin_name);
- if java_path.exists() {
- candidates.push(java_path);
- }
- }
-
- candidates
-}
-
-/// Check a specific Java installation and get its version info
-fn check_java_installation(path: &PathBuf) -> Option {
- let mut cmd = Command::new(path);
- cmd.arg("-version");
- #[cfg(target_os = "windows")]
- cmd.creation_flags(0x08000000);
-
- let output = cmd.output().ok()?;
-
- // Java outputs version info to stderr
- let version_output = String::from_utf8_lossy(&output.stderr);
-
- // Parse version string (e.g., "openjdk version \"17.0.1\"" or "java version \"1.8.0_301\"")
- let version = parse_version_string(&version_output)?;
- let is_64bit = version_output.contains("64-Bit");
-
- Some(JavaInstallation {
- path: path.to_string_lossy().to_string(),
- version,
- is_64bit,
- })
-}
-
-/// Parse version string from java -version output
-fn parse_version_string(output: &str) -> Option {
- for line in output.lines() {
- if line.contains("version") {
- // Find the quoted version string
- if let Some(start) = line.find('"') {
- if let Some(end) = line[start + 1..].find('"') {
- return Some(line[start + 1..start + 1 + end].to_string());
- }
- }
- }
- }
- None
-}
-
-/// Parse version for comparison (returns major version number)
-fn parse_java_version(version: &str) -> u32 {
- // Handle various formats:
- // - Old format: 1.8.0_xxx (Java 8 with update)
- // - New format: 17.0.1, 11.0.5+10 (Java 11+)
- // - Format with build: 21.0.3+13-Ubuntu-0ubuntu0.24.04.1
- // - Format with underscores: 1.8.0_411
-
- // First, strip build metadata (everything after '+')
- let version_only = version.split('+').next().unwrap_or(version);
-
- // Remove trailing junk (like "-Ubuntu-0ubuntu0.24.04.1")
- let version_only = version_only.split('-').next().unwrap_or(version_only);
-
- // Replace underscores with dots (1.8.0_411 -> 1.8.0.411)
- let normalized = version_only.replace('_', ".");
-
- // Split by dots
- let parts: Vec<&str> = normalized.split('.').collect();
-
- if let Some(first) = parts.first() {
- if *first == "1" {
- // Old format: 1.8.0 -> major is 8
- parts.get(1).and_then(|s| s.parse().ok()).unwrap_or(0)
- } else {
- // New format: 17.0.1 -> major is 17
- first.parse().unwrap_or(0)
- }
- } else {
- 0
- }
-}
-
-/// Get the best Java for a specific Minecraft version
-pub fn get_recommended_java(required_major_version: Option) -> Option {
- let installations = detect_java_installations();
-
- if let Some(required) = required_major_version {
- // Find exact match or higher
- installations.into_iter().find(|java| {
- let major = parse_java_version(&java.version);
- major >= required as u32
- })
- } else {
- // Return newest
- installations.into_iter().next()
- }
-}
-
-/// Get compatible Java for a specific Minecraft version with upper bound
-/// For older Minecraft versions (1.13.x and below), we need Java 8 specifically
-/// as newer Java versions have compatibility issues with old Forge versions
-pub fn get_compatible_java(
- app_handle: &AppHandle,
- required_major_version: Option,
- max_major_version: Option,
-) -> Option {
- let installations = detect_all_java_installations(app_handle);
-
- if let Some(max_version) = max_major_version {
- // Find Java version within the acceptable range
- installations.into_iter().find(|java| {
- let major = parse_java_version(&java.version);
- let meets_min = if let Some(required) = required_major_version {
- major >= required as u32
- } else {
- true
- };
- meets_min && major <= max_version
- })
- } else if let Some(required) = required_major_version {
- // Find exact match or higher (no upper bound)
- installations.into_iter().find(|java| {
- let major = parse_java_version(&java.version);
- major >= required as u32
- })
- } else {
- // Return newest
- installations.into_iter().next()
- }
-}
-
-/// Check if a Java installation is compatible with the required version range
-pub fn is_java_compatible(
- java_path: &str,
- required_major_version: Option,
- max_major_version: Option,
-) -> bool {
- let java_path_buf = PathBuf::from(java_path);
- if let Some(java) = check_java_installation(&java_path_buf) {
- let major = parse_java_version(&java.version);
- let meets_min = if let Some(required) = required_major_version {
- major >= required as u32
- } else {
- true
- };
- let meets_max = if let Some(max_version) = max_major_version {
- major <= max_version
- } else {
- true
- };
- meets_min && meets_max
- } else {
- false
- }
-}
-
-/// Detect all installed Java versions (including system installations and DropOut downloads)
-pub fn detect_all_java_installations(app_handle: &AppHandle) -> Vec {
- let mut installations = detect_java_installations();
-
- // Add DropOut downloaded Java versions
- let dropout_java_dir = get_java_install_dir(app_handle);
- if dropout_java_dir.exists() {
- if let Ok(entries) = std::fs::read_dir(&dropout_java_dir) {
- for entry in entries.flatten() {
- let path = entry.path();
- if path.is_dir() {
- // Find the java executable in this directory
- let java_bin = find_java_executable(&path);
- if let Some(java_path) = java_bin {
- if let Some(java) = check_java_installation(&java_path) {
- if !installations.iter().any(|j| j.path == java.path) {
- installations.push(java);
- }
- }
- }
- }
- }
- }
- }
-
- // Sort by version
- installations.sort_by(|a, b| {
- let v_a = parse_java_version(&a.version);
- let v_b = parse_java_version(&b.version);
- v_b.cmp(&v_a)
- });
-
- installations
-}
-
-/// Find the java executable in a directory using a limited-depth search
-fn find_java_executable(dir: &PathBuf) -> Option {
- let bin_name = if cfg!(windows) { "java.exe" } else { "java" };
-
- // Directly look in the bin directory
- let direct_bin = dir.join("bin").join(bin_name);
- if direct_bin.exists() {
- let resolved = std::fs::canonicalize(&direct_bin).unwrap_or(direct_bin);
- return Some(strip_unc_prefix(resolved));
- }
-
- // macOS: Contents/Home/bin/java
- #[cfg(target_os = "macos")]
- {
- let macos_bin = dir.join("Contents").join("Home").join("bin").join(bin_name);
- if macos_bin.exists() {
- return Some(macos_bin);
- }
- }
-
- // Look in subdirectories (handle nested directories after Adoptium extraction)
- if let Ok(entries) = std::fs::read_dir(dir) {
- for entry in entries.flatten() {
- let path = entry.path();
- if path.is_dir() {
- // Try direct bin path
- let nested_bin = path.join("bin").join(bin_name);
- if nested_bin.exists() {
- let resolved = std::fs::canonicalize(&nested_bin).unwrap_or(nested_bin);
- return Some(strip_unc_prefix(resolved));
- }
-
- // macOS: nested/Contents/Home/bin/java
- #[cfg(target_os = "macos")]
- {
- let macos_nested = path
- .join("Contents")
- .join("Home")
- .join("bin")
- .join(bin_name);
- if macos_nested.exists() {
- return Some(macos_nested);
- }
- }
- }
- }
- }
-
- None
-}
-
-/// Resume pending Java downloads from queue
-pub async fn resume_pending_downloads(
- app_handle: &AppHandle,
-) -> Result, String> {
- let queue = DownloadQueue::load(app_handle);
- let mut installed = Vec::new();
-
- for pending in queue.pending_downloads.iter() {
- let image_type = if pending.image_type == "jdk" {
- ImageType::Jdk
- } else {
- ImageType::Jre
- };
-
- // Try to resume the download
- match download_and_install_java(
- app_handle,
- pending.major_version,
- image_type,
- Some(PathBuf::from(&pending.install_path)),
- )
- .await
- {
- Ok(installation) => {
- installed.push(installation);
- }
- Err(e) => {
- eprintln!(
- "Failed to resume Java {} {} download: {}",
- pending.major_version, pending.image_type, e
- );
- }
- }
- }
-
- Ok(installed)
-}
-
-/// Cancel current Java download
-pub fn cancel_current_download() {
- downloader::cancel_java_download();
-}
-
-/// Get pending downloads from queue
-pub fn get_pending_downloads(app_handle: &AppHandle) -> Vec {
- let queue = DownloadQueue::load(app_handle);
- queue.pending_downloads
-}
-
-/// Clear a specific pending download
-#[allow(dead_code)]
-pub fn clear_pending_download(
- app_handle: &AppHandle,
- major_version: u32,
- image_type: &str,
-) -> Result<(), String> {
- let mut queue = DownloadQueue::load(app_handle);
- queue.remove(major_version, image_type);
- queue.save(app_handle)
-}
diff --git a/src-tauri/src/core/java/detection.rs b/src-tauri/src/core/java/detection.rs
new file mode 100644
index 0000000..95e7803
--- /dev/null
+++ b/src-tauri/src/core/java/detection.rs
@@ -0,0 +1,247 @@
+use std::io::Read;
+use std::path::PathBuf;
+use std::process::{Command, Stdio};
+use std::time::Duration;
+
+#[cfg(target_os = "windows")]
+use std::os::windows::process::CommandExt;
+
+use super::strip_unc_prefix;
+
+const WHICH_TIMEOUT: Duration = Duration::from_secs(2);
+
+/// Finds Java installation from SDKMAN! if available
+///
+/// Checks the standard SDKMAN! installation path:
+/// `~/.sdkman/candidates/java/current/bin/java`
+///
+/// # Returns
+/// `Some(PathBuf)` if SDKMAN! Java is found and exists, `None` otherwise
+pub fn find_sdkman_java() -> Option {
+ let home = std::env::var("HOME").ok()?;
+ let sdkman_path = PathBuf::from(&home).join(".sdkman/candidates/java/current/bin/java");
+ if sdkman_path.exists() {
+ Some(sdkman_path)
+ } else {
+ None
+ }
+}
+
+/// Runs `which` (Unix) or `where` (Windows) command to find Java in PATH with timeout
+///
+/// This function spawns a subprocess to locate the `java` executable in the system PATH.
+/// It enforces a 2-second timeout to prevent hanging if the command takes too long.
+///
+/// # Returns
+/// `Some(String)` containing the output (paths separated by newlines) if successful,
+/// `None` if the command fails, times out, or returns non-zero exit code
+///
+/// # Platform-specific behavior
+/// - Unix/Linux/macOS: Uses `which java`
+/// - Windows: Uses `where java` and hides the console window
+///
+/// # Timeout Behavior
+/// If the command does not complete within 2 seconds, the process is killed
+/// and `None` is returned. This prevents the launcher from hanging on systems
+/// where `which`/`where` may be slow or unresponsive.
+fn run_which_command_with_timeout() -> Option {
+ let mut cmd = Command::new(if cfg!(windows) { "where" } else { "which" });
+ cmd.arg("java");
+ // Hide console window on Windows
+ #[cfg(target_os = "windows")]
+ cmd.creation_flags(0x08000000);
+ cmd.stdout(Stdio::piped());
+
+ let mut child = cmd.spawn().ok()?;
+ let start = std::time::Instant::now();
+
+ loop {
+ // Check if timeout has been exceeded
+ if start.elapsed() > WHICH_TIMEOUT {
+ let _ = child.kill();
+ let _ = child.wait();
+ return None;
+ }
+
+ match child.try_wait() {
+ Ok(Some(status)) => {
+ if status.success() {
+ let mut output = String::new();
+ if let Some(mut stdout) = child.stdout.take() {
+ let _ = stdout.read_to_string(&mut output);
+ }
+ return Some(output);
+ } else {
+ let _ = child.wait();
+ return None;
+ }
+ }
+ Ok(None) => {
+ // Command still running, sleep briefly before checking again
+ std::thread::sleep(Duration::from_millis(50));
+ }
+ Err(_) => {
+ let _ = child.kill();
+ let _ = child.wait();
+ return None;
+ }
+ }
+ }
+}
+
+/// Detects all available Java installations on the system
+///
+/// This function searches for Java installations in multiple locations:
+/// - **All platforms**: `JAVA_HOME` environment variable, `java` in PATH
+/// - **Linux**: `/usr/lib/jvm`, `/usr/java`, `/opt/java`, `/opt/jdk`, `/opt/openjdk`, SDKMAN!
+/// - **macOS**: `/Library/Java/JavaVirtualMachines`, `/System/Library/Java/JavaVirtualMachines`,
+/// Homebrew paths (`/usr/local/opt/openjdk`, `/opt/homebrew/opt/openjdk`), SDKMAN!
+/// - **Windows**: `Program Files`, `Program Files (x86)`, `LOCALAPPDATA` for various JDK distributions
+///
+/// # Returns
+/// A vector of `PathBuf` pointing to Java executables found on the system.
+/// Note: Paths may include symlinks and duplicates; callers should canonicalize and deduplicate as needed.
+///
+/// # Examples
+/// ```ignore
+/// let candidates = get_java_candidates();
+/// for java_path in candidates {
+/// println!("Found Java at: {}", java_path.display());
+/// }
+/// ```
+pub fn get_java_candidates() -> Vec {
+ let mut candidates = Vec::new();
+
+ // Try to find Java in PATH using 'which' or 'where' command with timeout
+ // CAUTION: linux 'which' may return symlinks, so we need to canonicalize later
+ if let Some(paths_str) = run_which_command_with_timeout() {
+ for line in paths_str.lines() {
+ let path = PathBuf::from(line.trim());
+ if path.exists() {
+ let resolved = std::fs::canonicalize(&path).unwrap_or(path);
+ let final_path = strip_unc_prefix(resolved);
+ candidates.push(final_path);
+ }
+ }
+ }
+
+ #[cfg(target_os = "linux")]
+ {
+ let linux_paths = [
+ "/usr/lib/jvm",
+ "/usr/java",
+ "/opt/java",
+ "/opt/jdk",
+ "/opt/openjdk",
+ ];
+
+ for base in &linux_paths {
+ if let Ok(entries) = std::fs::read_dir(base) {
+ for entry in entries.flatten() {
+ let java_path = entry.path().join("bin/java");
+ if java_path.exists() {
+ candidates.push(java_path);
+ }
+ }
+ }
+ }
+
+ // Check common SDKMAN! java candidates
+ if let Some(sdkman_java) = find_sdkman_java() {
+ candidates.push(sdkman_java);
+ }
+ }
+
+ #[cfg(target_os = "macos")]
+ {
+ let mac_paths = [
+ "/Library/Java/JavaVirtualMachines",
+ "/System/Library/Java/JavaVirtualMachines",
+ "/usr/local/opt/openjdk/bin/java",
+ "/opt/homebrew/opt/openjdk/bin/java",
+ ];
+
+ for path in &mac_paths {
+ let p = PathBuf::from(path);
+ if p.is_dir() {
+ if let Ok(entries) = std::fs::read_dir(&p) {
+ for entry in entries.flatten() {
+ let java_path = entry.path().join("Contents/Home/bin/java");
+ if java_path.exists() {
+ candidates.push(java_path);
+ }
+ }
+ }
+ } else if p.exists() {
+ candidates.push(p);
+ }
+ }
+
+ // Check common Homebrew java candidates for aarch64 macs
+ let homebrew_arm = PathBuf::from("/opt/homebrew/Cellar/openjdk");
+ if homebrew_arm.exists() {
+ if let Ok(entries) = std::fs::read_dir(&homebrew_arm) {
+ for entry in entries.flatten() {
+ let java_path = entry
+ .path()
+ .join("libexec/openjdk.jdk/Contents/Home/bin/java");
+ if java_path.exists() {
+ candidates.push(java_path);
+ }
+ }
+ }
+ }
+
+ // Check common SDKMAN! java candidates
+ if let Some(sdkman_java) = find_sdkman_java() {
+ candidates.push(sdkman_java);
+ }
+ }
+
+ #[cfg(target_os = "windows")]
+ {
+ let program_files =
+ std::env::var("ProgramFiles").unwrap_or_else(|_| "C:\\Program Files".to_string());
+ let program_files_x86 = std::env::var("ProgramFiles(x86)")
+ .unwrap_or_else(|_| "C:\\Program Files (x86)".to_string());
+ let local_app_data = std::env::var("LOCALAPPDATA").unwrap_or_default();
+
+ // Common installation paths for various JDK distributions
+ let mut win_paths = vec![];
+ for base in &[&program_files, &program_files_x86, &local_app_data] {
+ win_paths.push(format!("{}\\Java", base));
+ win_paths.push(format!("{}\\Eclipse Adoptium", base));
+ win_paths.push(format!("{}\\AdoptOpenJDK", base));
+ win_paths.push(format!("{}\\Microsoft\\jdk", base));
+ win_paths.push(format!("{}\\Zulu", base));
+ win_paths.push(format!("{}\\Amazon Corretto", base));
+ win_paths.push(format!("{}\\BellSoft\\LibericaJDK", base));
+ win_paths.push(format!("{}\\Programs\\Eclipse Adoptium", base));
+ }
+
+ for base in &win_paths {
+ let base_path = PathBuf::from(base);
+ if base_path.exists() {
+ if let Ok(entries) = std::fs::read_dir(&base_path) {
+ for entry in entries.flatten() {
+ let java_path = entry.path().join("bin\\java.exe");
+ if java_path.exists() {
+ candidates.push(java_path);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Check JAVA_HOME environment variable
+ if let Ok(java_home) = std::env::var("JAVA_HOME") {
+ let bin_name = if cfg!(windows) { "java.exe" } else { "java" };
+ let java_path = PathBuf::from(&java_home).join("bin").join(bin_name);
+ if java_path.exists() {
+ candidates.push(java_path);
+ }
+ }
+
+ candidates
+}
diff --git a/src-tauri/src/core/java/error.rs b/src-tauri/src/core/java/error.rs
new file mode 100644
index 0000000..bf78d3b
--- /dev/null
+++ b/src-tauri/src/core/java/error.rs
@@ -0,0 +1,95 @@
+use std::fmt;
+
+/// Unified error type for Java component operations
+///
+/// This enum represents all possible errors that can occur in the Java component,
+/// providing a consistent error handling interface across all modules.
+#[derive(Debug, Clone)]
+pub enum JavaError {
+ // Java installation not found at the specified path
+ NotFound,
+ // Invalid Java version format or unable to parse version
+ InvalidVersion(String),
+ // Java installation verification failed (e.g., -version command failed)
+ VerificationFailed(String),
+ // Network error during API calls or downloads
+ NetworkError(String),
+ // File I/O error (reading, writing, or accessing files)
+ IoError(String),
+ // Timeout occurred during operation
+ Timeout(String),
+ // Serialization/deserialization error
+ SerializationError(String),
+ // Invalid configuration or parameters
+ InvalidConfig(String),
+ // Download or installation failed
+ DownloadFailed(String),
+ // Extraction or decompression failed
+ ExtractionFailed(String),
+ // Checksum verification failed
+ ChecksumMismatch(String),
+ // Other unspecified errors
+ Other(String),
+}
+
+impl fmt::Display for JavaError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ JavaError::NotFound => write!(f, "Java installation not found"),
+ JavaError::InvalidVersion(msg) => write!(f, "Invalid Java version: {}", msg),
+ JavaError::VerificationFailed(msg) => write!(f, "Java verification failed: {}", msg),
+ JavaError::NetworkError(msg) => write!(f, "Network error: {}", msg),
+ JavaError::IoError(msg) => write!(f, "I/O error: {}", msg),
+ JavaError::Timeout(msg) => write!(f, "Operation timeout: {}", msg),
+ JavaError::SerializationError(msg) => write!(f, "Serialization error: {}", msg),
+ JavaError::InvalidConfig(msg) => write!(f, "Invalid configuration: {}", msg),
+ JavaError::DownloadFailed(msg) => write!(f, "Download failed: {}", msg),
+ JavaError::ExtractionFailed(msg) => write!(f, "Extraction failed: {}", msg),
+ JavaError::ChecksumMismatch(msg) => write!(f, "Checksum mismatch: {}", msg),
+ JavaError::Other(msg) => write!(f, "{}", msg),
+ }
+ }
+}
+
+impl std::error::Error for JavaError {}
+
+/// Convert JavaError to String for Tauri command results
+impl From for String {
+ fn from(err: JavaError) -> Self {
+ err.to_string()
+ }
+}
+
+/// Convert std::io::Error to JavaError
+impl From for JavaError {
+ fn from(err: std::io::Error) -> Self {
+ JavaError::IoError(err.to_string())
+ }
+}
+
+/// Convert serde_json::Error to JavaError
+impl From for JavaError {
+ fn from(err: serde_json::Error) -> Self {
+ JavaError::SerializationError(err.to_string())
+ }
+}
+
+/// Convert reqwest::Error to JavaError
+impl From for JavaError {
+ fn from(err: reqwest::Error) -> Self {
+ if err.is_timeout() {
+ JavaError::Timeout(err.to_string())
+ } else if err.is_connect() || err.is_request() {
+ JavaError::NetworkError(err.to_string())
+ } else {
+ JavaError::NetworkError(err.to_string())
+ }
+ }
+}
+
+/// Convert String to JavaError
+impl From for JavaError {
+ fn from(err: String) -> Self {
+ JavaError::Other(err)
+ }
+}
diff --git a/src-tauri/src/core/java/mod.rs b/src-tauri/src/core/java/mod.rs
new file mode 100644
index 0000000..770ba08
--- /dev/null
+++ b/src-tauri/src/core/java/mod.rs
@@ -0,0 +1,530 @@
+use serde::{Deserialize, Serialize};
+use std::path::PathBuf;
+use tauri::{AppHandle, Emitter, Manager};
+
+pub mod detection;
+pub mod error;
+pub mod persistence;
+pub mod priority;
+pub mod provider;
+pub mod providers;
+pub mod validation;
+
+pub use error::JavaError;
+
+/// Remove the UNC prefix (\\?\) from Windows paths
+pub fn strip_unc_prefix(path: PathBuf) -> PathBuf {
+ #[cfg(target_os = "windows")]
+ {
+ let s = path.to_string_lossy().to_string();
+ if s.starts_with(r"\\?\\") {
+ return PathBuf::from(&s[4..]);
+ }
+ }
+ path
+}
+
+use crate::core::downloader::{DownloadQueue, JavaDownloadProgress, PendingJavaDownload};
+use crate::utils::zip;
+use provider::JavaProvider;
+use providers::AdoptiumProvider;
+
+const CACHE_DURATION_SECS: u64 = 24 * 60 * 60;
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct JavaInstallation {
+ pub path: String,
+ pub version: String,
+ pub arch: String,
+ pub vendor: String,
+ pub source: String,
+ pub is_64bit: bool,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "lowercase")]
+pub enum ImageType {
+ Jre,
+ Jdk,
+}
+
+impl Default for ImageType {
+ fn default() -> Self {
+ Self::Jre
+ }
+}
+
+impl std::fmt::Display for ImageType {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Self::Jre => write!(f, "jre"),
+ Self::Jdk => write!(f, "jdk"),
+ }
+ }
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct JavaReleaseInfo {
+ pub major_version: u32,
+ pub image_type: String,
+ pub version: String,
+ pub release_name: String,
+ pub release_date: Option,
+ pub file_size: u64,
+ pub checksum: Option,
+ pub download_url: String,
+ pub is_lts: bool,
+ pub is_available: bool,
+ pub architecture: String,
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize, Default)]
+pub struct JavaCatalog {
+ pub releases: Vec,
+ pub available_major_versions: Vec,
+ pub lts_versions: Vec,
+ pub cached_at: u64,
+}
+
+#[derive(Debug, Clone, Serialize)]
+pub struct JavaDownloadInfo {
+ pub version: String, // e.g., "17.0.2+8"
+ pub release_name: String, // e.g., "jdk-17.0.2+8"
+ pub download_url: String, // Direct download URL
+ pub file_name: String, // e.g., "OpenJDK17U-jre_x64_linux_hotspot_17.0.2_8.tar.gz"
+ pub file_size: u64, // in bytes
+ pub checksum: Option, // SHA256 checksum
+ pub image_type: String, // "jre" or "jdk"
+}
+
+pub fn get_java_install_dir(app_handle: &AppHandle) -> PathBuf {
+ app_handle.path().app_data_dir().unwrap().join("java")
+}
+
+fn get_catalog_cache_path(app_handle: &AppHandle) -> PathBuf {
+ app_handle
+ .path()
+ .app_data_dir()
+ .unwrap()
+ .join("java_catalog_cache.json")
+}
+
+pub fn load_cached_catalog(app_handle: &AppHandle) -> Option {
+ let cache_path = get_catalog_cache_path(app_handle);
+ if !cache_path.exists() {
+ return None;
+ }
+
+ // Read cache file
+ let content = std::fs::read_to_string(&cache_path).ok()?;
+ let catalog: JavaCatalog = serde_json::from_str(&content).ok()?;
+
+ // Get current time in seconds since UNIX_EPOCH
+ let now = std::time::SystemTime::now()
+ .duration_since(std::time::UNIX_EPOCH)
+ .unwrap()
+ .as_secs();
+
+ // Check if cache is still valid
+ if now - catalog.cached_at < CACHE_DURATION_SECS {
+ Some(catalog)
+ } else {
+ None
+ }
+}
+
+pub fn save_catalog_cache(app_handle: &AppHandle, catalog: &JavaCatalog) -> Result<(), String> {
+ let cache_path = get_catalog_cache_path(app_handle);
+ let content = serde_json::to_string_pretty(catalog).map_err(|e| e.to_string())?;
+ std::fs::write(&cache_path, content).map_err(|e| e.to_string())?;
+ Ok(())
+}
+
+#[allow(dead_code)]
+pub fn clear_catalog_cache(app_handle: &AppHandle) -> Result<(), String> {
+ let cache_path = get_catalog_cache_path(app_handle);
+ if cache_path.exists() {
+ std::fs::remove_file(&cache_path).map_err(|e| e.to_string())?;
+ }
+ Ok(())
+}
+
+pub async fn fetch_java_catalog(
+ app_handle: &AppHandle,
+ force_refresh: bool,
+) -> Result {
+ let provider = AdoptiumProvider::new();
+ provider
+ .fetch_catalog(app_handle, force_refresh)
+ .await
+ .map_err(|e| e.to_string())
+}
+
+pub async fn fetch_java_release(
+ major_version: u32,
+ image_type: ImageType,
+) -> Result {
+ let provider = AdoptiumProvider::new();
+ provider
+ .fetch_release(major_version, image_type)
+ .await
+ .map_err(|e| e.to_string())
+}
+
+pub async fn fetch_available_versions() -> Result, String> {
+ let provider = AdoptiumProvider::new();
+ provider
+ .available_versions()
+ .await
+ .map_err(|e| e.to_string())
+}
+
+pub async fn download_and_install_java(
+ app_handle: &AppHandle,
+ major_version: u32,
+ image_type: ImageType,
+ custom_path: Option,
+) -> Result {
+ let provider = AdoptiumProvider::new();
+ let info = provider.fetch_release(major_version, image_type).await?;
+ let file_name = info.file_name.clone();
+
+ let install_base = custom_path.unwrap_or_else(|| get_java_install_dir(app_handle));
+ let version_dir = install_base.join(format!(
+ "{}-{}-{}",
+ provider.install_prefix(),
+ major_version,
+ image_type
+ ));
+
+ std::fs::create_dir_all(&install_base)
+ .map_err(|e| format!("Failed to create installation directory: {}", e))?;
+
+ let mut queue = DownloadQueue::load(app_handle);
+ queue.add(PendingJavaDownload {
+ major_version,
+ image_type: image_type.to_string(),
+ download_url: info.download_url.clone(),
+ file_name: info.file_name.clone(),
+ file_size: info.file_size,
+ checksum: info.checksum.clone(),
+ install_path: install_base.to_string_lossy().to_string(),
+ created_at: std::time::SystemTime::now()
+ .duration_since(std::time::UNIX_EPOCH)
+ .unwrap()
+ .as_secs(),
+ });
+ queue.save(app_handle)?;
+
+ let archive_path = install_base.join(&info.file_name);
+
+ let need_download = if archive_path.exists() {
+ if let Some(expected_checksum) = &info.checksum {
+ let data = std::fs::read(&archive_path)
+ .map_err(|e| format!("Failed to read downloaded file: {}", e))?;
+ !crate::core::downloader::verify_checksum(&data, Some(expected_checksum), None)
+ } else {
+ false
+ }
+ } else {
+ true
+ };
+
+ if need_download {
+ crate::core::downloader::download_with_resume(
+ app_handle,
+ &info.download_url,
+ &archive_path,
+ info.checksum.as_deref(),
+ info.file_size,
+ )
+ .await?;
+ }
+
+ let _ = app_handle.emit(
+ "java-download-progress",
+ JavaDownloadProgress {
+ file_name: file_name.clone(),
+ downloaded_bytes: info.file_size,
+ total_bytes: info.file_size,
+ speed_bytes_per_sec: 0,
+ eta_seconds: 0,
+ status: "Extracting".to_string(),
+ percentage: 100.0,
+ },
+ );
+
+ if version_dir.exists() {
+ std::fs::remove_dir_all(&version_dir)
+ .map_err(|e| format!("Failed to remove old version directory: {}", e))?;
+ }
+
+ std::fs::create_dir_all(&version_dir)
+ .map_err(|e| format!("Failed to create version directory: {}", e))?;
+
+ let top_level_dir = if info.file_name.ends_with(".tar.gz") || info.file_name.ends_with(".tgz") {
+ zip::extract_tar_gz(&archive_path, &version_dir)?
+ } else if info.file_name.ends_with(".zip") {
+ zip::extract_zip(&archive_path, &version_dir)?;
+ find_top_level_dir(&version_dir)?
+ } else {
+ return Err(format!("Unsupported archive format: {}", info.file_name));
+ };
+
+ let _ = std::fs::remove_file(&archive_path);
+
+ let java_home = version_dir.join(&top_level_dir);
+ let java_bin = if cfg!(target_os = "macos") {
+ java_home
+ .join("Contents")
+ .join("Home")
+ .join("bin")
+ .join("java")
+ } else if cfg!(windows) {
+ java_home.join("bin").join("java.exe")
+ } else {
+ java_home.join("bin").join("java")
+ };
+
+ if !java_bin.exists() {
+ return Err(format!(
+ "Installation completed but Java executable not found: {}",
+ java_bin.display()
+ ));
+ }
+
+ let java_bin = std::fs::canonicalize(&java_bin).map_err(|e| e.to_string())?;
+ let java_bin = strip_unc_prefix(java_bin);
+
+ let installation = validation::check_java_installation(&java_bin)
+ .await
+ .ok_or_else(|| "Failed to verify Java installation".to_string())?;
+
+ queue.remove(major_version, &image_type.to_string());
+ queue.save(app_handle)?;
+
+ let _ = app_handle.emit(
+ "java-download-progress",
+ JavaDownloadProgress {
+ file_name,
+ downloaded_bytes: info.file_size,
+ total_bytes: info.file_size,
+ speed_bytes_per_sec: 0,
+ eta_seconds: 0,
+ status: "Completed".to_string(),
+ percentage: 100.0,
+ },
+ );
+
+ Ok(installation)
+}
+
+fn find_top_level_dir(extract_dir: &PathBuf) -> Result {
+ let entries: Vec<_> = std::fs::read_dir(extract_dir)
+ .map_err(|e| format!("Failed to read directory: {}", e))?
+ .filter_map(|e| e.ok())
+ .filter(|e| e.path().is_dir())
+ .collect();
+
+ if entries.len() == 1 {
+ Ok(entries[0].file_name().to_string_lossy().to_string())
+ } else {
+ Ok(String::new())
+ }
+}
+
+pub async fn detect_java_installations() -> Vec {
+ let mut installations = Vec::new();
+ let candidates = detection::get_java_candidates();
+
+ for candidate in candidates {
+ if let Some(java) = validation::check_java_installation(&candidate).await {
+ if !installations
+ .iter()
+ .any(|j: &JavaInstallation| j.path == java.path)
+ {
+ installations.push(java);
+ }
+ }
+ }
+
+ installations.sort_by(|a, b| {
+ let v_a = validation::parse_java_version(&a.version);
+ let v_b = validation::parse_java_version(&b.version);
+ v_b.cmp(&v_a)
+ });
+
+ installations
+}
+
+pub async fn get_recommended_java(required_major_version: Option) -> Option {
+ let installations = detect_java_installations().await;
+
+ if let Some(required) = required_major_version {
+ installations.into_iter().find(|java| {
+ let major = validation::parse_java_version(&java.version);
+ major >= required as u32
+ })
+ } else {
+ installations.into_iter().next()
+ }
+}
+
+pub async fn get_compatible_java(
+ app_handle: &AppHandle,
+ required_major_version: Option,
+ max_major_version: Option,
+) -> Option {
+ let installations = detect_all_java_installations(app_handle).await;
+
+ installations.into_iter().find(|java| {
+ let major = validation::parse_java_version(&java.version);
+ validation::is_version_compatible(major, required_major_version, max_major_version)
+ })
+}
+
+pub async fn is_java_compatible(
+ java_path: &str,
+ required_major_version: Option,
+ max_major_version: Option,
+) -> bool {
+ let java_path_buf = PathBuf::from(java_path);
+ if let Some(java) = validation::check_java_installation(&java_path_buf).await {
+ let major = validation::parse_java_version(&java.version);
+ validation::is_version_compatible(major, required_major_version, max_major_version)
+ } else {
+ false
+ }
+}
+
+pub async fn detect_all_java_installations(app_handle: &AppHandle) -> Vec {
+ let mut installations = detect_java_installations().await;
+
+ let dropout_java_dir = get_java_install_dir(app_handle);
+ if dropout_java_dir.exists() {
+ if let Ok(entries) = std::fs::read_dir(&dropout_java_dir) {
+ for entry in entries.flatten() {
+ let path = entry.path();
+ if path.is_dir() {
+ let java_bin = find_java_executable(&path);
+ if let Some(java_path) = java_bin {
+ if let Some(java) = validation::check_java_installation(&java_path).await {
+ if !installations.iter().any(|j| j.path == java.path) {
+ installations.push(java);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ installations.sort_by(|a, b| {
+ let v_a = validation::parse_java_version(&a.version);
+ let v_b = validation::parse_java_version(&b.version);
+ v_b.cmp(&v_a)
+ });
+
+ installations
+}
+
+fn find_java_executable(dir: &PathBuf) -> Option {
+ let bin_name = if cfg!(windows) { "java.exe" } else { "java" };
+
+ let direct_bin = dir.join("bin").join(bin_name);
+ if direct_bin.exists() {
+ let resolved = std::fs::canonicalize(&direct_bin).unwrap_or(direct_bin);
+ return Some(strip_unc_prefix(resolved));
+ }
+
+ #[cfg(target_os = "macos")]
+ {
+ let macos_bin = dir.join("Contents").join("Home").join("bin").join(bin_name);
+ if macos_bin.exists() {
+ return Some(macos_bin);
+ }
+ }
+
+ if let Ok(entries) = std::fs::read_dir(dir) {
+ for entry in entries.flatten() {
+ let path = entry.path();
+ if path.is_dir() {
+ let nested_bin = path.join("bin").join(bin_name);
+ if nested_bin.exists() {
+ let resolved = std::fs::canonicalize(&nested_bin).unwrap_or(nested_bin);
+ return Some(strip_unc_prefix(resolved));
+ }
+
+ #[cfg(target_os = "macos")]
+ {
+ let macos_nested = path
+ .join("Contents")
+ .join("Home")
+ .join("bin")
+ .join(bin_name);
+ if macos_nested.exists() {
+ return Some(macos_nested);
+ }
+ }
+ }
+ }
+ }
+
+ None
+}
+
+pub async fn resume_pending_downloads(
+ app_handle: &AppHandle,
+) -> Result, String> {
+ let queue = DownloadQueue::load(app_handle);
+ let mut installed = Vec::new();
+
+ for pending in queue.pending_downloads.iter() {
+ let image_type = if pending.image_type == "jdk" {
+ ImageType::Jdk
+ } else {
+ ImageType::Jre
+ };
+
+ match download_and_install_java(
+ app_handle,
+ pending.major_version,
+ image_type,
+ Some(PathBuf::from(&pending.install_path)),
+ )
+ .await
+ {
+ Ok(installation) => {
+ installed.push(installation);
+ }
+ Err(e) => {
+ eprintln!(
+ "Failed to resume Java {} {} download: {}",
+ pending.major_version, pending.image_type, e
+ );
+ }
+ }
+ }
+
+ Ok(installed)
+}
+
+pub fn cancel_current_download() {
+ crate::core::downloader::cancel_java_download();
+}
+
+pub fn get_pending_downloads(app_handle: &AppHandle) -> Vec {
+ let queue = DownloadQueue::load(app_handle);
+ queue.pending_downloads
+}
+
+#[allow(dead_code)]
+pub fn clear_pending_download(
+ app_handle: &AppHandle,
+ major_version: u32,
+ image_type: &str,
+) -> Result<(), String> {
+ let mut queue = DownloadQueue::load(app_handle);
+ queue.remove(major_version, image_type);
+ queue.save(app_handle)
+}
diff --git a/src-tauri/src/core/java/persistence.rs b/src-tauri/src/core/java/persistence.rs
new file mode 100644
index 0000000..fd81394
--- /dev/null
+++ b/src-tauri/src/core/java/persistence.rs
@@ -0,0 +1,114 @@
+use serde::{Deserialize, Serialize};
+use std::path::PathBuf;
+use tauri::{AppHandle, Manager};
+
+use super::error::JavaError;
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct JavaConfig {
+ pub user_defined_paths: Vec,
+ pub preferred_java_path: Option,
+ pub last_detection_time: u64,
+}
+
+impl Default for JavaConfig {
+ fn default() -> Self {
+ Self {
+ user_defined_paths: Vec::new(),
+ preferred_java_path: None,
+ last_detection_time: 0,
+ }
+ }
+}
+
+fn get_java_config_path(app_handle: &AppHandle) -> PathBuf {
+ app_handle
+ .path()
+ .app_data_dir()
+ .unwrap()
+ .join("java_config.json")
+}
+
+pub fn load_java_config(app_handle: &AppHandle) -> JavaConfig {
+ let config_path = get_java_config_path(app_handle);
+ if !config_path.exists() {
+ return JavaConfig::default();
+ }
+
+ match std::fs::read_to_string(&config_path) {
+ Ok(content) => match serde_json::from_str(&content) {
+ Ok(config) => config,
+ Err(err) => {
+ // Log the error but don't panic - return default config
+ log::warn!(
+ "Failed to parse Java config at {}: {}. Using default configuration.",
+ config_path.display(),
+ err
+ );
+ JavaConfig::default()
+ }
+ },
+ Err(err) => {
+ log::warn!(
+ "Failed to read Java config at {}: {}. Using default configuration.",
+ config_path.display(),
+ err
+ );
+ JavaConfig::default()
+ }
+ }
+}
+
+pub fn save_java_config(app_handle: &AppHandle, config: &JavaConfig) -> Result<(), JavaError> {
+ let config_path = get_java_config_path(app_handle);
+ let content = serde_json::to_string_pretty(config)?;
+
+ std::fs::create_dir_all(config_path.parent().ok_or_else(|| {
+ JavaError::InvalidConfig("Java config path has no parent directory".to_string())
+ })?)?;
+
+ std::fs::write(&config_path, content)?;
+ Ok(())
+}
+
+#[allow(dead_code)]
+pub fn add_user_defined_path(app_handle: &AppHandle, path: String) -> Result<(), JavaError> {
+ let mut config = load_java_config(app_handle);
+ if !config.user_defined_paths.contains(&path) {
+ config.user_defined_paths.push(path);
+ }
+ save_java_config(app_handle, &config)
+}
+
+#[allow(dead_code)]
+pub fn remove_user_defined_path(app_handle: &AppHandle, path: &str) -> Result<(), JavaError> {
+ let mut config = load_java_config(app_handle);
+ config.user_defined_paths.retain(|p| p != path);
+ save_java_config(app_handle, &config)
+}
+
+#[allow(dead_code)]
+pub fn set_preferred_java_path(
+ app_handle: &AppHandle,
+ path: Option,
+) -> Result<(), JavaError> {
+ let mut config = load_java_config(app_handle);
+ config.preferred_java_path = path;
+ save_java_config(app_handle, &config)
+}
+
+#[allow(dead_code)]
+pub fn get_preferred_java_path(app_handle: &AppHandle) -> Option {
+ let config = load_java_config(app_handle);
+ config.preferred_java_path
+}
+
+#[allow(dead_code)]
+pub fn update_last_detection_time(app_handle: &AppHandle) -> Result<(), JavaError> {
+ let mut config = load_java_config(app_handle);
+ config.last_detection_time = std::time::SystemTime::now()
+ .duration_since(std::time::UNIX_EPOCH)
+ .map_err(|e| JavaError::Other(format!("System time error: {}", e)))?
+ .as_secs();
+ save_java_config(app_handle, &config)
+}
diff --git a/src-tauri/src/core/java/priority.rs b/src-tauri/src/core/java/priority.rs
new file mode 100644
index 0000000..e456680
--- /dev/null
+++ b/src-tauri/src/core/java/priority.rs
@@ -0,0 +1,59 @@
+use tauri::AppHandle;
+
+use super::JavaInstallation;
+use crate::core::java::persistence;
+use crate::core::java::validation;
+
+pub async fn resolve_java_for_launch(
+ app_handle: &AppHandle,
+ instance_java_override: Option<&str>,
+ global_java_path: Option<&str>,
+ required_major_version: Option,
+ max_major_version: Option,
+) -> Option {
+ if let Some(override_path) = instance_java_override {
+ if !override_path.is_empty() {
+ let path_buf = std::path::PathBuf::from(override_path);
+ if let Some(java) = validation::check_java_installation(&path_buf).await {
+ if is_version_compatible(&java, required_major_version, max_major_version) {
+ return Some(java);
+ }
+ }
+ }
+ }
+
+ if let Some(global_path) = global_java_path {
+ if !global_path.is_empty() {
+ let path_buf = std::path::PathBuf::from(global_path);
+ if let Some(java) = validation::check_java_installation(&path_buf).await {
+ if is_version_compatible(&java, required_major_version, max_major_version) {
+ return Some(java);
+ }
+ }
+ }
+ }
+
+ let preferred = persistence::get_preferred_java_path(app_handle);
+ if let Some(pref_path) = preferred {
+ let path_buf = std::path::PathBuf::from(&pref_path);
+ if let Some(java) = validation::check_java_installation(&path_buf).await {
+ if is_version_compatible(&java, required_major_version, max_major_version) {
+ return Some(java);
+ }
+ }
+ }
+
+ let installations = super::detect_all_java_installations(app_handle).await;
+ installations
+ .into_iter()
+ .find(|java| is_version_compatible(java, required_major_version, max_major_version))
+}
+
+fn is_version_compatible(
+ java: &JavaInstallation,
+ required_major_version: Option,
+ max_major_version: Option,
+) -> bool {
+ let major = validation::parse_java_version(&java.version);
+ validation::is_version_compatible(major, required_major_version, max_major_version)
+}
diff --git a/src-tauri/src/core/java/provider.rs b/src-tauri/src/core/java/provider.rs
new file mode 100644
index 0000000..8aa0a0d
--- /dev/null
+++ b/src-tauri/src/core/java/provider.rs
@@ -0,0 +1,58 @@
+use crate::core::java::{ImageType, JavaCatalog, JavaDownloadInfo, JavaError};
+use tauri::AppHandle;
+
+/// Trait for Java distribution providers (e.g., Adoptium, Corretto)
+///
+/// Implementations handle fetching Java catalogs and release information
+/// from different distribution providers.
+pub trait JavaProvider: Send + Sync {
+ /// Fetch the Java catalog (all available versions for this provider)
+ ///
+ /// # Arguments
+ /// * `app_handle` - The Tauri app handle for cache access
+ /// * `force_refresh` - If true, bypass cache and fetch fresh data
+ ///
+ /// # Returns
+ /// * `Ok(JavaCatalog)` with available versions
+ /// * `Err(JavaError)` if fetch or parsing fails
+ async fn fetch_catalog(
+ &self,
+ app_handle: &AppHandle,
+ force_refresh: bool,
+ ) -> Result;
+
+ /// Fetch a specific Java release
+ ///
+ /// # Arguments
+ /// * `major_version` - The major version number (e.g., 17, 21)
+ /// * `image_type` - Whether to fetch JRE or JDK
+ ///
+ /// # Returns
+ /// * `Ok(JavaDownloadInfo)` with download details
+ /// * `Err(JavaError)` if fetch or parsing fails
+ async fn fetch_release(
+ &self,
+ major_version: u32,
+ image_type: ImageType,
+ ) -> Result;
+
+ /// Get list of available major versions
+ ///
+ /// # Returns
+ /// * `Ok(Vec)` with available major versions
+ /// * `Err(JavaError)` if fetch fails
+ async fn available_versions(&self) -> Result, JavaError>;
+
+ /// Get provider name (e.g., "adoptium", "corretto")
+ #[allow(dead_code)]
+ fn provider_name(&self) -> &'static str;
+
+ /// Get OS name for this provider's API
+ fn os_name(&self) -> &'static str;
+
+ /// Get architecture name for this provider's API
+ fn arch_name(&self) -> &'static str;
+
+ /// Get installation directory prefix (e.g., "temurin", "corretto")
+ fn install_prefix(&self) -> &'static str;
+}
diff --git a/src-tauri/src/core/java/providers/adoptium.rs b/src-tauri/src/core/java/providers/adoptium.rs
new file mode 100644
index 0000000..a73a0f6
--- /dev/null
+++ b/src-tauri/src/core/java/providers/adoptium.rs
@@ -0,0 +1,334 @@
+use crate::core::java::error::JavaError;
+use crate::core::java::provider::JavaProvider;
+use crate::core::java::save_catalog_cache;
+use crate::core::java::{ImageType, JavaCatalog, JavaDownloadInfo, JavaReleaseInfo};
+use serde::Deserialize;
+use tauri::AppHandle;
+
+const ADOPTIUM_API_BASE: &str = "https://api.adoptium.net/v3";
+
+#[derive(Debug, Clone, Deserialize)]
+pub struct AdoptiumAsset {
+ pub binary: AdoptiumBinary,
+ pub release_name: String,
+ pub version: AdoptiumVersionData,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+#[allow(dead_code)]
+pub struct AdoptiumBinary {
+ pub os: String,
+ pub architecture: String,
+ pub image_type: String,
+ pub package: AdoptiumPackage,
+ #[serde(default)]
+ pub updated_at: Option,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+pub struct AdoptiumPackage {
+ pub name: String,
+ pub link: String,
+ pub size: u64,
+ pub checksum: Option,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+#[allow(dead_code)]
+pub struct AdoptiumVersionData {
+ pub major: u32,
+ pub minor: u32,
+ pub security: u32,
+ pub semver: String,
+ pub openjdk_version: String,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+#[allow(dead_code)]
+pub struct AvailableReleases {
+ pub available_releases: Vec,
+ pub available_lts_releases: Vec,
+ pub most_recent_lts: Option,
+ pub most_recent_feature_release: Option,
+}
+
+pub struct AdoptiumProvider;
+
+impl AdoptiumProvider {
+ pub fn new() -> Self {
+ Self
+ }
+}
+
+impl Default for AdoptiumProvider {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl JavaProvider for AdoptiumProvider {
+ async fn fetch_catalog(
+ &self,
+ app_handle: &AppHandle,
+ force_refresh: bool,
+ ) -> Result {
+ if !force_refresh {
+ if let Some(cached) = crate::core::java::load_cached_catalog(app_handle) {
+ return Ok(cached);
+ }
+ }
+
+ let os = self.os_name();
+ let arch = self.arch_name();
+ let client = reqwest::Client::new();
+
+ let releases_url = format!("{}/info/available_releases", ADOPTIUM_API_BASE);
+ let available: AvailableReleases = client
+ .get(&releases_url)
+ .header("Accept", "application/json")
+ .send()
+ .await
+ .map_err(|e| {
+ JavaError::NetworkError(format!("Failed to fetch available releases: {}", e))
+ })?
+ .json::()
+ .await
+ .map_err(|e| {
+ JavaError::SerializationError(format!("Failed to parse available releases: {}", e))
+ })?;
+
+ // Parallelize HTTP requests for better performance
+ let mut fetch_tasks = Vec::new();
+
+ for major_version in &available.available_releases {
+ for image_type in &["jre", "jdk"] {
+ let major_version = *major_version;
+ let image_type = image_type.to_string();
+ let url = format!(
+ "{}/assets/latest/{}/hotspot?os={}&architecture={}&image_type={}",
+ ADOPTIUM_API_BASE, major_version, os, arch, image_type
+ );
+ let client = client.clone();
+ let is_lts = available.available_lts_releases.contains(&major_version);
+ let arch = arch.to_string();
+
+ let task = tokio::spawn(async move {
+ match client
+ .get(&url)
+ .header("Accept", "application/json")
+ .send()
+ .await
+ {
+ Ok(response) => {
+ if response.status().is_success() {
+ if let Ok(assets) = response.json::>().await {
+ if let Some(asset) = assets.into_iter().next() {
+ let release_date = asset.binary.updated_at.clone();
+ return Some(JavaReleaseInfo {
+ major_version,
+ image_type,
+ version: asset.version.semver.clone(),
+ release_name: asset.release_name.clone(),
+ release_date,
+ file_size: asset.binary.package.size,
+ checksum: asset.binary.package.checksum,
+ download_url: asset.binary.package.link,
+ is_lts,
+ is_available: true,
+ architecture: asset.binary.architecture.clone(),
+ });
+ }
+ }
+ }
+ // Fallback for unsuccessful response
+ Some(JavaReleaseInfo {
+ major_version,
+ image_type,
+ version: format!("{}.x", major_version),
+ release_name: format!("jdk-{}", major_version),
+ release_date: None,
+ file_size: 0,
+ checksum: None,
+ download_url: String::new(),
+ is_lts,
+ is_available: false,
+ architecture: arch,
+ })
+ }
+ Err(_) => Some(JavaReleaseInfo {
+ major_version,
+ image_type,
+ version: format!("{}.x", major_version),
+ release_name: format!("jdk-{}", major_version),
+ release_date: None,
+ file_size: 0,
+ checksum: None,
+ download_url: String::new(),
+ is_lts,
+ is_available: false,
+ architecture: arch,
+ }),
+ }
+ });
+ fetch_tasks.push(task);
+ }
+ }
+
+ // Collect all results concurrently
+ let mut releases = Vec::new();
+ for task in fetch_tasks {
+ match task.await {
+ Ok(Some(release)) => {
+ releases.push(release);
+ }
+ Ok(None) => {
+ // Task completed but returned None, should not happen in current implementation
+ }
+ Err(e) => {
+ return Err(JavaError::NetworkError(format!(
+ "Failed to join Adoptium catalog fetch task: {}",
+ e
+ )));
+ }
+ }
+ }
+
+ let now = std::time::SystemTime::now()
+ .duration_since(std::time::UNIX_EPOCH)
+ .unwrap()
+ .as_secs();
+
+ let catalog = JavaCatalog {
+ releases,
+ available_major_versions: available.available_releases,
+ lts_versions: available.available_lts_releases,
+ cached_at: now,
+ };
+
+ let _ = save_catalog_cache(app_handle, &catalog);
+
+ Ok(catalog)
+ }
+
+ async fn fetch_release(
+ &self,
+ major_version: u32,
+ image_type: ImageType,
+ ) -> Result {
+ let os = self.os_name();
+ let arch = self.arch_name();
+
+ let url = format!(
+ "{}/assets/latest/{}/hotspot?os={}&architecture={}&image_type={}",
+ ADOPTIUM_API_BASE, major_version, os, arch, image_type
+ );
+
+ let client = reqwest::Client::new();
+ let response = client
+ .get(&url)
+ .header("Accept", "application/json")
+ .send()
+ .await
+ .map_err(|e| JavaError::NetworkError(format!("Network request failed: {}", e)))?;
+
+ if !response.status().is_success() {
+ return Err(JavaError::NetworkError(format!(
+ "Adoptium API returned error: {} - The version/platform might be unavailable",
+ response.status()
+ )));
+ }
+
+ let assets: Vec =
+ response.json::>().await.map_err(|e| {
+ JavaError::SerializationError(format!("Failed to parse API response: {}", e))
+ })?;
+
+ let asset = assets
+ .into_iter()
+ .next()
+ .ok_or_else(|| JavaError::NotFound)?;
+
+ Ok(JavaDownloadInfo {
+ version: asset.version.semver.clone(),
+ release_name: asset.release_name,
+ download_url: asset.binary.package.link,
+ file_name: asset.binary.package.name,
+ file_size: asset.binary.package.size,
+ checksum: asset.binary.package.checksum,
+ image_type: asset.binary.image_type,
+ })
+ }
+
+ async fn available_versions(&self) -> Result, JavaError> {
+ let url = format!("{}/info/available_releases", ADOPTIUM_API_BASE);
+
+ let response = reqwest::get(url)
+ .await
+ .map_err(|e| JavaError::NetworkError(format!("Network request failed: {}", e)))?;
+
+ let releases: AvailableReleases =
+ response.json::().await.map_err(|e| {
+ JavaError::SerializationError(format!("Failed to parse response: {}", e))
+ })?;
+
+ Ok(releases.available_releases)
+ }
+
+ fn provider_name(&self) -> &'static str {
+ "adoptium"
+ }
+
+ fn os_name(&self) -> &'static str {
+ #[cfg(target_os = "linux")]
+ {
+ if std::path::Path::new("/etc/alpine-release").exists() {
+ return "alpine-linux";
+ }
+ "linux"
+ }
+ #[cfg(target_os = "macos")]
+ {
+ "mac"
+ }
+ #[cfg(target_os = "windows")]
+ {
+ "windows"
+ }
+ #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
+ {
+ "linux"
+ }
+ }
+
+ fn arch_name(&self) -> &'static str {
+ #[cfg(target_arch = "x86_64")]
+ {
+ "x64"
+ }
+ #[cfg(target_arch = "aarch64")]
+ {
+ "aarch64"
+ }
+ #[cfg(target_arch = "x86")]
+ {
+ "x86"
+ }
+ #[cfg(target_arch = "arm")]
+ {
+ "arm"
+ }
+ #[cfg(not(any(
+ target_arch = "x86_64",
+ target_arch = "aarch64",
+ target_arch = "x86",
+ target_arch = "arm"
+ )))]
+ {
+ "x64"
+ }
+ }
+
+ fn install_prefix(&self) -> &'static str {
+ "temurin"
+ }
+}
diff --git a/src-tauri/src/core/java/providers/mod.rs b/src-tauri/src/core/java/providers/mod.rs
new file mode 100644
index 0000000..16eb5c7
--- /dev/null
+++ b/src-tauri/src/core/java/providers/mod.rs
@@ -0,0 +1,3 @@
+pub mod adoptium;
+
+pub use adoptium::AdoptiumProvider;
diff --git a/src-tauri/src/core/java/validation.rs b/src-tauri/src/core/java/validation.rs
new file mode 100644
index 0000000..48782f6
--- /dev/null
+++ b/src-tauri/src/core/java/validation.rs
@@ -0,0 +1,146 @@
+use std::collections::HashMap;
+use std::path::PathBuf;
+use std::process::Command;
+
+#[cfg(target_os = "windows")]
+use std::os::windows::process::CommandExt;
+
+use super::JavaInstallation;
+
+pub async fn check_java_installation(path: &PathBuf) -> Option {
+ let path = path.clone();
+ tokio::task::spawn_blocking(move || check_java_installation_blocking(&path))
+ .await
+ .ok()?
+}
+
+fn check_java_installation_blocking(path: &PathBuf) -> Option {
+ let mut cmd = Command::new(path);
+ cmd.arg("-version");
+
+ // Hide console window
+ #[cfg(target_os = "windows")]
+ cmd.creation_flags(0x08000000);
+
+ let output = cmd.output().ok()?;
+
+ let version_output = String::from_utf8_lossy(&output.stderr);
+
+ let version = parse_version_string(&version_output)?;
+ let arch = extract_architecture(&version_output);
+ let vendor = extract_vendor(&version_output);
+ let is_64bit = version_output.to_lowercase().contains("64-bit") || arch == "aarch64";
+
+ Some(JavaInstallation {
+ path: path.to_string_lossy().to_string(),
+ version,
+ arch,
+ vendor,
+ source: "system".to_string(),
+ is_64bit,
+ })
+}
+
+pub fn parse_version_string(output: &str) -> Option {
+ for line in output.lines() {
+ if line.contains("version") {
+ if let Some(start) = line.find('"') {
+ if let Some(end) = line[start + 1..].find('"') {
+ return Some(line[start + 1..start + 1 + end].to_string());
+ }
+ }
+ }
+ }
+ None
+}
+
+pub fn parse_java_version(version: &str) -> u32 {
+ let parts: Vec<&str> = version.split('.').collect();
+ if let Some(first) = parts.first() {
+ // Handle both legacy (1.x) and modern (x) versioning
+ if *first == "1" {
+ // Legacy versioning
+ parts.get(1).and_then(|s| s.parse().ok()).unwrap_or(0)
+ } else {
+ // Modern versioning
+ first.parse().unwrap_or(0)
+ }
+ } else {
+ 0
+ }
+}
+
+pub fn extract_architecture(version_output: &str) -> String {
+ if version_output.contains("64-Bit") {
+ "x64".to_string()
+ } else if version_output.contains("32-Bit") {
+ "x86".to_string()
+ } else if version_output.contains("aarch64") || version_output.contains("ARM64") {
+ "aarch64".to_string()
+ } else {
+ "x64".to_string()
+ }
+}
+
+pub fn extract_vendor(version_output: &str) -> String {
+ let lower = version_output.to_lowercase();
+
+ let vendor_name: HashMap<&str, &str> = [
+ // Eclipse/Adoptium
+ ("temurin", "Temurin (Eclipse)"),
+ ("adoptium", "Eclipse Adoptium"),
+ // Amazon
+ ("corretto", "Corretto (Amazon)"),
+ ("amzn", "Corretto (Amazon)"),
+ // Alibaba
+ ("dragonwell", "Dragonwell (Alibaba)"),
+ ("albba", "Dragonwell (Alibaba)"),
+ // GraalVM
+ ("graalvm", "GraalVM"),
+ // Oracle
+ ("oracle", "Java SE Development Kit (Oracle)"),
+ // Tencent
+ ("kona", "Kona (Tencent)"),
+ // BellSoft
+ ("liberica", "Liberica (Bellsoft)"),
+ ("mandrel", "Mandrel (Red Hat)"),
+ // Microsoft
+ ("microsoft", "OpenJDK (Microsoft)"),
+ // SAP
+ ("sapmachine", "SapMachine (SAP)"),
+ // IBM
+ ("semeru", "Semeru (IBM)"),
+ ("sem", "Semeru (IBM)"),
+ // Azul
+ ("zulu", "Zulu (Azul Systems)"),
+ // Trava
+ ("trava", "Trava (Trava)"),
+ // Huawei
+ ("bisheng", "BiSheng (Huawei)"),
+ // Generic OpenJDK
+ ("openjdk", "OpenJDK"),
+ ]
+ .iter()
+ .cloned()
+ .collect();
+
+ for (key, name) in vendor_name {
+ if lower.contains(key) {
+ return name.to_string();
+ }
+ }
+
+ "Unknown".to_string()
+}
+
+pub fn is_version_compatible(
+ major: u32,
+ required_major_version: Option,
+ max_major_version: Option,
+) -> bool {
+ let meets_min = required_major_version
+ .map(|r| major >= r as u32)
+ .unwrap_or(true);
+ let meets_max = max_major_version.map(|m| major <= m).unwrap_or(true);
+ meets_min && meets_max
+}
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index 45fa77b..b74c746 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -4,10 +4,9 @@
use serde::{Deserialize, Serialize};
use std::process::Stdio;
use std::sync::Mutex;
-use tauri::{Emitter, Manager, State, Window};
+use tauri::{Emitter, Manager, State, Window}; // Added Emitter
use tokio::io::{AsyncBufReadExt, BufReader};
-use tokio::process::Command;
-use ts_rs::TS;
+use tokio::process::Command; // Added Serialize
#[cfg(target_os = "windows")]
use std::os::windows::process::CommandExt;
@@ -199,92 +198,54 @@ async fn start_game(
None
};
- // Check if configured Java is compatible
+ // Resolve Java using priority-based resolution
+ // Priority: instance override > global config > user preference > auto-detect
+ // TODO: refactor into a separate function
let app_handle = window.app_handle();
- let mut java_path_to_use = config.java_path.clone();
- if !java_path_to_use.is_empty() && java_path_to_use != "java" {
- let is_compatible =
- core::java::is_java_compatible(&java_path_to_use, required_java_major, max_java_major);
-
- if !is_compatible {
- emit_log!(
- window,
- format!(
- "Configured Java version may not be compatible. Looking for compatible Java..."
- )
- );
-
- // Try to find a compatible Java version
- if let Some(compatible_java) =
- core::java::get_compatible_java(app_handle, required_java_major, max_java_major)
- {
- emit_log!(
- window,
- format!(
- "Found compatible Java {} at: {}",
- compatible_java.version, compatible_java.path
- )
- );
- java_path_to_use = compatible_java.path;
- } else {
- let version_constraint = if let Some(max) = max_java_major {
- if let Some(min) = required_java_major {
- if min == max as u64 {
- format!("Java {}", min)
- } else {
- format!("Java {} to {}", min, max)
- }
- } else {
- format!("Java {} (or lower)", max)
- }
- } else if let Some(min) = required_java_major {
- format!("Java {} or higher", min)
- } else {
- "any Java version".to_string()
- };
+ let instance = instance_state
+ .get_instance(&instance_id)
+ .ok_or_else(|| format!("Instance {} not found", instance_id))?;
- return Err(format!(
- "No compatible Java installation found. This version requires {}. Please install a compatible Java version in settings.",
- version_constraint
- ));
- }
- }
- } else {
- // No Java configured, try to find a compatible one
- if let Some(compatible_java) =
- core::java::get_compatible_java(app_handle, required_java_major, max_java_major)
- {
- emit_log!(
- window,
- format!(
- "Using Java {} at: {}",
- compatible_java.version, compatible_java.path
- )
- );
- java_path_to_use = compatible_java.path;
- } else {
- let version_constraint = if let Some(max) = max_java_major {
- if let Some(min) = required_java_major {
- if min == max as u64 {
- format!("Java {}", min)
- } else {
- format!("Java {} to {}", min, max)
- }
+ let java_installation = core::java::priority::resolve_java_for_launch(
+ app_handle,
+ instance.java_path_override.as_deref(),
+ Some(&config.java_path),
+ required_java_major,
+ max_java_major,
+ )
+ .await
+ .ok_or_else(|| {
+ let version_constraint = if let Some(max) = max_java_major {
+ if let Some(min) = required_java_major {
+ if min == max as u64 {
+ format!("Java {}", min)
} else {
- format!("Java {} (or lower)", max)
+ format!("Java {} to {}", min, max)
}
- } else if let Some(min) = required_java_major {
- format!("Java {} or higher", min)
} else {
- "any Java version".to_string()
- };
+ format!("Java {} (or lower)", max)
+ }
+ } else if let Some(min) = required_java_major {
+ format!("Java {} or higher", min)
+ } else {
+ "any Java version".to_string()
+ };
- return Err(format!(
- "No compatible Java installation found. This version requires {}. Please install a compatible Java version in settings.",
- version_constraint
- ));
- }
- }
+ format!(
+ "No compatible Java installation found. This version requires {}. Please install a compatible Java version in settings.",
+ version_constraint
+ )
+ })?;
+
+ emit_log!(
+ window,
+ format!(
+ "Using Java {} at: {}",
+ java_installation.version, java_installation.path
+ )
+ );
+
+ let java_path_to_use = java_installation.path;
// 2. Prepare download tasks
emit_log!(window, "Preparing download tasks...".to_string());
@@ -1556,10 +1517,18 @@ async fn refresh_account(
/// Detect Java installations on the system
#[tauri::command]
+async fn detect_all_java_installations(
+ app_handle: tauri::AppHandle,
+) -> Result, String> {
+ Ok(core::java::detect_all_java_installations(&app_handle).await)
+}
+
+/// Alias for detect_all_java_installations (for backward compatibility)
+#[tauri::command]
async fn detect_java(
app_handle: tauri::AppHandle,
) -> Result, String> {
- Ok(core::java::detect_all_java_installations(&app_handle))
+ Ok(core::java::detect_all_java_installations(&app_handle).await)
}
/// Get recommended Java for a specific Minecraft version
@@ -1567,7 +1536,7 @@ async fn detect_java(
async fn get_recommended_java(
required_major_version: Option,
) -> Result