Skip to content

dominiquekossi/signal-status-js

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🚦 Signal Status JS

npm version License: MIT TypeScript Bundle Size

A lightweight, dependency-free TypeScript library for monitoring network connectivity, latency, API health, and WebSocket status in web applications.

✨ Features

  • 🌐 Network Connectivity - Detect online/offline status
  • ⚑ Latency Monitoring - Measure network speed and detect slow connections
  • πŸ₯ API Health Checks - Monitor multiple API endpoints with retry logic
  • πŸ”Œ WebSocket Monitoring - Track WebSocket connection state
  • πŸ”” UI Alerts - Built-in Toast, Banner, and Modal notifications
  • βš›οΈ React & Vue - First-class framework integrations
  • πŸ”Œ Plugin System - Extend functionality with custom plugins
  • πŸ“Š Metrics & History - Track uptime, downtime, and connection quality
  • πŸ’Ύ State Persistence - Maintain state across page reloads
  • β™Ώ Accessible - Full ARIA support and keyboard navigation
  • πŸ“¦ Tiny Bundle - < 8KB gzipped, zero dependencies
  • 🎯 TypeScript - Full type safety with strict mode

πŸ“¦ Installation

npm install signal-status-js
yarn add signal-status-js
pnpm add signal-status-js

πŸš€ Quick Start

Basic Usage

import { SignalStatusWatcher } from "signal-status-js";

const watcher = new SignalStatusWatcher({
  healthCheckUrl: "/api/health",
  latencyThreshold: 500,
});

watcher.on("offline", () => {
  console.log("Connection lost!");
});

watcher.on("slow_connection", ({ latency }) => {
  console.log(`Slow connection: ${latency}ms`);
});

watcher.start();

React Integration

import { SignalStatusWatcher } from "signal-status-js";
import { useSignalStatus } from "signal-status-js/react";
import { useMemo } from "react";

function App() {
  const watcher = useMemo(
    () =>
      new SignalStatusWatcher({
        healthCheckUrl: "/api/health",
      }),
    []
  );

  const status = useSignalStatus(watcher);

  return (
    <div>
      {!status.online && <div>You are offline</div>}
      {status.slow && <div>Slow connection detected</div>}
      {status.apiDown && <div>Service unavailable</div>}
    </div>
  );
}

Vue Integration

<template>
  <div>
    <div v-if="!status.online">You are offline</div>
    <div v-if="status.slow">Slow connection detected</div>
    <div v-if="status.apiDown">Service unavailable</div>
  </div>
</template>

<script setup>
import { SignalStatusWatcher } from "signal-status-js";
import { useSignalStatus } from "signal-status-js/vue";
import { onMounted } from "vue";

const watcher = new SignalStatusWatcher({
  healthCheckUrl: "/api/health",
});

const status = useSignalStatus(watcher);

onMounted(() => {
  watcher.start();
});
</script>

πŸ“– Documentation

Configuration Options

interface SignalStatusConfig {
  // Network Monitoring
  pingUrl?: string; // Default: 'https://www.google.com/favicon.ico'
  pingInterval?: number; // Default: 30000 (30s)
  latencyThreshold?: number; // Default: 800 (ms)

  // API Health Checks
  healthCheckUrl?: string; // Single API endpoint
  healthChecks?: HealthCheckConfig[]; // Multiple API endpoints
  healthCheckInterval?: number; // Default: 10000 (10s)
  healthCheckValidator?: (response: Response) => boolean | Promise<boolean>;

  // Retry Logic
  maxRetries?: number; // Default: 5
  retryDelay?: number; // Default: 1000 (ms)

  // WebSocket
  websocket?: WebSocket; // WebSocket instance to monitor

  // History & Metrics
  historySize?: number; // Default: 100

  // Persistence
  persist?: boolean; // Default: false
  persistKey?: string; // Default: 'signal-status-state'

  // UI Alerts
  alerts?: AlertConfig;

  // Misc
  silent?: boolean; // Default: false
}

Events

// Connectivity Events
watcher.on("online", ({ timestamp }) => {});
watcher.on("offline", ({ timestamp }) => {});

// Latency Events
watcher.on("slow_connection", ({ latency, threshold, timestamp }) => {});

