Add support for @snort/worker-relay as a cache relay

This commit is contained in:
hzrd149 2024-04-11 10:16:55 -05:00
parent 781948afd6
commit 8defd6621e
22 changed files with 844 additions and 348 deletions

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Add support for @snort/worker-relay as a cache relay

View File

@ -34,6 +34,7 @@
"@noble/curves": "^1.3.0",
"@noble/hashes": "^1.3.2",
"@noble/secp256k1": "^1.7.0",
"@snort/worker-relay": "^1.0.9",
"@uiw/codemirror-theme-github": "^4.21.21",
"@uiw/react-codemirror": "^4.21.21",
"@webscopeio/react-textarea-autocomplete": "^4.9.2",
@ -103,8 +104,8 @@
"camelcase": "^8.0.0",
"prettier": "^3.1.1",
"typescript": "^5.3.3",
"vite": "^5.0.10",
"vite-plugin-pwa": "^0.17.4",
"vite": "^5.2.8",
"vite-plugin-pwa": "^0.19.8",
"workbox-build": "^7.0.0",
"workbox-window": "^7.0.0"
},

View File

@ -91,6 +91,7 @@ import VideoDetailsView from "./views/videos/video";
import BookmarksView from "./views/bookmarks";
import LoginNostrAddressView from "./views/signin/address";
import LoginNostrAddressCreate from "./views/signin/address/create";
import DatabaseView from "./views/relays/cache/database";
const TracksView = lazy(() => import("./views/tracks"));
const UserTracksTab = lazy(() => import("./views/user/tracks"));
const UserVideosTab = lazy(() => import("./views/user/videos"));
@ -270,7 +271,13 @@ const router = createHashRouter([
children: [
{ path: "", element: <AppRelays /> },
{ path: "app", element: <AppRelays /> },
{ path: "cache", element: <CacheRelayView /> },
{
path: "cache",
children: [
{ path: "database", element: <DatabaseView /> },
{ path: "", element: <CacheRelayView /> },
],
},
{ path: "mailboxes", element: <MailboxesView /> },
{ path: "media-servers", element: <MediaServersView /> },
{ path: "nip05", element: <NIP05RelaysView /> },

View File

@ -0,0 +1,60 @@
import { useMemo } from "react";
import { useColorModeValue, useTheme } from "@chakra-ui/react";
import {
Chart as ChartJS,
ArcElement,
CategoryScale,
ChartData,
Colors,
Legend,
LineElement,
LinearScale,
PointElement,
Title,
Tooltip,
} from "chart.js";
import { Pie } from "react-chartjs-2";
ChartJS.register(
ArcElement,
Tooltip,
Legend,
Colors,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
);
function createChartData(kinds: Record<string, number>) {
const sortedKinds = Object.entries(kinds)
.map(([kind, count]) => ({ kind, count }))
.sort((a, b) => b.count - a.count);
const data: ChartData<"pie", number[], string> = {
labels: sortedKinds.map(({ kind }) => String(kind)),
datasets: [{ label: "# of events", data: sortedKinds.map(({ count }) => count) }],
};
return data;
}
export default function EventKindsPieChart({ kinds }: { kinds: Record<string, number> }) {
const theme = useTheme();
const token = theme.semanticTokens.colors["chakra-body-text"];
const color = useColorModeValue(token._light, token._dark) as string;
const chartData = useMemo(() => createChartData(kinds), [kinds]);
return (
<Pie
data={chartData}
options={{
color,
plugins: { colors: { forceOverride: true } },
}}
/>
);
}

View File

@ -0,0 +1,54 @@
import { useMemo } from "react";
import { ButtonGroup, IconButton, Table, TableContainer, Tbody, Td, Th, Thead, Tr } from "@chakra-ui/react";
import { TrashIcon } from "../icons";
export default function EventKindsTable({
kinds,
deleteKind,
}: {
kinds: Record<string, number>;
deleteKind?: (kind: string) => Promise<void>;
}) {
const sorted = useMemo(
() =>
Object.entries(kinds)
.map(([kind, count]) => ({ kind, count }))
.sort((a, b) => b.count - a.count),
[kinds],
);
return (
<TableContainer>
<Table size="sm">
<Thead>
<Tr>
<Th isNumeric>Kind</Th>
<Th isNumeric>Count</Th>
{deleteKind && <Th></Th>}
</Tr>
</Thead>
<Tbody>
{sorted.map(({ kind, count }) => (
<Tr key={kind}>
<Td isNumeric>{kind}</Td>
<Td isNumeric>{count}</Td>
{deleteKind && (
<Td isNumeric>
<ButtonGroup size="xs">
<IconButton
icon={<TrashIcon />}
aria-label="Delete kind"
colorScheme="red"
variant="ghost"
onClick={() => deleteKind(kind)}
/>
</ButtonGroup>
</Td>
)}
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
);
}

View File

@ -56,6 +56,7 @@ export default function ReactionPicker({ onSelect }: ReactionPickerProps) {
/>
{quickReactions.map((emoji) => (
<IconButton
key={emoji}
icon={<span>{emoji}</span>}
aria-label="Shaka"
variant="ghost"

View File

@ -1,7 +1,8 @@
import { IconButton, IconButtonProps } from "@chakra-ui/react";
import { ChevronLeftIcon } from "../icons";
import { useNavigate } from "react-router-dom";
import { ChevronLeftIcon } from "../icons";
export default function BackButton({ ...props }: Omit<IconButtonProps, "onClick" | "children" | "aria-label">) {
const navigate = useNavigate();
return (

View File

@ -2,6 +2,7 @@ import { CacheRelay, openDB } from "nostr-idb";
import { Relay } from "nostr-tools";
import { logger } from "../helpers/debug";
import { safeRelayUrl } from "../helpers/relay";
import WasmRelay from "./wasm-relay";
// save the local relay from query params to localStorage
const params = new URLSearchParams(location.search);
@ -38,7 +39,9 @@ async function createRelay() {
const localRelayURL = localStorage.getItem("localRelay");
if (localRelayURL) {
if (localRelayURL.startsWith("nostr-idb://")) {
if (localRelayURL === "nostr-idb://wasm-worker" && WasmRelay.SUPPORTED) {
return new WasmRelay();
} else if (localRelayURL.startsWith("nostr-idb://")) {
return createInternalRelay();
} else if (safeRelayUrl(localRelayURL)) {
return new Relay(safeRelayUrl(localRelayURL)!);

View File

@ -0,0 +1,96 @@
import { type WorkerRelayInterface } from "@snort/worker-relay";
import { nanoid } from "nanoid";
import { SimpleRelay, Subscription, SubscriptionOptions } from "nostr-idb";
import { Filter, NostrEvent } from "nostr-tools";
import { logger } from "../../helpers/debug";
import { WASM_RELAY_SUPPORTED } from "./supported";
export default class WasmRelay implements SimpleRelay {
log = logger.extend("WasmRelay");
url = "nostr-idb://wasm-worker";
connected = false;
worker?: WorkerRelayInterface;
static SUPPORTED = WASM_RELAY_SUPPORTED;
private subscriptions: Map<
string,
SubscriptionOptions & {
filters: Filter[];
}
> = new Map();
async connect() {
if (this.connected || this.worker) return;
console.time("Starting Wasm Worker");
const { default: worker } = await import("./worker");
this.worker = worker;
this.connected = true;
console.timeEnd("Starting Wasm Worker");
}
async close() {
console.error("Cant stop wasm worker");
}
async publish(event: NostrEvent) {
if (!this.worker) throw new Error("Worker not setup");
const res = await this.worker.event(event);
if (res.message) return res.message;
return res.ok ? "success" : "failed";
}
async count(filters: Filter[], params: { id?: string | null }) {
if (!this.worker) throw new Error("Worker not setup");
return await this.worker.count(["REQ", params.id || nanoid(), ...filters]);
}
private async executeSubscription(sub: Subscription) {
if (!this.worker) throw new Error("Worker not setup");
const start = new Date().valueOf();
this.log(`Running ${sub.id}`, sub.filters);
// get events
await this.worker.query(["REQ", sub.id, ...sub.filters]).then((events) => {
const delta = new Date().valueOf() - start;
this.log(`Finished ${sub.id} took ${delta}ms and got ${events.length} events`);
if (sub.onevent) {
for (const event of events) sub.onevent(event);
}
if (sub.oneose) sub.oneose();
});
}
subscribe(filters: Filter[], options: Partial<SubscriptionOptions>): Subscription {
// remove any duplicate subscriptions
if (options.id && this.subscriptions.has(options.id)) {
this.subscriptions.delete(options.id);
}
const id = options.id || nanoid();
const sub = {
id,
filters,
close: () => this.subscriptions.delete(id),
fire: () => this.executeSubscription(sub),
...options,
};
this.subscriptions.set(id, sub);
this.executeSubscription(sub);
return sub;
}
unsubscribe(id: string) {
const sub = this.subscriptions.get(id);
if (sub) {
sub.onclose?.("unsubscribe");
this.subscriptions.delete(id);
}
}
}

View File

@ -0,0 +1 @@
export const WASM_RELAY_SUPPORTED = "WebAssembly" in self && "Worker" in self && "storage" in navigator;

View File

@ -0,0 +1,16 @@
import { WorkerRelayInterface } from "@snort/worker-relay";
import WorkerVite from "@snort/worker-relay/src/worker?worker";
const workerScript = import.meta.env.DEV
? new URL("@snort/worker-relay/dist/esm/worker.mjs", import.meta.url)
: new WorkerVite();
const workerRelay = new WorkerRelayInterface(workerScript);
await workerRelay.init("nostrudel.db");
if (import.meta.env.DEV) {
// @ts-expect-error
window.workerRelay = workerRelay;
}
export default workerRelay;

View File

@ -0,0 +1,26 @@
import { useState } from "react";
import { Button } from "@chakra-ui/react";
import { NostrEvent } from "nostr-tools";
import stringify from "json-stringify-deterministic";
import Upload01 from "../../../../../components/icons/upload-01";
export default function ExportEventsButton({ getEvents }: { getEvents: () => Promise<NostrEvent[]> }) {
const [loading, setLoading] = useState(false);
const exportDatabase = async () => {
setLoading(true);
const rows = await getEvents();
const lines = rows.map((event) => stringify(event));
const file = new File([lines.join("\n")], "noStrudel-export.jsonl", {
type: "application/jsonl",
});
const url = URL.createObjectURL(file);
window.open(url);
setLoading(false);
};
return (
<Button onClick={exportDatabase} isLoading={loading} leftIcon={<Upload01 />}>
Export database
</Button>
);
}

View File

@ -0,0 +1,44 @@
import { Button, Input } from "@chakra-ui/react";
import { NostrEvent } from "nostr-tools";
import { useRef, useState } from "react";
import Download01 from "../../../../../components/icons/download-01";
export default function ImportEventsButton({ onLoad }: { onLoad: (events: NostrEvent[]) => Promise<void> }) {
const ref = useRef<HTMLInputElement | null>(null);
const [loading, setLoading] = useState(false);
const importFile = (file: File) => {
setLoading(true);
const reader = new FileReader();
reader.readAsText(file, "utf8");
reader.onload = async () => {
if (typeof reader.result !== "string") return;
const lines = reader.result.split("\n");
const events: NostrEvent[] = [];
for (const line of lines) {
try {
const event = JSON.parse(line) as NostrEvent;
events.push(event);
} catch (e) {}
}
await onLoad(events);
alert(`Imported ${events.length} events`);
setLoading(false);
};
};
return (
<>
<Button onClick={() => ref.current?.click()} isLoading={loading} leftIcon={<Download01 />}>
Import events
</Button>
<Input
hidden
type="file"
accept=".jsonl"
onChange={(e) => e.target.files?.[0] && importFile(e.target.files[0])}
ref={ref}
/>
</>
);
}

View File

@ -0,0 +1,38 @@
import { lazy } from "react";
import { Flex, Heading, Link, Text } from "@chakra-ui/react";
import { CacheRelay } from "nostr-idb";
import { Link as RouterLink } from "react-router-dom";
import BackButton from "../../../../components/router/back-button";
import { localRelay } from "../../../../services/local-relay";
import WasmRelay from "../../../../services/wasm-relay";
const WasmDatabasePage = lazy(() => import("./wasm"));
const InternalDatabasePage = lazy(() => import("./internal"));
export default function DatabaseView() {
let content = (
<Text>
noStrudel dose not have access to the selected cache relays database{" "}
<Link as={RouterLink} to="/relays/cache" color="blue.500">
Change cache relay
</Link>
</Text>
);
if (localRelay instanceof WasmRelay) content = <WasmDatabasePage />;
else if (localRelay instanceof CacheRelay) content = <InternalDatabasePage />;
return (
<Flex gap="2" direction="column" flex={1}>
<Flex gap="2" direction="column">
<Flex gap="2">
<BackButton hideFrom="lg" size="sm" />
<Heading size="lg">Database Tools</Heading>
</Flex>
{content}
</Flex>
</Flex>
);
}

View File

@ -0,0 +1,73 @@
import { useState } from "react";
import { addEvents, countEvents, countEventsByKind, getEventUID, updateUsed } from "nostr-idb";
import { Button, ButtonGroup, Card, Flex, Heading, Text } from "@chakra-ui/react";
import { useAsync } from "react-use";
import { NostrEvent } from "nostr-tools";
import { localDatabase, localRelay } from "../../../../services/local-relay";
import EventKindsPieChart from "../../../../components/charts/event-kinds-pie-chart";
import EventKindsTable from "../../../../components/charts/event-kinds-table";
import ImportEventsButton from "./components/import-events-button";
import ExportEventsButton from "./components/export-events-button";
import { clearCacheData, deleteDatabase } from "../../../../services/db";
async function importEvents(events: NostrEvent[]) {
await addEvents(localDatabase, events);
await updateUsed(
localDatabase,
events.map((e) => getEventUID(e)),
);
}
async function exportEvents() {
return (await localDatabase.getAll("events")).map((row) => row.event);
}
export default function InternalDatabasePage() {
const { value: count } = useAsync(async () => await countEvents(localDatabase), []);
const { value: kinds } = useAsync(async () => await countEventsByKind(localDatabase), []);
const [clearing, setClearing] = useState(false);
const handleClearData = async () => {
setClearing(true);
await clearCacheData();
setClearing(false);
};
const [deleting, setDeleting] = useState(false);
const handleDeleteDatabase = async () => {
setDeleting(true);
await deleteDatabase();
setDeleting(false);
};
return (
<>
<Text>Total events: {count ?? "Loading..."}</Text>
<ButtonGroup flexWrap="wrap">
<ImportEventsButton onLoad={importEvents} />
<ExportEventsButton getEvents={exportEvents} />
</ButtonGroup>
<ButtonGroup flexWrap="wrap">
<Button onClick={handleClearData} isLoading={clearing} colorScheme="primary" variant="outline">
Clear cache
</Button>
<Button colorScheme="red" onClick={handleDeleteDatabase} isLoading={deleting}>
Delete database
</Button>
</ButtonGroup>
<Flex gap="2" wrap="wrap" alignItems="flex-start" w="full">
{kinds && (
<>
<Card p="2" minW="sm" maxW="lg" flex={1}>
<Heading size="sm">Events by kind</Heading>
<EventKindsPieChart kinds={kinds} />
</Card>
<Card p="2" minW="sm" maxW="md" flex={1}>
<EventKindsTable kinds={kinds} />
</Card>
</>
)}
</Flex>
</>
);
}

View File

@ -0,0 +1,80 @@
import { useCallback, useEffect, useState } from "react";
import { ButtonGroup, Card, Flex, Heading, Text } from "@chakra-ui/react";
import { NostrEvent } from "nostr-tools";
import { localRelay } from "../../../../services/local-relay";
import WasmRelay from "../../../../services/wasm-relay";
import EventKindsPieChart from "../../../../components/charts/event-kinds-pie-chart";
import EventKindsTable from "../../../../components/charts/event-kinds-table";
import ImportEventsButton from "./components/import-events-button";
import ExportEventsButton from "./components/export-events-button";
export default function WasmDatabasePage() {
const relay = localRelay;
if (!(relay instanceof WasmRelay)) return null;
const worker = relay.worker;
if (!worker) return null;
const [summary, setSummary] = useState<Record<string, number>>();
const total = summary ? Object.values(summary).reduce((t, v) => t + v, 0) : undefined;
const refresh = useCallback(async () => {
await worker.summary().then((v) => setSummary(v));
}, [setSummary, worker]);
const importEvents = useCallback(
async (events: NostrEvent[]) => {
const batchSize = 100;
const queue = Array.from(events);
const next = () => {
const p: Promise<any>[] = [];
for (let i = 0; i < batchSize; i++) {
const event = queue.pop();
if (!event) break;
p.push(worker.event(event));
}
return Promise.all(p);
};
while (queue.length > 0) {
await next();
await refresh();
}
},
[worker],
);
const exportEvents = useCallback(async () => {
return worker.query(["REQ", "export", {}]);
}, [worker]);
useEffect(() => {
refresh();
}, []);
return (
<>
<Text>Wasm Relay Database</Text>
<Text>Total events: {total ?? "Loading..."}</Text>
<ButtonGroup flexWrap="wrap">
<ImportEventsButton onLoad={importEvents} />
<ExportEventsButton getEvents={exportEvents} />
</ButtonGroup>
<Flex gap="2" wrap="wrap" alignItems="flex-start" w="full">
{summary && (
<>
<Card p="2" minW="sm" maxW="lg" flex={1}>
<Heading size="sm">Events by kind</Heading>
<EventKindsPieChart kinds={summary} />
</Card>
<Card p="2" minW="sm" maxW="md" flex={1}>
<EventKindsTable kinds={summary} />
</Card>
</>
)}
</Flex>
</>
);
}

View File

@ -1,8 +1,22 @@
import { Button, Card, CardBody, CardHeader, Flex, Heading, Link, Text } from "@chakra-ui/react";
import BackButton from "../../../components/router/back-button";
import { useAsync } from "react-use";
import { NOSTR_RELAY_TRAY_URL, checkNostrRelayTray, localRelay } from "../../../services/local-relay";
import {
Button,
ButtonGroup,
Card,
CardBody,
CardFooter,
CardHeader,
Flex,
Heading,
Link,
Text,
} from "@chakra-ui/react";
import { CacheRelay } from "nostr-idb";
import { Link as RouterLink } from "react-router-dom";
import BackButton from "../../../components/router/back-button";
import { NOSTR_RELAY_TRAY_URL, checkNostrRelayTray, localRelay } from "../../../services/local-relay";
import WasmRelay from "../../../services/wasm-relay";
function InternalRelay() {
const enabled = localRelay instanceof CacheRelay;
@ -24,9 +38,59 @@ function InternalRelay() {
<Text>Maximum capacity: 10k events</Text>
<Text>Performance: Usable, but limited by the browser</Text>
</CardBody>
{enabled && (
<CardFooter p="4" pt="0">
<Button size="sm" colorScheme="primary" ml="auto" as={RouterLink} to="/relays/cache/database">
Database Tools
</Button>
</CardFooter>
)}
</Card>
);
}
function WasmWorkerRelay() {
const enabled = localRelay instanceof WasmRelay;
const enable = () => {
localStorage.setItem("localRelay", "nostr-idb://wasm-worker");
location.reload();
};
return (
<Card borderColor={enabled ? "primary.500" : undefined} variant="outline">
<CardHeader p="4" display="flex" gap="2" alignItems="center">
<Heading size="md">Internal SQLite Cache</Heading>
<Button size="sm" colorScheme="primary" ml="auto" onClick={enable} isDisabled={enabled}>
{enabled ? "Enabled" : "Enable"}
</Button>
</CardHeader>
<CardBody p="4" pt="0">
<Text mb="2">
Use{" "}
<Link
href="https://git.v0l.io/Kieran/snort/src/branch/main/packages/worker-relay"
isExternal
color="blue.500"
>
@snort/worker-relay
</Link>{" "}
with SQLite running in the browser.
</Text>
<Text>Maximum capacity: Unlimited</Text>
<Text>Performance: Slightly slower than Browser Cache</Text>
<Text color="yellow.500">NOTE: Can increase the initial load time of the app by ~2 seconds</Text>
</CardBody>
{enabled && (
<CardFooter p="4" pt="0">
<Button size="sm" colorScheme="primary" ml="auto" as={RouterLink} to="/relays/cache/database">
Database Tools
</Button>
</CardFooter>
)}
</Card>
);
}
function NostrRelayTray() {
const { value: available, loading: checking } = useAsync(checkNostrRelayTray);
@ -68,6 +132,7 @@ function NostrRelayTray() {
</Card>
);
}
function SatelliteRelay() {
const { value: relay } = useAsync(() => window.satellite!.getLocalRelay());
const { value: enabled } = useAsync(async () => localRelay.url === relay, [localRelay.url, relay]);
@ -130,6 +195,7 @@ export default function CacheRelayView() {
The cache relay is used to cache events locally so they can be loaded quickly
</Text>
<InternalRelay />
{WasmRelay.SUPPORTED && <WasmWorkerRelay />}
<NostrRelayTray />
{window.satellite && <SatelliteRelay />}
{window.CACHE_RELAY_ENABLED && <HostedRelay />}

View File

@ -1,11 +1,9 @@
import { Outlet, Link as RouterLink, useLocation } from "react-router-dom";
import { Button, Flex, Heading } from "@chakra-ui/react";
import { Button, Flex } from "@chakra-ui/react";
import VerticalPageLayout from "../../components/vertical-page-layout";
import useCurrentAccount from "../../hooks/use-current-account";
import useUserRelaySets from "../../hooks/use-user-relay-sets";
import { getListName } from "../../helpers/nostr/lists";
import { getEventCoordinate } from "../../helpers/nostr/event";
import { useBreakpointValue } from "../../providers/global/breakpoint-provider";
import Database01 from "../../components/icons/database-01";
import { AtIcon, RelayIcon } from "../../components/icons";
@ -43,7 +41,7 @@ export default function RelaysView() {
<Button
as={RouterLink}
variant="outline"
colorScheme={location.pathname === "/relays/cache" ? "primary" : undefined}
colorScheme={location.pathname.startsWith("/relays/cache") ? "primary" : undefined}
to="/relays/cache"
leftIcon={<Database01 boxSize={6} />}
>
@ -56,7 +54,7 @@ export default function RelaysView() {
as={RouterLink}
to="/relays/mailboxes"
leftIcon={<Mail02 boxSize={6} />}
colorScheme={location.pathname === "/relays/mailboxes" ? "primary" : undefined}
colorScheme={location.pathname.startsWith("/relays/mailboxes") ? "primary" : undefined}
>
Mailboxes
</Button>
@ -65,7 +63,7 @@ export default function RelaysView() {
as={RouterLink}
to="/relays/media-servers"
leftIcon={<Image01 boxSize={6} />}
colorScheme={location.pathname === "/relays/media-servers" ? "primary" : undefined}
colorScheme={location.pathname.startsWith("/relays/media-servers") ? "primary" : undefined}
>
Media Servers
</Button>
@ -77,7 +75,7 @@ export default function RelaysView() {
as={RouterLink}
to="/relays/nip05"
leftIcon={<AtIcon boxSize={6} />}
colorScheme={location.pathname === "/relays/nip05" ? "primary" : undefined}
colorScheme={location.pathname.startsWith("/relays/nip05") ? "primary" : undefined}
>
NIP-05 Relays
</Button>
@ -87,7 +85,7 @@ export default function RelaysView() {
as={RouterLink}
to="/relays/contacts"
leftIcon={<UserSquare boxSize={6} />}
colorScheme={location.pathname === "/relays/contacts" ? "primary" : undefined}
colorScheme={location.pathname.startsWith("/relays/contacts") ? "primary" : undefined}
>
Contact List Relays
</Button>

View File

@ -40,6 +40,8 @@ import EventStore from "../../../classes/event-store";
import { sortByDate } from "../../../helpers/nostr/event";
import { NostrQuery } from "../../../types/nostr-relay";
import relayPoolService from "../../../services/relay-pool";
import EventKindsPieChart from "../../../components/charts/event-kinds-pie-chart";
import EventKindsTable from "../../../components/charts/event-kinds-table";
ChartJS.register(
ArcElement,
@ -75,28 +77,13 @@ function groupByKind(events: NostrEvent[]) {
return byKind;
}
function buildPieChartData(events: NostrEvent[]) {
function getSortedKinds(events: NostrEvent[]) {
const byKind = groupByKind(events);
const sortedKinds = Object.entries(byKind)
return Object.entries(byKind)
.map(([kind, events]) => ({ kind, count: events.length }))
.sort((a, b) => b.count - a.count);
const data: ChartData<"pie", number[], string> = {
labels: sortedKinds.map(({ kind }) => String(kind)),
datasets: [{ label: "# of events", data: sortedKinds.map(({ count }) => count) }],
};
return data;
}
function buildTableData(events: NostrEvent[]) {
const byKind = groupByKind(events);
const sortedKinds = Object.entries(byKind)
.map(([kind, events]) => ({ kind, count: events.length }))
.sort((a, b) => b.count - a.count);
return sortedKinds;
.sort((a, b) => b.count - a.count)
.reduce((dir, k) => ({ ...dir, [k.kind]: k.count }), {} as Record<string, number>);
}
function buildLineChartData(events: NostrEvent[], timeBlock = 60 * 60): ChartData<"line", number[], string> {
@ -175,8 +162,7 @@ export default function RelayDetailsTab({ relay }: { relay: string }) {
const events = Array.from(store.events.values()).sort(sortByDate);
const pieChartData = buildPieChartData(events);
const tableData = buildTableData(events);
const kinds = getSortedKinds(events);
return (
<VerticalPageLayout>
@ -189,33 +175,10 @@ export default function RelayDetailsTab({ relay }: { relay: string }) {
<Flex wrap="wrap" gap="4" alignItems="flex-start">
<Card p="2" w="50%">
<Heading size="sm">Events by kind</Heading>
<Pie
data={pieChartData}
options={{
color,
plugins: { colors: { forceOverride: true } },
}}
/>
<EventKindsPieChart kinds={kinds} />
</Card>
<Card p="2" minW="xs">
<TableContainer>
<Table size="sm">
<Thead>
<Tr>
<Th isNumeric>Kind</Th>
<Th isNumeric>Count</Th>
</Tr>
</Thead>
<Tbody>
{tableData.map(({ kind, count }) => (
<Tr key={kind}>
<Td isNumeric>{kind}</Td>
<Td isNumeric>{count}</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
<EventKindsTable kinds={kinds} />
</Card>
{/* <Card p="2" w="full" aspectRatio={16 / 9}>
<Heading size="sm">Event kinds over time</Heading>

View File

@ -1,4 +1,4 @@
import { useRef, useState } from "react";
import { useState } from "react";
import { useAsync } from "react-use";
import {
Button,
@ -7,18 +7,15 @@ import {
AccordionButton,
Box,
AccordionIcon,
ButtonGroup,
Text,
Input,
Flex,
} from "@chakra-ui/react";
import { addEvents, countEvents, countEventsByKind, getEventUID, updateUsed } from "nostr-idb";
import stringify from "json-stringify-deterministic";
import { countEvents, countEventsByKind } from "nostr-idb";
import { Link as RouterLink } from "react-router-dom";
import { clearCacheData, deleteDatabase } from "../../services/db";
import { DatabaseIcon } from "../../components/icons";
import { localDatabase } from "../../services/local-relay";
import { NostrEvent } from "../../types/nostr-event";
function DatabaseStats() {
const { value: count } = useAsync(async () => await countEvents(localDatabase), []);
@ -36,49 +33,6 @@ function DatabaseStats() {
);
}
function ImportButton() {
const ref = useRef<HTMLInputElement | null>(null);
const [importing, setImporting] = useState(false);
const importFile = (file: File) => {
setImporting(true);
const reader = new FileReader();
reader.readAsText(file, "utf8");
reader.onload = async () => {
if (typeof reader.result !== "string") return;
const lines = reader.result.split("\n");
const events: NostrEvent[] = [];
for (const line of lines) {
try {
const event = JSON.parse(line) as NostrEvent;
events.push(event);
} catch (e) {}
}
await addEvents(localDatabase, events);
await updateUsed(
localDatabase,
events.map((e) => getEventUID(e)),
);
alert(`Imported ${events.length} events`);
setImporting(false);
};
};
return (
<>
<Input
hidden
type="file"
accept=".jsonl"
onChange={(e) => e.target.files?.[0] && importFile(e.target.files[0])}
ref={ref}
/>
<Button onClick={() => ref.current?.click()} isLoading={importing}>
Import events
</Button>
</>
);
}
export default function DatabaseSettings() {
const [clearing, setClearing] = useState(false);
const handleClearData = async () => {
@ -94,19 +48,6 @@ export default function DatabaseSettings() {
setDeleting(false);
};
const [exporting, setExporting] = useState(false);
const exportDatabase = async () => {
setExporting(true);
const rows = await localDatabase.getAll("events");
const lines = rows.map((row) => stringify(row.event));
const file = new File([lines.join("\n")], "noStrudel-export.jsonl", {
type: "application/jsonl",
});
const url = URL.createObjectURL(file);
window.open(url);
setExporting(false);
};
return (
<AccordionItem>
<h2>
@ -119,19 +60,10 @@ export default function DatabaseSettings() {
</AccordionButton>
</h2>
<AccordionPanel>
<DatabaseStats />
<Flex mt="2" gap="2" wrap="wrap">
<Button onClick={handleClearData} isLoading={clearing}>
Clear cache
</Button>
<ImportButton />
<Button onClick={exportDatabase} isLoading={exporting}>
Export database
</Button>
<Button colorScheme="red" onClick={handleDeleteDatabase} isLoading={deleting}>
Delete database
</Button>
</Flex>
<Text>Database tools have moved</Text>
<Button as={RouterLink} to="/relays/cache/database" size="sm" colorScheme="primary">
Database Tools
</Button>
</AccordionPanel>
</AccordionItem>
);

View File

@ -36,8 +36,8 @@ import { DownloadIcon, ShareIcon } from "../../../components/icons";
import { RelayUrlInput } from "../../../components/relay-url-input";
import { validateRelayURL } from "../../../helpers/relay";
import FilterEditor from "./filter-editor";
import { CopyIconButton } from "../../../components/copy-icon-button";
import { safeJson } from "../../../helpers/parse";
import WasmRelay from "../../../services/wasm-relay";
const EventTimeline = memo(({ events }: { events: NostrEvent[] }) => {
return (
@ -86,7 +86,7 @@ export default function EventConsoleView() {
if (sub) sub.close();
let r: Relay | CacheRelay = localRelay;
let r: Relay | CacheRelay | WasmRelay = localRelay;
if (queryRelay.isOpen) {
const url = validateRelayURL(relayURL);
if (!relay || relay.url !== url.toString()) {

449
yarn.lock
View File

@ -2227,120 +2227,120 @@
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6"
integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==
"@esbuild/aix-ppc64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz#d1bc06aedb6936b3b6d313bf809a5a40387d2b7f"
integrity sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==
"@esbuild/aix-ppc64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537"
integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==
"@esbuild/android-arm64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz#7ad65a36cfdb7e0d429c353e00f680d737c2aed4"
integrity sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==
"@esbuild/android-arm64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9"
integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==
"@esbuild/android-arm@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.12.tgz#b0c26536f37776162ca8bde25e42040c203f2824"
integrity sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==
"@esbuild/android-arm@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995"
integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==
"@esbuild/android-x64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.12.tgz#cb13e2211282012194d89bf3bfe7721273473b3d"
integrity sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==
"@esbuild/android-x64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98"
integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==
"@esbuild/darwin-arm64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz#cbee41e988020d4b516e9d9e44dd29200996275e"
integrity sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==
"@esbuild/darwin-arm64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb"
integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==
"@esbuild/darwin-x64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz#e37d9633246d52aecf491ee916ece709f9d5f4cd"
integrity sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==
"@esbuild/darwin-x64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0"
integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==
"@esbuild/freebsd-arm64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz#1ee4d8b682ed363b08af74d1ea2b2b4dbba76487"
integrity sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==
"@esbuild/freebsd-arm64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911"
integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==
"@esbuild/freebsd-x64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz#37a693553d42ff77cd7126764b535fb6cc28a11c"
integrity sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==
"@esbuild/freebsd-x64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c"
integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==
"@esbuild/linux-arm64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz#be9b145985ec6c57470e0e051d887b09dddb2d4b"
integrity sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==
"@esbuild/linux-arm64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5"
integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==
"@esbuild/linux-arm@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz#207ecd982a8db95f7b5279207d0ff2331acf5eef"
integrity sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==
"@esbuild/linux-arm@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c"
integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==
"@esbuild/linux-ia32@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz#d0d86b5ca1562523dc284a6723293a52d5860601"
integrity sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==
"@esbuild/linux-ia32@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa"
integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==
"@esbuild/linux-loong64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz#9a37f87fec4b8408e682b528391fa22afd952299"
integrity sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==
"@esbuild/linux-loong64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5"
integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==
"@esbuild/linux-mips64el@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz#4ddebd4e6eeba20b509d8e74c8e30d8ace0b89ec"
integrity sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==
"@esbuild/linux-mips64el@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa"
integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==
"@esbuild/linux-ppc64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz#adb67dadb73656849f63cd522f5ecb351dd8dee8"
integrity sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==
"@esbuild/linux-ppc64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20"
integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==
"@esbuild/linux-riscv64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz#11bc0698bf0a2abf8727f1c7ace2112612c15adf"
integrity sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==
"@esbuild/linux-riscv64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300"
integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==
"@esbuild/linux-s390x@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz#e86fb8ffba7c5c92ba91fc3b27ed5a70196c3cc8"
integrity sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==
"@esbuild/linux-s390x@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685"
integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==
"@esbuild/linux-x64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz#5f37cfdc705aea687dfe5dfbec086a05acfe9c78"
integrity sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==
"@esbuild/linux-x64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff"
integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==
"@esbuild/netbsd-x64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz#29da566a75324e0d0dd7e47519ba2f7ef168657b"
integrity sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==
"@esbuild/netbsd-x64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6"
integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==
"@esbuild/openbsd-x64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz#306c0acbdb5a99c95be98bdd1d47c916e7dc3ff0"
integrity sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==
"@esbuild/openbsd-x64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf"
integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==
"@esbuild/sunos-x64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz#0933eaab9af8b9b2c930236f62aae3fc593faf30"
integrity sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==
"@esbuild/sunos-x64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f"
integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==
"@esbuild/win32-arm64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz#773bdbaa1971b36db2f6560088639ccd1e6773ae"
integrity sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==
"@esbuild/win32-arm64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90"
integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==
"@esbuild/win32-ia32@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz#000516cad06354cc84a73f0943a4aa690ef6fd67"
integrity sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==
"@esbuild/win32-ia32@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23"
integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==
"@esbuild/win32-x64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz#c57c8afbb4054a3ab8317591a0b7320360b444ae"
integrity sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==
"@esbuild/win32-x64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc"
integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==
"@gandlaf21/bolt11-decode@^3.0.6":
version "3.0.6"
@ -2629,70 +2629,80 @@
estree-walker "^1.0.1"
picomatch "^2.2.2"
"@rollup/rollup-android-arm-eabi@4.9.6":
version "4.9.6"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz#66b8d9cb2b3a474d115500f9ebaf43e2126fe496"
integrity sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==
"@rollup/rollup-android-arm-eabi@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.1.tgz#ca0501dd836894216cb9572848c5dde4bfca3bec"
integrity sha512-fH8/o8nSUek8ceQnT7K4EQbSiV7jgkHq81m9lWZFIXjJ7lJzpWXbQFpT/Zh6OZYnpFykvzC3fbEvEAFZu03dPA==
"@rollup/rollup-android-arm64@4.9.6":
version "4.9.6"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.6.tgz#46327d5b86420d2307946bec1535fdf00356e47d"
integrity sha512-T14aNLpqJ5wzKNf5jEDpv5zgyIqcpn1MlwCrUXLrwoADr2RkWA0vOWP4XxbO9aiO3dvMCQICZdKeDrFl7UMClw==
"@rollup/rollup-android-arm64@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.1.tgz#154ca7e4f815d2e442ffc62ee7f64aee8b2547b0"
integrity sha512-Y/9OHLjzkunF+KGEoJr3heiD5X9OLa8sbT1lm0NYeKyaM3oMhhQFvPB0bNZYJwlq93j8Z6wSxh9+cyKQaxS7PQ==
"@rollup/rollup-darwin-arm64@4.9.6":
version "4.9.6"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.6.tgz#166987224d2f8b1e2fd28ee90c447d52271d5e90"
integrity sha512-CqNNAyhRkTbo8VVZ5R85X73H3R5NX9ONnKbXuHisGWC0qRbTTxnF1U4V9NafzJbgGM0sHZpdO83pLPzq8uOZFw==
"@rollup/rollup-darwin-arm64@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.1.tgz#02b522ab6ccc2c504634651985ff8e657b42c055"
integrity sha512-+kecg3FY84WadgcuSVm6llrABOdQAEbNdnpi5X3UwWiFVhZIZvKgGrF7kmLguvxHNQy+UuRV66cLVl3S+Rkt+Q==
"@rollup/rollup-darwin-x64@4.9.6":
version "4.9.6"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.6.tgz#a2e6e096f74ccea6e2f174454c26aef6bcdd1274"
integrity sha512-zRDtdJuRvA1dc9Mp6BWYqAsU5oeLixdfUvkTHuiYOHwqYuQ4YgSmi6+/lPvSsqc/I0Omw3DdICx4Tfacdzmhog==
"@rollup/rollup-darwin-x64@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.1.tgz#217737f9f73de729fdfd7d529afebb6c8283f554"
integrity sha512-2pYRzEjVqq2TB/UNv47BV/8vQiXkFGVmPFwJb+1E0IFFZbIX8/jo1olxqqMbo6xCXf8kabANhp5bzCij2tFLUA==
"@rollup/rollup-linux-arm-gnueabihf@4.9.6":
version "4.9.6"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.6.tgz#09fcd4c55a2d6160c5865fec708a8e5287f30515"
integrity sha512-oNk8YXDDnNyG4qlNb6is1ojTOGL/tRhbbKeE/YuccItzerEZT68Z9gHrY3ROh7axDc974+zYAPxK5SH0j/G+QQ==
"@rollup/rollup-linux-arm-gnueabihf@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.1.tgz#a87e478ab3f697c7f4e74c8b1cac1e0667f8f4be"
integrity sha512-mS6wQ6Do6/wmrF9aTFVpIJ3/IDXhg1EZcQFYHZLHqw6AzMBjTHWnCG35HxSqUNphh0EHqSM6wRTT8HsL1C0x5g==
"@rollup/rollup-linux-arm64-gnu@4.9.6":
version "4.9.6"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.6.tgz#19a3c0b6315c747ca9acf86e9b710cc2440f83c9"
integrity sha512-Z3O60yxPtuCYobrtzjo0wlmvDdx2qZfeAWTyfOjEDqd08kthDKexLpV97KfAeUXPosENKd8uyJMRDfFMxcYkDQ==
"@rollup/rollup-linux-arm64-gnu@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.1.tgz#4da6830eca27e5f4ca15f9197e5660952ca185c6"
integrity sha512-p9rGKYkHdFMzhckOTFubfxgyIO1vw//7IIjBBRVzyZebWlzRLeNhqxuSaZ7kCEKVkm/kuC9fVRW9HkC/zNRG2w==
"@rollup/rollup-linux-arm64-musl@4.9.6":
version "4.9.6"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.6.tgz#94aaf95fdaf2ad9335983a4552759f98e6b2e850"
integrity sha512-gpiG0qQJNdYEVad+1iAsGAbgAnZ8j07FapmnIAQgODKcOTjLEWM9sRb+MbQyVsYCnA0Im6M6QIq6ax7liws6eQ==
"@rollup/rollup-linux-arm64-musl@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.1.tgz#0b0ed35720aebc8f5e501d370a9ea0f686ead1e0"
integrity sha512-nDY6Yz5xS/Y4M2i9JLQd3Rofh5OR8Bn8qe3Mv/qCVpHFlwtZSBYSPaU4mrGazWkXrdQ98GB//H0BirGR/SKFSw==
"@rollup/rollup-linux-riscv64-gnu@4.9.6":
version "4.9.6"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.6.tgz#160510e63f4b12618af4013bddf1761cf9fc9880"
integrity sha512-+uCOcvVmFUYvVDr27aiyun9WgZk0tXe7ThuzoUTAukZJOwS5MrGbmSlNOhx1j80GdpqbOty05XqSl5w4dQvcOA==
"@rollup/rollup-linux-powerpc64le-gnu@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.1.tgz#024ad04d162726f25e62915851f7df69a9677c17"
integrity sha512-im7HE4VBL+aDswvcmfx88Mp1soqL9OBsdDBU8NqDEYtkri0qV0THhQsvZtZeNNlLeCUQ16PZyv7cqutjDF35qw==
"@rollup/rollup-linux-x64-gnu@4.9.6":
version "4.9.6"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.6.tgz#5ac5d068ce0726bd0a96ca260d5bd93721c0cb98"
integrity sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==
"@rollup/rollup-linux-riscv64-gnu@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.1.tgz#180694d1cd069ddbe22022bb5b1bead3b7de581c"
integrity sha512-RWdiHuAxWmzPJgaHJdpvUUlDz8sdQz4P2uv367T2JocdDa98iRw2UjIJ4QxSyt077mXZT2X6pKfT2iYtVEvOFw==
"@rollup/rollup-linux-x64-musl@4.9.6":
version "4.9.6"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.6.tgz#bafa759ab43e8eab9edf242a8259ffb4f2a57a5d"
integrity sha512-ch7M+9Tr5R4FK40FHQk8VnML0Szi2KRujUgHXd/HjuH9ifH72GUmw6lStZBo3c3GB82vHa0ZoUfjfcM7JiiMrQ==
"@rollup/rollup-linux-s390x-gnu@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.1.tgz#f7b4e2b0ca49be4e34f9ef0b548c926d94edee87"
integrity sha512-VMgaGQ5zRX6ZqV/fas65/sUGc9cPmsntq2FiGmayW9KMNfWVG/j0BAqImvU4KTeOOgYSf1F+k6at1UfNONuNjA==
"@rollup/rollup-win32-arm64-msvc@4.9.6":
version "4.9.6"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.6.tgz#1cc3416682e5a20d8f088f26657e6e47f8db468e"
integrity sha512-VD6qnR99dhmTQ1mJhIzXsRcTBvTjbfbGGwKAHcu+52cVl15AC/kplkhxzW/uT0Xl62Y/meBKDZvoJSJN+vTeGA==
"@rollup/rollup-linux-x64-gnu@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.1.tgz#0aaf79e5b9ccf7db3084fe6c3f2d2873a27d5af4"
integrity sha512-9Q7DGjZN+hTdJomaQ3Iub4m6VPu1r94bmK2z3UeWP3dGUecRC54tmVu9vKHTm1bOt3ASoYtEz6JSRLFzrysKlA==
"@rollup/rollup-win32-ia32-msvc@4.9.6":
version "4.9.6"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.6.tgz#7d2251e1aa5e8a1e47c86891fe4547a939503461"
integrity sha512-J9AFDq/xiRI58eR2NIDfyVmTYGyIZmRcvcAoJ48oDld/NTR8wyiPUu2X/v1navJ+N/FGg68LEbX3Ejd6l8B7MQ==
"@rollup/rollup-linux-x64-musl@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.1.tgz#38f0a37ca5015eb07dff86a1b6f94279c179f4ed"
integrity sha512-JNEG/Ti55413SsreTguSx0LOVKX902OfXIKVg+TCXO6Gjans/k9O6ww9q3oLGjNDaTLxM+IHFMeXy/0RXL5R/g==
"@rollup/rollup-win32-x64-msvc@4.9.6":
version "4.9.6"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.6.tgz#2c1fb69e02a3f1506f52698cfdc3a8b6386df9a6"
integrity sha512-jqzNLhNDvIZOrt69Ce4UjGRpXJBzhUBzawMwnaDAwyHriki3XollsewxWzOzz+4yOFDkuJHtTsZFwMxhYJWmLQ==
"@rollup/rollup-win32-arm64-msvc@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.1.tgz#84d48c55740ede42c77373f76e85f368633a0cc3"
integrity sha512-ryS22I9y0mumlLNwDFYZRDFLwWh3aKaC72CWjFcFvxK0U6v/mOkM5Up1bTbCRAhv3kEIwW2ajROegCIQViUCeA==
"@rollup/rollup-win32-ia32-msvc@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.1.tgz#c1e0bc39e20e760f0a526ddf14ae0543af796605"
integrity sha512-TdloItiGk+T0mTxKx7Hp279xy30LspMso+GzQvV2maYePMAWdmrzqSNZhUpPj3CGw12aGj57I026PgLCTu8CGg==
"@rollup/rollup-win32-x64-msvc@4.14.1":
version "4.14.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.1.tgz#299eee74b7d87e116083ac5b1ce8dd9434668294"
integrity sha512-wQGI+LY/Py20zdUPq+XCem7JcPOyzIJBm3dli+56DJsQOHbnXZFEwgmnC6el1TPAfC8lBT3m+z69RmLykNUbew==
"@sagold/json-pointer@^5.1.1":
version "5.1.1"
@ -2756,6 +2766,20 @@
"@noble/hashes" "~1.3.2"
"@scure/base" "~1.1.4"
"@snort/worker-relay@^1.0.9":
version "1.0.9"
resolved "https://registry.yarnpkg.com/@snort/worker-relay/-/worker-relay-1.0.9.tgz#7e51597a5834b9b5ebba9ef7725af3ef46e71559"
integrity sha512-mm5Y8GFxKUEzlmGFcmB9vIommBUCL9GBix4qzjgZzdfYrlJ/7mlCR+wEUd3KcbqnKYVKfDQpaFTUjAuGJmEiJw==
dependencies:
"@sqlite.org/sqlite-wasm" "^3.45.1-build1"
eventemitter3 "^5.0.1"
uuid "^9.0.1"
"@sqlite.org/sqlite-wasm@^3.45.1-build1":
version "3.45.1-build1"
resolved "https://registry.yarnpkg.com/@sqlite.org/sqlite-wasm/-/sqlite-wasm-3.45.1-build1.tgz#648f6a0a0a4c3a67aff24b0e1331af655b86fb60"
integrity sha512-1EgshFNhVeBtZ9KtQPm3PzzJ2CtpmXAq2DAPywy7WZ3gOK6p5n8TY+M+mBMpQCF5cLqrdNFb3Kp9uNie9rUAHw==
"@surma/rollup-plugin-off-main-thread@^2.2.3":
version "2.2.3"
resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz#ee34985952ca21558ab0d952f00298ad2190c053"
@ -4174,34 +4198,34 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
esbuild@^0.19.3:
version "0.19.12"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.12.tgz#dc82ee5dc79e82f5a5c3b4323a2a641827db3e04"
integrity sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==
esbuild@^0.20.1:
version "0.20.2"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1"
integrity sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==
optionalDependencies:
"@esbuild/aix-ppc64" "0.19.12"
"@esbuild/android-arm" "0.19.12"
"@esbuild/android-arm64" "0.19.12"
"@esbuild/android-x64" "0.19.12"
"@esbuild/darwin-arm64" "0.19.12"
"@esbuild/darwin-x64" "0.19.12"
"@esbuild/freebsd-arm64" "0.19.12"
"@esbuild/freebsd-x64" "0.19.12"
"@esbuild/linux-arm" "0.19.12"
"@esbuild/linux-arm64" "0.19.12"
"@esbuild/linux-ia32" "0.19.12"
"@esbuild/linux-loong64" "0.19.12"
"@esbuild/linux-mips64el" "0.19.12"
"@esbuild/linux-ppc64" "0.19.12"
"@esbuild/linux-riscv64" "0.19.12"
"@esbuild/linux-s390x" "0.19.12"
"@esbuild/linux-x64" "0.19.12"
"@esbuild/netbsd-x64" "0.19.12"
"@esbuild/openbsd-x64" "0.19.12"
"@esbuild/sunos-x64" "0.19.12"
"@esbuild/win32-arm64" "0.19.12"
"@esbuild/win32-ia32" "0.19.12"
"@esbuild/win32-x64" "0.19.12"
"@esbuild/aix-ppc64" "0.20.2"
"@esbuild/android-arm" "0.20.2"
"@esbuild/android-arm64" "0.20.2"
"@esbuild/android-x64" "0.20.2"
"@esbuild/darwin-arm64" "0.20.2"
"@esbuild/darwin-x64" "0.20.2"
"@esbuild/freebsd-arm64" "0.20.2"
"@esbuild/freebsd-x64" "0.20.2"
"@esbuild/linux-arm" "0.20.2"
"@esbuild/linux-arm64" "0.20.2"
"@esbuild/linux-ia32" "0.20.2"
"@esbuild/linux-loong64" "0.20.2"
"@esbuild/linux-mips64el" "0.20.2"
"@esbuild/linux-ppc64" "0.20.2"
"@esbuild/linux-riscv64" "0.20.2"
"@esbuild/linux-s390x" "0.20.2"
"@esbuild/linux-x64" "0.20.2"
"@esbuild/netbsd-x64" "0.20.2"
"@esbuild/openbsd-x64" "0.20.2"
"@esbuild/sunos-x64" "0.20.2"
"@esbuild/win32-arm64" "0.20.2"
"@esbuild/win32-ia32" "0.20.2"
"@esbuild/win32-x64" "0.20.2"
escalade@^3.1.1:
version "3.1.2"
@ -4233,6 +4257,11 @@ esutils@^2.0.2:
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
eventemitter3@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4"
integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
events@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
@ -5629,14 +5658,14 @@ polished@4:
dependencies:
"@babel/runtime" "^7.17.8"
postcss@^8.4.32:
version "8.4.34"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.34.tgz#563276e86b4ff20dfa5eed0d394d4c53853b2051"
integrity sha512-4eLTO36woPSocqZ1zIrFD2K1v6wH7pY1uBh0JIM2KKfrVtGvPFiAku6aNOP0W1Wr9qwnaCsF0Z+CrVnryB2A8Q==
postcss@^8.4.38:
version "8.4.38"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e"
integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==
dependencies:
nanoid "^3.3.7"
picocolors "^1.0.0"
source-map-js "^1.0.2"
source-map-js "^1.2.0"
potpack@^1.0.1:
version "1.0.2"
@ -6147,26 +6176,28 @@ rollup@^2.43.1:
optionalDependencies:
fsevents "~2.3.2"
rollup@^4.2.0:
version "4.9.6"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.9.6.tgz#4515facb0318ecca254a2ee1315e22e09efc50a0"
integrity sha512-05lzkCS2uASX0CiLFybYfVkwNbKZG5NFQ6Go0VWyogFTXXbR039UVsegViTntkk4OglHBdF54ccApXRRuXRbsg==
rollup@^4.13.0:
version "4.14.1"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.14.1.tgz#228d5159c3f4d8745bd24819d734bc6c6ca87c09"
integrity sha512-4LnHSdd3QK2pa1J6dFbfm1HN0D7vSK/ZuZTsdyUAlA6Rr1yTouUTL13HaDOGJVgby461AhrNGBS7sCGXXtT+SA==
dependencies:
"@types/estree" "1.0.5"
optionalDependencies:
"@rollup/rollup-android-arm-eabi" "4.9.6"
"@rollup/rollup-android-arm64" "4.9.6"
"@rollup/rollup-darwin-arm64" "4.9.6"
"@rollup/rollup-darwin-x64" "4.9.6"
"@rollup/rollup-linux-arm-gnueabihf" "4.9.6"
"@rollup/rollup-linux-arm64-gnu" "4.9.6"
"@rollup/rollup-linux-arm64-musl" "4.9.6"
"@rollup/rollup-linux-riscv64-gnu" "4.9.6"
"@rollup/rollup-linux-x64-gnu" "4.9.6"
"@rollup/rollup-linux-x64-musl" "4.9.6"
"@rollup/rollup-win32-arm64-msvc" "4.9.6"
"@rollup/rollup-win32-ia32-msvc" "4.9.6"
"@rollup/rollup-win32-x64-msvc" "4.9.6"
"@rollup/rollup-android-arm-eabi" "4.14.1"
"@rollup/rollup-android-arm64" "4.14.1"
"@rollup/rollup-darwin-arm64" "4.14.1"
"@rollup/rollup-darwin-x64" "4.14.1"
"@rollup/rollup-linux-arm-gnueabihf" "4.14.1"
"@rollup/rollup-linux-arm64-gnu" "4.14.1"
"@rollup/rollup-linux-arm64-musl" "4.14.1"
"@rollup/rollup-linux-powerpc64le-gnu" "4.14.1"
"@rollup/rollup-linux-riscv64-gnu" "4.14.1"
"@rollup/rollup-linux-s390x-gnu" "4.14.1"
"@rollup/rollup-linux-x64-gnu" "4.14.1"
"@rollup/rollup-linux-x64-musl" "4.14.1"
"@rollup/rollup-win32-arm64-msvc" "4.14.1"
"@rollup/rollup-win32-ia32-msvc" "4.14.1"
"@rollup/rollup-win32-x64-msvc" "4.14.1"
fsevents "~2.3.2"
rtl-css-js@^1.16.1:
@ -6328,10 +6359,10 @@ smtp-address-parser@1.0.10:
dependencies:
nearley "^2.20.1"
source-map-js@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
source-map-js@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"
integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==
source-map-support@~0.5.20:
version "0.5.21"
@ -6897,7 +6928,7 @@ use-sync-external-store@1.2.0:
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
uuid@^9.0.0:
uuid@^9.0.0, uuid@^9.0.1:
version "9.0.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"
integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
@ -6915,10 +6946,10 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
vite-plugin-pwa@^0.17.4:
version "0.17.5"
resolved "https://registry.yarnpkg.com/vite-plugin-pwa/-/vite-plugin-pwa-0.17.5.tgz#e821c14ac776742e2921fea9833dd2664ad2969b"
integrity sha512-UxRNPiJBzh4tqU/vc8G2TxmrUTzT6BqvSzhszLk62uKsf+npXdvLxGDz9C675f4BJi6MbD2tPnJhi5txlMzxbQ==
vite-plugin-pwa@^0.19.8:
version "0.19.8"
resolved "https://registry.yarnpkg.com/vite-plugin-pwa/-/vite-plugin-pwa-0.19.8.tgz#f7be200a4426207358aef807b4a6e1ecbc14d345"
integrity sha512-e1oK0dfhzhDhY3VBuML6c0h8Xfx6EkOVYqolj7g+u8eRfdauZe5RLteCIA/c5gH0CBQ0CNFAuv/AFTx4Z7IXTw==
dependencies:
debug "^4.3.4"
fast-glob "^3.3.2"
@ -6926,14 +6957,14 @@ vite-plugin-pwa@^0.17.4:
workbox-build "^7.0.0"
workbox-window "^7.0.0"
vite@^5.0.10:
version "5.0.12"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.0.12.tgz#8a2ffd4da36c132aec4adafe05d7adde38333c47"
integrity sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==
vite@^5.2.8:
version "5.2.8"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.8.tgz#a99e09939f1a502992381395ce93efa40a2844aa"
integrity sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==
dependencies:
esbuild "^0.19.3"
postcss "^8.4.32"
rollup "^4.2.0"
esbuild "^0.20.1"
postcss "^8.4.38"
rollup "^4.13.0"
optionalDependencies:
fsevents "~2.3.3"