featurely-site-manager 1.3.3 → 1.4.1
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/dist/index.js +63 -17
- package/dist/index.mjs +63 -17
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -256,7 +256,10 @@ var _SiteManager = class _SiteManager {
|
|
|
256
256
|
return defaultValue;
|
|
257
257
|
}
|
|
258
258
|
const flag = this.siteConfig.featureFlags.find((f) => f.key === flagKey);
|
|
259
|
-
this.debugLog(
|
|
259
|
+
this.debugLog(
|
|
260
|
+
"info",
|
|
261
|
+
`[flag-eval] Checking "${flagKey}" - found: ${!!flag}, enabled: ${(flag == null ? void 0 : flag.enabled) || false}`
|
|
262
|
+
);
|
|
260
263
|
if (!flag || !flag.enabled) {
|
|
261
264
|
return defaultValue;
|
|
262
265
|
}
|
|
@@ -696,9 +699,15 @@ var _SiteManager = class _SiteManager {
|
|
|
696
699
|
if (this.consecutiveFetchFailures <= _SiteManager.MAX_CONSECUTIVE_FAILURES) {
|
|
697
700
|
const isNetworkError = error instanceof TypeError && (error.message.includes("NetworkError") || error.message.includes("Failed to fetch") || error.message.includes("fetch"));
|
|
698
701
|
if (isNetworkError) {
|
|
699
|
-
this.debugLog(
|
|
702
|
+
this.debugLog(
|
|
703
|
+
"error",
|
|
704
|
+
"[config] Network error - request blocked. Check Content-Security-Policy connect-src directive includes https://www.featurely.no"
|
|
705
|
+
);
|
|
700
706
|
} else {
|
|
701
|
-
this.debugLog(
|
|
707
|
+
this.debugLog(
|
|
708
|
+
"error",
|
|
709
|
+
`[config] Failed to fetch configuration: ${error instanceof Error ? error.message : String(error)}`
|
|
710
|
+
);
|
|
702
711
|
}
|
|
703
712
|
if (this.config.onError && error instanceof Error) {
|
|
704
713
|
this.config.onError(error);
|
|
@@ -912,7 +921,10 @@ var _SiteManager = class _SiteManager {
|
|
|
912
921
|
this.debugOverlayEl = el;
|
|
913
922
|
this.setupGlobalErrorCapture();
|
|
914
923
|
this.debugLog("info", `[site-manager] debug overlay initialized`);
|
|
915
|
-
this.debugLog(
|
|
924
|
+
this.debugLog(
|
|
925
|
+
"info",
|
|
926
|
+
`[site-manager] v${SDK_VERSION} | project: ${this.config.projectId}`
|
|
927
|
+
);
|
|
916
928
|
this.renderDebugOverlay();
|
|
917
929
|
this.debugRefreshId = setInterval(() => this.renderDebugOverlay(), 1500);
|
|
918
930
|
}
|
|
@@ -1015,10 +1027,14 @@ var _SiteManager = class _SiteManager {
|
|
|
1015
1027
|
const details = [];
|
|
1016
1028
|
if (flag.rolloutPercentage !== void 0 && flag.rolloutPercentage < 100) {
|
|
1017
1029
|
const bucket = this.getUserBucket(flag.key);
|
|
1018
|
-
details.push(
|
|
1030
|
+
details.push(
|
|
1031
|
+
`Rollout: ${flag.rolloutPercentage}% (bucket: ${bucket.toFixed(0)})`
|
|
1032
|
+
);
|
|
1019
1033
|
}
|
|
1020
1034
|
if (flag.betaUsersOnly) {
|
|
1021
|
-
const isBeta = (_b2 = (_a2 = this.siteConfig) == null ? void 0 : _a2.betaUserEmails) == null ? void 0 : _b2.includes(
|
|
1035
|
+
const isBeta = (_b2 = (_a2 = this.siteConfig) == null ? void 0 : _a2.betaUserEmails) == null ? void 0 : _b2.includes(
|
|
1036
|
+
this.config.userEmail || ""
|
|
1037
|
+
);
|
|
1022
1038
|
details.push(`Beta only: ${isBeta ? "\u2713 enrolled" : "\u2717 not enrolled"}`);
|
|
1023
1039
|
}
|
|
1024
1040
|
if (flag.availableOnLocalhost) {
|
|
@@ -1026,15 +1042,21 @@ var _SiteManager = class _SiteManager {
|
|
|
1026
1042
|
details.push(`Localhost: ${isLocal ? "\u2713" : "\u2717"}`);
|
|
1027
1043
|
}
|
|
1028
1044
|
if (flag.targetEmails && flag.targetEmails.length > 0) {
|
|
1029
|
-
const isTargeted = flag.targetEmails.includes(
|
|
1045
|
+
const isTargeted = flag.targetEmails.includes(
|
|
1046
|
+
this.config.userEmail || ""
|
|
1047
|
+
);
|
|
1030
1048
|
details.push(`Email targeted: ${isTargeted ? "\u2713" : "\u2717"}`);
|
|
1031
1049
|
}
|
|
1032
1050
|
if (flag.excludeEmails && flag.excludeEmails.length > 0) {
|
|
1033
|
-
const isExcluded = flag.excludeEmails.includes(
|
|
1051
|
+
const isExcluded = flag.excludeEmails.includes(
|
|
1052
|
+
this.config.userEmail || ""
|
|
1053
|
+
);
|
|
1034
1054
|
details.push(`Excluded: ${isExcluded ? "\u2713" : "\u2717"}`);
|
|
1035
1055
|
}
|
|
1036
1056
|
if (flag.targetAttributes && flag.targetAttributes.length > 0) {
|
|
1037
|
-
details.push(
|
|
1057
|
+
details.push(
|
|
1058
|
+
`Custom attributes: ${flag.targetAttributes.length} rule(s)`
|
|
1059
|
+
);
|
|
1038
1060
|
}
|
|
1039
1061
|
if (flag.variants && flag.variants.length > 0) {
|
|
1040
1062
|
const variant = this.getFeatureVariant(flag.key);
|
|
@@ -1831,7 +1853,10 @@ var _SiteManager = class _SiteManager {
|
|
|
1831
1853
|
}
|
|
1832
1854
|
return versionInfo;
|
|
1833
1855
|
} catch (error) {
|
|
1834
|
-
this.debugLog(
|
|
1856
|
+
this.debugLog(
|
|
1857
|
+
"error",
|
|
1858
|
+
`[version-check] ${error instanceof Error ? error.message : String(error)}`
|
|
1859
|
+
);
|
|
1835
1860
|
if (this.config.onError) {
|
|
1836
1861
|
this.config.onError(
|
|
1837
1862
|
error instanceof Error ? error : new Error("Failed to check version")
|
|
@@ -1967,20 +1992,32 @@ var _SiteManager = class _SiteManager {
|
|
|
1967
1992
|
}
|
|
1968
1993
|
const userEmail = this.config.userEmail;
|
|
1969
1994
|
if (flag.excludeEmails && userEmail && flag.excludeEmails.includes(userEmail)) {
|
|
1970
|
-
this.debugLog(
|
|
1995
|
+
this.debugLog(
|
|
1996
|
+
"info",
|
|
1997
|
+
`[flag-eval] "${flag.key}": DISABLED (user ${userEmail} excluded)`
|
|
1998
|
+
);
|
|
1971
1999
|
return false;
|
|
1972
2000
|
}
|
|
1973
2001
|
if (flag.betaUsersOnly) {
|
|
1974
2002
|
if (!userEmail) {
|
|
1975
|
-
this.debugLog(
|
|
2003
|
+
this.debugLog(
|
|
2004
|
+
"info",
|
|
2005
|
+
`[flag-eval] "${flag.key}": DISABLED (beta-only, no email provided)`
|
|
2006
|
+
);
|
|
1976
2007
|
return false;
|
|
1977
2008
|
}
|
|
1978
2009
|
const betaUsers = ((_a = this.siteConfig) == null ? void 0 : _a.betaUserEmails) || [];
|
|
1979
2010
|
if (!betaUsers.includes(userEmail)) {
|
|
1980
|
-
this.debugLog(
|
|
2011
|
+
this.debugLog(
|
|
2012
|
+
"info",
|
|
2013
|
+
`[flag-eval] "${flag.key}": DISABLED (beta-only, ${userEmail} not in beta list)`
|
|
2014
|
+
);
|
|
1981
2015
|
return false;
|
|
1982
2016
|
}
|
|
1983
|
-
this.debugLog(
|
|
2017
|
+
this.debugLog(
|
|
2018
|
+
"info",
|
|
2019
|
+
`[flag-eval] "${flag.key}": beta check passed for ${userEmail}`
|
|
2020
|
+
);
|
|
1984
2021
|
}
|
|
1985
2022
|
if (flag.targetAttributes && flag.targetAttributes.length > 0) {
|
|
1986
2023
|
const attrs = (_b = this.config.customAttributes) != null ? _b : {};
|
|
@@ -2003,14 +2040,20 @@ var _SiteManager = class _SiteManager {
|
|
|
2003
2040
|
}
|
|
2004
2041
|
});
|
|
2005
2042
|
if (!allMatch) {
|
|
2006
|
-
this.debugLog(
|
|
2043
|
+
this.debugLog(
|
|
2044
|
+
"info",
|
|
2045
|
+
`[flag-eval] "${flag.key}": DISABLED (custom attribute rules not matched)`
|
|
2046
|
+
);
|
|
2007
2047
|
return false;
|
|
2008
2048
|
}
|
|
2009
2049
|
this.debugLog("info", `[flag-eval] "${flag.key}": custom attribute rules matched`);
|
|
2010
2050
|
}
|
|
2011
2051
|
if (flag.targetEmails && flag.targetEmails.length > 0) {
|
|
2012
2052
|
if (!userEmail || !flag.targetEmails.includes(userEmail)) {
|
|
2013
|
-
this.debugLog(
|
|
2053
|
+
this.debugLog(
|
|
2054
|
+
"info",
|
|
2055
|
+
`[flag-eval] "${flag.key}": DISABLED (not in targetEmails)`
|
|
2056
|
+
);
|
|
2014
2057
|
return false;
|
|
2015
2058
|
}
|
|
2016
2059
|
this.debugLog("info", `[flag-eval] "${flag.key}": ENABLED (user in targetEmails)`);
|
|
@@ -2019,7 +2062,10 @@ var _SiteManager = class _SiteManager {
|
|
|
2019
2062
|
if (flag.rolloutPercentage !== void 0 && flag.rolloutPercentage < 100) {
|
|
2020
2063
|
const bucket = this.getUserBucket(flag.key);
|
|
2021
2064
|
const enabled = bucket < flag.rolloutPercentage;
|
|
2022
|
-
this.debugLog(
|
|
2065
|
+
this.debugLog(
|
|
2066
|
+
"info",
|
|
2067
|
+
`[flag-eval] "${flag.key}": ${enabled ? "ENABLED" : "DISABLED"} (rollout ${flag.rolloutPercentage}%, bucket ${bucket})`
|
|
2068
|
+
);
|
|
2023
2069
|
return enabled;
|
|
2024
2070
|
}
|
|
2025
2071
|
this.debugLog("info", `[flag-eval] "${flag.key}": ENABLED (no restrictions)`);
|
package/dist/index.mjs
CHANGED
|
@@ -220,7 +220,10 @@ var _SiteManager = class _SiteManager {
|
|
|
220
220
|
return defaultValue;
|
|
221
221
|
}
|
|
222
222
|
const flag = this.siteConfig.featureFlags.find((f) => f.key === flagKey);
|
|
223
|
-
this.debugLog(
|
|
223
|
+
this.debugLog(
|
|
224
|
+
"info",
|
|
225
|
+
`[flag-eval] Checking "${flagKey}" - found: ${!!flag}, enabled: ${(flag == null ? void 0 : flag.enabled) || false}`
|
|
226
|
+
);
|
|
224
227
|
if (!flag || !flag.enabled) {
|
|
225
228
|
return defaultValue;
|
|
226
229
|
}
|
|
@@ -660,9 +663,15 @@ var _SiteManager = class _SiteManager {
|
|
|
660
663
|
if (this.consecutiveFetchFailures <= _SiteManager.MAX_CONSECUTIVE_FAILURES) {
|
|
661
664
|
const isNetworkError = error instanceof TypeError && (error.message.includes("NetworkError") || error.message.includes("Failed to fetch") || error.message.includes("fetch"));
|
|
662
665
|
if (isNetworkError) {
|
|
663
|
-
this.debugLog(
|
|
666
|
+
this.debugLog(
|
|
667
|
+
"error",
|
|
668
|
+
"[config] Network error - request blocked. Check Content-Security-Policy connect-src directive includes https://www.featurely.no"
|
|
669
|
+
);
|
|
664
670
|
} else {
|
|
665
|
-
this.debugLog(
|
|
671
|
+
this.debugLog(
|
|
672
|
+
"error",
|
|
673
|
+
`[config] Failed to fetch configuration: ${error instanceof Error ? error.message : String(error)}`
|
|
674
|
+
);
|
|
666
675
|
}
|
|
667
676
|
if (this.config.onError && error instanceof Error) {
|
|
668
677
|
this.config.onError(error);
|
|
@@ -876,7 +885,10 @@ var _SiteManager = class _SiteManager {
|
|
|
876
885
|
this.debugOverlayEl = el;
|
|
877
886
|
this.setupGlobalErrorCapture();
|
|
878
887
|
this.debugLog("info", `[site-manager] debug overlay initialized`);
|
|
879
|
-
this.debugLog(
|
|
888
|
+
this.debugLog(
|
|
889
|
+
"info",
|
|
890
|
+
`[site-manager] v${SDK_VERSION} | project: ${this.config.projectId}`
|
|
891
|
+
);
|
|
880
892
|
this.renderDebugOverlay();
|
|
881
893
|
this.debugRefreshId = setInterval(() => this.renderDebugOverlay(), 1500);
|
|
882
894
|
}
|
|
@@ -979,10 +991,14 @@ var _SiteManager = class _SiteManager {
|
|
|
979
991
|
const details = [];
|
|
980
992
|
if (flag.rolloutPercentage !== void 0 && flag.rolloutPercentage < 100) {
|
|
981
993
|
const bucket = this.getUserBucket(flag.key);
|
|
982
|
-
details.push(
|
|
994
|
+
details.push(
|
|
995
|
+
`Rollout: ${flag.rolloutPercentage}% (bucket: ${bucket.toFixed(0)})`
|
|
996
|
+
);
|
|
983
997
|
}
|
|
984
998
|
if (flag.betaUsersOnly) {
|
|
985
|
-
const isBeta = (_b2 = (_a2 = this.siteConfig) == null ? void 0 : _a2.betaUserEmails) == null ? void 0 : _b2.includes(
|
|
999
|
+
const isBeta = (_b2 = (_a2 = this.siteConfig) == null ? void 0 : _a2.betaUserEmails) == null ? void 0 : _b2.includes(
|
|
1000
|
+
this.config.userEmail || ""
|
|
1001
|
+
);
|
|
986
1002
|
details.push(`Beta only: ${isBeta ? "\u2713 enrolled" : "\u2717 not enrolled"}`);
|
|
987
1003
|
}
|
|
988
1004
|
if (flag.availableOnLocalhost) {
|
|
@@ -990,15 +1006,21 @@ var _SiteManager = class _SiteManager {
|
|
|
990
1006
|
details.push(`Localhost: ${isLocal ? "\u2713" : "\u2717"}`);
|
|
991
1007
|
}
|
|
992
1008
|
if (flag.targetEmails && flag.targetEmails.length > 0) {
|
|
993
|
-
const isTargeted = flag.targetEmails.includes(
|
|
1009
|
+
const isTargeted = flag.targetEmails.includes(
|
|
1010
|
+
this.config.userEmail || ""
|
|
1011
|
+
);
|
|
994
1012
|
details.push(`Email targeted: ${isTargeted ? "\u2713" : "\u2717"}`);
|
|
995
1013
|
}
|
|
996
1014
|
if (flag.excludeEmails && flag.excludeEmails.length > 0) {
|
|
997
|
-
const isExcluded = flag.excludeEmails.includes(
|
|
1015
|
+
const isExcluded = flag.excludeEmails.includes(
|
|
1016
|
+
this.config.userEmail || ""
|
|
1017
|
+
);
|
|
998
1018
|
details.push(`Excluded: ${isExcluded ? "\u2713" : "\u2717"}`);
|
|
999
1019
|
}
|
|
1000
1020
|
if (flag.targetAttributes && flag.targetAttributes.length > 0) {
|
|
1001
|
-
details.push(
|
|
1021
|
+
details.push(
|
|
1022
|
+
`Custom attributes: ${flag.targetAttributes.length} rule(s)`
|
|
1023
|
+
);
|
|
1002
1024
|
}
|
|
1003
1025
|
if (flag.variants && flag.variants.length > 0) {
|
|
1004
1026
|
const variant = this.getFeatureVariant(flag.key);
|
|
@@ -1795,7 +1817,10 @@ var _SiteManager = class _SiteManager {
|
|
|
1795
1817
|
}
|
|
1796
1818
|
return versionInfo;
|
|
1797
1819
|
} catch (error) {
|
|
1798
|
-
this.debugLog(
|
|
1820
|
+
this.debugLog(
|
|
1821
|
+
"error",
|
|
1822
|
+
`[version-check] ${error instanceof Error ? error.message : String(error)}`
|
|
1823
|
+
);
|
|
1799
1824
|
if (this.config.onError) {
|
|
1800
1825
|
this.config.onError(
|
|
1801
1826
|
error instanceof Error ? error : new Error("Failed to check version")
|
|
@@ -1931,20 +1956,32 @@ var _SiteManager = class _SiteManager {
|
|
|
1931
1956
|
}
|
|
1932
1957
|
const userEmail = this.config.userEmail;
|
|
1933
1958
|
if (flag.excludeEmails && userEmail && flag.excludeEmails.includes(userEmail)) {
|
|
1934
|
-
this.debugLog(
|
|
1959
|
+
this.debugLog(
|
|
1960
|
+
"info",
|
|
1961
|
+
`[flag-eval] "${flag.key}": DISABLED (user ${userEmail} excluded)`
|
|
1962
|
+
);
|
|
1935
1963
|
return false;
|
|
1936
1964
|
}
|
|
1937
1965
|
if (flag.betaUsersOnly) {
|
|
1938
1966
|
if (!userEmail) {
|
|
1939
|
-
this.debugLog(
|
|
1967
|
+
this.debugLog(
|
|
1968
|
+
"info",
|
|
1969
|
+
`[flag-eval] "${flag.key}": DISABLED (beta-only, no email provided)`
|
|
1970
|
+
);
|
|
1940
1971
|
return false;
|
|
1941
1972
|
}
|
|
1942
1973
|
const betaUsers = ((_a = this.siteConfig) == null ? void 0 : _a.betaUserEmails) || [];
|
|
1943
1974
|
if (!betaUsers.includes(userEmail)) {
|
|
1944
|
-
this.debugLog(
|
|
1975
|
+
this.debugLog(
|
|
1976
|
+
"info",
|
|
1977
|
+
`[flag-eval] "${flag.key}": DISABLED (beta-only, ${userEmail} not in beta list)`
|
|
1978
|
+
);
|
|
1945
1979
|
return false;
|
|
1946
1980
|
}
|
|
1947
|
-
this.debugLog(
|
|
1981
|
+
this.debugLog(
|
|
1982
|
+
"info",
|
|
1983
|
+
`[flag-eval] "${flag.key}": beta check passed for ${userEmail}`
|
|
1984
|
+
);
|
|
1948
1985
|
}
|
|
1949
1986
|
if (flag.targetAttributes && flag.targetAttributes.length > 0) {
|
|
1950
1987
|
const attrs = (_b = this.config.customAttributes) != null ? _b : {};
|
|
@@ -1967,14 +2004,20 @@ var _SiteManager = class _SiteManager {
|
|
|
1967
2004
|
}
|
|
1968
2005
|
});
|
|
1969
2006
|
if (!allMatch) {
|
|
1970
|
-
this.debugLog(
|
|
2007
|
+
this.debugLog(
|
|
2008
|
+
"info",
|
|
2009
|
+
`[flag-eval] "${flag.key}": DISABLED (custom attribute rules not matched)`
|
|
2010
|
+
);
|
|
1971
2011
|
return false;
|
|
1972
2012
|
}
|
|
1973
2013
|
this.debugLog("info", `[flag-eval] "${flag.key}": custom attribute rules matched`);
|
|
1974
2014
|
}
|
|
1975
2015
|
if (flag.targetEmails && flag.targetEmails.length > 0) {
|
|
1976
2016
|
if (!userEmail || !flag.targetEmails.includes(userEmail)) {
|
|
1977
|
-
this.debugLog(
|
|
2017
|
+
this.debugLog(
|
|
2018
|
+
"info",
|
|
2019
|
+
`[flag-eval] "${flag.key}": DISABLED (not in targetEmails)`
|
|
2020
|
+
);
|
|
1978
2021
|
return false;
|
|
1979
2022
|
}
|
|
1980
2023
|
this.debugLog("info", `[flag-eval] "${flag.key}": ENABLED (user in targetEmails)`);
|
|
@@ -1983,7 +2026,10 @@ var _SiteManager = class _SiteManager {
|
|
|
1983
2026
|
if (flag.rolloutPercentage !== void 0 && flag.rolloutPercentage < 100) {
|
|
1984
2027
|
const bucket = this.getUserBucket(flag.key);
|
|
1985
2028
|
const enabled = bucket < flag.rolloutPercentage;
|
|
1986
|
-
this.debugLog(
|
|
2029
|
+
this.debugLog(
|
|
2030
|
+
"info",
|
|
2031
|
+
`[flag-eval] "${flag.key}": ${enabled ? "ENABLED" : "DISABLED"} (rollout ${flag.rolloutPercentage}%, bucket ${bucket})`
|
|
2032
|
+
);
|
|
1987
2033
|
return enabled;
|
|
1988
2034
|
}
|
|
1989
2035
|
this.debugLog("info", `[flag-eval] "${flag.key}": ENABLED (no restrictions)`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "featurely-site-manager",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "Complete site management SDK for maintenance mode, status messages, feature flags, version checking, and analytics",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -65,7 +65,8 @@
|
|
|
65
65
|
"dompurify": "^3.3.3",
|
|
66
66
|
"featurely-error-tracker": "^1.0.23",
|
|
67
67
|
"featurely-mcp": "^1.0.6",
|
|
68
|
-
"featurely-site-manager": "^1.3.
|
|
69
|
-
"jose": "^6.2.3"
|
|
68
|
+
"featurely-site-manager": "^1.3.3",
|
|
69
|
+
"jose": "^6.2.3",
|
|
70
|
+
"rrweb": "^1.1.3"
|
|
70
71
|
}
|
|
71
72
|
}
|