@atmosx/event-product-parser 3.0.48 → 3.0.51

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 +48 -21
  2. package/dist/cjs/index.cjs +1895 -1812
  3. package/dist/esm/index.mjs +1898 -1815
  4. package/package.json +2 -2
  5. package/src/@building/building.attachments.ts +5 -5
  6. package/src/@building/building.create.ts +19 -5
  7. package/src/@building/building.enhance.ts +1 -1
  8. package/src/@building/building.geometry.ts +1 -1
  9. package/src/@building/building.polygon.ts +1 -2
  10. package/src/@building/building.signature.ts +0 -1
  11. package/src/@building/building.tracking.ts +4 -4
  12. package/src/@building/building.validate.ts +11 -6
  13. package/src/@core/core.clearEvents.ts +0 -1
  14. package/src/@core/core.createEvent.ts +0 -1
  15. package/src/@core/core.getEvents.ts +0 -1
  16. package/src/@core/core.getNodes.ts +0 -1
  17. package/src/@core/core.getRandomEvent.ts +0 -1
  18. package/src/@core/core.getVersion.ts +0 -1
  19. package/src/@dictionaries/dictionaries.awips.ts +3 -3
  20. package/src/@events/events.api.ts +7 -9
  21. package/src/@events/events.text.ts +5 -6
  22. package/src/@events/events.ugc.ts +5 -5
  23. package/src/@events/events.vtec.ts +4 -5
  24. package/src/@manager/manager.mkEvent.ts +17 -12
  25. package/src/@manager/manager.rmEvent.ts +5 -3
  26. package/src/@manager/manager.setHash.ts +0 -1
  27. package/src/@manager/manager.updateEvents.ts +1 -3
  28. package/src/@manager/manager.updateListener.ts +22 -27
  29. package/src/@manager/manager.updateNodes.ts +2 -3
  30. package/src/@modules/@database/database.cache.ts +6 -4
  31. package/src/@modules/@database/database.init.ts +5 -4
  32. package/src/@modules/@database/database.shapefiles.ts +11 -11
  33. package/src/@modules/@database/database.stanza.ts +2 -3
  34. package/src/@modules/@eas/eas.setAFSK.ts +0 -1
  35. package/src/@modules/@eas/eas.setAsciiToBits.ts +0 -1
  36. package/src/@modules/@eas/eas.setEasTone.ts +6 -2
  37. package/src/@modules/@eas/eas.setNoise.ts +1 -0
  38. package/src/@modules/@eas/eas.setRadioEffect.ts +1 -0
  39. package/src/@modules/@eas/eas.setSameHeader.ts +0 -1
  40. package/src/@modules/@utilities/utilities.getMatched.ts +33 -0
  41. package/src/@modules/@utilities/utilities.setDebug.ts +38 -0
  42. package/src/@modules/@utilities/utilities.setTimeoutAction.ts +5 -1
  43. package/src/@modules/@xmpp/xmpp.xDeploy.ts +1 -2
  44. package/src/@modules/@xmpp/xmpp.xError.ts +0 -2
  45. package/src/@modules/@xmpp/xmpp.xOffline.ts +0 -1
  46. package/src/@modules/@xmpp/xmpp.xOnline.ts +2 -2
  47. package/src/@parsers/@text/text.getEmbed.ts +0 -2
  48. package/src/@parsers/@ugc/ugc.coordinates.ts +2 -1
  49. package/src/@parsers/@ugc/ugc.getCache.ts +24 -0
  50. package/src/@parsers/@ugc/ugc.locations.ts +35 -7
  51. package/src/@parsers/@ugc/ugc.setCache.ts +28 -0
  52. package/src/@types/type.settings.ts +1 -0
  53. package/src/bootstrap.ts +4 -1
  54. package/test.js +15 -21
  55. package/tsup.config.ts +1 -1
  56. package/dist/index.d.mts +0 -299
  57. package/dist/index.d.ts +0 -299
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atmosx/event-product-parser",
3
- "version": "3.0.48",
3
+ "version": "3.0.51",
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",
@@ -12,7 +12,6 @@
12
12
  "scripts": {
13
13
  "start": "cd ./test && node ./index.js",
14
14
  "build": "tsup && cd ./test && node ./index.js",
15
- "heap-memory-errors": "node --heap-prof --heap-prof-name=heap-profile-%p.heapsnapshot ./test/index.js",
16
15
  "publish": "tsup && npm publish --access public",
17
16
  "publish-beta-branch": "tsup && npm publish --tag v3-beta-branch --access public"
18
17
  },
