@vercel/flags-core 1.10.2 → 1.10.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.
@@ -559,7 +559,7 @@ function bulkEvaluate(flags, shared) {
559
559
  }
560
560
 
561
561
  // package.json
562
- var version = "1.10.2";
562
+ var version = "1.10.3";
563
563
 
564
564
  // src/lib/report-value.ts
565
565
  function internalReportValue(key, value, data) {
@@ -1089,17 +1089,26 @@ function unauthorizedMessage(sourceProjectId) {
1089
1089
  }
1090
1090
  return `unauthorized (401): this deployment is not allowed to read the flags of project "${sourceProjectId}". Check that the project is connected. See https://vercel.com/docs/flags/vercel-flags/project-connections`;
1091
1091
  }
1092
+ var oidcTokenMessage = [
1093
+ "@vercel/flags-core: Failed to get OIDC token.",
1094
+ "Are you running in a Vercel Environment where OIDC tokens are available?",
1095
+ "Did you mean to use an SDK Key instead? Use the environment variable FLAGS or pass it directly to the client."
1096
+ ].join(" ");
1097
+ var missingCredentials = /`vc link|vercel login|^The 'x-vercel-oidc-token' header is missing from the request\.$/;
1098
+ var OidcTokenError = class extends Error {
1099
+ constructor(cause) {
1100
+ super(oidcTokenMessage, { cause });
1101
+ this.name = "OidcTokenError";
1102
+ }
1103
+ };
1092
1104
  async function getOidcToken() {
1093
1105
  try {
1094
1106
  return await getVercelOidcToken();
1095
- } catch {
1096
- throw new Error(
1097
- [
1098
- "@vercel/flags-core: Failed to get OIDC token.",
1099
- "Are you running in a Vercel Environment where OIDC tokens are available?",
1100
- "Did you mean to use an SDK Key instead? Use the environment variable FLAGS or pass it directly to the client."
1101
- ].join(" ")
1102
- );
1107
+ } catch (error) {
1108
+ if (error instanceof Error && missingCredentials.test(error.message)) {
1109
+ throw new OidcTokenError(error);
1110
+ }
1111
+ throw new Error(oidcTokenMessage, { cause: error });
1103
1112
  }
1104
1113
  }
1105
1114
  function getProjectIdFromOidcToken(oidcToken) {
@@ -2143,7 +2152,8 @@ async function fetchDatafile(options) {
2143
2152
  return await Promise.race([fetchAttempt(attempt + 1), aborted]);
2144
2153
  } catch (error) {
2145
2154
  signal.throwIfAborted();
2146
- if (attempt === maxAttempts - 1 || error instanceof DatafileHttpError && !error.retryable) {
2155
+ if (attempt === maxAttempts - 1 || error instanceof DatafileHttpError && !error.retryable || // Retrying will not produce a token that is not there.
2156
+ error instanceof OidcTokenError) {
2147
2157
  throw error instanceof Error ? error : new Error("Unknown fetch error");
2148
2158
  }
2149
2159
  debug(options.clientName, "datafile.fetch.retry", () => ({
@@ -2561,7 +2571,7 @@ async function connectStream(config, callbacks) {
2561
2571
  rejectInit(error);
2562
2572
  }
2563
2573
  onDisconnect?.();
2564
- abortController.abort();
2574
+ abortController.abort(error);
2565
2575
  break;
2566
2576
  }
2567
2577
  if (!response.ok) {
@@ -2663,7 +2673,7 @@ async function connectStream(config, callbacks) {
2663
2673
  }
2664
2674
  if (error instanceof TokenResolutionError && !initialDataReceived) {
2665
2675
  rejectInit(error.cause);
2666
- abortController.abort();
2676
+ abortController.abort(error.cause);
2667
2677
  break;
2668
2678
  }
2669
2679
  if (connectionAbort.signal.reason !== PING_TIMEOUT) {
@@ -2737,7 +2747,7 @@ var StreamSource = class extends TypedEmitter {
2737
2747
  if (this.abortController === abortController) {
2738
2748
  this.promise = void 0;
2739
2749
  this.abortController = void 0;
2740
- this.emit("exhausted");
2750
+ this.emit("exhausted", abortController.signal.reason);
2741
2751
  }
2742
2752
  },
2743
2753
  { once: true }
@@ -2798,7 +2808,7 @@ var UNKNOWN_FRESHNESS = {
2798
2808
  assess: () => ({ status: "unknown" })
2799
2809
  };
2800
2810
  function isUnauthorizedError(error) {
2801
- if (error instanceof UnauthorizedError) {
2811
+ if (error instanceof UnauthorizedError || error instanceof OidcTokenError) {
2802
2812
  return true;
2803
2813
  }
2804
2814
  if (!(error instanceof Error)) {
@@ -2833,8 +2843,9 @@ var Controller = class {
2833
2843
  // Build-step deduplication
2834
2844
  buildDataPromise = null;
2835
2845
  buildReadTracked = false;
2836
- // Suppresses usage tracking while the credential is rejected. Set on a 401
2837
- // from any source, cleared as soon as a source delivers data again.
2846
+ // Suppresses usage tracking while the credential is rejected or no OIDC
2847
+ // token is available. Set on an auth failure from any source, cleared as
2848
+ // soon as a source delivers data again.
2838
2849
  unauthorized = false;
2839
2850
  constructor(options) {
2840
2851
  this.options = normalizeOptions(options);
@@ -2930,10 +2941,16 @@ var Controller = class {
2930
2941
  this.transition("degraded", "stream-disconnected");
2931
2942
  }
2932
2943
  };
2933
- onStreamExhausted = () => {
2944
+ onStreamExhausted = (reason) => {
2934
2945
  if (this.state !== "streaming" && this.state !== "degraded") {
2935
2946
  return;
2936
2947
  }
2948
+ if (isUnauthorizedError(reason)) {
2949
+ if (this.state === "streaming") {
2950
+ this.transition("degraded", "stream-auth-failed");
2951
+ }
2952
+ return;
2953
+ }
2937
2954
  void this.activateFallbackSource().catch(() => {
2938
2955
  });
2939
2956
  };
@@ -2945,7 +2962,7 @@ var Controller = class {
2945
2962
  this.onSourceError(error);
2946
2963
  if (this.state === "polling" && isUnauthorizedError(error)) {
2947
2964
  this.pollingSource.stop();
2948
- this.transition("degraded", "polling-unauthorized");
2965
+ this.transition("degraded", "polling-auth-failed");
2949
2966
  }
2950
2967
  };
2951
2968
  // ---------------------------------------------------------------------------
@@ -3355,6 +3372,10 @@ var Controller = class {
3355
3372
  this.transition("degraded", "stream-still-connecting");
3356
3373
  return;
3357
3374
  }
3375
+ if (outcome === "auth-failed") {
3376
+ this.transition("degraded", "stream-auth-failed");
3377
+ return;
3378
+ }
3358
3379
  }
3359
3380
  if (this.options.polling.enabled) {
3360
3381
  if (this.state !== "polling") {
@@ -3387,7 +3408,7 @@ var Controller = class {
3387
3408
  return "connected";
3388
3409
  } catch (error) {
3389
3410
  this.noteUnauthorized(error);
3390
- return "failed";
3411
+ return isUnauthorizedError(error) ? "auth-failed" : "failed";
3391
3412
  }
3392
3413
  }
3393
3414
  let timeoutId;
@@ -3421,7 +3442,7 @@ var Controller = class {
3421
3442
  } catch (error) {
3422
3443
  clearTimeout(timeoutId);
3423
3444
  this.noteUnauthorized(error);
3424
- return "failed";
3445
+ return isUnauthorizedError(error) ? "auth-failed" : "failed";
3425
3446
  }
3426
3447
  }
3427
3448
  // ---------------------------------------------------------------------------
@@ -3775,4 +3796,4 @@ export {
3775
3796
  resetDefaultFlagsClient,
3776
3797
  createClient
3777
3798
  };
3778
- //# sourceMappingURL=chunk-7A7RG7ST.js.map
3799
+ //# sourceMappingURL=chunk-OIOT7N7A.js.map