@airframes/acars-decoder 1.8.13 → 1.9.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/License.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Airframes contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,17 +1,7 @@
1
- # Node.js Support Policy
2
-
3
- - Runtime support: Node.js >= 18
4
- - Development and CI: validated on Node 18.x, 20.x, 22.x, and 24.x
5
- - TypeScript development uses the latest stable Node types (currently v24) without forcing consumers to use a specific Node types version, since `@types/node` is a devDependency.
6
- - The published builds are compiled targeting Node 18 runtime via `tsup` so they remain compatible across supported Node versions.
7
-
8
- # @airframes/acars-decoder
9
-
10
- This is a no-op documentation tweak to verify repository access, build/lint, tests, and PR workflow. No functional code changes are included.
11
-
12
1
  # acars-decoder-typescript
13
2
 
14
3
  [![NPM Version](https://badge.fury.io/js/@airframes%2Facars-decoder.svg)](https://badge.fury.io/js/@airframes%2Facars-decoder)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./License.md)
15
5
  [![GitHub Actions Workflow Status](https://github.com/airframesio/acars-decoder-typescript/actions/workflows/yarn-test.yml/badge.svg)
16
6
  ](https://github.com/airframesio/acars-decoder-typescript/actions/workflows/yarn-test.yml)
17
7
  ![CodeRabbit Pull Request Reviews](https://img.shields.io/coderabbit/prs/github/airframesio/acars-decoder-typescript?utm_source=oss&utm_medium=github&utm_campaign=airframesio%2Facars-decoder-typescript&labelColor=171717&color=FF570A&link=https%3A%2F%2Fcoderabbit.ai&label=CodeRabbit+Reviews)
@@ -27,6 +17,13 @@ It has been written in TypeScript (which compiles to Javascript) and is publishe
27
17
 
28
18
  You are welcome to contribute (please see https://github.com/airframesio/acars-message-documentation where we collaborate to research and document the various types of messages), and while it was primarily developed to power [Airframes](https://app.airframes.io) and [AcarsHub](https://sdr-e.com/docker-acarshub), you may use this library in your own applications freely.
29
19
 
20
+ # Node.js Support Policy
21
+
22
+ - Runtime support: Node.js >= 18
23
+ - Development and CI: validated on Node 18.x, 20.x, 22.x, and 24.x
24
+ - TypeScript development uses the latest stable Node types (currently v24) without forcing consumers to use a specific Node types version, since `@types/node` is a devDependency.
25
+ - The published builds are compiled targeting Node 18 runtime via `tsup` so they remain compatible across supported Node versions.
26
+
30
27
  # Installation
31
28
 
32
29
  Add the `@airframes/acars-decoder` library to your JavaScript or TypeScript project.
package/dist/index.d.mts CHANGED
@@ -6,6 +6,70 @@ declare class IcaoDecoder {
6
6
  isMilitary(): boolean;
7
7
  }
8
8
 
9
+ /**
10
+ * Represenation of a waypoint.
11
+ *
12
+ * Usually used in Routes which is an array of waypoints.
13
+ * Airways/Jetways can also be represented as a waypoint, by just the name.
14
+ * There is no distinction between the two currently because there is no difference from the current messages
15
+ * Distinction must be determined from tne name.
16
+ * In the event that a waypoint is a GPS position, the name can be the raw position string (N12345W012345)
17
+ */
18
+ interface Waypoint {
19
+ /** unique identifier of the waypoint*/
20
+ name: string;
21
+ /**
22
+ * latitude in decimal degrees
23
+ *
24
+ * if set, longitude must be provided
25
+ */
26
+ latitude?: number;
27
+ /** longitude in decimal degrees
28
+ *
29
+ * if set, latitude must be provided
30
+ */
31
+ longitude?: number;
32
+ /**
33
+ * time of arrival. If in future, it is an ETA.
34
+ */
35
+ time?: number;
36
+ /**
37
+ * offset from the actual waypoint
38
+ *
39
+ * bearing: degrees from the waypoint
40
+ * distance: distance in nautical miles
41
+ */
42
+ offset?: {
43
+ bearing: number;
44
+ distance: number;
45
+ };
46
+ }
47
+
48
+ /**
49
+ * Representation of a route
50
+ *
51
+ * Typically a list of waypoints, this can also be a named company route.
52
+ */
53
+ interface Route {
54
+ /** optional name. If not set, `waypoints` is required */
55
+ name?: string;
56
+ /** optional runway */
57
+ runway?: string;
58
+ /** optional list of waypoints. If not set, `name` is required */
59
+ waypoints?: Waypoint[];
60
+ }
61
+
62
+ interface Wind {
63
+ waypoint: Waypoint;
64
+ flightLevel: number;
65
+ windDirection: number;
66
+ windSpeed: number;
67
+ temperature?: {
68
+ flightLevel: number;
69
+ degreesC: number;
70
+ };
71
+ }
72
+
9
73
  /**
10
74
  * Representation of a Message
11
75
  */
@@ -20,6 +84,87 @@ interface Message {
20
84
  interface Options {
21
85
  debug?: boolean;
22
86
  }
87
+ /**
88
+ * Known fields that can appear on DecodeResult.raw.
89
+ * The index signature allows plugin-specific fields without losing type safety
90
+ * on the well-known ones.
91
+ */
92
+ interface RawFields {
93
+ position?: {
94
+ latitude: number;
95
+ longitude: number;
96
+ };
97
+ altitude?: number;
98
+ heading?: number;
99
+ groundspeed?: number;
100
+ airspeed?: number;
101
+ mach?: number;
102
+ flight_number?: string;
103
+ callsign?: string;
104
+ tail?: string;
105
+ departure_icao?: string;
106
+ departure_iata?: string;
107
+ arrival_icao?: string;
108
+ arrival_iata?: string;
109
+ alternate_icao?: string;
110
+ departure_runway?: string;
111
+ arrival_runway?: string;
112
+ alternate_runway?: string;
113
+ message_timestamp?: number;
114
+ eta_time?: number;
115
+ out_time?: number;
116
+ off_time?: number;
117
+ on_time?: number;
118
+ in_time?: number;
119
+ engine_start_time?: number;
120
+ engine_stop_time?: number;
121
+ day?: number | string;
122
+ month?: number;
123
+ departure_day?: number;
124
+ arrival_day?: number;
125
+ fuel_on_board?: number;
126
+ fuel_burned?: number;
127
+ fuel_remaining?: number;
128
+ fuel_in_tons?: number;
129
+ out_fuel?: number;
130
+ off_fuel?: number;
131
+ on_fuel?: number;
132
+ in_fuel?: number;
133
+ start_fuel?: number;
134
+ outside_air_temperature?: number;
135
+ total_air_temperature?: number;
136
+ center_of_gravity?: number;
137
+ cg_lower_limit?: number;
138
+ cg_upper_limit?: number;
139
+ mac?: number;
140
+ trim?: number;
141
+ route?: Route;
142
+ wind_data?: Wind[];
143
+ requested_alts?: number[];
144
+ desired_alt?: number;
145
+ start_point?: string;
146
+ route_number?: string;
147
+ flight_plan?: string;
148
+ label?: string;
149
+ sublabel?: string;
150
+ preamble?: string;
151
+ version?: number;
152
+ checksum_algorithm?: string;
153
+ checksum?: number;
154
+ sequence_number?: number;
155
+ sequence_response?: number;
156
+ ground_address?: string;
157
+ text?: string;
158
+ state_change?: {
159
+ from: string;
160
+ to: string;
161
+ };
162
+ door_event?: {
163
+ door: string;
164
+ state: string;
165
+ };
166
+ [key: string]: unknown;
167
+ }
23
168
  /**
24
169
  * Results from decoding a message
25
170
  */
@@ -41,7 +186,7 @@ interface DecodeResult {
41
186
  }[];
42
187
  };
43
188
  message?: Message;
44
- raw: any;
189
+ raw: RawFields;
45
190
  remaining: {
46
191
  text?: string;
47
192
  };
@@ -51,7 +196,7 @@ interface Qualifiers {
51
196
  preambles?: string[];
52
197
  }
53
198
  interface DecoderPluginInterface {
54
- decode(message: Message): DecodeResult;
199
+ decode(message: Message, options?: Options): DecodeResult;
55
200
  meetsStateRequirements(): boolean;
56
201
  qualifiers(): Qualifiers;
57
202
  }
@@ -60,9 +205,16 @@ declare class MessageDecoder {
60
205
  name: string;
61
206
  plugins: Array<DecoderPluginInterface>;
62
207
  debug: boolean;
208
+ /** Maps a label string to the candidate entries (wildcard + label-specific) in registration order. */
209
+ private candidatesByLabel;
210
+ /** Wildcard entries (plugins that register the '*' label). */
211
+ private wildcardEntries;
212
+ /** Membership set for wildcard entries to dedupe when a plugin also registers a specific label. */
213
+ private wildcardSet;
63
214
  constructor();
64
215
  registerPlugin(plugin: DecoderPluginInterface): boolean;
65
216
  decode(message: Message, options?: Options): DecodeResult;
217
+ private matchesPreambles;
66
218
  }
67
219
 
68
220
  export { IcaoDecoder, MessageDecoder };
package/dist/index.d.ts CHANGED
@@ -6,6 +6,70 @@ declare class IcaoDecoder {
6
6
  isMilitary(): boolean;
7
7
  }
8
8
 
9
+ /**
10
+ * Represenation of a waypoint.
11
+ *
12
+ * Usually used in Routes which is an array of waypoints.
13
+ * Airways/Jetways can also be represented as a waypoint, by just the name.
14
+ * There is no distinction between the two currently because there is no difference from the current messages
15
+ * Distinction must be determined from tne name.
16
+ * In the event that a waypoint is a GPS position, the name can be the raw position string (N12345W012345)
17
+ */
18
+ interface Waypoint {
19
+ /** unique identifier of the waypoint*/
20
+ name: string;
21
+ /**
22
+ * latitude in decimal degrees
23
+ *
24
+ * if set, longitude must be provided
25
+ */
26
+ latitude?: number;
27
+ /** longitude in decimal degrees
28
+ *
29
+ * if set, latitude must be provided
30
+ */
31
+ longitude?: number;
32
+ /**
33
+ * time of arrival. If in future, it is an ETA.
34
+ */
35
+ time?: number;
36
+ /**
37
+ * offset from the actual waypoint
38
+ *
39
+ * bearing: degrees from the waypoint
40
+ * distance: distance in nautical miles
41
+ */
42
+ offset?: {
43
+ bearing: number;
44
+ distance: number;
45
+ };
46
+ }
47
+
48
+ /**
49
+ * Representation of a route
50
+ *
51
+ * Typically a list of waypoints, this can also be a named company route.
52
+ */
53
+ interface Route {
54
+ /** optional name. If not set, `waypoints` is required */
55
+ name?: string;
56
+ /** optional runway */
57
+ runway?: string;
58
+ /** optional list of waypoints. If not set, `name` is required */
59
+ waypoints?: Waypoint[];
60
+ }
61
+
62
+ interface Wind {
63
+ waypoint: Waypoint;
64
+ flightLevel: number;
65
+ windDirection: number;
66
+ windSpeed: number;
67
+ temperature?: {
68
+ flightLevel: number;
69
+ degreesC: number;
70
+ };
71
+ }
72
+
9
73
  /**
10
74
  * Representation of a Message
11
75
  */
@@ -20,6 +84,87 @@ interface Message {
20
84
  interface Options {
21
85
  debug?: boolean;
22
86
  }
87
+ /**
88
+ * Known fields that can appear on DecodeResult.raw.
89
+ * The index signature allows plugin-specific fields without losing type safety
90
+ * on the well-known ones.
91
+ */
92
+ interface RawFields {
93
+ position?: {
94
+ latitude: number;
95
+ longitude: number;
96
+ };
97
+ altitude?: number;
98
+ heading?: number;
99
+ groundspeed?: number;
100
+ airspeed?: number;
101
+ mach?: number;
102
+ flight_number?: string;
103
+ callsign?: string;
104
+ tail?: string;
105
+ departure_icao?: string;
106
+ departure_iata?: string;
107
+ arrival_icao?: string;
108
+ arrival_iata?: string;
109
+ alternate_icao?: string;
110
+ departure_runway?: string;
111
+ arrival_runway?: string;
112
+ alternate_runway?: string;
113
+ message_timestamp?: number;
114
+ eta_time?: number;
115
+ out_time?: number;
116
+ off_time?: number;
117
+ on_time?: number;
118
+ in_time?: number;
119
+ engine_start_time?: number;
120
+ engine_stop_time?: number;
121
+ day?: number | string;
122
+ month?: number;
123
+ departure_day?: number;
124
+ arrival_day?: number;
125
+ fuel_on_board?: number;
126
+ fuel_burned?: number;
127
+ fuel_remaining?: number;
128
+ fuel_in_tons?: number;
129
+ out_fuel?: number;
130
+ off_fuel?: number;
131
+ on_fuel?: number;
132
+ in_fuel?: number;
133
+ start_fuel?: number;
134
+ outside_air_temperature?: number;
135
+ total_air_temperature?: number;
136
+ center_of_gravity?: number;
137
+ cg_lower_limit?: number;
138
+ cg_upper_limit?: number;
139
+ mac?: number;
140
+ trim?: number;
141
+ route?: Route;
142
+ wind_data?: Wind[];
143
+ requested_alts?: number[];
144
+ desired_alt?: number;
145
+ start_point?: string;
146
+ route_number?: string;
147
+ flight_plan?: string;
148
+ label?: string;
149
+ sublabel?: string;
150
+ preamble?: string;
151
+ version?: number;
152
+ checksum_algorithm?: string;
153
+ checksum?: number;
154
+ sequence_number?: number;
155
+ sequence_response?: number;
156
+ ground_address?: string;
157
+ text?: string;
158
+ state_change?: {
159
+ from: string;
160
+ to: string;
161
+ };
162
+ door_event?: {
163
+ door: string;
164
+ state: string;
165
+ };
166
+ [key: string]: unknown;
167
+ }
23
168
  /**
24
169
  * Results from decoding a message
25
170
  */
@@ -41,7 +186,7 @@ interface DecodeResult {
41
186
  }[];
42
187
  };
43
188
  message?: Message;
44
- raw: any;
189
+ raw: RawFields;
45
190
  remaining: {
46
191
  text?: string;
47
192
  };
@@ -51,7 +196,7 @@ interface Qualifiers {
51
196
  preambles?: string[];
52
197
  }
53
198
  interface DecoderPluginInterface {
54
- decode(message: Message): DecodeResult;
199
+ decode(message: Message, options?: Options): DecodeResult;
55
200
  meetsStateRequirements(): boolean;
56
201
  qualifiers(): Qualifiers;
57
202
  }
@@ -60,9 +205,16 @@ declare class MessageDecoder {
60
205
  name: string;
61
206
  plugins: Array<DecoderPluginInterface>;
62
207
  debug: boolean;
208
+ /** Maps a label string to the candidate entries (wildcard + label-specific) in registration order. */
209
+ private candidatesByLabel;
210
+ /** Wildcard entries (plugins that register the '*' label). */
211
+ private wildcardEntries;
212
+ /** Membership set for wildcard entries to dedupe when a plugin also registers a specific label. */
213
+ private wildcardSet;
63
214
  constructor();
64
215
  registerPlugin(plugin: DecoderPluginInterface): boolean;
65
216
  decode(message: Message, options?: Options): DecodeResult;
217
+ private matchesPreambles;
66
218
  }
67
219
 
68
220
  export { IcaoDecoder, MessageDecoder };