Skip to content

Commit 4f38a9c

Browse files
authored
fix: avoid Next.js Edge Runtime warnings in Node.js deprecation check (#1520)
* fix: avoid Next.js Edge Runtime warnings in Node.js deprecation check Use dynamic property access for process.version to prevent Next.js static analysis from flagging the code as incompatible with Edge Runtime. The deprecation warning logic remains unchanged - it only runs in actual Node.js environments and is properly guarded against Edge Runtime execution. Fixes #1515 * fix: restore undefined and null checks for process.version Maintain the original defensive programming checks while still using dynamic property access to avoid Edge Runtime warnings * test: add comprehensive tests for Node.js deprecation warning - Test browser environment detection - Test Edge Runtime compatibility (no process object) - Test various process.version states (undefined, null, invalid) - Test version detection for Node.js 16, 18, 20, 22 - Test invalid version format handling * fix: update deprecation tests to work with TypeScript isolatedModules - Add export {} to make file a module - Remove problematic test for undefined process (dependencies require it) - Add comment explaining why Edge Runtime scenario is hard to test in Node * test: eliminate TTYWRAP warnings in deprecation tests Use Object.defineProperty to mock only process.version instead of spreading the entire process object. This avoids copying TTY handles and other complex properties that cause Jest warnings.
1 parent 75dd796 commit 4f38a9c

File tree

2 files changed

+157
-7
lines changed

2 files changed

+157
-7
lines changed

src/index.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,23 @@ export const createClient = <
4242

4343
// Check for Node.js <= 18 deprecation
4444
function shouldShowDeprecationWarning(): boolean {
45-
if (
46-
typeof window !== 'undefined' ||
47-
typeof process === 'undefined' ||
48-
process.version === undefined ||
49-
process.version === null
50-
) {
45+
// Skip in browser environments
46+
if (typeof window !== 'undefined') {
5147
return false
5248
}
5349

54-
const versionMatch = process.version.match(/^v(\d+)\./)
50+
// Skip if process is not available (e.g., Edge Runtime)
51+
if (typeof process === 'undefined') {
52+
return false
53+
}
54+
55+
// Use dynamic property access to avoid Next.js Edge Runtime static analysis warnings
56+
const processVersion = (process as any)['version']
57+
if (processVersion === undefined || processVersion === null) {
58+
return false
59+
}
60+
61+
const versionMatch = processVersion.match(/^v(\d+)\./)
5562
if (!versionMatch) {
5663
return false
5764
}

test/unit/deprecation.test.ts

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/**
2+
* @jest-environment node
3+
*/
4+
5+
// Make this file a module to satisfy TypeScript's isolatedModules
6+
export {}
7+
8+
describe('Node.js deprecation warning', () => {
9+
const originalProcess = global.process
10+
const originalWindow = global.window
11+
const originalConsoleWarn = console.warn
12+
13+
beforeEach(() => {
14+
// Reset modules to re-run the deprecation check
15+
jest.resetModules()
16+
// Mock console.warn
17+
console.warn = jest.fn()
18+
})
19+
20+
afterEach(() => {
21+
// Restore original values
22+
global.process = originalProcess
23+
global.window = originalWindow
24+
console.warn = originalConsoleWarn
25+
jest.resetModules()
26+
})
27+
28+
it('should not show warning in browser environment', () => {
29+
// Simulate browser environment
30+
global.window = {} as any
31+
32+
require('../../src/index')
33+
34+
expect(console.warn).not.toHaveBeenCalled()
35+
})
36+
37+
// Note: We can't easily test "process is undefined" because dependencies like ws require it
38+
// The code handles it correctly with typeof process === 'undefined' check
39+
// In real Edge Runtime, the module loading context is different
40+
41+
it('should not show warning when process.version is undefined', () => {
42+
// Process exists but version is undefined
43+
// Only mock the version property to avoid TTYWRAP warnings
44+
Object.defineProperty(global.process, 'version', {
45+
value: undefined,
46+
configurable: true,
47+
})
48+
49+
require('../../src/index')
50+
51+
expect(console.warn).not.toHaveBeenCalled()
52+
})
53+
54+
it('should not show warning when process.version is null', () => {
55+
// Process exists but version is null
56+
// Only mock the version property to avoid TTYWRAP warnings
57+
Object.defineProperty(global.process, 'version', {
58+
value: null,
59+
configurable: true,
60+
})
61+
62+
require('../../src/index')
63+
64+
expect(console.warn).not.toHaveBeenCalled()
65+
})
66+
67+
it('should show warning for Node.js 18', () => {
68+
Object.defineProperty(global.process, 'version', {
69+
value: 'v18.0.0',
70+
configurable: true,
71+
})
72+
delete (global as any).window
73+
74+
require('../../src/index')
75+
76+
expect(console.warn).toHaveBeenCalledWith(
77+
expect.stringContaining('Node.js 18 and below are deprecated')
78+
)
79+
})
80+
81+
it('should show warning for Node.js 16', () => {
82+
Object.defineProperty(global.process, 'version', {
83+
value: 'v16.14.0',
84+
configurable: true,
85+
})
86+
delete (global as any).window
87+
88+
require('../../src/index')
89+
90+
expect(console.warn).toHaveBeenCalledWith(
91+
expect.stringContaining('Node.js 18 and below are deprecated')
92+
)
93+
})
94+
95+
it('should not show warning for Node.js 20', () => {
96+
Object.defineProperty(global.process, 'version', {
97+
value: 'v20.0.0',
98+
configurable: true,
99+
})
100+
delete (global as any).window
101+
102+
require('../../src/index')
103+
104+
expect(console.warn).not.toHaveBeenCalled()
105+
})
106+
107+
it('should not show warning for Node.js 22', () => {
108+
Object.defineProperty(global.process, 'version', {
109+
value: 'v22.0.0',
110+
configurable: true,
111+
})
112+
delete (global as any).window
113+
114+
require('../../src/index')
115+
116+
expect(console.warn).not.toHaveBeenCalled()
117+
})
118+
119+
it('should handle invalid version format gracefully', () => {
120+
Object.defineProperty(global.process, 'version', {
121+
value: 'invalid-version',
122+
configurable: true,
123+
})
124+
delete (global as any).window
125+
126+
require('../../src/index')
127+
128+
expect(console.warn).not.toHaveBeenCalled()
129+
})
130+
131+
it('should handle version without v prefix', () => {
132+
Object.defineProperty(global.process, 'version', {
133+
value: '18.0.0',
134+
configurable: true,
135+
})
136+
delete (global as any).window
137+
138+
require('../../src/index')
139+
140+
// Should not match the regex and thus not show warning
141+
expect(console.warn).not.toHaveBeenCalled()
142+
})
143+
})

0 commit comments

Comments
 (0)