posthog-node 2.1.0 → 2.2.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/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ # 2.2.1 - 2022-11-24
2
+ 1. Add standard 10 second timeout
3
+
4
+ # 2.2.0 - 2022-11-18
5
+
6
+ 1. Add support for variant overrides for feature flag local evaluation.
7
+ 2. Add support for date operators in feature flag local evaluation.
8
+
1
9
  # 2.1.0 - 2022-09-08
2
10
 
3
11
  1. Swaps `unidici` for `axios` in order to support older versions of Node
package/lib/index.cjs.js CHANGED
@@ -163,7 +163,7 @@ function __spreadArray(to, from, pack) {
163
163
  return to.concat(ar || Array.prototype.slice.call(from));
164
164
  }
165
165
 
166
- var version = "2.1.0";
166
+ var version = "2.2.1";
167
167
 
168
168
  var PostHogPersistedProperty;
169
169
  (function (PostHogPersistedProperty) {
@@ -724,7 +724,7 @@ var SimpleEventEmitter = /** @class */ (function () {
724
724
  var PostHogCore = /** @class */ (function () {
725
725
  function PostHogCore(apiKey, options) {
726
726
  var _this = this;
727
- var _a, _b, _c, _d, _e;
727
+ var _a, _b, _c, _d, _e, _f;
728
728
  this.flagCallReported = {};
729
729
  // internal
730
730
  this._events = new SimpleEventEmitter();
@@ -741,7 +741,8 @@ var PostHogCore = /** @class */ (function () {
741
741
  retryCount: (_c = options === null || options === void 0 ? void 0 : options.fetchRetryCount) !== null && _c !== void 0 ? _c : 3,
742
742
  retryDelay: (_d = options === null || options === void 0 ? void 0 : options.fetchRetryDelay) !== null && _d !== void 0 ? _d : 3000,
743
743
  };
744
- this._sessionExpirationTimeSeconds = (_e = options === null || options === void 0 ? void 0 : options.sessionExpirationTimeSeconds) !== null && _e !== void 0 ? _e : 1800; // 30 minutes
744
+ this.requestTimeout = (_e = options === null || options === void 0 ? void 0 : options.requestTimeout) !== null && _e !== void 0 ? _e : 10;
745
+ this._sessionExpirationTimeSeconds = (_f = options === null || options === void 0 ? void 0 : options.sessionExpirationTimeSeconds) !== null && _f !== void 0 ? _f : 1800; // 30 minutes
745
746
  // NOTE: It is important we don't initiate anything in the constructor as some async IO may still be underway on the parent
746
747
  if ((options === null || options === void 0 ? void 0 : options.preloadFeatureFlags) !== false) {
747
748
  safeSetTimeout(function () {
@@ -760,6 +761,26 @@ var PostHogCore = /** @class */ (function () {
760
761
  }
761
762
  return __assign({ $lib: this.getLibraryId(), $lib_version: this.getLibraryVersion(), $active_feature_flags: featureFlags ? Object.keys(featureFlags) : undefined }, featureVariantProperties);
762
763
  };
764
+ PostHogCore.prototype.setupBootstrap = function (options) {
765
+ var _a, _b, _c, _d;
766
+ if ((_a = options === null || options === void 0 ? void 0 : options.bootstrap) === null || _a === void 0 ? void 0 : _a.distinctId) {
767
+ if ((_b = options === null || options === void 0 ? void 0 : options.bootstrap) === null || _b === void 0 ? void 0 : _b.isIdentifiedId) {
768
+ this.setPersistedProperty(PostHogPersistedProperty.DistinctId, options.bootstrap.distinctId);
769
+ }
770
+ else {
771
+ this.setPersistedProperty(PostHogPersistedProperty.AnonymousId, options.bootstrap.distinctId);
772
+ }
773
+ }
774
+ if ((_c = options === null || options === void 0 ? void 0 : options.bootstrap) === null || _c === void 0 ? void 0 : _c.featureFlags) {
775
+ var activeFlags = Object.keys(((_d = options.bootstrap) === null || _d === void 0 ? void 0 : _d.featureFlags) || {})
776
+ .filter(function (flag) { var _a, _b; return !!((_b = (_a = options.bootstrap) === null || _a === void 0 ? void 0 : _a.featureFlags) === null || _b === void 0 ? void 0 : _b[flag]); })
777
+ .reduce(function (res, key) {
778
+ var _a, _b;
779
+ return ((res[key] = ((_b = (_a = options.bootstrap) === null || _a === void 0 ? void 0 : _a.featureFlags) === null || _b === void 0 ? void 0 : _b[key]) || false), res);
780
+ }, {});
781
+ this.setKnownFeatureFlags(activeFlags);
782
+ }
783
+ };
763
784
  Object.defineProperty(PostHogCore.prototype, "props", {
764
785
  // NOTE: Props are lazy loaded from localstorage hence the complex getter setter logic
765
786
  get: function () {
@@ -1003,8 +1024,7 @@ var PostHogCore = /** @class */ (function () {
1003
1024
  .then(function (r) { return r.json(); })
1004
1025
  .then(function (res) {
1005
1026
  if (res.featureFlags) {
1006
- _this.setPersistedProperty(PostHogPersistedProperty.FeatureFlags, res.featureFlags);
1007
- _this._events.emit('featureflags', res.featureFlags);
1027
+ _this.setKnownFeatureFlags(res.featureFlags);
1008
1028
  }
1009
1029
  return res;
1010
1030
  })
@@ -1015,6 +1035,10 @@ var PostHogCore = /** @class */ (function () {
1015
1035
  });
1016
1036
  });
1017
1037
  };
1038
+ PostHogCore.prototype.setKnownFeatureFlags = function (featureFlags) {
1039
+ this.setPersistedProperty(PostHogPersistedProperty.FeatureFlags, featureFlags);
1040
+ this._events.emit('featureflags', featureFlags);
1041
+ };
1018
1042
  PostHogCore.prototype.getFeatureFlag = function (key) {
1019
1043
  var featureFlags = this.getFeatureFlags();
1020
1044
  if (!featureFlags) {
@@ -1202,10 +1226,19 @@ var PostHogCore = /** @class */ (function () {
1202
1226
  });
1203
1227
  };
1204
1228
  PostHogCore.prototype.fetchWithRetry = function (url, options, retryOptions) {
1229
+ var _a;
1230
+ var _b;
1205
1231
  return __awaiter(this, void 0, void 0, function () {
1206
1232
  var _this = this;
1207
- return __generator(this, function (_a) {
1208
- return [2 /*return*/, retriable(function () { return _this.fetch(url, options); }, retryOptions || this._retryOptions)];
1233
+ return __generator(this, function (_c) {
1234
+ (_a = (_b = AbortSignal).timeout) !== null && _a !== void 0 ? _a : (_b.timeout = function timeout(ms) {
1235
+ var ctrl = new AbortController();
1236
+ setTimeout(function () { return ctrl.abort(); }, ms);
1237
+ return ctrl.signal;
1238
+ });
1239
+ return [2 /*return*/, retriable(function () {
1240
+ return _this.fetch(url, __assign({ signal: AbortSignal.timeout(_this.requestTimeout) }, options));
1241
+ }, retryOptions || this._retryOptions)];
1209
1242
  });
1210
1243
  });
1211
1244
  };
@@ -1505,16 +1538,44 @@ function () {
1505
1538
  };
1506
1539
 
1507
1540
  FeatureFlagsPoller.prototype.matchFeatureFlagProperties = function (flag, distinctId, properties) {
1508
- var _this = this;
1541
+ var _a;
1509
1542
 
1510
1543
  var flagFilters = flag.filters || {};
1511
1544
  var flagConditions = flagFilters.groups || [];
1512
1545
  var isInconclusive = false;
1513
- var result = undefined;
1514
- flagConditions.forEach(function (condition) {
1546
+ var result = undefined; // # Stable sort conditions with variant overrides to the top. This ensures that if overrides are present, they are
1547
+ // # evaluated first, and the variant override is applied to the first matching condition.
1548
+
1549
+ var sortedFlagConditions = __spreadArray([], flagConditions, true).sort(function (conditionA, conditionB) {
1550
+ var AHasVariantOverride = !!conditionA.variant;
1551
+ var BHasVariantOverride = !!conditionB.variant;
1552
+
1553
+ if (AHasVariantOverride && BHasVariantOverride) {
1554
+ return 0;
1555
+ } else if (AHasVariantOverride) {
1556
+ return -1;
1557
+ } else if (BHasVariantOverride) {
1558
+ return 1;
1559
+ } else {
1560
+ return 0;
1561
+ }
1562
+ });
1563
+
1564
+ var _loop_1 = function (condition) {
1515
1565
  try {
1516
- if (_this.isConditionMatch(flag, distinctId, condition, properties)) {
1517
- result = _this.getMatchingVariant(flag, distinctId) || true;
1566
+ if (this_1.isConditionMatch(flag, distinctId, condition, properties)) {
1567
+ var variantOverride_1 = condition.variant;
1568
+ var flagVariants = ((_a = flagFilters.multivariate) === null || _a === void 0 ? void 0 : _a.variants) || [];
1569
+
1570
+ if (variantOverride_1 && flagVariants.some(function (variant) {
1571
+ return variant.key === variantOverride_1;
1572
+ })) {
1573
+ result = variantOverride_1;
1574
+ } else {
1575
+ result = this_1.getMatchingVariant(flag, distinctId) || true;
1576
+ }
1577
+
1578
+ return "break";
1518
1579
  }
1519
1580
  } catch (e) {
1520
1581
  if (e instanceof InconclusiveMatchError) {
@@ -1523,7 +1584,17 @@ function () {
1523
1584
  throw e;
1524
1585
  }
1525
1586
  }
1526
- });
1587
+ };
1588
+
1589
+ var this_1 = this;
1590
+
1591
+ for (var _i = 0, sortedFlagConditions_1 = sortedFlagConditions; _i < sortedFlagConditions_1.length; _i++) {
1592
+ var condition = sortedFlagConditions_1[_i];
1593
+
1594
+ var state_1 = _loop_1(condition);
1595
+
1596
+ if (state_1 === "break") break;
1597
+ }
1527
1598
 
1528
1599
  if (result !== undefined) {
1529
1600
  return result;
@@ -1820,6 +1891,17 @@ function matchProperty(property, propertyValues) {
1820
1891
  case 'lte':
1821
1892
  return typeof overrideValue == typeof value && overrideValue <= value;
1822
1893
 
1894
+ case 'is_date_after':
1895
+ case 'is_date_before':
1896
+ var parsedDate = convertToDateTime(value);
1897
+ var overrideDate = convertToDateTime(overrideValue);
1898
+
1899
+ if (operator === 'is_date_before') {
1900
+ return overrideDate < parsedDate;
1901
+ }
1902
+
1903
+ return overrideDate > parsedDate;
1904
+
1823
1905
  default:
1824
1906
  console.error("Unknown operator: ".concat(operator));
1825
1907
  return false;
@@ -1835,6 +1917,22 @@ function isValidRegex(regex) {
1835
1917
  }
1836
1918
  }
1837
1919
 
1920
+ function convertToDateTime(value) {
1921
+ if (value instanceof Date) {
1922
+ return value;
1923
+ } else if (typeof value === 'string' || typeof value === 'number') {
1924
+ var date = new Date(value);
1925
+
1926
+ if (!isNaN(date.valueOf())) {
1927
+ return date;
1928
+ }
1929
+
1930
+ throw new InconclusiveMatchError("".concat(value, " is in an invalid date format"));
1931
+ } else {
1932
+ throw new InconclusiveMatchError("The date provided ".concat(value, " must be a string, number, or date object"));
1933
+ }
1934
+ }
1935
+
1838
1936
  var THIRTY_SECONDS = 30 * 1000;
1839
1937
  var MAX_CACHE_SIZE = 50 * 1000;
1840
1938
 
@@ -1902,6 +2000,8 @@ function () {
1902
2000
  options = {};
1903
2001
  }
1904
2002
 
2003
+ var _a;
2004
+
1905
2005
  this._sharedClient = new PostHogClient(apiKey, options);
1906
2006
 
1907
2007
  if (options.personalApiKey) {
@@ -1909,7 +2009,7 @@ function () {
1909
2009
  pollingInterval: typeof options.featureFlagsPollingInterval === 'number' ? options.featureFlagsPollingInterval : THIRTY_SECONDS,
1910
2010
  personalApiKey: options.personalApiKey,
1911
2011
  projectApiKey: apiKey,
1912
- timeout: options.requestTimeout,
2012
+ timeout: (_a = options.requestTimeout) !== null && _a !== void 0 ? _a : 10,
1913
2013
  host: this._sharedClient.host,
1914
2014
  fetch: options.fetch
1915
2015
  });