@gravito/zenith 1.0.1 → 1.1.1

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 (46) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/ECOSYSTEM_EXPANSION_RFC.md +130 -0
  3. package/dist/bin.js +11945 -4241
  4. package/dist/client/assets/index-BSMp8oq_.js +436 -0
  5. package/dist/client/assets/index-BwxlHx-_.css +1 -0
  6. package/dist/client/index.html +2 -2
  7. package/dist/server/index.js +11945 -4241
  8. package/package.json +1 -1
  9. package/scripts/verify-throttle.ts +6 -2
  10. package/scripts/worker.ts +2 -1
  11. package/src/client/Layout.tsx +10 -0
  12. package/src/client/Sidebar.tsx +9 -0
  13. package/src/client/ThroughputChart.tsx +9 -0
  14. package/src/client/WorkerStatus.tsx +14 -3
  15. package/src/client/components/BrandIcons.tsx +30 -0
  16. package/src/client/components/ConfirmDialog.tsx +24 -0
  17. package/src/client/components/JobInspector.tsx +18 -0
  18. package/src/client/components/LogArchiveModal.tsx +51 -2
  19. package/src/client/components/NotificationBell.tsx +9 -0
  20. package/src/client/components/PageHeader.tsx +9 -0
  21. package/src/client/components/Toaster.tsx +10 -0
  22. package/src/client/components/UserProfileDropdown.tsx +9 -0
  23. package/src/client/contexts/AuthContext.tsx +12 -0
  24. package/src/client/contexts/NotificationContext.tsx +25 -0
  25. package/src/client/pages/LoginPage.tsx +9 -0
  26. package/src/client/pages/MetricsPage.tsx +9 -0
  27. package/src/client/pages/OverviewPage.tsx +9 -0
  28. package/src/client/pages/PulsePage.tsx +10 -0
  29. package/src/client/pages/QueuesPage.tsx +9 -0
  30. package/src/client/pages/SchedulesPage.tsx +9 -0
  31. package/src/client/pages/SettingsPage.tsx +9 -0
  32. package/src/client/pages/WorkersPage.tsx +10 -0
  33. package/src/client/utils.ts +9 -0
  34. package/src/server/config/ServerConfigManager.ts +87 -0
  35. package/src/server/index.ts +19 -18
  36. package/src/server/services/AlertService.ts +16 -3
  37. package/src/server/services/LogStreamProcessor.ts +93 -0
  38. package/src/server/services/MaintenanceScheduler.ts +78 -0
  39. package/src/server/services/PulseService.ts +12 -1
  40. package/src/server/services/QueueMetricsCollector.ts +138 -0
  41. package/src/server/services/QueueService.ts +29 -283
  42. package/src/shared/types.ts +126 -27
  43. package/vite.config.ts +1 -1
  44. package/DEMO.md +0 -156
  45. package/dist/client/assets/index-C332gZ-J.css +0 -1
  46. package/dist/client/assets/index-D4HibwTK.js +0 -436
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravito/zenith",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "description": "Gravito Zenith: Zero-config control plane for Gravito Flux & Stream",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,8 @@
1
1
  console.log('🎧 Connecting to log stream...')
2
2
  const req = await fetch('http://localhost:3000/api/logs/stream')
3
- if (!req.body) throw new Error('No body')
3
+ if (!req.body) {
4
+ throw new Error('No body')
5
+ }
4
6
 
5
7
  const reader = req.body.getReader()
6
8
  const decoder = new TextDecoder()
