posthog-node 5.8.1 → 5.8.3

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.
@@ -778,7 +778,7 @@ function setupExpressErrorHandler(_posthog, app) {
778
778
  });
779
779
  }
780
780
 
781
- var version = "5.8.1";
781
+ var version = "5.8.3";
782
782
 
783
783
  /**
784
784
  * A lazy value that is only computed when needed. Inspired by C#'s Lazy<T> class.
@@ -965,12 +965,14 @@ class FeatureFlagsPoller {
965
965
  const payloads = {};
966
966
  let fallbackToFlags = this.featureFlags.length == 0;
967
967
  const flagsToEvaluate = flagKeysToExplicitlyEvaluate ? flagKeysToExplicitlyEvaluate.map(key => this.featureFlagsByKey[key]).filter(Boolean) : this.featureFlags;
968
+ // Create a shared evaluation cache to prevent memory leaks when processing many flags
969
+ const sharedEvaluationCache = {};
968
970
  await Promise.all(flagsToEvaluate.map(async flag => {
969
971
  try {
970
972
  const {
971
973
  value: matchValue,
972
974
  payload: matchPayload
973
- } = await this.computeFlagAndPayloadLocally(flag, distinctId, groups, personProperties, groupProperties);
975
+ } = await this.computeFlagAndPayloadLocally(flag, distinctId, groups, personProperties, groupProperties, undefined /* matchValue */, sharedEvaluationCache);
974
976
  response[flag.key] = matchValue;
975
977
  if (matchPayload) {
976
978
  payloads[flag.key] = matchPayload;
@@ -990,9 +992,11 @@ class FeatureFlagsPoller {
990
992
  fallbackToFlags
991
993
  };
992
994
  }
