@atmosx/event-product-parser 3.0.62 → 3.0.63

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 (112) hide show
  1. package/README.md +6 -4
  2. package/dist/cjs/index.cjs +21216 -6908
  3. package/dist/esm/index.mjs +21207 -6900
  4. package/package.json +49 -47
  5. package/pnpm-workspace.yaml +4 -0
  6. package/src/@building/CreateEvent.ts +20 -22
  7. package/src/@building/GetEventAttachments.ts +8 -8
  8. package/src/@building/GetEventEnhancedName.ts +2 -4
  9. package/src/@building/GetEventGeometry.ts +5 -5
  10. package/src/@building/GetEventHeader.ts +11 -11
  11. package/src/@building/GetEventNodes.ts +12 -12
  12. package/src/@building/GetEventOffice.ts +11 -11
  13. package/src/@building/GetEventProperties.ts +60 -55
  14. package/src/@building/GetEventSignature.ts +7 -7
  15. package/src/@building/GetEventTags.ts +1 -1
  16. package/src/@building/GetEventTracking.ts +28 -32
  17. package/src/@core/ClearEvents.ts +7 -7
  18. package/src/@core/CreateListener.ts +2 -2
  19. package/src/@core/GetEvents.ts +2 -2
  20. package/src/@core/GetNodes.ts +2 -2
  21. package/src/@core/GetRandomEvent.ts +2 -2
  22. package/src/@core/GetVersion.ts +2 -2
  23. package/src/@core/ManualEvent.ts +20 -21
  24. package/src/@core/QueryStanza.ts +7 -7
  25. package/src/@core/SetNode.ts +32 -26
  26. package/src/@core/StartService.ts +18 -18
  27. package/src/@core/StopService.ts +8 -8
  28. package/src/@enums/Expressions.ts +1 -1
  29. package/src/@enums/Tags.ts +1 -1
  30. package/src/@events/ParseAPI.ts +44 -39
  31. package/src/@events/ParseText.ts +19 -19
  32. package/src/@events/ParseUGC.ts +21 -21
  33. package/src/@events/ParseVTEC.ts +32 -33
  34. package/src/@manager/MakeEvents.ts +33 -30
  35. package/src/@manager/RemoveEvent.ts +38 -34
  36. package/src/@manager/SetHash.ts +16 -11
  37. package/src/@manager/UpdateEvents.ts +10 -10
  38. package/src/@manager/UpdateNode.ts +13 -13
  39. package/src/@manager/ValidateEvents.ts +36 -37
  40. package/src/@modules/@database/GetCachedEvents.ts +10 -12
  41. package/src/@modules/@database/ImportBroadcastify.ts +12 -13
  42. package/src/@modules/@database/ImportShapefiles.ts +17 -18
  43. package/src/@modules/@database/ImportStanza.ts +11 -11
  44. package/src/@modules/@database/InitializeDatabase.ts +16 -16
  45. package/src/@modules/@eas/GenerateEASMessage.ts +53 -47
  46. package/src/@modules/@eas/GetPCM16.ts +11 -6
  47. package/src/@modules/@eas/GetSampledPCM16.ts +12 -6
  48. package/src/@modules/@eas/GetTTS.ts +12 -7
  49. package/src/@modules/@eas/GetWavPCM16.ts +5 -5
  50. package/src/@modules/@eas/SetAFSK.ts +11 -6
  51. package/src/@modules/@eas/SetAttentionTone.ts +9 -4
  52. package/src/@modules/@eas/SetNoise.ts +10 -5
  53. package/src/@modules/@eas/SetRadioEffect.ts +10 -5
  54. package/src/@modules/@eas/SetSameHeader.ts +20 -12
  55. package/src/@modules/@stanza/GetAwipsType.ts +14 -15
  56. package/src/@modules/@stanza/ValidateStanza.ts +25 -13
  57. package/src/@modules/@utilities/CreateHttp.ts +24 -24
  58. package/src/@modules/@utilities/GetMatched.ts +8 -3
  59. package/src/@modules/@utilities/GetSettings.ts +3 -3
  60. package/src/@modules/@utilities/GetShapeNearestPoint.ts +22 -17
  61. package/src/@modules/@utilities/QueueManager.ts +70 -0
  62. package/src/@modules/@utilities/SetCronSchedule.ts +20 -20
  63. package/src/@modules/@utilities/SetDebug.ts +10 -10
  64. package/src/@modules/@utilities/SetEventEmit.ts +15 -15
  65. package/src/@modules/@utilities/SetListener.ts +6 -6
  66. package/src/@modules/@utilities/SetSettings.ts +5 -5
  67. package/src/@modules/@utilities/SetSleep.ts +3 -3
  68. package/src/@modules/@utilities/SetTimeoutAction.ts +25 -25
  69. package/src/@modules/@utilities/SetWarning.ts +8 -8
  70. package/src/@modules/@xmpp/DeployXMPP.ts +16 -16
  71. package/src/@modules/@xmpp/ErrorXMPP.ts +4 -4
  72. package/src/@modules/@xmpp/OfflineXMPP.ts +11 -11
  73. package/src/@modules/@xmpp/OnlineXMPP.ts +16 -16
  74. package/src/@modules/@xmpp/ReconnectXMPP.ts +27 -27
  75. package/src/@modules/@xmpp/StanzaXMPP.ts +23 -23
  76. package/src/@parsers/@hvtec/HVExtract.ts +9 -9
  77. package/src/@parsers/@text/GetDescriptionFromProduct.ts +18 -19
  78. package/src/@parsers/@text/GetEmbededText.ts +3 -3
  79. package/src/@parsers/@text/GetStringText.ts +6 -6
  80. package/src/@parsers/@text/GetTextFromProduct.ts +10 -10
  81. package/src/@parsers/@text/GetXML.ts +5 -5
  82. package/src/@parsers/@ugc/GetCache.ts +2 -2
  83. package/src/@parsers/@ugc/{GetUGCHeader.ts → GetHeader.ts} +2 -2
  84. package/src/@parsers/@ugc/GetLocations.ts +5 -5
  85. package/src/@parsers/@ugc/GetZonePolygon.ts +10 -10
  86. package/src/@parsers/@ugc/GetZones.ts +1 -1
  87. package/src/@parsers/@ugc/SetCache.ts +11 -6
  88. package/src/@parsers/@ugc/UGCExtract.ts +10 -10
  89. package/src/@parsers/{@pvtec → @vtec}/VTECExtract.ts +19 -19
  90. package/src/@tasks/CreateTasks.ts +110 -0
  91. package/src/@tasks/TaskGenerateAudio.ts +34 -0
  92. package/src/@tasks/TaskGenerateJSON.ts +34 -0
  93. package/src/@tasks/TaskGenerateText.ts +34 -0
  94. package/src/@tasks/TaskSendNTFY.ts +91 -0
  95. package/src/@tasks/TaskSendWebhook.ts +100 -0
  96. package/src/@types/HVTEC.ts +4 -4
  97. package/src/@types/Hash.ts +3 -3
  98. package/src/@types/Settings.ts +1 -1
  99. package/src/@types/StanzaCompiled.ts +13 -13
  100. package/src/@types/UGC.ts +3 -3
  101. package/src/@types/VTEC.ts +10 -10
  102. package/src/{@types → @types-lower}/Event.ts +4 -4
  103. package/src/{@types → @types-lower}/Properties.ts +2 -1
  104. package/src/{@types → @types-lower}/Stanza.ts +1 -1
  105. package/src/bootstrap.ts +26 -26
  106. package/src/index.ts +30 -27
  107. package/tools/build.js +45 -0
  108. package/tsconfig.json +21 -1
  109. package/src/@manager/Tasks.ts +0 -246
  110. package/tsup.config.ts +0 -16
  111. /package/src/@parsers/{@pvtec → @vtec}/GetExpiry.ts +0 -0
  112. /package/src/{@types → @types-lower}/Attributes.ts +0 -0
