import { createEventSignal } from '@solid-primitives/event-listener' import { createReconnectingWS } from '@solid-primitives/websocket' import { ColumnDef, createSolidTable, flexRender, getCoreRowModel, } from '@tanstack/solid-table' import byteSize from 'byte-size' import { isIPv6 } from 'is-ip' import { For, createSignal } from 'solid-js' import { wsEndpointURL } from '~/signals' import type { Connection } from '../types' export const Connections = () => { const [search, setSearch] = createSignal('') const ws = createReconnectingWS(`${wsEndpointURL()}/connections`) const messageEvent = createEventSignal<{ message: WebSocketEventMap['message'] }>(ws, 'message') const connections = () => { const data = messageEvent()?.data if (!data) { return [] } return ( JSON.parse(data) as { connections: Connection[] } ).connections.slice(-100) } const columns: ColumnDef[] = [ { accessorKey: 'ID', accessorFn: (row) => row.id, }, { accessorKey: 'Network', accessorFn: (row) => row.metadata.network, }, { accessorKey: 'Download', accessorFn: (row) => byteSize(row.download), }, { accessorKey: 'Upload', accessorFn: (row) => byteSize(row.upload), }, { accessorKey: 'Rule', accessorFn: (row) => row.rule, }, { accessorKey: 'Chains', accessorFn: (row) => row.chains.join(' -> '), }, { accessorKey: 'Remote Destination', accessorFn: (row) => row.metadata.remoteDestination, }, { accessorKey: 'Host', accessorFn: (row) => row.metadata.host, }, { accessorKey: 'DNS Mode', accessorFn: (row) => row.metadata.dnsMode, }, { accessorKey: 'Type', accessorFn: (row) => row.metadata.type, }, { accessorKey: 'Source', accessorFn: (row) => isIPv6(row.metadata.sourceIP) ? `[${row.metadata.sourceIP}]:${row.metadata.sourcePort}` : `${row.metadata.sourceIP}:${row.metadata.sourcePort}`, }, { accessorKey: 'Destination', accessorFn: (row) => isIPv6(row.metadata.destinationIP) ? `[${row.metadata.destinationIP}]:${row.metadata.destinationPort}` : `${row.metadata.destinationIP}:${row.metadata.destinationPort}`, }, ] const table = createSolidTable({ get data() { return search() ? connections().filter((connection) => Object.values(connection).some((conn) => JSON.stringify(conn) .toLowerCase() .includes(search().toLowerCase()), ), ) : connections() }, columns, getCoreRowModel: getCoreRowModel(), }) return (
setSearch(e.target.value)} />
{(headerGroup) => ( {(header) => ( )} )} {(row) => ( {(cell) => ( )} )}
{header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext(), )}
{flexRender( cell.column.columnDef.cell, cell.getContext(), )}
) }