@vercel/flags-core 1.8.0 → 1.8.1-559c1e7-20260903094652

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @vercel/flags-core
2
2
 
3
+ ## 1.8.1-559c1e7-20260903094652
4
+
5
+ ### Patch Changes
6
+
7
+ - [#490](https://github.com/vercel/flags/pull/490) [`559c1e7`](https://github.com/vercel/flags/commit/559c1e7bb14765acb234bf004c8e839fadfc2922) Thanks [@AndyBitz](https://github.com/AndyBitz)! - Use the runtime-provided ingest transport when available
8
+
3
9
  ## 1.8.0
4
10
 
5
11
  ### Minor Changes
@@ -493,7 +493,7 @@ function bulkEvaluate(flags, shared) {
493
493
  }
494
494
 
495
495
  // package.json
496
- var version = "1.8.0";
496
+ var version = "1.8.1-559c1e7-20260903094652";
497
497
 
498
498
  // src/lib/report-value.ts
499
499
  function internalReportValue(key, value, data) {
@@ -866,12 +866,23 @@ function getJitteredWaitMs(baseMs, ratio) {
866
866
  return Math.floor(min + Math.random() * span);
867
867
  }
868
868
 
869
+ // src/utils/runtime-ingest.ts
870
+ var FLAGS_CONTEXT_SYMBOL = /* @__PURE__ */ Symbol.for("@vercel/flags-context");
871
+ function getRuntimeIngest() {
872
+ try {
873
+ const context = globalThis[FLAGS_CONTEXT_SYMBOL];
874
+ return typeof _optionalChain([context, 'optionalAccess', _25 => _25.ingest]) === "function" ? context.ingest : void 0;
875
+ } catch (e4) {
876
+ return void 0;
877
+ }
878
+ }
879
+
869
880
  // src/utils/ingest.ts
870
881
  var MAX_RETRIES = 3;
871
882
  var MAX_EVENTS_PER_REQUEST = 2e3;
872
883
  var EVALUATING_OIDC_TOKEN_HEADER = "X-Vercel-Flags-OIDC-Token";
873
884
  var FLUSH_REASON_HEADER = "X-Vercel-Flags-Flush-Reason";
874
- var isDebugMode = _optionalChain([process, 'access', _25 => _25.env, 'access', _26 => _26.DEBUG, 'optionalAccess', _27 => _27.includes, 'call', _28 => _28("@vercel/flags-core")]);
885
+ var isDebugMode = _optionalChain([process, 'access', _26 => _26.env, 'access', _27 => _27.DEBUG, 'optionalAccess', _28 => _28.includes, 'call', _29 => _29("@vercel/flags-core")]);
875
886
  var debugLog = (...args) => {
876
887
  if (!isDebugMode) return;
877
888
  console.log(...args);
@@ -880,7 +891,7 @@ async function getEvaluatingOidcToken(auth) {
880
891
  if (!auth.sdkKey) return void 0;
881
892
  try {
882
893
  return await _oidc.getVercelOidcToken.call(void 0, );
883
- } catch (e4) {
894
+ } catch (e5) {
884
895
  return void 0;
885
896
  }
886
897
  }
@@ -900,7 +911,15 @@ async function getIngestHeaders(options, flushReason) {
900
911
  };
901
912
  }
902
913
  async function sendIngestEvents(options, events, flushId, flushReason) {
903
- const eventsToSend = events.map((event) => event.ingestEvent());
914
+ let eventsToSend = events.map((event) => event.ingestEvent());
915
+ const runtimeIngest = getRuntimeIngest();
916
+ if (runtimeIngest) {
917
+ const headers = await getIngestHeaders(options, flushReason);
918
+ eventsToSend = eventsToSend.filter(
919
+ (event) => !runtimeIngest({ headers, body: [event] })
920
+ );
921
+ if (eventsToSend.length === 0) return;
922
+ }
904
923
  for (let i = 0; i < eventsToSend.length; i += MAX_EVENTS_PER_REQUEST) {
905
924
  await sendIngestChunk(
906
925
  options,
@@ -950,7 +969,7 @@ var SYMBOL_FOR_REQ_CONTEXT = /* @__PURE__ */ Symbol.for("@vercel/request-context
950
969
  var fromSymbol = globalThis;
951
970
  function getRequestContext() {
952
971
  try {
953
- const ctx = _optionalChain([fromSymbol, 'access', _29 => _29[SYMBOL_FOR_REQ_CONTEXT], 'optionalAccess', _30 => _30.get, 'optionalCall', _31 => _31()]);
972
+ const ctx = _optionalChain([fromSymbol, 'access', _30 => _30[SYMBOL_FOR_REQ_CONTEXT], 'optionalAccess', _31 => _31.get, 'optionalCall', _32 => _32()]);
954
973
  if (ctx && Object.hasOwn(ctx, "headers")) {
955
974
  return {
956
975
  ctx,
@@ -958,7 +977,7 @@ function getRequestContext() {
958
977
  };
959
978
  }
960
979
  return { ctx, headers: void 0 };
961
- } catch (e5) {
980
+ } catch (e6) {
962
981
  return { ctx: void 0, headers: void 0 };
963
982
  }
964
983
  }
@@ -988,7 +1007,7 @@ var Scheduler = (_class = class {
988
1007
  })();
989
1008
  try {
990
1009
  _functions.waitUntil.call(void 0, this.pending);
991
- } catch (e6) {
1010
+ } catch (e7) {
992
1011
  }
993
1012
  this.maxTimeout = setTimeout(
994
1013
  () => this.resolveScheduledFlush("max_timeout"),
@@ -1015,7 +1034,7 @@ var Scheduler = (_class = class {
1015
1034
  }
1016
1035
  resolveScheduledFlush(reason) {
1017
1036
  this.clearTimeouts();
1018
- _optionalChain([this, 'access', _32 => _32.resolveWait, 'optionalCall', _33 => _33(reason)]);
1037
+ _optionalChain([this, 'access', _33 => _33.resolveWait, 'optionalCall', _34 => _34(reason)]);
1019
1038
  }
1020
1039
  reset() {
1021
1040
  this.pending = null;
@@ -1159,7 +1178,7 @@ var UsageTracker = (_class4 = class {
1159
1178
  if (this.trackedRequests.has(ctx)) return;
1160
1179
  this.trackedRequests.add(ctx);
1161
1180
  this.readEvents.push(new FlagsConfigReadEvent(headers, options));
1162
- this.scheduler.scheduleFlush();
1181
+ this.requestFlush();
1163
1182
  } catch (error) {
1164
1183
  console.error("@vercel/flags-core: Failed to record event:", error);
1165
1184
  }
@@ -1183,7 +1202,7 @@ var UsageTracker = (_class4 = class {
1183
1202
  new FlagsEvaluationEvent(bucketedOptions)
1184
1203
  );
1185
1204
  }
1186
- this.scheduler.scheduleFlush();
1205
+ this.requestFlush();
1187
1206
  } catch (error) {
1188
1207
  console.error(
1189
1208
  "@vercel/flags-core: Failed to record evaluation event:",
@@ -1191,6 +1210,19 @@ var UsageTracker = (_class4 = class {
1191
1210
  );
1192
1211
  }
1193
1212
  }
1213
+ /**
1214
+ * Flushes immediately when the runtime provides an ingest transport,
1215
+ * otherwise falls back to the time-based scheduler.
1216
+ */
1217
+ requestFlush() {
1218
+ if (getRuntimeIngest()) {
1219
+ void this.flushEvents("immediate").catch((error) => {
1220
+ console.error("@vercel/flags-core: Failed to flush events:", error);
1221
+ });
1222
+ } else {
1223
+ this.scheduler.scheduleFlush();
1224
+ }
1225
+ }
1194
1226
  /**
1195
1227
  * Send all events to the ingest service
1196
1228
  */
@@ -1263,7 +1295,7 @@ var BundledSource = class {
1263
1295
  */
1264
1296
  async tryLoad() {
1265
1297
  const result = await this.getResult();
1266
- if (_optionalChain([result, 'optionalAccess', _34 => _34.state]) === "ok" && result.definitions) {
1298
+ if (_optionalChain([result, 'optionalAccess', _35 => _35.state]) === "ok" && result.definitions) {
1267
1299
  return result.definitions;
1268
1300
  }
1269
1301
  return void 0;
@@ -1303,14 +1335,14 @@ async function fetchDatafile(options) {
1303
1335
  signal: controller.signal
1304
1336
  });
1305
1337
  clearTimeout(timeoutId);
1306
- _optionalChain([options, 'access', _35 => _35.signal, 'optionalAccess', _36 => _36.removeEventListener, 'call', _37 => _37("abort", onExternalAbort)]);
1338
+ _optionalChain([options, 'access', _36 => _36.signal, 'optionalAccess', _37 => _37.removeEventListener, 'call', _38 => _38("abort", onExternalAbort)]);
1307
1339
  if (!res.ok) {
1308
1340
  throw new Error(`Failed to fetch data: ${res.statusText}`);
1309
1341
  }
1310
1342
  return res.json();
1311
1343
  } catch (error) {
1312
1344
  clearTimeout(timeoutId);
1313
- _optionalChain([options, 'access', _38 => _38.signal, 'optionalAccess', _39 => _39.removeEventListener, 'call', _40 => _40("abort", onExternalAbort)]);
1345
+ _optionalChain([options, 'access', _39 => _39.signal, 'optionalAccess', _40 => _40.removeEventListener, 'call', _41 => _41("abort", onExternalAbort)]);
1314
1346
  throw error instanceof Error ? error : new Error("Unknown fetch error");
1315
1347
  }
1316
1348
  }
@@ -1378,7 +1410,7 @@ var TypedEmitter = (_class5 = class {constructor() { _class5.prototype.__init11.
1378
1410
  set.add(handler);
1379
1411
  }
1380
1412
  off(event, handler) {
1381
- _optionalChain([this, 'access', _41 => _41.handlers, 'access', _42 => _42.get, 'call', _43 => _43(event), 'optionalAccess', _44 => _44.delete, 'call', _45 => _45(handler)]);
1413
+ _optionalChain([this, 'access', _42 => _42.handlers, 'access', _43 => _43.get, 'call', _44 => _44(event), 'optionalAccess', _45 => _45.delete, 'call', _46 => _46(handler)]);
1382
1414
  }
1383
1415
  emit(event, ...args) {
1384
1416
  const set = this.handlers.get(event);
@@ -1404,11 +1436,11 @@ var PollingSource = class extends TypedEmitter {
1404
1436
  * Emits 'data' on success, 'error' on failure.
1405
1437
  */
1406
1438
  async poll() {
1407
- if (_optionalChain([this, 'access', _46 => _46.abortController, 'optionalAccess', _47 => _47.signal, 'access', _48 => _48.aborted])) return;
1439
+ if (_optionalChain([this, 'access', _47 => _47.abortController, 'optionalAccess', _48 => _48.signal, 'access', _49 => _49.aborted])) return;
1408
1440
  try {
1409
1441
  const data = await fetchDatafile({
1410
1442
  ...this.config,
1411
- signal: _optionalChain([this, 'access', _49 => _49.abortController, 'optionalAccess', _50 => _50.signal])
1443
+ signal: _optionalChain([this, 'access', _50 => _50.abortController, 'optionalAccess', _51 => _51.signal])
1412
1444
  });
1413
1445
  this.emit("data", data);
1414
1446
  } catch (error) {
@@ -1437,7 +1469,7 @@ var PollingSource = class extends TypedEmitter {
1437
1469
  clearInterval(this.intervalId);
1438
1470
  this.intervalId = void 0;
1439
1471
  }
1440
- _optionalChain([this, 'access', _51 => _51.abortController, 'optionalAccess', _52 => _52.abort, 'call', _53 => _53()]);
1472
+ _optionalChain([this, 'access', _52 => _52.abortController, 'optionalAccess', _53 => _53.abort, 'call', _54 => _54()]);
1441
1473
  this.abortController = void 0;
1442
1474
  }
1443
1475
  };
@@ -1511,7 +1543,7 @@ async function connectStream(config, callbacks) {
1511
1543
  if (pingTimeoutId !== void 0) clearTimeout(pingTimeoutId);
1512
1544
  if (!initialDataReceived) return;
1513
1545
  pingTimeoutId = setTimeout(() => {
1514
- _optionalChain([responseBody, 'optionalAccess', _54 => _54.cancel, 'call', _55 => _55(), 'access', _56 => _56.catch, 'call', _57 => _57(() => {
1546
+ _optionalChain([responseBody, 'optionalAccess', _55 => _55.cancel, 'call', _56 => _56(), 'access', _57 => _57.catch, 'call', _58 => _58(() => {
1515
1547
  })]);
1516
1548
  connectionAbort.abort();
1517
1549
  }, PING_TIMEOUT_MS);
@@ -1530,7 +1562,7 @@ async function connectStream(config, callbacks) {
1530
1562
  if (vercelEnv) {
1531
1563
  headers["X-Vercel-Env"] = vercelEnv;
1532
1564
  }
1533
- const revision = _optionalChain([config, 'access', _58 => _58.revision, 'optionalCall', _59 => _59()]);
1565
+ const revision = _optionalChain([config, 'access', _59 => _59.revision, 'optionalCall', _60 => _60()]);
1534
1566
  if (revision !== void 0) {
1535
1567
  headers["X-Revision"] = String(revision);
1536
1568
  }
@@ -1576,7 +1608,7 @@ async function connectStream(config, callbacks) {
1576
1608
  let message;
1577
1609
  try {
1578
1610
  message = JSON.parse(line);
1579
- } catch (e7) {
1611
+ } catch (e8) {
1580
1612
  console.warn(
1581
1613
  "@vercel/flags-core: Failed to parse stream message, skipping"
1582
1614
  );
@@ -1592,7 +1624,7 @@ async function connectStream(config, callbacks) {
1592
1624
  resetPingTimeout();
1593
1625
  }
1594
1626
  if (message.type === "primed") {
1595
- _optionalChain([onPrimed, 'optionalCall', _60 => _60(message)]);
1627
+ _optionalChain([onPrimed, 'optionalCall', _61 => _61(message)]);
1596
1628
  retryCount = 0;
1597
1629
  if (!initialDataReceived) {
1598
1630
  initialDataReceived = true;
@@ -1615,7 +1647,7 @@ async function connectStream(config, callbacks) {
1615
1647
  clearTimeout(pingTimeoutId);
1616
1648
  abortController.signal.removeEventListener("abort", onMainAbort);
1617
1649
  if (!abortController.signal.aborted) {
1618
- _optionalChain([onDisconnect, 'optionalCall', _61 => _61()]);
1650
+ _optionalChain([onDisconnect, 'optionalCall', _62 => _62()]);
1619
1651
  retryCount++;
1620
1652
  const elapsed = Date.now() - lastAttemptTime;
1621
1653
  const minGap = Math.max(0, BASE_RETRY_DELAY_MS - elapsed);
@@ -1636,7 +1668,7 @@ async function connectStream(config, callbacks) {
1636
1668
  if (!connectionAbort.signal.aborted) {
1637
1669
  lastError = error;
1638
1670
  }
1639
- _optionalChain([onDisconnect, 'optionalCall', _62 => _62()]);
1671
+ _optionalChain([onDisconnect, 'optionalCall', _63 => _63()]);
1640
1672
  retryCount++;
1641
1673
  const elapsed = Date.now() - lastAttemptTime;
1642
1674
  const minGap = Math.max(0, BASE_RETRY_DELAY_MS - elapsed);
@@ -1715,7 +1747,7 @@ var StreamSource = class extends TypedEmitter {
1715
1747
  * Stop the stream connection.
1716
1748
  */
1717
1749
  stop() {
1718
- _optionalChain([this, 'access', _63 => _63.abortController, 'optionalAccess', _64 => _64.abort, 'call', _65 => _65()]);
1750
+ _optionalChain([this, 'access', _64 => _64.abortController, 'optionalAccess', _65 => _65.abort, 'call', _66 => _66()]);
1719
1751
  this.abortController = void 0;
1720
1752
  this.promise = void 0;
1721
1753
  }
@@ -1774,7 +1806,7 @@ var Controller = (_class6 = class {
1774
1806
  this.options = normalizeOptions(options);
1775
1807
  this.streamSource = new StreamSource(
1776
1808
  this.options,
1777
- () => _optionalChain([this, 'access', _66 => _66.data, 'optionalAccess', _67 => _67.revision])
1809
+ () => _optionalChain([this, 'access', _67 => _67.data, 'optionalAccess', _68 => _68.revision])
1778
1810
  );
1779
1811
  this.pollingSource = new PollingSource(this.options);
1780
1812
  this.bundledSource = new BundledSource({
@@ -1882,7 +1914,7 @@ var Controller = (_class6 = class {
1882
1914
  if (bundled) {
1883
1915
  this.data = tagData(bundled, "bundled");
1884
1916
  }
1885
- } catch (e8) {
1917
+ } catch (e9) {
1886
1918
  }
1887
1919
  }
1888
1920
  if (this.data) {
@@ -1984,7 +2016,7 @@ var Controller = (_class6 = class {
1984
2016
  this.data = tagData(fetched, "fetched");
1985
2017
  result = this.data;
1986
2018
  cacheStatus = "MISS";
1987
- } catch (e9) {
2019
+ } catch (e10) {
1988
2020
  throw new Error(
1989
2021
  "@vercel/flags-core: No flag definitions available. Initialize the client or provide a datafile."
1990
2022
  );
@@ -2103,7 +2135,7 @@ var Controller = (_class6 = class {
2103
2135
  return true;
2104
2136
  }
2105
2137
  return false;
2106
- } catch (e10) {
2138
+ } catch (e11) {
2107
2139
  return false;
2108
2140
  }
2109
2141
  }
@@ -2128,7 +2160,7 @@ var Controller = (_class6 = class {
2128
2160
  return true;
2129
2161
  }
2130
2162
  return false;
2131
- } catch (e11) {
2163
+ } catch (e12) {
2132
2164
  clearTimeout(timeoutId);
2133
2165
  return false;
2134
2166
  }
@@ -2178,7 +2210,7 @@ var Controller = (_class6 = class {
2178
2210
  fetch: this.options.fetch
2179
2211
  });
2180
2212
  return tagData(fetched, "fetched");
2181
- } catch (e12) {
2213
+ } catch (e13) {
2182
2214
  }
2183
2215
  throw new Error(
2184
2216
  "@vercel/flags-core: No flag definitions available during build. Provide a datafile or bundled definitions."
@@ -2212,7 +2244,7 @@ var Controller = (_class6 = class {
2212
2244
  this.data = tagData(fetched, "fetched");
2213
2245
  this.transition("degraded");
2214
2246
  return;
2215
- } catch (e13) {
2247
+ } catch (e14) {
2216
2248
  }
2217
2249
  }
2218
2250
  throw new Error(
@@ -2264,7 +2296,7 @@ var Controller = (_class6 = class {
2264
2296
  this.data = tagData(fetched, "fetched");
2265
2297
  this.transition("degraded");
2266
2298
  return [this.data, "MISS"];
2267
- } catch (e14) {
2299
+ } catch (e15) {
2268
2300
  }
2269
2301
  }
2270
2302
  throw new Error(
@@ -2316,11 +2348,11 @@ var Controller = (_class6 = class {
2316
2348
  duration: Date.now() - startTime,
2317
2349
  mode: mode === "streaming" ? "stream" : mode === "polling" ? "poll" : mode
2318
2350
  };
2319
- const configUpdatedAt = _optionalChain([this, 'access', _68 => _68.data, 'optionalAccess', _69 => _69.configUpdatedAt]);
2351
+ const configUpdatedAt = _optionalChain([this, 'access', _69 => _69.data, 'optionalAccess', _70 => _70.configUpdatedAt]);
2320
2352
  if (typeof configUpdatedAt === "number") {
2321
2353
  trackOptions.configUpdatedAt = configUpdatedAt;
2322
2354
  }
2323
- const revision = _optionalChain([this, 'access', _70 => _70.data, 'optionalAccess', _71 => _71.revision]);
2355
+ const revision = _optionalChain([this, 'access', _71 => _71.data, 'optionalAccess', _72 => _72.revision]);
2324
2356
  if (typeof revision === "number") {
2325
2357
  trackOptions.revision = revision;
2326
2358
  }
@@ -2353,7 +2385,7 @@ function parseSdkKeyFromFlagsConnectionString(text) {
2353
2385
  const params = new URLSearchParams(text.slice(6));
2354
2386
  const sdkKey = params.get("sdkKey");
2355
2387
  if (sdkKey && SDK_KEY_REGEX.test(sdkKey)) return sdkKey;
2356
- } catch (e15) {
2388
+ } catch (e16) {
2357
2389
  }
2358
2390
  return null;
2359
2391
  }
@@ -2362,7 +2394,7 @@ function parseSdkKeyFromFlagsConnectionString(text) {
2362
2394
  async function getOidcToken() {
2363
2395
  try {
2364
2396
  return await _oidc.getVercelOidcToken.call(void 0, );
2365
- } catch (e16) {
2397
+ } catch (e17) {
2366
2398
  throw new Error(
2367
2399
  [
2368
2400
  "@vercel/flags-core: Failed to get OIDC token.",
@@ -2460,7 +2492,7 @@ function setCacheLife() {
2460
2492
  try {
2461
2493
  _cache.cacheLife.call(void 0, { revalidate: 0, expire: 0 });
2462
2494
  _cache.cacheLife.call(void 0, { stale: 60 });
2463
- } catch (e17) {
2495
+ } catch (e18) {
2464
2496
  }
2465
2497
  }
2466
2498
  var cachedFns = {
@@ -2509,4 +2541,4 @@ var { flagsClient, resetDefaultFlagsClient, createClient } = make(
2509
2541
 
2510
2542
 
2511
2543
  exports.ResolutionReason = ResolutionReason; exports.evaluate = evaluate; exports.FallbackNotFoundError = FallbackNotFoundError; exports.FallbackEntryNotFoundError = FallbackEntryNotFoundError; exports.Controller = Controller; exports.flagsClient = flagsClient; exports.resetDefaultFlagsClient = resetDefaultFlagsClient; exports.createClient = createClient;
2512
- //# sourceMappingURL=chunk-ID4ZKPA3.cjs.map
2544
+ //# sourceMappingURL=chunk-3B37P63B.cjs.map