package/package.json CHANGED
@@ -1,47 +1,49 @@
1
- {
2
- "name": "@atmosx/event-product-parser",
3
- "version": "3.0.62",
4
- "description": "NOAA Weather Wire & NWS API Parser - Built for standalone and Project AtmosphericX Integration.",
5
- "main": "dist/cjs/index.cjs",
6
- "module": "dist/esm/index.mjs",
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://github.com/AtmosphericX/event-product-parser",
10
- "branch": "v3-beta-branch"
11
- },
12
- "scripts": {
13
- "start": "cd ./test && node ./index.js",
14
- "build": "tsup && cd ./test && node ./index.js",
15
- "publish": "tsup && npm publish --access public",
16
- "publish-beta-branch": "tsup && npm publish --tag v3-beta-branch --access public"
17
- },
18
- "keywords": [
19
- "NWWS",
20
- "NOAA Weather Wire Service",
21
- "TypeScript",
22
- "XMPP",
23
- "Parser",
24
- "JavaScript",
25
- "CommonJS",
26
- "ESM"
27
- ],
28
- "author": "k3yomi, StarflightWx",
29
- "license": "MIT",
30
- "bugs": {
31
- "url": "https://github.com/AtmosphericX/event-product-parser/issues"
32
- },
33
- "homepage": "https://github.com/AtmosphericX/event-product-parser#readme",
34
- "dependencies": {
35
- "@xmpp/client": "0.14.0",
36
- "better-sqlite3": "12.9.0",
37
- "croner": "10.0.1",
38
- "jszip": "3.10.1",
39
- "polygon-clipping": "0.15.7",
40
- "shapefile": "0.6.6",
41
- "typescript": "5.9.3"
42
- },
43
- "devDependencies": {
44
- "@types/node": "25.2.0",
45
- "tsup": "8.5.1"
46
- }
47
- }
1
+ {
2
+ "name": "@atmosx/event-product-parser",
3
+ "version": "3.0.63",
4
+ "description": "NOAA Weather Wire & NWS API Parser - Built for standalone and Project AtmosphericX Integration.",
5
+ "main": "dist/cjs/index.cjs",
6
+ "module": "dist/esm/index.mjs",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/AtmosphericX/event-product-parser",
10
+ "branch": "v3-beta-branch"
11
+ },
12
+ "scripts": {
13
+ "start": "cd ./test && node ./index.js",
14
+ "build": "node ./tools/build.js && cd ./test && node index.js",
15
+ "watch": "node ./tools/build.js --watch",
16
+ "publish": "node ./tools/build.js && npm publish --access public",
17
+ "publish-beta-branch": "node ./tools/build.js && npm publish --tag v3-beta-branch --access public"
18
+ },
19
+ "keywords": [
20
+ "NWWS",
21
+ "NOAA Weather Wire Service",
22
+ "TypeScript",
23
+ "XMPP",
24
+ "Parser",
25
+ "JavaScript",
26
+ "CommonJS",
27
+ "ESM"
28
+ ],
29
+ "author": "k3yomi, StarflightWx",
30
+ "license": "MIT",
31
+ "bugs": {
32
+ "url": "https://github.com/AtmosphericX/event-product-parser/issues"
33
+ },
34
+ "homepage": "https://github.com/AtmosphericX/event-product-parser#readme",
35
+ "dependencies": {
36
+ "@xmpp/client": "0.14.0",
37
+ "better-sqlite3": "12.9.0",
38
+ "croner": "10.0.1",
39
+ "esbuild": "^0.28.1",
40
+ "fast-glob": "^3.3.3",
41
+ "jszip": "3.10.1",
42
+ "polygon-clipping": "0.15.7",
43
+ "shapefile": "0.6.6",
44
+ "typescript": "5.9.3"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "25.2.0"
48
+ }
49
+ }
@@ -0,0 +1,4 @@
1
+ allowBuilds:
2
+ better-sqlite3: true
3
+ esbuild: true
4
+ minimumReleaseAge: 43830
@@ -17,40 +17,38 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeStanzaCompiled } from "../@types/StanzaCompiled"
21
- import { TypeSettings } from "../@types/Settings"
22
- import { bootstrap } from "../bootstrap"
23
- import { ParseText } from "../@events/ParseText"
24
- import { ParseUGC } from "../@events/ParseUGC"
25
- import { ParseVTEC } from "../@events/ParseVTEC"
26
- import { ParseAPI } from "../@events/ParseAPI"
27
- import { ValidateEvents } from "../@manager/ValidateEvents"
20
+ import { TypeStanzaCompiled } from "types/StanzaCompiled"
21
+ import { TypeSettings } from "types/Settings"
22
+ import { Bootstrap } from "@bootstrap"
23
+ import { ParseText } from "@events/ParseText"
24
+ import { ParseUGC } from "@events/ParseUGC"
25
+ import { ParseVTEC } from "@events/ParseVTEC"
26
+ import { ParseAPI } from "@events/ParseAPI"
27
+ import { ValidateEvents } from "@manager/ValidateEvents"
28
28
 
