From f1bee546f6abf98fbe7a8fe700ad2e71cd95fdd0 Mon Sep 17 00:00:00 2001 From: Nora Date: Thu, 2 Jul 2026 09:01:53 -0600 Subject: [PATCH] feat(sp25): extend TailResource to include acks + ta1_acks The Acks page needs the same live-tail triplet (useTailStream + useMergedTail + TailStatusPill) that Claims/Remittances/Activity already use. The first step is widening the TailResource union so streamTail("acks") and streamTail("ta1_acks") are valid and the URL falls out as /api/acks/stream and /api/ta1-acks/stream. Two new tests assert the URL targets the new backend endpoints. --- src/lib/tail-stream.test.ts | 32 ++++++++++++++++++++++++++++++++ src/lib/tail-stream.ts | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/lib/tail-stream.test.ts b/src/lib/tail-stream.test.ts index 654b572..0f1424f 100644 --- a/src/lib/tail-stream.test.ts +++ b/src/lib/tail-stream.test.ts @@ -95,6 +95,38 @@ describe("streamTail", () => { ]); }); + it("test_targets_acks_stream_endpoint", async () => { + // SP25: the `acks` resource is part of TailResource; the URL must + // be /api/acks/stream so useTailStream("acks") can open it. + const driver = makeStream(); + const fetchMock = vi.fn().mockResolvedValue(driver.response); + vi.stubGlobal("fetch", fetchMock); + const gen = streamTail("acks"); + // Drive the generator one step so the fetch() call is reached + // before we close the stream. + await gen.next(); + driver.close(); + await gen.return(undefined); + expect(fetchMock).toHaveBeenCalledTimes(1); + const [calledUrl] = fetchMock.mock.calls[0] as [string]; + expect(calledUrl).toBe("/api/acks/stream"); + }); + + it("test_targets_ta1_acks_stream_endpoint", async () => { + // SP25: the `ta1_acks` resource is part of TailResource; the URL + // must be /api/ta1-acks/stream. + const driver = makeStream(); + const fetchMock = vi.fn().mockResolvedValue(driver.response); + vi.stubGlobal("fetch", fetchMock); + const gen = streamTail("ta1_acks"); + await gen.next(); + driver.close(); + await gen.return(undefined); + expect(fetchMock).toHaveBeenCalledTimes(1); + const [calledUrl] = fetchMock.mock.calls[0] as [string]; + expect(calledUrl).toBe("/api/ta1-acks/stream"); + }); + it("test_handles_heartbeat_silently", async () => { // "Silently" here means: still yields the correctly-typed heartbeat // (no special filtering) — the consumer (useTailStream) decides what diff --git a/src/lib/tail-stream.ts b/src/lib/tail-stream.ts index 6a8b3fc..a87e59c 100644 --- a/src/lib/tail-stream.ts +++ b/src/lib/tail-stream.ts @@ -26,7 +26,7 @@ export type TailEvent = | { type: "item_dropped"; data: { id: string } } | { type: "error"; data: { message: string } }; -export type TailResource = "claims" | "remittances" | "activity"; +export type TailResource = "claims" | "remittances" | "activity" | "acks" | "ta1_acks"; export interface StreamTailOptions { /** Forwarded to `fetch`; aborting the controller cleanly exits the generator. */