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