Skip to content

Commit 2f7183b

Browse files
committed
feature
1 parent 161eacb commit 2f7183b

File tree

3 files changed

+182
-3
lines changed

3 files changed

+182
-3
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
2+
import { generateRedisConnectionExpr } from '../../src/utils/generate-redis-connection-expr'
3+
4+
// Helper: evaluate the generated expression in current process context
5+
function evalExpr(expr: string): unknown {
6+
return eval(expr)
7+
}
8+
9+
function clearEnvKey(key: string) {
10+
Reflect.deleteProperty(process.env, key)
11+
}
12+
13+
describe('generateRedisConnectionExpr', () => {
14+
const savedEnv: Record<string, string | undefined> = {}
15+
const envKeys = [
16+
'NUXT_REDIS_URL',
17+
'NUXT_REDIS_HOST',
18+
'NUXT_REDIS_PORT',
19+
'NUXT_REDIS_PASSWORD',
20+
'NUXT_REDIS_USERNAME',
21+
'NUXT_REDIS_DB',
22+
'NUXT_REDIS_LAZY_CONNECT',
23+
'NUXT_REDIS_CONNECT_TIMEOUT',
24+
]
25+
26+
beforeEach(() => {
27+
for (const key of envKeys) {
28+
savedEnv[key] = process.env[key]
29+
clearEnvKey(key)
30+
}
31+
})
32+
33+
afterEach(() => {
34+
for (const key of envKeys) {
35+
if (savedEnv[key] !== undefined) {
36+
process.env[key] = savedEnv[key]
37+
}
38+
else {
39+
clearEnvKey(key)
40+
}
41+
}
42+
})
43+
44+
it('returns static config when no env vars are set', () => {
45+
const staticRedis = JSON.stringify({ host: '10.0.0.1', port: 6380, password: 'secret', db: 2 })
46+
const expr = generateRedisConnectionExpr(staticRedis)
47+
const result = evalExpr(expr) as Record<string, unknown>
48+
49+
expect(result).toEqual({
50+
host: '10.0.0.1',
51+
port: 6380,
52+
password: 'secret',
53+
username: undefined,
54+
db: 2,
55+
lazyConnect: undefined,
56+
connectTimeout: undefined,
57+
})
58+
})
59+
60+
it('returns NUXT_REDIS_URL when set at runtime', () => {
61+
process.env.NUXT_REDIS_URL = 'redis://prod-host:6379/1'
62+
const staticRedis = JSON.stringify({ host: '127.0.0.1', port: 6379 })
63+
const expr = generateRedisConnectionExpr(staticRedis)
64+
const result = evalExpr(expr)
65+
66+
expect(result).toBe('redis://prod-host:6379/1')
67+
})
68+
69+
it('returns static url when set in config and no env url', () => {
70+
const staticRedis = JSON.stringify({ url: 'redis://config-host:6379/0', host: '127.0.0.1' })
71+
const expr = generateRedisConnectionExpr(staticRedis)
72+
const result = evalExpr(expr)
73+
74+
expect(result).toBe('redis://config-host:6379/0')
75+
})
76+
77+
it('env vars override individual static fields', () => {
78+
process.env.NUXT_REDIS_HOST = '192.168.1.100'
79+
process.env.NUXT_REDIS_PORT = '6381'
80+
process.env.NUXT_REDIS_PASSWORD = 'runtime-pw'
81+
process.env.NUXT_REDIS_USERNAME = 'admin'
82+
process.env.NUXT_REDIS_DB = '5'
83+
84+
const staticRedis = JSON.stringify({ host: '10.0.0.1', port: 6380, password: 'build-pw', db: 2 })
85+
const expr = generateRedisConnectionExpr(staticRedis)
86+
const result = evalExpr(expr) as Record<string, unknown>
87+
88+
expect(result).toEqual({
89+
host: '192.168.1.100',
90+
port: 6381,
91+
password: 'runtime-pw',
92+
username: 'admin',
93+
db: 5,
94+
lazyConnect: undefined,
95+
connectTimeout: undefined,
96+
})
97+
})
98+
99+
it('env vars partially override static fields', () => {
100+
process.env.NUXT_REDIS_HOST = 'new-host'
101+
// port, password etc. not set in env
102+
103+
const staticRedis = JSON.stringify({ host: '10.0.0.1', port: 6380, password: 'build-pw', db: 2 })
104+
const expr = generateRedisConnectionExpr(staticRedis)
105+
const result = evalExpr(expr) as Record<string, unknown>
106+
107+
expect(result).toMatchObject({
108+
host: 'new-host',
109+
port: 6380,
110+
password: 'build-pw',
111+
db: 2,
112+
})
113+
})
114+
115+
it('NUXT_REDIS_URL env takes priority over static url in config', () => {
116+
process.env.NUXT_REDIS_URL = 'redis://env-host:6379'
117+
const staticRedis = JSON.stringify({ url: 'redis://config-host:6379' })
118+
const expr = generateRedisConnectionExpr(staticRedis)
119+
const result = evalExpr(expr)
120+
121+
expect(result).toBe('redis://env-host:6379')
122+
})
123+
124+
it('handles lazyConnect and connectTimeout from env', () => {
125+
process.env.NUXT_REDIS_LAZY_CONNECT = 'true'
126+
process.env.NUXT_REDIS_CONNECT_TIMEOUT = '5000'
127+
128+
const staticRedis = JSON.stringify({})
129+
const expr = generateRedisConnectionExpr(staticRedis)
130+
const result = evalExpr(expr) as Record<string, unknown>
131+
132+
expect(result).toMatchObject({
133+
lazyConnect: true,
134+
connectTimeout: 5000,
135+
})
136+
})
137+
138+
it('falls back to defaults when both static and env are empty', () => {
139+
const staticRedis = JSON.stringify({})
140+
const expr = generateRedisConnectionExpr(staticRedis)
141+
const result = evalExpr(expr) as Record<string, unknown>
142+
143+
expect(result).toEqual({
144+
host: '127.0.0.1',
145+
port: 6379,
146+
password: '',
147+
username: undefined,
148+
db: 0,
149+
lazyConnect: undefined,
150+
connectTimeout: undefined,
151+
})
152+
})
153+
154+
it('generated expression contains process.env references', () => {
155+
const expr = generateRedisConnectionExpr('{}')
156+
expect(expr).toContain('process.env.NUXT_REDIS_URL')
157+
expect(expr).toContain('process.env.NUXT_REDIS_HOST')
158+
expect(expr).toContain('process.env.NUXT_REDIS_PORT')
159+
expect(expr).toContain('process.env.NUXT_REDIS_PASSWORD')
160+
})
161+
})

