225 lines
5.4 KiB
Markdown

# 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
```typescript
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
```typescript
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
```typescript
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
```typescript
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**
```typescript
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**
```typescript
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
```typescript
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:
```typescript
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:
```bash
# Logging
LOG_LEVEL=info # Minimum log level
NODE_ENV=production # Environment mode
# Metrics
METRICS_ENABLED=true # Enable Prometheus metrics
```
## Related Documentation
- [Backend Overview](../index.md)
- [Observability](../../features/observability/index.md)
- [Security](../../deployment/security.md)
- [Map Features](../../features/map/index.md)
- [Monitoring Stack](../../deployment/monitoring-stack.md)