@luckystack/core 0.2.4 → 0.2.6
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/{chunk-HQX3X5QW.js → chunk-6YKLU3ZR.js} +4 -4
- package/dist/chunk-6YKLU3ZR.js.map +1 -0
- package/dist/{chunk-V2WKGTZH.js → chunk-OHGJSQZE.js} +22 -8
- package/dist/chunk-OHGJSQZE.js.map +1 -0
- package/dist/client.js +9 -4
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +50 -3
- package/dist/index.js +56 -18
- package/dist/index.js.map +1 -1
- package/dist/{sentrySetup-Q4BKUAQ3.js → sentrySetup-UCBMZPLQ.js} +2 -2
- package/package.json +2 -2
- package/dist/chunk-HQX3X5QW.js.map +0 -1
- package/dist/chunk-V2WKGTZH.js.map +0 -1
- /package/dist/{sentrySetup-Q4BKUAQ3.js.map → sentrySetup-UCBMZPLQ.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
tryCatchSync,
|
|
50
50
|
validatePagePath,
|
|
51
51
|
waitForSocket
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-6YKLU3ZR.js";
|
|
53
53
|
import {
|
|
54
54
|
DEFAULT_PROJECT_CONFIG,
|
|
55
55
|
deepMerge,
|
|
@@ -96,7 +96,7 @@ import {
|
|
|
96
96
|
startSpan,
|
|
97
97
|
startSpanAcrossTrackers,
|
|
98
98
|
startSpanHandle
|
|
99
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-OHGJSQZE.js";
|
|
100
100
|
import {
|
|
101
101
|
createRegistry
|
|
102
102
|
} from "./chunk-USQA6QTX.js";
|
|
@@ -1246,10 +1246,16 @@ var isLoopbackIp = (ip) => {
|
|
|
1246
1246
|
};
|
|
1247
1247
|
var TOKEN_HASH_LENGTH = 32;
|
|
1248
1248
|
var deriveTokenBucketId = (token) => createHash2("sha256").update(token).digest("hex").slice(0, TOKEN_HASH_LENGTH);
|
|
1249
|
+
var UNKNOWN_IP_WARN_COOLDOWN_MS = 6e4;
|
|
1250
|
+
var unknownIpLastWarnedAt = 0;
|
|
1249
1251
|
var resolveClientIp = ({ rawAddress, headers, trustProxy = false, trustedProxyHopCount = 1 }) => {
|
|
1250
1252
|
const resolved = resolveRaw({ rawAddress, headers, trustProxy, trustedProxyHopCount });
|
|
1251
1253
|
if (resolved === UNKNOWN_CLIENT_IP) {
|
|
1252
|
-
|
|
1254
|
+
const now = Date.now();
|
|
1255
|
+
if (now - unknownIpLastWarnedAt >= UNKNOWN_IP_WARN_COOLDOWN_MS) {
|
|
1256
|
+
unknownIpLastWarnedAt = now;
|
|
1257
|
+
getLogger().warn('rate-limit: client IP unresolved \u2014 keyed into the shared "unknown" bucket', { trustProxy });
|
|
1258
|
+
}
|
|
1253
1259
|
}
|
|
1254
1260
|
return resolved;
|
|
1255
1261
|
};
|
|
@@ -1359,8 +1365,15 @@ var checkRateLimitInMemory = ({
|
|
|
1359
1365
|
const entry = rateLimitStore.get(key);
|
|
1360
1366
|
if (!entry || entry.resetAt < now) {
|
|
1361
1367
|
if (rateLimitStore.size >= MAX_MEMORY_STORE_SIZE) {
|
|
1362
|
-
|
|
1363
|
-
|
|
1368
|
+
let evictKey;
|
|
1369
|
+
for (const [k, e] of rateLimitStore) {
|
|
1370
|
+
if (e.resetAt < now) {
|
|
1371
|
+
evictKey = k;
|
|
1372
|
+
break;
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
evictKey ??= rateLimitStore.keys().next().value;
|
|
1376
|
+
if (evictKey !== void 0) rateLimitStore.delete(evictKey);
|
|
1364
1377
|
}
|
|
1365
1378
|
rateLimitStore.set(key, { count: 1, resetAt: now + safeWindowMs });
|
|
1366
1379
|
return { allowed: true, remaining: limit - 1, resetIn: Math.ceil(safeWindowMs / 1e3) };
|
|
@@ -1508,8 +1521,7 @@ var getRateLimitStatus = async (key, limit) => {
|
|
|
1508
1521
|
var clearRateLimit = async (key) => strategyRegistry.get().clear(key);
|
|
1509
1522
|
var clearAllRateLimits = async () => {
|
|
1510
1523
|
if (process.env.NODE_ENV === "production") {
|
|
1511
|
-
|
|
1512
|
-
return;
|
|
1524
|
+
throw new Error("[RateLimiter] clearAllRateLimits() is not allowed in production. Use clearRateLimit(key) for scoped resets.");
|
|
1513
1525
|
}
|
|
1514
1526
|
return strategyRegistry.get().clearAll();
|
|
1515
1527
|
};
|
|
@@ -1631,17 +1643,40 @@ var parseObjectFields = (typeText) => {
|
|
|
1631
1643
|
const indexSignatures = [];
|
|
1632
1644
|
let part = "";
|
|
1633
1645
|
let depth = 0;
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1646
|
+
let inString = null;
|
|
1647
|
+
const codePoints = [...inner];
|
|
1648
|
+
let i = 0;
|
|
1649
|
+
while (i < codePoints.length) {
|
|
1650
|
+
const char = codePoints[i] ?? "";
|
|
1651
|
+
i += 1;
|
|
1652
|
+
if (inString && char === "\\") {
|
|
1653
|
+
part += char;
|
|
1654
|
+
const next = codePoints[i] ?? "";
|
|
1655
|
+
part += next;
|
|
1656
|
+
i += 1;
|
|
1657
|
+
continue;
|
|
1658
|
+
}
|
|
1659
|
+
if (char === '"' || char === "'") {
|
|
1660
|
+
if (inString === char) {
|
|
1661
|
+
inString = null;
|
|
1662
|
+
} else {
|
|
1663
|
+
inString ??= char;
|
|
1641
1664
|
}
|
|
1642
|
-
part
|
|
1665
|
+
part += char;
|
|
1643
1666
|
continue;
|
|
1644
1667
|
}
|
|
1668
|
+
if (!inString) {
|
|
1669
|
+
if (char === "{" || char === "[" || char === "(" || char === "<") depth += 1;
|
|
1670
|
+
if (char === "}" || char === "]" || char === ")" || char === ">") depth -= 1;
|
|
1671
|
+
if (char === ";" && depth === 0) {
|
|
1672
|
+
const trimmed = part.trim();
|
|
1673
|
+
if (trimmed) {
|
|
1674
|
+
parseFieldOrIndex(trimmed, fields, indexSignatures);
|
|
1675
|
+
}
|
|
1676
|
+
part = "";
|
|
1677
|
+
continue;
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1645
1680
|
part += char;
|
|
1646
1681
|
}
|
|
1647
1682
|
const final = part.trim();
|
|
@@ -1905,16 +1940,17 @@ var allowedOrigin = (origin) => {
|
|
|
1905
1940
|
}
|
|
1906
1941
|
}
|
|
1907
1942
|
const debugAllowedOrigins = typeof configured === "function" ? ["<dynamic-resolver>", location] : [location, ...configured].map((value) => normalizeOrigin({ value, secure })).filter(Boolean);
|
|
1943
|
+
const safeOrigin = origin.slice(0, 512).replaceAll(/[^ -~]/g, "");
|
|
1908
1944
|
if (getProjectConfig().logging.devLogs) {
|
|
1909
1945
|
getLogger().warn("cors: origin not allowed", {
|
|
1910
|
-
origin,
|
|
1946
|
+
origin: safeOrigin,
|
|
1911
1947
|
normalizedOrigin,
|
|
1912
1948
|
allowedOrigins: debugAllowedOrigins,
|
|
1913
1949
|
allowLocalhost: cors.allowLocalhost
|
|
1914
1950
|
});
|
|
1915
1951
|
}
|
|
1916
1952
|
void dispatchHook("corsRejected", {
|
|
1917
|
-
origin,
|
|
1953
|
+
origin: safeOrigin,
|
|
1918
1954
|
normalizedOrigin,
|
|
1919
1955
|
allowedOrigins: debugAllowedOrigins,
|
|
1920
1956
|
allowLocalhost: cors.allowLocalhost
|
|
@@ -1994,11 +2030,13 @@ var consumeOneTimeToken = async (namespace, token) => {
|
|
|
1994
2030
|
if (!token || typeof token !== "string") return null;
|
|
1995
2031
|
const key = tokenKey(namespace, token);
|
|
1996
2032
|
const txResult = await redis_default.multi().get(key).del(key).exec();
|
|
1997
|
-
if (!txResult || txResult.length
|
|
2033
|
+
if (!txResult || txResult.length < 2) return null;
|
|
1998
2034
|
const first = txResult[0];
|
|
1999
2035
|
if (!first) return null;
|
|
2000
2036
|
const [getErr, value] = first;
|
|
2001
2037
|
if (getErr) return null;
|
|
2038
|
+
const second = txResult[1];
|
|
2039
|
+
if (!second || second[0]) return null;
|
|
2002
2040
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
2003
2041
|
};
|
|
2004
2042
|
var consumeOneTimeTokenJson = async (namespace, token) => {
|