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/lib/index.d.ts CHANGED
@@ -6,8 +6,14 @@ declare type PosthogCoreOptions = {
6
6
  enable?: boolean;
7
7
  sendFeatureFlagEvent?: boolean;
8
8
  preloadFeatureFlags?: boolean;
9
+ bootstrap?: {
10
+ distinctId?: string;
11
+ isIdentifiedId?: boolean;
12
+ featureFlags?: Record<string, boolean | string>;
13
+ };
9
14
  fetchRetryCount?: number;
10
15
  fetchRetryDelay?: number;
16
+ requestTimeout?: number;
11
17
  sessionExpirationTimeSeconds?: number;
12
18
  captureMode?: 'json' | 'form';
13
19
  };
package/lib/index.esm.js CHANGED
@@ -155,7 +155,7 @@ function __spreadArray(to, from, pack) {
155
155
  return to.concat(ar || Array.prototype.slice.call(from));
156
156
  }
157
157
 
158
- var version = "2.1.0";
158
+ var version = "2.2.1";
159
159
 
160
160
  var PostHogPersistedProperty;
161
161
  (function (PostHogPersistedProperty) {
@@ -716,7 +716,7 @@ var SimpleEventEmitter = /** @class */ (function () {
716
716
  var PostHogCore = /** @class */ (function () {
717
717
  function PostHogCore(apiKey, options) {
718
718
  var _this = this;
719
- var _a, _b, _c, _d, _e;
719
+ var _a, _b, _c, _d, _e, _f;
720
720
  this.flagCallReported = {};
721
721
  // internal
722
722
  this._events = new SimpleEventEmitter();
@@ -733,7 +733,8 @@ var PostHogCore = /** @class */ (function () {
733
733
  retryCount: (_c = options === null || options === void 0 ? void 0 : options.fetchRetryCount) !== null && _c !== void 0 ? _c : 3,
734
734
  retryDelay: (_d = options === null || options === void 0 ? void 0 : options.fetchRetryDelay) !== null && _d !== void 0 ? _d : 3000,
735
735
  };
736
- this._sessionExpirationTimeSeconds = (_e = options === null || options === void 0 ? void 0 : options.sessionExpirationTimeSeconds) !== null && _e !== void 0 ? _e : 1800; // 30 minutes
736
+ this.requestTimeout = (_e = options === null || options === void 0 ? void 0 : options.requestTimeout) !== null && _e !== void 0 ? _e : 10;
737
+ this._sessionExpirationTimeSeconds = (_f = options === null || options === void 0 ? void 0 : options.sessionExpirationTimeSeconds) !== null && _f !== void 0 ? _f : 1800; // 30 minutes
737
738
  // NOTE: It is important we don't initiate anything in the constructor as some async IO may still be underway on the parent
738
739
  if ((options === null || options === void 0 ? void 0 : options.preloadFeatureFlags) !== false) {
739
740
  safeSetTimeout(function () {
@@ -752,6 +753,26 @@ var PostHogCore = /** @class */ (function () {
752
753
  }
753
754
  return __assign({ $lib: this.getLibraryId(), $lib_version: this.getLibraryVersion(), $active_feature_flags: featureFlags ? Object.keys(featureFlags) : undefined }, featureVariantProperties);
754
755
  };
756
+ PostHogCore.prototype.setupBootstrap = function (options) {
757
+ var _a, _b, _c, _d;
758
+ if ((_a = options === null || options === void 0 ? void 0 : options.bootstrap) === null || _a === void 0 ? void 0 : _a.distinctId) {
759
+ if ((_b = options === null || options === void 0 ? void 0 : options.bootstrap) === null || _b === void 0 ? void 0 : _b.isIdentifiedId) {
760
+ this.setPersistedProperty(PostHogPersistedProperty.DistinctId, options.bootstrap.distinctId);
761
+ }
762
+ else {
763
+ this.setPersistedProperty(PostHogPersistedProperty.AnonymousId, options.bootstrap.distinctId);
764
+ }
765
+ }
766
+ if ((_c = options === null || options === void 0 ? void 0 : options.bootstrap) === null || _c === void 0 ? void 0 : _c.featureFlags) {
767
+ var activeFlags = Object.keys(((_d = options.bootstrap) === null || _d === void 0 ? void 0 : _d.featureFlags) || {})
768
+ .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]); })
769
+ .reduce(function (res, key) {
770
+ var _a, _b;
771
+ 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);
772
+ }, {});
773
+ this.setKnownFeatureFlags(activeFlags);
774
+ }
775
+ };
755
776
  Object.defineProperty(PostHogCore.prototype, "props", {
756
777
  // NOTE: Props are lazy loaded from localstorage hence the complex getter setter logic
757
778
  get: function () {
@@ -995,8 +1016,7 @@ var PostHogCore = /** @class */ (function () {
995
1016
  .then(function (r) { return r.json(); })
996
1017
  .then(function (res) {
997
1018
  if (res.featureFlags) {
998
- _this.setPersistedProperty(PostHogPersistedProperty.FeatureFlags, res.featureFlags);
999
- _this._events.emit('featureflags', res.featureFlags);
1019
+ _this.setKnownFeatureFlags(res.featureFlags);
1000
1020
  }
1001
1021
  return res;
1002
1022
  })
@@ -1007,6 +1027,10 @@ var PostHogCore = /** @class */ (function () {
1007
1027
  });
1008
1028
  });
1009
1029
  };
1030
+ PostHogCore.prototype.setKnownFeatureFlags = function (featureFlags) {
1031
+ this.setPersistedProperty(PostHogPersistedProperty.FeatureFlags, featureFlags);
1032
+ this._events.emit('featureflags', featureFlags);
1033
+ };
1010
1034
  PostHogCore.prototype.getFeatureFlag = function (key) {
1011
1035
  var featureFlags = this.getFeatureFlags();
1012
1036
  if (!featureFlags) {
@@ -1194,10 +1218,19 @@ var PostHogCore = /** @class */ (function () {
1194
1218
  });
1195
1219
  };
1196
1220
  PostHogCore.prototype.fetchWithRetry = function (url, options, retryOptions) {
1221
+ var _a;
1222
+ var _b;
1197
1223
  return __awaiter(this, void 0, void 0, function () {
1198
1224
  var _this = this;
1199
- return __generator(this, function (_a) {
1200
- return [2 /*return*/, retriable(function () { return _this.fetch(url, options); }, retryOptions || this._retryOptions)];
1225
+ return __generator(this, function (_c) {
1226
+ (_a = (_b = AbortSignal).timeout) !== null && _a !== void 0 ? _a : (_b.timeout = function timeout(ms) {
1227
+ var ctrl = new AbortController();
1228
+ setTimeout(function () { return ctrl.abort(); }, ms);
1229
+ return ctrl.signal;
1230
+ });
1231
+ return [2 /*return*/, retriable(function () {
1232
+ return _this.fetch(url, __assign({ signal: AbortSignal.timeout(_this.requestTimeout) }, options));
1233
+ }, retryOptions || this._retryOptions)];
1201
1234
  });
1202
1235
  });
1203
1236
  };
@@ -1497,16 +1530,44 @@ function () {
1497
1530
  };
1498
1531
 
1499
1532
  FeatureFlagsPoller.prototype.matchFeatureFlagProperties = function (flag, distinctId, properties) {
1500
- var _this = this;
1533
+ var _a;
1501
1534
 
1502
1535
  var flagFilters = flag.filters || {};
1503
1536
  var flagConditions = flagFilters.groups || [];
1504
1537
  var isInconclusive = false;
1505
- var result = undefined;
1506
- flagConditions.forEach(function (condition) {
1538
+ var result = undefined; // # Stable sort conditions with variant overrides to the top. This ensures that if overrides are present, they are
1539
+ // # evaluated first, and the variant override is applied to the first matching condition.
1540
+
1541
+ var sortedFlagConditions = __spreadArray([], flagConditions, true).sort(function (conditionA, conditionB) {
1542
+ var AHasVariantOverride = !!conditionA.variant;
1543
+ var BHasVariantOverride = !!conditionB.variant;
1544
+
1545
+ if (AHasVariantOverride && BHasVariantOverride) {
1546
+ return 0;
1547
+ } else if (AHasVariantOverride) {
1548
+ return -1;
1549
+ } else if (BHasVariantOverride) {
1550
+ return 1;
1551
+ } else {
1552
+ return 0;
1553
+ }
1554
+ });
1555
+
1556
+ var _loop_1 = function (condition) {
1507
1557
  try {
1508
- if (_this.isConditionMatch(flag, distinctId, condition, properties)) {
1509
- result = _this.getMatchingVariant(flag, distinctId) || true;
1558
+ if (this_1.isConditionMatch(flag, distinctId, condition, properties)) {
1559
+ var variantOverride_1 = condition.variant;
1560
+ var flagVariants = ((_a = flagFilters.multivariate) === null || _a === void 0 ? void 0 : _a.variants) || [];
1561
+
1562
+ if (variantOverride_1 && flagVariants.some(function (variant) {
1563
+ return variant.key === variantOverride_1;
1564
+ })) {
1565
+ result = variantOverride_1;
1566
+ } else {
1567
+ result = this_1.getMatchingVariant(flag, distinctId) || true;
1568
+ }
1569
+
1570
+ return "break";
1510
1571
  }
1511
1572
  } catch (e) {
1512
1573
  if (e instanceof InconclusiveMatchError) {
@@ -1515,7 +1576,17 @@ function () {
1515
1576
  throw e;
1516
1577
  }
1517
1578
  }
1518
- });
1579
+ };
1580
+
1581
+ var this_1 = this;
1582
+
1583
+ for (var _i = 0, sortedFlagConditions_1 = sortedFlagConditions; _i < sortedFlagConditions_1.length; _i++) {
1584
+ var condition = sortedFlagConditions_1[_i];
1585
+
1586
+ var state_1 = _loop_1(condition);
1587
+
1588
+ if (state_1 === "break") break;
1589
+ }
1519
1590
 
1520
1591
  if (result !== undefined) {
1521
1592
  return result;
@@ -1812,6 +1883,17 @@ function matchProperty(property, propertyValues) {
1812
1883
  case 'lte':
1813
1884
  return typeof overrideValue == typeof value && overrideValue <= value;
1814
1885
 
1886
+ case 'is_date_after':
1887
+ case 'is_date_before':
1888
+ var parsedDate = convertToDateTime(value);
1889
+ var overrideDate = convertToDateTime(overrideValue);
1890
+
1891
+ if (operator === 'is_date_before') {
1892
+ return overrideDate < parsedDate;
1893
+ }
1894
+
1895
+ return overrideDate > parsedDate;
1896
+
1815
1897
  default:
1816
1898
  console.error("Unknown operator: ".concat(operator));
1817
1899
  return false;
@@ -1827,6 +1909,22 @@ function isValidRegex(regex) {
1827
1909
  }
1828
1910
  }
1829
1911
 
1912
+ function convertToDateTime(value) {
1913
+ if (value instanceof Date) {
1914
+ return value;
1915
+ } else if (typeof value === 'string' || typeof value === 'number') {
1916
+ var date = new Date(value);
1917
+
1918
+ if (!isNaN(date.valueOf())) {
1919
+ return date;
1920
+ }
1921
+
1922
+ throw new InconclusiveMatchError("".concat(value, " is in an invalid date format"));
1923
+ } else {
1924
+ throw new InconclusiveMatchError("The date provided ".concat(value, " must be a string, number, or date object"));
1925
+ }
1926
+ }
1927
+
1830
1928
  var THIRTY_SECONDS = 30 * 1000;
1831
1929
  var MAX_CACHE_SIZE = 50 * 1000;
1832
1930
 
@@ -1894,6 +1992,8 @@ function () {
1894
1992
  options = {};
1895
1993
  }
1896
1994
 
1995
+ var _a;
1996
+
1897
1997
  this._sharedClient = new PostHogClient(apiKey, options);
1898
1998
 
1899
1999
  if (options.personalApiKey) {
@@ -1901,7 +2001,7 @@ function () {
1901
2001
  pollingInterval: typeof options.featureFlagsPollingInterval === 'number' ? options.featureFlagsPollingInterval : THIRTY_SECONDS,
1902
2002
  personalApiKey: options.personalApiKey,
1903
2003
  projectApiKey: apiKey,
1904
- timeout: options.requestTimeout,
2004
+ timeout: (_a = options.requestTimeout) !== null && _a !== void 0 ? _a : 10,
1905
2005
  host: this._sharedClient.host,
1906
2006
  fetch: options.fetch
1907
2007
  });