@@ -39,6 +38,7 @@
39
38
  "express": "5.2.1",
40
39
  "express-ws": "5.0.2",
41
40
  "jszip": "3.10.1",
41
+ "p-queue": "^9.3.0",
42
42
  "polygon-clipping": "0.15.7",
43
43
  "say": "0.16.0",
44
44
  "shapefile": "0.6.6",
@@ -17,11 +17,11 @@
17
17
 
18
18
  */
19
19
 
20
- import { bootstrap } from "../bootstrap"
21
20
  import { TypeEvent } from "../@types/type.event"
22
- import { getLatestIssuance } from "../@modules/@utilities/utilities.getLatestIssuance";
21
+ import { bootstrap } from "../bootstrap"
23
22
  import { dict_states } from "../@dictionaries/dictionaries.states"
24
23
  import { dict_expressions } from "../@dictionaries/dictionaries.expressions"
24
+ import { getLatestIssuance } from "../@modules/@utilities/utilities.getLatestIssuance";
25
25
 
26
26
  interface GetEventAttachmentsResponse {
27
27
  name: string
@@ -43,9 +43,9 @@ export const getEventAttachments = (event: TypeEvent): GetEventAttachmentsRespon
43
43
  const watchNumber = event?.properties?.watch_parameters?.watch_number;
44
44
  const locations = event?.properties?.locations_array;
45
45
  const events = [
46
- { target: "Day 1", attachment: `https://www.spc.noaa.gov/products/outlook/day1otlk_${issuanceTime}.png` },
47
- { target: "Day 2", attachment: `https://www.spc.noaa.gov/products/outlook/day2otlk.png` },
48
- { target: "Day 3", attachment: `https://www.spc.noaa.gov/products/outlook/day3otlk.png` },
46
+ { target: "SPC Day 1 Outlook", attachment: `https://www.spc.noaa.gov/products/outlook/day1otlk_${issuanceTime}.png` },
47
+ { target: "SPC Day 2 Outlook", attachment: `https://www.spc.noaa.gov/products/outlook/day2otlk.png` },
48
+ { target: "SPC Day 3 Outlook", attachment: `https://www.spc.noaa.gov/products/outlook/day3otlk.png` },
49
49
  { target: "Mesoscale Discussion", attachment: `https://www.spc.noaa.gov/products/md/mcd${spcNumber}.png` },
50
50
  { target: "Tornado Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
51
51
  { target: "PDS Tornado Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
@@ -24,8 +24,9 @@ import { text } from "../@events/events.text"
24
24
  import { ugc } from "../@events/events.ugc"
25
25
  import { vtec } from "../@events/events.vtec"
26
26
  import { api } from "../@events/events.api"
27
+ import { validateEvents } from "./building.validate"
27
28
 
28
- export const createEvent = async (stanza: TypeStanzaCompiled): Promise<void | string> => {
29
+ export const createEvent = async (stanza: TypeStanzaCompiled, ignorePushing?: boolean): Promise<void | string> => {
29
30
  const settings = bootstrap.settings as TypeSettings
30
31
  const StanzaSettings = settings.NOAAWeatherWireServiceSettings.StanzaSettings;
31
32
 
@@ -34,9 +35,22 @@ export const createEvent = async (stanza: TypeStanzaCompiled): Promise<void | st
34
35
  const isTextEvent = (!stanza.isVTEC && !stanza.isUGC)
35
36
  const isNWWS = (stanza.isNWWS)
36
37
 
37
- if (!isNWWS) return await api(stanza)
38
- if (!StanzaSettings.DisableVTEC && isVtecEvent) return await vtec(stanza)
39
- if (!StanzaSettings.DisableUGC && isUgcEvent) return await ugc(stanza);
40
- if (!StanzaSettings.DisableText && isTextEvent) return await text(stanza);
38
+ switch (true) {
39
+ case (!isNWWS):
40
+ await api(stanza)
41
+ break;
42
+ case (isNWWS && !StanzaSettings.DisableVTEC && isVtecEvent):
43
+ await vtec(stanza)
44
+ break;
45
+ case (isNWWS && !StanzaSettings.DisableUGC && isUgcEvent):
46
+ await ugc(stanza)
47
+ break;
48
+ case (isNWWS && !StanzaSettings.DisableText && isTextEvent):
49
+ await text(stanza)
50
+ break;
51
+ }
52
+ if (!ignorePushing) {
53
+ validateEvents(bootstrap.cache.processed)
54
+ }
41
55
  return 'nothing picked';
42
56
  }
@@ -19,8 +19,8 @@
19
19
 
20
20
  import { TypeEvent } from "../@types/type.event";
21
21
  import { TypeSettings } from "../@types/type.settings";
22
- import { bootstrap } from "../bootstrap"
23
22
  import { dict_enhanced } from "../@dictionaries/dictionaries.enhanced"
23
+ import { bootstrap } from "../bootstrap"
24
24
 
25
25
  export const getEventEnhancedName = (event: TypeEvent): string => {
26
26
  const configurations = bootstrap.settings as TypeSettings
@@ -17,9 +17,9 @@
17
17
 
18
18
  */
19
19
 
20
- import { getSettings } from "../@modules/@utilities/utilities.getSettings";
21
20
  import { TypeSettings } from "../@types/type.settings"
22
21
  import { TypeEvent } from "../@types/type.event"
22
+ import { getSettings } from "../@modules/@utilities/utilities.getSettings";
23
23
  import { getZonePolygon } from "../@parsers/@ugc/ugc.coordinates";
24
24
 
25
25
  interface GetGeometryResponse {
@@ -17,10 +17,9 @@
17
17
 
18
18
  */
19
19
 
20
-
21
20
  import { TypeEvent } from "../@types/type.event"
22
- import { getEventGeometry } from "./building.geometry"
23
21
  import { bootstrap } from "../bootstrap"
22
+ import { getEventGeometry } from "./building.geometry"
24
23
  import { getShapeNearestPoint } from "../@modules/@utilities/utilities.getShapeNearestPoint"
25
24
 
26
25
  interface GetEventNodesResponse {
@@ -24,7 +24,6 @@ import { dict_testing} from "../@dictionaries/dictionaries.testing"
24
24
  import { dict_products } from "../@dictionaries/dictionaries.products";
25
25
  import { dict_hail } from "../@dictionaries/dictionaries.hail"
26
26
 
27
-
28
27
  export const getEventSignature = (event: TypeEvent): TypeEvent => {
29
28
  const properties = event?.properties;
30
29
  const vtec = event?.properties?.metadata?.vtec
@@ -57,12 +57,12 @@ export const getEventTracking = (options: GetTrackingOptions): string => {
57
57
  return `${splitPVTEC[2]}.${splitPVTEC[3]}.${splitPVTEC[4]}.${splitPVTEC[5]}`;
58
58
  }
59
59
  const wmoMatch = options.organization?.wmoidentifier?.match(/([A-Z]{4}\d{2})\s+([A-Z]{4})/);
60
- const station = wmoMatch?.[2] ?? 'N/A';
60
+ const station = wmoMatch?.[2] ?? '---';
61
61
  if (options.organization.featureId) {
62
62
  const idMatch = options.organization.featureId.match(/([a-f0-9]+)\.(\d+)\.(\d+)$/);
63
- return `${station}.${idMatch?.[0]?.replace(/\./g, '') ?? 'N/A'}`;
63
+ return `${station}.${idMatch?.[0]?.replace(/\./g, '') ?? '---'}`;
64
64
  }
65
- const id = wmoMatch?.[1] ?? 'N/A';
66
- return `${station}.${id?.replace(/\./g, '') ?? 'N/A'}`;
65
+ const id = wmoMatch?.[1] ?? '---';
66
+ return `${station}.${id?.replace(/\./g, '') ?? '---'}`;
67
67
  }
68
68
  }
@@ -17,7 +17,6 @@
17
17
 
18
18
  */
19
19
 
20
- import { createHash } from "crypto"
21
20
  import { TypeEvent } from "../@types/type.event";
22
21
  import { TypeSettings } from "../@types/type.settings";
23
22
  import { bootstrap } from "../bootstrap"
@@ -29,9 +28,13 @@ import { getEventGeometry } from "./building.geometry";
29
28
  import { getEventAttachments } from "./building.attachments";
30
29
  import { updateNode } from "../@manager/manager.updateNodes";
31
30
  import { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
31
+ import { setDebug } from "../@modules/@utilities/utilities.setDebug";
32
+ import { getMatched } from "../@modules/@utilities/utilities.getMatched";
33
+ import { createHash } from "crypto"
32
34
 
33
35
  export const validateEvents = async (events: TypeEvent[]): Promise<void> => {
34
- if (events.length === 0) return;
36
+ const tick = performance.now();
37
+ if (events.length === 0) return
35
38
  const configurations = bootstrap.settings as TypeSettings
36
39
  const sets = {} as Record<string, Set<string>>;
37
40
  const bools = {} as Record<string, boolean>;
@@ -42,6 +45,7 @@ export const validateEvents = async (events: TypeEvent[]): Promise<void> => {
42
45
  if (typeof setting === 'boolean') { bools[key] = setting; }
43
46
  }
44
47
  const filterd = events.filter((event: TypeEvent) => {
48
+ bootstrap.cache.processed = bootstrap.cache.processed.filter((e) => e !== event);
45
49
  const define = getEventSignature(event) as TypeEvent;
46
50
  const properties = define.properties;
47
51
  const zones = properties.geocode.ugc;
@@ -51,11 +55,11 @@ export const validateEvents = async (events: TypeEvent[]): Promise<void> => {
51
55
  if (filteredProperties?.metadata && 'ms' in filteredProperties.metadata) {
52
56
  delete filteredProperties.metadata.ms;
53
57
  }
58
+
54
59
  filteredProperties.metadata = filteredProperties.metadata ?? {} as any;
55
60
  properties.metadata.hash = createHash("sha256").update(JSON.stringify(filteredProperties)).digest("hex")
56
61
  properties.metadata.attachments = getEventAttachments(event)
57
62
  setEventEmit({ event: `onProductType${enhancedEventName.replace(/\s+/g, '')}`, metadata: define });
58
-
59
63
  if (properties.status_metadata.is_test) {
60
64
  setEventEmit({ event: `onTestProduct`, metadata: define })
61
65
  if (bools?.IgnoreTestProducts) return false;
@@ -80,14 +84,15 @@ export const validateEvents = async (events: TypeEvent[]): Promise<void> => {
80
84
 
81
85
  for (const key in sets) {
82
86
  const setting = sets[key]
83
- if (key === 'ListeningEvents' && setting.size > 0 && !setting.has(define.properties.event.toLowerCase())) {
87
+ const values = [...setting];
88
+ if (key === 'ListeningEvents' && setting.size > 0 && !getMatched(values, define.properties.event)) {
84
89
  setEventEmit({
85
90
  event: `onFilteredEvent`,
86
91
  metadata: define
87
92
  });
88
93
  return false
89
94
  }
90
- if (key === 'IgnoredEvents' && setting.size > 0 && setting.has(define.properties.event.toLowerCase())) {
95
+ if (key === 'IgnoredEvents' && setting.size > 0 && getMatched(values, define.properties.event)) {
91
96
  setEventEmit({
92
97
  event: `onIgnoredEvent`,
93
98
  metadata: define
@@ -126,7 +131,6 @@ export const validateEvents = async (events: TypeEvent[]): Promise<void> => {
126
131
  return true;
127
132
  })
128
133
 
129
-
130
134
  if (!configurations?.GlobalSettings?.DisableGeometryParsing) {
131
135
  for (const event of filterd) {
132
136
  event.geometry = await getEventGeometry(event)
@@ -144,4 +148,5 @@ export const validateEvents = async (events: TypeEvent[]): Promise<void> => {
144
148
  metadata: bootstrap.cache.events,
145
149
  limited: true
146
150
  })
151
+ setDebug({ title: `@building.validate`, message: `Filtered ${filterd.length} events which took ${performance.now() - tick} ms` })
147
152
  }
@@ -20,7 +20,6 @@
20
20
  import { bootstrap } from "../bootstrap";
21
21
  import { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
22
22
 
23
-
24
23
  export const clearEvents = (): void => {
25
24
  bootstrap.cache.events.features = [];
26
25
  bootstrap.cache.hashes = [];
@@ -18,7 +18,6 @@
18
18
  */
19
19
 
20
20
  import { validateEvents } from "../@building/building.validate";
21
- import { dict_correlations } from "../@dictionaries/dictionaries.correlations";
22
21
 
23
22
  interface CreateEventOptions {
24
23
  event: string
@@ -19,7 +19,6 @@
19
19
 
20
20
  import { bootstrap } from "../bootstrap";
21
21
 
22
-
23
22
  export const getEvents = (): any => {
24
23
  return bootstrap.cache.events
25
24
  }
@@ -19,7 +19,6 @@
19
19
 
20
20
  import { bootstrap } from "../bootstrap";
21
21
 
22
-
23
22
  export const getNodes = (): any => {
24
23
  return bootstrap.cache.nodes
25
24
  }
@@ -19,7 +19,6 @@
19
19
 
20
20
  import { bootstrap } from "../bootstrap";
21
21
 
22
-
23
22
  export const getRandomEvent = (): any => {
24
23
  return bootstrap.cache.events.features[Math.floor(Math.random() * bootstrap.cache.events.features.length)]
25
24
  }
@@ -19,7 +19,6 @@
19
19
 
20
20
  import { bootstrap } from "../bootstrap";
21
21
 
22
-
23
22
  export const getVersion = (): any => {
24
23
  return bootstrap.version
25
24
  }
@@ -296,9 +296,9 @@ export const dict_awips: Record<string, string> = {
296
296
  SVR: `severe-thunderstorm-warning`,
297
297
  SVS: `severe-weather-statement`,
298
298
  SWOMCD: `mesoscale-discussion`,
299
- SWODY1: `day-1`,
300
- SWODY2: `day-2`,
301
- SWODY3: `day-3`,
299
+ SWODY1: `spc-day-1-outlook`,
300
+ SWODY2: `spc-day-2-outlook`,
301
+ SWODY3: `spc-day-3-outlook`,
302
302
  SWS: `state-weather-summary`,
303
303
  SYN: `regional-weather-synopsis`,
304
304
  TAF: `terminal-aerodrome-forecast`,
@@ -18,23 +18,21 @@
18
18
  */
19
19
 
20
20
  import { TypeStanzaCompiled } from "../@types/type.compiled"
21
- import { TypeEvent } from "../@types/type.event";
21
+ import { TypePVTEC } from "../@types/type.pvtec";
22
+ import { dict_icao } from "../@dictionaries/dictionaries.icao";
23
+ import { bootstrap } from "../bootstrap";
22
24
  import { getEventTracking } from "../@building/building.tracking";
23
- import { validateEvents } from "../@building/building.validate";
24
25
  import { pvExtract } from "../@parsers/@pvtec/pvtec.extract"
25
26
  import { getEventTags } from "../@building/building.tags";
26
27
  import { getTextFromProduct } from "../@parsers/@text/text.getTextFromProduct";
27
- import { dict_icao } from "../@dictionaries/dictionaries.icao";
28
- import { TypePVTEC } from "../@types/type.pvtec";
29
-
28
+ import { setDebug } from "../@modules/@utilities/utilities.setDebug";
30
29
 
31
30
  export const api = async (stanza: TypeStanzaCompiled): Promise<void> => {
32
- let processed: TypeEvent[] = [];
33
- const messages = Object.values(JSON.parse(stanza.message).features) as any;
31
+ const messages = Object.values(JSON.parse(stanza.message).features) as any;
34
32
  for (const feature of messages) {
35
33
  const tick = performance.now();
36
34
  const pVtec = pvExtract(feature?.properties?.parameters?.VTEC?.[0]) ?? null as TypePVTEC[]
37
- processed.push({
35
+ bootstrap.cache.processed.push({
38
36
  type: `Feature`,
39
37
  geometry: {
40
38
  type: `Point`,
@@ -114,6 +112,6 @@ export const api = async (stanza: TypeStanzaCompiled): Promise<void> => {
114
112
  }
115
113
  }
116
114
  })
115
+ setDebug({ title: `@events.api`, message: `Event process took ${performance.now() - tick} ms` })
117
116
  }
118
- validateEvents(processed)
119
117
  }
@@ -19,15 +19,14 @@
19
19
 
20
20
  import { TypeAttributes } from "../@types/type.attributes";
21
21
  import { TypeStanzaCompiled } from "../@types/type.compiled"
22
- import { TypeEvent } from "../@types/type.event";
22
+ import { dict_matches } from "../@dictionaries/dictionaries.matches";
23
+ import { bootstrap } from "../bootstrap";
23
24
  import { properties } from "../@building/building.properties";
24
25
  import { getEventHeader } from "../@building/building.headers";
25
- import { dict_matches } from "../@dictionaries/dictionaries.matches";
26
26
  import { getEventTracking } from "../@building/building.tracking";
27
- import { validateEvents } from "../@building/building.validate";
27
+ import { setDebug } from "../@modules/@utilities/utilities.setDebug";
28
28
 
29
29
  export const text = async (stanza: TypeStanzaCompiled): Promise<void> => {
30
- let processed: TypeEvent[] = [];
31
30
  const getMessages = stanza?.message
32
31
  ?.split(/(?=\$\$)/g)
33
32
  ?.map(message => message.trim())
@@ -46,7 +45,7 @@ export const text = async (stanza: TypeStanzaCompiled): Promise<void> => {
46
45
  event = stanza.getType.type.split(`-`).map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `)
47
46
  isStatement = true;
48
47
  }
49
- processed.push({
48
+ bootstrap.cache.processed.push({
50
49
  type: `Feature`,
51
50
  geometry: {
52
51
  type: `Point`,
@@ -77,6 +76,6 @@ export const text = async (stanza: TypeStanzaCompiled): Promise<void> => {
77
76
  }
78
77
  }
79
78
  })
79
+ setDebug({ title: `@events.text`, message: `Event process took ${performance.now() - tick} ms` })
80
80
  }
81
- validateEvents(processed)
82
81
  }
@@ -19,16 +19,15 @@
19
19
 
20
20
  import { TypeAttributes } from "../@types/type.attributes";
21
21
  import { TypeStanzaCompiled } from "../@types/type.compiled"
22
- import { TypeEvent } from "../@types/type.event";
23
22
  import { dict_matches } from "../@dictionaries/dictionaries.matches";
23
+ import { bootstrap } from "../bootstrap";
24
24
  import { ugcExtract } from "../@parsers/@ugc/ugc.extract";
25
25
  import { properties } from "../@building/building.properties";
26
26
  import { getEventHeader } from "../@building/building.headers";
27
27
  import { getEventTracking } from "../@building/building.tracking";
28
- import { validateEvents } from "../@building/building.validate";
28
+ import { setDebug } from "../@modules/@utilities/utilities.setDebug";
29
29
 
30
30
  export const ugc = async (stanza: TypeStanzaCompiled): Promise<void> => {
31
- let processed: TypeEvent[] = [];
32
31
  const getMessages = stanza?.message
33
32
  ?.split(/(?=\$\$)/g)
34
33
  ?.map(message => message.trim())
@@ -38,6 +37,7 @@ export const ugc = async (stanza: TypeStanzaCompiled): Promise<void> => {
38
37
  const tick = performance.now();
39
38
  const attributes = stanza?.attributes as TypeAttributes
40
39
  const ugc = await ugcExtract(message)
40
+
41
41
  if (ugc != null ) {
42
42
  const props = properties({ message, attributes, ugc: ugc })
43
43
  const issued = new Date(attributes.issue)
@@ -49,7 +49,7 @@ export const ugc = async (stanza: TypeStanzaCompiled): Promise<void> => {
49
49
  event = stanza.getType.type.split(`-`).map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `)
50
50
  isStatement = true;
51
51
  }
52
- processed.push({
52
+ bootstrap.cache.processed.push({
53
53
  type: `Feature`,
54
54
  geometry: {
55
55
  type: `Point`,
@@ -80,7 +80,7 @@ export const ugc = async (stanza: TypeStanzaCompiled): Promise<void> => {
80
80
  }
81
81
  }
82
82
  })
83
+ setDebug({ title: `@events.ugc`, message: `Event process took ${performance.now() - tick} ms` })
83
84
  }
84
85
  }
85
- validateEvents(processed)
86
86
  }
@@ -19,19 +19,18 @@
19
19
 
20
20
  import { TypeAttributes } from "../@types/type.attributes";
21
21
  import { TypeStanzaCompiled } from "../@types/type.compiled"
22
- import { TypeEvent } from "../@types/type.event";
23
22
  import { TypePVTEC } from "../@types/type.pvtec";
24
23
  import { TypeHVTEC } from "../@types/type.hvtec";
24
+ import { bootstrap } from "../bootstrap";
25
25
  import { pvExtract } from "../@parsers/@pvtec/pvtec.extract";
26
26
  import { hvExtract } from "../@parsers/@hvtec/hvtec.extract";
27
27
  import { ugcExtract } from "../@parsers/@ugc/ugc.extract";
28
28
  import { properties } from "../@building/building.properties";
29
29
  import { getEventHeader } from "../@building/building.headers";
30
30
  import { getEventTracking } from "../@building/building.tracking";
31
- import { validateEvents } from "../@building/building.validate";
31
+ import { setDebug } from "../@modules/@utilities/utilities.setDebug";
32
32
 
33
33
  export const vtec = async (stanza: TypeStanzaCompiled): Promise<void> => {
34
- let processed: TypeEvent[] = [];
35
34
  const getMessages = stanza?.message
36
35
  ?.split(/(?=\$\$)/g)
37
36
  ?.map(message => message.trim())
@@ -50,7 +49,7 @@ export const vtec = async (stanza: TypeStanzaCompiled): Promise<void> => {
50
49
  const header = getEventHeader({properties: props, getType: stanza.getType, vtec: vtec})
51
50
  const issued = new Date(attributes.issue)?? new Date()
52
51
  const expires = new Date(vtec.expires)
53
- processed.push({
52
+ bootstrap.cache.processed.push({
54
53
  type: `Feature`,
55
54
  geometry: {
56
55
  type: `Point`,
@@ -81,8 +80,8 @@ export const vtec = async (stanza: TypeStanzaCompiled): Promise<void> => {
81
80
  }
82
81
  }
83
82
  })
83
+ setDebug({ title: `@events.vtec`, message: `Event process took ${performance.now() - tick} ms` })
84
84
  }
85
85
  }
86
86
  }
87
- validateEvents(processed)
88
87
  }
@@ -17,13 +17,14 @@
17
17
 
18
18
  */
19
19
 
20
- import { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
21
20
  import { TypeEvent } from "../@types/type.event";
21
+ import { TypeSettings } from "../@types/type.settings";
22
22
  import { bootstrap } from "../bootstrap"
23
23
  import { setHash } from "./manager.setHash";
24
24
  import { updateListener } from "./manager.updateListener";
25
25
  import { updateNode } from "./manager.updateNodes";
26
- import { TypeSettings } from "../@types/type.settings";
26
+ import { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
27
+ import { setTimeoutAction } from "../@modules/@utilities/utilities.setTimeoutAction";
27
28
 
28
29
  export const mkEvent = async (event: TypeEvent): Promise<void> => {
29
30
  const settings = bootstrap.settings as TypeSettings;
@@ -40,14 +41,18 @@ export const mkEvent = async (event: TypeEvent): Promise<void> => {
40
41
  const isFilteredLocation = await updateNode(event).then(() => event.properties.metadata.filtered_proximity);
41
42
  if (!isFilteredLocation && settings.GlobalSettings.EventFiltering.NodeLocationFiltering) { return }
42
43
 
43
- setEventEmit({
44
- event: `onEventStatus`,
45
- metadata: {
46
- type: getFeature ? `Updated` : `New`,
47
- event: event
48
- },
49
- message: `[${getFeature ? 'Updated' : 'New'}] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
50
- })
44
+ const isRatelimited = setTimeoutAction({ identifier: getTracking, interval: 1, max: 1, addTime: true })
45
+ if (!isRatelimited.limited) {
46
+ setEventEmit({
47
+ event: `onEventStatus`,
48
+ metadata: {
49
+ type: getFeature ? `Updated` : `New`,
50
+ event: event
51
+ },
52
+ message: `[${getFeature ? 'Updated' : 'New'}] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
53
+ })
54
+ }
55
+
51
56
  if (settings.GlobalSettings.EventManagement) {
52
57
  if (event.properties.status_metadata.is_issued || event.properties.status_metadata.is_updated) {
53
58
  if (getFeature) {
@@ -79,10 +84,10 @@ export const mkEvent = async (event: TypeEvent): Promise<void> => {
79
84
  },
80
85
  }
81
86
  };
82
- updateListener(bootstrap.cache.events.features[getIndex])
87
+ await updateListener(bootstrap.cache.events.features[getIndex])
83
88
  } else {
84
89
  features.push(event)
85
- updateListener(event)
90
+ await updateListener(event)
86
91
  }
87
92
  }
88
93
  }
@@ -17,12 +17,13 @@
17
17
 
18
18
  */
19
19
 
20
- import { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
21
20
  import { TypeEvent } from "../@types/type.event";
22
21
  import { bootstrap } from "../bootstrap"
22
+ import { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
23
+ import { setTimeoutAction } from "../@modules/@utilities/utilities.setTimeoutAction";
23
24
  import { updateListener } from "./manager.updateListener";
24
25
 
25
- export const rmEvent = (event: TypeEvent): void => {
26
+ export const rmEvent = async (event: TypeEvent): Promise<void> => {
26
27
  const getEvent = bootstrap.cache.events.features.find(f => f?.properties?.metadata?.tracking === event?.properties?.metadata?.tracking);
27
28
  const cachedStatus = event.properties.status;
28
29
  event.properties.expires = new Date().toISOString();
@@ -38,9 +39,10 @@ export const rmEvent = (event: TypeEvent): void => {
38
39
  message: `[Removed] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
39
40
  })
40
41
  setEventEmit({ event: `onExpiredProduct`, metadata: event })
41
- if (cachedStatus != `Statement`) updateListener(event)
42
+ if (cachedStatus != `Statement`) await updateListener(event)
42
43
  bootstrap.cache.events.features.splice(bootstrap.cache.events.features.indexOf(getEvent), 1);
43
44
  bootstrap.cache.hashes = bootstrap.cache.hashes.filter(hash => hash.tracking !== event.properties.metadata.tracking);
45
+ setTimeoutAction({ identifier: event.properties.metadata.tracking, expire: true })
44
46
  }
45
47
  setEventEmit({
46
48
  event: `onEventCache`,
@@ -21,7 +21,6 @@ import { TypeEvent } from "../@types/type.event";
21
21
  import { TypeHash } from "../@types/type.hash"
22
22
  import { bootstrap } from "../bootstrap"
23
23
 
24
-
25
24
  export const setHash = (event: TypeEvent, entry: TypeHash): void => {
26
25
  if (entry) {
27
26
  entry.hashes.push(event.properties.metadata.hash);
@@ -17,17 +17,15 @@
17
17
 
18
18
  */
19
19
 
20
- import { getFormattedTime } from "../@modules/@utilities/utilities.getFormattedTime";
21
20
  import { TypeEvent } from "../@types/type.event";
22
21
  import { bootstrap } from "../bootstrap"
23
22
  import { rmEvent } from "./manager.rmEvent";
24
23
 
25
-
26
24
  export const updateEvents = async (selectedEvent?: TypeEvent): Promise<void> => {
27
25
  const events = bootstrap.cache.events.features;
28
26
  async function update(evt: TypeEvent) {
29
27
  if (new Date(evt.properties.expires) < new Date()) {
30
- rmEvent(evt);
28
+ await rmEvent(evt);
31
29
  }
32
30
  }
33
31
  if (!selectedEvent) { await Promise.all(events.map(async (evt) => { await update(evt) })) }