local-risk-alert-feed 0.1.0
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/dist/cjs/adapters/index.js +8 -0
- package/dist/cjs/adapters/index.js.map +1 -0
- package/dist/cjs/adapters/lambda.js +143 -0
- package/dist/cjs/adapters/lambda.js.map +1 -0
- package/dist/cjs/adapters/vercel.js +119 -0
- package/dist/cjs/adapters/vercel.js.map +1 -0
- package/dist/cjs/core/alert-aggregator.js +207 -0
- package/dist/cjs/core/alert-aggregator.js.map +1 -0
- package/dist/cjs/core/alert-feed.js +236 -0
- package/dist/cjs/core/alert-feed.js.map +1 -0
- package/dist/cjs/core/index.js +22 -0
- package/dist/cjs/core/index.js.map +1 -0
- package/dist/cjs/core/plugin-registry.js +193 -0
- package/dist/cjs/core/plugin-registry.js.map +1 -0
- package/dist/cjs/core/plugin-resolver.js +121 -0
- package/dist/cjs/core/plugin-resolver.js.map +1 -0
- package/dist/cjs/core/time-range.js +67 -0
- package/dist/cjs/core/time-range.js.map +1 -0
- package/dist/cjs/errors/fetch-error.js +71 -0
- package/dist/cjs/errors/fetch-error.js.map +1 -0
- package/dist/cjs/errors/index.js +15 -0
- package/dist/cjs/errors/index.js.map +1 -0
- package/dist/cjs/errors/plugin-error.js +80 -0
- package/dist/cjs/errors/plugin-error.js.map +1 -0
- package/dist/cjs/errors/validation-error.js +49 -0
- package/dist/cjs/errors/validation-error.js.map +1 -0
- package/dist/cjs/geo/distance.js +94 -0
- package/dist/cjs/geo/distance.js.map +1 -0
- package/dist/cjs/geo/index.js +18 -0
- package/dist/cjs/geo/index.js.map +1 -0
- package/dist/cjs/geo/point-in-radius.js +86 -0
- package/dist/cjs/geo/point-in-radius.js.map +1 -0
- package/dist/cjs/index.js +90 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/plugins/air-quality/airnow.plugin.js +343 -0
- package/dist/cjs/plugins/air-quality/airnow.plugin.js.map +1 -0
- package/dist/cjs/plugins/air-quality/index.js +6 -0
- package/dist/cjs/plugins/air-quality/index.js.map +1 -0
- package/dist/cjs/plugins/base-plugin.js +213 -0
- package/dist/cjs/plugins/base-plugin.js.map +1 -0
- package/dist/cjs/plugins/events/index.js +6 -0
- package/dist/cjs/plugins/events/index.js.map +1 -0
- package/dist/cjs/plugins/events/phoenix-events.plugin.js +382 -0
- package/dist/cjs/plugins/events/phoenix-events.plugin.js.map +1 -0
- package/dist/cjs/plugins/fire-emt/index.js +6 -0
- package/dist/cjs/plugins/fire-emt/index.js.map +1 -0
- package/dist/cjs/plugins/fire-emt/phoenix-fire.plugin.js +262 -0
- package/dist/cjs/plugins/fire-emt/phoenix-fire.plugin.js.map +1 -0
- package/dist/cjs/plugins/index.js +28 -0
- package/dist/cjs/plugins/index.js.map +1 -0
- package/dist/cjs/plugins/police-blotter/index.js +6 -0
- package/dist/cjs/plugins/police-blotter/index.js.map +1 -0
- package/dist/cjs/plugins/police-blotter/phoenix-police.plugin.js +198 -0
- package/dist/cjs/plugins/police-blotter/phoenix-police.plugin.js.map +1 -0
- package/dist/cjs/plugins/pulsepoint/index.js +6 -0
- package/dist/cjs/plugins/pulsepoint/index.js.map +1 -0
- package/dist/cjs/plugins/pulsepoint/pulsepoint.plugin.js +275 -0
- package/dist/cjs/plugins/pulsepoint/pulsepoint.plugin.js.map +1 -0
- package/dist/cjs/plugins/traffic/arizona-traffic.plugin.js +391 -0
- package/dist/cjs/plugins/traffic/arizona-traffic.plugin.js.map +1 -0
- package/dist/cjs/plugins/traffic/index.js +6 -0
- package/dist/cjs/plugins/traffic/index.js.map +1 -0
- package/dist/cjs/plugins/weather/index.js +6 -0
- package/dist/cjs/plugins/weather/index.js.map +1 -0
- package/dist/cjs/plugins/weather/nws-weather.plugin.js +180 -0
- package/dist/cjs/plugins/weather/nws-weather.plugin.js.map +1 -0
- package/dist/cjs/schemas/alert.schema.js +93 -0
- package/dist/cjs/schemas/alert.schema.js.map +1 -0
- package/dist/cjs/schemas/index.js +24 -0
- package/dist/cjs/schemas/index.js.map +1 -0
- package/dist/cjs/schemas/query.schema.js +76 -0
- package/dist/cjs/schemas/query.schema.js.map +1 -0
- package/dist/cjs/types/alert.js +35 -0
- package/dist/cjs/types/alert.js.map +1 -0
- package/dist/cjs/types/config.js +13 -0
- package/dist/cjs/types/config.js.map +1 -0
- package/dist/cjs/types/geo.js +3 -0
- package/dist/cjs/types/geo.js.map +1 -0
- package/dist/cjs/types/index.js +16 -0
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/cjs/types/plugin.js +3 -0
- package/dist/cjs/types/plugin.js.map +1 -0
- package/dist/cjs/types/query.js +28 -0
- package/dist/cjs/types/query.js.map +1 -0
- package/dist/cjs/utils/cache.js +188 -0
- package/dist/cjs/utils/cache.js.map +1 -0
- package/dist/cjs/utils/csv.js +189 -0
- package/dist/cjs/utils/csv.js.map +1 -0
- package/dist/cjs/utils/date.js +153 -0
- package/dist/cjs/utils/date.js.map +1 -0
- package/dist/cjs/utils/index.js +28 -0
- package/dist/cjs/utils/index.js.map +1 -0
- package/dist/cjs/utils/retry.js +109 -0
- package/dist/cjs/utils/retry.js.map +1 -0
- package/dist/esm/adapters/index.js +3 -0
- package/dist/esm/adapters/index.js.map +1 -0
- package/dist/esm/adapters/lambda.js +140 -0
- package/dist/esm/adapters/lambda.js.map +1 -0
- package/dist/esm/adapters/vercel.js +116 -0
- package/dist/esm/adapters/vercel.js.map +1 -0
- package/dist/esm/core/alert-aggregator.js +203 -0
- package/dist/esm/core/alert-aggregator.js.map +1 -0
- package/dist/esm/core/alert-feed.js +232 -0
- package/dist/esm/core/alert-feed.js.map +1 -0
- package/dist/esm/core/index.js +6 -0
- package/dist/esm/core/index.js.map +1 -0
- package/dist/esm/core/plugin-registry.js +189 -0
- package/dist/esm/core/plugin-registry.js.map +1 -0
- package/dist/esm/core/plugin-resolver.js +117 -0
- package/dist/esm/core/plugin-resolver.js.map +1 -0
- package/dist/esm/core/time-range.js +57 -0
- package/dist/esm/core/time-range.js.map +1 -0
- package/dist/esm/errors/fetch-error.js +67 -0
- package/dist/esm/errors/fetch-error.js.map +1 -0
- package/dist/esm/errors/index.js +4 -0
- package/dist/esm/errors/index.js.map +1 -0
- package/dist/esm/errors/plugin-error.js +71 -0
- package/dist/esm/errors/plugin-error.js.map +1 -0
- package/dist/esm/errors/validation-error.js +45 -0
- package/dist/esm/errors/validation-error.js.map +1 -0
- package/dist/esm/geo/distance.js +85 -0
- package/dist/esm/geo/distance.js.map +1 -0
- package/dist/esm/geo/index.js +3 -0
- package/dist/esm/geo/index.js.map +1 -0
- package/dist/esm/geo/point-in-radius.js +79 -0
- package/dist/esm/geo/point-in-radius.js.map +1 -0
- package/dist/esm/index.js +30 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/plugins/air-quality/airnow.plugin.js +339 -0
- package/dist/esm/plugins/air-quality/airnow.plugin.js.map +1 -0
- package/dist/esm/plugins/air-quality/index.js +2 -0
- package/dist/esm/plugins/air-quality/index.js.map +1 -0
- package/dist/esm/plugins/base-plugin.js +209 -0
- package/dist/esm/plugins/base-plugin.js.map +1 -0
- package/dist/esm/plugins/events/index.js +2 -0
- package/dist/esm/plugins/events/index.js.map +1 -0
- package/dist/esm/plugins/events/phoenix-events.plugin.js +378 -0
- package/dist/esm/plugins/events/phoenix-events.plugin.js.map +1 -0
- package/dist/esm/plugins/fire-emt/index.js +2 -0
- package/dist/esm/plugins/fire-emt/index.js.map +1 -0
- package/dist/esm/plugins/fire-emt/phoenix-fire.plugin.js +258 -0
- package/dist/esm/plugins/fire-emt/phoenix-fire.plugin.js.map +1 -0
- package/dist/esm/plugins/index.js +17 -0
- package/dist/esm/plugins/index.js.map +1 -0
- package/dist/esm/plugins/police-blotter/index.js +2 -0
- package/dist/esm/plugins/police-blotter/index.js.map +1 -0
- package/dist/esm/plugins/police-blotter/phoenix-police.plugin.js +194 -0
- package/dist/esm/plugins/police-blotter/phoenix-police.plugin.js.map +1 -0
- package/dist/esm/plugins/pulsepoint/index.js +2 -0
- package/dist/esm/plugins/pulsepoint/index.js.map +1 -0
- package/dist/esm/plugins/pulsepoint/pulsepoint.plugin.js +271 -0
- package/dist/esm/plugins/pulsepoint/pulsepoint.plugin.js.map +1 -0
- package/dist/esm/plugins/traffic/arizona-traffic.plugin.js +387 -0
- package/dist/esm/plugins/traffic/arizona-traffic.plugin.js.map +1 -0
- package/dist/esm/plugins/traffic/index.js +2 -0
- package/dist/esm/plugins/traffic/index.js.map +1 -0
- package/dist/esm/plugins/weather/index.js +2 -0
- package/dist/esm/plugins/weather/index.js.map +1 -0
- package/dist/esm/plugins/weather/nws-weather.plugin.js +176 -0
- package/dist/esm/plugins/weather/nws-weather.plugin.js.map +1 -0
- package/dist/esm/schemas/alert.schema.js +90 -0
- package/dist/esm/schemas/alert.schema.js.map +1 -0
- package/dist/esm/schemas/index.js +5 -0
- package/dist/esm/schemas/index.js.map +1 -0
- package/dist/esm/schemas/query.schema.js +72 -0
- package/dist/esm/schemas/query.schema.js.map +1 -0
- package/dist/esm/types/alert.js +32 -0
- package/dist/esm/types/alert.js.map +1 -0
- package/dist/esm/types/config.js +10 -0
- package/dist/esm/types/config.js.map +1 -0
- package/dist/esm/types/geo.js +2 -0
- package/dist/esm/types/geo.js.map +1 -0
- package/dist/esm/types/index.js +4 -0
- package/dist/esm/types/index.js.map +1 -0
- package/dist/esm/types/plugin.js +2 -0
- package/dist/esm/types/plugin.js.map +1 -0
- package/dist/esm/types/query.js +25 -0
- package/dist/esm/types/query.js.map +1 -0
- package/dist/esm/utils/cache.js +181 -0
- package/dist/esm/utils/cache.js.map +1 -0
- package/dist/esm/utils/csv.js +185 -0
- package/dist/esm/utils/csv.js.map +1 -0
- package/dist/esm/utils/date.js +142 -0
- package/dist/esm/utils/date.js.map +1 -0
- package/dist/esm/utils/index.js +5 -0
- package/dist/esm/utils/index.js.map +1 -0
- package/dist/esm/utils/retry.js +102 -0
- package/dist/esm/utils/retry.js.map +1 -0
- package/dist/types/adapters/index.d.ts +5 -0
- package/dist/types/adapters/index.d.ts.map +1 -0
- package/dist/types/adapters/lambda.d.ts +37 -0
- package/dist/types/adapters/lambda.d.ts.map +1 -0
- package/dist/types/adapters/vercel.d.ts +54 -0
- package/dist/types/adapters/vercel.d.ts.map +1 -0
- package/dist/types/core/alert-aggregator.d.ts +81 -0
- package/dist/types/core/alert-aggregator.d.ts.map +1 -0
- package/dist/types/core/alert-feed.d.ts +80 -0
- package/dist/types/core/alert-feed.d.ts.map +1 -0
- package/dist/types/core/index.d.ts +8 -0
- package/dist/types/core/index.d.ts.map +1 -0
- package/dist/types/core/plugin-registry.d.ts +91 -0
- package/dist/types/core/plugin-registry.d.ts.map +1 -0
- package/dist/types/core/plugin-resolver.d.ts +78 -0
- package/dist/types/core/plugin-resolver.d.ts.map +1 -0
- package/dist/types/core/time-range.d.ts +40 -0
- package/dist/types/core/time-range.d.ts.map +1 -0
- package/dist/types/errors/fetch-error.d.ts +46 -0
- package/dist/types/errors/fetch-error.d.ts.map +1 -0
- package/dist/types/errors/index.d.ts +5 -0
- package/dist/types/errors/index.d.ts.map +1 -0
- package/dist/types/errors/plugin-error.d.ts +42 -0
- package/dist/types/errors/plugin-error.d.ts.map +1 -0
- package/dist/types/errors/validation-error.d.ts +34 -0
- package/dist/types/errors/validation-error.d.ts.map +1 -0
- package/dist/types/geo/distance.d.ts +50 -0
- package/dist/types/geo/distance.d.ts.map +1 -0
- package/dist/types/geo/index.d.ts +3 -0
- package/dist/types/geo/index.d.ts.map +1 -0
- package/dist/types/geo/point-in-radius.d.ts +44 -0
- package/dist/types/geo/point-in-radius.d.ts.map +1 -0
- package/dist/types/index.d.ts +32 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/plugins/air-quality/airnow.plugin.d.ts +84 -0
- package/dist/types/plugins/air-quality/airnow.plugin.d.ts.map +1 -0
- package/dist/types/plugins/air-quality/index.d.ts +3 -0
- package/dist/types/plugins/air-quality/index.d.ts.map +1 -0
- package/dist/types/plugins/base-plugin.d.ts +99 -0
- package/dist/types/plugins/base-plugin.d.ts.map +1 -0
- package/dist/types/plugins/events/index.d.ts +3 -0
- package/dist/types/plugins/events/index.d.ts.map +1 -0
- package/dist/types/plugins/events/phoenix-events.plugin.d.ts +71 -0
- package/dist/types/plugins/events/phoenix-events.plugin.d.ts.map +1 -0
- package/dist/types/plugins/fire-emt/index.d.ts +3 -0
- package/dist/types/plugins/fire-emt/index.d.ts.map +1 -0
- package/dist/types/plugins/fire-emt/phoenix-fire.plugin.d.ts +47 -0
- package/dist/types/plugins/fire-emt/phoenix-fire.plugin.d.ts.map +1 -0
- package/dist/types/plugins/index.d.ts +17 -0
- package/dist/types/plugins/index.d.ts.map +1 -0
- package/dist/types/plugins/police-blotter/index.d.ts +3 -0
- package/dist/types/plugins/police-blotter/index.d.ts.map +1 -0
- package/dist/types/plugins/police-blotter/phoenix-police.plugin.d.ts +49 -0
- package/dist/types/plugins/police-blotter/phoenix-police.plugin.d.ts.map +1 -0
- package/dist/types/plugins/pulsepoint/index.d.ts +3 -0
- package/dist/types/plugins/pulsepoint/index.d.ts.map +1 -0
- package/dist/types/plugins/pulsepoint/pulsepoint.plugin.d.ts +61 -0
- package/dist/types/plugins/pulsepoint/pulsepoint.plugin.d.ts.map +1 -0
- package/dist/types/plugins/traffic/arizona-traffic.plugin.d.ts +83 -0
- package/dist/types/plugins/traffic/arizona-traffic.plugin.d.ts.map +1 -0
- package/dist/types/plugins/traffic/index.d.ts +3 -0
- package/dist/types/plugins/traffic/index.d.ts.map +1 -0
- package/dist/types/plugins/weather/index.d.ts +3 -0
- package/dist/types/plugins/weather/index.d.ts.map +1 -0
- package/dist/types/plugins/weather/nws-weather.plugin.d.ts +50 -0
- package/dist/types/plugins/weather/nws-weather.plugin.d.ts.map +1 -0
- package/dist/types/schemas/alert.schema.d.ts +266 -0
- package/dist/types/schemas/alert.schema.d.ts.map +1 -0
- package/dist/types/schemas/index.d.ts +5 -0
- package/dist/types/schemas/index.d.ts.map +1 -0
- package/dist/types/schemas/query.schema.d.ts +150 -0
- package/dist/types/schemas/query.schema.d.ts.map +1 -0
- package/dist/types/types/alert.d.ts +96 -0
- package/dist/types/types/alert.d.ts.map +1 -0
- package/dist/types/types/config.d.ts +63 -0
- package/dist/types/types/config.d.ts.map +1 -0
- package/dist/types/types/geo.d.ts +33 -0
- package/dist/types/types/geo.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +9 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/types/types/plugin.d.ts +125 -0
- package/dist/types/types/plugin.d.ts.map +1 -0
- package/dist/types/types/query.d.ts +86 -0
- package/dist/types/types/query.d.ts.map +1 -0
- package/dist/types/utils/cache.d.ts +112 -0
- package/dist/types/utils/cache.d.ts.map +1 -0
- package/dist/types/utils/csv.d.ts +38 -0
- package/dist/types/utils/csv.d.ts.map +1 -0
- package/dist/types/utils/date.d.ts +47 -0
- package/dist/types/utils/date.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +7 -0
- package/dist/types/utils/index.d.ts.map +1 -0
- package/dist/types/utils/retry.d.ts +51 -0
- package/dist/types/utils/retry.d.ts.map +1 -0
- package/package.json +115 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory cache provider implementation.
|
|
3
|
+
* Suitable for development, testing, or single-instance deployments.
|
|
4
|
+
*/
|
|
5
|
+
export class InMemoryCacheProvider {
|
|
6
|
+
cache = new Map();
|
|
7
|
+
cleanupIntervalId;
|
|
8
|
+
constructor(cleanupIntervalMs = 60_000) {
|
|
9
|
+
// Periodically clean up expired entries
|
|
10
|
+
this.cleanupIntervalId = setInterval(() => this.cleanup(), cleanupIntervalMs);
|
|
11
|
+
}
|
|
12
|
+
async get(key) {
|
|
13
|
+
const entry = this.cache.get(key);
|
|
14
|
+
if (!entry) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
// Check if expired
|
|
18
|
+
if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
|
|
19
|
+
this.cache.delete(key);
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return entry.value;
|
|
23
|
+
}
|
|
24
|
+
async set(key, value, ttlMs) {
|
|
25
|
+
const expiresAt = ttlMs ? Date.now() + ttlMs : null;
|
|
26
|
+
this.cache.set(key, { value, expiresAt });
|
|
27
|
+
}
|
|
28
|
+
async delete(key) {
|
|
29
|
+
this.cache.delete(key);
|
|
30
|
+
}
|
|
31
|
+
async has(key) {
|
|
32
|
+
const value = await this.get(key);
|
|
33
|
+
return value !== null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Clear all entries from the cache.
|
|
37
|
+
*/
|
|
38
|
+
async clear() {
|
|
39
|
+
this.cache.clear();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get the number of entries in the cache.
|
|
43
|
+
*/
|
|
44
|
+
size() {
|
|
45
|
+
return this.cache.size;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Dispose of the cache provider and stop cleanup interval.
|
|
49
|
+
*/
|
|
50
|
+
dispose() {
|
|
51
|
+
if (this.cleanupIntervalId) {
|
|
52
|
+
clearInterval(this.cleanupIntervalId);
|
|
53
|
+
this.cleanupIntervalId = undefined;
|
|
54
|
+
}
|
|
55
|
+
this.cache.clear();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Remove expired entries from the cache.
|
|
59
|
+
*/
|
|
60
|
+
cleanup() {
|
|
61
|
+
const now = Date.now();
|
|
62
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
63
|
+
if (entry.expiresAt !== null && now > entry.expiresAt) {
|
|
64
|
+
this.cache.delete(key);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Vercel KV cache provider implementation.
|
|
71
|
+
* Requires @vercel/kv package to be installed.
|
|
72
|
+
*/
|
|
73
|
+
export class VercelKVCacheProvider {
|
|
74
|
+
kv;
|
|
75
|
+
prefix;
|
|
76
|
+
constructor(kv, prefix = 'alert-feed:') {
|
|
77
|
+
this.kv = kv;
|
|
78
|
+
this.prefix = prefix;
|
|
79
|
+
}
|
|
80
|
+
getKey(key) {
|
|
81
|
+
return `${this.prefix}${key}`;
|
|
82
|
+
}
|
|
83
|
+
async get(key) {
|
|
84
|
+
const result = await this.kv.get(this.getKey(key));
|
|
85
|
+
return result ?? null;
|
|
86
|
+
}
|
|
87
|
+
async set(key, value, ttlMs) {
|
|
88
|
+
const fullKey = this.getKey(key);
|
|
89
|
+
if (ttlMs) {
|
|
90
|
+
// Vercel KV expects TTL in seconds
|
|
91
|
+
await this.kv.set(fullKey, value, { ex: Math.ceil(ttlMs / 1000) });
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
await this.kv.set(fullKey, value);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async delete(key) {
|
|
98
|
+
await this.kv.del(this.getKey(key));
|
|
99
|
+
}
|
|
100
|
+
async has(key) {
|
|
101
|
+
const exists = await this.kv.exists(this.getKey(key));
|
|
102
|
+
return exists === 1;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* DynamoDB cache provider implementation.
|
|
107
|
+
* Requires @aws-sdk/client-dynamodb and @aws-sdk/lib-dynamodb packages.
|
|
108
|
+
*/
|
|
109
|
+
export class DynamoDBCacheProvider {
|
|
110
|
+
client;
|
|
111
|
+
tableName;
|
|
112
|
+
keyAttribute;
|
|
113
|
+
valueAttribute;
|
|
114
|
+
ttlAttribute;
|
|
115
|
+
constructor(client, options) {
|
|
116
|
+
this.client = client;
|
|
117
|
+
this.tableName = options.tableName;
|
|
118
|
+
this.keyAttribute = options.keyAttribute ?? 'pk';
|
|
119
|
+
this.valueAttribute = options.valueAttribute ?? 'value';
|
|
120
|
+
this.ttlAttribute = options.ttlAttribute ?? 'ttl';
|
|
121
|
+
}
|
|
122
|
+
async get(key) {
|
|
123
|
+
const result = await this.client.get({
|
|
124
|
+
TableName: this.tableName,
|
|
125
|
+
Key: { [this.keyAttribute]: key },
|
|
126
|
+
});
|
|
127
|
+
if (!result.Item) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
// Check if TTL has expired (DynamoDB doesn't immediately delete expired items)
|
|
131
|
+
const ttl = result.Item[this.ttlAttribute];
|
|
132
|
+
if (ttl && Date.now() / 1000 > ttl) {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
return result.Item[this.valueAttribute];
|
|
136
|
+
}
|
|
137
|
+
async set(key, value, ttlMs) {
|
|
138
|
+
const item = {
|
|
139
|
+
[this.keyAttribute]: key,
|
|
140
|
+
[this.valueAttribute]: value,
|
|
141
|
+
};
|
|
142
|
+
if (ttlMs) {
|
|
143
|
+
// DynamoDB TTL expects Unix timestamp in seconds
|
|
144
|
+
item[this.ttlAttribute] = Math.floor((Date.now() + ttlMs) / 1000);
|
|
145
|
+
}
|
|
146
|
+
await this.client.put({
|
|
147
|
+
TableName: this.tableName,
|
|
148
|
+
Item: item,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
async delete(key) {
|
|
152
|
+
await this.client.delete({
|
|
153
|
+
TableName: this.tableName,
|
|
154
|
+
Key: { [this.keyAttribute]: key },
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
async has(key) {
|
|
158
|
+
const result = await this.get(key);
|
|
159
|
+
return result !== null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Generate a cache key for alert feed queries.
|
|
164
|
+
*
|
|
165
|
+
* @param pluginId - Plugin identifier
|
|
166
|
+
* @param location - Location coordinates
|
|
167
|
+
* @param timeRange - Time range for the query
|
|
168
|
+
* @returns A unique cache key string
|
|
169
|
+
*/
|
|
170
|
+
export function generateCacheKey(pluginId, location, timeRange) {
|
|
171
|
+
// Round coordinates to 3 decimal places (~100m precision) for cache hit efficiency
|
|
172
|
+
const lat = location.latitude.toFixed(3);
|
|
173
|
+
const lon = location.longitude.toFixed(3);
|
|
174
|
+
const locationHash = `${lat},${lon}`;
|
|
175
|
+
// Use date only for time range (hourly granularity would cause too many cache misses)
|
|
176
|
+
const startDate = timeRange.start.slice(0, 10);
|
|
177
|
+
const endDate = timeRange.end.slice(0, 10);
|
|
178
|
+
const timeHash = `${startDate}_${endDate}`;
|
|
179
|
+
return `alert-feed:${pluginId}:${locationHash}:${timeHash}`;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/utils/cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple CSV parser for handling Phoenix Open Data CSV responses.
|
|
3
|
+
*
|
|
4
|
+
* This is a lightweight parser that handles:
|
|
5
|
+
* - Quoted fields with commas
|
|
6
|
+
* - Escaped quotes within fields
|
|
7
|
+
* - Header row parsing
|
|
8
|
+
* - Type coercion for common patterns
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Parse a CSV string into an array of objects.
|
|
12
|
+
*
|
|
13
|
+
* @param csvText - The raw CSV text
|
|
14
|
+
* @param options - Parser options
|
|
15
|
+
* @returns Array of parsed objects with headers as keys
|
|
16
|
+
*/
|
|
17
|
+
export function parseCSV(csvText, options = {}) {
|
|
18
|
+
const { delimiter = ',', hasHeader = true, trimFields = true } = options;
|
|
19
|
+
const lines = splitCSVLines(csvText);
|
|
20
|
+
if (lines.length === 0) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
const headerLine = hasHeader ? lines[0] : null;
|
|
24
|
+
const dataLines = hasHeader ? lines.slice(1) : lines;
|
|
25
|
+
const headers = headerLine
|
|
26
|
+
? parseCSVLine(headerLine, delimiter).map((h) => (trimFields ? h.trim() : h))
|
|
27
|
+
: [];
|
|
28
|
+
const results = [];
|
|
29
|
+
for (const line of dataLines) {
|
|
30
|
+
if (line.trim() === '')
|
|
31
|
+
continue;
|
|
32
|
+
const values = parseCSVLine(line, delimiter);
|
|
33
|
+
const obj = {};
|
|
34
|
+
for (let i = 0; i < values.length; i++) {
|
|
35
|
+
const key = headers[i] ?? `column_${i}`;
|
|
36
|
+
let value = trimFields ? values[i].trim() : values[i];
|
|
37
|
+
// Type coercion for common patterns
|
|
38
|
+
if (options.coerceTypes !== false) {
|
|
39
|
+
value = coerceValue(value);
|
|
40
|
+
}
|
|
41
|
+
obj[key] = value;
|
|
42
|
+
}
|
|
43
|
+
results.push(obj);
|
|
44
|
+
}
|
|
45
|
+
return results;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Split CSV text into lines, handling quoted newlines.
|
|
49
|
+
*/
|
|
50
|
+
function splitCSVLines(text) {
|
|
51
|
+
const lines = [];
|
|
52
|
+
let currentLine = '';
|
|
53
|
+
let inQuotes = false;
|
|
54
|
+
for (let i = 0; i < text.length; i++) {
|
|
55
|
+
const char = text[i];
|
|
56
|
+
if (char === '"') {
|
|
57
|
+
// Check for escaped quote
|
|
58
|
+
if (inQuotes && text[i + 1] === '"') {
|
|
59
|
+
currentLine += '""';
|
|
60
|
+
i++;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
inQuotes = !inQuotes;
|
|
64
|
+
currentLine += char;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if ((char === '\n' || char === '\r') && !inQuotes) {
|
|
68
|
+
// End of line
|
|
69
|
+
if (currentLine.length > 0) {
|
|
70
|
+
lines.push(currentLine);
|
|
71
|
+
}
|
|
72
|
+
currentLine = '';
|
|
73
|
+
// Skip \r\n as single line ending
|
|
74
|
+
if (char === '\r' && text[i + 1] === '\n') {
|
|
75
|
+
i++;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
currentLine += char;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Add final line if exists
|
|
83
|
+
if (currentLine.length > 0) {
|
|
84
|
+
lines.push(currentLine);
|
|
85
|
+
}
|
|
86
|
+
return lines;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Parse a single CSV line into fields.
|
|
90
|
+
*/
|
|
91
|
+
function parseCSVLine(line, delimiter) {
|
|
92
|
+
const fields = [];
|
|
93
|
+
let currentField = '';
|
|
94
|
+
let inQuotes = false;
|
|
95
|
+
for (let i = 0; i < line.length; i++) {
|
|
96
|
+
const char = line[i];
|
|
97
|
+
if (char === '"') {
|
|
98
|
+
if (inQuotes && line[i + 1] === '"') {
|
|
99
|
+
// Escaped quote
|
|
100
|
+
currentField += '"';
|
|
101
|
+
i++;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// Toggle quote mode
|
|
105
|
+
inQuotes = !inQuotes;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else if (char === delimiter && !inQuotes) {
|
|
109
|
+
// End of field
|
|
110
|
+
fields.push(currentField);
|
|
111
|
+
currentField = '';
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
currentField += char;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Add final field
|
|
118
|
+
fields.push(currentField);
|
|
119
|
+
return fields;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Attempt to coerce a string value to a more specific type.
|
|
123
|
+
*/
|
|
124
|
+
function coerceValue(value) {
|
|
125
|
+
// Empty or null-like values
|
|
126
|
+
if (value === '' || value.toLowerCase() === 'null' || value.toLowerCase() === 'undefined') {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
// Boolean
|
|
130
|
+
if (value.toLowerCase() === 'true')
|
|
131
|
+
return true;
|
|
132
|
+
if (value.toLowerCase() === 'false')
|
|
133
|
+
return false;
|
|
134
|
+
// Number (integer or float)
|
|
135
|
+
if (/^-?\d+$/.test(value)) {
|
|
136
|
+
const num = parseInt(value, 10);
|
|
137
|
+
if (!isNaN(num) && num >= Number.MIN_SAFE_INTEGER && num <= Number.MAX_SAFE_INTEGER) {
|
|
138
|
+
return num;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (/^-?\d*\.\d+$/.test(value)) {
|
|
142
|
+
const num = parseFloat(value);
|
|
143
|
+
if (!isNaN(num)) {
|
|
144
|
+
return num;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Return as string
|
|
148
|
+
return value;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Convert an array of objects to CSV string.
|
|
152
|
+
*/
|
|
153
|
+
export function toCSV(data, options = {}) {
|
|
154
|
+
if (data.length === 0)
|
|
155
|
+
return '';
|
|
156
|
+
const { delimiter = ',' } = options;
|
|
157
|
+
const headers = options.headers ?? Object.keys(data[0]);
|
|
158
|
+
const lines = [];
|
|
159
|
+
// Header row
|
|
160
|
+
lines.push(headers.map((h) => escapeCSVField(String(h), delimiter)).join(delimiter));
|
|
161
|
+
// Data rows
|
|
162
|
+
for (const row of data) {
|
|
163
|
+
const values = headers.map((h) => {
|
|
164
|
+
const value = row[h];
|
|
165
|
+
if (value === null || value === undefined)
|
|
166
|
+
return '';
|
|
167
|
+
return escapeCSVField(String(value), delimiter);
|
|
168
|
+
});
|
|
169
|
+
lines.push(values.join(delimiter));
|
|
170
|
+
}
|
|
171
|
+
return lines.join('\n');
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Escape a field for CSV output.
|
|
175
|
+
*/
|
|
176
|
+
function escapeCSVField(value, delimiter) {
|
|
177
|
+
// Check if quoting is needed
|
|
178
|
+
if (value.includes('"') || value.includes(delimiter) || value.includes('\n') || value.includes('\r')) {
|
|
179
|
+
// Escape quotes by doubling them
|
|
180
|
+
const escaped = value.replace(/"/g, '""');
|
|
181
|
+
return `"${escaped}"`;
|
|
182
|
+
}
|
|
183
|
+
return value;
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=csv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csv.js","sourceRoot":"","sources":["../../../src/utils/csv.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Duration constants in milliseconds.
|
|
3
|
+
*/
|
|
4
|
+
export const HOUR_MS = 60 * 60 * 1000;
|
|
5
|
+
export const DAY_MS = 24 * HOUR_MS;
|
|
6
|
+
/**
|
|
7
|
+
* Check if a string is a valid TimeRangePreset.
|
|
8
|
+
*/
|
|
9
|
+
export function isTimeRangePreset(value) {
|
|
10
|
+
return [
|
|
11
|
+
'past-24h',
|
|
12
|
+
'past-7d',
|
|
13
|
+
'past-30d',
|
|
14
|
+
'next-4h',
|
|
15
|
+
'next-12h',
|
|
16
|
+
'next-24h',
|
|
17
|
+
'next-7d',
|
|
18
|
+
].includes(value);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Check if an object is a TimeRange.
|
|
22
|
+
*/
|
|
23
|
+
export function isTimeRange(value) {
|
|
24
|
+
return (typeof value === 'object' &&
|
|
25
|
+
value !== null &&
|
|
26
|
+
'start' in value &&
|
|
27
|
+
'end' in value &&
|
|
28
|
+
typeof value.start === 'string' &&
|
|
29
|
+
typeof value.end === 'string');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve a TimeRangeInput to an explicit TimeRange.
|
|
33
|
+
*
|
|
34
|
+
* @param input - Either a preset string or explicit time range
|
|
35
|
+
* @param now - Optional reference time (defaults to current time)
|
|
36
|
+
* @returns Resolved TimeRange with start and end as ISO strings
|
|
37
|
+
*/
|
|
38
|
+
export function resolveTimeRange(input, now) {
|
|
39
|
+
const reference = now ?? new Date();
|
|
40
|
+
// Default to next-24h if no input provided
|
|
41
|
+
if (!input) {
|
|
42
|
+
return resolveTimeRangePreset('next-24h', reference);
|
|
43
|
+
}
|
|
44
|
+
// If it's already a TimeRange, return it
|
|
45
|
+
if (isTimeRange(input)) {
|
|
46
|
+
return input;
|
|
47
|
+
}
|
|
48
|
+
// Otherwise it's a preset
|
|
49
|
+
return resolveTimeRangePreset(input, reference);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Resolve a TimeRangePreset to an explicit TimeRange.
|
|
53
|
+
*/
|
|
54
|
+
export function resolveTimeRangePreset(preset, now) {
|
|
55
|
+
const reference = now.getTime();
|
|
56
|
+
switch (preset) {
|
|
57
|
+
case 'past-24h':
|
|
58
|
+
return {
|
|
59
|
+
start: new Date(reference - DAY_MS).toISOString(),
|
|
60
|
+
end: now.toISOString(),
|
|
61
|
+
};
|
|
62
|
+
case 'past-7d':
|
|
63
|
+
return {
|
|
64
|
+
start: new Date(reference - 7 * DAY_MS).toISOString(),
|
|
65
|
+
end: now.toISOString(),
|
|
66
|
+
};
|
|
67
|
+
case 'past-30d':
|
|
68
|
+
return {
|
|
69
|
+
start: new Date(reference - 30 * DAY_MS).toISOString(),
|
|
70
|
+
end: now.toISOString(),
|
|
71
|
+
};
|
|
72
|
+
case 'next-4h':
|
|
73
|
+
return {
|
|
74
|
+
start: now.toISOString(),
|
|
75
|
+
end: new Date(reference + 4 * HOUR_MS).toISOString(),
|
|
76
|
+
};
|
|
77
|
+
case 'next-12h':
|
|
78
|
+
return {
|
|
79
|
+
start: now.toISOString(),
|
|
80
|
+
end: new Date(reference + 12 * HOUR_MS).toISOString(),
|
|
81
|
+
};
|
|
82
|
+
case 'next-24h':
|
|
83
|
+
return {
|
|
84
|
+
start: now.toISOString(),
|
|
85
|
+
end: new Date(reference + DAY_MS).toISOString(),
|
|
86
|
+
};
|
|
87
|
+
case 'next-7d':
|
|
88
|
+
return {
|
|
89
|
+
start: now.toISOString(),
|
|
90
|
+
end: new Date(reference + 7 * DAY_MS).toISOString(),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Check if a date falls within a time range.
|
|
96
|
+
*
|
|
97
|
+
* @param date - The date to check (string or Date)
|
|
98
|
+
* @param range - The time range to check against
|
|
99
|
+
* @returns true if the date falls within the range (inclusive)
|
|
100
|
+
*/
|
|
101
|
+
export function isDateInRange(date, range) {
|
|
102
|
+
const timestamp = typeof date === 'string' ? new Date(date).getTime() : date.getTime();
|
|
103
|
+
const start = new Date(range.start).getTime();
|
|
104
|
+
const end = new Date(range.end).getTime();
|
|
105
|
+
return timestamp >= start && timestamp <= end;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Check if two time ranges overlap.
|
|
109
|
+
*/
|
|
110
|
+
export function doRangesOverlap(range1, range2) {
|
|
111
|
+
const start1 = new Date(range1.start).getTime();
|
|
112
|
+
const end1 = new Date(range1.end).getTime();
|
|
113
|
+
const start2 = new Date(range2.start).getTime();
|
|
114
|
+
const end2 = new Date(range2.end).getTime();
|
|
115
|
+
return start1 <= end2 && start2 <= end1;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Format a duration in milliseconds to a human-readable string.
|
|
119
|
+
*/
|
|
120
|
+
export function formatDuration(ms) {
|
|
121
|
+
if (ms < 1000) {
|
|
122
|
+
return `${ms}ms`;
|
|
123
|
+
}
|
|
124
|
+
if (ms < 60_000) {
|
|
125
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
126
|
+
}
|
|
127
|
+
if (ms < HOUR_MS) {
|
|
128
|
+
return `${(ms / 60_000).toFixed(1)}m`;
|
|
129
|
+
}
|
|
130
|
+
if (ms < DAY_MS) {
|
|
131
|
+
return `${(ms / HOUR_MS).toFixed(1)}h`;
|
|
132
|
+
}
|
|
133
|
+
return `${(ms / DAY_MS).toFixed(1)}d`;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Parse an ISO date string to a Date object, returning null if invalid.
|
|
137
|
+
*/
|
|
138
|
+
export function parseISODate(dateString) {
|
|
139
|
+
const date = new Date(dateString);
|
|
140
|
+
return isNaN(date.getTime()) ? null : date;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=date.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date.js","sourceRoot":"","sources":["../../../src/utils/date.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { HOUR_MS, DAY_MS, isTimeRangePreset, isTimeRange, resolveTimeRange, resolveTimeRangePreset, isDateInRange, doRangesOverlap, formatDuration, parseISODate, } from './date';
|
|
2
|
+
export { withRetry, withTimeout, sleep, TimeoutError } from './retry';
|
|
3
|
+
export { InMemoryCacheProvider, VercelKVCacheProvider, DynamoDBCacheProvider, generateCacheKey, } from './cache';
|
|
4
|
+
export { parseCSV, toCSV } from './csv';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,MAAM,EACN,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,sBAAsB,EACtB,aAAa,EACb,eAAe,EACf,cAAc,EACd,YAAY,GACb,MAAM,QAAQ,CAAC;AAEhB,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGtE,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default retry options.
|
|
3
|
+
*/
|
|
4
|
+
const DEFAULT_OPTIONS = {
|
|
5
|
+
maxAttempts: 3,
|
|
6
|
+
initialDelayMs: 1000,
|
|
7
|
+
maxDelayMs: 10000,
|
|
8
|
+
backoffMultiplier: 2,
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Execute a function with automatic retry on failure.
|
|
12
|
+
*
|
|
13
|
+
* Uses exponential backoff with jitter for retry delays.
|
|
14
|
+
*
|
|
15
|
+
* @param fn - The async function to execute
|
|
16
|
+
* @param options - Retry configuration options
|
|
17
|
+
* @returns The result of the function
|
|
18
|
+
* @throws The last error if all retries fail
|
|
19
|
+
*/
|
|
20
|
+
export async function withRetry(fn, options) {
|
|
21
|
+
const config = {
|
|
22
|
+
...DEFAULT_OPTIONS,
|
|
23
|
+
...options,
|
|
24
|
+
};
|
|
25
|
+
let lastError;
|
|
26
|
+
let delay = config.initialDelayMs;
|
|
27
|
+
for (let attempt = 1; attempt <= config.maxAttempts; attempt++) {
|
|
28
|
+
try {
|
|
29
|
+
return await fn();
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
33
|
+
// Check if we should retry
|
|
34
|
+
const shouldRetry = attempt < config.maxAttempts && (config.isRetryable ? config.isRetryable(lastError) : true);
|
|
35
|
+
if (!shouldRetry) {
|
|
36
|
+
throw lastError;
|
|
37
|
+
}
|
|
38
|
+
// Notify about retry
|
|
39
|
+
if (config.onRetry) {
|
|
40
|
+
config.onRetry(lastError, attempt, delay);
|
|
41
|
+
}
|
|
42
|
+
// Wait with jitter
|
|
43
|
+
await sleep(addJitter(delay));
|
|
44
|
+
// Increase delay for next retry
|
|
45
|
+
delay = Math.min(delay * config.backoffMultiplier, config.maxDelayMs);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
throw lastError;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Sleep for a given duration.
|
|
52
|
+
*/
|
|
53
|
+
export function sleep(ms) {
|
|
54
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Add random jitter to a delay value (±25%).
|
|
58
|
+
*/
|
|
59
|
+
function addJitter(delay) {
|
|
60
|
+
const jitter = delay * 0.25 * (Math.random() * 2 - 1);
|
|
61
|
+
return Math.max(0, Math.round(delay + jitter));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Execute a function with a timeout.
|
|
65
|
+
*
|
|
66
|
+
* @param fn - The async function to execute
|
|
67
|
+
* @param timeoutMs - Maximum execution time in milliseconds
|
|
68
|
+
* @param timeoutMessage - Optional error message for timeout
|
|
69
|
+
* @returns The result of the function
|
|
70
|
+
* @throws TimeoutError if the function takes longer than timeoutMs
|
|
71
|
+
*/
|
|
72
|
+
export async function withTimeout(fn, timeoutMs, timeoutMessage = 'Operation timed out') {
|
|
73
|
+
let timeoutId;
|
|
74
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
75
|
+
timeoutId = setTimeout(() => {
|
|
76
|
+
reject(new TimeoutError(timeoutMessage, timeoutMs));
|
|
77
|
+
}, timeoutMs);
|
|
78
|
+
});
|
|
79
|
+
try {
|
|
80
|
+
const result = await Promise.race([fn(), timeoutPromise]);
|
|
81
|
+
clearTimeout(timeoutId);
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
clearTimeout(timeoutId);
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Error thrown when an operation times out.
|
|
91
|
+
*/
|
|
92
|
+
export class TimeoutError extends Error {
|
|
93
|
+
code = 'TIMEOUT_ERROR';
|
|
94
|
+
timeoutMs;
|
|
95
|
+
constructor(message, timeoutMs) {
|
|
96
|
+
super(message);
|
|
97
|
+
this.name = 'TimeoutError';
|
|
98
|
+
this.timeoutMs = timeoutMs;
|
|
99
|
+
Object.setPrototypeOf(this, TimeoutError.prototype);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../../src/utils/retry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createLambdaHandler } from './lambda';
|
|
2
|
+
export type { LambdaHandlerOptions, LambdaHandler } from './lambda';
|
|
3
|
+
export { createVercelHandler } from './vercel';
|
|
4
|
+
export type { VercelHandlerOptions, VercelHandler, VercelHandlerResult } from './vercel';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,YAAY,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,YAAY,EAAE,oBAAoB,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC"}
|