posthog-node 4.14.0 → 4.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { posix, dirname, sep } from 'path';
2
2
 
3
- var version = "4.14.0";
3
+ var version = "4.16.0";
4
4
 
5
5
  var PostHogPersistedProperty;
6
6
  (function (PostHogPersistedProperty) {
@@ -256,6 +256,7 @@ const NEW_FLAGS_EXCLUDED_HASHES = new Set([
256
256
  'fc80b8e2',
257
257
  '75cc0998',
258
258
  ]);
259
+ const STRING_FORMAT = 'utf8';
259
260
  function assert(truthyValue, message) {
260
261
  if (!truthyValue || typeof truthyValue !== 'string' || isEmpty(truthyValue)) {
261
262
  throw new Error(message);
@@ -1194,11 +1195,21 @@ const uuidv7 = () => uuidv7obj().toString();
1194
1195
  const uuidv7obj = () => (defaultGenerator || (defaultGenerator = new V7Generator())).generate();
1195
1196
 
1196
1197
  class PostHogFetchHttpError extends Error {
1197
- constructor(response) {
1198
- super('HTTP error while fetching PostHog: ' + response.status);
1198
+ constructor(response, reqByteLength) {
1199
+ super('HTTP error while fetching PostHog: status=' + response.status + ', reqByteLength=' + reqByteLength);
1199
1200
  this.response = response;
1201
+ this.reqByteLength = reqByteLength;
1200
1202
  this.name = 'PostHogFetchHttpError';
1201
1203
  }
1204
+ get status() {
1205
+ return this.response.status;
1206
+ }
1207
+ get text() {
1208
+ return this.response.text();
1209
+ }
1210
+ get json() {
1211
+ return this.response.json();
1212
+ }
1202
1213
  }
1203
1214
  class PostHogFetchNetworkError extends Error {
1204
1215
  constructor(error) {
@@ -1210,9 +1221,26 @@ class PostHogFetchNetworkError extends Error {
1210
1221
  this.name = 'PostHogFetchNetworkError';
1211
1222
  }
1212
1223
  }
1224
+ async function logFlushError(err) {
1225
+ if (err instanceof PostHogFetchHttpError) {
1226
+ let text = '';
1227
+ try {
1228
+ text = await err.text;
1229
+ }
1230
+ catch { }
1231
+ console.error(`Error while flushing PostHog: message=${err.message}, response body=${text}`, err);
1232
+ }
1233
+ else {
1234
+ console.error('Error while flushing PostHog', err);
1235
+ }
1236
+ return Promise.resolve();
1237
+ }
1213
1238
  function isPostHogFetchError(err) {
1214
1239
  return typeof err === 'object' && (err instanceof PostHogFetchHttpError || err instanceof PostHogFetchNetworkError);
1215
1240
  }
1241
+ function isPostHogFetchContentTooLargeError(err) {
1242
+ return typeof err === 'object' && err instanceof PostHogFetchHttpError && err.status === 413;
1243
+ }
1216
1244
  var QuotaLimitedFeature;
1217
1245
  (function (QuotaLimitedFeature) {
1218
1246
  QuotaLimitedFeature["FeatureFlags"] = "feature_flags";
@@ -1221,6 +1249,7 @@ var QuotaLimitedFeature;
1221
1249
  class PostHogCoreStateless {
1222
1250
  constructor(apiKey, options) {
1223
1251
  this.flushPromise = null;
1252
+ this.shutdownPromise = null;
1224
1253
  this.pendingPromises = {};
1225
1254
  // internal
1226
1255
  this._events = new SimpleEventEmitter();
@@ -1343,12 +1372,26 @@ class PostHogCoreStateless {
1343
1372
  this.enqueue('identify', payload, options);
1344
1373
  });
1345
1374
  }
1375
+ async identifyStatelessImmediate(distinctId, properties, options) {
1376
+ const payload = {
1377
+ ...this.buildPayload({
1378
+ distinct_id: distinctId,
1379
+ event: '$identify',
1380
+ properties,
1381
+ }),
1382
+ };
1383
+ await this.sendImmediate('identify', payload, options);
1384
+ }
1346
1385
  captureStateless(distinctId, event, properties, options) {
1347
1386
  this.wrap(() => {
1348
1387
  const payload = this.buildPayload({ distinct_id: distinctId, event, properties });
1349
1388
  this.enqueue('capture', payload, options);
1350
1389
  });
1351
1390
  }
1391
+ async captureStatelessImmediate(distinctId, event, properties, options) {
1392
+ const payload = this.buildPayload({ distinct_id: distinctId, event, properties });
1393
+ await this.sendImmediate('capture', payload, options);
1394
+ }
1352
1395
  aliasStateless(alias, distinctId, properties, options) {
1353
1396
  this.wrap(() => {
1354
1397
  const payload = this.buildPayload({
@@ -1363,6 +1406,18 @@ class PostHogCoreStateless {
1363
1406
  this.enqueue('alias', payload, options);
1364
1407
  });
1365
1408
  }
1409
+ async aliasStatelessImmediate(alias, distinctId, properties, options) {
1410
+ const payload = this.buildPayload({
1411
+ event: '$create_alias',
1412
+ distinct_id: distinctId,
1413
+ properties: {
1414
+ ...(properties || {}),
1415
+ distinct_id: distinctId,
1416
+ alias,
1417
+ },
1418
+ });
1419
+ await this.sendImmediate('alias', payload, options);
1420
+ }
1366
1421
  /***
1367
1422
  *** GROUPS
1368
1423
  ***/
@@ -1606,25 +1661,7 @@ class PostHogCoreStateless {
1606
1661
  this._events.emit(type, `Library is disabled. Not sending event. To re-enable, call posthog.optIn()`);
1607
1662
  return;
1608
1663
  }
1609
- const message = {
1610
- ..._message,
1611
- type: type,
1612
- library: this.getLibraryId(),
1613
- library_version: this.getLibraryVersion(),
1614
- timestamp: options?.timestamp ? options?.timestamp : currentISOTime(),
1615
- uuid: options?.uuid ? options.uuid : uuidv7(),
1616
- };
1617
- const addGeoipDisableProperty = options?.disableGeoip ?? this.disableGeoip;
1618
- if (addGeoipDisableProperty) {
1619
- if (!message.properties) {
1620
- message.properties = {};
1621
- }
1622
- message['properties']['$geoip_disable'] = true;
1623
- }
1624
- if (message.distinctId) {
1625
- message.distinct_id = message.distinctId;
1626
- delete message.distinctId;
1627
- }
1664
+ const message = this.prepareMessage(type, _message, options);
1628
1665
  const queue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
1629
1666
  if (queue.length >= this.maxQueueSize) {
1630
1667
  queue.shift();
@@ -1642,6 +1679,73 @@ class PostHogCoreStateless {
1642
1679
  }
1643
1680
  });
1644
1681
  }
1682
+ async sendImmediate(type, _message, options) {
1683
+ if (this.disabled) {
1684
+ this.logMsgIfDebug(() => console.warn('[PostHog] The client is disabled'));
1685
+ return;
1686
+ }
1687
+ if (!this._isInitialized) {
1688
+ await this._initPromise;
1689
+ }
1690
+ if (this.optedOut) {
1691
+ this._events.emit(type, `Library is disabled. Not sending event. To re-enable, call posthog.optIn()`);
1692
+ return;
1693
+ }
1694
+ const data = {
1695
+ api_key: this.apiKey,
1696
+ batch: [this.prepareMessage(type, _message, options)],
1697
+ sent_at: currentISOTime(),
1698
+ };
1699
+ if (this.historicalMigration) {
1700
+ data.historical_migration = true;
1701
+ }
1702
+ const payload = JSON.stringify(data);
1703
+ const url = this.captureMode === 'form'
1704
+ ? `${this.host}/e/?ip=1&_=${currentTimestamp()}&v=${this.getLibraryVersion()}`
1705
+ : `${this.host}/batch/`;
1706
+ const fetchOptions = this.captureMode === 'form'
1707
+ ? {
1708
+ method: 'POST',
1709
+ mode: 'no-cors',
1710
+ credentials: 'omit',
1711
+ headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/x-www-form-urlencoded' },
1712
+ body: `data=${encodeURIComponent(LZString.compressToBase64(payload))}&compression=lz64`,
1713
+ }
1714
+ : {
1715
+ method: 'POST',
1716
+ headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/json' },
1717
+ body: payload,
1718
+ };
1719
+ try {
1720
+ await this.fetchWithRetry(url, fetchOptions);
1721
+ }
1722
+ catch (err) {
1723
+ this._events.emit('error', err);
1724
+ throw err;
1725
+ }
1726
+ }
1727
+ prepareMessage(type, _message, options) {
1728
+ const message = {
1729
+ ..._message,
1730
+ type: type,
1731
+ library: this.getLibraryId(),
1732
+ library_version: this.getLibraryVersion(),
1733
+ timestamp: options?.timestamp ? options?.timestamp : currentISOTime(),
1734
+ uuid: options?.uuid ? options.uuid : uuidv7(),
1735
+ };
1736
+ const addGeoipDisableProperty = options?.disableGeoip ?? this.disableGeoip;
1737
+ if (addGeoipDisableProperty) {
1738
+ if (!message.properties) {
1739
+ message.properties = {};
1740
+ }
1741
+ message['properties']['$geoip_disable'] = true;
1742
+ }
1743
+ if (message.distinctId) {
1744
+ message.distinct_id = message.distinctId;
1745
+ delete message.distinctId;
1746
+ }
1747
+ return message;
1748
+ }
1645
1749
  clearFlushTimer() {
1646
1750
  if (this._flushTimer) {
1647
1751
  clearTimeout(this._flushTimer);
@@ -1653,16 +1757,26 @@ class PostHogCoreStateless {
1653
1757
  * Avoids unnecessary promise errors
1654
1758
  */
1655
1759
  flushBackground() {
1656
- void this.flush().catch(() => { });
1760
+ void this.flush().catch(async (err) => {
1761
+ await logFlushError(err);
1762
+ });
1657
1763
  }
1658
1764
  async flush() {
1659
- if (!this.flushPromise) {
1660
- this.flushPromise = this._flush().finally(() => {
1765
+ // Wait for the current flush operation to finish (regardless of success or failure), then try to flush again.
1766
+ // Use allSettled instead of finally to be defensive around flush throwing errors immediately rather than rejecting.
1767
+ const nextFlushPromise = Promise.allSettled([this.flushPromise]).then(() => {
1768
+ return this._flush();
1769
+ });
1770
+ this.flushPromise = nextFlushPromise;
1771
+ void this.addPendingPromise(nextFlushPromise);
1772
+ Promise.allSettled([nextFlushPromise]).then(() => {
1773
+ // If there are no others waiting to flush, clear the promise.
1774
+ // We don't strictly need to do this, but it could make debugging easier
1775
+ if (this.flushPromise === nextFlushPromise) {
1661
1776
  this.flushPromise = null;
1662
- });
1663
- this.addPendingPromise(this.flushPromise);
1664
- }
1665
- return this.flushPromise;
1777
+ }
1778
+ });
1779
+ return nextFlushPromise;
1666
1780
  }
1667
1781
  getCustomHeaders() {
1668
1782
  // Don't set the user agent if we're not on a browser. The latest spec allows
@@ -1679,56 +1793,80 @@ class PostHogCoreStateless {
1679
1793
  async _flush() {
1680
1794
  this.clearFlushTimer();
1681
1795
  await this._initPromise;
1682
- const queue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
1796
+ let queue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
1683
1797
  if (!queue.length) {
1684
1798
  return [];
1685
1799
  }
1686
- const items = queue.slice(0, this.maxBatchSize);
1687
- const messages = items.map((item) => item.message);
1688
- const persistQueueChange = () => {
1689
- const refreshedQueue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
1690
- this.setPersistedProperty(PostHogPersistedProperty.Queue, refreshedQueue.slice(items.length));
1691
- };
1692
- const data = {
1693
- api_key: this.apiKey,
1694
- batch: messages,
1695
- sent_at: currentISOTime(),
1696
- };
1697
- if (this.historicalMigration) {
1698
- data.historical_migration = true;
1699
- }
1700
- const payload = JSON.stringify(data);
1701
- const url = this.captureMode === 'form'
1702
- ? `${this.host}/e/?ip=1&_=${currentTimestamp()}&v=${this.getLibraryVersion()}`
1703
- : `${this.host}/batch/`;
1704
- const fetchOptions = this.captureMode === 'form'
1705
- ? {
1706
- method: 'POST',
1707
- mode: 'no-cors',
1708
- credentials: 'omit',
1709
- headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/x-www-form-urlencoded' },
1710
- body: `data=${encodeURIComponent(LZString.compressToBase64(payload))}&compression=lz64`,
1800
+ const sentMessages = [];
1801
+ const originalQueueLength = queue.length;
1802
+ while (queue.length > 0 && sentMessages.length < originalQueueLength) {
1803
+ const batchItems = queue.slice(0, this.maxBatchSize);
1804
+ const batchMessages = batchItems.map((item) => item.message);
1805
+ const persistQueueChange = () => {
1806
+ const refreshedQueue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
1807
+ const newQueue = refreshedQueue.slice(batchItems.length);
1808
+ this.setPersistedProperty(PostHogPersistedProperty.Queue, newQueue);
1809
+ queue = newQueue;
1810
+ };
1811
+ const data = {
1812
+ api_key: this.apiKey,
1813
+ batch: batchMessages,
1814
+ sent_at: currentISOTime(),
1815
+ };
1816
+ if (this.historicalMigration) {
1817
+ data.historical_migration = true;
1711
1818
  }
1712
- : {
1713
- method: 'POST',
1714
- headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/json' },
1715
- body: payload,
1819
+ const payload = JSON.stringify(data);
1820
+ const url = this.captureMode === 'form'
1821
+ ? `${this.host}/e/?ip=1&_=${currentTimestamp()}&v=${this.getLibraryVersion()}`
1822
+ : `${this.host}/batch/`;
1823
+ const fetchOptions = this.captureMode === 'form'
1824
+ ? {
1825
+ method: 'POST',
1826
+ mode: 'no-cors',
1827
+ credentials: 'omit',
1828
+ headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/x-www-form-urlencoded' },
1829
+ body: `data=${encodeURIComponent(LZString.compressToBase64(payload))}&compression=lz64`,
1830
+ }
1831
+ : {
1832
+ method: 'POST',
1833
+ headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/json' },
1834
+ body: payload,
1835
+ };
1836
+ const retryOptions = {
1837
+ retryCheck: (err) => {
1838
+ // don't automatically retry on 413 errors, we want to reduce the batch size first
1839
+ if (isPostHogFetchContentTooLargeError(err)) {
1840
+ return false;
1841
+ }
1842
+ // otherwise, retry on network errors
1843
+ return isPostHogFetchError(err);
1844
+ },
1716
1845
  };
1717
- try {
1718
- await this.fetchWithRetry(url, fetchOptions);
1719
- }
1720
- catch (err) {
1721
- // depending on the error type, eg a malformed JSON or broken queue, it'll always return an error
1722
- // and this will be an endless loop, in this case, if the error isn't a network issue, we always remove the items from the queue
1723
- if (!(err instanceof PostHogFetchNetworkError)) {
1724
- persistQueueChange();
1846
+ try {
1847
+ await this.fetchWithRetry(url, fetchOptions, retryOptions);
1725
1848
  }
1726
- this._events.emit('error', err);
1727
- throw err;
1849
+ catch (err) {
1850
+ if (isPostHogFetchContentTooLargeError(err) && batchMessages.length > 1) {
1851
+ // if we get a 413 error, we want to reduce the batch size and try again
1852
+ this.maxBatchSize = Math.max(1, Math.floor(batchMessages.length / 2));
1853
+ this.logMsgIfDebug(() => console.warn(`Received 413 when sending batch of size ${batchMessages.length}, reducing batch size to ${this.maxBatchSize}`));
1854
+ // do not persist the queue change, we want to retry the same batch
1855
+ continue;
1856
+ }
1857
+ // depending on the error type, eg a malformed JSON or broken queue, it'll always return an error
1858
+ // and this will be an endless loop, in this case, if the error isn't a network issue, we always remove the items from the queue
1859
+ if (!(err instanceof PostHogFetchNetworkError)) {
1860
+ persistQueueChange();
1861
+ }
1862
+ this._events.emit('error', err);
1863
+ throw err;
1864
+ }
1865
+ persistQueueChange();
1866
+ sentMessages.push(...batchMessages);
1728
1867
  }
1729
- persistQueueChange();
1730
- this._events.emit('flush', messages);
1731
- return messages;
1868
+ this._events.emit('flush', sentMessages);
1869
+ return sentMessages;
1732
1870
  }
1733
1871
  async fetchWithRetry(url, options, retryOptions, requestTimeout) {
1734
1872
  var _a;
@@ -1737,6 +1875,8 @@ class PostHogCoreStateless {
1737
1875
  setTimeout(() => ctrl.abort(), ms);
1738
1876
  return ctrl.signal;
1739
1877
  });
1878
+ const body = options.body ? options.body : '';
1879
+ const reqByteLength = Buffer.byteLength(body, STRING_FORMAT);
1740
1880
  return await retriable(async () => {
1741
1881
  let res = null;
1742
1882
  try {
@@ -1754,12 +1894,12 @@ class PostHogCoreStateless {
1754
1894
  // https://developer.mozilla.org/en-US/docs/Web/API/Request/mode#no-cors
1755
1895
  const isNoCors = options.mode === 'no-cors';
1756
1896
  if (!isNoCors && (res.status < 200 || res.status >= 400)) {
1757
- throw new PostHogFetchHttpError(res);
1897
+ throw new PostHogFetchHttpError(res, reqByteLength);
1758
1898
  }
1759
1899
  return res;
1760
1900
  }, { ...this._retryOptions, ...retryOptions });
1761
1901
  }
1762
- async shutdown(shutdownTimeoutMs = 30000) {
1902
+ async _shutdown(shutdownTimeoutMs = 30000) {
1763
1903
  // A little tricky - we want to have a max shutdown time and enforce it, even if that means we have some
1764
1904
  // dangling promises. We'll keep track of the timeout and resolve/reject based on that.
1765
1905
  await this._initPromise;
@@ -1786,7 +1926,7 @@ class PostHogCoreStateless {
1786
1926
  if (!isPostHogFetchError(e)) {
1787
1927
  throw e;
1788
1928
  }
1789
- this.logMsgIfDebug(() => console.error('Error while shutting down PostHog', e));
1929
+ await logFlushError(e);
1790
1930
  }
1791
1931
  };
1792
1932
  return Promise.race([
@@ -1800,6 +1940,22 @@ class PostHogCoreStateless {
1800
1940
  doShutdown(),
1801
1941
  ]);
1802
1942
  }
1943
+ /**
1944
+ * Call shutdown() once before the node process exits, so ensure that all events have been sent and all promises
1945
+ * have resolved. Do not use this function if you intend to keep using this PostHog instance after calling it.
1946
+ * @param shutdownTimeoutMs
1947
+ */
1948
+ async shutdown(shutdownTimeoutMs = 30000) {
1949
+ if (this.shutdownPromise) {
1950
+ this.logMsgIfDebug(() => console.warn('shutdown() called while already shutting down. shutdown() is meant to be called once before process exit - use flush() for per-request cleanup'));
1951
+ }
1952
+ else {
1953
+ this.shutdownPromise = this._shutdown(shutdownTimeoutMs).finally(() => {
1954
+ this.shutdownPromise = null;
1955
+ });
1956
+ }
1957
+ return this.shutdownPromise;
1958
+ }
1803
1959
  }
1804
1960
 
1805
1961
  class PostHogMemoryStorage {
@@ -3667,6 +3823,79 @@ class PostHog extends PostHogCoreStateless {
3667
3823
  });
3668
3824
  this.addPendingPromise(capturePromise);
3669
3825
  }
3826
+ async captureImmediate(props) {
3827
+ if (typeof props === 'string') {
3828
+ this.logMsgIfDebug(() => console.warn('Called capture() with a string as the first argument when an object was expected.'));
3829
+ }
3830
+ const {
3831
+ distinctId,
3832
+ event,
3833
+ properties,
3834
+ groups,
3835
+ sendFeatureFlags,
3836
+ timestamp,
3837
+ disableGeoip,
3838
+ uuid
3839
+ } = props;
3840
+ const _capture = props => {
3841
+ return super.captureStatelessImmediate(distinctId, event, props, {
3842
+ timestamp,
3843
+ disableGeoip,
3844
+ uuid
3845
+ });
3846
+ };
3847
+ const _getFlags = async (distinctId, groups, disableGeoip) => {
3848
+ return (await super.getFeatureFlagsStateless(distinctId, groups, undefined, undefined, disableGeoip)).flags;
3849
+ };
3850
+ const capturePromise = Promise.resolve().then(async () => {
3851
+ if (sendFeatureFlags) {
3852
+ // If we are sending feature flags, we need to make sure we have the latest flags
3853
+ // return await super.getFeatureFlagsStateless(distinctId, groups, undefined, undefined, disableGeoip)
3854
+ return await _getFlags(distinctId, groups, disableGeoip);
3855
+ }
3856
+ if (event === '$feature_flag_called') {
3857
+ // If we're capturing a $feature_flag_called event, we don't want to enrich the event with cached flags that may be out of date.
3858
+ return {};
3859
+ }
3860
+ if ((this.featureFlagsPoller?.featureFlags?.length || 0) > 0) {
3861
+ // Otherwise we may as well check for the flags locally and include them if they are already loaded
3862
+ const groupsWithStringValues = {};
3863
+ for (const [key, value] of Object.entries(groups || {})) {
3864
+ groupsWithStringValues[key] = String(value);
3865
+ }
3866
+ return await this.getAllFlags(distinctId, {
3867
+ groups: groupsWithStringValues,
3868
+ disableGeoip,
3869
+ onlyEvaluateLocally: true
3870
+ });
3871
+ }
3872
+ return {};
3873
+ }).then(flags => {
3874
+ // Derive the relevant flag properties to add
3875
+ const additionalProperties = {};
3876
+ if (flags) {
3877
+ for (const [feature, variant] of Object.entries(flags)) {
3878
+ additionalProperties[`$feature/${feature}`] = variant;
3879
+ }
3880
+ }
3881
+ const activeFlags = Object.keys(flags || {}).filter(flag => flags?.[flag] !== false).sort();
3882
+ if (activeFlags.length > 0) {
3883
+ additionalProperties['$active_feature_flags'] = activeFlags;
3884
+ }
3885
+ return additionalProperties;
3886
+ }).catch(() => {
3887
+ // Something went wrong getting the flag info - we should capture the event anyways
3888
+ return {};
3889
+ }).then(additionalProperties => {
3890
+ // No matter what - capture the event
3891
+ _capture({
3892
+ ...additionalProperties,
3893
+ ...properties,
3894
+ $groups: groups
3895
+ });
3896
+ });
3897
+ await capturePromise;
3898
+ }
3670
3899
  identify({
3671
3900
  distinctId,
3672
3901
  properties,
@@ -3685,11 +3914,33 @@ class PostHog extends PostHogCoreStateless {
3685
3914
  disableGeoip
3686
3915
  });
3687
3916
  }
3917
+ async identifyImmediate({
3918
+ distinctId,
3919
+ properties,
3920
+ disableGeoip
3921
+ }) {
3922
+ // promote $set and $set_once to top level
3923
+ const userPropsOnce = properties?.$set_once;
3924
+ delete properties?.$set_once;
3925
+ // if no $set is provided we assume all properties are $set
3926
+ const userProps = properties?.$set || properties;
3927
+ await super.identifyStatelessImmediate(distinctId, {
3928
+ $set: userProps,
3929
+ $set_once: userPropsOnce
3930
+ }, {
3931
+ disableGeoip
3932
+ });
3933
+ }
3688
3934
  alias(data) {
3689
3935
  super.aliasStateless(data.alias, data.distinctId, undefined, {
3690
3936
  disableGeoip: data.disableGeoip
3691
3937
  });
3692
3938
  }
3939
+ async aliasImmediate(data) {
3940
+ await super.aliasStatelessImmediate(data.alias, data.distinctId, undefined, {
3941
+ disableGeoip: data.disableGeoip
3942
+ });
3943
+ }
3693
3944
  isLocalEvaluationReady() {
3694
3945
  return this.featureFlagsPoller?.isLocalEvaluationReady() ?? false;
3695
3946
  }
@@ -3896,9 +4147,9 @@ class PostHog extends PostHogCoreStateless {
3896
4147
  async reloadFeatureFlags() {
3897
4148
  await this.featureFlagsPoller?.loadFeatureFlags(true);
3898
4149
  }
3899
- async shutdown(shutdownTimeoutMs) {
4150
+ async _shutdown(shutdownTimeoutMs) {
3900
4151
  this.featureFlagsPoller?.stopPoller();
3901
- return super.shutdown(shutdownTimeoutMs);
4152
+ return super._shutdown(shutdownTimeoutMs);
3902
4153
  }
3903
4154
  addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties) {
3904
4155
  const allPersonProperties = {