posthog-node 2.1.0 → 2.2.0

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,8 @@
1
+ # 2.2.0 - 2022-11-18
2
+
3
+ 1. Add support for variant overrides for feature flag local evaluation.
4
+ 2. Add support for date operators in feature flag local evaluation.
5
+
1
6
  # 2.1.0 - 2022-09-08
2
7
 
3
8
  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.0";
167
167
 
168
168
  var PostHogPersistedProperty;
169
169
  (function (PostHogPersistedProperty) {
@@ -760,6 +760,26 @@ var PostHogCore = /** @class */ (function () {
760
760
  }
761
761
  return __assign({ $lib: this.getLibraryId(), $lib_version: this.getLibraryVersion(), $active_feature_flags: featureFlags ? Object.keys(featureFlags) : undefined }, featureVariantProperties);
762
762
  };
763
+ PostHogCore.prototype.setupBootstrap = function (options) {
764
+ var _a, _b, _c, _d;
765
+ if ((_a = options === null || options === void 0 ? void 0 : options.bootstrap) === null || _a === void 0 ? void 0 : _a.distinctId) {
766
+ if ((_b = options === null || options === void 0 ? void 0 : options.bootstrap) === null || _b === void 0 ? void 0 : _b.isIdentifiedId) {
767
+ this.setPersistedProperty(PostHogPersistedProperty.DistinctId, options.bootstrap.distinctId);
768
+ }
769
+ else {
770
+ this.setPersistedProperty(PostHogPersistedProperty.AnonymousId, options.bootstrap.distinctId);
771
+ }
772
+ }
773
+ if ((_c = options === null || options === void 0 ? void 0 : options.bootstrap) === null || _c === void 0 ? void 0 : _c.featureFlags) {
774
+ var activeFlags = Object.keys(((_d = options.bootstrap) === null || _d === void 0 ? void 0 : _d.featureFlags) || {})
775
+ .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]); })
776
+ .reduce(function (res, key) {
777
+ var _a, _b;
778
+ 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);
779
+ }, {});
780
+ this.setKnownFeatureFlags(activeFlags);
781
+ }
782
+ };
763
783
  Object.defineProperty(PostHogCore.prototype, "props", {
764
784
  // NOTE: Props are lazy loaded from localstorage hence the complex getter setter logic
765
785
  get: function () {
@@ -1003,8 +1023,7 @@ var PostHogCore = /** @class */ (function () {
1003
1023
  .then(function (r) { return r.json(); })
1004
1024
  .then(function (res) {
1005
1025
  if (res.featureFlags) {
1006
- _this.setPersistedProperty(PostHogPersistedProperty.FeatureFlags, res.featureFlags);
1007
- _this._events.emit('featureflags', res.featureFlags);
1026
+ _this.setKnownFeatureFlags(res.featureFlags);
1008
1027
  }
1009
1028
  return res;
1010
1029
  })
@@ -1015,6 +1034,10 @@ var PostHogCore = /** @class */ (function () {
1015
1034
  });
1016
1035
  });
1017
1036
  };
1037
+ PostHogCore.prototype.setKnownFeatureFlags = function (featureFlags) {
1038
+ this.setPersistedProperty(PostHogPersistedProperty.FeatureFlags, featureFlags);
1039
+ this._events.emit('featureflags', featureFlags);
1040
+ };
1018
1041
  PostHogCore.prototype.getFeatureFlag = function (key) {
1019
1042
  var featureFlags = this.getFeatureFlags();
1020
1043
  if (!featureFlags) {
@@ -1505,16 +1528,44 @@ function () {
1505
1528
  };
1506
1529
 
1507
1530
  FeatureFlagsPoller.prototype.matchFeatureFlagProperties = function (flag, distinctId, properties) {
1508
- var _this = this;
1531
+ var _a;
1509
1532
 
1510
1533
  var flagFilters = flag.filters || {};
1511
1534
  var flagConditions = flagFilters.groups || [];
1512
1535
  var isInconclusive = false;
1513
- var result = undefined;
1514
- flagConditions.forEach(function (condition) {
1536
+ var result = undefined; // # Stable sort conditions with variant overrides to the top. This ensures that if overrides are present, they are
1537
+ // # evaluated first, and the variant override is applied to the first matching condition.
1538
+
1539
+ var sortedFlagConditions = __spreadArray([], flagConditions, true).sort(function (conditionA, conditionB) {
1540
+ var AHasVariantOverride = !!conditionA.variant;
1541
+ var BHasVariantOverride = !!conditionB.variant;
1542
+
1543
+ if (AHasVariantOverride && BHasVariantOverride) {
1544
+ return 0;
1545
+ } else if (AHasVariantOverride) {
1546
+ return -1;
1547
+ } else if (BHasVariantOverride) {
1548
+ return 1;
1549
+ } else {
1550
+ return 0;
1551
+ }
1552
+ });
1553
+
1554
+ var _loop_1 = function (condition) {
1515
1555
  try {
1516
- if (_this.isConditionMatch(flag, distinctId, condition, properties)) {
1517
- result = _this.getMatchingVariant(flag, distinctId) || true;
1556
+ if (this_1.isConditionMatch(flag, distinctId, condition, properties)) {
1557
+ var variantOverride_1 = condition.variant;
1558
+ var flagVariants = ((_a = flagFilters.multivariate) === null || _a === void 0 ? void 0 : _a.variants) || [];
1559
+
1560
+ if (variantOverride_1 && flagVariants.some(function (variant) {
1561
+ return variant.key === variantOverride_1;
1562
+ })) {
1563
+ result = variantOverride_1;
1564
+ } else {
1565
+ result = this_1.getMatchingVariant(flag, distinctId) || true;
1566
+ }
1567
+
1568
+ return "break";
1518
1569
  }
1519
1570
  } catch (e) {
1520
1571
  if (e instanceof InconclusiveMatchError) {
@@ -1523,7 +1574,17 @@ function () {
1523
1574
  throw e;
1524
1575
  }
1525
1576
  }
1526
- });
1577
+ };
1578
+
1579
+ var this_1 = this;
1580
+
1581
+ for (var _i = 0, sortedFlagConditions_1 = sortedFlagConditions; _i < sortedFlagConditions_1.length; _i++) {
1582
+ var condition = sortedFlagConditions_1[_i];
1583
+
1584
+ var state_1 = _loop_1(condition);
1585
+
1586
+ if (state_1 === "break") break;
1587
+ }
1527
1588
 
1528
1589
  if (result !== undefined) {
1529
1590
  return result;
@@ -1820,6 +1881,17 @@ function matchProperty(property, propertyValues) {
1820
1881
  case 'lte':
1821
1882
  return typeof overrideValue == typeof value && overrideValue <= value;
1822
1883
 
1884
+ case 'is_date_after':
1885
+ case 'is_date_before':
1886
+ var parsedDate = convertToDateTime(value);
1887
+ var overrideDate = convertToDateTime(overrideValue);
1888
+
1889
+ if (operator === 'is_date_before') {
1890
+ return overrideDate < parsedDate;
1891
+ }
1892
+
1893
+ return overrideDate > parsedDate;
1894
+
1823
1895
  default:
1824
1896
  console.error("Unknown operator: ".concat(operator));
1825
1897
  return false;
@@ -1835,6 +1907,22 @@ function isValidRegex(regex) {
1835
1907
  }
1836
1908
  }
1837
1909
 
1910
+ function convertToDateTime(value) {
1911
+ if (value instanceof Date) {
1912
+ return value;
1913
+ } else if (typeof value === 'string' || typeof value === 'number') {
1914
+ var date = new Date(value);
1915
+
1916
+ if (!isNaN(date.valueOf())) {
1917
+ return date;
1918
+ }
1919
+
1920
+ throw new InconclusiveMatchError("".concat(value, " is in an invalid date format"));
1921
+ } else {
1922
+ throw new InconclusiveMatchError("The date provided ".concat(value, " must be a string, number, or date object"));
1923
+ }
1924
+ }
1925
+
1838
1926
  var THIRTY_SECONDS = 30 * 1000;
1839
1927
  var MAX_CACHE_SIZE = 50 * 1000;
1840
1928