@atmosx/event-product-parser 2.0.1 → 2.0.11

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.
@@ -0,0 +1,10 @@
1
+ # Code of Conduct
2
+ AtmosphericX is an independent, open source project and is **not** affiliated with, endorsed by, or sponsored by any government agency, meteorological organization, emergency management service, or official weather provider. This project may reference, parse, or process publicly available weather data, including but **not** limited to services operated by the National Weather Service (NWS) and the National Oceanic and Atmospheric Administration (NOAA). All trademarks, service marks, and data rights remain the property of their respective owners. AtmosphericX is provided "as is", without warranty of any kind, express or implied, including but **not** limited to:
3
+
4
+ - Accuracy or completeness of parsed weather data
5
+ - Fitness for a particular purpose
6
+ - Protection against sources and data retrieval
7
+ - Availability or reliability of upstream data sources
8
+ - Protection against service interruptions or data delays
9
+
10
+ AtmosphericX should **not** be relied upon for life safety decisions, emergency response coordination, aviation, marine navigation, or other critical applications. Always consult official sources for authoritative weather information. By using this software, you acknowledge and agree that the maintainers and contributors are **not** liable for any damages, losses, or consequences resulting from its use.
@@ -0,0 +1,30 @@
1
+ # Contributing
2
+
3
+ This project is community driven and primarily maintained by `k3yomi` and `StarflightWx`
4
+
5
+ ## How to Contribute
6
+
7
+ At this time, contributions are limited to:
8
+
9
+ - **Corrections** – Fix broken TypeScript syntax, outdated operations, or errors.
10
+ - **Additions** – Add new functions, tools, or services.
11
+ - **Clarity Improvements** – Improve explanations in plain English.
12
+ - **Documentation** – Add helpful content to the documentation.
13
+
14
+ ## What Will Not Be Accepted
15
+
16
+ - Content that introduces new packages.
17
+ - Anything that violates GitHub's Terms of Service.
18
+
19
+ ## How to Submit
20
+
21
+ 1. Fork the repository.
22
+ 2. Create a new branch: `fix/description` or `add/description`.
23
+ 3. Make your changes.
24
+ 4. Open a pull request with a clear description of **what changed and why**.
25
+
26
+ ## Requirements
27
+
28
+ - Use **plain English first, details later**.
29
+ - Provide **real working examples only** (do not make up syntax).
30
+ - Follow the existing **file structure and function signature format**.
package/README.md CHANGED
@@ -12,8 +12,7 @@
12
12
 
13
13
  ## Installation (NPM)
14
14
  ```bash
15
- npm install @atmosx/event-product-parser@latest # Latest
16
- npm install @atmosx/event-product-parser@beta # Beta
15
+ npm install @atmosx/event-product-parser@latest
17
16
  ```
18
17
 
19
18
  ## Example Usage
package/SECURITY.md ADDED
@@ -0,0 +1,21 @@
1
+ # Security Policy
2
+
3
+ ## Reporting Vulnerabilities
4
+ If you discover a security vulnerability or issue in this repository such as exposed sensitive data, misconfigurations, or content that could cause harm. Please report it **immediately and responsibly**.
5
+
6
+ **Do not report security issues publicly.**
7
+ Instead, report privately by emailing **antimal@scriptkitty.cafe**, clearly describing the vulnerability.
8
+
9
+ ## What to Include
10
+ When reporting a vulnerability, please include:
11
+ - A detailed description of the issue
12
+ - Affected files (include line numbers if possible)
13
+ - Any recommendations
14
+
15
+ ## Response
16
+ All reports will be reviewed and addressed as quickly as possible.
17
+ This is a community driven project, so response times may vary. Please allow up to a few weeks for a full response.
18
+
19
+ ## Scope
20
+ This repository **does not contain any credentials, keys, tokens, or personally identifiable information (PII)**.
21
+ If you discover any such data, report it immediately.
@@ -6513,6 +6513,41 @@ var Database = class {
6513
6513
  }
6514
6514
  });
6515
6515
  }
