posthog-node 4.12.0 → 4.14.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/CHANGELOG.md +8 -0
- package/lib/index.cjs.js +83 -9
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +27 -0
- package/lib/index.esm.js +83 -9
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-core/src/index.d.ts +10 -7
- package/lib/posthog-node/src/feature-flags.d.ts +7 -0
- package/lib/posthog-node/src/posthog-node.d.ts +6 -0
- package/lib/posthog-node/src/types.d.ts +11 -0
- package/package.json +2 -2
- package/src/extensions/error-tracking/error-conversion.ts +23 -10
- package/src/feature-flags.ts +12 -1
- package/src/posthog-node.ts +34 -0
- package/src/types.ts +13 -0
- package/test/extensions/error-conversion.spec.ts +44 -0
- package/test/feature-flags.spec.ts +218 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
# 4.14.0 - 2025-04-24
|
|
2
|
+
|
|
3
|
+
1. feat: Add super properties as a concept to the Node SDK
|
|
4
|
+
|
|
5
|
+
# 4.13.0 - 2025-04-21
|
|
6
|
+
|
|
7
|
+
1. feat: Add method to wait for local evaluation feature flag definitions to be loaded
|
|
8
|
+
|
|
1
9
|
# 4.12.0 – 2025-04-17
|
|
2
10
|
|
|
3
11
|
1. chore: roll out new feature flag evaluation backend to majority of customers
|
package/lib/index.cjs.js
CHANGED
|
@@ -22,7 +22,7 @@ function _interopNamespace(e) {
|
|
|
22
22
|
return Object.freeze(n);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
var version = "4.
|
|
25
|
+
var version = "4.14.0";
|
|
26
26
|
|
|
27
27
|
var PostHogPersistedProperty;
|
|
28
28
|
(function (PostHogPersistedProperty) {
|
|
@@ -327,7 +327,7 @@ function safeSetTimeout(fn, timeout) {
|
|
|
327
327
|
return t;
|
|
328
328
|
}
|
|
329
329
|
function getFetch() {
|
|
330
|
-
return typeof fetch !== 'undefined' ? fetch : typeof
|
|
330
|
+
return typeof fetch !== 'undefined' ? fetch : typeof globalThis.fetch !== 'undefined' ? globalThis.fetch : undefined;
|
|
331
331
|
}
|
|
332
332
|
// FNV-1a hash function
|
|
333
333
|
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
|
|
@@ -1595,6 +1595,30 @@ class PostHogCoreStateless {
|
|
|
1595
1595
|
}
|
|
1596
1596
|
return newSurveys ?? [];
|
|
1597
1597
|
}
|
|
1598
|
+
get props() {
|
|
1599
|
+
if (!this._props) {
|
|
1600
|
+
this._props = this.getPersistedProperty(PostHogPersistedProperty.Props);
|
|
1601
|
+
}
|
|
1602
|
+
return this._props || {};
|
|
1603
|
+
}
|
|
1604
|
+
set props(val) {
|
|
1605
|
+
this._props = val;
|
|
1606
|
+
}
|
|
1607
|
+
async register(properties) {
|
|
1608
|
+
this.wrap(() => {
|
|
1609
|
+
this.props = {
|
|
1610
|
+
...this.props,
|
|
1611
|
+
...properties,
|
|
1612
|
+
};
|
|
1613
|
+
this.setPersistedProperty(PostHogPersistedProperty.Props, this.props);
|
|
1614
|
+
});
|
|
1615
|
+
}
|
|
1616
|
+
async unregister(property) {
|
|
1617
|
+
this.wrap(() => {
|
|
1618
|
+
delete this.props[property];
|
|
1619
|
+
this.setPersistedProperty(PostHogPersistedProperty.Props, this.props);
|
|
1620
|
+
});
|
|
1621
|
+
}
|
|
1598
1622
|
/***
|
|
1599
1623
|
*** QUEUEING AND FLUSHING
|
|
1600
1624
|
***/
|
|
@@ -1988,6 +2012,7 @@ class FeatureFlagsPoller {
|
|
|
1988
2012
|
this.fetch = options.fetch || fetch$1;
|
|
1989
2013
|
this.onError = options.onError;
|
|
1990
2014
|
this.customHeaders = customHeaders;
|
|
2015
|
+
this.onLoad = options.onLoad;
|
|
1991
2016
|
void this.loadFeatureFlags();
|
|
1992
2017
|
}
|
|
1993
2018
|
debug(enabled = true) {
|
|
@@ -2204,6 +2229,13 @@ class FeatureFlagsPoller {
|
|
|
2204
2229
|
await this._loadFeatureFlags();
|
|
2205
2230
|
}
|
|
2206
2231
|
}
|
|
2232
|
+
/**
|
|
2233
|
+
* Returns true if the feature flags poller has loaded successfully at least once and has more than 0 feature flags.
|
|
2234
|
+
* This is useful to check if local evaluation is ready before calling getFeatureFlag.
|
|
2235
|
+
*/
|
|
2236
|
+
isLocalEvaluationReady() {
|
|
2237
|
+
return (this.loadedSuccessfullyOnce ?? false) && (this.featureFlags?.length ?? 0) > 0;
|
|
2238
|
+
}
|
|
2207
2239
|
/**
|
|
2208
2240
|
* If a client is misconfigured with an invalid or improper API key, the polling interval is doubled each time
|
|
2209
2241
|
* until a successful request is made, up to a maximum of 60 seconds.
|
|
@@ -2279,6 +2311,7 @@ class FeatureFlagsPoller {
|
|
|
2279
2311
|
this.loadedSuccessfullyOnce = true;
|
|
2280
2312
|
this.shouldBeginExponentialBackoff = false;
|
|
2281
2313
|
this.backOffCount = 0;
|
|
2314
|
+
this.onLoad?.(this.featureFlags.length);
|
|
2282
2315
|
break;
|
|
2283
2316
|
}
|
|
2284
2317
|
default:
|
|
@@ -3069,16 +3102,28 @@ async function propertiesFromUnknownInput(stackParser, input, hint) {
|
|
|
3069
3102
|
handled: true,
|
|
3070
3103
|
type: 'generic'
|
|
3071
3104
|
};
|
|
3072
|
-
const
|
|
3073
|
-
const
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3105
|
+
const errorList = getErrorList(mechanism, input, hint);
|
|
3106
|
+
const exceptionList = await Promise.all(errorList.map(async error => {
|
|
3107
|
+
const exception = await exceptionFromError(stackParser, error);
|
|
3108
|
+
exception.value = exception.value || '';
|
|
3109
|
+
exception.type = exception.type || 'Error';
|
|
3110
|
+
exception.mechanism = mechanism;
|
|
3111
|
+
return exception;
|
|
3112
|
+
}));
|
|
3077
3113
|
const properties = {
|
|
3078
|
-
$exception_list:
|
|
3114
|
+
$exception_list: exceptionList
|
|
3079
3115
|
};
|
|
3080
3116
|
return properties;
|
|
3081
3117
|
}
|
|
3118
|
+
// Flatten error causes into a list of errors
|
|
3119
|
+
// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause
|
|
3120
|
+
function getErrorList(mechanism, input, hint) {
|
|
3121
|
+
const error = getError(mechanism, input, hint);
|
|
3122
|
+
if (error.cause) {
|
|
3123
|
+
return [error, ...getErrorList(mechanism, error.cause, hint)];
|
|
3124
|
+
}
|
|
3125
|
+
return [error];
|
|
3126
|
+
}
|
|
3082
3127
|
function getError(mechanism, exception, hint) {
|
|
3083
3128
|
if (isError(exception)) {
|
|
3084
3129
|
return exception;
|
|
@@ -3105,7 +3150,7 @@ function getErrorPropertyFromObject(obj) {
|
|
|
3105
3150
|
for (const prop in obj) {
|
|
3106
3151
|
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
|
|
3107
3152
|
const value = obj[prop];
|
|
3108
|
-
if (value
|
|
3153
|
+
if (isError(value)) {
|
|
3109
3154
|
return value;
|
|
3110
3155
|
}
|
|
3111
3156
|
}
|
|
@@ -3532,6 +3577,9 @@ class PostHog extends PostHogCoreStateless {
|
|
|
3532
3577
|
onError: err => {
|
|
3533
3578
|
this._events.emit('error', err);
|
|
3534
3579
|
},
|
|
3580
|
+
onLoad: count => {
|
|
3581
|
+
this._events.emit('localEvaluationFlagsLoaded', count);
|
|
3582
|
+
},
|
|
3535
3583
|
customHeaders: this.getCustomHeaders()
|
|
3536
3584
|
});
|
|
3537
3585
|
}
|
|
@@ -3664,6 +3712,28 @@ class PostHog extends PostHogCoreStateless {
|
|
|
3664
3712
|
disableGeoip: data.disableGeoip
|
|
3665
3713
|
});
|
|
3666
3714
|
}
|
|
3715
|
+
isLocalEvaluationReady() {
|
|
3716
|
+
return this.featureFlagsPoller?.isLocalEvaluationReady() ?? false;
|
|
3717
|
+
}
|
|
3718
|
+
async waitForLocalEvaluationReady(timeoutMs = THIRTY_SECONDS) {
|
|
3719
|
+
if (this.isLocalEvaluationReady()) {
|
|
3720
|
+
return true;
|
|
3721
|
+
}
|
|
3722
|
+
if (this.featureFlagsPoller === undefined) {
|
|
3723
|
+
return false;
|
|
3724
|
+
}
|
|
3725
|
+
return new Promise(resolve => {
|
|
3726
|
+
const timeout = setTimeout(() => {
|
|
3727
|
+
cleanup();
|
|
3728
|
+
resolve(false);
|
|
3729
|
+
}, timeoutMs);
|
|
3730
|
+
const cleanup = this._events.on('localEvaluationFlagsLoaded', count => {
|
|
3731
|
+
clearTimeout(timeout);
|
|
3732
|
+
cleanup();
|
|
3733
|
+
resolve(count > 0);
|
|
3734
|
+
});
|
|
3735
|
+
});
|
|
3736
|
+
}
|
|
3667
3737
|
async getFeatureFlag(key, distinctId, options) {
|
|
3668
3738
|
const {
|
|
3669
3739
|
groups,
|
|
@@ -3841,6 +3911,10 @@ class PostHog extends PostHogCoreStateless {
|
|
|
3841
3911
|
disableGeoip
|
|
3842
3912
|
}, distinctId);
|
|
3843
3913
|
}
|
|
3914
|
+
/**
|
|
3915
|
+
* Reloads the feature flag definitions from the server for local evaluation.
|
|
3916
|
+
* This is useful to call if you want to ensure that the feature flags are up to date before calling getFeatureFlag.
|
|
3917
|
+
*/
|
|
3844
3918
|
async reloadFeatureFlags() {
|
|
3845
3919
|
await this.featureFlagsPoller?.loadFeatureFlags(true);
|
|
3846
3920
|
}
|