diff --git a/meshexplorer/src/server/connect/mappers.ts b/meshexplorer/src/server/connect/mappers.ts index 1a4d3f5..b823fe2 100644 --- a/meshexplorer/src/server/connect/mappers.ts +++ b/meshexplorer/src/server/connect/mappers.ts @@ -24,6 +24,12 @@ export function num(v: unknown): number { return Number(v ?? 0); } +// ClickHouse returns UInt8 boolean-ish columns (e.g. is_recent) as JSON numbers +// (1/0). Coerce before feeding a proto `bool` field. +export function bool(v: unknown): boolean { + return v === true || v === 1 || v === "1"; +} + /** Maps a ClickHouse neighbor-edge row to the NeighborEdge proto init shape. */ export function toNeighborEdge(row: NeighborEdgeRow): MessageInitShape { return { diff --git a/meshexplorer/src/server/connect/node.ts b/meshexplorer/src/server/connect/node.ts index 7c112c4..8ae3d36 100644 --- a/meshexplorer/src/server/connect/node.ts +++ b/meshexplorer/src/server/connect/node.ts @@ -7,7 +7,7 @@ import { getMeshcoreNodeNeighbors, searchMeshcoreNodes, } from "@/lib/clickhouse/actions"; -import { num } from "./mappers"; +import { bool, num } from "./mappers"; interface SearchResultRow { public_key: string; @@ -112,13 +112,13 @@ export const nodeServiceImpl: ServiceImpl = { longitude: l.longitude, })), mqtt: { - isUplinked: nodeInfo.mqtt.is_uplinked, - hasPackets: nodeInfo.mqtt.has_packets, + isUplinked: bool(nodeInfo.mqtt.is_uplinked), + hasPackets: bool(nodeInfo.mqtt.has_packets), topics: nodeInfo.mqtt.topics.map((t) => ({ topic: t.topic, broker: t.broker, lastPacketTime: t.last_packet_time, - isRecent: t.is_recent, + isRecent: bool(t.is_recent), })), }, region: nodeInfo.region ?? undefined,