Skip to content

Commit 2ab6be6

Browse files
authored
fix(logger): stop a server-side jsdom window from silencing all logging in production (#6339)
* fix(logger): stop a server-side jsdom window from silencing all logging in production * fix(logger): widen the stubbed process cast so type-check passes
1 parent 93b68f0 commit 2ab6be6

2 files changed

Lines changed: 46 additions & 4 deletions

File tree

packages/logger/src/index.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,36 @@ describe('Logger', () => {
4646
})
4747
})
4848

49+
describe('browser suppression in production', () => {
50+
const realProcess = globalThis.process
51+
52+
afterEach(() => {
53+
Reflect.deleteProperty(globalThis, 'window')
54+
globalThis.process = realProcess
55+
})
56+
57+
test('should keep logging when the server installs a DOM', () => {
58+
globalThis.process = {
59+
...realProcess,
60+
env: { ...realProcess.env, NODE_ENV: 'production' },
61+
} as typeof realProcess
62+
Object.assign(globalThis, { window: { document: {} } })
63+
64+
createLogger('Test').error('server still logs')
65+
66+
expect(consoleErrorSpy).toHaveBeenCalled()
67+
})
68+
69+
test('should stay silent in a real browser', () => {
70+
globalThis.process = { env: { NODE_ENV: 'production' } } as unknown as typeof realProcess
71+
Object.assign(globalThis, { window: { document: {} } })
72+
73+
createLogger('Test').error('browser stays quiet')
74+
75+
expect(consoleErrorSpy).not.toHaveBeenCalled()
76+
})
77+
})
78+
4979
describe('LogLevel enum', () => {
5080
test('should have correct log levels', () => {
5181
expect(LogLevel.DEBUG).toBe('DEBUG')

packages/logger/src/index.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@ const getNodeEnv = (): string => {
4848
return 'development'
4949
}
5050

51+
/**
52+
* True only in a real browser.
53+
*
54+
* Server code can legitimately install a DOM — `ensureDomForTipTap` in the
55+
* collab-doc converter mounts a jsdom `window` so TipTap runs headless — so the
56+
* presence of `window` alone does not mean the browser. Node always exposes
57+
* `process.versions.node` and a browser never does, which keeps a server-side
58+
* DOM from silencing the logger for the rest of the process's life.
59+
*/
60+
const isBrowserRuntime = (): boolean => {
61+
if (typeof (globalThis as { window?: unknown }).window === 'undefined') return false
62+
const runtime = (globalThis as { process?: { versions?: { node?: unknown } } }).process
63+
return typeof runtime?.versions?.node !== 'string'
64+
}
65+
5166
const getLogLevel = (): string | undefined => {
5267
if (typeof process !== 'undefined' && process.env) {
5368
return process.env.LOG_LEVEL
@@ -201,10 +216,7 @@ export class Logger {
201216
private shouldLog(level: LogLevel): boolean {
202217
if (!this.config.enabled) return false
203218

204-
if (
205-
getNodeEnv() === 'production' &&
206-
typeof (globalThis as { window?: unknown }).window !== 'undefined'
207-
) {
219+
if (getNodeEnv() === 'production' && isBrowserRuntime()) {
208220
return false
209221
}
210222

0 commit comments

Comments
 (0)