posthog-node 4.1.0 → 4.2.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 +25 -3
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.esm.js +25 -3
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-core/src/index.d.ts +1 -0
- package/lib/posthog-core/src/types.d.ts +2 -0
- package/lib/posthog-node/src/feature-flags.d.ts +1 -1
- package/package.json +1 -1
- package/src/feature-flags.ts +18 -3
- package/test/feature-flags.spec.ts +141 -12
package/lib/index.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ declare type PostHogCoreOptions = {
|
|
|
40
40
|
/** Whether to post events to PostHog in JSON or compressed format. Defaults to 'form' */
|
|
41
41
|
captureMode?: 'json' | 'form';
|
|
42
42
|
disableGeoip?: boolean;
|
|
43
|
+
/** Special flag to indicate ingested data is for a historical migration. */
|
|
44
|
+
historicalMigration?: boolean;
|
|
43
45
|
};
|
|
44
46
|
declare enum PostHogPersistedProperty {
|
|
45
47
|
AnonymousId = "anonymous_id",
|
|
@@ -137,6 +139,7 @@ declare abstract class PostHogCoreStateless {
|
|
|
137
139
|
private captureMode;
|
|
138
140
|
private removeDebugCallback?;
|
|
139
141
|
private disableGeoip;
|
|
142
|
+
private historicalMigration;
|
|
140
143
|
disabled: boolean;
|
|
141
144
|
private defaultOptIn;
|
|
142
145
|
private pendingPromises;
|
package/lib/index.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from 'rusha';
|
|
2
2
|
|
|
3
|
-
var version = "4.
|
|
3
|
+
var version = "4.2.0";
|
|
4
4
|
|
|
5
5
|
var PostHogPersistedProperty;
|
|
6
6
|
(function (PostHogPersistedProperty) {
|
|
@@ -948,6 +948,7 @@ class PostHogCoreStateless {
|
|
|
948
948
|
constructor(apiKey, options) {
|
|
949
949
|
this.flushPromise = null;
|
|
950
950
|
this.disableGeoip = true;
|
|
951
|
+
this.historicalMigration = false;
|
|
951
952
|
this.disabled = false;
|
|
952
953
|
this.defaultOptIn = true;
|
|
953
954
|
this.pendingPromises = {};
|
|
@@ -973,6 +974,7 @@ class PostHogCoreStateless {
|
|
|
973
974
|
this.featureFlagsRequestTimeoutMs = options?.featureFlagsRequestTimeoutMs ?? 3000; // 3 seconds
|
|
974
975
|
this.disableGeoip = options?.disableGeoip ?? true;
|
|
975
976
|
this.disabled = options?.disabled ?? false;
|
|
977
|
+
this.historicalMigration = options?.historicalMigration ?? false;
|
|
976
978
|
// Init promise allows the derived class to block calls until it is ready
|
|
977
979
|
this._initPromise = Promise.resolve();
|
|
978
980
|
this._isInitialized = true;
|
|
@@ -1287,6 +1289,9 @@ class PostHogCoreStateless {
|
|
|
1287
1289
|
batch: messages,
|
|
1288
1290
|
sent_at: currentISOTime(),
|
|
1289
1291
|
};
|
|
1292
|
+
if (this.historicalMigration) {
|
|
1293
|
+
data.historical_migration = true;
|
|
1294
|
+
}
|
|
1290
1295
|
const payload = JSON.stringify(data);
|
|
1291
1296
|
const url = this.captureMode === 'form'
|
|
1292
1297
|
? `${this.host}/e/?ip=1&_=${currentTimestamp()}&v=${this.getLibraryVersion()}`
|
|
@@ -1430,6 +1435,7 @@ if (!_fetch) {
|
|
|
1430
1435
|
var fetch$1 = _fetch;
|
|
1431
1436
|
|
|
1432
1437
|
const LONG_SCALE = 0xfffffffffffffff;
|
|
1438
|
+
const NULL_VALUES_ALLOWED_OPERATORS = ['is_not'];
|
|
1433
1439
|
|
|
1434
1440
|
class ClientError extends Error {
|
|
1435
1441
|
constructor(message) {
|
|
@@ -1676,6 +1682,12 @@ class FeatureFlagsPoller {
|
|
|
1676
1682
|
isConditionMatch(flag, distinctId, condition, properties) {
|
|
1677
1683
|
const rolloutPercentage = condition.rollout_percentage;
|
|
1678
1684
|
|
|
1685
|
+
const warnFunction = msg => {
|
|
1686
|
+
if (this.debugMode) {
|
|
1687
|
+
console.warn(msg);
|
|
1688
|
+
}
|
|
1689
|
+
};
|
|
1690
|
+
|
|
1679
1691
|
if ((condition.properties || []).length > 0) {
|
|
1680
1692
|
for (const prop of condition.properties) {
|
|
1681
1693
|
const propertyType = prop.type;
|
|
@@ -1684,7 +1696,7 @@ class FeatureFlagsPoller {
|
|
|
1684
1696
|
if (propertyType === 'cohort') {
|
|
1685
1697
|
matches = matchCohort(prop, properties, this.cohorts, this.debugMode);
|
|
1686
1698
|
} else {
|
|
1687
|
-
matches = matchProperty(prop, properties);
|
|
1699
|
+
matches = matchProperty(prop, properties, warnFunction);
|
|
1688
1700
|
}
|
|
1689
1701
|
|
|
1690
1702
|
if (!matches) {
|
|
@@ -1826,7 +1838,7 @@ function _hash(key, distinctId, salt = '') {
|
|
|
1826
1838
|
return parseInt(sha1Hash.digest('hex').slice(0, 15), 16) / LONG_SCALE;
|
|
1827
1839
|
}
|
|
1828
1840
|
|
|
1829
|
-
function matchProperty(property, propertyValues) {
|
|
1841
|
+
function matchProperty(property, propertyValues, warnFunction) {
|
|
1830
1842
|
const key = property.key;
|
|
1831
1843
|
const value = property.value;
|
|
1832
1844
|
const operator = property.operator || 'exact';
|
|
@@ -1839,6 +1851,16 @@ function matchProperty(property, propertyValues) {
|
|
|
1839
1851
|
|
|
1840
1852
|
const overrideValue = propertyValues[key];
|
|
1841
1853
|
|
|
1854
|
+
if (overrideValue == null && !NULL_VALUES_ALLOWED_OPERATORS.includes(operator)) {
|
|
1855
|
+
// if the value is null, just fail the feature flag comparison
|
|
1856
|
+
// this isn't an InconclusiveMatchError because the property value was provided.
|
|
1857
|
+
if (warnFunction) {
|
|
1858
|
+
warnFunction(`Property ${key} cannot have a value of null/undefined with the ${operator} operator`);
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
return false;
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1842
1864
|
function computeExactMatch(value, overrideValue) {
|
|
1843
1865
|
if (Array.isArray(value)) {
|
|
1844
1866
|
return value.map(val => String(val).toLowerCase()).includes(String(overrideValue).toLowerCase());
|