featurely-site-manager 1.3.2 → 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.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- declare const SDK_VERSION = "1.3.2";
1
+ declare const SDK_VERSION = "1.3.3";
2
2
  type MessageType = "info" | "warning" | "error" | "success";
3
3
  type MessagePosition = "top" | "bottom";
4
4
  type MessageStyle = "banner" | "toast";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- declare const SDK_VERSION = "1.3.2";
1
+ declare const SDK_VERSION = "1.3.3";
2
2
  type MessageType = "info" | "warning" | "error" | "success";
3
3
  type MessagePosition = "top" | "bottom";
4
4
  type MessageStyle = "banner" | "toast";
package/dist/index.js CHANGED
@@ -36,7 +36,7 @@ __export(index_exports, {
36
36
  });
37
37
  module.exports = __toCommonJS(index_exports);
38
38
  var import_dompurify = __toESM(require("dompurify"));
39
- var SDK_VERSION = "1.3.2";
39
+ var SDK_VERSION = "1.3.3";
40
40
  var _SiteManager = class _SiteManager {
41
41
  constructor(config) {
42
42
  this.siteConfig = null;
@@ -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("info", `[flag-eval] Checking "${flagKey}" - found: ${!!flag}, enabled: ${(flag == null ? void 0 : flag.enabled) || false}`);
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("error", "[config] Network error - request blocked. Check Content-Security-Policy connect-src directive includes https://www.featurely.no");
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("error", `[config] Failed to fetch configuration: ${error instanceof Error ? error.message : String(error)}`);
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("info", `[site-manager] v${SDK_VERSION} | project: ${this.config.projectId}`);
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(`Rollout: ${flag.rolloutPercentage}% (bucket: ${bucket.toFixed(0)})`);
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(this.config.userEmail || "");
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(this.config.userEmail || "");
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(this.config.userEmail || "");
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(`Custom attributes: ${flag.targetAttributes.length} rule(s)`);
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);
@@ -1109,10 +1131,12 @@ var _SiteManager = class _SiteManager {
1109
1131
  </div>
1110
1132
  ${minimized ? "" : `<div id="__ft_dbg_content__" style="padding:8px 10px;max-height:300px;overflow-y:auto">${content}</div>`}
1111
1133
  `;
1112
- if (!minimized) {
1134
+ if (!minimized && scrollTop > 0) {
1113
1135
  const newContentContainer = el.querySelector("#__ft_dbg_content__");
1114
1136
  if (newContentContainer) {
1115
- newContentContainer.scrollTop = scrollTop;
1137
+ requestAnimationFrame(() => {
1138
+ newContentContainer.scrollTop = scrollTop;
1139
+ });
1116
1140
  }
1117
1141
  }
1118
1142
  el.querySelectorAll("[data-tab]").forEach((btn) => {
@@ -1829,7 +1853,10 @@ var _SiteManager = class _SiteManager {
1829
1853
  }
1830
1854
  return versionInfo;
1831
1855
  } catch (error) {
1832
- this.debugLog("error", `[version-check] ${error instanceof Error ? error.message : String(error)}`);
1856
+ this.debugLog(
1857
+ "error",
1858
+ `[version-check] ${error instanceof Error ? error.message : String(error)}`
1859
+ );
1833
1860
  if (this.config.onError) {
1834
1861
  this.config.onError(
1835
1862
  error instanceof Error ? error : new Error("Failed to check version")
@@ -1965,20 +1992,32 @@ var _SiteManager = class _SiteManager {
1965
1992
  }
1966
1993
  const userEmail = this.config.userEmail;
1967
1994
  if (flag.excludeEmails && userEmail && flag.excludeEmails.includes(userEmail)) {
1968
- this.debugLog("info", `[flag-eval] "${flag.key}": DISABLED (user ${userEmail} excluded)`);
1995
+ this.debugLog(
1996
+ "info",
1997
+ `[flag-eval] "${flag.key}": DISABLED (user ${userEmail} excluded)`
1998
+ );
1969
1999
  return false;
1970
2000
  }
1971
2001
  if (flag.betaUsersOnly) {
1972
2002
  if (!userEmail) {
1973
- this.debugLog("info", `[flag-eval] "${flag.key}": DISABLED (beta-only, no email provided)`);
2003
+ this.debugLog(
2004
+ "info",
2005
+ `[flag-eval] "${flag.key}": DISABLED (beta-only, no email provided)`
2006
+ );
1974
2007
  return false;
1975
2008
  }
1976
2009
  const betaUsers = ((_a = this.siteConfig) == null ? void 0 : _a.betaUserEmails) || [];
1977
2010
  if (!betaUsers.includes(userEmail)) {
1978
- this.debugLog("info", `[flag-eval] "${flag.key}": DISABLED (beta-only, ${userEmail} not in beta list)`);
2011
+ this.debugLog(
2012
+ "info",
2013
+ `[flag-eval] "${flag.key}": DISABLED (beta-only, ${userEmail} not in beta list)`
2014
+ );
1979
2015
  return false;
1980
2016
  }
1981
- this.debugLog("info", `[flag-eval] "${flag.key}": beta check passed for ${userEmail}`);
2017
+ this.debugLog(
2018
+ "info",
2019
+ `[flag-eval] "${flag.key}": beta check passed for ${userEmail}`
2020
+ );
1982
2021
  }
1983
2022
  if (flag.targetAttributes && flag.targetAttributes.length > 0) {
1984
2023
  const attrs = (_b = this.config.customAttributes) != null ? _b : {};
@@ -2001,14 +2040,20 @@ var _SiteManager = class _SiteManager {
2001
2040
  }
2002
2041
  });
2003
2042
  if (!allMatch) {
2004
- this.debugLog("info", `[flag-eval] "${flag.key}": DISABLED (custom attribute rules not matched)`);
2043
+ this.debugLog(
2044
+ "info",
2045
+ `[flag-eval] "${flag.key}": DISABLED (custom attribute rules not matched)`
2046
+ );
2005
2047
  return false;
2006
2048
  }
2007
2049
  this.debugLog("info", `[flag-eval] "${flag.key}": custom attribute rules matched`);
2008
2050
  }
2009
2051
  if (flag.targetEmails && flag.targetEmails.length > 0) {
2010
2052
  if (!userEmail || !flag.targetEmails.includes(userEmail)) {
2011
- this.debugLog("info", `[flag-eval] "${flag.key}": DISABLED (not in targetEmails)`);
2053
+ this.debugLog(
2054
+ "info",
2055
+ `[flag-eval] "${flag.key}": DISABLED (not in targetEmails)`
2056
+ );
2012
2057
  return false;
2013
2058
  }
2014
2059
  this.debugLog("info", `[flag-eval] "${flag.key}": ENABLED (user in targetEmails)`);
@@ -2017,7 +2062,10 @@ var _SiteManager = class _SiteManager {
2017
2062
  if (flag.rolloutPercentage !== void 0 && flag.rolloutPercentage < 100) {
2018
2063
  const bucket = this.getUserBucket(flag.key);
2019
2064
  const enabled = bucket < flag.rolloutPercentage;
2020
- this.debugLog("info", `[flag-eval] "${flag.key}": ${enabled ? "ENABLED" : "DISABLED"} (rollout ${flag.rolloutPercentage}%, bucket ${bucket})`);
2065
+ this.debugLog(
2066
+ "info",
2067
+ `[flag-eval] "${flag.key}": ${enabled ? "ENABLED" : "DISABLED"} (rollout ${flag.rolloutPercentage}%, bucket ${bucket})`
2068
+ );
2021
2069
  return enabled;
2022
2070
  }
2023
2071
  this.debugLog("info", `[flag-eval] "${flag.key}": ENABLED (no restrictions)`);
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/index.ts
2
2
  import DOMPurify from "dompurify";
3
- var SDK_VERSION = "1.3.2";
3
+ var SDK_VERSION = "1.3.3";
4
4
  var _SiteManager = class _SiteManager {
5
5
  constructor(config) {
6
6
  this.siteConfig = null;
@@ -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("info", `[flag-eval] Checking "${flagKey}" - found: ${!!flag}, enabled: ${(flag == null ? void 0 : flag.enabled) || false}`);
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("error", "[config] Network error - request blocked. Check Content-Security-Policy connect-src directive includes https://www.featurely.no");
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("error", `[config] Failed to fetch configuration: ${error instanceof Error ? error.message : String(error)}`);
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("info", `[site-manager] v${SDK_VERSION} | project: ${this.config.projectId}`);
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(`Rollout: ${flag.rolloutPercentage}% (bucket: ${bucket.toFixed(0)})`);
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(this.config.userEmail || "");
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(this.config.userEmail || "");
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(this.config.userEmail || "");
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(`Custom attributes: ${flag.targetAttributes.length} rule(s)`);
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);
@@ -1073,10 +1095,12 @@ var _SiteManager = class _SiteManager {
1073
1095
  </div>
1074
1096
  ${minimized ? "" : `<div id="__ft_dbg_content__" style="padding:8px 10px;max-height:300px;overflow-y:auto">${content}</div>`}
1075
1097
  `;
1076
- if (!minimized) {
1098
+ if (!minimized && scrollTop > 0) {
1077
1099
  const newContentContainer = el.querySelector("#__ft_dbg_content__");
1078
1100
  if (newContentContainer) {
1079
- newContentContainer.scrollTop = scrollTop;
1101
+ requestAnimationFrame(() => {
1102
+ newContentContainer.scrollTop = scrollTop;
1103
+ });
1080
1104
  }
1081
1105
  }
1082
1106
  el.querySelectorAll("[data-tab]").forEach((btn) => {
@@ -1793,7 +1817,10 @@ var _SiteManager = class _SiteManager {
1793
1817
  }
1794
1818
  return versionInfo;
1795
1819
  } catch (error) {
1796
- this.debugLog("error", `[version-check] ${error instanceof Error ? error.message : String(error)}`);
1820
+ this.debugLog(
1821
+ "error",
1822
+ `[version-check] ${error instanceof Error ? error.message : String(error)}`
1823
+ );
1797
1824
  if (this.config.onError) {
1798
1825
  this.config.onError(
1799
1826
  error instanceof Error ? error : new Error("Failed to check version")
@@ -1929,20 +1956,32 @@ var _SiteManager = class _SiteManager {
1929
1956
  }
1930
1957
  const userEmail = this.config.userEmail;
1931
1958
  if (flag.excludeEmails && userEmail && flag.excludeEmails.includes(userEmail)) {
1932
- this.debugLog("info", `[flag-eval] "${flag.key}": DISABLED (user ${userEmail} excluded)`);
1959
+ this.debugLog(
1960
+ "info",
1961
+ `[flag-eval] "${flag.key}": DISABLED (user ${userEmail} excluded)`
1962
+ );
1933
1963
  return false;
1934
1964
  }
1935
1965
  if (flag.betaUsersOnly) {
1936
1966
  if (!userEmail) {
1937
- this.debugLog("info", `[flag-eval] "${flag.key}": DISABLED (beta-only, no email provided)`);
1967
+ this.debugLog(
1968
+ "info",
1969
+ `[flag-eval] "${flag.key}": DISABLED (beta-only, no email provided)`
1970
+ );
1938
1971
  return false;
1939
1972
  }
1940
1973
  const betaUsers = ((_a = this.siteConfig) == null ? void 0 : _a.betaUserEmails) || [];
1941
1974
  if (!betaUsers.includes(userEmail)) {
1942
- this.debugLog("info", `[flag-eval] "${flag.key}": DISABLED (beta-only, ${userEmail} not in beta list)`);
1975
+ this.debugLog(
1976
+ "info",
1977
+ `[flag-eval] "${flag.key}": DISABLED (beta-only, ${userEmail} not in beta list)`
1978
+ );
1943
1979
  return false;
1944
1980
  }
1945
- this.debugLog("info", `[flag-eval] "${flag.key}": beta check passed for ${userEmail}`);
1981
+ this.debugLog(
1982
+ "info",
1983
+ `[flag-eval] "${flag.key}": beta check passed for ${userEmail}`
1984
+ );
1946
1985
  }
1947
1986
  if (flag.targetAttributes && flag.targetAttributes.length > 0) {
1948
1987
  const attrs = (_b = this.config.customAttributes) != null ? _b : {};
@@ -1965,14 +2004,20 @@ var _SiteManager = class _SiteManager {
1965
2004
  }
1966
2005
  });
1967
2006
  if (!allMatch) {
1968
- this.debugLog("info", `[flag-eval] "${flag.key}": DISABLED (custom attribute rules not matched)`);
2007
+ this.debugLog(
2008
+ "info",
2009
+ `[flag-eval] "${flag.key}": DISABLED (custom attribute rules not matched)`
2010
+ );
1969
2011
  return false;
1970
2012
  }
1971
2013
  this.debugLog("info", `[flag-eval] "${flag.key}": custom attribute rules matched`);
1972
2014
  }
1973
2015
  if (flag.targetEmails && flag.targetEmails.length > 0) {
1974
2016
  if (!userEmail || !flag.targetEmails.includes(userEmail)) {
1975
- this.debugLog("info", `[flag-eval] "${flag.key}": DISABLED (not in targetEmails)`);
2017
+ this.debugLog(
2018
+ "info",
2019
+ `[flag-eval] "${flag.key}": DISABLED (not in targetEmails)`
2020
+ );
1976
2021
  return false;
1977
2022
  }
1978
2023
  this.debugLog("info", `[flag-eval] "${flag.key}": ENABLED (user in targetEmails)`);
@@ -1981,7 +2026,10 @@ var _SiteManager = class _SiteManager {
1981
2026
  if (flag.rolloutPercentage !== void 0 && flag.rolloutPercentage < 100) {
1982
2027
  const bucket = this.getUserBucket(flag.key);
1983
2028
  const enabled = bucket < flag.rolloutPercentage;
1984
- this.debugLog("info", `[flag-eval] "${flag.key}": ${enabled ? "ENABLED" : "DISABLED"} (rollout ${flag.rolloutPercentage}%, bucket ${bucket})`);
2029
+ this.debugLog(
2030
+ "info",
2031
+ `[flag-eval] "${flag.key}": ${enabled ? "ENABLED" : "DISABLED"} (rollout ${flag.rolloutPercentage}%, bucket ${bucket})`
2032
+ );
1985
2033
  return enabled;
1986
2034
  }
1987
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.2",
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",
@@ -57,8 +57,16 @@
57
57
  "typescript": "^5.0.0"
58
58
  },
59
59
  "dependencies": {
60
+ "@tiptap/core": "^3.22.5",
61
+ "@tiptap/extension-link": "^3.22.5",
62
+ "@tiptap/extension-placeholder": "^3.22.5",
63
+ "@tiptap/react": "^3.22.5",
64
+ "@tiptap/starter-kit": "^3.22.5",
60
65
  "dompurify": "^3.3.3",
61
66
  "featurely-error-tracker": "^1.0.23",
62
- "featurely-mcp": "^1.0.6"
67
+ "featurely-mcp": "^1.0.6",
68
+ "featurely-site-manager": "^1.3.3",
69
+ "jose": "^6.2.3",
70
+ "rrweb": "^1.1.3"
63
71
  }
64
72
  }