posthog-node 5.1.1 → 5.3.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/CHANGELOG.md +8 -0
- package/lib/edge/index.cjs +80 -41
- package/lib/edge/index.cjs.map +1 -1
- package/lib/edge/index.mjs +80 -41
- package/lib/edge/index.mjs.map +1 -1
- package/lib/index.d.ts +10 -1
- package/lib/node/index.cjs +80 -41
- package/lib/node/index.cjs.map +1 -1
- package/lib/node/index.mjs +80 -41
- package/lib/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Next
|
|
2
2
|
|
|
3
|
+
# 5.3.1 - 2025-07-07
|
|
4
|
+
|
|
5
|
+
1. feat: decouple feature flag local evaluation from personal API keys; support decrypting remote config payloads without relying on the feature flags poller
|
|
6
|
+
|
|
7
|
+
# 5.2.1 - 2025-07-07
|
|
8
|
+
|
|
9
|
+
1. feat: add captureExceptionImmediate method on posthog client
|
|
10
|
+
|
|
3
11
|
# 5.1.1 - 2025-06-16
|
|
4
12
|
|
|
5
13
|
1. fix: Handle double-encoded JSON payloads from the remote config endpoint
|
package/lib/edge/index.cjs
CHANGED
|
@@ -877,7 +877,7 @@ function applyChunkIds(frames, parser) {
|
|
|
877
877
|
|
|
878
878
|
const SHUTDOWN_TIMEOUT = 2000;
|
|
879
879
|
class ErrorTracking {
|
|
880
|
-
static async
|
|
880
|
+
static async buildEventMessage(error, hint, distinctId, additionalProperties) {
|
|
881
881
|
const properties = {
|
|
882
882
|
...additionalProperties
|
|
883
883
|
};
|
|
@@ -887,14 +887,14 @@ class ErrorTracking {
|
|
|
887
887
|
properties.$process_person_profile = false;
|
|
888
888
|
}
|
|
889
889
|
const exceptionProperties = await propertiesFromUnknownInput(this.stackParser, this.frameModifiers, error, hint);
|
|
890
|
-
|
|
890
|
+
return {
|
|
891
891
|
event: '$exception',
|
|
892
892
|
distinctId: distinctId || uuidv7(),
|
|
893
893
|
properties: {
|
|
894
894
|
...exceptionProperties,
|
|
895
895
|
...properties
|
|
896
896
|
}
|
|
897
|
-
}
|
|
897
|
+
};
|
|
898
898
|
}
|
|
899
899
|
constructor(client, options) {
|
|
900
900
|
this.client = client;
|
|
@@ -908,7 +908,9 @@ class ErrorTracking {
|
|
|
908
908
|
}
|
|
909
909
|
}
|
|
910
910
|
onException(exception, hint) {
|
|
911
|
-
ErrorTracking.
|
|
911
|
+
void ErrorTracking.buildEventMessage(exception, hint).then(msg => {
|
|
912
|
+
this.client.capture(msg);
|
|
913
|
+
});
|
|
912
914
|
}
|
|
913
915
|
async onFatalError() {
|
|
914
916
|
await this.client.shutdown(SHUTDOWN_TIMEOUT);
|
|
@@ -928,14 +930,14 @@ function setupExpressErrorHandler(_posthog, app) {
|
|
|
928
930
|
};
|
|
929
931
|
// Given stateless nature of Node SDK we capture exceptions using personless processing
|
|
930
932
|
// when no user can be determined e.g. in the case of exception autocapture
|
|
931
|
-
ErrorTracking.
|
|
933
|
+
ErrorTracking.buildEventMessage(error, hint, uuidv7(), {
|
|
932
934
|
$process_person_profile: false
|
|
933
|
-
});
|
|
935
|
+
}).then(msg => _posthog.capture(msg));
|
|
934
936
|
next(error);
|
|
935
937
|
});
|
|
936
938
|
}
|
|
937
939
|
|
|
938
|
-
var version = "5.
|
|
940
|
+
var version = "5.3.1";
|
|
939
941
|
|
|
940
942
|
var PostHogPersistedProperty;
|
|
941
943
|
(function (PostHogPersistedProperty) {
|
|
@@ -973,6 +975,12 @@ var Compression;
|
|
|
973
975
|
})(Compression || (Compression = {}));
|
|
974
976
|
var SurveyPosition;
|
|
975
977
|
(function (SurveyPosition) {
|
|
978
|
+
SurveyPosition["TopLeft"] = "top_left";
|
|
979
|
+
SurveyPosition["TopCenter"] = "top_center";
|
|
980
|
+
SurveyPosition["TopRight"] = "top_right";
|
|
981
|
+
SurveyPosition["MiddleLeft"] = "middle_left";
|
|
982
|
+
SurveyPosition["MiddleCenter"] = "middle_center";
|
|
983
|
+
SurveyPosition["MiddleRight"] = "middle_right";
|
|
976
984
|
SurveyPosition["Left"] = "left";
|
|
977
985
|
SurveyPosition["Right"] = "right";
|
|
978
986
|
SurveyPosition["Center"] = "center";
|
|
@@ -2493,23 +2501,6 @@ class FeatureFlagsPoller {
|
|
|
2493
2501
|
stopPoller() {
|
|
2494
2502
|
clearTimeout(this.poller);
|
|
2495
2503
|
}
|
|
2496
|
-
_requestRemoteConfigPayload(flagKey) {
|
|
2497
|
-
const url = `${this.host}/api/projects/@current/feature_flags/${flagKey}/remote_config/`;
|
|
2498
|
-
const options = this.getPersonalApiKeyRequestOptions();
|
|
2499
|
-
let abortTimeout = null;
|
|
2500
|
-
if (this.timeout && typeof this.timeout === 'number') {
|
|
2501
|
-
const controller = new AbortController();
|
|
2502
|
-
abortTimeout = safeSetTimeout(() => {
|
|
2503
|
-
controller.abort();
|
|
2504
|
-
}, this.timeout);
|
|
2505
|
-
options.signal = controller.signal;
|
|
2506
|
-
}
|
|
2507
|
-
try {
|
|
2508
|
-
return this.fetch(url, options);
|
|
2509
|
-
} finally {
|
|
2510
|
-
clearTimeout(abortTimeout);
|
|
2511
|
-
}
|
|
2512
|
-
}
|
|
2513
2504
|
}
|
|
2514
2505
|
// # This function takes a distinct_id and a feature flag key and returns a float between 0 and 1.
|
|
2515
2506
|
// # Given the same distinct_id and key, it'll always return the same float. These floats are
|
|
@@ -2794,21 +2785,25 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
2794
2785
|
if (options.personalApiKey.includes('phc_')) {
|
|
2795
2786
|
throw new Error('Your Personal API key is invalid. These keys are prefixed with "phx_" and can be created in PostHog project settings.');
|
|
2796
2787
|
}
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
this.
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2788
|
+
// Only start the poller if local evaluation is enabled (defaults to true for backward compatibility)
|
|
2789
|
+
const shouldEnableLocalEvaluation = options.enableLocalEvaluation !== false;
|
|
2790
|
+
if (shouldEnableLocalEvaluation) {
|
|
2791
|
+
this.featureFlagsPoller = new FeatureFlagsPoller({
|
|
2792
|
+
pollingInterval: this.options.featureFlagsPollingInterval,
|
|
2793
|
+
personalApiKey: options.personalApiKey,
|
|
2794
|
+
projectApiKey: apiKey,
|
|
2795
|
+
timeout: options.requestTimeout ?? 10000,
|
|
2796
|
+
host: this.host,
|
|
2797
|
+
fetch: options.fetch,
|
|
2798
|
+
onError: err => {
|
|
2799
|
+
this._events.emit('error', err);
|
|
2800
|
+
},
|
|
2801
|
+
onLoad: count => {
|
|
2802
|
+
this._events.emit('localEvaluationFlagsLoaded', count);
|
|
2803
|
+
},
|
|
2804
|
+
customHeaders: this.getCustomHeaders()
|
|
2805
|
+
});
|
|
2806
|
+
}
|
|
2812
2807
|
}
|
|
2813
2808
|
this.errorTracking = new ErrorTracking(this, options);
|
|
2814
2809
|
this.distinctIdHasSentFlagCalls = {};
|
|
@@ -3164,7 +3159,10 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
3164
3159
|
return response;
|
|
3165
3160
|
}
|
|
3166
3161
|
async getRemoteConfigPayload(flagKey) {
|
|
3167
|
-
|
|
3162
|
+
if (!this.options.personalApiKey) {
|
|
3163
|
+
throw new Error('Personal API key is required for remote config payload decryption');
|
|
3164
|
+
}
|
|
3165
|
+
const response = await this._requestRemoteConfigPayload(flagKey);
|
|
3168
3166
|
if (!response) {
|
|
3169
3167
|
return undefined;
|
|
3170
3168
|
}
|
|
@@ -3258,6 +3256,38 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
3258
3256
|
this.featureFlagsPoller?.stopPoller();
|
|
3259
3257
|
return super._shutdown(shutdownTimeoutMs);
|
|
3260
3258
|
}
|
|
3259
|
+
async _requestRemoteConfigPayload(flagKey) {
|
|
3260
|
+
if (!this.options.personalApiKey) {
|
|
3261
|
+
return undefined;
|
|
3262
|
+
}
|
|
3263
|
+
const url = `${this.host}/api/projects/@current/feature_flags/${flagKey}/remote_config/`;
|
|
3264
|
+
const options = {
|
|
3265
|
+
method: 'GET',
|
|
3266
|
+
headers: {
|
|
3267
|
+
...this.getCustomHeaders(),
|
|
3268
|
+
'Content-Type': 'application/json',
|
|
3269
|
+
Authorization: `Bearer ${this.options.personalApiKey}`
|
|
3270
|
+
}
|
|
3271
|
+
};
|
|
3272
|
+
let abortTimeout = null;
|
|
3273
|
+
if (this.options.requestTimeout && typeof this.options.requestTimeout === 'number') {
|
|
3274
|
+
const controller = new AbortController();
|
|
3275
|
+
abortTimeout = safeSetTimeout(() => {
|
|
3276
|
+
controller.abort();
|
|
3277
|
+
}, this.options.requestTimeout);
|
|
3278
|
+
options.signal = controller.signal;
|
|
3279
|
+
}
|
|
3280
|
+
try {
|
|
3281
|
+
return await this.fetch(url, options);
|
|
3282
|
+
} catch (error) {
|
|
3283
|
+
this._events.emit('error', error);
|
|
3284
|
+
return undefined;
|
|
3285
|
+
} finally {
|
|
3286
|
+
if (abortTimeout) {
|
|
3287
|
+
clearTimeout(abortTimeout);
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
}
|
|
3261
3291
|
addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties) {
|
|
3262
3292
|
const allPersonProperties = {
|
|
3263
3293
|
distinct_id: distinctId,
|
|
@@ -3279,9 +3309,18 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
3279
3309
|
}
|
|
3280
3310
|
captureException(error, distinctId, additionalProperties) {
|
|
3281
3311
|
const syntheticException = new Error('PostHog syntheticException');
|
|
3282
|
-
ErrorTracking.
|
|
3312
|
+
ErrorTracking.buildEventMessage(error, {
|
|
3313
|
+
syntheticException
|
|
3314
|
+
}, distinctId, additionalProperties).then(msg => {
|
|
3315
|
+
this.capture(msg);
|
|
3316
|
+
});
|
|
3317
|
+
}
|
|
3318
|
+
async captureExceptionImmediate(error, distinctId, additionalProperties) {
|
|
3319
|
+
const syntheticException = new Error('PostHog syntheticException');
|
|
3320
|
+
const evtMsg = await ErrorTracking.buildEventMessage(error, {
|
|
3283
3321
|
syntheticException
|
|
3284
3322
|
}, distinctId, additionalProperties);
|
|
3323
|
+
return await this.captureImmediate(evtMsg);
|
|
3285
3324
|
}
|
|
3286
3325
|
}
|
|
3287
3326
|
|