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.
- package/README.md +8 -2
- package/dist/{lib/command → command}/common.d.ts +1 -1
- package/dist/{lib/command → command}/common.js +4 -4
- package/dist/{lib/command → command}/metar.d.ts +5 -1
- package/dist/{lib/command → command}/metar.js +6 -5
- package/dist/{lib/command → command}/remark.d.ts +5 -1
- package/dist/{lib/command → command}/remark.js +130 -148
- package/dist/{lib/commons → commons}/converter.d.ts +0 -0
- package/dist/{lib/commons → commons}/converter.js +2 -2
- package/dist/{lib/commons → commons}/errors.d.ts +7 -2
- package/dist/{lib/commons → commons}/errors.js +8 -3
- package/dist/commons/i18n.d.ts +12 -0
- package/dist/{lib/commons → commons}/i18n.js +12 -4
- package/dist/{lib/helpers → helpers}/helpers.d.ts +0 -1
- package/dist/helpers/helpers.js +23 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +38 -0
- package/dist/locale/de.d.ts +321 -0
- package/dist/locale/de.js +322 -0
- package/dist/locale/en.d.ts +387 -0
- package/dist/locale/en.js +398 -0
- package/dist/locale/fr.d.ts +365 -0
- package/dist/locale/fr.js +376 -0
- package/dist/locale/it.d.ts +337 -0
- package/dist/locale/it.js +338 -0
- package/dist/locale/pl.d.ts +98 -0
- package/dist/locale/pl.js +99 -0
- package/dist/locale/zh-CN.d.ts +111 -0
- package/dist/locale/zh-CN.js +112 -0
- package/dist/model/enum.d.ts +221 -0
- package/dist/model/enum.js +231 -0
- package/dist/{lib/model → model}/model.d.ts +14 -7
- package/dist/{lib/model → model}/model.js +1 -1
- package/dist/parser/parser.d.ts +66 -0
- package/dist/parser/parser.js +322 -0
- package/package.json +8 -3
- package/dist/lib/commons/i18n.d.ts +0 -3
- package/dist/lib/helpers/helpers.js +0 -28
- package/dist/lib/index.d.ts +0 -1
- package/dist/lib/index.js +0 -3
- package/dist/lib/locale/en.json +0 -396
- package/dist/lib/model/enum.d.ts +0 -122
- package/dist/lib/model/enum.js +0 -132
- package/dist/lib/parser/parser.d.ts +0 -26
- package/dist/lib/parser/parser.js +0 -198
- package/dist/tests/command/common.test.d.ts +0 -1
- package/dist/tests/command/common.test.js +0 -102
- package/dist/tests/command/metar.test.d.ts +0 -1
- package/dist/tests/command/metar.test.js +0 -52
- package/dist/tests/command/remark.test.d.ts +0 -1
- package/dist/tests/command/remark.test.js +0 -689
- package/dist/tests/common/converter.test.d.ts +0 -1
- package/dist/tests/common/converter.test.js +0 -78
- package/dist/tests/helpers/helpers.test.d.ts +0 -1
- package/dist/tests/helpers/helpers.test.js +0 -17
- package/dist/tests/parser/parser.test.d.ts +0 -1
- package/dist/tests/parser/parser.test.js +0 -96
|
@@ -1,198 +0,0 @@
|
|
|
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_FM, _AbstractParser_TEMPO, _AbstractParser_BECMG, _AbstractParser_RMK, _AbstractParser_TOKENIZE_REGEX, _AbstractParser_INTENSITY_REGEX, _AbstractParser_CAVOK, _AbstractParser_commonSupplier, _RemarkParser_supplier;
|
|
31
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
exports.RemarkParser = exports.AbstractParser = 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
|
-
/**
|
|
40
|
-
* Parses the delivery time of a METAR/TAF
|
|
41
|
-
* @param abstractWeatherCode The TAF or METAR object
|
|
42
|
-
* @param timeString The string representing the delivery time
|
|
43
|
-
*/
|
|
44
|
-
function parseDeliveryTime(abstractWeatherCode, timeString) {
|
|
45
|
-
abstractWeatherCode.day = +timeString.slice(2);
|
|
46
|
-
// TODO
|
|
47
|
-
// abstractWeatherCode.time = new Date()
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* This function parses the array containing the remark and concat the array into a string
|
|
51
|
-
* @param container the metar, taf or taf trend to update
|
|
52
|
-
* @param line The array containing the current line tokens
|
|
53
|
-
* @param index the index starting the remark ie token RMK
|
|
54
|
-
*/
|
|
55
|
-
function parseRemark(container, line, index) {
|
|
56
|
-
const remarks = new RemarkParser().parse(line.slice(1).join(" "));
|
|
57
|
-
container.remarks = remarks;
|
|
58
|
-
container.remark = remarks.join(" ");
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Parses the temperature in a TAF
|
|
62
|
-
* @param input the string containing the temperature
|
|
63
|
-
* @returns TemperatureDated object
|
|
64
|
-
*/
|
|
65
|
-
function parseTemperature(input) {
|
|
66
|
-
const parts = (0, helpers_1.pySplit)(input, "/");
|
|
67
|
-
return {
|
|
68
|
-
temperature: converter.convertTemperature(parts[0].slice(2)),
|
|
69
|
-
day: +parts[1].slice(0, 2),
|
|
70
|
-
hour: +parts[1].slice(2, 4),
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Parses validity of a TAF or a TAFTrend
|
|
75
|
-
* @param input the string containing the validity
|
|
76
|
-
* @returns Validity object
|
|
77
|
-
*/
|
|
78
|
-
function parseValidity(input) {
|
|
79
|
-
const parts = (0, helpers_1.pySplit)(input, "/");
|
|
80
|
-
return {
|
|
81
|
-
startDay: +parts[0].slice(0, 2),
|
|
82
|
-
startHour: +parts[0].slice(2),
|
|
83
|
-
endDay: +parts[1].slice(0, 2),
|
|
84
|
-
endHour: +parts[1].slice(2),
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Parses the validity for a FROM taf trend
|
|
89
|
-
* @param input the string containing the validity
|
|
90
|
-
* @returns a Validity object
|
|
91
|
-
*/
|
|
92
|
-
function parseFromValidity(input) {
|
|
93
|
-
return {
|
|
94
|
-
startDay: +input.slice(2, 4),
|
|
95
|
-
startHour: +input.slice(4, 6),
|
|
96
|
-
startMinutes: +input.slice(6, 8),
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Abstract class.
|
|
101
|
-
* Base parser.
|
|
102
|
-
*/
|
|
103
|
-
class AbstractParser {
|
|
104
|
-
constructor() {
|
|
105
|
-
_AbstractParser_FM.set(this, "FM");
|
|
106
|
-
_AbstractParser_TEMPO.set(this, "TEMPO");
|
|
107
|
-
_AbstractParser_BECMG.set(this, "BECMG");
|
|
108
|
-
_AbstractParser_RMK.set(this, "RMK");
|
|
109
|
-
_AbstractParser_TOKENIZE_REGEX.set(this, /\s((?=\d\/\dSM)(?<!\s\d\s)|(?!\d\/\dSM))|=/);
|
|
110
|
-
_AbstractParser_INTENSITY_REGEX.set(this, /^(-|\+|VC)/);
|
|
111
|
-
_AbstractParser_CAVOK.set(this, "CAVOK");
|
|
112
|
-
_AbstractParser_commonSupplier.set(this, new common_1.CommandSupplier());
|
|
113
|
-
}
|
|
114
|
-
parseWeatherCondition(input) {
|
|
115
|
-
var _a;
|
|
116
|
-
let intensity;
|
|
117
|
-
if (input.match(__classPrivateFieldGet(this, _AbstractParser_INTENSITY_REGEX, "f"))) {
|
|
118
|
-
const match = (_a = input.match(__classPrivateFieldGet(this, _AbstractParser_INTENSITY_REGEX, "f"))) === null || _a === void 0 ? void 0 : _a[0];
|
|
119
|
-
if (match)
|
|
120
|
-
intensity = match;
|
|
121
|
-
}
|
|
122
|
-
let descriptive;
|
|
123
|
-
for (const key of Object.values(enum_1.Descriptive)) {
|
|
124
|
-
if (input.includes(key))
|
|
125
|
-
descriptive = key;
|
|
126
|
-
}
|
|
127
|
-
const weatherCondition = {
|
|
128
|
-
intensity,
|
|
129
|
-
descriptive,
|
|
130
|
-
phenomenons: [],
|
|
131
|
-
};
|
|
132
|
-
for (const key of Object.values(enum_1.Phenomenon)) {
|
|
133
|
-
if (input.includes(key))
|
|
134
|
-
weatherCondition.phenomenons.push(key);
|
|
135
|
-
}
|
|
136
|
-
return weatherCondition;
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Parses the message into different tokens
|
|
140
|
-
* @param input The metar or TAF as string
|
|
141
|
-
* @returns List of tokens
|
|
142
|
-
*/
|
|
143
|
-
tokenize(input) {
|
|
144
|
-
return input.split(__classPrivateFieldGet(this, _AbstractParser_TOKENIZE_REGEX, "f")).filter((v) => v);
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Common parse method for METAR, TAF and trends object
|
|
148
|
-
* @param abstractWeatherCode the object to update
|
|
149
|
-
* @param input The token to parse
|
|
150
|
-
* @returns True if the token was parsed false otherwise
|
|
151
|
-
*/
|
|
152
|
-
generalParse(abstractWeatherContainer, input) {
|
|
153
|
-
if (__classPrivateFieldGet(this, _AbstractParser_CAVOK, "f") === input) {
|
|
154
|
-
abstractWeatherContainer.cavok = true;
|
|
155
|
-
const distance = "> 10km";
|
|
156
|
-
if (!abstractWeatherContainer.visibility)
|
|
157
|
-
abstractWeatherContainer.visibility = {
|
|
158
|
-
distance,
|
|
159
|
-
};
|
|
160
|
-
abstractWeatherContainer.visibility.distance = distance;
|
|
161
|
-
return true;
|
|
162
|
-
}
|
|
163
|
-
const command = __classPrivateFieldGet(this, _AbstractParser_commonSupplier, "f").get(input);
|
|
164
|
-
if (command) {
|
|
165
|
-
return command.execute(abstractWeatherContainer, input);
|
|
166
|
-
}
|
|
167
|
-
const weatherCondition = this.parseWeatherCondition(input);
|
|
168
|
-
if ((0, model_1.isWeatherConditionValid)(weatherCondition)) {
|
|
169
|
-
abstractWeatherContainer.weatherConditions.push(weatherCondition);
|
|
170
|
-
return true;
|
|
171
|
-
}
|
|
172
|
-
return false;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
exports.AbstractParser = AbstractParser;
|
|
176
|
-
_AbstractParser_FM = new WeakMap(), _AbstractParser_TEMPO = new WeakMap(), _AbstractParser_BECMG = new WeakMap(), _AbstractParser_RMK = new WeakMap(), _AbstractParser_TOKENIZE_REGEX = new WeakMap(), _AbstractParser_INTENSITY_REGEX = new WeakMap(), _AbstractParser_CAVOK = new WeakMap(), _AbstractParser_commonSupplier = new WeakMap();
|
|
177
|
-
class RemarkParser {
|
|
178
|
-
constructor() {
|
|
179
|
-
_RemarkParser_supplier.set(this, new remark_1.RemarkCommandSupplier());
|
|
180
|
-
}
|
|
181
|
-
parse(code) {
|
|
182
|
-
let rmkStr = code;
|
|
183
|
-
let rmkList = [];
|
|
184
|
-
while (rmkStr) {
|
|
185
|
-
try {
|
|
186
|
-
[rmkStr, rmkList] = __classPrivateFieldGet(this, _RemarkParser_supplier, "f").get(rmkStr).execute(rmkStr, rmkList);
|
|
187
|
-
}
|
|
188
|
-
catch (e) {
|
|
189
|
-
// TODO
|
|
190
|
-
// if (e instanceof TranslationError) this.#supplier.defaultCommand.execute(rmkStr, rmkList)
|
|
191
|
-
throw e;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return rmkList;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
exports.RemarkParser = RemarkParser;
|
|
198
|
-
_RemarkParser_supplier = new WeakMap();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const common_1 = require("command/common");
|
|
4
|
-
const enum_1 = require("model/enum");
|
|
5
|
-
describe("CloudCommand", () => {
|
|
6
|
-
const command = new common_1.CloudCommand();
|
|
7
|
-
(() => {
|
|
8
|
-
const code = "SKC";
|
|
9
|
-
describe(code, () => {
|
|
10
|
-
test("canParse", () => {
|
|
11
|
-
expect(command.canParse(code)).toBe(true);
|
|
12
|
-
});
|
|
13
|
-
test("parse", () => {
|
|
14
|
-
const cloud = command.parse(code);
|
|
15
|
-
expect(cloud).toBeDefined();
|
|
16
|
-
expect(cloud === null || cloud === void 0 ? void 0 : cloud.quantity).toBe(enum_1.CloudQuantity.SKC);
|
|
17
|
-
expect(cloud === null || cloud === void 0 ? void 0 : cloud.height).toBeUndefined();
|
|
18
|
-
expect(cloud === null || cloud === void 0 ? void 0 : cloud.type).toBeUndefined();
|
|
19
|
-
});
|
|
20
|
-
});
|
|
21
|
-
})();
|
|
22
|
-
(() => {
|
|
23
|
-
const code = "SCT016";
|
|
24
|
-
describe(code, () => {
|
|
25
|
-
test("canParse", () => {
|
|
26
|
-
expect(command.canParse(code)).toBe(true);
|
|
27
|
-
});
|
|
28
|
-
test("parse", () => {
|
|
29
|
-
const cloud = command.parse(code);
|
|
30
|
-
expect(cloud).toBeDefined();
|
|
31
|
-
expect(cloud === null || cloud === void 0 ? void 0 : cloud.quantity).toBe(enum_1.CloudQuantity.SCT);
|
|
32
|
-
expect(cloud === null || cloud === void 0 ? void 0 : cloud.height).toBe(1600);
|
|
33
|
-
expect(cloud === null || cloud === void 0 ? void 0 : cloud.type).toBeUndefined();
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
})();
|
|
37
|
-
(() => {
|
|
38
|
-
// With type
|
|
39
|
-
const code = "SCT026CB";
|
|
40
|
-
describe(code, () => {
|
|
41
|
-
test("canParse", () => {
|
|
42
|
-
expect(command.canParse(code)).toBe(true);
|
|
43
|
-
});
|
|
44
|
-
test("parse", () => {
|
|
45
|
-
const cloud = command.parse(code);
|
|
46
|
-
expect(cloud).toBeDefined();
|
|
47
|
-
expect(cloud === null || cloud === void 0 ? void 0 : cloud.quantity).toBe(enum_1.CloudQuantity.SCT);
|
|
48
|
-
expect(cloud === null || cloud === void 0 ? void 0 : cloud.height).toBe(2600);
|
|
49
|
-
expect(cloud === null || cloud === void 0 ? void 0 : cloud.type).toBe(enum_1.CloudType.CB);
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
})();
|
|
53
|
-
});
|
|
54
|
-
describe("WindCommand", () => {
|
|
55
|
-
const command = new common_1.WindCommand();
|
|
56
|
-
(() => {
|
|
57
|
-
const code = "34008KT";
|
|
58
|
-
describe(code, () => {
|
|
59
|
-
test("canParse", () => {
|
|
60
|
-
expect(command.canParse(code)).toBe(true);
|
|
61
|
-
});
|
|
62
|
-
test("parse", () => {
|
|
63
|
-
const wind = command.parseWind(code);
|
|
64
|
-
expect(wind.direction).toBe("NNW");
|
|
65
|
-
expect(wind.degrees).toBe(340);
|
|
66
|
-
expect(wind.speed).toBe(8);
|
|
67
|
-
expect(wind.gust).toBeUndefined();
|
|
68
|
-
expect(wind.unit).toBe("KT");
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
})();
|
|
72
|
-
(() => {
|
|
73
|
-
const code = "12017G20KT";
|
|
74
|
-
describe(code, () => {
|
|
75
|
-
test("canParse", () => {
|
|
76
|
-
expect(command.canParse(code)).toBe(true);
|
|
77
|
-
});
|
|
78
|
-
test("parse", () => {
|
|
79
|
-
const wind = command.parseWind(code);
|
|
80
|
-
expect(wind.direction).toBe("ESE");
|
|
81
|
-
expect(wind.degrees).toBe(120);
|
|
82
|
-
expect(wind.speed).toBe(17);
|
|
83
|
-
expect(wind.gust).toBe(20);
|
|
84
|
-
expect(wind.unit).toBe("KT");
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
})();
|
|
88
|
-
(() => {
|
|
89
|
-
const code = "VRB08KT";
|
|
90
|
-
describe(code, () => {
|
|
91
|
-
test("canParse", () => {
|
|
92
|
-
expect(command.canParse(code)).toBe(true);
|
|
93
|
-
});
|
|
94
|
-
test("parse", () => {
|
|
95
|
-
const wind = command.parseWind(code);
|
|
96
|
-
expect(wind.direction).toBe("VRB");
|
|
97
|
-
expect(wind.speed).toBe(8);
|
|
98
|
-
expect(wind.degrees).toBeUndefined();
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
})();
|
|
102
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const metar_1 = require("command/metar");
|
|
4
|
-
describe("RunwayCommand", () => {
|
|
5
|
-
const command = new metar_1.RunwayCommand();
|
|
6
|
-
(() => {
|
|
7
|
-
const code = "R26/0600U";
|
|
8
|
-
const metar = { runwaysInfo: [] };
|
|
9
|
-
describe(code, () => {
|
|
10
|
-
test("canParse", () => {
|
|
11
|
-
expect(command.canParse(code)).toBe(true);
|
|
12
|
-
});
|
|
13
|
-
test("parse", () => {
|
|
14
|
-
command.execute(metar, code);
|
|
15
|
-
expect(metar.runwaysInfo).toHaveLength(1);
|
|
16
|
-
expect(metar.runwaysInfo[0].name).toBe("26");
|
|
17
|
-
expect(metar.runwaysInfo[0].minRange).toBe(600);
|
|
18
|
-
expect(metar.runwaysInfo[0].trend).toBe("U");
|
|
19
|
-
});
|
|
20
|
-
});
|
|
21
|
-
})();
|
|
22
|
-
(() => {
|
|
23
|
-
const code = "R26L/0550V700U";
|
|
24
|
-
const metar = { runwaysInfo: [] };
|
|
25
|
-
describe(code, () => {
|
|
26
|
-
test("canParse", () => {
|
|
27
|
-
expect(command.canParse(code)).toBe(true);
|
|
28
|
-
});
|
|
29
|
-
test("parse", () => {
|
|
30
|
-
command.execute(metar, code);
|
|
31
|
-
expect(metar.runwaysInfo).toHaveLength(1);
|
|
32
|
-
expect(metar.runwaysInfo[0].name).toBe("26L");
|
|
33
|
-
expect(metar.runwaysInfo[0].minRange).toBe(550);
|
|
34
|
-
expect(metar.runwaysInfo[0].maxRange).toBe(700);
|
|
35
|
-
expect(metar.runwaysInfo[0].trend).toBe("U");
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
})();
|
|
39
|
-
(() => {
|
|
40
|
-
const code = "R26R/AZEAZEDS"; // wrong runway
|
|
41
|
-
const metar = { runwaysInfo: [] };
|
|
42
|
-
describe(code, () => {
|
|
43
|
-
test("canParse", () => {
|
|
44
|
-
expect(command.canParse(code)).toBe(true);
|
|
45
|
-
});
|
|
46
|
-
test("parse", () => {
|
|
47
|
-
command.execute(metar, code);
|
|
48
|
-
expect(metar.runwaysInfo).toHaveLength(0);
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
})();
|
|
52
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|