@gravito/zenith 1.1.2 → 1.1.3

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 (36) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +77 -22
  3. package/README.zh-TW.md +88 -0
  4. package/dist/bin.js +64681 -15842
  5. package/dist/client/assets/index-C80c1frR.css +1 -0
  6. package/dist/client/assets/index-CrWem9u3.js +434 -0
  7. package/dist/server/index.js +64681 -15842
  8. package/package.json +9 -7
  9. package/postcss.config.js +4 -4
  10. package/src/client/Layout.tsx +36 -39
  11. package/src/client/Sidebar.tsx +7 -7
  12. package/src/client/ThroughputChart.tsx +31 -17
  13. package/src/client/WorkerStatus.tsx +56 -80
  14. package/src/client/components/ConfirmDialog.tsx +22 -14
  15. package/src/client/components/JobInspector.tsx +95 -162
  16. package/src/client/index.css +29 -31
  17. package/src/client/pages/LoginPage.tsx +33 -31
  18. package/src/client/pages/MetricsPage.tsx +65 -37
  19. package/src/client/pages/OverviewPage.tsx +30 -28
  20. package/src/client/pages/PulsePage.tsx +111 -190
  21. package/src/client/pages/QueuesPage.tsx +82 -83
  22. package/src/client/pages/SchedulesPage.tsx +56 -61
  23. package/src/client/pages/SettingsPage.tsx +118 -137
  24. package/src/client/pages/WorkersPage.tsx +101 -115
  25. package/src/server/services/CommandService.ts +8 -9
  26. package/src/server/services/PulseService.ts +61 -4
  27. package/src/server/services/QueueService.ts +293 -0
  28. package/src/shared/types.ts +38 -13
  29. package/tailwind.config.js +75 -68
  30. package/tsconfig.json +28 -37
  31. package/tsconfig.node.json +9 -11
  32. package/dist/client/assets/index-BSMp8oq_.js +0 -436
  33. package/dist/client/assets/index-BwxlHx-_.css +0 -1
  34. package/dist/client/index.html +0 -13
  35. package/src/client/index.html +0 -12
  36. /package/{ECOSYSTEM_EXPANSION_RFC.md → doc/ECOSYSTEM_EXPANSION_RFC.md} +0 -0
@@ -1,14 +1,12 @@
1
1
  import { useQuery, useQueryClient } from '@tanstack/react-query'
