@vercel/flags-core 1.8.1 → 1.8.2
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 +11 -0
- package/README.md +14 -5
- package/dist/{chunk-CKL562EU.cjs → chunk-3WMSFQ2F.cjs} +142 -66
- package/dist/chunk-3WMSFQ2F.cjs.map +1 -0
- package/dist/{chunk-5BWCBI7I.js → chunk-AMDRNXFQ.js} +92 -15
- package/dist/chunk-AMDRNXFQ.js.map +1 -0
- package/dist/{chunk-DYSF37WV.js → chunk-KK44WKSW.js} +91 -15
- package/dist/chunk-KK44WKSW.js.map +1 -0
- package/dist/{chunk-CVDAHZHK.cjs → chunk-ODVYKYSM.cjs} +143 -66
- package/dist/chunk-ODVYKYSM.cjs.map +1 -0
- package/dist/index.default.cjs +2 -2
- package/dist/index.default.d.cts +9 -3
- package/dist/index.default.d.ts +9 -3
- package/dist/index.default.js +1 -1
- package/dist/index.next-js.cjs +2 -2
- package/dist/index.next-js.d.cts +9 -3
- package/dist/index.next-js.d.ts +9 -3
- package/dist/index.next-js.js +1 -1
- package/dist/openfeature.default.cjs +2 -2
- package/dist/openfeature.default.d.cts +1 -1
- package/dist/openfeature.default.d.ts +1 -1
- package/dist/openfeature.default.js +1 -1
- package/dist/openfeature.next-js.cjs +2 -2
- package/dist/openfeature.next-js.d.cts +1 -1
- package/dist/openfeature.next-js.d.ts +1 -1
- package/dist/openfeature.next-js.js +1 -1
- package/dist/{types-CIONStRG.d.cts → types-DLWRa9bG.d.cts} +17 -5
- package/dist/{types-CIONStRG.d.ts → types-DLWRa9bG.d.ts} +17 -5
- package/package.json +1 -1
- package/dist/chunk-5BWCBI7I.js.map +0 -1
- package/dist/chunk-CKL562EU.cjs.map +0 -1
- package/dist/chunk-CVDAHZHK.cjs.map +0 -1
- package/dist/chunk-DYSF37WV.js.map +0 -1
|
@@ -4,6 +4,9 @@ var __export = (target, all) => {
|
|
|
4
4
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
+
// src/index.default.ts
|
|
8
|
+
import { waitUntil as waitUntil2 } from "@vercel/functions";
|
|
9
|
+
|
|
7
10
|
// src/controller-fns.ts
|
|
8
11
|
var controller_fns_exports = {};
|
|
9
12
|
__export(controller_fns_exports, {
|
|
@@ -573,7 +576,7 @@ function bulkEvaluate(flags, shared) {
|
|
|
573
576
|
}
|
|
574
577
|
|
|
575
578
|
// package.json
|
|
576
|
-
var version = "1.8.
|
|
579
|
+
var version = "1.8.2";
|
|
577
580
|
|
|
578
581
|
// src/lib/report-value.ts
|
|
579
582
|
function internalReportValue(key, value, data) {
|
|
@@ -792,7 +795,7 @@ async function bulkEvaluate2(id, flags, entities) {
|
|
|
792
795
|
}
|
|
793
796
|
|
|
794
797
|
// src/create-raw-client.ts
|
|
795
|
-
import { waitUntil } from "@vercel/functions";
|
|
798
|
+
import { waitUntil as defaultWaitUntil } from "@vercel/functions";
|
|
796
799
|
import { dequal } from "dequal/lite";
|
|
797
800
|
var idCount = 0;
|
|
798
801
|
async function performInitialize(instance, initFn) {
|
|
@@ -808,9 +811,11 @@ function createCreateRawClient(fns) {
|
|
|
808
811
|
return function createRawClient({
|
|
809
812
|
controller,
|
|
810
813
|
origin,
|
|
811
|
-
experimental_reportExposures
|
|
814
|
+
experimental_reportExposures,
|
|
815
|
+
waitUntil: waitUntil3 = defaultWaitUntil
|
|
812
816
|
}) {
|
|
813
817
|
const id = idCount++;
|
|
818
|
+
const pendingExposureReports = /* @__PURE__ */ new Set();
|
|
814
819
|
controllerInstanceMap.set(id, {
|
|
815
820
|
controller,
|
|
816
821
|
initialized: false,
|
|
@@ -828,8 +833,10 @@ function createCreateRawClient(fns) {
|
|
|
828
833
|
);
|
|
829
834
|
}
|
|
830
835
|
})();
|
|
836
|
+
pendingExposureReports.add(pending);
|
|
837
|
+
void pending.finally(() => pendingExposureReports.delete(pending));
|
|
831
838
|
try {
|
|
832
|
-
|
|
839
|
+
waitUntil3(pending);
|
|
833
840
|
} catch {
|
|
834
841
|
}
|
|
835
842
|
}
|
|
@@ -864,6 +871,9 @@ function createCreateRawClient(fns) {
|
|
|
864
871
|
},
|
|
865
872
|
shutdown: async () => {
|
|
866
873
|
await fns.shutdown(id);
|
|
874
|
+
while (pendingExposureReports.size > 0) {
|
|
875
|
+
await Promise.all(pendingExposureReports);
|
|
876
|
+
}
|
|
867
877
|
controllerInstanceMap.delete(id);
|
|
868
878
|
},
|
|
869
879
|
getDatafile: async () => {
|
|
@@ -1045,6 +1055,17 @@ function getJitteredWaitMs(baseMs, ratio) {
|
|
|
1045
1055
|
return Math.floor(min + Math.random() * span);
|
|
1046
1056
|
}
|
|
1047
1057
|
|
|
1058
|
+
// src/utils/runtime-ingest.ts
|
|
1059
|
+
var FLAGS_CONTEXT_SYMBOL = /* @__PURE__ */ Symbol.for("@vercel/flags-context");
|
|
1060
|
+
function getRuntimeIngest() {
|
|
1061
|
+
try {
|
|
1062
|
+
const context = globalThis[FLAGS_CONTEXT_SYMBOL];
|
|
1063
|
+
return typeof context?.ingest === "function" ? context.ingest : void 0;
|
|
1064
|
+
} catch {
|
|
1065
|
+
return void 0;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1048
1069
|
// src/utils/ingest.ts
|
|
1049
1070
|
var MAX_RETRIES = 3;
|
|
1050
1071
|
var MAX_EVENTS_PER_REQUEST = 2e3;
|
|
@@ -1078,8 +1099,28 @@ async function getIngestHeaders(options, flushReason) {
|
|
|
1078
1099
|
...isDebugMode ? { "x-vercel-debug-ingest": "1" } : null
|
|
1079
1100
|
};
|
|
1080
1101
|
}
|
|
1102
|
+
function getRuntimeIngestHeaders(options, flushReason) {
|
|
1103
|
+
return {
|
|
1104
|
+
"Content-Type": "application/json",
|
|
1105
|
+
...options.auth.sdkKey ? { Authorization: `Bearer ${options.auth.sdkKey}` } : null,
|
|
1106
|
+
"User-Agent": `VercelFlagsCore/${version}`,
|
|
1107
|
+
[FLUSH_REASON_HEADER]: flushReason,
|
|
1108
|
+
...options.metricEnvironment ?? process.env.VERCEL_ENV ? {
|
|
1109
|
+
"X-Vercel-Env": options.metricEnvironment ?? process.env.VERCEL_ENV
|
|
1110
|
+
} : null,
|
|
1111
|
+
...isDebugMode ? { "x-vercel-debug-ingest": "1" } : null
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1081
1114
|
async function sendIngestEvents(options, events, flushId, flushReason) {
|
|
1082
|
-
|
|
1115
|
+
let eventsToSend = events.map((event) => event.ingestEvent());
|
|
1116
|
+
const runtimeIngest = getRuntimeIngest();
|
|
1117
|
+
if (runtimeIngest) {
|
|
1118
|
+
const headers = getRuntimeIngestHeaders(options, flushReason);
|
|
1119
|
+
eventsToSend = eventsToSend.filter(
|
|
1120
|
+
(event) => !runtimeIngest({ headers, body: [event] })
|
|
1121
|
+
);
|
|
1122
|
+
if (eventsToSend.length === 0) return;
|
|
1123
|
+
}
|
|
1083
1124
|
for (let i = 0; i < eventsToSend.length; i += MAX_EVENTS_PER_REQUEST) {
|
|
1084
1125
|
await sendIngestChunk(
|
|
1085
1126
|
options,
|
|
@@ -1143,15 +1184,17 @@ function getRequestContext() {
|
|
|
1143
1184
|
}
|
|
1144
1185
|
|
|
1145
1186
|
// src/utils/scheduler.ts
|
|
1146
|
-
import { waitUntil
|
|
1187
|
+
import { waitUntil } from "@vercel/functions";
|
|
1147
1188
|
var IDLE_FLUSH_WAIT_MS = 5e3;
|
|
1148
1189
|
var IDLE_FLUSH_JITTER_RATIO = 0.2;
|
|
1149
1190
|
var MAX_FLUSH_WAIT_MS = 6e4;
|
|
1150
1191
|
var Scheduler = class {
|
|
1151
|
-
constructor(onFlush) {
|
|
1192
|
+
constructor(onFlush, scheduleTask = waitUntil) {
|
|
1152
1193
|
this.onFlush = onFlush;
|
|
1194
|
+
this.scheduleTask = scheduleTask;
|
|
1153
1195
|
}
|
|
1154
1196
|
onFlush;
|
|
1197
|
+
scheduleTask;
|
|
1155
1198
|
resolveWait = null;
|
|
1156
1199
|
pending = null;
|
|
1157
1200
|
idleTimeout = null;
|
|
@@ -1166,7 +1209,7 @@ var Scheduler = class {
|
|
|
1166
1209
|
await this.onFlush(reason);
|
|
1167
1210
|
})();
|
|
1168
1211
|
try {
|
|
1169
|
-
|
|
1212
|
+
this.scheduleTask(this.pending);
|
|
1170
1213
|
} catch {
|
|
1171
1214
|
}
|
|
1172
1215
|
this.maxTimeout = setTimeout(
|
|
@@ -1313,12 +1356,18 @@ var UsageTracker = class {
|
|
|
1313
1356
|
flushCount = 0;
|
|
1314
1357
|
options;
|
|
1315
1358
|
scheduler;
|
|
1359
|
+
waitUntil;
|
|
1360
|
+
inflightFlushes = /* @__PURE__ */ new Set();
|
|
1316
1361
|
trackedRequests = /* @__PURE__ */ new WeakSet();
|
|
1317
1362
|
readEvents = [];
|
|
1318
1363
|
evaluationEvents = /* @__PURE__ */ new Map();
|
|
1319
1364
|
constructor(options) {
|
|
1320
1365
|
this.options = options;
|
|
1321
|
-
this.
|
|
1366
|
+
this.waitUntil = options.waitUntil;
|
|
1367
|
+
this.scheduler = new Scheduler(
|
|
1368
|
+
(reason) => this.flushEvents(reason),
|
|
1369
|
+
options.waitUntil
|
|
1370
|
+
);
|
|
1322
1371
|
}
|
|
1323
1372
|
/**
|
|
1324
1373
|
* Triggers an immediate flush of any pending events.
|
|
@@ -1327,6 +1376,7 @@ var UsageTracker = class {
|
|
|
1327
1376
|
async shutdown() {
|
|
1328
1377
|
await this.scheduler.shutdown();
|
|
1329
1378
|
await this.flushEvents("shutdown");
|
|
1379
|
+
await Promise.all([...this.inflightFlushes]);
|
|
1330
1380
|
}
|
|
1331
1381
|
/**
|
|
1332
1382
|
* Tracks a config read event. Deduplicates by request context.
|
|
@@ -1338,7 +1388,7 @@ var UsageTracker = class {
|
|
|
1338
1388
|
if (this.trackedRequests.has(ctx)) return;
|
|
1339
1389
|
this.trackedRequests.add(ctx);
|
|
1340
1390
|
this.readEvents.push(new FlagsConfigReadEvent(headers, options));
|
|
1341
|
-
this.
|
|
1391
|
+
this.requestFlush();
|
|
1342
1392
|
} catch (error) {
|
|
1343
1393
|
console.error("@vercel/flags-core: Failed to record event:", error);
|
|
1344
1394
|
}
|
|
@@ -1362,7 +1412,7 @@ var UsageTracker = class {
|
|
|
1362
1412
|
new FlagsEvaluationEvent(bucketedOptions)
|
|
1363
1413
|
);
|
|
1364
1414
|
}
|
|
1365
|
-
this.
|
|
1415
|
+
this.requestFlush();
|
|
1366
1416
|
} catch (error) {
|
|
1367
1417
|
console.error(
|
|
1368
1418
|
"@vercel/flags-core: Failed to record evaluation event:",
|
|
@@ -1370,6 +1420,25 @@ var UsageTracker = class {
|
|
|
1370
1420
|
);
|
|
1371
1421
|
}
|
|
1372
1422
|
}
|
|
1423
|
+
/**
|
|
1424
|
+
* Flushes immediately when the runtime provides an ingest transport,
|
|
1425
|
+
* otherwise falls back to the time-based scheduler.
|
|
1426
|
+
*/
|
|
1427
|
+
requestFlush() {
|
|
1428
|
+
if (getRuntimeIngest()) {
|
|
1429
|
+
const flush = this.flushEvents("immediate").catch((error) => {
|
|
1430
|
+
console.error("@vercel/flags-core: Failed to flush events:", error);
|
|
1431
|
+
});
|
|
1432
|
+
this.inflightFlushes.add(flush);
|
|
1433
|
+
void flush.finally(() => this.inflightFlushes.delete(flush));
|
|
1434
|
+
try {
|
|
1435
|
+
this.waitUntil?.(flush);
|
|
1436
|
+
} catch {
|
|
1437
|
+
}
|
|
1438
|
+
} else {
|
|
1439
|
+
this.scheduler.scheduleFlush();
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1373
1442
|
/**
|
|
1374
1443
|
* Send all events to the ingest service
|
|
1375
1444
|
*/
|
|
@@ -1495,6 +1564,7 @@ async function fetchDatafile(options) {
|
|
|
1495
1564
|
}
|
|
1496
1565
|
|
|
1497
1566
|
// src/controller/normalized-options.ts
|
|
1567
|
+
import { waitUntil as defaultWaitUntil2 } from "@vercel/functions";
|
|
1498
1568
|
var DEFAULT_STREAM_INIT_TIMEOUT_MS = 3e3;
|
|
1499
1569
|
var DEFAULT_POLLING_INTERVAL_MS = 3e4;
|
|
1500
1570
|
var MIN_POLLING_INTERVAL_MS = 3e4;
|
|
@@ -1538,6 +1608,7 @@ function normalizeOptions(options) {
|
|
|
1538
1608
|
polling,
|
|
1539
1609
|
buildStep,
|
|
1540
1610
|
fetch: options.fetch ?? globalThis.fetch,
|
|
1611
|
+
waitUntil: options.waitUntil ?? defaultWaitUntil2,
|
|
1541
1612
|
host: "https://flags.vercel.com",
|
|
1542
1613
|
metricEnvironment: options.metricEnvironment,
|
|
1543
1614
|
clientName: options.clientName,
|
|
@@ -2611,7 +2682,7 @@ var Authentication = class {
|
|
|
2611
2682
|
};
|
|
2612
2683
|
|
|
2613
2684
|
// src/index.make.ts
|
|
2614
|
-
function make(createRawClient) {
|
|
2685
|
+
function make(createRawClient, defaults) {
|
|
2615
2686
|
let _defaultFlagsClient = null;
|
|
2616
2687
|
function createClient2(sdkKeyOrConnectionStringOrOptions, options) {
|
|
2617
2688
|
const optionsOnly = typeof sdkKeyOrConnectionStringOrOptions === "object" && sdkKeyOrConnectionStringOrOptions !== null;
|
|
@@ -2619,10 +2690,16 @@ function make(createRawClient) {
|
|
|
2619
2690
|
const createClientOptions = optionsOnly ? sdkKeyOrConnectionStringOrOptions : options;
|
|
2620
2691
|
const { experimental_reportExposures, ...controllerOptions } = createClientOptions ?? {};
|
|
2621
2692
|
const auth = new Authentication(sdkKeyOrConnectionString);
|
|
2622
|
-
const
|
|
2693
|
+
const waitUntil3 = controllerOptions.waitUntil ?? defaults.waitUntil;
|
|
2694
|
+
const controller = new Controller({
|
|
2695
|
+
auth,
|
|
2696
|
+
...controllerOptions,
|
|
2697
|
+
waitUntil: waitUntil3
|
|
2698
|
+
});
|
|
2623
2699
|
return createRawClient({
|
|
2624
2700
|
controller,
|
|
2625
2701
|
origin: { provider: "vercel", sdkKey: auth.sdkKey },
|
|
2702
|
+
waitUntil: waitUntil3,
|
|
2626
2703
|
...experimental_reportExposures ? { experimental_reportExposures } : {}
|
|
2627
2704
|
});
|
|
2628
2705
|
}
|
|
@@ -2661,7 +2738,7 @@ var {
|
|
|
2661
2738
|
* Create a flags client using an SDK key, connection string, or Vercel OIDC.
|
|
2662
2739
|
*/
|
|
2663
2740
|
createClient
|
|
2664
|
-
} = make(createCreateRawClient(controller_fns_exports));
|
|
2741
|
+
} = make(createCreateRawClient(controller_fns_exports), { waitUntil: waitUntil2 });
|
|
2665
2742
|
|
|
2666
2743
|
export {
|
|
2667
2744
|
ResolutionReason,
|
|
@@ -2673,4 +2750,4 @@ export {
|
|
|
2673
2750
|
resetDefaultFlagsClient,
|
|
2674
2751
|
createClient
|
|
2675
2752
|
};
|
|
2676
|
-
//# sourceMappingURL=chunk-
|
|
2753
|
+
//# sourceMappingURL=chunk-AMDRNXFQ.js.map
|