Skip to content

Commit 170bc8f

Browse files
authored
Refactor logging, enhance TypeScript type safety, and improve environment variable handling (#79)
* Refactor logging to use slog package, update TypeScript code for better type safety, and enhance environment variable handling - Replaced standard log package with log/slog for structured logging in Go files. - Updated TypeScript code to use `as const` and `satisfies` for improved type safety and clarity. - Refactored environment variable sensitivity checks to use Set for better performance. - Improved handling of user agent detection for Mac platform in shortcuts-utils. - Updated TypeScript configuration to target ES2024 and adjusted deprecation settings. - Enhanced health check and service management functions with clearer error handling. - Removed unused max function in service graph calculations. - Updated YAML utility functions to use `any` type for better flexibility with parsed data. * refactor: update tsconfig to remove deprecated baseUrl and improve path mapping comments
1 parent 61d1fcf commit 170bc8f

36 files changed

+220
-229
lines changed

cli/dashboard/src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ function App() {
8585
}
8686

8787
// Navigation shortcuts (1-6)
88-
const view = keyToView[key]
88+
const view = keyToView[key as keyof typeof keyToView]
8989
if (view) {
9090
event.preventDefault()
9191
setActiveView(view)

cli/dashboard/src/components/LogsMultiPaneView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const HEALTH_FILTER_KEY = 'logs-health-status-filter'
1515
const COLLAPSED_PANES_KEY = 'logs-pane-collapsed-states'
1616

1717
// Valid health statuses
18-
const VALID_HEALTH_STATUSES: readonly HealthStatus[] = ['healthy', 'degraded', 'unhealthy', 'starting', 'unknown']
18+
const VALID_HEALTH_STATUSES = ['healthy', 'degraded', 'unhealthy', 'starting', 'unknown'] as const satisfies readonly HealthStatus[]
1919

2020
// Validator for health filter array
2121
const isValidHealthFilterArray = createStringArrayValidator(VALID_HEALTH_STATUSES)

cli/dashboard/src/components/LogsPane.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export function LogsPane({
108108
const res = await fetch(`/api/logs?service=${serviceName}&tail=500`)
109109
if (res.ok) {
110110
const data = await res.json() as LogEntry[]
111-
setLogs(data || [])
111+
setLogs(data ?? [])
112112
}
113113
} catch (err) {
114114
console.error(`Failed to fetch logs for ${serviceName}:`, err)
@@ -465,10 +465,10 @@ export function LogsPane({
465465

466466
<div className="flex-1 min-w-0 select-text">
467467
<span className="text-muted-foreground text-xs">
468-
[{formatLogTimestamp(log?.timestamp || '')}]
468+
[{formatLogTimestamp(log.timestamp ?? '')}]
469469
</span>
470470
{' '}
471-
<span dangerouslySetInnerHTML={{ __html: convertAnsiToHtml(log?.message || '') }} />
471+
<span dangerouslySetInnerHTML={{ __html: convertAnsiToHtml(log.message ?? '') }} />
472472
</div>
473473

474474
{/* Copy button - appears on hover */}

cli/dashboard/src/components/LogsView.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export function LogsView({ selectedServices, levelFilter }: LogsViewProps = {})
6969
throw new Error(`HTTP error! status: ${res.status}`)
7070
}
7171
const data = await res.json() as LogEntry[]
72-
setLogs(data || [])
72+
setLogs(data ?? [])
7373
} catch (err) {
7474
console.error('Failed to fetch logs:', err)
7575
setLogs([])
@@ -185,7 +185,7 @@ export function LogsView({ selectedServices, levelFilter }: LogsViewProps = {})
185185

186186
const exportLogs = useCallback(() => {
187187
const content = filteredLogs
188-
.map(log => `[${log.timestamp || ''}] [${log.service || ''}] ${log.message || ''}`)
188+
.map(log => `[${log.timestamp ?? ''}] [${log.service ?? ''}] ${log.message ?? ''}`)
189189
.join('\n')
190190

191191
const blob = new Blob([content], { type: 'text/plain' })
@@ -300,13 +300,13 @@ export function LogsView({ selectedServices, levelFilter }: LogsViewProps = {})
300300
[{formatLogTimestamp(String(log?.timestamp ?? ''))}]
301301
</span>
302302
{' '}
303-
<span className={getServiceColor(log?.service || 'unknown')}>
304-
[{log?.service || 'unknown'}]
303+
<span className={getServiceColor(log?.service ?? 'unknown')}>
304+
[{log?.service ?? 'unknown'}]
305305
</span>
306306
{' '}
307307
<span
308308
dangerouslySetInnerHTML={{
309-
__html: convertAnsiToHtml(log?.message || '')
309+
__html: convertAnsiToHtml(log?.message ?? '')
310310
}}
311311
/>
312312
</div>

cli/dashboard/src/components/ServiceCard.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function ServiceCard({ service, healthStatus, onClick }: ServiceCardProps
1919
// Use real-time health from health stream if available
2020
// Pass operation state to getEffectiveStatus for optimistic updates
2121
const { status, health: baseHealth } = getEffectiveStatus(service, operationState)
22-
const health = healthStatus?.status || baseHealth
22+
const health = healthStatus?.status ?? baseHealth
2323
const statusDisplay = getStatusDisplay(status, health)
2424
const healthy = isServiceHealthy(status, health)
2525
const Icon = statusDisplay.icon
@@ -84,22 +84,22 @@ export function ServiceCard({ service, healthStatus, onClick }: ServiceCardProps
8484
</div>
8585

8686
{/* Error/Warning Banner - Shown prominently after header */}
87-
{(service.error || healthDetails?.lastError) && (
87+
{(service.error ?? healthDetails?.lastError) && (
8888
<div className="mb-4 p-3 rounded-xl bg-destructive/15 border border-destructive/50">
8989
<div className="flex items-start gap-3">
9090
<XCircle className="w-5 h-5 text-destructive shrink-0 mt-0.5" />
9191
<div className="flex-1 min-w-0">
9292
<p className="font-semibold text-sm text-destructive">Error Detected</p>
9393
<p className="text-xs text-destructive/80 mt-1">
94-
{service.error || healthDetails?.lastError}
94+
{service.error ?? healthDetails?.lastError}
9595
</p>
9696
</div>
9797
</div>
9898
</div>
9999
)}
100100

101101
{/* Degraded Warning Banner */}
102-
{!service.error && !healthDetails?.lastError && health === 'degraded' && (
102+
{!(service.error ?? healthDetails?.lastError) && health === 'degraded' && (
103103
<div className="mb-4 p-3 rounded-xl bg-amber-500/15 border border-amber-500/50">
104104
<div className="flex items-start gap-3">
105105
<AlertTriangle className="w-5 h-5 text-amber-500 shrink-0 mt-0.5" />
@@ -258,18 +258,18 @@ export function ServiceCard({ service, healthStatus, onClick }: ServiceCardProps
258258
)}
259259

260260
{/* Footer */}
261-
{(service.local?.startTime || service.local?.lastChecked || service.startTime || service.lastChecked) && (
261+
{(service.local?.startTime ?? service.local?.lastChecked ?? service.startTime ?? service.lastChecked) && (
262262
<div className="pt-4 border-t border-border space-y-1.5 text-xs text-muted-foreground">
263-
{(service.local?.startTime || service.startTime) && (
263+
{(service.local?.startTime ?? service.startTime) && (
264264
<div className="flex items-center justify-between">
265265
<span>Started</span>
266-
<span className="font-medium">{formatRelativeTime(service.local?.startTime || service.startTime)}</span>
266+
<span className="font-medium">{formatRelativeTime(service.local?.startTime ?? service.startTime)}</span>
267267
</div>
268268
)}
269-
{(service.local?.lastChecked || service.lastChecked) && (
269+
{(service.local?.lastChecked ?? service.lastChecked) && (
270270
<div className="flex items-center justify-between">
271271
<span>Last checked</span>
272-
<span className="font-medium">{formatRelativeTime(service.local?.lastChecked || service.lastChecked)}</span>
272+
<span className="font-medium">{formatRelativeTime(service.local?.lastChecked ?? service.lastChecked)}</span>
273273
</div>
274274
)}
275275
</div>

cli/dashboard/src/components/ServiceTableRow.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export function ServiceTableRow({ service, onViewLogs, onClick, healthStatus }:
2323
// Use real-time health from stream if available (but only when not in operation)
2424
const status = effectiveStatus as 'starting' | 'ready' | 'running' | 'stopping' | 'stopped' | 'error' | 'not-running' | 'restarting'
2525
const health = (operationState === 'idle'
26-
? (healthStatus?.status || effectiveHealth)
26+
? (healthStatus?.status ?? effectiveHealth)
2727
: effectiveHealth) as HealthStatus
2828

2929
const getStatusColor = (status: string, health: string) => {
@@ -67,14 +67,14 @@ export function ServiceTableRow({ service, onViewLogs, onClick, healthStatus }:
6767

6868
{/* Start Time Column */}
6969
<TableCell className="text-muted-foreground">
70-
{formatStartTime(service.local?.startTime || service.startTime)}
70+
{formatStartTime(service.local?.startTime ?? service.startTime)}
7171
</TableCell>
7272

7373
{/* Source Column */}
7474
<TableCell className="max-w-[250px]">
75-
<div className="truncate" title={service.project || service.framework || '-'}>
75+
<div className="truncate" title={service.project ?? service.framework ?? '-'}>
7676
<span className="text-sm text-foreground/90">
77-
{service.project || service.framework || '-'}
77+
{service.project ?? service.framework ?? '-'}
7878
</span>
7979
</div>
8080
</TableCell>

cli/dashboard/src/components/ui/button.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
2525

2626
return (
2727
<button
28-
className={`${baseStyles} ${variantStyles[variant]} ${sizeStyles[size]} ${className || ''}`}
28+
className={`${baseStyles} ${variantStyles[variant]} ${sizeStyles[size]} ${className ?? ''}`}
2929
style={style}
3030
ref={ref}
3131
{...props}

cli/dashboard/src/components/ui/input.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
77
return (
88
<input
99
type={type}
10-
className={`flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 ${className || ''}`}
10+
className={`flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 ${className ?? ''}`}
1111
ref={ref}
1212
{...props}
1313
/>

cli/dashboard/src/components/ui/select.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElemen
77
export function Select({ children, className, ...props }: SelectProps) {
88
return (
99
<select
10-
className={`h-10 w-full rounded-md px-3 py-2 text-sm bg-input-background text-input-foreground border border-input-border focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary hover:border-border-secondary transition-colors disabled:cursor-not-allowed disabled:opacity-50 [&>option]:bg-input-background [&>option]:text-input-foreground ${className || ''}`}
10+
className={`h-10 w-full rounded-md px-3 py-2 text-sm bg-input-background text-input-foreground border border-input-border focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary hover:border-border-secondary transition-colors disabled:cursor-not-allowed disabled:opacity-50 [&>option]:bg-input-background [&>option]:text-input-foreground ${className ?? ''}`}
1111
{...props}
1212
>
1313
{children}

cli/dashboard/src/components/ui/tabs.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export interface TabsListProps {
2929

3030
export function TabsList({ children, className }: TabsListProps) {
3131
return (
32-
<div className={`inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground ${className || ''}`}>
32+
<div className={`inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground ${className ?? ''}`}>
3333
{children}
3434
</div>
3535
)
@@ -54,7 +54,7 @@ export function TabsTrigger({ value, children, className }: TabsTriggerProps) {
5454
isActive
5555
? 'bg-background text-foreground shadow-sm'
5656
: 'hover:bg-background/50'
57-
} ${className || ''}`}
57+
} ${className ?? ''}`}
5858
>
5959
{children}
6060
</button>
@@ -74,7 +74,7 @@ export function TabsContent({ value, children, className }: TabsContentProps) {
7474
if (context.value !== value) return null
7575

7676
return (
77-
<div className={`mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 bg-card ${className || ''}`}>
77+
<div className={`mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 bg-card ${className ?? ''}`}>
7878
{children}
7979
</div>
8080
)

0 commit comments

Comments
 (0)