@aeroswarm/core 0.2.9 → 0.2.10

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.
@@ -112,7 +112,8 @@ var TOPICS = {
112
112
  HEALTH: "aero.source.health.v1",
113
113
  LIFECYCLE: "aero.track.lifecycle.v1",
114
114
  DEADLETTER: "aero.deadletter.v1",
115
- MOVEMENT: "aero.movement.v1"
115
+ MOVEMENT: "aero.movement.v1",
116
+ FLIGHT_PLAN: "aero.flightplan.v1"
116
117
  };
117
118
  var STALE_AFTER_MS = 15e3;
118
119
  var LOST_AFTER_MS = 9e4;
@@ -12,6 +12,21 @@ var velocitySchema = z.object({
12
12
  heading: z.number().min(-1).max(361).optional(),
13
13
  verticalRate: z.number().optional()
14
14
  });
15
+ var flightPlanSummarySchema = z.object({
16
+ id: z.string(),
17
+ adep: z.string().optional(),
18
+ ades: z.string().optional(),
19
+ aircraftType: z.string().optional(),
20
+ registration: z.string().optional(),
21
+ eobtAt: z.number().optional(),
22
+ atdAt: z.number().optional(),
23
+ ataAt: z.number().optional(),
24
+ etaAt: z.number().optional(),
25
+ cruiseLevel: z.string().optional(),
26
+ route: z.string().optional(),
27
+ status: z.enum(["filed", "delayed", "departed", "arrived", "cancelled"]),
28
+ phase: z.enum(["ARRIVAL", "DEPARTURE", "OVERFLIGHT", "UNKNOWN"])
29
+ });
15
30
  var currentTrackSchema = z.object({
16
31
  trackId: z.string(),
17
32
  source: z.enum(["ADSB", "ASTERIX_CAT010", "ASTERIX_CAT011", "ASTERIX_CAT020", "ASTERIX_CAT021", "ASTERIX_CAT048", "ASTERIX_CAT062", "FUSED"]),
@@ -29,7 +44,8 @@ var currentTrackSchema = z.object({
29
44
  verticalRateFpm: z.number().nullable(),
30
45
  confidence: z.number().min(0).max(1),
31
46
  lastSeenAt: z.number(),
32
- status: z.enum(["active", "stale", "lost"])
47
+ status: z.enum(["active", "stale", "lost"]),
48
+ flightPlan: flightPlanSummarySchema.optional()
33
49
  });
34
50
  var streamEnvelopeSchema = z.discriminatedUnion("type", [
35
51
  z.object({
@@ -117,6 +133,7 @@ var apiResponseSchema = (dataSchema) => z.union([apiSuccessSchema(dataSchema), a
117
133
  export {
118
134
  positionSchema,
119
135
  velocitySchema,
136
+ flightPlanSummarySchema,
120
137
  currentTrackSchema,
121
138
  streamEnvelopeSchema,
122
139
  sourceHeartbeatSchema,
package/dist/index.d.ts CHANGED
@@ -1,14 +1,32 @@
1
- import { SourceHealthEvent, FusedTrackEvent } from './types/index.js';
2
- export { AeroConnectionStatus, AeroRecoverableError, AssignedRoute, Bbox, ConfidenceBudget, CurrentTrack, Position, Protocol, RouteAssignment, SourceStatus, StreamEnvelope, TargetType, TrackSource, TrackStatus, Velocity } from './types/index.js';
1
+ import { FlightPlan, FlightPlanEvent, FlightPhase, AftnMessagePayload, FlightPlanSummary, SourceHealthEvent, FusedTrackEvent } from './types/index.js';
2
+ export { AeroConnectionStatus, AeroRecoverableError, AssignedRoute, Bbox, ConfidenceBudget, CurrentTrack, FlightPlanStatus, Position, Protocol, RouteAssignment, SourceStatus, StreamEnvelope, 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
- export { CurrentTrackInput, StreamEnvelopeInput, WsSubscribeInput, apiErrorSchema, apiResponseSchema, apiSuccessSchema, currentTrackSchema, positionSchema, sourceHeartbeatSchema, streamEnvelopeSchema, velocitySchema, wsSubscribeSchema, wsUpdateFilterSchema } from './validation/index.js';
5
+ export { CurrentTrackInput, StreamEnvelopeInput, WsSubscribeInput, apiErrorSchema, apiResponseSchema, apiSuccessSchema, currentTrackSchema, flightPlanSummarySchema, positionSchema, sourceHeartbeatSchema, streamEnvelopeSchema, velocitySchema, wsSubscribeSchema, wsUpdateFilterSchema } from './validation/index.js';
6
6
  import pino, { Logger } from 'pino';
7
7
  import { Registry, Counter, Gauge } from 'prom-client';
8
8
  import { Redis } from 'ioredis';
9
9
  import { Kafka, Producer, EachMessagePayload, GroupDescription } from 'kafkajs';
10
10
  import 'zod';
11
11
 
12
+ declare function normalizeCallsign(cs?: string | null): string | undefined;
13
+ /** Stable identity of one flight: callsign + route + day of flight. */
14
+ declare function flightPlanId(msg: AftnMessagePayload, receivedAt: number): string | null;
15
+ /** Pick the existing plan (candidates share the callsign) that a CHG/DLA/DEP/ARR/CNL
16
+ * refers to: same departure/destination when given, closest in time, within the window. */
17
+ declare function pickMatchingPlan(candidates: Iterable<FlightPlan>, msg: AftnMessagePayload, receivedAt: number): FlightPlan | undefined;
18
+ /**
19
+ * Fold one AFTN message into the flight's current state. Returns `null` when
20
+ * the message carries no aircraft identification.
21
+ *
22
+ * FPL (re)files the plan; CHG amends the changed items; DLA moves the EOBT;
23
+ * DEP/ARR record actual times; CNL cancels. Other types only bump counters.
24
+ */
25
+ declare function applyFlightPlanEvent(prev: FlightPlan | undefined, ev: FlightPlanEvent): FlightPlan | null;
26
+ /** Arrival/departure relative to an airport (ICAO). */
27
+ declare function flightPhase(plan: Pick<FlightPlan, "adep" | "ades">, airportId?: string): FlightPhase;
28
+ declare function summarizeFlightPlan(plan: FlightPlan, airportId?: string): FlightPlanSummary;
29
+
12
30
  declare const ENV_VARS: {
13
31
  readonly KAFKA_BROKERS: "KAFKA_BROKERS";
14
32
  readonly KAFKA_CLIENT_ID: "KAFKA_CLIENT_ID";
@@ -241,6 +259,12 @@ declare const TOPIC_REGISTRY: {
241
259
  readonly producer: "process-movement-detector";
242
260
  readonly consumers: readonly ["connector-service"];
243
261
  };
262
+ readonly "aero.flightplan.v1": {
263
+ readonly name: "aero.flightplan.v1";
264
+ readonly description: "Parsed AFTN/ATS messages (FPL, CHG, DLA, DEP, ARR, CNL) from AFTN feeds";
265
+ readonly producer: "simulator-service";
266
+ readonly consumers: readonly ["client-service"];
267
+ };
244
268
  };
245
269
  type TopicInfo = typeof TOPIC_REGISTRY[keyof typeof TOPIC_REGISTRY];
246
270
  declare function getTopicInfo(topic: string): TopicInfo | undefined;
@@ -250,4 +274,4 @@ declare function validateTopics(topics: string[]): {
250
274
  invalidTopics: string[];
251
275
  };
252
276
 
253
- export { type ConsumerConfig, type ConsumerControl, ENV_DEFAULTS, ENV_VARS, type EnvVarName, FusedTrackEvent, type HealthStatus, KAFKA_GROUPS, type KafkaGroupId, LIFECYCLE_STATES, type LifecycleState, PROTOCOL_TYPES, type ProtocolType, SERVICE_PORTS, type ServicePort, SourceHealthEvent, type SourceTokenInfo, TOPIC_REGISTRY, type TopicInfo, TopicName, buildHealthResponse, cacheSourceToken, checkKafkaHealth, checkRateLimit, createConsumer, createLogger, deleteTrack, disconnectProducer, disconnectRedis, ensureTopics, getConsumerGroupHealth, getDbSchema, getDbSearchPath, getEnv, getEnvNumber, getKafka, getProducer, getRedis, getSnapshot, getSourceHealth, getSystemConfig, getTopicInfo, getTrack, getWsClientCount, isConsumerGroupHealthy, isValidTopic, logger, partitionKeys, publishEvent, registerWsClient, registry, revokeSourceToken, runHealthCheck, setSnapshot, setSourceHealth, setSystemConfig, setTrack, trackUpdateRate, unregisterWsClient, validateSourceToken, validateTopics, wsClients };
277
+ export { AftnMessagePayload, type ConsumerConfig, type ConsumerControl, ENV_DEFAULTS, ENV_VARS, type EnvVarName, FlightPhase, FlightPlan, FlightPlanEvent, FlightPlanSummary, FusedTrackEvent, type HealthStatus, KAFKA_GROUPS, type KafkaGroupId, LIFECYCLE_STATES, type LifecycleState, PROTOCOL_TYPES, type ProtocolType, SERVICE_PORTS, type ServicePort, SourceHealthEvent, type SourceTokenInfo, TOPIC_REGISTRY, type TopicInfo, TopicName, applyFlightPlanEvent, buildHealthResponse, cacheSourceToken, checkKafkaHealth, checkRateLimit, createConsumer, createLogger, deleteTrack, disconnectProducer, disconnectRedis, ensureTopics, flightPhase, flightPlanId, getConsumerGroupHealth, getDbSchema, getDbSearchPath, getEnv, getEnvNumber, getKafka, getProducer, getRedis, getSnapshot, getSourceHealth, getSystemConfig, getTopicInfo, getTrack, getWsClientCount, isConsumerGroupHealthy, isValidTopic, logger, normalizeCallsign, partitionKeys, pickMatchingPlan, publishEvent, registerWsClient, registry, revokeSourceToken, runHealthCheck, setSnapshot, setSourceHealth, setSystemConfig, setTrack, summarizeFlightPlan, trackUpdateRate, unregisterWsClient, validateSourceToken, validateTopics, wsClients };
package/dist/index.js CHANGED
@@ -1,4 +1,17 @@
1
1
  import "./chunk-FXPGR372.js";
2
+ import {
3
+ apiErrorSchema,
4
+ apiResponseSchema,
5
+ apiSuccessSchema,
6
+ currentTrackSchema,
7
+ flightPlanSummarySchema,
8
+ positionSchema,
9
+ sourceHeartbeatSchema,
10
+ streamEnvelopeSchema,
11
+ velocitySchema,
12
+ wsSubscribeSchema,
13
+ wsUpdateFilterSchema
14
+ } from "./chunk-ZYX6U3ZK.js";
2
15
  import {
3
16
  EMERGENCY_SQUAWKS,
4
17
  LOST_AFTER_MS,
@@ -16,19 +29,144 @@ import {
16
29
  isInsideBbox,
17
30
  isRenderableTrack,
18
31
  toCurrentTrack
19
- } from "./chunk-ZBO7NUV3.js";
20
- import {
21
- apiErrorSchema,
22
- apiResponseSchema,
23
- apiSuccessSchema,
24
- currentTrackSchema,
25
- positionSchema,
26
- sourceHeartbeatSchema,
27
- streamEnvelopeSchema,
28
- velocitySchema,
29
- wsSubscribeSchema,
30
- wsUpdateFilterSchema
31
- } from "./chunk-TAFKYKUB.js";
32
+ } from "./chunk-J2UTSYKD.js";
33
+
34
+ // src/flightplan/index.ts
35
+ var FLIGHT_PLAN_MATCH_WINDOW_MS = 36 * 36e5;
36
+ function normalizeCallsign(cs) {
37
+ const v = cs?.trim().toUpperCase().replace(/\s+/g, "");
38
+ return v || void 0;
39
+ }
40
+ function dayKey(msg, receivedAt) {
41
+ if (msg.dof && /^\d{6}$/.test(msg.dof)) return `20${msg.dof}`;
42
+ const t = msg.eobtAt ?? msg.atdAt ?? msg.ataAt ?? receivedAt;
43
+ return new Date(t).toISOString().slice(0, 10).replace(/-/g, "");
44
+ }
45
+ function flightPlanId(msg, receivedAt) {
46
+ const callsign = normalizeCallsign(msg.callsign);
47
+ if (!callsign) return null;
48
+ return `${callsign}|${msg.adep ?? "-"}|${msg.ades ?? "-"}|${dayKey(msg, receivedAt)}`;
49
+ }
50
+ function pickMatchingPlan(candidates, msg, receivedAt) {
51
+ const ref = msg.eobtAt ?? msg.atdAt ?? msg.ataAt ?? receivedAt;
52
+ let best;
53
+ let bestDiff = Infinity;
54
+ for (const c of candidates) {
55
+ if (msg.adep && c.adep && msg.adep !== c.adep) continue;
56
+ if (msg.ades && c.ades && msg.ades !== c.ades) continue;
57
+ const planTime = c.atdAt ?? c.eobtAt ?? c.firstSeenAt;
58
+ const diff = Math.abs(planTime - ref);
59
+ if (diff <= FLIGHT_PLAN_MATCH_WINDOW_MS && diff < bestDiff) {
60
+ best = c;
61
+ bestDiff = diff;
62
+ }
63
+ }
64
+ return best;
65
+ }
66
+ function assignDefined(target, patch) {
67
+ for (const [k, v] of Object.entries(patch)) {
68
+ if (v !== void 0 && v !== null && v !== "") target[k] = v;
69
+ }
70
+ }
71
+ function eetMs(eet) {
72
+ if (!eet || !/^\d{4}$/.test(eet)) return void 0;
73
+ return (Number(eet.slice(0, 2)) * 60 + Number(eet.slice(2, 4))) * 6e4;
74
+ }
75
+ function applyFlightPlanEvent(prev, ev) {
76
+ const m = ev.message;
77
+ const callsign = normalizeCallsign(m.callsign);
78
+ if (!callsign) return null;
79
+ const id = prev?.id ?? flightPlanId(m, ev.receivedAt);
80
+ if (!id) return null;
81
+ const next = {
82
+ status: "filed",
83
+ airportId: ev.airportId,
84
+ firstSeenAt: ev.receivedAt,
85
+ ...prev,
86
+ id,
87
+ callsign,
88
+ other: { ...prev?.other ?? {} },
89
+ lastMessageType: m.type,
90
+ messageCount: (prev?.messageCount ?? 0) + 1,
91
+ updatedAt: ev.receivedAt
92
+ };
93
+ assignDefined(next, { icao24: m.icao24, registration: m.registration, dof: m.dof });
94
+ Object.assign(next.other, m.other);
95
+ if (!next.adep && m.adep) next.adep = m.adep;
96
+ if (!next.ades && m.ades) next.ades = m.ades;
97
+ switch (m.type) {
98
+ case "FPL":
99
+ assignDefined(next, {
100
+ aircraftType: m.aircraftType,
101
+ wake: m.wake,
102
+ flightRules: m.flightRules,
103
+ flightType: m.flightType,
104
+ adep: m.adep,
105
+ ades: m.ades,
106
+ alternates: m.alternates,
107
+ eobtAt: m.eobtAt,
108
+ eet: m.eet,
109
+ cruiseSpeed: m.cruiseSpeed,
110
+ cruiseLevel: m.cruiseLevel,
111
+ route: m.route,
112
+ equipment: m.equipment
113
+ });
114
+ if (prev?.status !== "departed" && prev?.status !== "arrived") next.status = "filed";
115
+ break;
116
+ case "CHG":
117
+ assignDefined(next, {
118
+ aircraftType: m.aircraftType,
119
+ wake: m.wake,
120
+ cruiseSpeed: m.cruiseSpeed,
121
+ cruiseLevel: m.cruiseLevel,
122
+ route: m.route
123
+ });
124
+ if (m.changes?.["13"]) assignDefined(next, { adep: m.adep, eobtAt: m.eobtAt });
125
+ if (m.changes?.["16"]) assignDefined(next, { ades: m.ades, eet: m.eet });
126
+ break;
127
+ case "DLA":
128
+ assignDefined(next, { eobtAt: m.eobtAt });
129
+ if (next.status === "filed" || next.status === "delayed") next.status = "delayed";
130
+ break;
131
+ case "DEP":
132
+ next.atdAt = m.atdAt ?? ev.receivedAt;
133
+ next.status = "departed";
134
+ break;
135
+ case "ARR":
136
+ next.ataAt = m.ataAt ?? ev.receivedAt;
137
+ next.status = "arrived";
138
+ break;
139
+ case "CNL":
140
+ next.status = "cancelled";
141
+ break;
142
+ }
143
+ const departure = next.atdAt ?? next.eobtAt;
144
+ const flightTime = eetMs(next.eet);
145
+ next.etaAt = next.ataAt ?? (departure !== void 0 && flightTime !== void 0 ? departure + flightTime : void 0);
146
+ return next;
147
+ }
148
+ function flightPhase(plan, airportId) {
149
+ const icao = airportId?.trim().toUpperCase();
150
+ if (icao && plan.ades === icao) return "ARRIVAL";
151
+ if (icao && plan.adep === icao) return "DEPARTURE";
152
+ return plan.adep || plan.ades ? "OVERFLIGHT" : "UNKNOWN";
153
+ }
154
+ function summarizeFlightPlan(plan, airportId) {
155
+ const summary = { id: plan.id, status: plan.status, phase: flightPhase(plan, airportId) };
156
+ assignDefined(summary, {
157
+ adep: plan.adep,
158
+ ades: plan.ades,
159
+ aircraftType: plan.aircraftType,
160
+ registration: plan.registration,
161
+ eobtAt: plan.eobtAt,
162
+ atdAt: plan.atdAt,
163
+ ataAt: plan.ataAt,
164
+ etaAt: plan.etaAt,
165
+ cruiseLevel: plan.cruiseLevel,
166
+ route: plan.route
167
+ });
168
+ return summary;
169
+ }
32
170
 
33
171
  // src/config/index.ts
34
172
  import { config } from "dotenv";
@@ -332,6 +470,12 @@ var TOPIC_REGISTRY = {
332
470
  description: "Takeoff/landing transitions detected from fused track altitude/speed",
333
471
  producer: "process-movement-detector",
334
472
  consumers: ["connector-service"]
473
+ },
474
+ [TOPICS.FLIGHT_PLAN]: {
475
+ name: TOPICS.FLIGHT_PLAN,
476
+ description: "Parsed AFTN/ATS messages (FPL, CHG, DLA, DEP, ARR, CNL) from AFTN feeds",
477
+ producer: "simulator-service",
478
+ consumers: ["client-service"]
335
479
  }
336
480
  };
337
481
  function getTopicInfo(topic) {
@@ -522,6 +666,7 @@ export {
522
666
  apiErrorSchema,
523
667
  apiResponseSchema,
524
668
  apiSuccessSchema,
669
+ applyFlightPlanEvent,
525
670
  buildHealthResponse,
526
671
  cacheSourceToken,
527
672
  checkKafkaHealth,
@@ -540,6 +685,9 @@ export {
540
685
  disconnectRedis,
541
686
  distanceToPolylineM,
542
687
  ensureTopics,
688
+ flightPhase,
689
+ flightPlanId,
690
+ flightPlanSummarySchema,
543
691
  getConsumerGroupHealth,
544
692
  getDbSchema,
545
693
  getDbSearchPath,
@@ -560,7 +708,9 @@ export {
560
708
  isRenderableTrack,
561
709
  isValidTopic,
562
710
  logger,
711
+ normalizeCallsign,
563
712
  partitionKeys,
713
+ pickMatchingPlan,
564
714
  positionSchema,
565
715
  publishEvent,
566
716
  registerWsClient,
@@ -573,6 +723,7 @@ export {
573
723
  setTrack,
574
724
  sourceHeartbeatSchema,
575
725
  streamEnvelopeSchema,
726
+ summarizeFlightPlan,
576
727
  toCurrentTrack,
577
728
  trackUpdateRate,
578
729
  unregisterWsClient,
@@ -74,6 +74,104 @@ interface RouteAssignment {
74
74
  }
75
75
  type TrackStatus = "active" | "stale" | "lost";
76
76
  type TrackSource = "ADSB" | "ASTERIX_CAT010" | "ASTERIX_CAT011" | "ASTERIX_CAT020" | "ASTERIX_CAT021" | "ASTERIX_CAT048" | "ASTERIX_CAT062" | "FUSED";
77
+ type FlightPlanStatus = "filed" | "delayed" | "departed" | "arrived" | "cancelled";
78
+ type FlightPhase = "ARRIVAL" | "DEPARTURE" | "OVERFLIGHT" | "UNKNOWN";
79
+ /** One parsed AFTN/ATS message — mirrors `AftnMessage` from @aeroswarm/codec
80
+ * (kept as a plain structural type so core stays free of a codec dependency). */
81
+ interface AftnMessagePayload {
82
+ type: string;
83
+ header: {
84
+ priority?: string;
85
+ addressees: string[];
86
+ originTime?: string;
87
+ originator?: string;
88
+ };
89
+ text: string;
90
+ callsign?: string;
91
+ flightRules?: string;
92
+ flightType?: string;
93
+ aircraftType?: string;
94
+ wake?: string;
95
+ equipment?: string;
96
+ adep?: string;
97
+ ades?: string;
98
+ eobt?: string;
99
+ atd?: string;
100
+ ata?: string;
101
+ eet?: string;
102
+ cruiseSpeed?: string;
103
+ cruiseLevel?: string;
104
+ route?: string;
105
+ alternates?: string[];
106
+ other: Record<string, string>;
107
+ registration?: string;
108
+ icao24?: string;
109
+ dof?: string;
110
+ changes?: Record<string, string>;
111
+ eobtAt?: number;
112
+ atdAt?: number;
113
+ ataAt?: number;
114
+ }
115
+ /** Published by an AFTN feed on TOPICS.FLIGHT_PLAN. */
116
+ interface FlightPlanEvent {
117
+ messageId: string;
118
+ sourceId: string;
119
+ feedId?: string;
120
+ /** Airport the feed is attached to (same convention as tracks) */
121
+ airportId?: string;
122
+ receivedAt: number;
123
+ message: AftnMessagePayload;
124
+ }
125
+ /** Current state of one flight, folded from FPL/CHG/DLA/DEP/ARR/CNL messages. */
126
+ interface FlightPlan {
127
+ id: string;
128
+ callsign: string;
129
+ icao24?: string;
130
+ registration?: string;
131
+ aircraftType?: string;
132
+ wake?: string;
133
+ flightRules?: string;
134
+ flightType?: string;
135
+ adep?: string;
136
+ ades?: string;
137
+ alternates?: string[];
138
+ eobtAt?: number;
139
+ atdAt?: number;
140
+ ataAt?: number;
141
+ /** Estimated elapsed time HHMM from item 16 */
142
+ eet?: string;
143
+ /** Estimated arrival: (actual or estimated departure) + EET */
144
+ etaAt?: number;
145
+ cruiseSpeed?: string;
146
+ cruiseLevel?: string;
147
+ route?: string;
148
+ equipment?: string;
149
+ dof?: string;
150
+ status: FlightPlanStatus;
151
+ airportId?: string;
152
+ other: Record<string, string>;
153
+ lastMessageType: string;
154
+ messageCount: number;
155
+ firstSeenAt: number;
156
+ updatedAt: number;
157
+ }
158
+ /** The subset attached to a live track for rendering. */
159
+ interface FlightPlanSummary {
160
+ id: string;
161
+ adep?: string;
162
+ ades?: string;
163
+ aircraftType?: string;
164
+ registration?: string;
165
+ eobtAt?: number;
166
+ atdAt?: number;
167
+ ataAt?: number;
168
+ etaAt?: number;
169
+ cruiseLevel?: string;
170
+ route?: string;
171
+ status: FlightPlanStatus;
172
+ /** Relative to the track's airport (ARRIVAL = ades matches, DEPARTURE = adep matches) */
173
+ phase: FlightPhase;
174
+ }
77
175
  interface CurrentTrack {
78
176
  trackId: string;
79
177
  source: TrackSource;
@@ -95,6 +193,8 @@ interface CurrentTrack {
95
193
  confidence: number;
96
194
  lastSeenAt: number;
97
195
  status: TrackStatus;
196
+ /** Flight-plan data correlated from AFTN (by Mode-S address, else callsign); absent when none matched */
197
+ flightPlan?: FlightPlanSummary;
98
198
  }
99
199
  type StreamEnvelope = {
100
200
  type: "snapshot";
@@ -157,4 +257,4 @@ interface AeroRecoverableError {
157
257
  }
158
258
  type SourceStatus = SourceHealthEvent["status"];
159
259
 
160
- export type { AeroConnectionStatus, AeroRecoverableError, AssignedRoute, Bbox, ConfidenceBudget, CurrentTrack, FusedTrackEvent, Position, Protocol, RouteAssignment, SourceHealthEvent, SourceStatus, StreamEnvelope, TargetType, TrackSource, TrackStatus, Velocity };
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 };
@@ -36,6 +36,7 @@ declare const TOPICS: {
36
36
  readonly LIFECYCLE: "aero.track.lifecycle.v1";
37
37
  readonly DEADLETTER: "aero.deadletter.v1";
38
38
  readonly MOVEMENT: "aero.movement.v1";
39
+ readonly FLIGHT_PLAN: "aero.flightplan.v1";
39
40
  };
40
41
  type TopicName = (typeof TOPICS)[keyof typeof TOPICS];
41
42
  declare const STALE_AFTER_MS = 15000;
@@ -15,7 +15,7 @@ import {
15
15
  isInsideBbox,
16
16
  isRenderableTrack,
17
17
  toCurrentTrack
18
- } from "../chunk-ZBO7NUV3.js";
18
+ } from "../chunk-J2UTSYKD.js";
19
19
  export {
20
20
  EMERGENCY_SQUAWKS,
21
21
  LOST_AFTER_MS,
@@ -16,6 +16,32 @@ declare const velocitySchema: z.ZodObject<{
16
16
  heading: z.ZodOptional<z.ZodNumber>;
17
17
  verticalRate: z.ZodOptional<z.ZodNumber>;
18
18
  }, z.core.$strip>;
19
+ declare const flightPlanSummarySchema: z.ZodObject<{
20
+ id: z.ZodString;
21
+ adep: z.ZodOptional<z.ZodString>;
22
+ ades: z.ZodOptional<z.ZodString>;
23
+ aircraftType: z.ZodOptional<z.ZodString>;
24
+ registration: z.ZodOptional<z.ZodString>;
25
+ eobtAt: z.ZodOptional<z.ZodNumber>;
26
+ atdAt: z.ZodOptional<z.ZodNumber>;
27
+ ataAt: z.ZodOptional<z.ZodNumber>;
28
+ etaAt: z.ZodOptional<z.ZodNumber>;
29
+ cruiseLevel: z.ZodOptional<z.ZodString>;
30
+ route: z.ZodOptional<z.ZodString>;
31
+ status: z.ZodEnum<{
32
+ filed: "filed";
33
+ delayed: "delayed";
34
+ departed: "departed";
35
+ arrived: "arrived";
36
+ cancelled: "cancelled";
37
+ }>;
38
+ phase: z.ZodEnum<{
39
+ ARRIVAL: "ARRIVAL";
40
+ DEPARTURE: "DEPARTURE";
41
+ OVERFLIGHT: "OVERFLIGHT";
42
+ UNKNOWN: "UNKNOWN";
43
+ }>;
44
+ }, z.core.$strip>;
19
45
  declare const currentTrackSchema: z.ZodObject<{
20
46
  trackId: z.ZodString;
21
47
  source: z.ZodEnum<{
@@ -51,6 +77,32 @@ declare const currentTrackSchema: z.ZodObject<{
51
77
  stale: "stale";
52
78
  lost: "lost";
53
79
  }>;
80
+ flightPlan: z.ZodOptional<z.ZodObject<{
81
+ id: z.ZodString;
82
+ adep: z.ZodOptional<z.ZodString>;
83
+ ades: z.ZodOptional<z.ZodString>;
84
+ aircraftType: z.ZodOptional<z.ZodString>;
85
+ registration: z.ZodOptional<z.ZodString>;
86
+ eobtAt: z.ZodOptional<z.ZodNumber>;
87
+ atdAt: z.ZodOptional<z.ZodNumber>;
88
+ ataAt: z.ZodOptional<z.ZodNumber>;
89
+ etaAt: z.ZodOptional<z.ZodNumber>;
90
+ cruiseLevel: z.ZodOptional<z.ZodString>;
91
+ route: z.ZodOptional<z.ZodString>;
92
+ status: z.ZodEnum<{
93
+ filed: "filed";
94
+ delayed: "delayed";
95
+ departed: "departed";
96
+ arrived: "arrived";
97
+ cancelled: "cancelled";
98
+ }>;
99
+ phase: z.ZodEnum<{
100
+ ARRIVAL: "ARRIVAL";
101
+ DEPARTURE: "DEPARTURE";
102
+ OVERFLIGHT: "OVERFLIGHT";
103
+ UNKNOWN: "UNKNOWN";
104
+ }>;
105
+ }, z.core.$strip>>;
54
106
  }, z.core.$strip>;
55
107
  declare const streamEnvelopeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
56
108
  type: z.ZodLiteral<"snapshot">;
@@ -92,6 +144,32 @@ declare const streamEnvelopeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
92
144
  stale: "stale";
93
145
  lost: "lost";
94
146
  }>;
147
+ flightPlan: z.ZodOptional<z.ZodObject<{
148
+ id: z.ZodString;
149
+ adep: z.ZodOptional<z.ZodString>;
150
+ ades: z.ZodOptional<z.ZodString>;
151
+ aircraftType: z.ZodOptional<z.ZodString>;
152
+ registration: z.ZodOptional<z.ZodString>;
153
+ eobtAt: z.ZodOptional<z.ZodNumber>;
154
+ atdAt: z.ZodOptional<z.ZodNumber>;
155
+ ataAt: z.ZodOptional<z.ZodNumber>;
156
+ etaAt: z.ZodOptional<z.ZodNumber>;
157
+ cruiseLevel: z.ZodOptional<z.ZodString>;
158
+ route: z.ZodOptional<z.ZodString>;
159
+ status: z.ZodEnum<{
160
+ filed: "filed";
161
+ delayed: "delayed";
162
+ departed: "departed";
163
+ arrived: "arrived";
164
+ cancelled: "cancelled";
165
+ }>;
166
+ phase: z.ZodEnum<{
167
+ ARRIVAL: "ARRIVAL";
168
+ DEPARTURE: "DEPARTURE";
169
+ OVERFLIGHT: "OVERFLIGHT";
170
+ UNKNOWN: "UNKNOWN";
171
+ }>;
172
+ }, z.core.$strip>>;
95
173
  }, z.core.$strip>>;
96
174
  }, z.core.$strip>;
97
175
  }, z.core.$strip>, z.ZodObject<{
@@ -134,6 +212,32 @@ declare const streamEnvelopeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
134
212
  stale: "stale";
135
213
  lost: "lost";
136
214
  }>;
215
+ flightPlan: z.ZodOptional<z.ZodObject<{
216
+ id: z.ZodString;
217
+ adep: z.ZodOptional<z.ZodString>;
218
+ ades: z.ZodOptional<z.ZodString>;
219
+ aircraftType: z.ZodOptional<z.ZodString>;
220
+ registration: z.ZodOptional<z.ZodString>;
221
+ eobtAt: z.ZodOptional<z.ZodNumber>;
222
+ atdAt: z.ZodOptional<z.ZodNumber>;
223
+ ataAt: z.ZodOptional<z.ZodNumber>;
224
+ etaAt: z.ZodOptional<z.ZodNumber>;
225
+ cruiseLevel: z.ZodOptional<z.ZodString>;
226
+ route: z.ZodOptional<z.ZodString>;
227
+ status: z.ZodEnum<{
228
+ filed: "filed";
229
+ delayed: "delayed";
230
+ departed: "departed";
231
+ arrived: "arrived";
232
+ cancelled: "cancelled";
233
+ }>;
234
+ phase: z.ZodEnum<{
235
+ ARRIVAL: "ARRIVAL";
236
+ DEPARTURE: "DEPARTURE";
237
+ OVERFLIGHT: "OVERFLIGHT";
238
+ UNKNOWN: "UNKNOWN";
239
+ }>;
240
+ }, z.core.$strip>>;
137
241
  }, z.core.$strip>;
138
242
  }, z.core.$strip>;
139
243
  }, z.core.$strip>, z.ZodObject<{
@@ -248,4 +352,4 @@ type CurrentTrackInput = z.infer<typeof currentTrackSchema>;
248
352
  type WsSubscribeInput = z.infer<typeof wsSubscribeSchema>;
249
353
  type StreamEnvelopeInput = z.infer<typeof streamEnvelopeSchema>;
250
354
 
251
- export { type CurrentTrackInput, type StreamEnvelopeInput, type WsSubscribeInput, apiErrorSchema, apiResponseSchema, apiSuccessSchema, currentTrackSchema, positionSchema, sourceHeartbeatSchema, streamEnvelopeSchema, velocitySchema, wsSubscribeSchema, wsUpdateFilterSchema };
355
+ export { type CurrentTrackInput, type StreamEnvelopeInput, type WsSubscribeInput, apiErrorSchema, apiResponseSchema, apiSuccessSchema, currentTrackSchema, flightPlanSummarySchema, positionSchema, sourceHeartbeatSchema, streamEnvelopeSchema, velocitySchema, wsSubscribeSchema, wsUpdateFilterSchema };
@@ -3,18 +3,20 @@ import {
3
3
  apiResponseSchema,
4
4
  apiSuccessSchema,
5
5
  currentTrackSchema,
6
+ flightPlanSummarySchema,
6
7
  positionSchema,
7
8
  sourceHeartbeatSchema,
8
9
  streamEnvelopeSchema,
9
10
  velocitySchema,
10
11
  wsSubscribeSchema,
11
12
  wsUpdateFilterSchema
12
- } from "../chunk-TAFKYKUB.js";
13
+ } from "../chunk-ZYX6U3ZK.js";
13
14
  export {
14
15
  apiErrorSchema,
15
16
  apiResponseSchema,
16
17
  apiSuccessSchema,
17
18
  currentTrackSchema,
19
+ flightPlanSummarySchema,
18
20
  positionSchema,
19
21
  sourceHeartbeatSchema,
20
22
  streamEnvelopeSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aeroswarm/core",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",