metar-taf-parser 0.0.1 → 0.0.2

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.
Files changed (57) hide show
  1. package/README.md +8 -2
  2. package/dist/{lib/command → command}/common.d.ts +1 -1
  3. package/dist/{lib/command → command}/common.js +4 -4
  4. package/dist/{lib/command → command}/metar.d.ts +5 -1
  5. package/dist/{lib/command → command}/metar.js +6 -5
  6. package/dist/{lib/command → command}/remark.d.ts +5 -1
  7. package/dist/{lib/command → command}/remark.js +130 -148
  8. package/dist/{lib/commons → commons}/converter.d.ts +0 -0
  9. package/dist/{lib/commons → commons}/converter.js +2 -2
  10. package/dist/{lib/commons → commons}/errors.d.ts +7 -2
  11. package/dist/{lib/commons → commons}/errors.js +8 -3
  12. package/dist/commons/i18n.d.ts +12 -0
  13. package/dist/{lib/commons → commons}/i18n.js +12 -4
  14. package/dist/{lib/helpers → helpers}/helpers.d.ts +0 -1
  15. package/dist/helpers/helpers.js +23 -0
  16. package/dist/index.d.ts +10 -0
  17. package/dist/index.js +38 -0
  18. package/dist/locale/de.d.ts +321 -0
  19. package/dist/locale/de.js +322 -0
  20. package/dist/locale/en.d.ts +387 -0
  21. package/dist/locale/en.js +398 -0
  22. package/dist/locale/fr.d.ts +365 -0
  23. package/dist/locale/fr.js +376 -0
  24. package/dist/locale/it.d.ts +337 -0
  25. package/dist/locale/it.js +338 -0
  26. package/dist/locale/pl.d.ts +98 -0
  27. package/dist/locale/pl.js +99 -0
  28. package/dist/locale/zh-CN.d.ts +111 -0
  29. package/dist/locale/zh-CN.js +112 -0
  30. package/dist/model/enum.d.ts +221 -0
  31. package/dist/model/enum.js +231 -0
  32. package/dist/{lib/model → model}/model.d.ts +14 -7
  33. package/dist/{lib/model → model}/model.js +1 -1
  34. package/dist/parser/parser.d.ts +66 -0
  35. package/dist/parser/parser.js +322 -0
  36. package/package.json +8 -3
  37. package/dist/lib/commons/i18n.d.ts +0 -3
  38. package/dist/lib/helpers/helpers.js +0 -28
  39. package/dist/lib/index.d.ts +0 -1
  40. package/dist/lib/index.js +0 -3
  41. package/dist/lib/locale/en.json +0 -396
  42. package/dist/lib/model/enum.d.ts +0 -122
  43. package/dist/lib/model/enum.js +0 -132
  44. package/dist/lib/parser/parser.d.ts +0 -26
  45. package/dist/lib/parser/parser.js +0 -198
  46. package/dist/tests/command/common.test.d.ts +0 -1
  47. package/dist/tests/command/common.test.js +0 -102
  48. package/dist/tests/command/metar.test.d.ts +0 -1
  49. package/dist/tests/command/metar.test.js +0 -52
  50. package/dist/tests/command/remark.test.d.ts +0 -1
  51. package/dist/tests/command/remark.test.js +0 -689
  52. package/dist/tests/common/converter.test.d.ts +0 -1
  53. package/dist/tests/common/converter.test.js +0 -78
  54. package/dist/tests/helpers/helpers.test.d.ts +0 -1
  55. package/dist/tests/helpers/helpers.test.js +0 -17
  56. package/dist/tests/parser/parser.test.d.ts +0 -1
  57. package/dist/tests/parser/parser.test.js +0 -96
