npm.io
0.8.0 • Published 3d ago

@vigilisai/local-risk-alert-feed

Licence
MIT
Version
0.8.0
Deps
2
Size
1.9 MB
Vulns
0
Weekly
0

local-risk-alert-feed

A TypeScript library for aggregating local risk alerts from multiple data sources via a plugin system. Designed for SaaS and serverless applications.

Installation

npm install @vigilisai/local-risk-alert-feed

Quick Start

import {
  AlertFeed,
  NWSWeatherPlugin,
  PhoenixFirePlugin,
  NIFCWildfirePlugin,
  ArizonaTrafficPlugin,
} from '@vigilisai/local-risk-alert-feed';

// Create the feed
const feed = new AlertFeed({
  continueOnPluginError: true,
  pluginTimeoutMs: 30000,
});

// Register plugins
await feed.registerPlugins([
  { plugin: new NWSWeatherPlugin() },
  { plugin: new PhoenixFirePlugin({ includeEMS: true }) },
  { plugin: new NIFCWildfirePlugin() },
  { plugin: new ArizonaTrafficPlugin() },
]);

// Query for alerts near a location
const response = await feed.query({
  location: { latitude: 33.4484, longitude: -112.074 },
  timeRange: 'past-7d',
  radiusMeters: 2000,
  limit: 100,
});

console.log(`Found ${response.alerts.length} alerts`);

// Cleanup when done
await feed.dispose();

Available Plugins

Plugin Coverage Categories Data Freshness
NWSWeatherPlugin United States weather Real-time
PhoenixFirePlugin Phoenix metro fire, medical ~1-2 days
NIFCWildfirePlugin United States fire Real-time
ArizonaTrafficPlugin Arizona traffic Real-time
PhoenixEventsPlugin Phoenix area event Real-time
PhoenixConventionCenterPlugin Downtown Phoenix event Real-time
AirNowPlugin United States air-quality Real-time
GlendaleEventsPlugin Glendale, AZ event Scheduled
GlendalePolicePlugin Glendale, AZ crime, traffic ~24 hours
GlendaleFirePlugin Glendale, AZ fire, medical ~24 hours

Plugin Configuration

NWSWeatherPlugin

National Weather Service alerts for the United States.

new NWSWeatherPlugin({
  cacheTtlMs: 300000, // 5 minute cache (default)
});
PhoenixFirePlugin

Fire and EMS incidents from Phoenix Fire Department (ArcGIS 30-day history).

new PhoenixFirePlugin({
  includeEMS: true,      // Include medical calls (default: true)
  includeService: false, // Include non-emergency service calls (default: false)
  limit: 500,            // Max records per request (default: 500)
});
NIFCWildfirePlugin

Active wildfires from National Interagency Fire Center.

new NIFCWildfirePlugin({
  includePrescribedBurns: false, // Include RX burns (default: false)
  minAcres: 0,                   // Minimum fire size (default: 0)
  states: ['AZ', 'CA', 'NV'],    // Filter by states (default: all)
});
PhoenixEventsPlugin

Events from Ticketmaster Discovery API.

new PhoenixEventsPlugin({
  ticketmasterApiKey: process.env.TICKETMASTER_API_KEY,
  limit: 100,
});
AirNowPlugin

Air quality data from EPA AirNow.

new AirNowPlugin({
  apiKey: process.env.AIRNOW_API_KEY, // Required
});

Cache Providers

The library uses a bring-your-own-client pattern for caching. No external dependencies are required.

In-Memory (Default)

Zero dependencies, suitable for development or single-instance deployments.

import { AlertFeed, InMemoryCacheProvider } from '@vigilisai/local-risk-alert-feed';

const feed = new AlertFeed({
  cacheProvider: new InMemoryCacheProvider(),
});
Vercel KV

Pass your own @vercel/kv instance (any version).

import { kv } from '@vercel/kv';
import { AlertFeed, VercelKVCacheProvider } from '@vigilisai/local-risk-alert-feed';

const feed = new AlertFeed({
  cacheProvider: new VercelKVCacheProvider(kv, 'my-prefix:'),
});
DynamoDB

Pass your own AWS SDK DynamoDB Document Client (any v3 version).

import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
import { AlertFeed, DynamoDBCacheProvider } from '@vigilisai/local-risk-alert-feed';

const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);

const feed = new AlertFeed({
  cacheProvider: new DynamoDBCacheProvider(docClient, {
    tableName: 'alert-cache',
    keyAttribute: 'pk',       // optional, default: 'pk'
    valueAttribute: 'value',  // optional, default: 'value'
    ttlAttribute: 'ttl',      // optional, default: 'ttl'
  }),
});
Custom Cache Provider

Implement the CacheProvider interface for any backend.

import { CacheProvider, AlertFeed } from '@vigilisai/local-risk-alert-feed';

