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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Next
|
|
2
2
|
|
|
3
|
+
# 4.2.0 - 2024-08-26
|
|
4
|
+
|
|
5
|
+
1. Added `historicalMigration` option for use in tools that are migrating large data to PostHog
|
|
6
|
+
|
|
7
|
+
# 4.1.1 - 2024-08-20
|
|
8
|
+
|
|
9
|
+
1. Local evaluation returns correct results on `undefined/null` values
|
|
10
|
+
|
|
3
11
|
# 4.1.0 - 2024-08-14
|
|
4
12
|
|
|
5
13
|
1. chore: change host to new address.
|
package/lib/index.cjs.js
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var rusha = require('rusha');
|
|
6
6
|
|
|
7
|
-
var version = "4.
|
|
7
|
+
var version = "4.2.0";
|
|
8
8
|
|
|
9
9
|
var PostHogPersistedProperty;
|
|
10
10
|
(function (PostHogPersistedProperty) {
|
|
@@ -952,6 +952,7 @@ class PostHogCoreStateless {
|
|
|
952
952
|
constructor(apiKey, options) {
|
|
953
953
|
this.flushPromise = null;
|
|
954
954
|
this.disableGeoip = true;
|
|
955
|
+
this.historicalMigration = false;
|
|
955
956
|
this.disabled = false;
|
|
956
957
|
this.defaultOptIn = true;
|
|
957
958
|
this.pendingPromises = {};
|
|
@@ -977,6 +978,7 @@ class PostHogCoreStateless {
|
|
|
977
978
|
this.featureFlagsRequestTimeoutMs = options?.featureFlagsRequestTimeoutMs ?? 3000; // 3 seconds
|
|
978
979
|
this.disableGeoip = options?.disableGeoip ?? true;
|
|
979
980
|
this.disabled = options?.disabled ?? false;
|
|
981
|
+
this.historicalMigration = options?.historicalMigration ?? false;
|
|
980
982
|
// Init promise allows the derived class to block calls until it is ready
|
|
981
983
|
this._initPromise = Promise.resolve();
|
|
982
984
|
this._isInitialized = true;
|
|
@@ -1291,6 +1293,9 @@ class PostHogCoreStateless {
|
|
|
1291
1293
|
batch: messages,
|
|
1292
1294
|
sent_at: currentISOTime(),
|
|
1293
1295
|
};
|
|
1296
|
+
if (this.historicalMigration) {
|
|
1297
|
+
data.historical_migration = true;
|
|
1298
|
+
}
|
|
1294
1299
|
const payload = JSON.stringify(data);
|
|
1295
1300
|
const url = this.captureMode === 'form'
|
|
1296
1301
|
? `${this.host}/e/?ip=1&_=${currentTimestamp()}&v=${this.getLibraryVersion()}`
|
|
@@ -1434,6 +1439,7 @@ if (!_fetch) {
|
|
|
1434
1439
|
var fetch$1 = _fetch;
|
|
1435
1440
|
|
|
1436
1441
|
const LONG_SCALE = 0xfffffffffffffff;
|
|
1442
|
+
const NULL_VALUES_ALLOWED_OPERATORS = ['is_not'];
|
|
1437
1443
|
|
|
1438
1444
|
class ClientError extends Error {
|
|
1439
1445
|
constructor(message) {
|
|
@@ -1680,6 +1686,12 @@ class FeatureFlagsPoller {
|
|
|
1680
1686
|
isConditionMatch(flag, distinctId, condition, properties) {
|
|
1681
1687
|
const rolloutPercentage = condition.rollout_percentage;
|
|
1682
1688
|
|
|
1689
|
+
const warnFunction = msg => {
|
|
1690
|
+
if (this.debugMode) {
|
|
1691
|
+
console.warn(msg);
|
|
1692
|
+
}
|
|
1693
|
+
};
|
|
1694
|
+
|
|
1683
1695
|
if ((condition.properties || []).length > 0) {
|
|
1684
1696
|
for (const prop of condition.properties) {
|
|
1685
1697
|
const propertyType = prop.type;
|
|
@@ -1688,7 +1700,7 @@ class FeatureFlagsPoller {
|
|
|
1688
1700
|
if (propertyType === 'cohort') {
|
|
1689
1701
|
matches = matchCohort(prop, properties, this.cohorts, this.debugMode);
|
|
1690
1702
|
} else {
|
|
1691
|
-
matches = matchProperty(prop, properties);
|
|
1703
|
+
matches = matchProperty(prop, properties, warnFunction);
|
|
1692
1704
|
}
|
|
1693
1705
|
|
|
1694
1706
|
if (!matches) {
|
|
@@ -1830,7 +1842,7 @@ function _hash(key, distinctId, salt = '') {
|
|
|
1830
1842
|
return parseInt(sha1Hash.digest('hex').slice(0, 15), 16) / LONG_SCALE;
|
|
1831
1843
|
}
|
|
1832
1844
|
|
|
1833
|
-
function matchProperty(property, propertyValues) {
|
|
1845
|
+
function matchProperty(property, propertyValues, warnFunction) {
|
|
1834
1846
|
const key = property.key;
|
|
1835
1847
|
const value = property.value;
|
|
1836
1848
|
const operator = property.operator || 'exact';
|
|
@@ -1843,6 +1855,16 @@ function matchProperty(property, propertyValues) {
|
|
|
1843
1855
|
|
|
1844
1856
|
const overrideValue = propertyValues[key];
|
|
1845
1857
|
|
|
1858
|
+
if (overrideValue == null && !NULL_VALUES_ALLOWED_OPERATORS.includes(operator)) {
|
|
1859
|
+
// if the value is null, just fail the feature flag comparison
|
|
1860
|
+
// this isn't an InconclusiveMatchError because the property value was provided.
|
|
1861
|
+
if (warnFunction) {
|
|
1862
|
+
warnFunction(`Property ${key} cannot have a value of null/undefined with the ${operator} operator`);
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
return false;
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1846
1868
|
function computeExactMatch(value, overrideValue) {
|
|
1847
1869
|
if (Array.isArray(value)) {
|
|
1848
1870
|
return value.map(val => String(val).toLowerCase()).includes(String(overrideValue).toLowerCase());
|