feat: add React frontend with search and mod pages
Add apps/web (Vite + React Router + Tailwind v4 + Zustand) with a search page and a mod page that analyzes saves via @tts/extract. Document the frontend in the README and docs.
This commit is contained in:
@@ -7,6 +7,7 @@ analyze their contents. A lightweight, client-only pnpm monorepo.
|
|||||||
|
|
||||||
| Package | Role | Runtime |
|
| Package | Role | Runtime |
|
||||||
| ------------------- | ------------------------------------------------------ | ---------- |
|
| ------------------- | ------------------------------------------------------ | ---------- |
|
||||||
|
| `apps/web` | React frontend: search + mod pages | Browser |
|
||||||
| `apps/proxy` | Hono HTTP server: Workshop search + save fetch | Node |
|
| `apps/proxy` | Hono HTTP server: Workshop search + save fetch | Node |
|
||||||
| `packages/tts` | Fetch save from Steam, BSON-parse to `TTSMod` | Node |
|
| `packages/tts` | Fetch save from Steam, BSON-parse to `TTSMod` | Node |
|
||||||
| `packages/extract` | Analyze a `TTSMod`: objects, asset refs, downloads | Isomorphic |
|
| `packages/extract` | Analyze a `TTSMod`: objects, asset refs, downloads | Isomorphic |
|
||||||
@@ -25,6 +26,10 @@ pnpm dev # runs the proxy at http://localhost:3000
|
|||||||
|
|
||||||
Get a Steam Web API key at https://steamcommunity.com/dev/apikey (free).
|
Get a Steam Web API key at https://steamcommunity.com/dev/apikey (free).
|
||||||
|
|
||||||
|
To run the frontend alongside the proxy, open a second terminal and run
|
||||||
|
`pnpm --filter @tts/web dev` (serves at http://localhost:5173 and proxies
|
||||||
|
`/search`, `/items`, and `/health` to the backend).
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
| Method | Path | Description |
|
| Method | Path | Description |
|
||||||
@@ -38,6 +43,7 @@ Get a Steam Web API key at https://steamcommunity.com/dev/apikey (free).
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
pnpm dev # run the proxy (tsx watch)
|
pnpm dev # run the proxy (tsx watch)
|
||||||
|
pnpm dev:web # run the frontend (vite)
|
||||||
pnpm build # compile all packages
|
pnpm build # compile all packages
|
||||||
pnpm typecheck # typecheck all packages
|
pnpm typecheck # typecheck all packages
|
||||||
pnpm test # run the unit tests (vitest)
|
pnpm test # run the unit tests (vitest)
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>TTS Workshop</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "@tts/web",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc -p tsconfig.json && vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
||||||
|
"test": "vitest run",
|
||||||
|
"lint": "echo \"no lint configured\""
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@tts/extract": "workspace:*",
|
||||||
|
"@tts/shared": "workspace:*",
|
||||||
|
"react": "^19.2.8",
|
||||||
|
"react-dom": "^19.2.8",
|
||||||
|
"react-router-dom": "^7.18.2",
|
||||||
|
"zustand": "^5.0.14"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tailwindcss/vite": "^4.3.3",
|
||||||
|
"@types/react": "^19.2.18",
|
||||||
|
"@types/react-dom": "^19.2.4",
|
||||||
|
"@vitejs/plugin-react": "^6.0.5",
|
||||||
|
"tailwindcss": "^4.3.3",
|
||||||
|
"typescript": "^5.7.2",
|
||||||
|
"vite": "^8.2.1",
|
||||||
|
"vitest": "^4.1.10"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { Link, Route, Routes } from 'react-router-dom';
|
||||||
|
import SearchPage from './pages/SearchPage';
|
||||||
|
import ModPage from './pages/ModPage';
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-zinc-950 text-zinc-100">
|
||||||
|
<header className="border-b border-zinc-800">
|
||||||
|
<div className="mx-auto flex max-w-5xl items-center justify-between px-4 py-4">
|
||||||
|
<Link to="/" className="text-lg font-semibold tracking-tight">
|
||||||
|
TTS Workshop
|
||||||
|
</Link>
|
||||||
|
<nav className="flex gap-4 text-sm text-zinc-400">
|
||||||
|
<Link to="/" className="hover:text-zinc-100">
|
||||||
|
Search
|
||||||
|
</Link>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main className="mx-auto max-w-5xl px-4 py-8">
|
||||||
|
<Routes>
|
||||||
|
<Route path="/" element={<SearchPage />} />
|
||||||
|
<Route path="/mod/:id" element={<ModPage />} />
|
||||||
|
</Routes>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import type { SearchResult, TTSMod } from '@tts/shared';
|
||||||
|
|
||||||
|
const BASE = '';
|
||||||
|
|
||||||
|
async function getJson<T>(path: string): Promise<T> {
|
||||||
|
const res = await fetch(`${BASE}${path}`);
|
||||||
|
if (!res.ok) {
|
||||||
|
const body = (await res.json().catch(() => null)) as { error?: string } | null;
|
||||||
|
throw new Error(body?.error ?? `Request failed (${res.status})`);
|
||||||
|
}
|
||||||
|
return res.json() as Promise<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Search the Workshop. */
|
||||||
|
export function searchWorkshop(q: string, page = 1): Promise<SearchResult> {
|
||||||
|
const params = new URLSearchParams({ q, page: String(page) });
|
||||||
|
return getJson<SearchResult>(`/search?${params.toString()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fetch a full parsed TTS save. */
|
||||||
|
export function fetchMod(id: string): Promise<TTSMod> {
|
||||||
|
return getJson<TTSMod>(`/items/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Build a URL for the raw save file download. */
|
||||||
|
export function modFileUrl(id: string): string {
|
||||||
|
return `${BASE}/items/${id}/file`;
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { useSearchStore } from '../stores/searchStore';
|
||||||
|
|
||||||
|
export default function SearchResults() {
|
||||||
|
const { items, page, hasMore, loading, search } = useSearchStore();
|
||||||
|
|
||||||
|
if (loading) return null;
|
||||||
|
if (items.length === 0) {
|
||||||
|
return <p className="text-sm text-zinc-500">No results yet.</p>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<ul className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{items.map((item) => (
|
||||||
|
<li key={item.id}>
|
||||||
|
<Link
|
||||||
|
to={`/mod/${item.id}`}
|
||||||
|
className="block overflow-hidden rounded-lg border border-zinc-800 bg-zinc-900 hover:border-zinc-600"
|
||||||
|
>
|
||||||
|
{item.previewImageUrl && (
|
||||||
|
<img
|
||||||
|
src={item.previewImageUrl}
|
||||||
|
alt={item.title}
|
||||||
|
className="h-40 w-full object-cover"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div className="p-3">
|
||||||
|
<h3 className="truncate font-medium">{item.title}</h3>
|
||||||
|
<p className="truncate text-sm text-zinc-400">{item.author}</p>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between text-sm">
|
||||||
|
<button
|
||||||
|
onClick={() => search(useSearchStore.getState().query, page - 1)}
|
||||||
|
disabled={page <= 1 || loading}
|
||||||
|
className="rounded-lg border border-zinc-700 px-3 py-1.5 hover:bg-zinc-800 disabled:opacity-40"
|
||||||
|
>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
<span className="text-zinc-400">Page {page}</span>
|
||||||
|
<button
|
||||||
|
onClick={() => search(useSearchStore.getState().query, page + 1)}
|
||||||
|
disabled={!hasMore || loading}
|
||||||
|
className="rounded-lg border border-zinc-700 px-3 py-1.5 hover:bg-zinc-800 disabled:opacity-40"
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { StrictMode } from 'react';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
|
import App from './App';
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
createRoot(document.getElementById('root')!).render(
|
||||||
|
<StrictMode>
|
||||||
|
<BrowserRouter>
|
||||||
|
<App />
|
||||||
|
</BrowserRouter>
|
||||||
|
</StrictMode>,
|
||||||
|
);
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import { collectRefs, flattenObjects } from '@tts/extract';
|
||||||
|
import { useModStore } from '../stores/modStore';
|
||||||
|
import { modFileUrl } from '../api';
|
||||||
|
|
||||||
|
export default function ModPage() {
|
||||||
|
const { id } = useParams<{ id: string }>();
|
||||||
|
const { mod, loading, error, load } = useModStore();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (id) load(id);
|
||||||
|
}, [id, load]);
|
||||||
|
|
||||||
|
if (loading) return <p className="text-sm text-zinc-400">Loading mod…</p>;
|
||||||
|
if (error) return <p className="text-sm text-red-400">{error}</p>;
|
||||||
|
if (!mod) return <p className="text-sm text-zinc-500">No mod loaded.</p>;
|
||||||
|
|
||||||
|
const objects = flattenObjects(mod);
|
||||||
|
const refs = collectRefs(mod);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-semibold">Mod {id}</h1>
|
||||||
|
<p className="mt-1 text-sm text-zinc-400">
|
||||||
|
{mod.GameMode} · {mod.Date} · {objects.length} objects · {refs.length}{' '}
|
||||||
|
asset refs
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
href={modFileUrl(id!)}
|
||||||
|
className="mt-3 inline-block rounded-lg bg-zinc-100 px-4 py-2 text-sm font-medium text-zinc-900 hover:bg-zinc-300"
|
||||||
|
>
|
||||||
|
Download save file
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2 className="mb-2 text-lg font-semibold">Asset references</h2>
|
||||||
|
{refs.length === 0 ? (
|
||||||
|
<p className="text-sm text-zinc-500">No external assets found.</p>
|
||||||
|
) : (
|
||||||
|
<ul className="space-y-1">
|
||||||
|
{refs.map((ref) => (
|
||||||
|
<li key={ref.url} className="flex items-center gap-2 text-sm">
|
||||||
|
<span className="rounded bg-zinc-800 px-1.5 py-0.5 text-xs uppercase text-zinc-400">
|
||||||
|
{ref.kind}
|
||||||
|
</span>
|
||||||
|
<a
|
||||||
|
href={ref.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="truncate text-zinc-300 hover:text-zinc-100"
|
||||||
|
>
|
||||||
|
{ref.url}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2 className="mb-2 text-lg font-semibold">Objects</h2>
|
||||||
|
<ul className="divide-y divide-zinc-800 rounded-lg border border-zinc-800">
|
||||||
|
{objects.map((o) => (
|
||||||
|
<li key={o.GUID} className="flex items-center justify-between px-3 py-2 text-sm">
|
||||||
|
<span className="font-medium">{o.Name}</span>
|
||||||
|
<span className="font-mono text-xs text-zinc-500">{o.GUID}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { useSearchStore } from '../stores/searchStore';
|
||||||
|
import SearchResults from '../components/SearchResults';
|
||||||
|
|
||||||
|
export default function SearchPage() {
|
||||||
|
const { query, search, loading, error } = useSearchStore();
|
||||||
|
const [input, setInput] = useState(query);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (query) search(query);
|
||||||
|
}, [query, search]);
|
||||||
|
|
||||||
|
const onSubmit = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
search(input);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-semibold">Search the Workshop</h1>
|
||||||
|
<p className="mt-1 text-sm text-zinc-400">
|
||||||
|
Find Tabletop Simulator Workshop items by name.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form onSubmit={onSubmit} className="flex gap-2">
|
||||||
|
<input
|
||||||
|
value={input}
|
||||||
|
onChange={(e) => setInput(e.target.value)}
|
||||||
|
placeholder="e.g. wingspan"
|
||||||
|
className="flex-1 rounded-lg border border-zinc-700 bg-zinc-900 px-4 py-2 text-sm outline-none focus:border-zinc-500"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={loading}
|
||||||
|
className="rounded-lg bg-zinc-100 px-4 py-2 text-sm font-medium text-zinc-900 hover:bg-zinc-300 disabled:opacity-50"
|
||||||
|
>
|
||||||
|
Search
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{error && <p className="text-sm text-red-400">{error}</p>}
|
||||||
|
{loading && <p className="text-sm text-zinc-400">Searching…</p>}
|
||||||
|
<SearchResults />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
import type { TTSMod } from '@tts/shared';
|
||||||
|
import { fetchMod } from '../api';
|
||||||
|
|
||||||
|
interface ModState {
|
||||||
|
id: string | null;
|
||||||
|
mod: TTSMod | null;
|
||||||
|
loading: boolean;
|
||||||
|
error: string | null;
|
||||||
|
load: (id: string) => Promise<void>;
|
||||||
|
clear: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useModStore = create<ModState>((set) => ({
|
||||||
|
id: null,
|
||||||
|
mod: null,
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
load: async (id) => {
|
||||||
|
set({ loading: true, error: null, id });
|
||||||
|
try {
|
||||||
|
const mod = await fetchMod(id);
|
||||||
|
set({ mod, loading: false });
|
||||||
|
} catch (err) {
|
||||||
|
set({ loading: false, error: String(err) });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clear: () => set({ id: null, mod: null, error: null, loading: false }),
|
||||||
|
}));
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
import type { SearchResult } from '@tts/shared';
|
||||||
|
import { useSearchStore } from './searchStore';
|
||||||
|
|
||||||
|
const result: SearchResult = {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
title: 'Wingspan',
|
||||||
|
author: 'someone',
|
||||||
|
previewImageUrl: 'https://example.com/p.png',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
page: 1,
|
||||||
|
hasMore: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.unstubAllGlobals();
|
||||||
|
useSearchStore.setState({
|
||||||
|
query: '',
|
||||||
|
page: 1,
|
||||||
|
items: [],
|
||||||
|
hasMore: false,
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('searchStore', () => {
|
||||||
|
it('stores results from a successful search', async () => {
|
||||||
|
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(new Response(JSON.stringify(result))));
|
||||||
|
await useSearchStore.getState().search('wingspan');
|
||||||
|
const state = useSearchStore.getState();
|
||||||
|
expect(state.items).toHaveLength(1);
|
||||||
|
expect(state.items[0]!.title).toBe('Wingspan');
|
||||||
|
expect(state.loading).toBe(false);
|
||||||
|
expect(state.error).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('records an error on failure', async () => {
|
||||||
|
vi.stubGlobal(
|
||||||
|
'fetch',
|
||||||
|
vi.fn().mockResolvedValue(new Response(JSON.stringify({ error: 'boom' }), { status: 502 })),
|
||||||
|
);
|
||||||
|
await useSearchStore.getState().search('wingspan');
|
||||||
|
const state = useSearchStore.getState();
|
||||||
|
expect(state.error).toContain('boom');
|
||||||
|
expect(state.items).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ignores empty queries', async () => {
|
||||||
|
const fetchMock = vi.fn();
|
||||||
|
vi.stubGlobal('fetch', fetchMock);
|
||||||
|
await useSearchStore.getState().search(' ');
|
||||||
|
expect(fetchMock).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
import type { SearchResult, WorkshopItem } from '@tts/shared';
|
||||||
|
import { searchWorkshop } from '../api';
|
||||||
|
|
||||||
|
interface SearchState {
|
||||||
|
query: string;
|
||||||
|
page: number;
|
||||||
|
items: WorkshopItem[];
|
||||||
|
hasMore: boolean;
|
||||||
|
loading: boolean;
|
||||||
|
error: string | null;
|
||||||
|
search: (query: string, page?: number) => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSearchStore = create<SearchState>((set) => ({
|
||||||
|
query: '',
|
||||||
|
page: 1,
|
||||||
|
items: [],
|
||||||
|
hasMore: false,
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
search: async (query, page = 1) => {
|
||||||
|
if (!query.trim()) return;
|
||||||
|
set({ loading: true, error: null, query, page });
|
||||||
|
try {
|
||||||
|
const result: SearchResult = await searchWorkshop(query, page);
|
||||||
|
set({
|
||||||
|
items: result.items,
|
||||||
|
hasMore: result.hasMore,
|
||||||
|
loading: false,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
set({ loading: false, error: String(err) });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"noEmit": true,
|
||||||
|
"types": ["vite/client"]
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import tailwindcss from '@tailwindcss/vite';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react(), tailwindcss()],
|
||||||
|
server: {
|
||||||
|
// Proxy API calls to the Hono backend during development.
|
||||||
|
proxy: {
|
||||||
|
'/search': 'http://localhost:3000',
|
||||||
|
'/items': 'http://localhost:3000',
|
||||||
|
'/health': 'http://localhost:3000',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
+14
-5
@@ -27,6 +27,7 @@ shared types/validation package.
|
|||||||
|
|
||||||
| Package | Role | Runtime |
|
| Package | Role | Runtime |
|
||||||
| ------------------ | ------------------------------------------- | ------------ |
|
| ------------------ | ------------------------------------------- | ------------ |
|
||||||
|
| `apps/web` | React frontend: search + mod pages | Browser |
|
||||||
| `apps/proxy` | Hono HTTP server: search + fetch endpoints | Node |
|
| `apps/proxy` | Hono HTTP server: search + fetch endpoints | Node |
|
||||||
| `packages/tts` | Fetch save from Steam, BSON-parse to `TTSMod` | Node |
|
| `packages/tts` | Fetch save from Steam, BSON-parse to `TTSMod` | Node |
|
||||||
| `packages/extract` | Analyze a `TTSMod`: objects, refs, assets | Isomorphic |
|
| `packages/extract` | Analyze a `TTSMod`: objects, refs, assets | Isomorphic |
|
||||||
@@ -35,15 +36,19 @@ shared types/validation package.
|
|||||||
## Dependency graph
|
## Dependency graph
|
||||||
|
|
||||||
```
|
```
|
||||||
apps/proxy ──► packages/tts ──► packages/shared
|
apps/web ──► apps/proxy ──► packages/tts ──► packages/shared
|
||||||
│ │
|
│ │ │
|
||||||
│ └──► (fetchMod → TTSMod)
|
│ │ └──► (fetchMod → TTSMod)
|
||||||
▼
|
│ ▼
|
||||||
packages/extract ──► packages/tts (traverseMod) ──► packages/shared (types)
|
└──► packages/extract ──► packages/shared (types)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Edges
|
### Edges
|
||||||
|
|
||||||
|
- **`apps/web` → `apps/proxy`** — calls `/search`, `/items/:id`, and
|
||||||
|
`/items/:id/file` over HTTP.
|
||||||
|
- **`apps/web` → `packages/extract`** — uses `flattenObjects` / `collectRefs`
|
||||||
|
to analyze a loaded `TTSMod` in the browser.
|
||||||
- **`apps/proxy` → `packages/tts`** — calls `fetchMod` / `getFileName` to serve
|
- **`apps/proxy` → `packages/tts`** — calls `fetchMod` / `getFileName` to serve
|
||||||
item requests.
|
item requests.
|
||||||
- **`apps/proxy` → `packages/shared`** — uses shared types and zod schemas for
|
- **`apps/proxy` → `packages/shared`** — uses shared types and zod schemas for
|
||||||
@@ -90,11 +95,15 @@ packages/extract ──► packages/tts (traverseMod) ──► packages/shared
|
|||||||
|
|
||||||
- `typescript` (strict), `tsx` (dev runner), `eslint`, `prettier`.
|
- `typescript` (strict), `tsx` (dev runner), `eslint`, `prettier`.
|
||||||
- `vitest` (unit tests), colocated as `*.test.ts` next to sources.
|
- `vitest` (unit tests), colocated as `*.test.ts` next to sources.
|
||||||
|
- `vite`, `@vitejs/plugin-react`, `tailwindcss`, `@tailwindcss/vite` — frontend
|
||||||
|
build/dev tooling.
|
||||||
- `pnpm` workspaces for package management.
|
- `pnpm` workspaces for package management.
|
||||||
|
|
||||||
## Deployment / runtime shape
|
## Deployment / runtime shape
|
||||||
|
|
||||||
- The proxy runs as a single Node process via `@hono/node-server`.
|
- The proxy runs as a single Node process via `@hono/node-server`.
|
||||||
|
- `apps/web` is a static Vite build served separately; during development it
|
||||||
|
proxies `/search`, `/items`, and `/health` to the proxy.
|
||||||
- `packages/extract` is published/consumed as a plain ESM module usable from a
|
- `packages/extract` is published/consumed as a plain ESM module usable from a
|
||||||
browser bundle or Node.
|
browser bundle or Node.
|
||||||
- No shared state between requests; each request fetches fresh.
|
- No shared state between requests; each request fetches fresh.
|
||||||
@@ -96,3 +96,19 @@ available in Node.
|
|||||||
|
|
||||||
**Alternatives considered:** Raw `ArrayBuffer`. Rejected — less convenient for
|
**Alternatives considered:** Raw `ArrayBuffer`. Rejected — less convenient for
|
||||||
frontend rendering.
|
frontend rendering.
|
||||||
|
|
||||||
|
## D9 — Frontend stack: React + React Router + Tailwind v4 + Zustand
|
||||||
|
|
||||||
|
**Decision:** The frontend (`apps/web`) uses React with React Router for
|
||||||
|
routing, Tailwind CSS v4 for styling, and Zustand for state, built with Vite.
|
||||||
|
|
||||||
|
**Context:** The frontend consumes the proxy API for search/fetch and
|
||||||
|
`packages/extract` directly for analysis. React is the de-facto standard for
|
||||||
|
this kind of tool; React Router provides declarative routes (`/` and
|
||||||
|
`/mod/:id`); Tailwind v4 is the current major version and integrates via
|
||||||
|
`@tailwindcss/vite`; Zustand is a minimal, unopinionated store that fits the
|
||||||
|
small amount of client state (search + mod).
|
||||||
|
|
||||||
|
**Alternatives considered:** Next.js (heavier than needed for a client-only
|
||||||
|
tool); Redux Toolkit (more boilerplate than warranted); CSS Modules (no
|
||||||
|
utility styling).
|
||||||
+60
-17
@@ -21,20 +21,20 @@ Steam Workshop, fetching full TTS save files, and analyzing their contents.
|
|||||||
## Non-goals (for now)
|
## Non-goals (for now)
|
||||||
|
|
||||||
- Backend traversal endpoints (deferred by design).
|
- Backend traversal endpoints (deferred by design).
|
||||||
- Frontend app (later; will consume `packages/extract` directly).
|
|
||||||
- Caching / Redis / multi-instance concerns.
|
- Caching / Redis / multi-instance concerns.
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
```
|
```
|
||||||
apps/proxy ──► packages/tts ──► packages/shared
|
apps/web ──► apps/proxy ──► packages/tts ──► packages/shared
|
||||||
│ │
|
│ │ │
|
||||||
│ └──► (fetchMod → TTSMod)
|
│ │ └──► (fetchMod → TTSMod)
|
||||||
▼
|
│ ▼
|
||||||
packages/extract ──► packages/tts (traverseMod) ──► packages/shared (types)
|
└──► packages/extract ──► packages/shared (types)
|
||||||
(isomorphic, used by future frontend)
|
(isomorphic, used by the frontend)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- **`apps/web`** — React frontend (search + mod pages).
|
||||||
- **`apps/proxy`** — Hono server. Search + fetch only. No traversal endpoints.
|
- **`apps/proxy`** — Hono server. Search + fetch only. No traversal endpoints.
|
||||||
- **`packages/tts`** — low-level fetcher: Steam API call, BSON parse, filename
|
- **`packages/tts`** — low-level fetcher: Steam API call, BSON parse, filename
|
||||||
derivation. Returns raw parsed `TTSMod`.
|
derivation. Returns raw parsed `TTSMod`.
|
||||||
@@ -54,16 +54,34 @@ tts-workshop/
|
|||||||
├── docs/
|
├── docs/
|
||||||
│ └── implementation-plan.md # this file
|
│ └── implementation-plan.md # this file
|
||||||
├── apps/
|
├── apps/
|
||||||
│ └── proxy/
|
│ ├── proxy/
|
||||||
|
│ │ ├── package.json
|
||||||
|
│ │ ├── tsconfig.json
|
||||||
|
│ │ └── src/
|
||||||
|
│ │ ├── index.ts # Hono app + @hono/node-server
|
||||||
|
│ │ ├── routes/
|
||||||
|
│ │ │ ├── search.ts # GET /search?q=...&page=1
|
||||||
|
│ │ │ ├── items.ts # GET /items/:id, /items/:id/file
|
||||||
|
│ │ │ └── health.ts # GET /health
|
||||||
|
│ │ └── env.ts # zod env validation
|
||||||
|
│ └── web/
|
||||||
│ ├── package.json
|
│ ├── package.json
|
||||||
│ ├── tsconfig.json
|
│ ├── tsconfig.json
|
||||||
|
│ ├── vite.config.ts # dev proxy → localhost:3000
|
||||||
|
│ ├── index.html
|
||||||
│ └── src/
|
│ └── src/
|
||||||
│ ├── index.ts # Hono app + @hono/node-server
|
│ ├── main.tsx # React root + router
|
||||||
│ ├── routes/
|
│ ├── App.tsx # layout + routes
|
||||||
│ │ ├── search.ts # GET /search?q=...&page=1
|
│ ├── api.ts # fetch wrappers for /search, /items
|
||||||
│ │ ├── items.ts # GET /items/:id, /items/:id/file
|
│ ├── index.css # tailwind v4 entry
|
||||||
│ │ └── health.ts # GET /health
|
│ ├── pages/
|
||||||
│ └── env.ts # zod env validation
|
│ │ ├── SearchPage.tsx
|
||||||
|
│ │ └── ModPage.tsx
|
||||||
|
│ ├── components/
|
||||||
|
│ │ └── SearchResults.tsx
|
||||||
|
│ └── stores/
|
||||||
|
│ ├── searchStore.ts # zustand
|
||||||
|
│ └── modStore.ts # zustand
|
||||||
└── packages/
|
└── packages/
|
||||||
├── shared/
|
├── shared/
|
||||||
│ └── src/
|
│ └── src/
|
||||||
@@ -159,6 +177,27 @@ Hono server exposing search + fetch.
|
|||||||
- `GET /health` — liveness.
|
- `GET /health` — liveness.
|
||||||
- `env.ts` — zod validation of `STEAM_API_KEY`, `PORT`.
|
- `env.ts` — zod validation of `STEAM_API_KEY`, `PORT`.
|
||||||
|
|
||||||
|
### `apps/web`
|
||||||
|
|
||||||
|
React frontend (Vite + React Router + Tailwind v4 + Zustand). Consumes the
|
||||||
|
proxy API and `packages/extract` directly for analysis.
|
||||||
|
|
||||||
|
- `main.tsx` — React root, `BrowserRouter`.
|
||||||
|
- `App.tsx` — app shell (header) + routes: `/` (search), `/mod/:id` (mod).
|
||||||
|
- `api.ts` — typed `fetch` wrappers for `/search` and `/items/:id`, plus a
|
||||||
|
`modFileUrl` helper for the raw-file download.
|
||||||
|
- `pages/SearchPage.tsx` — search form, drives `searchStore`.
|
||||||
|
- `pages/ModPage.tsx` — loads the mod via `modStore`, uses `@tts/extract`
|
||||||
|
(`flattenObjects`, `collectRefs`) to render objects and asset refs, and links
|
||||||
|
to the raw save file.
|
||||||
|
- `components/SearchResults.tsx` — result grid + pagination.
|
||||||
|
- `stores/searchStore.ts` / `stores/modStore.ts` — Zustand stores for search
|
||||||
|
and mod state.
|
||||||
|
- `vite.config.ts` — dev proxy for `/search`, `/items`, `/health` →
|
||||||
|
`http://localhost:3000`.
|
||||||
|
- Styling: Tailwind v4 via `@tailwindcss/vite`; `index.css` imports
|
||||||
|
`tailwindcss`.
|
||||||
|
|
||||||
## Endpoints
|
## Endpoints
|
||||||
|
|
||||||
| Method | Path | Description | Auth |
|
| Method | Path | Description | Auth |
|
||||||
@@ -186,14 +225,16 @@ packages/extract → flatten objects / extract refs / download assets
|
|||||||
- `bson` — BSON deserialization.
|
- `bson` — BSON deserialization.
|
||||||
- `cheerio` — Workshop browse page scraping (backend only).
|
- `cheerio` — Workshop browse page scraping (backend only).
|
||||||
- `zod` — validation.
|
- `zod` — validation.
|
||||||
|
- `react`, `react-dom`, `react-router-dom`, `zustand` — frontend.
|
||||||
|
- `vite`, `@vitejs/plugin-react`, `tailwindcss`, `@tailwindcss/vite` — frontend tooling.
|
||||||
- `tsx`, `typescript`, `eslint`, `prettier` — tooling.
|
- `tsx`, `typescript`, `eslint`, `prettier` — tooling.
|
||||||
|
|
||||||
## Tooling
|
## Tooling
|
||||||
|
|
||||||
- TypeScript strict mode.
|
- TypeScript strict mode.
|
||||||
- `tsx` for dev, `tsc` for build.
|
- `tsx` for dev, `tsc` for build; `vite` for the frontend dev server/build.
|
||||||
- `vitest` for unit tests, colocated as `*.test.ts` next to sources.
|
- `vitest` for unit tests, colocated as `*.test.ts` next to sources.
|
||||||
- Root scripts: `pnpm dev`, `pnpm build`, `pnpm test`, `pnpm lint`.
|
- Root scripts: `pnpm dev`, `pnpm dev:web`, `pnpm build`, `pnpm test`, `pnpm lint`.
|
||||||
|
|
||||||
## Build order
|
## Build order
|
||||||
|
|
||||||
@@ -203,7 +244,9 @@ packages/extract → flatten objects / extract refs / download assets
|
|||||||
3. `packages/tts` — fetch + parse (existing scraper code).
|
3. `packages/tts` — fetch + parse (existing scraper code).
|
||||||
4. `packages/extract` — objects, refs, download.
|
4. `packages/extract` — objects, refs, download.
|
||||||
5. `apps/proxy` — search + items + health routes, env validation.
|
5. `apps/proxy` — search + items + health routes, env validation.
|
||||||
6. Wire up root scripts, `.env.example`, README.
|
6. `apps/web` — React frontend (search + mod pages), consuming the proxy and
|
||||||
|
`packages/extract`.
|
||||||
|
7. Wire up root scripts, `.env.example`, README.
|
||||||
|
|
||||||
## Risks / caveats
|
## Risks / caveats
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "pnpm --filter @tts/proxy dev",
|
"dev": "pnpm --filter @tts/proxy dev",
|
||||||
|
"dev:web": "pnpm --filter @tts/web dev",
|
||||||
"build": "pnpm -r build",
|
"build": "pnpm -r build",
|
||||||
"lint": "pnpm -r lint",
|
"lint": "pnpm -r lint",
|
||||||
"typecheck": "pnpm -r typecheck",
|
"typecheck": "pnpm -r typecheck",
|
||||||
|
|||||||
Generated
+525
-7
@@ -13,7 +13,7 @@ importers:
|
|||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^4.1.10
|
specifier: ^4.1.10
|
||||||
version: 4.1.10(@types/node@22.20.1)(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.11))
|
version: 4.1.10(@types/node@22.20.1)(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11))
|
||||||
|
|
||||||
apps/proxy:
|
apps/proxy:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -43,6 +43,52 @@ importers:
|
|||||||
specifier: ^5.7.2
|
specifier: ^5.7.2
|
||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
|
|
||||||
|
apps/web:
|
||||||
|
dependencies:
|
||||||
|
'@tts/extract':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../packages/extract
|
||||||
|
'@tts/shared':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../packages/shared
|
||||||
|
react:
|
||||||
|
specifier: ^19.2.8
|
||||||
|
version: 19.2.8
|
||||||
|
react-dom:
|
||||||
|
specifier: ^19.2.8
|
||||||
|
version: 19.2.8(react@19.2.8)
|
||||||
|
react-router-dom:
|
||||||
|
specifier: ^7.18.2
|
||||||
|
version: 7.18.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
||||||
|
zustand:
|
||||||
|
specifier: ^5.0.14
|
||||||
|
version: 5.0.14(@types/react@19.2.18)(react@19.2.8)
|
||||||
|
devDependencies:
|
||||||
|
'@tailwindcss/vite':
|
||||||
|
specifier: ^4.3.3
|
||||||
|
version: 4.3.3(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11))
|
||||||
|
'@types/react':
|
||||||
|
specifier: ^19.2.18
|
||||||
|
version: 19.2.18
|
||||||
|
'@types/react-dom':
|
||||||
|
specifier: ^19.2.4
|
||||||
|
version: 19.2.4(@types/react@19.2.18)
|
||||||
|
'@vitejs/plugin-react':
|
||||||
|
specifier: ^6.0.5
|
||||||
|
version: 6.0.5(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11))
|
||||||
|
tailwindcss:
|
||||||
|
specifier: ^4.3.3
|
||||||
|
version: 4.3.3
|
||||||
|
typescript:
|
||||||
|
specifier: ^5.7.2
|
||||||
|
version: 5.9.3
|
||||||
|
vite:
|
||||||
|
specifier: ^8.2.1
|
||||||
|
version: 8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11)
|
||||||
|
vitest:
|
||||||
|
specifier: ^4.1.10
|
||||||
|
version: 4.1.10(@types/node@22.20.1)(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11))
|
||||||
|
|
||||||
packages/extract:
|
packages/extract:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tts/shared':
|
'@tts/shared':
|
||||||
@@ -240,9 +286,22 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
hono: ^4
|
hono: ^4
|
||||||
|
|
||||||
|
'@jridgewell/gen-mapping@0.3.13':
|
||||||
|
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
|
||||||
|
|
||||||
|
'@jridgewell/remapping@2.3.5':
|
||||||
|
resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
|
||||||
|
|
||||||
|
'@jridgewell/resolve-uri@3.1.2':
|
||||||
|
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
||||||
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.5.5':
|
'@jridgewell/sourcemap-codec@1.5.5':
|
||||||
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
|
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
|
||||||
|
|
||||||
|
'@jridgewell/trace-mapping@0.3.31':
|
||||||
|
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
||||||
|
|
||||||
'@oxc-project/types@0.143.0':
|
'@oxc-project/types@0.143.0':
|
||||||
resolution: {integrity: sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==}
|
resolution: {integrity: sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==}
|
||||||
|
|
||||||
@@ -342,6 +401,100 @@ packages:
|
|||||||
'@standard-schema/spec@1.1.0':
|
'@standard-schema/spec@1.1.0':
|
||||||
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
||||||
|
|
||||||
|
'@tailwindcss/node@4.3.3':
|
||||||
|
resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==}
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-android-arm64@4.3.3':
|
||||||
|
resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==}
|
||||||
|
engines: {node: '>= 20'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-darwin-arm64@4.3.3':
|
||||||
|
resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==}
|
||||||
|
engines: {node: '>= 20'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-darwin-x64@4.3.3':
|
||||||
|
resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==}
|
||||||
|
engines: {node: '>= 20'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-freebsd-x64@4.3.3':
|
||||||
|
resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==}
|
||||||
|
engines: {node: '>= 20'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
|
||||||
|
resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==}
|
||||||
|
engines: {node: '>= 20'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
|
||||||
|
resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==}
|
||||||
|
engines: {node: '>= 20'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm64-musl@4.3.3':
|
||||||
|
resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==}
|
||||||
|
engines: {node: '>= 20'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-x64-gnu@4.3.3':
|
||||||
|
resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==}
|
||||||
|
engines: {node: '>= 20'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-x64-musl@4.3.3':
|
||||||
|
resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==}
|
||||||
|
engines: {node: '>= 20'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-wasm32-wasi@4.3.3':
|
||||||
|
resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [wasm32]
|
||||||
|
bundledDependencies:
|
||||||
|
- '@napi-rs/wasm-runtime'
|
||||||
|
- '@emnapi/core'
|
||||||
|
- '@emnapi/runtime'
|
||||||
|
- '@tybys/wasm-util'
|
||||||
|
- '@emnapi/wasi-threads'
|
||||||
|
- tslib
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
|
||||||
|
resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==}
|
||||||
|
engines: {node: '>= 20'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-win32-x64-msvc@4.3.3':
|
||||||
|
resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==}
|
||||||
|
engines: {node: '>= 20'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide@4.3.3':
|
||||||
|
resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==}
|
||||||
|
engines: {node: '>= 20'}
|
||||||
|
|
||||||
|
'@tailwindcss/vite@4.3.3':
|
||||||
|
resolution: {integrity: sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==}
|
||||||
|
peerDependencies:
|
||||||
|
vite: ^5.2.0 || ^6 || ^7 || ^8
|
||||||
|
|
||||||
'@types/chai@5.2.3':
|
'@types/chai@5.2.3':
|
||||||
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
|
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
|
||||||
|
|
||||||
@@ -354,6 +507,27 @@ packages:
|
|||||||
'@types/node@22.20.1':
|
'@types/node@22.20.1':
|
||||||
resolution: {integrity: sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==}
|
resolution: {integrity: sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==}
|
||||||
|
|
||||||
|
'@types/react-dom@19.2.4':
|
||||||
|
resolution: {integrity: sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': ^19.2.0
|
||||||
|
|
||||||
|
'@types/react@19.2.18':
|
||||||
|
resolution: {integrity: sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==}
|
||||||
|
|
||||||
|
'@vitejs/plugin-react@6.0.5':
|
||||||
|
resolution: {integrity: sha512-BOVzne/NL162sMdResB25mUv+vWMF5NoAjNf09TeGlE7ZpszZWSD3winycicLJw72yeVsoCn/2kOhEuCvEShMA==}
|
||||||
|
engines: {node: ^20.19.0 || >=22.12.0}
|
||||||
|
peerDependencies:
|
||||||
|
'@rolldown/plugin-babel': ^0.1.7 || ^0.2.0
|
||||||
|
babel-plugin-react-compiler: ^1.0.0
|
||||||
|
vite: ^8.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@rolldown/plugin-babel':
|
||||||
|
optional: true
|
||||||
|
babel-plugin-react-compiler:
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@vitest/expect@4.1.10':
|
'@vitest/expect@4.1.10':
|
||||||
resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==}
|
resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==}
|
||||||
|
|
||||||
@@ -398,10 +572,21 @@ packages:
|
|||||||
convert-source-map@2.0.0:
|
convert-source-map@2.0.0:
|
||||||
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
||||||
|
|
||||||
|
cookie@1.1.1:
|
||||||
|
resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
csstype@3.2.3:
|
||||||
|
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
|
||||||
|
|
||||||
detect-libc@2.1.2:
|
detect-libc@2.1.2:
|
||||||
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
enhanced-resolve@5.24.5:
|
||||||
|
resolution: {integrity: sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==}
|
||||||
|
engines: {node: '>=10.13.0'}
|
||||||
|
|
||||||
es-module-lexer@2.3.1:
|
es-module-lexer@2.3.1:
|
||||||
resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==}
|
resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==}
|
||||||
|
|
||||||
@@ -431,40 +616,84 @@ packages:
|
|||||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
|
graceful-fs@4.2.11:
|
||||||
|
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||||
|
|
||||||
hono@4.13.1:
|
hono@4.13.1:
|
||||||
resolution: {integrity: sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw==}
|
resolution: {integrity: sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw==}
|
||||||
engines: {node: '>=16.9.0'}
|
engines: {node: '>=16.9.0'}
|
||||||
|
|
||||||
|
jiti@2.7.0:
|
||||||
|
resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
lightningcss-android-arm64@1.32.0:
|
||||||
|
resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
lightningcss-android-arm64@1.33.0:
|
lightningcss-android-arm64@1.33.0:
|
||||||
resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==}
|
resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
|
||||||
|
lightningcss-darwin-arm64@1.32.0:
|
||||||
|
resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
lightningcss-darwin-arm64@1.33.0:
|
lightningcss-darwin-arm64@1.33.0:
|
||||||
resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==}
|
resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
|
lightningcss-darwin-x64@1.32.0:
|
||||||
|
resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
lightningcss-darwin-x64@1.33.0:
|
lightningcss-darwin-x64@1.33.0:
|
||||||
resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==}
|
resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
|
lightningcss-freebsd-x64@1.32.0:
|
||||||
|
resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
lightningcss-freebsd-x64@1.33.0:
|
lightningcss-freebsd-x64@1.33.0:
|
||||||
resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==}
|
resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [freebsd]
|
os: [freebsd]
|
||||||
|
|
||||||
|
lightningcss-linux-arm-gnueabihf@1.32.0:
|
||||||
|
resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
lightningcss-linux-arm-gnueabihf@1.33.0:
|
lightningcss-linux-arm-gnueabihf@1.33.0:
|
||||||
resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==}
|
resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-gnu@1.32.0:
|
||||||
|
resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
lightningcss-linux-arm64-gnu@1.33.0:
|
lightningcss-linux-arm64-gnu@1.33.0:
|
||||||
resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==}
|
resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
@@ -472,6 +701,13 @@ packages:
|
|||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-musl@1.32.0:
|
||||||
|
resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
lightningcss-linux-arm64-musl@1.33.0:
|
lightningcss-linux-arm64-musl@1.33.0:
|
||||||
resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==}
|
resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
@@ -479,6 +715,13 @@ packages:
|
|||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
libc: [musl]
|
||||||
|
|
||||||
|
lightningcss-linux-x64-gnu@1.32.0:
|
||||||
|
resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
lightningcss-linux-x64-gnu@1.33.0:
|
lightningcss-linux-x64-gnu@1.33.0:
|
||||||
resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==}
|
resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
@@ -486,6 +729,13 @@ packages:
|
|||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
|
lightningcss-linux-x64-musl@1.32.0:
|
||||||
|
resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
lightningcss-linux-x64-musl@1.33.0:
|
lightningcss-linux-x64-musl@1.33.0:
|
||||||
resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==}
|
resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
@@ -493,18 +743,34 @@ packages:
|
|||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
libc: [musl]
|
||||||
|
|
||||||
|
lightningcss-win32-arm64-msvc@1.32.0:
|
||||||
|
resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
lightningcss-win32-arm64-msvc@1.33.0:
|
lightningcss-win32-arm64-msvc@1.33.0:
|
||||||
resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==}
|
resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
|
lightningcss-win32-x64-msvc@1.32.0:
|
||||||
|
resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
lightningcss-win32-x64-msvc@1.33.0:
|
lightningcss-win32-x64-msvc@1.33.0:
|
||||||
resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==}
|
resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
|
lightningcss@1.32.0:
|
||||||
|
resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
|
||||||
lightningcss@1.33.0:
|
lightningcss@1.33.0:
|
||||||
resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==}
|
resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
@@ -535,11 +801,43 @@ packages:
|
|||||||
resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==}
|
resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==}
|
||||||
engines: {node: ^10 || ^12 || >=14}
|
engines: {node: ^10 || ^12 || >=14}
|
||||||
|
|
||||||
|
react-dom@19.2.8:
|
||||||
|
resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^19.2.8
|
||||||
|
|
||||||
|
react-router-dom@7.18.2:
|
||||||
|
resolution: {integrity: sha512-AIKJ/jgGlFb3EbfCXk5Gzshiwt+l3mqbCrNjmEWMMjqQxNJ3svBa6bgzFyCC2Sw3RA0VWF1kg3uQf2OFhxb8hw==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=18'
|
||||||
|
react-dom: '>=18'
|
||||||
|
|
||||||
|
react-router@7.18.2:
|
||||||
|
resolution: {integrity: sha512-aUVMjFm3GAPTTZL7oYr5E7ETiqfQCHRLH+B+5afnICvf0r7kkK4eR6SMuwbSTJw/7t+12khT/Kahij49fqOCIg==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=18'
|
||||||
|
react-dom: '>=18'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
react@19.2.8:
|
||||||
|
resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
rolldown@1.2.3:
|
rolldown@1.2.3:
|
||||||
resolution: {integrity: sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==}
|
resolution: {integrity: sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==}
|
||||||
engines: {node: ^20.19.0 || >=22.12.0}
|
engines: {node: ^20.19.0 || >=22.12.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
scheduler@0.27.0:
|
||||||
|
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
|
||||||
|
|
||||||
|
set-cookie-parser@2.7.2:
|
||||||
|
resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
|
||||||
|
|
||||||
siginfo@2.0.0:
|
siginfo@2.0.0:
|
||||||
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
||||||
|
|
||||||
@@ -553,6 +851,13 @@ packages:
|
|||||||
std-env@4.2.0:
|
std-env@4.2.0:
|
||||||
resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==}
|
resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==}
|
||||||
|
|
||||||
|
tailwindcss@4.3.3:
|
||||||
|
resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==}
|
||||||
|
|
||||||
|
tapable@2.3.3:
|
||||||
|
resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
tinybench@2.9.0:
|
tinybench@2.9.0:
|
||||||
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
|
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
|
||||||
|
|
||||||
@@ -673,6 +978,24 @@ packages:
|
|||||||
zod@3.25.76:
|
zod@3.25.76:
|
||||||
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
|
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
|
||||||
|
|
||||||
|
zustand@5.0.14:
|
||||||
|
resolution: {integrity: sha512-/8tAspM5LMPr28b3fwLYrtdj77ECpfZviaP75CMTnwO8ISyaE4GDIG/9rDDYq/cH9D2Xw2A2RXglLInmVBQB/g==}
|
||||||
|
engines: {node: '>=12.20.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '>=18.0.0'
|
||||||
|
immer: '>=9.0.6'
|
||||||
|
react: '>=18.0.0'
|
||||||
|
use-sync-external-store: '>=1.2.0'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
immer:
|
||||||
|
optional: true
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
use-sync-external-store:
|
||||||
|
optional: true
|
||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.28.1':
|
'@esbuild/aix-ppc64@0.28.1':
|
||||||
@@ -757,8 +1080,25 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
hono: 4.13.1
|
hono: 4.13.1
|
||||||
|
|
||||||
|
'@jridgewell/gen-mapping@0.3.13':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
|
|
||||||
|
'@jridgewell/remapping@2.3.5':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/gen-mapping': 0.3.13
|
||||||
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
|
|
||||||
|
'@jridgewell/resolve-uri@3.1.2': {}
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.5.5': {}
|
'@jridgewell/sourcemap-codec@1.5.5': {}
|
||||||
|
|
||||||
|
'@jridgewell/trace-mapping@0.3.31':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
'@oxc-project/types@0.143.0': {}
|
'@oxc-project/types@0.143.0': {}
|
||||||
|
|
||||||
'@rolldown/binding-android-arm64@1.2.3':
|
'@rolldown/binding-android-arm64@1.2.3':
|
||||||
@@ -807,6 +1147,74 @@ snapshots:
|
|||||||
|
|
||||||
'@standard-schema/spec@1.1.0': {}
|
'@standard-schema/spec@1.1.0': {}
|
||||||
|
|
||||||
|
'@tailwindcss/node@4.3.3':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/remapping': 2.3.5
|
||||||
|
enhanced-resolve: 5.24.5
|
||||||
|
jiti: 2.7.0
|
||||||
|
lightningcss: 1.32.0
|
||||||
|
magic-string: 0.30.21
|
||||||
|
source-map-js: 1.2.1
|
||||||
|
tailwindcss: 4.3.3
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-android-arm64@4.3.3':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-darwin-arm64@4.3.3':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-darwin-x64@4.3.3':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-freebsd-x64@4.3.3':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm64-musl@4.3.3':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-x64-gnu@4.3.3':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-x64-musl@4.3.3':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-wasm32-wasi@4.3.3':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-win32-x64-msvc@4.3.3':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide@4.3.3':
|
||||||
|
optionalDependencies:
|
||||||
|
'@tailwindcss/oxide-android-arm64': 4.3.3
|
||||||
|
'@tailwindcss/oxide-darwin-arm64': 4.3.3
|
||||||
|
'@tailwindcss/oxide-darwin-x64': 4.3.3
|
||||||
|
'@tailwindcss/oxide-freebsd-x64': 4.3.3
|
||||||
|
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3
|
||||||
|
'@tailwindcss/oxide-linux-arm64-gnu': 4.3.3
|
||||||
|
'@tailwindcss/oxide-linux-arm64-musl': 4.3.3
|
||||||
|
'@tailwindcss/oxide-linux-x64-gnu': 4.3.3
|
||||||
|
'@tailwindcss/oxide-linux-x64-musl': 4.3.3
|
||||||
|
'@tailwindcss/oxide-wasm32-wasi': 4.3.3
|
||||||
|
'@tailwindcss/oxide-win32-arm64-msvc': 4.3.3
|
||||||
|
'@tailwindcss/oxide-win32-x64-msvc': 4.3.3
|
||||||
|
|
||||||
|
'@tailwindcss/vite@4.3.3(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11))':
|
||||||
|
dependencies:
|
||||||
|
'@tailwindcss/node': 4.3.3
|
||||||
|
'@tailwindcss/oxide': 4.3.3
|
||||||
|
tailwindcss: 4.3.3
|
||||||
|
vite: 8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11)
|
||||||
|
|
||||||
'@types/chai@5.2.3':
|
'@types/chai@5.2.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/deep-eql': 4.0.2
|
'@types/deep-eql': 4.0.2
|
||||||
@@ -820,6 +1228,19 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.21.0
|
undici-types: 6.21.0
|
||||||
|
|
||||||
|
'@types/react-dom@19.2.4(@types/react@19.2.18)':
|
||||||
|
dependencies:
|
||||||
|
'@types/react': 19.2.18
|
||||||
|
|
||||||
|
'@types/react@19.2.18':
|
||||||
|
dependencies:
|
||||||
|
csstype: 3.2.3
|
||||||
|
|
||||||
|
'@vitejs/plugin-react@6.0.5(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11))':
|
||||||
|
dependencies:
|
||||||
|
'@rolldown/pluginutils': 1.0.1
|
||||||
|
vite: 8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11)
|
||||||
|
|
||||||
'@vitest/expect@4.1.10':
|
'@vitest/expect@4.1.10':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@standard-schema/spec': 1.1.0
|
'@standard-schema/spec': 1.1.0
|
||||||
@@ -829,13 +1250,13 @@ snapshots:
|
|||||||
chai: 6.2.2
|
chai: 6.2.2
|
||||||
tinyrainbow: 3.1.1
|
tinyrainbow: 3.1.1
|
||||||
|
|
||||||
'@vitest/mocker@4.1.10(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.11))':
|
'@vitest/mocker@4.1.10(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/spy': 4.1.10
|
'@vitest/spy': 4.1.10
|
||||||
estree-walker: 3.0.3
|
estree-walker: 3.0.3
|
||||||
magic-string: 0.30.21
|
magic-string: 0.30.21
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
vite: 8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.11)
|
vite: 8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11)
|
||||||
|
|
||||||
'@vitest/pretty-format@4.1.10':
|
'@vitest/pretty-format@4.1.10':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -869,8 +1290,17 @@ snapshots:
|
|||||||
|
|
||||||
convert-source-map@2.0.0: {}
|
convert-source-map@2.0.0: {}
|
||||||
|
|
||||||
|
cookie@1.1.1: {}
|
||||||
|
|
||||||
|
csstype@3.2.3: {}
|
||||||
|
|
||||||
detect-libc@2.1.2: {}
|
detect-libc@2.1.2: {}
|
||||||
|
|
||||||
|
enhanced-resolve@5.24.5:
|
||||||
|
dependencies:
|
||||||
|
graceful-fs: 4.2.11
|
||||||
|
tapable: 2.3.3
|
||||||
|
|
||||||
es-module-lexer@2.3.1: {}
|
es-module-lexer@2.3.1: {}
|
||||||
|
|
||||||
esbuild@0.28.1:
|
esbuild@0.28.1:
|
||||||
@@ -915,41 +1345,94 @@ snapshots:
|
|||||||
fsevents@2.3.3:
|
fsevents@2.3.3:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
graceful-fs@4.2.11: {}
|
||||||
|
|
||||||
hono@4.13.1: {}
|
hono@4.13.1: {}
|
||||||
|
|
||||||
|
jiti@2.7.0: {}
|
||||||
|
|
||||||
|
lightningcss-android-arm64@1.32.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
lightningcss-android-arm64@1.33.0:
|
lightningcss-android-arm64@1.33.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-darwin-arm64@1.32.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
lightningcss-darwin-arm64@1.33.0:
|
lightningcss-darwin-arm64@1.33.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-darwin-x64@1.32.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
lightningcss-darwin-x64@1.33.0:
|
lightningcss-darwin-x64@1.33.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-freebsd-x64@1.32.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
lightningcss-freebsd-x64@1.33.0:
|
lightningcss-freebsd-x64@1.33.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-arm-gnueabihf@1.32.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
lightningcss-linux-arm-gnueabihf@1.33.0:
|
lightningcss-linux-arm-gnueabihf@1.33.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-gnu@1.32.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
lightningcss-linux-arm64-gnu@1.33.0:
|
lightningcss-linux-arm64-gnu@1.33.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-musl@1.32.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
lightningcss-linux-arm64-musl@1.33.0:
|
lightningcss-linux-arm64-musl@1.33.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-x64-gnu@1.32.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
lightningcss-linux-x64-gnu@1.33.0:
|
lightningcss-linux-x64-gnu@1.33.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-x64-musl@1.32.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
lightningcss-linux-x64-musl@1.33.0:
|
lightningcss-linux-x64-musl@1.33.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-win32-arm64-msvc@1.32.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
lightningcss-win32-arm64-msvc@1.33.0:
|
lightningcss-win32-arm64-msvc@1.33.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-win32-x64-msvc@1.32.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
lightningcss-win32-x64-msvc@1.33.0:
|
lightningcss-win32-x64-msvc@1.33.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
lightningcss@1.32.0:
|
||||||
|
dependencies:
|
||||||
|
detect-libc: 2.1.2
|
||||||
|
optionalDependencies:
|
||||||
|
lightningcss-android-arm64: 1.32.0
|
||||||
|
lightningcss-darwin-arm64: 1.32.0
|
||||||
|
lightningcss-darwin-x64: 1.32.0
|
||||||
|
lightningcss-freebsd-x64: 1.32.0
|
||||||
|
lightningcss-linux-arm-gnueabihf: 1.32.0
|
||||||
|
lightningcss-linux-arm64-gnu: 1.32.0
|
||||||
|
lightningcss-linux-arm64-musl: 1.32.0
|
||||||
|
lightningcss-linux-x64-gnu: 1.32.0
|
||||||
|
lightningcss-linux-x64-musl: 1.32.0
|
||||||
|
lightningcss-win32-arm64-msvc: 1.32.0
|
||||||
|
lightningcss-win32-x64-msvc: 1.32.0
|
||||||
|
|
||||||
lightningcss@1.33.0:
|
lightningcss@1.33.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
detect-libc: 2.1.2
|
detect-libc: 2.1.2
|
||||||
@@ -986,6 +1469,27 @@ snapshots:
|
|||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
source-map-js: 1.2.1
|
source-map-js: 1.2.1
|
||||||
|
|
||||||
|
react-dom@19.2.8(react@19.2.8):
|
||||||
|
dependencies:
|
||||||
|
react: 19.2.8
|
||||||
|
scheduler: 0.27.0
|
||||||
|
|
||||||
|
react-router-dom@7.18.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
|
||||||
|
dependencies:
|
||||||
|
react: 19.2.8
|
||||||
|
react-dom: 19.2.8(react@19.2.8)
|
||||||
|
react-router: 7.18.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
||||||
|
|
||||||
|
react-router@7.18.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
|
||||||
|
dependencies:
|
||||||
|
cookie: 1.1.1
|
||||||
|
react: 19.2.8
|
||||||
|
set-cookie-parser: 2.7.2
|
||||||
|
optionalDependencies:
|
||||||
|
react-dom: 19.2.8(react@19.2.8)
|
||||||
|
|
||||||
|
react@19.2.8: {}
|
||||||
|
|
||||||
rolldown@1.2.3:
|
rolldown@1.2.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@oxc-project/types': 0.143.0
|
'@oxc-project/types': 0.143.0
|
||||||
@@ -1006,6 +1510,10 @@ snapshots:
|
|||||||
'@rolldown/binding-win32-arm64-msvc': 1.2.3
|
'@rolldown/binding-win32-arm64-msvc': 1.2.3
|
||||||
'@rolldown/binding-win32-x64-msvc': 1.2.3
|
'@rolldown/binding-win32-x64-msvc': 1.2.3
|
||||||
|
|
||||||
|
scheduler@0.27.0: {}
|
||||||
|
|
||||||
|
set-cookie-parser@2.7.2: {}
|
||||||
|
|
||||||
siginfo@2.0.0: {}
|
siginfo@2.0.0: {}
|
||||||
|
|
||||||
source-map-js@1.2.1: {}
|
source-map-js@1.2.1: {}
|
||||||
@@ -1014,6 +1522,10 @@ snapshots:
|
|||||||
|
|
||||||
std-env@4.2.0: {}
|
std-env@4.2.0: {}
|
||||||
|
|
||||||
|
tailwindcss@4.3.3: {}
|
||||||
|
|
||||||
|
tapable@2.3.3: {}
|
||||||
|
|
||||||
tinybench@2.9.0: {}
|
tinybench@2.9.0: {}
|
||||||
|
|
||||||
tinyexec@1.3.0: {}
|
tinyexec@1.3.0: {}
|
||||||
@@ -1035,7 +1547,7 @@ snapshots:
|
|||||||
|
|
||||||
undici-types@6.21.0: {}
|
undici-types@6.21.0: {}
|
||||||
|
|
||||||
vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.11):
|
vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11):
|
||||||
dependencies:
|
dependencies:
|
||||||
lightningcss: 1.33.0
|
lightningcss: 1.33.0
|
||||||
picomatch: 4.0.5
|
picomatch: 4.0.5
|
||||||
@@ -1046,12 +1558,13 @@ snapshots:
|
|||||||
'@types/node': 22.20.1
|
'@types/node': 22.20.1
|
||||||
esbuild: 0.28.1
|
esbuild: 0.28.1
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
jiti: 2.7.0
|
||||||
tsx: 4.23.11
|
tsx: 4.23.11
|
||||||
|
|
||||||
vitest@4.1.10(@types/node@22.20.1)(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.11)):
|
vitest@4.1.10(@types/node@22.20.1)(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/expect': 4.1.10
|
'@vitest/expect': 4.1.10
|
||||||
'@vitest/mocker': 4.1.10(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.11))
|
'@vitest/mocker': 4.1.10(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11))
|
||||||
'@vitest/pretty-format': 4.1.10
|
'@vitest/pretty-format': 4.1.10
|
||||||
'@vitest/runner': 4.1.10
|
'@vitest/runner': 4.1.10
|
||||||
'@vitest/snapshot': 4.1.10
|
'@vitest/snapshot': 4.1.10
|
||||||
@@ -1068,7 +1581,7 @@ snapshots:
|
|||||||
tinyexec: 1.3.0
|
tinyexec: 1.3.0
|
||||||
tinyglobby: 0.2.17
|
tinyglobby: 0.2.17
|
||||||
tinyrainbow: 3.1.1
|
tinyrainbow: 3.1.1
|
||||||
vite: 8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(tsx@4.23.11)
|
vite: 8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.11)
|
||||||
why-is-node-running: 2.3.0
|
why-is-node-running: 2.3.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 22.20.1
|
'@types/node': 22.20.1
|
||||||
@@ -1081,3 +1594,8 @@ snapshots:
|
|||||||
stackback: 0.0.2
|
stackback: 0.0.2
|
||||||
|
|
||||||
zod@3.25.76: {}
|
zod@3.25.76: {}
|
||||||
|
|
||||||
|
zustand@5.0.14(@types/react@19.2.18)(react@19.2.8):
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.2.18
|
||||||
|
react: 19.2.8
|
||||||
|
|||||||
Reference in New Issue
Block a user