Coerce ClickHouse UInt8 booleans for proto bool fields

is_recent (and is_uplinked/has_packets) come back from ClickHouse as JSON
numbers (1/0); protobuf-es rejected them for the MqttTopic.is_recent bool
field ("expected boolean, got 1"). Add a bool() helper alongside num() and
apply it in the node handler.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alex Vanderpot
2026-06-14 17:44:21 -04:00
parent 637ee470c7
commit c6d688c931
2 changed files with 10 additions and 4 deletions
@@ -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<typeof NeighborEdgeSchema> {
return {
+4 -4
View File
@@ -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<typeof NodeService> = {
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,