@scalemule/nextjs 0.1.18 → 0.1.20
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/README.md +3 -1
- package/dist/index.d.mts +31 -2
- package/dist/index.d.ts +31 -2
- package/dist/index.js +287 -3
- package/dist/index.mjs +286 -4
- package/dist/server/index.js +678 -637
- package/dist/server/index.mjs +679 -638
- package/dist/server/ledvery.js +5 -1
- package/dist/server/ledvery.mjs +5 -1
- package/package.json +2 -2
package/dist/server/index.js
CHANGED
|
@@ -12,7 +12,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
12
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
13
|
var __getProtoOf = Object.getPrototypeOf;
|
|
14
14
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
15
|
-
var
|
|
15
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
16
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
17
|
+
}) : x)(function(x) {
|
|
18
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
19
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
20
|
+
});
|
|
21
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
16
22
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
17
23
|
};
|
|
18
24
|
var __copyProps = (to, from, except, desc) => {
|
|
@@ -28,13 +34,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
34
|
// file that has been converted to a CommonJS file using a Babel-
|
|
29
35
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
30
36
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
31
|
-
__defProp(target, "default", { value: mod, enumerable: true }) ,
|
|
37
|
+
!mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
32
38
|
mod
|
|
33
39
|
));
|
|
34
40
|
|
|
35
|
-
// node_modules/semver/internal/constants.js
|
|
41
|
+
// ../sdk/node_modules/semver/internal/constants.js
|
|
36
42
|
var require_constants = __commonJS({
|
|
37
|
-
"node_modules/semver/internal/constants.js"(exports$1, module) {
|
|
43
|
+
"../sdk/node_modules/semver/internal/constants.js"(exports$1, module) {
|
|
38
44
|
var SEMVER_SPEC_VERSION = "2.0.0";
|
|
39
45
|
var MAX_LENGTH = 256;
|
|
40
46
|
var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || /* istanbul ignore next */
|
|
@@ -63,18 +69,18 @@ var require_constants = __commonJS({
|
|
|
63
69
|
}
|
|
64
70
|
});
|
|
65
71
|
|
|
66
|
-
// node_modules/semver/internal/debug.js
|
|
72
|
+
// ../sdk/node_modules/semver/internal/debug.js
|
|
67
73
|
var require_debug = __commonJS({
|
|
68
|
-
"node_modules/semver/internal/debug.js"(exports$1, module) {
|
|
74
|
+
"../sdk/node_modules/semver/internal/debug.js"(exports$1, module) {
|
|
69
75
|
var debug = typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? (...args) => console.error("SEMVER", ...args) : () => {
|
|
70
76
|
};
|
|
71
77
|
module.exports = debug;
|
|
72
78
|
}
|
|
73
79
|
});
|
|
74
80
|
|
|
75
|
-
// node_modules/semver/internal/re.js
|
|
81
|
+
// ../sdk/node_modules/semver/internal/re.js
|
|
76
82
|
var require_re = __commonJS({
|
|
77
|
-
"node_modules/semver/internal/re.js"(exports$1, module) {
|
|
83
|
+
"../sdk/node_modules/semver/internal/re.js"(exports$1, module) {
|
|
78
84
|
var {
|
|
79
85
|
MAX_SAFE_COMPONENT_LENGTH,
|
|
80
86
|
MAX_SAFE_BUILD_LENGTH,
|
|
@@ -159,9 +165,9 @@ var require_re = __commonJS({
|
|
|
159
165
|
}
|
|
160
166
|
});
|
|
161
167
|
|
|
162
|
-
// node_modules/semver/internal/parse-options.js
|
|
168
|
+
// ../sdk/node_modules/semver/internal/parse-options.js
|
|
163
169
|
var require_parse_options = __commonJS({
|
|
164
|
-
"node_modules/semver/internal/parse-options.js"(exports$1, module) {
|
|
170
|
+
"../sdk/node_modules/semver/internal/parse-options.js"(exports$1, module) {
|
|
165
171
|
var looseOption = Object.freeze({ loose: true });
|
|
166
172
|
var emptyOpts = Object.freeze({});
|
|
167
173
|
var parseOptions = (options) => {
|
|
@@ -177,9 +183,9 @@ var require_parse_options = __commonJS({
|
|
|
177
183
|
}
|
|
178
184
|
});
|
|
179
185
|
|
|
180
|
-
// node_modules/semver/internal/identifiers.js
|
|
186
|
+
// ../sdk/node_modules/semver/internal/identifiers.js
|
|
181
187
|
var require_identifiers = __commonJS({
|
|
182
|
-
"node_modules/semver/internal/identifiers.js"(exports$1, module) {
|
|
188
|
+
"../sdk/node_modules/semver/internal/identifiers.js"(exports$1, module) {
|
|
183
189
|
var numeric = /^[0-9]+$/;
|
|
184
190
|
var compareIdentifiers = (a, b) => {
|
|
185
191
|
if (typeof a === "number" && typeof b === "number") {
|
|
@@ -201,9 +207,9 @@ var require_identifiers = __commonJS({
|
|
|
201
207
|
}
|
|
202
208
|
});
|
|
203
209
|
|
|
204
|
-
// node_modules/semver/classes/semver.js
|
|
210
|
+
// ../sdk/node_modules/semver/classes/semver.js
|
|
205
211
|
var require_semver = __commonJS({
|
|
206
|
-
"node_modules/semver/classes/semver.js"(exports$1, module) {
|
|
212
|
+
"../sdk/node_modules/semver/classes/semver.js"(exports$1, module) {
|
|
207
213
|
var debug = require_debug();
|
|
208
214
|
var { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants();
|
|
209
215
|
var { safeRe: re, t } = require_re();
|
|
@@ -479,9 +485,9 @@ var require_semver = __commonJS({
|
|
|
479
485
|
}
|
|
480
486
|
});
|
|
481
487
|
|
|
482
|
-
// node_modules/semver/functions/parse.js
|
|
488
|
+
// ../sdk/node_modules/semver/functions/parse.js
|
|
483
489
|
var require_parse = __commonJS({
|
|
484
|
-
"node_modules/semver/functions/parse.js"(exports$1, module) {
|
|
490
|
+
"../sdk/node_modules/semver/functions/parse.js"(exports$1, module) {
|
|
485
491
|
var SemVer = require_semver();
|
|
486
492
|
var parse = (version, options, throwErrors = false) => {
|
|
487
493
|
if (version instanceof SemVer) {
|
|
@@ -500,9 +506,9 @@ var require_parse = __commonJS({
|
|
|
500
506
|
}
|
|
501
507
|
});
|
|
502
508
|
|
|
503
|
-
// node_modules/semver/functions/valid.js
|
|
509
|
+
// ../sdk/node_modules/semver/functions/valid.js
|
|
504
510
|
var require_valid = __commonJS({
|
|
505
|
-
"node_modules/semver/functions/valid.js"(exports$1, module) {
|
|
511
|
+
"../sdk/node_modules/semver/functions/valid.js"(exports$1, module) {
|
|
506
512
|
var parse = require_parse();
|
|
507
513
|
var valid = (version, options) => {
|
|
508
514
|
const v = parse(version, options);
|
|
@@ -512,9 +518,9 @@ var require_valid = __commonJS({
|
|
|
512
518
|
}
|
|
513
519
|
});
|
|
514
520
|
|
|
515
|
-
// node_modules/semver/functions/clean.js
|
|
521
|
+
// ../sdk/node_modules/semver/functions/clean.js
|
|
516
522
|
var require_clean = __commonJS({
|
|
517
|
-
"node_modules/semver/functions/clean.js"(exports$1, module) {
|
|
523
|
+
"../sdk/node_modules/semver/functions/clean.js"(exports$1, module) {
|
|
518
524
|
var parse = require_parse();
|
|
519
525
|
var clean = (version, options) => {
|
|
520
526
|
const s = parse(version.trim().replace(/^[=v]+/, ""), options);
|
|
@@ -524,9 +530,9 @@ var require_clean = __commonJS({
|
|
|
524
530
|
}
|
|
525
531
|
});
|
|
526
532
|
|
|
527
|
-
// node_modules/semver/functions/inc.js
|
|
533
|
+
// ../sdk/node_modules/semver/functions/inc.js
|
|
528
534
|
var require_inc = __commonJS({
|
|
529
|
-
"node_modules/semver/functions/inc.js"(exports$1, module) {
|
|
535
|
+
"../sdk/node_modules/semver/functions/inc.js"(exports$1, module) {
|
|
530
536
|
var SemVer = require_semver();
|
|
531
537
|
var inc = (version, release, options, identifier, identifierBase) => {
|
|
532
538
|
if (typeof options === "string") {
|
|
@@ -547,9 +553,9 @@ var require_inc = __commonJS({
|
|
|
547
553
|
}
|
|
548
554
|
});
|
|
549
555
|
|
|
550
|
-
// node_modules/semver/functions/diff.js
|
|
556
|
+
// ../sdk/node_modules/semver/functions/diff.js
|
|
551
557
|
var require_diff = __commonJS({
|
|
552
|
-
"node_modules/semver/functions/diff.js"(exports$1, module) {
|
|
558
|
+
"../sdk/node_modules/semver/functions/diff.js"(exports$1, module) {
|
|
553
559
|
var parse = require_parse();
|
|
554
560
|
var diff = (version1, version2) => {
|
|
555
561
|
const v1 = parse(version1, null, true);
|
|
@@ -590,36 +596,36 @@ var require_diff = __commonJS({
|
|
|
590
596
|
}
|
|
591
597
|
});
|
|
592
598
|
|
|
593
|
-
// node_modules/semver/functions/major.js
|
|
599
|
+
// ../sdk/node_modules/semver/functions/major.js
|
|
594
600
|
var require_major = __commonJS({
|
|
595
|
-
"node_modules/semver/functions/major.js"(exports$1, module) {
|
|
601
|
+
"../sdk/node_modules/semver/functions/major.js"(exports$1, module) {
|
|
596
602
|
var SemVer = require_semver();
|
|
597
603
|
var major = (a, loose) => new SemVer(a, loose).major;
|
|
598
604
|
module.exports = major;
|
|
599
605
|
}
|
|
600
606
|
});
|
|
601
607
|
|
|
602
|
-
// node_modules/semver/functions/minor.js
|
|
608
|
+
// ../sdk/node_modules/semver/functions/minor.js
|
|
603
609
|
var require_minor = __commonJS({
|
|
604
|
-
"node_modules/semver/functions/minor.js"(exports$1, module) {
|
|
610
|
+
"../sdk/node_modules/semver/functions/minor.js"(exports$1, module) {
|
|
605
611
|
var SemVer = require_semver();
|
|
606
612
|
var minor = (a, loose) => new SemVer(a, loose).minor;
|
|
607
613
|
module.exports = minor;
|
|
608
614
|
}
|
|
609
615
|
});
|
|
610
616
|
|
|
611
|
-
// node_modules/semver/functions/patch.js
|
|
617
|
+
// ../sdk/node_modules/semver/functions/patch.js
|
|
612
618
|
var require_patch = __commonJS({
|
|
613
|
-
"node_modules/semver/functions/patch.js"(exports$1, module) {
|
|
619
|
+
"../sdk/node_modules/semver/functions/patch.js"(exports$1, module) {
|
|
614
620
|
var SemVer = require_semver();
|
|
615
621
|
var patch = (a, loose) => new SemVer(a, loose).patch;
|
|
616
622
|
module.exports = patch;
|
|
617
623
|
}
|
|
618
624
|
});
|
|
619
625
|
|
|
620
|
-
// node_modules/semver/functions/prerelease.js
|
|
626
|
+
// ../sdk/node_modules/semver/functions/prerelease.js
|
|
621
627
|
var require_prerelease = __commonJS({
|
|
622
|
-
"node_modules/semver/functions/prerelease.js"(exports$1, module) {
|
|
628
|
+
"../sdk/node_modules/semver/functions/prerelease.js"(exports$1, module) {
|
|
623
629
|
var parse = require_parse();
|
|
624
630
|
var prerelease = (version, options) => {
|
|
625
631
|
const parsed = parse(version, options);
|
|
@@ -629,36 +635,36 @@ var require_prerelease = __commonJS({
|
|
|
629
635
|
}
|
|
630
636
|
});
|
|
631
637
|
|
|
632
|
-
// node_modules/semver/functions/compare.js
|
|
638
|
+
// ../sdk/node_modules/semver/functions/compare.js
|
|
633
639
|
var require_compare = __commonJS({
|
|
634
|
-
"node_modules/semver/functions/compare.js"(exports$1, module) {
|
|
640
|
+
"../sdk/node_modules/semver/functions/compare.js"(exports$1, module) {
|
|
635
641
|
var SemVer = require_semver();
|
|
636
642
|
var compare = (a, b, loose) => new SemVer(a, loose).compare(new SemVer(b, loose));
|
|
637
643
|
module.exports = compare;
|
|
638
644
|
}
|
|
639
645
|
});
|
|
640
646
|
|
|
641
|
-
// node_modules/semver/functions/rcompare.js
|
|
647
|
+
// ../sdk/node_modules/semver/functions/rcompare.js
|
|
642
648
|
var require_rcompare = __commonJS({
|
|
643
|
-
"node_modules/semver/functions/rcompare.js"(exports$1, module) {
|
|
649
|
+
"../sdk/node_modules/semver/functions/rcompare.js"(exports$1, module) {
|
|
644
650
|
var compare = require_compare();
|
|
645
651
|
var rcompare = (a, b, loose) => compare(b, a, loose);
|
|
646
652
|
module.exports = rcompare;
|
|
647
653
|
}
|
|
648
654
|
});
|
|
649
655
|
|
|
650
|
-
// node_modules/semver/functions/compare-loose.js
|
|
656
|
+
// ../sdk/node_modules/semver/functions/compare-loose.js
|
|
651
657
|
var require_compare_loose = __commonJS({
|
|
652
|
-
"node_modules/semver/functions/compare-loose.js"(exports$1, module) {
|
|
658
|
+
"../sdk/node_modules/semver/functions/compare-loose.js"(exports$1, module) {
|
|
653
659
|
var compare = require_compare();
|
|
654
660
|
var compareLoose = (a, b) => compare(a, b, true);
|
|
655
661
|
module.exports = compareLoose;
|
|
656
662
|
}
|
|
657
663
|
});
|
|
658
664
|
|
|
659
|
-
// node_modules/semver/functions/compare-build.js
|
|
665
|
+
// ../sdk/node_modules/semver/functions/compare-build.js
|
|
660
666
|
var require_compare_build = __commonJS({
|
|
661
|
-
"node_modules/semver/functions/compare-build.js"(exports$1, module) {
|
|
667
|
+
"../sdk/node_modules/semver/functions/compare-build.js"(exports$1, module) {
|
|
662
668
|
var SemVer = require_semver();
|
|
663
669
|
var compareBuild = (a, b, loose) => {
|
|
664
670
|
const versionA = new SemVer(a, loose);
|
|
@@ -669,81 +675,81 @@ var require_compare_build = __commonJS({
|
|
|
669
675
|
}
|
|
670
676
|
});
|
|
671
677
|
|
|
672
|
-
// node_modules/semver/functions/sort.js
|
|
678
|
+
// ../sdk/node_modules/semver/functions/sort.js
|
|
673
679
|
var require_sort = __commonJS({
|
|
674
|
-
"node_modules/semver/functions/sort.js"(exports$1, module) {
|
|
680
|
+
"../sdk/node_modules/semver/functions/sort.js"(exports$1, module) {
|
|
675
681
|
var compareBuild = require_compare_build();
|
|
676
682
|
var sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose));
|
|
677
683
|
module.exports = sort;
|
|
678
684
|
}
|
|
679
685
|
});
|
|
680
686
|
|
|
681
|
-
// node_modules/semver/functions/rsort.js
|
|
687
|
+
// ../sdk/node_modules/semver/functions/rsort.js
|
|
682
688
|
var require_rsort = __commonJS({
|
|
683
|
-
"node_modules/semver/functions/rsort.js"(exports$1, module) {
|
|
689
|
+
"../sdk/node_modules/semver/functions/rsort.js"(exports$1, module) {
|
|
684
690
|
var compareBuild = require_compare_build();
|
|
685
691
|
var rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose));
|
|
686
692
|
module.exports = rsort;
|
|
687
693
|
}
|
|
688
694
|
});
|
|
689
695
|
|
|
690
|
-
// node_modules/semver/functions/gt.js
|
|
696
|
+
// ../sdk/node_modules/semver/functions/gt.js
|
|
691
697
|
var require_gt = __commonJS({
|
|
692
|
-
"node_modules/semver/functions/gt.js"(exports$1, module) {
|
|
698
|
+
"../sdk/node_modules/semver/functions/gt.js"(exports$1, module) {
|
|
693
699
|
var compare = require_compare();
|
|
694
700
|
var gt = (a, b, loose) => compare(a, b, loose) > 0;
|
|
695
701
|
module.exports = gt;
|
|
696
702
|
}
|
|
697
703
|
});
|
|
698
704
|
|
|
699
|
-
// node_modules/semver/functions/lt.js
|
|
705
|
+
// ../sdk/node_modules/semver/functions/lt.js
|
|
700
706
|
var require_lt = __commonJS({
|
|
701
|
-
"node_modules/semver/functions/lt.js"(exports$1, module) {
|
|
707
|
+
"../sdk/node_modules/semver/functions/lt.js"(exports$1, module) {
|
|
702
708
|
var compare = require_compare();
|
|
703
709
|
var lt = (a, b, loose) => compare(a, b, loose) < 0;
|
|
704
710
|
module.exports = lt;
|
|
705
711
|
}
|
|
706
712
|
});
|
|
707
713
|
|
|
708
|
-
// node_modules/semver/functions/eq.js
|
|
714
|
+
// ../sdk/node_modules/semver/functions/eq.js
|
|
709
715
|
var require_eq = __commonJS({
|
|
710
|
-
"node_modules/semver/functions/eq.js"(exports$1, module) {
|
|
716
|
+
"../sdk/node_modules/semver/functions/eq.js"(exports$1, module) {
|
|
711
717
|
var compare = require_compare();
|
|
712
718
|
var eq = (a, b, loose) => compare(a, b, loose) === 0;
|
|
713
719
|
module.exports = eq;
|
|
714
720
|
}
|
|
715
721
|
});
|
|
716
722
|
|
|
717
|
-
// node_modules/semver/functions/neq.js
|
|
723
|
+
// ../sdk/node_modules/semver/functions/neq.js
|
|
718
724
|
var require_neq = __commonJS({
|
|
719
|
-
"node_modules/semver/functions/neq.js"(exports$1, module) {
|
|
725
|
+
"../sdk/node_modules/semver/functions/neq.js"(exports$1, module) {
|
|
720
726
|
var compare = require_compare();
|
|
721
727
|
var neq = (a, b, loose) => compare(a, b, loose) !== 0;
|
|
722
728
|
module.exports = neq;
|
|
723
729
|
}
|
|
724
730
|
});
|
|
725
731
|
|
|
726
|
-
// node_modules/semver/functions/gte.js
|
|
732
|
+
// ../sdk/node_modules/semver/functions/gte.js
|
|
727
733
|
var require_gte = __commonJS({
|
|
728
|
-
"node_modules/semver/functions/gte.js"(exports$1, module) {
|
|
734
|
+
"../sdk/node_modules/semver/functions/gte.js"(exports$1, module) {
|
|
729
735
|
var compare = require_compare();
|
|
730
736
|
var gte = (a, b, loose) => compare(a, b, loose) >= 0;
|
|
731
737
|
module.exports = gte;
|
|
732
738
|
}
|
|
733
739
|
});
|
|
734
740
|
|
|
735
|
-
// node_modules/semver/functions/lte.js
|
|
741
|
+
// ../sdk/node_modules/semver/functions/lte.js
|
|
736
742
|
var require_lte = __commonJS({
|
|
737
|
-
"node_modules/semver/functions/lte.js"(exports$1, module) {
|
|
743
|
+
"../sdk/node_modules/semver/functions/lte.js"(exports$1, module) {
|
|
738
744
|
var compare = require_compare();
|
|
739
745
|
var lte = (a, b, loose) => compare(a, b, loose) <= 0;
|
|
740
746
|
module.exports = lte;
|
|
741
747
|
}
|
|
742
748
|
});
|
|
743
749
|
|
|
744
|
-
// node_modules/semver/functions/cmp.js
|
|
750
|
+
// ../sdk/node_modules/semver/functions/cmp.js
|
|
745
751
|
var require_cmp = __commonJS({
|
|
746
|
-
"node_modules/semver/functions/cmp.js"(exports$1, module) {
|
|
752
|
+
"../sdk/node_modules/semver/functions/cmp.js"(exports$1, module) {
|
|
747
753
|
var eq = require_eq();
|
|
748
754
|
var neq = require_neq();
|
|
749
755
|
var gt = require_gt();
|
|
@@ -790,9 +796,9 @@ var require_cmp = __commonJS({
|
|
|
790
796
|
}
|
|
791
797
|
});
|
|
792
798
|
|
|
793
|
-
// node_modules/semver/functions/coerce.js
|
|
799
|
+
// ../sdk/node_modules/semver/functions/coerce.js
|
|
794
800
|
var require_coerce = __commonJS({
|
|
795
|
-
"node_modules/semver/functions/coerce.js"(exports$1, module) {
|
|
801
|
+
"../sdk/node_modules/semver/functions/coerce.js"(exports$1, module) {
|
|
796
802
|
var SemVer = require_semver();
|
|
797
803
|
var parse = require_parse();
|
|
798
804
|
var { safeRe: re, t } = require_re();
|
|
@@ -835,9 +841,9 @@ var require_coerce = __commonJS({
|
|
|
835
841
|
}
|
|
836
842
|
});
|
|
837
843
|
|
|
838
|
-
// node_modules/semver/internal/lrucache.js
|
|
844
|
+
// ../sdk/node_modules/semver/internal/lrucache.js
|
|
839
845
|
var require_lrucache = __commonJS({
|
|
840
|
-
"node_modules/semver/internal/lrucache.js"(exports$1, module) {
|
|
846
|
+
"../sdk/node_modules/semver/internal/lrucache.js"(exports$1, module) {
|
|
841
847
|
var LRUCache = class {
|
|
842
848
|
constructor() {
|
|
843
849
|
this.max = 1e3;
|
|
@@ -872,9 +878,9 @@ var require_lrucache = __commonJS({
|
|
|
872
878
|
}
|
|
873
879
|
});
|
|
874
880
|
|
|
875
|
-
// node_modules/semver/classes/range.js
|
|
881
|
+
// ../sdk/node_modules/semver/classes/range.js
|
|
876
882
|
var require_range = __commonJS({
|
|
877
|
-
"node_modules/semver/classes/range.js"(exports$1, module) {
|
|
883
|
+
"../sdk/node_modules/semver/classes/range.js"(exports$1, module) {
|
|
878
884
|
var SPACE_CHARACTERS = /\s+/g;
|
|
879
885
|
var Range = class _Range {
|
|
880
886
|
constructor(range, options) {
|
|
@@ -976,9 +982,9 @@ var require_range = __commonJS({
|
|
|
976
982
|
if (rangeMap.size > 1 && rangeMap.has("")) {
|
|
977
983
|
rangeMap.delete("");
|
|
978
984
|
}
|
|
979
|
-
const
|
|
980
|
-
cache.set(memoKey,
|
|
981
|
-
return
|
|
985
|
+
const result = [...rangeMap.values()];
|
|
986
|
+
cache.set(memoKey, result);
|
|
987
|
+
return result;
|
|
982
988
|
}
|
|
983
989
|
intersects(range, options) {
|
|
984
990
|
if (!(range instanceof _Range)) {
|
|
@@ -1032,16 +1038,16 @@ var require_range = __commonJS({
|
|
|
1032
1038
|
var isNullSet = (c) => c.value === "<0.0.0-0";
|
|
1033
1039
|
var isAny = (c) => c.value === "";
|
|
1034
1040
|
var isSatisfiable = (comparators, options) => {
|
|
1035
|
-
let
|
|
1041
|
+
let result = true;
|
|
1036
1042
|
const remainingComparators = comparators.slice();
|
|
1037
1043
|
let testComparator = remainingComparators.pop();
|
|
1038
|
-
while (
|
|
1039
|
-
|
|
1044
|
+
while (result && remainingComparators.length) {
|
|
1045
|
+
result = remainingComparators.every((otherComparator) => {
|
|
1040
1046
|
return testComparator.intersects(otherComparator, options);
|
|
1041
1047
|
});
|
|
1042
1048
|
testComparator = remainingComparators.pop();
|
|
1043
1049
|
}
|
|
1044
|
-
return
|
|
1050
|
+
return result;
|
|
1045
1051
|
};
|
|
1046
1052
|
var parseComparator = (comp, options) => {
|
|
1047
1053
|
comp = comp.replace(re[t.BUILD], "");
|
|
@@ -1248,9 +1254,9 @@ var require_range = __commonJS({
|
|
|
1248
1254
|
}
|
|
1249
1255
|
});
|
|
1250
1256
|
|
|
1251
|
-
// node_modules/semver/classes/comparator.js
|
|
1257
|
+
// ../sdk/node_modules/semver/classes/comparator.js
|
|
1252
1258
|
var require_comparator = __commonJS({
|
|
1253
|
-
"node_modules/semver/classes/comparator.js"(exports$1, module) {
|
|
1259
|
+
"../sdk/node_modules/semver/classes/comparator.js"(exports$1, module) {
|
|
1254
1260
|
var ANY = /* @__PURE__ */ Symbol("SemVer ANY");
|
|
1255
1261
|
var Comparator = class _Comparator {
|
|
1256
1262
|
static get ANY() {
|
|
@@ -1360,9 +1366,9 @@ var require_comparator = __commonJS({
|
|
|
1360
1366
|
}
|
|
1361
1367
|
});
|
|
1362
1368
|
|
|
1363
|
-
// node_modules/semver/functions/satisfies.js
|
|
1369
|
+
// ../sdk/node_modules/semver/functions/satisfies.js
|
|
1364
1370
|
var require_satisfies = __commonJS({
|
|
1365
|
-
"node_modules/semver/functions/satisfies.js"(exports$1, module) {
|
|
1371
|
+
"../sdk/node_modules/semver/functions/satisfies.js"(exports$1, module) {
|
|
1366
1372
|
var Range = require_range();
|
|
1367
1373
|
var satisfies = (version, range, options) => {
|
|
1368
1374
|
try {
|
|
@@ -1376,18 +1382,18 @@ var require_satisfies = __commonJS({
|
|
|
1376
1382
|
}
|
|
1377
1383
|
});
|
|
1378
1384
|
|
|
1379
|
-
// node_modules/semver/ranges/to-comparators.js
|
|
1385
|
+
// ../sdk/node_modules/semver/ranges/to-comparators.js
|
|
1380
1386
|
var require_to_comparators = __commonJS({
|
|
1381
|
-
"node_modules/semver/ranges/to-comparators.js"(exports$1, module) {
|
|
1387
|
+
"../sdk/node_modules/semver/ranges/to-comparators.js"(exports$1, module) {
|
|
1382
1388
|
var Range = require_range();
|
|
1383
1389
|
var toComparators = (range, options) => new Range(range, options).set.map((comp) => comp.map((c) => c.value).join(" ").trim().split(" "));
|
|
1384
1390
|
module.exports = toComparators;
|
|
1385
1391
|
}
|
|
1386
1392
|
});
|
|
1387
1393
|
|
|
1388
|
-
// node_modules/semver/ranges/max-satisfying.js
|
|
1394
|
+
// ../sdk/node_modules/semver/ranges/max-satisfying.js
|
|
1389
1395
|
var require_max_satisfying = __commonJS({
|
|
1390
|
-
"node_modules/semver/ranges/max-satisfying.js"(exports$1, module) {
|
|
1396
|
+
"../sdk/node_modules/semver/ranges/max-satisfying.js"(exports$1, module) {
|
|
1391
1397
|
var SemVer = require_semver();
|
|
1392
1398
|
var Range = require_range();
|
|
1393
1399
|
var maxSatisfying = (versions, range, options) => {
|
|
@@ -1413,9 +1419,9 @@ var require_max_satisfying = __commonJS({
|
|
|
1413
1419
|
}
|
|
1414
1420
|
});
|
|
1415
1421
|
|
|
1416
|
-
// node_modules/semver/ranges/min-satisfying.js
|
|
1422
|
+
// ../sdk/node_modules/semver/ranges/min-satisfying.js
|
|
1417
1423
|
var require_min_satisfying = __commonJS({
|
|
1418
|
-
"node_modules/semver/ranges/min-satisfying.js"(exports$1, module) {
|
|
1424
|
+
"../sdk/node_modules/semver/ranges/min-satisfying.js"(exports$1, module) {
|
|
1419
1425
|
var SemVer = require_semver();
|
|
1420
1426
|
var Range = require_range();
|
|
1421
1427
|
var minSatisfying = (versions, range, options) => {
|
|
@@ -1441,9 +1447,9 @@ var require_min_satisfying = __commonJS({
|
|
|
1441
1447
|
}
|
|
1442
1448
|
});
|
|
1443
1449
|
|
|
1444
|
-
// node_modules/semver/ranges/min-version.js
|
|
1450
|
+
// ../sdk/node_modules/semver/ranges/min-version.js
|
|
1445
1451
|
var require_min_version = __commonJS({
|
|
1446
|
-
"node_modules/semver/ranges/min-version.js"(exports$1, module) {
|
|
1452
|
+
"../sdk/node_modules/semver/ranges/min-version.js"(exports$1, module) {
|
|
1447
1453
|
var SemVer = require_semver();
|
|
1448
1454
|
var Range = require_range();
|
|
1449
1455
|
var gt = require_gt();
|
|
@@ -1499,9 +1505,9 @@ var require_min_version = __commonJS({
|
|
|
1499
1505
|
}
|
|
1500
1506
|
});
|
|
1501
1507
|
|
|
1502
|
-
// node_modules/semver/ranges/valid.js
|
|
1508
|
+
// ../sdk/node_modules/semver/ranges/valid.js
|
|
1503
1509
|
var require_valid2 = __commonJS({
|
|
1504
|
-
"node_modules/semver/ranges/valid.js"(exports$1, module) {
|
|
1510
|
+
"../sdk/node_modules/semver/ranges/valid.js"(exports$1, module) {
|
|
1505
1511
|
var Range = require_range();
|
|
1506
1512
|
var validRange = (range, options) => {
|
|
1507
1513
|
try {
|
|
@@ -1514,9 +1520,9 @@ var require_valid2 = __commonJS({
|
|
|
1514
1520
|
}
|
|
1515
1521
|
});
|
|
1516
1522
|
|
|
1517
|
-
// node_modules/semver/ranges/outside.js
|
|
1523
|
+
// ../sdk/node_modules/semver/ranges/outside.js
|
|
1518
1524
|
var require_outside = __commonJS({
|
|
1519
|
-
"node_modules/semver/ranges/outside.js"(exports$1, module) {
|
|
1525
|
+
"../sdk/node_modules/semver/ranges/outside.js"(exports$1, module) {
|
|
1520
1526
|
var SemVer = require_semver();
|
|
1521
1527
|
var Comparator = require_comparator();
|
|
1522
1528
|
var { ANY } = Comparator;
|
|
@@ -1582,27 +1588,27 @@ var require_outside = __commonJS({
|
|
|
1582
1588
|
}
|
|
1583
1589
|
});
|
|
1584
1590
|
|
|
1585
|
-
// node_modules/semver/ranges/gtr.js
|
|
1591
|
+
// ../sdk/node_modules/semver/ranges/gtr.js
|
|
1586
1592
|
var require_gtr = __commonJS({
|
|
1587
|
-
"node_modules/semver/ranges/gtr.js"(exports$1, module) {
|
|
1593
|
+
"../sdk/node_modules/semver/ranges/gtr.js"(exports$1, module) {
|
|
1588
1594
|
var outside = require_outside();
|
|
1589
1595
|
var gtr = (version, range, options) => outside(version, range, ">", options);
|
|
1590
1596
|
module.exports = gtr;
|
|
1591
1597
|
}
|
|
1592
1598
|
});
|
|
1593
1599
|
|
|
1594
|
-
// node_modules/semver/ranges/ltr.js
|
|
1600
|
+
// ../sdk/node_modules/semver/ranges/ltr.js
|
|
1595
1601
|
var require_ltr = __commonJS({
|
|
1596
|
-
"node_modules/semver/ranges/ltr.js"(exports$1, module) {
|
|
1602
|
+
"../sdk/node_modules/semver/ranges/ltr.js"(exports$1, module) {
|
|
1597
1603
|
var outside = require_outside();
|
|
1598
1604
|
var ltr = (version, range, options) => outside(version, range, "<", options);
|
|
1599
1605
|
module.exports = ltr;
|
|
1600
1606
|
}
|
|
1601
1607
|
});
|
|
1602
1608
|
|
|
1603
|
-
// node_modules/semver/ranges/intersects.js
|
|
1609
|
+
// ../sdk/node_modules/semver/ranges/intersects.js
|
|
1604
1610
|
var require_intersects = __commonJS({
|
|
1605
|
-
"node_modules/semver/ranges/intersects.js"(exports$1, module) {
|
|
1611
|
+
"../sdk/node_modules/semver/ranges/intersects.js"(exports$1, module) {
|
|
1606
1612
|
var Range = require_range();
|
|
1607
1613
|
var intersects = (r1, r2, options) => {
|
|
1608
1614
|
r1 = new Range(r1, options);
|
|
@@ -1613,9 +1619,9 @@ var require_intersects = __commonJS({
|
|
|
1613
1619
|
}
|
|
1614
1620
|
});
|
|
1615
1621
|
|
|
1616
|
-
// node_modules/semver/ranges/simplify.js
|
|
1622
|
+
// ../sdk/node_modules/semver/ranges/simplify.js
|
|
1617
1623
|
var require_simplify = __commonJS({
|
|
1618
|
-
"node_modules/semver/ranges/simplify.js"(exports$1, module) {
|
|
1624
|
+
"../sdk/node_modules/semver/ranges/simplify.js"(exports$1, module) {
|
|
1619
1625
|
var satisfies = require_satisfies();
|
|
1620
1626
|
var compare = require_compare();
|
|
1621
1627
|
module.exports = (versions, range, options) => {
|
|
@@ -1662,9 +1668,9 @@ var require_simplify = __commonJS({
|
|
|
1662
1668
|
}
|
|
1663
1669
|
});
|
|
1664
1670
|
|
|
1665
|
-
// node_modules/semver/ranges/subset.js
|
|
1671
|
+
// ../sdk/node_modules/semver/ranges/subset.js
|
|
1666
1672
|
var require_subset = __commonJS({
|
|
1667
|
-
"node_modules/semver/ranges/subset.js"(exports$1, module) {
|
|
1673
|
+
"../sdk/node_modules/semver/ranges/subset.js"(exports$1, module) {
|
|
1668
1674
|
var Range = require_range();
|
|
1669
1675
|
var Comparator = require_comparator();
|
|
1670
1676
|
var { ANY } = Comparator;
|
|
@@ -1823,9 +1829,9 @@ var require_subset = __commonJS({
|
|
|
1823
1829
|
}
|
|
1824
1830
|
});
|
|
1825
1831
|
|
|
1826
|
-
// node_modules/semver/index.js
|
|
1832
|
+
// ../sdk/node_modules/semver/index.js
|
|
1827
1833
|
var require_semver2 = __commonJS({
|
|
1828
|
-
"node_modules/semver/index.js"(exports$1, module) {
|
|
1834
|
+
"../sdk/node_modules/semver/index.js"(exports$1, module) {
|
|
1829
1835
|
var internalRe = require_re();
|
|
1830
1836
|
var constants = require_constants();
|
|
1831
1837
|
var SemVer = require_semver();
|
|
@@ -1917,6 +1923,546 @@ var require_semver2 = __commonJS({
|
|
|
1917
1923
|
}
|
|
1918
1924
|
});
|
|
1919
1925
|
|
|
1926
|
+
// ../sdk/dist/flags/server.js
|
|
1927
|
+
var require_server = __commonJS({
|
|
1928
|
+
"../sdk/dist/flags/server.js"(exports$1, module) {
|
|
1929
|
+
var __defProp2 = Object.defineProperty;
|
|
1930
|
+
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
1931
|
+
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
1932
|
+
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
1933
|
+
var __export = (target, all) => {
|
|
1934
|
+
for (var name in all)
|
|
1935
|
+
__defProp2(target, name, { get: all[name], enumerable: true });
|
|
1936
|
+
};
|
|
1937
|
+
var __copyProps2 = (to, from, except, desc) => {
|
|
1938
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
1939
|
+
for (let key of __getOwnPropNames2(from))
|
|
1940
|
+
if (!__hasOwnProp2.call(to, key) && key !== except)
|
|
1941
|
+
__defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
|
|
1942
|
+
}
|
|
1943
|
+
return to;
|
|
1944
|
+
};
|
|
1945
|
+
var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
1946
|
+
var server_exports = {};
|
|
1947
|
+
__export(server_exports, {
|
|
1948
|
+
FlagClient: () => FlagClient2,
|
|
1949
|
+
allConditionsMatch: () => allConditionsMatch,
|
|
1950
|
+
evaluateFlag: () => evaluateFlag,
|
|
1951
|
+
hashToBucket: () => hashToBucket
|
|
1952
|
+
});
|
|
1953
|
+
module.exports = __toCommonJS(server_exports);
|
|
1954
|
+
var import_node_crypto = __require("crypto");
|
|
1955
|
+
function hashToBucket(flagKey, identifier, salt) {
|
|
1956
|
+
const hash = (0, import_node_crypto.createHash)("sha256").update(`${salt}.${flagKey}.${identifier}`).digest();
|
|
1957
|
+
return hash.readUInt32BE(0) % 1e4;
|
|
1958
|
+
}
|
|
1959
|
+
var import_semver = require_semver2();
|
|
1960
|
+
function allConditionsMatch(conditions, context) {
|
|
1961
|
+
return conditions.every((c) => conditionMatches(c, context));
|
|
1962
|
+
}
|
|
1963
|
+
function conditionMatches(condition, context) {
|
|
1964
|
+
const attributeValue = getAttribute(context, condition.attribute);
|
|
1965
|
+
const op = condition.operator;
|
|
1966
|
+
if (op === "exists") return attributeValue !== void 0 && attributeValue !== null;
|
|
1967
|
+
if (op === "not_exists") return attributeValue === void 0 || attributeValue === null;
|
|
1968
|
+
if (attributeValue === void 0 || attributeValue === null) return false;
|
|
1969
|
+
switch (op) {
|
|
1970
|
+
case "eq":
|
|
1971
|
+
return compareValues(attributeValue, condition.value) === 0;
|
|
1972
|
+
case "neq":
|
|
1973
|
+
return compareValues(attributeValue, condition.value) !== 0;
|
|
1974
|
+
case "in":
|
|
1975
|
+
return candidateValues(condition).some((v) => compareValues(attributeValue, v) === 0);
|
|
1976
|
+
case "not_in":
|
|
1977
|
+
return !candidateValues(condition).some((v) => compareValues(attributeValue, v) === 0);
|
|
1978
|
+
case "contains":
|
|
1979
|
+
return containsValue(attributeValue, condition.value);
|
|
1980
|
+
case "starts_with":
|
|
1981
|
+
return typeof attributeValue === "string" && typeof condition.value === "string" ? attributeValue.startsWith(condition.value) : false;
|
|
1982
|
+
case "ends_with":
|
|
1983
|
+
return typeof attributeValue === "string" && typeof condition.value === "string" ? attributeValue.endsWith(condition.value) : false;
|
|
1984
|
+
case "gt":
|
|
1985
|
+
return compareValues(attributeValue, condition.value) === 1;
|
|
1986
|
+
case "gte": {
|
|
1987
|
+
const cmp = compareValues(attributeValue, condition.value);
|
|
1988
|
+
return cmp === 1 || cmp === 0;
|
|
1989
|
+
}
|
|
1990
|
+
case "lt":
|
|
1991
|
+
return compareValues(attributeValue, condition.value) === -1;
|
|
1992
|
+
case "lte": {
|
|
1993
|
+
const cmp = compareValues(attributeValue, condition.value);
|
|
1994
|
+
return cmp === -1 || cmp === 0;
|
|
1995
|
+
}
|
|
1996
|
+
case "regex": {
|
|
1997
|
+
if (typeof attributeValue !== "string" || typeof condition.value !== "string") return false;
|
|
1998
|
+
try {
|
|
1999
|
+
return new RegExp(condition.value).test(attributeValue);
|
|
2000
|
+
} catch {
|
|
2001
|
+
return false;
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
case "semver_eq":
|
|
2005
|
+
return semverCmp(attributeValue, condition.value) === 0;
|
|
2006
|
+
case "semver_neq":
|
|
2007
|
+
return semverCmp(attributeValue, condition.value) !== 0;
|
|
2008
|
+
case "semver_gt":
|
|
2009
|
+
return semverCmp(attributeValue, condition.value) === 1;
|
|
2010
|
+
case "semver_gte": {
|
|
2011
|
+
const cmp = semverCmp(attributeValue, condition.value);
|
|
2012
|
+
return cmp === 1 || cmp === 0;
|
|
2013
|
+
}
|
|
2014
|
+
case "semver_lt":
|
|
2015
|
+
return semverCmp(attributeValue, condition.value) === -1;
|
|
2016
|
+
case "semver_lte": {
|
|
2017
|
+
const cmp = semverCmp(attributeValue, condition.value);
|
|
2018
|
+
return cmp === -1 || cmp === 0;
|
|
2019
|
+
}
|
|
2020
|
+
default:
|
|
2021
|
+
return false;
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
function getAttribute(context, key) {
|
|
2025
|
+
switch (key) {
|
|
2026
|
+
case "user_id":
|
|
2027
|
+
return context.user_id;
|
|
2028
|
+
case "email":
|
|
2029
|
+
return context.email;
|
|
2030
|
+
case "session_id":
|
|
2031
|
+
return context.session_id;
|
|
2032
|
+
case "ip_address":
|
|
2033
|
+
return context.ip_address;
|
|
2034
|
+
case "user_agent":
|
|
2035
|
+
return context.user_agent;
|
|
2036
|
+
case "timestamp":
|
|
2037
|
+
return context.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
2038
|
+
default:
|
|
2039
|
+
return context[key];
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
function candidateValues(condition) {
|
|
2043
|
+
if (condition.values && condition.values.length > 0) return condition.values;
|
|
2044
|
+
if (condition.value === void 0 || condition.value === null) return [];
|
|
2045
|
+
if (Array.isArray(condition.value)) return condition.value;
|
|
2046
|
+
return [condition.value];
|
|
2047
|
+
}
|
|
2048
|
+
function compareValues(actual, expected) {
|
|
2049
|
+
if (expected === void 0 || expected === null) return null;
|
|
2050
|
+
const numA = toNumber(actual);
|
|
2051
|
+
const numB = toNumber(expected);
|
|
2052
|
+
if (numA !== null && numB !== null) {
|
|
2053
|
+
if (numA < numB) return -1;
|
|
2054
|
+
if (numA > numB) return 1;
|
|
2055
|
+
return 0;
|
|
2056
|
+
}
|
|
2057
|
+
if (typeof actual === "boolean" && typeof expected === "boolean") {
|
|
2058
|
+
if (actual === expected) return 0;
|
|
2059
|
+
return actual ? 1 : -1;
|
|
2060
|
+
}
|
|
2061
|
+
const strA = toString(actual);
|
|
2062
|
+
const strB = toString(expected);
|
|
2063
|
+
if (strA !== null && strB !== null) {
|
|
2064
|
+
if (strA < strB) return -1;
|
|
2065
|
+
if (strA > strB) return 1;
|
|
2066
|
+
return 0;
|
|
2067
|
+
}
|
|
2068
|
+
return null;
|
|
2069
|
+
}
|
|
2070
|
+
function containsValue(actual, expected) {
|
|
2071
|
+
if (expected === void 0 || expected === null) return false;
|
|
2072
|
+
if (Array.isArray(actual)) {
|
|
2073
|
+
return actual.some((item) => compareValues(item, expected) === 0);
|
|
2074
|
+
}
|
|
2075
|
+
if (typeof actual === "string" && typeof expected === "string") {
|
|
2076
|
+
return actual.includes(expected);
|
|
2077
|
+
}
|
|
2078
|
+
return false;
|
|
2079
|
+
}
|
|
2080
|
+
function toNumber(value) {
|
|
2081
|
+
if (typeof value === "number") return value;
|
|
2082
|
+
if (typeof value === "string") {
|
|
2083
|
+
const n = Number(value);
|
|
2084
|
+
return isNaN(n) ? null : n;
|
|
2085
|
+
}
|
|
2086
|
+
return null;
|
|
2087
|
+
}
|
|
2088
|
+
function toString(value) {
|
|
2089
|
+
if (typeof value === "string") return value;
|
|
2090
|
+
return null;
|
|
2091
|
+
}
|
|
2092
|
+
function semverCmp(actual, expected) {
|
|
2093
|
+
if (typeof actual !== "string" || typeof expected !== "string") return null;
|
|
2094
|
+
try {
|
|
2095
|
+
const a = (0, import_semver.parse)(actual);
|
|
2096
|
+
const b = (0, import_semver.parse)(expected);
|
|
2097
|
+
if (!a || !b) return null;
|
|
2098
|
+
return (0, import_semver.compare)(a, b);
|
|
2099
|
+
} catch {
|
|
2100
|
+
return null;
|
|
2101
|
+
}
|
|
2102
|
+
}
|
|
2103
|
+
function evaluateFlag(flag, config, context, segmentIndex) {
|
|
2104
|
+
const effectiveDefault = flag.environment_default_value ?? flag.default_value;
|
|
2105
|
+
if (flag.status !== "active") {
|
|
2106
|
+
return result(flag, config.environment, effectiveDefault, "disabled");
|
|
2107
|
+
}
|
|
2108
|
+
if (!flag.environment_enabled) {
|
|
2109
|
+
return result(flag, config.environment, effectiveDefault, "disabled");
|
|
2110
|
+
}
|
|
2111
|
+
const bucketIdentifier = getBucketIdentifier(context);
|
|
2112
|
+
for (const rule of flag.rules) {
|
|
2113
|
+
if (!rule.enabled) continue;
|
|
2114
|
+
if (rule.segment_ids.length > 0) {
|
|
2115
|
+
const segmentMatched = rule.segment_ids.some((segId) => {
|
|
2116
|
+
const segment = segmentIndex ? segmentIndex.get(segId) : config.segments.find((s) => s.id === segId);
|
|
2117
|
+
if (!segment) return false;
|
|
2118
|
+
return userMatchesSegment(segment, context);
|
|
2119
|
+
});
|
|
2120
|
+
if (!segmentMatched) continue;
|
|
2121
|
+
}
|
|
2122
|
+
if (!allConditionsMatch(rule.conditions, context)) continue;
|
|
2123
|
+
if (rule.rollout_percentage !== null && rule.rollout_percentage !== void 0) {
|
|
2124
|
+
const bucket = hashToBucket(flag.flag_key, bucketIdentifier, config.rollout_salt);
|
|
2125
|
+
if (bucket >= rule.rollout_percentage) continue;
|
|
2126
|
+
return {
|
|
2127
|
+
flag_id: flag.flag_id,
|
|
2128
|
+
flag_key: flag.flag_key,
|
|
2129
|
+
environment: config.environment,
|
|
2130
|
+
value: rule.serve_value,
|
|
2131
|
+
reason: "rule_match",
|
|
2132
|
+
matched_rule_id: rule.id,
|
|
2133
|
+
variant_key: null,
|
|
2134
|
+
bucket
|
|
2135
|
+
};
|
|
2136
|
+
}
|
|
2137
|
+
return {
|
|
2138
|
+
flag_id: flag.flag_id,
|
|
2139
|
+
flag_key: flag.flag_key,
|
|
2140
|
+
environment: config.environment,
|
|
2141
|
+
value: rule.serve_value,
|
|
2142
|
+
reason: "rule_match",
|
|
2143
|
+
matched_rule_id: rule.id,
|
|
2144
|
+
variant_key: null,
|
|
2145
|
+
bucket: null
|
|
2146
|
+
};
|
|
2147
|
+
}
|
|
2148
|
+
if (flag.variants.length > 0) {
|
|
2149
|
+
const totalWeight = flag.variants.reduce((sum, v) => sum + v.weight, 0);
|
|
2150
|
+
if (totalWeight > 0) {
|
|
2151
|
+
const bucket = hashToBucket(flag.flag_key, bucketIdentifier, config.rollout_salt);
|
|
2152
|
+
const scaled = Math.floor(bucket * totalWeight / 1e4);
|
|
2153
|
+
let cursor = 0;
|
|
2154
|
+
for (const variant of flag.variants) {
|
|
2155
|
+
cursor += variant.weight;
|
|
2156
|
+
if (scaled < cursor) {
|
|
2157
|
+
return {
|
|
2158
|
+
flag_id: flag.flag_id,
|
|
2159
|
+
flag_key: flag.flag_key,
|
|
2160
|
+
environment: config.environment,
|
|
2161
|
+
value: variant.value,
|
|
2162
|
+
reason: "variant",
|
|
2163
|
+
matched_rule_id: null,
|
|
2164
|
+
variant_key: variant.variant_key,
|
|
2165
|
+
bucket
|
|
2166
|
+
};
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
return result(flag, config.environment, effectiveDefault, "default");
|
|
2172
|
+
}
|
|
2173
|
+
function getBucketIdentifier(context) {
|
|
2174
|
+
return context.user_id ?? context.session_id ?? context.email ?? context.ip_address ?? "anonymous";
|
|
2175
|
+
}
|
|
2176
|
+
function userMatchesSegment(segment, context) {
|
|
2177
|
+
const identifiers = [context.user_id, context.email, context.session_id].filter(
|
|
2178
|
+
(v) => v !== void 0 && v !== null
|
|
2179
|
+
);
|
|
2180
|
+
if (identifiers.some((id) => segment.excluded_users.includes(id))) {
|
|
2181
|
+
return false;
|
|
2182
|
+
}
|
|
2183
|
+
if (identifiers.some((id) => segment.included_users.includes(id))) {
|
|
2184
|
+
return true;
|
|
2185
|
+
}
|
|
2186
|
+
return allConditionsMatch(segment.conditions, context);
|
|
2187
|
+
}
|
|
2188
|
+
function result(flag, environment, value, reason) {
|
|
2189
|
+
return {
|
|
2190
|
+
flag_id: flag.flag_id,
|
|
2191
|
+
flag_key: flag.flag_key,
|
|
2192
|
+
environment,
|
|
2193
|
+
value,
|
|
2194
|
+
reason,
|
|
2195
|
+
matched_rule_id: null,
|
|
2196
|
+
variant_key: null,
|
|
2197
|
+
bucket: null
|
|
2198
|
+
};
|
|
2199
|
+
}
|
|
2200
|
+
var FlagClient2 = class {
|
|
2201
|
+
constructor(options) {
|
|
2202
|
+
this.config = null;
|
|
2203
|
+
this.flagIndex = /* @__PURE__ */ new Map();
|
|
2204
|
+
this.segmentIndex = /* @__PURE__ */ new Map();
|
|
2205
|
+
this.lastETag = "";
|
|
2206
|
+
this.streamState = "idle";
|
|
2207
|
+
this.pollTimer = null;
|
|
2208
|
+
this.reconnectTimer = null;
|
|
2209
|
+
this.telemetryTimer = null;
|
|
2210
|
+
this.abortController = null;
|
|
2211
|
+
this.initPromise = null;
|
|
2212
|
+
this.telemetryCounters = /* @__PURE__ */ new Map();
|
|
2213
|
+
this.isShuttingDown = false;
|
|
2214
|
+
this.streamConnectInFlight = false;
|
|
2215
|
+
this.apiKey = options.apiKey;
|
|
2216
|
+
this.environment = options.environment;
|
|
2217
|
+
this.gatewayUrl = options.gatewayUrl;
|
|
2218
|
+
}
|
|
2219
|
+
async init() {
|
|
2220
|
+
this.isShuttingDown = false;
|
|
2221
|
+
if (this.config) return;
|
|
2222
|
+
if (this.initPromise) return this.initPromise;
|
|
2223
|
+
this.initPromise = this.doInit();
|
|
2224
|
+
try {
|
|
2225
|
+
await this.initPromise;
|
|
2226
|
+
} finally {
|
|
2227
|
+
this.initPromise = null;
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
async doInit() {
|
|
2231
|
+
const resp = await fetch(`${this.gatewayUrl}/v1/flags/config?environment=${encodeURIComponent(this.environment)}`, {
|
|
2232
|
+
headers: { "x-api-key": this.apiKey }
|
|
2233
|
+
});
|
|
2234
|
+
if (resp.status === 403) throw new Error("Secret API key required for /config");
|
|
2235
|
+
if (!resp.ok) throw new Error(`Config fetch failed: ${resp.status}`);
|
|
2236
|
+
const json = await resp.json();
|
|
2237
|
+
this.config = json.data;
|
|
2238
|
+
this.buildIndexes();
|
|
2239
|
+
this.lastETag = resp.headers.get("etag") || "";
|
|
2240
|
+
this.connectStream();
|
|
2241
|
+
this.startTelemetryFlush();
|
|
2242
|
+
}
|
|
2243
|
+
buildIndexes() {
|
|
2244
|
+
this.flagIndex.clear();
|
|
2245
|
+
this.segmentIndex.clear();
|
|
2246
|
+
if (!this.config) return;
|
|
2247
|
+
for (const flag of this.config.flags) {
|
|
2248
|
+
this.flagIndex.set(flag.flag_key, flag);
|
|
2249
|
+
}
|
|
2250
|
+
for (const segment of this.config.segments) {
|
|
2251
|
+
this.segmentIndex.set(segment.id, segment);
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
evaluate(flagKey, context) {
|
|
2255
|
+
if (!this.config) throw new Error("FlagClient not initialized \u2014 call init() first");
|
|
2256
|
+
const flagConfig = this.flagIndex.get(flagKey);
|
|
2257
|
+
if (!flagConfig) {
|
|
2258
|
+
return {
|
|
2259
|
+
flag_id: "",
|
|
2260
|
+
flag_key: flagKey,
|
|
2261
|
+
environment: this.environment,
|
|
2262
|
+
value: null,
|
|
2263
|
+
reason: "not_found",
|
|
2264
|
+
matched_rule_id: null,
|
|
2265
|
+
variant_key: null,
|
|
2266
|
+
bucket: null
|
|
2267
|
+
};
|
|
2268
|
+
}
|
|
2269
|
+
const result2 = evaluateFlag(flagConfig, this.config, context, this.segmentIndex);
|
|
2270
|
+
this.recordTelemetry(result2);
|
|
2271
|
+
return result2;
|
|
2272
|
+
}
|
|
2273
|
+
evaluateBatch(flagKeys, context) {
|
|
2274
|
+
if (!this.config) throw new Error("FlagClient not initialized \u2014 call init() first");
|
|
2275
|
+
const results = {};
|
|
2276
|
+
for (const key of flagKeys) {
|
|
2277
|
+
const flagConfig = this.flagIndex.get(key);
|
|
2278
|
+
if (flagConfig) {
|
|
2279
|
+
const result2 = evaluateFlag(flagConfig, this.config, context, this.segmentIndex);
|
|
2280
|
+
this.recordTelemetry(result2);
|
|
2281
|
+
results[key] = result2;
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
return results;
|
|
2285
|
+
}
|
|
2286
|
+
async shutdown() {
|
|
2287
|
+
this.isShuttingDown = true;
|
|
2288
|
+
this.streamState = "idle";
|
|
2289
|
+
this.abortController?.abort();
|
|
2290
|
+
this.abortController = null;
|
|
2291
|
+
if (this.pollTimer) {
|
|
2292
|
+
clearInterval(this.pollTimer);
|
|
2293
|
+
this.pollTimer = null;
|
|
2294
|
+
}
|
|
2295
|
+
if (this.reconnectTimer) {
|
|
2296
|
+
clearInterval(this.reconnectTimer);
|
|
2297
|
+
this.reconnectTimer = null;
|
|
2298
|
+
}
|
|
2299
|
+
if (this.telemetryTimer) {
|
|
2300
|
+
clearInterval(this.telemetryTimer);
|
|
2301
|
+
this.telemetryTimer = null;
|
|
2302
|
+
}
|
|
2303
|
+
await this.flushTelemetry();
|
|
2304
|
+
}
|
|
2305
|
+
// ======== SSE Streaming ========
|
|
2306
|
+
async connectStream() {
|
|
2307
|
+
if (this.isShuttingDown || this.streamState === "streaming" || this.streamConnectInFlight) return;
|
|
2308
|
+
this.streamConnectInFlight = true;
|
|
2309
|
+
this.abortController?.abort();
|
|
2310
|
+
const abortController = new AbortController();
|
|
2311
|
+
this.abortController = abortController;
|
|
2312
|
+
const shouldResumePolling = this.streamState !== "polling";
|
|
2313
|
+
let startPolling = shouldResumePolling;
|
|
2314
|
+
try {
|
|
2315
|
+
const resp = await fetch(
|
|
2316
|
+
`${this.gatewayUrl}/v1/flags/stream?environment=${encodeURIComponent(this.environment)}`,
|
|
2317
|
+
{
|
|
2318
|
+
headers: {
|
|
2319
|
+
"x-api-key": this.apiKey,
|
|
2320
|
+
"Last-Event-ID": String(this.config?.version ?? 0)
|
|
2321
|
+
},
|
|
2322
|
+
signal: abortController.signal
|
|
2323
|
+
}
|
|
2324
|
+
);
|
|
2325
|
+
if (resp.ok && resp.body) {
|
|
2326
|
+
this.streamState = "streaming";
|
|
2327
|
+
this.stopPolling();
|
|
2328
|
+
startPolling = false;
|
|
2329
|
+
const reader = resp.body.getReader();
|
|
2330
|
+
const decoder = new TextDecoder();
|
|
2331
|
+
let buffer = "";
|
|
2332
|
+
while (true) {
|
|
2333
|
+
const { done, value } = await reader.read();
|
|
2334
|
+
if (done) break;
|
|
2335
|
+
buffer += decoder.decode(value, { stream: true });
|
|
2336
|
+
let idx;
|
|
2337
|
+
while ((idx = buffer.indexOf("\n\n")) !== -1) {
|
|
2338
|
+
const frame = buffer.slice(0, idx);
|
|
2339
|
+
buffer = buffer.slice(idx + 2);
|
|
2340
|
+
this.handleSseFrame(frame);
|
|
2341
|
+
}
|
|
2342
|
+
}
|
|
2343
|
+
if (this.streamState === "streaming") {
|
|
2344
|
+
this.streamState = "idle";
|
|
2345
|
+
startPolling = true;
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
} catch {
|
|
2349
|
+
startPolling = !abortController.signal.aborted && shouldResumePolling;
|
|
2350
|
+
} finally {
|
|
2351
|
+
this.streamConnectInFlight = false;
|
|
2352
|
+
}
|
|
2353
|
+
if (!this.isShuttingDown && startPolling) {
|
|
2354
|
+
this.startPolling();
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
handleSseFrame(frame) {
|
|
2358
|
+
let eventType = "";
|
|
2359
|
+
let data = "";
|
|
2360
|
+
for (const line of frame.split("\n")) {
|
|
2361
|
+
if (line.startsWith("event:")) eventType = line.slice(6).trim();
|
|
2362
|
+
else if (line.startsWith("data:")) data += line.slice(5).trim();
|
|
2363
|
+
}
|
|
2364
|
+
if (eventType === "config" && data) {
|
|
2365
|
+
try {
|
|
2366
|
+
const parsed = JSON.parse(data);
|
|
2367
|
+
const newConfig = parsed.data;
|
|
2368
|
+
if (newConfig && newConfig.version !== void 0) {
|
|
2369
|
+
this.config = newConfig;
|
|
2370
|
+
this.buildIndexes();
|
|
2371
|
+
}
|
|
2372
|
+
} catch {
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
// ======== Polling Fallback ========
|
|
2377
|
+
startPolling() {
|
|
2378
|
+
if (this.streamState === "polling") return;
|
|
2379
|
+
this.streamState = "polling";
|
|
2380
|
+
this.pollTimer = setInterval(() => void this.pollConfig(), 6e4);
|
|
2381
|
+
this.reconnectTimer = setInterval(() => void this.connectStream(), 3e5);
|
|
2382
|
+
}
|
|
2383
|
+
stopPolling() {
|
|
2384
|
+
if (this.pollTimer) {
|
|
2385
|
+
clearInterval(this.pollTimer);
|
|
2386
|
+
this.pollTimer = null;
|
|
2387
|
+
}
|
|
2388
|
+
if (this.reconnectTimer) {
|
|
2389
|
+
clearInterval(this.reconnectTimer);
|
|
2390
|
+
this.reconnectTimer = null;
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
async pollConfig() {
|
|
2394
|
+
try {
|
|
2395
|
+
const headers2 = { "x-api-key": this.apiKey };
|
|
2396
|
+
if (this.lastETag) headers2["if-none-match"] = this.lastETag;
|
|
2397
|
+
const resp = await fetch(
|
|
2398
|
+
`${this.gatewayUrl}/v1/flags/config?environment=${encodeURIComponent(this.environment)}`,
|
|
2399
|
+
{ headers: headers2 }
|
|
2400
|
+
);
|
|
2401
|
+
if (resp.status === 304) return;
|
|
2402
|
+
if (!resp.ok) return;
|
|
2403
|
+
const json = await resp.json();
|
|
2404
|
+
this.config = json.data;
|
|
2405
|
+
this.buildIndexes();
|
|
2406
|
+
this.lastETag = resp.headers.get("etag") || "";
|
|
2407
|
+
} catch {
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
// ======== Telemetry ========
|
|
2411
|
+
recordTelemetry(evaluation) {
|
|
2412
|
+
const key = `${evaluation.flag_key}:${evaluation.reason}:${String(evaluation.value)}`;
|
|
2413
|
+
const existing = this.telemetryCounters.get(key);
|
|
2414
|
+
if (existing) {
|
|
2415
|
+
existing.count++;
|
|
2416
|
+
if (evaluation.value === true) existing.true_count++;
|
|
2417
|
+
else if (evaluation.value === false) existing.false_count++;
|
|
2418
|
+
} else {
|
|
2419
|
+
this.telemetryCounters.set(key, {
|
|
2420
|
+
flag_key: evaluation.flag_key,
|
|
2421
|
+
flag_id: evaluation.flag_id,
|
|
2422
|
+
reason: evaluation.reason,
|
|
2423
|
+
count: 1,
|
|
2424
|
+
true_count: evaluation.value === true ? 1 : 0,
|
|
2425
|
+
false_count: evaluation.value === false ? 1 : 0
|
|
2426
|
+
});
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
startTelemetryFlush() {
|
|
2430
|
+
this.telemetryTimer = setInterval(() => void this.flushTelemetry(), 6e4);
|
|
2431
|
+
}
|
|
2432
|
+
async flushTelemetry() {
|
|
2433
|
+
if (this.telemetryCounters.size === 0) return;
|
|
2434
|
+
const evaluations = Array.from(this.telemetryCounters.values());
|
|
2435
|
+
this.telemetryCounters.clear();
|
|
2436
|
+
try {
|
|
2437
|
+
await fetch(`${this.gatewayUrl}/v1/flags/telemetry`, {
|
|
2438
|
+
method: "POST",
|
|
2439
|
+
headers: {
|
|
2440
|
+
"Content-Type": "application/json",
|
|
2441
|
+
"x-api-key": this.apiKey
|
|
2442
|
+
},
|
|
2443
|
+
body: JSON.stringify({
|
|
2444
|
+
environment: this.environment,
|
|
2445
|
+
evaluations
|
|
2446
|
+
})
|
|
2447
|
+
});
|
|
2448
|
+
} catch {
|
|
2449
|
+
for (const counter of evaluations) {
|
|
2450
|
+
const key = `${counter.flag_key}:${counter.reason}:${counter.count}`;
|
|
2451
|
+
const existing = this.telemetryCounters.get(key);
|
|
2452
|
+
if (existing) {
|
|
2453
|
+
existing.count += counter.count;
|
|
2454
|
+
existing.true_count += counter.true_count;
|
|
2455
|
+
existing.false_count += counter.false_count;
|
|
2456
|
+
} else {
|
|
2457
|
+
this.telemetryCounters.set(key, counter);
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
};
|
|
2463
|
+
}
|
|
2464
|
+
});
|
|
2465
|
+
|
|
1920
2466
|
// src/types/index.ts
|
|
1921
2467
|
var ScaleMuleApiError = class extends Error {
|
|
1922
2468
|
constructor(error, status) {
|
|
@@ -3315,7 +3861,7 @@ function createAuthRoutes(config = {}) {
|
|
|
3315
3861
|
if (!email) {
|
|
3316
3862
|
return errorResponse("VALIDATION_ERROR", "Email required", 400);
|
|
3317
3863
|
}
|
|
3318
|
-
const
|
|
3864
|
+
const result = await sm.auth.forgotPassword(email, { clientContext });
|
|
3319
3865
|
return successResponse({ message: "If an account exists, a reset email has been sent" });
|
|
3320
3866
|
}
|
|
3321
3867
|
// ==================== Reset Password ====================
|
|
@@ -3955,8 +4501,10 @@ function getLedverySession(request) {
|
|
|
3955
4501
|
if (!raw) return null;
|
|
3956
4502
|
try {
|
|
3957
4503
|
const parsed = JSON.parse(raw);
|
|
4504
|
+
const accessToken = getCookie(request, SM_LEDVERY_ACCESS_TOKEN_COOKIE);
|
|
3958
4505
|
return {
|
|
3959
4506
|
idToken: parsed.idToken || "",
|
|
4507
|
+
accessToken,
|
|
3960
4508
|
claims: parsed.claims,
|
|
3961
4509
|
expiresAt: parsed.expiresAt
|
|
3962
4510
|
};
|
|
@@ -4058,9 +4606,11 @@ function createLedveryRoutes(config) {
|
|
|
4058
4606
|
async function handleLogin(request) {
|
|
4059
4607
|
const url = new URL(request.url);
|
|
4060
4608
|
const returnTo = url.searchParams.get("returnTo");
|
|
4609
|
+
const provider = url.searchParams.get("provider");
|
|
4061
4610
|
const validatedReturnTo = validateSafeRedirect(returnTo, { defaultPath: postLoginRedirect });
|
|
4062
4611
|
const authResult = await client.createAuthorizationUrl({
|
|
4063
|
-
scope: defaultScope
|
|
4612
|
+
scope: defaultScope,
|
|
4613
|
+
extraParams: provider ? { upstream: provider } : void 0
|
|
4064
4614
|
});
|
|
4065
4615
|
const response = new Response(null, {
|
|
4066
4616
|
status: 302,
|
|
@@ -4460,9 +5010,9 @@ var CODE_TO_STATUS = {
|
|
|
4460
5010
|
function errorCodeToStatus(code) {
|
|
4461
5011
|
return CODE_TO_STATUS[code.toLowerCase()] || 400;
|
|
4462
5012
|
}
|
|
4463
|
-
function unwrap(
|
|
4464
|
-
if (
|
|
4465
|
-
const envelope =
|
|
5013
|
+
function unwrap(result) {
|
|
5014
|
+
if (result !== null && result !== void 0 && typeof result === "object" && ("success" in result || "error" in result) && "data" in result) {
|
|
5015
|
+
const envelope = result;
|
|
4466
5016
|
if (envelope.error || envelope.success === false) {
|
|
4467
5017
|
const err = envelope.error;
|
|
4468
5018
|
const code = err?.code || "UNKNOWN_ERROR";
|
|
@@ -4476,7 +5026,7 @@ function unwrap(result2) {
|
|
|
4476
5026
|
}
|
|
4477
5027
|
return envelope.data;
|
|
4478
5028
|
}
|
|
4479
|
-
return
|
|
5029
|
+
return result;
|
|
4480
5030
|
}
|
|
4481
5031
|
|
|
4482
5032
|
// src/server/handler.ts
|
|
@@ -4503,10 +5053,10 @@ function apiHandler(handler, options) {
|
|
|
4503
5053
|
searchParams: request.nextUrl.searchParams,
|
|
4504
5054
|
session
|
|
4505
5055
|
};
|
|
4506
|
-
const
|
|
4507
|
-
if (
|
|
4508
|
-
if (
|
|
4509
|
-
return Response.json({ success: true, data:
|
|
5056
|
+
const result = await handler(request, context);
|
|
5057
|
+
if (result instanceof Response) return result;
|
|
5058
|
+
if (result !== void 0) {
|
|
5059
|
+
return Response.json({ success: true, data: result }, { status: 200 });
|
|
4510
5060
|
}
|
|
4511
5061
|
return new Response(null, { status: 204 });
|
|
4512
5062
|
} catch (error) {
|
|
@@ -4553,14 +5103,14 @@ function parseWebhookEvent(payload) {
|
|
|
4553
5103
|
}
|
|
4554
5104
|
async function registerVideoWebhook(url, options) {
|
|
4555
5105
|
const sm = createServerClient(options?.clientConfig);
|
|
4556
|
-
const
|
|
5106
|
+
const result = await sm.webhooks.create({
|
|
4557
5107
|
webhook_name: options?.name || "Video Status Webhook",
|
|
4558
5108
|
url,
|
|
4559
5109
|
events: options?.events || ["video.ready", "video.failed"]
|
|
4560
5110
|
});
|
|
4561
5111
|
return {
|
|
4562
|
-
id:
|
|
4563
|
-
secret:
|
|
5112
|
+
id: result.id,
|
|
5113
|
+
secret: result.secret
|
|
4564
5114
|
};
|
|
4565
5115
|
}
|
|
4566
5116
|
function createWebhookRoutes(config = {}) {
|
|
@@ -4648,517 +5198,8 @@ function createWebhookHandler(config = {}) {
|
|
|
4648
5198
|
};
|
|
4649
5199
|
}
|
|
4650
5200
|
|
|
4651
|
-
// node_modules/@scalemule/sdk/dist/flags/server.mjs
|
|
4652
|
-
var import_semver = __toESM(require_semver2());
|
|
4653
|
-
function hashToBucket(flagKey, identifier, salt) {
|
|
4654
|
-
const hash = crypto$1.createHash("sha256").update(`${salt}.${flagKey}.${identifier}`).digest();
|
|
4655
|
-
return hash.readUInt32BE(0) % 1e4;
|
|
4656
|
-
}
|
|
4657
|
-
function allConditionsMatch(conditions, context) {
|
|
4658
|
-
return conditions.every((c) => conditionMatches(c, context));
|
|
4659
|
-
}
|
|
4660
|
-
function conditionMatches(condition, context) {
|
|
4661
|
-
const attributeValue = getAttribute(context, condition.attribute);
|
|
4662
|
-
const op = condition.operator;
|
|
4663
|
-
if (op === "exists") return attributeValue !== void 0 && attributeValue !== null;
|
|
4664
|
-
if (op === "not_exists") return attributeValue === void 0 || attributeValue === null;
|
|
4665
|
-
if (attributeValue === void 0 || attributeValue === null) return false;
|
|
4666
|
-
switch (op) {
|
|
4667
|
-
case "eq":
|
|
4668
|
-
return compareValues(attributeValue, condition.value) === 0;
|
|
4669
|
-
case "neq":
|
|
4670
|
-
return compareValues(attributeValue, condition.value) !== 0;
|
|
4671
|
-
case "in":
|
|
4672
|
-
return candidateValues(condition).some((v) => compareValues(attributeValue, v) === 0);
|
|
4673
|
-
case "not_in":
|
|
4674
|
-
return !candidateValues(condition).some((v) => compareValues(attributeValue, v) === 0);
|
|
4675
|
-
case "contains":
|
|
4676
|
-
return containsValue(attributeValue, condition.value);
|
|
4677
|
-
case "starts_with":
|
|
4678
|
-
return typeof attributeValue === "string" && typeof condition.value === "string" ? attributeValue.startsWith(condition.value) : false;
|
|
4679
|
-
case "ends_with":
|
|
4680
|
-
return typeof attributeValue === "string" && typeof condition.value === "string" ? attributeValue.endsWith(condition.value) : false;
|
|
4681
|
-
case "gt":
|
|
4682
|
-
return compareValues(attributeValue, condition.value) === 1;
|
|
4683
|
-
case "gte": {
|
|
4684
|
-
const cmp = compareValues(attributeValue, condition.value);
|
|
4685
|
-
return cmp === 1 || cmp === 0;
|
|
4686
|
-
}
|
|
4687
|
-
case "lt":
|
|
4688
|
-
return compareValues(attributeValue, condition.value) === -1;
|
|
4689
|
-
case "lte": {
|
|
4690
|
-
const cmp = compareValues(attributeValue, condition.value);
|
|
4691
|
-
return cmp === -1 || cmp === 0;
|
|
4692
|
-
}
|
|
4693
|
-
case "regex": {
|
|
4694
|
-
if (typeof attributeValue !== "string" || typeof condition.value !== "string") return false;
|
|
4695
|
-
try {
|
|
4696
|
-
return new RegExp(condition.value).test(attributeValue);
|
|
4697
|
-
} catch {
|
|
4698
|
-
return false;
|
|
4699
|
-
}
|
|
4700
|
-
}
|
|
4701
|
-
case "semver_eq":
|
|
4702
|
-
return semverCmp(attributeValue, condition.value) === 0;
|
|
4703
|
-
case "semver_neq":
|
|
4704
|
-
return semverCmp(attributeValue, condition.value) !== 0;
|
|
4705
|
-
case "semver_gt":
|
|
4706
|
-
return semverCmp(attributeValue, condition.value) === 1;
|
|
4707
|
-
case "semver_gte": {
|
|
4708
|
-
const cmp = semverCmp(attributeValue, condition.value);
|
|
4709
|
-
return cmp === 1 || cmp === 0;
|
|
4710
|
-
}
|
|
4711
|
-
case "semver_lt":
|
|
4712
|
-
return semverCmp(attributeValue, condition.value) === -1;
|
|
4713
|
-
case "semver_lte": {
|
|
4714
|
-
const cmp = semverCmp(attributeValue, condition.value);
|
|
4715
|
-
return cmp === -1 || cmp === 0;
|
|
4716
|
-
}
|
|
4717
|
-
default:
|
|
4718
|
-
return false;
|
|
4719
|
-
}
|
|
4720
|
-
}
|
|
4721
|
-
function getAttribute(context, key) {
|
|
4722
|
-
switch (key) {
|
|
4723
|
-
case "user_id":
|
|
4724
|
-
return context.user_id;
|
|
4725
|
-
case "email":
|
|
4726
|
-
return context.email;
|
|
4727
|
-
case "session_id":
|
|
4728
|
-
return context.session_id;
|
|
4729
|
-
case "ip_address":
|
|
4730
|
-
return context.ip_address;
|
|
4731
|
-
case "user_agent":
|
|
4732
|
-
return context.user_agent;
|
|
4733
|
-
case "timestamp":
|
|
4734
|
-
return context.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
4735
|
-
default:
|
|
4736
|
-
return context[key];
|
|
4737
|
-
}
|
|
4738
|
-
}
|
|
4739
|
-
function candidateValues(condition) {
|
|
4740
|
-
if (condition.values && condition.values.length > 0) return condition.values;
|
|
4741
|
-
if (condition.value === void 0 || condition.value === null) return [];
|
|
4742
|
-
if (Array.isArray(condition.value)) return condition.value;
|
|
4743
|
-
return [condition.value];
|
|
4744
|
-
}
|
|
4745
|
-
function compareValues(actual, expected) {
|
|
4746
|
-
if (expected === void 0 || expected === null) return null;
|
|
4747
|
-
const numA = toNumber(actual);
|
|
4748
|
-
const numB = toNumber(expected);
|
|
4749
|
-
if (numA !== null && numB !== null) {
|
|
4750
|
-
if (numA < numB) return -1;
|
|
4751
|
-
if (numA > numB) return 1;
|
|
4752
|
-
return 0;
|
|
4753
|
-
}
|
|
4754
|
-
if (typeof actual === "boolean" && typeof expected === "boolean") {
|
|
4755
|
-
if (actual === expected) return 0;
|
|
4756
|
-
return actual ? 1 : -1;
|
|
4757
|
-
}
|
|
4758
|
-
const strA = toString(actual);
|
|
4759
|
-
const strB = toString(expected);
|
|
4760
|
-
if (strA !== null && strB !== null) {
|
|
4761
|
-
if (strA < strB) return -1;
|
|
4762
|
-
if (strA > strB) return 1;
|
|
4763
|
-
return 0;
|
|
4764
|
-
}
|
|
4765
|
-
return null;
|
|
4766
|
-
}
|
|
4767
|
-
function containsValue(actual, expected) {
|
|
4768
|
-
if (expected === void 0 || expected === null) return false;
|
|
4769
|
-
if (Array.isArray(actual)) {
|
|
4770
|
-
return actual.some((item) => compareValues(item, expected) === 0);
|
|
4771
|
-
}
|
|
4772
|
-
if (typeof actual === "string" && typeof expected === "string") {
|
|
4773
|
-
return actual.includes(expected);
|
|
4774
|
-
}
|
|
4775
|
-
return false;
|
|
4776
|
-
}
|
|
4777
|
-
function toNumber(value) {
|
|
4778
|
-
if (typeof value === "number") return value;
|
|
4779
|
-
if (typeof value === "string") {
|
|
4780
|
-
const n = Number(value);
|
|
4781
|
-
return isNaN(n) ? null : n;
|
|
4782
|
-
}
|
|
4783
|
-
return null;
|
|
4784
|
-
}
|
|
4785
|
-
function toString(value) {
|
|
4786
|
-
if (typeof value === "string") return value;
|
|
4787
|
-
return null;
|
|
4788
|
-
}
|
|
4789
|
-
function semverCmp(actual, expected) {
|
|
4790
|
-
if (typeof actual !== "string" || typeof expected !== "string") return null;
|
|
4791
|
-
try {
|
|
4792
|
-
const a = (0, import_semver.parse)(actual);
|
|
4793
|
-
const b = (0, import_semver.parse)(expected);
|
|
4794
|
-
if (!a || !b) return null;
|
|
4795
|
-
return (0, import_semver.compare)(a, b);
|
|
4796
|
-
} catch {
|
|
4797
|
-
return null;
|
|
4798
|
-
}
|
|
4799
|
-
}
|
|
4800
|
-
function evaluateFlag(flag, config, context, segmentIndex) {
|
|
4801
|
-
const effectiveDefault = flag.environment_default_value ?? flag.default_value;
|
|
4802
|
-
if (flag.status !== "active") {
|
|
4803
|
-
return result(flag, config.environment, effectiveDefault, "disabled");
|
|
4804
|
-
}
|
|
4805
|
-
if (!flag.environment_enabled) {
|
|
4806
|
-
return result(flag, config.environment, effectiveDefault, "disabled");
|
|
4807
|
-
}
|
|
4808
|
-
const bucketIdentifier = getBucketIdentifier(context);
|
|
4809
|
-
for (const rule of flag.rules) {
|
|
4810
|
-
if (!rule.enabled) continue;
|
|
4811
|
-
if (rule.segment_ids.length > 0) {
|
|
4812
|
-
const segmentMatched = rule.segment_ids.some((segId) => {
|
|
4813
|
-
const segment = segmentIndex ? segmentIndex.get(segId) : config.segments.find((s) => s.id === segId);
|
|
4814
|
-
if (!segment) return false;
|
|
4815
|
-
return userMatchesSegment(segment, context);
|
|
4816
|
-
});
|
|
4817
|
-
if (!segmentMatched) continue;
|
|
4818
|
-
}
|
|
4819
|
-
if (!allConditionsMatch(rule.conditions, context)) continue;
|
|
4820
|
-
if (rule.rollout_percentage !== null && rule.rollout_percentage !== void 0) {
|
|
4821
|
-
const bucket = hashToBucket(flag.flag_key, bucketIdentifier, config.rollout_salt);
|
|
4822
|
-
if (bucket >= rule.rollout_percentage) continue;
|
|
4823
|
-
return {
|
|
4824
|
-
flag_id: flag.flag_id,
|
|
4825
|
-
flag_key: flag.flag_key,
|
|
4826
|
-
environment: config.environment,
|
|
4827
|
-
value: rule.serve_value,
|
|
4828
|
-
reason: "rule_match",
|
|
4829
|
-
matched_rule_id: rule.id,
|
|
4830
|
-
variant_key: null,
|
|
4831
|
-
bucket
|
|
4832
|
-
};
|
|
4833
|
-
}
|
|
4834
|
-
return {
|
|
4835
|
-
flag_id: flag.flag_id,
|
|
4836
|
-
flag_key: flag.flag_key,
|
|
4837
|
-
environment: config.environment,
|
|
4838
|
-
value: rule.serve_value,
|
|
4839
|
-
reason: "rule_match",
|
|
4840
|
-
matched_rule_id: rule.id,
|
|
4841
|
-
variant_key: null,
|
|
4842
|
-
bucket: null
|
|
4843
|
-
};
|
|
4844
|
-
}
|
|
4845
|
-
if (flag.variants.length > 0) {
|
|
4846
|
-
const totalWeight = flag.variants.reduce((sum, v) => sum + v.weight, 0);
|
|
4847
|
-
if (totalWeight > 0) {
|
|
4848
|
-
const bucket = hashToBucket(flag.flag_key, bucketIdentifier, config.rollout_salt);
|
|
4849
|
-
const scaled = Math.floor(bucket * totalWeight / 1e4);
|
|
4850
|
-
let cursor = 0;
|
|
4851
|
-
for (const variant of flag.variants) {
|
|
4852
|
-
cursor += variant.weight;
|
|
4853
|
-
if (scaled < cursor) {
|
|
4854
|
-
return {
|
|
4855
|
-
flag_id: flag.flag_id,
|
|
4856
|
-
flag_key: flag.flag_key,
|
|
4857
|
-
environment: config.environment,
|
|
4858
|
-
value: variant.value,
|
|
4859
|
-
reason: "variant",
|
|
4860
|
-
matched_rule_id: null,
|
|
4861
|
-
variant_key: variant.variant_key,
|
|
4862
|
-
bucket
|
|
4863
|
-
};
|
|
4864
|
-
}
|
|
4865
|
-
}
|
|
4866
|
-
}
|
|
4867
|
-
}
|
|
4868
|
-
return result(flag, config.environment, effectiveDefault, "default");
|
|
4869
|
-
}
|
|
4870
|
-
function getBucketIdentifier(context) {
|
|
4871
|
-
return context.user_id ?? context.session_id ?? context.email ?? context.ip_address ?? "anonymous";
|
|
4872
|
-
}
|
|
4873
|
-
function userMatchesSegment(segment, context) {
|
|
4874
|
-
const identifiers = [context.user_id, context.email, context.session_id].filter(
|
|
4875
|
-
(v) => v !== void 0 && v !== null
|
|
4876
|
-
);
|
|
4877
|
-
if (identifiers.some((id) => segment.excluded_users.includes(id))) {
|
|
4878
|
-
return false;
|
|
4879
|
-
}
|
|
4880
|
-
if (identifiers.some((id) => segment.included_users.includes(id))) {
|
|
4881
|
-
return true;
|
|
4882
|
-
}
|
|
4883
|
-
return allConditionsMatch(segment.conditions, context);
|
|
4884
|
-
}
|
|
4885
|
-
function result(flag, environment, value, reason) {
|
|
4886
|
-
return {
|
|
4887
|
-
flag_id: flag.flag_id,
|
|
4888
|
-
flag_key: flag.flag_key,
|
|
4889
|
-
environment,
|
|
4890
|
-
value,
|
|
4891
|
-
reason,
|
|
4892
|
-
matched_rule_id: null,
|
|
4893
|
-
variant_key: null,
|
|
4894
|
-
bucket: null
|
|
4895
|
-
};
|
|
4896
|
-
}
|
|
4897
|
-
var FlagClient = class {
|
|
4898
|
-
constructor(options) {
|
|
4899
|
-
this.config = null;
|
|
4900
|
-
this.flagIndex = /* @__PURE__ */ new Map();
|
|
4901
|
-
this.segmentIndex = /* @__PURE__ */ new Map();
|
|
4902
|
-
this.lastETag = "";
|
|
4903
|
-
this.streamState = "idle";
|
|
4904
|
-
this.pollTimer = null;
|
|
4905
|
-
this.reconnectTimer = null;
|
|
4906
|
-
this.telemetryTimer = null;
|
|
4907
|
-
this.abortController = null;
|
|
4908
|
-
this.initPromise = null;
|
|
4909
|
-
this.telemetryCounters = /* @__PURE__ */ new Map();
|
|
4910
|
-
this.isShuttingDown = false;
|
|
4911
|
-
this.streamConnectInFlight = false;
|
|
4912
|
-
this.apiKey = options.apiKey;
|
|
4913
|
-
this.environment = options.environment;
|
|
4914
|
-
this.gatewayUrl = options.gatewayUrl;
|
|
4915
|
-
}
|
|
4916
|
-
async init() {
|
|
4917
|
-
this.isShuttingDown = false;
|
|
4918
|
-
if (this.config) return;
|
|
4919
|
-
if (this.initPromise) return this.initPromise;
|
|
4920
|
-
this.initPromise = this.doInit();
|
|
4921
|
-
try {
|
|
4922
|
-
await this.initPromise;
|
|
4923
|
-
} finally {
|
|
4924
|
-
this.initPromise = null;
|
|
4925
|
-
}
|
|
4926
|
-
}
|
|
4927
|
-
async doInit() {
|
|
4928
|
-
const resp = await fetch(`${this.gatewayUrl}/v1/flags/config?environment=${encodeURIComponent(this.environment)}`, {
|
|
4929
|
-
headers: { "x-api-key": this.apiKey }
|
|
4930
|
-
});
|
|
4931
|
-
if (resp.status === 403) throw new Error("Secret API key required for /config");
|
|
4932
|
-
if (!resp.ok) throw new Error(`Config fetch failed: ${resp.status}`);
|
|
4933
|
-
const json = await resp.json();
|
|
4934
|
-
this.config = json.data;
|
|
4935
|
-
this.buildIndexes();
|
|
4936
|
-
this.lastETag = resp.headers.get("etag") || "";
|
|
4937
|
-
this.connectStream();
|
|
4938
|
-
this.startTelemetryFlush();
|
|
4939
|
-
}
|
|
4940
|
-
buildIndexes() {
|
|
4941
|
-
this.flagIndex.clear();
|
|
4942
|
-
this.segmentIndex.clear();
|
|
4943
|
-
if (!this.config) return;
|
|
4944
|
-
for (const flag of this.config.flags) {
|
|
4945
|
-
this.flagIndex.set(flag.flag_key, flag);
|
|
4946
|
-
}
|
|
4947
|
-
for (const segment of this.config.segments) {
|
|
4948
|
-
this.segmentIndex.set(segment.id, segment);
|
|
4949
|
-
}
|
|
4950
|
-
}
|
|
4951
|
-
evaluate(flagKey, context) {
|
|
4952
|
-
if (!this.config) throw new Error("FlagClient not initialized \u2014 call init() first");
|
|
4953
|
-
const flagConfig = this.flagIndex.get(flagKey);
|
|
4954
|
-
if (!flagConfig) {
|
|
4955
|
-
return {
|
|
4956
|
-
flag_id: "",
|
|
4957
|
-
flag_key: flagKey,
|
|
4958
|
-
environment: this.environment,
|
|
4959
|
-
value: null,
|
|
4960
|
-
reason: "not_found",
|
|
4961
|
-
matched_rule_id: null,
|
|
4962
|
-
variant_key: null,
|
|
4963
|
-
bucket: null
|
|
4964
|
-
};
|
|
4965
|
-
}
|
|
4966
|
-
const result2 = evaluateFlag(flagConfig, this.config, context, this.segmentIndex);
|
|
4967
|
-
this.recordTelemetry(result2);
|
|
4968
|
-
return result2;
|
|
4969
|
-
}
|
|
4970
|
-
evaluateBatch(flagKeys, context) {
|
|
4971
|
-
if (!this.config) throw new Error("FlagClient not initialized \u2014 call init() first");
|
|
4972
|
-
const results = {};
|
|
4973
|
-
for (const key of flagKeys) {
|
|
4974
|
-
const flagConfig = this.flagIndex.get(key);
|
|
4975
|
-
if (flagConfig) {
|
|
4976
|
-
const result2 = evaluateFlag(flagConfig, this.config, context, this.segmentIndex);
|
|
4977
|
-
this.recordTelemetry(result2);
|
|
4978
|
-
results[key] = result2;
|
|
4979
|
-
}
|
|
4980
|
-
}
|
|
4981
|
-
return results;
|
|
4982
|
-
}
|
|
4983
|
-
async shutdown() {
|
|
4984
|
-
this.isShuttingDown = true;
|
|
4985
|
-
this.streamState = "idle";
|
|
4986
|
-
this.abortController?.abort();
|
|
4987
|
-
this.abortController = null;
|
|
4988
|
-
if (this.pollTimer) {
|
|
4989
|
-
clearInterval(this.pollTimer);
|
|
4990
|
-
this.pollTimer = null;
|
|
4991
|
-
}
|
|
4992
|
-
if (this.reconnectTimer) {
|
|
4993
|
-
clearInterval(this.reconnectTimer);
|
|
4994
|
-
this.reconnectTimer = null;
|
|
4995
|
-
}
|
|
4996
|
-
if (this.telemetryTimer) {
|
|
4997
|
-
clearInterval(this.telemetryTimer);
|
|
4998
|
-
this.telemetryTimer = null;
|
|
4999
|
-
}
|
|
5000
|
-
await this.flushTelemetry();
|
|
5001
|
-
}
|
|
5002
|
-
// ======== SSE Streaming ========
|
|
5003
|
-
async connectStream() {
|
|
5004
|
-
if (this.isShuttingDown || this.streamState === "streaming" || this.streamConnectInFlight) return;
|
|
5005
|
-
this.streamConnectInFlight = true;
|
|
5006
|
-
this.abortController?.abort();
|
|
5007
|
-
const abortController = new AbortController();
|
|
5008
|
-
this.abortController = abortController;
|
|
5009
|
-
const shouldResumePolling = this.streamState !== "polling";
|
|
5010
|
-
let startPolling = shouldResumePolling;
|
|
5011
|
-
try {
|
|
5012
|
-
const resp = await fetch(
|
|
5013
|
-
`${this.gatewayUrl}/v1/flags/stream?environment=${encodeURIComponent(this.environment)}`,
|
|
5014
|
-
{
|
|
5015
|
-
headers: {
|
|
5016
|
-
"x-api-key": this.apiKey,
|
|
5017
|
-
"Last-Event-ID": String(this.config?.version ?? 0)
|
|
5018
|
-
},
|
|
5019
|
-
signal: abortController.signal
|
|
5020
|
-
}
|
|
5021
|
-
);
|
|
5022
|
-
if (resp.ok && resp.body) {
|
|
5023
|
-
this.streamState = "streaming";
|
|
5024
|
-
this.stopPolling();
|
|
5025
|
-
startPolling = false;
|
|
5026
|
-
const reader = resp.body.getReader();
|
|
5027
|
-
const decoder = new TextDecoder();
|
|
5028
|
-
let buffer = "";
|
|
5029
|
-
while (true) {
|
|
5030
|
-
const { done, value } = await reader.read();
|
|
5031
|
-
if (done) break;
|
|
5032
|
-
buffer += decoder.decode(value, { stream: true });
|
|
5033
|
-
let idx;
|
|
5034
|
-
while ((idx = buffer.indexOf("\n\n")) !== -1) {
|
|
5035
|
-
const frame = buffer.slice(0, idx);
|
|
5036
|
-
buffer = buffer.slice(idx + 2);
|
|
5037
|
-
this.handleSseFrame(frame);
|
|
5038
|
-
}
|
|
5039
|
-
}
|
|
5040
|
-
if (this.streamState === "streaming") {
|
|
5041
|
-
this.streamState = "idle";
|
|
5042
|
-
startPolling = true;
|
|
5043
|
-
}
|
|
5044
|
-
}
|
|
5045
|
-
} catch {
|
|
5046
|
-
startPolling = !abortController.signal.aborted && shouldResumePolling;
|
|
5047
|
-
} finally {
|
|
5048
|
-
this.streamConnectInFlight = false;
|
|
5049
|
-
}
|
|
5050
|
-
if (!this.isShuttingDown && startPolling) {
|
|
5051
|
-
this.startPolling();
|
|
5052
|
-
}
|
|
5053
|
-
}
|
|
5054
|
-
handleSseFrame(frame) {
|
|
5055
|
-
let eventType = "";
|
|
5056
|
-
let data = "";
|
|
5057
|
-
for (const line of frame.split("\n")) {
|
|
5058
|
-
if (line.startsWith("event:")) eventType = line.slice(6).trim();
|
|
5059
|
-
else if (line.startsWith("data:")) data += line.slice(5).trim();
|
|
5060
|
-
}
|
|
5061
|
-
if (eventType === "config" && data) {
|
|
5062
|
-
try {
|
|
5063
|
-
const parsed = JSON.parse(data);
|
|
5064
|
-
const newConfig = parsed.data;
|
|
5065
|
-
if (newConfig && newConfig.version !== void 0) {
|
|
5066
|
-
this.config = newConfig;
|
|
5067
|
-
this.buildIndexes();
|
|
5068
|
-
}
|
|
5069
|
-
} catch {
|
|
5070
|
-
}
|
|
5071
|
-
}
|
|
5072
|
-
}
|
|
5073
|
-
// ======== Polling Fallback ========
|
|
5074
|
-
startPolling() {
|
|
5075
|
-
if (this.streamState === "polling") return;
|
|
5076
|
-
this.streamState = "polling";
|
|
5077
|
-
this.pollTimer = setInterval(() => void this.pollConfig(), 6e4);
|
|
5078
|
-
this.reconnectTimer = setInterval(() => void this.connectStream(), 3e5);
|
|
5079
|
-
}
|
|
5080
|
-
stopPolling() {
|
|
5081
|
-
if (this.pollTimer) {
|
|
5082
|
-
clearInterval(this.pollTimer);
|
|
5083
|
-
this.pollTimer = null;
|
|
5084
|
-
}
|
|
5085
|
-
if (this.reconnectTimer) {
|
|
5086
|
-
clearInterval(this.reconnectTimer);
|
|
5087
|
-
this.reconnectTimer = null;
|
|
5088
|
-
}
|
|
5089
|
-
}
|
|
5090
|
-
async pollConfig() {
|
|
5091
|
-
try {
|
|
5092
|
-
const headers2 = { "x-api-key": this.apiKey };
|
|
5093
|
-
if (this.lastETag) headers2["if-none-match"] = this.lastETag;
|
|
5094
|
-
const resp = await fetch(
|
|
5095
|
-
`${this.gatewayUrl}/v1/flags/config?environment=${encodeURIComponent(this.environment)}`,
|
|
5096
|
-
{ headers: headers2 }
|
|
5097
|
-
);
|
|
5098
|
-
if (resp.status === 304) return;
|
|
5099
|
-
if (!resp.ok) return;
|
|
5100
|
-
const json = await resp.json();
|
|
5101
|
-
this.config = json.data;
|
|
5102
|
-
this.buildIndexes();
|
|
5103
|
-
this.lastETag = resp.headers.get("etag") || "";
|
|
5104
|
-
} catch {
|
|
5105
|
-
}
|
|
5106
|
-
}
|
|
5107
|
-
// ======== Telemetry ========
|
|
5108
|
-
recordTelemetry(evaluation) {
|
|
5109
|
-
const key = `${evaluation.flag_key}:${evaluation.reason}:${String(evaluation.value)}`;
|
|
5110
|
-
const existing = this.telemetryCounters.get(key);
|
|
5111
|
-
if (existing) {
|
|
5112
|
-
existing.count++;
|
|
5113
|
-
if (evaluation.value === true) existing.true_count++;
|
|
5114
|
-
else if (evaluation.value === false) existing.false_count++;
|
|
5115
|
-
} else {
|
|
5116
|
-
this.telemetryCounters.set(key, {
|
|
5117
|
-
flag_key: evaluation.flag_key,
|
|
5118
|
-
flag_id: evaluation.flag_id,
|
|
5119
|
-
reason: evaluation.reason,
|
|
5120
|
-
count: 1,
|
|
5121
|
-
true_count: evaluation.value === true ? 1 : 0,
|
|
5122
|
-
false_count: evaluation.value === false ? 1 : 0
|
|
5123
|
-
});
|
|
5124
|
-
}
|
|
5125
|
-
}
|
|
5126
|
-
startTelemetryFlush() {
|
|
5127
|
-
this.telemetryTimer = setInterval(() => void this.flushTelemetry(), 6e4);
|
|
5128
|
-
}
|
|
5129
|
-
async flushTelemetry() {
|
|
5130
|
-
if (this.telemetryCounters.size === 0) return;
|
|
5131
|
-
const evaluations = Array.from(this.telemetryCounters.values());
|
|
5132
|
-
this.telemetryCounters.clear();
|
|
5133
|
-
try {
|
|
5134
|
-
await fetch(`${this.gatewayUrl}/v1/flags/telemetry`, {
|
|
5135
|
-
method: "POST",
|
|
5136
|
-
headers: {
|
|
5137
|
-
"Content-Type": "application/json",
|
|
5138
|
-
"x-api-key": this.apiKey
|
|
5139
|
-
},
|
|
5140
|
-
body: JSON.stringify({
|
|
5141
|
-
environment: this.environment,
|
|
5142
|
-
evaluations
|
|
5143
|
-
})
|
|
5144
|
-
});
|
|
5145
|
-
} catch {
|
|
5146
|
-
for (const counter of evaluations) {
|
|
5147
|
-
const key = `${counter.flag_key}:${counter.reason}:${counter.count}`;
|
|
5148
|
-
const existing = this.telemetryCounters.get(key);
|
|
5149
|
-
if (existing) {
|
|
5150
|
-
existing.count += counter.count;
|
|
5151
|
-
existing.true_count += counter.true_count;
|
|
5152
|
-
existing.false_count += counter.false_count;
|
|
5153
|
-
} else {
|
|
5154
|
-
this.telemetryCounters.set(key, counter);
|
|
5155
|
-
}
|
|
5156
|
-
}
|
|
5157
|
-
}
|
|
5158
|
-
}
|
|
5159
|
-
};
|
|
5160
|
-
|
|
5161
5201
|
// src/server/bootstrap-flags.ts
|
|
5202
|
+
var import_server2 = __toESM(require_server());
|
|
5162
5203
|
var _clients = /* @__PURE__ */ new Map();
|
|
5163
5204
|
var _initPromises = /* @__PURE__ */ new Map();
|
|
5164
5205
|
var _serverClient = null;
|
|
@@ -5186,7 +5227,7 @@ async function getFlagClient(environment) {
|
|
|
5186
5227
|
const pending = _initPromises.get(key);
|
|
5187
5228
|
if (pending) return pending;
|
|
5188
5229
|
const promise = (async () => {
|
|
5189
|
-
const client = new FlagClient({ apiKey, environment, gatewayUrl });
|
|
5230
|
+
const client = new import_server2.FlagClient({ apiKey, environment, gatewayUrl });
|
|
5190
5231
|
await Promise.race([
|
|
5191
5232
|
client.init(),
|
|
5192
5233
|
new Promise(
|
|
@@ -5235,8 +5276,8 @@ async function getBootstrapFlags(flagKeys, environment = "prod", extraContext =
|
|
|
5235
5276
|
const clientIp = extractClientIp(hdrs);
|
|
5236
5277
|
const context = { ...extraContext };
|
|
5237
5278
|
if (clientIp) context.ip_address = clientIp;
|
|
5238
|
-
const
|
|
5239
|
-
return
|
|
5279
|
+
const result = await getServerClient().flags.evaluateBatch(flagKeys, context, environment);
|
|
5280
|
+
return result || {};
|
|
5240
5281
|
} catch {
|
|
5241
5282
|
return {};
|
|
5242
5283
|
}
|
|
@@ -5386,15 +5427,15 @@ async function getAppSecret(key) {
|
|
|
5386
5427
|
}
|
|
5387
5428
|
try {
|
|
5388
5429
|
const client = createServerClient();
|
|
5389
|
-
const
|
|
5390
|
-
if (!noCache &&
|
|
5430
|
+
const result = await client.secrets.get(key);
|
|
5431
|
+
if (!noCache && result) {
|
|
5391
5432
|
secretsCache[key] = {
|
|
5392
|
-
value:
|
|
5393
|
-
version:
|
|
5433
|
+
value: result.value,
|
|
5434
|
+
version: result.version,
|
|
5394
5435
|
cachedAt: Date.now()
|
|
5395
5436
|
};
|
|
5396
5437
|
}
|
|
5397
|
-
return
|
|
5438
|
+
return result?.value;
|
|
5398
5439
|
} catch (error) {
|
|
5399
5440
|
if (error instanceof ScaleMuleApiError && error.code === "SECRET_NOT_FOUND") {
|
|
5400
5441
|
return void 0;
|
|
@@ -5445,17 +5486,17 @@ async function getBundle(key, resolve = true) {
|
|
|
5445
5486
|
}
|
|
5446
5487
|
try {
|
|
5447
5488
|
const client = createServerClient();
|
|
5448
|
-
const
|
|
5449
|
-
if (!noCache &&
|
|
5489
|
+
const result = await client.bundles.get(key, resolve);
|
|
5490
|
+
if (!noCache && result) {
|
|
5450
5491
|
bundlesCache[key] = {
|
|
5451
|
-
type:
|
|
5452
|
-
data:
|
|
5453
|
-
version:
|
|
5454
|
-
inheritsFrom:
|
|
5492
|
+
type: result.type,
|
|
5493
|
+
data: result.data,
|
|
5494
|
+
version: result.version,
|
|
5495
|
+
inheritsFrom: result.inherits_from,
|
|
5455
5496
|
cachedAt: Date.now()
|
|
5456
5497
|
};
|
|
5457
5498
|
}
|
|
5458
|
-
return
|
|
5499
|
+
return result?.data;
|
|
5459
5500
|
} catch (error) {
|
|
5460
5501
|
if (error instanceof ScaleMuleApiError && error.code === "BUNDLE_NOT_FOUND") {
|
|
5461
5502
|
return void 0;
|