expf-sigma-node.js 3.3.6 → 3.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/public/sigma.js +164 -89
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expf-sigma-node.js",
3
- "version": "3.3.6",
3
+ "version": "3.4.1",
4
4
  "description": "expf-sigma-node.js lets you manage features flags and remote config across web, server side applications. Deliver true Continuous Integration. Get builds out faster. Control who has access to new features.",
5
5
  "main": "public/sigma.js",
6
6
  "keywords": [
package/public/sigma.js CHANGED
@@ -918,25 +918,28 @@ var sigmaHashes_default = Hashes;
918
918
 
919
919
  // src/helpers/constants.js
920
920
  var defaultApi = "https://api.expf.ru/api/v1";
921
- var sigmaUserId = "sigmaUserId";
922
- var sigmaProfileId = "sigmaProfileId";
923
- var sigmaDeviceId = "sigmaDeviceId";
924
921
  var sigmaPrivateId = "sigmaPrivateId";
925
922
  var sigmaHash = "sigmaHash";
926
923
  var sigmaDataFileLastUpdate = "sigmaDataFileLastUpdate";
927
- var sigmaExpiration = "sigmaExpiration";
928
924
  var sigmaDataFile = "sigmaDataFile";
929
925
  var sigmaExperiments = "sigmaExperiments";
926
+ var sigmaHoldouts = "sigmaHoldouts";
927
+ var sigmaGeoData = "sigmaGeoData";
930
928
  var max_decimal_64 = 18446744073709552e3;
931
929
  var zeta = 8540717056e4;
932
930
  var SHA256 = new sigmaHashes_default.SHA256();
933
931
  var MD5 = new sigmaHashes_default.MD5();
934
- var expirationDate = 24 * 60 * 60 * 1e3;
935
932
  var secondsIn24Hours = 24 * 60 * 60;
936
- var sigmaGeoData = "sigmaGeoData";
937
933
  var defaultGeoCacheTTL = 5 * 60;
938
934
  var cacheStandardTimeToLive = 3600;
939
935
  var cacheCheckPeriod = 600;
936
+ var experimentType = {
937
+ featureFlag: 1,
938
+ param: 2,
939
+ splitUrl: 3,
940
+ webBuilder: 4,
941
+ holdout: 5
942
+ };
940
943
  var errorMessages = {
941
944
  emptyToken: "Please specify a token",
942
945
  APIRequestErrorConfig: {
@@ -958,9 +961,10 @@ var errorMessages = {
958
961
  };
959
962
  var signsForHash = ["equal", "not equal", "any of", "none of"];
960
963
  var prefixGroup = "sigma_group";
961
- var errorTypesInConfig = {
962
- invalidJson: 'Sigma warning. Invalid type json "%value%" in config.',
963
- invalidType: 'Sigma warning. Invalid type "%type%" in config.'
964
+ var warnings = {
965
+ invalidJson: 'Sigma warning: Invalid type json "%value%" in config.',
966
+ invalidType: 'Sigma warning: Invalid type "%type%" in config.',
967
+ emptyHoldoutId: "Sigma warning: Empty holdout id"
964
968
  };
965
969
  var sdkName = "node.js";
966
970
  var statusSuccess = "success";
@@ -1183,7 +1187,7 @@ function doTypeConversion(type, value) {
1183
1187
  return JSON.parse("{}");
1184
1188
  return JSON.parse(value);
1185
1189
  } catch (e) {
1186
- console.error(errorTypesInConfig.invalidJson.replace("%value%", value), e);
1190
+ console.error(warnings.invalidJson.replace("%value%", value), e);
1187
1191
  return null;
1188
1192
  }
1189
1193
  default:
@@ -1262,7 +1266,7 @@ function generateFilteredList(array, name) {
1262
1266
  }
1263
1267
 
1264
1268
  // package.json
1265
- var version = "3.3.6";
1269
+ var version = "3.4.1";
1266
1270
 
1267
1271
  // src/helpers/sdkVersion.js
1268
1272
  var sdkVersion = version;
@@ -1337,28 +1341,9 @@ var Sigma = class {
1337
1341
  pathname: this.userData.pathname || null,
1338
1342
  ua: this.userData.ua || void 0
1339
1343
  });
1340
- this.setSplitIdsToCache(this.userData);
1341
1344
  this.makePrivateIdInCache();
1342
1345
  this.geoCache = new SigmaGeoCache(`${this.cache.get(sigmaPrivateId)}__${this.token}`);
1343
1346
  }
1344
- setSplitIdsToCache(userData) {
1345
- for (let [key, value] of Object.entries(userData)) {
1346
- if (!value || !String(value).trim().length)
1347
- continue;
1348
- switch (key) {
1349
- case "userId":
1350
- this.cache.set(sigmaUserId, String(value).trim());
1351
- this.cache.set(sigmaExpiration, new Date().getTime() + expirationDate);
1352
- break;
1353
- case "profileId":
1354
- this.cache.set(sigmaProfileId, String(value).trim());
1355
- break;
1356
- case "deviceId":
1357
- this.cache.set(sigmaDeviceId, String(value).trim());
1358
- break;
1359
- }
1360
- }
1361
- }
1362
1347
  makePrivateIdInCache() {
1363
1348
  if (!this.cache.get(sigmaPrivateId)) {
1364
1349
  this.cache.set(sigmaPrivateId, generateRandomId());
@@ -1483,11 +1468,10 @@ var Sigma = class {
1483
1468
  if (!this.cache.get(sigmaDataFile) || this.hasExpireCache()) {
1484
1469
  return this.saveToCache();
1485
1470
  }
1486
- return true;
1487
1471
  }
1488
1472
  updateGeoCache() {
1489
1473
  if (!this.geoCache.get(sigmaGeoData)) {
1490
- this.saveToGeoCache();
1474
+ return this.saveToGeoCache();
1491
1475
  }
1492
1476
  }
1493
1477
  async getFlags() {
@@ -1627,19 +1611,15 @@ var Sigma = class {
1627
1611
  }
1628
1612
  switchSplitById(splitBy) {
1629
1613
  let id = null;
1630
- const cacheSigmaExpiration = this.cache.get(sigmaExpiration);
1631
1614
  switch (splitBy) {
1632
1615
  case "userId":
1633
- id = this.cache.get(sigmaUserId) || null;
1634
- if (typeof cacheSigmaExpiration !== "undefined" && new Date().getTime() >= Number(cacheSigmaExpiration)) {
1635
- id = null;
1636
- }
1616
+ id = this.userData.userId ? String(this.userData.userId).trim() : null;
1637
1617
  break;
1638
1618
  case "profileId":
1639
- id = this.cache.get(sigmaProfileId) || null;
1619
+ id = this.userData.profileId ? String(this.userData.profileId).trim() : null;
1640
1620
  break;
1641
1621
  case "deviceId":
1642
- id = this.cache.get(sigmaDeviceId) || null;
1622
+ id = this.userData.deviceId ? String(this.userData.deviceId).trim() : null;
1643
1623
  break;
1644
1624
  }
1645
1625
  return id;
@@ -1705,20 +1685,31 @@ var Sigma = class {
1705
1685
  let groupIndex = null;
1706
1686
  let forcedUser = false;
1707
1687
  let splitById = null;
1688
+ let userInHoldout = false;
1708
1689
  for (let i = 0; i < sigmaDataLs.experiments.length; i++) {
1709
- if (sigmaDataLs.experiments[i]["name"] === experimentName && checkBoolValue(sigmaDataLs.experiments[i]["layer_id"])) {
1710
- layer = sigmaDataLs.experiments[i]["layer_id"];
1711
- bounds = sigmaDataLs.experiments[i]["layer_bounds"];
1712
- }
1713
- if (sigmaDataLs.experiments[i]["name"] === experimentName && !experiment) {
1714
- splitById = this.getSplitById(sigmaDataLs.experiments[i]);
1715
- forcedUser = checkForcedList(sigmaDataLs.experiments[i].forced_user_list, splitById);
1716
- groupName = this.findUserInForcedGroup(sigmaDataLs.experiments[i]);
1717
- experiment = this.experimentDefinition(sigmaDataLs.experiments[i], groupName, forcedUser);
1690
+ const experimentIndex = sigmaDataLs.experiments[i];
1691
+ if (experimentIndex["name"] === experimentName && checkBoolValue(experimentIndex["layer_id"])) {
1692
+ layer = experimentIndex["layer_id"];
1693
+ bounds = experimentIndex["layer_bounds"];
1694
+ }
1695
+ if (experimentIndex["name"] === experimentName) {
1696
+ splitById = this.getSplitById(experimentIndex);
1697
+ forcedUser = checkForcedList(experimentIndex.forced_user_list, splitById);
1698
+ groupName = this.findUserInForcedGroup(experimentIndex);
1699
+ experiment = this.experimentDefinition(experimentIndex, groupName, forcedUser);
1700
+ if (experimentIndex.holdouts && experimentIndex.holdouts.length) {
1701
+ for (const holdoutName of experimentIndex.holdouts) {
1702
+ userInHoldout = await this.getHoldout(holdoutName);
1703
+ if (userInHoldout)
1704
+ break;
1705
+ }
1706
+ }
1718
1707
  break;
1719
1708
  }
1720
1709
  }
1721
1710
  const localStorageGroupName = `${prefixGroup}_${experimentName}`;
1711
+ if (this.cache.get(localStorageGroupName))
1712
+ this.cache.remove(localStorageGroupName);
1722
1713
  if (experiment) {
1723
1714
  if (!groupName) {
1724
1715
  groupName = this.calcUserInGroup(
@@ -1731,11 +1722,18 @@ var Sigma = class {
1731
1722
  splitById
1732
1723
  );
1733
1724
  }
1734
- this.cache.set(localStorageGroupName, groupName);
1735
- groupIndex = experiment.groups.findIndex((i) => i.name == groupName);
1725
+ if (experiment.type === experimentType.holdout) {
1726
+ if (groupName)
1727
+ this.cache.set(localStorageGroupName, groupName);
1728
+ return groupName;
1729
+ }
1730
+ if (!userInHoldout) {
1731
+ this.cache.set(localStorageGroupName, groupName);
1732
+ groupIndex = experiment.groups.findIndex((i) => i.name == groupName);
1733
+ }
1736
1734
  }
1737
1735
  const getParamValue = (paramName) => {
1738
- if (!paramName || !experiment) {
1736
+ if (!paramName || !experiment || userInHoldout) {
1739
1737
  return null;
1740
1738
  }
1741
1739
  const groupName2 = this.cache.get(localStorageGroupName);
@@ -1758,7 +1756,7 @@ var Sigma = class {
1758
1756
  return paramValue;
1759
1757
  };
1760
1758
  const getFeatureValue = (flagName) => {
1761
- if (!flagName || !experiment) {
1759
+ if (!flagName || !experiment || userInHoldout) {
1762
1760
  return null;
1763
1761
  }
1764
1762
  const groupName2 = this.cache.get(localStorageGroupName);
@@ -1786,10 +1784,11 @@ var Sigma = class {
1786
1784
  return {
1787
1785
  getParamValue,
1788
1786
  getFeatureValue,
1789
- groupIndex: groupIndex < 0 ? null : groupIndex
1787
+ groupIndex: groupIndex < 0 ? null : groupIndex,
1788
+ userInHoldout
1790
1789
  };
1791
1790
  }
1792
- async getAllUserExperiments() {
1791
+ async getAllUserExperiments(estimateHoldouts = true) {
1793
1792
  await this.updateCache();
1794
1793
  await this.updateGeoCache();
1795
1794
  const sigmaDataLs = this.cache.parse(sigmaDataFile);
@@ -1797,33 +1796,70 @@ var Sigma = class {
1797
1796
  return null;
1798
1797
  let result = "";
1799
1798
  for (let i in sigmaDataLs.experiments) {
1799
+ if (!estimateHoldouts && sigmaDataLs.experiments[i].type === experimentType.holdout)
1800
+ continue;
1800
1801
  let layer = null;
1801
1802
  let bounds = [];
1802
1803
  let splitById = this.getSplitById(sigmaDataLs.experiments[i]);
1803
1804
  let forcedUser = checkForcedList(sigmaDataLs.experiments[i].forced_user_list, splitById);
1804
1805
  let userInGroupExperiment = this.findUserInForcedGroup(sigmaDataLs.experiments[i]);
1805
1806
  let experiment = this.experimentDefinition(sigmaDataLs.experiments[i], userInGroupExperiment, forcedUser);
1806
- if (experiment) {
1807
- if (checkBoolValue(experiment["layer_id"]) && !userInGroupExperiment) {
1808
- layer = experiment["layer_id"];
1809
- bounds = experiment["layer_bounds"];
1810
- }
1811
- if (!userInGroupExperiment) {
1812
- userInGroupExperiment = this.calcUserInGroup(
1813
- experiment.salt,
1814
- experiment.allocation,
1815
- experiment.groups,
1816
- forcedUser,
1817
- layer,
1818
- bounds,
1819
- splitById
1807
+ let userInHoldout;
1808
+ if (!experiment)
1809
+ continue;
1810
+ if (checkBoolValue(experiment["layer_id"]) && !userInGroupExperiment) {
1811
+ layer = experiment["layer_id"];
1812
+ bounds = experiment["layer_bounds"];
1813
+ }
1814
+ if (!userInGroupExperiment) {
1815
+ userInGroupExperiment = this.calcUserInGroup(
1816
+ experiment.salt,
1817
+ experiment.allocation,
1818
+ experiment.groups,
1819
+ forcedUser,
1820
+ layer,
1821
+ bounds,
1822
+ splitById
1823
+ );
1824
+ }
1825
+ if (!userInGroupExperiment)
1826
+ continue;
1827
+ if (sigmaDataLs.experiments[i].holdouts && sigmaDataLs.experiments[i].holdouts.length > 0) {
1828
+ for (const holdout of sigmaDataLs.experiments[i].holdouts) {
1829
+ const foundingExperimentHoldout = sigmaDataLs.experiments.find((exp) => exp.name === holdout);
1830
+ if (!foundingExperimentHoldout)
1831
+ break;
1832
+ const splitByHoldoutId = this.getSplitById(foundingExperimentHoldout);
1833
+ if (!splitByHoldoutId)
1834
+ continue;
1835
+ const holdoutForcedUser = checkForcedList(foundingExperimentHoldout.forced_user_list, splitByHoldoutId);
1836
+ let userInGroupHoldout = this.findUserInForcedGroup(foundingExperimentHoldout);
1837
+ if (userInGroupHoldout) {
1838
+ userInHoldout = true;
1839
+ break;
1840
+ }
1841
+ const experimentByHoldout = this.experimentDefinition(foundingExperimentHoldout, userInGroupHoldout, holdoutForcedUser);
1842
+ if (!experimentByHoldout)
1843
+ continue;
1844
+ userInGroupHoldout = this.calcUserInGroup(
1845
+ experimentByHoldout.salt,
1846
+ experimentByHoldout.allocation,
1847
+ experimentByHoldout.groups,
1848
+ holdoutForcedUser,
1849
+ null,
1850
+ [],
1851
+ splitByHoldoutId
1820
1852
  );
1853
+ if (userInGroupHoldout) {
1854
+ userInHoldout = true;
1855
+ break;
1856
+ }
1821
1857
  }
1822
1858
  }
1823
- if (userInGroupExperiment) {
1824
- const groupIndex = experiment.groups.findIndex((i2) => i2.name == userInGroupExperiment);
1825
- result = result.concat(experiment.name).concat(".").concat(groupIndex).concat("|");
1826
- }
1859
+ if (userInHoldout)
1860
+ continue;
1861
+ const groupIndex = experiment.groups.findIndex((i2) => i2.name == userInGroupExperiment);
1862
+ result = result.concat(experiment.name).concat(".").concat(groupIndex).concat("|");
1827
1863
  }
1828
1864
  if (result.length > 0) {
1829
1865
  this.cache.set(sigmaExperiments, result.slice(0, -1));
@@ -1833,6 +1869,52 @@ var Sigma = class {
1833
1869
  }
1834
1870
  return null;
1835
1871
  }
1872
+ async getHoldout(name) {
1873
+ if (!name)
1874
+ return console.log(warnings.emptyHoldoutId);
1875
+ const holdoutGroup = await this.getExperiment(name);
1876
+ if (holdoutGroup && typeof holdoutGroup === "string")
1877
+ return true;
1878
+ return false;
1879
+ }
1880
+ async getAllUserHoldouts() {
1881
+ await this.updateCache();
1882
+ const sigmaDataLs = await this.cache.parse(sigmaDataFile);
1883
+ if (!sigmaDataLs.experiments.length)
1884
+ return null;
1885
+ let result = "";
1886
+ for (const holdout of sigmaDataLs.experiments) {
1887
+ if (holdout.type !== experimentType.holdout)
1888
+ continue;
1889
+ let userInGroupExperiment = false;
1890
+ const layer = null;
1891
+ const bounds = [];
1892
+ const splitById = this.getSplitById(holdout);
1893
+ const forcedUser = checkForcedList(holdout.forced_user_list, splitById);
1894
+ const experiment = this.experimentDefinition(holdout, userInGroupExperiment, forcedUser);
1895
+ if (!experiment)
1896
+ continue;
1897
+ userInGroupExperiment = this.calcUserInGroup(
1898
+ experiment.salt,
1899
+ experiment.allocation,
1900
+ experiment.groups,
1901
+ forcedUser,
1902
+ layer,
1903
+ bounds,
1904
+ splitById
1905
+ );
1906
+ if (!userInGroupExperiment)
1907
+ continue;
1908
+ result = result.concat(holdout.name).concat(".").concat("0").concat("|");
1909
+ }
1910
+ if (result.length > 0) {
1911
+ this.cache.set(sigmaHoldouts, result.slice(0, -1));
1912
+ return result.slice(0, -1);
1913
+ } else {
1914
+ this.cache.remove(sigmaHoldouts);
1915
+ }
1916
+ return null;
1917
+ }
1836
1918
  findUserInForcedGroup(experiment) {
1837
1919
  let groupName = false;
1838
1920
  for (const groupItem in experiment.groups) {
@@ -1916,10 +1998,6 @@ var Sigma = class {
1916
1998
  const data = await this.cache.get(sigmaHash);
1917
1999
  return data;
1918
2000
  }
1919
- async getCacheUserId() {
1920
- const data = await this.cache.get(sigmaUserId);
1921
- return data;
1922
- }
1923
2001
  checkConditionsStatement(ruleStatement, items) {
1924
2002
  let isSuccessRule = false;
1925
2003
  if (ruleStatement == "OR") {
@@ -1938,14 +2016,11 @@ var Sigma = class {
1938
2016
  }
1939
2017
  }
1940
2018
  clearUserProperties() {
1941
- this.clearCacheByKeys([
1942
- sigmaUserId,
1943
- sigmaDeviceId,
1944
- sigmaProfileId,
1945
- sigmaExpiration,
1946
- sigmaExperiments
1947
- ]);
2019
+ this.userData.userId = void 0;
2020
+ this.userData.profileId = void 0;
2021
+ this.userData.deviceId = void 0;
1948
2022
  this.sigmaUserData.removeInjectedProperties();
2023
+ this.clearCacheByKeys([sigmaExperiments]);
1949
2024
  }
1950
2025
  overwriteGeoCache(key, value) {
1951
2026
  const geoCache = this.geoCache.parse(sigmaGeoData);
@@ -1956,17 +2031,17 @@ var Sigma = class {
1956
2031
  return {
1957
2032
  setUserId: (userId) => {
1958
2033
  this.sigmaUserData.setUserId(userId);
1959
- this.cache.set(sigmaUserId, userId);
2034
+ this.userData.userId = userId;
1960
2035
  return this.editUserProperties();
1961
2036
  },
1962
2037
  setDeviceId: (deviceId) => {
1963
2038
  this.sigmaUserData.setDeviceId(deviceId);
1964
- this.cache.set(sigmaDeviceId, deviceId);
2039
+ this.userData.deviceId = deviceId;
1965
2040
  return this.editUserProperties();
1966
2041
  },
1967
2042
  setProfileId: (profileId) => {
1968
2043
  this.sigmaUserData.setProfileId(profileId);
1969
- this.cache.set(sigmaProfileId, profileId);
2044
+ this.userData.profileId = profileId;
1970
2045
  return this.editUserProperties();
1971
2046
  },
1972
2047
  setEmail: (email) => {
@@ -2024,17 +2099,17 @@ var Sigma = class {
2024
2099
  },
2025
2100
  removeUserId: () => {
2026
2101
  this.sigmaUserData.removeUserId();
2027
- this.cache.remove(sigmaUserId);
2102
+ this.userData.userId = void 0;
2028
2103
  return this.editUserProperties();
2029
2104
  },
2030
2105
  removeDeviceId: () => {
2031
2106
  this.sigmaUserData.removeDeviceId();
2032
- this.cache.remove(sigmaDeviceId);
2107
+ this.userData.deviceId = void 0;
2033
2108
  return this.editUserProperties();
2034
2109
  },
2035
2110
  removeProfileId: () => {
2036
2111
  this.sigmaUserData.removeProfileId();
2037
- this.cache.remove(sigmaProfileId);
2112
+ this.userData.profileId = void 0;
2038
2113
  return this.editUserProperties();
2039
2114
  },
2040
2115
  removeAppVersion: () => {