posthog-node 4.2.0 → 4.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.cjs.js CHANGED
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var rusha = require('rusha');
6
6
 
7
- var version = "4.2.0";
7
+ var version = "4.2.1";
8
8
 
9
9
  var PostHogPersistedProperty;
10
10
  (function (PostHogPersistedProperty) {
@@ -22,6 +22,7 @@ var PostHogPersistedProperty;
22
22
  PostHogPersistedProperty["GroupProperties"] = "group_properties";
23
23
  PostHogPersistedProperty["InstalledAppBuild"] = "installed_app_build";
24
24
  PostHogPersistedProperty["InstalledAppVersion"] = "installed_app_version";
25
+ PostHogPersistedProperty["SessionReplay"] = "session_replay";
25
26
  })(PostHogPersistedProperty || (PostHogPersistedProperty = {}));
26
27
 
27
28
  function assert(truthyValue, message) {
@@ -966,7 +967,7 @@ class PostHogCoreStateless {
966
967
  this.maxBatchSize = Math.max(this.flushAt, options?.maxBatchSize ?? 100);
967
968
  this.maxQueueSize = Math.max(this.flushAt, options?.maxQueueSize ?? 1000);
968
969
  this.flushInterval = options?.flushInterval ?? 10000;
969
- this.captureMode = options?.captureMode || 'form';
970
+ this.captureMode = options?.captureMode || 'json';
970
971
  // If enable is explicitly set to false we override the optout
971
972
  this.defaultOptIn = options?.defaultOptIn ?? true;
972
973
  this._retryOptions = {
@@ -983,11 +984,14 @@ class PostHogCoreStateless {
983
984
  this._initPromise = Promise.resolve();
984
985
  this._isInitialized = true;
985
986
  }
987
+ logMsgIfDebug(fn) {
988
+ if (this.isDebug) {
989
+ fn();
990
+ }
991
+ }
986
992
  wrap(fn) {
987
993
  if (this.disabled) {
988
- if (this.isDebug) {
989
- console.warn('[PostHog] The client is disabled');
990
- }
994
+ this.logMsgIfDebug(() => console.warn('[PostHog] The client is disabled'));
991
995
  return;
992
996
  }
993
997
  if (this._isInitialized) {
@@ -1227,7 +1231,7 @@ class PostHogCoreStateless {
1227
1231
  const queue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
1228
1232
  if (queue.length >= this.maxQueueSize) {
1229
1233
  queue.shift();
1230
- console.info('Queue is full, the oldest event is dropped.');
1234
+ this.logMsgIfDebug(() => console.info('Queue is full, the oldest event is dropped.'));
1231
1235
  }
1232
1236
  queue.push({ message });
1233
1237
  this.setPersistedProperty(PostHogPersistedProperty.Queue, queue);
@@ -1384,7 +1388,7 @@ class PostHogCoreStateless {
1384
1388
  if (!isPostHogFetchError(e)) {
1385
1389
  throw e;
1386
1390
  }
1387
- console.error('Error while shutting down PostHog', e);
1391
+ this.logMsgIfDebug(() => console.error('Error while shutting down PostHog', e));
1388
1392
  }
1389
1393
  }
1390
1394
  }
@@ -1409,14 +1413,13 @@ class PostHogMemoryStorage {
1409
1413
  * This is currently solved by using the global fetch if available instead.
1410
1414
  * See https://github.com/PostHog/posthog-js-lite/issues/127 for more info
1411
1415
  */
1412
- let _fetch = // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
1416
+ let _fetch =
1417
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
1413
1418
  // @ts-ignore
1414
1419
  typeof fetch !== 'undefined' ? fetch : typeof global.fetch !== 'undefined' ? global.fetch : undefined;
1415
-
1416
1420
  if (!_fetch) {
1417
1421
  // eslint-disable-next-line @typescript-eslint/no-var-requires
1418
1422
  const axios = require('axios');
1419
-
1420
1423
  _fetch = async (url, options) => {
1421
1424
  const res = await axios.request({
1422
1425
  url,
@@ -1433,14 +1436,13 @@ if (!_fetch) {
1433
1436
  json: async () => res.data
1434
1437
  };
1435
1438
  };
1436
- } // NOTE: We have to export this as default, even though we prefer named exports as we are relying on detecting "fetch" in the global scope
1437
-
1438
-
1439
+ }
1440
+ // NOTE: We have to export this as default, even though we prefer named exports as we are relying on detecting "fetch" in the global scope
1439
1441
  var fetch$1 = _fetch;
1440
1442
 
1443
+ // eslint-disable-next-line
1441
1444
  const LONG_SCALE = 0xfffffffffffffff;
1442
1445
  const NULL_VALUES_ALLOWED_OPERATORS = ['is_not'];
1443
-
1444
1446
  class ClientError extends Error {
1445
1447
  constructor(message) {
1446
1448
  super();
@@ -1449,22 +1451,18 @@ class ClientError extends Error {
1449
1451
  this.message = message;
1450
1452
  Object.setPrototypeOf(this, ClientError.prototype);
1451
1453
  }
1452
-
1453
1454
  }
1454
-
1455
1455
  class InconclusiveMatchError extends Error {
1456
1456
  constructor(message) {
1457
1457
  super(message);
1458
1458
  this.name = this.constructor.name;
1459
- Error.captureStackTrace(this, this.constructor); // instanceof doesn't work in ES3 or ES5
1459
+ Error.captureStackTrace(this, this.constructor);
1460
+ // instanceof doesn't work in ES3 or ES5
1460
1461
  // https://www.dannyguo.com/blog/how-to-fix-instanceof-not-working-for-custom-errors-in-typescript/
1461
1462
  // this is the workaround
1462
-
1463
1463
  Object.setPrototypeOf(this, InconclusiveMatchError.prototype);
1464
1464
  }
1465
-
1466
1465
  }
1467
-
1468
1466
  class FeatureFlagsPoller {
1469
1467
  constructor({
1470
1468
  pollingInterval,
@@ -1486,81 +1484,69 @@ class FeatureFlagsPoller {
1486
1484
  this.timeout = timeout;
1487
1485
  this.projectApiKey = projectApiKey;
1488
1486
  this.host = host;
1489
- this.poller = undefined; // NOTE: as any is required here as the AbortSignal typing is slightly misaligned but works just fine
1490
-
1487
+ this.poller = undefined;
1488
+ // NOTE: as any is required here as the AbortSignal typing is slightly misaligned but works just fine
1491
1489
  this.fetch = options.fetch || fetch$1;
1492
1490
  this.onError = options.onError;
1493
1491
  this.customHeaders = customHeaders;
1494
1492
  void this.loadFeatureFlags();
1495
1493
  }
1496
-
1497
1494
  debug(enabled = true) {
1498
1495
  this.debugMode = enabled;
1499
1496
  }
1500
-
1497
+ logMsgIfDebug(fn) {
1498
+ if (this.debugMode) {
1499
+ fn();
1500
+ }
1501
+ }
1501
1502
  async getFeatureFlag(key, distinctId, groups = {}, personProperties = {}, groupProperties = {}) {
1502
1503
  await this.loadFeatureFlags();
1503
1504
  let response = undefined;
1504
1505
  let featureFlag = undefined;
1505
-
1506
1506
  if (!this.loadedSuccessfullyOnce) {
1507
1507
  return response;
1508
1508
  }
1509
-
1510
1509
  for (const flag of this.featureFlags) {
1511
1510
  if (key === flag.key) {
1512
1511
  featureFlag = flag;
1513
1512
  break;
1514
1513
  }
1515
1514
  }
1516
-
1517
1515
  if (featureFlag !== undefined) {
1518
1516
  try {
1519
1517
  response = this.computeFlagLocally(featureFlag, distinctId, groups, personProperties, groupProperties);
1520
-
1521
- if (this.debugMode) {
1522
- console.debug(`Successfully computed flag locally: ${key} -> ${response}`);
1523
- }
1518
+ this.logMsgIfDebug(() => console.debug(`Successfully computed flag locally: ${key} -> ${response}`));
1524
1519
  } catch (e) {
1525
1520
  if (e instanceof InconclusiveMatchError) {
1526
- if (this.debugMode) {
1527
- console.debug(`InconclusiveMatchError when computing flag locally: ${key}: ${e}`);
1528
- }
1521
+ this.logMsgIfDebug(() => console.debug(`InconclusiveMatchError when computing flag locally: ${key}: ${e}`));
1529
1522
  } else if (e instanceof Error) {
1530
1523
  this.onError?.(new Error(`Error computing flag locally: ${key}: ${e}`));
1531
1524
  }
1532
1525
  }
1533
1526
  }
1534
-
1535
1527
  return response;
1536
1528
  }
1537
-
1538
1529
  async computeFeatureFlagPayloadLocally(key, matchValue) {
1539
1530
  await this.loadFeatureFlags();
1540
1531
  let response = undefined;
1541
-
1542
1532
  if (!this.loadedSuccessfullyOnce) {
1543
1533
  return undefined;
1544
1534
  }
1545
-
1546
1535
  if (typeof matchValue == 'boolean') {
1547
1536
  response = this.featureFlagsByKey?.[key]?.filters?.payloads?.[matchValue.toString()];
1548
1537
  } else if (typeof matchValue == 'string') {
1549
1538
  response = this.featureFlagsByKey?.[key]?.filters?.payloads?.[matchValue];
1550
- } // Undefined means a loading or missing data issue. Null means evaluation happened and there was no match
1551
-
1552
-
1539
+ }
1540
+ // Undefined means a loading or missing data issue. Null means evaluation happened and there was no match
1553
1541
  if (response === undefined || response === null) {
1554
1542
  return null;
1555
1543
  }
1556
-
1557
1544
  try {
1558
1545
  return JSON.parse(response);
1559
1546
  } catch {
1560
1547
  return response;
1561
1548
  }
1562
1549
  }
1563
-
1564
1550
  async getAllFlagsAndPayloads(distinctId, groups = {}, personProperties = {}, groupProperties = {}) {
1565
1551
  await this.loadFeatureFlags();
1566
1552
  const response = {};
@@ -1571,7 +1557,6 @@ class FeatureFlagsPoller {
1571
1557
  const matchValue = this.computeFlagLocally(flag, distinctId, groups, personProperties, groupProperties);
1572
1558
  response[flag.key] = matchValue;
1573
1559
  const matchPayload = await this.computeFeatureFlagPayloadLocally(flag.key, matchValue);
1574
-
1575
1560
  if (matchPayload) {
1576
1561
  payloads[flag.key] = matchPayload;
1577
1562
  }
@@ -1579,7 +1564,6 @@ class FeatureFlagsPoller {
1579
1564
  if (e instanceof InconclusiveMatchError) ; else if (e instanceof Error) {
1580
1565
  this.onError?.(new Error(`Error computing flag locally: ${flag.key}: ${e}`));
1581
1566
  }
1582
-
1583
1567
  fallbackToDecide = true;
1584
1568
  }
1585
1569
  });
@@ -1589,56 +1573,41 @@ class FeatureFlagsPoller {
1589
1573
  fallbackToDecide
1590
1574
  };
1591
1575
  }
1592
-
1593
1576
  computeFlagLocally(flag, distinctId, groups = {}, personProperties = {}, groupProperties = {}) {
1594
1577
  if (flag.ensure_experience_continuity) {
1595
1578
  throw new InconclusiveMatchError('Flag has experience continuity enabled');
1596
1579
  }
1597
-
1598
1580
  if (!flag.active) {
1599
1581
  return false;
1600
1582
  }
1601
-
1602
1583
  const flagFilters = flag.filters || {};
1603
1584
  const aggregation_group_type_index = flagFilters.aggregation_group_type_index;
1604
-
1605
1585
  if (aggregation_group_type_index != undefined) {
1606
1586
  const groupName = this.groupTypeMapping[String(aggregation_group_type_index)];
1607
-
1608
1587
  if (!groupName) {
1609
- if (this.debugMode) {
1610
- console.warn(`[FEATURE FLAGS] Unknown group type index ${aggregation_group_type_index} for feature flag ${flag.key}`);
1611
- }
1612
-
1588
+ this.logMsgIfDebug(() => console.warn(`[FEATURE FLAGS] Unknown group type index ${aggregation_group_type_index} for feature flag ${flag.key}`));
1613
1589
  throw new InconclusiveMatchError('Flag has unknown group type index');
1614
1590
  }
1615
-
1616
1591
  if (!(groupName in groups)) {
1617
- if (this.debugMode) {
1618
- console.warn(`[FEATURE FLAGS] Can't compute group feature flag: ${flag.key} without group names passed in`);
1619
- }
1620
-
1592
+ this.logMsgIfDebug(() => console.warn(`[FEATURE FLAGS] Can't compute group feature flag: ${flag.key} without group names passed in`));
1621
1593
  return false;
1622
1594
  }
1623
-
1624
1595
  const focusedGroupProperties = groupProperties[groupName];
1625
1596
  return this.matchFeatureFlagProperties(flag, groups[groupName], focusedGroupProperties);
1626
1597
  } else {
1627
1598
  return this.matchFeatureFlagProperties(flag, distinctId, personProperties);
1628
1599
  }
1629
1600
  }
1630
-
1631
1601
  matchFeatureFlagProperties(flag, distinctId, properties) {
1632
1602
  const flagFilters = flag.filters || {};
1633
1603
  const flagConditions = flagFilters.groups || [];
1634
1604
  let isInconclusive = false;
1635
- let result = undefined; // # Stable sort conditions with variant overrides to the top. This ensures that if overrides are present, they are
1605
+ let result = undefined;
1606
+ // # Stable sort conditions with variant overrides to the top. This ensures that if overrides are present, they are
1636
1607
  // # evaluated first, and the variant override is applied to the first matching condition.
1637
-
1638
1608
  const sortedFlagConditions = [...flagConditions].sort((conditionA, conditionB) => {
1639
1609
  const AHasVariantOverride = !!conditionA.variant;
1640
1610
  const BHasVariantOverride = !!conditionB.variant;
1641
-
1642
1611
  if (AHasVariantOverride && BHasVariantOverride) {
1643
1612
  return 0;
1644
1613
  } else if (AHasVariantOverride) {
@@ -1649,19 +1618,16 @@ class FeatureFlagsPoller {
1649
1618
  return 0;
1650
1619
  }
1651
1620
  });
1652
-
1653
1621
  for (const condition of sortedFlagConditions) {
1654
1622
  try {
1655
1623
  if (this.isConditionMatch(flag, distinctId, condition, properties)) {
1656
1624
  const variantOverride = condition.variant;
1657
1625
  const flagVariants = flagFilters.multivariate?.variants || [];
1658
-
1659
1626
  if (variantOverride && flagVariants.some(variant => variant.key === variantOverride)) {
1660
1627
  result = variantOverride;
1661
1628
  } else {
1662
1629
  result = this.getMatchingVariant(flag, distinctId) || true;
1663
1630
  }
1664
-
1665
1631
  break;
1666
1632
  }
1667
1633
  } catch (e) {
@@ -1672,68 +1638,51 @@ class FeatureFlagsPoller {
1672
1638
  }
1673
1639
  }
1674
1640
  }
1675
-
1676
1641
  if (result !== undefined) {
1677
1642
  return result;
1678
1643
  } else if (isInconclusive) {
1679
1644
  throw new InconclusiveMatchError("Can't determine if feature flag is enabled or not with given properties");
1680
- } // We can only return False when all conditions are False
1681
-
1682
-
1645
+ }
1646
+ // We can only return False when all conditions are False
1683
1647
  return false;
1684
1648
  }
1685
-
1686
1649
  isConditionMatch(flag, distinctId, condition, properties) {
1687
1650
  const rolloutPercentage = condition.rollout_percentage;
1688
-
1689
1651
  const warnFunction = msg => {
1690
- if (this.debugMode) {
1691
- console.warn(msg);
1692
- }
1652
+ this.logMsgIfDebug(() => console.warn(msg));
1693
1653
  };
1694
-
1695
1654
  if ((condition.properties || []).length > 0) {
1696
1655
  for (const prop of condition.properties) {
1697
1656
  const propertyType = prop.type;
1698
1657
  let matches = false;
1699
-
1700
1658
  if (propertyType === 'cohort') {
1701
1659
  matches = matchCohort(prop, properties, this.cohorts, this.debugMode);
1702
1660
  } else {
1703
1661
  matches = matchProperty(prop, properties, warnFunction);
1704
1662
  }
1705
-
1706
1663
  if (!matches) {
1707
1664
  return false;
1708
1665
  }
1709
1666
  }
1710
-
1711
1667
  if (rolloutPercentage == undefined) {
1712
1668
  return true;
1713
1669
  }
1714
1670
  }
1715
-
1716
1671
  if (rolloutPercentage != undefined && _hash(flag.key, distinctId) > rolloutPercentage / 100.0) {
1717
1672
  return false;
1718
1673
  }
1719
-
1720
1674
  return true;
1721
1675
  }
1722
-
1723
1676
  getMatchingVariant(flag, distinctId) {
1724
1677
  const hashValue = _hash(flag.key, distinctId, 'variant');
1725
-
1726
1678
  const matchingVariant = this.variantLookupTable(flag).find(variant => {
1727
1679
  return hashValue >= variant.valueMin && hashValue < variant.valueMax;
1728
1680
  });
1729
-
1730
1681
  if (matchingVariant) {
1731
1682
  return matchingVariant.key;
1732
1683
  }
1733
-
1734
1684
  return undefined;
1735
1685
  }
1736
-
1737
1686
  variantLookupTable(flag) {
1738
1687
  const lookupTable = [];
1739
1688
  let valueMin = 0;
@@ -1751,40 +1700,31 @@ class FeatureFlagsPoller {
1751
1700
  });
1752
1701
  return lookupTable;
1753
1702
  }
1754
-
1755
1703
  async loadFeatureFlags(forceReload = false) {
1756
1704
  if (!this.loadedSuccessfullyOnce || forceReload) {
1757
1705
  await this._loadFeatureFlags();
1758
1706
  }
1759
1707
  }
1760
-
1761
1708
  async _loadFeatureFlags() {
1762
1709
  if (this.poller) {
1763
1710
  clearTimeout(this.poller);
1764
1711
  this.poller = undefined;
1765
1712
  }
1766
-
1767
1713
  this.poller = setTimeout(() => this._loadFeatureFlags(), this.pollingInterval);
1768
-
1769
1714
  try {
1770
1715
  const res = await this._requestFeatureFlagDefinitions();
1771
-
1772
1716
  if (res && res.status === 401) {
1773
1717
  throw new ClientError(`Your personalApiKey is invalid. Are you sure you're not using your Project API key? More information: https://posthog.com/docs/api/overview`);
1774
1718
  }
1775
-
1776
1719
  if (res && res.status !== 200) {
1777
1720
  // something else went wrong, or the server is down.
1778
1721
  // In this case, don't override existing flags
1779
1722
  return;
1780
1723
  }
1781
-
1782
1724
  const responseJson = await res.json();
1783
-
1784
1725
  if (!('flags' in responseJson)) {
1785
1726
  this.onError?.(new Error(`Invalid response when getting feature flags: ${JSON.stringify(responseJson)}`));
1786
1727
  }
1787
-
1788
1728
  this.featureFlags = responseJson.flags || [];
1789
1729
  this.featureFlagsByKey = this.featureFlags.reduce((acc, curr) => (acc[curr.key] = curr, acc), {});
1790
1730
  this.groupTypeMapping = responseJson.group_type_mapping || {};
@@ -1798,18 +1738,17 @@ class FeatureFlagsPoller {
1798
1738
  }
1799
1739
  }
1800
1740
  }
1801
-
1802
1741
  async _requestFeatureFlagDefinitions() {
1803
1742
  const url = `${this.host}/api/feature_flag/local_evaluation?token=${this.projectApiKey}&send_cohorts`;
1804
1743
  const options = {
1805
1744
  method: 'GET',
1806
- headers: { ...this.customHeaders,
1745
+ headers: {
1746
+ ...this.customHeaders,
1807
1747
  'Content-Type': 'application/json',
1808
1748
  Authorization: `Bearer ${this.personalApiKey}`
1809
1749
  }
1810
1750
  };
1811
1751
  let abortTimeout = null;
1812
-
1813
1752
  if (this.timeout && typeof this.timeout === 'number') {
1814
1753
  const controller = new AbortController();
1815
1754
  abortTimeout = safeSetTimeout(() => {
@@ -1817,62 +1756,50 @@ class FeatureFlagsPoller {
1817
1756
  }, this.timeout);
1818
1757
  options.signal = controller.signal;
1819
1758
  }
1820
-
1821
1759
  try {
1822
1760
  return await this.fetch(url, options);
1823
1761
  } finally {
1824
1762
  clearTimeout(abortTimeout);
1825
1763
  }
1826
1764
  }
1827
-
1828
1765
  stopPoller() {
1829
1766
  clearTimeout(this.poller);
1830
1767
  }
1831
-
1832
- } // # This function takes a distinct_id and a feature flag key and returns a float between 0 and 1.
1768
+ }
1769
+ // # This function takes a distinct_id and a feature flag key and returns a float between 0 and 1.
1833
1770
  // # Given the same distinct_id and key, it'll always return the same float. These floats are
1834
1771
  // # uniformly distributed between 0 and 1, so if we want to show this feature to 20% of traffic
1835
1772
  // # we can do _hash(key, distinct_id) < 0.2
1836
-
1837
-
1838
1773
  function _hash(key, distinctId, salt = '') {
1839
1774
  // rusha is a fast sha1 implementation in pure javascript
1840
1775
  const sha1Hash = rusha.createHash();
1841
1776
  sha1Hash.update(`${key}.${distinctId}${salt}`);
1842
1777
  return parseInt(sha1Hash.digest('hex').slice(0, 15), 16) / LONG_SCALE;
1843
1778
  }
1844
-
1845
1779
  function matchProperty(property, propertyValues, warnFunction) {
1846
1780
  const key = property.key;
1847
1781
  const value = property.value;
1848
1782
  const operator = property.operator || 'exact';
1849
-
1850
1783
  if (!(key in propertyValues)) {
1851
1784
  throw new InconclusiveMatchError(`Property ${key} not found in propertyValues`);
1852
1785
  } else if (operator === 'is_not_set') {
1853
1786
  throw new InconclusiveMatchError(`Operator is_not_set is not supported`);
1854
1787
  }
1855
-
1856
1788
  const overrideValue = propertyValues[key];
1857
-
1858
1789
  if (overrideValue == null && !NULL_VALUES_ALLOWED_OPERATORS.includes(operator)) {
1859
1790
  // if the value is null, just fail the feature flag comparison
1860
1791
  // this isn't an InconclusiveMatchError because the property value was provided.
1861
1792
  if (warnFunction) {
1862
1793
  warnFunction(`Property ${key} cannot have a value of null/undefined with the ${operator} operator`);
1863
1794
  }
1864
-
1865
1795
  return false;
1866
1796
  }
1867
-
1868
1797
  function computeExactMatch(value, overrideValue) {
1869
1798
  if (Array.isArray(value)) {
1870
1799
  return value.map(val => String(val).toLowerCase()).includes(String(overrideValue).toLowerCase());
1871
1800
  }
1872
-
1873
1801
  return String(value).toLowerCase() === String(overrideValue).toLowerCase();
1874
1802
  }
1875
-
1876
1803
  function compare(lhs, rhs, operator) {
1877
1804
  if (operator === 'gt') {
1878
1805
  return lhs > rhs;
@@ -1886,29 +1813,21 @@ function matchProperty(property, propertyValues, warnFunction) {
1886
1813
  throw new Error(`Invalid operator: ${operator}`);
1887
1814
  }
1888
1815
  }
1889
-
1890
1816
  switch (operator) {
1891
1817
  case 'exact':
1892
1818
  return computeExactMatch(value, overrideValue);
1893
-
1894
1819
  case 'is_not':
1895
1820
  return !computeExactMatch(value, overrideValue);
1896
-
1897
1821
  case 'is_set':
1898
1822
  return key in propertyValues;
1899
-
1900
1823
  case 'icontains':
1901
1824
  return String(overrideValue).toLowerCase().includes(String(value).toLowerCase());
1902
-
1903
1825
  case 'not_icontains':
1904
1826
  return !String(overrideValue).toLowerCase().includes(String(value).toLowerCase());
1905
-
1906
1827
  case 'regex':
1907
1828
  return isValidRegex(String(value)) && String(overrideValue).match(String(value)) !== null;
1908
-
1909
1829
  case 'not_regex':
1910
1830
  return isValidRegex(String(value)) && String(overrideValue).match(String(value)) === null;
1911
-
1912
1831
  case 'gt':
1913
1832
  case 'gte':
1914
1833
  case 'lt':
@@ -1917,14 +1836,13 @@ function matchProperty(property, propertyValues, warnFunction) {
1917
1836
  // :TRICKY: We adjust comparison based on the override value passed in,
1918
1837
  // to make sure we handle both numeric and string comparisons appropriately.
1919
1838
  let parsedValue = typeof value === 'number' ? value : null;
1920
-
1921
1839
  if (typeof value === 'string') {
1922
1840
  try {
1923
1841
  parsedValue = parseFloat(value);
1924
- } catch (err) {// pass
1842
+ } catch (err) {
1843
+ // pass
1925
1844
  }
1926
1845
  }
1927
-
1928
1846
  if (parsedValue != null && overrideValue != null) {
1929
1847
  // check both null and undefined
1930
1848
  if (typeof overrideValue === 'string') {
@@ -1936,66 +1854,50 @@ function matchProperty(property, propertyValues, warnFunction) {
1936
1854
  return compare(String(overrideValue), String(value), operator);
1937
1855
  }
1938
1856
  }
1939
-
1940
1857
  case 'is_date_after':
1941
1858
  case 'is_date_before':
1942
1859
  {
1943
1860
  let parsedDate = relativeDateParseForFeatureFlagMatching(String(value));
1944
-
1945
1861
  if (parsedDate == null) {
1946
1862
  parsedDate = convertToDateTime(value);
1947
1863
  }
1948
-
1949
1864
  if (parsedDate == null) {
1950
1865
  throw new InconclusiveMatchError(`Invalid date: ${value}`);
1951
1866
  }
1952
-
1953
1867
  const overrideDate = convertToDateTime(overrideValue);
1954
-
1955
1868
  if (['is_date_before'].includes(operator)) {
1956
1869
  return overrideDate < parsedDate;
1957
1870
  }
1958
-
1959
1871
  return overrideDate > parsedDate;
1960
1872
  }
1961
-
1962
1873
  default:
1963
1874
  throw new InconclusiveMatchError(`Unknown operator: ${operator}`);
1964
1875
  }
1965
1876
  }
1966
-
1967
1877
  function matchCohort(property, propertyValues, cohortProperties, debugMode = false) {
1968
1878
  const cohortId = String(property.value);
1969
-
1970
1879
  if (!(cohortId in cohortProperties)) {
1971
1880
  throw new InconclusiveMatchError("can't match cohort without a given cohort property value");
1972
1881
  }
1973
-
1974
1882
  const propertyGroup = cohortProperties[cohortId];
1975
1883
  return matchPropertyGroup(propertyGroup, propertyValues, cohortProperties, debugMode);
1976
1884
  }
1977
-
1978
1885
  function matchPropertyGroup(propertyGroup, propertyValues, cohortProperties, debugMode = false) {
1979
1886
  if (!propertyGroup) {
1980
1887
  return true;
1981
1888
  }
1982
-
1983
1889
  const propertyGroupType = propertyGroup.type;
1984
1890
  const properties = propertyGroup.values;
1985
-
1986
1891
  if (!properties || properties.length === 0) {
1987
1892
  // empty groups are no-ops, always match
1988
1893
  return true;
1989
1894
  }
1990
-
1991
1895
  let errorMatchingLocally = false;
1992
-
1993
1896
  if ('values' in properties[0]) {
1994
1897
  // a nested property group
1995
1898
  for (const prop of properties) {
1996
1899
  try {
1997
1900
  const matches = matchPropertyGroup(prop, propertyValues, cohortProperties, debugMode);
1998
-
1999
1901
  if (propertyGroupType === 'AND') {
2000
1902
  if (!matches) {
2001
1903
  return false;
@@ -2011,39 +1913,32 @@ function matchPropertyGroup(propertyGroup, propertyValues, cohortProperties, deb
2011
1913
  if (debugMode) {
2012
1914
  console.debug(`Failed to compute property ${prop} locally: ${err}`);
2013
1915
  }
2014
-
2015
1916
  errorMatchingLocally = true;
2016
1917
  } else {
2017
1918
  throw err;
2018
1919
  }
2019
1920
  }
2020
1921
  }
2021
-
2022
1922
  if (errorMatchingLocally) {
2023
1923
  throw new InconclusiveMatchError("Can't match cohort without a given cohort property value");
2024
- } // if we get here, all matched in AND case, or none matched in OR case
2025
-
2026
-
1924
+ }
1925
+ // if we get here, all matched in AND case, or none matched in OR case
2027
1926
  return propertyGroupType === 'AND';
2028
1927
  } else {
2029
1928
  for (const prop of properties) {
2030
1929
  try {
2031
1930
  let matches;
2032
-
2033
1931
  if (prop.type === 'cohort') {
2034
1932
  matches = matchCohort(prop, propertyValues, cohortProperties, debugMode);
2035
1933
  } else {
2036
1934
  matches = matchProperty(prop, propertyValues);
2037
1935
  }
2038
-
2039
1936
  const negation = prop.negation || false;
2040
-
2041
1937
  if (propertyGroupType === 'AND') {
2042
1938
  // if negated property, do the inverse
2043
1939
  if (!matches && !negation) {
2044
1940
  return false;
2045
1941
  }
2046
-
2047
1942
  if (matches && negation) {
2048
1943
  return false;
2049
1944
  }
@@ -2052,7 +1947,6 @@ function matchPropertyGroup(propertyGroup, propertyValues, cohortProperties, deb
2052
1947
  if (matches && !negation) {
2053
1948
  return true;
2054
1949
  }
2055
-
2056
1950
  if (!matches && negation) {
2057
1951
  return true;
2058
1952
  }
@@ -2062,23 +1956,19 @@ function matchPropertyGroup(propertyGroup, propertyValues, cohortProperties, deb
2062
1956
  if (debugMode) {
2063
1957
  console.debug(`Failed to compute property ${prop} locally: ${err}`);
2064
1958
  }
2065
-
2066
1959
  errorMatchingLocally = true;
2067
1960
  } else {
2068
1961
  throw err;
2069
1962
  }
2070
1963
  }
2071
1964
  }
2072
-
2073
1965
  if (errorMatchingLocally) {
2074
1966
  throw new InconclusiveMatchError("can't match cohort without a given cohort property value");
2075
- } // if we get here, all matched in AND case, or none matched in OR case
2076
-
2077
-
1967
+ }
1968
+ // if we get here, all matched in AND case, or none matched in OR case
2078
1969
  return propertyGroupType === 'AND';
2079
1970
  }
2080
1971
  }
2081
-
2082
1972
  function isValidRegex(regex) {
2083
1973
  try {
2084
1974
  new RegExp(regex);
@@ -2087,42 +1977,33 @@ function isValidRegex(regex) {
2087
1977
  return false;
2088
1978
  }
2089
1979
  }
2090
-
2091
1980
  function convertToDateTime(value) {
2092
1981
  if (value instanceof Date) {
2093
1982
  return value;
2094
1983
  } else if (typeof value === 'string' || typeof value === 'number') {
2095
1984
  const date = new Date(value);
2096
-
2097
1985
  if (!isNaN(date.valueOf())) {
2098
1986
  return date;
2099
1987
  }
2100
-
2101
1988
  throw new InconclusiveMatchError(`${value} is in an invalid date format`);
2102
1989
  } else {
2103
1990
  throw new InconclusiveMatchError(`The date provided ${value} must be a string, number, or date object`);
2104
1991
  }
2105
1992
  }
2106
-
2107
1993
  function relativeDateParseForFeatureFlagMatching(value) {
2108
1994
  const regex = /^-?(?<number>[0-9]+)(?<interval>[a-z])$/;
2109
1995
  const match = value.match(regex);
2110
1996
  const parsedDt = new Date(new Date().toISOString());
2111
-
2112
1997
  if (match) {
2113
1998
  if (!match.groups) {
2114
1999
  return null;
2115
2000
  }
2116
-
2117
2001
  const number = parseInt(match.groups['number']);
2118
-
2119
2002
  if (number >= 10000) {
2120
2003
  // Guard against overflow, disallow numbers greater than 10_000
2121
2004
  return null;
2122
2005
  }
2123
-
2124
2006
  const interval = match.groups['interval'];
2125
-
2126
2007
  if (interval == 'h') {
2127
2008
  parsedDt.setUTCHours(parsedDt.getUTCHours() - number);
2128
2009
  } else if (interval == 'd') {
@@ -2136,7 +2017,6 @@ function relativeDateParseForFeatureFlagMatching(value) {
2136
2017
  } else {
2137
2018
  return null;
2138
2019
  }
2139
-
2140
2020
  return parsedDt;
2141
2021
  } else {
2142
2022
  return null;
@@ -2144,15 +2024,13 @@ function relativeDateParseForFeatureFlagMatching(value) {
2144
2024
  }
2145
2025
 
2146
2026
  const THIRTY_SECONDS = 30 * 1000;
2147
- const MAX_CACHE_SIZE = 50 * 1000; // The actual exported Nodejs API.
2148
-
2027
+ const MAX_CACHE_SIZE = 50 * 1000;
2028
+ // The actual exported Nodejs API.
2149
2029
  class PostHog extends PostHogCoreStateless {
2150
2030
  constructor(apiKey, options = {}) {
2151
- options.captureMode = options?.captureMode || 'json';
2152
2031
  super(apiKey, options);
2153
2032
  this._memoryStorage = new PostHogMemoryStorage();
2154
2033
  this.options = options;
2155
-
2156
2034
  if (options.personalApiKey) {
2157
2035
  this.featureFlagsPoller = new FeatureFlagsPoller({
2158
2036
  pollingInterval: typeof options.featureFlagsPollingInterval === 'number' ? options.featureFlagsPollingInterval : THIRTY_SECONDS,
@@ -2167,48 +2045,37 @@ class PostHog extends PostHogCoreStateless {
2167
2045
  customHeaders: this.getCustomHeaders()
2168
2046
  });
2169
2047
  }
2170
-
2171
2048
  this.distinctIdHasSentFlagCalls = {};
2172
2049
  this.maxCacheSize = options.maxCacheSize || MAX_CACHE_SIZE;
2173
2050
  }
2174
-
2175
2051
  getPersistedProperty(key) {
2176
2052
  return this._memoryStorage.getProperty(key);
2177
2053
  }
2178
-
2179
2054
  setPersistedProperty(key, value) {
2180
2055
  return this._memoryStorage.setProperty(key, value);
2181
2056
  }
2182
-
2183
2057
  fetch(url, options) {
2184
2058
  return this.options.fetch ? this.options.fetch(url, options) : fetch$1(url, options);
2185
2059
  }
2186
-
2187
2060
  getLibraryId() {
2188
2061
  return 'posthog-node';
2189
2062
  }
2190
-
2191
2063
  getLibraryVersion() {
2192
2064
  return version;
2193
2065
  }
2194
-
2195
2066
  getCustomUserAgent() {
2196
2067
  return `${this.getLibraryId()}/${this.getLibraryVersion()}`;
2197
2068
  }
2198
-
2199
2069
  enable() {
2200
2070
  return super.optIn();
2201
2071
  }
2202
-
2203
2072
  disable() {
2204
2073
  return super.optOut();
2205
2074
  }
2206
-
2207
2075
  debug(enabled = true) {
2208
2076
  super.debug(enabled);
2209
2077
  this.featureFlagsPoller?.debug(enabled);
2210
2078
  }
2211
-
2212
2079
  capture({
2213
2080
  distinctId,
2214
2081
  event,
@@ -2226,65 +2093,55 @@ class PostHog extends PostHogCoreStateless {
2226
2093
  uuid
2227
2094
  });
2228
2095
  };
2229
-
2230
2096
  const _getFlags = (distinctId, groups, disableGeoip) => {
2231
2097
  return super.getFeatureFlagsStateless(distinctId, groups, undefined, undefined, disableGeoip);
2232
- }; // :TRICKY: If we flush, or need to shut down, to not lose events we want this promise to resolve before we flush
2233
-
2234
-
2098
+ };
2099
+ // :TRICKY: If we flush, or need to shut down, to not lose events we want this promise to resolve before we flush
2235
2100
  const capturePromise = Promise.resolve().then(async () => {
2236
2101
  if (sendFeatureFlags) {
2237
2102
  // If we are sending feature flags, we need to make sure we have the latest flags
2238
2103
  // return await super.getFeatureFlagsStateless(distinctId, groups, undefined, undefined, disableGeoip)
2239
2104
  return await _getFlags(distinctId, groups, disableGeoip);
2240
2105
  }
2241
-
2242
2106
  if ((this.featureFlagsPoller?.featureFlags?.length || 0) > 0) {
2243
2107
  // Otherwise we may as well check for the flags locally and include them if there
2244
2108
  const groupsWithStringValues = {};
2245
-
2246
2109
  for (const [key, value] of Object.entries(groups || {})) {
2247
2110
  groupsWithStringValues[key] = String(value);
2248
2111
  }
2249
-
2250
2112
  return await this.getAllFlags(distinctId, {
2251
2113
  groups: groupsWithStringValues,
2252
2114
  disableGeoip,
2253
2115
  onlyEvaluateLocally: true
2254
2116
  });
2255
2117
  }
2256
-
2257
2118
  return {};
2258
2119
  }).then(flags => {
2259
2120
  // Derive the relevant flag properties to add
2260
2121
  const additionalProperties = {};
2261
-
2262
2122
  if (flags) {
2263
2123
  for (const [feature, variant] of Object.entries(flags)) {
2264
2124
  additionalProperties[`$feature/${feature}`] = variant;
2265
2125
  }
2266
2126
  }
2267
-
2268
2127
  const activeFlags = Object.keys(flags || {}).filter(flag => flags?.[flag] !== false);
2269
-
2270
2128
  if (activeFlags.length > 0) {
2271
2129
  additionalProperties['$active_feature_flags'] = activeFlags;
2272
2130
  }
2273
-
2274
2131
  return additionalProperties;
2275
2132
  }).catch(() => {
2276
2133
  // Something went wrong getting the flag info - we should capture the event anyways
2277
2134
  return {};
2278
2135
  }).then(additionalProperties => {
2279
2136
  // No matter what - capture the event
2280
- _capture({ ...additionalProperties,
2137
+ _capture({
2138
+ ...additionalProperties,
2281
2139
  ...properties,
2282
2140
  $groups: groups
2283
2141
  });
2284
2142
  });
2285
2143
  this.addPendingPromise(capturePromise);
2286
2144
  }
2287
-
2288
2145
  identify({
2289
2146
  distinctId,
2290
2147
  properties,
@@ -2298,13 +2155,11 @@ class PostHog extends PostHogCoreStateless {
2298
2155
  disableGeoip
2299
2156
  });
2300
2157
  }
2301
-
2302
2158
  alias(data) {
2303
2159
  super.aliasStateless(data.alias, data.distinctId, undefined, {
2304
2160
  disableGeoip: data.disableGeoip
2305
2161
  });
2306
2162
  }
2307
-
2308
2163
  async getFeatureFlag(key, distinctId, options) {
2309
2164
  const {
2310
2165
  groups,
@@ -2318,36 +2173,29 @@ class PostHog extends PostHogCoreStateless {
2318
2173
  } = options || {};
2319
2174
  const adjustedProperties = this.addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties);
2320
2175
  personProperties = adjustedProperties.allPersonProperties;
2321
- groupProperties = adjustedProperties.allGroupProperties; // set defaults
2322
-
2176
+ groupProperties = adjustedProperties.allGroupProperties;
2177
+ // set defaults
2323
2178
  if (onlyEvaluateLocally == undefined) {
2324
2179
  onlyEvaluateLocally = false;
2325
2180
  }
2326
-
2327
2181
  if (sendFeatureFlagEvents == undefined) {
2328
2182
  sendFeatureFlagEvents = true;
2329
2183
  }
2330
-
2331
2184
  let response = await this.featureFlagsPoller?.getFeatureFlag(key, distinctId, groups, personProperties, groupProperties);
2332
2185
  const flagWasLocallyEvaluated = response !== undefined;
2333
-
2334
2186
  if (!flagWasLocallyEvaluated && !onlyEvaluateLocally) {
2335
2187
  response = await super.getFeatureFlagStateless(key, distinctId, groups, personProperties, groupProperties, disableGeoip);
2336
2188
  }
2337
-
2338
2189
  const featureFlagReportedKey = `${key}_${response}`;
2339
-
2340
2190
  if (sendFeatureFlagEvents && (!(distinctId in this.distinctIdHasSentFlagCalls) || !this.distinctIdHasSentFlagCalls[distinctId].includes(featureFlagReportedKey))) {
2341
2191
  if (Object.keys(this.distinctIdHasSentFlagCalls).length >= this.maxCacheSize) {
2342
2192
  this.distinctIdHasSentFlagCalls = {};
2343
2193
  }
2344
-
2345
2194
  if (Array.isArray(this.distinctIdHasSentFlagCalls[distinctId])) {
2346
2195
  this.distinctIdHasSentFlagCalls[distinctId].push(featureFlagReportedKey);
2347
2196
  } else {
2348
2197
  this.distinctIdHasSentFlagCalls[distinctId] = [featureFlagReportedKey];
2349
2198
  }
2350
-
2351
2199
  this.capture({
2352
2200
  distinctId,
2353
2201
  event: '$feature_flag_called',
@@ -2361,10 +2209,8 @@ class PostHog extends PostHogCoreStateless {
2361
2209
  disableGeoip
2362
2210
  });
2363
2211
  }
2364
-
2365
2212
  return response;
2366
2213
  }
2367
-
2368
2214
  async getFeatureFlagPayload(key, distinctId, matchValue, options) {
2369
2215
  const {
2370
2216
  groups,
@@ -2379,56 +2225,45 @@ class PostHog extends PostHogCoreStateless {
2379
2225
  const adjustedProperties = this.addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties);
2380
2226
  personProperties = adjustedProperties.allPersonProperties;
2381
2227
  groupProperties = adjustedProperties.allGroupProperties;
2382
- let response = undefined; // Try to get match value locally if not provided
2383
-
2228
+ let response = undefined;
2229
+ // Try to get match value locally if not provided
2384
2230
  if (!matchValue) {
2385
- matchValue = await this.getFeatureFlag(key, distinctId, { ...options,
2231
+ matchValue = await this.getFeatureFlag(key, distinctId, {
2232
+ ...options,
2386
2233
  onlyEvaluateLocally: true
2387
2234
  });
2388
2235
  }
2389
-
2390
2236
  if (matchValue) {
2391
2237
  response = await this.featureFlagsPoller?.computeFeatureFlagPayloadLocally(key, matchValue);
2392
- } // set defaults
2393
-
2394
-
2238
+ }
2239
+ // set defaults
2395
2240
  if (onlyEvaluateLocally == undefined) {
2396
2241
  onlyEvaluateLocally = false;
2397
2242
  }
2398
-
2399
2243
  if (sendFeatureFlagEvents == undefined) {
2400
2244
  sendFeatureFlagEvents = true;
2401
- } // set defaults
2402
-
2403
-
2245
+ }
2246
+ // set defaults
2404
2247
  if (onlyEvaluateLocally == undefined) {
2405
2248
  onlyEvaluateLocally = false;
2406
2249
  }
2407
-
2408
2250
  const payloadWasLocallyEvaluated = response !== undefined;
2409
-
2410
2251
  if (!payloadWasLocallyEvaluated && !onlyEvaluateLocally) {
2411
2252
  response = await super.getFeatureFlagPayloadStateless(key, distinctId, groups, personProperties, groupProperties, disableGeoip);
2412
2253
  }
2413
-
2414
2254
  return response;
2415
2255
  }
2416
-
2417
2256
  async isFeatureEnabled(key, distinctId, options) {
2418
2257
  const feat = await this.getFeatureFlag(key, distinctId, options);
2419
-
2420
2258
  if (feat === undefined) {
2421
2259
  return undefined;
2422
2260
  }
2423
-
2424
2261
  return !!feat || false;
2425
2262
  }
2426
-
2427
2263
  async getAllFlags(distinctId, options) {
2428
2264
  const response = await this.getAllFlagsAndPayloads(distinctId, options);
2429
2265
  return response.featureFlags;
2430
2266
  }
2431
-
2432
2267
  async getAllFlagsAndPayloads(distinctId, options) {
2433
2268
  const {
2434
2269
  groups,
@@ -2441,39 +2276,36 @@ class PostHog extends PostHogCoreStateless {
2441
2276
  } = options || {};
2442
2277
  const adjustedProperties = this.addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties);
2443
2278
  personProperties = adjustedProperties.allPersonProperties;
2444
- groupProperties = adjustedProperties.allGroupProperties; // set defaults
2445
-
2279
+ groupProperties = adjustedProperties.allGroupProperties;
2280
+ // set defaults
2446
2281
  if (onlyEvaluateLocally == undefined) {
2447
2282
  onlyEvaluateLocally = false;
2448
2283
  }
2449
-
2450
2284
  const localEvaluationResult = await this.featureFlagsPoller?.getAllFlagsAndPayloads(distinctId, groups, personProperties, groupProperties);
2451
2285
  let featureFlags = {};
2452
2286
  let featureFlagPayloads = {};
2453
2287
  let fallbackToDecide = true;
2454
-
2455
2288
  if (localEvaluationResult) {
2456
2289
  featureFlags = localEvaluationResult.response;
2457
2290
  featureFlagPayloads = localEvaluationResult.payloads;
2458
2291
  fallbackToDecide = localEvaluationResult.fallbackToDecide;
2459
2292
  }
2460
-
2461
2293
  if (fallbackToDecide && !onlyEvaluateLocally) {
2462
2294
  const remoteEvaluationResult = await super.getFeatureFlagsAndPayloadsStateless(distinctId, groups, personProperties, groupProperties, disableGeoip);
2463
- featureFlags = { ...featureFlags,
2295
+ featureFlags = {
2296
+ ...featureFlags,
2464
2297
  ...(remoteEvaluationResult.flags || {})
2465
2298
  };
2466
- featureFlagPayloads = { ...featureFlagPayloads,
2299
+ featureFlagPayloads = {
2300
+ ...featureFlagPayloads,
2467
2301
  ...(remoteEvaluationResult.payloads || {})
2468
2302
  };
2469
2303
  }
2470
-
2471
2304
  return {
2472
2305
  featureFlags,
2473
2306
  featureFlagPayloads
2474
2307
  };
2475
2308
  }
2476
-
2477
2309
  groupIdentify({
2478
2310
  groupType,
2479
2311
  groupKey,
@@ -2485,23 +2317,19 @@ class PostHog extends PostHogCoreStateless {
2485
2317
  disableGeoip
2486
2318
  }, distinctId);
2487
2319
  }
2488
-
2489
2320
  async reloadFeatureFlags() {
2490
2321
  await this.featureFlagsPoller?.loadFeatureFlags(true);
2491
2322
  }
2492
-
2493
2323
  async shutdown(shutdownTimeoutMs) {
2494
2324
  this.featureFlagsPoller?.stopPoller();
2495
2325
  return super.shutdown(shutdownTimeoutMs);
2496
2326
  }
2497
-
2498
2327
  addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties) {
2499
2328
  const allPersonProperties = {
2500
2329
  distinct_id: distinctId,
2501
2330
  ...(personProperties || {})
2502
2331
  };
2503
2332
  const allGroupProperties = {};
2504
-
2505
2333
  if (groups) {
2506
2334
  for (const groupName of Object.keys(groups)) {
2507
2335
  allGroupProperties[groupName] = {
@@ -2510,13 +2338,11 @@ class PostHog extends PostHogCoreStateless {
2510
2338
  };
2511
2339
  }
2512
2340
  }
2513
-
2514
2341
  return {
2515
2342
  allPersonProperties,
2516
2343
  allGroupProperties
2517
2344
  };
2518
2345
  }
2519
-
2520
2346
  }
2521
2347
 
2522
2348
  /**
@@ -2547,26 +2373,21 @@ class PostHogSentryIntegration {
2547
2373
  this.name = 'posthog-node';
2548
2374
  this.posthogHost = posthog.options.host ?? 'https://us.i.posthog.com';
2549
2375
  }
2550
-
2551
2376
  setupOnce(addGlobalEventProcessor, getCurrentHub) {
2552
2377
  addGlobalEventProcessor(event => {
2553
2378
  if (event.exception?.values === undefined || event.exception.values.length === 0) {
2554
2379
  return event;
2555
2380
  }
2556
-
2557
2381
  if (!event.tags) {
2558
2382
  event.tags = {};
2559
2383
  }
2560
-
2561
- const sentry = getCurrentHub(); // Get the PostHog user ID from a specific tag, which users can set on their Sentry scope as they need.
2562
-
2384
+ const sentry = getCurrentHub();
2385
+ // Get the PostHog user ID from a specific tag, which users can set on their Sentry scope as they need.
2563
2386
  const userId = event.tags[PostHogSentryIntegration.POSTHOG_ID_TAG];
2564
-
2565
2387
  if (userId === undefined) {
2566
2388
  // If we can't find a user ID, don't bother linking the event. We won't be able to send anything meaningful to PostHog without it.
2567
2389
  return event;
2568
2390
  }
2569
-
2570
2391
  event.tags['PostHog Person URL'] = new URL(`/person/${userId}`, this.posthogHost).toString();
2571
2392
  const properties = {
2572
2393
  // PostHog Exception Properties
@@ -2581,11 +2402,9 @@ class PostHogSentryIntegration {
2581
2402
  $sentry_tags: event.tags
2582
2403
  };
2583
2404
  const projectId = sentry.getClient()?.getDsn()?.projectId;
2584
-
2585
2405
  if (this.organization !== undefined && projectId !== undefined && event.event_id !== undefined) {
2586
2406
  properties.$sentry_url = `${this.prefix ?? 'https://sentry.io/organizations'}/${this.organization}/issues/?project=${projectId}&query=${event.event_id}`;
2587
2407
  }
2588
-
2589
2408
  this.posthog.capture({
2590
2409
  event: '$exception',
2591
2410
  distinctId: userId,
@@ -2594,7 +2413,6 @@ class PostHogSentryIntegration {
2594
2413
  return event;
2595
2414
  });
2596
2415
  }
2597
-
2598
2416
  }
2599
2417
  PostHogSentryIntegration.POSTHOG_ID_TAG = 'posthog_distinct_id';
2600
2418