posthog-node 4.8.0 → 4.9.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.d.ts CHANGED
@@ -108,6 +108,7 @@ type PostHogDecideResponse = {
108
108
  [key: string]: JsonType;
109
109
  };
110
110
  errorsWhileComputingFlags: boolean;
111
+ quotaLimited?: string[];
111
112
  sessionRecording?: boolean | {
112
113
  [key: string]: JsonType;
113
114
  };
@@ -196,10 +197,10 @@ declare abstract class PostHogCoreStateless {
196
197
  protected getDecide(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, extraPayload?: Record<string, any>): Promise<PostHogDecideResponse | undefined>;
197
198
  protected getFeatureFlagStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<boolean | string | undefined>;
198
199
  protected getFeatureFlagPayloadStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<JsonType | undefined>;
199
- protected getFeatureFlagPayloadsStateless(distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<PostHogDecideResponse['featureFlagPayloads'] | undefined>;
200
+ protected getFeatureFlagPayloadsStateless(distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean, flagKeysToEvaluate?: string[]): Promise<PostHogDecideResponse['featureFlagPayloads'] | undefined>;
200
201
  protected _parsePayload(response: any): any;
201
- protected getFeatureFlagsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<PostHogDecideResponse['featureFlags'] | undefined>;
202
- protected getFeatureFlagsAndPayloadsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<{
202
+ protected getFeatureFlagsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean, flagKeysToEvaluate?: string[]): Promise<PostHogDecideResponse['featureFlags'] | undefined>;
203
+ protected getFeatureFlagsAndPayloadsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean, flagKeysToEvaluate?: string[]): Promise<{
203
204
  flags: PostHogDecideResponse['featureFlags'] | undefined;
204
205
  payloads: PostHogDecideResponse['featureFlagPayloads'] | undefined;
205
206
  }>;
package/lib/index.esm.js CHANGED
@@ -3,7 +3,7 @@ import { createReadStream } from 'node:fs';
3
3
  import { createInterface } from 'node:readline';
4
4
  import { posix, dirname, sep } from 'node:path';
5
5
 
6
- var version = "4.8.0";
6
+ var version = "4.9.0";
7
7
 
8
8
  var PostHogPersistedProperty;
9
9
  (function (PostHogPersistedProperty) {
@@ -954,6 +954,11 @@ class PostHogFetchNetworkError extends Error {
954
954
  function isPostHogFetchError(err) {
955
955
  return typeof err === 'object' && (err instanceof PostHogFetchHttpError || err instanceof PostHogFetchNetworkError);
956
956
  }
957
+ var QuotaLimitedFeature;
958
+ (function (QuotaLimitedFeature) {
959
+ QuotaLimitedFeature["FeatureFlags"] = "feature_flags";
960
+ QuotaLimitedFeature["Recordings"] = "recordings";
961
+ })(QuotaLimitedFeature || (QuotaLimitedFeature = {}));
957
962
  class PostHogCoreStateless {
958
963
  constructor(apiKey, options) {
959
964
  this.flushPromise = null;
@@ -1146,7 +1151,7 @@ class PostHogCoreStateless {
1146
1151
  }
1147
1152
  async getFeatureFlagStateless(key, distinctId, groups = {}, personProperties = {}, groupProperties = {}, disableGeoip) {
1148
1153
  await this._initPromise;
1149
- const featureFlags = await this.getFeatureFlagsStateless(distinctId, groups, personProperties, groupProperties, disableGeoip);
1154
+ const featureFlags = await this.getFeatureFlagsStateless(distinctId, groups, personProperties, groupProperties, disableGeoip, [key]);
1150
1155
  if (!featureFlags) {
1151
1156
  // If we haven't loaded flags yet, or errored out, we respond with undefined
1152
1157
  return undefined;
@@ -1162,7 +1167,7 @@ class PostHogCoreStateless {
1162
1167
  }
1163
1168
  async getFeatureFlagPayloadStateless(key, distinctId, groups = {}, personProperties = {}, groupProperties = {}, disableGeoip) {
1164
1169
  await this._initPromise;
1165
- const payloads = await this.getFeatureFlagPayloadsStateless(distinctId, groups, personProperties, groupProperties, disableGeoip);
1170
+ const payloads = await this.getFeatureFlagPayloadsStateless(distinctId, groups, personProperties, groupProperties, disableGeoip, [key]);
1166
1171
  if (!payloads) {
1167
1172
  return undefined;
1168
1173
  }
@@ -1173,9 +1178,9 @@ class PostHogCoreStateless {
1173
1178
  }
1174
1179
  return response;
1175
1180
  }
1176
- async getFeatureFlagPayloadsStateless(distinctId, groups = {}, personProperties = {}, groupProperties = {}, disableGeoip) {
1181
+ async getFeatureFlagPayloadsStateless(distinctId, groups = {}, personProperties = {}, groupProperties = {}, disableGeoip, flagKeysToEvaluate) {
1177
1182
  await this._initPromise;
1178
- const payloads = (await this.getFeatureFlagsAndPayloadsStateless(distinctId, groups, personProperties, groupProperties, disableGeoip)).payloads;
1183
+ const payloads = (await this.getFeatureFlagsAndPayloadsStateless(distinctId, groups, personProperties, groupProperties, disableGeoip, flagKeysToEvaluate)).payloads;
1179
1184
  return payloads;
1180
1185
  }
1181
1186
  _parsePayload(response) {
@@ -1186,17 +1191,28 @@ class PostHogCoreStateless {
1186
1191
  return response;
1187
1192
  }
1188
1193
  }
1189
- async getFeatureFlagsStateless(distinctId, groups = {}, personProperties = {}, groupProperties = {}, disableGeoip) {
1194
+ async getFeatureFlagsStateless(distinctId, groups = {}, personProperties = {}, groupProperties = {}, disableGeoip, flagKeysToEvaluate) {
1190
1195
  await this._initPromise;
1191
- return (await this.getFeatureFlagsAndPayloadsStateless(distinctId, groups, personProperties, groupProperties, disableGeoip)).flags;
1196
+ return (await this.getFeatureFlagsAndPayloadsStateless(distinctId, groups, personProperties, groupProperties, disableGeoip, flagKeysToEvaluate)).flags;
1192
1197
  }
1193
- async getFeatureFlagsAndPayloadsStateless(distinctId, groups = {}, personProperties = {}, groupProperties = {}, disableGeoip) {
1198
+ async getFeatureFlagsAndPayloadsStateless(distinctId, groups = {}, personProperties = {}, groupProperties = {}, disableGeoip, flagKeysToEvaluate) {
1194
1199
  await this._initPromise;
1195
1200
  const extraPayload = {};
1196
1201
  if (disableGeoip ?? this.disableGeoip) {
1197
1202
  extraPayload['geoip_disable'] = true;
1198
1203
  }
1204
+ if (flagKeysToEvaluate) {
1205
+ extraPayload['flag_keys_to_evaluate'] = flagKeysToEvaluate;
1206
+ }
1199
1207
  const decideResponse = await this.getDecide(distinctId, groups, personProperties, groupProperties, extraPayload);
1208
+ // Add check for quota limitation on feature flags
1209
+ if (decideResponse?.quotaLimited?.includes(QuotaLimitedFeature.FeatureFlags)) {
1210
+ console.warn('[FEATURE FLAGS] Feature flags quota limit exceeded - feature flags unavailable. Learn more about billing limits at https://posthog.com/docs/billing/limits-alerts');
1211
+ return {
1212
+ flags: undefined,
1213
+ payloads: undefined,
1214
+ };
1215
+ }
1200
1216
  const flags = decideResponse?.featureFlags;
1201
1217
  const payloads = decideResponse?.featureFlagPayloads;
1202
1218
  let parsedPayloads = payloads;
@@ -1753,6 +1769,16 @@ class FeatureFlagsPoller {
1753
1769
  this.authenticationErrorCount += 1;
1754
1770
  throw new ClientError(`Your personal API key does not have permission to fetch feature flag definitions for local evaluation. Setting next polling interval to ${this.getPollingInterval()}ms. Are you sure you're using the correct personal and Project API key pair? More information: https://posthog.com/docs/api/overview`);
1755
1771
  }
1772
+ if (res && res.status === 402) {
1773
+ // Quota limited - clear all flags
1774
+ console.warn('[FEATURE FLAGS] Feature flags quota limit exceeded - unsetting all local flags. Learn more about billing limits at https://posthog.com/docs/billing/limits-alerts');
1775
+ this.featureFlags = [];
1776
+ this.featureFlagsByKey = {};
1777
+ this.groupTypeMapping = {};
1778
+ this.cohorts = {};
1779
+ this.loadedSuccessfullyOnce = false;
1780
+ return;
1781
+ }
1756
1782
  if (res && res.status !== 200) {
1757
1783
  // something else went wrong, or the server is down.
1758
1784
  // In this case, don't override existing flags