2
2
  import {
3
3
  Bell,
4
- Clock,
5
4
  Database,
6
5
  ExternalLink,
7
6
  Info,
8
7
  Monitor,
9
8
  Moon,
10
9
  Palette,
11
- RefreshCcw,
12
10
  Server,
13
11
  Shield,
14
12
  Sun,
@@ -82,43 +80,48 @@ export function SettingsPage() {
82
80
  </div>
83
81
 
84
82
  {/* Appearance Section */}
85
- <section className="card-premium p-6">
86
- <div className="flex items-center gap-3 mb-6">
87
- <div className="w-10 h-10 rounded-xl bg-primary/10 flex items-center justify-center text-primary">
88
- <Palette size={20} />
83
+ <section className="card-premium p-6 border-l-4 border-primary">
84
+ <div className="flex items-center gap-4 mb-8">
85
+ <div className="w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center text-primary border border-primary/20 shadow-[0_0_15px_rgba(0,240,255,0.1)]">
86
+ <Palette size={24} />
89
87
  </div>
90
88
  <div>
91
- <h2 className="text-lg font-bold">Appearance</h2>
92
- <p className="text-[10px] text-muted-foreground uppercase tracking-widest font-bold">
93
- Customize the look and feel
89
+ <h2 className="text-xl font-black font-heading tracking-tight">
90
+ Appearance Architecture
91
+ </h2>
92
+ <p className="text-[10px] text-muted-foreground uppercase tracking-[0.2em] font-black opacity-50 mt-0.5">
93
+ Customize Visual Interface
94
94
  </p>
95
95
  </div>
96
96
  </div>
97
97
 
98
- <div className="space-y-4">
98
+ <div className="space-y-6">
99
99
  <div>
100
- <label htmlFor="theme-select" className="text-sm font-bold mb-3 block">
101
- Theme
100
+ <label
101
+ htmlFor="theme-select"
102
+ className="text-[10px] font-black uppercase tracking-widest mb-4 block text-muted-foreground ml-1"
103
+ >
104
+ Interface Mode
102
105
  </label>
103
- <div id="theme-select" className="flex gap-3">
106
+ <div id="theme-select" className="flex gap-4">
104
107
  {[
105
- { value: 'light', icon: Sun, label: 'Light' },
106
- { value: 'dark', icon: Moon, label: 'Dark' },
107
- { value: 'system', icon: Monitor, label: 'System' },
108
+ { value: 'light', icon: Sun, label: 'Standard' },
109
+ { value: 'dark', icon: Moon, label: 'Quantum' },
110
+ { value: 'system', icon: Monitor, label: 'Auto' },
108
111
  ].map(({ value, icon: Icon, label }) => (
109
112
  <button
110
113
  type="button"
111
114
  key={value}
112
115
  onClick={() => handleThemeChange(value as 'light' | 'dark' | 'system')}
113
116
  className={cn(
114
- 'flex-1 flex items-center justify-center gap-2 px-4 py-3 rounded-xl border transition-all',
117
+ 'flex-1 flex items-center justify-center gap-3 px-4 py-4 rounded-xl border transition-all font-heading uppercase text-[11px] font-black tracking-widest',
115
118
  theme === value
116
- ? 'bg-primary text-primary-foreground border-primary'
117
- : 'bg-muted/40 border-border/50 hover:border-primary/30'
119
+ ? 'bg-primary text-black border-primary shadow-[0_0_30px_rgba(0,240,255,0.2)] scale-[1.02]'
120
+ : 'bg-zinc-900/40 border-white/5 hover:border-primary/30 text-muted-foreground hover:text-foreground'
118
121
  )}
119
122
  >
120
123
  <Icon size={18} />
121
- <span className="font-bold text-sm">{label}</span>
124
+ <span>{label}</span>
122
125
  </button>
123
126
  ))}
124
127
  </div>
@@ -127,119 +130,107 @@ export function SettingsPage() {
127
130
  </section>
128
131
 
129
132
  {/* Connection Info Section */}
130
- <section className="card-premium p-6">
131
- <div className="flex items-center gap-3 mb-6">
132
- <div className="w-10 h-10 rounded-xl bg-indigo-500/10 flex items-center justify-center text-indigo-500">
133
- <Database size={20} />
133
+ <section className="card-premium p-6 border-l-4 border-indigo-500/40">
134
+ <div className="flex items-center gap-4 mb-8">
135
+ <div className="w-12 h-12 rounded-xl bg-indigo-500/10 flex items-center justify-center text-indigo-400 border border-indigo-500/20 shadow-[0_0_15px_rgba(99,102,241,0.1)]">
136
+ <Database size={24} />
134
137
  </div>
135
138
  <div>
136
- <h2 className="text-lg font-bold">Connection Status</h2>
137
- <p className="text-[10px] text-muted-foreground uppercase tracking-widest font-bold">
138
- Redis and system connectivity
139
+ <h2 className="text-xl font-black font-heading tracking-tight">Quantum Connectivity</h2>
140
+ <p className="text-[10px] text-muted-foreground uppercase tracking-[0.2em] font-black opacity-50 mt-0.5">
141
+ Infrastructure Bridge Status
139
142
  </p>
140
143
  </div>
141
144
  </div>
142
145
 
143
- <div className="space-y-4">
144
- <div className="flex items-center justify-between py-3 border-b border-border/30">
146
+ <div className="space-y-2 font-mono">
147
+ <div className="flex items-center justify-between py-4 border-b border-white/5 group">
145
148
  <div className="flex items-center gap-3">
146
- <Server size={16} className="text-muted-foreground" />
147
- <span className="font-medium">Redis Connection</span>
149
+ <Server
150
+ size={16}
151
+ className="text-muted-foreground group-hover:text-primary transition-colors"
152
+ />
153
+ <span className="text-xs font-bold uppercase tracking-widest text-muted-foreground">
154
+ Redis Protocol
155
+ </span>
148
156
  </div>
149
- <div className="flex items-center gap-2">
150
- <span className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></span>
151
- <span className="text-sm font-bold text-green-500">Connected</span>
157
+ <div className="flex items-center gap-3">
158
+ <span className="w-2 h-2 bg-emerald-500 rounded-full glow-pulse shadow-[0_0_10px_#10B981]"></span>
159
+ <span className="text-xs font-black text-emerald-500 uppercase tracking-[0.2em]">
160
+ Established
161
+ </span>
152
162
  </div>
153
163
  </div>
154
164
 
155
- <div className="flex items-center justify-between py-3 border-b border-border/30">
165
+ <div className="flex items-center justify-between py-4 border-b border-white/5 group">
156
166
  <div className="flex items-center gap-3">
157
- <Database size={16} className="text-muted-foreground" />
158
- <span className="font-medium">Redis URL</span>
167
+ <Database
168
+ size={16}
169
+ className="text-muted-foreground group-hover:text-primary transition-colors"
170
+ />
171
+ <span className="text-xs font-bold uppercase tracking-widest text-muted-foreground">
172
+ Endpoint URI
173
+ </span>
159
174
  </div>
160
- <code className="text-sm bg-muted px-2 py-1 rounded font-mono">
175
+ <code className="text-[11px] bg-black/40 px-3 py-1.5 rounded-lg border border-white/5 text-primary">
161
176
  {systemStatus?.redisUrl || 'redis://localhost:6379'}
162
177
  </code>
163
178
  </div>
164
-
165
- <div className="flex items-center justify-between py-3 border-b border-border/30">
166
- <div className="flex items-center gap-3">
167
- <Clock size={16} className="text-muted-foreground" />
168
- <span className="font-medium">Service Uptime</span>
169
- </div>
170
- <span className="text-sm font-mono font-bold">
171
- {systemStatus?.uptime ? formatUptime(systemStatus.uptime) : 'Loading...'}
172
- </span>
173
- </div>
174
-
175
- <div className="flex items-center justify-between py-3">
176
- <div className="flex items-center gap-3">
177
- <RefreshCcw size={16} className="text-muted-foreground" />
178
- <span className="font-medium">Engine Version</span>
179
- </div>
180
- <span className="text-sm font-bold">{systemStatus?.engine || 'Loading...'}</span>
181
- </div>
182
179
  </div>
183
180
  </section>
184
181
 
185
182
  {/* System Info Section */}
186
- <section className="card-premium p-6">
187
- <div className="flex items-center gap-3 mb-6">
188
- <div className="w-10 h-10 rounded-xl bg-green-500/10 flex items-center justify-center text-green-500">
189
- <Info size={20} />
183
+ <section className="card-premium p-6 border-l-4 border-emerald-500/40">
184
+ <div className="flex items-center gap-4 mb-8">
185
+ <div className="w-12 h-12 rounded-xl bg-emerald-500/10 flex items-center justify-center text-emerald-400 border border-emerald-500/20 shadow-[0_0_15px_rgba(16,185,129,0.1)]">
186
+ <Info size={24} />
190
187
  </div>
191
188
  <div>
192
- <h2 className="text-lg font-bold">System Information</h2>
193
- <p className="text-[10px] text-muted-foreground uppercase tracking-widest font-bold">
194
- Runtime and memory details
189
+ <h2 className="text-xl font-black font-heading tracking-tight">Quantum Runtime</h2>
190
+ <p className="text-[10px] text-muted-foreground uppercase tracking-[0.2em] font-black opacity-50 mt-0.5">
191
+ Kernel Environment & Metrics
195
192
  </p>
196
193
  </div>
197
194
  </div>
198
195
 
199
- <div className="grid grid-cols-2 gap-4">
200
- <div className="bg-muted/20 rounded-xl p-4">
201
- <p className="text-[10px] font-black text-muted-foreground/50 uppercase tracking-widest mb-1">
202
- Node.js Version
196
+ <div className="grid grid-cols-2 md:grid-cols-3 gap-4">
197
+ <div className="bg-black/40 rounded-xl p-5 border border-white/5 group hover:border-primary/20 transition-all flex flex-col justify-between">
198
+ <p className="text-[9px] font-black text-muted-foreground/40 uppercase tracking-widest mb-2">
199
+ Runtime Engine
203
200
  </p>
204
- <p className="text-lg font-mono font-bold">{systemStatus?.node || '...'}</p>
205
- </div>
206
- <div className="bg-muted/20 rounded-xl p-4">
207
- <p className="text-[10px] font-black text-muted-foreground/50 uppercase tracking-widest mb-1">
208
- Environment
201
+ <p className="text-lg font-mono font-black text-primary/80">
202
+ {systemStatus?.node || '...'}
209
203
  </p>
210
- <p className="text-lg font-mono font-bold">{systemStatus?.env || '...'}</p>
211
204
  </div>
212
- <div className="bg-muted/20 rounded-xl p-4">
213
- <p className="text-[10px] font-black text-muted-foreground/50 uppercase tracking-widest mb-1">
214
- Memory (RSS)
205
+ <div className="bg-black/40 rounded-xl p-5 border border-white/5 group hover:border-primary/20 transition-all flex flex-col justify-between">
206
+ <p className="text-[9px] font-black text-muted-foreground/40 uppercase tracking-widest mb-2">
207
+ Namespace
215
208
  </p>
216
- <p className="text-lg font-mono font-bold">{systemStatus?.memory?.rss || '...'}</p>
217
- </div>
218
- <div className="bg-muted/20 rounded-xl p-4">
219
- <p className="text-[10px] font-black text-muted-foreground/50 uppercase tracking-widest mb-1">
220
- Heap Used
209
+ <p className="text-sm font-mono font-black text-white/60 uppercase truncate">
210
+ {systemStatus?.env || '...'}
221
211
  </p>
222
- <p className="text-lg font-mono font-bold">{systemStatus?.memory?.heapUsed || '...'}</p>
223
212
  </div>
224
- <div className="bg-muted/20 rounded-xl p-4">
225
- <p className="text-[10px] font-black text-muted-foreground/50 uppercase tracking-widest mb-1">
226
- Total System RAM
213
+ <div className="bg-black/40 rounded-xl p-5 border border-white/5 group hover:border-primary/20 transition-all flex flex-col justify-between">
214
+ <p className="text-[9px] font-black text-muted-foreground/40 uppercase tracking-widest mb-2">
215
+ Memory Footprint
216
+ </p>
217
+ <p className="text-lg font-mono font-black text-white/80 tracking-tighter">
218
+ {systemStatus?.memory?.rss || '...'}
227
219
  </p>
228
- <p className="text-lg font-mono font-bold">{systemStatus?.memory?.total || '...'}</p>
229
220
  </div>
230
221
  </div>
231
222
  </section>
232
223
 
233
224
  {/* Alerting Section */}
234
- <section className="card-premium p-6">
235
- <div className="flex items-center gap-3 mb-6">
236
- <div className="w-10 h-10 rounded-xl bg-orange-500/10 flex items-center justify-center text-orange-500">
237
- <Bell size={20} />
225
+ <section className="card-premium p-6 border-l-4 border-orange-500/60">
226
+ <div className="flex items-center gap-4 mb-8">
227
+ <div className="w-12 h-12 rounded-xl bg-orange-500/10 flex items-center justify-center text-orange-500 border border-orange-500/20 shadow-[0_0_15px_rgba(249,115,22,0.1)]">
228
+ <Bell size={24} />
238
229
  </div>
239
230
  <div>
240
- <h2 className="text-lg font-bold">Alerting & Notifications</h2>
241
- <p className="text-[10px] text-muted-foreground uppercase tracking-widest font-bold">
242
- System health and failure monitoring
231
+ <h2 className="text-xl font-black font-heading tracking-tight">Signal Monitoring</h2>
232
+ <p className="text-[10px] text-muted-foreground uppercase tracking-[0.2em] font-black opacity-50 mt-0.5">
233
+ Automated Incident Alerting
243
234
  </p>
244
235
  </div>
245
236
  </div>
@@ -247,21 +238,23 @@ export function SettingsPage() {
247
238
  <div className="space-y-8">
248
239
  {/* Notification Channels */}
249
240
  <div className="space-y-4">
250
- <h3 className="text-xs font-black uppercase tracking-widest text-muted-foreground/60 mb-2">
251
- Notification Channels
241
+ <h3 className="text-[10px] font-black uppercase tracking-[0.3em] text-muted-foreground/40 mb-4 ml-1">
242
+ Communication Transports
252
243
  </h3>
253
244
 
254
245
  {/* Slack */}
255
- <div className="p-4 bg-muted/20 rounded-xl border border-border/10">
256
- <div className="flex items-center justify-between mb-4">
257
- <div className="flex items-center gap-3">
258
- <div className="w-8 h-8 rounded-lg bg-[#4A154B]/10 flex items-center justify-center text-[#4A154B] dark:text-[#E01E5A]">
259
- <Bell size={16} />
246
+ <div className="p-5 bg-zinc-900/40 rounded-2xl border border-white/5 group hover:border-primary/20 transition-all">
247
+ <div className="flex items-center justify-between mb-5">
248
+ <div className="flex items-center gap-4">
249
+ <div className="w-10 h-10 rounded-xl bg-white/5 flex items-center justify-center text-white/60 group-hover:text-primary transition-colors">
250
+ <Bell size={18} />
260
251
  </div>
261
252
  <div>
262
- <h4 className="text-sm font-bold">Slack</h4>
263
- <p className="text-[10px] text-muted-foreground font-medium uppercase tracking-tighter">
264
- Standard notification webhook
253
+ <h4 className="text-sm font-black font-heading text-white tracking-widest uppercase">
254
+ Slack Bridge
255
+ </h4>
256
+ <p className="text-[9px] text-muted-foreground font-bold uppercase tracking-tighter opacity-40">
257
+ Standard Event Webhook
265
258
  </p>
266
259
  </div>
267
260
  </div>
@@ -284,19 +277,19 @@ export function SettingsPage() {
284
277
  queryClient.invalidateQueries({ queryKey: ['alerts-config'] })
285
278
  }}
286
279
  className={cn(
287
- 'px-3 py-1 rounded-full text-[10px] font-black uppercase tracking-widest transition-all',
280
+ 'px-4 py-1.5 rounded-lg text-[9px] font-black uppercase tracking-widest transition-all border font-mono',
288
281
  alertConfig?.config?.channels?.slack?.enabled
289
- ? 'bg-green-500 text-white shadow-lg shadow-green-500/20'
290
- : 'bg-muted-foreground/20 text-muted-foreground'
282
+ ? 'bg-emerald-500/10 text-emerald-500 border-emerald-500/40 shadow-[0_0_15px_rgba(16,185,129,0.1)]'
283
+ : 'bg-zinc-800 text-muted-foreground border-transparent opacity-40 hover:opacity-100'
291
284
  )}
292
285
  >
293
- {alertConfig?.config?.channels?.slack?.enabled ? 'Enabled' : 'Disabled'}
286
+ {alertConfig?.config?.channels?.slack?.enabled ? 'Online' : 'Offline'}
294
287
  </button>
295
288
  </div>
296
289
  <div className="flex gap-3">
297
290
  <input
298
291
  type="password"
299
- placeholder="https://hooks.slack.com/services/..."
292
+ placeholder="SLACK_WEBHOOK_URL"
300
293
  defaultValue={alertConfig?.config?.channels?.slack?.webhookUrl || ''}
301
294
  onBlur={async (e) => {
302
295
  const val = e.target.value
@@ -319,22 +312,24 @@ export function SettingsPage() {
319
312
  })
320
313
  queryClient.invalidateQueries({ queryKey: ['alerts-config'] })
321
314
  }}
322
- className="flex-1 bg-background/50 border border-border/50 rounded-lg px-3 py-2 text-xs font-mono outline-none focus:ring-1 focus:ring-primary/30"
315
+ className="flex-1 bg-black/40 border border-white/5 rounded-lg px-4 py-3 text-[11px] font-mono outline-none focus:ring-1 focus:ring-primary/30 text-primary/80 placeholder:text-white/5"
323
316
  />
324
317
  </div>
325
318
  </div>
326
319
 
327
320
  {/* Discord */}
328
- <div className="p-4 bg-muted/20 rounded-xl border border-border/10">
329
- <div className="flex items-center justify-between mb-4">
330
- <div className="flex items-center gap-3">
331
- <div className="w-8 h-8 rounded-lg bg-[#5865F2]/10 flex items-center justify-center text-[#5865F2]">
332
- <Monitor size={16} />
321
+ <div className="p-5 bg-zinc-900/40 rounded-2xl border border-white/5 group hover:border-primary/20 transition-all">
322
+ <div className="flex items-center justify-between mb-5">
323
+ <div className="flex items-center gap-4">
324
+ <div className="w-10 h-10 rounded-xl bg-white/5 flex items-center justify-center text-white/60 group-hover:text-[#5865F2] transition-colors">
325
+ <Monitor size={18} />
333
326
  </div>
334
327
  <div>
335
- <h4 className="text-sm font-bold">Discord</h4>
336
- <p className="text-[10px] text-muted-foreground font-medium uppercase tracking-tighter">
337
- Webhook integration for servers
328
+ <h4 className="text-sm font-black font-heading text-white tracking-widest uppercase">
329
+ Discord Relay
330
+ </h4>
331
+ <p className="text-[9px] text-muted-foreground font-bold uppercase tracking-tighter opacity-40">
332
+ Webhook Cluster Transport
338
333
  </p>
339
334
  </div>
340
335
  </div>
@@ -357,19 +352,19 @@ export function SettingsPage() {
357
352
  queryClient.invalidateQueries({ queryKey: ['alerts-config'] })
358
353
  }}
359
354
  className={cn(
360
- 'px-3 py-1 rounded-full text-[10px] font-black uppercase tracking-widest transition-all',
355
+ 'px-4 py-1.5 rounded-lg text-[9px] font-black uppercase tracking-widest transition-all border font-mono',
361
356
  alertConfig?.config?.channels?.discord?.enabled
362
- ? 'bg-green-500 text-white shadow-lg shadow-green-500/20'
363
- : 'bg-muted-foreground/20 text-muted-foreground'
357
+ ? 'bg-[#5865F2]/10 text-[#5865F2] border-[#5865F2]/40 shadow-[0_0_15px_rgba(88,101,242,0.1)]'
358
+ : 'bg-zinc-800 text-muted-foreground border-transparent opacity-40 hover:opacity-100'
364
359
  )}
365
360
  >
366
- {alertConfig?.config?.channels?.discord?.enabled ? 'Enabled' : 'Disabled'}
361
+ {alertConfig?.config?.channels?.discord?.enabled ? 'Online' : 'Offline'}
367
362
  </button>
368
363
  </div>
369
364
  <div className="flex gap-3">
370
365
  <input
371
366
  type="password"
372
- placeholder="https://discord.com/api/webhooks/..."
367
+ placeholder="DISCORD_WEBHOOK_URL"
373
368
  defaultValue={alertConfig?.config?.channels?.discord?.webhookUrl || ''}
374
369
  onBlur={async (e) => {
375
370
  const val = e.target.value
@@ -392,7 +387,7 @@ export function SettingsPage() {
392
387
  })
393
388
  queryClient.invalidateQueries({ queryKey: ['alerts-config'] })
394
389
  }}
395
- className="flex-1 bg-background/50 border border-border/50 rounded-lg px-3 py-2 text-xs font-mono outline-none focus:ring-1 focus:ring-primary/30"
390
+ className="flex-1 bg-black/40 border border-white/5 rounded-lg px-4 py-3 text-[11px] font-mono outline-none focus:ring-1 focus:ring-primary/30 text-primary/80 placeholder:text-white/5"
396
391
  />
397
392
  </div>
398
393
  </div>
@@ -1004,17 +999,3 @@ export function SettingsPage() {
1004
999
  </div>
1005
1000
  )
1006
1001
  }
1007
-
1008
- function formatUptime(seconds: number): string {
1009
- const days = Math.floor(seconds / 86400)
1010
- const hours = Math.floor((seconds % 86400) / 3600)
1011
- const minutes = Math.floor((seconds % 3600) / 60)
1012
-
1013
- if (days > 0) {
1014
- return `${days}d ${hours}h ${minutes}m`
1015
- }
1016
- if (hours > 0) {
1017
- return `${hours}h ${minutes}m`
1018
- }
1019
- return `${minutes}m ${Math.floor(seconds % 60)}s`
1020
- }