@gravito/zenith 1.1.2 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +95 -22
  2. package/README.zh-TW.md +88 -0
  3. package/dist/bin.js +54699 -39316
  4. package/dist/client/assets/index-C80c1frR.css +1 -0
  5. package/dist/client/assets/index-CrWem9u3.js +434 -0
  6. package/dist/client/index.html +2 -2
  7. package/dist/server/index.js +54699 -39316
  8. package/package.json +20 -9
  9. package/CHANGELOG.md +0 -47
  10. package/Dockerfile +0 -46
  11. package/Dockerfile.demo-worker +0 -29
  12. package/ECOSYSTEM_EXPANSION_RFC.md +0 -130
  13. package/bin/flux-console.ts +0 -2
  14. package/dist/client/assets/index-BSMp8oq_.js +0 -436
  15. package/dist/client/assets/index-BwxlHx-_.css +0 -1
  16. package/docker-compose.yml +0 -40
  17. package/docs/ALERTING_GUIDE.md +0 -71
  18. package/docs/DEPLOYMENT.md +0 -157
  19. package/docs/DOCS_INTERNAL.md +0 -73
  20. package/docs/LARAVEL_ZENITH_ROADMAP.md +0 -109
  21. package/docs/QUASAR_MASTER_PLAN.md +0 -140
  22. package/docs/QUICK_TEST_GUIDE.md +0 -72
  23. package/docs/ROADMAP.md +0 -85
  24. package/docs/integrations/LARAVEL.md +0 -207
  25. package/postcss.config.js +0 -6
  26. package/scripts/debug_redis_keys.ts +0 -24
  27. package/scripts/flood-logs.ts +0 -21
  28. package/scripts/seed.ts +0 -213
  29. package/scripts/verify-throttle.ts +0 -49
  30. package/scripts/worker.ts +0 -124
  31. package/specs/PULSE_SPEC.md +0 -86
  32. package/src/bin.ts +0 -6
  33. package/src/client/App.tsx +0 -72
  34. package/src/client/Layout.tsx +0 -672
  35. package/src/client/Sidebar.tsx +0 -112
  36. package/src/client/ThroughputChart.tsx +0 -144
  37. package/src/client/WorkerStatus.tsx +0 -226
  38. package/src/client/components/BrandIcons.tsx +0 -168
  39. package/src/client/components/ConfirmDialog.tsx +0 -126
  40. package/src/client/components/JobInspector.tsx +0 -554
  41. package/src/client/components/LogArchiveModal.tsx +0 -432
  42. package/src/client/components/NotificationBell.tsx +0 -212
  43. package/src/client/components/PageHeader.tsx +0 -47
  44. package/src/client/components/Toaster.tsx +0 -90
  45. package/src/client/components/UserProfileDropdown.tsx +0 -186
  46. package/src/client/contexts/AuthContext.tsx +0 -105
  47. package/src/client/contexts/NotificationContext.tsx +0 -128
  48. package/src/client/index.css +0 -174
  49. package/src/client/index.html +0 -12
  50. package/src/client/main.tsx +0 -15
  51. package/src/client/pages/LoginPage.tsx +0 -162
  52. package/src/client/pages/MetricsPage.tsx +0 -417
  53. package/src/client/pages/OverviewPage.tsx +0 -517
  54. package/src/client/pages/PulsePage.tsx +0 -488
  55. package/src/client/pages/QueuesPage.tsx +0 -379
  56. package/src/client/pages/SchedulesPage.tsx +0 -540
  57. package/src/client/pages/SettingsPage.tsx +0 -1020
  58. package/src/client/pages/WorkersPage.tsx +0 -394
  59. package/src/client/pages/index.ts +0 -8
  60. package/src/client/utils.ts +0 -15
  61. package/src/server/config/ServerConfigManager.ts +0 -90
  62. package/src/server/index.ts +0 -860
  63. package/src/server/middleware/auth.ts +0 -127
  64. package/src/server/services/AlertService.ts +0 -321
  65. package/src/server/services/CommandService.ts +0 -137
  66. package/src/server/services/LogStreamProcessor.ts +0 -93
  67. package/src/server/services/MaintenanceScheduler.ts +0 -78
  68. package/src/server/services/PulseService.ts +0 -91
  69. package/src/server/services/QueueMetricsCollector.ts +0 -138
  70. package/src/server/services/QueueService.ts +0 -631
  71. package/src/shared/types.ts +0 -198
  72. package/tailwind.config.js +0 -73
  73. package/tests/placeholder.test.ts +0 -7
  74. package/tsconfig.json +0 -38
  75. package/tsconfig.node.json +0 -12
  76. package/vite.config.ts +0 -27
