feat(web): implement SWR for instant data fetching
- Add SWR package and global SWRProvider - Create reusable hooks: useTools, useAgents, useCollections, useStats, useLikeStatus, useBundleSize, useActivity - Update tool-search page to use useTools hook - Update agents page to use useAgents hook - Update BundleSize component to use useBundleSize hook - Update LikeButton with optimistic updates via useLikeStatus - Add simple about page with creator info
This commit is contained in:
parent
7483e697fc
commit
0489f5cfdb
17 changed files with 1085 additions and 255 deletions
|
|
@ -27,6 +27,8 @@
|
||||||
"@ai-sdk/openai": "3.0.7",
|
"@ai-sdk/openai": "3.0.7",
|
||||||
"@modelcontextprotocol/sdk": "^1.25.2",
|
"@modelcontextprotocol/sdk": "^1.25.2",
|
||||||
"@prisma/client": "^6.19.1",
|
"@prisma/client": "^6.19.1",
|
||||||
|
"@react-three/drei": "^10.7.7",
|
||||||
|
"@react-three/fiber": "^9.5.0",
|
||||||
"@tpmjs/db": "workspace:*",
|
"@tpmjs/db": "workspace:*",
|
||||||
"@tpmjs/env": "workspace:*",
|
"@tpmjs/env": "workspace:*",
|
||||||
"@tpmjs/npm-client": "workspace:*",
|
"@tpmjs/npm-client": "workspace:*",
|
||||||
|
|
@ -57,7 +59,9 @@
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"resend": "^6.7.0",
|
"resend": "^6.7.0",
|
||||||
"sonner": "^2.0.7",
|
"sonner": "^2.0.7",
|
||||||
|
"swr": "^2.2.5",
|
||||||
"streamdown": "^1.6.11",
|
"streamdown": "^1.6.11",
|
||||||
|
"three": "^0.182.0",
|
||||||
"zod": "^4.3.5"
|
"zod": "^4.3.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -68,6 +72,7 @@
|
||||||
"@types/node": "^25.0.3",
|
"@types/node": "^25.0.3",
|
||||||
"@types/react": "^19.2.7",
|
"@types/react": "^19.2.7",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
|
"@types/three": "^0.182.0",
|
||||||
"autoprefixer": "^10.4.23",
|
"autoprefixer": "^10.4.23",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
"eslint": "^9.39.2",
|
"eslint": "^9.39.2",
|
||||||
|
|
|
||||||
57
apps/web/src/app/about/page.tsx
Normal file
57
apps/web/src/app/about/page.tsx
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { Container } from '@tpmjs/ui/Container/Container';
|
||||||
|
import { Icon } from '@tpmjs/ui/Icon/Icon';
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
import { AppHeader } from '~/components/AppHeader';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'About',
|
||||||
|
description: 'About TPMJS and its creator',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AboutPage(): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-background">
|
||||||
|
<AppHeader />
|
||||||
|
|
||||||
|
<Container size="md" padding="lg" className="py-16">
|
||||||
|
<h1 className="text-3xl font-bold mb-8 text-foreground">About TPMJS</h1>
|
||||||
|
|
||||||
|
<div className="prose prose-neutral dark:prose-invert max-w-none">
|
||||||
|
<p className="text-lg text-foreground-secondary mb-6">
|
||||||
|
TPMJS (Tool Package Manager for JavaScript) is the npm registry for AI agent tools.
|
||||||
|
It was started in 2024 to make it easy for developers to publish and discover tools
|
||||||
|
that AI agents can use.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-xl font-semibold mt-10 mb-4 text-foreground">Creator</h2>
|
||||||
|
|
||||||
|
<p className="text-foreground-secondary mb-6">
|
||||||
|
TPMJS was created by <strong>Ajax Davis</strong> (Thomas Davis).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-6">
|
||||||
|
<a
|
||||||
|
href="https://x.com/ajaxdavis"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center gap-2 text-foreground-secondary hover:text-primary transition-colors"
|
||||||
|
>
|
||||||
|
<Icon icon="x" size="md" />
|
||||||
|
<span>@ajaxdavis</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="https://ajaxdavis.dev"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center gap-2 text-foreground-secondary hover:text-primary transition-colors"
|
||||||
|
>
|
||||||
|
<Icon icon="globe" size="md" />
|
||||||
|
<span>ajaxdavis.dev</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -9,30 +9,12 @@ import { LoadingState } from '@tpmjs/ui/LoadingState/LoadingState';
|
||||||
import { PageHeader } from '@tpmjs/ui/PageHeader/PageHeader';
|
import { PageHeader } from '@tpmjs/ui/PageHeader/PageHeader';
|
||||||
import { Select } from '@tpmjs/ui/Select/Select';
|
import { Select } from '@tpmjs/ui/Select/Select';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { TableVirtuoso } from 'react-virtuoso';
|
import { TableVirtuoso } from 'react-virtuoso';
|
||||||
import { AppHeader } from '~/components/AppHeader';
|
import { AppHeader } from '~/components/AppHeader';
|
||||||
import { CopyDropdown, getAgentCopyOptions } from '~/components/CopyDropdown';
|
import { CopyDropdown, getAgentCopyOptions } from '~/components/CopyDropdown';
|
||||||
import { LikeButton } from '~/components/LikeButton';
|
import { LikeButton } from '~/components/LikeButton';
|
||||||
|
import { type PublicAgent, useAgents } from '~/hooks/useAgents';
|
||||||
interface PublicAgent {
|
|
||||||
id: string;
|
|
||||||
uid: string;
|
|
||||||
name: string;
|
|
||||||
description: string | null;
|
|
||||||
provider: string;
|
|
||||||
modelId: string;
|
|
||||||
likeCount: number;
|
|
||||||
toolCount: number;
|
|
||||||
collectionCount: number;
|
|
||||||
createdAt: string;
|
|
||||||
createdBy: {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
image: string | null;
|
|
||||||
username: string | null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
type SortOption = 'likes' | 'recent' | 'tools';
|
type SortOption = 'likes' | 'recent' | 'tools';
|
||||||
|
|
||||||
|
|
@ -57,68 +39,24 @@ function truncateText(text: string, maxLength: number): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function PublicAgentsPage(): React.ReactElement {
|
export default function PublicAgentsPage(): React.ReactElement {
|
||||||
const [agents, setAgents] = useState<PublicAgent[]>([]);
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
|
||||||
const [hasMore, setHasMore] = useState(false);
|
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
const [sort, setSort] = useState<SortOption>('likes');
|
const [sort, setSort] = useState<SortOption>('likes');
|
||||||
const loadingMore = useRef(false);
|
|
||||||
|
|
||||||
const fetchAgents = useCallback(
|
// Fetch agents using SWR
|
||||||
async (offset: number, resetList = false) => {
|
const { data, isLoading, error: swrError, mutate } = useAgents({ sort });
|
||||||
try {
|
|
||||||
if (loadingMore.current && !resetList) return;
|
|
||||||
loadingMore.current = true;
|
|
||||||
|
|
||||||
const params = new URLSearchParams({
|
const agents = data?.agents ?? [];
|
||||||
limit: '100',
|
const hasMore = data?.pagination.hasMore ?? false;
|
||||||
offset: String(offset),
|
const error = swrError?.message ?? null;
|
||||||
sort,
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await fetch(`/api/public/agents?${params}`);
|
// Filter and sort agents (client-side search)
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
if (data.success) {
|
|
||||||
if (resetList || offset === 0) {
|
|
||||||
setAgents(data.data);
|
|
||||||
} else {
|
|
||||||
setAgents((prev) => [...prev, ...data.data]);
|
|
||||||
}
|
|
||||||
setHasMore(data.pagination.hasMore);
|
|
||||||
} else {
|
|
||||||
setError(data.error?.message || 'Failed to fetch agents');
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Failed to fetch agents:', err);
|
|
||||||
setError('Failed to fetch agents');
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
loadingMore.current = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[sort]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setIsLoading(true);
|
|
||||||
fetchAgents(0, true);
|
|
||||||
}, [fetchAgents]);
|
|
||||||
|
|
||||||
const loadMore = useCallback(() => {
|
|
||||||
if (!hasMore || loadingMore.current) return;
|
|
||||||
fetchAgents(agents.length);
|
|
||||||
}, [hasMore, agents.length, fetchAgents]);
|
|
||||||
|
|
||||||
// Filter and sort agents
|
|
||||||
const filteredAgents = useMemo(() => {
|
const filteredAgents = useMemo(() => {
|
||||||
let result = agents;
|
let result = agents;
|
||||||
|
|
||||||
if (search) {
|
if (search) {
|
||||||
const query = search.toLowerCase();
|
const query = search.toLowerCase();
|
||||||
result = result.filter(
|
result = result.filter(
|
||||||
(a) =>
|
(a: PublicAgent) =>
|
||||||
a.name.toLowerCase().includes(query) ||
|
a.name.toLowerCase().includes(query) ||
|
||||||
a.description?.toLowerCase().includes(query) ||
|
a.description?.toLowerCase().includes(query) ||
|
||||||
a.provider.toLowerCase().includes(query)
|
a.provider.toLowerCase().includes(query)
|
||||||
|
|
@ -253,7 +191,7 @@ export default function PublicAgentsPage(): React.ReactElement {
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
{error ? (
|
{error ? (
|
||||||
<ErrorState message={error} onRetry={() => fetchAgents(0, true)} />
|
<ErrorState message={error} onRetry={() => mutate()} />
|
||||||
) : isLoading ? (
|
) : isLoading ? (
|
||||||
<LoadingState message="Loading agents..." size="lg" />
|
<LoadingState message="Loading agents..." size="lg" />
|
||||||
) : filteredAgents.length === 0 ? (
|
) : filteredAgents.length === 0 ? (
|
||||||
|
|
@ -269,7 +207,6 @@ export default function PublicAgentsPage(): React.ReactElement {
|
||||||
style={{ height: 'calc(100vh - 350px)', minHeight: '400px' }}
|
style={{ height: 'calc(100vh - 350px)', minHeight: '400px' }}
|
||||||
data={filteredAgents}
|
data={filteredAgents}
|
||||||
overscan={30}
|
overscan={30}
|
||||||
endReached={loadMore}
|
|
||||||
fixedHeaderContent={TableHeader}
|
fixedHeaderContent={TableHeader}
|
||||||
itemContent={TableRow}
|
itemContent={TableRow}
|
||||||
components={{
|
components={{
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import Script from 'next/script';
|
||||||
import { Toaster } from 'sonner';
|
import { Toaster } from 'sonner';
|
||||||
import { AppFooter } from '../components/AppFooter';
|
import { AppFooter } from '../components/AppFooter';
|
||||||
import { ThemeProvider } from '../components/providers/ThemeProvider';
|
import { ThemeProvider } from '../components/providers/ThemeProvider';
|
||||||
|
import { SWRProvider } from '../components/SWRProvider';
|
||||||
import './globals.css';
|
import './globals.css';
|
||||||
|
|
||||||
const spaceGrotesk = Space_Grotesk({
|
const spaceGrotesk = Space_Grotesk({
|
||||||
|
|
@ -157,11 +158,13 @@ export default function RootLayout({
|
||||||
enableSystem={true}
|
enableSystem={true}
|
||||||
disableTransitionOnChange={false}
|
disableTransitionOnChange={false}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col min-h-screen">
|
<SWRProvider>
|
||||||
<div className="flex-1">{children}</div>
|
<div className="flex flex-col min-h-screen">
|
||||||
<AppFooter />
|
<div className="flex-1">{children}</div>
|
||||||
</div>
|
<AppFooter />
|
||||||
<Toaster position="bottom-right" richColors closeButton />
|
</div>
|
||||||
|
<Toaster position="bottom-right" richColors closeButton />
|
||||||
|
</SWRProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
<Analytics />
|
<Analytics />
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import { LoadingState } from '@tpmjs/ui/LoadingState/LoadingState';
|
||||||
import { PageHeader } from '@tpmjs/ui/PageHeader/PageHeader';
|
import { PageHeader } from '@tpmjs/ui/PageHeader/PageHeader';
|
||||||
import { Select } from '@tpmjs/ui/Select/Select';
|
import { Select } from '@tpmjs/ui/Select/Select';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { TableVirtuoso } from 'react-virtuoso';
|
import { TableVirtuoso } from 'react-virtuoso';
|
||||||
import { AppHeader } from '~/components/AppHeader';
|
import { AppHeader } from '~/components/AppHeader';
|
||||||
import { CopyButton } from '~/components/CopyButton';
|
import { CopyButton } from '~/components/CopyButton';
|
||||||
|
|
@ -21,26 +21,7 @@ import {
|
||||||
getInstallCommand,
|
getInstallCommand,
|
||||||
usePackageManager,
|
usePackageManager,
|
||||||
} from '~/components/PackageManagerSelector';
|
} from '~/components/PackageManagerSelector';
|
||||||
|
import { type Tool, useTools } from '~/hooks/useTools';
|
||||||
interface Tool {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
qualityScore: string;
|
|
||||||
likeCount?: number;
|
|
||||||
importHealth?: 'HEALTHY' | 'BROKEN' | 'UNKNOWN';
|
|
||||||
executionHealth?: 'HEALTHY' | 'BROKEN' | 'UNKNOWN';
|
|
||||||
createdAt: string;
|
|
||||||
package: {
|
|
||||||
npmPackageName: string;
|
|
||||||
npmVersion: string;
|
|
||||||
npmPublishedAt: string;
|
|
||||||
category: string;
|
|
||||||
npmRepository: { url: string; type: string } | null;
|
|
||||||
isOfficial: boolean;
|
|
||||||
npmDownloadsLastMonth: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
type SortOption = 'downloads' | 'likes' | 'recent' | 'name';
|
type SortOption = 'downloads' | 'likes' | 'recent' | 'name';
|
||||||
|
|
||||||
|
|
@ -97,60 +78,28 @@ export default function ToolSearchPage(): React.ReactElement {
|
||||||
const [categoryFilter, setCategoryFilter] = useState('all');
|
const [categoryFilter, setCategoryFilter] = useState('all');
|
||||||
const [healthFilter, setHealthFilter] = useState('all');
|
const [healthFilter, setHealthFilter] = useState('all');
|
||||||
const [sortBy, setSortBy] = useState<SortOption>('downloads');
|
const [sortBy, setSortBy] = useState<SortOption>('downloads');
|
||||||
const [tools, setTools] = useState<Tool[]>([]);
|
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
|
||||||
const [availableCategories, setAvailableCategories] = useState<string[]>([]);
|
|
||||||
const [packageManager, setPackageManager] = usePackageManager();
|
const [packageManager, setPackageManager] = usePackageManager();
|
||||||
|
|
||||||
// Fetch tools from API
|
// Fetch tools from API using SWR
|
||||||
useEffect(() => {
|
const { data: tools = [], isLoading: loading, error: swrError } = useTools({
|
||||||
const fetchTools = async () => {
|
category: categoryFilter !== 'all' ? categoryFilter : undefined,
|
||||||
try {
|
importHealth: healthFilter === 'healthy' ? 'HEALTHY' : undefined,
|
||||||
setLoading(true);
|
executionHealth: healthFilter === 'healthy' ? 'HEALTHY' : undefined,
|
||||||
const params = new URLSearchParams();
|
broken: healthFilter === 'broken' ? true : undefined,
|
||||||
|
});
|
||||||
|
|
||||||
if (categoryFilter !== 'all') {
|
const error = swrError?.message ?? null;
|
||||||
params.set('category', categoryFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (healthFilter === 'healthy') {
|
// Extract unique categories from all tools
|
||||||
params.set('importHealth', 'HEALTHY');
|
const availableCategories = useMemo(() => {
|
||||||
params.set('executionHealth', 'HEALTHY');
|
const categories = new Set<string>();
|
||||||
} else if (healthFilter === 'broken') {
|
for (const tool of tools) {
|
||||||
params.set('broken', 'true');
|
if (tool.package.category) {
|
||||||
}
|
categories.add(tool.package.category);
|
||||||
|
|
||||||
// Fetch all tools (no pagination limit)
|
|
||||||
params.set('limit', '1000');
|
|
||||||
const toolsResponse = await fetch(`/api/tools?${params.toString()}`);
|
|
||||||
const toolsData = await toolsResponse.json();
|
|
||||||
|
|
||||||
if (toolsData.success) {
|
|
||||||
const fetchedTools = toolsData.data;
|
|
||||||
setTools(fetchedTools);
|
|
||||||
setError(null);
|
|
||||||
|
|
||||||
// Extract unique categories from all tools
|
|
||||||
const categories = new Set<string>();
|
|
||||||
for (const tool of fetchedTools) {
|
|
||||||
if (tool.package.category) {
|
|
||||||
categories.add(tool.package.category);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setAvailableCategories(Array.from(categories).sort());
|
|
||||||
} else {
|
|
||||||
setError(toolsData.error || 'Failed to fetch tools');
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
return Array.from(categories).sort();
|
||||||
fetchTools();
|
}, [tools]);
|
||||||
}, [categoryFilter, healthFilter]);
|
|
||||||
|
|
||||||
// Filter and sort tools
|
// Filter and sort tools
|
||||||
const filteredTools = useMemo(() => {
|
const filteredTools = useMemo(() => {
|
||||||
|
|
@ -160,7 +109,7 @@ export default function ToolSearchPage(): React.ReactElement {
|
||||||
if (searchQuery) {
|
if (searchQuery) {
|
||||||
const query = searchQuery.toLowerCase();
|
const query = searchQuery.toLowerCase();
|
||||||
result = result.filter(
|
result = result.filter(
|
||||||
(tool) =>
|
(tool: Tool) =>
|
||||||
tool.name.toLowerCase().includes(query) ||
|
tool.name.toLowerCase().includes(query) ||
|
||||||
tool.package.npmPackageName.toLowerCase().includes(query) ||
|
tool.package.npmPackageName.toLowerCase().includes(query) ||
|
||||||
tool.description.toLowerCase().includes(query)
|
tool.description.toLowerCase().includes(query)
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,7 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@tpmjs/ui/Card/Card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@tpmjs/ui/Card/Card';
|
||||||
import { useEffect, useState } from 'react';
|
import { useBundleSize } from '~/hooks/useBundleSize';
|
||||||
|
|
||||||
interface BundleSizeData {
|
|
||||||
name: string;
|
|
||||||
version: string;
|
|
||||||
size: number;
|
|
||||||
gzip: number;
|
|
||||||
dependencyCount: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface BundleSizeProps {
|
interface BundleSizeProps {
|
||||||
packageName: string;
|
packageName: string;
|
||||||
|
|
@ -25,42 +17,10 @@ function formatBytes(bytes: number): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BundleSize({ packageName, version }: BundleSizeProps): React.ReactElement | null {
|
export function BundleSize({ packageName, version }: BundleSizeProps): React.ReactElement | null {
|
||||||
const [data, setData] = useState<BundleSizeData | null>(null);
|
const { data, isLoading: loading, error } = useBundleSize(packageName, version);
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
// Don't render anything if package not found (common for scoped packages) or error
|
||||||
const fetchBundleSize = async () => {
|
if (error || (!loading && !data)) {
|
||||||
setLoading(true);
|
|
||||||
setError(null);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const params = new URLSearchParams({ package: packageName, version });
|
|
||||||
const response = await fetch(`/api/bundlephobia?${params}`);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
if (response.status === 404) {
|
|
||||||
setError('not-found');
|
|
||||||
} else {
|
|
||||||
setError('failed');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await response.json();
|
|
||||||
setData(result);
|
|
||||||
} catch {
|
|
||||||
setError('failed');
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchBundleSize();
|
|
||||||
}, [packageName, version]);
|
|
||||||
|
|
||||||
// Don't render anything if package not found (common for scoped packages)
|
|
||||||
if (error === 'not-found') {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,7 +40,7 @@ export function BundleSize({ packageName, version }: BundleSizeProps): React.Rea
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error || !data) {
|
if (!data) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@
|
||||||
import { useSession } from '@/lib/auth-client';
|
import { useSession } from '@/lib/auth-client';
|
||||||
import { Button } from '@tpmjs/ui/Button/Button';
|
import { Button } from '@tpmjs/ui/Button/Button';
|
||||||
import { Icon } from '@tpmjs/ui/Icon/Icon';
|
import { Icon } from '@tpmjs/ui/Icon/Icon';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
import { useLikeStatus } from '~/hooks/useLikeStatus';
|
||||||
|
|
||||||
export type LikeEntityType = 'tool' | 'collection' | 'agent';
|
export type LikeEntityType = 'tool' | 'collection' | 'agent';
|
||||||
|
|
||||||
|
|
@ -31,41 +32,19 @@ export function LikeButton({
|
||||||
onLikeChange,
|
onLikeChange,
|
||||||
}: LikeButtonProps): React.ReactElement {
|
}: LikeButtonProps): React.ReactElement {
|
||||||
const { data: session } = useSession();
|
const { data: session } = useSession();
|
||||||
const [liked, setLiked] = useState(initialLiked);
|
|
||||||
const [count, setCount] = useState(initialCount);
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
const [hasFetched, setHasFetched] = useState(false);
|
|
||||||
const [showTooltip, setShowTooltip] = useState(false);
|
const [showTooltip, setShowTooltip] = useState(false);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
// Fetch initial like status when user is logged in
|
// Use SWR for like status with optimistic updates
|
||||||
useEffect(() => {
|
const { data, toggleLike } = useLikeStatus(
|
||||||
if (!session || hasFetched) return;
|
entityType,
|
||||||
|
entityId,
|
||||||
|
!!session,
|
||||||
|
{ liked: initialLiked, likeCount: initialCount }
|
||||||
|
);
|
||||||
|
|
||||||
const fetchLikeStatus = async () => {
|
const liked = data?.liked ?? initialLiked;
|
||||||
try {
|
const count = data?.likeCount ?? initialCount;
|
||||||
const response = await fetch(`/api/${entityType}s/${entityId}/like`);
|
|
||||||
const data = await response.json();
|
|
||||||
if (data.success) {
|
|
||||||
setLiked(data.data.liked);
|
|
||||||
setCount(data.data.likeCount);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to fetch like status:', error);
|
|
||||||
} finally {
|
|
||||||
setHasFetched(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchLikeStatus();
|
|
||||||
}, [session, entityType, entityId, hasFetched]);
|
|
||||||
|
|
||||||
// Update from props when they change
|
|
||||||
useEffect(() => {
|
|
||||||
if (!hasFetched) {
|
|
||||||
setLiked(initialLiked);
|
|
||||||
setCount(initialCount);
|
|
||||||
}
|
|
||||||
}, [initialLiked, initialCount, hasFetched]);
|
|
||||||
|
|
||||||
const handleClick = useCallback(async () => {
|
const handleClick = useCallback(async () => {
|
||||||
if (!session) {
|
if (!session) {
|
||||||
|
|
@ -77,40 +56,17 @@ export function LikeButton({
|
||||||
|
|
||||||
if (isLoading) return;
|
if (isLoading) return;
|
||||||
|
|
||||||
// Optimistic update
|
|
||||||
const newLiked = !liked;
|
|
||||||
const newCount = newLiked ? count + 1 : Math.max(0, count - 1);
|
|
||||||
setLiked(newLiked);
|
|
||||||
setCount(newCount);
|
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/${entityType}s/${entityId}/like`, {
|
await toggleLike();
|
||||||
method: newLiked ? 'POST' : 'DELETE',
|
// Call the onLikeChange callback if provided
|
||||||
});
|
if (onLikeChange && data) {
|
||||||
|
onLikeChange(!data.liked, data.liked ? data.likeCount - 1 : data.likeCount + 1);
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
if (data.success) {
|
|
||||||
// Update with server values
|
|
||||||
setLiked(data.data.liked);
|
|
||||||
setCount(data.data.likeCount);
|
|
||||||
onLikeChange?.(data.data.liked, data.data.likeCount);
|
|
||||||
} else {
|
|
||||||
// Revert on error
|
|
||||||
setLiked(!newLiked);
|
|
||||||
setCount(liked ? count : Math.max(0, count - 1));
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to toggle like:', error);
|
|
||||||
// Revert on error
|
|
||||||
setLiked(!newLiked);
|
|
||||||
setCount(liked ? count : Math.max(0, count - 1));
|
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}, [session, liked, count, isLoading, entityType, entityId, onLikeChange]);
|
}, [session, isLoading, toggleLike, onLikeChange, data]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative inline-block">
|
<div className="relative inline-block">
|
||||||
|
|
|
||||||
23
apps/web/src/components/SWRProvider.tsx
Normal file
23
apps/web/src/components/SWRProvider.tsx
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
|
import { SWRConfig } from 'swr';
|
||||||
|
import { fetcher } from '~/lib/swr/fetcher';
|
||||||
|
|
||||||
|
interface SWRProviderProps {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SWRProvider({ children }: SWRProviderProps): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<SWRConfig
|
||||||
|
value={{
|
||||||
|
fetcher,
|
||||||
|
revalidateOnFocus: false,
|
||||||
|
dedupingInterval: 5000,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</SWRConfig>
|
||||||
|
);
|
||||||
|
}
|
||||||
91
apps/web/src/hooks/useActivity.ts
Normal file
91
apps/web/src/hooks/useActivity.ts
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
import useSWRInfinite from 'swr/infinite';
|
||||||
|
|
||||||
|
export interface Activity {
|
||||||
|
id: string;
|
||||||
|
type: string;
|
||||||
|
metadata: Record<string, unknown>;
|
||||||
|
createdAt: string;
|
||||||
|
tool?: {
|
||||||
|
name: string;
|
||||||
|
package: { npmPackageName: string };
|
||||||
|
};
|
||||||
|
agent?: {
|
||||||
|
name: string;
|
||||||
|
uid: string;
|
||||||
|
};
|
||||||
|
collection?: {
|
||||||
|
name: string;
|
||||||
|
uid: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ActivityResponse {
|
||||||
|
activities: Activity[];
|
||||||
|
pagination: {
|
||||||
|
nextCursor: string | null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Infinite scroll hook for user activity stream
|
||||||
|
*/
|
||||||
|
export function useActivity(limit = 20) {
|
||||||
|
const getKey = (pageIndex: number, previousPageData: ActivityResponse | null) => {
|
||||||
|
// Reached the end
|
||||||
|
if (previousPageData && !previousPageData.pagination.nextCursor) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First page
|
||||||
|
if (pageIndex === 0) {
|
||||||
|
return `/api/user/activity?limit=${limit}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next pages
|
||||||
|
const cursor = previousPageData?.pagination.nextCursor;
|
||||||
|
return `/api/user/activity?limit=${limit}&cursor=${cursor}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data, error, isLoading, isValidating, size, setSize, mutate } =
|
||||||
|
useSWRInfinite<ActivityResponse>(
|
||||||
|
getKey,
|
||||||
|
async (url: string) => {
|
||||||
|
const res = await fetch(url);
|
||||||
|
const json = await res.json();
|
||||||
|
|
||||||
|
if (!json.success) {
|
||||||
|
throw new Error(json.error || 'Failed to fetch activity');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
activities: json.data,
|
||||||
|
pagination: json.pagination,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
{
|
||||||
|
revalidateFirstPage: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Flatten all activities from all pages
|
||||||
|
const activities = data ? data.flatMap((page: ActivityResponse) => page.activities) : [];
|
||||||
|
|
||||||
|
// Check if there are more pages
|
||||||
|
const hasMore = data ? data[data.length - 1]?.pagination.nextCursor !== null : false;
|
||||||
|
|
||||||
|
const loadMore = () => {
|
||||||
|
if (hasMore && !isValidating) {
|
||||||
|
setSize(size + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
activities,
|
||||||
|
isLoading,
|
||||||
|
isLoadingMore: isValidating && data && data.length > 0,
|
||||||
|
error,
|
||||||
|
hasMore,
|
||||||
|
loadMore,
|
||||||
|
mutate,
|
||||||
|
};
|
||||||
|
}
|
||||||
66
apps/web/src/hooks/useAgents.ts
Normal file
66
apps/web/src/hooks/useAgents.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
import useSWR from 'swr';
|
||||||
|
|
||||||
|
export interface PublicAgent {
|
||||||
|
id: string;
|
||||||
|
uid: string;
|
||||||
|
name: string;
|
||||||
|
description: string | null;
|
||||||
|
provider: string;
|
||||||
|
modelId: string;
|
||||||
|
likeCount: number;
|
||||||
|
toolCount: number;
|
||||||
|
collectionCount: number;
|
||||||
|
createdAt: string;
|
||||||
|
createdBy: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
image: string | null;
|
||||||
|
username: string | null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UseAgentsParams {
|
||||||
|
sort?: 'likes' | 'recent' | 'tools';
|
||||||
|
limit?: number;
|
||||||
|
offset?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AgentsResponse {
|
||||||
|
agents: PublicAgent[];
|
||||||
|
pagination: {
|
||||||
|
hasMore: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch public agents
|
||||||
|
*/
|
||||||
|
export function useAgents(params: UseAgentsParams = {}) {
|
||||||
|
const searchParams = new URLSearchParams();
|
||||||
|
|
||||||
|
searchParams.set('limit', String(params.limit ?? 100));
|
||||||
|
searchParams.set('offset', String(params.offset ?? 0));
|
||||||
|
if (params.sort) {
|
||||||
|
searchParams.set('sort', params.sort);
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
// Custom response handler since the API returns { success, data, pagination }
|
||||||
|
return useSWR<AgentsResponse>(
|
||||||
|
`/api/public/agents?${queryString}`,
|
||||||
|
async (url: string) => {
|
||||||
|
const res = await fetch(url);
|
||||||
|
const json = await res.json();
|
||||||
|
|
||||||
|
if (!json.success) {
|
||||||
|
throw new Error(json.error?.message || 'Failed to fetch agents');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
agents: json.data,
|
||||||
|
pagination: json.pagination,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
31
apps/web/src/hooks/useBundleSize.ts
Normal file
31
apps/web/src/hooks/useBundleSize.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
import useSWR from 'swr';
|
||||||
|
|
||||||
|
export interface BundleSizeData {
|
||||||
|
name: string;
|
||||||
|
version: string;
|
||||||
|
size: number;
|
||||||
|
gzip: number;
|
||||||
|
dependencyCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch bundle size data from bundlephobia API
|
||||||
|
* Returns null for the key if packageName is not provided (disables fetching)
|
||||||
|
*/
|
||||||
|
export function useBundleSize(packageName: string | undefined, version?: string) {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
if (packageName) {
|
||||||
|
params.set('package', packageName);
|
||||||
|
if (version) {
|
||||||
|
params.set('version', version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return useSWR<BundleSizeData>(
|
||||||
|
packageName ? `/api/bundlephobia?${params.toString()}` : null,
|
||||||
|
{
|
||||||
|
// Don't retry on 404s (common for scoped packages)
|
||||||
|
shouldRetryOnError: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
64
apps/web/src/hooks/useCollections.ts
Normal file
64
apps/web/src/hooks/useCollections.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
import useSWR from 'swr';
|
||||||
|
|
||||||
|
export interface PublicCollection {
|
||||||
|
id: string;
|
||||||
|
uid: string;
|
||||||
|
name: string;
|
||||||
|
description: string | null;
|
||||||
|
likeCount: number;
|
||||||
|
forkCount: number;
|
||||||
|
toolCount: number;
|
||||||
|
createdAt: string;
|
||||||
|
createdBy: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
image: string | null;
|
||||||
|
username: string | null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UseCollectionsParams {
|
||||||
|
sort?: 'likes' | 'recent' | 'tools';
|
||||||
|
limit?: number;
|
||||||
|
offset?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CollectionsResponse {
|
||||||
|
collections: PublicCollection[];
|
||||||
|
pagination: {
|
||||||
|
hasMore: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch public collections
|
||||||
|
*/
|
||||||
|
export function useCollections(params: UseCollectionsParams = {}) {
|
||||||
|
const searchParams = new URLSearchParams();
|
||||||
|
|
||||||
|
searchParams.set('limit', String(params.limit ?? 100));
|
||||||
|
searchParams.set('offset', String(params.offset ?? 0));
|
||||||
|
if (params.sort) {
|
||||||
|
searchParams.set('sort', params.sort);
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
// Custom response handler since the API returns { success, data, pagination }
|
||||||
|
return useSWR<CollectionsResponse>(
|
||||||
|
`/api/public/collections?${queryString}`,
|
||||||
|
async (url: string) => {
|
||||||
|
const res = await fetch(url);
|
||||||
|
const json = await res.json();
|
||||||
|
|
||||||
|
if (!json.success) {
|
||||||
|
throw new Error(json.error?.message || 'Failed to fetch collections');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
collections: json.data,
|
||||||
|
pagination: json.pagination,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
76
apps/web/src/hooks/useLikeStatus.ts
Normal file
76
apps/web/src/hooks/useLikeStatus.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
import useSWR, { type KeyedMutator } from 'swr';
|
||||||
|
import type { LikeEntityType } from '~/components/LikeButton';
|
||||||
|
|
||||||
|
export interface LikeStatusData {
|
||||||
|
liked: boolean;
|
||||||
|
likeCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UseLikeStatusReturn {
|
||||||
|
data: LikeStatusData | undefined;
|
||||||
|
isLoading: boolean;
|
||||||
|
error: Error | undefined;
|
||||||
|
mutate: KeyedMutator<LikeStatusData>;
|
||||||
|
toggleLike: () => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook for managing like status with optimistic updates
|
||||||
|
* @param entityType - 'tool' | 'collection' | 'agent'
|
||||||
|
* @param entityId - The ID of the entity
|
||||||
|
* @param enabled - Whether to enable fetching (typically based on session)
|
||||||
|
* @param initialData - Optional initial data to use before fetch completes
|
||||||
|
*/
|
||||||
|
export function useLikeStatus(
|
||||||
|
entityType: LikeEntityType,
|
||||||
|
entityId: string,
|
||||||
|
enabled: boolean,
|
||||||
|
initialData?: LikeStatusData
|
||||||
|
): UseLikeStatusReturn {
|
||||||
|
const key = enabled ? `/api/${entityType}s/${entityId}/like` : null;
|
||||||
|
|
||||||
|
const { data, error, isLoading, mutate } = useSWR<LikeStatusData>(key, {
|
||||||
|
fallbackData: initialData,
|
||||||
|
revalidateOnFocus: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const toggleLike = async () => {
|
||||||
|
if (!data) return;
|
||||||
|
|
||||||
|
const newLiked = !data.liked;
|
||||||
|
const newCount = newLiked ? data.likeCount + 1 : Math.max(0, data.likeCount - 1);
|
||||||
|
|
||||||
|
// Optimistic update
|
||||||
|
await mutate(
|
||||||
|
{ liked: newLiked, likeCount: newCount },
|
||||||
|
{ revalidate: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/api/${entityType}s/${entityId}/like`, {
|
||||||
|
method: newLiked ? 'POST' : 'DELETE',
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
// Update with server values
|
||||||
|
await mutate(result.data, { revalidate: false });
|
||||||
|
} else {
|
||||||
|
// Revert on error
|
||||||
|
await mutate(data, { revalidate: false });
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Revert on error
|
||||||
|
await mutate(data, { revalidate: false });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
isLoading,
|
||||||
|
error,
|
||||||
|
mutate,
|
||||||
|
toggleLike,
|
||||||
|
};
|
||||||
|
}
|
||||||
61
apps/web/src/hooks/useStats.ts
Normal file
61
apps/web/src/hooks/useStats.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
import useSWR from 'swr';
|
||||||
|
|
||||||
|
export interface PlatformStats {
|
||||||
|
packages: number;
|
||||||
|
tools: number;
|
||||||
|
agents: number;
|
||||||
|
collections: number;
|
||||||
|
executions: number;
|
||||||
|
users: number;
|
||||||
|
categories: { category: string; _count: { _all: number } }[];
|
||||||
|
healthyTools: number;
|
||||||
|
brokenTools: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExecutionStats {
|
||||||
|
total: number;
|
||||||
|
successRate: number;
|
||||||
|
avgDurationMs: number;
|
||||||
|
dailyExecutions: { date: string; count: number }[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HistorySnapshot {
|
||||||
|
date: string;
|
||||||
|
data: {
|
||||||
|
packages?: number;
|
||||||
|
tools?: number;
|
||||||
|
agents?: number;
|
||||||
|
collections?: number;
|
||||||
|
users?: number;
|
||||||
|
executions?: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch platform statistics
|
||||||
|
* Returns multiple SWR hooks for parallel fetching
|
||||||
|
*/
|
||||||
|
export function useStats() {
|
||||||
|
const stats = useSWR<PlatformStats>('/api/stats');
|
||||||
|
const executions = useSWR<ExecutionStats>('/api/stats/executions');
|
||||||
|
const history = useSWR<HistorySnapshot[]>('/api/sync/stats-snapshot?days=90');
|
||||||
|
|
||||||
|
return {
|
||||||
|
stats: {
|
||||||
|
data: stats.data,
|
||||||
|
isLoading: stats.isLoading,
|
||||||
|
error: stats.error,
|
||||||
|
},
|
||||||
|
executions: {
|
||||||
|
data: executions.data,
|
||||||
|
isLoading: executions.isLoading,
|
||||||
|
error: executions.error,
|
||||||
|
},
|
||||||
|
history: {
|
||||||
|
data: history.data,
|
||||||
|
isLoading: history.isLoading,
|
||||||
|
error: history.error,
|
||||||
|
},
|
||||||
|
isLoading: stats.isLoading || executions.isLoading || history.isLoading,
|
||||||
|
};
|
||||||
|
}
|
||||||
51
apps/web/src/hooks/useTools.ts
Normal file
51
apps/web/src/hooks/useTools.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import useSWR from 'swr';
|
||||||
|
|
||||||
|
export interface Tool {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
qualityScore: string;
|
||||||
|
likeCount?: number;
|
||||||
|
importHealth?: 'HEALTHY' | 'BROKEN' | 'UNKNOWN';
|
||||||
|
executionHealth?: 'HEALTHY' | 'BROKEN' | 'UNKNOWN';
|
||||||
|
createdAt: string;
|
||||||
|
package: {
|
||||||
|
npmPackageName: string;
|
||||||
|
npmVersion: string;
|
||||||
|
npmPublishedAt: string;
|
||||||
|
category: string;
|
||||||
|
npmRepository: { url: string; type: string } | null;
|
||||||
|
isOfficial: boolean;
|
||||||
|
npmDownloadsLastMonth: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UseToolsParams {
|
||||||
|
category?: string;
|
||||||
|
importHealth?: string;
|
||||||
|
executionHealth?: string;
|
||||||
|
broken?: boolean;
|
||||||
|
limit?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useTools(params: UseToolsParams = {}) {
|
||||||
|
const searchParams = new URLSearchParams();
|
||||||
|
|
||||||
|
if (params.category && params.category !== 'all') {
|
||||||
|
searchParams.set('category', params.category);
|
||||||
|
}
|
||||||
|
if (params.importHealth) {
|
||||||
|
searchParams.set('importHealth', params.importHealth);
|
||||||
|
}
|
||||||
|
if (params.executionHealth) {
|
||||||
|
searchParams.set('executionHealth', params.executionHealth);
|
||||||
|
}
|
||||||
|
if (params.broken) {
|
||||||
|
searchParams.set('broken', 'true');
|
||||||
|
}
|
||||||
|
searchParams.set('limit', String(params.limit ?? 1000));
|
||||||
|
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
return useSWR<Tool[]>(`/api/tools?${queryString}`);
|
||||||
|
}
|
||||||
14
apps/web/src/lib/swr/fetcher.ts
Normal file
14
apps/web/src/lib/swr/fetcher.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
/**
|
||||||
|
* SWR fetcher that handles our API response format
|
||||||
|
* All API responses have { success: boolean, data: T, error?: string }
|
||||||
|
*/
|
||||||
|
export const fetcher = async <T>(url: string): Promise<T> => {
|
||||||
|
const res = await fetch(url);
|
||||||
|
const json = await res.json();
|
||||||
|
|
||||||
|
if (!json.success) {
|
||||||
|
throw new Error(json.error || 'Request failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.data;
|
||||||
|
};
|
||||||
486
pnpm-lock.yaml
generated
486
pnpm-lock.yaml
generated
|
|
@ -248,6 +248,12 @@ importers:
|
||||||
'@prisma/client':
|
'@prisma/client':
|
||||||
specifier: ^6.19.1
|
specifier: ^6.19.1
|
||||||
version: 6.19.1(prisma@6.19.1(typescript@5.9.3))(typescript@5.9.3)
|
version: 6.19.1(prisma@6.19.1(typescript@5.9.3))(typescript@5.9.3)
|
||||||
|
'@react-three/drei':
|
||||||
|
specifier: ^10.7.7
|
||||||
|
version: 10.7.7(@react-three/fiber@9.5.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(three@0.182.0))(@types/react@19.2.7)(@types/three@0.182.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(three@0.182.0)
|
||||||
|
'@react-three/fiber':
|
||||||
|
specifier: ^9.5.0
|
||||||
|
version: 9.5.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(three@0.182.0)
|
||||||
'@tpmjs/db':
|
'@tpmjs/db':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/db
|
version: link:../../packages/db
|
||||||
|
|
@ -341,6 +347,12 @@ importers:
|
||||||
streamdown:
|
streamdown:
|
||||||
specifier: ^1.6.11
|
specifier: ^1.6.11
|
||||||
version: 1.6.11(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(react@19.2.3)
|
version: 1.6.11(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(react@19.2.3)
|
||||||
|
swr:
|
||||||
|
specifier: ^2.2.5
|
||||||
|
version: 2.3.8(react@19.2.3)
|
||||||
|
three:
|
||||||
|
specifier: ^0.182.0
|
||||||
|
version: 0.182.0
|
||||||
zod:
|
zod:
|
||||||
specifier: ^4.3.5
|
specifier: ^4.3.5
|
||||||
version: 4.3.5
|
version: 4.3.5
|
||||||
|
|
@ -366,6 +378,9 @@ importers:
|
||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
specifier: ^19.2.3
|
specifier: ^19.2.3
|
||||||
version: 19.2.3(@types/react@19.2.7)
|
version: 19.2.3(@types/react@19.2.7)
|
||||||
|
'@types/three':
|
||||||
|
specifier: ^0.182.0
|
||||||
|
version: 0.182.0
|
||||||
autoprefixer:
|
autoprefixer:
|
||||||
specifier: ^10.4.23
|
specifier: ^10.4.23
|
||||||
version: 10.4.23(postcss@8.5.6)
|
version: 10.4.23(postcss@8.5.6)
|
||||||
|
|
@ -4328,6 +4343,9 @@ packages:
|
||||||
resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==}
|
resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
'@dimforge/rapier3d-compat@0.12.0':
|
||||||
|
resolution: {integrity: sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==}
|
||||||
|
|
||||||
'@drizzle-team/brocli@0.10.2':
|
'@drizzle-team/brocli@0.10.2':
|
||||||
resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
|
resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
|
||||||
|
|
||||||
|
|
@ -5133,6 +5151,9 @@ packages:
|
||||||
'@types/react': '>=16'
|
'@types/react': '>=16'
|
||||||
react: '>=16'
|
react: '>=16'
|
||||||
|
|
||||||
|
'@mediapipe/tasks-vision@0.10.17':
|
||||||
|
resolution: {integrity: sha512-CZWV/q6TTe8ta61cZXjfnnHsfWIdFhms03M9T7Cnd5y2mdpylJM0rF1qRq+wsQVRMLz1OYPVEBU9ph2Bx8cxrg==}
|
||||||
|
|
||||||
'@mendable/firecrawl-js@4.10.0':
|
'@mendable/firecrawl-js@4.10.0':
|
||||||
resolution: {integrity: sha512-40qtKCVY3a1A4Y6t/m5Ar10HbzrWuyCNt7vR3uBh+j14GZC0JoxEkjaFRC00wBmPD9N5JMT4gmTXvzM/SI9enw==}
|
resolution: {integrity: sha512-40qtKCVY3a1A4Y6t/m5Ar10HbzrWuyCNt7vR3uBh+j14GZC0JoxEkjaFRC00wBmPD9N5JMT4gmTXvzM/SI9enw==}
|
||||||
engines: {node: '>=22.0.0'}
|
engines: {node: '>=22.0.0'}
|
||||||
|
|
@ -5156,6 +5177,11 @@ packages:
|
||||||
'@mongodb-js/saslprep@1.4.4':
|
'@mongodb-js/saslprep@1.4.4':
|
||||||
resolution: {integrity: sha512-p7X/ytJDIdwUfFL/CLOhKgdfJe1Fa8uw9seJYvdOmnP9JBWGWHW69HkOixXS6Wy9yvGf1MbhcS6lVmrhy4jm2g==}
|
resolution: {integrity: sha512-p7X/ytJDIdwUfFL/CLOhKgdfJe1Fa8uw9seJYvdOmnP9JBWGWHW69HkOixXS6Wy9yvGf1MbhcS6lVmrhy4jm2g==}
|
||||||
|
|
||||||
|
'@monogrid/gainmap-js@3.4.0':
|
||||||
|
resolution: {integrity: sha512-2Z0FATFHaoYJ8b+Y4y4Hgfn3FRFwuU5zRrk+9dFWp4uGAdHGqVEdP7HP+gLA3X469KXHmfupJaUbKo1b/aDKIg==}
|
||||||
|
peerDependencies:
|
||||||
|
three: '>= 0.159.0'
|
||||||
|
|
||||||
'@mozilla/readability@0.6.0':
|
'@mozilla/readability@0.6.0':
|
||||||
resolution: {integrity: sha512-juG5VWh4qAivzTAeMzvY9xs9HY5rAcr2E4I7tiSSCokRFi7XIZCAu92ZkSTsIj1OPceCifL3cpfteP3pDT9/QQ==}
|
resolution: {integrity: sha512-juG5VWh4qAivzTAeMzvY9xs9HY5rAcr2E4I7tiSSCokRFi7XIZCAu92ZkSTsIj1OPceCifL3cpfteP3pDT9/QQ==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
@ -5454,6 +5480,42 @@ packages:
|
||||||
react: ^18.0.0 || ^19.0.0
|
react: ^18.0.0 || ^19.0.0
|
||||||
react-dom: ^18.0.0 || ^19.0.0
|
react-dom: ^18.0.0 || ^19.0.0
|
||||||
|
|
||||||
|
'@react-three/drei@10.7.7':
|
||||||
|
resolution: {integrity: sha512-ff+J5iloR0k4tC++QtD/j9u3w5fzfgFAWDtAGQah9pF2B1YgOq/5JxqY0/aVoQG5r3xSZz0cv5tk2YuBob4xEQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@react-three/fiber': ^9.0.0
|
||||||
|
react: ^19
|
||||||
|
react-dom: ^19
|
||||||
|
three: '>=0.159'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@react-three/fiber@9.5.0':
|
||||||
|
resolution: {integrity: sha512-FiUzfYW4wB1+PpmsE47UM+mCads7j2+giRBltfwH7SNhah95rqJs3ltEs9V3pP8rYdS0QlNne+9Aj8dS/SiaIA==}
|
||||||
|
peerDependencies:
|
||||||
|
expo: '>=43.0'
|
||||||
|
expo-asset: '>=8.4'
|
||||||
|
expo-file-system: '>=11.0'
|
||||||
|
expo-gl: '>=11.0'
|
||||||
|
react: '>=19 <19.3'
|
||||||
|
react-dom: '>=19 <19.3'
|
||||||
|
react-native: '>=0.78'
|
||||||
|
three: '>=0.156'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
expo:
|
||||||
|
optional: true
|
||||||
|
expo-asset:
|
||||||
|
optional: true
|
||||||
|
expo-file-system:
|
||||||
|
optional: true
|
||||||
|
expo-gl:
|
||||||
|
optional: true
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
react-native:
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@redis/bloom@1.2.0':
|
'@redis/bloom@1.2.0':
|
||||||
resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==}
|
resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
@ -5892,6 +5954,9 @@ packages:
|
||||||
'@total-typescript/ts-reset@0.6.1':
|
'@total-typescript/ts-reset@0.6.1':
|
||||||
resolution: {integrity: sha512-cka47fVSo6lfQDIATYqb/vO1nvFfbPw7uWLayIXIhGETj0wcOOlrlkobOMDNQOFr9QOafegUPq13V2+6vtD7yg==}
|
resolution: {integrity: sha512-cka47fVSo6lfQDIATYqb/vO1nvFfbPw7uWLayIXIhGETj0wcOOlrlkobOMDNQOFr9QOafegUPq13V2+6vtD7yg==}
|
||||||
|
|
||||||
|
'@tweenjs/tween.js@23.1.3':
|
||||||
|
resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==}
|
||||||
|
|
||||||
'@tybys/wasm-util@0.10.1':
|
'@tybys/wasm-util@0.10.1':
|
||||||
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
|
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
|
||||||
|
|
||||||
|
|
@ -6026,6 +6091,9 @@ packages:
|
||||||
'@types/doctrine@0.0.9':
|
'@types/doctrine@0.0.9':
|
||||||
resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==}
|
resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==}
|
||||||
|
|
||||||
|
'@types/draco3d@1.4.10':
|
||||||
|
resolution: {integrity: sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw==}
|
||||||
|
|
||||||
'@types/estree-jsx@1.0.5':
|
'@types/estree-jsx@1.0.5':
|
||||||
resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
|
resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
|
||||||
|
|
||||||
|
|
@ -6085,6 +6153,9 @@ packages:
|
||||||
'@types/node@25.0.3':
|
'@types/node@25.0.3':
|
||||||
resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==}
|
resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==}
|
||||||
|
|
||||||
|
'@types/offscreencanvas@2019.7.3':
|
||||||
|
resolution: {integrity: sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==}
|
||||||
|
|
||||||
'@types/papaparse@5.5.2':
|
'@types/papaparse@5.5.2':
|
||||||
resolution: {integrity: sha512-gFnFp/JMzLHCwRf7tQHrNnfhN4eYBVYYI897CGX4MY1tzY9l2aLkVyx2IlKZ/SAqDbB3I1AOZW5gTMGGsqWliA==}
|
resolution: {integrity: sha512-gFnFp/JMzLHCwRf7tQHrNnfhN4eYBVYYI897CGX4MY1tzY9l2aLkVyx2IlKZ/SAqDbB3I1AOZW5gTMGGsqWliA==}
|
||||||
|
|
||||||
|
|
@ -6096,6 +6167,11 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@types/react': ^19.2.0
|
'@types/react': ^19.2.0
|
||||||
|
|
||||||
|
'@types/react-reconciler@0.28.9':
|
||||||
|
resolution: {integrity: sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
|
||||||
'@types/react-syntax-highlighter@15.5.13':
|
'@types/react-syntax-highlighter@15.5.13':
|
||||||
resolution: {integrity: sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==}
|
resolution: {integrity: sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==}
|
||||||
|
|
||||||
|
|
@ -6111,9 +6187,15 @@ packages:
|
||||||
'@types/semver@7.7.1':
|
'@types/semver@7.7.1':
|
||||||
resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==}
|
resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==}
|
||||||
|
|
||||||
|
'@types/stats.js@0.17.4':
|
||||||
|
resolution: {integrity: sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==}
|
||||||
|
|
||||||
'@types/statuses@2.0.6':
|
'@types/statuses@2.0.6':
|
||||||
resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==}
|
resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==}
|
||||||
|
|
||||||
|
'@types/three@0.182.0':
|
||||||
|
resolution: {integrity: sha512-WByN9V3Sbwbe2OkWuSGyoqQO8Du6yhYaXtXLoA5FkKTUJorZ+yOHBZ35zUUPQXlAKABZmbYp5oAqpA4RBjtJ/Q==}
|
||||||
|
|
||||||
'@types/tough-cookie@4.0.5':
|
'@types/tough-cookie@4.0.5':
|
||||||
resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==}
|
resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==}
|
||||||
|
|
||||||
|
|
@ -6138,6 +6220,9 @@ packages:
|
||||||
'@types/webidl-conversions@7.0.3':
|
'@types/webidl-conversions@7.0.3':
|
||||||
resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==}
|
resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==}
|
||||||
|
|
||||||
|
'@types/webxr@0.5.24':
|
||||||
|
resolution: {integrity: sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==}
|
||||||
|
|
||||||
'@types/whatwg-mimetype@3.0.2':
|
'@types/whatwg-mimetype@3.0.2':
|
||||||
resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==}
|
resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==}
|
||||||
|
|
||||||
|
|
@ -6307,6 +6392,14 @@ packages:
|
||||||
'@upstash/redis@1.36.1':
|
'@upstash/redis@1.36.1':
|
||||||
resolution: {integrity: sha512-N6SjDcgXdOcTAF+7uNoY69o7hCspe9BcA7YjQdxVu5d25avljTwyLaHBW3krWjrP0FfocgMk94qyVtQbeDp39A==}
|
resolution: {integrity: sha512-N6SjDcgXdOcTAF+7uNoY69o7hCspe9BcA7YjQdxVu5d25avljTwyLaHBW3krWjrP0FfocgMk94qyVtQbeDp39A==}
|
||||||
|
|
||||||
|
'@use-gesture/core@10.3.1':
|
||||||
|
resolution: {integrity: sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==}
|
||||||
|
|
||||||
|
'@use-gesture/react@10.3.1':
|
||||||
|
resolution: {integrity: sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>= 16.8.0'
|
||||||
|
|
||||||
'@vercel/analytics@1.6.1':
|
'@vercel/analytics@1.6.1':
|
||||||
resolution: {integrity: sha512-oH9He/bEM+6oKlv3chWuOOcp8Y6fo6/PSro8hEkgCW3pu9/OiCXiUpRUogDh3Fs3LH2sosDrx8CxeOLBEE+afg==}
|
resolution: {integrity: sha512-oH9He/bEM+6oKlv3chWuOOcp8Y6fo6/PSro8hEkgCW3pu9/OiCXiUpRUogDh3Fs3LH2sosDrx8CxeOLBEE+afg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
@ -6396,6 +6489,9 @@ packages:
|
||||||
'@vitest/utils@4.0.16':
|
'@vitest/utils@4.0.16':
|
||||||
resolution: {integrity: sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==}
|
resolution: {integrity: sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==}
|
||||||
|
|
||||||
|
'@webgpu/types@0.1.69':
|
||||||
|
resolution: {integrity: sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ==}
|
||||||
|
|
||||||
accepts@2.0.0:
|
accepts@2.0.0:
|
||||||
resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
|
resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
@ -6766,6 +6862,9 @@ packages:
|
||||||
buffer@5.7.1:
|
buffer@5.7.1:
|
||||||
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
||||||
|
|
||||||
|
buffer@6.0.3:
|
||||||
|
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
|
||||||
|
|
||||||
bundle-require@5.1.0:
|
bundle-require@5.1.0:
|
||||||
resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==}
|
resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==}
|
||||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
|
|
@ -6808,6 +6907,12 @@ packages:
|
||||||
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
|
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
|
camera-controls@3.1.2:
|
||||||
|
resolution: {integrity: sha512-xkxfpG2ECZ6Ww5/9+kf4mfg1VEYAoe9aDSY+IwF0UEs7qEzwy0aVRfs2grImIECs/PoBtWFrh7RXsQkwG922JA==}
|
||||||
|
engines: {node: '>=22.0.0', npm: '>=10.5.1'}
|
||||||
|
peerDependencies:
|
||||||
|
three: '>=0.126.1'
|
||||||
|
|
||||||
caniuse-lite@1.0.30001763:
|
caniuse-lite@1.0.30001763:
|
||||||
resolution: {integrity: sha512-mh/dGtq56uN98LlNX9qdbKnzINhX0QzhiWBFEkFfsFO4QyCvL8YegrJAazCwXIeqkIob8BlZPGM3xdnY+sgmvQ==}
|
resolution: {integrity: sha512-mh/dGtq56uN98LlNX9qdbKnzINhX0QzhiWBFEkFfsFO4QyCvL8YegrJAazCwXIeqkIob8BlZPGM3xdnY+sgmvQ==}
|
||||||
|
|
||||||
|
|
@ -7014,6 +7119,11 @@ packages:
|
||||||
cose-base@2.2.0:
|
cose-base@2.2.0:
|
||||||
resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==}
|
resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==}
|
||||||
|
|
||||||
|
cross-env@7.0.3:
|
||||||
|
resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==}
|
||||||
|
engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
cross-spawn@7.0.6:
|
cross-spawn@7.0.6:
|
||||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|
@ -7314,6 +7424,9 @@ packages:
|
||||||
destr@2.0.5:
|
destr@2.0.5:
|
||||||
resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
|
resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
|
||||||
|
|
||||||
|
detect-gpu@5.0.70:
|
||||||
|
resolution: {integrity: sha512-bqerEP1Ese6nt3rFkwPnGbsUF9a4q+gMmpTVVOEzoCyeCc+y7/RvJnQZJx1JwhgQI5Ntg0Kgat8Uu7XpBqnz1w==}
|
||||||
|
|
||||||
detect-indent@6.1.0:
|
detect-indent@6.1.0:
|
||||||
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
|
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
@ -7377,6 +7490,9 @@ packages:
|
||||||
resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==}
|
resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
draco3d@1.5.7:
|
||||||
|
resolution: {integrity: sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==}
|
||||||
|
|
||||||
drizzle-kit@0.31.8:
|
drizzle-kit@0.31.8:
|
||||||
resolution: {integrity: sha512-O9EC/miwdnRDY10qRxM8P3Pg8hXe3LyU4ZipReKOgTwn4OqANmftj8XJz1UPUAS6NMHf0E2htjsbQujUTkncCg==}
|
resolution: {integrity: sha512-O9EC/miwdnRDY10qRxM8P3Pg8hXe3LyU4ZipReKOgTwn4OqANmftj8XJz1UPUAS6NMHf0E2htjsbQujUTkncCg==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
@ -7830,6 +7946,12 @@ packages:
|
||||||
picomatch:
|
picomatch:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
fflate@0.6.10:
|
||||||
|
resolution: {integrity: sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==}
|
||||||
|
|
||||||
|
fflate@0.8.2:
|
||||||
|
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
|
||||||
|
|
||||||
file-entry-cache@8.0.0:
|
file-entry-cache@8.0.0:
|
||||||
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
|
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
|
||||||
engines: {node: '>=16.0.0'}
|
engines: {node: '>=16.0.0'}
|
||||||
|
|
@ -8047,6 +8169,9 @@ packages:
|
||||||
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
|
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
glsl-noise@0.0.0:
|
||||||
|
resolution: {integrity: sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w==}
|
||||||
|
|
||||||
gopd@1.2.0:
|
gopd@1.2.0:
|
||||||
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
|
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
@ -8169,6 +8294,9 @@ packages:
|
||||||
highlightjs-vue@1.0.0:
|
highlightjs-vue@1.0.0:
|
||||||
resolution: {integrity: sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==}
|
resolution: {integrity: sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==}
|
||||||
|
|
||||||
|
hls.js@1.6.15:
|
||||||
|
resolution: {integrity: sha512-E3a5VwgXimGHwpRGV+WxRTKeSp2DW5DI5MWv34ulL3t5UNmyJWCQ1KmLEHbYzcfThfXG8amBL+fCYPneGHC4VA==}
|
||||||
|
|
||||||
hono@4.10.6:
|
hono@4.10.6:
|
||||||
resolution: {integrity: sha512-BIdolzGpDO9MQ4nu3AUuDwHZZ+KViNm+EZ75Ae55eMXMqLVhDFqEMXxtUe9Qh8hjL+pIna/frs2j6Y2yD5Ua/g==}
|
resolution: {integrity: sha512-BIdolzGpDO9MQ4nu3AUuDwHZZ+KViNm+EZ75Ae55eMXMqLVhDFqEMXxtUe9Qh8hjL+pIna/frs2j6Y2yD5Ua/g==}
|
||||||
engines: {node: '>=16.9.0'}
|
engines: {node: '>=16.9.0'}
|
||||||
|
|
@ -8241,6 +8369,9 @@ packages:
|
||||||
resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
|
resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
|
immediate@3.0.6:
|
||||||
|
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
|
||||||
|
|
||||||
import-fresh@3.3.1:
|
import-fresh@3.3.1:
|
||||||
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
|
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
@ -8411,6 +8542,9 @@ packages:
|
||||||
is-potential-custom-element-name@1.0.1:
|
is-potential-custom-element-name@1.0.1:
|
||||||
resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
|
resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
|
||||||
|
|
||||||
|
is-promise@2.2.2:
|
||||||
|
resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==}
|
||||||
|
|
||||||
is-promise@4.0.0:
|
is-promise@4.0.0:
|
||||||
resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
|
resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
|
||||||
|
|
||||||
|
|
@ -8497,6 +8631,11 @@ packages:
|
||||||
resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
|
resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
its-fine@2.0.0:
|
||||||
|
resolution: {integrity: sha512-KLViCmWx94zOvpLwSlsx6yOCeMhZYaxrJV87Po5k/FoZzcPSahvK5qJ7fYhS61sZi5ikmh2S3Hz55A2l3U69ng==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^19.0.0
|
||||||
|
|
||||||
jackspeak@3.4.3:
|
jackspeak@3.4.3:
|
||||||
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
|
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
|
||||||
|
|
||||||
|
|
@ -8720,6 +8859,9 @@ packages:
|
||||||
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
|
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
|
|
||||||
|
lie@3.3.0:
|
||||||
|
resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
|
||||||
|
|
||||||
lightningcss-android-arm64@1.30.2:
|
lightningcss-android-arm64@1.30.2:
|
||||||
resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
|
resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
|
|
@ -8875,6 +9017,12 @@ packages:
|
||||||
resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
|
resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
maath@0.10.8:
|
||||||
|
resolution: {integrity: sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/three': '>=0.134.0'
|
||||||
|
three: '>=0.134.0'
|
||||||
|
|
||||||
magic-string@0.27.0:
|
magic-string@0.27.0:
|
||||||
resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
|
resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
@ -8978,6 +9126,14 @@ packages:
|
||||||
mermaid@11.12.2:
|
mermaid@11.12.2:
|
||||||
resolution: {integrity: sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==}
|
resolution: {integrity: sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==}
|
||||||
|
|
||||||
|
meshline@3.3.1:
|
||||||
|
resolution: {integrity: sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ==}
|
||||||
|
peerDependencies:
|
||||||
|
three: '>=0.137'
|
||||||
|
|
||||||
|
meshoptimizer@0.22.0:
|
||||||
|
resolution: {integrity: sha512-IebiK79sqIy+E4EgOr+CAw+Ke8hAspXKzBd0JdgEmPHiAwmvEj2S4h1rfvo+o/BnfEYd/jAOg5IeeIjzlzSnDg==}
|
||||||
|
|
||||||
micromark-core-commonmark@2.0.3:
|
micromark-core-commonmark@2.0.3:
|
||||||
resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
|
resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
|
||||||
|
|
||||||
|
|
@ -9726,6 +9882,9 @@ packages:
|
||||||
resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==}
|
resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
potpack@1.0.2:
|
||||||
|
resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==}
|
||||||
|
|
||||||
prebuild-install@7.1.3:
|
prebuild-install@7.1.3:
|
||||||
resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==}
|
resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
@ -9778,6 +9937,9 @@ packages:
|
||||||
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
|
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
|
||||||
engines: {node: '>= 0.6.0'}
|
engines: {node: '>= 0.6.0'}
|
||||||
|
|
||||||
|
promise-worker-transferable@1.0.4:
|
||||||
|
resolution: {integrity: sha512-bN+0ehEnrXfxV2ZQvU2PetO0n4gqBD4ulq3MI1WOPLgr7/Mg9yRQkX5+0v1vagr74ZTsl7XtzlaYDo2EuCeYJw==}
|
||||||
|
|
||||||
prompts@2.4.2:
|
prompts@2.4.2:
|
||||||
resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
|
resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
|
|
@ -9872,6 +10034,15 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: '>= 0.14.0'
|
react: '>= 0.14.0'
|
||||||
|
|
||||||
|
react-use-measure@2.1.7:
|
||||||
|
resolution: {integrity: sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=16.13'
|
||||||
|
react-dom: '>=16.13'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
|
||||||
react-virtuoso@4.18.1:
|
react-virtuoso@4.18.1:
|
||||||
resolution: {integrity: sha512-KF474cDwaSb9+SJ380xruBB4P+yGWcVkcu26HtMqYNMTYlYbrNy8vqMkE+GpAApPPufJqgOLMoWMFG/3pJMXUA==}
|
resolution: {integrity: sha512-KF474cDwaSb9+SJ380xruBB4P+yGWcVkcu26HtMqYNMTYlYbrNy8vqMkE+GpAApPPufJqgOLMoWMFG/3pJMXUA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
@ -10297,6 +10468,15 @@ packages:
|
||||||
standardwebhooks@1.0.0:
|
standardwebhooks@1.0.0:
|
||||||
resolution: {integrity: sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==}
|
resolution: {integrity: sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==}
|
||||||
|
|
||||||
|
stats-gl@2.4.2:
|
||||||
|
resolution: {integrity: sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/three': '*'
|
||||||
|
three: '*'
|
||||||
|
|
||||||
|
stats.js@0.17.0:
|
||||||
|
resolution: {integrity: sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==}
|
||||||
|
|
||||||
statuses@2.0.2:
|
statuses@2.0.2:
|
||||||
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
@ -10451,6 +10631,11 @@ packages:
|
||||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
suspend-react@0.1.3:
|
||||||
|
resolution: {integrity: sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=17.0'
|
||||||
|
|
||||||
svix@1.84.1:
|
svix@1.84.1:
|
||||||
resolution: {integrity: sha512-K8DPPSZaW/XqXiz1kEyzSHYgmGLnhB43nQCMeKjWGCUpLIpAMMM8kx3rVVOSm6Bo6EHyK1RQLPT4R06skM/MlQ==}
|
resolution: {integrity: sha512-K8DPPSZaW/XqXiz1kEyzSHYgmGLnhB43nQCMeKjWGCUpLIpAMMM8kx3rVVOSm6Bo6EHyK1RQLPT4R06skM/MlQ==}
|
||||||
|
|
||||||
|
|
@ -10500,6 +10685,19 @@ packages:
|
||||||
thenify@3.3.1:
|
thenify@3.3.1:
|
||||||
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
|
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
|
||||||
|
|
||||||
|
three-mesh-bvh@0.8.3:
|
||||||
|
resolution: {integrity: sha512-4G5lBaF+g2auKX3P0yqx+MJC6oVt6sB5k+CchS6Ob0qvH0YIhuUk1eYr7ktsIpY+albCqE80/FVQGV190PmiAg==}
|
||||||
|
peerDependencies:
|
||||||
|
three: '>= 0.159.0'
|
||||||
|
|
||||||
|
three-stdlib@2.36.1:
|
||||||
|
resolution: {integrity: sha512-XyGQrFmNQ5O/IoKm556ftwKsBg11TIb301MB5dWNicziQBEs2g3gtOYIf7pFiLa0zI2gUwhtCjv9fmjnxKZ1Cg==}
|
||||||
|
peerDependencies:
|
||||||
|
three: '>=0.128.0'
|
||||||
|
|
||||||
|
three@0.182.0:
|
||||||
|
resolution: {integrity: sha512-GbHabT+Irv+ihI1/f5kIIsZ+Ef9Sl5A1Y7imvS5RQjWgtTPfPnZ43JmlYI7NtCRDK9zir20lQpfg8/9Yd02OvQ==}
|
||||||
|
|
||||||
throttleit@2.1.0:
|
throttleit@2.1.0:
|
||||||
resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==}
|
resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
@ -10571,6 +10769,19 @@ packages:
|
||||||
trim-lines@3.0.1:
|
trim-lines@3.0.1:
|
||||||
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
|
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
|
||||||
|
|
||||||
|
troika-three-text@0.52.4:
|
||||||
|
resolution: {integrity: sha512-V50EwcYGruV5rUZ9F4aNsrytGdKcXKALjEtQXIOBfhVoZU9VAqZNIoGQ3TMiooVqFAbR1w15T+f+8gkzoFzawg==}
|
||||||
|
peerDependencies:
|
||||||
|
three: '>=0.125.0'
|
||||||
|
|
||||||
|
troika-three-utils@0.52.4:
|
||||||
|
resolution: {integrity: sha512-NORAStSVa/BDiG52Mfudk4j1FG4jC4ILutB3foPnfGbOeIs9+G5vZLa0pnmnaftZUGm4UwSoqEpWdqvC7zms3A==}
|
||||||
|
peerDependencies:
|
||||||
|
three: '>=0.125.0'
|
||||||
|
|
||||||
|
troika-worker-utils@0.52.0:
|
||||||
|
resolution: {integrity: sha512-W1CpvTHykaPH5brv5VHLfQo9D1OYuo0cSBEUQFFT/nBUzM8iD6Lq2/tgG/f1OelbAS1WtaTPQzE5uM49egnngw==}
|
||||||
|
|
||||||
trough@2.2.0:
|
trough@2.2.0:
|
||||||
resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
|
resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
|
||||||
|
|
||||||
|
|
@ -10637,6 +10848,9 @@ packages:
|
||||||
tunnel-agent@0.6.0:
|
tunnel-agent@0.6.0:
|
||||||
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
|
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
|
||||||
|
|
||||||
|
tunnel-rat@0.1.2:
|
||||||
|
resolution: {integrity: sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ==}
|
||||||
|
|
||||||
turbo-darwin-64@2.7.3:
|
turbo-darwin-64@2.7.3:
|
||||||
resolution: {integrity: sha512-aZHhvRiRHXbJw1EcEAq4aws1hsVVUZ9DPuSFaq9VVFAKCup7niIEwc22glxb7240yYEr1vLafdQ2U294Vcwz+w==}
|
resolution: {integrity: sha512-aZHhvRiRHXbJw1EcEAq4aws1hsVVUZ9DPuSFaq9VVFAKCup7niIEwc22glxb7240yYEr1vLafdQ2U294Vcwz+w==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
|
|
@ -10829,6 +11043,10 @@ packages:
|
||||||
util@0.12.5:
|
util@0.12.5:
|
||||||
resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==}
|
resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==}
|
||||||
|
|
||||||
|
utility-types@3.11.0:
|
||||||
|
resolution: {integrity: sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==}
|
||||||
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
uuid@10.0.0:
|
uuid@10.0.0:
|
||||||
resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==}
|
resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
@ -10985,6 +11203,12 @@ packages:
|
||||||
web-namespaces@2.0.1:
|
web-namespaces@2.0.1:
|
||||||
resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
|
resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
|
||||||
|
|
||||||
|
webgl-constants@1.1.1:
|
||||||
|
resolution: {integrity: sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg==}
|
||||||
|
|
||||||
|
webgl-sdf-generator@1.1.1:
|
||||||
|
resolution: {integrity: sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA==}
|
||||||
|
|
||||||
webidl-conversions@7.0.0:
|
webidl-conversions@7.0.0:
|
||||||
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
@ -11165,6 +11389,39 @@ packages:
|
||||||
zod@4.3.5:
|
zod@4.3.5:
|
||||||
resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==}
|
resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==}
|
||||||
|
|
||||||
|
zustand@4.5.7:
|
||||||
|
resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==}
|
||||||
|
engines: {node: '>=12.7.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '>=16.8'
|
||||||
|
immer: '>=9.0.6'
|
||||||
|
react: '>=16.8'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
immer:
|
||||||
|
optional: true
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
zustand@5.0.10:
|
||||||
|
resolution: {integrity: sha512-U1AiltS1O9hSy3rul+Ub82ut2fqIAefiSuwECWt6jlMVUGejvf+5omLcRBSzqbRagSM3hQZbtzdeRc6QVScXTg==}
|
||||||
|
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
|
||||||
|
|
||||||
zwitch@2.0.4:
|
zwitch@2.0.4:
|
||||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||||
|
|
||||||
|
|
@ -11743,6 +12000,8 @@ snapshots:
|
||||||
|
|
||||||
'@csstools/css-tokenizer@3.0.4': {}
|
'@csstools/css-tokenizer@3.0.4': {}
|
||||||
|
|
||||||
|
'@dimforge/rapier3d-compat@0.12.0': {}
|
||||||
|
|
||||||
'@drizzle-team/brocli@0.10.2': {}
|
'@drizzle-team/brocli@0.10.2': {}
|
||||||
|
|
||||||
'@electric-sql/pglite-socket@0.0.6(@electric-sql/pglite@0.3.2)':
|
'@electric-sql/pglite-socket@0.0.6(@electric-sql/pglite@0.3.2)':
|
||||||
|
|
@ -12289,6 +12548,8 @@ snapshots:
|
||||||
'@types/react': 19.2.7
|
'@types/react': 19.2.7
|
||||||
react: 19.2.3
|
react: 19.2.3
|
||||||
|
|
||||||
|
'@mediapipe/tasks-vision@0.10.17': {}
|
||||||
|
|
||||||
'@mendable/firecrawl-js@4.10.0':
|
'@mendable/firecrawl-js@4.10.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
axios: 1.13.2
|
axios: 1.13.2
|
||||||
|
|
@ -12330,6 +12591,11 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
sparse-bitfield: 3.0.3
|
sparse-bitfield: 3.0.3
|
||||||
|
|
||||||
|
'@monogrid/gainmap-js@3.4.0(three@0.182.0)':
|
||||||
|
dependencies:
|
||||||
|
promise-worker-transferable: 1.0.4
|
||||||
|
three: 0.182.0
|
||||||
|
|
||||||
'@mozilla/readability@0.6.0': {}
|
'@mozilla/readability@0.6.0': {}
|
||||||
|
|
||||||
'@mrleebo/prisma-ast@0.12.1':
|
'@mrleebo/prisma-ast@0.12.1':
|
||||||
|
|
@ -12611,6 +12877,59 @@ snapshots:
|
||||||
react-dom: 19.2.3(react@19.2.3)
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@react-three/drei@10.7.7(@react-three/fiber@9.5.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(three@0.182.0))(@types/react@19.2.7)(@types/three@0.182.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(three@0.182.0)':
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.28.4
|
||||||
|
'@mediapipe/tasks-vision': 0.10.17
|
||||||
|
'@monogrid/gainmap-js': 3.4.0(three@0.182.0)
|
||||||
|
'@react-three/fiber': 9.5.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(three@0.182.0)
|
||||||
|
'@use-gesture/react': 10.3.1(react@19.2.3)
|
||||||
|
camera-controls: 3.1.2(three@0.182.0)
|
||||||
|
cross-env: 7.0.3
|
||||||
|
detect-gpu: 5.0.70
|
||||||
|
glsl-noise: 0.0.0
|
||||||
|
hls.js: 1.6.15
|
||||||
|
maath: 0.10.8(@types/three@0.182.0)(three@0.182.0)
|
||||||
|
meshline: 3.3.1(three@0.182.0)
|
||||||
|
react: 19.2.3
|
||||||
|
stats-gl: 2.4.2(@types/three@0.182.0)(three@0.182.0)
|
||||||
|
stats.js: 0.17.0
|
||||||
|
suspend-react: 0.1.3(react@19.2.3)
|
||||||
|
three: 0.182.0
|
||||||
|
three-mesh-bvh: 0.8.3(three@0.182.0)
|
||||||
|
three-stdlib: 2.36.1(three@0.182.0)
|
||||||
|
troika-three-text: 0.52.4(three@0.182.0)
|
||||||
|
tunnel-rat: 0.1.2(@types/react@19.2.7)(react@19.2.3)
|
||||||
|
use-sync-external-store: 1.6.0(react@19.2.3)
|
||||||
|
utility-types: 3.11.0
|
||||||
|
zustand: 5.0.10(@types/react@19.2.7)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3))
|
||||||
|
optionalDependencies:
|
||||||
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@types/react'
|
||||||
|
- '@types/three'
|
||||||
|
- immer
|
||||||
|
|
||||||
|
'@react-three/fiber@9.5.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(three@0.182.0)':
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.28.4
|
||||||
|
'@types/webxr': 0.5.24
|
||||||
|
base64-js: 1.5.1
|
||||||
|
buffer: 6.0.3
|
||||||
|
its-fine: 2.0.0(@types/react@19.2.7)(react@19.2.3)
|
||||||
|
react: 19.2.3
|
||||||
|
react-use-measure: 2.1.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
scheduler: 0.27.0
|
||||||
|
suspend-react: 0.1.3(react@19.2.3)
|
||||||
|
three: 0.182.0
|
||||||
|
use-sync-external-store: 1.6.0(react@19.2.3)
|
||||||
|
zustand: 5.0.10(@types/react@19.2.7)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3))
|
||||||
|
optionalDependencies:
|
||||||
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@types/react'
|
||||||
|
- immer
|
||||||
|
|
||||||
'@redis/bloom@1.2.0(@redis/client@1.6.1)':
|
'@redis/bloom@1.2.0(@redis/client@1.6.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@redis/client': 1.6.1
|
'@redis/client': 1.6.1
|
||||||
|
|
@ -13076,6 +13395,8 @@ snapshots:
|
||||||
|
|
||||||
'@total-typescript/ts-reset@0.6.1': {}
|
'@total-typescript/ts-reset@0.6.1': {}
|
||||||
|
|
||||||
|
'@tweenjs/tween.js@23.1.3': {}
|
||||||
|
|
||||||
'@tybys/wasm-util@0.10.1':
|
'@tybys/wasm-util@0.10.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
@ -13246,6 +13567,8 @@ snapshots:
|
||||||
|
|
||||||
'@types/doctrine@0.0.9': {}
|
'@types/doctrine@0.0.9': {}
|
||||||
|
|
||||||
|
'@types/draco3d@1.4.10': {}
|
||||||
|
|
||||||
'@types/estree-jsx@1.0.5':
|
'@types/estree-jsx@1.0.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.8
|
'@types/estree': 1.0.8
|
||||||
|
|
@ -13304,6 +13627,8 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 7.16.0
|
undici-types: 7.16.0
|
||||||
|
|
||||||
|
'@types/offscreencanvas@2019.7.3': {}
|
||||||
|
|
||||||
'@types/papaparse@5.5.2':
|
'@types/papaparse@5.5.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 25.0.3
|
'@types/node': 25.0.3
|
||||||
|
|
@ -13314,6 +13639,10 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 19.2.7
|
'@types/react': 19.2.7
|
||||||
|
|
||||||
|
'@types/react-reconciler@0.28.9(@types/react@19.2.7)':
|
||||||
|
dependencies:
|
||||||
|
'@types/react': 19.2.7
|
||||||
|
|
||||||
'@types/react-syntax-highlighter@15.5.13':
|
'@types/react-syntax-highlighter@15.5.13':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 19.2.7
|
'@types/react': 19.2.7
|
||||||
|
|
@ -13328,8 +13657,20 @@ snapshots:
|
||||||
|
|
||||||
'@types/semver@7.7.1': {}
|
'@types/semver@7.7.1': {}
|
||||||
|
|
||||||
|
'@types/stats.js@0.17.4': {}
|
||||||
|
|
||||||
'@types/statuses@2.0.6': {}
|
'@types/statuses@2.0.6': {}
|
||||||
|
|
||||||
|
'@types/three@0.182.0':
|
||||||
|
dependencies:
|
||||||
|
'@dimforge/rapier3d-compat': 0.12.0
|
||||||
|
'@tweenjs/tween.js': 23.1.3
|
||||||
|
'@types/stats.js': 0.17.4
|
||||||
|
'@types/webxr': 0.5.24
|
||||||
|
'@webgpu/types': 0.1.69
|
||||||
|
fflate: 0.8.2
|
||||||
|
meshoptimizer: 0.22.0
|
||||||
|
|
||||||
'@types/tough-cookie@4.0.5': {}
|
'@types/tough-cookie@4.0.5': {}
|
||||||
|
|
||||||
'@types/trusted-types@2.0.7':
|
'@types/trusted-types@2.0.7':
|
||||||
|
|
@ -13347,6 +13688,8 @@ snapshots:
|
||||||
|
|
||||||
'@types/webidl-conversions@7.0.3': {}
|
'@types/webidl-conversions@7.0.3': {}
|
||||||
|
|
||||||
|
'@types/webxr@0.5.24': {}
|
||||||
|
|
||||||
'@types/whatwg-mimetype@3.0.2': {}
|
'@types/whatwg-mimetype@3.0.2': {}
|
||||||
|
|
||||||
'@types/whatwg-url@11.0.5':
|
'@types/whatwg-url@11.0.5':
|
||||||
|
|
@ -13513,6 +13856,13 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
uncrypto: 0.1.3
|
uncrypto: 0.1.3
|
||||||
|
|
||||||
|
'@use-gesture/core@10.3.1': {}
|
||||||
|
|
||||||
|
'@use-gesture/react@10.3.1(react@19.2.3)':
|
||||||
|
dependencies:
|
||||||
|
'@use-gesture/core': 10.3.1
|
||||||
|
react: 19.2.3
|
||||||
|
|
||||||
'@vercel/analytics@1.6.1(next@16.1.1(@opentelemetry/api@1.9.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)':
|
'@vercel/analytics@1.6.1(next@16.1.1(@opentelemetry/api@1.9.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)':
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
next: 16.1.1(@opentelemetry/api@1.9.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
next: 16.1.1(@opentelemetry/api@1.9.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
|
@ -13606,6 +13956,8 @@ snapshots:
|
||||||
'@vitest/pretty-format': 4.0.16
|
'@vitest/pretty-format': 4.0.16
|
||||||
tinyrainbow: 3.0.3
|
tinyrainbow: 3.0.3
|
||||||
|
|
||||||
|
'@webgpu/types@0.1.69': {}
|
||||||
|
|
||||||
accepts@2.0.0:
|
accepts@2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
mime-types: 3.0.2
|
mime-types: 3.0.2
|
||||||
|
|
@ -13987,6 +14339,11 @@ snapshots:
|
||||||
base64-js: 1.5.1
|
base64-js: 1.5.1
|
||||||
ieee754: 1.2.1
|
ieee754: 1.2.1
|
||||||
|
|
||||||
|
buffer@6.0.3:
|
||||||
|
dependencies:
|
||||||
|
base64-js: 1.5.1
|
||||||
|
ieee754: 1.2.1
|
||||||
|
|
||||||
bundle-require@5.1.0(esbuild@0.27.2):
|
bundle-require@5.1.0(esbuild@0.27.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.27.2
|
esbuild: 0.27.2
|
||||||
|
|
@ -14032,6 +14389,10 @@ snapshots:
|
||||||
|
|
||||||
camelcase-css@2.0.1: {}
|
camelcase-css@2.0.1: {}
|
||||||
|
|
||||||
|
camera-controls@3.1.2(three@0.182.0):
|
||||||
|
dependencies:
|
||||||
|
three: 0.182.0
|
||||||
|
|
||||||
caniuse-lite@1.0.30001763: {}
|
caniuse-lite@1.0.30001763: {}
|
||||||
|
|
||||||
caseless@0.12.0: {}
|
caseless@0.12.0: {}
|
||||||
|
|
@ -14222,6 +14583,10 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
layout-base: 2.0.1
|
layout-base: 2.0.1
|
||||||
|
|
||||||
|
cross-env@7.0.3:
|
||||||
|
dependencies:
|
||||||
|
cross-spawn: 7.0.6
|
||||||
|
|
||||||
cross-spawn@7.0.6:
|
cross-spawn@7.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
path-key: 3.1.1
|
path-key: 3.1.1
|
||||||
|
|
@ -14551,6 +14916,10 @@ snapshots:
|
||||||
|
|
||||||
destr@2.0.5: {}
|
destr@2.0.5: {}
|
||||||
|
|
||||||
|
detect-gpu@5.0.70:
|
||||||
|
dependencies:
|
||||||
|
webgl-constants: 1.1.1
|
||||||
|
|
||||||
detect-indent@6.1.0: {}
|
detect-indent@6.1.0: {}
|
||||||
|
|
||||||
detect-libc@2.1.2: {}
|
detect-libc@2.1.2: {}
|
||||||
|
|
@ -14607,6 +14976,8 @@ snapshots:
|
||||||
|
|
||||||
dotenv@17.2.3: {}
|
dotenv@17.2.3: {}
|
||||||
|
|
||||||
|
draco3d@1.5.7: {}
|
||||||
|
|
||||||
drizzle-kit@0.31.8:
|
drizzle-kit@0.31.8:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@drizzle-team/brocli': 0.10.2
|
'@drizzle-team/brocli': 0.10.2
|
||||||
|
|
@ -15261,6 +15632,10 @@ snapshots:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
picomatch: 4.0.3
|
picomatch: 4.0.3
|
||||||
|
|
||||||
|
fflate@0.6.10: {}
|
||||||
|
|
||||||
|
fflate@0.8.2: {}
|
||||||
|
|
||||||
file-entry-cache@8.0.0:
|
file-entry-cache@8.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
flat-cache: 4.0.1
|
flat-cache: 4.0.1
|
||||||
|
|
@ -15509,6 +15884,8 @@ snapshots:
|
||||||
merge2: 1.4.1
|
merge2: 1.4.1
|
||||||
slash: 3.0.0
|
slash: 3.0.0
|
||||||
|
|
||||||
|
glsl-noise@0.0.0: {}
|
||||||
|
|
||||||
gopd@1.2.0: {}
|
gopd@1.2.0: {}
|
||||||
|
|
||||||
graceful-fs@4.2.11: {}
|
graceful-fs@4.2.11: {}
|
||||||
|
|
@ -15702,6 +16079,8 @@ snapshots:
|
||||||
|
|
||||||
highlightjs-vue@1.0.0: {}
|
highlightjs-vue@1.0.0: {}
|
||||||
|
|
||||||
|
hls.js@1.6.15: {}
|
||||||
|
|
||||||
hono@4.10.6: {}
|
hono@4.10.6: {}
|
||||||
|
|
||||||
html-encoding-sniffer@3.0.0:
|
html-encoding-sniffer@3.0.0:
|
||||||
|
|
@ -15799,6 +16178,8 @@ snapshots:
|
||||||
|
|
||||||
ignore@7.0.5: {}
|
ignore@7.0.5: {}
|
||||||
|
|
||||||
|
immediate@3.0.6: {}
|
||||||
|
|
||||||
import-fresh@3.3.1:
|
import-fresh@3.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
parent-module: 1.0.1
|
parent-module: 1.0.1
|
||||||
|
|
@ -15946,6 +16327,8 @@ snapshots:
|
||||||
|
|
||||||
is-potential-custom-element-name@1.0.1: {}
|
is-potential-custom-element-name@1.0.1: {}
|
||||||
|
|
||||||
|
is-promise@2.2.2: {}
|
||||||
|
|
||||||
is-promise@4.0.0: {}
|
is-promise@4.0.0: {}
|
||||||
|
|
||||||
is-property@1.0.2:
|
is-property@1.0.2:
|
||||||
|
|
@ -16035,6 +16418,13 @@ snapshots:
|
||||||
has-symbols: 1.1.0
|
has-symbols: 1.1.0
|
||||||
set-function-name: 2.0.2
|
set-function-name: 2.0.2
|
||||||
|
|
||||||
|
its-fine@2.0.0(@types/react@19.2.7)(react@19.2.3):
|
||||||
|
dependencies:
|
||||||
|
'@types/react-reconciler': 0.28.9(@types/react@19.2.7)
|
||||||
|
react: 19.2.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@types/react'
|
||||||
|
|
||||||
jackspeak@3.4.3:
|
jackspeak@3.4.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@isaacs/cliui': 8.0.2
|
'@isaacs/cliui': 8.0.2
|
||||||
|
|
@ -16263,6 +16653,10 @@ snapshots:
|
||||||
prelude-ls: 1.2.1
|
prelude-ls: 1.2.1
|
||||||
type-check: 0.4.0
|
type-check: 0.4.0
|
||||||
|
|
||||||
|
lie@3.3.0:
|
||||||
|
dependencies:
|
||||||
|
immediate: 3.0.6
|
||||||
|
|
||||||
lightningcss-android-arm64@1.30.2:
|
lightningcss-android-arm64@1.30.2:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
|
@ -16383,6 +16777,11 @@ snapshots:
|
||||||
|
|
||||||
lz-string@1.5.0: {}
|
lz-string@1.5.0: {}
|
||||||
|
|
||||||
|
maath@0.10.8(@types/three@0.182.0)(three@0.182.0):
|
||||||
|
dependencies:
|
||||||
|
'@types/three': 0.182.0
|
||||||
|
three: 0.182.0
|
||||||
|
|
||||||
magic-string@0.27.0:
|
magic-string@0.27.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
@ -16605,6 +17004,12 @@ snapshots:
|
||||||
ts-dedent: 2.2.0
|
ts-dedent: 2.2.0
|
||||||
uuid: 11.1.0
|
uuid: 11.1.0
|
||||||
|
|
||||||
|
meshline@3.3.1(three@0.182.0):
|
||||||
|
dependencies:
|
||||||
|
three: 0.182.0
|
||||||
|
|
||||||
|
meshoptimizer@0.22.0: {}
|
||||||
|
|
||||||
micromark-core-commonmark@2.0.3:
|
micromark-core-commonmark@2.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
decode-named-character-reference: 1.2.0
|
decode-named-character-reference: 1.2.0
|
||||||
|
|
@ -17505,6 +17910,8 @@ snapshots:
|
||||||
postgres@3.4.7:
|
postgres@3.4.7:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
potpack@1.0.2: {}
|
||||||
|
|
||||||
prebuild-install@7.1.3:
|
prebuild-install@7.1.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
detect-libc: 2.1.2
|
detect-libc: 2.1.2
|
||||||
|
|
@ -17563,6 +17970,11 @@ snapshots:
|
||||||
|
|
||||||
process@0.11.10: {}
|
process@0.11.10: {}
|
||||||
|
|
||||||
|
promise-worker-transferable@1.0.4:
|
||||||
|
dependencies:
|
||||||
|
is-promise: 2.2.2
|
||||||
|
lie: 3.3.0
|
||||||
|
|
||||||
prompts@2.4.2:
|
prompts@2.4.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
kleur: 3.0.3
|
kleur: 3.0.3
|
||||||
|
|
@ -17690,6 +18102,12 @@ snapshots:
|
||||||
react: 19.2.3
|
react: 19.2.3
|
||||||
refractor: 5.0.0
|
refractor: 5.0.0
|
||||||
|
|
||||||
|
react-use-measure@2.1.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||||
|
dependencies:
|
||||||
|
react: 19.2.3
|
||||||
|
optionalDependencies:
|
||||||
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
|
|
||||||
react-virtuoso@4.18.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
react-virtuoso@4.18.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 19.2.3
|
react: 19.2.3
|
||||||
|
|
@ -18285,6 +18703,13 @@ snapshots:
|
||||||
'@stablelib/base64': 1.0.1
|
'@stablelib/base64': 1.0.1
|
||||||
fast-sha256: 1.3.0
|
fast-sha256: 1.3.0
|
||||||
|
|
||||||
|
stats-gl@2.4.2(@types/three@0.182.0)(three@0.182.0):
|
||||||
|
dependencies:
|
||||||
|
'@types/three': 0.182.0
|
||||||
|
three: 0.182.0
|
||||||
|
|
||||||
|
stats.js@0.17.0: {}
|
||||||
|
|
||||||
statuses@2.0.2: {}
|
statuses@2.0.2: {}
|
||||||
|
|
||||||
std-env@3.10.0: {}
|
std-env@3.10.0: {}
|
||||||
|
|
@ -18482,6 +18907,10 @@ snapshots:
|
||||||
|
|
||||||
supports-preserve-symlinks-flag@1.0.0: {}
|
supports-preserve-symlinks-flag@1.0.0: {}
|
||||||
|
|
||||||
|
suspend-react@0.1.3(react@19.2.3):
|
||||||
|
dependencies:
|
||||||
|
react: 19.2.3
|
||||||
|
|
||||||
svix@1.84.1:
|
svix@1.84.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
standardwebhooks: 1.0.0
|
standardwebhooks: 1.0.0
|
||||||
|
|
@ -18555,6 +18984,22 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
any-promise: 1.3.0
|
any-promise: 1.3.0
|
||||||
|
|
||||||
|
three-mesh-bvh@0.8.3(three@0.182.0):
|
||||||
|
dependencies:
|
||||||
|
three: 0.182.0
|
||||||
|
|
||||||
|
three-stdlib@2.36.1(three@0.182.0):
|
||||||
|
dependencies:
|
||||||
|
'@types/draco3d': 1.4.10
|
||||||
|
'@types/offscreencanvas': 2019.7.3
|
||||||
|
'@types/webxr': 0.5.24
|
||||||
|
draco3d: 1.5.7
|
||||||
|
fflate: 0.6.10
|
||||||
|
potpack: 1.0.2
|
||||||
|
three: 0.182.0
|
||||||
|
|
||||||
|
three@0.182.0: {}
|
||||||
|
|
||||||
throttleit@2.1.0: {}
|
throttleit@2.1.0: {}
|
||||||
|
|
||||||
tiny-invariant@1.3.3: {}
|
tiny-invariant@1.3.3: {}
|
||||||
|
|
@ -18609,6 +19054,20 @@ snapshots:
|
||||||
|
|
||||||
trim-lines@3.0.1: {}
|
trim-lines@3.0.1: {}
|
||||||
|
|
||||||
|
troika-three-text@0.52.4(three@0.182.0):
|
||||||
|
dependencies:
|
||||||
|
bidi-js: 1.0.3
|
||||||
|
three: 0.182.0
|
||||||
|
troika-three-utils: 0.52.4(three@0.182.0)
|
||||||
|
troika-worker-utils: 0.52.0
|
||||||
|
webgl-sdf-generator: 1.1.1
|
||||||
|
|
||||||
|
troika-three-utils@0.52.4(three@0.182.0):
|
||||||
|
dependencies:
|
||||||
|
three: 0.182.0
|
||||||
|
|
||||||
|
troika-worker-utils@0.52.0: {}
|
||||||
|
|
||||||
trough@2.2.0: {}
|
trough@2.2.0: {}
|
||||||
|
|
||||||
ts-api-utils@2.4.0(typescript@5.9.3):
|
ts-api-utils@2.4.0(typescript@5.9.3):
|
||||||
|
|
@ -18687,6 +19146,14 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer: 5.2.1
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
|
tunnel-rat@0.1.2(@types/react@19.2.7)(react@19.2.3):
|
||||||
|
dependencies:
|
||||||
|
zustand: 4.5.7(@types/react@19.2.7)(react@19.2.3)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@types/react'
|
||||||
|
- immer
|
||||||
|
- react
|
||||||
|
|
||||||
turbo-darwin-64@2.7.3:
|
turbo-darwin-64@2.7.3:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
|
@ -18933,6 +19400,8 @@ snapshots:
|
||||||
is-typed-array: 1.1.15
|
is-typed-array: 1.1.15
|
||||||
which-typed-array: 1.1.19
|
which-typed-array: 1.1.19
|
||||||
|
|
||||||
|
utility-types@3.11.0: {}
|
||||||
|
|
||||||
uuid@10.0.0: {}
|
uuid@10.0.0: {}
|
||||||
|
|
||||||
uuid@11.1.0: {}
|
uuid@11.1.0: {}
|
||||||
|
|
@ -19054,6 +19523,10 @@ snapshots:
|
||||||
|
|
||||||
web-namespaces@2.0.1: {}
|
web-namespaces@2.0.1: {}
|
||||||
|
|
||||||
|
webgl-constants@1.1.1: {}
|
||||||
|
|
||||||
|
webgl-sdf-generator@1.1.1: {}
|
||||||
|
|
||||||
webidl-conversions@7.0.0: {}
|
webidl-conversions@7.0.0: {}
|
||||||
|
|
||||||
webidl-conversions@8.0.1: {}
|
webidl-conversions@8.0.1: {}
|
||||||
|
|
@ -19223,4 +19696,17 @@ snapshots:
|
||||||
|
|
||||||
zod@4.3.5: {}
|
zod@4.3.5: {}
|
||||||
|
|
||||||
|
zustand@4.5.7(@types/react@19.2.7)(react@19.2.3):
|
||||||
|
dependencies:
|
||||||
|
use-sync-external-store: 1.6.0(react@19.2.3)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.2.7
|
||||||
|
react: 19.2.3
|
||||||
|
|
||||||
|
zustand@5.0.10(@types/react@19.2.7)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)):
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.2.7
|
||||||
|
react: 19.2.3
|
||||||
|
use-sync-external-store: 1.6.0(react@19.2.3)
|
||||||
|
|
||||||
zwitch@2.0.4: {}
|
zwitch@2.0.4: {}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue