๐ก API & IPC Documentation
Interface Reference: Comprehensive guide to IPC communication, events, and API patterns in Uptime Watcher.
๐ Overviewโ
Uptime Watcher uses type-safe IPC (Inter-Process Communication) between the Electron main process and React renderer, along with an event-driven architecture for internal communication.
๐ IPC Communicationโ
Access Patternโ
All IPC communication goes through the preload-exposed window.electronAPI
object:
// Available in renderer process (React components)
const result = await window.electronAPI.sites.getAll();
const site = await window.electronAPI.sites.create(siteData);
Type Safetyโ
All IPC calls are fully typed with TypeScript interfaces:
// Types are automatically inferred
const sites: Site[] = await window.electronAPI.sites.getAll();
const newSite: Site = await window.electronAPI.sites.create({
name: "Example Site",
url: "https://example.com",
monitors: [...]
});
๐๏ธ IPC API Referenceโ
Sites APIโ
sites.getAll(): Promise<Site[]>
โ
Retrieves all configured sites.
const sites = await window.electronAPI.sites.getAll();
sites.create(data: SiteCreationData): Promise<Site>
โ
Creates a new site with monitors.
const newSite = await window.electronAPI.sites.create({
name: "My Website",
url: "https://mywebsite.com",
monitors: [
{
type: "http",
checkInterval: 30000,
retryAttempts: 3,
timeout: 10000,
},
],
});
sites.update(id: string, data: Partial<Site>): Promise<Site>
โ
Updates an existing site.
const updatedSite = await window.electronAPI.sites.update(siteId, {
name: "New Site Name",
description: "Updated description",
});
sites.delete(id: string): Promise<void>
โ
Deletes a site and all its monitors.
await window.electronAPI.sites.delete(siteId);
sites.startMonitoring(id: string): Promise<void>
โ
Starts monitoring for a specific site.
await window.electronAPI.sites.startMonitoring(siteId);
sites.stopMonitoring(id: string): Promise<void>
โ
Stops monitoring for a specific site.
await window.electronAPI.sites.stopMonitoring(siteId);
Monitors APIโ
monitors.checkManually(siteId: string, monitorId: string): Promise<MonitorCheckResult>
โ
Performs a manual health check for a specific monitor.
const result = await window.electronAPI.monitors.checkManually(
siteId,
monitorId
);
// result: { status: "up" | "down", responseTime: number, details?: string, error?: string }
History APIโ
history.getByMonitor(monitorId: string, options?: HistoryQuery): Promise<HistoryEntry[]>
โ
Retrieves historical data for a monitor.
const history = await window.electronAPI.history.getByMonitor(monitorId, {
limit: 100,
startDate: new Date(Date.now() - 24 * 60 * 60 * 1000), // Last 24 hours
endDate: new Date(),
});
history.getStatsByMonitor(monitorId: string, options?: StatsQuery): Promise<MonitorStats>
โ
Gets statistical summary for a monitor.
const stats = await window.electronAPI.history.getStatsByMonitor(monitorId, {
period: "24h", // '1h', '24h', '7d', '30d'
});
// stats: { uptime: 99.5, avgResponseTime: 245, totalChecks: 1440 }
Settings APIโ
settings.get(): Promise<AppSettings>
โ
Retrieves application settings.
const settings = await window.electronAPI.settings.get();
settings.update(data: Partial<AppSettings>): Promise<AppSettings>
โ
Updates application settings.
const updated = await window.electronAPI.settings.update({
notifications: {
enabled: true,
onStatusChange: true,
onFailure: true,
},
theme: "dark",
});
๐ญ Event Systemโ
TypedEventBusโ
Internal event communication uses a type-safe event bus with automatic metadata injection.
Event Typesโ
Site Eventsโ
interface UptimeEvents {
"sites:added": { site: Site; timestamp: number };
"sites:updated": { site: Site; timestamp: number };
"sites:deleted": { siteId: string; timestamp: number };
"sites:monitoring-started": { siteId: string; timestamp: number };
"sites:monitoring-stopped": { siteId: string; timestamp: number };
}
Monitor Eventsโ
interface UptimeEvents {
"monitor:status-changed": {
monitorId: string;
siteId: string;
newStatus: "up" | "down";
previousStatus: "up" | "down";
responseTime: number;
details?: string;
timestamp: number;
};
"monitor:check-completed": {
monitorId: string;
siteId: string;
result: MonitorCheckResult;
timestamp: number;
};
}
Application Eventsโ
interface UptimeEvents {
"app:ready": { timestamp: number };
"app:before-quit": { timestamp: number };
"database:initialized": { timestamp: number };
"settings:updated": { settings: AppSettings; timestamp: number };
}
Event Listening (Backend Only)โ
// In Electron main process services
eventBus.onTyped("sites:added", (data) => {
console.log(`Site added: ${data.site.name} at ${data.timestamp}`);
// Automatically includes correlation ID and metadata
});
// Emit events
await eventBus.emitTyped("sites:added", {
site: newSite,
timestamp: Date.now(),
});
๐ Frontend Integrationโ
React Componentsโ
import { useSitesStore } from "../stores/useSitesStore";
function SiteManager() {
const { sites, addSite, updateSite, removeSite } = useSitesStore();
const handleCreateSite = async (siteData: SiteCreationData) => {
try {
const newSite = await window.electronAPI.sites.create(siteData);
addSite(newSite); // Update local state
} catch (error) {
console.error("Failed to create site:", error);
}
};
return (
<div>
{sites.map((site) => (
<SiteCard key={site.id} site={site} />
))}
</div>
);
}
Store Integrationโ
// Zustand store with IPC integration
export const useSitesStore = create<SitesStore>()((set, get) => ({
sites: [],
fetchSites: async () => {
const sites = await window.electronAPI.sites.getAll();
set({ sites });
},
addSite: async (siteData: SiteCreationData) => {
const newSite = await window.electronAPI.sites.create(siteData);
set((state) => ({ sites: [...state.sites, newSite] }));
return newSite;
},
// ... other actions
}));
๐ Data Types Referenceโ
Core Interfacesโ
Siteโ
interface Site {
id: string;
name: string;
url: string;
description?: string;
tags: string[];
monitoring: boolean;
monitors: Monitor[];
createdAt: number;
updatedAt: number;
}
Monitorโ
interface Monitor {
id: string;
type: "http" | "port" | "ping";
siteId: string;
checkInterval: number; // milliseconds
retryAttempts: number;
timeout: number; // milliseconds
config: HttpMonitorConfig | PortMonitorConfig | PingMonitorConfig;
lastResult?: MonitorCheckResult;
createdAt: number;
updatedAt: number;
}
MonitorCheckResultโ
interface MonitorCheckResult {
status: "up" | "down";
responseTime: number; // milliseconds
details?: string; // Human-readable details
error?: string; // Technical error message
}
HistoryEntryโ
interface HistoryEntry {
id: string;
monitorId: string;
timestamp: number;
status: "up" | "down";
responseTime: number;
details?: string;
error?: string;
}
Monitor Type Configurationsโ
HTTP Monitorโ
interface HttpMonitorConfig {
method: "GET" | "POST" | "PUT" | "DELETE" | "HEAD";
headers?: Record<string, string>;
body?: string;
expectedStatusCode?: number;
expectedContent?: string;
followRedirects: boolean;
sslCheck: boolean;
}
Port Monitorโ
interface PortMonitorConfig {
port: number;
host?: string; // defaults to site URL hostname
}
Ping Monitorโ
interface PingMonitorConfig {
packetSize: number;
packetCount: number;
}
๐ ๏ธ Error Handlingโ
IPC Error Responsesโ
All IPC calls include consistent error handling:
try {
const site = await window.electronAPI.sites.create(siteData);
} catch (error) {
// Error includes:
// - message: Human-readable error message
// - code: Error code for programmatic handling
// - details: Additional context (development only)
console.error("Site creation failed:", error.message);
}
Common Error Codesโ
VALIDATION_ERROR
: Invalid input dataNOT_FOUND
: Resource doesn't existALREADY_EXISTS
: Duplicate resourceDATABASE_ERROR
: Database operation failedNETWORK_ERROR
: Network request failedPERMISSION_DENIED
: Insufficient permissions
๐ Securityโ
Context Isolationโ
All IPC communication uses Electron's context isolation for security:
// preload.ts - Secure exposure
const electronAPI = {
sites: {
getAll: () => ipcRenderer.invoke("sites:get-all"),
create: (data: SiteCreationData) =>
ipcRenderer.invoke("sites:create", data),
// ... other methods
},
} as const;
contextBridge.exposeInMainWorld("electronAPI", electronAPI);
Validationโ
All IPC handlers include input validation:
// Backend handler with validation
ipcService.registerStandardizedIpcHandler(
"sites:create",
async (data: SiteCreationData) => {
return await siteManager.createSite(data);
},
isSiteCreationData // Type guard function
);
๐ Adding New APIsโ
1. Define Typesโ
// shared/types/apiTypes.ts
export interface NewFeatureData {
name: string;
config: NewFeatureConfig;
}
2. Create IPC Handlerโ
// electron/services/ipc/IpcService.ts
ipcService.registerStandardizedIpcHandler(
"feature:create",
async (data: NewFeatureData) => {
return await featureManager.create(data);
},
isNewFeatureData
);
3. Expose in Preloadโ
// electron/preload.ts
const electronAPI = {
// ... existing APIs
feature: {
create: (data: NewFeatureData) =>
ipcRenderer.invoke("feature:create", data),
},
};
4. Use in Frontendโ
// src/components/FeatureComponent.tsx
const newFeature = await window.electronAPI.feature.create(featureData);
๐ก Best Practices: Always use TypeScript interfaces, validate inputs, handle errors gracefully, and follow the established naming conventions (domain:action
).