local-risk-alert-feed 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/cjs/core/alert-aggregator.js +24 -15
  2. package/dist/cjs/core/alert-aggregator.js.map +1 -1
  3. package/dist/cjs/index.js +3 -6
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/cjs/plugins/events/index.js +3 -1
  6. package/dist/cjs/plugins/events/index.js.map +1 -1
  7. package/dist/cjs/plugins/events/phoenix-convention-center.plugin.js +235 -0
  8. package/dist/cjs/plugins/events/phoenix-convention-center.plugin.js.map +1 -0
  9. package/dist/cjs/plugins/events/phoenix-events.plugin.js +24 -195
  10. package/dist/cjs/plugins/events/phoenix-events.plugin.js.map +1 -1
  11. package/dist/cjs/plugins/fire-emt/index.js +3 -1
  12. package/dist/cjs/plugins/fire-emt/index.js.map +1 -1
  13. package/dist/cjs/plugins/fire-emt/nifc-wildfire.plugin.js +221 -0
  14. package/dist/cjs/plugins/fire-emt/nifc-wildfire.plugin.js.map +1 -0
  15. package/dist/cjs/plugins/fire-emt/phoenix-fire.plugin.js +153 -154
  16. package/dist/cjs/plugins/fire-emt/phoenix-fire.plugin.js.map +1 -1
  17. package/dist/cjs/plugins/index.js +2 -7
  18. package/dist/cjs/plugins/index.js.map +1 -1
  19. package/dist/cjs/plugins/traffic/arizona-traffic.plugin.js +70 -77
  20. package/dist/cjs/plugins/traffic/arizona-traffic.plugin.js.map +1 -1
  21. package/dist/esm/core/alert-aggregator.js +24 -15
  22. package/dist/esm/core/alert-aggregator.js.map +1 -1
  23. package/dist/esm/index.js +1 -3
  24. package/dist/esm/index.js.map +1 -1
  25. package/dist/esm/plugins/events/index.js +1 -0
  26. package/dist/esm/plugins/events/index.js.map +1 -1
  27. package/dist/esm/plugins/events/phoenix-convention-center.plugin.js +231 -0
  28. package/dist/esm/plugins/events/phoenix-convention-center.plugin.js.map +1 -0
  29. package/dist/esm/plugins/events/phoenix-events.plugin.js +24 -195
  30. package/dist/esm/plugins/events/phoenix-events.plugin.js.map +1 -1
  31. package/dist/esm/plugins/fire-emt/index.js +1 -0
  32. package/dist/esm/plugins/fire-emt/index.js.map +1 -1
  33. package/dist/esm/plugins/fire-emt/nifc-wildfire.plugin.js +217 -0
  34. package/dist/esm/plugins/fire-emt/nifc-wildfire.plugin.js.map +1 -0
  35. package/dist/esm/plugins/fire-emt/phoenix-fire.plugin.js +153 -154
  36. package/dist/esm/plugins/fire-emt/phoenix-fire.plugin.js.map +1 -1
  37. package/dist/esm/plugins/index.js +1 -5
  38. package/dist/esm/plugins/index.js.map +1 -1
  39. package/dist/esm/plugins/traffic/arizona-traffic.plugin.js +70 -77
  40. package/dist/esm/plugins/traffic/arizona-traffic.plugin.js.map +1 -1
  41. package/dist/types/core/alert-aggregator.d.ts +1 -1
  42. package/dist/types/core/alert-aggregator.d.ts.map +1 -1
  43. package/dist/types/index.d.ts +2 -6
  44. package/dist/types/index.d.ts.map +1 -1
  45. package/dist/types/plugins/events/index.d.ts +2 -0
  46. package/dist/types/plugins/events/index.d.ts.map +1 -1
  47. package/dist/types/plugins/events/phoenix-convention-center.plugin.d.ts +55 -0
  48. package/dist/types/plugins/events/phoenix-convention-center.plugin.d.ts.map +1 -0
  49. package/dist/types/plugins/events/phoenix-events.plugin.d.ts +5 -37
  50. package/dist/types/plugins/events/phoenix-events.plugin.d.ts.map +1 -1
  51. package/dist/types/plugins/fire-emt/index.d.ts +2 -0
  52. package/dist/types/plugins/fire-emt/index.d.ts.map +1 -1
  53. package/dist/types/plugins/fire-emt/nifc-wildfire.plugin.d.ts +43 -0
  54. package/dist/types/plugins/fire-emt/nifc-wildfire.plugin.d.ts.map +1 -0
  55. package/dist/types/plugins/fire-emt/phoenix-fire.plugin.d.ts +21 -13
  56. package/dist/types/plugins/fire-emt/phoenix-fire.plugin.d.ts.map +1 -1
  57. package/dist/types/plugins/index.d.ts +2 -6
  58. package/dist/types/plugins/index.d.ts.map +1 -1
  59. package/dist/types/plugins/traffic/arizona-traffic.plugin.d.ts +5 -14
  60. package/dist/types/plugins/traffic/arizona-traffic.plugin.d.ts.map +1 -1
  61. package/package.json +1 -11
  62. package/dist/cjs/plugins/police-blotter/index.js +0 -6
  63. package/dist/cjs/plugins/police-blotter/index.js.map +0 -1
  64. package/dist/cjs/plugins/police-blotter/phoenix-police.plugin.js +0 -198
  65. package/dist/cjs/plugins/police-blotter/phoenix-police.plugin.js.map +0 -1
  66. package/dist/cjs/plugins/pulsepoint/index.js +0 -6
  67. package/dist/cjs/plugins/pulsepoint/index.js.map +0 -1
  68. package/dist/cjs/plugins/pulsepoint/pulsepoint.plugin.js +0 -275
  69. package/dist/cjs/plugins/pulsepoint/pulsepoint.plugin.js.map +0 -1
  70. package/dist/esm/plugins/police-blotter/index.js +0 -2
  71. package/dist/esm/plugins/police-blotter/index.js.map +0 -1
  72. package/dist/esm/plugins/police-blotter/phoenix-police.plugin.js +0 -194
  73. package/dist/esm/plugins/police-blotter/phoenix-police.plugin.js.map +0 -1
  74. package/dist/esm/plugins/pulsepoint/index.js +0 -2
  75. package/dist/esm/plugins/pulsepoint/index.js.map +0 -1
  76. package/dist/esm/plugins/pulsepoint/pulsepoint.plugin.js +0 -271
  77. package/dist/esm/plugins/pulsepoint/pulsepoint.plugin.js.map +0 -1
  78. package/dist/types/plugins/police-blotter/index.d.ts +0 -3
  79. package/dist/types/plugins/police-blotter/index.d.ts.map +0 -1
  80. package/dist/types/plugins/police-blotter/phoenix-police.plugin.d.ts +0 -49
  81. package/dist/types/plugins/police-blotter/phoenix-police.plugin.d.ts.map +0 -1
  82. package/dist/types/plugins/pulsepoint/index.d.ts +0 -3
  83. package/dist/types/plugins/pulsepoint/index.d.ts.map +0 -1
  84. package/dist/types/plugins/pulsepoint/pulsepoint.plugin.d.ts +0 -61
  85. package/dist/types/plugins/pulsepoint/pulsepoint.plugin.d.ts.map +0 -1
