From e6f8e1e53169032d05fb996ad7f00dc0e0f06092 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 8 Jan 2026 10:31:16 +0100 Subject: [PATCH] fix(telegram): restrict native fetch to bun --- src/telegram/bot.test.ts | 49 +++++++++++++++++++++++++++++++--------- src/telegram/fetch.ts | 8 +++---- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/telegram/bot.test.ts b/src/telegram/bot.test.ts index c53682fce..095bab255 100644 --- a/src/telegram/bot.test.ts +++ b/src/telegram/bot.test.ts @@ -135,25 +135,52 @@ describe("createTelegramBot", () => { expect(useSpy).toHaveBeenCalledWith("throttler"); }); - it("forces native fetch for BAN compatibility", () => { + it("forces native fetch only under Bun", () => { const originalFetch = globalThis.fetch; + const originalBun = (globalThis as { Bun?: unknown }).Bun; const fetchSpy = vi.fn() as unknown as typeof fetch; globalThis.fetch = fetchSpy; try { + (globalThis as { Bun?: unknown }).Bun = {}; createTelegramBot({ token: "tok" }); const fetchImpl = resolveTelegramFetch(); - if (fetchImpl) { - expect(botCtorSpy).toHaveBeenCalledWith( - "tok", - expect.objectContaining({ - client: expect.objectContaining({ fetch: fetchSpy }), - }), - ); - } else { - expect(botCtorSpy).toHaveBeenCalledWith("tok", undefined); - } + expect(fetchImpl).toBe(fetchSpy); + expect(botCtorSpy).toHaveBeenCalledWith( + "tok", + expect.objectContaining({ + client: expect.objectContaining({ fetch: fetchSpy }), + }), + ); } finally { globalThis.fetch = originalFetch; + if (originalBun === undefined) { + delete (globalThis as { Bun?: unknown }).Bun; + } else { + (globalThis as { Bun?: unknown }).Bun = originalBun; + } + } + }); + + it("does not force native fetch on Node", () => { + const originalFetch = globalThis.fetch; + const originalBun = (globalThis as { Bun?: unknown }).Bun; + const fetchSpy = vi.fn() as unknown as typeof fetch; + globalThis.fetch = fetchSpy; + try { + if (originalBun !== undefined) { + delete (globalThis as { Bun?: unknown }).Bun; + } + createTelegramBot({ token: "tok" }); + const fetchImpl = resolveTelegramFetch(); + expect(fetchImpl).toBeUndefined(); + expect(botCtorSpy).toHaveBeenCalledWith("tok", undefined); + } finally { + globalThis.fetch = originalFetch; + if (originalBun === undefined) { + delete (globalThis as { Bun?: unknown }).Bun; + } else { + (globalThis as { Bun?: unknown }).Bun = originalBun; + } } }); diff --git a/src/telegram/fetch.ts b/src/telegram/fetch.ts index fa94a4f93..4d0270bab 100644 --- a/src/telegram/fetch.ts +++ b/src/telegram/fetch.ts @@ -1,15 +1,13 @@ -// Ensure native fetch is used when available (Bun + Node 18+). +// Bun-only: force native fetch to avoid grammY's Node shim under Bun. export function resolveTelegramFetch( proxyFetch?: typeof fetch, ): typeof fetch | undefined { if (proxyFetch) return proxyFetch; const fetchImpl = globalThis.fetch; const isBun = "Bun" in globalThis || Boolean(process?.versions?.bun); + if (!isBun) return undefined; if (!fetchImpl) { - if (isBun) { - throw new Error("fetch is not available; set telegram.proxy in config"); - } - return undefined; + throw new Error("fetch is not available; set telegram.proxy in config"); } return fetchImpl; }