6516
+ /**
6517
+ * @function loadCollectionCache
6518
+ * @description
6519
+ * Loads cached stanzas from the database, validates them, and processes them through the event parser.
6520
+ * Only processes stanzas that are not marked to be ignored and match the CAP preferences.
6521
+ *
6522
+ * @static
6523
+ * @async
6524
+ * @returns {Promise<void>}
6525
+ */
6526
+ static loadCollectionCache() {
6527
+ return __async(this, null, function* () {
6528
+ var _a;
6529
+ try {
6530
+ const settings2 = settings;
6531
+ if (settings2.noaa_weather_wire_service_settings.cache.enabled) {
6532
+ const maxRows = (_a = settings2.noaa_weather_wire_service_settings.cache.max_db_cache_size) != null ? _a : 5e3;
6533
+ const rows = yield cache.db.prepare(`SELECT * FROM stanzas ORDER BY rowid DESC LIMIT ?`).all(maxRows);
6534
+ utils_default.warn(definitions.messages.dump_cache.replace(`{count}`, rows.length.toString()), true);
6535
+ const eventsToProcess = rows.map((row) => {
6536
+ return JSON.parse(row.stanza);
6537
+ }).filter((validate) => {
6538
+ if (!validate) return false;
6539
+ const skip = validate.ignore || validate.isCap && !settings2.noaa_weather_wire_service_settings.preferences.cap_only || !validate.isCap && settings2.noaa_weather_wire_service_settings.preferences.cap_only || validate.isCap && !validate.isCapDescription;
6540
+ return !skip;
6541
+ });
6542
+ yield Promise.all(eventsToProcess.map((validate) => events_default.eventHandler(validate)));
6543
+ utils_default.warn(definitions.messages.dump_cache_complete, true);
6544
+ return;
6545
+ }
6546
+ } catch (error) {
6547
+ utils_default.warn(`Failed to load cache: ${error.stack}`);
6548
+ }
6549
+ });
6550
+ }
6516
6551
  };
6517
6552
  var database_default = Database;
6518
6553
 
@@ -6686,41 +6721,6 @@ var Utils = class _Utils {
6686
6721
  cache.lastWarn = Date.now();
6687
6722
  console.warn(`\x1B[33m[ATMOSX-PARSER]\x1B[0m [${(/* @__PURE__ */ new Date()).toLocaleString()}] ${message}`);
6688
6723
  }
6689
- /**
6690
- * @function loadCollectionCache
6691
- * @description
6692
- * Loads cached stanzas from the database, validates them, and processes them through the event parser.
6693
- * Only processes stanzas that are not marked to be ignored and match the CAP preferences.
6694
- *
6695
- * @static
6696
- * @async
6697
- * @returns {Promise<void>}
6698
- */
6699
- static loadCollectionCache() {
6700
- return __async(this, null, function* () {
6701
- var _a;
6702
- try {
6703
- const settings2 = settings;
6704
- if (settings2.noaa_weather_wire_service_settings.cache.enabled) {
6705
- const maxRows = (_a = settings2.noaa_weather_wire_service_settings.cache.max_db_cache_size) != null ? _a : 5e3;
6706
- const rows = yield cache.db.prepare(`SELECT * FROM stanzas ORDER BY rowid DESC LIMIT ?`).all(maxRows);
6707
- this.warn(definitions.messages.dump_cache.replace(`{count}`, rows.length.toString()), true);
6708
- const eventsToProcess = rows.map((row) => {
6709
- return JSON.parse(row.stanza);
6710
- }).filter((validate) => {
6711
- if (!validate) return false;
6712
- const skip = validate.ignore || validate.isCap && !settings2.noaa_weather_wire_service_settings.preferences.cap_only || !validate.isCap && settings2.noaa_weather_wire_service_settings.preferences.cap_only || validate.isCap && !validate.isCapDescription;
6713
- return !skip;
6714
- });
6715
- yield Promise.all(eventsToProcess.map((validate) => events_default.eventHandler(validate)));
6716
- this.warn(definitions.messages.dump_cache_complete, true);
6717
- return;
6718
- }
6719
- } catch (error) {
6720
- _Utils.warn(`Failed to load cache: ${error.stack}`);
6721
- }
6722
- });
6723
- }
6724
6724
  /**
6725
6725
  * @function loadGeoJsonData
6726
6726
  * @description
@@ -7480,7 +7480,7 @@ var Manager = class {
7480
7480
  (() => __async(this, null, function* () {
7481
7481
  try {
7482
7482
  yield xmpp_default.deploySession();
7483
- yield utils_default.loadCollectionCache();
7483
+ yield database_default.loadCollectionCache();
7484
7484
  } catch (err) {
7485
7485
  const msg = err instanceof Error ? err.message : String(err);
7486
7486
  utils_default.warn(`Failed to initialize NWWS services: ${msg}`);
@@ -6501,6 +6501,41 @@ var Database = class {
6501
6501
  }
6502
6502
  });
6503
6503
  }
6504
+ /**
6505
+ * @function loadCollectionCache
6506
+ * @description
6507
+ * Loads cached stanzas from the database, validates them, and processes them through the event parser.
6508
+ * Only processes stanzas that are not marked to be ignored and match the CAP preferences.
6509
+ *
6510
+ * @static
6511
+ * @async
6512
+ * @returns {Promise<void>}
6513
+ */
6514
+ static loadCollectionCache() {
6515
+ return __async(this, null, function* () {
6516
+ var _a;
6517
+ try {
6518
+ const settings2 = settings;
6519
+ if (settings2.noaa_weather_wire_service_settings.cache.enabled) {
6520
+ const maxRows = (_a = settings2.noaa_weather_wire_service_settings.cache.max_db_cache_size) != null ? _a : 5e3;
6521
+ const rows = yield cache.db.prepare(`SELECT * FROM stanzas ORDER BY rowid DESC LIMIT ?`).all(maxRows);
6522
+ utils_default.warn(definitions.messages.dump_cache.replace(`{count}`, rows.length.toString()), true);
6523
+ const eventsToProcess = rows.map((row) => {
6524
+ return JSON.parse(row.stanza);
6525
+ }).filter((validate) => {
6526
+ if (!validate) return false;
6527
+ const skip = validate.ignore || validate.isCap && !settings2.noaa_weather_wire_service_settings.preferences.cap_only || !validate.isCap && settings2.noaa_weather_wire_service_settings.preferences.cap_only || validate.isCap && !validate.isCapDescription;
6528
+ return !skip;
6529
+ });
6530
+ yield Promise.all(eventsToProcess.map((validate) => events_default.eventHandler(validate)));
6531
+ utils_default.warn(definitions.messages.dump_cache_complete, true);
6532
+ return;
6533
+ }
6534
+ } catch (error) {
6535
+ utils_default.warn(`Failed to load cache: ${error.stack}`);
6536
+ }
6537
+ });
6538
+ }
6504
6539
  };