29
- export const CreateEvent = async (stanza: TypeStanzaCompiled, ignorePushing?: boolean): Promise<void | string> => {
30
- const settings = bootstrap.settings as TypeSettings
29
+ export const CreateEvent = async (Stanza: TypeStanzaCompiled): Promise<void | string> => {
30
+ const settings = Bootstrap.Settings as TypeSettings
31
31
  const StanzaSettings = settings.NOAAWeatherWireServiceSettings.StanzaSettings;
32
32
 
33
- const isVtecEvent = (stanza.isVTEC && stanza.isUGC)
34
- const isUgcEvent = (!stanza.isVTEC && stanza.isUGC)
35
- const isTextEvent = (!stanza.isVTEC && !stanza.isUGC)
36
- const isNWWS = (stanza.isNWWS)
37
-
33
+ const isVtecEvent = (Stanza.VTEC && Stanza.UGC)
34
+ const isUgcEvent = (!Stanza.VTEC && Stanza.UGC)
35
+ const isTextEvent = (!Stanza.VTEC && !Stanza.UGC)
36
+
37
+ const isNWWS = (Stanza.NWWS)
38
38
  switch (true) {
39
39
  case (!isNWWS):
40
- await ParseAPI(stanza)
40
+ await ParseAPI(Stanza)
41
41
  break;
42
42
  case (isNWWS && !StanzaSettings.DisableVTEC && isVtecEvent):
43
- await ParseVTEC(stanza)
43
+ await ParseVTEC(Stanza)
44
44
  break;
45
45
  case (isNWWS && !StanzaSettings.DisableUGC && isUgcEvent):
46
- await ParseUGC(stanza)
46
+ await ParseUGC(Stanza)
47
47
  break;
48
48
  case (isNWWS && !StanzaSettings.DisableText && isTextEvent):
49
- await ParseText(stanza)
49
+ await ParseText(Stanza)
50
50
  break;
51
51
  }
52
- if (!ignorePushing) {
53
- await ValidateEvents(bootstrap.cache.processed)
54
- }
52
+ await ValidateEvents(Bootstrap.Cache.Parsed)
55
53
  return 'nothing picked';
56
54
  }
@@ -17,11 +17,11 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeEvent } from "../@types/Event"
21
- import { bootstrap } from "../bootstrap"
22
- import { EnumStates } from "../@enums/States"
23
- import { EnumExpressions } from "../@enums/Expressions"
24
- import { GetLatestIssuance } from "../@modules/@utilities/GetLatestIssuance";
20
+ import { TypeEvent } from "types-lower/Event"
21
+ import { Bootstrap } from "@bootstrap"
22
+ import { EnumStates } from "@enums/States"
23
+ import { EnumExpressions } from "@enums/Expressions"
24
+ import { GetLatestIssuance } from "@utilities/GetLatestIssuance"
25
25
 
