@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.
- package/dist/{chunk-ZBO7NUV3.js → chunk-J2UTSYKD.js} +2 -1
- package/dist/{chunk-TAFKYKUB.js → chunk-ZYX6U3ZK.js} +18 -1
- package/dist/index.d.ts +28 -4
- package/dist/index.js +164 -13
- package/dist/types/index.d.ts +101 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -1
- package/dist/validation/index.d.ts +105 -1
- package/dist/validation/index.js +3 -1
- package/package.json +1 -1
|
@@ -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-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
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,
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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 };
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -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;
|
package/dist/utils/index.js
CHANGED
|
@@ -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 };
|
package/dist/validation/index.js
CHANGED
|
@@ -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-
|
|
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,
|