@vercel/flags-core 1.5.1 → 1.6.0-7d29945-20260616152249
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 +3 -9
- package/dist/{chunk-JTIP7QPD.cjs → chunk-LPIUDLYE.cjs} +488 -254
- package/dist/chunk-LPIUDLYE.cjs.map +1 -0
- package/dist/{chunk-AXRUQULC.cjs → chunk-NHWFZTK2.cjs} +487 -253
- package/dist/chunk-NHWFZTK2.cjs.map +1 -0
- package/dist/{chunk-ITF6ZJ32.js → chunk-PSYHUXJC.js} +433 -199
- package/dist/chunk-PSYHUXJC.js.map +1 -0
- package/dist/{chunk-4B7CLR4J.js → chunk-S62BO7JU.js} +433 -199
- package/dist/chunk-S62BO7JU.js.map +1 -0
- package/dist/index.default.cjs +2 -2
- package/dist/index.default.d.cts +18 -3
- package/dist/index.default.d.ts +18 -3
- package/dist/index.default.js +1 -1
- package/dist/index.next-js.cjs +2 -2
- package/dist/index.next-js.d.cts +18 -3
- package/dist/index.next-js.d.ts +18 -3
- 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 +1 -1
- package/dist/chunk-4B7CLR4J.js.map +0 -1
- package/dist/chunk-AXRUQULC.cjs.map +0 -1
- package/dist/chunk-ITF6ZJ32.js.map +0 -1
- package/dist/chunk-JTIP7QPD.cjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3;// src/index.next-js.ts
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5;// src/index.next-js.ts
|
|
2
2
|
var _cache = require('next/cache');
|
|
3
3
|
|
|
4
4
|
// src/evaluate.ts
|
|
@@ -35,6 +35,22 @@ var MAX_REGEX_INPUT_LENGTH = 1e4;
|
|
|
35
35
|
var UINT32_MAX = 4294967295;
|
|
36
36
|
var SCALED_WEIGHTS = /* @__PURE__ */ Symbol("@vercel/flags-core:scaledWeights");
|
|
37
37
|
var COMPILED_REGEX = /* @__PURE__ */ Symbol("@vercel/flags-core:compiledRegex");
|
|
38
|
+
var EVALUATION_VARIANT_INDEX = /* @__PURE__ */ Symbol(
|
|
39
|
+
"@vercel/flags-core:evaluationVariantIndex"
|
|
40
|
+
);
|
|
41
|
+
function withVariantIndex(value, outcomeType, variantIndex) {
|
|
42
|
+
return Object.defineProperty(
|
|
43
|
+
{
|
|
44
|
+
value,
|
|
45
|
+
outcomeType
|
|
46
|
+
},
|
|
47
|
+
EVALUATION_VARIANT_INDEX,
|
|
48
|
+
{ value: variantIndex }
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
function getEvaluationVariantIndex(result) {
|
|
52
|
+
return result[EVALUATION_VARIANT_INDEX];
|
|
53
|
+
}
|
|
38
54
|
function getScaledWeights(outcome) {
|
|
39
55
|
const cached = outcome[SCALED_WEIGHTS];
|
|
40
56
|
if (cached) return cached;
|
|
@@ -298,10 +314,11 @@ function getVariant(variants, index) {
|
|
|
298
314
|
}
|
|
299
315
|
function handleOutcome(params, outcome) {
|
|
300
316
|
if (typeof outcome === "number") {
|
|
301
|
-
return
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
317
|
+
return withVariantIndex(
|
|
318
|
+
getVariant(params.definition.variants, outcome),
|
|
319
|
+
"value" /* VALUE */,
|
|
320
|
+
outcome
|
|
321
|
+
);
|
|
305
322
|
}
|
|
306
323
|
switch (outcome.type) {
|
|
307
324
|
case "split": {
|
|
@@ -311,15 +328,21 @@ function handleOutcome(params, outcome) {
|
|
|
311
328
|
outcome.defaultVariant
|
|
312
329
|
);
|
|
313
330
|
if (typeof lhs !== "string") {
|
|
314
|
-
return
|
|
331
|
+
return withVariantIndex(
|
|
332
|
+
defaultOutcome,
|
|
333
|
+
"split" /* SPLIT */,
|
|
334
|
+
outcome.defaultVariant
|
|
335
|
+
);
|
|
315
336
|
}
|
|
316
337
|
const value = _jsxxhash.xxHash32.call(void 0, lhs, params.definition.seed);
|
|
317
338
|
const scaledWeights = getScaledWeights(outcome);
|
|
318
339
|
const variantIndex = findWeightedIndex(scaledWeights, value, UINT32_MAX);
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
340
|
+
const selectedVariantIndex = variantIndex === -1 ? outcome.defaultVariant : variantIndex;
|
|
341
|
+
return withVariantIndex(
|
|
342
|
+
selectedVariantIndex === outcome.defaultVariant ? defaultOutcome : getVariant(params.definition.variants, selectedVariantIndex),
|
|
343
|
+
"split" /* SPLIT */,
|
|
344
|
+
selectedVariantIndex
|
|
345
|
+
);
|
|
323
346
|
}
|
|
324
347
|
case "rollout": {
|
|
325
348
|
const lhs = access(outcome.base, params);
|
|
@@ -328,18 +351,20 @@ function handleOutcome(params, outcome) {
|
|
|
328
351
|
outcome.defaultVariant
|
|
329
352
|
);
|
|
330
353
|
if (typeof lhs !== "string") {
|
|
331
|
-
return
|
|
354
|
+
return withVariantIndex(
|
|
355
|
+
defaultOutcome,
|
|
356
|
+
"rollout" /* ROLLOUT */,
|
|
357
|
+
outcome.defaultVariant
|
|
358
|
+
);
|
|
332
359
|
}
|
|
333
360
|
const now = Date.now();
|
|
334
361
|
const elapsed = now - outcome.startTimestamp;
|
|
335
362
|
if (elapsed < 0 || outcome.slots.length === 0) {
|
|
336
|
-
return
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
outcomeType: "rollout" /* ROLLOUT */
|
|
342
|
-
};
|
|
363
|
+
return withVariantIndex(
|
|
364
|
+
getVariant(params.definition.variants, outcome.rollFromVariant),
|
|
365
|
+
"rollout" /* ROLLOUT */,
|
|
366
|
+
outcome.rollFromVariant
|
|
367
|
+
);
|
|
343
368
|
}
|
|
344
369
|
let cumulativeDuration = 0;
|
|
345
370
|
let currentPromille = 0;
|
|
@@ -354,32 +379,27 @@ function handleOutcome(params, outcome) {
|
|
|
354
379
|
}
|
|
355
380
|
if (exhausted) currentPromille = 1e5;
|
|
356
381
|
if (currentPromille <= 0) {
|
|
357
|
-
return
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
outcomeType: "rollout" /* ROLLOUT */
|
|
363
|
-
};
|
|
382
|
+
return withVariantIndex(
|
|
383
|
+
getVariant(params.definition.variants, outcome.rollFromVariant),
|
|
384
|
+
"rollout" /* ROLLOUT */,
|
|
385
|
+
outcome.rollFromVariant
|
|
386
|
+
);
|
|
364
387
|
}
|
|
365
388
|
if (currentPromille >= 1e5) {
|
|
366
|
-
return
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
outcomeType: "rollout" /* ROLLOUT */
|
|
372
|
-
};
|
|
389
|
+
return withVariantIndex(
|
|
390
|
+
getVariant(params.definition.variants, outcome.rollToVariant),
|
|
391
|
+
"rollout" /* ROLLOUT */,
|
|
392
|
+
outcome.rollToVariant
|
|
393
|
+
);
|
|
373
394
|
}
|
|
374
395
|
const value = _jsxxhash.xxHash32.call(void 0, lhs, params.definition.seed);
|
|
375
396
|
const threshold = currentPromille / 1e5 * UINT32_MAX;
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
};
|
|
397
|
+
const selectedVariantIndex = value < threshold ? outcome.rollToVariant : outcome.rollFromVariant;
|
|
398
|
+
return withVariantIndex(
|
|
399
|
+
getVariant(params.definition.variants, selectedVariantIndex),
|
|
400
|
+
"rollout" /* ROLLOUT */,
|
|
401
|
+
selectedVariantIndex
|
|
402
|
+
);
|
|
383
403
|
}
|
|
384
404
|
default: {
|
|
385
405
|
const { type } = outcome;
|
|
@@ -467,7 +487,7 @@ function findWeightedIndex(weights, value, maxValue) {
|
|
|
467
487
|
}
|
|
468
488
|
|
|
469
489
|
// package.json
|
|
470
|
-
var version = "1.
|
|
490
|
+
var version = "1.6.0-7d29945-20260616152249";
|
|
471
491
|
|
|
472
492
|
// src/lib/report-value.ts
|
|
473
493
|
function internalReportValue(key, value, data) {
|
|
@@ -506,6 +526,14 @@ function getFallbackDatafile(id) {
|
|
|
506
526
|
if (ds.getFallbackDatafile) return ds.getFallbackDatafile();
|
|
507
527
|
throw new Error("flags: This data source does not support fallbacks");
|
|
508
528
|
}
|
|
529
|
+
function getVariantIdentifier(definition, result) {
|
|
530
|
+
const variantIndex = getEvaluationVariantIndex(result);
|
|
531
|
+
if (variantIndex === void 0) return "unknown";
|
|
532
|
+
return _nullishCoalesce(_optionalChain([definition, 'access', _20 => _20.variantIds, 'optionalAccess', _21 => _21[variantIndex]]), () => ( String(variantIndex)));
|
|
533
|
+
}
|
|
534
|
+
function trackEvaluation(controller, options) {
|
|
535
|
+
_optionalChain([controller, 'access', _22 => _22.trackEvaluation, 'optionalCall', _23 => _23(options)]);
|
|
536
|
+
}
|
|
509
537
|
async function evaluate2(id, flagKey, defaultValue, entities) {
|
|
510
538
|
const controller = getInstance(id).controller;
|
|
511
539
|
let datafile;
|
|
@@ -513,11 +541,17 @@ async function evaluate2(id, flagKey, defaultValue, entities) {
|
|
|
513
541
|
datafile = await controller.read();
|
|
514
542
|
} catch (error) {
|
|
515
543
|
if (defaultValue !== void 0) {
|
|
516
|
-
|
|
544
|
+
const result2 = {
|
|
517
545
|
value: defaultValue,
|
|
518
546
|
reason: "error" /* ERROR */,
|
|
519
547
|
errorMessage: error instanceof Error ? error.message : "Failed to read datafile"
|
|
520
548
|
};
|
|
549
|
+
trackEvaluation(controller, {
|
|
550
|
+
flagKey,
|
|
551
|
+
variant: "unknown",
|
|
552
|
+
reason: result2.reason
|
|
553
|
+
});
|
|
554
|
+
return result2;
|
|
521
555
|
}
|
|
522
556
|
throw error;
|
|
523
557
|
}
|
|
@@ -530,7 +564,7 @@ async function evaluate2(id, flagKey, defaultValue, entities) {
|
|
|
530
564
|
reason: "error" /* ERROR */
|
|
531
565
|
});
|
|
532
566
|
}
|
|
533
|
-
|
|
567
|
+
const result2 = {
|
|
534
568
|
value: defaultValue,
|
|
535
569
|
reason: "error" /* ERROR */,
|
|
536
570
|
errorCode: "FLAG_NOT_FOUND" /* FLAG_NOT_FOUND */,
|
|
@@ -544,6 +578,12 @@ async function evaluate2(id, flagKey, defaultValue, entities) {
|
|
|
544
578
|
mode: datafile.metrics.mode
|
|
545
579
|
}
|
|
546
580
|
};
|
|
581
|
+
trackEvaluation(controller, {
|
|
582
|
+
flagKey,
|
|
583
|
+
variant: "unknown",
|
|
584
|
+
reason: result2.reason
|
|
585
|
+
});
|
|
586
|
+
return result2;
|
|
547
587
|
}
|
|
548
588
|
const evalStartTime = Date.now();
|
|
549
589
|
const result = evaluate({
|
|
@@ -562,6 +602,14 @@ async function evaluate2(id, flagKey, defaultValue, entities) {
|
|
|
562
602
|
outcomeType: result.reason !== "error" /* ERROR */ ? result.outcomeType : void 0
|
|
563
603
|
});
|
|
564
604
|
}
|
|
605
|
+
trackEvaluation(controller, {
|
|
606
|
+
flagKey,
|
|
607
|
+
variant: getVariantIdentifier(
|
|
608
|
+
flagDefinition,
|
|
609
|
+
result
|
|
610
|
+
),
|
|
611
|
+
reason: result.reason
|
|
612
|
+
});
|
|
565
613
|
return Object.assign(result, {
|
|
566
614
|
metrics: {
|
|
567
615
|
evaluationMs: evaluationDurationMs,
|
|
@@ -587,6 +635,11 @@ async function bulkEvaluate2(id, flags, entities) {
|
|
|
587
635
|
reason: "error" /* ERROR */,
|
|
588
636
|
errorMessage
|
|
589
637
|
};
|
|
638
|
+
trackEvaluation(controller, {
|
|
639
|
+
flagKey: flag.key,
|
|
640
|
+
variant: "unknown",
|
|
641
|
+
reason: "error" /* ERROR */
|
|
642
|
+
});
|
|
590
643
|
}
|
|
591
644
|
return results2;
|
|
592
645
|
}
|
|
@@ -618,6 +671,11 @@ async function bulkEvaluate2(id, flags, entities) {
|
|
|
618
671
|
errorMessage: `@vercel/flags-core: Definition not found for flag "${key}"`,
|
|
619
672
|
metrics: { evaluationMs: 0, ...baseMetrics }
|
|
620
673
|
};
|
|
674
|
+
trackEvaluation(controller, {
|
|
675
|
+
flagKey: key,
|
|
676
|
+
variant: "unknown",
|
|
677
|
+
reason: "error" /* ERROR */
|
|
678
|
+
});
|
|
621
679
|
continue;
|
|
622
680
|
}
|
|
623
681
|
toEvaluate[key] = { definition: flagDefinition, defaultValue };
|
|
@@ -639,6 +697,14 @@ async function bulkEvaluate2(id, flags, entities) {
|
|
|
639
697
|
outcomeType: result.reason !== "error" /* ERROR */ ? result.outcomeType : void 0
|
|
640
698
|
});
|
|
641
699
|
}
|
|
700
|
+
trackEvaluation(controller, {
|
|
701
|
+
flagKey: key,
|
|
702
|
+
variant: getVariantIdentifier(
|
|
703
|
+
toEvaluate[key].definition,
|
|
704
|
+
result
|
|
705
|
+
),
|
|
706
|
+
reason: result.reason
|
|
707
|
+
});
|
|
642
708
|
results[key] = Object.assign(result, {
|
|
643
709
|
metrics: { evaluationMs: evaluationDurationMs, ...baseMetrics }
|
|
644
710
|
});
|
|
@@ -691,7 +757,7 @@ function createCreateRawClient(fns) {
|
|
|
691
757
|
},
|
|
692
758
|
getDatafile: async () => {
|
|
693
759
|
const instance = controllerInstanceMap.get(id);
|
|
694
|
-
if (_optionalChain([instance, 'optionalAccess',
|
|
760
|
+
if (_optionalChain([instance, 'optionalAccess', _24 => _24.initPromise])) {
|
|
695
761
|
try {
|
|
696
762
|
await instance.initPromise;
|
|
697
763
|
} catch (e) {
|
|
@@ -704,7 +770,7 @@ function createCreateRawClient(fns) {
|
|
|
704
770
|
},
|
|
705
771
|
evaluate: async (flagKey, defaultValue, entities) => {
|
|
706
772
|
const instance = controllerInstanceMap.get(id);
|
|
707
|
-
if (!_optionalChain([instance, 'optionalAccess',
|
|
773
|
+
if (!_optionalChain([instance, 'optionalAccess', _25 => _25.initialized])) {
|
|
708
774
|
try {
|
|
709
775
|
await api.initialize();
|
|
710
776
|
} catch (e2) {
|
|
@@ -714,7 +780,7 @@ function createCreateRawClient(fns) {
|
|
|
714
780
|
},
|
|
715
781
|
bulkEvaluate: async (flags, entities) => {
|
|
716
782
|
const instance = controllerInstanceMap.get(id);
|
|
717
|
-
if (!_optionalChain([instance, 'optionalAccess',
|
|
783
|
+
if (!_optionalChain([instance, 'optionalAccess', _26 => _26.initialized])) {
|
|
718
784
|
try {
|
|
719
785
|
await api.initialize();
|
|
720
786
|
} catch (e3) {
|
|
@@ -783,8 +849,8 @@ async function readBundledDefinitions(auth) {
|
|
|
783
849
|
return { definitions: null, state: "missing-entry" };
|
|
784
850
|
}
|
|
785
851
|
|
|
786
|
-
// src/utils/
|
|
787
|
-
var
|
|
852
|
+
// src/utils/ingest.ts
|
|
853
|
+
var _oidc = require('@vercel/oidc');
|
|
788
854
|
|
|
789
855
|
// src/utils/backoff.ts
|
|
790
856
|
var DEFAULT_BASE_MS = 250;
|
|
@@ -795,64 +861,304 @@ function getRetryDelayMs(attempt, options = {}) {
|
|
|
795
861
|
const ceiling = Math.min(capMs, baseMs * 2 ** Math.max(0, attempt - 1));
|
|
796
862
|
return Math.floor(Math.random() * ceiling);
|
|
797
863
|
}
|
|
798
|
-
function getJitteredWaitMs(baseMs, ratio) {
|
|
799
|
-
const min = baseMs * (1 - ratio);
|
|
800
|
-
const span = baseMs * 2 * ratio;
|
|
801
|
-
return Math.floor(min + Math.random() * span);
|
|
802
|
-
}
|
|
803
864
|
|
|
804
|
-
// src/utils/
|
|
805
|
-
var
|
|
806
|
-
var
|
|
865
|
+
// src/utils/ingest.ts
|
|
866
|
+
var MAX_RETRIES = 3;
|
|
867
|
+
var EVALUATING_OIDC_TOKEN_HEADER = "X-Vercel-Flags-Evaluating-OIDC-Token";
|
|
868
|
+
var isDebugMode = _optionalChain([process, 'access', _27 => _27.env, 'access', _28 => _28.DEBUG, 'optionalAccess', _29 => _29.includes, 'call', _30 => _30("@vercel/flags-core")]);
|
|
807
869
|
var debugLog = (...args) => {
|
|
808
870
|
if (!isDebugMode) return;
|
|
809
871
|
console.log(...args);
|
|
810
872
|
};
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
873
|
+
async function getEvaluatingOidcToken(auth) {
|
|
874
|
+
if (!auth.sdkKey) return void 0;
|
|
875
|
+
try {
|
|
876
|
+
return await _oidc.getVercelOidcToken.call(void 0, );
|
|
877
|
+
} catch (e4) {
|
|
878
|
+
return void 0;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
async function getIngestHeaders(options) {
|
|
882
|
+
const token = await options.auth.resolveToken();
|
|
883
|
+
const evaluatingOidcToken = await getEvaluatingOidcToken(options.auth);
|
|
884
|
+
return {
|
|
885
|
+
"Content-Type": "application/json",
|
|
886
|
+
Authorization: `Bearer ${token}`,
|
|
887
|
+
"User-Agent": `VercelFlagsCore/${version}`,
|
|
888
|
+
...process.env.VERCEL_ENV ? { "X-Vercel-Env": process.env.VERCEL_ENV } : null,
|
|
889
|
+
...evaluatingOidcToken ? { [EVALUATING_OIDC_TOKEN_HEADER]: evaluatingOidcToken } : null,
|
|
890
|
+
...isDebugMode ? { "x-vercel-debug-ingest": "1" } : null
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
async function sendIngestEvents(options, events, flushId) {
|
|
894
|
+
const eventsToSend = events.map((event) => event.ingestEvent());
|
|
895
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
896
|
+
try {
|
|
897
|
+
const response = await options.fetch(`${options.host}/v1/ingest`, {
|
|
898
|
+
method: "POST",
|
|
899
|
+
headers: await getIngestHeaders(options),
|
|
900
|
+
body: JSON.stringify(eventsToSend)
|
|
901
|
+
});
|
|
902
|
+
debugLog(
|
|
903
|
+
`@vercel/flags-core: Ingest response ${response.status} for ${eventsToSend.length} events on ${response.headers.get("x-vercel-id")}`
|
|
904
|
+
);
|
|
905
|
+
if (response.ok) {
|
|
906
|
+
break;
|
|
907
|
+
}
|
|
908
|
+
throw new Error(
|
|
909
|
+
`Ingest endpoint responded with status ${response.status} for ${eventsToSend.length} events on request ${response.headers.get("x-vercel-id")}.
|
|
910
|
+
Response body: ${await response.text().catch(() => null)}`
|
|
911
|
+
);
|
|
912
|
+
} catch (error) {
|
|
913
|
+
console.error(
|
|
914
|
+
`@vercel/flags-core: Error sending events (attempt=${attempt}/${MAX_RETRIES} flushId=${flushId}):`,
|
|
915
|
+
error
|
|
916
|
+
);
|
|
917
|
+
if (attempt < MAX_RETRIES) {
|
|
918
|
+
const delayMs = getRetryDelayMs(attempt);
|
|
919
|
+
await new Promise((res) => setTimeout(res, delayMs));
|
|
920
|
+
} else {
|
|
921
|
+
console.error(
|
|
922
|
+
`@vercel/flags-core: Dropped ${eventsToSend.length} events after ${MAX_RETRIES} attempts (flushId=${flushId})`
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// src/utils/request-context.ts
|
|
815
930
|
var SYMBOL_FOR_REQ_CONTEXT = /* @__PURE__ */ Symbol.for("@vercel/request-context");
|
|
816
931
|
var fromSymbol = globalThis;
|
|
817
932
|
function getRequestContext() {
|
|
818
933
|
try {
|
|
819
|
-
const ctx = _optionalChain([fromSymbol, 'access',
|
|
934
|
+
const ctx = _optionalChain([fromSymbol, 'access', _31 => _31[SYMBOL_FOR_REQ_CONTEXT], 'optionalAccess', _32 => _32.get, 'optionalCall', _33 => _33()]);
|
|
820
935
|
if (ctx && Object.hasOwn(ctx, "headers")) {
|
|
821
936
|
return {
|
|
822
937
|
ctx,
|
|
823
938
|
headers: ctx.headers
|
|
824
939
|
};
|
|
825
940
|
}
|
|
826
|
-
return { ctx, headers: void 0 };
|
|
827
|
-
} catch (
|
|
941
|
+
return { ctx: void 0, headers: void 0 };
|
|
942
|
+
} catch (e5) {
|
|
828
943
|
return { ctx: void 0, headers: void 0 };
|
|
829
944
|
}
|
|
830
945
|
}
|
|
831
|
-
|
|
832
|
-
|
|
946
|
+
|
|
947
|
+
// src/utils/scheduler.ts
|
|
948
|
+
var _functions = require('@vercel/functions');
|
|
949
|
+
var MAX_COUNT = 50;
|
|
950
|
+
var IDLE_FLUSH_WAIT_MS = 5e3;
|
|
951
|
+
var MAX_FLUSH_WAIT_MS = 6e4;
|
|
952
|
+
var Scheduler = (_class = class {
|
|
953
|
+
constructor(onFlush) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);
|
|
954
|
+
this.onFlush = onFlush;
|
|
955
|
+
}
|
|
956
|
+
__init() {this.count = 0}
|
|
957
|
+
__init2() {this.resolveWait = null}
|
|
958
|
+
__init3() {this.pending = null}
|
|
959
|
+
__init4() {this.idleTimeout = null}
|
|
960
|
+
__init5() {this.maxTimeout = null}
|
|
961
|
+
increment() {
|
|
962
|
+
this.count += 1;
|
|
963
|
+
if (this.count >= MAX_COUNT) {
|
|
964
|
+
this.resolveScheduledFlush();
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
scheduleFlush() {
|
|
968
|
+
if (!this.pending) {
|
|
969
|
+
this.pending = (async () => {
|
|
970
|
+
await new Promise((res) => {
|
|
971
|
+
this.resolveWait = res;
|
|
972
|
+
});
|
|
973
|
+
this.reset();
|
|
974
|
+
await this.onFlush();
|
|
975
|
+
})();
|
|
976
|
+
try {
|
|
977
|
+
_functions.waitUntil.call(void 0, this.pending);
|
|
978
|
+
} catch (e6) {
|
|
979
|
+
}
|
|
980
|
+
this.maxTimeout = setTimeout(
|
|
981
|
+
() => this.resolveScheduledFlush(),
|
|
982
|
+
MAX_FLUSH_WAIT_MS
|
|
983
|
+
);
|
|
984
|
+
}
|
|
985
|
+
this.resetIdleTimeout();
|
|
986
|
+
}
|
|
987
|
+
/**
|
|
988
|
+
* Resolves any in-flight scheduled flush and waits for its ingest to finish.
|
|
989
|
+
*/
|
|
990
|
+
async shutdown() {
|
|
991
|
+
this.clearTimeouts();
|
|
992
|
+
const pending = this.pending;
|
|
993
|
+
_optionalChain([this, 'access', _34 => _34.resolveWait, 'optionalCall', _35 => _35()]);
|
|
994
|
+
if (pending) await pending;
|
|
995
|
+
}
|
|
996
|
+
resetIdleTimeout() {
|
|
997
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
998
|
+
this.idleTimeout = setTimeout(
|
|
999
|
+
() => this.resolveScheduledFlush(),
|
|
1000
|
+
IDLE_FLUSH_WAIT_MS
|
|
1001
|
+
);
|
|
1002
|
+
}
|
|
1003
|
+
resolveScheduledFlush() {
|
|
1004
|
+
this.clearTimeouts();
|
|
1005
|
+
_optionalChain([this, 'access', _36 => _36.resolveWait, 'optionalCall', _37 => _37()]);
|
|
1006
|
+
}
|
|
1007
|
+
reset() {
|
|
1008
|
+
this.pending = null;
|
|
1009
|
+
this.resolveWait = null;
|
|
1010
|
+
this.count = 0;
|
|
1011
|
+
this.clearTimeouts();
|
|
1012
|
+
}
|
|
1013
|
+
clearTimeouts() {
|
|
1014
|
+
if (this.idleTimeout) {
|
|
1015
|
+
clearTimeout(this.idleTimeout);
|
|
1016
|
+
this.idleTimeout = null;
|
|
1017
|
+
}
|
|
1018
|
+
if (this.maxTimeout) {
|
|
1019
|
+
clearTimeout(this.maxTimeout);
|
|
1020
|
+
this.maxTimeout = null;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}, _class);
|
|
1024
|
+
|
|
1025
|
+
// src/utils/usage/flags-config-read.ts
|
|
1026
|
+
var FlagsConfigReadEvent = class {
|
|
833
1027
|
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
1028
|
+
constructor(headers, options) {
|
|
1029
|
+
this.payload = {
|
|
1030
|
+
deploymentId: process.env.VERCEL_DEPLOYMENT_ID,
|
|
1031
|
+
region: process.env.VERCEL_REGION
|
|
1032
|
+
};
|
|
1033
|
+
if (headers) {
|
|
1034
|
+
this.payload.vercelRequestId = _nullishCoalesce(headers["x-vercel-id"], () => ( void 0));
|
|
1035
|
+
this.payload.invocationHost = _nullishCoalesce(headers.host, () => ( void 0));
|
|
1036
|
+
}
|
|
1037
|
+
if (options) {
|
|
1038
|
+
this.payload.configOrigin = options.configOrigin;
|
|
1039
|
+
if (options.cacheStatus !== void 0) {
|
|
1040
|
+
this.payload.cacheStatus = options.cacheStatus;
|
|
1041
|
+
}
|
|
1042
|
+
if (options.cacheAction !== void 0) {
|
|
1043
|
+
this.payload.cacheAction = options.cacheAction;
|
|
1044
|
+
}
|
|
1045
|
+
if (options.cacheIsFirstRead !== void 0) {
|
|
1046
|
+
this.payload.cacheIsFirstRead = options.cacheIsFirstRead;
|
|
1047
|
+
}
|
|
1048
|
+
if (options.cacheIsBlocking !== void 0) {
|
|
1049
|
+
this.payload.cacheIsBlocking = options.cacheIsBlocking;
|
|
1050
|
+
}
|
|
1051
|
+
if (options.duration !== void 0) {
|
|
1052
|
+
this.payload.duration = options.duration;
|
|
1053
|
+
}
|
|
1054
|
+
if (options.configUpdatedAt !== void 0) {
|
|
1055
|
+
this.payload.configUpdatedAt = options.configUpdatedAt;
|
|
1056
|
+
}
|
|
1057
|
+
if (options.mode !== void 0) {
|
|
1058
|
+
this.payload.mode = options.mode;
|
|
1059
|
+
}
|
|
1060
|
+
if (options.revision !== void 0) {
|
|
1061
|
+
this.payload.revision = String(options.revision);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
const environment = process.env.VERCEL_ENV || process.env.NODE_ENV || void 0;
|
|
1065
|
+
if (environment) {
|
|
1066
|
+
this.payload.environment = environment;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
ingestEvent() {
|
|
1070
|
+
return {
|
|
1071
|
+
type: "FLAGS_CONFIG_READ",
|
|
1072
|
+
ts: Date.now(),
|
|
1073
|
+
payload: this.payload
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
};
|
|
1077
|
+
|
|
1078
|
+
// src/utils/usage/flags-evaluation.ts
|
|
1079
|
+
function evaluationBatchKey(options) {
|
|
1080
|
+
return JSON.stringify([
|
|
1081
|
+
options.flagKey,
|
|
1082
|
+
options.variant,
|
|
1083
|
+
options.reason,
|
|
1084
|
+
_nullishCoalesce(options.clientName, () => ( null))
|
|
1085
|
+
]);
|
|
1086
|
+
}
|
|
1087
|
+
var FlagsEvaluationEvent = class {
|
|
1088
|
+
|
|
1089
|
+
constructor(eventOptions) {
|
|
1090
|
+
this.payload = {
|
|
1091
|
+
flagKey: eventOptions.flagKey,
|
|
1092
|
+
variant: eventOptions.variant,
|
|
1093
|
+
reason: eventOptions.reason,
|
|
1094
|
+
count: 1
|
|
1095
|
+
};
|
|
1096
|
+
if (eventOptions.clientName) {
|
|
1097
|
+
this.payload.clientName = eventOptions.clientName;
|
|
1098
|
+
}
|
|
1099
|
+
Object.defineProperty(this, "batchKey", {
|
|
1100
|
+
value: JSON.stringify([
|
|
1101
|
+
this.payload.flagKey,
|
|
1102
|
+
this.payload.variant,
|
|
1103
|
+
this.payload.reason,
|
|
1104
|
+
_nullishCoalesce(this.payload.clientName, () => ( null))
|
|
1105
|
+
]),
|
|
1106
|
+
enumerable: false
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
increment() {
|
|
1110
|
+
this.payload.count += 1;
|
|
1111
|
+
}
|
|
1112
|
+
ingestEvent() {
|
|
1113
|
+
return {
|
|
1114
|
+
type: "FLAGS_EVALUATION",
|
|
1115
|
+
ts: Date.now(),
|
|
1116
|
+
payload: this.payload
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1120
|
+
|
|
1121
|
+
// src/utils/weak-map.ts
|
|
1122
|
+
var BetterWeakMap = (_class2 = class {constructor() { _class2.prototype.__init6.call(this);_class2.prototype.__init7.call(this); }
|
|
1123
|
+
__init6() {this._values = []}
|
|
1124
|
+
__init7() {this._keys = []}
|
|
1125
|
+
set(key, value) {
|
|
1126
|
+
this._keys.push(key);
|
|
1127
|
+
this._values.push(value);
|
|
1128
|
+
}
|
|
1129
|
+
values() {
|
|
1130
|
+
return this._values;
|
|
1131
|
+
}
|
|
1132
|
+
has(key) {
|
|
1133
|
+
return this._keys.includes(key);
|
|
1134
|
+
}
|
|
1135
|
+
keys() {
|
|
1136
|
+
return this._keys;
|
|
1137
|
+
}
|
|
1138
|
+
clear() {
|
|
1139
|
+
this._values = [];
|
|
1140
|
+
this._keys = [];
|
|
1141
|
+
}
|
|
1142
|
+
}, _class2);
|
|
1143
|
+
|
|
1144
|
+
// src/utils/usage-tracker.ts
|
|
1145
|
+
var UsageTracker = (_class3 = class {
|
|
1146
|
+
__init8() {this.flushCount = 0}
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
__init9() {this.readEvents = new BetterWeakMap()}
|
|
1150
|
+
__init10() {this.evaluationEvents = /* @__PURE__ */ new Map()}
|
|
1151
|
+
constructor(options) {;_class3.prototype.__init8.call(this);_class3.prototype.__init9.call(this);_class3.prototype.__init10.call(this);
|
|
841
1152
|
this.options = options;
|
|
1153
|
+
this.scheduler = new Scheduler(() => this.flushEvents());
|
|
842
1154
|
}
|
|
843
1155
|
/**
|
|
844
1156
|
* Triggers an immediate flush of any pending events.
|
|
845
1157
|
* Returns a promise that resolves when the flush completes.
|
|
846
1158
|
*/
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
return this.batcher.pending;
|
|
851
|
-
}
|
|
852
|
-
if (this.batcher.events.length > 0) {
|
|
853
|
-
return this.flushEvents();
|
|
854
|
-
}
|
|
855
|
-
return RESOLVED_VOID;
|
|
1159
|
+
async shutdown() {
|
|
1160
|
+
await this.scheduler.shutdown();
|
|
1161
|
+
await this.flushEvents();
|
|
856
1162
|
}
|
|
857
1163
|
/**
|
|
858
1164
|
* Tracks a config read event. Deduplicates by request context.
|
|
@@ -861,132 +1167,53 @@ var UsageTracker = (_class = class {
|
|
|
861
1167
|
try {
|
|
862
1168
|
const { ctx, headers } = getRequestContext();
|
|
863
1169
|
if (!ctx) return;
|
|
864
|
-
if (this.
|
|
865
|
-
|
|
866
|
-
const event = {
|
|
867
|
-
type: "FLAGS_CONFIG_READ",
|
|
868
|
-
ts: Date.now(),
|
|
869
|
-
payload: {
|
|
870
|
-
deploymentId: process.env.VERCEL_DEPLOYMENT_ID,
|
|
871
|
-
region: process.env.VERCEL_REGION
|
|
872
|
-
}
|
|
873
|
-
};
|
|
874
|
-
if (headers) {
|
|
875
|
-
event.payload.vercelRequestId = _nullishCoalesce(headers["x-vercel-id"], () => ( void 0));
|
|
876
|
-
event.payload.invocationHost = _nullishCoalesce(headers.host, () => ( void 0));
|
|
877
|
-
}
|
|
878
|
-
if (options) {
|
|
879
|
-
event.payload.configOrigin = options.configOrigin;
|
|
880
|
-
if (options.cacheStatus !== void 0) {
|
|
881
|
-
event.payload.cacheStatus = options.cacheStatus;
|
|
882
|
-
}
|
|
883
|
-
if (options.cacheAction !== void 0) {
|
|
884
|
-
event.payload.cacheAction = options.cacheAction;
|
|
885
|
-
}
|
|
886
|
-
if (options.cacheIsFirstRead !== void 0) {
|
|
887
|
-
event.payload.cacheIsFirstRead = options.cacheIsFirstRead;
|
|
888
|
-
}
|
|
889
|
-
if (options.cacheIsBlocking !== void 0) {
|
|
890
|
-
event.payload.cacheIsBlocking = options.cacheIsBlocking;
|
|
891
|
-
}
|
|
892
|
-
if (options.duration !== void 0) {
|
|
893
|
-
event.payload.duration = options.duration;
|
|
894
|
-
}
|
|
895
|
-
if (options.configUpdatedAt !== void 0) {
|
|
896
|
-
event.payload.configUpdatedAt = options.configUpdatedAt;
|
|
897
|
-
}
|
|
898
|
-
if (options.mode !== void 0) {
|
|
899
|
-
event.payload.mode = options.mode;
|
|
900
|
-
}
|
|
901
|
-
if (options.revision !== void 0) {
|
|
902
|
-
event.payload.revision = String(options.revision);
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
const environment = process.env.VERCEL_ENV || process.env.NODE_ENV || void 0;
|
|
906
|
-
if (environment) {
|
|
907
|
-
event.payload.environment = environment;
|
|
1170
|
+
if (this.readEvents.has(ctx)) {
|
|
1171
|
+
return;
|
|
908
1172
|
}
|
|
909
|
-
this.
|
|
910
|
-
this.scheduleFlush();
|
|
1173
|
+
this.readEvents.set(ctx, new FlagsConfigReadEvent(headers, options));
|
|
1174
|
+
this.scheduler.scheduleFlush();
|
|
1175
|
+
this.scheduler.increment();
|
|
911
1176
|
} catch (error) {
|
|
912
1177
|
console.error("@vercel/flags-core: Failed to record event:", error);
|
|
913
1178
|
}
|
|
914
1179
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
this.
|
|
927
|
-
this.batcher.resolveWait = null;
|
|
928
|
-
if (timeout) clearTimeout(timeout);
|
|
929
|
-
await this.flushEvents();
|
|
930
|
-
})();
|
|
931
|
-
try {
|
|
932
|
-
_functions.waitUntil.call(void 0, pending);
|
|
933
|
-
} catch (e5) {
|
|
1180
|
+
/**
|
|
1181
|
+
* Tracks a flag evaluation event.
|
|
1182
|
+
*/
|
|
1183
|
+
trackEvaluation(options) {
|
|
1184
|
+
try {
|
|
1185
|
+
const batchKey = evaluationBatchKey(options);
|
|
1186
|
+
const existingEvent = this.evaluationEvents.get(batchKey);
|
|
1187
|
+
if (existingEvent) {
|
|
1188
|
+
existingEvent.increment();
|
|
1189
|
+
} else {
|
|
1190
|
+
this.evaluationEvents.set(batchKey, new FlagsEvaluationEvent(options));
|
|
1191
|
+
this.scheduler.increment();
|
|
934
1192
|
}
|
|
935
|
-
this.
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
|
|
1193
|
+
this.scheduler.scheduleFlush();
|
|
1194
|
+
} catch (error) {
|
|
1195
|
+
console.error(
|
|
1196
|
+
"@vercel/flags-core: Failed to record evaluation event:",
|
|
1197
|
+
error
|
|
1198
|
+
);
|
|
939
1199
|
}
|
|
940
1200
|
}
|
|
1201
|
+
/**
|
|
1202
|
+
* Send all events to the ingest service
|
|
1203
|
+
*/
|
|
941
1204
|
async flushEvents() {
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
method: "POST",
|
|
953
|
-
headers: {
|
|
954
|
-
"Content-Type": "application/json",
|
|
955
|
-
Authorization: `Bearer ${token}`,
|
|
956
|
-
"User-Agent": `VercelFlagsCore/${version}`,
|
|
957
|
-
...process.env.VERCEL_ENV ? { "X-Vercel-Env": process.env.VERCEL_ENV } : null,
|
|
958
|
-
...isDebugMode ? { "x-vercel-debug-ingest": "1" } : null
|
|
959
|
-
},
|
|
960
|
-
body: JSON.stringify(eventsToSend)
|
|
961
|
-
}
|
|
962
|
-
);
|
|
963
|
-
debugLog(
|
|
964
|
-
`@vercel/flags-core: Ingest response ${response.status} for ${eventsToSend.length} events on ${response.headers.get("x-vercel-id")}`
|
|
965
|
-
);
|
|
966
|
-
if (response.ok) {
|
|
967
|
-
break;
|
|
968
|
-
}
|
|
969
|
-
throw new Error(
|
|
970
|
-
`Ingest endpoint responded with status ${response.status} for ${eventsToSend.length} events on request ${response.headers.get("x-vercel-id")}.
|
|
971
|
-
Response body: ${await response.text().catch(() => null)}`
|
|
972
|
-
);
|
|
973
|
-
} catch (error) {
|
|
974
|
-
console.error(
|
|
975
|
-
`@vercel/flags-core: Error sending events (attempt=${attempt}/${MAX_RETRIES} flushId=${flushId}):`,
|
|
976
|
-
error
|
|
977
|
-
);
|
|
978
|
-
if (attempt < MAX_RETRIES) {
|
|
979
|
-
const delayMs = getRetryDelayMs(attempt);
|
|
980
|
-
await new Promise((res) => setTimeout(res, delayMs));
|
|
981
|
-
} else {
|
|
982
|
-
console.error(
|
|
983
|
-
`@vercel/flags-core: Dropped ${eventsToSend.length} events after ${MAX_RETRIES} attempts (flushId=${flushId})`
|
|
984
|
-
);
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
}
|
|
1205
|
+
const events = [
|
|
1206
|
+
...this.readEvents.values(),
|
|
1207
|
+
...this.evaluationEvents.values()
|
|
1208
|
+
];
|
|
1209
|
+
if (events.length === 0) return;
|
|
1210
|
+
this.flushCount += 1;
|
|
1211
|
+
const flushId = this.flushCount;
|
|
1212
|
+
this.readEvents.clear();
|
|
1213
|
+
this.evaluationEvents.clear();
|
|
1214
|
+
await sendIngestEvents(this.options, events, flushId);
|
|
988
1215
|
}
|
|
989
|
-
},
|
|
1216
|
+
}, _class3);
|
|
990
1217
|
|
|
991
1218
|
// src/errors.ts
|
|
992
1219
|
var FallbackNotFoundError = class extends Error {
|
|
@@ -1045,7 +1272,7 @@ var BundledSource = class {
|
|
|
1045
1272
|
*/
|
|
1046
1273
|
async tryLoad() {
|
|
1047
1274
|
const result = await this.getResult();
|
|
1048
|
-
if (_optionalChain([result, 'optionalAccess',
|
|
1275
|
+
if (_optionalChain([result, 'optionalAccess', _38 => _38.state]) === "ok" && result.definitions) {
|
|
1049
1276
|
return result.definitions;
|
|
1050
1277
|
}
|
|
1051
1278
|
return void 0;
|
|
@@ -1085,14 +1312,14 @@ async function fetchDatafile(options) {
|
|
|
1085
1312
|
signal: controller.signal
|
|
1086
1313
|
});
|
|
1087
1314
|
clearTimeout(timeoutId);
|
|
1088
|
-
_optionalChain([options, 'access',
|
|
1315
|
+
_optionalChain([options, 'access', _39 => _39.signal, 'optionalAccess', _40 => _40.removeEventListener, 'call', _41 => _41("abort", onExternalAbort)]);
|
|
1089
1316
|
if (!res.ok) {
|
|
1090
1317
|
throw new Error(`Failed to fetch data: ${res.statusText}`);
|
|
1091
1318
|
}
|
|
1092
1319
|
return res.json();
|
|
1093
1320
|
} catch (error) {
|
|
1094
1321
|
clearTimeout(timeoutId);
|
|
1095
|
-
_optionalChain([options, 'access',
|
|
1322
|
+
_optionalChain([options, 'access', _42 => _42.signal, 'optionalAccess', _43 => _43.removeEventListener, 'call', _44 => _44("abort", onExternalAbort)]);
|
|
1096
1323
|
throw error instanceof Error ? error : new Error("Unknown fetch error");
|
|
1097
1324
|
}
|
|
1098
1325
|
}
|
|
@@ -1141,13 +1368,14 @@ function normalizeOptions(options) {
|
|
|
1141
1368
|
polling,
|
|
1142
1369
|
buildStep,
|
|
1143
1370
|
fetch: _nullishCoalesce(options.fetch, () => ( globalThis.fetch)),
|
|
1144
|
-
host: "https://flags.vercel.com"
|
|
1371
|
+
host: "https://flags.vercel.com",
|
|
1372
|
+
clientName: options.clientName
|
|
1145
1373
|
};
|
|
1146
1374
|
}
|
|
1147
1375
|
|
|
1148
1376
|
// src/controller/typed-emitter.ts
|
|
1149
|
-
var TypedEmitter = (
|
|
1150
|
-
|
|
1377
|
+
var TypedEmitter = (_class4 = class {constructor() { _class4.prototype.__init11.call(this); }
|
|
1378
|
+
__init11() {this.handlers = /* @__PURE__ */ new Map()}
|
|
1151
1379
|
on(event, handler) {
|
|
1152
1380
|
let set = this.handlers.get(event);
|
|
1153
1381
|
if (!set) {
|
|
@@ -1157,7 +1385,7 @@ var TypedEmitter = (_class2 = class {constructor() { _class2.prototype.__init4.c
|
|
|
1157
1385
|
set.add(handler);
|
|
1158
1386
|
}
|
|
1159
1387
|
off(event, handler) {
|
|
1160
|
-
_optionalChain([this, 'access',
|
|
1388
|
+
_optionalChain([this, 'access', _45 => _45.handlers, 'access', _46 => _46.get, 'call', _47 => _47(event), 'optionalAccess', _48 => _48.delete, 'call', _49 => _49(handler)]);
|
|
1161
1389
|
}
|
|
1162
1390
|
emit(event, ...args) {
|
|
1163
1391
|
const set = this.handlers.get(event);
|
|
@@ -1167,7 +1395,7 @@ var TypedEmitter = (_class2 = class {constructor() { _class2.prototype.__init4.c
|
|
|
1167
1395
|
}
|
|
1168
1396
|
}
|
|
1169
1397
|
}
|
|
1170
|
-
},
|
|
1398
|
+
}, _class4);
|
|
1171
1399
|
|
|
1172
1400
|
// src/controller/polling-source.ts
|
|
1173
1401
|
var PollingSource = class extends TypedEmitter {
|
|
@@ -1183,11 +1411,11 @@ var PollingSource = class extends TypedEmitter {
|
|
|
1183
1411
|
* Emits 'data' on success, 'error' on failure.
|
|
1184
1412
|
*/
|
|
1185
1413
|
async poll() {
|
|
1186
|
-
if (_optionalChain([this, 'access',
|
|
1414
|
+
if (_optionalChain([this, 'access', _50 => _50.abortController, 'optionalAccess', _51 => _51.signal, 'access', _52 => _52.aborted])) return;
|
|
1187
1415
|
try {
|
|
1188
1416
|
const data = await fetchDatafile({
|
|
1189
1417
|
...this.config,
|
|
1190
|
-
signal: _optionalChain([this, 'access',
|
|
1418
|
+
signal: _optionalChain([this, 'access', _53 => _53.abortController, 'optionalAccess', _54 => _54.signal])
|
|
1191
1419
|
});
|
|
1192
1420
|
this.emit("data", data);
|
|
1193
1421
|
} catch (error) {
|
|
@@ -1216,7 +1444,7 @@ var PollingSource = class extends TypedEmitter {
|
|
|
1216
1444
|
clearInterval(this.intervalId);
|
|
1217
1445
|
this.intervalId = void 0;
|
|
1218
1446
|
}
|
|
1219
|
-
_optionalChain([this, 'access',
|
|
1447
|
+
_optionalChain([this, 'access', _55 => _55.abortController, 'optionalAccess', _56 => _56.abort, 'call', _57 => _57()]);
|
|
1220
1448
|
this.abortController = void 0;
|
|
1221
1449
|
}
|
|
1222
1450
|
};
|
|
@@ -1264,13 +1492,9 @@ async function connectStream(config, callbacks) {
|
|
|
1264
1492
|
});
|
|
1265
1493
|
void (async () => {
|
|
1266
1494
|
let initialDataReceived = false;
|
|
1267
|
-
let lastError;
|
|
1268
1495
|
while (!abortController.signal.aborted) {
|
|
1269
1496
|
if (retryCount > MAX_RETRY_COUNT) {
|
|
1270
|
-
console.error(
|
|
1271
|
-
"@vercel/flags-core: Max retry count exceeded",
|
|
1272
|
-
_nullishCoalesce(lastError, () => ( "stream closed repeatedly without an error"))
|
|
1273
|
-
);
|
|
1497
|
+
console.error("@vercel/flags-core: Max retry count exceeded");
|
|
1274
1498
|
if (!initialDataReceived) {
|
|
1275
1499
|
rejectInit(
|
|
1276
1500
|
new Error("stream: max retry count exceeded before receiving data")
|
|
@@ -1290,7 +1514,7 @@ async function connectStream(config, callbacks) {
|
|
|
1290
1514
|
if (pingTimeoutId !== void 0) clearTimeout(pingTimeoutId);
|
|
1291
1515
|
if (!initialDataReceived) return;
|
|
1292
1516
|
pingTimeoutId = setTimeout(() => {
|
|
1293
|
-
_optionalChain([responseBody, 'optionalAccess',
|
|
1517
|
+
_optionalChain([responseBody, 'optionalAccess', _58 => _58.cancel, 'call', _59 => _59(), 'access', _60 => _60.catch, 'call', _61 => _61(() => {
|
|
1294
1518
|
})]);
|
|
1295
1519
|
connectionAbort.abort();
|
|
1296
1520
|
}, PING_TIMEOUT_MS);
|
|
@@ -1309,7 +1533,7 @@ async function connectStream(config, callbacks) {
|
|
|
1309
1533
|
if (vercelEnv) {
|
|
1310
1534
|
headers["X-Vercel-Env"] = vercelEnv;
|
|
1311
1535
|
}
|
|
1312
|
-
const revision = _optionalChain([config, 'access',
|
|
1536
|
+
const revision = _optionalChain([config, 'access', _62 => _62.revision, 'optionalCall', _63 => _63()]);
|
|
1313
1537
|
if (revision !== void 0) {
|
|
1314
1538
|
headers["X-Revision"] = String(revision);
|
|
1315
1539
|
}
|
|
@@ -1355,7 +1579,7 @@ async function connectStream(config, callbacks) {
|
|
|
1355
1579
|
let message;
|
|
1356
1580
|
try {
|
|
1357
1581
|
message = JSON.parse(line);
|
|
1358
|
-
} catch (
|
|
1582
|
+
} catch (e7) {
|
|
1359
1583
|
console.warn(
|
|
1360
1584
|
"@vercel/flags-core: Failed to parse stream message, skipping"
|
|
1361
1585
|
);
|
|
@@ -1371,7 +1595,7 @@ async function connectStream(config, callbacks) {
|
|
|
1371
1595
|
resetPingTimeout();
|
|
1372
1596
|
}
|
|
1373
1597
|
if (message.type === "primed") {
|
|
1374
|
-
_optionalChain([onPrimed, 'optionalCall',
|
|
1598
|
+
_optionalChain([onPrimed, 'optionalCall', _64 => _64(message)]);
|
|
1375
1599
|
retryCount = 0;
|
|
1376
1600
|
if (!initialDataReceived) {
|
|
1377
1601
|
initialDataReceived = true;
|
|
@@ -1394,7 +1618,7 @@ async function connectStream(config, callbacks) {
|
|
|
1394
1618
|
clearTimeout(pingTimeoutId);
|
|
1395
1619
|
abortController.signal.removeEventListener("abort", onMainAbort);
|
|
1396
1620
|
if (!abortController.signal.aborted) {
|
|
1397
|
-
_optionalChain([onDisconnect, 'optionalCall',
|
|
1621
|
+
_optionalChain([onDisconnect, 'optionalCall', _65 => _65()]);
|
|
1398
1622
|
retryCount++;
|
|
1399
1623
|
const elapsed = Date.now() - lastAttemptTime;
|
|
1400
1624
|
const minGap = Math.max(0, BASE_RETRY_DELAY_MS - elapsed);
|
|
@@ -1413,9 +1637,9 @@ async function connectStream(config, callbacks) {
|
|
|
1413
1637
|
break;
|
|
1414
1638
|
}
|
|
1415
1639
|
if (!connectionAbort.signal.aborted) {
|
|
1416
|
-
|
|
1640
|
+
console.error("@vercel/flags-core: Stream error", error);
|
|
1417
1641
|
}
|
|
1418
|
-
_optionalChain([onDisconnect, 'optionalCall',
|
|
1642
|
+
_optionalChain([onDisconnect, 'optionalCall', _66 => _66()]);
|
|
1419
1643
|
retryCount++;
|
|
1420
1644
|
const elapsed = Date.now() - lastAttemptTime;
|
|
1421
1645
|
const minGap = Math.max(0, BASE_RETRY_DELAY_MS - elapsed);
|
|
@@ -1494,7 +1718,7 @@ var StreamSource = class extends TypedEmitter {
|
|
|
1494
1718
|
* Stop the stream connection.
|
|
1495
1719
|
*/
|
|
1496
1720
|
stop() {
|
|
1497
|
-
_optionalChain([this, 'access',
|
|
1721
|
+
_optionalChain([this, 'access', _67 => _67.abortController, 'optionalAccess', _68 => _68.abort, 'call', _69 => _69()]);
|
|
1498
1722
|
this.abortController = void 0;
|
|
1499
1723
|
this.promise = void 0;
|
|
1500
1724
|
}
|
|
@@ -1526,34 +1750,34 @@ function parseConfigUpdatedAt(value) {
|
|
|
1526
1750
|
}
|
|
1527
1751
|
return void 0;
|
|
1528
1752
|
}
|
|
1529
|
-
var Controller = (
|
|
1753
|
+
var Controller = (_class5 = class {
|
|
1530
1754
|
|
|
1531
1755
|
// State machine
|
|
1532
|
-
|
|
1756
|
+
__init12() {this.state = "idle"}
|
|
1533
1757
|
// Data state — tagged with origin
|
|
1534
1758
|
|
|
1535
1759
|
// Memoized data spread for read() / getDatafile().
|
|
1536
1760
|
// Rebuilt only when `this.data` reference changes (e.g. on stream/poll update).
|
|
1537
1761
|
// Holds the result of stripping `_origin`; metrics are appended per-call.
|
|
1538
|
-
|
|
1539
|
-
|
|
1762
|
+
__init13() {this.dataViewSource = void 0}
|
|
1763
|
+
__init14() {this.dataViewBase = void 0}
|
|
1540
1764
|
// Sources (I/O delegates)
|
|
1541
1765
|
|
|
1542
1766
|
|
|
1543
1767
|
|
|
1544
1768
|
// Usage tracking
|
|
1545
1769
|
|
|
1546
|
-
|
|
1770
|
+
__init15() {this.isFirstGetData = true}
|
|
1547
1771
|
// Build-step deduplication
|
|
1548
|
-
|
|
1549
|
-
|
|
1772
|
+
__init16() {this.buildDataPromise = null}
|
|
1773
|
+
__init17() {this.buildReadTracked = false}
|
|
1550
1774
|
// Suppresses usage tracking when the SDK key is unauthorized
|
|
1551
|
-
|
|
1552
|
-
constructor(options) {;
|
|
1775
|
+
__init18() {this.unauthorized = false}
|
|
1776
|
+
constructor(options) {;_class5.prototype.__init12.call(this);_class5.prototype.__init13.call(this);_class5.prototype.__init14.call(this);_class5.prototype.__init15.call(this);_class5.prototype.__init16.call(this);_class5.prototype.__init17.call(this);_class5.prototype.__init18.call(this);_class5.prototype.__init19.call(this);_class5.prototype.__init20.call(this);_class5.prototype.__init21.call(this);_class5.prototype.__init22.call(this);_class5.prototype.__init23.call(this);_class5.prototype.__init24.call(this);
|
|
1553
1777
|
this.options = normalizeOptions(options);
|
|
1554
1778
|
this.streamSource = new StreamSource(
|
|
1555
1779
|
this.options,
|
|
1556
|
-
() => _optionalChain([this, 'access',
|
|
1780
|
+
() => _optionalChain([this, 'access', _70 => _70.data, 'optionalAccess', _71 => _71.revision])
|
|
1557
1781
|
);
|
|
1558
1782
|
this.pollingSource = new PollingSource(this.options);
|
|
1559
1783
|
this.bundledSource = new BundledSource({
|
|
@@ -1567,32 +1791,32 @@ var Controller = (_class3 = class {
|
|
|
1567
1791
|
this.usageTracker = new UsageTracker(this.options);
|
|
1568
1792
|
}
|
|
1569
1793
|
// Source event handlers (stored for cleanup)
|
|
1570
|
-
|
|
1794
|
+
__init19() {this.onStreamData = (data) => {
|
|
1571
1795
|
if (this.isNewerData(data)) {
|
|
1572
1796
|
this.data = tagData(data, "stream");
|
|
1573
1797
|
}
|
|
1574
1798
|
}}
|
|
1575
|
-
|
|
1799
|
+
__init20() {this.onStreamPrimed = () => {
|
|
1576
1800
|
if (this.state === "degraded" || this.state === "initializing:stream") {
|
|
1577
1801
|
this.transition("streaming");
|
|
1578
1802
|
}
|
|
1579
1803
|
}}
|
|
1580
|
-
|
|
1804
|
+
__init21() {this.onStreamConnected = () => {
|
|
1581
1805
|
if (this.state === "degraded" || this.state === "initializing:stream") {
|
|
1582
1806
|
this.transition("streaming");
|
|
1583
1807
|
}
|
|
1584
1808
|
}}
|
|
1585
|
-
|
|
1809
|
+
__init22() {this.onStreamDisconnected = () => {
|
|
1586
1810
|
if (this.state === "streaming") {
|
|
1587
1811
|
this.transition("degraded");
|
|
1588
1812
|
}
|
|
1589
1813
|
}}
|
|
1590
|
-
|
|
1814
|
+
__init23() {this.onPollData = (data) => {
|
|
1591
1815
|
if (this.isNewerData(data)) {
|
|
1592
1816
|
this.data = tagData(data, "poll");
|
|
1593
1817
|
}
|
|
1594
1818
|
}}
|
|
1595
|
-
|
|
1819
|
+
__init24() {this.onPollError = (error) => {
|
|
1596
1820
|
console.error("@vercel/flags-core: Poll failed:", error);
|
|
1597
1821
|
}}
|
|
1598
1822
|
// ---------------------------------------------------------------------------
|
|
@@ -1661,7 +1885,7 @@ var Controller = (_class3 = class {
|
|
|
1661
1885
|
if (bundled) {
|
|
1662
1886
|
this.data = tagData(bundled, "bundled");
|
|
1663
1887
|
}
|
|
1664
|
-
} catch (
|
|
1888
|
+
} catch (e8) {
|
|
1665
1889
|
}
|
|
1666
1890
|
}
|
|
1667
1891
|
if (this.data) {
|
|
@@ -1730,7 +1954,7 @@ var Controller = (_class3 = class {
|
|
|
1730
1954
|
this.pollingSource.stop();
|
|
1731
1955
|
this.data = this.options.datafile ? tagData(this.options.datafile, "provided") : void 0;
|
|
1732
1956
|
this.transition("shutdown");
|
|
1733
|
-
await this.usageTracker.
|
|
1957
|
+
await this.usageTracker.shutdown();
|
|
1734
1958
|
}
|
|
1735
1959
|
/**
|
|
1736
1960
|
* Returns the datafile with metrics.
|
|
@@ -1763,7 +1987,7 @@ var Controller = (_class3 = class {
|
|
|
1763
1987
|
this.data = tagData(fetched, "fetched");
|
|
1764
1988
|
result = this.data;
|
|
1765
1989
|
cacheStatus = "MISS";
|
|
1766
|
-
} catch (
|
|
1990
|
+
} catch (e9) {
|
|
1767
1991
|
throw new Error(
|
|
1768
1992
|
"@vercel/flags-core: No flag definitions available. Initialize the client or provide a datafile."
|
|
1769
1993
|
);
|
|
@@ -1848,7 +2072,7 @@ var Controller = (_class3 = class {
|
|
|
1848
2072
|
clearTimeout(timeoutId);
|
|
1849
2073
|
if (result === "timeout") {
|
|
1850
2074
|
console.warn(
|
|
1851
|
-
"@vercel/flags-core: Stream initialization timeout, falling back
|
|
2075
|
+
"@vercel/flags-core: Stream initialization timeout, falling back"
|
|
1852
2076
|
);
|
|
1853
2077
|
void this.streamSource.start().catch(() => {
|
|
1854
2078
|
});
|
|
@@ -1882,7 +2106,7 @@ var Controller = (_class3 = class {
|
|
|
1882
2106
|
return true;
|
|
1883
2107
|
}
|
|
1884
2108
|
return false;
|
|
1885
|
-
} catch (
|
|
2109
|
+
} catch (e10) {
|
|
1886
2110
|
return false;
|
|
1887
2111
|
}
|
|
1888
2112
|
}
|
|
@@ -1898,7 +2122,7 @@ var Controller = (_class3 = class {
|
|
|
1898
2122
|
clearTimeout(timeoutId);
|
|
1899
2123
|
if (result === "timeout") {
|
|
1900
2124
|
console.warn(
|
|
1901
|
-
"@vercel/flags-core: Polling initialization timeout, falling back
|
|
2125
|
+
"@vercel/flags-core: Polling initialization timeout, falling back"
|
|
1902
2126
|
);
|
|
1903
2127
|
return false;
|
|
1904
2128
|
}
|
|
@@ -1907,7 +2131,7 @@ var Controller = (_class3 = class {
|
|
|
1907
2131
|
return true;
|
|
1908
2132
|
}
|
|
1909
2133
|
return false;
|
|
1910
|
-
} catch (
|
|
2134
|
+
} catch (e11) {
|
|
1911
2135
|
clearTimeout(timeoutId);
|
|
1912
2136
|
return false;
|
|
1913
2137
|
}
|
|
@@ -1957,7 +2181,7 @@ var Controller = (_class3 = class {
|
|
|
1957
2181
|
fetch: this.options.fetch
|
|
1958
2182
|
});
|
|
1959
2183
|
return tagData(fetched, "fetched");
|
|
1960
|
-
} catch (
|
|
2184
|
+
} catch (e12) {
|
|
1961
2185
|
}
|
|
1962
2186
|
throw new Error(
|
|
1963
2187
|
"@vercel/flags-core: No flag definitions available during build. Provide a datafile or bundled definitions."
|
|
@@ -1991,7 +2215,7 @@ var Controller = (_class3 = class {
|
|
|
1991
2215
|
this.data = tagData(fetched, "fetched");
|
|
1992
2216
|
this.transition("degraded");
|
|
1993
2217
|
return;
|
|
1994
|
-
} catch (
|
|
2218
|
+
} catch (e13) {
|
|
1995
2219
|
}
|
|
1996
2220
|
}
|
|
1997
2221
|
throw new Error(
|
|
@@ -2043,7 +2267,7 @@ var Controller = (_class3 = class {
|
|
|
2043
2267
|
this.data = tagData(fetched, "fetched");
|
|
2044
2268
|
this.transition("degraded");
|
|
2045
2269
|
return [this.data, "MISS"];
|
|
2046
|
-
} catch (
|
|
2270
|
+
} catch (e14) {
|
|
2047
2271
|
}
|
|
2048
2272
|
}
|
|
2049
2273
|
throw new Error(
|
|
@@ -2095,11 +2319,11 @@ var Controller = (_class3 = class {
|
|
|
2095
2319
|
duration: Date.now() - startTime,
|
|
2096
2320
|
mode: mode === "streaming" ? "stream" : mode === "polling" ? "poll" : mode
|
|
2097
2321
|
};
|
|
2098
|
-
const configUpdatedAt = _optionalChain([this, 'access',
|
|
2322
|
+
const configUpdatedAt = _optionalChain([this, 'access', _72 => _72.data, 'optionalAccess', _73 => _73.configUpdatedAt]);
|
|
2099
2323
|
if (typeof configUpdatedAt === "number") {
|
|
2100
2324
|
trackOptions.configUpdatedAt = configUpdatedAt;
|
|
2101
2325
|
}
|
|
2102
|
-
const revision = _optionalChain([this, 'access',
|
|
2326
|
+
const revision = _optionalChain([this, 'access', _74 => _74.data, 'optionalAccess', _75 => _75.revision]);
|
|
2103
2327
|
if (typeof revision === "number") {
|
|
2104
2328
|
trackOptions.revision = revision;
|
|
2105
2329
|
}
|
|
@@ -2108,10 +2332,20 @@ var Controller = (_class3 = class {
|
|
|
2108
2332
|
}
|
|
2109
2333
|
this.usageTracker.trackRead(trackOptions);
|
|
2110
2334
|
}
|
|
2111
|
-
|
|
2335
|
+
/**
|
|
2336
|
+
* Tracks a flag evaluation for usage analytics.
|
|
2337
|
+
*/
|
|
2338
|
+
trackEvaluation(options) {
|
|
2339
|
+
if (this.unauthorized) return;
|
|
2340
|
+
this.usageTracker.trackEvaluation({
|
|
2341
|
+
...options,
|
|
2342
|
+
clientName: _nullishCoalesce(options.clientName, () => ( this.options.clientName))
|
|
2343
|
+
});
|
|
2344
|
+
}
|
|
2345
|
+
}, _class5);
|
|
2112
2346
|
|
|
2113
2347
|
// src/controller/auth.ts
|
|
2114
|
-
|
|
2348
|
+
|
|
2115
2349
|
|
|
2116
2350
|
// src/utils/sdk-keys.ts
|
|
2117
2351
|
var SDK_KEY_REGEX = /^vf_(?:server|client)_/;
|
|
@@ -2122,7 +2356,7 @@ function parseSdkKeyFromFlagsConnectionString(text) {
|
|
|
2122
2356
|
const params = new URLSearchParams(text.slice(6));
|
|
2123
2357
|
const sdkKey = params.get("sdkKey");
|
|
2124
2358
|
if (sdkKey && SDK_KEY_REGEX.test(sdkKey)) return sdkKey;
|
|
2125
|
-
} catch (
|
|
2359
|
+
} catch (e15) {
|
|
2126
2360
|
}
|
|
2127
2361
|
return null;
|
|
2128
2362
|
}
|
|
@@ -2131,7 +2365,7 @@ function parseSdkKeyFromFlagsConnectionString(text) {
|
|
|
2131
2365
|
async function getOidcToken() {
|
|
2132
2366
|
try {
|
|
2133
2367
|
return await _oidc.getVercelOidcToken.call(void 0, );
|
|
2134
|
-
} catch (
|
|
2368
|
+
} catch (e16) {
|
|
2135
2369
|
throw new Error(
|
|
2136
2370
|
[
|
|
2137
2371
|
"@vercel/flags-core: Failed to get OIDC token.",
|
|
@@ -2226,7 +2460,7 @@ function setCacheLife() {
|
|
|
2226
2460
|
try {
|
|
2227
2461
|
_cache.cacheLife.call(void 0, { revalidate: 0, expire: 0 });
|
|
2228
2462
|
_cache.cacheLife.call(void 0, { stale: 60 });
|
|
2229
|
-
} catch (
|
|
2463
|
+
} catch (e17) {
|
|
2230
2464
|
}
|
|
2231
2465
|
}
|
|
2232
2466
|
var cachedFns = {
|
|
@@ -2275,4 +2509,4 @@ var { flagsClient, resetDefaultFlagsClient, createClient } = make(
|
|
|
2275
2509
|
|
|
2276
2510
|
|
|
2277
2511
|
exports.ResolutionReason = ResolutionReason; exports.evaluate = evaluate; exports.FallbackNotFoundError = FallbackNotFoundError; exports.FallbackEntryNotFoundError = FallbackEntryNotFoundError; exports.Controller = Controller; exports.flagsClient = flagsClient; exports.resetDefaultFlagsClient = resetDefaultFlagsClient; exports.createClient = createClient;
|
|
2278
|
-
//# sourceMappingURL=chunk-
|
|
2512
|
+
//# sourceMappingURL=chunk-LPIUDLYE.cjs.map
|