diff --git a/src/mesh/mesh.service.spec.ts b/src/mesh/mesh.service.spec.ts index 40f08bc..967b694 100644 --- a/src/mesh/mesh.service.spec.ts +++ b/src/mesh/mesh.service.spec.ts @@ -594,6 +594,7 @@ describe('MeshService message history', () => { id: 1, dir: 'rx', from: KAMIL_NUM, + to: 42, // destination persisted on rx records (broadcast addr for broadcasts) text: 'ping', channel: 2, at: expect.any(Number), @@ -715,10 +716,9 @@ describe('MeshService opencode notifier', () => { // MeshService with a mocked OpencodeService wired in (structural cast — only notify() is used) function makeSvc(): MeshService { - return new MeshService( - undefined, - { notify: notifyMock } as unknown as OpencodeService, - ); + return new MeshService(undefined, { + notify: notifyMock, + } as unknown as OpencodeService); } it('notifies via the opencode service when an rx text lands on the notify channel (default 3)', async () => { @@ -1318,6 +1318,44 @@ describe('MeshService SQLite persistence', () => { } }); + it('persists the destination (to) of captured rx packets on poller tick', async () => { + const bridge = await startBridge(); + process.env.MESH_HOST = '127.0.0.1'; + process.env.MESH_PORT = String(bridge.port); + process.env.MESH_POLL_MS = '50'; + const db = new DatabaseSync(':memory:'); + initMessagesTable(db); + const svc = new MeshService(db); + try { + svc.onModuleInit(); + await waitFor( + () => bridge.sockets.length === 1 && svc.status().connected, + ); + + bridge.sockets[0].write(textPacketFrame(KAMIL_NUM, 42, 'ping', 3)); + + // the poller tick must pick it up — no flushHistory() call here + await waitFor( + () => + ( + db.prepare('SELECT COUNT(*) AS n FROM messages').get() as { + n: number; + } + ).n === 1, + ); + const row = db + .prepare('SELECT * FROM messages WHERE id = ?') + .get(1) as Record; + expect(row.dir).toBe('rx'); + expect(row.from_node).toBe(KAMIL_NUM); + expect(row.to_node).toBe(42); // rx rows carry the destination now (no schema change — to_node existed for tx) + } finally { + delete process.env.MESH_POLL_MS; + svc.onModuleDestroy(); + bridge.close(); + } + }); + it('reflects the ACK status update in the database after the next tick', async () => { const bridge = await startBridge(); process.env.MESH_HOST = '127.0.0.1'; diff --git a/src/mesh/mesh.service.ts b/src/mesh/mesh.service.ts index 17f533e..da3229d 100644 --- a/src/mesh/mesh.service.ts +++ b/src/mesh/mesh.service.ts @@ -37,7 +37,7 @@ export interface MessageRecord { dir: 'rx' | 'tx'; /** sender node num — rx only */ from?: number; - /** destination node num (broadcast addr for broadcasts) — tx only */ + /** destination node num (broadcast addr for broadcasts) — captured rx packets and all tx records */ to?: number; text: string; channel: number; @@ -626,6 +626,7 @@ export class MeshService implements OnModuleInit, OnModuleDestroy { id: pkt.id, dir: 'rx', from: pkt.from, + to: pkt.to, // destination (broadcast addr for broadcasts) — lets a later reply tell DM vs broadcast apart text, channel: pkt.channel ?? 0, at: Date.now(),