src/module.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { Plugin } from 'rollup'
55
import { relative } from 'node:path'
66
import scanFolder from './utils/scan-folder'
77
import { generateWorkersEntryContent } from './utils/generate-workers-entry-content'
8+
import { generateRedisConnectionExpr } from './utils/generate-redis-connection-expr'
89

910
// Module options TypeScript interface definition
1011
type ModuleRedisOptions = BullRedisOptions & { url?: string }
@@ -43,14 +44,15 @@ export default defineNuxtModule<ModuleOptions>({
4344
async setup(_options, nuxt) {
4445
const { resolve } = createResolver(import.meta.url)
4546

46-
const redisInline = JSON.stringify(_options.redis ?? {})
47+
const staticRedis = JSON.stringify(_options.redis ?? {})
48+
const redisConnectionExpr = generateRedisConnectionExpr(staticRedis)
4749

4850
const nitroPlugin = `
4951
import { defineNitroPlugin } from '#imports'
5052
import { $workers } from '#processor-utils'
5153
5254
export default defineNitroPlugin(() => {
53-
$workers().setConnection(${redisInline})
55+
$workers().setConnection(${redisConnectionExpr})
5456
})
5557
`
5658

@@ -109,7 +111,7 @@ declare module '#bullmq' {
109111
virtualCode = ''
110112
return
111113
}
112-
virtualCode = generateWorkersEntryContent(workerFiles, redisInline)
114+
virtualCode = generateWorkersEntryContent(workerFiles, redisConnectionExpr)
113115
for (const id of workerFiles) {
114116
this.addWatchFile(id)
115117
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export function generateRedisConnectionExpr(staticRedis: string): string {
2+
return `(() => {
3+
const s = ${staticRedis};
4+
const url = process.env.NUXT_REDIS_URL ?? s.url;
5+
if (url) return url;
6+
return {
7+
host: process.env.NUXT_REDIS_HOST ?? s.host ?? '127.0.0.1',
8+
port: Number(process.env.NUXT_REDIS_PORT ?? s.port ?? 6379),
9+
password: process.env.NUXT_REDIS_PASSWORD ?? s.password ?? '',
10+
username: process.env.NUXT_REDIS_USERNAME ?? s.username ?? undefined,
11+
db: Number(process.env.NUXT_REDIS_DB ?? s.db ?? 0),
12+
lazyConnect: process.env.NUXT_REDIS_LAZY_CONNECT ? process.env.NUXT_REDIS_LAZY_CONNECT === 'true' : s.lazyConnect,
13+
connectTimeout: process.env.NUXT_REDIS_CONNECT_TIMEOUT ? Number(process.env.NUXT_REDIS_CONNECT_TIMEOUT) : s.connectTimeout,
14+
};
15+
})()`
16+
}

0 commit comments

Comments
 (0)