26
26
  interface GetEventAttachmentsResponse {
27
27
  name: string
@@ -38,7 +38,7 @@ type BroadcastifyResponse = {
38
38
 
39
39
  export const GetEventAttachments = (event: TypeEvent): GetEventAttachmentsResponse[] | null => {
40
40
  let attachments = [];
41
- const settings = bootstrap.settings;
41
+ const settings = Bootstrap.Settings;
42
42
  const issuanceTime = GetLatestIssuance();
43
43
  const spcNumber = event?.properties?.discussion_parameters?.discussion_number;
44
44
  const watchNumber = event?.properties?.watch_parameters?.watch_number;
@@ -64,13 +64,13 @@ export const GetEventAttachments = (event: TypeEvent): GetEventAttachmentsRespon
64
64
  const lines = [`Northern`, `Southern`, `Eastern`, `Western`, `Inland`, `Costal`, `County`]
65
65
  const county = location?.split(',')[0]?.trim().replace(new RegExp(`^(${lines.join('|')}) `), '')
66
66
  const state = EnumStates[location?.split(',')[1]?.trim()]
67
- const feeds = bootstrap.database.prepare(`SELECT * FROM broadcastify WHERE state = ? AND county = ?`).all(state, county).sort((a, b) => {
67
+ const feeds = Bootstrap.Database.prepare(`SELECT * FROM broadcastify WHERE state = ? AND county = ?`).all(state, county).sort((a, b) => {
68
68
  const typeOrder = ['Other', 'Public Safety'];
69
69
  const indexA = typeOrder.indexOf(a.type);
70
70
  const indexB = typeOrder.indexOf(b.type);
71
71
  return indexA - indexB;
72
72
  })
73
- const tags = bootstrap.settings.BroadcastifySettings.BroadcastifyTags;
73
+ const tags = Bootstrap.Settings.BroadcastifySettings.BroadcastifyTags;
74
74
  const filtered = feeds.filter((feed: BroadcastifyResponse) => tags.includes(feed.type));
75
75
  if (filtered.length > 0) {
76
76
  filtered.map((filtered: BroadcastifyResponse) => {
@@ -17,10 +17,8 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeEvent } from "../@types/Event";
21
- import { TypeSettings } from "../@types/Settings";
22
- import { EnumEnhanced } from "../@enums/Enhanced"
23
- import { bootstrap } from "../bootstrap"
20
+ import { TypeEvent } from "types-lower/Event"
21
+ import { EnumEnhanced } from "@enums/Enhanced"
24
22
 
25
23
  export const GetEventEnhancedName = (event: TypeEvent): string => {
26
24
  let name = event?.properties?.event;
@@ -17,10 +17,10 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeSettings } from "../@types/Settings"
21
- import { TypeEvent } from "../@types/Event"
22
- import { GetSettings } from "../@modules/@utilities/GetSettings";
23
- import { getZonePolygon } from "../@parsers/@ugc/GetZonePolygon";
20
+ import { TypeSettings } from "types/Settings"
21
+ import { TypeEvent } from "types-lower/Event"
22
+ import { GetSettings } from "@utilities/GetSettings"
23
+ import { getZonePolygon } from "@parsers/ugc/GetZonePolygon"
24
24
 
25
25
  interface GetGeometryResponse {
26
26
  type: `Polygon` | `MultiPolygon`
@@ -36,7 +36,7 @@ export const GetEventGeometry = (event: TypeEvent): GetGeometryResponse => {
36
36
  coordinates: generated != null ? JSON.parse(Buffer.from(generated, 'base64').toString('utf-8')) : null
37
37
  }
38
38
  if (settings.GlobalSettings.UseShapefileCoordinates && generated == null && ugc != null) {
39
- geo = getZonePolygon({zones: ugc, isUnion: false})
39
+ geo = getZonePolygon({Zones: ugc, Union: false})
40
40
  if (geo == null) {
41
41
  geo = {
42
42
  type: `Polygon`,
@@ -17,21 +17,21 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypePVTEC } from "../@types/VTEC";
21
- import { TypeEventProperties } from "../@types/Properties";
20
+ import { TypeVTEC } from "types/VTEC"
21
+ import { TypeEventProperties } from "types-lower/Properties"
22
22
 
23
23
  interface GetHeaderOptions {
24
- properties: TypeEventProperties
25
- vtec?: TypePVTEC
26
- getType: {
27
- type: string
28
- prefix: string
24
+ Properties: TypeEventProperties
25
+ VTEC?: TypeVTEC
26
+ Type: {
27
+ Type: string
28
+ Prefix: string
29
29
  }
30
30
  }
31
31
 
32
- export const GetEventHeader = (options: GetHeaderOptions): string => {
33
- const properties = options.properties
34
- const vtec = options.vtec ?? null
32
+ export const GetEventHeader = ({ Properties, VTEC, Type }: GetHeaderOptions): string => {
33
+ const properties = Properties
34
+ const vtec = VTEC ?? null
35
35
  const ugc = properties.geocode.ugc != null ? properties.geocode.ugc.join(`-`) : `0`;
36
- return `ZCZC-ATMOSX-${options.getType.prefix}-${ugc}-${vtec?.status ?? `Issued`}-${new Date().toISOString().replace(/[-:]/g, '').split('.')[0]}-${properties.geocode.office.office ?? `KWNS`}`
36
+ return `ZCZC-ATMOSX-${Type?.Prefix}-${ugc}-${vtec?.Status ?? `Issued`}-${new Date().toISOString().replace(/[-:]/g, '').split('.')[0]}-${properties.geocode.office.office ?? `KWNS`}`
37
37
  }
@@ -17,10 +17,10 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeEvent } from "../@types/Event"
21
- import { bootstrap } from "../bootstrap"
22
- import { GetEventGeometry } from "./GetEventGeometry"
23
- import { GetShapeNearestPoint } from "../@modules/@utilities/GetShapeNearestPoint"
20
+ import { TypeEvent } from "types-lower/Event"
21
+ import { Bootstrap } from "@bootstrap"
22
+ import { GetEventGeometry } from "@building/GetEventGeometry"
23
+ import { GetShapeNearestPoint } from "@utilities/GetShapeNearestPoint"
24
24
 
25
25
  interface GetEventNodesResponse {
26
26
  nodes: {
@@ -36,9 +36,9 @@ interface GetEventNodesResponse {
36
36
  }
37
37
 
38
38
  export const GetEventNodes = async (event: TypeEvent): Promise<GetEventNodesResponse> => {
39
- const nodes = bootstrap.cache.nodes.features;
39
+ const nodes = Bootstrap.Cache.Nodes.features;
40
40
  if (!nodes || nodes.length === 0) {
41
- return { nodes: [], filtered: true, updated: Date.now() };
41
+ return { nodes: [], filtered: false, updated: Date.now() };
42
42
  }
43
43
  const metadata = { nodes: [], proximity: false, filtered: false };
44
44
  const geometry = await GetEventGeometry(event);
@@ -47,23 +47,23 @@ export const GetEventNodes = async (event: TypeEvent): Promise<GetEventNodesResp
47
47
  }
48
48
  for (const node of nodes) {
49
49
  const [longitude, latitude] = node.geometry.coordinates;
50
- const getPoint = GetShapeNearestPoint(geometry.coordinates, [longitude, latitude])
51
- const miles = getPoint.distance ?? null;
50
+ const getPoint = GetShapeNearestPoint({ Coordinates: geometry.coordinates, Point: [longitude, latitude] });
51
+ const miles = getPoint.Distance ?? null;
52
52
  const kilometers = Number((miles * 1.609344).toFixed(3));
53
53
 
54
54
  const info = {
55
55
  id: node.properties?.identifier,
56
56
  coordinates: [longitude, latitude],
57
- nearest: getPoint.point,
57
+ nearest: getPoint.Point,
58
58
  miles,
59
59
  kilometers,
60
60
  proximity: false
61
61
  }
62
- metadata.nodes.push(info)
63
- if (miles != null && (bootstrap.settings.GlobalSettings.EventFiltering.NodeLocationFiltering) && (miles < bootstrap.settings.GlobalSettings.NodeMaxDistance)) {
64
- metadata.proximity = true;
62
+ if (miles != null && (miles < Bootstrap.Settings.GlobalSettings.NodeMaxDistance)) {
65
63
  info.proximity = true;
64
+ metadata.proximity = true;
66
65
  }
66
+ metadata.nodes.push(info)
67
67
  }
68
68
  return {
69
69
  nodes: metadata.nodes,
@@ -17,14 +17,14 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeAttributes } from "../@types/Attributes";
21
- import { TypePVTEC } from "../@types/VTEC";
22
- import { EnumICAO } from "../@enums/ICAO";
20
+ import { TypeAttributes } from "types-lower/Attributes"
21
+ import { TypeVTEC } from "types/VTEC"
22
+ import { EnumICAO } from "@enums/ICAO"
23
23
 
24
24
  interface GetOfficeOptions {
25
- attributes: TypeAttributes
26
- organization: string
27
- pVtec: TypePVTEC
25
+ Attributes: TypeAttributes
26
+ Organization: string
27
+ VTEC: TypeVTEC
28
28
  }
29
29
 
30
30
  interface GetOfficeResponse {
@@ -32,11 +32,11 @@ interface GetOfficeResponse {
32
32
  name: string | null
33
33
  }
34
34
 
35
- export const GetEventOffice = (options: GetOfficeOptions): GetOfficeResponse => {
36
- const office = options.pVtec != null
37
- ? options.pVtec?.tracking?.split(`.`)[0] : (options.attributes?.cccc ??
38
- (options.organization != null ?
39
- (Array.isArray(options.organization) ? options.organization?.[0] : options.organization)
35
+ export const GetEventOffice = ({ Attributes, Organization, VTEC }: GetOfficeOptions): GetOfficeResponse => {
36
+ const office = VTEC != null
37
+ ? VTEC?.Tracking?.split(`.`)[0] : (Attributes?.cccc ??
38
+ (Organization != null ?
39
+ (Array.isArray(Organization) ? Organization?.[0] : Organization)
40
40
  : null));
41
41
  const name = EnumICAO?.[office] ?? null;
42
42
  return { office, name };
@@ -17,76 +17,81 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeEventProperties } from "../@types/Properties";
21
- import { TypeAttributes } from "../@types/Attributes";
22
- import { TypeUGC } from "../@types/UGC";
23
- import { TypePVTEC } from "../@types/VTEC";
24
- import { TypeHVTEC } from "../@types/HVTEC";
25
- import { EnumExpressions } from "../@enums/Expressions";
26
- import { GetDescriptionFromProduct } from "../@parsers/@text/GetDescriptionFromProduct";
27
- import { getPolygonFromProduct } from "../@parsers/@text/GetPolygonFromProduct";
28
- import { GetTextFromProduct } from "../@parsers/@text/GetTextFromProduct";
29
- import { GetEventOffice } from "./GetEventOffice";
30
- import { GetEventTags } from "./GetEventTags";
20
+ import { TypeEventProperties } from "types-lower/Properties"
21
+ import { TypeAttributes } from "types-lower/Attributes"
22
+ import { TypeUGC } from "types/UGC"
23
+ import { TypeVTEC } from "types/VTEC"
24
+ import { TypeHVTEC } from "types/HVTEC"
25
+ import { EnumExpressions } from "@enums/Expressions"
26
+ import { GetDescriptionFromProduct } from "@parsers/text/GetDescriptionFromProduct"
27
+ import { getPolygonFromProduct } from "@parsers/text/GetPolygonFromProduct"
28
+ import { GetTextFromProduct } from "@parsers/text/GetTextFromProduct"
29
+ import { GetEventOffice } from "@building/GetEventOffice"
30
+ import { GetEventTags } from "@building/GetEventTags"
31
31
 
32
32
  interface GetEventPropertiesOptions {
33
- message: string
34
- attributes: TypeAttributes
35
- ugc?: TypeUGC
36
- pVtec?: TypePVTEC
37
- hVtec?: TypeHVTEC
33
+ Message: string
34
+ Attributes: TypeAttributes
35
+ UGC?: TypeUGC
36
+ VTEC?: TypeVTEC
38
37
  }
39
38
 
40
- export const GetEventProperties = (options: GetEventPropertiesOptions): TypeEventProperties => {
41
- const organization = options.message.match(EnumExpressions.wmo)?.[0] ?? null
42
- const polygons = getPolygonFromProduct(options.message)
39
+
40
+ export const GetEventProperties = ({ Message, Attributes, UGC, VTEC }: GetEventPropertiesOptions): TypeEventProperties => {
41
+ const organization = Message.match(EnumExpressions.wmo)?.[0] ?? null
42
+ const polygons = getPolygonFromProduct(Message)
43
43
  const properties = {
44
- locations: options?.ugc?.locations?.join(`; `) ?? null,
45
- locations_array: options?.ugc?.locations ?? [],
46
- description: GetDescriptionFromProduct({ message: options.message, handle: options?.pVtec?.vtec ?? null }),
47
- attributes: options.attributes,
44
+ locations: UGC?.Locations?.join(`; `) ?? null,
45
+ locations_array: UGC?.Locations ?? [],
46
+ location_states: [...new Set(
47
+ UGC?.Locations
48
+ ?.map((location: string) => location.match(/,\s*([A-Z]{2})\b/)?.[1])
49
+ .filter(Boolean) ?? []
50
+ )],
51
+ description: GetDescriptionFromProduct({ Message: Message, Handle: VTEC?.Raw ?? null }),
52
+ attributes: Attributes,
48
53
  geocode: {
49
- office: GetEventOffice({ attributes: options.attributes, organization: organization, pVtec: options.pVtec }),
54
+ office: GetEventOffice({ Attributes: Attributes, Organization: organization, VTEC: VTEC }),
50
55
  organization: organization,
51
- ugc: options?.ugc?.zones ?? [],
56
+ ugc: UGC?.Zones ?? [],
52
57
  polygon: polygons.length > 0 ? Buffer.from(JSON.stringify([polygons])).toString('base64') : null,
53
58
  polygon_generated: polygons.length > 0 ? true : false
54
59
  },
55
60
  parameters: {
56
- tags: GetEventTags(options.message),
57
- instructions: GetTextFromProduct({ message: options.message, find: [`For your protection`, `do not`, `use extreme caution`], append: `...`, removal: [`.`]}) ?? null,
58
- source: GetTextFromProduct({ message: options.message, find: [`SOURCE...`], removal: [`.`]}) ?? null,
59
- hazards: GetTextFromProduct({ message: options.message, find: [`HAZARD...`], removal: [`.`]}) ?? null,
60
- impacts: GetTextFromProduct({ message: options.message, find: [`IMPACT...`], removal: [`.`]}) ?? null,
61
- estimated_hail_size: GetTextFromProduct({ message: options.message, find: [`MAX HAIL SIZE...`, `HAIL...`], removal: ['in']}) ?? null,
62
- estimated_wind_gusts: GetTextFromProduct({ message: options.message, find: [`MAX WIND GUST...`, `WIND...`]}) ?? null,
63
- damage_threat: GetTextFromProduct({ message: options.message, find: [`DAMAGE THREAT...`], removal: []}) ?? null,
64
- tornado_threat: GetTextFromProduct({ message: options.message, find: [`TORNADO...`, `WATERSPOUT...`] }) ?? null,
65
- flood_threat: GetTextFromProduct({ message: options.message, find: [`FLASH FLOOD...`]}) ?? null,
66
- wind_threat: GetTextFromProduct({ message: options.message, find: [`WIND THREAT...`]}) ?? null,
67
- hail_threat: GetTextFromProduct({ message: options.message, find: [`HAIL THREAT...`], removal: []}) ?? null,
61
+ tags: GetEventTags(Message),
62
+ instructions: GetTextFromProduct({ Message: Message, Find: [`For your protection`, `do not`, `use extreme caution`], Append: `...`, Removal: [`.`]}) ?? null,
63
+ source: GetTextFromProduct({ Message: Message, Find: [`SOURCE...`], Removal: [`.`]}) ?? null,
64
+ hazards: GetTextFromProduct({ Message: Message, Find: [`HAZARD...`], Removal: [`.`]}) ?? null,
65
+ impacts: GetTextFromProduct({ Message: Message, Find: [`IMPACT...`], Removal: [`.`]}) ?? null,
66
+ estimated_hail_size: GetTextFromProduct({ Message: Message, Find: [`MAX HAIL SIZE...`, `HAIL...`], Removal: ['in']}) ?? null,
67
+ estimated_wind_gusts: GetTextFromProduct({ Message: Message, Find: [`MAX WIND GUST...`, `WIND...`]}) ?? null,
68
+ damage_threat: GetTextFromProduct({ Message: Message, Find: [`DAMAGE THREAT...`], Removal: []}) ?? null,
69
+ tornado_threat: GetTextFromProduct({ Message: Message, Find: [`TORNADO...`, `WATERSPOUT...`] }) ?? null,
70
+ flood_threat: GetTextFromProduct({ Message: Message, Find: [`FLASH FLOOD...`]}) ?? null,
71
+ wind_threat: GetTextFromProduct({ Message: Message, Find: [`WIND THREAT...`]}) ?? null,
72
+ hail_threat: GetTextFromProduct({ Message: Message, Find: [`HAIL THREAT...`], Removal: []}) ?? null,
68
73
  },
69
74
  discussion_parameters: {
70
- discussion_number: GetTextFromProduct({ message: options.message, find: [`Mesoscale Discussion `], removal: [`Mesoscale Discussion`, `Number`, `...`] })?.toString()?.padStart(4, "0") ?? null,
71
- discussion_concerning: GetTextFromProduct({ message: options.message, find: [`Concerning...`] }) ?? null,
72
- discussion_max_tornado: GetTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK TORNADO INTENSITY...`] }) ?? null,
73
- discussion_max_hail: GetTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK HAIL SIZE...`] }) ?? null,
74
- discussion_max_wind: GetTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK WIND GUST...`] }) ?? null,
75
- discussion_watch_issuance: GetTextFromProduct({ message: options.message, find: [`Probability of Watch Issuance...`], removal: [`percent`]}) ?? null,
75
+ discussion_number: GetTextFromProduct({ Message: Message, Find: [`Mesoscale Discussion `], Removal: [`Mesoscale Discussion`, `Number`, `...`] })?.toString()?.padStart(4, "0") ?? null,
76
+ discussion_concerning: GetTextFromProduct({ Message: Message, Find: [`Concerning...`] }) ?? null,
77
+ discussion_max_tornado: GetTextFromProduct({ Message: Message, Find: [`MOST PROBABLE PEAK TORNADO INTENSITY...`] }) ?? null,
78
+ discussion_max_hail: GetTextFromProduct({ Message: Message, Find: [`MOST PROBABLE PEAK HAIL SIZE...`] }) ?? null,
79
+ discussion_max_wind: GetTextFromProduct({ Message: Message, Find: [`MOST PROBABLE PEAK WIND GUST...`] }) ?? null,
80
+ discussion_watch_issuance: GetTextFromProduct({ Message: Message, Find: [`Probability of Watch Issuance...`], Removal: [`percent`]}) ?? null,
76
81
  },
77
82
  watch_parameters: {
78
- watch_number: options?.pVtec?.is_watch ? ( GetTextFromProduct({ message: options.message, find: [`ITIES FOR`, `UPDATE FOR`, `Watch Number `], removal: [`%`, `<`, `:`] })?.replace(/(WT|WS|)/g, '')?.trim()?.toString()?.padStart(4, "0") ?? options?.pVtec?.tracking?.slice(-4)?.toString()?.padStart(4, "0") ?? null) : null,
79
- watch_type: options.message.includes(`TORNADO WATCH`) ? `Tornado` : options?.message.includes(`SEVERE`) ? `Severe` : null,
80
- additional_tornadoes_probability: GetTextFromProduct({ message: options.message, find: [`PROB OF 2 OR MORE TORNADOES`], removal: [`%`, `<`, `:`] }) ?? null,
81
- strong_tornadoes_probability: GetTextFromProduct({ message: options.message, find: [`PROB OF 1 OR MORE STRONG /EF2-EF5/ TORNADOES`], removal: [`%`, `<`, `:`] }) ?? null,
82
- severe_wind_probability: GetTextFromProduct({ message: options.message, find: [`PROB OF 10 OR MORE SEVERE WIND EVENTS`], removal: [`%`, `<`, `:`] }) ?? null,
83
- severe_hail_probability: GetTextFromProduct({ message: options.message, find: [`PROB OF 10 OR MORE SEVERE HAIL EVENTS`], removal: [`%`, `<`, `:`] }) ?? null,
84
- hail_2in_probability: GetTextFromProduct({ message: options.message, find: [`PROB OF 1 OR MORE HAIL EVENTS >= 2 INCHES`], removal: [`%`, `<`, `:`] }) ?? null,
85
- combined_hail_wind_probability: GetTextFromProduct({ message: options.message, find: [`PROB OF 6 OR MORE COMBINED SEVERE HAIL/WIND EVENTS`], removal: [`%`, `<`, `:`] }) ?? null,
86
- max_hail_in: GetTextFromProduct({ message: options.message, find: [`MAX HAIL /INCHES/`], removal: [`%`, `<`, `:`] }) ?? null,
87
- max_wind_surface: GetTextFromProduct({ message: options.message, find: [`MAX WIND GUSTS SURFACE /KNOTS/`], removal: [`%`, `<`, `:`] }) ?? null,
88
- max_tops_x100feet: GetTextFromProduct({ message: options.message, find: [`MAX TOPS /X 100 FEET/`], removal: [`%`, `<`, `:`] }) ?? null,
89
- pds_watch: (GetTextFromProduct({ message: options.message, find: [`PARTICULARLY DANGEROUS SITUATION`], removal: [`%`, `<`, `:`] }) === `YES` ? true : null)
83
+ watch_number: VTEC?.Watch ? ( GetTextFromProduct({ Message: Message, Find: [`ITIES FOR`, `UPDATE FOR`, `Watch Number `], Removal: [`%`, `<`, `:`] })?.replace(/(WT|WS|)/g, '')?.trim()?.toString()?.padStart(4, "0") ?? VTEC?.Tracking?.slice(-4)?.toString()?.padStart(4, "0") ?? null) : null,
84
+ watch_type: Message.includes(`TORNADO WATCH`) ? `Tornado` : Message.includes(`SEVERE`) ? `Severe` : null,
85
+ additional_tornadoes_probability: GetTextFromProduct({ Message: Message, Find: [`PROB OF 2 OR MORE TORNADOES`], Removal: [`%`, `<`, `:`] }) ?? null,
86
+ strong_tornadoes_probability: GetTextFromProduct({ Message: Message, Find: [`PROB OF 1 OR MORE STRONG /EF2-EF5/ TORNADOES`], Removal: [`%`, `<`, `:`] }) ?? null,
87
+ severe_wind_probability: GetTextFromProduct({ Message: Message, Find: [`PROB OF 10 OR MORE SEVERE WIND EVENTS`], Removal: [`%`, `<`, `:`] }) ?? null,
88
+ severe_hail_probability: GetTextFromProduct({ Message: Message, Find: [`PROB OF 10 OR MORE SEVERE HAIL EVENTS`], Removal: [`%`, `<`, `:`] }) ?? null,
89
+ hail_2in_probability: GetTextFromProduct({ Message: Message, Find: [`PROB OF 1 OR MORE HAIL EVENTS >= 2 INCHES`], Removal: [`%`, `<`, `:`] }) ?? null,
90
+ combined_hail_wind_probability: GetTextFromProduct({ Message: Message, Find: [`PROB OF 6 OR MORE COMBINED SEVERE HAIL/WIND EVENTS`], Removal: [`%`, `<`, `:`] }) ?? null,
91
+ max_hail_in: GetTextFromProduct({ Message: Message, Find: [`MAX HAIL /INCHES/`], Removal: [`%`, `<`, `:`] }) ?? null,
92
+ max_wind_surface: GetTextFromProduct({ Message: Message, Find: [`MAX WIND GUSTS SURFACE /KNOTS/`], Removal: [`%`, `<`, `:`] }) ?? null,
93
+ max_tops_x100feet: GetTextFromProduct({ Message: Message, Find: [`MAX TOPS /X 100 FEET/`], Removal: [`%`, `<`, `:`] }) ?? null,
94
+ pds_watch: (GetTextFromProduct({ Message: Message, Find: [`PARTICULARLY DANGEROUS SITUATION`], Removal: [`%`, `<`, `:`] }) === `YES` ? true : null)
90
95
  }
91
96
  }
92
97
  if (isNaN(Number(properties.watch_parameters.watch_number))) {
@@ -17,12 +17,12 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeEvent } from "../@types/Event";
21
- import { EnumCorrelations } from "../@enums/Correlations";
22
- import { EnumCancellation } from "../@enums/Cancellation";
23
- import { EnumTesting} from "../@enums/Testing"
24
- import { EnumProducts } from "../@enums/Products";
25
- import { EnumHail } from "../@enums/Hail"
20
+ import { TypeEvent } from "types-lower/Event"
21
+ import { EnumCorrelations } from "@enums/Correlations"
22
+ import { EnumCancellation } from "@enums/Cancellation"
23
+ import { EnumTesting} from "@enums/Testing"
24
+ import { EnumProducts } from "@enums/Products"
25
+ import { EnumHail } from "@enums/Hail"
26
26
 
27
27
  export const GetEventSignature = (event: TypeEvent): TypeEvent => {
28
28
  const properties = event?.properties;
@@ -44,7 +44,7 @@ export const GetEventSignature = (event: TypeEvent): TypeEvent => {
44
44
  properties.status_metadata = { ...properties.status_metadata, is_expired: true };
45
45
  }
46
46
 
47
- const getProduct = vtec?.vtec?.split(`.`)[0]?.replace(`/`, ``)
47
+ const getProduct = vtec?.Raw?.split(`.`)[0]?.replace(`/`, ``)
48
48
  const isTestProduct = EnumProducts[getProduct] == `Test Product`
49
49
  if (isTestProduct || EnumTesting.some(sig => properties.description?.toLowerCase().includes(sig.toLowerCase()) ?? properties?.parameters?.instructions?.toLowerCase().includes(sig.toLowerCase()))) {
50
50
  properties.status_metadata = { ...properties.status_metadata, is_test: true }
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- import { EnumTags } from "../@enums/Tags";
20
+ import { EnumTags } from "@enums/Tags"
21
21
 
22
22
  export const GetEventTags = (message: string): string[] => {
23
23
  if (!message) return [];