@vercel/flags-core 1.8.2-d31aae4-20260916165712 → 1.8.3
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/CHANGELOG.md +10 -2
- package/dist/{chunk-3GJDKSPG.js → chunk-NPKDNJX6.js} +73 -24
- package/dist/chunk-NPKDNJX6.js.map +1 -0
- package/dist/{chunk-2WO37TKH.cjs → chunk-UX43BKE3.cjs} +86 -37
- package/dist/chunk-UX43BKE3.cjs.map +1 -0
- package/dist/{chunk-UNFOBBPJ.cjs → chunk-UYSSHTCJ.cjs} +86 -37
- package/dist/chunk-UYSSHTCJ.cjs.map +1 -0
- package/dist/{chunk-DAWMMLXD.js → chunk-ZUA6TEG3.js} +73 -24
- package/dist/chunk-ZUA6TEG3.js.map +1 -0
- package/dist/index.default.cjs +2 -2
- package/dist/index.default.js +1 -1
- package/dist/index.next-js.cjs +2 -2
- package/dist/index.next-js.js +1 -1
- package/dist/openfeature.default.cjs +2 -2
- package/dist/openfeature.default.js +1 -1
- package/dist/openfeature.next-js.cjs +2 -2
- package/dist/openfeature.next-js.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-2WO37TKH.cjs.map +0 -1
- package/dist/chunk-3GJDKSPG.js.map +0 -1
- package/dist/chunk-DAWMMLXD.js.map +0 -1
- package/dist/chunk-UNFOBBPJ.cjs.map +0 -1
|
@@ -56,7 +56,7 @@ function getSplitBoundaries(outcome) {
|
|
|
56
56
|
function getCompiledRegex(rhs) {
|
|
57
57
|
const cached = compiledRegexCache.get(rhs);
|
|
58
58
|
if (cached) return cached;
|
|
59
|
-
const compiled = new RegExp(rhs.pattern, rhs.flags.replace(/[gy]
|
|
59
|
+
const compiled = new RegExp(rhs.pattern, rhs.flags.replace(/[gy]/g, ""));
|
|
60
60
|
compiledRegexCache.set(rhs, compiled);
|
|
61
61
|
return compiled;
|
|
62
62
|
}
|
|
@@ -559,7 +559,7 @@ function bulkEvaluate(flags, shared) {
|
|
|
559
559
|
}
|
|
560
560
|
|
|
561
561
|
// package.json
|
|
562
|
-
var version = "1.8.
|
|
562
|
+
var version = "1.8.3";
|
|
563
563
|
|
|
564
564
|
// src/lib/report-value.ts
|
|
565
565
|
function internalReportValue(key, value, data) {
|
|
@@ -1509,40 +1509,86 @@ var BundledSource = class {
|
|
|
1509
1509
|
|
|
1510
1510
|
// src/controller/fetch-datafile.ts
|
|
1511
1511
|
var DEFAULT_FETCH_TIMEOUT_MS = 1e4;
|
|
1512
|
+
var DEFAULT_MAX_ATTEMPTS = 3;
|
|
1513
|
+
var DatafileHttpError = class extends Error {
|
|
1514
|
+
constructor(status, statusText) {
|
|
1515
|
+
super(`Failed to fetch data: ${statusText}`);
|
|
1516
|
+
this.status = status;
|
|
1517
|
+
}
|
|
1518
|
+
status;
|
|
1519
|
+
get retryable() {
|
|
1520
|
+
return this.status === 408 || this.status === 429 || this.status >= 500;
|
|
1521
|
+
}
|
|
1522
|
+
};
|
|
1512
1523
|
async function fetchDatafile(options) {
|
|
1513
|
-
|
|
1524
|
+
options.signal?.throwIfAborted();
|
|
1525
|
+
const maxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
1526
|
+
if (!Number.isInteger(maxAttempts) || maxAttempts < 1) {
|
|
1527
|
+
throw new Error("maxAttempts must be a positive integer");
|
|
1528
|
+
}
|
|
1514
1529
|
const controller = new AbortController();
|
|
1530
|
+
const { signal } = controller;
|
|
1531
|
+
let rejectAbort;
|
|
1532
|
+
const aborted = new Promise((_, reject) => {
|
|
1533
|
+
rejectAbort = reject;
|
|
1534
|
+
});
|
|
1535
|
+
const onAbort = () => rejectAbort(signal.reason);
|
|
1536
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1537
|
+
const onExternalAbort = () => controller.abort(options.signal?.reason);
|
|
1538
|
+
options.signal?.addEventListener("abort", onExternalAbort, { once: true });
|
|
1515
1539
|
const timeoutId = setTimeout(
|
|
1516
|
-
() => controller.abort(
|
|
1540
|
+
() => controller.abort(
|
|
1541
|
+
new Error("@vercel/flags-core: Datafile fetch deadline exceeded")
|
|
1542
|
+
),
|
|
1517
1543
|
DEFAULT_FETCH_TIMEOUT_MS
|
|
1518
1544
|
);
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
throw new Error("Fetch aborted");
|
|
1524
|
-
}
|
|
1525
|
-
options.signal.addEventListener("abort", onExternalAbort, { once: true });
|
|
1526
|
-
}
|
|
1527
|
-
try {
|
|
1545
|
+
let delay;
|
|
1546
|
+
const fetchAttempt = async () => {
|
|
1547
|
+
const token = await options.auth.resolveToken();
|
|
1548
|
+
signal.throwIfAborted();
|
|
1528
1549
|
const res = await options.fetch(`${options.host}/v1/datafile`, {
|
|
1529
1550
|
headers: {
|
|
1530
1551
|
Authorization: `Bearer ${token}`,
|
|
1531
1552
|
"User-Agent": `VercelFlagsCore/${version}`,
|
|
1532
1553
|
...process.env.VERCEL_ENV ? { "X-Vercel-Env": process.env.VERCEL_ENV } : null
|
|
1533
1554
|
},
|
|
1534
|
-
signal
|
|
1555
|
+
signal
|
|
1535
1556
|
});
|
|
1536
|
-
|
|
1537
|
-
options.signal?.removeEventListener("abort", onExternalAbort);
|
|
1557
|
+
signal.throwIfAborted();
|
|
1538
1558
|
if (!res.ok) {
|
|
1539
|
-
|
|
1559
|
+
void res.body?.cancel().catch(() => {
|
|
1560
|
+
});
|
|
1561
|
+
throw new DatafileHttpError(res.status, res.statusText);
|
|
1540
1562
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1563
|
+
const data = await res.json();
|
|
1564
|
+
signal.throwIfAborted();
|
|
1565
|
+
return data;
|
|
1566
|
+
};
|
|
1567
|
+
try {
|
|
1568
|
+
for (let attempt = 0; ; attempt++) {
|
|
1569
|
+
if (attempt > 0) {
|
|
1570
|
+
await Promise.race([
|
|
1571
|
+
new Promise((resolve) => {
|
|
1572
|
+
delay = setTimeout(resolve, 100 * 2 ** (attempt - 1));
|
|
1573
|
+
}),
|
|
1574
|
+
aborted
|
|
1575
|
+
]);
|
|
1576
|
+
}
|
|
1577
|
+
signal.throwIfAborted();
|
|
1578
|
+
try {
|
|
1579
|
+
return await Promise.race([fetchAttempt(), aborted]);
|
|
1580
|
+
} catch (error) {
|
|
1581
|
+
signal.throwIfAborted();
|
|
1582
|
+
if (attempt === maxAttempts - 1 || error instanceof DatafileHttpError && !error.retryable) {
|
|
1583
|
+
throw error instanceof Error ? error : new Error("Unknown fetch error");
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
} finally {
|
|
1543
1588
|
clearTimeout(timeoutId);
|
|
1589
|
+
clearTimeout(delay);
|
|
1590
|
+
signal.removeEventListener("abort", onAbort);
|
|
1544
1591
|
options.signal?.removeEventListener("abort", onExternalAbort);
|
|
1545
|
-
throw error instanceof Error ? error : new Error("Unknown fetch error");
|
|
1546
1592
|
}
|
|
1547
1593
|
}
|
|
1548
1594
|
|
|
@@ -1638,13 +1684,16 @@ var PollingSource = class extends TypedEmitter {
|
|
|
1638
1684
|
*/
|
|
1639
1685
|
async poll() {
|
|
1640
1686
|
if (this.abortController?.signal.aborted) return;
|
|
1687
|
+
this.abortController ??= new AbortController();
|
|
1688
|
+
const controller = this.abortController;
|
|
1641
1689
|
try {
|
|
1642
1690
|
const data = await fetchDatafile({
|
|
1643
1691
|
...this.config,
|
|
1644
|
-
signal:
|
|
1692
|
+
signal: controller.signal
|
|
1645
1693
|
});
|
|
1646
1694
|
this.emit("data", data);
|
|
1647
1695
|
} catch (error) {
|
|
1696
|
+
controller.signal.throwIfAborted();
|
|
1648
1697
|
const err = error instanceof Error ? error : new Error("Unknown poll error");
|
|
1649
1698
|
this.emit("error", err);
|
|
1650
1699
|
}
|
|
@@ -1656,9 +1705,9 @@ var PollingSource = class extends TypedEmitter {
|
|
|
1656
1705
|
*/
|
|
1657
1706
|
startInterval() {
|
|
1658
1707
|
if (this.intervalId) return;
|
|
1659
|
-
this.abortController = new AbortController();
|
|
1660
1708
|
this.intervalId = setInterval(
|
|
1661
|
-
() => void this.poll()
|
|
1709
|
+
() => void this.poll().catch(() => {
|
|
1710
|
+
}),
|
|
1662
1711
|
this.config.polling.intervalMs
|
|
1663
1712
|
);
|
|
1664
1713
|
}
|
|
@@ -2759,4 +2808,4 @@ export {
|
|
|
2759
2808
|
resetDefaultFlagsClient,
|
|
2760
2809
|
createClient
|
|
2761
2810
|
};
|
|
2762
|
-
//# sourceMappingURL=chunk-
|
|
2811
|
+
//# sourceMappingURL=chunk-ZUA6TEG3.js.map
|