@@ -1,394 +0,0 @@
1
- import { useQuery, useQueryClient } from '@tanstack/react-query'
2
- import { motion } from 'framer-motion'
3
- import { AlertCircle, Clock, Cpu, Gauge, MemoryStick, RefreshCcw, Server, Zap } from 'lucide-react'
4
- import { useEffect } from 'react'
5
- import { cn } from '../utils'
6
-
7
- interface Worker {
8
- id: string
9
- status: string
10
- pid: number
11
- uptime: number
12
- metrics?: {
13
- cpu: number
14
- cores?: number
15
- ram: {
16
- rss: number
17
- heapUsed: number
18
- total?: number
19
- }
20
- }
21
- queues?: {
22
- name: string
23
- size: {
24
- waiting: number
25
- active: number
26
- failed: number
27
- delayed: number
28
- }
29
- }[]
30
- meta?: {
31
- laravel?: {
32
- workerCount: number
33
- roots: string[]
34
- }
35
- }
36
- }
37
-
38
- /**
39
- * Worker Nodes Dashboard Page.
40
- *
41
- * Provides a detailed view of all active and inactive worker nodes in the
42
- * cluster, including their resource usage, monitored queues, and Laravel
43
- * worker status.
44
- *
45
- * @public
46
- * @since 3.0.0
47
- */
48
- export function WorkersPage() {
49
- const queryClient = useQueryClient()
50
- const { isPending, error, data } = useQuery<{ workers: Worker[] }>({
51
- queryKey: ['workers'],
52
- queryFn: async () => {
53
- const res = await fetch('/api/workers')
54
- return res.json()
55
- },
56
- refetchInterval: 5000,
57
- })
58
-
59
- // Listen to real-time stats updates from SSE
60
- useEffect(() => {
61
- const handler = (e: any) => {
62
- if (e.detail?.workers) {
63
- // Optimistically update the query cache with fresh worker data from SSE
64
- queryClient.setQueryData(['workers'], { workers: e.detail.workers })
65
- }
66
- }
67
- window.addEventListener('flux-stats-update', handler)
68
- return () => window.removeEventListener('flux-stats-update', handler)
69
- }, [queryClient])
70
-
71
- const workers = data?.workers || []
72
- const onlineWorkers = workers.filter((w) => w.status === 'online')
73
- const offlineWorkers = workers.filter((w) => w.status !== 'online')
74
-
75
- const totalCpu = workers.reduce((acc, w) => acc + (w.metrics?.cpu || 0), 0)
76
- const avgCpu = workers.length > 0 ? totalCpu / workers.length : 0
77
- const totalRam = workers.reduce((acc, w) => acc + (w.metrics?.ram?.rss || 0), 0)
78
- const totalCapacity = workers.reduce((acc, w) => acc + (w.metrics?.ram?.total || 0), 0)
79
-
80
- if (isPending) {
81
- return (
82
- <div className="flex flex-col items-center justify-center p-20 space-y-6">
83
- <RefreshCcw className="animate-spin text-primary" size={48} />
84
- <p className="text-muted-foreground font-bold uppercase tracking-[0.3em] text-xs">
85
- Loading workers...
86
- </p>
87
- </div>
88
- )
89
- }
90
-
91
- if (error) {
92
- return (
93
- <div className="text-center p-20">
94
- <div className="bg-red-500/10 text-red-500 p-10 rounded-3xl border border-red-500/20 max-w-md mx-auto shadow-2xl">
95
- <AlertCircle size={56} className="mx-auto mb-6 opacity-80" />
96
- <h3 className="text-2xl font-black mb-2 uppercase tracking-tight">
97
- Failed to Load Workers
98
- </h3>
99
- <p className="text-sm font-medium opacity-70">{error.message}</p>
100
- </div>
101
- </div>
102
- )
103
- }
104
-
105
- return (
106
- <div className="space-y-8">
107
- {/* Header */}
108
- <div className="flex justify-between items-end">
109
- <div>
110
- <h1 className="text-4xl font-black tracking-tighter">Worker Nodes</h1>
111
- <p className="text-muted-foreground mt-2 text-sm font-bold opacity-60 uppercase tracking-widest">
112
- Monitor and manage cluster processing nodes.
113
- </p>
114
- </div>
115
- <div className="flex items-center gap-2 text-[10px] font-black text-green-500 bg-green-500/10 px-4 py-2 rounded-full border border-green-500/20 uppercase tracking-[0.2em]">
116
- <span className="w-2 h-2 bg-green-500 rounded-full shadow-[0_0_8px_rgba(34,197,94,0.6)] animate-pulse"></span>
117
- {onlineWorkers.length} Online
118
- </div>
119
- </div>
120
-
121
- {/* Summary Cards */}
122
- <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
123
- <div className="card-premium p-6 relative overflow-hidden group">
124
- <div className="absolute top-0 right-0 w-20 h-20 bg-green-500/10 rounded-full -translate-y-1/2 translate-x-1/2 group-hover:scale-150 transition-transform duration-500" />
125
- <div className="relative">
126
- <div className="flex items-center gap-2 mb-2">
127
- <Server size={16} className="text-green-500" />
128
- <p className="text-[10px] font-black text-muted-foreground/50 uppercase tracking-widest">
129
- Online Nodes
130
- </p>
131
- </div>
132
- <p className="text-3xl font-black text-green-500">{onlineWorkers.length}</p>
133
- </div>
134
- </div>
135
- <div className="card-premium p-6 relative overflow-hidden group">
136
- <div className="absolute top-0 right-0 w-20 h-20 bg-muted/20 rounded-full -translate-y-1/2 translate-x-1/2 group-hover:scale-150 transition-transform duration-500" />
137
- <div className="relative">
138
- <div className="flex items-center gap-2 mb-2">
139
- <Zap size={16} className="text-muted-foreground" />
140
- <p className="text-[10px] font-black text-muted-foreground/50 uppercase tracking-widest">
141
- Offline Nodes
142
- </p>
143
- </div>
144
- <p className="text-3xl font-black text-muted-foreground">{offlineWorkers.length}</p>
145
- </div>
146
- </div>
147
- <div className="card-premium p-6 relative overflow-hidden group">
148
- <div className="absolute top-0 right-0 w-20 h-20 bg-primary/10 rounded-full -translate-y-1/2 translate-x-1/2 group-hover:scale-150 transition-transform duration-500" />
149
- <div className="relative">
150
- <div className="flex items-center gap-2 mb-2">
151
- <Gauge size={16} className="text-primary" />
152
- <p className="text-[10px] font-black text-muted-foreground/50 uppercase tracking-widest">
153
- Avg Load
154
- </p>
155
- </div>
156
- <p className="text-3xl font-black">{avgCpu.toFixed(2)}</p>
157
- </div>
158
- </div>
159
- <div className="card-premium p-6 relative overflow-hidden group">
160
- <div className="absolute top-0 right-0 w-20 h-20 bg-indigo-500/10 rounded-full -translate-y-1/2 translate-x-1/2 group-hover:scale-150 transition-transform duration-500" />
161
- <div className="relative">
162
- <div className="flex items-center gap-2 mb-2">
163
- <MemoryStick size={16} className="text-indigo-500" />
164
- <p className="text-[10px] font-black text-muted-foreground/50 uppercase tracking-widest">
165
- Cluster RAM
166
- </p>
167
- </div>
168
- <div className="flex items-baseline gap-1">
169
- <p className="text-3xl font-black text-indigo-500">{(totalRam / 1024).toFixed(2)}</p>
170
- {totalCapacity > 0 && (
171
- <span className="text-sm font-bold text-muted-foreground opacity-50">
172
- / {(totalCapacity / 1024).toFixed(0)} GB
173
- </span>
174
- )}
175
- </div>
176
- </div>
177
- </div>
178
- </div>
179
-
180
- {/* Workers Grid */}
181
- <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
182
- {workers.length === 0 && (
183
- <div className="col-span-full py-20 text-center text-muted-foreground/30">
184
- <Cpu size={48} className="mx-auto mb-4 opacity-20 animate-pulse" />
185
- <p className="text-sm font-bold uppercase tracking-widest">No worker nodes connected</p>
186
- <p className="text-xs opacity-60 mt-2">Start a worker to see it appear here</p>
187
- </div>
188
- )}
189
- {workers.map((worker, index) => (
190
- <motion.div
191
- key={worker.id}
192
- initial={{ opacity: 0, y: 20 }}
193
- animate={{ opacity: 1, y: 0 }}
194
- transition={{ delay: index * 0.1 }}
195
- className="card-premium p-6 relative overflow-hidden group"
196
- >
197
- {/* Status indicator bar */}
198
- <div
199
- className={cn(
200
- 'absolute left-0 top-0 bottom-0 w-1.5 transition-all',
201
- worker.status === 'online' ? 'bg-green-500' : 'bg-muted-foreground/30'
202
- )}
203
- />
204
-
205
- {/* Header */}
206
- <div className="flex items-start justify-between mb-6">
207
- <div className="flex items-center gap-4">
208
- <div className="relative">
209
- <div
210
- className={cn(
211
- 'w-12 h-12 rounded-2xl flex items-center justify-center transition-all',
212
- worker.status === 'online'
213
- ? 'bg-green-500/10 text-green-500'
214
- : 'bg-muted text-muted-foreground'
215
- )}
216
- >
217
- <Cpu size={24} />
218
- </div>
219
- <div
220
- className={cn(
221
- 'absolute -bottom-1 -right-1 w-4 h-4 rounded-full border-2 border-card',
222
- worker.status === 'online'
223
- ? 'bg-green-500 animate-pulse'
224
- : 'bg-muted-foreground'
225
- )}
226
- />
227
- </div>
228
- <div>
229
- <h3 className="font-black tracking-tight text-lg group-hover:text-primary transition-colors">
230
- {worker.id}
231
- </h3>
232
- <p className="text-[10px] font-bold text-muted-foreground uppercase tracking-widest">
233
- PID: {worker.pid}
234
- </p>
235
- </div>
236
- </div>
237
- <span
238
- className={cn(
239
- 'px-3 py-1 rounded-full text-[9px] font-black uppercase tracking-widest border',
240
- worker.status === 'online'
241
- ? 'bg-green-500/10 text-green-500 border-green-500/20'
242
- : 'bg-muted/40 text-muted-foreground border-transparent'
243
- )}
244
- >
245
- {worker.status}
246
- </span>
247
- </div>
248
-
249
- {/* Metrics */}
250
- {worker.metrics && (
251
- <div className="space-y-4">
252
- {/* CPU */}
253
- <div>
254
- <div className="flex justify-between text-[10px] font-black uppercase tracking-widest mb-2">
255
- <span className="text-muted-foreground">
256
- Load (Cap: {worker.metrics.cores || '-'})
257
- </span>
258
- <span
259
- className={cn(
260
- worker.metrics.cpu > (worker.metrics.cores || 4)
261
- ? 'text-red-500'
262
- : worker.metrics.cpu > (worker.metrics.cores || 4) * 0.7
263
- ? 'text-amber-500'
264
- : 'text-green-500'
265
- )}
266
- >
267
- {worker.metrics.cpu.toFixed(2)}
268
- </span>
269
- </div>
270
- <div className="h-2 w-full bg-muted rounded-full overflow-hidden">
271
- <motion.div
272
- initial={{ width: 0 }}
273
- animate={{
274
- width: `${Math.min(100, (worker.metrics.cpu / (worker.metrics.cores || 1)) * 100)}%`,
275
- }}
276
- transition={{ duration: 0.5 }}
277
- className={cn(
278
- 'h-full transition-colors',
279
- worker.metrics.cpu > (worker.metrics.cores || 4)
280
- ? 'bg-red-500'
281
- : worker.metrics.cpu > (worker.metrics.cores || 4) * 0.7
282
- ? 'bg-amber-500'
283
- : 'bg-green-500'
284
- )}
285
- />
286
- </div>
287
- </div>
288
-
289
- {/* RAM */}
290
- <div>
291
- <div className="flex justify-between text-[10px] font-black uppercase tracking-widest mb-2">
292
- <span className="text-muted-foreground">Memory (RSS / Total)</span>
293
- <span className="text-indigo-500">
294
- {(worker.metrics.ram.rss / 1024).toFixed(2)} GB /{' '}
295
- {worker.metrics.ram.total
296
- ? (worker.metrics.ram.total / 1024).toFixed(0)
297
- : '-'}{' '}
298
- GB
299
- </span>
300
- </div>
301
- <div className="h-2 w-full bg-muted rounded-full overflow-hidden">
302
- <motion.div
303
- initial={{ width: 0 }}
304
- animate={{
305
- width: `${Math.min(100, (worker.metrics.ram.rss / (worker.metrics.ram.total || 2048)) * 100)}%`,
306
- }}
307
- transition={{ duration: 0.5 }}
308
- className="h-full bg-indigo-500"
309
- />
310
- </div>
311
- </div>
312
- </div>
313
- )}
314
-
315
- {/* Laravel & Queue Info (New) */}
316
- <div className="mt-6 space-y-3">
317
- {/* Monitored Queues */}
318
- {worker.queues && worker.queues.length > 0 && (
319
- <div className="bg-muted/10 p-3 rounded-xl border border-border/50">
320
- <div className="flex items-center gap-2 mb-2">
321
- <div className="w-1.5 h-1.5 bg-orange-500 rounded-full" />
322
- <span className="text-[9px] font-black uppercase tracking-widest text-muted-foreground">
323
- Monitored Queues
324
- </span>
325
- </div>
326
- <div className="flex flex-wrap gap-2">
327
- {worker.queues.map((q, i) => (
328
- <div
329
- key={i}
330
- className="flex items-center gap-1.5 text-xs font-bold text-foreground/80 bg-background/80 px-2 py-1 rounded-md shadow-sm border border-border/50"
331
- >
332
- <span className="opacity-70">{q.name}</span>
333
- {(q.size.waiting > 0 || q.size.failed > 0) && (
334
- <span
335
- className={cn(
336
- 'px-1 rounded bg-muted text-[9px]',
337
- q.size.failed > 0
338
- ? 'text-red-500 bg-red-500/10'
339
- : 'text-amber-500 bg-amber-500/10'
340
- )}
341
- >
342
- {q.size.failed > 0
343
- ? `${q.size.failed} failed`
344
- : `${q.size.waiting} wait`}
345
- </span>
346
- )}
347
- </div>
348
- ))}
349
- </div>
350
- </div>
351
- )}
352
-
353
- {/* Laravel Workers Info */}
354
- {worker.meta?.laravel && (
355
- <div className="flex items-center justify-between p-3 bg-red-500/5 border border-red-500/10 rounded-xl">
356
- <div className="flex items-center gap-2">
357
- <span className="w-1.5 h-1.5 bg-red-500 rounded-full animate-pulse" />
358
- <span className="text-[10px] font-black uppercase tracking-widest text-red-500/80">
359
- Laravel Workers
360
- </span>
361
- </div>
362
- <span className="font-mono text-sm font-black text-red-500">
363
- {worker.meta.laravel.workerCount || 0}
364
- </span>
365
- </div>
366
- )}
367
- </div>
368
-
369
- {/* Uptime */}
370
- <div className="mt-4 pt-4 border-t border-border/30 flex items-center justify-between">
371
- <div className="flex items-center gap-2 text-muted-foreground">
372
- <Clock size={14} />
373
- <span className="text-[10px] font-bold uppercase tracking-widest">Uptime</span>
374
- </div>
375
- <span className="font-mono text-sm font-bold">{formatUptime(worker.uptime)}</span>
376
- </div>
377
- </motion.div>
378
- ))}
379
- </div>
380
- </div>
381
- )
382
- }
383
-
384
- function formatUptime(seconds: number): string {
385
- if (seconds < 60) {
386
- return `${Math.floor(seconds)}s`
387
- }
388
- if (seconds < 3600) {
389
- return `${Math.floor(seconds / 60)}m ${Math.floor(seconds % 60)}s`
390
- }
391
- const hours = Math.floor(seconds / 3600)
392
- const minutes = Math.floor((seconds % 3600) / 60)
393
- return `${hours}h ${minutes}m`
394
- }
@@ -1,8 +0,0 @@
1
- export { LoginPage } from './LoginPage'
2
- export { MetricsPage } from './MetricsPage'
3
- export { OverviewPage } from './OverviewPage'
4
- export { PulsePage } from './PulsePage'
5
- export { QueuesPage } from './QueuesPage'
6
- export { SchedulesPage } from './SchedulesPage'
7
- export { SettingsPage } from './SettingsPage'
8
- export { WorkersPage } from './WorkersPage'
@@ -1,15 +0,0 @@
1
- import { type ClassValue, clsx } from 'clsx'
2
- import { twMerge } from 'tailwind-merge'
3
-
4
- /**
5
- * Conditionally join class names and merge Tailwind CSS classes.
6
- *
7
- * @param inputs - A list of class values to be merged.
8
- * @returns The merged class string.
9
- *
10
- * @public
11
- * @since 3.0.0
12
- */
13
- export function cn(...inputs: ClassValue[]) {
14
- return twMerge(clsx(inputs))
15
- }
@@ -1,90 +0,0 @@
1
- import { DB } from '@gravito/atlas'
2
- import { MySQLPersistence, SQLitePersistence } from '@gravito/stream'
3
-
4
- export interface ServerConfig {
5
- port: number
6
- redisUrl: string
7
- queuePrefix: string
8
- dbDriver: 'sqlite' | 'mysql'
9
- dbConfig: {
10
- name?: string
11
- host?: string
12
- port?: number
13
- username?: string
14
- password?: string
15
- }
16
- persistence?: {
17
- adapter: any
18
- archiveCompleted: boolean
19
- archiveFailed: boolean
20
- archiveEnqueued: boolean
21
- }
22
- }
23
-
24
- export class ServerConfigManager {
25
- static load(): ServerConfig {
26
- const dbDriver = (process.env.DB_DRIVER || (process.env.DB_HOST ? 'mysql' : 'sqlite')) as
27
- | 'sqlite'
28
- | 'mysql'
29
-
30
- const dbConfig: ServerConfig['dbConfig'] = {}
31
- if (dbDriver === 'mysql') {
32
- dbConfig.host = process.env.DB_HOST
33
- dbConfig.port = parseInt(process.env.DB_PORT || '3306', 10)
34
- dbConfig.name = process.env.DB_NAME
35
- dbConfig.username = process.env.DB_USER
36
- dbConfig.password = process.env.DB_PASSWORD
37
- } else {
38
- dbConfig.name = process.env.DB_NAME || 'flux.sqlite'
39
- }
40
-
41
- let persistence: ServerConfig['persistence']
42
-
43
- if (dbDriver === 'sqlite' || process.env.DB_HOST) {
44
- this.setupDatabase(dbDriver, dbConfig)
45
-
46
- const adapter =
47
- dbDriver === 'sqlite'
48
- ? new SQLitePersistence(DB.connection())
49
- : new MySQLPersistence(DB.connection())
50
- adapter
51
- .setupTable()
52
- .catch((err) => console.error('[FluxConsole] SQL Archive Setup Error:', err))
53
-
54
- persistence = {
55
- adapter,
56
- archiveCompleted: process.env.PERSIST_ARCHIVE_COMPLETED === 'true',
57
- archiveFailed: process.env.PERSIST_ARCHIVE_FAILED !== 'false',
58
- archiveEnqueued: process.env.PERSIST_ARCHIVE_ENQUEUED === 'true',
59
- }
60
- console.log(`[FluxConsole] SQL Archive enabled via ${dbDriver}`)
61
- }
62
-
63
- return {
64
- port: parseInt(process.env.PORT || '3000', 10),
65
- redisUrl: process.env.REDIS_URL || 'redis://localhost:6379',
66
- queuePrefix: process.env.QUEUE_PREFIX || 'queue:',
67
- dbDriver,
68
- dbConfig,
69
- persistence,
70
- }
71
- }
72
-
73
- private static setupDatabase(driver: 'sqlite' | 'mysql', config: ServerConfig['dbConfig']): void {
74
- if (driver === 'sqlite') {
75
- DB.addConnection('default', {
76
- driver: 'sqlite',
77
- database: config.name,
78
- })
79
- } else {
80
- DB.addConnection('default', {
81
- driver,
82
- host: config.host,
83
- port: config.port,
84
- database: config.name,
85
- username: config.username,
86
- password: config.password,
87
- })
88
- }
89
- }
90
- }