5.4 KiB

Backend Utilities

Utility modules provide common functionality for spatial calculations, logging, metrics collection, and data processing across the Changemaker Lite platform.

Utility Modules

Spatial Utilities

spatial.ts (utils/spatial.ts)

Provides geospatial calculations and polygon operations:

Point-in-Polygon

  • Ray-casting algorithm for polygon containment
  • Supports GeoJSON polygon format
  • Handles holes in polygons
  • Used for cut assignment
import { isPointInPolygon } from '../utils/spatial';

const inside = isPointInPolygon(
  { lat: 43.65, lng: -79.38 },
  geoJsonPolygon
);

Haversine Distance

  • Calculate distance between two coordinates
  • Returns distance in kilometers
  • Great-circle distance calculation
import { haversineDistance } from '../utils/spatial';

const distance = haversineDistance(
  { lat: 43.65, lng: -79.38 },
  { lat: 43.66, lng: -79.39 }
);
// Returns: 1.23 (km)

Bounds Calculation

  • Calculate bounding box for set of locations
  • Returns min/max lat/lng
  • Used for map centering
import { calculateBounds } from '../utils/spatial';

const bounds = calculateBounds(locations);
// Returns: { minLat, maxLat, minLng, maxLng }

Centroid Calculation

  • Calculate center point of locations
  • Geographic mean of coordinates
  • Used for map initial center
import { calculateCentroid } from '../utils/spatial';

const center = calculateCentroid(locations);
// Returns: { lat, lng }

GeoJSON Parsing

  • Parse GeoJSON geometry to coordinate arrays
  • Support for Polygon and MultiPolygon
  • Coordinate validation

Logging Utilities

logger.ts (utils/logger.ts)

Winston-based logging with multiple transports:

Log Levels

  • error - Error conditions
  • warn - Warning messages
  • info - Informational messages
  • http - HTTP request logs
  • debug - Debug-level messages

Usage

import logger from '../utils/logger';

logger.info('Campaign created', { campaignId: 123 });
logger.error('Failed to send email', { error: err.message });
logger.debug('Geocoding result', { lat, lng });

Features

  • JSON formatting for production
  • Colorized console output for development
  • File rotation for error logs
  • Separate error log file
  • Timestamp on all logs
  • Request ID tracking

Metrics Utilities

metrics.ts (utils/metrics.ts)

Prometheus metrics collection with 12 custom cm_* metrics:

Counter Metrics

  • cm_api_uptime_seconds - API uptime counter
  • cm_canvass_visits_total - Total canvass visits
  • cm_campaign_emails_sent_total - Total campaign emails
  • cm_geocode_requests_total - Total geocode requests

Gauge Metrics

  • cm_canvass_sessions_active - Active canvass sessions
  • cm_email_queue_size - Email queue depth
  • cm_geocode_queue_size - Geocode queue depth
  • cm_external_service_health - Service health status (0/1)

Histogram Metrics

  • cm_geocode_duration_seconds - Geocoding request duration
  • http_request_duration_ms - HTTP request duration

Usage

import { metrics } from '../utils/metrics';

// Increment counter
metrics.campaignEmailsSent.inc();

// Set gauge
metrics.emailQueueSize.set(42);

// Observe histogram
const end = metrics.geocodeDuration.startTimer();
await geocode(address);
end();

HTTP Metrics

Automatic tracking of:

  • Request count by method, route, status
  • Request duration percentiles
  • Active requests gauge

Path Validation

path-validator.ts (utils/path-validator.ts)

Security utilities for path validation:

Features

  • Null byte detection
  • Path traversal prevention (../ patterns)
  • Encoded traversal detection (%2e%2e)
  • Path normalization
import { validatePath } from '../utils/path-validator';

const safe = validatePath(userInput);
if (!safe) {
  throw new Error('Invalid path');
}

HTML Sanitization

sanitize.ts (utils/sanitize.ts)

XSS prevention utilities:

import { escapeHtml } from '../utils/sanitize';

const safe = escapeHtml(userInput);
// Escapes: < > & " ' to HTML entities

Utility Functions Summary

Utility Function Purpose
Spatial
isPointInPolygon() Check if point is inside polygon
haversineDistance() Calculate distance between points
calculateBounds() Calculate bounding box
calculateCentroid() Calculate center point
parseGeoJSON() Parse GeoJSON to coordinates
Logging
logger.info() Log informational message
logger.error() Log error message
logger.debug() Log debug message
Metrics
metrics.*.inc() Increment counter
metrics.*.set() Set gauge value
metrics.*.startTimer() Start histogram timer
Security
validatePath() Validate file path safety
escapeHtml() Sanitize HTML content

Configuration

Utilities are configured via environment variables:

# Logging
LOG_LEVEL=info              # Minimum log level
NODE_ENV=production         # Environment mode

# Metrics
METRICS_ENABLED=true        # Enable Prometheus metrics