- {node.node_name || 'Unnamed Node'}
+ {node.nodeName || 'Unnamed Node'}
{isRepeater && (
@@ -76,9 +62,9 @@ export default function NodeCard({ node, className = "", showTopicInfo = true }:
)}
- Last seen: {moment.utc(node.last_seen).local().fromNow()}
+ Last seen: {moment.utc(node.lastSeen).local().fromNow()}
- {formatPublicKey(node.public_key)}
+ {formatPublicKey(node.publicKey)}
diff --git a/meshexplorer/src/components/NodeLinkWithHover.tsx b/meshexplorer/src/components/NodeLinkWithHover.tsx
index b13034e..6b6af58 100644
--- a/meshexplorer/src/components/NodeLinkWithHover.tsx
+++ b/meshexplorer/src/components/NodeLinkWithHover.tsx
@@ -51,7 +51,7 @@ export default function NodeLinkWithHover({
if (isSearchLoading) return "#";
// If exactly one result found, link directly to node
- if (foundNode) return `/meshcore/node/${foundNode.public_key}`;
+ if (foundNode) return `/meshcore/node/${foundNode.publicKey}`;
// If no results or multiple results, link to search page
const searchUrl = `/search?q=${encodeURIComponent(nodeName)}`;
@@ -83,7 +83,7 @@ export default function NodeLinkWithHover({
// Calculate navigation URL directly here since linkHref might still be "#"
const navigationUrl = foundNode
- ? `/meshcore/node/${foundNode.public_key}`
+ ? `/meshcore/node/${foundNode.publicKey}`
: (() => {
const searchUrl = `/search?q=${encodeURIComponent(nodeName)}`;
const params = [];
diff --git a/meshexplorer/src/components/PathVisualization.tsx b/meshexplorer/src/components/PathVisualization.tsx
index e0a1b97..0a6be5a 100644
--- a/meshexplorer/src/components/PathVisualization.tsx
+++ b/meshexplorer/src/components/PathVisualization.tsx
@@ -8,7 +8,6 @@ import { ArrowsPointingOutIcon, ArrowsPointingInIcon } from "@heroicons/react/24
import { ExternalLink } from "lucide-react";
import NodeLinkWithHover from "./NodeLinkWithHover";
import { useMeshcoreSearches } from "@/hooks/useMeshcoreSearch";
-import type { MeshcoreSearchResult } from "@/hooks/useMeshcoreSearch";
import { useConfigWithRegion } from "@/hooks/useConfigWithRegion";
import {
PathData,
@@ -91,10 +90,10 @@ export default function PathVisualization({
const searchResult = searchResults[index];
if (searchResult?.data?.results) {
const matchingNodes = searchResult.data.results
- .filter(result => result.public_key.toLowerCase().startsWith(prefix.toLowerCase()) && result.node_name)
+ .filter(result => result.publicKey.toLowerCase().startsWith(prefix.toLowerCase()) && result.nodeName)
.map(result => ({
- name: result.node_name,
- publicKey: result.public_key
+ name: result.nodeName,
+ publicKey: result.publicKey
}))
.filter(node => node.name.length > 0);
diff --git a/meshexplorer/src/components/SearchResults.tsx b/meshexplorer/src/components/SearchResults.tsx
index 69ae5e2..1fb7e2b 100644
--- a/meshexplorer/src/components/SearchResults.tsx
+++ b/meshexplorer/src/components/SearchResults.tsx
@@ -1,11 +1,11 @@
"use client";
-import { MeshcoreSearchResult } from '@/hooks/useMeshcoreSearch';
+import type { SearchResult } from '@/gen/meshexplorer/v1/node_pb';
import { WifiIcon, MagnifyingGlassIcon } from '@heroicons/react/24/outline';
import NodeCard from '@/components/NodeCard';
interface SearchResultsProps {
- results: MeshcoreSearchResult[];
+ results: SearchResult[];
isLoading: boolean;
error: Error | null;
query: string;
@@ -84,7 +84,7 @@ export default function SearchResults({ results, isLoading, error, query, total
{results.map((node) => (
-
+
))}
diff --git a/meshexplorer/src/hooks/useAllNeighbors.ts b/meshexplorer/src/hooks/useAllNeighbors.ts
deleted file mode 100644
index eaafaf5..0000000
--- a/meshexplorer/src/hooks/useAllNeighbors.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import { useQuery } from '@connectrpc/connect-query';
-import { NeighborsService } from '@/gen/meshexplorer/v1/neighbors_pb';
-
-export interface AllNeighborsConnection {
- source_node: string;
- target_node: string;
- connection_type: string;
- packet_count: number;
- source_name: string;
- source_latitude: number;
- source_longitude: number;
- source_has_location: number;
- target_name: string;
- target_latitude: number;
- target_longitude: number;
- target_has_location: number;
-}
-
-interface UseAllNeighborsParams {
- minLat?: number | null;
- maxLat?: number | null;
- minLng?: number | null;
- maxLng?: number | null;
- nodeTypes?: string[];
- lastSeen?: number | null;
- region?: string;
- enabled?: boolean;
-}
-
-export function useAllNeighbors({
- minLat,
- maxLat,
- minLng,
- maxLng,
- nodeTypes,
- lastSeen,
- region,
- enabled = true,
-}: UseAllNeighborsParams) {
- return useQuery(
- NeighborsService.method.getAllNeighbors,
- {
- minLat: minLat ?? undefined,
- maxLat: maxLat ?? undefined,
- minLng: minLng ?? undefined,
- maxLng: maxLng ?? undefined,
- nodeTypes: nodeTypes ?? [],
- lastSeen: lastSeen ?? undefined,
- region,
- },
- {
- select: (res): AllNeighborsConnection[] =>
- res.neighbors.map((n) => ({
- source_node: n.sourceNode,
- target_node: n.targetNode,
- connection_type: n.connectionType,
- packet_count: n.packetCount,
- source_name: n.sourceName,
- source_latitude: n.sourceLatitude,
- source_longitude: n.sourceLongitude,
- source_has_location: n.sourceHasLocation,
- target_name: n.targetName,
- target_latitude: n.targetLatitude,
- target_longitude: n.targetLongitude,
- target_has_location: n.targetHasLocation,
- })),
- enabled,
- staleTime: 5 * 60 * 1000, // 5 minutes
- gcTime: 15 * 60 * 1000, // 15 minutes
- },
- );
-}
diff --git a/meshexplorer/src/hooks/useChatMessages.ts b/meshexplorer/src/hooks/useChatMessages.ts
index a539c1a..28e0068 100644
--- a/meshexplorer/src/hooks/useChatMessages.ts
+++ b/meshexplorer/src/hooks/useChatMessages.ts
@@ -4,8 +4,7 @@ import { useInfiniteQuery, useQueryClient } from '@tanstack/react-query';
import { useEffect, useMemo } from 'react';
import { Code, ConnectError } from '@connectrpc/connect';
import { chatClient } from '@/lib/connect/client';
-import type { ChatMessage as GenChatMessage } from '@/gen/meshexplorer/v1/chat_pb';
-import { ChatMessage } from '@/components/ChatMessageItem';
+import type { ChatMessage } from '@/gen/meshexplorer/v1/chat_pb';
interface ChatMessagesParams {
channelId?: string;
@@ -22,38 +21,13 @@ interface ChatMessagesPage {
const PAGE_SIZE = 20;
-// Maps the generated (camelCase) ChatMessage to the snake_case shape the chat
-// components consume. `origins`/`path_len` were never populated by the REST API
-// and are unused by the renderer, so they're intentionally omitted.
-function toChatMessage(m: GenChatMessage): ChatMessage {
- return {
- message_id: m.messageId,
- ingest_timestamp: m.ingestTimestamp,
- mesh_timestamp: m.meshTimestamp,
- channel_hash: m.channelHash,
- mac: m.mac,
- encrypted_message: m.encryptedMessage,
- message_count: m.messageCount,
- origin_path_info: m.originPathInfo.map(
- (o) =>
- [o.origin, o.originPubkey, o.path, o.broker, o.topic] as [
- string,
- string,
- string,
- string,
- string,
- ],
- ),
- } as ChatMessage;
-}
-
// Inserts a single streamed message into the infinite-query cache, de-duping by
-// message_id, keeping newest-first order, and re-paginating into PAGE_SIZE pages.
+// messageId, keeping newest-first order, and re-paginating into PAGE_SIZE pages.
function mergeStreamedMessage(oldData: any, newMessage: ChatMessage) {
if (!oldData?.pages?.[0]) return oldData;
const all = oldData.pages.flatMap((p: ChatMessagesPage) => p.messages) as ChatMessage[];
- const existingIndex = all.findIndex((m) => m.message_id === newMessage.message_id);
+ const existingIndex = all.findIndex((m) => m.messageId === newMessage.messageId);
let merged: ChatMessage[];
if (existingIndex !== -1) {
@@ -64,7 +38,7 @@ function mergeStreamedMessage(oldData: any, newMessage: ChatMessage) {
}
merged.sort(
- (a, b) => new Date(b.ingest_timestamp).getTime() - new Date(a.ingest_timestamp).getTime(),
+ (a, b) => new Date(b.ingestTimestamp).getTime() - new Date(a.ingestTimestamp).getTime(),
);
const pages = [];
@@ -111,13 +85,13 @@ export function useChatMessages({
{ signal },
);
- const messages = res.messages.map(toChatMessage);
+ const messages = res.messages;
return {
messages,
hasMore: messages.length === PAGE_SIZE,
oldestTimestamp:
- messages.length > 0 ? messages[messages.length - 1].ingest_timestamp : undefined,
+ messages.length > 0 ? messages[messages.length - 1].ingestTimestamp : undefined,
};
},
getNextPageParam: (lastPage) => {
@@ -152,9 +126,10 @@ export function useChatMessages({
{ signal: controller.signal },
);
- for await (const genMsg of stream) {
+ for await (const resp of stream) {
if (cancelled) break;
- const msg = toChatMessage(genMsg);
+ if (!resp.message) continue;
+ const msg = resp.message;
queryClient.setQueryData(baseQueryKey, (oldData: any) =>
mergeStreamedMessage(oldData, msg),
);
diff --git a/meshexplorer/src/hooks/useMeshcoreSearch.ts b/meshexplorer/src/hooks/useMeshcoreSearch.ts
index df7f1b0..7477bc5 100644
--- a/meshexplorer/src/hooks/useMeshcoreSearch.ts
+++ b/meshexplorer/src/hooks/useMeshcoreSearch.ts
@@ -4,43 +4,8 @@ import { nodeClient } from '@/lib/connect/client';
import type { SearchResult } from '@/gen/meshexplorer/v1/node_pb';
import { useMemo } from 'react';
-export interface MeshcoreSearchResult {
- public_key: string;
- node_name: string;
- latitude: number | null;
- longitude: number | null;
- has_location: number;
- is_repeater: number;
- is_chat_node: number;
- is_room_server: number;
- has_name: number;
- first_heard: string;
- last_seen: string;
- broker: string;
- topic: string;
-}
-
-// Maps a generated (camelCase) SearchResult to the snake_case shape consumers use.
-function toSearchResult(r: SearchResult): MeshcoreSearchResult {
- return {
- public_key: r.publicKey,
- node_name: r.nodeName,
- latitude: r.latitude ?? null,
- longitude: r.longitude ?? null,
- has_location: r.hasLocation,
- is_repeater: r.isRepeater,
- is_chat_node: r.isChatNode,
- is_room_server: r.isRoomServer,
- has_name: r.hasName,
- first_heard: r.firstHeard,
- last_seen: r.lastSeen,
- broker: r.broker,
- topic: r.topic,
- };
-}
-
export interface MeshcoreSearchResponse {
- results: MeshcoreSearchResult[];
+ results: SearchResult[];
total: number;
}
@@ -88,12 +53,12 @@ const searchBatcher = create({
// Return results with batch context for resolver (array-of-arrays, one per query)
return {
- results: response.results.map((list) => list.results.map(toSearchResult)),
+ results: response.results.map((list) => list.results),
queries: queries
};
},
-
- resolver: (batchData: {results: MeshcoreSearchResult[][], queries: SearchQuery[]}, query: SearchQuery) => {
+
+ resolver: (batchData: {results: SearchResult[][], queries: SearchQuery[]}, query: SearchQuery) => {
const index = batchData.queries.findIndex(q => JSON.stringify(q) === JSON.stringify(query));
return batchData.results[index] || [];
},
@@ -146,7 +111,7 @@ export function useMeshcoreSearch({
signal?.addEventListener('abort', handleAbort);
try {
- const queryResults = await searchBatcher.fetch(searchQuery) as MeshcoreSearchResult[] || [];
+ const queryResults = await searchBatcher.fetch(searchQuery) as SearchResult[] || [];
return {
results: queryResults,
total: queryResults.length
@@ -214,7 +179,7 @@ export function useMeshcoreSearches({ searches }: UseMeshcoreSearchesParams) {
signal?.addEventListener('abort', handleAbort);
try {
- const queryResults = await searchBatcher.fetch(searchQuery) as MeshcoreSearchResult[] || [];
+ const queryResults = await searchBatcher.fetch(searchQuery) as SearchResult[] || [];
return {
results: queryResults,
total: queryResults.length
diff --git a/meshexplorer/src/hooks/useNeighbors.ts b/meshexplorer/src/hooks/useNeighbors.ts
index cedb46d..1612c4e 100644
--- a/meshexplorer/src/hooks/useNeighbors.ts
+++ b/meshexplorer/src/hooks/useNeighbors.ts
@@ -1,19 +1,6 @@
import { useQuery } from '@connectrpc/connect-query';
import { NodeService } from '@/gen/meshexplorer/v1/node_pb';
-export interface Neighbor {
- public_key: string;
- node_name: string;
- latitude: number | null;
- longitude: number | null;
- has_location: number;
- is_repeater: number;
- is_chat_node: number;
- is_room_server: number;
- has_name: number;
- directions: string[];
-}
-
interface UseNeighborsParams {
nodeId: string | null;
lastSeen?: number | null;
@@ -28,19 +15,8 @@ export function useNeighbors({ nodeId, lastSeen, enabled = true }: UseNeighborsP
lastSeen: lastSeen ?? undefined,
},
{
- select: (res): Neighbor[] =>
- res.neighbors.map((n) => ({
- public_key: n.publicKey,
- node_name: n.nodeName,
- latitude: n.latitude ?? null,
- longitude: n.longitude ?? null,
- has_location: n.hasLocation,
- is_repeater: n.isRepeater,
- is_chat_node: n.isChatNode,
- is_room_server: n.isRoomServer,
- has_name: n.hasName,
- directions: n.directions,
- })),
+ // Unwrap the response to the generated Neighbor[] (no field mapping).
+ select: (res) => res.neighbors,
enabled: enabled && !!nodeId,
staleTime: 15 * 60 * 1000, // 15 minutes
gcTime: 15 * 60 * 1000, // 15 minutes
diff --git a/meshexplorer/src/hooks/useNodeData.ts b/meshexplorer/src/hooks/useNodeData.ts
index c714afc..6d3dc60 100644
--- a/meshexplorer/src/hooks/useNodeData.ts
+++ b/meshexplorer/src/hooks/useNodeData.ts
@@ -1,71 +1,6 @@
-import { useQuery } from '@tanstack/react-query';
+import { useQuery } from '@connectrpc/connect-query';
import { Code, ConnectError } from '@connectrpc/connect';
-import { nodeClient } from '@/lib/connect/client';
-import type { GetNodeResponse } from '@/gen/meshexplorer/v1/node_pb';
-
-export interface NodeInfo {
- public_key: string;
- node_name: string;
- latitude: number | null;
- longitude: number | null;
- has_location: number;
- is_repeater: number;
- is_chat_node: number;
- is_room_server: number;
- has_name: number;
- broker: string | null;
- topic: string | null;
- first_seen: string;
- last_seen: string;
-}
-
-export interface Advert {
- group_id: number;
- origin_path_pubkey_tuples: Array<[string, string, string]>; // Array of [origin, path, origin_pubkey] tuples
- advert_count: number;
- earliest_timestamp: string;
- latest_timestamp: string;
- latitude: number | null;
- longitude: number | null;
- is_repeater: number;
- is_chat_node: number;
- is_room_server: number;
- has_location: number;
- packet_hash: string;
-}
-
-export interface LocationHistory {
- mesh_timestamp: string;
- latitude: number;
- longitude: number;
-}
-
-export interface MqttTopic {
- topic: string;
- broker: string;
- last_packet_time: string;
- is_recent: boolean;
-}
-
-export interface MqttInfo {
- is_uplinked: boolean;
- has_packets: boolean;
- topics: MqttTopic[];
-}
-
-export interface NodeData {
- node: NodeInfo;
- recentAdverts: Advert[];
- locationHistory: LocationHistory[];
- mqtt: MqttInfo;
- region: string | null;
-}
-
-export interface NodeError {
- error: string;
- code: string;
- publicKey?: string;
-}
+import { NodeService } from '@/gen/meshexplorer/v1/node_pb';
interface UseNodeDataParams {
publicKey: string | null;
@@ -73,107 +8,37 @@ interface UseNodeDataParams {
enabled?: boolean;
}
-// Maps the generated (camelCase) GetNodeResponse to the snake_case NodeData
-// shape the page components already consume.
-function toNodeData(res: GetNodeResponse): NodeData {
- const node = res.node!;
- return {
- node: {
- public_key: node.publicKey,
- node_name: node.nodeName,
- latitude: node.latitude ?? null,
- longitude: node.longitude ?? null,
- has_location: node.hasLocation,
- is_repeater: node.isRepeater,
- is_chat_node: node.isChatNode,
- is_room_server: node.isRoomServer,
- has_name: node.hasName,
- broker: node.broker ?? null,
- topic: node.topic ?? null,
- first_seen: node.firstSeen,
- last_seen: node.lastSeen,
- },
- recentAdverts: res.recentAdverts.map((a, index) => ({
- group_id: index,
- origin_path_pubkey_tuples: a.originPathPubkeyTuples.map(
- (t) => [t.origin, t.path, t.originPubkey] as [string, string, string],
- ),
- advert_count: a.advertCount,
- earliest_timestamp: a.earliestTimestamp,
- latest_timestamp: a.latestTimestamp,
- latitude: a.latitude ?? null,
- longitude: a.longitude ?? null,
- is_repeater: a.isRepeater,
- is_chat_node: a.isChatNode,
- is_room_server: a.isRoomServer,
- has_location: a.hasLocation,
- packet_hash: a.packetHash,
- })),
- locationHistory: res.locationHistory.map((l) => ({
- mesh_timestamp: l.meshTimestamp,
- latitude: l.latitude,
- longitude: l.longitude,
- })),
- mqtt: {
- is_uplinked: res.mqtt?.isUplinked ?? false,
- has_packets: res.mqtt?.hasPackets ?? false,
- topics: (res.mqtt?.topics ?? []).map((t) => ({
- topic: t.topic,
- broker: t.broker,
- last_packet_time: t.lastPacketTime,
- is_recent: t.isRecent,
- })),
- },
- region: res.region ?? null,
- };
-}
-
-// Maps a ConnectError to the NodeError shape (with HTTP-like status) the
-// node page uses to pick an error icon/title and drive retry behavior.
-function toNodeError(err: unknown): NodeError & { status: number } {
- if (err instanceof ConnectError) {
- switch (err.code) {
- case Code.NotFound:
- return { error: err.message, code: 'NODE_NOT_FOUND', status: 404 };
- case Code.InvalidArgument:
- return { error: err.message, code: 'INVALID_PUBLIC_KEY', status: 400 };
- case Code.Unavailable:
- return { error: err.message, code: 'DATABASE_ERROR', status: 503 };
- default:
- return { error: err.message, code: 'INTERNAL_ERROR', status: 500 };
- }
+// Maps a ConnectError to the string code the node page uses to pick an
+// error icon/title/description. (Error-code mapping, not a proto-type mirror.)
+export function nodeErrorCode(err: ConnectError | null): string | null {
+ if (!err) return null;
+ switch (err.code) {
+ case Code.NotFound:
+ return 'NODE_NOT_FOUND';
+ case Code.InvalidArgument:
+ return 'INVALID_PUBLIC_KEY';
+ case Code.Unavailable:
+ return 'DATABASE_ERROR';
+ default:
+ return 'INTERNAL_ERROR';
}
- return { error: 'An unexpected error occurred', code: 'UNKNOWN_ERROR', status: 500 };
}
export function useNodeData({ publicKey, limit = 50, enabled = true }: UseNodeDataParams) {
- return useQuery
({
- queryKey: ['node-data', publicKey, limit],
- queryFn: async (): Promise => {
- if (!publicKey) {
- throw { error: 'Public key is required', code: 'MISSING_PUBLIC_KEY', status: 400 } as NodeError & {
- status: number;
- };
- }
-
- try {
- const res = await nodeClient.getNode({ publicKey, limit });
- return toNodeData(res);
- } catch (err) {
- throw toNodeError(err);
- }
+ return useQuery(
+ NodeService.method.getNode,
+ { publicKey: publicKey ?? '', limit },
+ {
+ enabled: enabled && !!publicKey,
+ staleTime: 15 * 60 * 1000, // 15 minutes
+ gcTime: 15 * 60 * 1000, // 15 minutes
+ retry: (failureCount, error) => {
+ // Don't retry client errors (bad key / not found).
+ if (error.code === Code.NotFound || error.code === Code.InvalidArgument) {
+ return false;
+ }
+ return failureCount < 1;
+ },
},
- enabled: enabled && !!publicKey,
- staleTime: 15 * 60 * 1000, // 15 minutes
- gcTime: 15 * 60 * 1000, // 15 minutes
- retry: (failureCount, error) => {
- // Don't retry for client errors (4xx)
- const status = error?.status;
- if (status && status >= 400 && status < 500) {
- return false;
- }
- // Retry up to 1 time for server errors
- return failureCount < 1;
- },
- });
+ );
}
diff --git a/meshexplorer/src/hooks/useStats.ts b/meshexplorer/src/hooks/useStats.ts
index a05f5de..6dd8759 100644
--- a/meshexplorer/src/hooks/useStats.ts
+++ b/meshexplorer/src/hooks/useStats.ts
@@ -2,41 +2,6 @@ import React from "react";
import { useQuery } from "@connectrpc/connect-query";
import { StatsService } from "@/gen/meshexplorer/v1/stats_pb";
-interface TotalNodesResponse {
- total_nodes: number;
-}
-
-interface NodesOverTimeRow {
- day: string;
- cumulative_unique_nodes: number;
- nodes_with_location: number;
- nodes_without_location: number;
- repeaters: number;
- room_servers: number;
-}
-
-interface NodesOverTimeResponse {
- data: NodesOverTimeRow[];
-}
-
-interface PopularChannelRow {
- channel_hash: string;
- message_count: number;
-}
-
-interface PopularChannelsResponse {
- data: PopularChannelRow[];
-}
-
-interface RepeaterPrefixRow {
- prefix: string;
- node_names: string[];
-}
-
-interface RepeaterPrefixesResponse {
- data: RepeaterPrefixRow[];
-}
-
const STALE_TIME = 5 * 60 * 1000; // 5 minutes
const GC_TIME = 10 * 60 * 1000; // 10 minutes
@@ -44,12 +9,7 @@ export function useTotalNodes(region?: string) {
return useQuery(
StatsService.method.getTotalNodes,
{ region },
- {
- select: (res): TotalNodesResponse => ({ total_nodes: res.totalNodes }),
- staleTime: STALE_TIME,
- gcTime: GC_TIME,
- retry: 2,
- },
+ { staleTime: STALE_TIME, gcTime: GC_TIME, retry: 2 },
);
}
@@ -57,21 +17,7 @@ export function useNodesOverTime(region?: string) {
return useQuery(
StatsService.method.getNodesOverTime,
{ region },
- {
- select: (res): NodesOverTimeResponse => ({
- data: res.data.map((r) => ({
- day: r.day,
- cumulative_unique_nodes: r.cumulativeUniqueNodes,
- nodes_with_location: r.nodesWithLocation,
- nodes_without_location: r.nodesWithoutLocation,
- repeaters: r.repeaters,
- room_servers: r.roomServers,
- })),
- }),
- staleTime: STALE_TIME,
- gcTime: GC_TIME,
- retry: 2,
- },
+ { staleTime: STALE_TIME, gcTime: GC_TIME, retry: 2 },
);
}
@@ -79,17 +25,7 @@ export function usePopularChannels(region?: string) {
return useQuery(
StatsService.method.getPopularChannels,
{ region },
- {
- select: (res): PopularChannelsResponse => ({
- data: res.data.map((r) => ({
- channel_hash: r.channelHash,
- message_count: r.messageCount,
- })),
- }),
- staleTime: STALE_TIME,
- gcTime: GC_TIME,
- retry: 2,
- },
+ { staleTime: STALE_TIME, gcTime: GC_TIME, retry: 2 },
);
}
@@ -97,17 +33,7 @@ export function useRepeaterPrefixes(region?: string) {
return useQuery(
StatsService.method.getRepeaterPrefixes,
{ region },
- {
- select: (res): RepeaterPrefixesResponse => ({
- data: res.data.map((r) => ({
- prefix: r.prefix,
- node_names: r.nodeNames,
- })),
- }),
- staleTime: STALE_TIME,
- gcTime: GC_TIME,
- retry: 2,
- },
+ { staleTime: STALE_TIME, gcTime: GC_TIME, retry: 2 },
);
}
@@ -124,10 +50,10 @@ export function useUnusedPrefixes(region?: string) {
}
// Get used prefixes from the API response
- const usedPrefixes = new Set(repeaterPrefixesData.data.map(row => row.prefix));
+ const usedPrefixes = new Set(repeaterPrefixesData.data.map((row) => row.prefix));
// Find unused prefixes
- return allPrefixes.filter(prefix => !usedPrefixes.has(prefix));
+ return allPrefixes.filter((prefix) => !usedPrefixes.has(prefix));
}, [repeaterPrefixesData?.data]);
return {
diff --git a/meshexplorer/src/server/connect/chat.ts b/meshexplorer/src/server/connect/chat.ts
index c4f96aa..09ac1f3 100644
--- a/meshexplorer/src/server/connect/chat.ts
+++ b/meshexplorer/src/server/connect/chat.ts
@@ -122,7 +122,7 @@ export const chatServiceImpl: ServiceImpl = {
for await (const result of streamer(params)) {
const row = result.row;
const decrypted = req.decrypt ? await decryptRow(row, keys) : null;
- yield toChatMessage(row, decrypted);
+ yield { message: toChatMessage(row, decrypted) };
}
},
};
diff --git a/meshexplorer/src/server/connect/packets.ts b/meshexplorer/src/server/connect/packets.ts
index 0bccde7..bc1af84 100644
--- a/meshexplorer/src/server/connect/packets.ts
+++ b/meshexplorer/src/server/connect/packets.ts
@@ -43,18 +43,20 @@ export const packetsServiceImpl: ServiceImpl = {
for await (const result of streamer(params)) {
const row = result.row;
yield {
- ingestTimestamp: row.ingest_timestamp,
- meshTimestamp: row.mesh_timestamp,
- broker: row.broker,
- topic: row.topic,
- packet: row.packet,
- pathLen: num(row.path_len),
- path: row.path,
- routeType: num(row.route_type),
- payloadType: num(row.payload_type),
- payloadVersion: num(row.payload_version),
- header: num(row.header),
- originPubkey: row.origin_pubkey,
+ packet: {
+ ingestTimestamp: row.ingest_timestamp,
+ meshTimestamp: row.mesh_timestamp,
+ broker: row.broker,
+ topic: row.topic,
+ packet: row.packet,
+ pathLen: num(row.path_len),
+ path: row.path,
+ routeType: num(row.route_type),
+ payloadType: num(row.payload_type),
+ payloadVersion: num(row.payload_version),
+ header: num(row.header),
+ originPubkey: row.origin_pubkey,
+ },
};
}
},
diff --git a/meshexplorer/src/types/map.ts b/meshexplorer/src/types/map.ts
deleted file mode 100644
index 2ac685d..0000000
--- a/meshexplorer/src/types/map.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export type NodePosition = {
- node_id: string;
- latitude: number;
- longitude: number;
- altitude?: number;
- last_seen?: string;
- first_seen?: string;
- type?: string;
- short_name?: string;
- name?: string | null;
-};