@@ -0,0 +1,322 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
26
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
27
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
28
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
29
+ };
30
+ var _AbstractParser_INTENSITY_REGEX, _AbstractParser_CAVOK, _AbstractParser_commonSupplier, _MetarParser_commandSupplier, _RemarkParser_supplier;
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.RemarkParser = exports.MetarParser = exports.AbstractParser = exports.parseValidity = exports.parseTemperature = void 0;
33
+ const remark_1 = require("../command/remark");
34
+ const model_1 = require("../model/model");
35
+ const converter = __importStar(require("../commons/converter"));
36
+ const helpers_1 = require("../helpers/helpers");
37
+ const common_1 = require("../command/common");
38
+ const enum_1 = require("../model/enum");
39
+ const metar_1 = require("../command/metar");
40
+ const errors_1 = require("../commons/errors");
41
+ /**
42
+ * Parses the delivery time of a METAR/TAF
43
+ * @param abstractWeatherCode The TAF or METAR object
44
+ * @param timeString The string representing the delivery time
45
+ */
46
+ function parseDeliveryTime(timeString) {
47
+ return {
48
+ day: +timeString.slice(0, 2),
49
+ hour: +timeString.slice(2, 4),
50
+ minute: +timeString.slice(4, 6),
51
+ };
52
+ // TODO
53
+ // abstractWeatherCode.time = new Date()
54
+ }
55
+ /**
56
+ * This function parses the array containing the remark and concat the array into a string
57
+ * @param container the metar, taf or taf trend to update
58
+ * @param line The array containing the current line tokens
59
+ * @param index the index starting the remark ie token RMK
60
+ */
61
+ function parseRemark(container, line, index, locale) {
62
+ const remarks = new RemarkParser(locale).parse(line.slice(index + 1).join(" "));
63
+ container.remarks = remarks;
64
+ container.remark = remarks.join(" ");
65
+ }
66
+ /**
67
+ * Parses the temperature in a TAF
68
+ * @param input the string containing the temperature
69
+ * @returns TemperatureDated object
70
+ */
71
+ function parseTemperature(input) {
72
+ const parts = (0, helpers_1.pySplit)(input, "/");
73
+ return {
74
+ temperature: converter.convertTemperature(parts[0].slice(2)),
75
+ day: +parts[1].slice(0, 2),
76
+ hour: +parts[1].slice(2, 4),
77
+ };
78
+ }
79
+ exports.parseTemperature = parseTemperature;
80
+ /**
81
+ * Parses validity of a TAF or a TAFTrend
82
+ * @param input the string containing the validity
83
+ * @returns Validity object
84
+ */
85
+ function parseValidity(input) {
86
+ const parts = (0, helpers_1.pySplit)(input, "/");
87
+ return {
88
+ startDay: +parts[0].slice(0, 2),
89
+ startHour: +parts[0].slice(2),
90
+ endDay: +parts[1].slice(0, 2),
91
+ endHour: +parts[1].slice(2),
92
+ };
93
+ }
94
+ exports.parseValidity = parseValidity;
95
+ /**
96
+ * Parses the validity for a FROM taf trend
97
+ * @param input the string containing the validity
98
+ * @returns a Validity object
99
+ */
100
+ function parseFromValidity(input) {
101
+ return {
102
+ startDay: +input.slice(2, 4),
103
+ startHour: +input.slice(4, 6),
104
+ startMinutes: +input.slice(6, 8),
105
+ };
106
+ }
107
+ /**
108
+ * Abstract class.
109
+ * Base parser.
110
+ */
111
+ class AbstractParser {
112
+ constructor() {
113
+ this.FM = "FM";
114
+ this.TEMPO = "TEMPO";
115
+ this.BECMG = "BECMG";
116
+ this.RMK = "RMK";
117
+ // Safari does not currently support negative lookbehind
118
+ // #TOKENIZE_REGEX = /\s((?=\d\/\dSM)(?<!\s\d\s)|(?!\d\/\dSM))|=/;
119
+ _AbstractParser_INTENSITY_REGEX.set(this, /^(-|\+|VC)/);
120
+ _AbstractParser_CAVOK.set(this, "CAVOK");
121
+ _AbstractParser_commonSupplier.set(this, new common_1.CommandSupplier());
122
+ }
123
+ parseWeatherCondition(input) {
124
+ var _a;
125
+ let intensity;
126
+ if (input.match(__classPrivateFieldGet(this, _AbstractParser_INTENSITY_REGEX, "f"))) {
127
+ const match = (_a = input.match(__classPrivateFieldGet(this, _AbstractParser_INTENSITY_REGEX, "f"))) === null || _a === void 0 ? void 0 : _a[0];
128
+ if (match)
129
+ intensity = match;
130
+ }
131
+ let descriptive;
132
+ for (const key of Object.values(enum_1.Descriptive)) {
133
+ if (input.includes(key))
134
+ descriptive = key;
135
+ }
136
+ const weatherCondition = {
137
+ intensity,
138
+ descriptive,
139
+ phenomenons: [],
140
+ };
141
+ for (const key of Object.values(enum_1.Phenomenon)) {
142
+ if (input.includes(key))
143
+ weatherCondition.phenomenons.push(key);
144
+ }
145
+ return weatherCondition;
146
+ }
147
+ /**
148
+ * Parses the message into different tokens
149
+ * @param input The metar or TAF as string
150
+ * @returns List of tokens
151
+ */
152
+ tokenize(input) {
153
+ // Missing safari support. If added in the future, put this back
154
+ // return input.split(this.#TOKENIZE_REGEX).filter((v) => v);
155
+ // Hack for safari below...
156
+ const splitRegex = /\s|=/;
157
+ const smRegex = /^\d\/\dSM$/;
158
+ const digitRegex = /^\d$/;
159
+ // return input.split(this.#TOKENIZE_REGEX).filter((v) => v);
160
+ const splitted = input.split(splitRegex);
161
+ for (let i = 0; i < splitted.length; i++) {
162
+ if (digitRegex.test(splitted[i])) {
163
+ if (splitted[i + 1] && smRegex.test(splitted[i + 1])) {
164
+ splitted.splice(i, 2, `${splitted[i]} ${splitted[i + 1]}`);
165
+ i--;
166
+ }
167
+ }
168
+ }
169
+ return splitted.filter((t) => t);
170
+ }
171
+ /**
172
+ * Common parse method for METAR, TAF and trends object
173
+ * @param abstractWeatherCode the object to update
174
+ * @param input The token to parse
175
+ * @returns True if the token was parsed false otherwise
176
+ */
177
+ generalParse(abstractWeatherContainer, input) {
178
+ if (input === __classPrivateFieldGet(this, _AbstractParser_CAVOK, "f")) {
179
+ abstractWeatherContainer.cavok = true;
180
+ const distance = "> 10km";
181
+ if (!abstractWeatherContainer.visibility)
182
+ abstractWeatherContainer.visibility = {
183
+ distance,
184
+ };
185
+ abstractWeatherContainer.visibility.distance = distance;
186
+ return true;
187
+ }
188
+ const command = __classPrivateFieldGet(this, _AbstractParser_commonSupplier, "f").get(input);
189
+ if (command) {
190
+ return command.execute(abstractWeatherContainer, input);
191
+ }
192
+ const weatherCondition = this.parseWeatherCondition(input);
193
+ if ((0, model_1.isWeatherConditionValid)(weatherCondition)) {
194
+ abstractWeatherContainer.weatherConditions.push(weatherCondition);
195
+ return true;
196
+ }
197
+ return false;
198
+ }
199
+ }
200
+ exports.AbstractParser = AbstractParser;
201
+ _AbstractParser_INTENSITY_REGEX = new WeakMap(), _AbstractParser_CAVOK = new WeakMap(), _AbstractParser_commonSupplier = new WeakMap();
202
+ class MetarParser extends AbstractParser {
203
+ constructor(locale) {
204
+ super();
205
+ this.locale = locale;
206
+ this.AT = "AT";
207
+ this.TL = "TL";
208
+ _MetarParser_commandSupplier.set(this, new metar_1.CommandSupplier());
209
+ }
210
+ /**
211
+ * Parses a trend of a metar
212
+ * @param index the index starting the trend in the list
213
+ * @param trend The trend to update
214
+ * @param trendParts array of tokens
215
+ * @returns the last index of the token that was last parsed
216
+ */
217
+ parseTrend(index, trend, trendParts) {
218
+ let i = index + 1;
219
+ while (i < trendParts.length &&
220
+ trendParts[i] !== this.TEMPO &&
221
+ trendParts[i] !== this.BECMG) {
222
+ if (trendParts[i].startsWith(this.FM) ||
223
+ trendParts[i].startsWith(this.TL) ||
224
+ trendParts[i].startsWith(this.AT)) {
225
+ const trendTime = {
226
+ type: enum_1.TimeIndicator[trendParts[i].slice(0, 2)],
227
+ // TODO implement time
228
+ hour: +trendParts[i].slice(2, 4),
229
+ minute: +trendParts[i].slice(4, 6),
230
+ };
231
+ trend.times.push(trendTime);
232
+ }
233
+ else {
234
+ this.generalParse(trend, trendParts[i]);
235
+ }
236
+ i = i + 1;
237
+ }
238
+ return i - 1;
239
+ }
240
+ /**
241
+ * Parses an message and returns a METAR
242
+ * @param input The message to parse
243
+ * @returns METAR
244
+ */
245
+ parse(input) {
246
+ const metarTab = this.tokenize(input);
247
+ const metar = Object.assign(Object.assign({}, parseDeliveryTime(metarTab[1])), { station: metarTab[0], message: input,
248
+ // wind: IWind,
249
+ // visibility?: Visibility,
250
+ // verticalVisibility: number,
251
+ // windShear: IWindShear,
252
+ cavok: false, remark: "", remarks: [], clouds: [], weatherConditions: [],
253
+ // airport: IAirport,
254
+ trends: [],
255
+ // temperature: number,
256
+ // dewPoint: number,
257
+ // altimeter: number,
258
+ nosig: false, auto: false, runwaysInfo: [] }); // TODO remove cast
259
+ let index = 2;
260
+ while (index < metarTab.length) {
261
+ if (!super.generalParse(metar, metarTab[index])) {
262
+ if (metarTab[index] === "NOSIG") {
263
+ metar.nosig = true;
264
+ }
265
+ else if (metarTab[index] === "AUTO") {
266
+ metar.auto = true;
267
+ }
268
+ else if (metarTab[index] === this.TEMPO ||
269
+ metarTab[index] === this.BECMG) {
270
+ const trend = {
271
+ type: enum_1.WeatherChangeType[metarTab[index]],
272
+ weatherConditions: [],
273
+ clouds: [],
274
+ times: [],
275
+ };
276
+ // TODO - remove casting
277
+ index = this.parseTrend(index, trend, metarTab);
278
+ metar.trends.push(trend);
279
+ }
280
+ else if (metarTab[index] === this.RMK) {
281
+ parseRemark(metar, metarTab, index, this.locale);
282
+ break;
283
+ }
284
+ else {
285
+ const command = __classPrivateFieldGet(this, _MetarParser_commandSupplier, "f").get(metarTab[index]);
286
+ if (command)
287
+ command.execute(metar, metarTab[index]);
288
+ }
289
+ }
290
+ index = index + 1;
291
+ }
292
+ return metar;
293
+ }
294
+ }
295
+ exports.MetarParser = MetarParser;
296
+ _MetarParser_commandSupplier = new WeakMap();
297
+ class RemarkParser {
298
+ constructor(locale) {
299
+ this.locale = locale;
300
+ _RemarkParser_supplier.set(this, new remark_1.RemarkCommandSupplier(this.locale));
301
+ }
302
+ parse(code) {
303
+ let rmkStr = code;
304
+ let rmkList = [];
305
+ while (rmkStr) {
306
+ try {
307
+ [rmkStr, rmkList] = __classPrivateFieldGet(this, _RemarkParser_supplier, "f").get(rmkStr).execute(rmkStr, rmkList);
308
+ }
309
+ catch (e) {
310
+ if (e instanceof errors_1.TranslationError) {
311
+ [rmkStr, rmkList] = __classPrivateFieldGet(this, _RemarkParser_supplier, "f").defaultCommand.execute(rmkStr, rmkList);
312
+ }
313
+ else {
314
+ throw e;
315
+ }
316
+ }
317
+ }
318
+ return rmkList;
319
+ }
320
+ }
321
+ exports.RemarkParser = RemarkParser;
322
+ _RemarkParser_supplier = new WeakMap();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metar-taf-parser",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Parse METAR and TAF files",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -11,7 +11,7 @@
11
11
  "url": "https://github.com/aeharding/metar-taf-parser.git"
