From 5ed2bac8a68c2c12ada3356af3c161015a93e565 Mon Sep 17 00:00:00 2001 From: os-zhuang Date: Wed, 10 Jun 2026 18:15:15 +0500 Subject: [PATCH] fix(objectstack): clean SDK client logger (no ANSI in RN/web) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Browser flow testing surfaced a red dev error toast showing raw ANSI escape codes: "[31m…ERROR[0m HTTP request failed". The SDK client's default logger formats with terminal ANSI colour codes + timestamps, which leak as literal "[31m…" text into the RN/web console and trip the dev error overlay (notably on a benign notifications 404). Pass a clean `logger` to every ObjectStackClient: plain console output, no ANSI; debug/info silenced outside __DEV__; SDK `error` routed to console.warn (so a benign HTTP failure no longer pops the red error overlay), `fatal` stays console.error. Verified in the browser against a live server: the ANSI error toast is gone. Suite 1266/1266, lint clean. Co-Authored-By: Claude Opus 4.8 --- lib/objectstack.ts | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/objectstack.ts b/lib/objectstack.ts index 4304a7f..ce338a7 100644 --- a/lib/objectstack.ts +++ b/lib/objectstack.ts @@ -1,10 +1,37 @@ -import { ObjectStackClient } from "@objectstack/client"; +import { ObjectStackClient, type ClientConfig } from "@objectstack/client"; import { Platform } from "react-native"; let API_URL = process.env.EXPO_PUBLIC_API_URL ?? "http://localhost:3100"; const isWeb = Platform.OS === "web"; +/** + * A clean logger for the SDK client. The SDK's default logger formats messages + * with ANSI colour codes + timestamps meant for a Node terminal; in React + * Native / web those escape codes leak as literal `[31m…` garbage into the + * console and the dev error overlay. This routes SDK logs through plain + * `console` calls (no ANSI), and silences debug/info noise outside dev. + * + * `child`/`withTrace` return the same logger (we don't need scoped context); + * `destroy` is a no-op. Typed loosely to satisfy `ClientConfig["logger"]` + * without depending on the core logger's exact class shape. + */ +const clientLogger = (() => { + const dev = typeof __DEV__ !== "undefined" && __DEV__; + const self = { + debug: (m: string, meta?: unknown) => dev && console.log("[objectstack]", m, meta ?? ""), + info: (m: string, meta?: unknown) => dev && console.log("[objectstack]", m, meta ?? ""), + warn: (m: string, meta?: unknown) => console.warn("[objectstack]", m, meta ?? ""), + error: (m: string, err?: unknown) => console.warn("[objectstack]", m, err ?? ""), + fatal: (m: string, err?: unknown) => console.error("[objectstack]", m, err ?? ""), + log: (m: string, ...args: unknown[]) => dev && console.log("[objectstack]", m, ...args), + child: () => self, + withTrace: () => self, + destroy: async () => {}, + }; + return self as unknown as NonNullable; +})(); + /** * Read the better-auth session cookie for native requests. Lazily required so * that loading this module (e.g. in unit tests, or on web where the cookie is @@ -121,6 +148,7 @@ export function createObjectStackClient(token?: string): ObjectStackClient { baseUrl: API_URL, token, fetch: authAwareFetch, + logger: clientLogger, }); } @@ -143,6 +171,7 @@ export function getObjectStackClient(): ObjectStackClient { return new ObjectStackClient({ baseUrl: API_URL, fetch: authAwareFetch, + logger: clientLogger, }); } @@ -152,4 +181,5 @@ export function getObjectStackClient(): ObjectStackClient { export const objectStackClient = new ObjectStackClient({ baseUrl: API_URL, fetch: authAwareFetch, + logger: clientLogger, });