6505
6540
  var database_default = Database;
6506
6541
 
@@ -6674,41 +6709,6 @@ var Utils = class _Utils {
6674
6709
  cache.lastWarn = Date.now();
6675
6710
  console.warn(`\x1B[33m[ATMOSX-PARSER]\x1B[0m [${(/* @__PURE__ */ new Date()).toLocaleString()}] ${message}`);
6676
6711
  }
6677
- /**
6678
- * @function loadCollectionCache
6679
- * @description
6680
- * Loads cached stanzas from the database, validates them, and processes them through the event parser.
6681
- * Only processes stanzas that are not marked to be ignored and match the CAP preferences.
6682
- *
6683
- * @static
6684
- * @async
6685
- * @returns {Promise<void>}
6686
- */
6687
- static loadCollectionCache() {
6688
- return __async(this, null, function* () {
6689
- var _a;
6690
- try {
6691
- const settings2 = settings;
6692
- if (settings2.noaa_weather_wire_service_settings.cache.enabled) {
6693
- const maxRows = (_a = settings2.noaa_weather_wire_service_settings.cache.max_db_cache_size) != null ? _a : 5e3;
6694
- const rows = yield cache.db.prepare(`SELECT * FROM stanzas ORDER BY rowid DESC LIMIT ?`).all(maxRows);
6695
- this.warn(definitions.messages.dump_cache.replace(`{count}`, rows.length.toString()), true);
6696
- const eventsToProcess = rows.map((row) => {
6697
- return JSON.parse(row.stanza);
6698
- }).filter((validate) => {
6699
- if (!validate) return false;
6700
- const skip = validate.ignore || validate.isCap && !settings2.noaa_weather_wire_service_settings.preferences.cap_only || !validate.isCap && settings2.noaa_weather_wire_service_settings.preferences.cap_only || validate.isCap && !validate.isCapDescription;
6701
- return !skip;
6702
- });
6703
- yield Promise.all(eventsToProcess.map((validate) => events_default.eventHandler(validate)));
6704
- this.warn(definitions.messages.dump_cache_complete, true);
6705
- return;
6706
- }
6707
- } catch (error) {
6708
- _Utils.warn(`Failed to load cache: ${error.stack}`);
6709
- }
6710
- });
6711
- }
6712
6712
  /**
6713
6713
  * @function loadGeoJsonData
6714
6714
  * @description
@@ -7468,7 +7468,7 @@ var Manager = class {
7468
7468
  (() => __async(this, null, function* () {
7469
7469
  try {
7470
7470
  yield xmpp_default.deploySession();
7471
- yield utils_default.loadCollectionCache();
7471
+ yield database_default.loadCollectionCache();
7472
7472
  } catch (err) {
7473
7473
  const msg = err instanceof Error ? err.message : String(err);
7474
7474
  utils_default.warn(`Failed to initialize NWWS services: ${msg}`);
package/package.json CHANGED
@@ -1,14 +1,9 @@
1
1
  {
2
2
  "name": "@atmosx/event-product-parser",
3
- "version": "2.0.01",
3
+ "version": "2.0.011",
4
4
  "description": "NOAA Weather Wire & NWS API Parser - Built for standalone and Project AtmosphericX Integration.",
5
5
  "main": "dist/cjs/index.cjs",
6
6
  "module": "dist/esm/index.mjs",
7
- "types": "dist/index.d.ts",
8
- "files": [
9
- "dist/**/*",
10
- "src/**/*"
11
- ],
12
7
  "repository": {
13
8
  "type": "git",
14
9
  "url": "git+https://github.com/AtmosphericX/event-product-parser",
@@ -14,6 +14,7 @@
14
14
  import * as loader from '../bootstrap';
15
15
  import * as types from '../types';
16
16
  import Utils from './utils';
17
+ import EventParser from '../@parsers/events';
17
18
 
18
19
  export class Database {
19
20
 
@@ -157,6 +158,43 @@ export class Database {
157
158
  Utils.warn(`Failed to load database: ${msg}`);
158
159
  }
159
160
  }
161
+
162
+ /**
163
+ * @function loadCollectionCache
164
+ * @description
165
+ * Loads cached stanzas from the database, validates them, and processes them through the event parser.
166
+ * Only processes stanzas that are not marked to be ignored and match the CAP preferences.
167
+ *
168
+ * @static
169
+ * @async
170
+ * @returns {Promise<void>}
171
+ */
172
+ public static async loadCollectionCache(): Promise<void> {
173
+ try {
174
+ const settings = loader.settings as types.ClientSettingsTypes;
175
+ if (settings.noaa_weather_wire_service_settings.cache.enabled) {
176
+ const maxRows = settings.noaa_weather_wire_service_settings.cache.max_db_cache_size ?? 5000;
177
+ const rows = await loader.cache.db.prepare(`SELECT * FROM stanzas ORDER BY rowid DESC LIMIT ?`)
178
+ .all(maxRows) as { rowid: number; stanza: string }[];
179
+ Utils.warn(loader.definitions.messages.dump_cache.replace(`{count}`, rows.length.toString()), true);
180
+ const eventsToProcess = rows
181
+ .map(row => {return JSON.parse(row.stanza)})
182
+ .filter(validate => {
183
+ if (!validate) return false;
184
+ const skip = validate.ignore ||
185
+ (validate.isCap && !settings.noaa_weather_wire_service_settings.preferences.cap_only) ||
186
+ (!validate.isCap && settings.noaa_weather_wire_service_settings.preferences.cap_only) ||
187
+ (validate.isCap && !validate.isCapDescription);
188
+ return !skip;
189
+ });
190
+ await Promise.all(eventsToProcess.map(validate => EventParser.eventHandler(validate)));
191
+ Utils.warn(loader.definitions.messages.dump_cache_complete, true);
192
+ return;
193
+ }
194
+ } catch (error: any) {
195
+ Utils.warn(`Failed to load cache: ${error.stack}`);
196
+ }
197
+ }
160
198
  }