993
- async computeFlagAndPayloadLocally(flag, distinctId, groups = {}, personProperties = {}, groupProperties = {}, matchValue) {
994
- // Always ensure flags are loaded for payload computation
995
- await this.loadFeatureFlags();
995
+ async computeFlagAndPayloadLocally(flag, distinctId, groups = {}, personProperties = {}, groupProperties = {}, matchValue, evaluationCache, skipLoadCheck = false) {
996
+ // Only load flags if not already loaded and not skipping the check
997
+ if (!skipLoadCheck) {
998
+ await this.loadFeatureFlags();
999
+ }
996
1000
  if (!this.loadedSuccessfullyOnce) {
997
1001
  return {
998
1002
  value: false,
@@ -1004,7 +1008,7 @@ class FeatureFlagsPoller {
1004
1008
  if (matchValue !== undefined) {
1005
1009
  flagValue = matchValue;
1006
1010
  } else {
1007
- flagValue = await this.computeFlagValueLocally(flag, distinctId, groups, personProperties, groupProperties);
1011
+ flagValue = await this.computeFlagValueLocally(flag, distinctId, groups, personProperties, groupProperties, evaluationCache);
1008
1012
  }
1009
1013
  // Always compute payload based on the final flagValue (whether provided or computed)
1010
1014
  const payload = this.getFeatureFlagPayload(flag.key, flagValue);
@@ -1013,7 +1017,7 @@ class FeatureFlagsPoller {
1013
1017
  payload
1014
1018
  };
1015
1019
  }
1016
- async computeFlagValueLocally(flag, distinctId, groups = {}, personProperties = {}, groupProperties = {}) {
1020
+ async computeFlagValueLocally(flag, distinctId, groups = {}, personProperties = {}, groupProperties = {}, evaluationCache = {}) {
1017
1021
  if (flag.ensure_experience_continuity) {
1018
1022
  throw new InconclusiveMatchError('Flag has experience continuity enabled');
1019
1023
  }
@@ -1033,9 +1037,9 @@ class FeatureFlagsPoller {
1033
1037
  return false;
1034
1038
  }
1035
1039
  const focusedGroupProperties = groupProperties[groupName];
1036
- return await this.matchFeatureFlagProperties(flag, groups[groupName], focusedGroupProperties);
1040
+ return await this.matchFeatureFlagProperties(flag, groups[groupName], focusedGroupProperties, evaluationCache);
1037
1041
  } else {
1038
- return await this.matchFeatureFlagProperties(flag, distinctId, personProperties);
1042
+ return await this.matchFeatureFlagProperties(flag, distinctId, personProperties, evaluationCache);
1039
1043
  }
1040
1044
  }
1041
1045
  getFeatureFlagPayload(key, flagValue) {
@@ -1679,6 +1683,35 @@ const THIRTY_SECONDS = 30 * 1000;
1679
1683
  const MAX_CACHE_SIZE = 50 * 1000;
1680
1684
  // The actual exported Nodejs API.
1681
1685
  class PostHogBackendClient extends PostHogCoreStateless {
1686
+ /**
1687
+ * Initialize a new PostHog client instance.
1688
+ *
1689
+ * @example
1690
+ * ```ts
1691
+ * // Basic initialization
1692
+ * const client = new PostHogBackendClient(
1693
+ * 'your-api-key',
1694
+ * { host: 'https://app.posthog.com' }
1695
+ * )
1696
+ * ```
1697
+ *
1698
+ * @example
1699
+ * ```ts
1700
+ * // With personal API key
1701
+ * const client = new PostHogBackendClient(
1702
+ * 'your-api-key',
1703
+ * {
1704
+ * host: 'https://app.posthog.com',
1705
+ * personalApiKey: 'your-personal-api-key'
1706
+ * }
1707
+ * )
1708
+ * ```
1709
+ *
1710
+ * {@label Initialization}
1711
+ *
1712
+ * @param apiKey - Your PostHog project API key
1713
+ * @param options - Configuration options for the client
1714
+ */
1682
1715
  constructor(apiKey, options = {}) {
1683
1716
  super(apiKey, options);
1684
1717
  this._memoryStorage = new PostHogMemoryStorage();
@@ -1714,31 +1747,185 @@ class PostHogBackendClient extends PostHogCoreStateless {
1714
1747
  this.distinctIdHasSentFlagCalls = {};
1715
1748
  this.maxCacheSize = options.maxCacheSize || MAX_CACHE_SIZE;
1716
1749
  }
1750
+ /**
1751
+ * Get a persisted property value from memory storage.
1752
+ *
1753
+ * @example
1754
+ * ```ts
1755
+ * // Get user ID
1756
+ * const userId = client.getPersistedProperty('userId')
1757
+ * ```
1758
+ *
1759
+ * @example
1760
+ * ```ts
1761
+ * // Get session ID
1762
+ * const sessionId = client.getPersistedProperty('sessionId')
1763
+ * ```
1764
+ *
1765
+ * {@label Initialization}
1766
+ *
1767
+ * @param key - The property key to retrieve
1768
+ * @returns The stored property value or undefined if not found
1769
+ */
1717
1770
  getPersistedProperty(key) {
1718
1771
  return this._memoryStorage.getProperty(key);
1719
1772
  }
1773
+ /**
1774
+ * Set a persisted property value in memory storage.
1775
+ *
1776
+ * @example
1777
+ * ```ts
1778
+ * // Set user ID
1779
+ * client.setPersistedProperty('userId', 'user_123')
1780
+ * ```
1781
+ *
1782
+ * @example
1783
+ * ```ts
1784
+ * // Set session ID
1785
+ * client.setPersistedProperty('sessionId', 'session_456')
1786
+ * ```
1787
+ *
1788
+ * {@label Initialization}
1789
+ *
1790
+ * @param key - The property key to set
1791
+ * @param value - The value to store (null to remove)
1792
+ */
1720
1793
  setPersistedProperty(key, value) {
1721
1794
  return this._memoryStorage.setProperty(key, value);
1722
1795
  }
1796
+ /**
1797
+ * Make an HTTP request using the configured fetch function or default fetch.
1798
+ *
1799
+ * @example
1800
+ * ```ts
1801
+ * // POST request
1802
+ * const response = await client.fetch('/api/endpoint', {
1803
+ * method: 'POST',
1804
+ * headers: { 'Content-Type': 'application/json' },
1805
+ * body: JSON.stringify(data)
1806
+ * })
1807
+ * ```
1808
+ *
1809
+ * @internal
1810
+ *
1811
+ * {@label Initialization}
1812
+ *
1813
+ * @param url - The URL to fetch
1814
+ * @param options - Fetch options
1815
+ * @returns Promise resolving to the fetch response
1816
+ */
1723
1817
  fetch(url, options) {
1724
1818
  return this.options.fetch ? this.options.fetch(url, options) : fetch(url, options);
1725
1819
  }
1820
+ /**
1821
+ * Get the library version from package.json.
1822
+ *
1823
+ * @example
1824
+ * ```ts
1825
+ * // Get version
1826
+ * const version = client.getLibraryVersion()
1827
+ * console.log(`Using PostHog SDK version: ${version}`)
1828
+ * ```
1829
+ *
1830
+ * {@label Initialization}
1831
+ *
1832
+ * @returns The current library version string
1833
+ */
1726
1834
  getLibraryVersion() {
1727
1835
  return version;
1728
1836
  }
1837
+ /**
1838
+ * Get the custom user agent string for this client.
1839
+ *
1840
+ * @example
1841
+ * ```ts
1842
+ * // Get user agent
1843
+ * const userAgent = client.getCustomUserAgent()
1844
+ * // Returns: "posthog-node/5.7.0"
1845
+ * ```
1846
+ *
1847
+ * {@label Identification}
1848
+ *
1849
+ * @returns The formatted user agent string
1850
+ */
1729
1851
  getCustomUserAgent() {
1730
1852
  return `${this.getLibraryId()}/${this.getLibraryVersion()}`;
1731
1853
  }
1854
+ /**
1855
+ * Enable the PostHog client (opt-in).
1856
+ *
1857
+ * @example
1858
+ * ```ts
1859
+ * // Enable client
1860
+ * await client.enable()
1861
+ * // Client is now enabled and will capture events
1862
+ * ```
1863
+ *
1864
+ * {@label Privacy}
1865
+ *
1866
+ * @returns Promise that resolves when the client is enabled
1867
+ */
1732
1868
  enable() {
1733
1869
  return super.optIn();
1734
1870
  }
1871
+ /**
1872
+ * Disable the PostHog client (opt-out).
1873
+ *
1874
+ * @example
1875
+ * ```ts
1876
+ * // Disable client
1877
+ * await client.disable()
1878
+ * // Client is now disabled and will not capture events
1879
+ * ```
1880
+ *
1881
+ * {@label Privacy}
1882
+ *
1883
+ * @returns Promise that resolves when the client is disabled
1884
+ */
1735
1885
  disable() {
1736
1886
  return super.optOut();
1737
1887
  }
1888
+ /**
1889
+ * Enable or disable debug logging.
1890
+ *
1891
+ * @example
1892
+ * ```ts
1893
+ * // Enable debug logging
1894
+ * client.debug(true)
1895
+ * ```
1896
+ *
1897
+ * @example
1898
+ * ```ts
1899
+ * // Disable debug logging
1900
+ * client.debug(false)
1901
+ * ```
1902
+ *
1903
+ * {@label Initialization}
1904
+ *
1905
+ * @param enabled - Whether to enable debug logging
1906
+ */
1738
1907
  debug(enabled = true) {
1739
1908
  super.debug(enabled);
1740
1909
  this.featureFlagsPoller?.debug(enabled);
1741
1910
  }
1911
+ /**
1912
+ * Capture an event manually.
1913
+ *
1914
+ * @example
1915
+ * ```ts
1916
+ * // Basic capture
1917
+ * client.capture({
1918
+ * distinctId: 'user_123',
1919
+ * event: 'button_clicked',
1920
+ * properties: { button_color: 'red' }
1921
+ * })
1922
+ * ```
1923
+ *
1924
+ * {@label Capture}
1925
+ *
1926
+ * @param props - The event properties
1927
+ * @returns void
1928
+ */
1742
1929
  capture(props) {
1743
1930
  if (typeof props === 'string') {
1744
1931
  this.logMsgIfDebug(() => console.warn('Called capture() with a string as the first argument when an object was expected.'));
@@ -1760,6 +1947,49 @@ class PostHogBackendClient extends PostHogCoreStateless {
1760
1947
  }
1761
1948
  }));
1762
1949
  }
1950
+ /**
1951
+ * Capture an event immediately (synchronously).
1952
+ *
1953
+ * @example
1954
+ * ```ts
1955
+ * // Basic immediate capture
1956
+ * await client.captureImmediate({
1957
+ * distinctId: 'user_123',
1958
+ * event: 'button_clicked',
1959
+ * properties: { button_color: 'red' }
1960
+ * })
1961
+ * ```
1962
+ *
1963
+ * @example
1964
+ * ```ts
1965
+ * // With feature flags
1966
+ * await client.captureImmediate({
1967
+ * distinctId: 'user_123',
1968
+ * event: 'user_action',
1969
+ * sendFeatureFlags: true
1970
+ * })
1971
+ * ```
1972
+ *
1973
+ * @example
1974
+ * ```ts
1975
+ * // With custom feature flags options
1976
+ * await client.captureImmediate({
1977
+ * distinctId: 'user_123',
1978
+ * event: 'user_action',
1979
+ * sendFeatureFlags: {
1980
+ * onlyEvaluateLocally: true,
1981
+ * personProperties: { plan: 'premium' },
1982
+ * groupProperties: { org: { tier: 'enterprise' } }
1983
+ * flagKeys: ['flag1', 'flag2']
1984
+ * }
1985
+ * })
1986
+ * ```
1987
+ *
1988
+ * {@label Capture}
1989
+ *
1990
+ * @param props - The event properties
1991
+ * @returns Promise that resolves when the event is captured
1992
+ */
1763
1993
  async captureImmediate(props) {
1764
1994
  if (typeof props === 'string') {
1765
1995
  this.logMsgIfDebug(() => console.warn('Called captureImmediate() with a string as the first argument when an object was expected.'));
@@ -1781,6 +2011,38 @@ class PostHogBackendClient extends PostHogCoreStateless {
1781
2011
  }
1782
2012
  }));
1783
2013
  }
2014
+ /**
2015
+ * Identify a user and set their properties.
2016
+ *
2017
+ * @example
2018
+ * ```ts
2019
+ * // Basic identify with properties
2020
+ * client.identify({
2021
+ * distinctId: 'user_123',
2022
+ * properties: {
2023
+ * name: 'John Doe',
2024
+ * email: 'john@example.com',
2025
+ * plan: 'premium'
2026
+ * }
2027
+ * })
2028
+ * ```
2029
+ *
2030
+ * @example
2031
+ * ```ts
2032
+ * // Using $set and $set_once
2033
+ * client.identify({
2034
+ * distinctId: 'user_123',
2035
+ * properties: {
2036
+ * $set: { name: 'John Doe', email: 'john@example.com' },
2037
+ * $set_once: { first_login: new Date().toISOString() }
2038
+ * }
2039
+ * })
2040
+ * ```
2041
+ *
2042
+ * {@label Identification}
2043
+ *
2044
+ * @param data - The identify data containing distinctId and properties
2045
+ */
1784
2046
  identify({
1785
2047
  distinctId,
1786
2048
  properties,
@@ -1799,6 +2061,26 @@ class PostHogBackendClient extends PostHogCoreStateless {
1799
2061
  disableGeoip
1800
2062
  });
1801
2063
  }
2064
+ /**
2065
+ * Identify a user and set their properties immediately (synchronously).
2066
+ *
2067
+ * @example
2068
+ * ```ts
2069
+ * // Basic immediate identify
2070
+ * await client.identifyImmediate({
2071
+ * distinctId: 'user_123',
2072
+ * properties: {
2073
+ * name: 'John Doe',
2074
+ * email: 'john@example.com'
2075
+ * }
2076
+ * })
2077
+ * ```
2078
+ *
2079
+ * {@label Identification}
2080
+ *
2081
+ * @param data - The identify data containing distinctId and properties
2082
+ * @returns Promise that resolves when the identify is processed
2083
+ */
1802
2084
  async identifyImmediate({
1803
2085
  distinctId,
1804
2086
  properties,
@@ -1816,19 +2098,96 @@ class PostHogBackendClient extends PostHogCoreStateless {
1816
2098
  disableGeoip
1817
2099
  });
1818
2100
  }
2101
+ /**
2102
+ * Create an alias to link two distinct IDs together.
2103
+ *
2104
+ * @example
2105
+ * ```ts
2106
+ * // Link an anonymous user to an identified user
2107
+ * client.alias({
2108
+ * distinctId: 'anonymous_123',
2109
+ * alias: 'user_456'
2110
+ * })
2111
+ * ```
2112
+ *
2113
+ * {@label Identification}
2114
+ *
2115
+ * @param data - The alias data containing distinctId and alias
2116
+ */
1819
2117
  alias(data) {
1820
2118
  super.aliasStateless(data.alias, data.distinctId, undefined, {
1821
2119
  disableGeoip: data.disableGeoip
1822
2120
  });
1823
2121
  }
2122
+ /**
2123
+ * Create an alias to link two distinct IDs together immediately (synchronously).
2124
+ *
2125
+ * @example
2126
+ * ```ts
2127
+ * // Link an anonymous user to an identified user immediately
2128
+ * await client.aliasImmediate({
2129
+ * distinctId: 'anonymous_123',
2130
+ * alias: 'user_456'
2131
+ * })
2132
+ * ```
2133
+ *
2134
+ * {@label Identification}
2135
+ *
2136
+ * @param data - The alias data containing distinctId and alias
2137
+ * @returns Promise that resolves when the alias is processed
2138
+ */
1824
2139
  async aliasImmediate(data) {
1825
2140
  await super.aliasStatelessImmediate(data.alias, data.distinctId, undefined, {
1826
2141
  disableGeoip: data.disableGeoip
1827
2142
  });
1828
2143
  }
2144
+ /**
2145
+ * Check if local evaluation of feature flags is ready.
2146
+ *
2147
+ * @example
2148
+ * ```ts
2149
+ * // Check if ready
2150
+ * if (client.isLocalEvaluationReady()) {
2151
+ * // Local evaluation is ready, can evaluate flags locally
2152
+ * const flag = await client.getFeatureFlag('flag-key', 'user_123')
2153
+ * } else {
2154
+ * // Local evaluation not ready, will use remote evaluation
2155
+ * const flag = await client.getFeatureFlag('flag-key', 'user_123')
2156
+ * }
2157
+ * ```
2158
+ *
2159
+ * {@label Feature flags}
2160
+ *
2161
+ * @returns true if local evaluation is ready, false otherwise
2162
+ */
1829
2163
  isLocalEvaluationReady() {
1830
2164
  return this.featureFlagsPoller?.isLocalEvaluationReady() ?? false;
1831
2165
  }
2166
+ /**
2167
+ * Wait for local evaluation of feature flags to be ready.
2168
+ *
2169
+ * @example
2170
+ * ```ts
2171
+ * // Wait for local evaluation
2172
+ * const isReady = await client.waitForLocalEvaluationReady()
2173
+ * if (isReady) {
2174
+ * console.log('Local evaluation is ready')
2175
+ * } else {
2176
+ * console.log('Local evaluation timed out')
2177
+ * }
2178
+ * ```
2179
+ *
2180
+ * @example
2181
+ * ```ts
2182
+ * // Wait with custom timeout
2183
+ * const isReady = await client.waitForLocalEvaluationReady(10000) // 10 seconds
2184
+ * ```
2185
+ *
2186
+ * {@label Feature flags}
2187
+ *
2188
+ * @param timeoutMs - Timeout in milliseconds (default: 30000)
2189
+ * @returns Promise that resolves to true if ready, false if timed out
2190
+ */
1832
2191
  async waitForLocalEvaluationReady(timeoutMs = THIRTY_SECONDS) {
1833
2192
  if (this.isLocalEvaluationReady()) {
1834
2193
  return true;
@@ -1848,6 +2207,47 @@ class PostHogBackendClient extends PostHogCoreStateless {
1848
2207
  });
1849
2208
  });
1850
2209
  }
2210
+ /**
2211
+ * Get the value of a feature flag for a specific user.
2212
+ *
2213
+ * @example
2214
+ * ```ts
2215
+ * // Basic feature flag check
2216
+ * const flagValue = await client.getFeatureFlag('new-feature', 'user_123')
2217
+ * if (flagValue === 'variant-a') {
2218
+ * // Show variant A
2219
+ * } else if (flagValue === 'variant-b') {
2220
+ * // Show variant B
2221
+ * } else {
2222
+ * // Flag is disabled or not found
2223
+ * }
2224
+ * ```
2225
+ *
2226
+ * @example
2227
+ * ```ts
2228
+ * // With groups and properties
2229
+ * const flagValue = await client.getFeatureFlag('org-feature', 'user_123', {
2230
+ * groups: { organization: 'acme-corp' },
2231
+ * personProperties: { plan: 'enterprise' },
2232
+ * groupProperties: { organization: { tier: 'premium' } }
2233
+ * })
2234
+ * ```
2235
+ *
2236
+ * @example
2237
+ * ```ts
2238
+ * // Only evaluate locally
2239
+ * const flagValue = await client.getFeatureFlag('local-flag', 'user_123', {
2240
+ * onlyEvaluateLocally: true
2241
+ * })
2242
+ * ```
2243
+ *
2244
+ * {@label Feature flags}
2245
+ *
2246
+ * @param key - The feature flag key
2247
+ * @param distinctId - The user's distinct ID
2248
+ * @param options - Optional configuration for flag evaluation
2249
+ * @returns Promise that resolves to the flag value or undefined
2250
+ */
1851
2251
  async getFeatureFlag(key, distinctId, options) {
1852
2252
  const {
1853
2253
  groups,
@@ -1867,7 +2267,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
1867
2267
  onlyEvaluateLocally = false;
1868
2268
  }
1869
2269
  if (sendFeatureFlagEvents == undefined) {
1870
- sendFeatureFlagEvents = true;
2270
+ sendFeatureFlagEvents = this.options.sendFeatureFlagEvent ?? true;
1871
2271
  }
1872
2272
  let response = await this.featureFlagsPoller?.getFeatureFlag(key, distinctId, groups, personProperties, groupProperties);
1873
2273
  const flagWasLocallyEvaluated = response !== undefined;
@@ -1911,6 +2311,41 @@ class PostHogBackendClient extends PostHogCoreStateless {
1911
2311
  }
1912
2312
  return response;
1913
2313
  }
2314
+ /**
2315
+ * Get the payload for a feature flag.
2316
+ *
2317
+ * @example
2318
+ * ```ts
2319
+ * // Get payload for a feature flag
2320
+ * const payload = await client.getFeatureFlagPayload('flag-key', 'user_123')
2321
+ * if (payload) {
2322
+ * console.log('Flag payload:', payload)
2323
+ * }
2324
+ * ```
2325
+ *
2326
+ * @example
2327
+ * ```ts
2328
+ * // Get payload with specific match value
2329
+ * const payload = await client.getFeatureFlagPayload('flag-key', 'user_123', 'variant-a')
2330
+ * ```
2331
+ *
2332
+ * @example
2333
+ * ```ts
2334
+ * // With groups and properties
2335
+ * const payload = await client.getFeatureFlagPayload('org-flag', 'user_123', undefined, {
2336
+ * groups: { organization: 'acme-corp' },
2337
+ * personProperties: { plan: 'enterprise' }
2338
+ * })
2339
+ * ```
2340
+ *
2341
+ * {@label Feature flags}
2342
+ *
2343
+ * @param key - The feature flag key
2344
+ * @param distinctId - The user's distinct ID
2345
+ * @param matchValue - Optional match value to get payload for
2346
+ * @param options - Optional configuration for flag evaluation
2347
+ * @returns Promise that resolves to the flag payload or undefined
2348
+ */
1914
2349
  async getFeatureFlagPayload(key, distinctId, matchValue, options) {
1915
2350
  const {
1916
2351
  groups,
@@ -1918,7 +2353,6 @@ class PostHogBackendClient extends PostHogCoreStateless {
1918
2353
  } = options || {};
1919
2354
  let {
1920
2355
  onlyEvaluateLocally,
1921
- sendFeatureFlagEvents,
1922
2356
  personProperties,
1923
2357
  groupProperties
1924
2358
  } = options || {};
@@ -1943,15 +2377,30 @@ class PostHogBackendClient extends PostHogCoreStateless {
1943
2377
  if (onlyEvaluateLocally == undefined) {
1944
2378
  onlyEvaluateLocally = false;
1945
2379
  }
1946
- if (sendFeatureFlagEvents == undefined) {
1947
- sendFeatureFlagEvents = true;
1948
- }
1949
2380
  const payloadWasLocallyEvaluated = response !== undefined;
1950
2381
  if (!payloadWasLocallyEvaluated && !onlyEvaluateLocally) {
1951
2382
  response = await super.getFeatureFlagPayloadStateless(key, distinctId, groups, personProperties, groupProperties, disableGeoip);
1952
2383
  }
1953
2384
  return response;
1954
2385
  }
2386
+ /**
2387
+ * Get the remote config payload for a feature flag.
2388
+ *
2389
+ * @example
2390
+ * ```ts
2391
+ * // Get remote config payload
2392
+ * const payload = await client.getRemoteConfigPayload('flag-key')
2393
+ * if (payload) {
2394
+ * console.log('Remote config payload:', payload)
2395
+ * }
2396
+ * ```
2397
+ *
2398
+ * {@label Feature flags}
2399
+ *
2400
+ * @param flagKey - The feature flag key
2401
+ * @returns Promise that resolves to the remote config payload or undefined
2402
+ * @throws Error if personal API key is not provided
2403
+ */
1955
2404
  async getRemoteConfigPayload(flagKey) {
1956
2405
  if (!this.options.personalApiKey) {
1957
2406
  throw new Error('Personal API key is required for remote config payload decryption');
@@ -1975,6 +2424,38 @@ class PostHogBackendClient extends PostHogCoreStateless {
1975
2424
  }
1976
2425
  return parsed;
1977
2426
  }
2427
+ /**
2428
+ * Check if a feature flag is enabled for a specific user.
2429
+ *
2430
+ * @example
2431
+ * ```ts
2432
+ * // Basic feature flag check
2433
+ * const isEnabled = await client.isFeatureEnabled('new-feature', 'user_123')
2434
+ * if (isEnabled) {
2435
+ * // Feature is enabled
2436
+ * console.log('New feature is active')
2437
+ * } else {
2438
+ * // Feature is disabled
2439
+ * console.log('New feature is not active')
2440
+ * }
2441
+ * ```
2442
+ *
2443
+ * @example
2444
+ * ```ts
2445
+ * // With groups and properties
2446
+ * const isEnabled = await client.isFeatureEnabled('org-feature', 'user_123', {
2447
+ * groups: { organization: 'acme-corp' },
2448
+ * personProperties: { plan: 'enterprise' }
2449
+ * })
2450
+ * ```
2451
+ *
2452
+ * {@label Feature flags}
2453
+ *
2454
+ * @param key - The feature flag key
2455
+ * @param distinctId - The user's distinct ID
2456
+ * @param options - Optional configuration for flag evaluation
2457
+ * @returns Promise that resolves to true if enabled, false if disabled, undefined if not found
2458
+ */
1978
2459
  async isFeatureEnabled(key, distinctId, options) {
1979
2460
  const feat = await this.getFeatureFlag(key, distinctId, options);
1980
2461
  if (feat === undefined) {
@@ -1982,10 +2463,77 @@ class PostHogBackendClient extends PostHogCoreStateless {
1982
2463
  }
1983
2464
  return !!feat || false;
1984
2465
  }
2466
+ /**
2467
+ * Get all feature flag values for a specific user.
2468
+ *
2469
+ * @example
2470
+ * ```ts
2471
+ * // Get all flags for a user
2472
+ * const allFlags = await client.getAllFlags('user_123')
2473
+ * console.log('User flags:', allFlags)
2474
+ * // Output: { 'flag-1': 'variant-a', 'flag-2': false, 'flag-3': 'variant-b' }
2475
+ * ```
2476
+ *
2477
+ * @example
2478
+ * ```ts
2479
+ * // With specific flag keys
2480
+ * const specificFlags = await client.getAllFlags('user_123', {
2481
+ * flagKeys: ['flag-1', 'flag-2']
2482
+ * })
2483
+ * ```
2484
+ *
2485
+ * @example
2486
+ * ```ts
2487
+ * // With groups and properties
2488
+ * const orgFlags = await client.getAllFlags('user_123', {
2489
+ * groups: { organization: 'acme-corp' },
2490
+ * personProperties: { plan: 'enterprise' }
2491
+ * })
2492
+ * ```
2493
+ *
2494
+ * {@label Feature flags}
2495
+ *
2496
+ * @param distinctId - The user's distinct ID
2497
+ * @param options - Optional configuration for flag evaluation
2498
+ * @returns Promise that resolves to a record of flag keys and their values
2499
+ */
1985
2500
  async getAllFlags(distinctId, options) {
1986
2501
  const response = await this.getAllFlagsAndPayloads(distinctId, options);
1987
2502
  return response.featureFlags || {};
1988
2503
  }
2504
+ /**
2505
+ * Get all feature flag values and payloads for a specific user.
2506
+ *
2507
+ * @example
2508
+ * ```ts
2509
+ * // Get all flags and payloads for a user
2510
+ * const result = await client.getAllFlagsAndPayloads('user_123')
2511
+ * console.log('Flags:', result.featureFlags)
2512
+ * console.log('Payloads:', result.featureFlagPayloads)
2513
+ * ```
2514
+ *
2515
+ * @example
2516
+ * ```ts
2517
+ * // With specific flag keys
2518
+ * const result = await client.getAllFlagsAndPayloads('user_123', {
2519
+ * flagKeys: ['flag-1', 'flag-2']
2520
+ * })
2521
+ * ```
2522
+ *
2523
+ * @example
2524
+ * ```ts
2525
+ * // Only evaluate locally
2526
+ * const result = await client.getAllFlagsAndPayloads('user_123', {
2527
+ * onlyEvaluateLocally: true
2528
+ * })
2529
+ * ```
2530
+ *
2531
+ * {@label Feature flags}
2532
+ *
2533
+ * @param distinctId - The user's distinct ID
2534
+ * @param options - Optional configuration for flag evaluation
2535
+ * @returns Promise that resolves to flags and payloads
2536
+ */
1989
2537
  async getAllFlagsAndPayloads(distinctId, options) {
1990
2538
  const {
1991
2539
  groups,
@@ -2029,6 +2577,41 @@ class PostHogBackendClient extends PostHogCoreStateless {
2029
2577
  featureFlagPayloads
2030
2578
  };
2031
2579
  }
2580
+ /**
2581
+ * Create or update a group and its properties.
2582
+ *
2583
+ * @example
2584
+ * ```ts
2585
+ * // Create a company group
2586
+ * client.groupIdentify({
2587
+ * groupType: 'company',
2588
+ * groupKey: 'acme-corp',
2589
+ * properties: {
2590
+ * name: 'Acme Corporation',
2591
+ * industry: 'Technology',
2592
+ * employee_count: 500
2593
+ * },
2594
+ * distinctId: 'user_123'
2595
+ * })
2596
+ * ```
2597
+ *
2598
+ * @example
2599
+ * ```ts
2600
+ * // Update organization properties
2601
+ * client.groupIdentify({
2602
+ * groupType: 'organization',
2603
+ * groupKey: 'org-456',
2604
+ * properties: {
2605
+ * plan: 'enterprise',
2606
+ * region: 'US-West'
2607
+ * }
2608
+ * })
2609
+ * ```
2610
+ *
2611
+ * {@label Identification}
2612
+ *
2613
+ * @param data - The group identify data
2614
+ */
2032
2615
  groupIdentify({
2033
2616
  groupType,
2034
2617
  groupKey,
@@ -2041,12 +2624,49 @@ class PostHogBackendClient extends PostHogCoreStateless {
2041
2624
  }, distinctId);
2042
2625
  }
2043
2626
  /**
2044
- * Reloads the feature flag definitions from the server for local evaluation.
2045
- * This is useful to call if you want to ensure that the feature flags are up to date before calling getFeatureFlag.
2627
+ * Reload feature flag definitions from the server for local evaluation.
2628
+ *
2629
+ * @example
2630
+ * ```ts
2631
+ * // Force reload of feature flags
2632
+ * await client.reloadFeatureFlags()
2633
+ * console.log('Feature flags reloaded')
2634
+ * ```
2635
+ *
2636
+ * @example
2637
+ * ```ts
2638
+ * // Reload before checking a specific flag
2639
+ * await client.reloadFeatureFlags()
2640
+ * const flag = await client.getFeatureFlag('flag-key', 'user_123')
2641
+ * ```
2642
+ *
2643
+ * {@label Feature flags}
2644
+ *
2645
+ * @returns Promise that resolves when flags are reloaded
2046
2646
  */
2047
2647
  async reloadFeatureFlags() {
2048
2648
  await this.featureFlagsPoller?.loadFeatureFlags(true);
2049
2649
  }
2650
+ /**
2651
+ * Shutdown the PostHog client gracefully.
2652
+ *
2653
+ * @example
2654
+ * ```ts
2655
+ * // Shutdown with default timeout
2656
+ * await client._shutdown()
2657
+ * ```
2658
+ *
2659
+ * @example
2660
+ * ```ts
2661
+ * // Shutdown with custom timeout
2662
+ * await client._shutdown(5000) // 5 seconds
2663
+ * ```
2664
+ *
2665
+ * {@label Shutdown}
2666
+ *
2667
+ * @param shutdownTimeoutMs - Timeout in milliseconds for shutdown
2668
+ * @returns Promise that resolves when shutdown is complete
2669
+ */
2050
2670
  async _shutdown(shutdownTimeoutMs) {
2051
2671
  this.featureFlagsPoller?.stopPoller();
2052
2672
  this.errorTracking.shutdown();
@@ -2175,12 +2795,81 @@ class PostHogBackendClient extends PostHogCoreStateless {
2175
2795
  allGroupProperties
2176
2796
  };
2177
2797
  }
2798
+ /**
2799
+ * Capture an error exception as an event.
2800
+ *
2801
+ * @example
2802
+ * ```ts
2803
+ * // Capture an error with user ID
2804
+ * try {
2805
+ * // Some risky operation
2806
+ * riskyOperation()
2807
+ * } catch (error) {
2808
+ * client.captureException(error, 'user_123')
2809
+ * }
2810
+ * ```
2811
+ *
2812
+ * @example
2813
+ * ```ts
2814
+ * // Capture with additional properties
2815
+ * try {
2816
+ * apiCall()
2817
+ * } catch (error) {
2818
+ * client.captureException(error, 'user_123', {
2819
+ * endpoint: '/api/users',
2820
+ * method: 'POST',
2821
+ * status_code: 500
2822
+ * })
2823
+ * }
2824
+ * ```
2825
+ *
2826
+ * {@label Error tracking}
2827
+ *
2828
+ * @param error - The error to capture
2829
+ * @param distinctId - Optional user distinct ID
2830
+ * @param additionalProperties - Optional additional properties to include
2831
+ */
2178
2832
  captureException(error, distinctId, additionalProperties) {
2179
2833
  const syntheticException = new Error('PostHog syntheticException');
2180
2834
  this.addPendingPromise(ErrorTracking.buildEventMessage(error, {
2181
2835
  syntheticException
2182
2836
  }, distinctId, additionalProperties).then(msg => this.capture(msg)));
2183
2837
  }
2838
+ /**
2839
+ * Capture an error exception as an event immediately (synchronously).
2840
+ *
2841
+ * @example
2842
+ * ```ts
2843
+ * // Capture an error immediately with user ID
2844
+ * try {
2845
+ * // Some risky operation
2846
+ * riskyOperation()
2847
+ * } catch (error) {
2848
+ * await client.captureExceptionImmediate(error, 'user_123')
2849
+ * }
2850
+ * ```
2851
+ *
2852
+ * @example
2853
+ * ```ts
2854
+ * // Capture with additional properties
2855
+ * try {
2856
+ * apiCall()
2857
+ * } catch (error) {
2858
+ * await client.captureExceptionImmediate(error, 'user_123', {
2859
+ * endpoint: '/api/users',
2860
+ * method: 'POST',
2861
+ * status_code: 500
2862
+ * })
2863
+ * }
2864
+ * ```
2865
+ *
2866
+ * {@label Error tracking}
2867
+ *
2868
+ * @param error - The error to capture
2869
+ * @param distinctId - Optional user distinct ID
2870
+ * @param additionalProperties - Optional additional properties to include
2871
+ * @returns Promise that resolves when the error is captured
2872
+ */
2184
2873
  async captureExceptionImmediate(error, distinctId, additionalProperties) {
2185
2874
  const syntheticException = new Error('PostHog syntheticException');
2186
2875
  this.addPendingPromise(ErrorTracking.buildEventMessage(error, {