// API Health Events
watcher.on("api_down", ({ apiId, statusCode, error, timestamp }) => {});
watcher.on("api_up", ({ apiId, responseTime, timestamp }) => {});
watcher.on("maintenance", ({ apiId, data, timestamp }) => {});

// WebSocket Events
watcher.on("ws_disconnected", ({ error, timestamp }) => {});
watcher.on("ws_reconnected", ({ timestamp }) => {});

// Network Info Events
watcher.on(
  "connection_type_changed",
  ({ type, effectiveType, timestamp }) => {}
);

UI Alerts

// Toast Notifications
watcher.enableAlerts({
  type: "toast",
  position: "top-right",
  duration: 5000,
  messages: {
    offline: "You are offline",
    online: "Connection restored",
    slow: "Slow connection detected",
    api_down: "Service unavailable",
    api_up: "Service restored",
  },
});

// Banner Alerts
watcher.enableAlerts({
  type: "banner",
  position: "top",
  messages: {
    offline: "⚠️ You are offline. Working in local mode.",
  },
});

// Modal Alerts
watcher.enableAlerts({
  type: "modal",
  messages: {
    maintenance: "System under maintenance. We'll be back soon.",
  },
});

Multiple API Monitoring

const watcher = new SignalStatusWatcher({
  healthChecks: [
    {
      id: "auth-api",
      url: "/api/auth/health",
      interval: 15000,
    },
    {
      id: "data-api",
      url: "/api/data/health",
      interval: 10000,
    },
    {
      id: "payment-api",
      url: "/api/payment/health",
      interval: 20000,
    },
  ],
});

watcher.on("api_down", ({ apiId, statusCode }) => {
  console.log(`API ${apiId} is down (${statusCode})`);
});

Metrics & History

// Get metrics
const metrics = watcher.getMetrics();
console.log({
  uptimePercentage: metrics.uptimePercentage,
  totalDowntime: metrics.totalDowntime,
  averageLatency: metrics.averageLatency,
  slowConnectionCount: metrics.slowConnectionCount,
  apiDownCount: metrics.apiDownCount,
});

// Get history
const history = watcher.getHistory();
history.forEach((entry) => {
  console.log(`${entry.event} at ${new Date(entry.timestamp)}`);
});

Plugin System

const analyticsPlugin = {
  name: "analytics",

  onEvent(event, payload, watcher) {
    // Send events to analytics
    gtag("event", event, payload);
  },
};

watcher.registerPlugin(analyticsPlugin);

🎯 Use Cases

E-commerce Checkout

const watcher = new SignalStatusWatcher({
  healthChecks: [
    { id: "payment", url: "/api/payment/health" },
    { id: "inventory", url: "/api/inventory/health" },
  ],
});

watcher.on("api_down", ({ apiId }) => {
  if (apiId === "payment") {
    disableCheckoutButton();
    showMessage("Payment service temporarily unavailable");
  }
});

Real-time Chat

const ws = new WebSocket("wss://chat.example.com");
const watcher = new SignalStatusWatcher({
  websocket: ws,
  healthCheckUrl: "/api/chat/health",
});

watcher.on("ws_disconnected", () => {
  showReconnectingIndicator();
  disableMessageInput();
});

watcher.on("ws_reconnected", () => {
  hideReconnectingIndicator();
  enableMessageInput();
  loadMissedMessages();
});

Progressive Web App

const watcher = new SignalStatusWatcher({
  persist: true,
  healthCheckUrl: "/api/health",
});

watcher.on("offline", () => {
  // Enable service worker cache
  navigator.serviceWorker.controller?.postMessage({
    type: "ENABLE_OFFLINE_MODE",
  });
});

watcher.on("online", () => {
  // Sync data in background
  navigator.serviceWorker.controller?.postMessage({
    type: "SYNC_DATA",
  });
});

πŸ“Š Bundle Size

Package Size (gzipped)
Core 7.41 KB
React +0.34 KB
Vue +0.33 KB

πŸ§ͺ Testing

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Type check
npm run type-check

# Build
npm run build

🀝 Contributing

Contributions are welcome! Please read our Contributing Guide for details.

πŸ“„ License

MIT Β© Dominique Kossi

πŸ”— Links

⭐ Show Your Support

Give a ⭐️ if this project helped you!


Made with ❀️ by Dominique Kossi

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published