posthog-node 2.5.3 → 2.6.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 +7 -0
- package/lib/index.cjs.js +163 -10
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.esm.js +163 -10
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-core/src/index.d.ts +1 -0
- package/lib/posthog-node/src/feature-flags.d.ts +4 -1
- package/lib/posthog-node/src/posthog-node.d.ts +1 -0
- package/lib/posthog-node/src/types.d.ts +12 -6
- package/package.json +1 -1
- package/src/feature-flags.ts +143 -10
- package/src/posthog-node.ts +5 -0
- package/src/types.ts +14 -6
- package/test/feature-flags.spec.ts +173 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# 2.6.0 - 2023-03-14
|
|
2
|
+
|
|
3
|
+
1. Add support for all cohorts local evaluation in feature flags.
|
|
4
|
+
|
|
5
|
+
# 2.5.4 - 2023-02-27
|
|
6
|
+
|
|
7
|
+
1. Fix error log for local evaluation of feature flags (InconclusiveMatchError(s)) to only show during debug mode.
|
|
1
8
|
# 2.5.3 - 2023-02-21
|
|
2
9
|
|
|
3
10
|
1. Allow passing in a distinctId to `groupIdentify()`.
|
package/lib/index.cjs.js
CHANGED
|
@@ -163,7 +163,7 @@ function __spreadArray(to, from, pack) {
|
|
|
163
163
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
var version = "2.
|
|
166
|
+
var version = "2.6.0";
|
|
167
167
|
|
|
168
168
|
var PostHogPersistedProperty;
|
|
169
169
|
(function (PostHogPersistedProperty) {
|
|
@@ -725,6 +725,7 @@ var SimpleEventEmitter = /** @class */ (function () {
|
|
|
725
725
|
var PostHogCoreStateless = /** @class */ (function () {
|
|
726
726
|
function PostHogCoreStateless(apiKey, options) {
|
|
727
727
|
var _a, _b, _c, _d;
|
|
728
|
+
this.debugMode = false;
|
|
728
729
|
this.pendingPromises = {};
|
|
729
730
|
// internal
|
|
730
731
|
this._events = new SimpleEventEmitter();
|
|
@@ -769,6 +770,7 @@ var PostHogCoreStateless = /** @class */ (function () {
|
|
|
769
770
|
var _a;
|
|
770
771
|
if (enabled === void 0) { enabled = true; }
|
|
771
772
|
(_a = this.removeDebugCallback) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
773
|
+
this.debugMode = enabled;
|
|
772
774
|
if (enabled) {
|
|
773
775
|
this.removeDebugCallback = this.on('*', function (event, payload) { return console.log('PostHog Debug', event, payload); });
|
|
774
776
|
}
|
|
@@ -1598,11 +1600,13 @@ function () {
|
|
|
1598
1600
|
host = _a.host,
|
|
1599
1601
|
options = __rest(_a, ["pollingInterval", "personalApiKey", "projectApiKey", "timeout", "host"]);
|
|
1600
1602
|
|
|
1603
|
+
this.debugMode = false;
|
|
1601
1604
|
this.pollingInterval = pollingInterval;
|
|
1602
1605
|
this.personalApiKey = personalApiKey;
|
|
1603
1606
|
this.featureFlags = [];
|
|
1604
1607
|
this.featureFlagsByKey = {};
|
|
1605
1608
|
this.groupTypeMapping = {};
|
|
1609
|
+
this.cohorts = {};
|
|
1606
1610
|
this.loadedSuccessfullyOnce = false;
|
|
1607
1611
|
this.timeout = timeout;
|
|
1608
1612
|
this.projectApiKey = projectApiKey;
|
|
@@ -1613,6 +1617,14 @@ function () {
|
|
|
1613
1617
|
void this.loadFeatureFlags();
|
|
1614
1618
|
}
|
|
1615
1619
|
|
|
1620
|
+
FeatureFlagsPoller.prototype.debug = function (enabled) {
|
|
1621
|
+
if (enabled === void 0) {
|
|
1622
|
+
enabled = true;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
this.debugMode = enabled;
|
|
1626
|
+
};
|
|
1627
|
+
|
|
1616
1628
|
FeatureFlagsPoller.prototype.getFeatureFlag = function (key, distinctId, groups, personProperties, groupProperties) {
|
|
1617
1629
|
if (groups === void 0) {
|
|
1618
1630
|
groups = {};
|
|
@@ -1660,9 +1672,15 @@ function () {
|
|
|
1660
1672
|
if (featureFlag !== undefined) {
|
|
1661
1673
|
try {
|
|
1662
1674
|
response = this.computeFlagLocally(featureFlag, distinctId, groups, personProperties, groupProperties);
|
|
1675
|
+
|
|
1676
|
+
if (this.debugMode) {
|
|
1677
|
+
console.debug("Successfully computed flag locally: ".concat(key, " -> ").concat(response));
|
|
1678
|
+
}
|
|
1663
1679
|
} catch (e) {
|
|
1664
1680
|
if (e instanceof InconclusiveMatchError) {
|
|
1665
|
-
|
|
1681
|
+
if (this.debugMode) {
|
|
1682
|
+
console.debug("InconclusiveMatchError when computing flag locally: ".concat(key, ": ").concat(e));
|
|
1683
|
+
}
|
|
1666
1684
|
} else if (e instanceof Error) {
|
|
1667
1685
|
console.error("Error computing flag locally: ".concat(key, ": ").concat(e));
|
|
1668
1686
|
}
|
|
@@ -1926,14 +1944,23 @@ function () {
|
|
|
1926
1944
|
var rolloutPercentage = condition.rollout_percentage;
|
|
1927
1945
|
|
|
1928
1946
|
if ((condition.properties || []).length > 0) {
|
|
1929
|
-
var
|
|
1930
|
-
|
|
1931
|
-
|
|
1947
|
+
for (var _i = 0, _a = condition.properties; _i < _a.length; _i++) {
|
|
1948
|
+
var prop = _a[_i];
|
|
1949
|
+
var propertyType = prop.type;
|
|
1950
|
+
var matches = false;
|
|
1932
1951
|
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1952
|
+
if (propertyType === 'cohort') {
|
|
1953
|
+
matches = matchCohort(prop, properties, this.cohorts);
|
|
1954
|
+
} else {
|
|
1955
|
+
matches = matchProperty(prop, properties);
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
if (!matches) {
|
|
1959
|
+
return false;
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
if (rolloutPercentage == undefined) {
|
|
1937
1964
|
return true;
|
|
1938
1965
|
}
|
|
1939
1966
|
}
|
|
@@ -2066,6 +2093,7 @@ function () {
|
|
|
2066
2093
|
return acc[curr.key] = curr, acc;
|
|
2067
2094
|
}, {});
|
|
2068
2095
|
this.groupTypeMapping = responseJson.group_type_mapping || {};
|
|
2096
|
+
this.cohorts = responseJson.cohorts || [];
|
|
2069
2097
|
this.loadedSuccessfullyOnce = true;
|
|
2070
2098
|
return [3
|
|
2071
2099
|
/*break*/
|
|
@@ -2098,7 +2126,7 @@ function () {
|
|
|
2098
2126
|
return __generator(this, function (_a) {
|
|
2099
2127
|
switch (_a.label) {
|
|
2100
2128
|
case 0:
|
|
2101
|
-
url = "".concat(this.host, "/api/feature_flag/local_evaluation?token=").concat(this.projectApiKey);
|
|
2129
|
+
url = "".concat(this.host, "/api/feature_flag/local_evaluation?token=").concat(this.projectApiKey, "&send_cohorts");
|
|
2102
2130
|
options = {
|
|
2103
2131
|
method: 'GET',
|
|
2104
2132
|
headers: {
|
|
@@ -2235,6 +2263,119 @@ function matchProperty(property, propertyValues) {
|
|
|
2235
2263
|
}
|
|
2236
2264
|
}
|
|
2237
2265
|
|
|
2266
|
+
function matchCohort(property, propertyValues, cohortProperties) {
|
|
2267
|
+
var cohortId = String(property.value);
|
|
2268
|
+
|
|
2269
|
+
if (!(cohortId in cohortProperties)) {
|
|
2270
|
+
throw new InconclusiveMatchError("can't match cohort without a given cohort property value");
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
var propertyGroup = cohortProperties[cohortId];
|
|
2274
|
+
return matchPropertyGroup(propertyGroup, propertyValues, cohortProperties);
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2277
|
+
function matchPropertyGroup(propertyGroup, propertyValues, cohortProperties) {
|
|
2278
|
+
if (!propertyGroup) {
|
|
2279
|
+
return true;
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2282
|
+
var propertyGroupType = propertyGroup.type;
|
|
2283
|
+
var properties = propertyGroup.values;
|
|
2284
|
+
|
|
2285
|
+
if (!properties || properties.length === 0) {
|
|
2286
|
+
// empty groups are no-ops, always match
|
|
2287
|
+
return true;
|
|
2288
|
+
}
|
|
2289
|
+
|
|
2290
|
+
var errorMatchingLocally = false;
|
|
2291
|
+
|
|
2292
|
+
if ('values' in properties[0]) {
|
|
2293
|
+
// a nested property group
|
|
2294
|
+
for (var _i = 0, _a = properties; _i < _a.length; _i++) {
|
|
2295
|
+
var prop = _a[_i];
|
|
2296
|
+
|
|
2297
|
+
try {
|
|
2298
|
+
var matches = matchPropertyGroup(prop, propertyValues, cohortProperties);
|
|
2299
|
+
|
|
2300
|
+
if (propertyGroupType === 'AND') {
|
|
2301
|
+
if (!matches) {
|
|
2302
|
+
return false;
|
|
2303
|
+
}
|
|
2304
|
+
} else {
|
|
2305
|
+
// OR group
|
|
2306
|
+
if (matches) {
|
|
2307
|
+
return true;
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
} catch (err) {
|
|
2311
|
+
if (err instanceof InconclusiveMatchError) {
|
|
2312
|
+
console.debug("Failed to compute property ".concat(prop, " locally: ").concat(err));
|
|
2313
|
+
errorMatchingLocally = true;
|
|
2314
|
+
} else {
|
|
2315
|
+
throw err;
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
|
|
2320
|
+
if (errorMatchingLocally) {
|
|
2321
|
+
throw new InconclusiveMatchError("Can't match cohort without a given cohort property value");
|
|
2322
|
+
} // if we get here, all matched in AND case, or none matched in OR case
|
|
2323
|
+
|
|
2324
|
+
|
|
2325
|
+
return propertyGroupType === 'AND';
|
|
2326
|
+
} else {
|
|
2327
|
+
for (var _b = 0, _c = properties; _b < _c.length; _b++) {
|
|
2328
|
+
var prop = _c[_b];
|
|
2329
|
+
|
|
2330
|
+
try {
|
|
2331
|
+
var matches = void 0;
|
|
2332
|
+
|
|
2333
|
+
if (prop.type === 'cohort') {
|
|
2334
|
+
matches = matchCohort(prop, propertyValues, cohortProperties);
|
|
2335
|
+
} else {
|
|
2336
|
+
matches = matchProperty(prop, propertyValues);
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
var negation = prop.negation || false;
|
|
2340
|
+
|
|
2341
|
+
if (propertyGroupType === 'AND') {
|
|
2342
|
+
// if negated property, do the inverse
|
|
2343
|
+
if (!matches && !negation) {
|
|
2344
|
+
return false;
|
|
2345
|
+
}
|
|
2346
|
+
|
|
2347
|
+
if (matches && negation) {
|
|
2348
|
+
return false;
|
|
2349
|
+
}
|
|
2350
|
+
} else {
|
|
2351
|
+
// OR group
|
|
2352
|
+
if (matches && !negation) {
|
|
2353
|
+
return true;
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
if (!matches && negation) {
|
|
2357
|
+
return true;
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
} catch (err) {
|
|
2361
|
+
if (err instanceof InconclusiveMatchError) {
|
|
2362
|
+
console.debug("Failed to compute property ".concat(prop, " locally: ").concat(err));
|
|
2363
|
+
errorMatchingLocally = true;
|
|
2364
|
+
} else {
|
|
2365
|
+
throw err;
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
|
|
2370
|
+
if (errorMatchingLocally) {
|
|
2371
|
+
throw new InconclusiveMatchError("can't match cohort without a given cohort property value");
|
|
2372
|
+
} // if we get here, all matched in AND case, or none matched in OR case
|
|
2373
|
+
|
|
2374
|
+
|
|
2375
|
+
return propertyGroupType === 'AND';
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2238
2379
|
function isValidRegex(regex) {
|
|
2239
2380
|
try {
|
|
2240
2381
|
new RegExp(regex);
|
|
@@ -2330,6 +2471,18 @@ function (_super) {
|
|
|
2330
2471
|
return _super.prototype.optOut.call(this);
|
|
2331
2472
|
};
|
|
2332
2473
|
|
|
2474
|
+
PostHog.prototype.debug = function (enabled) {
|
|
2475
|
+
var _a;
|
|
2476
|
+
|
|
2477
|
+
if (enabled === void 0) {
|
|
2478
|
+
enabled = true;
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2481
|
+
_super.prototype.debug.call(this, enabled);
|
|
2482
|
+
|
|
2483
|
+
(_a = this.featureFlagsPoller) === null || _a === void 0 ? void 0 : _a.debug(enabled);
|
|
2484
|
+
};
|
|
2485
|
+
|
|
2333
2486
|
PostHog.prototype.capture = function (_a) {
|
|
2334
2487
|
var _this = this;
|
|
2335
2488
|
|