@sierragridteam/sdk 0.0.0-stage → 0.1.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.
- package/README.md +49 -2
- package/dist/fixtures-data.d.ts +609 -0
- package/dist/fixtures-data.js +2676 -0
- package/dist/fixtures.d.ts +12 -0
- package/dist/fixtures.js +139 -0
- package/dist/generated/client/client.gen.d.ts +2 -0
- package/dist/generated/client/client.gen.js +216 -0
- package/dist/generated/client/index.d.ts +10 -0
- package/dist/generated/client/index.js +6 -0
- package/dist/generated/client/types.gen.d.ts +120 -0
- package/dist/generated/client/types.gen.js +2 -0
- package/dist/generated/client/utils.gen.d.ts +37 -0
- package/dist/generated/client/utils.gen.js +228 -0
- package/dist/generated/client.gen.d.ts +12 -0
- package/dist/generated/client.gen.js +3 -0
- package/dist/generated/core/auth.gen.d.ts +25 -0
- package/dist/generated/core/auth.gen.js +14 -0
- package/dist/generated/core/bodySerializer.gen.d.ts +25 -0
- package/dist/generated/core/bodySerializer.gen.js +57 -0
- package/dist/generated/core/params.gen.d.ts +43 -0
- package/dist/generated/core/params.gen.js +109 -0
- package/dist/generated/core/pathSerializer.gen.d.ts +33 -0
- package/dist/generated/core/pathSerializer.gen.js +106 -0
- package/dist/generated/core/queryKeySerializer.gen.d.ts +18 -0
- package/dist/generated/core/queryKeySerializer.gen.js +92 -0
- package/dist/generated/core/serverSentEvents.gen.d.ts +71 -0
- package/dist/generated/core/serverSentEvents.gen.js +132 -0
- package/dist/generated/core/types.gen.d.ts +83 -0
- package/dist/generated/core/types.gen.js +2 -0
- package/dist/generated/core/utils.gen.d.ts +19 -0
- package/dist/generated/core/utils.gen.js +87 -0
- package/dist/generated/index.d.ts +2 -0
- package/dist/generated/index.js +2 -0
- package/dist/generated/sdk.gen.d.ts +210 -0
- package/dist/generated/sdk.gen.js +336 -0
- package/dist/generated/types.gen.d.ts +3474 -0
- package/dist/generated/types.gen.js +2 -0
- package/dist/generated/zod.gen.d.ts +6537 -0
- package/dist/generated/zod.gen.js +1849 -0
- package/dist/index.d.ts +1287 -0
- package/dist/index.js +99 -0
- package/package.json +42 -4
|
@@ -0,0 +1,1849 @@
|
|
|
1
|
+
// This file is auto-generated by @hey-api/openapi-ts
|
|
2
|
+
import * as z from 'zod';
|
|
3
|
+
export const zBurnLineReading = z.object({
|
|
4
|
+
cleaned_transcription: z.string().optional(),
|
|
5
|
+
confidence: z.int().gte(0).lte(100).optional(),
|
|
6
|
+
line_id: z.string(),
|
|
7
|
+
message: z.string().optional(),
|
|
8
|
+
observed_at: z.iso.datetime(),
|
|
9
|
+
status: z.enum([
|
|
10
|
+
'green',
|
|
11
|
+
'red',
|
|
12
|
+
'orange'
|
|
13
|
+
])
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* `burn.line` (schema_version 1): readings of the county burn-day phone
|
|
17
|
+
* recordings, sent as ONE batched report per run (the per-reporter rate
|
|
18
|
+
* limit would 429 a second push). Each reading is staged durably.
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
export const zBurnLineReport = z.object({
|
|
22
|
+
generated_at: z.iso.datetime().optional(),
|
|
23
|
+
readings: z.array(zBurnLineReading).min(1).max(1000),
|
|
24
|
+
schema_version: z.literal(1)
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* The 202 body. Validated and queued, not yet stored; it lands on the next ingest cycle (about a minute).
|
|
28
|
+
*/
|
|
29
|
+
export const zIngestAccepted = z.object({
|
|
30
|
+
accepted: z.int(),
|
|
31
|
+
receivedAt: z.iso.datetime(),
|
|
32
|
+
reporterId: z.string(),
|
|
33
|
+
stream: z.string(),
|
|
34
|
+
warnings: z.array(z.string()).optional()
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* A JSON-RPC 2.0 request. Omit `id` for a notification (answered 202, no body).
|
|
38
|
+
*/
|
|
39
|
+
export const zJsonRpcRequest = z.object({
|
|
40
|
+
id: z.unknown().optional(),
|
|
41
|
+
jsonrpc: z.enum(['2.0']),
|
|
42
|
+
method: z.enum([
|
|
43
|
+
'initialize',
|
|
44
|
+
'ping',
|
|
45
|
+
'tools/list',
|
|
46
|
+
'tools/call',
|
|
47
|
+
'resources/list',
|
|
48
|
+
'resources/read',
|
|
49
|
+
'prompts/list',
|
|
50
|
+
'prompts/get',
|
|
51
|
+
'notifications/initialized'
|
|
52
|
+
]),
|
|
53
|
+
params: z.record(z.string(), z.unknown()).optional()
|
|
54
|
+
});
|
|
55
|
+
export const zJsonRpcResponse = z.object({
|
|
56
|
+
error: z.object({
|
|
57
|
+
code: z.int(),
|
|
58
|
+
message: z.string()
|
|
59
|
+
}).optional(),
|
|
60
|
+
id: z.unknown().optional(),
|
|
61
|
+
jsonrpc: z.enum(['2.0']),
|
|
62
|
+
result: z.record(z.string(), z.unknown()).optional()
|
|
63
|
+
});
|
|
64
|
+
/**
|
|
65
|
+
* camera block - a Caltrans CCTV camera, same data as GET /api/v1/cameras?place=. Load the image and stream directly from Caltrans; they are not proxied.
|
|
66
|
+
*/
|
|
67
|
+
export const zMapCameraProps = z.object({
|
|
68
|
+
county: z.string().optional(),
|
|
69
|
+
direction: z.string().optional(),
|
|
70
|
+
distanceMeters: z.int(),
|
|
71
|
+
elevationFeet: z.int().optional(),
|
|
72
|
+
imageRefreshMinutes: z.int().optional(),
|
|
73
|
+
imageUrl: z.string(),
|
|
74
|
+
route: z.string().optional(),
|
|
75
|
+
streamUrl: z.string().optional()
|
|
76
|
+
});
|
|
77
|
+
/**
|
|
78
|
+
* chain_control block. Severity follows the level (R1 MINOR, R2 MODERATE, R3 SEVERE); a seasonal pass closure (`category` closed) is MINOR.
|
|
79
|
+
*/
|
|
80
|
+
export const zMapChainControlProps = z.object({
|
|
81
|
+
direction: z.string().optional(),
|
|
82
|
+
highway: z.string().optional(),
|
|
83
|
+
level: z.enum([
|
|
84
|
+
'R1',
|
|
85
|
+
'R2',
|
|
86
|
+
'R3'
|
|
87
|
+
]).optional()
|
|
88
|
+
});
|
|
89
|
+
/**
|
|
90
|
+
* Set on Caltrans planned lane closures (category `closure`) only. One
|
|
91
|
+
* feature per work window. `plannedEnd` is an estimate crews overrun: an
|
|
92
|
+
* ACTIVE closure past it is still on the road until Caltrans records it
|
|
93
|
+
* picked up.
|
|
94
|
+
*
|
|
95
|
+
*/
|
|
96
|
+
export const zMapClosureProps = z.object({
|
|
97
|
+
closureType: z.string().optional(),
|
|
98
|
+
estimatedDelayMinutes: z.int().optional(),
|
|
99
|
+
lanesClosed: z.string().optional(),
|
|
100
|
+
plannedEnd: z.iso.datetime().optional(),
|
|
101
|
+
plannedStart: z.iso.datetime().optional(),
|
|
102
|
+
setUpAt: z.iso.datetime().optional(),
|
|
103
|
+
totalLanes: z.int().optional(),
|
|
104
|
+
windowId: z.string(),
|
|
105
|
+
workType: z.string().optional()
|
|
106
|
+
});
|
|
107
|
+
/**
|
|
108
|
+
* earthquake block (USGS).
|
|
109
|
+
*/
|
|
110
|
+
export const zMapEarthquakeProps = z.object({
|
|
111
|
+
depthKm: z.number(),
|
|
112
|
+
felt: z.int().optional(),
|
|
113
|
+
magnitude: z.number()
|
|
114
|
+
});
|
|
115
|
+
/**
|
|
116
|
+
* evacuation block (Cal OES / Genasys zones). Life-safety; reference only, link `source.url`.
|
|
117
|
+
*/
|
|
118
|
+
export const zMapEvacuationProps = z.object({
|
|
119
|
+
county: z.string().optional(),
|
|
120
|
+
eventType: z.string().optional(),
|
|
121
|
+
level: z.enum([
|
|
122
|
+
'ORDER',
|
|
123
|
+
'WARNING',
|
|
124
|
+
'ADVISORY',
|
|
125
|
+
'SHELTER_IN_PLACE'
|
|
126
|
+
]),
|
|
127
|
+
zoneId: z.string().optional()
|
|
128
|
+
});
|
|
129
|
+
/**
|
|
130
|
+
* The upstream feed this feature came from. Render `attribution` with the feature.
|
|
131
|
+
*/
|
|
132
|
+
export const zMapFeatureSource = z.object({
|
|
133
|
+
attribution: z.string().optional(),
|
|
134
|
+
fetchedAt: z.iso.datetime().optional(),
|
|
135
|
+
id: z.string(),
|
|
136
|
+
name: z.string(),
|
|
137
|
+
url: z.string().optional()
|
|
138
|
+
});
|
|
139
|
+
/**
|
|
140
|
+
* fire_weather block. The region banner (id `fw:region`, null geometry)
|
|
141
|
+
* carries the ISSUED `state`; only NWS products set it (Fire Weather Watch
|
|
142
|
+
* -> elevated, Red Flag Warning -> red-flag). Forecast points (id
|
|
143
|
+
* `fw:forecast:<location>`) carry `forecast` instead, are always INFO and
|
|
144
|
+
* never imply a warning.
|
|
145
|
+
*
|
|
146
|
+
*/
|
|
147
|
+
export const zMapFireWeatherProps = z.object({
|
|
148
|
+
forecast: z.object({
|
|
149
|
+
horizonHours: z.int().optional(),
|
|
150
|
+
issuedAt: z.iso.datetime().optional(),
|
|
151
|
+
minHumidityPercent: z.int().optional(),
|
|
152
|
+
peakWindGustAt: z.iso.datetime().optional(),
|
|
153
|
+
peakWindGustKmh: z.int().optional(),
|
|
154
|
+
source: z.string().optional()
|
|
155
|
+
}).optional(),
|
|
156
|
+
sourceEvent: z.string().optional(),
|
|
157
|
+
state: z.enum([
|
|
158
|
+
'normal',
|
|
159
|
+
'elevated',
|
|
160
|
+
'red-flag'
|
|
161
|
+
]).optional(),
|
|
162
|
+
zones: z.array(z.string()).optional()
|
|
163
|
+
});
|
|
164
|
+
/**
|
|
165
|
+
* An RFC 7946 geometry, or `null` for a feature with no location (NWS zone
|
|
166
|
+
* alerts and the fire-weather region banner): render those as a banner
|
|
167
|
+
* or list row, not a shape.
|
|
168
|
+
*
|
|
169
|
+
* A position is `[longitude, latitude]`, longitude FIRST (RFC 7946
|
|
170
|
+
* §3.1.1), the reverse of the `{lat, lng}` objects on the JSON RPCs.
|
|
171
|
+
* Store-derived positions are trimmed to 5 decimals (~1 m).
|
|
172
|
+
*
|
|
173
|
+
* Which types appear: Point (most layers: incidents, signs, cameras,
|
|
174
|
+
* chain controls, quakes, mesh nodes, forecast points, unmapped fires);
|
|
175
|
+
* LineString (road_segment routes, mesh_link edges); Polygon or
|
|
176
|
+
* MultiPolygon (power outage areas, evacuation zones, fire perimeters).
|
|
177
|
+
* Geometry passed through from an upstream ArcGIS feed may be any RFC 7946
|
|
178
|
+
* type except GeometryCollection.
|
|
179
|
+
*
|
|
180
|
+
*/
|
|
181
|
+
export const zMapGeometry = z.object({
|
|
182
|
+
coordinates: z.array(z.unknown()),
|
|
183
|
+
type: z.enum([
|
|
184
|
+
'Point',
|
|
185
|
+
'MultiPoint',
|
|
186
|
+
'LineString',
|
|
187
|
+
'MultiLineString',
|
|
188
|
+
'Polygon',
|
|
189
|
+
'MultiPolygon'
|
|
190
|
+
])
|
|
191
|
+
}).nullable();
|
|
192
|
+
/**
|
|
193
|
+
* An RFC 7946 geometry object, the same shape as a map feature's
|
|
194
|
+
* `geometry` (MapGeometry) but never `null`: an event's or place's
|
|
195
|
+
* `geometry.object` when the request passes `geometryFormat=OBJECT`.
|
|
196
|
+
* A position is `[longitude, latitude]`, longitude first.
|
|
197
|
+
*
|
|
198
|
+
*/
|
|
199
|
+
export const zGeoJsonGeometry = zMapGeometry;
|
|
200
|
+
/**
|
|
201
|
+
* road_incident block.
|
|
202
|
+
*/
|
|
203
|
+
export const zMapIncidentProps = z.object({
|
|
204
|
+
closure: zMapClosureProps.optional(),
|
|
205
|
+
logNumber: z.string().optional()
|
|
206
|
+
});
|
|
207
|
+
/**
|
|
208
|
+
* Provenance and freshness of the whole layer.
|
|
209
|
+
*/
|
|
210
|
+
export const zMapLayerMetadata = z.object({
|
|
211
|
+
area: z.string(),
|
|
212
|
+
attribution: z.string().optional(),
|
|
213
|
+
generatedAt: z.iso.datetime(),
|
|
214
|
+
lastSourceUpdate: z.iso.datetime().optional(),
|
|
215
|
+
layer: z.enum([
|
|
216
|
+
'road_incident',
|
|
217
|
+
'chain_control',
|
|
218
|
+
'road_segment',
|
|
219
|
+
'message_sign',
|
|
220
|
+
'weather_alert',
|
|
221
|
+
'fire_weather',
|
|
222
|
+
'earthquake',
|
|
223
|
+
'wildfire',
|
|
224
|
+
'evacuation',
|
|
225
|
+
'power',
|
|
226
|
+
'mesh_node',
|
|
227
|
+
'mesh_link',
|
|
228
|
+
'camera'
|
|
229
|
+
]),
|
|
230
|
+
schemaVersion: z.literal(1),
|
|
231
|
+
sourceStatus: z.enum([
|
|
232
|
+
'OK',
|
|
233
|
+
'STALE',
|
|
234
|
+
'UNAVAILABLE'
|
|
235
|
+
]),
|
|
236
|
+
sourceUrl: z.string().optional()
|
|
237
|
+
});
|
|
238
|
+
/**
|
|
239
|
+
* The last sample an operator monitor read off the node itself. Gauges the device did not report are absent, never 0.
|
|
240
|
+
*/
|
|
241
|
+
export const zMapMeshAdminProps = z.object({
|
|
242
|
+
airtimeMs: z.int().optional(),
|
|
243
|
+
batteryPercent: z.number().optional(),
|
|
244
|
+
batteryPercentSource: z.string().optional(),
|
|
245
|
+
batteryVolts: z.number().optional(),
|
|
246
|
+
lastSuccessAt: z.iso.datetime().optional(),
|
|
247
|
+
noiseFloorDbm: z.int().optional(),
|
|
248
|
+
packetsReceived: z.int().optional(),
|
|
249
|
+
packetsSent: z.int().optional(),
|
|
250
|
+
recvErrors: z.int().optional(),
|
|
251
|
+
reportedAt: z.iso.datetime().optional(),
|
|
252
|
+
reporterId: z.string(),
|
|
253
|
+
rxAirtimeMs: z.int().optional(),
|
|
254
|
+
temperatureC: z.number().optional(),
|
|
255
|
+
txQueueLen: z.int().optional(),
|
|
256
|
+
uptimeSeconds: z.int().optional()
|
|
257
|
+
});
|
|
258
|
+
/**
|
|
259
|
+
* mesh_link edge block - one undirected relay link between two located nodes. Weight by `daysActive`/`observations`, fade by `lastSeen`.
|
|
260
|
+
*/
|
|
261
|
+
export const zMapMeshLinkProps = z.object({
|
|
262
|
+
a: z.string(),
|
|
263
|
+
b: z.string(),
|
|
264
|
+
bestSnr: z.number().optional(),
|
|
265
|
+
daysActive: z.int(),
|
|
266
|
+
firstSeen: z.iso.datetime().optional(),
|
|
267
|
+
lastSeen: z.iso.datetime().optional(),
|
|
268
|
+
observations: z.int()
|
|
269
|
+
});
|
|
270
|
+
/**
|
|
271
|
+
* mesh_node block (MeshCore node presence; also on the MESH_NODE points of
|
|
272
|
+
* the mesh_link layer). Signal readings are absent when no bridge heard the
|
|
273
|
+
* node; a present 0 is a reading. A node's freshness is the later of
|
|
274
|
+
* `lastHeardAt` and `lastRelayedAt`, never the feature's `updatedAt`.
|
|
275
|
+
*
|
|
276
|
+
*/
|
|
277
|
+
export const zMapMeshProps = z.object({
|
|
278
|
+
admin: zMapMeshAdminProps.optional(),
|
|
279
|
+
gateways: z.array(z.string()).optional(),
|
|
280
|
+
hopCount: z.int().optional(),
|
|
281
|
+
inRegion: z.boolean().optional(),
|
|
282
|
+
lastHeardAt: z.iso.datetime().optional(),
|
|
283
|
+
lastRelayedAt: z.iso.datetime().optional(),
|
|
284
|
+
name: z.string().optional(),
|
|
285
|
+
nodeType: z.enum([
|
|
286
|
+
'companion',
|
|
287
|
+
'repeater',
|
|
288
|
+
'room_server',
|
|
289
|
+
'sensor'
|
|
290
|
+
]).optional(),
|
|
291
|
+
publicKey: z.string(),
|
|
292
|
+
reachability: z.enum(['REACHABLE', 'UNREACHABLE']).optional(),
|
|
293
|
+
rssi: z.int().optional(),
|
|
294
|
+
snr: z.number().optional()
|
|
295
|
+
});
|
|
296
|
+
/**
|
|
297
|
+
* message_sign block - what a Caltrans changeable message sign is showing, verbatim. Context, not a hazard.
|
|
298
|
+
*/
|
|
299
|
+
export const zMapMessageSignProps = z.object({
|
|
300
|
+
direction: z.string().optional(),
|
|
301
|
+
district: z.int(),
|
|
302
|
+
inService: z.boolean(),
|
|
303
|
+
pages: z.array(z.tuple([
|
|
304
|
+
z.string(),
|
|
305
|
+
z.string(),
|
|
306
|
+
z.string()
|
|
307
|
+
])).optional(),
|
|
308
|
+
route: z.string().optional(),
|
|
309
|
+
signId: z.string()
|
|
310
|
+
});
|
|
311
|
+
/**
|
|
312
|
+
* power block, both PG&E feeds. `category` unplanned|planned sets the
|
|
313
|
+
* outage fields; `psps` (Public Safety Power Shutoff) sets the PSPS fields.
|
|
314
|
+
* `estimatedRestoration`, `deEnergizationEnd` and `allClear` are PG&E
|
|
315
|
+
* ESTIMATES that are routinely overrun; label them as estimates.
|
|
316
|
+
*
|
|
317
|
+
*/
|
|
318
|
+
export const zMapPowerProps = z.object({
|
|
319
|
+
allClear: z.iso.datetime().optional(),
|
|
320
|
+
cause: z.string().optional(),
|
|
321
|
+
crewStatus: z.string().optional(),
|
|
322
|
+
customersAffected: z.int().optional(),
|
|
323
|
+
deEnergizationEnd: z.iso.datetime().optional(),
|
|
324
|
+
deEnergizationStart: z.iso.datetime().optional(),
|
|
325
|
+
estimatedRestoration: z.iso.datetime().optional(),
|
|
326
|
+
eventName: z.string().optional(),
|
|
327
|
+
medicalBaselineAffected: z.int().optional(),
|
|
328
|
+
outageId: z.string().optional(),
|
|
329
|
+
stage: z.enum(['Watch', 'Warning']).optional()
|
|
330
|
+
});
|
|
331
|
+
/**
|
|
332
|
+
* road_segment block (Google Routes travel time over a configured route). The numbers are absent, not 0, until the route has been measured.
|
|
333
|
+
*/
|
|
334
|
+
export const zMapRoadProps = z.object({
|
|
335
|
+
congestion: z.enum([
|
|
336
|
+
'CLEAR',
|
|
337
|
+
'LIGHT',
|
|
338
|
+
'MODERATE',
|
|
339
|
+
'HEAVY',
|
|
340
|
+
'SEVERE',
|
|
341
|
+
'UNSPECIFIED'
|
|
342
|
+
]).optional(),
|
|
343
|
+
delayMinutes: z.int().optional(),
|
|
344
|
+
distanceKm: z.int().optional(),
|
|
345
|
+
durationMinutes: z.int().optional(),
|
|
346
|
+
roadId: z.string()
|
|
347
|
+
});
|
|
348
|
+
/**
|
|
349
|
+
* weather_alert block. The NWS CAP fields are verbatim; `nwsSeverity` is NWS's own scale, distinct from the unified `severity`.
|
|
350
|
+
*/
|
|
351
|
+
export const zMapWeatherProps = z.object({
|
|
352
|
+
certainty: z.string().optional(),
|
|
353
|
+
event: z.string().optional(),
|
|
354
|
+
instruction: z.string().optional(),
|
|
355
|
+
nwsSeverity: z.enum([
|
|
356
|
+
'Extreme',
|
|
357
|
+
'Severe',
|
|
358
|
+
'Moderate',
|
|
359
|
+
'Minor',
|
|
360
|
+
'Unknown'
|
|
361
|
+
]).optional(),
|
|
362
|
+
source: z.enum(['NWS']).optional(),
|
|
363
|
+
urgency: z.string().optional(),
|
|
364
|
+
zones: z.array(z.string()).optional()
|
|
365
|
+
});
|
|
366
|
+
/**
|
|
367
|
+
* wildfire block (CAL FIRE incidents and FIRIS perimeters).
|
|
368
|
+
*/
|
|
369
|
+
export const zMapWildfireProps = z.object({
|
|
370
|
+
acres: z.number().optional(),
|
|
371
|
+
cause: z.string().optional(),
|
|
372
|
+
containment: z.int().gte(0).lte(100),
|
|
373
|
+
county: z.string().optional(),
|
|
374
|
+
hasPerimeter: z.boolean()
|
|
375
|
+
});
|
|
376
|
+
/**
|
|
377
|
+
* The envelope shared by every feature of every layer, plus exactly one
|
|
378
|
+
* per-kind block named after the layer (`incident`, `road`,
|
|
379
|
+
* `chainControl`, `messageSign`, `weather`, `fireWeather`, `earthquake`,
|
|
380
|
+
* `wildfire`, `evacuation`, `power`, `mesh`, `meshLink`, `camera`).
|
|
381
|
+
* Optional members are omitted, never `""` or `0`, when they have no value.
|
|
382
|
+
*
|
|
383
|
+
*/
|
|
384
|
+
export const zMapFeatureProperties = z.object({
|
|
385
|
+
areaLabel: z.string().optional(),
|
|
386
|
+
camera: zMapCameraProps.optional(),
|
|
387
|
+
category: z.string().optional(),
|
|
388
|
+
chainControl: zMapChainControlProps.optional(),
|
|
389
|
+
description: z.string().optional(),
|
|
390
|
+
earthquake: zMapEarthquakeProps.optional(),
|
|
391
|
+
effective: z.iso.datetime().optional(),
|
|
392
|
+
evacuation: zMapEvacuationProps.optional(),
|
|
393
|
+
expires: z.iso.datetime().optional(),
|
|
394
|
+
fireWeather: zMapFireWeatherProps.optional(),
|
|
395
|
+
headline: z.string(),
|
|
396
|
+
id: z.string(),
|
|
397
|
+
incident: zMapIncidentProps.optional(),
|
|
398
|
+
kind: z.enum([
|
|
399
|
+
'Road incident',
|
|
400
|
+
'Chain control',
|
|
401
|
+
'Road segment',
|
|
402
|
+
'Message sign',
|
|
403
|
+
'Weather alert',
|
|
404
|
+
'Fire weather',
|
|
405
|
+
'Fire-weather forecast',
|
|
406
|
+
'Earthquake',
|
|
407
|
+
'Wildfire',
|
|
408
|
+
'Evacuation',
|
|
409
|
+
'Power outage',
|
|
410
|
+
'Public Safety Power Shutoff',
|
|
411
|
+
'Mesh node',
|
|
412
|
+
'Relay link',
|
|
413
|
+
'Traffic camera'
|
|
414
|
+
]),
|
|
415
|
+
layer: z.enum([
|
|
416
|
+
'ROAD_INCIDENT',
|
|
417
|
+
'CHAIN_CONTROL',
|
|
418
|
+
'ROAD_SEGMENT',
|
|
419
|
+
'MESSAGE_SIGN',
|
|
420
|
+
'WEATHER_ALERT',
|
|
421
|
+
'FIRE_WEATHER',
|
|
422
|
+
'EARTHQUAKE',
|
|
423
|
+
'WILDFIRE',
|
|
424
|
+
'EVACUATION',
|
|
425
|
+
'POWER',
|
|
426
|
+
'MESH_NODE',
|
|
427
|
+
'MESH_LINK',
|
|
428
|
+
'CAMERA'
|
|
429
|
+
]),
|
|
430
|
+
mesh: zMapMeshProps.optional(),
|
|
431
|
+
meshLink: zMapMeshLinkProps.optional(),
|
|
432
|
+
messageSign: zMapMessageSignProps.optional(),
|
|
433
|
+
power: zMapPowerProps.optional(),
|
|
434
|
+
road: zMapRoadProps.optional(),
|
|
435
|
+
severity: z.enum([
|
|
436
|
+
'INFO',
|
|
437
|
+
'MINOR',
|
|
438
|
+
'MODERATE',
|
|
439
|
+
'SEVERE',
|
|
440
|
+
'EXTREME'
|
|
441
|
+
]),
|
|
442
|
+
severityRank: z.int().gte(0).lte(4),
|
|
443
|
+
source: zMapFeatureSource,
|
|
444
|
+
status: z.enum([
|
|
445
|
+
'ACTIVE',
|
|
446
|
+
'SCHEDULED',
|
|
447
|
+
'ORDER',
|
|
448
|
+
'WARNING',
|
|
449
|
+
'ADVISORY',
|
|
450
|
+
'SHELTER_IN_PLACE',
|
|
451
|
+
'OPEN',
|
|
452
|
+
'CLOSED',
|
|
453
|
+
'RESTRICTED',
|
|
454
|
+
'MAINTENANCE',
|
|
455
|
+
'UNSPECIFIED'
|
|
456
|
+
]).optional(),
|
|
457
|
+
summary: z.string().optional(),
|
|
458
|
+
summaryEnhanced: z.object({
|
|
459
|
+
enhancedAt: z.iso.datetime().optional()
|
|
460
|
+
}).optional(),
|
|
461
|
+
updatedAt: z.iso.datetime().optional(),
|
|
462
|
+
weather: zMapWeatherProps.optional(),
|
|
463
|
+
wildfire: zMapWildfireProps.optional()
|
|
464
|
+
});
|
|
465
|
+
/**
|
|
466
|
+
* An RFC 7946 Feature.
|
|
467
|
+
*/
|
|
468
|
+
export const zMapFeature = z.object({
|
|
469
|
+
geometry: zMapGeometry,
|
|
470
|
+
properties: zMapFeatureProperties,
|
|
471
|
+
type: z.enum(['Feature'])
|
|
472
|
+
});
|
|
473
|
+
/**
|
|
474
|
+
* An RFC 7946 FeatureCollection for one place and one layer. `metadata` is
|
|
475
|
+
* an RFC 7946 §6.1 foreign member that map libraries ignore; read it for
|
|
476
|
+
* source health and attribution before drawing.
|
|
477
|
+
*
|
|
478
|
+
*/
|
|
479
|
+
export const zMapFeatureCollection = z.object({
|
|
480
|
+
features: z.array(zMapFeature),
|
|
481
|
+
metadata: zMapLayerMetadata,
|
|
482
|
+
type: z.enum(['FeatureCollection'])
|
|
483
|
+
});
|
|
484
|
+
/**
|
|
485
|
+
* One undirected relay link. Every member is always present.
|
|
486
|
+
*/
|
|
487
|
+
export const zMeshLink = z.object({
|
|
488
|
+
a: z.string(),
|
|
489
|
+
b: z.string(),
|
|
490
|
+
bestSnr: z.number(),
|
|
491
|
+
daysActive: z.int(),
|
|
492
|
+
firstSeen: z.iso.datetime(),
|
|
493
|
+
lastSeen: z.iso.datetime(),
|
|
494
|
+
observations: z.int()
|
|
495
|
+
});
|
|
496
|
+
export const zMeshLinkList = z.object({
|
|
497
|
+
generatedAt: z.iso.datetime(),
|
|
498
|
+
links: z.array(zMeshLink),
|
|
499
|
+
window: z.string()
|
|
500
|
+
});
|
|
501
|
+
/**
|
|
502
|
+
* One reception. Extra bridge fields are accepted and ignored.
|
|
503
|
+
*/
|
|
504
|
+
export const zMeshPacket = z.object({
|
|
505
|
+
RSSI: z.unknown().optional(),
|
|
506
|
+
SNR: z.unknown().optional(),
|
|
507
|
+
origin_id: z.string().optional(),
|
|
508
|
+
packet_type: z.int(),
|
|
509
|
+
raw: z.string(),
|
|
510
|
+
timestamp: z.string().optional()
|
|
511
|
+
});
|
|
512
|
+
/**
|
|
513
|
+
* `mesh.packet` (schema_version 1): raw MeshCore frames a companion radio
|
|
514
|
+
* heard, in the per-packet envelope the MQTT bridges publish. ADVERTs
|
|
515
|
+
* (packet_type 4) update a node after its Ed25519 signature verifies;
|
|
516
|
+
* other flood-routed packets credit relays. Answers 400 when MeshCore
|
|
517
|
+
* ingest is off on the server.
|
|
518
|
+
*
|
|
519
|
+
*/
|
|
520
|
+
export const zMeshPacketReport = z.object({
|
|
521
|
+
generated_at: z.iso.datetime().optional(),
|
|
522
|
+
observer: z.string().regex(/^[0-9a-fA-F]{8,64}$/).optional(),
|
|
523
|
+
packets: z.array(zMeshPacket).max(1000),
|
|
524
|
+
schema_version: z.literal(1)
|
|
525
|
+
});
|
|
526
|
+
export const zMeshRepeaterReading = z.object({
|
|
527
|
+
airtime_ms: z.int().nullish(),
|
|
528
|
+
battery_percent: z.number().nullish(),
|
|
529
|
+
battery_percent_source: z.string().optional(),
|
|
530
|
+
battery_voltage: z.number().nullish(),
|
|
531
|
+
direct_dups: z.int().nullish(),
|
|
532
|
+
flood_dups: z.int().nullish(),
|
|
533
|
+
full_evts: z.int().nullish(),
|
|
534
|
+
humidity: z.number().nullish(),
|
|
535
|
+
id: z.string().regex(/^[0-9a-fA-F]{8,64}$/),
|
|
536
|
+
last_attempt: z.int().nullish(),
|
|
537
|
+
last_rssi_dbm: z.int().nullish(),
|
|
538
|
+
last_snr_db: z.number().nullish(),
|
|
539
|
+
last_success: z.int().nullish(),
|
|
540
|
+
name: z.string().optional(),
|
|
541
|
+
nb_recv: z.int().nullish(),
|
|
542
|
+
nb_sent: z.int().nullish(),
|
|
543
|
+
noise_floor_dbm: z.int().nullish(),
|
|
544
|
+
online: z.boolean().nullish(),
|
|
545
|
+
pressure: z.number().nullish(),
|
|
546
|
+
recv_direct: z.int().nullish(),
|
|
547
|
+
recv_errors: z.int().nullish(),
|
|
548
|
+
recv_flood: z.int().nullish(),
|
|
549
|
+
rx_airtime_ms: z.int().nullish(),
|
|
550
|
+
sent_direct: z.int().nullish(),
|
|
551
|
+
sent_flood: z.int().nullish(),
|
|
552
|
+
temperature_c: z.number().nullish(),
|
|
553
|
+
tx_queue_len: z.int().nullish(),
|
|
554
|
+
uptime_s: z.int().nullish()
|
|
555
|
+
});
|
|
556
|
+
/**
|
|
557
|
+
* `mesh.repeater` (schema_version 1): an operator monitor's COMPLETE
|
|
558
|
+
* current set of MeshCore repeaters it logged into. A report replaces the
|
|
559
|
+
* reporter's previous set; a node left out is no longer monitored. Request
|
|
560
|
+
* bodies are snake_case. Unknown fields are ignored. Unread values are
|
|
561
|
+
* `null`, never `0`.
|
|
562
|
+
*
|
|
563
|
+
*/
|
|
564
|
+
export const zMeshRepeaterReport = z.object({
|
|
565
|
+
generated_at: z.iso.datetime().optional(),
|
|
566
|
+
repeaters: z.array(zMeshRepeaterReading).max(1000),
|
|
567
|
+
schema_version: z.literal(1)
|
|
568
|
+
});
|
|
569
|
+
export const zProtobufAny = z.object({
|
|
570
|
+
'@type': z.string().optional()
|
|
571
|
+
});
|
|
572
|
+
/**
|
|
573
|
+
* The error body of every JSON route: the RPCs (gRPC-Gateway rendering of
|
|
574
|
+
* google.rpc.Status) and the hand-built GeoJSON, mesh-links and ingest
|
|
575
|
+
* routes alike. Served with the HTTP status mapped from `code`
|
|
576
|
+
* (3 INVALID_ARGUMENT -> 400, 5 NOT_FOUND -> 404, 13 INTERNAL -> 500,
|
|
577
|
+
* 14 UNAVAILABLE -> 503, ...). All four members are always present.
|
|
578
|
+
*
|
|
579
|
+
*/
|
|
580
|
+
export const zRpcStatus = z.object({
|
|
581
|
+
code: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).optional(),
|
|
582
|
+
codeName: z.enum([
|
|
583
|
+
'OK',
|
|
584
|
+
'CANCELLED',
|
|
585
|
+
'UNKNOWN',
|
|
586
|
+
'INVALID_ARGUMENT',
|
|
587
|
+
'DEADLINE_EXCEEDED',
|
|
588
|
+
'NOT_FOUND',
|
|
589
|
+
'ALREADY_EXISTS',
|
|
590
|
+
'PERMISSION_DENIED',
|
|
591
|
+
'RESOURCE_EXHAUSTED',
|
|
592
|
+
'FAILED_PRECONDITION',
|
|
593
|
+
'ABORTED',
|
|
594
|
+
'OUT_OF_RANGE',
|
|
595
|
+
'UNIMPLEMENTED',
|
|
596
|
+
'INTERNAL',
|
|
597
|
+
'UNAVAILABLE',
|
|
598
|
+
'DATA_LOSS',
|
|
599
|
+
'UNAUTHENTICATED'
|
|
600
|
+
]).optional(),
|
|
601
|
+
details: z.array(zProtobufAny).optional(),
|
|
602
|
+
message: z.string().optional()
|
|
603
|
+
});
|
|
604
|
+
/**
|
|
605
|
+
* BoundingBox is a WGS 84 bounding box in decimal degrees.
|
|
606
|
+
*/
|
|
607
|
+
export const zV1BoundingBox = z.object({
|
|
608
|
+
maxLat: z.number(),
|
|
609
|
+
maxLng: z.number(),
|
|
610
|
+
minLat: z.number(),
|
|
611
|
+
minLng: z.number()
|
|
612
|
+
});
|
|
613
|
+
/**
|
|
614
|
+
* BurnDay is the county air district's call for today.
|
|
615
|
+
*
|
|
616
|
+
* - BURN_DAY_UNKNOWN: Not read, unreadable, or older than 36 hours. Never treat as permissive.
|
|
617
|
+
* - BURN_DAY_YES: Permissive burn day: burning allowed (subject to CAL FIRE's status).
|
|
618
|
+
* - BURN_DAY_NO: No-burn day: burning prohibited.
|
|
619
|
+
* - BURN_DAY_MARGINAL: Restricted or partial day (for example elevation limits). Treated as a
|
|
620
|
+
* restriction, not a yes.
|
|
621
|
+
*/
|
|
622
|
+
export const zV1BurnDay = z.enum([
|
|
623
|
+
'BURN_DAY_UNKNOWN',
|
|
624
|
+
'BURN_DAY_YES',
|
|
625
|
+
'BURN_DAY_NO',
|
|
626
|
+
'BURN_DAY_MARGINAL'
|
|
627
|
+
]).default('BURN_DAY_UNKNOWN');
|
|
628
|
+
/**
|
|
629
|
+
* BurnObservation is the latest reading of one burn line. The line's message
|
|
630
|
+
* names the date, so it changes every day even when the answer does not; that
|
|
631
|
+
* is why it writes no revision.
|
|
632
|
+
*
|
|
633
|
+
*/
|
|
634
|
+
export const zV1BurnObservation = z.object({
|
|
635
|
+
confidence: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
636
|
+
message: z.string(),
|
|
637
|
+
observedAt: z.iso.datetime(),
|
|
638
|
+
transcript: z.string()
|
|
639
|
+
});
|
|
640
|
+
/**
|
|
641
|
+
* BurnLineReading is one recorded phone line's answer for today.
|
|
642
|
+
*/
|
|
643
|
+
export const zV1BurnLineReading = z.object({
|
|
644
|
+
burnDay: zV1BurnDay,
|
|
645
|
+
id: z.string(),
|
|
646
|
+
name: z.string(),
|
|
647
|
+
observation: zV1BurnObservation.nullable(),
|
|
648
|
+
phone: z.string()
|
|
649
|
+
});
|
|
650
|
+
/**
|
|
651
|
+
* BurnPermission is the combined answer, deliberately pessimistic.
|
|
652
|
+
*
|
|
653
|
+
* - BURN_PERMISSION_UNKNOWN: At least one facet is unknown or stale and none prohibits: assume nothing.
|
|
654
|
+
* - BURN_PERMISSION_ALLOWED: Both facets are known and permit burning today.
|
|
655
|
+
* - BURN_PERMISSION_PROHIBITED: At least one facet prohibits burning today.
|
|
656
|
+
*/
|
|
657
|
+
export const zV1BurnPermission = z.enum([
|
|
658
|
+
'BURN_PERMISSION_UNKNOWN',
|
|
659
|
+
'BURN_PERMISSION_ALLOWED',
|
|
660
|
+
'BURN_PERMISSION_PROHIBITED'
|
|
661
|
+
]).default('BURN_PERMISSION_UNKNOWN');
|
|
662
|
+
/**
|
|
663
|
+
* CalfireBurnStatus is CAL FIRE's permit status for State Responsibility Area
|
|
664
|
+
* land in the county.
|
|
665
|
+
*
|
|
666
|
+
* - CALFIRE_BURN_STATUS_UNKNOWN: Unknown: CAL FIRE's page has not been read.
|
|
667
|
+
* - CALFIRE_BURNING_SUSPENDED: Permits suspended: no residential burning.
|
|
668
|
+
* - CALFIRE_PERMIT_REQUIRED: Burning allowed with a valid CAL FIRE permit.
|
|
669
|
+
* - CALFIRE_NO_PERMIT_REQUIRED: Off-season: no permit needed.
|
|
670
|
+
*/
|
|
671
|
+
export const zV1CalfireBurnStatus = z.enum([
|
|
672
|
+
'CALFIRE_BURN_STATUS_UNKNOWN',
|
|
673
|
+
'CALFIRE_BURNING_SUSPENDED',
|
|
674
|
+
'CALFIRE_PERMIT_REQUIRED',
|
|
675
|
+
'CALFIRE_NO_PERMIT_REQUIRED'
|
|
676
|
+
]).default('CALFIRE_BURN_STATUS_UNKNOWN');
|
|
677
|
+
/**
|
|
678
|
+
* BurnStatusDetail is the BURN_STATUS detail block: whether residential/outdoor
|
|
679
|
+
* burning is allowed today in one county.
|
|
680
|
+
*
|
|
681
|
+
* Two independent authorities must BOTH permit a burn, and each is a separate
|
|
682
|
+
* facet because they fail independently: `burnDay`, the county air district's
|
|
683
|
+
* daily permissive-burn-day call (read from its recorded phone line), and
|
|
684
|
+
* `calfireStatus`, CAL FIRE's seasonal suspension of burn permits on State
|
|
685
|
+
* Responsibility Area land (changes about twice a year). `permission` combines
|
|
686
|
+
* them pessimistically.
|
|
687
|
+
*
|
|
688
|
+
* The event exists for each tracked county at all times, is always INFO and
|
|
689
|
+
* ACTIVE, and is left out of the summary's hazard rollup (it has its own `burn`
|
|
690
|
+
* domain). `GET /api/v1/events/burn:{county slug}/history` shows when it changed.
|
|
691
|
+
*/
|
|
692
|
+
export const zV1BurnStatusDetail = z.object({
|
|
693
|
+
burnDay: zV1BurnDay,
|
|
694
|
+
burnLines: z.array(zV1BurnLineReading),
|
|
695
|
+
calfireArea: z.string(),
|
|
696
|
+
calfireEffective: z.iso.datetime().nullable(),
|
|
697
|
+
calfireObservedAt: z.iso.datetime().nullable(),
|
|
698
|
+
calfireStatus: zV1CalfireBurnStatus,
|
|
699
|
+
permission: zV1BurnPermission
|
|
700
|
+
});
|
|
701
|
+
/**
|
|
702
|
+
* EarthquakeDetail is the EARTHQUAKE detail block. The USGS event page is the
|
|
703
|
+
* envelope `canonicalUrl`.
|
|
704
|
+
*/
|
|
705
|
+
export const zV1EarthquakeDetail = z.object({
|
|
706
|
+
depthKm: z.number(),
|
|
707
|
+
felt: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
708
|
+
magnitude: z.number()
|
|
709
|
+
});
|
|
710
|
+
/**
|
|
711
|
+
* Enhancement marks AI-generated text so a client can badge it. The model
|
|
712
|
+
* translates and summarizes the upstream text; it never asserts new facts, and
|
|
713
|
+
* the original stays in `description`.
|
|
714
|
+
*/
|
|
715
|
+
export const zV1Enhancement = z.object({
|
|
716
|
+
enhancedAt: z.iso.datetime().nullable(),
|
|
717
|
+
fields: z.array(z.string()),
|
|
718
|
+
model: z.string(),
|
|
719
|
+
request: z.string(),
|
|
720
|
+
response: z.string()
|
|
721
|
+
});
|
|
722
|
+
/**
|
|
723
|
+
* EvacuationDetail is the EVACUATION detail block, one Cal OES / Genasys zone.
|
|
724
|
+
*/
|
|
725
|
+
export const zV1EvacuationDetail = z.object({
|
|
726
|
+
county: z.string(),
|
|
727
|
+
eventType: z.string(),
|
|
728
|
+
level: z.enum([
|
|
729
|
+
'ORDER',
|
|
730
|
+
'WARNING',
|
|
731
|
+
'ADVISORY',
|
|
732
|
+
'SHELTER_IN_PLACE'
|
|
733
|
+
]),
|
|
734
|
+
zoneId: z.string()
|
|
735
|
+
});
|
|
736
|
+
/**
|
|
737
|
+
* EventStatus is an event's lifecycle state. Every transition is a revision, so
|
|
738
|
+
* the history keeps when an event started and ended.
|
|
739
|
+
*
|
|
740
|
+
* - EVENT_STATUS_UNSPECIFIED: Never returned.
|
|
741
|
+
* - SCHEDULED: Planned or forecast and not yet in effect, e.g. a Caltrans lane-closure
|
|
742
|
+
* window the crew has not set up yet.
|
|
743
|
+
* - ACTIVE: In effect now.
|
|
744
|
+
* - RESOLVED: Over: an authoritatively active-only feed (CAL FIRE, Cal OES, CHP, Caltrans,
|
|
745
|
+
* PG&E) stopped listing it after a successful poll, or a closure passed its
|
|
746
|
+
* planned end plus an overrun grace without a pickup call.
|
|
747
|
+
* - EXPIRED: Aged out: past its own `expires`, or unseen for longer than the source's
|
|
748
|
+
* grace (`Source.expireAfterSeconds`). Used where a feed going quiet proves
|
|
749
|
+
* nothing (NWS alerts, FIRIS perimeters, mesh nodes).
|
|
750
|
+
*/
|
|
751
|
+
export const zV1EventStatus = z.enum([
|
|
752
|
+
'EVENT_STATUS_UNSPECIFIED',
|
|
753
|
+
'SCHEDULED',
|
|
754
|
+
'ACTIVE',
|
|
755
|
+
'RESOLVED',
|
|
756
|
+
'EXPIRED'
|
|
757
|
+
]).default('EVENT_STATUS_UNSPECIFIED');
|
|
758
|
+
/**
|
|
759
|
+
* FireWeatherConditions is the region's fire-weather state, from issued NWS
|
|
760
|
+
* products only. It never claims a Red Flag Warning that NWS has not issued.
|
|
761
|
+
*/
|
|
762
|
+
export const zV1FireWeatherConditions = z.object({
|
|
763
|
+
headline: z.string(),
|
|
764
|
+
state: z.enum([
|
|
765
|
+
'normal',
|
|
766
|
+
'elevated',
|
|
767
|
+
'red-flag',
|
|
768
|
+
''
|
|
769
|
+
]),
|
|
770
|
+
zones: z.array(z.string())
|
|
771
|
+
});
|
|
772
|
+
/**
|
|
773
|
+
* FireWeatherDetail is never populated on an event. Fire weather is a condition,
|
|
774
|
+
* served by `GET /api/v1/conditions` (`fireWeather`) and the `fire_weather` map
|
|
775
|
+
* layer.
|
|
776
|
+
*
|
|
777
|
+
*/
|
|
778
|
+
export const zV1FireWeatherDetail = z.object({
|
|
779
|
+
sourceEvent: z.string(),
|
|
780
|
+
state: z.enum([
|
|
781
|
+
'normal',
|
|
782
|
+
'elevated',
|
|
783
|
+
'red-flag'
|
|
784
|
+
]),
|
|
785
|
+
zones: z.array(z.string())
|
|
786
|
+
});
|
|
787
|
+
/**
|
|
788
|
+
* ForecastPeriod is one hour of a location's forecast (NWS gridpoint data),
|
|
789
|
+
* rounded to whole numbers. A value NWS did not give is 0.
|
|
790
|
+
*/
|
|
791
|
+
export const zV1ForecastPeriod = z.object({
|
|
792
|
+
humidityPercent: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
793
|
+
temperatureCelsius: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
794
|
+
time: z.iso.datetime().nullable(),
|
|
795
|
+
windDirectionDegrees: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
796
|
+
windGustKmh: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
797
|
+
windSpeedKmh: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })
|
|
798
|
+
});
|
|
799
|
+
/**
|
|
800
|
+
* LatLng is one WGS 84 point in decimal degrees. Note the order: unlike GeoJSON
|
|
801
|
+
* coordinates, this is latitude first.
|
|
802
|
+
*/
|
|
803
|
+
export const zV1LatLng = z.object({
|
|
804
|
+
lat: z.number(),
|
|
805
|
+
lng: z.number()
|
|
806
|
+
});
|
|
807
|
+
/**
|
|
808
|
+
* Camera is one Caltrans CCTV camera. Every listed camera is in service and has
|
|
809
|
+
* an image; an out-of-service camera is dropped, not flagged.
|
|
810
|
+
*/
|
|
811
|
+
export const zV1Camera = z.object({
|
|
812
|
+
county: z.string(),
|
|
813
|
+
description: z.string(),
|
|
814
|
+
direction: z.enum([
|
|
815
|
+
'',
|
|
816
|
+
'North',
|
|
817
|
+
'South',
|
|
818
|
+
'East',
|
|
819
|
+
'West'
|
|
820
|
+
]),
|
|
821
|
+
distanceMeters: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
822
|
+
elevationFeet: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
823
|
+
id: z.string(),
|
|
824
|
+
imageRefreshMinutes: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
825
|
+
imageUrl: z.string(),
|
|
826
|
+
location: zV1LatLng,
|
|
827
|
+
name: z.string(),
|
|
828
|
+
nearbyPlace: z.string(),
|
|
829
|
+
route: z.string(),
|
|
830
|
+
streamUrl: z.string()
|
|
831
|
+
});
|
|
832
|
+
/**
|
|
833
|
+
* CameraList is the camera directory.
|
|
834
|
+
*/
|
|
835
|
+
export const zV1CameraList = z.object({
|
|
836
|
+
attribution: z.string(),
|
|
837
|
+
cameras: z.array(zV1Camera),
|
|
838
|
+
lastSourceUpdate: z.iso.datetime().nullable(),
|
|
839
|
+
sourceStatus: z.enum([
|
|
840
|
+
'OK',
|
|
841
|
+
'STALE',
|
|
842
|
+
'UNAVAILABLE'
|
|
843
|
+
])
|
|
844
|
+
});
|
|
845
|
+
/**
|
|
846
|
+
* Geometry is an event's or place's footprint.
|
|
847
|
+
*
|
|
848
|
+
* The GeoJSON comes in one of two forms, chosen per request with
|
|
849
|
+
* `geometryFormat`: `BASE64` (the default and legacy form) fills `geojson`;
|
|
850
|
+
* `OBJECT` fills `object` and leaves `geojson` empty. `bbox` and `centroid`
|
|
851
|
+
* are the same in both.
|
|
852
|
+
*/
|
|
853
|
+
export const zV1Geometry = z.object({
|
|
854
|
+
bbox: zV1BoundingBox,
|
|
855
|
+
centroid: zV1LatLng,
|
|
856
|
+
geojson: z.string(),
|
|
857
|
+
object: zGeoJsonGeometry.optional()
|
|
858
|
+
});
|
|
859
|
+
/**
|
|
860
|
+
* LaneClosureDetail is one Caltrans planned lane-closure WINDOW from the CWWP2
|
|
861
|
+
* data portal. Every field is Caltrans data; none of it is AI-generated.
|
|
862
|
+
*
|
|
863
|
+
* A multi-day job is one window (one event) per day, and neither `closureId`
|
|
864
|
+
* nor `logNumber` identifies a job; `windowId` is the only unique key. A window
|
|
865
|
+
* is SCHEDULED until the crew radios it set up (`setUpAt`), then ACTIVE until
|
|
866
|
+
* they radio it picked up, or until `plannedEnd` plus a 12-hour overrun grace
|
|
867
|
+
* passes with no pickup call, when it is presumed over and RESOLVED. The
|
|
868
|
+
* planned end is an estimate crews overrun, so it is never mapped onto the
|
|
869
|
+
* envelope `expires`.
|
|
870
|
+
*/
|
|
871
|
+
export const zV1LaneClosureDetail = z.object({
|
|
872
|
+
begin: zV1LatLng.nullable(),
|
|
873
|
+
beginLocation: z.string(),
|
|
874
|
+
closureDuration: z.enum([
|
|
875
|
+
'Standard',
|
|
876
|
+
'Long Term',
|
|
877
|
+
'Intermittent'
|
|
878
|
+
]),
|
|
879
|
+
closureId: z.string(),
|
|
880
|
+
closureType: z.string(),
|
|
881
|
+
direction: z.string(),
|
|
882
|
+
district: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
883
|
+
end: zV1LatLng.nullable(),
|
|
884
|
+
endIndefinite: z.boolean(),
|
|
885
|
+
endLocation: z.string(),
|
|
886
|
+
estimatedDelayMinutes: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
887
|
+
facility: z.string(),
|
|
888
|
+
lanesClosed: z.string(),
|
|
889
|
+
logNumber: z.string(),
|
|
890
|
+
plannedEnd: z.iso.datetime().nullable(),
|
|
891
|
+
plannedStart: z.iso.datetime(),
|
|
892
|
+
route: z.string(),
|
|
893
|
+
setUpAt: z.iso.datetime().nullable(),
|
|
894
|
+
totalLanes: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
895
|
+
windowId: z.string(),
|
|
896
|
+
workType: z.string()
|
|
897
|
+
});
|
|
898
|
+
/**
|
|
899
|
+
* Layer is the event taxonomy. Response values are these UPPERCASE names; the
|
|
900
|
+
* `layer` query parameter also accepts lowercase slugs (`road_incident`).
|
|
901
|
+
*
|
|
902
|
+
* Only event layers appear here. The condition layers (`road_segment`,
|
|
903
|
+
* `chain_control`, `fire_weather`, `message_sign`) are map layers and summary
|
|
904
|
+
* inputs, never events.
|
|
905
|
+
*
|
|
906
|
+
* - LAYER_UNSPECIFIED: Never returned.
|
|
907
|
+
* - WILDFIRE: Wildfires: CAL FIRE incidents joined with FIRIS/NIFC perimeters (sources
|
|
908
|
+
* `calfire`, `firis`). Scoped wider than other layers, so a fire approaching
|
|
909
|
+
* the region shows up before it arrives.
|
|
910
|
+
* - EVACUATION: Evacuation zones under an order, warning, advisory or shelter-in-place,
|
|
911
|
+
* from Cal OES / Genasys (source `caloes`). Life-safety: see the summary's
|
|
912
|
+
* `activeEvacuations`.
|
|
913
|
+
* - WEATHER_ALERT: National Weather Service watches, warnings and advisories for the region's
|
|
914
|
+
* forecast zones (source `nws`). No geometry; attached to places by zone.
|
|
915
|
+
* - FIRE_WEATHER: Reserved. Fire weather is a condition (`GET /api/v1/conditions`), not an
|
|
916
|
+
* event layer; no event carries it.
|
|
917
|
+
* - EARTHQUAKE: USGS earthquakes of magnitude 2.5 or more in the last 7 days (source `usgs`).
|
|
918
|
+
* - ROAD_INCIDENT: CHP traffic incidents (source `chp`, AI-summarized) and Caltrans planned
|
|
919
|
+
* lane-closure windows (source `caltrans`). Planned windows not yet set up are
|
|
920
|
+
* SCHEDULED.
|
|
921
|
+
* - POWER:
|
|
922
|
+
* PG&E electric outages (source `pge`) and Public Safety Power Shutoffs
|
|
923
|
+
* (source `psps`). Most outages affect one customer and are INFO.
|
|
924
|
+
* - GAUGE: Reserved for stream gauges; no events today.
|
|
925
|
+
* - AIR_QUALITY: Reserved for air quality; no events today.
|
|
926
|
+
* - MESH: MeshCore community radio nodes (source `meshcore`), one event per node.
|
|
927
|
+
* Ambient INFO state, not a hazard. It dominates an unscoped event query.
|
|
928
|
+
* - ANNOUNCEMENT: Reserved for announcements; no events today.
|
|
929
|
+
* - BURN_STATUS: One event per tracked county saying whether residential burning is allowed
|
|
930
|
+
* today (sources `burnline`, `calfire-burn`). Ambient, permanently ACTIVE,
|
|
931
|
+
* always INFO; its revision history is the record of changes.
|
|
932
|
+
*/
|
|
933
|
+
export const zV1Layer = z.enum([
|
|
934
|
+
'LAYER_UNSPECIFIED',
|
|
935
|
+
'WILDFIRE',
|
|
936
|
+
'EVACUATION',
|
|
937
|
+
'WEATHER_ALERT',
|
|
938
|
+
'FIRE_WEATHER',
|
|
939
|
+
'EARTHQUAKE',
|
|
940
|
+
'ROAD_INCIDENT',
|
|
941
|
+
'POWER',
|
|
942
|
+
'GAUGE',
|
|
943
|
+
'AIR_QUALITY',
|
|
944
|
+
'MESH',
|
|
945
|
+
'ANNOUNCEMENT',
|
|
946
|
+
'BURN_STATUS'
|
|
947
|
+
]).default('LAYER_UNSPECIFIED');
|
|
948
|
+
/**
|
|
949
|
+
* MeshAdminTelemetry is one reading taken from a node's own admin interface by an
|
|
950
|
+
* operator-run monitor. It is the node's self-reported view, which is why it
|
|
951
|
+
* sits beside rather than replaces the gateway-reported `snr`/`rssi`: those are
|
|
952
|
+
* what a distant listener heard, these are what the node measured.
|
|
953
|
+
*
|
|
954
|
+
* Gauges are nullable: `null` means the monitor could not read it, which is not
|
|
955
|
+
* the same as 0 (a 0% battery and an unknown battery must not render alike).
|
|
956
|
+
* Counters are plain, count since the node's last boot (they reset at a
|
|
957
|
+
* reboot), and are 64-bit, so they arrive as JSON STRINGS.
|
|
958
|
+
*/
|
|
959
|
+
export const zV1MeshAdminTelemetry = z.object({
|
|
960
|
+
airtimeMs: z.string().regex(/^-?[0-9]+$/),
|
|
961
|
+
batteryPercent: z.number().nullable(),
|
|
962
|
+
batteryPercentSource: z.enum([
|
|
963
|
+
'',
|
|
964
|
+
'measured',
|
|
965
|
+
'estimated'
|
|
966
|
+
]),
|
|
967
|
+
batteryVolts: z.number().nullable(),
|
|
968
|
+
directDups: z.string().regex(/^-?[0-9]+$/),
|
|
969
|
+
floodDups: z.string().regex(/^-?[0-9]+$/),
|
|
970
|
+
fullEvents: z.string().regex(/^-?[0-9]+$/),
|
|
971
|
+
humidity: z.number().nullable(),
|
|
972
|
+
lastAttemptAt: z.iso.datetime().nullable(),
|
|
973
|
+
lastRssiDbm: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).nullable(),
|
|
974
|
+
lastSnrDb: z.number().nullable(),
|
|
975
|
+
lastSuccessAt: z.iso.datetime().nullable(),
|
|
976
|
+
noiseFloorDbm: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).nullable(),
|
|
977
|
+
packetsReceived: z.string().regex(/^-?[0-9]+$/),
|
|
978
|
+
packetsSent: z.string().regex(/^-?[0-9]+$/),
|
|
979
|
+
pressure: z.number().nullable(),
|
|
980
|
+
recvDirect: z.string().regex(/^-?[0-9]+$/),
|
|
981
|
+
recvErrors: z.string().regex(/^-?[0-9]+$/),
|
|
982
|
+
recvFlood: z.string().regex(/^-?[0-9]+$/),
|
|
983
|
+
reportedAt: z.iso.datetime().nullable(),
|
|
984
|
+
reporterId: z.string(),
|
|
985
|
+
rxAirtimeMs: z.string().regex(/^-?[0-9]+$/),
|
|
986
|
+
sentDirect: z.string().regex(/^-?[0-9]+$/),
|
|
987
|
+
sentFlood: z.string().regex(/^-?[0-9]+$/),
|
|
988
|
+
temperatureC: z.number().nullable(),
|
|
989
|
+
txQueueLen: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).nullable(),
|
|
990
|
+
uptimeSeconds: z.string().regex(/^-?[0-9]+$/)
|
|
991
|
+
});
|
|
992
|
+
/**
|
|
993
|
+
* MeshReachability is an operator monitor's verdict on a node's admin interface,
|
|
994
|
+
* smoothed so a marginal link does not flap.
|
|
995
|
+
*
|
|
996
|
+
* - MESH_REACHABILITY_UNSPECIFIED: No monitor watches this node (most nodes). Says nothing about liveness.
|
|
997
|
+
* - REACHABLE: A monitor reached it recently.
|
|
998
|
+
* - UNREACHABLE: A monitor has been failing to reach it for longer than its window.
|
|
999
|
+
*/
|
|
1000
|
+
export const zV1MeshReachability = z.enum([
|
|
1001
|
+
'MESH_REACHABILITY_UNSPECIFIED',
|
|
1002
|
+
'REACHABLE',
|
|
1003
|
+
'UNREACHABLE'
|
|
1004
|
+
]).default('MESH_REACHABILITY_UNSPECIFIED');
|
|
1005
|
+
/**
|
|
1006
|
+
* MeshTelemetry is a mesh node's volatile signal state and activity clocks. None
|
|
1007
|
+
* of it writes a revision, so history snapshots do not reflect it.
|
|
1008
|
+
*
|
|
1009
|
+
* For "is this node up right now", use `lastRelayedAt` (repeaters relay
|
|
1010
|
+
* constantly but advertise only every day or two), then `lastHeardAt`; never
|
|
1011
|
+
* the event's `observedAt`.
|
|
1012
|
+
*
|
|
1013
|
+
*/
|
|
1014
|
+
export const zV1MeshTelemetry = z.object({
|
|
1015
|
+
admin: zV1MeshAdminTelemetry.nullable(),
|
|
1016
|
+
gateways: z.array(z.string()),
|
|
1017
|
+
hopCount: z.int().nullable(),
|
|
1018
|
+
lastAdvertAt: z.iso.datetime().nullable(),
|
|
1019
|
+
lastHeardAt: z.iso.datetime().nullable(),
|
|
1020
|
+
lastRelayedAt: z.iso.datetime().nullable(),
|
|
1021
|
+
rssi: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).nullable(),
|
|
1022
|
+
snr: z.number().nullable()
|
|
1023
|
+
});
|
|
1024
|
+
/**
|
|
1025
|
+
* MeshDetail is the MESH detail block, for one MeshCore radio node, keyed by its
|
|
1026
|
+
* Ed25519 public key.
|
|
1027
|
+
*
|
|
1028
|
+
* Identity, location and reachability changes write a revision. The volatile
|
|
1029
|
+
* signal readings in `telemetry` change constantly without one.
|
|
1030
|
+
*
|
|
1031
|
+
*/
|
|
1032
|
+
export const zV1MeshDetail = z.object({
|
|
1033
|
+
name: z.string(),
|
|
1034
|
+
nodeType: z.enum([
|
|
1035
|
+
'companion',
|
|
1036
|
+
'repeater',
|
|
1037
|
+
'room_server',
|
|
1038
|
+
'sensor'
|
|
1039
|
+
]),
|
|
1040
|
+
publicKey: z.string().regex(/^[0-9a-f]{64}$/),
|
|
1041
|
+
reachability: zV1MeshReachability,
|
|
1042
|
+
telemetry: zV1MeshTelemetry.nullable()
|
|
1043
|
+
});
|
|
1044
|
+
/**
|
|
1045
|
+
* MeshTelemetryCoverage is the span of the whole archive for one node.
|
|
1046
|
+
*/
|
|
1047
|
+
export const zV1MeshTelemetryCoverage = z.object({
|
|
1048
|
+
from: z.iso.datetime().nullable(),
|
|
1049
|
+
samples: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1050
|
+
to: z.iso.datetime().nullable()
|
|
1051
|
+
});
|
|
1052
|
+
/**
|
|
1053
|
+
* MeshTelemetrySample is one archived report.
|
|
1054
|
+
*
|
|
1055
|
+
*/
|
|
1056
|
+
export const zV1MeshTelemetrySample = z.object({
|
|
1057
|
+
reading: zV1MeshAdminTelemetry,
|
|
1058
|
+
receivedAt: z.iso.datetime()
|
|
1059
|
+
});
|
|
1060
|
+
/**
|
|
1061
|
+
* MeshTelemetryArchive is one node's samples over a window, with what a chart
|
|
1062
|
+
* needs in order not to lie about them.
|
|
1063
|
+
*/
|
|
1064
|
+
export const zV1MeshTelemetryArchive = z.object({
|
|
1065
|
+
cadenceSeconds: z.string().regex(/^-?[0-9]+$/).nullable(),
|
|
1066
|
+
coverage: zV1MeshTelemetryCoverage,
|
|
1067
|
+
from: z.iso.datetime(),
|
|
1068
|
+
node: z.string(),
|
|
1069
|
+
reboots: z.array(z.iso.datetime()),
|
|
1070
|
+
samples: z.array(zV1MeshTelemetrySample),
|
|
1071
|
+
to: z.iso.datetime(),
|
|
1072
|
+
truncated: z.boolean()
|
|
1073
|
+
});
|
|
1074
|
+
/**
|
|
1075
|
+
* PlaceKind is the type of a place.
|
|
1076
|
+
*
|
|
1077
|
+
* - PLACE_KIND_UNSPECIFIED: Never returned.
|
|
1078
|
+
* - AREA: A configured coverage area such as `ebbetts-pass` (the Highway 4 corridor
|
|
1079
|
+
* region). Area places own the scanner feeds and the fire-weather zones.
|
|
1080
|
+
* - COUNTY: A county, from Census polygons.
|
|
1081
|
+
* - TOWN: A town, stored as a Point. `places:resolve` matches a town within 3 km of
|
|
1082
|
+
* its point. Events attach to a town only by overlapping polygons (and
|
|
1083
|
+
* wildfires by proximity), never by that radius.
|
|
1084
|
+
* - EVAC_ZONE: Reserved for evacuation zones as places; none exist today.
|
|
1085
|
+
* - CORRIDOR: A highway segment, stored as a LineString. Point events within about 1.5 km
|
|
1086
|
+
* of the line attach to it.
|
|
1087
|
+
* - SITE: Reserved for individual sites; none exist today.
|
|
1088
|
+
*/
|
|
1089
|
+
export const zV1PlaceKind = z.enum([
|
|
1090
|
+
'PLACE_KIND_UNSPECIFIED',
|
|
1091
|
+
'AREA',
|
|
1092
|
+
'COUNTY',
|
|
1093
|
+
'TOWN',
|
|
1094
|
+
'EVAC_ZONE',
|
|
1095
|
+
'CORRIDOR',
|
|
1096
|
+
'SITE'
|
|
1097
|
+
]).default('PLACE_KIND_UNSPECIFIED');
|
|
1098
|
+
/**
|
|
1099
|
+
* Place is a named geography that events attach to.
|
|
1100
|
+
*/
|
|
1101
|
+
export const zV1Place = z.object({
|
|
1102
|
+
geometry: zV1Geometry,
|
|
1103
|
+
id: z.string(),
|
|
1104
|
+
kind: zV1PlaceKind,
|
|
1105
|
+
name: z.string(),
|
|
1106
|
+
parentId: z.string(),
|
|
1107
|
+
slug: z.string()
|
|
1108
|
+
});
|
|
1109
|
+
/**
|
|
1110
|
+
* PlaceList is the place directory.
|
|
1111
|
+
*/
|
|
1112
|
+
export const zV1PlaceList = z.object({
|
|
1113
|
+
places: z.array(zV1Place)
|
|
1114
|
+
});
|
|
1115
|
+
/**
|
|
1116
|
+
* PowerDetail is the POWER detail block, for a PG&E outage or a Public Safety
|
|
1117
|
+
* Power Shutoff (PSPS). The envelope `category` says which: `unplanned` and
|
|
1118
|
+
* `planned` outages fill the outage fields; `psps` fills the PSPS fields. The
|
|
1119
|
+
* other group is zero, empty or `null`.
|
|
1120
|
+
*
|
|
1121
|
+
* Every PG&E time here is an estimate PG&E often overruns, so none of them is
|
|
1122
|
+
* mapped onto the envelope `expires` or drives the lifecycle.
|
|
1123
|
+
*/
|
|
1124
|
+
export const zV1PowerDetail = z.object({
|
|
1125
|
+
allClear: z.iso.datetime().nullable(),
|
|
1126
|
+
cause: z.string(),
|
|
1127
|
+
crewStatus: z.string(),
|
|
1128
|
+
customersAffected: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1129
|
+
deEnergizationEnd: z.iso.datetime().nullable(),
|
|
1130
|
+
deEnergizationStart: z.iso.datetime().nullable(),
|
|
1131
|
+
estimatedRestoration: z.iso.datetime().nullable(),
|
|
1132
|
+
eventId: z.string(),
|
|
1133
|
+
eventName: z.string(),
|
|
1134
|
+
medicalBaselineAffected: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1135
|
+
outageId: z.string(),
|
|
1136
|
+
stage: z.enum([
|
|
1137
|
+
'',
|
|
1138
|
+
'Watch',
|
|
1139
|
+
'Warning'
|
|
1140
|
+
]),
|
|
1141
|
+
timePeriod: z.string()
|
|
1142
|
+
});
|
|
1143
|
+
/**
|
|
1144
|
+
* Provenance says which upstream published an event. Show `attribution` next to
|
|
1145
|
+
* the data.
|
|
1146
|
+
*/
|
|
1147
|
+
export const zV1Provenance = z.object({
|
|
1148
|
+
attribution: z.string(),
|
|
1149
|
+
fetchedAt: z.iso.datetime(),
|
|
1150
|
+
sourceId: z.enum([
|
|
1151
|
+
'calfire',
|
|
1152
|
+
'firis',
|
|
1153
|
+
'caloes',
|
|
1154
|
+
'nws',
|
|
1155
|
+
'usgs',
|
|
1156
|
+
'chp',
|
|
1157
|
+
'caltrans',
|
|
1158
|
+
'pge',
|
|
1159
|
+
'psps',
|
|
1160
|
+
'meshcore',
|
|
1161
|
+
'burnline',
|
|
1162
|
+
'calfire-burn'
|
|
1163
|
+
]),
|
|
1164
|
+
sourceName: z.string(),
|
|
1165
|
+
sourceUrl: z.string()
|
|
1166
|
+
});
|
|
1167
|
+
/**
|
|
1168
|
+
* ResolveQuery echoes the point that was resolved.
|
|
1169
|
+
*/
|
|
1170
|
+
export const zV1ResolveQuery = z.object({
|
|
1171
|
+
lat: z.number(),
|
|
1172
|
+
lng: z.number(),
|
|
1173
|
+
matchedAddress: z.string()
|
|
1174
|
+
});
|
|
1175
|
+
/**
|
|
1176
|
+
* ResolvePlaceResponse lists the places containing a point.
|
|
1177
|
+
*/
|
|
1178
|
+
export const zV1ResolvePlaceResponse = z.object({
|
|
1179
|
+
places: z.array(zV1Place),
|
|
1180
|
+
query: zV1ResolveQuery
|
|
1181
|
+
});
|
|
1182
|
+
/**
|
|
1183
|
+
* RoadIncidentDetail is the ROAD_INCIDENT detail block, for a CHP incident or a
|
|
1184
|
+
* Caltrans lane-closure window. The incident type is the envelope `category`,
|
|
1185
|
+
* the location is `areaLabel`, and the short line is `headline`.
|
|
1186
|
+
*/
|
|
1187
|
+
export const zV1RoadIncidentDetail = z.object({
|
|
1188
|
+
closure: zV1LaneClosureDetail.nullable(),
|
|
1189
|
+
duration: z.enum([
|
|
1190
|
+
'',
|
|
1191
|
+
'unknown',
|
|
1192
|
+
'< 1 hour',
|
|
1193
|
+
'several hours',
|
|
1194
|
+
'ongoing'
|
|
1195
|
+
]),
|
|
1196
|
+
impact: z.enum([
|
|
1197
|
+
'',
|
|
1198
|
+
'none',
|
|
1199
|
+
'light',
|
|
1200
|
+
'moderate',
|
|
1201
|
+
'severe'
|
|
1202
|
+
]),
|
|
1203
|
+
logNumber: z.string(),
|
|
1204
|
+
metadata: z.record(z.string(), z.string())
|
|
1205
|
+
});
|
|
1206
|
+
/**
|
|
1207
|
+
* Scanner is one Broadcastify audio feed.
|
|
1208
|
+
*/
|
|
1209
|
+
export const zV1Scanner = z.object({
|
|
1210
|
+
agency: z.string(),
|
|
1211
|
+
broadcastifyUrl: z.string(),
|
|
1212
|
+
channelLabel: z.string(),
|
|
1213
|
+
feedId: z.string()
|
|
1214
|
+
});
|
|
1215
|
+
/**
|
|
1216
|
+
* ScannerList is the scanner feeds.
|
|
1217
|
+
*/
|
|
1218
|
+
export const zV1ScannerList = z.object({
|
|
1219
|
+
scanners: z.array(zV1Scanner)
|
|
1220
|
+
});
|
|
1221
|
+
/**
|
|
1222
|
+
* Severity is the unified 5-level scale shared by every layer: how urgently the
|
|
1223
|
+
* public should respond, not physical magnitude. The enum number is the rank
|
|
1224
|
+
* (`severityRank`, 0-4), for sorting and colour ramps.
|
|
1225
|
+
*
|
|
1226
|
+
* How each layer is graded. WILDFIRE: the worse of a containment floor (under
|
|
1227
|
+
* 50% contained SEVERE, 50-99% MODERATE, 100% MINOR) and size (1,000+ acres
|
|
1228
|
+
* under 50% contained EXTREME, 100+ acres SEVERE). EVACUATION: ORDER EXTREME,
|
|
1229
|
+
* WARNING and SHELTER_IN_PLACE SEVERE, ADVISORY MODERATE. WEATHER_ALERT: the NWS
|
|
1230
|
+
* severity (Extreme..Minor) one-to-one, otherwise INFO. EARTHQUAKE: M5+ SEVERE,
|
|
1231
|
+
* M4+ MODERATE, M2.5+ MINOR. ROAD_INCIDENT: a CHP incident by its AI-assessed
|
|
1232
|
+
* impact (severe SEVERE, moderate MODERATE, light MINOR, none INFO); a Caltrans
|
|
1233
|
+
* closure by its structure (full closure SEVERE, a travel lane or one-way
|
|
1234
|
+
* traffic MODERATE, shoulder only MINOR). POWER: 1,000+ customers SEVERE, 100+
|
|
1235
|
+
* MODERATE, 10+ MINOR, fewer INFO, unknown count MINOR, planned outages one rank
|
|
1236
|
+
* lower; PSPS Warning SEVERE, Watch MODERATE. MESH and BURN_STATUS: always INFO.
|
|
1237
|
+
* Condition layers on the map: road segment CLOSED SEVERE, restricted or heavy
|
|
1238
|
+
* congestion MODERATE; chain control R3 SEVERE, R2 MODERATE, R1 MINOR, road
|
|
1239
|
+
* closed MINOR; fire weather red-flag SEVERE, elevated MODERATE.
|
|
1240
|
+
*
|
|
1241
|
+
* - INFO: Rank 0. Informational: ambient state, single-customer outages, small quakes,
|
|
1242
|
+
* clear roads. Also the default when a source gives no grade.
|
|
1243
|
+
* - MINOR: Rank 1. Minor impact.
|
|
1244
|
+
* - MODERATE: Rank 2. Moderate impact; worth attention.
|
|
1245
|
+
* - SEVERE: Rank 3. Severe; act or prepare now.
|
|
1246
|
+
* - EXTREME: Rank 4. Extreme; life-safety (evacuation orders, large uncontained fires).
|
|
1247
|
+
*/
|
|
1248
|
+
export const zV1Severity = z.enum([
|
|
1249
|
+
'INFO',
|
|
1250
|
+
'MINOR',
|
|
1251
|
+
'MODERATE',
|
|
1252
|
+
'SEVERE',
|
|
1253
|
+
'EXTREME'
|
|
1254
|
+
]).default('INFO');
|
|
1255
|
+
/**
|
|
1256
|
+
* SourceKind says what a source registry row describes.
|
|
1257
|
+
*
|
|
1258
|
+
* - SOURCE_KIND_UNSPECIFIED: Never returned.
|
|
1259
|
+
* - FEED: An upstream feed the Grid fetches on a schedule (CAL FIRE, NWS, PG&E, ...).
|
|
1260
|
+
* Events name it in `provenance.sourceId`.
|
|
1261
|
+
* - REPORTER: An operator-run monitor that pushes to the Grid's ingest endpoint. Health
|
|
1262
|
+
* only: no event carries its id, and `homepageUrl` is empty.
|
|
1263
|
+
*/
|
|
1264
|
+
export const zV1SourceKind = z.enum([
|
|
1265
|
+
'SOURCE_KIND_UNSPECIFIED',
|
|
1266
|
+
'FEED',
|
|
1267
|
+
'REPORTER'
|
|
1268
|
+
]).default('SOURCE_KIND_UNSPECIFIED');
|
|
1269
|
+
/**
|
|
1270
|
+
* SourceStatus is a source's health. The same three values appear as strings in
|
|
1271
|
+
* the summary's domains and sidecar, on `/api/v1/cameras`, and on the map
|
|
1272
|
+
* layers' `metadata.sourceStatus`.
|
|
1273
|
+
*
|
|
1274
|
+
* - SOURCE_STATUS_UNSPECIFIED: Not polled yet since the registry row was created. Treat as UNAVAILABLE.
|
|
1275
|
+
* - OK: The last attempt succeeded.
|
|
1276
|
+
* - STALE: The last attempt failed, but the last success is within
|
|
1277
|
+
* `staleAfterSeconds`; what is served is last-good data.
|
|
1278
|
+
* - UNAVAILABLE: Failing beyond `staleAfterSeconds`, or never succeeded. Nothing current can
|
|
1279
|
+
* be vouched for: render "unknown", never "none".
|
|
1280
|
+
*/
|
|
1281
|
+
export const zV1SourceStatus = z.enum([
|
|
1282
|
+
'SOURCE_STATUS_UNSPECIFIED',
|
|
1283
|
+
'OK',
|
|
1284
|
+
'STALE',
|
|
1285
|
+
'UNAVAILABLE'
|
|
1286
|
+
]).default('SOURCE_STATUS_UNSPECIFIED');
|
|
1287
|
+
/**
|
|
1288
|
+
* Source is one row of the source registry, with its health.
|
|
1289
|
+
*
|
|
1290
|
+
* Two kinds of row, told apart by `kind`: a FEED is an upstream the Grid
|
|
1291
|
+
* fetches on a schedule, and its id is what events carry in
|
|
1292
|
+
* `provenance.sourceId`. A REPORTER is an operator-run monitor that pushes data
|
|
1293
|
+
* to the Grid (`alanpi`, `relay`, `burn-line`); its row carries health only and
|
|
1294
|
+
* no event names it as its source.
|
|
1295
|
+
*
|
|
1296
|
+
* To judge health, read `status`. It is rewritten at every attempt, so as a
|
|
1297
|
+
* second check against the Grid itself stalling, treat a row as suspect when
|
|
1298
|
+
* `lastAttemptAt` is older than `staleAfterSeconds`. Do not compare
|
|
1299
|
+
* `lastAttemptAt` with `pollIntervalSeconds`: that misfires for reporters.
|
|
1300
|
+
*
|
|
1301
|
+
* Not every source id that appears in the API has a row. The live condition
|
|
1302
|
+
* layers fetch on request, outside the scheduler that writes this registry, so
|
|
1303
|
+
* `google` (the `road_segment` layer's travel times) has no row, and the
|
|
1304
|
+
* `caltrans` and `nws` rows describe the scheduled lane-closure and alert
|
|
1305
|
+
* polls, not the live `chain_control`, `message_sign`, `road_segment` and
|
|
1306
|
+
* `fire_weather` fetches. For those layers read the map layer's
|
|
1307
|
+
* `metadata.sourceStatus` or the summary domain's `status`.
|
|
1308
|
+
*/
|
|
1309
|
+
export const zV1Source = z.object({
|
|
1310
|
+
attribution: z.string(),
|
|
1311
|
+
expireAfterSeconds: z.int(),
|
|
1312
|
+
homepageUrl: z.string(),
|
|
1313
|
+
id: z.string(),
|
|
1314
|
+
kind: zV1SourceKind,
|
|
1315
|
+
lastAttemptAt: z.iso.datetime().nullable(),
|
|
1316
|
+
lastError: z.string(),
|
|
1317
|
+
lastSuccessAt: z.iso.datetime().nullable(),
|
|
1318
|
+
name: z.string(),
|
|
1319
|
+
pollIntervalSeconds: z.int(),
|
|
1320
|
+
staleAfterSeconds: z.int(),
|
|
1321
|
+
status: zV1SourceStatus
|
|
1322
|
+
});
|
|
1323
|
+
/**
|
|
1324
|
+
* SourceList is the source registry.
|
|
1325
|
+
*/
|
|
1326
|
+
export const zV1SourceList = z.object({
|
|
1327
|
+
sources: z.array(zV1Source)
|
|
1328
|
+
});
|
|
1329
|
+
/**
|
|
1330
|
+
* SummaryDomainHeadline is one item in a domain's headline list: an event, or a
|
|
1331
|
+
* live condition-layer feature (a closed road segment, a chain control, a fire
|
|
1332
|
+
* weather banner). Use `kind` to tell them apart before following `id`.
|
|
1333
|
+
*/
|
|
1334
|
+
export const zV1SummaryDomainHeadline = z.object({
|
|
1335
|
+
headline: z.string(),
|
|
1336
|
+
id: z.string(),
|
|
1337
|
+
kind: z.enum(['EVENT', 'CONDITION']),
|
|
1338
|
+
layer: z.enum([
|
|
1339
|
+
'WILDFIRE',
|
|
1340
|
+
'EVACUATION',
|
|
1341
|
+
'WEATHER_ALERT',
|
|
1342
|
+
'EARTHQUAKE',
|
|
1343
|
+
'ROAD_INCIDENT',
|
|
1344
|
+
'POWER',
|
|
1345
|
+
'MESH',
|
|
1346
|
+
'BURN_STATUS',
|
|
1347
|
+
'ROAD_SEGMENT',
|
|
1348
|
+
'CHAIN_CONTROL',
|
|
1349
|
+
'FIRE_WEATHER'
|
|
1350
|
+
]),
|
|
1351
|
+
severity: z.enum([
|
|
1352
|
+
'INFO',
|
|
1353
|
+
'MINOR',
|
|
1354
|
+
'MODERATE',
|
|
1355
|
+
'SEVERE',
|
|
1356
|
+
'EXTREME'
|
|
1357
|
+
])
|
|
1358
|
+
});
|
|
1359
|
+
/**
|
|
1360
|
+
* SummaryDomain is one subject area's status for the place.
|
|
1361
|
+
*
|
|
1362
|
+
* Domain inputs: `fire` = WILDFIRE events + the fire_weather condition;
|
|
1363
|
+
* `evacuation` = EVACUATION; `weather` = WEATHER_ALERT; `roads` = ROAD_INCIDENT
|
|
1364
|
+
* events (not SCHEDULED roadwork) + the chain_control and road_segment
|
|
1365
|
+
* conditions; `seismic` = EARTHQUAKE; `power` = POWER (including INFO
|
|
1366
|
+
* outages); `burn` = BURN_STATUS; `comms` = MESH. A domain counts every one of
|
|
1367
|
+
* its ACTIVE and SCHEDULED events at any severity, but a condition only when it
|
|
1368
|
+
* is above INFO (an open road or normal fire weather is not "active").
|
|
1369
|
+
*/
|
|
1370
|
+
export const zV1SummaryDomain = z.object({
|
|
1371
|
+
activeCount: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1372
|
+
domain: z.enum([
|
|
1373
|
+
'fire',
|
|
1374
|
+
'evacuation',
|
|
1375
|
+
'weather',
|
|
1376
|
+
'roads',
|
|
1377
|
+
'seismic',
|
|
1378
|
+
'power',
|
|
1379
|
+
'burn',
|
|
1380
|
+
'comms'
|
|
1381
|
+
]),
|
|
1382
|
+
headlines: z.array(zV1SummaryDomainHeadline),
|
|
1383
|
+
highestSeverity: z.enum([
|
|
1384
|
+
'INFO',
|
|
1385
|
+
'MINOR',
|
|
1386
|
+
'MODERATE',
|
|
1387
|
+
'SEVERE',
|
|
1388
|
+
'EXTREME'
|
|
1389
|
+
]),
|
|
1390
|
+
status: z.enum([
|
|
1391
|
+
'OK',
|
|
1392
|
+
'STALE',
|
|
1393
|
+
'UNAVAILABLE'
|
|
1394
|
+
])
|
|
1395
|
+
});
|
|
1396
|
+
/**
|
|
1397
|
+
* SummarySourceHealth is one source registry row behind the summary's layers.
|
|
1398
|
+
*/
|
|
1399
|
+
export const zV1SummarySourceHealth = z.object({
|
|
1400
|
+
id: z.string(),
|
|
1401
|
+
lastSuccessAt: z.iso.datetime().nullable(),
|
|
1402
|
+
status: z.enum([
|
|
1403
|
+
'OK',
|
|
1404
|
+
'STALE',
|
|
1405
|
+
'UNAVAILABLE'
|
|
1406
|
+
])
|
|
1407
|
+
});
|
|
1408
|
+
/**
|
|
1409
|
+
* SummaryTopEvent is one of the place's most urgent hazard events.
|
|
1410
|
+
*/
|
|
1411
|
+
export const zV1SummaryTopEvent = z.object({
|
|
1412
|
+
headline: z.string(),
|
|
1413
|
+
id: z.string(),
|
|
1414
|
+
layer: z.enum([
|
|
1415
|
+
'WILDFIRE',
|
|
1416
|
+
'EVACUATION',
|
|
1417
|
+
'WEATHER_ALERT',
|
|
1418
|
+
'EARTHQUAKE',
|
|
1419
|
+
'ROAD_INCIDENT',
|
|
1420
|
+
'POWER'
|
|
1421
|
+
]),
|
|
1422
|
+
severity: z.enum([
|
|
1423
|
+
'INFO',
|
|
1424
|
+
'MINOR',
|
|
1425
|
+
'MODERATE',
|
|
1426
|
+
'SEVERE',
|
|
1427
|
+
'EXTREME'
|
|
1428
|
+
]),
|
|
1429
|
+
severityRank: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1430
|
+
source: z.string()
|
|
1431
|
+
});
|
|
1432
|
+
/**
|
|
1433
|
+
* SummaryStats is the place's hazard rollup.
|
|
1434
|
+
*
|
|
1435
|
+
* It counts the place's ACTIVE and SCHEDULED events except four carve-outs:
|
|
1436
|
+
* MESH nodes and BURN_STATUS (ambient state, shown in their own domains), POWER
|
|
1437
|
+
* outages at INFO (single-customer service calls), and SCHEDULED road closures
|
|
1438
|
+
* (planned roadwork). A SCHEDULED weather watch or PSPS still counts. Condition
|
|
1439
|
+
* layers never count here.
|
|
1440
|
+
*/
|
|
1441
|
+
export const zV1SummaryStats = z.object({
|
|
1442
|
+
activeEvacuations: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).nullable(),
|
|
1443
|
+
evacuationSourceUrl: z.string(),
|
|
1444
|
+
evacuationStatus: z.enum([
|
|
1445
|
+
'OK',
|
|
1446
|
+
'STALE',
|
|
1447
|
+
'UNAVAILABLE'
|
|
1448
|
+
]),
|
|
1449
|
+
highestSeverity: z.enum([
|
|
1450
|
+
'INFO',
|
|
1451
|
+
'MINOR',
|
|
1452
|
+
'MODERATE',
|
|
1453
|
+
'SEVERE',
|
|
1454
|
+
'EXTREME'
|
|
1455
|
+
]),
|
|
1456
|
+
highestSeverityRank: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).lte(4),
|
|
1457
|
+
severityCounts: z.record(z.string(), z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })),
|
|
1458
|
+
topEvents: z.array(zV1SummaryTopEvent),
|
|
1459
|
+
totalActive: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })
|
|
1460
|
+
});
|
|
1461
|
+
/**
|
|
1462
|
+
* PlaceSummary is the one-call rollup for a place.
|
|
1463
|
+
*
|
|
1464
|
+
* `summary` covers hazards only. Each entry in `domains` covers one subject
|
|
1465
|
+
* area, including the ambient ones (`burn`, `comms`) that the hazard rollup
|
|
1466
|
+
* leaves out.
|
|
1467
|
+
*/
|
|
1468
|
+
export const zV1PlaceSummary = z.object({
|
|
1469
|
+
domains: z.array(zV1SummaryDomain),
|
|
1470
|
+
generatedAt: z.iso.datetime(),
|
|
1471
|
+
mode: z.enum([
|
|
1472
|
+
'QUIET',
|
|
1473
|
+
'WATCH',
|
|
1474
|
+
'ACTIVE'
|
|
1475
|
+
]),
|
|
1476
|
+
place: z.string(),
|
|
1477
|
+
placeId: z.string(),
|
|
1478
|
+
placeName: z.string(),
|
|
1479
|
+
sources: z.array(zV1SummarySourceHealth),
|
|
1480
|
+
summary: zV1SummaryStats
|
|
1481
|
+
});
|
|
1482
|
+
/**
|
|
1483
|
+
* WeatherAlertDetail is the WEATHER_ALERT detail block, for one NWS product.
|
|
1484
|
+
*
|
|
1485
|
+
* It carries only fields the envelope lacks: the NWS event name is the
|
|
1486
|
+
* envelope `category`, and the issuing office is `provenance.sourceName`.
|
|
1487
|
+
*/
|
|
1488
|
+
export const zV1WeatherAlertDetail = z.object({
|
|
1489
|
+
areaDesc: z.string(),
|
|
1490
|
+
certainty: z.enum([
|
|
1491
|
+
'Observed',
|
|
1492
|
+
'Likely',
|
|
1493
|
+
'Possible',
|
|
1494
|
+
'Unlikely',
|
|
1495
|
+
'Unknown'
|
|
1496
|
+
]),
|
|
1497
|
+
instruction: z.string(),
|
|
1498
|
+
nwsSeverity: z.enum([
|
|
1499
|
+
'Extreme',
|
|
1500
|
+
'Severe',
|
|
1501
|
+
'Moderate',
|
|
1502
|
+
'Minor',
|
|
1503
|
+
'Unknown'
|
|
1504
|
+
]),
|
|
1505
|
+
urgency: z.enum([
|
|
1506
|
+
'Immediate',
|
|
1507
|
+
'Expected',
|
|
1508
|
+
'Future',
|
|
1509
|
+
'Past',
|
|
1510
|
+
'Unknown'
|
|
1511
|
+
]),
|
|
1512
|
+
zones: z.array(z.string())
|
|
1513
|
+
});
|
|
1514
|
+
/**
|
|
1515
|
+
* WeatherConditions is current weather at one location, from OpenWeatherMap.
|
|
1516
|
+
* Whole numbers, metric units. A value that could not be read is 0.
|
|
1517
|
+
*/
|
|
1518
|
+
export const zV1WeatherConditions = z.object({
|
|
1519
|
+
feelsLikeCelsius: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1520
|
+
humidityPercent: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1521
|
+
locationId: z.string(),
|
|
1522
|
+
locationName: z.string(),
|
|
1523
|
+
temperatureCelsius: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1524
|
+
visibilityKm: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1525
|
+
weatherDescription: z.string(),
|
|
1526
|
+
weatherIcon: z.string(),
|
|
1527
|
+
weatherMain: z.string(),
|
|
1528
|
+
windDirectionDegrees: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1529
|
+
windSpeedKmh: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })
|
|
1530
|
+
});
|
|
1531
|
+
/**
|
|
1532
|
+
* WeatherForecast is a location's short-range forecast: the hourly NWS gridpoint
|
|
1533
|
+
* series (wind, gust, humidity, temperature) plus an at-a-glance summary.
|
|
1534
|
+
* Informational only: it never implies a fire-weather warning (issued products
|
|
1535
|
+
* are in `fireWeather`).
|
|
1536
|
+
*
|
|
1537
|
+
*/
|
|
1538
|
+
export const zV1WeatherForecast = z.object({
|
|
1539
|
+
horizonHours: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1540
|
+
issuedAt: z.iso.datetime().nullable(),
|
|
1541
|
+
locationId: z.string(),
|
|
1542
|
+
minHumidityPercent: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1543
|
+
peakWindGustAt: z.iso.datetime().nullable(),
|
|
1544
|
+
peakWindGustKmh: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1545
|
+
periods: z.array(zV1ForecastPeriod),
|
|
1546
|
+
source: z.string()
|
|
1547
|
+
});
|
|
1548
|
+
/**
|
|
1549
|
+
* Conditions is current, non-event state.
|
|
1550
|
+
*/
|
|
1551
|
+
export const zV1Conditions = z.object({
|
|
1552
|
+
fireWeather: zV1FireWeatherConditions.nullable(),
|
|
1553
|
+
forecast: z.array(zV1WeatherForecast),
|
|
1554
|
+
lastUpdated: z.iso.datetime().nullable(),
|
|
1555
|
+
weather: z.array(zV1WeatherConditions)
|
|
1556
|
+
});
|
|
1557
|
+
/**
|
|
1558
|
+
* WildfireDetail is the WILDFIRE detail block.
|
|
1559
|
+
*/
|
|
1560
|
+
export const zV1WildfireDetail = z.object({
|
|
1561
|
+
acres: z.number(),
|
|
1562
|
+
cause: z.string(),
|
|
1563
|
+
containment: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
|
|
1564
|
+
county: z.string(),
|
|
1565
|
+
hasPerimeter: z.boolean()
|
|
1566
|
+
});
|
|
1567
|
+
/**
|
|
1568
|
+
* Event is one item from one upstream source: a hazard, or a piece of ambient
|
|
1569
|
+
* state such as a mesh node or a county's burn status.
|
|
1570
|
+
*
|
|
1571
|
+
* The envelope fields are the same for every layer, so a client can render a
|
|
1572
|
+
* card from `headline`, `severity`, `status` and `provenance` without knowing the
|
|
1573
|
+
* layer. Layer-specific fields are in exactly one detail block (`wildfire`,
|
|
1574
|
+
* `evacuation`, `weatherAlert`, `earthquake`, `roadIncident`, `mesh`, `power` or
|
|
1575
|
+
* `burnStatus`), chosen by `layer`; the other blocks are absent. `fireWeather`
|
|
1576
|
+
* is never populated on an event.
|
|
1577
|
+
*/
|
|
1578
|
+
export const zV1Event = z.object({
|
|
1579
|
+
areaLabel: z.string(),
|
|
1580
|
+
burnStatus: zV1BurnStatusDetail.optional(),
|
|
1581
|
+
canonicalUrl: z.string(),
|
|
1582
|
+
category: z.string(),
|
|
1583
|
+
description: z.string(),
|
|
1584
|
+
earthquake: zV1EarthquakeDetail.optional(),
|
|
1585
|
+
effective: z.iso.datetime().nullable(),
|
|
1586
|
+
enhancement: zV1Enhancement.nullable(),
|
|
1587
|
+
evacuation: zV1EvacuationDetail.optional(),
|
|
1588
|
+
expires: z.iso.datetime().nullable(),
|
|
1589
|
+
fireWeather: zV1FireWeatherDetail.optional(),
|
|
1590
|
+
geometry: zV1Geometry.nullable(),
|
|
1591
|
+
headline: z.string(),
|
|
1592
|
+
id: z.string(),
|
|
1593
|
+
ingestedAt: z.iso.datetime(),
|
|
1594
|
+
layer: zV1Layer,
|
|
1595
|
+
mesh: zV1MeshDetail.optional(),
|
|
1596
|
+
observedAt: z.iso.datetime().nullable(),
|
|
1597
|
+
placeIds: z.array(z.string()),
|
|
1598
|
+
power: zV1PowerDetail.optional(),
|
|
1599
|
+
provenance: zV1Provenance,
|
|
1600
|
+
revision: z.int(),
|
|
1601
|
+
roadIncident: zV1RoadIncidentDetail.optional(),
|
|
1602
|
+
severity: zV1Severity,
|
|
1603
|
+
status: zV1EventStatus,
|
|
1604
|
+
summary: z.string(),
|
|
1605
|
+
weatherAlert: zV1WeatherAlertDetail.optional(),
|
|
1606
|
+
wildfire: zV1WildfireDetail.optional()
|
|
1607
|
+
});
|
|
1608
|
+
/**
|
|
1609
|
+
* EventList is one page of events.
|
|
1610
|
+
*/
|
|
1611
|
+
export const zV1EventList = z.object({
|
|
1612
|
+
events: z.array(zV1Event),
|
|
1613
|
+
nextPageToken: z.string()
|
|
1614
|
+
});
|
|
1615
|
+
/**
|
|
1616
|
+
* EventRevision is one stored snapshot of an event.
|
|
1617
|
+
*/
|
|
1618
|
+
export const zV1EventRevision = z.object({
|
|
1619
|
+
event: zV1Event,
|
|
1620
|
+
ingestedAt: z.iso.datetime(),
|
|
1621
|
+
observedAt: z.iso.datetime(),
|
|
1622
|
+
revision: z.int()
|
|
1623
|
+
});
|
|
1624
|
+
/**
|
|
1625
|
+
* EventRevisionList is one page of revisions.
|
|
1626
|
+
*/
|
|
1627
|
+
export const zV1EventRevisionList = z.object({
|
|
1628
|
+
nextPageToken: z.string(),
|
|
1629
|
+
revisions: z.array(zV1EventRevision)
|
|
1630
|
+
});
|
|
1631
|
+
/**
|
|
1632
|
+
* An `ETag` from an earlier response, for a `304` revalidation.
|
|
1633
|
+
*/
|
|
1634
|
+
export const zIfNoneMatch = z.string();
|
|
1635
|
+
/**
|
|
1636
|
+
* Recency window for relay links: a positive Go duration. The documented
|
|
1637
|
+
* choices are `24h`, `72h` (the default), `168h` and `720h`; any positive
|
|
1638
|
+
* duration works (`90m`), and values above `9600h` (400 days) are
|
|
1639
|
+
* clamped. Anything else (`abc`, `0`, `-1h`) is a `400
|
|
1640
|
+
* INVALID_ARGUMENT`. `/api/v1/mesh/links` echoes the applied window in
|
|
1641
|
+
* `window`.
|
|
1642
|
+
*
|
|
1643
|
+
*/
|
|
1644
|
+
export const zMeshWindow = z.string().default('72h');
|
|
1645
|
+
/**
|
|
1646
|
+
* A place slug (`calaveras-county`, `ebbetts-pass`, `hwy4-murphys-arnold`)
|
|
1647
|
+
* or namespaced id (`county:calaveras-county`). Slugs are globally unique.
|
|
1648
|
+
* `GET /api/v1/places` lists them; `GET /api/v1/places:resolve` maps an
|
|
1649
|
+
* address or lat/lng to the places containing it.
|
|
1650
|
+
*
|
|
1651
|
+
*/
|
|
1652
|
+
export const zPlace = z.string();
|
|
1653
|
+
export const zGridServiceListCamerasQuery = z.object({
|
|
1654
|
+
place: z.string().optional()
|
|
1655
|
+
});
|
|
1656
|
+
/**
|
|
1657
|
+
* A successful response.
|
|
1658
|
+
*/
|
|
1659
|
+
export const zGridServiceListCamerasResponse = zV1CameraList;
|
|
1660
|
+
export const zGridServiceGetConditionsQuery = z.object({
|
|
1661
|
+
place: z.string().optional()
|
|
1662
|
+
});
|
|
1663
|
+
/**
|
|
1664
|
+
* A successful response.
|
|
1665
|
+
*/
|
|
1666
|
+
export const zGridServiceGetConditionsResponse = zV1Conditions;
|
|
1667
|
+
export const zGridServiceListEventsQuery = z.object({
|
|
1668
|
+
place: z.string().optional(),
|
|
1669
|
+
layer: z.array(z.enum([
|
|
1670
|
+
'WILDFIRE',
|
|
1671
|
+
'EVACUATION',
|
|
1672
|
+
'WEATHER_ALERT',
|
|
1673
|
+
'EARTHQUAKE',
|
|
1674
|
+
'ROAD_INCIDENT',
|
|
1675
|
+
'POWER',
|
|
1676
|
+
'MESH',
|
|
1677
|
+
'BURN_STATUS'
|
|
1678
|
+
])).optional(),
|
|
1679
|
+
status: z.array(z.enum([
|
|
1680
|
+
'ACTIVE',
|
|
1681
|
+
'SCHEDULED',
|
|
1682
|
+
'RESOLVED',
|
|
1683
|
+
'EXPIRED'
|
|
1684
|
+
])).optional(),
|
|
1685
|
+
severityMin: z.enum([
|
|
1686
|
+
'INFO',
|
|
1687
|
+
'MINOR',
|
|
1688
|
+
'MODERATE',
|
|
1689
|
+
'SEVERE',
|
|
1690
|
+
'EXTREME'
|
|
1691
|
+
]).optional(),
|
|
1692
|
+
since: z.iso.datetime().optional(),
|
|
1693
|
+
pageSize: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).optional(),
|
|
1694
|
+
pageToken: z.string().optional(),
|
|
1695
|
+
enhancementIo: z.boolean().optional(),
|
|
1696
|
+
geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
|
|
1697
|
+
});
|
|
1698
|
+
/**
|
|
1699
|
+
* A successful response.
|
|
1700
|
+
*/
|
|
1701
|
+
export const zGridServiceListEventsResponse = zV1EventList;
|
|
1702
|
+
export const zGridServiceGetEventPath = z.object({
|
|
1703
|
+
id: z.string()
|
|
1704
|
+
});
|
|
1705
|
+
export const zGridServiceGetEventQuery = z.object({
|
|
1706
|
+
enhancementIo: z.boolean().optional(),
|
|
1707
|
+
geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
|
|
1708
|
+
});
|
|
1709
|
+
/**
|
|
1710
|
+
* A successful response.
|
|
1711
|
+
*/
|
|
1712
|
+
export const zGridServiceGetEventResponse = zV1Event;
|
|
1713
|
+
export const zGridServiceGetEventHistoryPath = z.object({
|
|
1714
|
+
id: z.string()
|
|
1715
|
+
});
|
|
1716
|
+
export const zGridServiceGetEventHistoryQuery = z.object({
|
|
1717
|
+
pageSize: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).optional(),
|
|
1718
|
+
pageToken: z.string().optional(),
|
|
1719
|
+
enhancementIo: z.boolean().optional(),
|
|
1720
|
+
geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
|
|
1721
|
+
});
|
|
1722
|
+
/**
|
|
1723
|
+
* A successful response.
|
|
1724
|
+
*/
|
|
1725
|
+
export const zGridServiceGetEventHistoryResponse = zV1EventRevisionList;
|
|
1726
|
+
export const zGridServiceListHistoryQuery = z.object({
|
|
1727
|
+
place: z.string().optional(),
|
|
1728
|
+
layer: z.array(z.enum([
|
|
1729
|
+
'WILDFIRE',
|
|
1730
|
+
'EVACUATION',
|
|
1731
|
+
'WEATHER_ALERT',
|
|
1732
|
+
'EARTHQUAKE',
|
|
1733
|
+
'ROAD_INCIDENT',
|
|
1734
|
+
'POWER',
|
|
1735
|
+
'MESH',
|
|
1736
|
+
'BURN_STATUS'
|
|
1737
|
+
])).optional(),
|
|
1738
|
+
from: z.iso.datetime().optional(),
|
|
1739
|
+
to: z.iso.datetime().optional(),
|
|
1740
|
+
pageSize: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).optional(),
|
|
1741
|
+
pageToken: z.string().optional(),
|
|
1742
|
+
enhancementIo: z.boolean().optional(),
|
|
1743
|
+
geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
|
|
1744
|
+
});
|
|
1745
|
+
/**
|
|
1746
|
+
* A successful response.
|
|
1747
|
+
*/
|
|
1748
|
+
export const zGridServiceListHistoryResponse = zV1EventRevisionList;
|
|
1749
|
+
export const zListMeshLinksHeaders = z.object({
|
|
1750
|
+
'If-None-Match': z.string().optional()
|
|
1751
|
+
});
|
|
1752
|
+
export const zListMeshLinksQuery = z.object({
|
|
1753
|
+
window: z.string().optional().default('72h')
|
|
1754
|
+
});
|
|
1755
|
+
/**
|
|
1756
|
+
* The links, possibly empty.
|
|
1757
|
+
*/
|
|
1758
|
+
export const zListMeshLinksResponse = zMeshLinkList;
|
|
1759
|
+
export const zGridServiceGetMeshTelemetryQuery = z.object({
|
|
1760
|
+
node: z.string().regex(/^([mM][eE][sS][hH][cC][oO][rR][eE]:)?([0-9a-fA-F]{2}){4,32}$/),
|
|
1761
|
+
from: z.iso.datetime().optional(),
|
|
1762
|
+
to: z.iso.datetime().optional()
|
|
1763
|
+
});
|
|
1764
|
+
/**
|
|
1765
|
+
* A successful response.
|
|
1766
|
+
*/
|
|
1767
|
+
export const zGridServiceGetMeshTelemetryResponse = zV1MeshTelemetryArchive;
|
|
1768
|
+
export const zGridServiceListPlacesQuery = z.object({
|
|
1769
|
+
kind: z.enum([
|
|
1770
|
+
'AREA',
|
|
1771
|
+
'COUNTY',
|
|
1772
|
+
'TOWN',
|
|
1773
|
+
'CORRIDOR',
|
|
1774
|
+
'EVAC_ZONE',
|
|
1775
|
+
'SITE'
|
|
1776
|
+
]).optional(),
|
|
1777
|
+
q: z.string().optional(),
|
|
1778
|
+
geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
|
|
1779
|
+
});
|
|
1780
|
+
/**
|
|
1781
|
+
* A successful response.
|
|
1782
|
+
*/
|
|
1783
|
+
export const zGridServiceListPlacesResponse = zV1PlaceList;
|
|
1784
|
+
export const zGridServiceGetPlacePath = z.object({
|
|
1785
|
+
place: z.string()
|
|
1786
|
+
});
|
|
1787
|
+
export const zGridServiceGetPlaceQuery = z.object({
|
|
1788
|
+
geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
|
|
1789
|
+
});
|
|
1790
|
+
/**
|
|
1791
|
+
* A successful response.
|
|
1792
|
+
*/
|
|
1793
|
+
export const zGridServiceGetPlaceResponse = zV1Place;
|
|
1794
|
+
export const zGetMapLayerHeaders = z.object({
|
|
1795
|
+
'If-None-Match': z.string().optional()
|
|
1796
|
+
});
|
|
1797
|
+
export const zGetMapLayerPath = z.object({
|
|
1798
|
+
place: z.string(),
|
|
1799
|
+
layer: z.enum([
|
|
1800
|
+
'road_incident',
|
|
1801
|
+
'chain_control',
|
|
1802
|
+
'road_segment',
|
|
1803
|
+
'message_sign',
|
|
1804
|
+
'weather_alert',
|
|
1805
|
+
'fire_weather',
|
|
1806
|
+
'earthquake',
|
|
1807
|
+
'wildfire',
|
|
1808
|
+
'evacuation',
|
|
1809
|
+
'power',
|
|
1810
|
+
'mesh_node',
|
|
1811
|
+
'mesh_link',
|
|
1812
|
+
'camera'
|
|
1813
|
+
])
|
|
1814
|
+
});
|
|
1815
|
+
export const zGetMapLayerQuery = z.object({
|
|
1816
|
+
window: z.string().optional().default('72h')
|
|
1817
|
+
});
|
|
1818
|
+
/**
|
|
1819
|
+
* The layer. Empty `features` is a valid answer; read `metadata.sourceStatus` to know whether it is confirmed-empty or unknown.
|
|
1820
|
+
*/
|
|
1821
|
+
export const zGetMapLayerResponse = zMapFeatureCollection;
|
|
1822
|
+
export const zGridServiceGetPlaceSummaryPath = z.object({
|
|
1823
|
+
place: z.string()
|
|
1824
|
+
});
|
|
1825
|
+
/**
|
|
1826
|
+
* A successful response.
|
|
1827
|
+
*/
|
|
1828
|
+
export const zGridServiceGetPlaceSummaryResponse = zV1PlaceSummary;
|
|
1829
|
+
export const zGridServiceResolvePlaceQuery = z.object({
|
|
1830
|
+
lat: z.number().optional(),
|
|
1831
|
+
lng: z.number().optional(),
|
|
1832
|
+
address: z.string().optional(),
|
|
1833
|
+
geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
|
|
1834
|
+
});
|
|
1835
|
+
/**
|
|
1836
|
+
* A successful response.
|
|
1837
|
+
*/
|
|
1838
|
+
export const zGridServiceResolvePlaceResponse = zV1ResolvePlaceResponse;
|
|
1839
|
+
export const zGridServiceListScannersQuery = z.object({
|
|
1840
|
+
place: z.string().optional()
|
|
1841
|
+
});
|
|
1842
|
+
/**
|
|
1843
|
+
* A successful response.
|
|
1844
|
+
*/
|
|
1845
|
+
export const zGridServiceListScannersResponse = zV1ScannerList;
|
|
1846
|
+
/**
|
|
1847
|
+
* A successful response.
|
|
1848
|
+
*/
|
|
1849
|
+
export const zGridServiceListSourcesResponse = zV1SourceList;
|