161
199
 
162
200
  export default Database;
@@ -13,7 +13,6 @@
13
13
 
14
14
  import * as loader from '../bootstrap';
15
15
  import * as types from '../types';
16
- import StanzaParser from '../@parsers/stanza';
17
16
  import EventParser from '../@parsers/events';
18
17
  import Xmpp from './xmpp';
19
18
 
@@ -52,43 +51,6 @@ export class Utils {
52
51
  console.warn(`\x1b[33m[ATMOSX-PARSER]\x1b[0m [${new Date().toLocaleString()}] ${message}`);
53
52
  }
54
53
 
55
- /**
56
- * @function loadCollectionCache
57
- * @description
58
- * Loads cached stanzas from the database, validates them, and processes them through the event parser.
59
- * Only processes stanzas that are not marked to be ignored and match the CAP preferences.
60
- *
61
- * @static
62
- * @async
63
- * @returns {Promise<void>}
64
- */
65
- public static async loadCollectionCache(): Promise<void> {
66
- try {
67
- const settings = loader.settings as types.ClientSettingsTypes;
68
- if (settings.noaa_weather_wire_service_settings.cache.enabled) {
69
- const maxRows = settings.noaa_weather_wire_service_settings.cache.max_db_cache_size ?? 5000;
70
- const rows = await loader.cache.db.prepare(`SELECT * FROM stanzas ORDER BY rowid DESC LIMIT ?`)
71
- .all(maxRows) as { rowid: number; stanza: string }[];
72
- this.warn(loader.definitions.messages.dump_cache.replace(`{count}`, rows.length.toString()), true);
73
- const eventsToProcess = rows
74
- .map(row => {return JSON.parse(row.stanza)})
75
- .filter(validate => {
76
- if (!validate) return false;
77
- const skip = validate.ignore ||
78
- (validate.isCap && !settings.noaa_weather_wire_service_settings.preferences.cap_only) ||
79
- (!validate.isCap && settings.noaa_weather_wire_service_settings.preferences.cap_only) ||
80
- (validate.isCap && !validate.isCapDescription);
81
- return !skip;
82
- });
83
- await Promise.all(eventsToProcess.map(validate => EventParser.eventHandler(validate)));
84
- this.warn(loader.definitions.messages.dump_cache_complete, true);
85
- return;
86
- }
87
- } catch (error: any) {
88
- Utils.warn(`Failed to load cache: ${error.stack}`);
89
- }
90
- }
91
-
92
54
  /**
93
55
  * @function loadGeoJsonData
94
56
  * @description
package/src/index.ts CHANGED
@@ -168,7 +168,7 @@ export class Manager {
168
168
  (async () => {
169
169
  try {
170
170
  await Xmpp.deploySession();
171
- await Utils.loadCollectionCache();
171
+ await Database.loadCollectionCache();
172
172
  } catch (err: unknown) {
173
173
  const msg = err instanceof Error ? err.message : String(err);
174
174
  Utils.warn(`Failed to initialize NWWS services: ${msg}`);
package/test.js ADDED
@@ -0,0 +1,62 @@
1
+ const { AlertManager } = require(`@atmosx/event-product-parser`)
2
+
3
+
4
+ const parser = new AlertManager({
5
+ database: `shapefile-manager.db`,
6
+ is_wire: true,
7
+ journal: true,
8
+ noaa_weather_wire_service_settings: {
9
+ reconnection_settings: {
10
+ enabled: true,
11
+ interval: 60,
12
+ },
13
+ credentials: {
14
+ username: `username123`,
15
+ password: `password123`,
16
+ nickname: "AtmosphericX Standalone Parser",
17
+ },
18
+ cache: {
19
+ enabled: false,
20
+ max_db_history: 5000,
21
+ max_db_cache_size: 1000,
22
+ },
23
+ preferences: {
24
+ disable_ugc: false,
25
+ disable_vtec: false,
26
+ disable_text: false,
27
+ cap_only: false,
28
+ }
29
+ },
30
+ national_weather_service_settings: {
31
+ interval: 15,
32
+ endpoint: `https://api.weather.gov/alerts/active`,
33
+ },
34
+ global_settings: {
35
+ parent_events_only: true,
36
+ better_event_parsing: true,
37
+ ignore_geometry_parsing: false,
38
+ shapefile_coordinates: true,
39
+ filtering: {
40
+ events: [`Severe Thunderstorm Warning`],
41
+ filtered_icao: ["PAFC"],
42
+ ignored_icao: [],
43
+ ignored_events: [`Xx`, `Test Message`],
44
+ ugc_filter: [],
45
+ state_filter: [],
46
+ check_expired: true,
47
+ ignore_test_products: true,
48
+ },
49
+ eas_settings: {
50
+ directory: null,
51
+ intro_wav: null,
52
+ }
53
+ }
54
+ })
55
+
56
+ parser.on(`onEvents`, (alerts) => {
57
+ for (const alert of alerts) {
58
+ if (alert.geometry != null) {
59
+ console.log(`[${ new Date(alert.properties.issued).toLocaleString()}] ${alert.properties.event} for ${alert.properties.locations} (ID: ${alert.properties.details.tracking})`);
60
+ }
61
+ }
62
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES6",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Node",
6
+ "outDir": "dist",
7
+ "declaration": true,
8
+ "declarationDir": "dist/types",
9
+ "esModuleInterop": true,
10
+ "allowSyntheticDefaultImports": true,
11
+ "skipLibCheck": true
12
+ },
13
+ "include": ["src"]
14
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { defineConfig } from 'tsup'
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ outDir: 'dist',
6
+ format: ['esm', 'cjs'],
7
+ noExternal: ["@xmpp/client", "@xmpp/sasl", "@xmpp/sasl-plain"],
8
+ clean: true,
9
+ outExtension({ format }) {
10
+ return { js: format === 'esm' ? '.mjs' : '.cjs' }
11
+ },
12
+ esbuildOptions(options, context) {
13
+ options.outdir = `dist/${context.format}`
14
+ },
15
+ })