@vercel/flags-core 1.5.0 → 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 +6 -0
- package/dist/{chunk-CSSU7O2G.cjs → chunk-LPIUDLYE.cjs} +484 -246
- package/dist/chunk-LPIUDLYE.cjs.map +1 -0
- package/dist/{chunk-K3VOC24J.cjs → chunk-NHWFZTK2.cjs} +483 -245
- package/dist/chunk-NHWFZTK2.cjs.map +1 -0
- package/dist/{chunk-WTGXBSWR.js → chunk-PSYHUXJC.js} +429 -191
- package/dist/chunk-PSYHUXJC.js.map +1 -0
- package/dist/{chunk-D3AZORK2.js → chunk-S62BO7JU.js} +429 -191
- 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-CSSU7O2G.cjs.map +0 -1
- package/dist/chunk-D3AZORK2.js.map +0 -1
- package/dist/chunk-K3VOC24J.cjs.map +0 -1
- package/dist/chunk-WTGXBSWR.js.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
|
};
|
|
@@ -1286,7 +1514,7 @@ async function connectStream(config, callbacks) {
|
|
|
1286
1514
|
if (pingTimeoutId !== void 0) clearTimeout(pingTimeoutId);
|
|
1287
1515
|
if (!initialDataReceived) return;
|
|
1288
1516
|
pingTimeoutId = setTimeout(() => {
|
|
1289
|
-
_optionalChain([responseBody, 'optionalAccess',
|
|
1517
|
+
_optionalChain([responseBody, 'optionalAccess', _58 => _58.cancel, 'call', _59 => _59(), 'access', _60 => _60.catch, 'call', _61 => _61(() => {
|
|
1290
1518
|
})]);
|
|
1291
1519
|
connectionAbort.abort();
|
|
1292
1520
|
}, PING_TIMEOUT_MS);
|
|
@@ -1305,7 +1533,7 @@ async function connectStream(config, callbacks) {
|
|
|
1305
1533
|
if (vercelEnv) {
|
|
1306
1534
|
headers["X-Vercel-Env"] = vercelEnv;
|
|
1307
1535
|
}
|
|
1308
|
-
const revision = _optionalChain([config, 'access',
|
|
1536
|
+
const revision = _optionalChain([config, 'access', _62 => _62.revision, 'optionalCall', _63 => _63()]);
|
|
1309
1537
|
if (revision !== void 0) {
|
|
1310
1538
|
headers["X-Revision"] = String(revision);
|
|
1311
1539
|
}
|
|
@@ -1351,7 +1579,7 @@ async function connectStream(config, callbacks) {
|
|
|
1351
1579
|
let message;
|
|
1352
1580
|
try {
|
|
1353
1581
|
message = JSON.parse(line);
|
|
1354
|
-
} catch (
|
|
1582
|
+
} catch (e7) {
|
|
1355
1583
|
console.warn(
|
|
1356
1584
|
"@vercel/flags-core: Failed to parse stream message, skipping"
|
|
1357
1585
|
);
|
|
@@ -1367,7 +1595,7 @@ async function connectStream(config, callbacks) {
|
|
|
1367
1595
|
resetPingTimeout();
|
|
1368
1596
|
}
|
|
1369
1597
|
if (message.type === "primed") {
|
|
1370
|
-
_optionalChain([onPrimed, 'optionalCall',
|
|
1598
|
+
_optionalChain([onPrimed, 'optionalCall', _64 => _64(message)]);
|
|
1371
1599
|
retryCount = 0;
|
|
1372
1600
|
if (!initialDataReceived) {
|
|
1373
1601
|
initialDataReceived = true;
|
|
@@ -1390,7 +1618,7 @@ async function connectStream(config, callbacks) {
|
|
|
1390
1618
|
clearTimeout(pingTimeoutId);
|
|
1391
1619
|
abortController.signal.removeEventListener("abort", onMainAbort);
|
|
1392
1620
|
if (!abortController.signal.aborted) {
|
|
1393
|
-
_optionalChain([onDisconnect, 'optionalCall',
|
|
1621
|
+
_optionalChain([onDisconnect, 'optionalCall', _65 => _65()]);
|
|
1394
1622
|
retryCount++;
|
|
1395
1623
|
const elapsed = Date.now() - lastAttemptTime;
|
|
1396
1624
|
const minGap = Math.max(0, BASE_RETRY_DELAY_MS - elapsed);
|
|
@@ -1411,7 +1639,7 @@ async function connectStream(config, callbacks) {
|
|
|
1411
1639
|
if (!connectionAbort.signal.aborted) {
|
|
1412
1640
|
console.error("@vercel/flags-core: Stream error", error);
|
|
1413
1641
|
}
|
|
1414
|
-
_optionalChain([onDisconnect, 'optionalCall',
|
|
1642
|
+
_optionalChain([onDisconnect, 'optionalCall', _66 => _66()]);
|
|
1415
1643
|
retryCount++;
|
|
1416
1644
|
const elapsed = Date.now() - lastAttemptTime;
|
|
1417
1645
|
const minGap = Math.max(0, BASE_RETRY_DELAY_MS - elapsed);
|
|
@@ -1490,7 +1718,7 @@ var StreamSource = class extends TypedEmitter {
|
|
|
1490
1718
|
* Stop the stream connection.
|
|
1491
1719
|
*/
|
|
1492
1720
|
stop() {
|
|
1493
|
-
_optionalChain([this, 'access',
|
|
1721
|
+
_optionalChain([this, 'access', _67 => _67.abortController, 'optionalAccess', _68 => _68.abort, 'call', _69 => _69()]);
|
|
1494
1722
|
this.abortController = void 0;
|
|
1495
1723
|
this.promise = void 0;
|
|
1496
1724
|
}
|
|
@@ -1522,34 +1750,34 @@ function parseConfigUpdatedAt(value) {
|
|
|
1522
1750
|
}
|
|
1523
1751
|
return void 0;
|
|
1524
1752
|
}
|
|
1525
|
-
var Controller = (
|
|
1753
|
+
var Controller = (_class5 = class {
|
|
1526
1754
|
|
|
1527
1755
|
// State machine
|
|
1528
|
-
|
|
1756
|
+
__init12() {this.state = "idle"}
|
|
1529
1757
|
// Data state — tagged with origin
|
|
1530
1758
|
|
|
1531
1759
|
// Memoized data spread for read() / getDatafile().
|
|
1532
1760
|
// Rebuilt only when `this.data` reference changes (e.g. on stream/poll update).
|
|
1533
1761
|
// Holds the result of stripping `_origin`; metrics are appended per-call.
|
|
1534
|
-
|
|
1535
|
-
|
|
1762
|
+
__init13() {this.dataViewSource = void 0}
|
|
1763
|
+
__init14() {this.dataViewBase = void 0}
|
|
1536
1764
|
// Sources (I/O delegates)
|
|
1537
1765
|
|
|
1538
1766
|
|
|
1539
1767
|
|
|
1540
1768
|
// Usage tracking
|
|
1541
1769
|
|
|
1542
|
-
|
|
1770
|
+
__init15() {this.isFirstGetData = true}
|
|
1543
1771
|
// Build-step deduplication
|
|
1544
|
-
|
|
1545
|
-
|
|
1772
|
+
__init16() {this.buildDataPromise = null}
|
|
1773
|
+
__init17() {this.buildReadTracked = false}
|
|
1546
1774
|
// Suppresses usage tracking when the SDK key is unauthorized
|
|
1547
|
-
|
|
1548
|
-
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);
|
|
1549
1777
|
this.options = normalizeOptions(options);
|
|
1550
1778
|
this.streamSource = new StreamSource(
|
|
1551
1779
|
this.options,
|
|
1552
|
-
() => _optionalChain([this, 'access',
|
|
1780
|
+
() => _optionalChain([this, 'access', _70 => _70.data, 'optionalAccess', _71 => _71.revision])
|
|
1553
1781
|
);
|
|
1554
1782
|
this.pollingSource = new PollingSource(this.options);
|
|
1555
1783
|
this.bundledSource = new BundledSource({
|
|
@@ -1563,32 +1791,32 @@ var Controller = (_class3 = class {
|
|
|
1563
1791
|
this.usageTracker = new UsageTracker(this.options);
|
|
1564
1792
|
}
|
|
1565
1793
|
// Source event handlers (stored for cleanup)
|
|
1566
|
-
|
|
1794
|
+
__init19() {this.onStreamData = (data) => {
|
|
1567
1795
|
if (this.isNewerData(data)) {
|
|
1568
1796
|
this.data = tagData(data, "stream");
|
|
1569
1797
|
}
|
|
1570
1798
|
}}
|
|
1571
|
-
|
|
1799
|
+
__init20() {this.onStreamPrimed = () => {
|
|
1572
1800
|
if (this.state === "degraded" || this.state === "initializing:stream") {
|
|
1573
1801
|
this.transition("streaming");
|
|
1574
1802
|
}
|
|
1575
1803
|
}}
|
|
1576
|
-
|
|
1804
|
+
__init21() {this.onStreamConnected = () => {
|
|
1577
1805
|
if (this.state === "degraded" || this.state === "initializing:stream") {
|
|
1578
1806
|
this.transition("streaming");
|
|
1579
1807
|
}
|
|
1580
1808
|
}}
|
|
1581
|
-
|
|
1809
|
+
__init22() {this.onStreamDisconnected = () => {
|
|
1582
1810
|
if (this.state === "streaming") {
|
|
1583
1811
|
this.transition("degraded");
|
|
1584
1812
|
}
|
|
1585
1813
|
}}
|
|
1586
|
-
|
|
1814
|
+
__init23() {this.onPollData = (data) => {
|
|
1587
1815
|
if (this.isNewerData(data)) {
|
|
1588
1816
|
this.data = tagData(data, "poll");
|
|
1589
1817
|
}
|
|
1590
1818
|
}}
|
|
1591
|
-
|
|
1819
|
+
__init24() {this.onPollError = (error) => {
|
|
1592
1820
|
console.error("@vercel/flags-core: Poll failed:", error);
|
|
1593
1821
|
}}
|
|
1594
1822
|
// ---------------------------------------------------------------------------
|
|
@@ -1657,7 +1885,7 @@ var Controller = (_class3 = class {
|
|
|
1657
1885
|
if (bundled) {
|
|
1658
1886
|
this.data = tagData(bundled, "bundled");
|
|
1659
1887
|
}
|
|
1660
|
-
} catch (
|
|
1888
|
+
} catch (e8) {
|
|
1661
1889
|
}
|
|
1662
1890
|
}
|
|
1663
1891
|
if (this.data) {
|
|
@@ -1726,7 +1954,7 @@ var Controller = (_class3 = class {
|
|
|
1726
1954
|
this.pollingSource.stop();
|
|
1727
1955
|
this.data = this.options.datafile ? tagData(this.options.datafile, "provided") : void 0;
|
|
1728
1956
|
this.transition("shutdown");
|
|
1729
|
-
await this.usageTracker.
|
|
1957
|
+
await this.usageTracker.shutdown();
|
|
1730
1958
|
}
|
|
1731
1959
|
/**
|
|
1732
1960
|
* Returns the datafile with metrics.
|
|
@@ -1759,7 +1987,7 @@ var Controller = (_class3 = class {
|
|
|
1759
1987
|
this.data = tagData(fetched, "fetched");
|
|
1760
1988
|
result = this.data;
|
|
1761
1989
|
cacheStatus = "MISS";
|
|
1762
|
-
} catch (
|
|
1990
|
+
} catch (e9) {
|
|
1763
1991
|
throw new Error(
|
|
1764
1992
|
"@vercel/flags-core: No flag definitions available. Initialize the client or provide a datafile."
|
|
1765
1993
|
);
|
|
@@ -1878,7 +2106,7 @@ var Controller = (_class3 = class {
|
|
|
1878
2106
|
return true;
|
|
1879
2107
|
}
|
|
1880
2108
|
return false;
|
|
1881
|
-
} catch (
|
|
2109
|
+
} catch (e10) {
|
|
1882
2110
|
return false;
|
|
1883
2111
|
}
|
|
1884
2112
|
}
|
|
@@ -1903,7 +2131,7 @@ var Controller = (_class3 = class {
|
|
|
1903
2131
|
return true;
|
|
1904
2132
|
}
|
|
1905
2133
|
return false;
|
|
1906
|
-
} catch (
|
|
2134
|
+
} catch (e11) {
|
|
1907
2135
|
clearTimeout(timeoutId);
|
|
1908
2136
|
return false;
|
|
1909
2137
|
}
|
|
@@ -1953,7 +2181,7 @@ var Controller = (_class3 = class {
|
|
|
1953
2181
|
fetch: this.options.fetch
|
|
1954
2182
|
});
|
|
1955
2183
|
return tagData(fetched, "fetched");
|
|
1956
|
-
} catch (
|
|
2184
|
+
} catch (e12) {
|
|
1957
2185
|
}
|
|
1958
2186
|
throw new Error(
|
|
1959
2187
|
"@vercel/flags-core: No flag definitions available during build. Provide a datafile or bundled definitions."
|
|
@@ -1987,7 +2215,7 @@ var Controller = (_class3 = class {
|
|
|
1987
2215
|
this.data = tagData(fetched, "fetched");
|
|
1988
2216
|
this.transition("degraded");
|
|
1989
2217
|
return;
|
|
1990
|
-
} catch (
|
|
2218
|
+
} catch (e13) {
|
|
1991
2219
|
}
|
|
1992
2220
|
}
|
|
1993
2221
|
throw new Error(
|
|
@@ -2039,7 +2267,7 @@ var Controller = (_class3 = class {
|
|
|
2039
2267
|
this.data = tagData(fetched, "fetched");
|
|
2040
2268
|
this.transition("degraded");
|
|
2041
2269
|
return [this.data, "MISS"];
|
|
2042
|
-
} catch (
|
|
2270
|
+
} catch (e14) {
|
|
2043
2271
|
}
|
|
2044
2272
|
}
|
|
2045
2273
|
throw new Error(
|
|
@@ -2091,11 +2319,11 @@ var Controller = (_class3 = class {
|
|
|
2091
2319
|
duration: Date.now() - startTime,
|
|
2092
2320
|
mode: mode === "streaming" ? "stream" : mode === "polling" ? "poll" : mode
|
|
2093
2321
|
};
|
|
2094
|
-
const configUpdatedAt = _optionalChain([this, 'access',
|
|
2322
|
+
const configUpdatedAt = _optionalChain([this, 'access', _72 => _72.data, 'optionalAccess', _73 => _73.configUpdatedAt]);
|
|
2095
2323
|
if (typeof configUpdatedAt === "number") {
|
|
2096
2324
|
trackOptions.configUpdatedAt = configUpdatedAt;
|
|
2097
2325
|
}
|
|
2098
|
-
const revision = _optionalChain([this, 'access',
|
|
2326
|
+
const revision = _optionalChain([this, 'access', _74 => _74.data, 'optionalAccess', _75 => _75.revision]);
|
|
2099
2327
|
if (typeof revision === "number") {
|
|
2100
2328
|
trackOptions.revision = revision;
|
|
2101
2329
|
}
|
|
@@ -2104,10 +2332,20 @@ var Controller = (_class3 = class {
|
|
|
2104
2332
|
}
|
|
2105
2333
|
this.usageTracker.trackRead(trackOptions);
|
|
2106
2334
|
}
|
|
2107
|
-
|
|
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);
|
|
2108
2346
|
|
|
2109
2347
|
// src/controller/auth.ts
|
|
2110
|
-
|
|
2348
|
+
|
|
2111
2349
|
|
|
2112
2350
|
// src/utils/sdk-keys.ts
|
|
2113
2351
|
var SDK_KEY_REGEX = /^vf_(?:server|client)_/;
|
|
@@ -2118,7 +2356,7 @@ function parseSdkKeyFromFlagsConnectionString(text) {
|
|
|
2118
2356
|
const params = new URLSearchParams(text.slice(6));
|
|
2119
2357
|
const sdkKey = params.get("sdkKey");
|
|
2120
2358
|
if (sdkKey && SDK_KEY_REGEX.test(sdkKey)) return sdkKey;
|
|
2121
|
-
} catch (
|
|
2359
|
+
} catch (e15) {
|
|
2122
2360
|
}
|
|
2123
2361
|
return null;
|
|
2124
2362
|
}
|
|
@@ -2127,7 +2365,7 @@ function parseSdkKeyFromFlagsConnectionString(text) {
|
|
|
2127
2365
|
async function getOidcToken() {
|
|
2128
2366
|
try {
|
|
2129
2367
|
return await _oidc.getVercelOidcToken.call(void 0, );
|
|
2130
|
-
} catch (
|
|
2368
|
+
} catch (e16) {
|
|
2131
2369
|
throw new Error(
|
|
2132
2370
|
[
|
|
2133
2371
|
"@vercel/flags-core: Failed to get OIDC token.",
|
|
@@ -2222,7 +2460,7 @@ function setCacheLife() {
|
|
|
2222
2460
|
try {
|
|
2223
2461
|
_cache.cacheLife.call(void 0, { revalidate: 0, expire: 0 });
|
|
2224
2462
|
_cache.cacheLife.call(void 0, { stale: 60 });
|
|
2225
|
-
} catch (
|
|
2463
|
+
} catch (e17) {
|
|
2226
2464
|
}
|
|
2227
2465
|
}
|
|
2228
2466
|
var cachedFns = {
|
|
@@ -2271,4 +2509,4 @@ var { flagsClient, resetDefaultFlagsClient, createClient } = make(
|
|
|
2271
2509
|
|
|
2272
2510
|
|
|
2273
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;
|
|
2274
|
-
//# sourceMappingURL=chunk-
|
|
2512
|
+
//# sourceMappingURL=chunk-LPIUDLYE.cjs.map
|