12
12
  },
13
13
  "scripts": {
14
- "build": "yarn clean; tsc",
14
+ "build": "yarn clean; tsc && tsc-alias",
15
15
  "clean": "rm -rf ./dist",
16
16
  "start": "node --experimental-specifier-resolution=node --loader ts-node/esm lib",
17
17
  "check-types": "tsc --noEmit",
@@ -30,13 +30,18 @@
30
30
  "@babel/preset-typescript": "^7.16.7",
31
31
  "@types/fs-extra": "^9.0.12",
32
32
  "@types/jest": "^27.4.1",
33
+ "@types/lodash": "^4.14.181",
33
34
  "fs-extra": "^10.0.0",
34
35
  "jest": "^27.5.1",
35
36
  "prettier": "^2.6.2",
36
37
  "ts-jest": "^27.1.4",
37
38
  "ts-node": "^10.2.1",
39
+ "tsc-alias": "^1.6.6",
38
40
  "typescript": "^4.4.2",
39
41
  "watch": "^1.0.2"
40
42
  },
41
- "dependencies": {}
43
+ "dependencies": {
44
+ "lodash": "^4.17.21",
45
+ "po2json": "^0.4.5"
46
+ }
42
47
  }
@@ -1,3 +0,0 @@
1
- import messages from "locale/en.json";
2
- export default messages;
3
- export declare function format(message: string, ...args: unknown[]): string;
@@ -1,28 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.findAll = exports.pySplit = void 0;
4
- /**
5
- * Split behaving similar to Python's implementation
6
- */
7
- function pySplit(string, separator, n) {
8
- const split = string.split(separator);
9
- if (n == null || split.length <= n)
10
- return split;
11
- const out = split.slice(0, n);
12
- out.push(split.slice(n).join(separator));
13
- return out;
14
- }
15
- exports.pySplit = pySplit;
16
- function findAll(regex, str) {
17
- const hits = [];
18
- // Iterate hits
19
- let match = null;
20
- do {
21
- match = regex.exec(str);
22
- if (match) {
23
- hits.push(match[0]);
24
- }
25
- } while (match);
26
- return hits;
27
- }
28
- exports.findAll = findAll;
@@ -1 +0,0 @@
1
- export {};
package/dist/lib/index.js DELETED
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- // i18n();