const customCache: CacheProvider = {
  async get<T>(key: string): Promise<T | null> {
    // Your implementation
  },
  async set<T>(key: string, value: T, ttlMs?: number): Promise<void> {
    // Your implementation
  },
  async delete(key: string): Promise<void> {
    // Your implementation
  },
  async has(key: string): Promise<boolean> {
    // Your implementation
  },
};

const feed = new AlertFeed({ cacheProvider: customCache });

Query Options

const response = await feed.query({
  // Required
  location: { latitude: 33.4484, longitude: -112.074 },

  // Time range - preset string or explicit range
  timeRange: 'past-7d',  // or 'past-24h', 'past-1h', 'next-7d', etc.
  // timeRange: { start: '2024-01-01T00:00:00Z', end: '2024-01-07T00:00:00Z' },

  // Optional filters
  radiusMeters: 2000,           // Default: 10000 (10km)
  categories: ['fire', 'weather'], // Filter by category
  plugins: ['nws-weather'],     // Filter by plugin ID
  limit: 100,                   // Max alerts to return

  // Include per-plugin timing/status info
  includePluginResults: true,
});

Response Format

interface AlertFeedResponse {
  alerts: Alert[];
  meta: {
    queriedAt: string;
    timeRange: { start: string; end: string };
    location: { latitude: number; longitude: number };
    radiusMeters: number;
    totalCount: number;
    truncated: boolean;
  };
  pluginResults?: PluginResult[];  // If includePluginResults: true
}

interface Alert {
  id: string;
  title: string;
  description: string;
  category: 'weather' | 'fire' | 'medical' | 'traffic' | 'event' | 'air-quality' | ...;
  riskLevel: 'low' | 'moderate' | 'high' | 'severe' | 'extreme';
  priority: number;  // 1-5, higher = more urgent
  temporalType: 'real-time' | 'scheduled' | 'historical';
  location: {
    point: { latitude: number; longitude: number };
    address?: string;
    city?: string;
    state?: string;
  };
  timestamps: {
    issued: string;
    eventStart?: string;
    eventEnd?: string;
    expires?: string;
  };
  source: {
    id: string;
    name: string;
  };
  url?: string;
  metadata?: Record<string, unknown>;
}

Serverless Adapters

Vercel Edge/Serverless
import { createVercelHandler } from 'local-risk-alert-feed/adapters/vercel';
import { NWSWeatherPlugin, PhoenixFirePlugin } from '@vigilisai/local-risk-alert-feed';

export default createVercelHandler({
  plugins: [
    new NWSWeatherPlugin(),
    new PhoenixFirePlugin(),
  ],
  // Optional: custom cache provider
  // cacheProvider: new VercelKVCacheProvider(kv),
});
AWS Lambda
import { createLambdaHandler } from 'local-risk-alert-feed/adapters/lambda';
import { NWSWeatherPlugin, PhoenixFirePlugin } from '@vigilisai/local-risk-alert-feed';

export const handler = createLambdaHandler({
  plugins: [
    new NWSWeatherPlugin(),
    new PhoenixFirePlugin(),
  ],
});

Creating Custom Plugins

Extend BasePlugin to create your own data source plugins.

import { BasePlugin, PluginMetadata, PluginFetchOptions, PluginFetchResult } from '@vigilisai/local-risk-alert-feed';

export class MyCustomPlugin extends BasePlugin {
  readonly metadata: PluginMetadata = {
    id: 'my-custom-plugin',
    name: 'My Custom Data Source',
    version: '1.0.0',
    description: 'Fetches alerts from my custom API',
    coverage: {
      type: 'regional',
      center: { latitude: 40.7128, longitude: -74.0060 },
      radiusMeters: 50000,
      description: 'New York City area',
    },
    supportedTemporalTypes: ['real-time'],
    supportedCategories: ['custom'],
    refreshIntervalMs: 60000,
  };

  async fetchAlerts(options: PluginFetchOptions): Promise<PluginFetchResult> {
    const { location, timeRange, radiusMeters } = options;

    // Fetch from your API
    const data = await this.fetchJson<MyApiResponse>('https://my-api.com/alerts');

    // Transform to Alert format
    const alerts = data.items.map(item => this.createAlert({
      id: `my-plugin-${item.id}`,
      title: item.title,
      description: item.description,
      riskLevel: 'moderate',
      priority: 3,
      category: 'custom',
      temporalType: 'real-time',
      location: {
        point: { latitude: item.lat, longitude: item.lng },
      },
      timestamps: {
        issued: item.createdAt,
      },
    }));

    return { alerts, fromCache: false };
  }
}

Environment Variables

# Optional - for Ticketmaster events
TICKETMASTER_API_KEY=your_key_here

# Optional - for AirNow air quality
AIRNOW_API_KEY=your_key_here

License

UNLICENSED - Private package