@@ -16,7 +18,9 @@ console.log(`⏳ Measuring received logs for ${DURATION}ms...`)
16
18
  async function readStream() {
17
19
  while (true) {
18
20
  const { done, value } = await reader.read()
19
- if (done) break
21
+ if (done) {
22
+ break
23
+ }
20
24
 
21
25
  const chunk = decoder.decode(value)
22
26
  // SSE format: event: log\ndata: ...\n\n
package/scripts/worker.ts CHANGED
@@ -53,7 +53,8 @@ if (queuesRaw === 'all') {
53
53
 
54
54
  const failRate = parseFloat(process.argv.find((a) => a.startsWith('--fail='))?.split('=')[1] || '0')
55
55
  const processDelay = parseInt(
56
- process.argv.find((a) => a.startsWith('--delay='))?.split('=')[1] || '100'
56
+ process.argv.find((a) => a.startsWith('--delay='))?.split('=')[1] || '100',
57
+ 10
57
58
  )
58
59
 
59
60
  // Simple Job class for testing
@@ -42,6 +42,16 @@ interface CommandItem {
42
42
  category: 'Navigation' | 'System' | 'Action'
43
43
  }
44
44
 
45
+ /**
46
+ * The main layout wrapper for the Zenith dashboard.
47
+ *
48
+ * It manages global state for the dashboard, including theme switching,
49
+ * the command palette (Ctrl+K), real-time event streaming (SSE),
50
+ * and the overall responsive structure.
51
+ *
52
+ * @public
53
+ * @since 3.0.0
54
+ */
45
55
  export function Layout({ children }: LayoutProps) {
46
56
  const navigate = useNavigate()
47
57
  const queryClient = useQueryClient()
@@ -18,6 +18,15 @@ interface SidebarProps {
18
18
  toggleCollapse: () => void
19
19
  }
20
20
 
21
+ /**
22
+ * Sidebar navigation component for the Zenith dashboard.
23
+ *
24
+ * Provides links to various sections of the dashboard and supports
25
+ * a collapsible state to maximize screen space.
26
+ *
27
+ * @public
28
+ * @since 3.0.0
29
+ */
21
30
  export function Sidebar({ className, collapsed, toggleCollapse }: SidebarProps) {
22
31
  const location = useLocation()
23
32
 
@@ -15,6 +15,15 @@ interface ThroughputPoint {
15
15
  count: number
16
16
  }
17
17
 
18
+ /**
19
+ * Real-time throughput visualization component.
20
+ *
21
+ * Displays a live-updating area chart of the number of jobs processed
22
+ * per minute across the system.
23
+ *
24
+ * @public
25
+ * @since 3.0.0
26
+ */
18
27
  export function ThroughputChart() {
19
28
  // Initial fetch via React Query
20
29
  const { data: initialData } = useQuery({
@@ -7,18 +7,20 @@ function cn(...inputs: ClassValue[]) {
7
7
  }
8
8
 
9
9
  function formatBytes(bytes: number) {
10
- if (bytes === 0) return '0 B'
10
+ if (bytes === 0) {
11
+ return '0 B'
12
+ }
11
13
  const k = 1024
12
14
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
13
15
  const i = Math.floor(Math.log(bytes) / Math.log(k))
14
- return parseFloat((bytes / k ** i).toFixed(1)) + ' ' + sizes[i]
16
+ return `${parseFloat((bytes / k ** i).toFixed(1))} ${sizes[i]}`
15
17
  }
16
18
 
17
19
  function getWorkerName(id: string, pid: number) {
18
20
  // If ID contains Hostname+PID, try to simplify it
19
21
  // Example: CarldeMacBook-Air.local-99401
20
22
  const complexIdMatch = id.match(/^(.*)-(\d+)$/)
21
- if (complexIdMatch && parseInt(complexIdMatch[2]) === pid) {
23
+ if (complexIdMatch && parseInt(complexIdMatch[2], 10) === pid) {
22
24
  // Return just the hostname part, and maybe truncate if too long
23
25
  let hostname = complexIdMatch[1]
24
26
  if (hostname.endsWith('.local')) {
@@ -51,6 +53,15 @@ interface WorkerInfo {
51
53
  }
52
54
  }
53
55
 
56
+ /**
57
+ * Real-time worker node status visualization component.
58
+ *
59
+ * Displays a list of active worker nodes with their CPU, RAM, uptime metrics,
60
+ * and highlights a specific worker if provided.
61
+ *
62
+ * @public
63
+ * @since 3.0.0
64
+ */
54
65
  export function WorkerStatus({
55
66
  highlightedWorkerId,
56
67
  workers = [],
@@ -1,5 +1,10 @@
1
1
  import type { SVGProps } from 'react'
2
2
 
3
+ /**
4
+ * SVG icon for Node.js runtime.
5
+ * @public
6
+ * @since 3.0.0
7
+ */
3
8
  export function NodeIcon(props: SVGProps<SVGSVGElement>) {
4
9
  return (
5
10
  <svg
@@ -19,6 +24,11 @@ export function NodeIcon(props: SVGProps<SVGSVGElement>) {
19
24
  )
20
25
  }
21
26
 
27
+ /**
28
+ * SVG icon for Bun runtime.
29
+ * @public
30
+ * @since 3.0.0
31
+ */
22
32
  export function BunIcon(props: SVGProps<SVGSVGElement>) {
23
33
  return (
24
34
  <svg
@@ -49,6 +59,11 @@ export function BunIcon(props: SVGProps<SVGSVGElement>) {
49
59
  )
50
60
  }
51
61
 
62
+ /**
63
+ * SVG icon for Deno runtime.
64
+ * @public
65
+ * @since 3.0.0
66
+ */
52
67
  export function DenoIcon(props: SVGProps<SVGSVGElement>) {
53
68
  return (
54
69
  <svg
@@ -69,6 +84,11 @@ export function DenoIcon(props: SVGProps<SVGSVGElement>) {
69
84
  )
70
85
  }
71
86
 
87
+ /**
88
+ * SVG icon for PHP runtime.
89
+ * @public
90
+ * @since 3.0.0
91
+ */
72
92
  export function PhpIcon(props: SVGProps<SVGSVGElement>) {
73
93
  return (
74
94
  <svg
@@ -95,6 +115,11 @@ export function PhpIcon(props: SVGProps<SVGSVGElement>) {
95
115
  )
96
116
  }
97
117
 
118
+ /**
119
+ * SVG icon for Go runtime.
120
+ * @public
121
+ * @since 3.0.0
122
+ */
98
123
  export function GoIcon(props: SVGProps<SVGSVGElement>) {
99
124
  return (
100
125
  <svg
@@ -115,6 +140,11 @@ export function GoIcon(props: SVGProps<SVGSVGElement>) {
115
140
  )
116
141
  }
117
142
 
143
+ /**
144
+ * SVG icon for Python runtime.
145
+ * @public
146
+ * @since 3.0.0
147
+ */
118
148
  export function PythonIcon(props: SVGProps<SVGSVGElement>) {
119
149
  return (
120
150
  <svg
@@ -2,18 +2,42 @@ import { AnimatePresence, motion } from 'framer-motion'
2
2
  import { createPortal } from 'react-dom'
3
3
  import { cn } from '../utils'
4
4
 
5
+ /**
6
+ * Props for the ConfirmDialog component.
7
+ *
8
+ * @public
9
+ * @since 3.0.0
10
+ */
5
11
  export interface ConfirmDialogProps {
12
+ /** Whether the dialog is visible. */
6
13
  open: boolean
14
+ /** Dialog title text. */
7
15
  title: string
16
+ /** Detailed confirmation message. */
8
17
  message: string
18
+ /** Text for the confirmation button. @default 'Confirm' */
9
19
  confirmText?: string
20
+ /** Text for the cancel button. @default 'Cancel' */
10
21
  cancelText?: string
22
+ /** Callback triggered when user confirms the action. */
11
23
  onConfirm: () => void
24
+ /** Callback triggered when user cancels the action. */
12
25
  onCancel: () => void
26
+ /** Visual style of the confirmation button. @default 'danger' */
13
27
  variant?: 'danger' | 'warning' | 'info'
28
+ /** Whether an action is currently in progress (shows a spinner). @default false */
14
29
  isProcessing?: boolean
15
30
  }
16
31
 
32
+ /**
33
+ * A modal dialog used for user confirmation before performing sensitive actions.
34
+ *
35
+ * It provides a consistent UI for confirmations across the Zenith dashboard
36
+ * and supports different visual variants.
37
+ *
38
+ * @public
39
+ * @since 3.0.0
40
+ */
17
41
  export function ConfirmDialog({
18
42
  open,
19
43
  title,
@@ -21,11 +21,29 @@ interface Job {
21
21
  _archivedAt?: string
22
22
  }
23
23
 
24
+ /**
25
+ * Props for the JobInspector component.
26
+ *
27
+ * @public
28
+ * @since 3.0.0
29
+ */
24
30
  export interface JobInspectorProps {
31
+ /** The name of the queue to inspect. */
25
32
  queueName: string
33
+ /** Callback triggered when the inspector is closed. */
26
34
  onClose: () => void
27
35
  }
28
36
 
37
+ /**
38
+ * A detailed view for inspecting jobs within a specific queue.
39
+ *
40
+ * It provides tabs for viewing waiting, delayed, and failed jobs,
41
+ * as well as an archive search. Users can perform bulk actions like
42
+ * deleting or retrying jobs.
43
+ *
44
+ * @public
45
+ * @since 3.0.0
46
+ */
29
47
  export function JobInspector({ queueName, onClose }: JobInspectorProps) {
30
48
  const [view, setView] = React.useState<'waiting' | 'delayed' | 'failed' | 'archive'>('waiting')
31
49
  const [page, setPage] = React.useState(1)
@@ -17,6 +17,15 @@ interface LogArchiveModalProps {
17
17
  onClose: () => void
18
18
  }
19
19
 
20
+ /**
21
+ * A modal for exploring and searching historical application logs and job events.
22
+ *
23
+ * It provides advanced filtering by search query, time range, and severity level.
24
+ * Users can trace specific events across time and export the audit trail.
25
+ *
26
+ * @public
27
+ * @since 3.0.0
28
+ */
20
29
  export function LogArchiveModal({ isOpen, onClose }: LogArchiveModalProps) {
21
30
  const [page, setPage] = React.useState(1)
22
31
  const [search, setSearch] = React.useState('')
@@ -329,9 +338,49 @@ export function LogArchiveModal({ isOpen, onClose }: LogArchiveModalProps) {
329
338
 
330
339
  {/* Footer / Pagination */}
331
340
  <div className="p-4 border-t bg-muted/5 flex flex-col sm:flex-row justify-between items-center gap-4 text-[10px] uppercase font-bold text-muted-foreground">
332
- <div>
333
- Scanning {total.toLocaleString()} events • Page {page} of {totalPages || 1}
341
+ <div className="flex items-center gap-4">
342
+ <span>
343
+ Scanning {total.toLocaleString()} events • Page {page} of {totalPages || 1}
344
+ </span>
345
+
346
+ <div className="h-4 w-px bg-border/50 hidden sm:block"></div>
347
+
348
+ {/* Export Controls */}
349
+ <div className="flex items-center gap-2">
350
+ <select
351
+ className="bg-background border border-border/50 rounded-lg px-2 py-1 outline-none focus:ring-1 focus:ring-primary/30"
352
+ onChange={(e) => {
353
+ // Trigger export
354
+ const format = e.target.value
355
+ const url = new URL('/api/logs/export', window.location.href)
356
+ if (search) {
357
+ url.searchParams.set('search', search)
358
+ }
359
+ if (status !== 'all') {
360
+ url.searchParams.set('status', status)
361
+ }
362
+ if (dateRange.start) {
363
+ url.searchParams.set('startTime', dateRange.start)
364
+ }
365
+ if (dateRange.end) {
366
+ url.searchParams.set('endTime', dateRange.end)
367
+ }
368
+ url.searchParams.set('format', format)
369
+
370
+ // For now, just open in new tab to trigger download
371
+ window.open(url.toString(), '_blank')
372
+ }}
373
+ defaultValue=""
374
+ >
375
+ <option value="" disabled>
376
+ Export As...
377
+ </option>
378
+ <option value="json">JSON</option>
379
+ <option value="csv">CSV</option>
380
+ </select>
381
+ </div>
334
382
  </div>
383
+
335
384
  <div className="flex items-center gap-2">
336
385
  <button
337
386
  type="button"
@@ -13,6 +13,15 @@ import { useEffect, useRef, useState } from 'react'
13
13
  import { type Notification, useNotifications } from '../contexts/NotificationContext'
14
14
  import { cn } from '../utils'
15
15
 
16
+ /**
17
+ * A notification bell icon component with a dropdown panel.
18
+ *
19
+ * Displays the unread notification count and provides a list view of recent
20
+ * system notifications with mark-as-read and clear-all functionality.
21
+ *
22
+ * @public
23
+ * @since 3.0.0
24
+ */
16
25
  export function NotificationBell() {
17
26
  const [isOpen, setIsOpen] = useState(false)
18
27
  const { notifications, unreadCount, markAsRead, markAllAsRead, clearAll, removeNotification } =
@@ -10,6 +10,15 @@ interface PageHeaderProps {
10
10
  className?: string
11
11
  }
12
12
 
13
+ /**
14
+ * Reusable header component for Zenith dashboard pages.
15
+ *
16
+ * Provides a consistent layout for the page title, icon, description,
17
+ * and optional action buttons.
18
+ *
19
+ * @public
20
+ * @since 3.0.0
21
+ */
13
22
  export function PageHeader({
14
23
  icon: Icon,
15
24
  title,
@@ -4,6 +4,16 @@ import { useEffect, useState } from 'react'
4
4
  import { useNotifications } from '../contexts/NotificationContext'
5
5
  import { cn } from '../utils'
6
6
 
7
+ /**
8
+ * Global toast notification container for Zenith.
9
+ *
10
+ * Renders an animated stack of floating notifications in the corner of the
11
+ * screen. It integrates with the `NotificationContext` to display real-time
12
+ * alerts and messages.
13
+ *
14
+ * @public
15
+ * @since 3.0.0
16
+ */
7
17
  export function Toaster() {
8
18
  const { notifications, removeNotification } = useNotifications()
9
19
  const [activeIds, setActiveIds] = useState<Set<string>>(new Set())
@@ -5,6 +5,15 @@ import { useEffect, useRef, useState } from 'react'
5
5
  import { useNavigate } from 'react-router-dom'
6
6
  import { useAuth } from '../contexts/AuthContext'
7
7
 
8
+ /**
9
+ * A user profile dropdown component for the Zenith dashboard.
10
+ *
11
+ * Displays current user information, system uptime, and provides access
12
+ * to settings and logout functionality.
13
+ *
14
+ * @public
15
+ * @since 3.0.0
16
+ */
8
17
  export function UserProfileDropdown() {
9
18
  const [isOpen, setIsOpen] = useState(false)
10
19
  const { isAuthEnabled, logout } = useAuth()
@@ -11,6 +11,12 @@ interface AuthContextType {
11
11
 
12
12
  const AuthContext = createContext<AuthContextType | null>(null)
13
13
 
14
+ /**
15
+ * React hook to access authentication state and methods.
16
+ *
17
+ * @public
18
+ * @since 3.0.0
19
+ */
14
20
  export function useAuth() {
15
21
  const context = useContext(AuthContext)
16
22
  if (!context) {
@@ -23,6 +29,12 @@ interface AuthProviderProps {
23
29
  children: ReactNode
24
30
  }
25
31
 
32
+ /**
33
+ * Provider component for managing global authentication state in Zenith.
34
+ *
35
+ * @public
36
+ * @since 3.0.0
37
+ */
26
38
  export function AuthProvider({ children }: AuthProviderProps) {
27
39
  const [isAuthenticated, setIsAuthenticated] = useState(false)
28
40
  const [isAuthEnabled, setIsAuthEnabled] = useState(false)
@@ -1,12 +1,25 @@
1
1
  import { createContext, type ReactNode, useCallback, useContext, useEffect, useState } from 'react'
2
2
 
3
+ /**
4
+ * Represents a system notification in the Zenith dashboard.
5
+ *
6
+ * @public
7
+ * @since 3.0.0
8
+ */
3
9
  export interface Notification {
10
+ /** Unique notification ID. */
4
11
  id: string
12
+ /** The severity type of the notification. */
5
13
  type: 'info' | 'success' | 'warning' | 'error'
14
+ /** Short title for the notification. */
6
15
  title: string
16
+ /** Detailed notification message. */
7
17
  message: string
18
+ /** Epoch timestamp when the notification was created. */
8
19
  timestamp: number
20
+ /** Whether the notification has been read by the user. */
9
21
  read: boolean
22
+ /** Optional source identifier (e.g., a queue name). */
10
23
  source?: string
11
24
  }
12
25
 
@@ -22,6 +35,12 @@ interface NotificationContextType {
22
35
 
23
36
  const NotificationContext = createContext<NotificationContextType | null>(null)
24
37
 
38
+ /**
39
+ * React hook to access the notification system.
40
+ *
41
+ * @public
42
+ * @since 3.0.0
43
+ */
25
44
  export function useNotifications() {
26
45
  const context = useContext(NotificationContext)
27
46
  if (!context) {
@@ -34,6 +53,12 @@ interface NotificationProviderProps {
34
53
  children: ReactNode
35
54
  }
36
55
 
56
+ /**
57
+ * Provider component for managing global notifications in Zenith.
58
+ *
59
+ * @public
60
+ * @since 3.0.0
61
+ */
37
62
  export function NotificationProvider({ children }: NotificationProviderProps) {
38
63
  const [notifications, setNotifications] = useState<Notification[]>([])
39
64
 
@@ -4,6 +4,15 @@ import { useState } from 'react'
4
4
  import { useAuth } from '../contexts/AuthContext'
5
5
  import { cn } from '../utils'
6
6
 
7
+ /**
8
+ * The login page for the Zenith dashboard.
9
+ *
10
+ * Provides a secure, password-protected entry point to the administration
11
+ * console with modern UI effects and smooth animations.
12
+ *
13
+ * @public
14
+ * @since 3.0.0
15
+ */
7
16
  export function LoginPage() {
8
17
  const { login } = useAuth()
9
18
  const [password, setPassword] = useState('')
@@ -25,6 +25,15 @@ import {
25
25
  } from 'recharts'
26
26
  import { cn } from '../utils'
27
27
 
28
+ /**
29
+ * System Metrics Page.
30
+ *
31
+ * Displays detailed performance analytics, throughput trends, and queue
32
+ * distribution charts using interactive visualizations.
33
+ *
34
+ * @public
35
+ * @since 3.0.0
36
+ */
28
37
  export function MetricsPage() {
29
38
  const [timeRange, setTimeRange] = React.useState<'15m' | '1h' | '6h' | '24h'>('15m')
30
39
 
@@ -347,6 +347,15 @@ function QueueList({
347
347
  )
348
348
  }
349
349
 
350
+ /**
351
+ * System Overview Dashboard Page.
352
+ *
353
+ * Provides a high-level, real-time view of all processing pipelines,
354
+ * including job counts, worker status, and live operational logs.
355
+ *
356
+ * @public
357
+ * @since 3.0.0
358
+ */
350
359
  export function OverviewPage() {
351
360
  const [selectedQueue, setSelectedQueue] = React.useState<string | null>(null)
352
361
  const [hoveredWorkerId, setHoveredWorkerId] = React.useState<string | null>(null)
@@ -394,6 +394,16 @@ function ServiceGroup({ service, nodes }: { service: string; nodes: PulseNode[]
394
394
  )
395
395
  }
396
396
 
397
+ /**
398
+ * System Pulse Dashboard Page.
399
+ *
400
+ * Provides real-time resource monitoring (CPU, RAM) and service discovery
401
+ * for all connected Quasar agents. It also allows remote management of
402
+ * connected worker nodes.
403
+ *
404
+ * @public
405
+ * @since 3.0.0
406
+ */
397
407
  export function PulsePage() {
398
408
  const { data: initialData, isLoading } = useQuery<{ nodes: Record<string, PulseNode[]> }>({
399
409
  queryKey: ['pulse-nodes'],
@@ -26,6 +26,15 @@ interface QueueStats {
26
26
  paused?: boolean
27
27
  }
28
28
 
29
+ /**
30
+ * Queue Management Page.
31
+ *
32
+ * Provides detailed monitoring and management controls for message queues,
33
+ * including job inspection, pausing/resuming queues, and bulk retry/purge actions.
34
+ *
35
+ * @public
36
+ * @since 3.0.0
37
+ */
29
38
  export function QueuesPage() {
30
39
  const [selectedQueue, setSelectedQueue] = React.useState<string | null>(null)
31
40
  const [searchQuery, setSearchQuery] = React.useState('')
@@ -45,6 +45,15 @@ interface QueueListItem {
45
45
  paused: boolean
46
46
  }
47
47
 
48
+ /**
49
+ * Task Schedules Page.
50
+ *
51
+ * View and manage all recurring jobs and cron tasks. Users can register new
52
+ * schedules, manually trigger execution, or delete existing schedules.
53
+ *
54
+ * @public
55
+ * @since 3.0.0
56
+ */
48
57
  export function SchedulesPage() {
49
58
  const queryClient = useQueryClient()
50
59
  const [isModalOpen, setIsModalOpen] = useState(false)
@@ -17,6 +17,15 @@ import {
17
17
  import React from 'react'
18
18
  import { cn } from '../utils'
19
19
 
20
+ /**
21
+ * System Settings Page.
22
+ *
23
+ * Allows administrators to configure dashboard appearance, monitoring alerts,
24
+ * and data retention policies. It also provides system-level information.
25
+ *
26
+ * @public
27
+ * @since 3.0.0
28
+ */
20
29
  export function SettingsPage() {
21
30
  const queryClient = useQueryClient()
22
31
  const [showAddRule, setShowAddRule] = React.useState(false)
@@ -35,6 +35,16 @@ interface Worker {
35
35
  }
36
36
  }
37
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
+ */
38
48
  export function WorkersPage() {
39
49
  const queryClient = useQueryClient()
40
50
  const { isPending, error, data } = useQuery<{ workers: Worker[] }>({
@@ -1,6 +1,15 @@
1
1
  import { type ClassValue, clsx } from 'clsx'
2
2
  import { twMerge } from 'tailwind-merge'
3
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
+ */
4
13
  export function cn(...inputs: ClassValue[]) {
5
14
  return twMerge(clsx(inputs))
6
15
  }