@@ -1,194 +0,0 @@
1
- import { BasePlugin } from '../base-plugin';
2
- /**
3
- * Phoenix Police crime center coordinates.
4
- */
5
- const PHOENIX_CENTER = {
6
- latitude: 33.4484,
7
- longitude: -112.074,
8
- };
9
- /**
10
- * Coverage radius in meters (approximately 50km covers greater Phoenix metro).
11
- */
12
- const COVERAGE_RADIUS_METERS = 50_000;
13
- /**
14
- * Crime categories and their risk mappings.
15
- */
16
- const CRIME_RISK_MAP = {
17
- HOMICIDE: 'extreme',
18
- 'AGGRAVATED ASSAULT': 'severe',
19
- ROBBERY: 'severe',
20
- 'SEXUAL ASSAULT': 'severe',
21
- ARSON: 'high',
22
- BURGLARY: 'high',
23
- 'MOTOR VEHICLE THEFT': 'moderate',
24
- THEFT: 'moderate',
25
- 'DRUG OFFENSE': 'moderate',
26
- LARCENY: 'low',
27
- MISCELLANEOUS: 'low',
28
- };
29
- /**
30
- * Plugin that fetches crime data from the Phoenix Open Data Portal.
31
- *
32
- * Uses the Phoenix Crime Incidents dataset via Socrata API.
33
- *
34
- * @see https://www.phoenixopendata.com/dataset/crime-data
35
- */
36
- export class PhoenixPolicePlugin extends BasePlugin {
37
- metadata = {
38
- id: 'phoenix-police',
39
- name: 'Phoenix Police Department',
40
- version: '1.0.0',
41
- description: 'Crime incidents from Phoenix Police Department',
42
- coverage: {
43
- type: 'regional',
44
- center: PHOENIX_CENTER,
45
- radiusMeters: COVERAGE_RADIUS_METERS,
46
- description: 'Phoenix, AZ metropolitan area',
47
- },
48
- supportedTemporalTypes: ['historical'],
49
- supportedCategories: ['crime'],
50
- refreshIntervalMs: 60 * 60 * 1000, // 1 hour
51
- };
52
- phoenixConfig;
53
- constructor(config) {
54
- super(config);
55
- this.phoenixConfig = {
56
- limit: 1000,
57
- ...config,
58
- };
59
- }
60
- async fetchAlerts(options) {
61
- const { location, timeRange, radiusMeters, limit } = options;
62
- const cacheKey = this.generateCacheKey(options);
63
- // Build Socrata API URL
64
- const url = this.buildApiUrl(location, timeRange, radiusMeters, limit);
65
- try {
66
- const { data, fromCache } = await this.getCachedOrFetch(cacheKey, () => this.fetchIncidents(url), this.config.cacheTtlMs);
67
- const alerts = data.map((incident) => this.transformIncident(incident));
68
- return {
69
- alerts,
70
- fromCache,
71
- cacheKey,
72
- };
73
- }
74
- catch (error) {
75
- // Log and return empty on non-critical errors
76
- console.error('Phoenix Police fetch error:', error);
77
- throw error;
78
- }
79
- }
80
- /**
81
- * Build the Socrata API URL for Phoenix crime data.
82
- */
83
- buildApiUrl(location, timeRange, radiusMeters, limit) {
84
- const baseUrl = 'https://www.phoenixopendata.com/resource/b4ez-nd22.json';
85
- // Build SoQL query
86
- const params = new URLSearchParams();
87
- // Limit results
88
- params.set('$limit', String(limit ?? this.phoenixConfig.limit));
89
- // Order by most recent
90
- params.set('$order', 'occurred_on DESC');
91
- // Build WHERE clause for time range and location
92
- const whereClauses = [];
93
- // Time filter using occurred_on field
94
- const startDate = timeRange.start.split('T')[0];
95
- const endDate = timeRange.end.split('T')[0];
96
- whereClauses.push(`occurred_on >= '${startDate}'`);
97
- whereClauses.push(`occurred_on <= '${endDate}'`);
98
- // Location filter using within_circle function (Socrata specific)
99
- // Convert radius from meters to meters (Socrata uses meters)
100
- whereClauses.push(`within_circle(location_1, ${location.latitude}, ${location.longitude}, ${radiusMeters})`);
101
- params.set('$where', whereClauses.join(' AND '));
102
- // Add app token if provided (for higher rate limits)
103
- if (this.phoenixConfig.appToken) {
104
- params.set('$$app_token', this.phoenixConfig.appToken);
105
- }
106
- return `${baseUrl}?${params.toString()}`;
107
- }
108
- /**
109
- * Fetch incidents from the API.
110
- */
111
- async fetchIncidents(url) {
112
- return this.fetchJson(url);
113
- }
114
- /**
115
- * Transform a Phoenix Police incident to our Alert format.
116
- */
117
- transformIncident(incident) {
118
- const category = incident.ucr_crime_category?.toUpperCase() ?? 'MISCELLANEOUS';
119
- const riskLevel = this.mapCrimeToRiskLevel(category);
120
- // Parse coordinates
121
- const latitude = incident.latitude ? parseFloat(incident.latitude) : PHOENIX_CENTER.latitude;
122
- const longitude = incident.longitude
123
- ? parseFloat(incident.longitude)
124
- : PHOENIX_CENTER.longitude;
125
- // Determine time - use occurred_on or reported_on
126
- const occurredOn = incident.occurred_on ?? incident.reported_on ?? new Date().toISOString();
127
- const occurredTo = incident.occurred_to;
128
- return this.createAlert({
129
- id: `phoenix-police-${incident.inc_number}`,
130
- externalId: incident.inc_number,
131
- title: this.formatCrimeTitle(category),
132
- description: this.buildDescription(incident),
133
- riskLevel,
134
- priority: this.riskLevelToPriority(riskLevel),
135
- category: 'crime',
136
- temporalType: 'historical',
137
- location: {
138
- point: { latitude, longitude },
139
- address: incident.hundredblockaddr,
140
- city: 'Phoenix',
141
- state: 'AZ',
142
- },
143
- timestamps: {
144
- issued: occurredOn,
145
- eventStart: occurredOn,
146
- eventEnd: occurredTo,
147
- },
148
- metadata: {
149
- incidentNumber: incident.inc_number,
150
- crimeCategory: category,
151
- grid: incident.grid,
152
- premiseType: incident.premise_type,
153
- disposition: incident.disposition,
154
- },
155
- });
156
- }
157
- /**
158
- * Map a crime category to a risk level.
159
- */
160
- mapCrimeToRiskLevel(category) {
161
- return CRIME_RISK_MAP[category] ?? 'moderate';
162
- }
163
- /**
164
- * Format the crime category as a title.
165
- */
166
- formatCrimeTitle(category) {
167
- // Convert "AGGRAVATED ASSAULT" to "Aggravated Assault"
168
- return category
169
- .toLowerCase()
170
- .split(' ')
171
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
172
- .join(' ');
173
- }
174
- /**
175
- * Build a description from incident data.
176
- */
177
- buildDescription(incident) {
178
- const parts = [];
179
- if (incident.ucr_crime_category) {
180
- parts.push(`Crime Type: ${this.formatCrimeTitle(incident.ucr_crime_category)}`);
181
- }
182
- if (incident.hundredblockaddr) {
183
- parts.push(`Location: ${incident.hundredblockaddr}`);
184
- }
185
- if (incident.premise_type) {
186
- parts.push(`Premise: ${incident.premise_type}`);
187
- }
188
- if (incident.disposition) {
189
- parts.push(`Status: ${incident.disposition}`);
190
- }
191
- return parts.join('\n');
192
- }
193
- }
194
- //# sourceMappingURL=phoenix-police.plugin.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"phoenix-police.plugin.js","sourceRoot":"","sources":["../../../../src/plugins/police-blotter/phoenix-police.plugin.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export { PulsepointPlugin } from './pulsepoint.plugin';
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/plugins/pulsepoint/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -1,271 +0,0 @@
1
- import { BasePlugin } from '../base-plugin';
2
- /**
3
- * Phoenix center coordinates.
4
- */
5
- const PHOENIX_CENTER = {
6
- latitude: 33.4484,
7
- longitude: -112.074,
8
- };
9
- /**
10
- * Coverage radius in meters (approximately 50km covers greater Phoenix metro).
11
- */
12
- const COVERAGE_RADIUS_METERS = 50_000;
13
- /**
14
- * Default Phoenix metro area agencies.
15
- */
16
- const DEFAULT_PHOENIX_AGENCIES = ['FPHX', 'FMES', 'FTEM', 'FGLN', 'FSCOT'];
17
- /**
18
- * Incident type to category and risk mappings.
19
- */
20
- const INCIDENT_TYPE_MAP = {
21
- // Fire incidents
22
- 'STRUCTURE FIRE': { category: 'fire', risk: 'extreme' },
23
- 'RESIDENTIAL FIRE': { category: 'fire', risk: 'extreme' },
24
- 'COMMERCIAL FIRE': { category: 'fire', risk: 'extreme' },
25
- 'INDUSTRIAL FIRE': { category: 'fire', risk: 'extreme' },
26
- 'APARTMENT FIRE': { category: 'fire', risk: 'extreme' },
27
- 'HIGHRISE FIRE': { category: 'fire', risk: 'extreme' },
28
- 'VEHICLE FIRE': { category: 'fire', risk: 'high' },
29
- 'BRUSH FIRE': { category: 'fire', risk: 'severe' },
30
- 'WILDFIRE': { category: 'fire', risk: 'severe' },
31
- 'GRASS FIRE': { category: 'fire', risk: 'high' },
32
- 'DUMPSTER FIRE': { category: 'fire', risk: 'moderate' },
33
- 'FIRE ALARM': { category: 'fire', risk: 'low' },
34
- 'SMOKE INVESTIGATION': { category: 'fire', risk: 'moderate' },
35
- // Medical emergencies
36
- 'CARDIAC ARREST': { category: 'medical', risk: 'severe' },
37
- 'CARDIAC EMERGENCY': { category: 'medical', risk: 'severe' },
38
- 'STROKE': { category: 'medical', risk: 'severe' },
39
- 'CHEST PAIN': { category: 'medical', risk: 'high' },
40
- 'DIFFICULTY BREATHING': { category: 'medical', risk: 'high' },
41
- 'RESPIRATORY': { category: 'medical', risk: 'high' },
42
- 'UNCONSCIOUS': { category: 'medical', risk: 'high' },
43
- 'OVERDOSE': { category: 'medical', risk: 'high' },
44
- 'MEDICAL EMERGENCY': { category: 'medical', risk: 'high' },
45
- 'MEDICAL AID': { category: 'medical', risk: 'moderate' },
46
- 'FALL': { category: 'medical', risk: 'moderate' },
47
- 'INJURY': { category: 'medical', risk: 'moderate' },
48
- 'DIABETIC': { category: 'medical', risk: 'high' },
49
- 'SEIZURE': { category: 'medical', risk: 'high' },
50
- // Traffic/rescue
51
- 'TRAFFIC COLLISION': { category: 'medical', risk: 'high' },
52
- 'TRAFFIC ACCIDENT': { category: 'medical', risk: 'high' },
53
- 'MVA': { category: 'medical', risk: 'high' },
54
- 'EXTRICATION': { category: 'medical', risk: 'severe' },
55
- 'RESCUE': { category: 'medical', risk: 'high' },
56
- 'WATER RESCUE': { category: 'medical', risk: 'severe' },
57
- 'SWIFT WATER RESCUE': { category: 'medical', risk: 'severe' },
58
- // Hazmat
59
- 'HAZMAT': { category: 'fire', risk: 'severe' },
60
- 'GAS LEAK': { category: 'fire', risk: 'high' },
61
- 'NATURAL GAS LEAK': { category: 'fire', risk: 'high' },
62
- 'CARBON MONOXIDE': { category: 'fire', risk: 'high' },
63
- 'ELECTRICAL': { category: 'fire', risk: 'high' },
64
- };
65
- /**
66
- * Plugin that fetches real-time fire and EMS incidents from Pulsepoint.
67
- *
68
- * Pulsepoint provides real-time incident data from participating fire departments.
69
- *
70
- * @see https://www.pulsepoint.org
71
- */
72
- export class PulsepointPlugin extends BasePlugin {
73
- metadata = {
74
- id: 'pulsepoint',
75
- name: 'Pulsepoint Real-Time Incidents',
76
- version: '1.0.0',
77
- description: 'Real-time fire and EMS incidents from Pulsepoint',
78
- coverage: {
79
- type: 'regional',
80
- center: PHOENIX_CENTER,
81
- radiusMeters: COVERAGE_RADIUS_METERS,
82
- description: 'Phoenix, AZ metropolitan area (participating agencies)',
83
- },
84
- supportedTemporalTypes: ['real-time'],
85
- supportedCategories: ['fire', 'medical'],
86
- refreshIntervalMs: 60 * 1000, // 1 minute - real-time data
87
- };
88
- pulsepointConfig;
89
- constructor(config) {
90
- super(config);
91
- this.pulsepointConfig = {
92
- agencyIds: DEFAULT_PHOENIX_AGENCIES,
93
- includeRecent: false,
94
- ...config,
95
- };
96
- }
97
- async fetchAlerts(options) {
98
- const { location, radiusMeters, categories } = options;
99
- const cacheKey = this.generateCacheKey(options);
100
- const warnings = [];
101
- try {
102
- const { data, fromCache } = await this.getCachedOrFetch(cacheKey, () => this.fetchAllAgencies(warnings),
103
- // Short cache TTL for real-time data
104
- 30 * 1000 // 30 seconds
105
- );
106
- // Filter by location radius
107
- let alerts = data.filter((alert) => {
108
- const distance = this.calculateDistance(location.latitude, location.longitude, alert.location.point.latitude, alert.location.point.longitude);
109
- return distance <= radiusMeters;
110
- });
111
- // Filter by categories if specified
112
- if (categories && categories.length > 0) {
113
- alerts = alerts.filter((alert) => categories.includes(alert.category));
114
- }
115
- return {
116
- alerts,
117
- fromCache,
118
- cacheKey,
119
- warnings: warnings.length > 0 ? warnings : undefined,
120
- };
121
- }
122
- catch (error) {
123
- console.error('Pulsepoint fetch error:', error);
124
- throw error;
125
- }
126
- }
127
- /**
128
- * Fetch incidents from all configured agencies.
129
- */
130
- async fetchAllAgencies(warnings) {
131
- const allAlerts = [];
132
- for (const agencyId of this.pulsepointConfig.agencyIds) {
133
- try {
134
- const incidents = await this.fetchAgencyIncidents(agencyId);
135
- const alerts = incidents.map((incident) => this.transformIncident(incident, agencyId));
136
- allAlerts.push(...alerts);
137
- }
138
- catch (error) {
139
- warnings.push(`Failed to fetch from agency ${agencyId}: ${error instanceof Error ? error.message : 'Unknown error'}`);
140
- }
141
- }
142
- return allAlerts;
143
- }
144
- /**
145
- * Fetch incidents from a single Pulsepoint agency.
146
- */
147
- async fetchAgencyIncidents(agencyId) {
148
- // Pulsepoint web API endpoint
149
- const url = `https://web.pulsepoint.org/DB/giba.php?agency_id=${agencyId}`;
150
- const response = await this.fetchJson(url);
151
- const incidents = [];
152
- if (response.incidents?.active) {
153
- incidents.push(...response.incidents.active);
154
- }
155
- if (this.pulsepointConfig.includeRecent && response.incidents?.recent) {
156
- incidents.push(...response.incidents.recent);
157
- }
158
- return incidents;
159
- }
160
- /**
161
- * Transform a Pulsepoint incident to our Alert format.
162
- */
163
- transformIncident(incident, agencyId) {
164
- const incidentType = incident.IncidentTypeName.toUpperCase();
165
- const { category, risk } = this.mapIncidentType(incidentType);
166
- const latitude = parseFloat(incident.Latitude);
167
- const longitude = parseFloat(incident.Longitude);
168
- // Use call received time as the incident time
169
- const issued = incident.CallReceivedDateTime;
170
- // Build description with unit info
171
- const description = this.buildDescription(incident);
172
- return this.createAlert({
173
- id: `pulsepoint-${agencyId}-${incident.ID}`,
174
- externalId: incident.ID,
175
- title: this.formatIncidentType(incident.IncidentTypeName),
176
- description,
177
- riskLevel: risk,
178
- priority: this.riskLevelToPriority(risk),
179
- category,
180
- temporalType: 'real-time',
181
- location: {
182
- point: { latitude, longitude },
183
- address: incident.MedicalEmergencyDisplayAddress ?? incident.FullDisplayAddress,
184
- },
185
- timestamps: {
186
- issued,
187
- eventStart: issued,
188
- },
189
- metadata: {
190
- agencyId,
191
- incidentTypeCode: incident.IncidentTypeCode,
192
- units: incident.Unit?.map((u) => ({
193
- id: u.UnitID,
194
- status: u.PulsePointDispatchStatus,
195
- })),
196
- isClosed: incident.Status?.IncidentClosed ?? false,
197
- },
198
- });
199
- }
200
- /**
201
- * Map incident type to category and risk level.
202
- */
203
- mapIncidentType(incidentType) {
204
- // Try exact match
205
- if (INCIDENT_TYPE_MAP[incidentType]) {
206
- return INCIDENT_TYPE_MAP[incidentType];
207
- }
208
- // Try partial match
209
- for (const [key, value] of Object.entries(INCIDENT_TYPE_MAP)) {
210
- if (incidentType.includes(key)) {
211
- return value;
212
- }
213
- }
214
- // Default based on keywords
215
- if (incidentType.includes('FIRE') || incidentType.includes('SMOKE') || incidentType.includes('BURN')) {
216
- return { category: 'fire', risk: 'high' };
217
- }
218
- if (incidentType.includes('MEDICAL') || incidentType.includes('EMS') || incidentType.includes('AMBULANCE')) {
219
- return { category: 'medical', risk: 'moderate' };
220
- }
221
- // Default to medical (most common)
222
- return { category: 'medical', risk: 'moderate' };
223
- }
224
- /**
225
- * Format incident type for display.
226
- */
227
- formatIncidentType(incidentType) {
228
- return incidentType
229
- .toLowerCase()
230
- .split(' ')
231
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
232
- .join(' ');
233
- }
234
- /**
235
- * Build description from incident data.
236
- */
237
- buildDescription(incident) {
238
- const parts = [];
239
- parts.push(`Type: ${this.formatIncidentType(incident.IncidentTypeName)}`);
240
- if (incident.FullDisplayAddress) {
241
- parts.push(`Location: ${incident.FullDisplayAddress}`);
242
- }
243
- if (incident.Unit && incident.Unit.length > 0) {
244
- const unitList = incident.Unit.map((u) => `${u.UnitID} (${u.PulsePointDispatchStatus})`).join(', ');
245
- parts.push(`Responding Units: ${unitList}`);
246
- }
247
- if (incident.Status?.IncidentClosed) {
248
- parts.push('Status: Closed');
249
- }
250
- else {
251
- parts.push('Status: Active');
252
- }
253
- return parts.join('\n');
254
- }
255
- /**
256
- * Calculate distance between two points in meters.
257
- */
258
- calculateDistance(lat1, lon1, lat2, lon2) {
259
- const R = 6371e3; // Earth radius in meters
260
- const φ1 = (lat1 * Math.PI) / 180;
261
- const φ2 = (lat2 * Math.PI) / 180;
262
- const Δφ = ((lat2 - lat1) * Math.PI) / 180;
263
- const Δλ = ((lon2 - lon1) * Math.PI) / 180;
264
- const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
265
- Math.cos(φ1) * Math.cos(φ2) *
266
- Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
267
- const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
268
- return R * c;
269
- }
270
- }
271
- //# sourceMappingURL=pulsepoint.plugin.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pulsepoint.plugin.js","sourceRoot":"","sources":["../../../../src/plugins/pulsepoint/pulsepoint.plugin.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- export { PhoenixPolicePlugin } from './phoenix-police.plugin';
2
- export type { PhoenixPolicePluginConfig } from './phoenix-police.plugin';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/plugins/police-blotter/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,YAAY,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,49 +0,0 @@
1
- import type { PluginMetadata, PluginFetchOptions, PluginFetchResult } from '../../types';
2
- import { BasePlugin, BasePluginConfig } from '../base-plugin';
3
- /**
4
- * Phoenix Police plugin configuration.
5
- */
6
- export interface PhoenixPolicePluginConfig extends BasePluginConfig {
7
- /** Socrata app token for higher rate limits (optional) */
8
- appToken?: string;
9
- /** Maximum records to fetch per request. Default: 1000 */
10
- limit?: number;
11
- }
12
- /**
13
- * Plugin that fetches crime data from the Phoenix Open Data Portal.
14
- *
15
- * Uses the Phoenix Crime Incidents dataset via Socrata API.
16
- *
17
- * @see https://www.phoenixopendata.com/dataset/crime-data
18
- */
19
- export declare class PhoenixPolicePlugin extends BasePlugin {
20
- readonly metadata: PluginMetadata;
21
- private phoenixConfig;
22
- constructor(config?: PhoenixPolicePluginConfig);
23
- fetchAlerts(options: PluginFetchOptions): Promise<PluginFetchResult>;
24
- /**
25
- * Build the Socrata API URL for Phoenix crime data.
26
- */
27
- private buildApiUrl;
28
- /**
29
- * Fetch incidents from the API.
30
- */
31
- private fetchIncidents;
32
- /**
33
- * Transform a Phoenix Police incident to our Alert format.
34
- */
35
- private transformIncident;
36
- /**
37
- * Map a crime category to a risk level.
38
- */
39
- private mapCrimeToRiskLevel;
40
- /**
41
- * Format the crime category as a title.
42
- */
43
- private formatCrimeTitle;
44
- /**
45
- * Build a description from incident data.
46
- */
47
- private buildDescription;
48
- }
49
- //# sourceMappingURL=phoenix-police.plugin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"phoenix-police.plugin.d.ts","sourceRoot":"","sources":["../../../../src/plugins/police-blotter/phoenix-police.plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAa,MAAM,aAAa,CAAC;AACpG,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAmB9D;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,gBAAgB;IACjE,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAgCD;;;;;;GAMG;AACH,qBAAa,mBAAoB,SAAQ,UAAU;IACjD,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAc/B;IAEF,OAAO,CAAC,aAAa,CAA4B;gBAErC,MAAM,CAAC,EAAE,yBAAyB;IAQxC,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA4B1E;;OAEG;IACH,OAAO,CAAC,WAAW;IA0CnB;;OAEG;YACW,cAAc;IAI5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA4CzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAI3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IASxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAqBzB"}
@@ -1,3 +0,0 @@
1
- export { PulsepointPlugin } from './pulsepoint.plugin';
2
- export type { PulsepointPluginConfig } from './pulsepoint.plugin';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/plugins/pulsepoint/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -1,61 +0,0 @@
1
- import type { PluginMetadata, PluginFetchOptions, PluginFetchResult } from '../../types';
2
- import { BasePlugin, BasePluginConfig } from '../base-plugin';
3
- /**
4
- * Pulsepoint plugin configuration.
5
- */
6
- export interface PulsepointPluginConfig extends BasePluginConfig {
7
- /**
8
- * Pulsepoint agency IDs to monitor.
9
- * For Phoenix area:
10
- * - FPHX (Phoenix Fire)
11
- * - FMES (Mesa Fire)
12
- * - FTEM (Tempe Fire)
13
- * - FGLN (Glendale Fire)
14
- * - FSCOT (Scottsdale Fire)
15
- */
16
- agencyIds?: string[];
17
- /** Include recently closed incidents. Default: false */
18
- includeRecent?: boolean;
19
- }
20
- /**
21
- * Plugin that fetches real-time fire and EMS incidents from Pulsepoint.
22
- *
23
- * Pulsepoint provides real-time incident data from participating fire departments.
24
- *
25
- * @see https://www.pulsepoint.org
26
- */
27
- export declare class PulsepointPlugin extends BasePlugin {
28
- readonly metadata: PluginMetadata;
29
- private pulsepointConfig;
30
- constructor(config?: PulsepointPluginConfig);
31
- fetchAlerts(options: PluginFetchOptions): Promise<PluginFetchResult>;
32
- /**
33
- * Fetch incidents from all configured agencies.
34
- */
35
- private fetchAllAgencies;
36
- /**
37
- * Fetch incidents from a single Pulsepoint agency.
38
- */
39
- private fetchAgencyIncidents;
40
- /**
41
- * Transform a Pulsepoint incident to our Alert format.
42
- */
43
- private transformIncident;
44
- /**
45
- * Map incident type to category and risk level.
46
- */
47
- private mapIncidentType;
48
- /**
49
- * Format incident type for display.
50
- */
51
- private formatIncidentType;
52
- /**
53
- * Build description from incident data.
54
- */
55
- private buildDescription;
56
- /**
57
- * Calculate distance between two points in meters.
58
- */
59
- private calculateDistance;
60
- }
61
- //# sourceMappingURL=pulsepoint.plugin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pulsepoint.plugin.d.ts","sourceRoot":"","sources":["../../../../src/plugins/pulsepoint/pulsepoint.plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAA4B,MAAM,aAAa,CAAC;AACnH,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAkC9D;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,wDAAwD;IACxD,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAwED;;;;;;GAMG;AACH,qBAAa,gBAAiB,SAAQ,UAAU;IAC9C,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAc/B;IAEF,OAAO,CAAC,gBAAgB,CAAyB;gBAErC,MAAM,CAAC,EAAE,sBAAsB;IASrC,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAyC1E;;OAEG;YACW,gBAAgB;IAkB9B;;OAEG;YACW,oBAAoB;IAmBlC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA0CzB;;OAEG;IACH,OAAO,CAAC,eAAe;IA0BvB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAQ1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAuBxB;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAc1B"}