@aeroswarm/core 0.2.11 → 0.2.13

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 CHANGED
@@ -54,6 +54,27 @@ Both `FusedTrackEvent` and `AlertEvent` carry an optional `airportId` (ICAO code
54
54
 
55
55
  `positionSchema`, `velocitySchema`, `currentTrackSchema`, `streamEnvelopeSchema`, `sourceHeartbeatSchema`, `wsSubscribeSchema`, `apiSuccessSchema`, `apiErrorSchema`, `apiResponseSchema` + inferred input types (`CurrentTrackInput`, `WsSubscribeInput`, `StreamEnvelopeInput`).
56
56
 
57
+ ### `api` — one response format for every REST endpoint (`@aeroswarm/core/api`)
58
+
59
+ So that a developer who adds an endpoint does not invent a new shape. The WebSocket has its own strict envelope (`streamEnvelopeSchema`); this is the REST counterpart, and its error has the same fields as the WS `stream.error` payload.
60
+
61
+ ```ts
62
+ import { ok, fail, toResponse } from "@aeroswarm/core/api";
63
+
64
+ return toResponse(ok(rows, { count: rows.length })); // { ok: true, data: rows, meta: { serverTime, count } }
65
+ return toResponse(fail("NOT_FOUND", "no such track")); // 404 { ok: false, error: { code, message, recoverable } }
66
+ ```
67
+
68
+ | | |
69
+ |---|---|
70
+ | Success | `{ "ok": true, "data": <T>, "meta": { "serverTime": 1730000000000, "count"?, "nextCursor"?, "truncated"? } }` |
71
+ | Failure | `{ "ok": false, "error": { "code", "message", "recoverable", "details"? } }` |
72
+ | Codes | `UNAUTHORIZED` 401, `FORBIDDEN` 403, `NOT_FOUND` 404, `BAD_REQUEST` 400, `CONFLICT` 409, `RATE_LIMITED` 429, `UNAVAILABLE` 503, `INTERNAL` 500. `recoverable` is true for the last three and for rate limits. A client must tolerate codes it does not know. |
73
+ | Conventions | times are epoch milliseconds (as in the WS); positions are `{ lat, lon }` (arrays `[lon, lat]` only inside GeoJSON); ids are strings; lists page with `nextCursor` |
74
+ | Older servers | an endpoint that existed before this format keeps its old shape unless the request asks for the envelope: `wantsEnvelope(url, headers)` is true for the header `x-aero-envelope: 1` (`ENVELOPE_HEADER`) or `?envelope=1`. `@aeroswarm/replay-server` does this. |
75
+
76
+ Also exported: `statusFor(code)`, `codeForStatus(status)`, `API_ERROR_CODES`, and the schemas `apiResponseSchema(dataSchema)`, `apiSuccessSchema`, `apiErrorSchema`, `apiMetaSchema`. Checklist for a new endpoint: answer with `ok()` / `fail()`; for a new WS message type, add it to `streamEnvelopeSchema` (turn on `validateOutgoing` in `@aeroswarm/live-server` in your tests to catch a type that was not added).
77
+
57
78
  ### `config` — environment access
58
79
 
59
80
  | Export | Purpose |
@@ -0,0 +1,45 @@
1
+ export { apiErrorSchema, apiMetaSchema, apiResponseSchema, apiSuccessSchema } from '../validation/index.js';
2
+ import 'zod';
3
+
4
+ declare const API_ERROR_CODES: readonly ["UNAUTHORIZED", "FORBIDDEN", "NOT_FOUND", "BAD_REQUEST", "CONFLICT", "RATE_LIMITED", "UNAVAILABLE", "INTERNAL"];
5
+ type ApiErrorCode = (typeof API_ERROR_CODES)[number];
6
+ interface ApiMeta {
7
+ serverTime: number;
8
+ count?: number;
9
+ nextCursor?: string;
10
+ truncated?: boolean;
11
+ }
12
+ interface ApiOk<T> {
13
+ ok: true;
14
+ data: T;
15
+ meta?: ApiMeta;
16
+ }
17
+ interface ApiErr {
18
+ ok: false;
19
+ error: {
20
+ code: string;
21
+ message: string;
22
+ recoverable: boolean;
23
+ details?: unknown;
24
+ };
25
+ }
26
+ type ApiResponse<T> = ApiOk<T> | ApiErr;
27
+ declare const statusFor: (code: ApiErrorCode) => number;
28
+ /** The code for an HTTP status from a server that does not send one. */
29
+ declare function codeForStatus(status: number): ApiErrorCode;
30
+ /** `meta.serverTime` is always set; pass `count`, `nextCursor` or `truncated` for lists. */
31
+ declare function ok<T>(data: T, meta?: Partial<ApiMeta>): ApiOk<T>;
32
+ declare function fail(code: ApiErrorCode, message: string, details?: unknown): ApiErr;
33
+ /** A standard `Response`: JSON, status 200 for success, `statusFor(code)` for a failure. */
34
+ declare function toResponse(body: ApiOk<unknown> | ApiErr, status?: number): Response;
35
+ /**
36
+ * Servers that existed before this format keep answering in their old shape unless the
37
+ * request asks for the envelope, so clients that were written against the old shape do
38
+ * not break. Ask with the header (or `?envelope=1`, for a plain browser request).
39
+ */
40
+ declare const ENVELOPE_HEADER = "x-aero-envelope";
41
+ declare function wantsEnvelope(url: URL, headers?: {
42
+ get(name: string): string | null;
43
+ }): boolean;
44
+
45
+ export { API_ERROR_CODES, type ApiErr, type ApiErrorCode, type ApiMeta, type ApiOk, type ApiResponse, ENVELOPE_HEADER, codeForStatus, fail, ok, statusFor, toResponse, wantsEnvelope };
@@ -0,0 +1,75 @@
1
+ import {
2
+ apiErrorSchema,
3
+ apiMetaSchema,
4
+ apiResponseSchema,
5
+ apiSuccessSchema
6
+ } from "../chunk-7SUMR3X2.js";
7
+
8
+ // src/api/index.ts
9
+ var API_ERROR_CODES = [
10
+ "UNAUTHORIZED",
11
+ "FORBIDDEN",
12
+ "NOT_FOUND",
13
+ "BAD_REQUEST",
14
+ "CONFLICT",
15
+ "RATE_LIMITED",
16
+ "UNAVAILABLE",
17
+ "INTERNAL"
18
+ ];
19
+ var STATUS = {
20
+ UNAUTHORIZED: 401,
21
+ FORBIDDEN: 403,
22
+ NOT_FOUND: 404,
23
+ BAD_REQUEST: 400,
24
+ CONFLICT: 409,
25
+ RATE_LIMITED: 429,
26
+ UNAVAILABLE: 503,
27
+ INTERNAL: 500
28
+ };
29
+ var RECOVERABLE = /* @__PURE__ */ new Set(["RATE_LIMITED", "UNAVAILABLE", "INTERNAL"]);
30
+ var statusFor = (code) => STATUS[code];
31
+ function codeForStatus(status) {
32
+ for (const code of API_ERROR_CODES) if (STATUS[code] === status) return code;
33
+ if (status >= 500) return "INTERNAL";
34
+ return "BAD_REQUEST";
35
+ }
36
+ function ok(data, meta = {}) {
37
+ return { ok: true, data, meta: { serverTime: Date.now(), ...meta } };
38
+ }
39
+ function fail(code, message, details) {
40
+ return {
41
+ ok: false,
42
+ error: {
43
+ code,
44
+ message,
45
+ recoverable: RECOVERABLE.has(code),
46
+ ...details !== void 0 && { details }
47
+ }
48
+ };
49
+ }
50
+ function toResponse(body, status) {
51
+ const code = body.ok ? void 0 : body.error.code;
52
+ const resolved = status ?? (body.ok ? 200 : (code && STATUS[code]) ?? 500);
53
+ return new Response(JSON.stringify(body), {
54
+ status: resolved,
55
+ headers: { "content-type": "application/json" }
56
+ });
57
+ }
58
+ var ENVELOPE_HEADER = "x-aero-envelope";
59
+ function wantsEnvelope(url, headers) {
60
+ return url.searchParams.get("envelope") === "1" || headers?.get(ENVELOPE_HEADER) === "1";
61
+ }
62
+ export {
63
+ API_ERROR_CODES,
64
+ ENVELOPE_HEADER,
65
+ apiErrorSchema,
66
+ apiMetaSchema,
67
+ apiResponseSchema,
68
+ apiSuccessSchema,
69
+ codeForStatus,
70
+ fail,
71
+ ok,
72
+ statusFor,
73
+ toResponse,
74
+ wantsEnvelope
75
+ };
@@ -27,6 +27,10 @@ var flightPlanSummarySchema = z.object({
27
27
  status: z.enum(["filed", "delayed", "departed", "arrived", "cancelled"]),
28
28
  phase: z.enum(["ARRIVAL", "DEPARTURE", "OVERFLIGHT", "UNKNOWN"])
29
29
  });
30
+ var dataSourceSchema = z.object({
31
+ sac: z.number().int().min(0).max(255),
32
+ sic: z.number().int().min(0).max(255)
33
+ });
30
34
  var currentTrackSchema = z.object({
31
35
  trackId: z.string(),
32
36
  source: z.enum(["ADSB", "ASTERIX_CAT010", "ASTERIX_CAT011", "ASTERIX_CAT020", "ASTERIX_CAT021", "ASTERIX_CAT048", "ASTERIX_CAT062", "FUSED"]),
@@ -35,7 +39,12 @@ var currentTrackSchema = z.object({
35
39
  squawk: z.string().nullable(),
36
40
  targetType: z.enum(["aircraft", "vehicle", "unknown"]).optional(),
37
41
  vehicleFleet: z.number().optional(),
42
+ aircraftType: z.string().optional(),
43
+ wake: z.string().optional(),
44
+ route: z.object({ adep: z.string().optional(), ades: z.string().optional() }).optional(),
45
+ onGround: z.boolean().optional(),
38
46
  airportId: z.string().optional(),
47
+ dataSource: dataSourceSchema.optional(),
39
48
  lat: z.number().min(-90).max(90).nullable(),
40
49
  lon: z.number().min(-180).max(180).nullable(),
41
50
  altitudeFt: z.number().nullable(),
@@ -119,13 +128,26 @@ var wsUpdateFilterSchema = z.object({
119
128
  maxUpdateHz: z.number().min(1).max(60).optional(),
120
129
  maxTracks: z.number().int().min(1).max(1e4).nullable().optional()
121
130
  });
122
- var apiSuccessSchema = (dataSchema) => z.object({ ok: z.literal(true), data: dataSchema });
131
+ var apiMetaSchema = z.object({
132
+ /** The server's clock when it answered (ms). */
133
+ serverTime: z.number(),
134
+ /** Number of items, for list responses. */
135
+ count: z.number().int().nonnegative().optional(),
136
+ /** Pass back to get the next page. */
137
+ nextCursor: z.string().optional(),
138
+ /** The server returned fewer items than matched (a `limit`, or thinning). */
139
+ truncated: z.boolean().optional()
140
+ });
141
+ var apiSuccessSchema = (dataSchema) => z.object({ ok: z.literal(true), data: dataSchema, meta: apiMetaSchema.optional() });
123
142
  var apiErrorSchema = z.object({
124
143
  ok: z.literal(false),
125
144
  error: z.object({
145
+ /** Stable machine-readable code, e.g. "NOT_FOUND". A client must tolerate codes it does not know. */
126
146
  code: z.string(),
127
147
  message: z.string(),
128
- recoverable: z.boolean()
148
+ /** Retrying the same request later may succeed. Same field as the WS `stream.error` payload. */
149
+ recoverable: z.boolean(),
150
+ details: z.unknown().optional()
129
151
  })
130
152
  });
131
153
  var apiResponseSchema = (dataSchema) => z.union([apiSuccessSchema(dataSchema), apiErrorSchema]);
@@ -134,11 +156,13 @@ export {
134
156
  positionSchema,
135
157
  velocitySchema,
136
158
  flightPlanSummarySchema,
159
+ dataSourceSchema,
137
160
  currentTrackSchema,
138
161
  streamEnvelopeSchema,
139
162
  sourceHeartbeatSchema,
140
163
  wsSubscribeSchema,
141
164
  wsUpdateFilterSchema,
165
+ apiMetaSchema,
142
166
  apiSuccessSchema,
143
167
  apiErrorSchema,
144
168
  apiResponseSchema
@@ -83,7 +83,12 @@ function toCurrentTrack(fused, staleAfterMs = 15e3, lostAfterMs = 9e4) {
83
83
  squawk: fused.identity.squawk ?? null,
84
84
  ...fused.identity.targetType !== void 0 && { targetType: fused.identity.targetType },
85
85
  ...fused.identity.vehicleFleet !== void 0 && { vehicleFleet: fused.identity.vehicleFleet },
86
+ ...fused.identity.aircraftType !== void 0 && { aircraftType: fused.identity.aircraftType },
87
+ ...fused.identity.wake !== void 0 && { wake: fused.identity.wake },
88
+ ...fused.route !== void 0 && { route: fused.route },
89
+ ...fused.position?.onGround !== void 0 && { onGround: fused.position.onGround },
86
90
  ...fused.airportId !== void 0 && { airportId: fused.airportId },
91
+ ...fused.dataSource !== void 0 && { dataSource: fused.dataSource },
87
92
  lat: fused.position?.lat ?? null,
88
93
  lon: fused.position?.lon ?? null,
89
94
  altitudeFt: fused.position?.alt ?? null,
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { SourceHealthEvent, FusedTrackEvent } from './types/index.js';
2
- export { AeroConnectionStatus, AeroRecoverableError, AftnMessagePayload, AssignedRoute, Bbox, ConfidenceBudget, CurrentTrack, FlightPhase, FlightPlan, FlightPlanEvent, FlightPlanStatus, FlightPlanSummary, Position, Protocol, RouteAssignment, SourceStatus, StreamEnvelope, TargetType, TrackSource, TrackStatus, Velocity } from './types/index.js';
2
+ export { AeroConnectionStatus, AeroRecoverableError, AftnMessagePayload, AssignedRoute, Bbox, ConfidenceBudget, CurrentTrack, DataSource, FlightPhase, FlightPlan, FlightPlanEvent, FlightPlanStatus, FlightPlanSummary, Position, Protocol, RouteAssignment, SourceStatus, StreamEnvelope, TargetDetails, TargetType, TrackSource, TrackStatus, Velocity } from './types/index.js';
3
3
  import { TopicName } from './utils/index.js';
4
4
  export { EMERGENCY_SQUAWKS, LOST_AFTER_MS, MACH1_KT, PolylineDistance, STALE_AFTER_MS, TOPICS, clamp, createEventId, createEventUid, createNanoid, createSessionId, createTrackId, distanceToPolylineM, haversineKm, isInsideBbox, isRenderableTrack, toCurrentTrack } from './utils/index.js';
5
5
  export { applyFlightPlanEvent, flightPhase, flightPlanId, normalizeCallsign, pickMatchingPlan, summarizeFlightPlan } from './flightplan/index.js';
6
- export { CurrentTrackInput, StreamEnvelopeInput, WsSubscribeInput, apiErrorSchema, apiResponseSchema, apiSuccessSchema, currentTrackSchema, flightPlanSummarySchema, positionSchema, sourceHeartbeatSchema, streamEnvelopeSchema, velocitySchema, wsSubscribeSchema, wsUpdateFilterSchema } from './validation/index.js';
6
+ export { CurrentTrackInput, StreamEnvelopeInput, WsSubscribeInput, apiErrorSchema, apiMetaSchema, apiResponseSchema, apiSuccessSchema, currentTrackSchema, dataSourceSchema, flightPlanSummarySchema, positionSchema, sourceHeartbeatSchema, streamEnvelopeSchema, velocitySchema, wsSubscribeSchema, wsUpdateFilterSchema } from './validation/index.js';
7
7
  import pino, { Logger } from 'pino';
8
8
  import { Registry, Counter, Gauge } from 'prom-client';
9
9
  import { Redis } from 'ioredis';
package/dist/index.js CHANGED
@@ -24,12 +24,14 @@ import {
24
24
  isInsideBbox,
25
25
  isRenderableTrack,
26
26
  toCurrentTrack
27
- } from "./chunk-J2UTSYKD.js";
27
+ } from "./chunk-UROKN5FM.js";
28
28
  import {
29
29
  apiErrorSchema,
30
+ apiMetaSchema,
30
31
  apiResponseSchema,
31
32
  apiSuccessSchema,
32
33
  currentTrackSchema,
34
+ dataSourceSchema,
33
35
  flightPlanSummarySchema,
34
36
  positionSchema,
35
37
  sourceHeartbeatSchema,
@@ -37,7 +39,7 @@ import {
37
39
  velocitySchema,
38
40
  wsSubscribeSchema,
39
41
  wsUpdateFilterSchema
40
- } from "./chunk-ZYX6U3ZK.js";
42
+ } from "./chunk-7SUMR3X2.js";
41
43
 
42
44
  // src/config/index.ts
43
45
  import { config } from "dotenv";
@@ -535,6 +537,7 @@ export {
535
537
  TOPICS,
536
538
  TOPIC_REGISTRY,
537
539
  apiErrorSchema,
540
+ apiMetaSchema,
538
541
  apiResponseSchema,
539
542
  apiSuccessSchema,
540
543
  applyFlightPlanEvent,
@@ -551,6 +554,7 @@ export {
551
554
  createSessionId,
552
555
  createTrackId,
553
556
  currentTrackSchema,
557
+ dataSourceSchema,
554
558
  deleteTrack,
555
559
  disconnectProducer,
556
560
  disconnectRedis,
@@ -22,6 +22,25 @@ type Protocol = "adsb" | "asterix-cat010" | "asterix-cat011" | "asterix-cat020"
22
22
  type Bbox = [minLon: number, minLat: number, maxLon: number, maxLat: number];
23
23
  /** Surface target classification (A-SMGCS CAT010/011). Absent for en-route tracks. */
24
24
  type TargetType = "aircraft" | "vehicle" | "unknown";
25
+ /** ASTERIX Data Source Identifier (I010 / I020 / I021 / I048 ...): which sensor or ground
26
+ * station reported a track, as System Area Code / System Identification Code (0-255 each). */
27
+ interface DataSource {
28
+ sac: number;
29
+ sic: number;
30
+ }
31
+ /** Facts a sensor reports about a target besides its position and identity. All optional: a sensor sends what it has. */
32
+ interface TargetDetails {
33
+ /** Track number the sensor assigned */
34
+ trackNumber?: number;
35
+ /** Time of the report as the sensor stamped it, seconds since midnight UTC */
36
+ timeOfDay?: number;
37
+ /** ADS-B emitter category (CAT021 ECAT) */
38
+ emitterCategory?: number;
39
+ /** Footprint of a surface target, metres, and the way it points, degrees */
40
+ lengthM?: number;
41
+ widthM?: number;
42
+ orientationDeg?: number;
43
+ }
25
44
  interface FusedTrackEvent {
26
45
  trackId: string;
27
46
  sources: [string, ...string[]];
@@ -33,8 +52,21 @@ interface FusedTrackEvent {
33
52
  squawk?: string;
34
53
  targetType?: TargetType;
35
54
  vehicleFleet?: number;
55
+ /** ICAO aircraft type designator the surveillance system reports, e.g. "A320" (ASTERIX CAT062) */
56
+ aircraftType?: string;
57
+ /** Wake turbulence category L / M / H / J, as in `FlightPlan.wake` */
58
+ wake?: string;
36
59
  };
60
+ /** Departure and destination aerodromes the surveillance system reports for the flight (ICAO), named as in `FlightPlan`. */
61
+ route?: {
62
+ adep?: string;
63
+ ades?: string;
64
+ };
65
+ /** What the sensor reported about the target besides where it is (ASTERIX feeds). */
66
+ details?: TargetDetails;
37
67
  protocol: Protocol;
68
+ /** Sensor that reported this track (ASTERIX feeds only). For a merged track: the sensor whose position is shown. */
69
+ dataSource?: DataSource;
38
70
  position?: Position;
39
71
  velocity?: Velocity;
40
72
  confidence: ConfidenceBudget;
@@ -182,8 +214,20 @@ interface CurrentTrack {
182
214
  targetType?: TargetType;
183
215
  /** I010/300 Vehicle Fleet Identification code; only present when targetType is "vehicle" */
184
216
  vehicleFleet?: number;
217
+ /** Aircraft type and wake category the surveillance system reports (not the flight plan's: see `flightPlan`) */
218
+ aircraftType?: string;
219
+ wake?: string;
220
+ /** Departure and destination the surveillance system reports for the flight */
221
+ route?: {
222
+ adep?: string;
223
+ ades?: string;
224
+ };
225
+ /** On the ground as the sensor reports it; the airport backend may replace it with its own derived state */
226
+ onGround?: boolean;
185
227
  /** ICAO airport code this track is attributed to; undefined = unscoped */
186
228
  airportId?: string;
229
+ /** Sensor (SAC/SIC) that reported the position shown; ASTERIX feeds only */
230
+ dataSource?: DataSource;
187
231
  lat: number | null;
188
232
  lon: number | null;
189
233
  altitudeFt: number | null;
@@ -257,4 +301,4 @@ interface AeroRecoverableError {
257
301
  }
258
302
  type SourceStatus = SourceHealthEvent["status"];
259
303
 
260
- export type { AeroConnectionStatus, AeroRecoverableError, AftnMessagePayload, AssignedRoute, Bbox, ConfidenceBudget, CurrentTrack, FlightPhase, FlightPlan, FlightPlanEvent, FlightPlanStatus, FlightPlanSummary, FusedTrackEvent, Position, Protocol, RouteAssignment, SourceHealthEvent, SourceStatus, StreamEnvelope, TargetType, TrackSource, TrackStatus, Velocity };
304
+ export type { AeroConnectionStatus, AeroRecoverableError, AftnMessagePayload, AssignedRoute, Bbox, ConfidenceBudget, CurrentTrack, DataSource, FlightPhase, FlightPlan, FlightPlanEvent, FlightPlanStatus, FlightPlanSummary, FusedTrackEvent, Position, Protocol, RouteAssignment, SourceHealthEvent, SourceStatus, StreamEnvelope, TargetDetails, TargetType, TrackSource, TrackStatus, Velocity };
@@ -15,7 +15,7 @@ import {
15
15
  isInsideBbox,
16
16
  isRenderableTrack,
17
17
  toCurrentTrack
18
- } from "../chunk-J2UTSYKD.js";
18
+ } from "../chunk-UROKN5FM.js";
19
19
  export {
20
20
  EMERGENCY_SQUAWKS,
21
21
  LOST_AFTER_MS,
@@ -42,6 +42,10 @@ declare const flightPlanSummarySchema: z.ZodObject<{
42
42
  UNKNOWN: "UNKNOWN";
43
43
  }>;
44
44
  }, z.core.$strip>;
45
+ declare const dataSourceSchema: z.ZodObject<{
46
+ sac: z.ZodNumber;
47
+ sic: z.ZodNumber;
48
+ }, z.core.$strip>;
45
49
  declare const currentTrackSchema: z.ZodObject<{
46
50
  trackId: z.ZodString;
47
51
  source: z.ZodEnum<{
@@ -63,7 +67,18 @@ declare const currentTrackSchema: z.ZodObject<{
63
67
  unknown: "unknown";
64
68
  }>>;
65
69
  vehicleFleet: z.ZodOptional<z.ZodNumber>;
70
+ aircraftType: z.ZodOptional<z.ZodString>;
71
+ wake: z.ZodOptional<z.ZodString>;
72
+ route: z.ZodOptional<z.ZodObject<{
73
+ adep: z.ZodOptional<z.ZodString>;
74
+ ades: z.ZodOptional<z.ZodString>;
75
+ }, z.core.$strip>>;
76
+ onGround: z.ZodOptional<z.ZodBoolean>;
66
77
  airportId: z.ZodOptional<z.ZodString>;
78
+ dataSource: z.ZodOptional<z.ZodObject<{
79
+ sac: z.ZodNumber;
80
+ sic: z.ZodNumber;
81
+ }, z.core.$strip>>;
67
82
  lat: z.ZodNullable<z.ZodNumber>;
68
83
  lon: z.ZodNullable<z.ZodNumber>;
69
84
  altitudeFt: z.ZodNullable<z.ZodNumber>;
@@ -130,7 +145,18 @@ declare const streamEnvelopeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
130
145
  unknown: "unknown";
131
146
  }>>;
132
147
  vehicleFleet: z.ZodOptional<z.ZodNumber>;
148
+ aircraftType: z.ZodOptional<z.ZodString>;
149
+ wake: z.ZodOptional<z.ZodString>;
150
+ route: z.ZodOptional<z.ZodObject<{
151
+ adep: z.ZodOptional<z.ZodString>;
152
+ ades: z.ZodOptional<z.ZodString>;
153
+ }, z.core.$strip>>;
154
+ onGround: z.ZodOptional<z.ZodBoolean>;
133
155
  airportId: z.ZodOptional<z.ZodString>;
156
+ dataSource: z.ZodOptional<z.ZodObject<{
157
+ sac: z.ZodNumber;
158
+ sic: z.ZodNumber;
159
+ }, z.core.$strip>>;
134
160
  lat: z.ZodNullable<z.ZodNumber>;
135
161
  lon: z.ZodNullable<z.ZodNumber>;
136
162
  altitudeFt: z.ZodNullable<z.ZodNumber>;
@@ -198,7 +224,18 @@ declare const streamEnvelopeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
198
224
  unknown: "unknown";
199
225
  }>>;
200
226
  vehicleFleet: z.ZodOptional<z.ZodNumber>;
227
+ aircraftType: z.ZodOptional<z.ZodString>;
228
+ wake: z.ZodOptional<z.ZodString>;
229
+ route: z.ZodOptional<z.ZodObject<{
230
+ adep: z.ZodOptional<z.ZodString>;
231
+ ades: z.ZodOptional<z.ZodString>;
232
+ }, z.core.$strip>>;
233
+ onGround: z.ZodOptional<z.ZodBoolean>;
201
234
  airportId: z.ZodOptional<z.ZodString>;
235
+ dataSource: z.ZodOptional<z.ZodObject<{
236
+ sac: z.ZodNumber;
237
+ sic: z.ZodNumber;
238
+ }, z.core.$strip>>;
202
239
  lat: z.ZodNullable<z.ZodNumber>;
203
240
  lon: z.ZodNullable<z.ZodNumber>;
204
241
  altitudeFt: z.ZodNullable<z.ZodNumber>;
@@ -325,9 +362,22 @@ declare const wsUpdateFilterSchema: z.ZodObject<{
325
362
  maxUpdateHz: z.ZodOptional<z.ZodNumber>;
326
363
  maxTracks: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
327
364
  }, z.core.$strip>;
365
+ /** Rides along with a successful REST response. */
366
+ declare const apiMetaSchema: z.ZodObject<{
367
+ serverTime: z.ZodNumber;
368
+ count: z.ZodOptional<z.ZodNumber>;
369
+ nextCursor: z.ZodOptional<z.ZodString>;
370
+ truncated: z.ZodOptional<z.ZodBoolean>;
371
+ }, z.core.$strip>;
328
372
  declare const apiSuccessSchema: <T extends z.ZodTypeAny>(dataSchema: T) => z.ZodObject<{
329
373
  ok: z.ZodLiteral<true>;
330
374
  data: T;
375
+ meta: z.ZodOptional<z.ZodObject<{
376
+ serverTime: z.ZodNumber;
377
+ count: z.ZodOptional<z.ZodNumber>;
378
+ nextCursor: z.ZodOptional<z.ZodString>;
379
+ truncated: z.ZodOptional<z.ZodBoolean>;
380
+ }, z.core.$strip>>;
331
381
  }, z.core.$strip>;
332
382
  declare const apiErrorSchema: z.ZodObject<{
333
383
  ok: z.ZodLiteral<false>;
@@ -335,21 +385,29 @@ declare const apiErrorSchema: z.ZodObject<{
335
385
  code: z.ZodString;
336
386
  message: z.ZodString;
337
387
  recoverable: z.ZodBoolean;
388
+ details: z.ZodOptional<z.ZodUnknown>;
338
389
  }, z.core.$strip>;
339
390
  }, z.core.$strip>;
340
391
  declare const apiResponseSchema: <T extends z.ZodTypeAny>(dataSchema: T) => z.ZodUnion<readonly [z.ZodObject<{
341
392
  ok: z.ZodLiteral<true>;
342
393
  data: T;
394
+ meta: z.ZodOptional<z.ZodObject<{
395
+ serverTime: z.ZodNumber;
396
+ count: z.ZodOptional<z.ZodNumber>;
397
+ nextCursor: z.ZodOptional<z.ZodString>;
398
+ truncated: z.ZodOptional<z.ZodBoolean>;
399
+ }, z.core.$strip>>;
343
400
  }, z.core.$strip>, z.ZodObject<{
344
401
  ok: z.ZodLiteral<false>;
345
402
  error: z.ZodObject<{
346
403
  code: z.ZodString;
347
404
  message: z.ZodString;
348
405
  recoverable: z.ZodBoolean;
406
+ details: z.ZodOptional<z.ZodUnknown>;
349
407
  }, z.core.$strip>;
350
408
  }, z.core.$strip>]>;
351
409
  type CurrentTrackInput = z.infer<typeof currentTrackSchema>;
352
410
  type WsSubscribeInput = z.infer<typeof wsSubscribeSchema>;
353
411
  type StreamEnvelopeInput = z.infer<typeof streamEnvelopeSchema>;
354
412
 
355
- export { type CurrentTrackInput, type StreamEnvelopeInput, type WsSubscribeInput, apiErrorSchema, apiResponseSchema, apiSuccessSchema, currentTrackSchema, flightPlanSummarySchema, positionSchema, sourceHeartbeatSchema, streamEnvelopeSchema, velocitySchema, wsSubscribeSchema, wsUpdateFilterSchema };
413
+ export { type CurrentTrackInput, type StreamEnvelopeInput, type WsSubscribeInput, apiErrorSchema, apiMetaSchema, apiResponseSchema, apiSuccessSchema, currentTrackSchema, dataSourceSchema, flightPlanSummarySchema, positionSchema, sourceHeartbeatSchema, streamEnvelopeSchema, velocitySchema, wsSubscribeSchema, wsUpdateFilterSchema };
@@ -1,8 +1,10 @@
1
1
  import {
2
2
  apiErrorSchema,
3
+ apiMetaSchema,
3
4
  apiResponseSchema,
4
5
  apiSuccessSchema,
5
6
  currentTrackSchema,
7
+ dataSourceSchema,
6
8
  flightPlanSummarySchema,
7
9
  positionSchema,
8
10
  sourceHeartbeatSchema,
@@ -10,12 +12,14 @@ import {
10
12
  velocitySchema,
11
13
  wsSubscribeSchema,
12
14
  wsUpdateFilterSchema
13
- } from "../chunk-ZYX6U3ZK.js";
15
+ } from "../chunk-7SUMR3X2.js";
14
16
  export {
15
17
  apiErrorSchema,
18
+ apiMetaSchema,
16
19
  apiResponseSchema,
17
20
  apiSuccessSchema,
18
21
  currentTrackSchema,
22
+ dataSourceSchema,
19
23
  flightPlanSummarySchema,
20
24
  positionSchema,
21
25
  sourceHeartbeatSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aeroswarm/core",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -21,6 +21,10 @@
21
21
  "import": "./dist/flightplan/index.js",
22
22
  "types": "./dist/flightplan/index.d.ts"
23
23
  },
24
+ "./api": {
25
+ "import": "./dist/api/index.js",
26
+ "types": "./dist/api/index.d.ts"
27
+ },
24
28
  "./types": {
25
29
  "import": "./dist/types/index.js",
26
30
  "types": "./dist/types/index.d.ts"
@@ -34,8 +38,8 @@
34
38
  "registry": "https://registry.npmjs.org/"
35
39
  },
36
40
  "scripts": {
37
- "build": "tsup src/index.ts src/utils/index.ts src/validation/index.ts src/types/index.ts src/flightplan/index.ts --format esm --clean --dts",
38
- "dev": "tsup src/index.ts src/utils/index.ts src/validation/index.ts src/types/index.ts src/flightplan/index.ts --format esm --dts --watch",
41
+ "build": "tsup src/index.ts src/utils/index.ts src/validation/index.ts src/types/index.ts src/flightplan/index.ts src/api/index.ts --format esm --clean --dts",
42
+ "dev": "tsup src/index.ts src/utils/index.ts src/validation/index.ts src/types/index.ts src/flightplan/index.ts src/api/index.ts --format esm --dts --watch",
39
43
  "test": "vitest run --passWithNoTests",
40
44
  "typecheck": "tsc --noEmit",
41
45
  "clean": "rm -rf dist",