expf-sigma-node.js 2.0.2 → 3.0.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 +181 -133
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expf-sigma-node.js",
3
- "version": "2.0.2",
3
+ "version": "3.0.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
@@ -35,6 +35,8 @@ var SigmaUserData = class {
35
35
  constructor() {
36
36
  this.user = {
37
37
  userId: null,
38
+ profileId: null,
39
+ deviceId: null,
38
40
  ip: null,
39
41
  email: null,
40
42
  appVersion: null,
@@ -68,6 +70,8 @@ var SigmaUserData = class {
68
70
  }
69
71
  init({
70
72
  userId,
73
+ profileId,
74
+ deviceId,
71
75
  ip,
72
76
  email,
73
77
  appVersion,
@@ -82,6 +86,8 @@ var SigmaUserData = class {
82
86
  pathname
83
87
  }) {
84
88
  this.user.userId = userId;
89
+ this.user.profileId = profileId;
90
+ this.user.deviceId = deviceId;
85
91
  this.user.ip = ip;
86
92
  this.user.email = email;
87
93
  this.user.appVersion = appVersion;
@@ -185,6 +191,107 @@ var SigmaGeoCache = class {
185
191
  }
186
192
  };
187
193
 
194
+ // src/helpers/checkBoolValue.js
195
+ function checkBoolValue(value) {
196
+ if (value)
197
+ return true;
198
+ return false;
199
+ }
200
+
201
+ // src/helpers/checkForcedList.js
202
+ function checkForcedList(usersList, data) {
203
+ if (usersList.length) {
204
+ for (let id in usersList) {
205
+ if (usersList[id] == data) {
206
+ return true;
207
+ }
208
+ }
209
+ }
210
+ return false;
211
+ }
212
+
213
+ // src/helpers/compareVersions.js
214
+ function compareVersions(versionA, versionB, strict = true) {
215
+ let resultCompare;
216
+ const versionsLength = Math.max(versionA.length, versionB.length);
217
+ versionA = (versionA + "").split(".");
218
+ versionB = (versionB + "").split(".");
219
+ for (let i = 0; i < versionsLength; i++) {
220
+ if (versionA[i] === void 0) {
221
+ versionA[i] = "0";
222
+ }
223
+ if (versionB[i] === void 0) {
224
+ versionB[i] = "0";
225
+ }
226
+ resultCompare = parseInt(versionA[i], 10) - parseInt(versionB[i], 10);
227
+ if (resultCompare !== 0) {
228
+ return resultCompare < 0 ? false : true;
229
+ }
230
+ }
231
+ if (strict) {
232
+ return false;
233
+ }
234
+ if (!strict) {
235
+ return true;
236
+ }
237
+ }
238
+
239
+ // src/helpers/delay.js
240
+ function delay(ms) {
241
+ new Promise((resolve) => setTimeout(() => resolve(void 0), ms));
242
+ }
243
+
244
+ // src/helpers/digestHash.js
245
+ function digestHash(string) {
246
+ let hash = 0, i, chr;
247
+ if (string.length === 0)
248
+ return hash;
249
+ for (i = 0; i < string.length; i++) {
250
+ chr = string.charCodeAt(i);
251
+ hash = (hash << 5) - hash + chr;
252
+ hash |= 0;
253
+ }
254
+ return hash;
255
+ }
256
+
257
+ // src/helpers/doTypeConversion.js
258
+ function doTypeConversion(type, value) {
259
+ if (type === "string")
260
+ return value;
261
+ if (type === "bool") {
262
+ return value === "true" ? true : false;
263
+ }
264
+ if (type === "integer" || type === "number")
265
+ return parseFloat(value);
266
+ return value;
267
+ }
268
+
269
+ // src/helpers/makeIdCookie.js
270
+ function makeIdCookie() {
271
+ let text = "";
272
+ let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
273
+ for (let i = 0; i < 80; i++)
274
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
275
+ return text;
276
+ }
277
+
278
+ // src/helpers/getUserGroup.js
279
+ function getUserGroup(salt, exposureRate, controlBucketPerc, forcedExp) {
280
+ let userInGroup = "a";
281
+ let currentDiapason = 0;
282
+ if (Math.abs(salt) / 100 <= parseFloat(exposureRate) * 100 || forcedExp) {
283
+ let bucket = Math.abs(salt) % 100;
284
+ for (let i = 0; i < controlBucketPerc.length; i++) {
285
+ currentDiapason += controlBucketPerc[i].weight * 100;
286
+ if (bucket <= currentDiapason) {
287
+ return userInGroup = controlBucketPerc[i].name;
288
+ }
289
+ }
290
+ return userInGroup;
291
+ }
292
+ return false;
293
+ }
294
+
188
295
  // src/modules/sigmaHashes.js
189
296
  var Hashes;
190
297
  function utf8Encode(str) {
@@ -820,118 +927,23 @@ Hashes = {
820
927
  };
821
928
  var sigmaHashes_default = Hashes;
822
929
 
823
- // src/helpers/checkBoolValue.js
824
- function checkBoolValue(value) {
825
- if (value)
826
- return true;
827
- return false;
828
- }
829
-
830
- // src/helpers/checkForcedList.js
831
- function checkForcedList(usersList, data) {
832
- if (usersList.length) {
833
- for (let id in usersList) {
834
- if (usersList[id] == data) {
835
- return true;
836
- }
837
- }
838
- }
839
- return false;
840
- }
841
-
842
- // src/helpers/compareVersions.js
843
- function compareVersions(versionA, versionB, strict = true) {
844
- let resultCompare;
845
- const versionsLength = Math.max(versionA.length, versionB.length);
846
- versionA = (versionA + "").split(".");
847
- versionB = (versionB + "").split(".");
848
- for (let i = 0; i < versionsLength; i++) {
849
- if (versionA[i] === void 0) {
850
- versionA[i] = "0";
851
- }
852
- if (versionB[i] === void 0) {
853
- versionB[i] = "0";
854
- }
855
- resultCompare = parseInt(versionA[i], 10) - parseInt(versionB[i], 10);
856
- if (resultCompare !== 0) {
857
- return resultCompare < 0 ? false : true;
858
- }
859
- }
860
- if (strict) {
861
- return false;
862
- }
863
- if (!strict) {
864
- return true;
865
- }
866
- }
867
-
868
- // src/helpers/delay.js
869
- function delay(ms) {
870
- new Promise((resolve) => setTimeout(() => resolve(void 0), ms));
871
- }
872
-
873
- // src/helpers/digestHash.js
874
- function digestHash(string) {
875
- let hash = 0, i, chr;
876
- if (string.length === 0)
877
- return hash;
878
- for (i = 0; i < string.length; i++) {
879
- chr = string.charCodeAt(i);
880
- hash = (hash << 5) - hash + chr;
881
- hash |= 0;
882
- }
883
- return hash;
884
- }
885
-
886
- // src/helpers/doTypeConversion.js
887
- function doTypeConversion(type, value) {
888
- if (type === "string")
889
- return value;
890
- if (type === "bool") {
891
- return value === "true" ? true : false;
892
- }
893
- if (type === "integer" || type === "number")
894
- return parseFloat(value);
895
- return value;
896
- }
897
-
898
- // src/helpers/makeIdCookie.js
899
- function makeIdCookie() {
900
- let text = "";
901
- let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
902
- for (let i = 0; i < 80; i++)
903
- text += possible.charAt(Math.floor(Math.random() * possible.length));
904
- return text;
905
- }
906
-
907
- // src/helpers/getUserGroup.js
908
- function getUserGroup(salt, exposureRate, controlBucketPerc, forcedExp) {
909
- let userInGroup = "a";
910
- let currentDiapason = 0;
911
- if (Math.abs(salt) / 100 <= parseFloat(exposureRate) * 100 || forcedExp) {
912
- let bucket = Math.abs(salt) % 100;
913
- for (let i = 0; i < controlBucketPerc.length; i++) {
914
- currentDiapason += controlBucketPerc[i].weight * 100;
915
- if (bucket <= currentDiapason) {
916
- return userInGroup = controlBucketPerc[i].name;
917
- }
918
- }
919
- return userInGroup;
920
- }
921
- return false;
922
- }
923
-
924
- // src/sigma.js
925
- if (typeof import_node_fetch.default.default !== "undefined")
926
- import_node_fetch.default.default;
930
+ // src/helpers/constants.js
927
931
  var defaultApi = "https://api.expf.ru/api/v1";
928
932
  var sigmaUserId = "sigmaUserId";
933
+ var sigmaProfileId = "sigmaProfileId";
934
+ var sigmaDeviceId = "sigmaDeviceId";
935
+ var sigmaHash = "sigmaHash";
936
+ var sigmaDataFileLastUpdate = "sigmaDataFileLastUpdate";
929
937
  var sigmaDataFile = "sigmaDataFile";
930
938
  var sigmaExperiments = "sigmaExperiments";
931
- var SHA256 = new sigmaHashes_default.SHA256();
932
- var MD5 = new sigmaHashes_default.MD5();
933
939
  var max_decimal_64 = 18446744073709552e3;
934
940
  var zeta = 8540717056e4;
941
+ var SHA256 = new sigmaHashes_default.SHA256();
942
+ var MD5 = new sigmaHashes_default.MD5();
943
+
944
+ // src/sigma.js
945
+ if (typeof import_node_fetch.default.default !== "undefined")
946
+ import_node_fetch.default.default;
935
947
  var Sigma = class {
936
948
  constructor(token, userData, cacheTTL = 10, options = {
937
949
  api: "",
@@ -950,9 +962,10 @@ var Sigma = class {
950
962
  this.sigmaUserData = new SigmaUserData();
951
963
  this.postfix = options.postfix || "";
952
964
  this.cache = new SigmaCache(this.postfix);
953
- this.userData.userId = this.validateUserDataUserId(this.userData.userId);
954
965
  this.sigmaUserData.init({
955
966
  userId: this.userData.userId || null,
967
+ profileId: this.userData.profileId || null,
968
+ deviceId: this.userData.deviceId || null,
956
969
  ip: this.userData.ip || null,
957
970
  email: this.userData.email || null,
958
971
  appVersion: this.userData.appVersion || null,
@@ -967,8 +980,25 @@ var Sigma = class {
967
980
  pathname: this.userData.pathname || null
968
981
  });
969
982
  this.geoCache = new SigmaGeoCache(this.token, options.geoCacheTTL);
970
- this.cache.set(sigmaUserId, this.userData.userId);
971
- this.setUserCookie();
983
+ this.setSplitIdsToCache(this.userData);
984
+ }
985
+ setSplitIdsToCache(userData) {
986
+ for (let [key, value] of Object.entries(userData)) {
987
+ switch (key) {
988
+ case "userId":
989
+ if (value)
990
+ this.cache.set(sigmaUserId, String(value).trim());
991
+ break;
992
+ case "profileId":
993
+ if (value)
994
+ this.cache.set(sigmaProfileId, String(value).trim());
995
+ break;
996
+ case "deviceId":
997
+ if (value)
998
+ this.cache.set(sigmaDeviceId, String(value).trim());
999
+ break;
1000
+ }
1001
+ }
972
1002
  }
973
1003
  validateUserDataUserId(userId) {
974
1004
  let hasMakeId = false;
@@ -1012,7 +1042,7 @@ var Sigma = class {
1012
1042
  "ip": this.userData.ip,
1013
1043
  "X-Real-IP": this.userData.ip,
1014
1044
  token: this.token,
1015
- "user-id": this.userData.userId ? this.userData.userId : this.sigmaUserData.user.userId
1045
+ "user-id": this.validateUserDataUserId(this.userData.userId)
1016
1046
  }
1017
1047
  };
1018
1048
  if (method !== "GET") {
@@ -1053,10 +1083,10 @@ var Sigma = class {
1053
1083
  }
1054
1084
  async saveToCache() {
1055
1085
  const { api } = this;
1056
- const localStorageHash = this.cache.get("sigmaHash");
1086
+ const localStorageHash = this.cache.get(sigmaHash);
1057
1087
  try {
1058
1088
  const timeRecord = Math.floor(Date.now() / 1e3);
1059
- this.cache.set("sigmaDataFileLastUpdate", timeRecord);
1089
+ this.cache.set(sigmaDataFileLastUpdate, timeRecord);
1060
1090
  } catch (error) {
1061
1091
  throw new Error(`save last update to cache: ${error},
1062
1092
  token: ${this.token}
@@ -1080,7 +1110,7 @@ var Sigma = class {
1080
1110
  }
1081
1111
  hash = await SHA256.hex(JSON.stringify(data));
1082
1112
  if (!localStorageHash || localStorageHash !== hash) {
1083
- this.cache.set("sigmaHash", hash);
1113
+ this.cache.set(sigmaHash, hash);
1084
1114
  this.cache.set(sigmaDataFile, JSON.stringify(data));
1085
1115
  this.sigmaUserData.clearFlags();
1086
1116
  }
@@ -1088,17 +1118,9 @@ var Sigma = class {
1088
1118
  throw new Error(`Save data to local storage`);
1089
1119
  }
1090
1120
  }
1091
- setUserCookie() {
1092
- let uin = this.cache.get(sigmaUserId);
1093
- if (!uin) {
1094
- uin = makeIdCookie();
1095
- this.cache.set(sigmaUserId, uin);
1096
- }
1097
- return;
1098
- }
1099
1121
  hasExpireCache() {
1100
1122
  const lastUpdate = parseInt(
1101
- this.cache.get("sigmaDataFileLastUpdate")
1123
+ this.cache.get(sigmaDataFileLastUpdate)
1102
1124
  );
1103
1125
  const currentTime = Math.floor(Date.now() / 1e3);
1104
1126
  if (currentTime > lastUpdate + this.cacheTTL) {
@@ -1107,14 +1129,14 @@ var Sigma = class {
1107
1129
  return false;
1108
1130
  }
1109
1131
  updateCache() {
1110
- if (!this.cache.get("sigmaDataFile") || this.hasExpireCache()) {
1132
+ if (!this.cache.get(sigmaDataFile) || this.hasExpireCache()) {
1111
1133
  return this.saveToCache();
1112
1134
  }
1113
1135
  return true;
1114
1136
  }
1115
1137
  async getFlags() {
1116
1138
  await this.updateCache();
1117
- const flags = this.cache.parse("sigmaDataFile");
1139
+ const flags = this.cache.parse(sigmaDataFile);
1118
1140
  if (!flags.feature_flags)
1119
1141
  return;
1120
1142
  return flags.feature_flags;
@@ -1261,15 +1283,16 @@ var Sigma = class {
1261
1283
  }
1262
1284
  return defaultValue;
1263
1285
  }
1264
- calcUserInGroup(salt, exposureRate, controlBucketPerc, forcedExp = false, layer = null, layerBounds = []) {
1265
- const userId = this.sigmaUserData.user.userId ? this.sigmaUserData.user.userId : this.cache.get(sigmaUserId);
1266
- const md5R = MD5.hex(String(userId) + salt);
1286
+ calcUserInGroup(salt, exposureRate, controlBucketPerc, forcedExp = false, layer = null, layerBounds = [], splitBy) {
1287
+ if (!splitBy)
1288
+ return false;
1289
+ const md5R = MD5.hex(String(splitBy) + salt);
1267
1290
  const R = digestHash(md5R) * zeta / max_decimal_64;
1268
1291
  let md5L = null;
1269
1292
  if (!layer && !layerBounds.length || forcedExp) {
1270
1293
  return getUserGroup(R, exposureRate, controlBucketPerc, forcedExp);
1271
1294
  } else {
1272
- md5L = MD5.hex(String(userId) + layer);
1295
+ md5L = MD5.hex(String(splitBy) + layer);
1273
1296
  const L = digestHash(md5L) * zeta / max_decimal_64;
1274
1297
  for (let i in layerBounds) {
1275
1298
  const result = Math.abs(L / 10);
@@ -1282,6 +1305,26 @@ var Sigma = class {
1282
1305
  }
1283
1306
  return false;
1284
1307
  }
1308
+ getSplitById(experiment) {
1309
+ if (!experiment)
1310
+ return;
1311
+ let id = null;
1312
+ if (!experiment.split_by) {
1313
+ experiment.split_by = "userId";
1314
+ }
1315
+ switch (experiment.split_by) {
1316
+ case "userId":
1317
+ id = this.cache.get(sigmaUserId) || null;
1318
+ break;
1319
+ case "profileId":
1320
+ id = this.cache.get(sigmaProfileId) || null;
1321
+ break;
1322
+ case "deviceId":
1323
+ id = this.cache.get(sigmaDeviceId) || null;
1324
+ break;
1325
+ }
1326
+ return id;
1327
+ }
1285
1328
  checkTargetConditions(experiment) {
1286
1329
  if (experiment.targets && experiment.targets.conditions && experiment.targets.conditions.length > 0) {
1287
1330
  const targets = experiment.targets;
@@ -1332,12 +1375,14 @@ var Sigma = class {
1332
1375
  let bounds = [];
1333
1376
  let userInGroupExperiment = null;
1334
1377
  let forcedUser = false;
1378
+ let splitById = null;
1335
1379
  for (let i = 0; i < sigmaDataLs.experiments.length; i++) {
1336
1380
  if (sigmaDataLs.experiments[i]["name"] === experimentName && checkBoolValue(sigmaDataLs.experiments[i]["layer_id"])) {
1337
1381
  layer = sigmaDataLs.experiments[i]["layer_id"];
1338
1382
  bounds = sigmaDataLs.experiments[i]["layer_bounds"];
1339
1383
  }
1340
1384
  if (sigmaDataLs.experiments[i]["name"] === experimentName && !experiment) {
1385
+ splitById = this.getSplitById(sigmaDataLs.experiments[i]);
1341
1386
  forcedUser = checkForcedList(sigmaDataLs.experiments[i].forced_user_list, this.sigmaUserData.user.userId);
1342
1387
  userInGroupExperiment = this.findUserInForcedGroup(sigmaDataLs.experiments[i]);
1343
1388
  experiment = this.experimentDefinition(sigmaDataLs.experiments[i], userInGroupExperiment);
@@ -1353,7 +1398,8 @@ var Sigma = class {
1353
1398
  experiment.groups,
1354
1399
  forcedUser,
1355
1400
  layer,
1356
- bounds
1401
+ bounds,
1402
+ splitById
1357
1403
  );
1358
1404
  }
1359
1405
  this.cache.set(localStorageGroupName, userInGroupExperiment);
@@ -1421,6 +1467,7 @@ var Sigma = class {
1421
1467
  for (let i in sigmaDataLs.experiments) {
1422
1468
  let layer = null;
1423
1469
  let bounds = [];
1470
+ let splitById = this.getSplitById(sigmaDataLs.experiments[i]);
1424
1471
  let userInGroupExperiment = this.findUserInForcedGroup(sigmaDataLs.experiments[i]);
1425
1472
  let experiment = this.experimentDefinition(sigmaDataLs.experiments[i], userInGroupExperiment);
1426
1473
  if (experiment) {
@@ -1433,9 +1480,10 @@ var Sigma = class {
1433
1480
  experiment.salt,
1434
1481
  experiment.allocation,
1435
1482
  experiment.groups,
1436
- checkForcedList(experiment.forced_user_list, this.sigmaUserData.user.userId),
1483
+ checkForcedList(experiment.forced_user_list, splitById),
1437
1484
  layer,
1438
- bounds
1485
+ bounds,
1486
+ splitById
1439
1487
  );
1440
1488
  }
1441
1489
  }
@@ -1456,7 +1504,7 @@ var Sigma = class {
1456
1504
  const forcedList = experiment.groups[groupItem].forced_user_list;
1457
1505
  if (forcedList && forcedList.length) {
1458
1506
  for (const item in forcedList) {
1459
- if (forcedList[item] === this.sigmaUserData.user.userId) {
1507
+ if (forcedList[item] === this.getSplitById(experiment)) {
1460
1508
  return groupName = experiment.groups[groupItem].name;
1461
1509
  }
1462
1510
  }
@@ -1528,7 +1576,7 @@ var Sigma = class {
1528
1576
  return this.cache.parse(sigmaDataFile);
1529
1577
  }
1530
1578
  async getCacheHash() {
1531
- const data = await this.cache.get("sigmaHash");
1579
+ const data = await this.cache.get(sigmaHash);
1532
1580
  return data;
1533
1581
  }
1534
1582
  async getCacheUserId() {