@aguacerowx/javascript-sdk 0.0.24 → 0.0.26

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,93 @@
1
+ /**
2
+ * NWWS `/alerts?hours=` sizing (aguacero-frontend baseline + overlap window parity).
3
+ *
4
+ * Hours follow the **active** observational mode only: NEXRAD → `nexradDurationValue`,
5
+ * MRMS → `mrmsDurationValue`, satellite → `satelliteDurationValue`, otherwise `1` (e.g. model-only).
6
+ * Tier cap uses {@link AguaceroCore} `satelliteTier` — the only subscription-style field on core today
7
+ * (same values as the frontend board tier: basic / enthusiast / professional).
8
+ */
9
+
10
+ import { parseTimelineDurationHours } from '../satellite_support.js';
11
+
12
+ const MAX_ALERT_HISTORY_HOURS = 8760;
13
+
14
+ /** Max option span (hours) per tier from frontend `RADAR_DURATION_CONFIG`. */
15
+ const TIER_MAX_HOURS = {
16
+ professional: 12,
17
+ enthusiast: 4,
18
+ basic: 1,
19
+ };
20
+
21
+ /**
22
+ * @param {string | undefined} tier
23
+ * @returns {'professional'|'enthusiast'|'basic'}
24
+ */
25
+ export function normalizeNwsSubscriptionTier(tier) {
26
+ const t = String(tier || 'basic').toLowerCase();
27
+ if (t === 'commercial' || t === 'lifetime' || t === 'partner') return 'professional';
28
+ if (t === 'professional' || t === 'enthusiast' || t === 'basic') return t;
29
+ return 'basic';
30
+ }
31
+
32
+ /**
33
+ * @param {string | undefined} tier
34
+ * @returns {number}
35
+ */
36
+ export function getMaxRadarHistoryHoursForTier(tier) {
37
+ const k = normalizeNwsSubscriptionTier(tier);
38
+ return TIER_MAX_HOURS[k] ?? TIER_MAX_HOURS.basic;
39
+ }
40
+
41
+ /**
42
+ * @param {object | null | undefined} state - {@link AguaceroCore} `state`
43
+ * @returns {number} integer hours in [1, MAX_ALERT_HISTORY_HOURS]
44
+ */
45
+ export function computeNwsAlertsFetchHoursFromAguaceroState(state) {
46
+ const tierMax = getMaxRadarHistoryHoursForTier(state?.satelliteTier);
47
+ let desired = 1;
48
+ if (state?.isNexrad) {
49
+ desired = parseTimelineDurationHours(state.nexradDurationValue);
50
+ } else if (state?.isMRMS) {
51
+ desired = parseTimelineDurationHours(state.mrmsDurationValue);
52
+ } else if (state?.isSatellite) {
53
+ desired = parseTimelineDurationHours(state.satelliteDurationValue);
54
+ }
55
+ const clamped = Math.min(tierMax, Math.max(1, desired));
56
+ return Math.min(MAX_ALERT_HISTORY_HOURS, Math.floor(clamped));
57
+ }
58
+
59
+ /**
60
+ * @param {number} hours
61
+ * @returns {string}
62
+ */
63
+ export function nwsAlertsFetchSpecCacheKey(hours) {
64
+ return `h${hours}`;
65
+ }
66
+
67
+ /**
68
+ * Unix window [start, end] for client-side validity overlap (wall-clock end at “now”).
69
+ *
70
+ * @param {number} hours
71
+ * @param {number | null} [anchorSec] - reserved; default now (matches frontend `anchorSec: null`)
72
+ * @returns {{ winStartSec: number; winEndSec: number }}
73
+ */
74
+ export function nwwsAlertsFetchUnixWindow(hours, anchorSec = null) {
75
+ const nowSec = Math.floor(Date.now() / 1000);
76
+ const winEndSec = anchorSec ?? nowSec;
77
+ const winStartSec = winEndSec - hours * 3600;
78
+ return { winStartSec, winEndSec };
79
+ }
80
+
81
+ /**
82
+ * @param {string} baseUrl - `/alerts` root (no query)
83
+ * @param {number} hours
84
+ * @returns {string}
85
+ */
86
+ export function buildNwwsActiveAlertsUrl(baseUrl, hours) {
87
+ const h = Math.max(1, Math.floor(Number(hours) || 1));
88
+ const params = new URLSearchParams();
89
+ params.set('hours', String(h));
90
+ const q = params.toString();
91
+ const base = String(baseUrl || '').replace(/\/$/, '');
92
+ return q ? `${base}?${q}` : base;
93
+ }