posthog-node 2.1.0 → 2.2.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/index.cjs.js +114 -14
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +6 -0
- package/lib/index.esm.js +114 -14
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-core/src/index.d.ts +3 -0
- package/lib/posthog-core/src/types.d.ts +6 -0
- package/lib/posthog-node/src/types.d.ts +1 -0
- package/package.json +2 -2
- package/src/feature-flags.ts +49 -3
- package/src/posthog-node.ts +2 -2
- package/src/types.ts +1 -0
- package/test/feature-flags.spec.ts +329 -0
package/lib/index.d.ts
CHANGED
|
@@ -6,8 +6,14 @@ declare type PosthogCoreOptions = {
|
|
|
6
6
|
enable?: boolean;
|
|
7
7
|
sendFeatureFlagEvent?: boolean;
|
|
8
8
|
preloadFeatureFlags?: boolean;
|
|
9
|
+
bootstrap?: {
|
|
10
|
+
distinctId?: string;
|
|
11
|
+
isIdentifiedId?: boolean;
|
|
12
|
+
featureFlags?: Record<string, boolean | string>;
|
|
13
|
+
};
|
|
9
14
|
fetchRetryCount?: number;
|
|
10
15
|
fetchRetryDelay?: number;
|
|
16
|
+
requestTimeout?: number;
|
|
11
17
|
sessionExpirationTimeSeconds?: number;
|
|
12
18
|
captureMode?: 'json' | 'form';
|
|
13
19
|
};
|
package/lib/index.esm.js
CHANGED
|
@@ -155,7 +155,7 @@ function __spreadArray(to, from, pack) {
|
|
|
155
155
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
var version = "2.1
|
|
158
|
+
var version = "2.2.1";
|
|
159
159
|
|
|
160
160
|
var PostHogPersistedProperty;
|
|
161
161
|
(function (PostHogPersistedProperty) {
|
|
@@ -716,7 +716,7 @@ var SimpleEventEmitter = /** @class */ (function () {
|
|
|
716
716
|
var PostHogCore = /** @class */ (function () {
|
|
717
717
|
function PostHogCore(apiKey, options) {
|
|
718
718
|
var _this = this;
|
|
719
|
-
var _a, _b, _c, _d, _e;
|
|
719
|
+
var _a, _b, _c, _d, _e, _f;
|
|
720
720
|
this.flagCallReported = {};
|
|
721
721
|
// internal
|
|
722
722
|
this._events = new SimpleEventEmitter();
|
|
@@ -733,7 +733,8 @@ var PostHogCore = /** @class */ (function () {
|
|
|
733
733
|
retryCount: (_c = options === null || options === void 0 ? void 0 : options.fetchRetryCount) !== null && _c !== void 0 ? _c : 3,
|
|
734
734
|
retryDelay: (_d = options === null || options === void 0 ? void 0 : options.fetchRetryDelay) !== null && _d !== void 0 ? _d : 3000,
|
|
735
735
|
};
|
|
736
|
-
this.
|
|
736
|
+
this.requestTimeout = (_e = options === null || options === void 0 ? void 0 : options.requestTimeout) !== null && _e !== void 0 ? _e : 10;
|
|
737
|
+
this._sessionExpirationTimeSeconds = (_f = options === null || options === void 0 ? void 0 : options.sessionExpirationTimeSeconds) !== null && _f !== void 0 ? _f : 1800; // 30 minutes
|
|
737
738
|
// NOTE: It is important we don't initiate anything in the constructor as some async IO may still be underway on the parent
|
|
738
739
|
if ((options === null || options === void 0 ? void 0 : options.preloadFeatureFlags) !== false) {
|
|
739
740
|
safeSetTimeout(function () {
|
|
@@ -752,6 +753,26 @@ var PostHogCore = /** @class */ (function () {
|
|
|
752
753
|
}
|
|
753
754
|
return __assign({ $lib: this.getLibraryId(), $lib_version: this.getLibraryVersion(), $active_feature_flags: featureFlags ? Object.keys(featureFlags) : undefined }, featureVariantProperties);
|
|
754
755
|
};
|
|
756
|
+
PostHogCore.prototype.setupBootstrap = function (options) {
|
|
757
|
+
var _a, _b, _c, _d;
|
|
758
|
+
if ((_a = options === null || options === void 0 ? void 0 : options.bootstrap) === null || _a === void 0 ? void 0 : _a.distinctId) {
|
|
759
|
+
if ((_b = options === null || options === void 0 ? void 0 : options.bootstrap) === null || _b === void 0 ? void 0 : _b.isIdentifiedId) {
|
|
760
|
+
this.setPersistedProperty(PostHogPersistedProperty.DistinctId, options.bootstrap.distinctId);
|
|
761
|
+
}
|
|
762
|
+
else {
|
|
763
|
+
this.setPersistedProperty(PostHogPersistedProperty.AnonymousId, options.bootstrap.distinctId);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
if ((_c = options === null || options === void 0 ? void 0 : options.bootstrap) === null || _c === void 0 ? void 0 : _c.featureFlags) {
|
|
767
|
+
var activeFlags = Object.keys(((_d = options.bootstrap) === null || _d === void 0 ? void 0 : _d.featureFlags) || {})
|
|
768
|
+
.filter(function (flag) { var _a, _b; return !!((_b = (_a = options.bootstrap) === null || _a === void 0 ? void 0 : _a.featureFlags) === null || _b === void 0 ? void 0 : _b[flag]); })
|
|
769
|
+
.reduce(function (res, key) {
|
|
770
|
+
var _a, _b;
|
|
771
|
+
return ((res[key] = ((_b = (_a = options.bootstrap) === null || _a === void 0 ? void 0 : _a.featureFlags) === null || _b === void 0 ? void 0 : _b[key]) || false), res);
|
|
772
|
+
}, {});
|
|
773
|
+
this.setKnownFeatureFlags(activeFlags);
|
|
774
|
+
}
|
|
775
|
+
};
|
|
755
776
|
Object.defineProperty(PostHogCore.prototype, "props", {
|
|
756
777
|
// NOTE: Props are lazy loaded from localstorage hence the complex getter setter logic
|
|
757
778
|
get: function () {
|
|
@@ -995,8 +1016,7 @@ var PostHogCore = /** @class */ (function () {
|
|
|
995
1016
|
.then(function (r) { return r.json(); })
|
|
996
1017
|
.then(function (res) {
|
|
997
1018
|
if (res.featureFlags) {
|
|
998
|
-
_this.
|
|
999
|
-
_this._events.emit('featureflags', res.featureFlags);
|
|
1019
|
+
_this.setKnownFeatureFlags(res.featureFlags);
|
|
1000
1020
|
}
|
|
1001
1021
|
return res;
|
|
1002
1022
|
})
|
|
@@ -1007,6 +1027,10 @@ var PostHogCore = /** @class */ (function () {
|
|
|
1007
1027
|
});
|
|
1008
1028
|
});
|
|
1009
1029
|
};
|
|
1030
|
+
PostHogCore.prototype.setKnownFeatureFlags = function (featureFlags) {
|
|
1031
|
+
this.setPersistedProperty(PostHogPersistedProperty.FeatureFlags, featureFlags);
|
|
1032
|
+
this._events.emit('featureflags', featureFlags);
|
|
1033
|
+
};
|
|
1010
1034
|
PostHogCore.prototype.getFeatureFlag = function (key) {
|
|
1011
1035
|
var featureFlags = this.getFeatureFlags();
|
|
1012
1036
|
if (!featureFlags) {
|
|
@@ -1194,10 +1218,19 @@ var PostHogCore = /** @class */ (function () {
|
|
|
1194
1218
|
});
|
|
1195
1219
|
};
|
|
1196
1220
|
PostHogCore.prototype.fetchWithRetry = function (url, options, retryOptions) {
|
|
1221
|
+
var _a;
|
|
1222
|
+
var _b;
|
|
1197
1223
|
return __awaiter(this, void 0, void 0, function () {
|
|
1198
1224
|
var _this = this;
|
|
1199
|
-
return __generator(this, function (
|
|
1200
|
-
|
|
1225
|
+
return __generator(this, function (_c) {
|
|
1226
|
+
(_a = (_b = AbortSignal).timeout) !== null && _a !== void 0 ? _a : (_b.timeout = function timeout(ms) {
|
|
1227
|
+
var ctrl = new AbortController();
|
|
1228
|
+
setTimeout(function () { return ctrl.abort(); }, ms);
|
|
1229
|
+
return ctrl.signal;
|
|
1230
|
+
});
|
|
1231
|
+
return [2 /*return*/, retriable(function () {
|
|
1232
|
+
return _this.fetch(url, __assign({ signal: AbortSignal.timeout(_this.requestTimeout) }, options));
|
|
1233
|
+
}, retryOptions || this._retryOptions)];
|
|
1201
1234
|
});
|
|
1202
1235
|
});
|
|
1203
1236
|
};
|
|
@@ -1497,16 +1530,44 @@ function () {
|
|
|
1497
1530
|
};
|
|
1498
1531
|
|
|
1499
1532
|
FeatureFlagsPoller.prototype.matchFeatureFlagProperties = function (flag, distinctId, properties) {
|
|
1500
|
-
var
|
|
1533
|
+
var _a;
|
|
1501
1534
|
|
|
1502
1535
|
var flagFilters = flag.filters || {};
|
|
1503
1536
|
var flagConditions = flagFilters.groups || [];
|
|
1504
1537
|
var isInconclusive = false;
|
|
1505
|
-
var result = undefined;
|
|
1506
|
-
|
|
1538
|
+
var result = undefined; // # Stable sort conditions with variant overrides to the top. This ensures that if overrides are present, they are
|
|
1539
|
+
// # evaluated first, and the variant override is applied to the first matching condition.
|
|
1540
|
+
|
|
1541
|
+
var sortedFlagConditions = __spreadArray([], flagConditions, true).sort(function (conditionA, conditionB) {
|
|
1542
|
+
var AHasVariantOverride = !!conditionA.variant;
|
|
1543
|
+
var BHasVariantOverride = !!conditionB.variant;
|
|
1544
|
+
|
|
1545
|
+
if (AHasVariantOverride && BHasVariantOverride) {
|
|
1546
|
+
return 0;
|
|
1547
|
+
} else if (AHasVariantOverride) {
|
|
1548
|
+
return -1;
|
|
1549
|
+
} else if (BHasVariantOverride) {
|
|
1550
|
+
return 1;
|
|
1551
|
+
} else {
|
|
1552
|
+
return 0;
|
|
1553
|
+
}
|
|
1554
|
+
});
|
|
1555
|
+
|
|
1556
|
+
var _loop_1 = function (condition) {
|
|
1507
1557
|
try {
|
|
1508
|
-
if (
|
|
1509
|
-
|
|
1558
|
+
if (this_1.isConditionMatch(flag, distinctId, condition, properties)) {
|
|
1559
|
+
var variantOverride_1 = condition.variant;
|
|
1560
|
+
var flagVariants = ((_a = flagFilters.multivariate) === null || _a === void 0 ? void 0 : _a.variants) || [];
|
|
1561
|
+
|
|
1562
|
+
if (variantOverride_1 && flagVariants.some(function (variant) {
|
|
1563
|
+
return variant.key === variantOverride_1;
|
|
1564
|
+
})) {
|
|
1565
|
+
result = variantOverride_1;
|
|
1566
|
+
} else {
|
|
1567
|
+
result = this_1.getMatchingVariant(flag, distinctId) || true;
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
return "break";
|
|
1510
1571
|
}
|
|
1511
1572
|
} catch (e) {
|
|
1512
1573
|
if (e instanceof InconclusiveMatchError) {
|
|
@@ -1515,7 +1576,17 @@ function () {
|
|
|
1515
1576
|
throw e;
|
|
1516
1577
|
}
|
|
1517
1578
|
}
|
|
1518
|
-
}
|
|
1579
|
+
};
|
|
1580
|
+
|
|
1581
|
+
var this_1 = this;
|
|
1582
|
+
|
|
1583
|
+
for (var _i = 0, sortedFlagConditions_1 = sortedFlagConditions; _i < sortedFlagConditions_1.length; _i++) {
|
|
1584
|
+
var condition = sortedFlagConditions_1[_i];
|
|
1585
|
+
|
|
1586
|
+
var state_1 = _loop_1(condition);
|
|
1587
|
+
|
|
1588
|
+
if (state_1 === "break") break;
|
|
1589
|
+
}
|
|
1519
1590
|
|
|
1520
1591
|
if (result !== undefined) {
|
|
1521
1592
|
return result;
|
|
@@ -1812,6 +1883,17 @@ function matchProperty(property, propertyValues) {
|
|
|
1812
1883
|
case 'lte':
|
|
1813
1884
|
return typeof overrideValue == typeof value && overrideValue <= value;
|
|
1814
1885
|
|
|
1886
|
+
case 'is_date_after':
|
|
1887
|
+
case 'is_date_before':
|
|
1888
|
+
var parsedDate = convertToDateTime(value);
|
|
1889
|
+
var overrideDate = convertToDateTime(overrideValue);
|
|
1890
|
+
|
|
1891
|
+
if (operator === 'is_date_before') {
|
|
1892
|
+
return overrideDate < parsedDate;
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
return overrideDate > parsedDate;
|
|
1896
|
+
|
|
1815
1897
|
default:
|
|
1816
1898
|
console.error("Unknown operator: ".concat(operator));
|
|
1817
1899
|
return false;
|
|
@@ -1827,6 +1909,22 @@ function isValidRegex(regex) {
|
|
|
1827
1909
|
}
|
|
1828
1910
|
}
|
|
1829
1911
|
|
|
1912
|
+
function convertToDateTime(value) {
|
|
1913
|
+
if (value instanceof Date) {
|
|
1914
|
+
return value;
|
|
1915
|
+
} else if (typeof value === 'string' || typeof value === 'number') {
|
|
1916
|
+
var date = new Date(value);
|
|
1917
|
+
|
|
1918
|
+
if (!isNaN(date.valueOf())) {
|
|
1919
|
+
return date;
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
throw new InconclusiveMatchError("".concat(value, " is in an invalid date format"));
|
|
1923
|
+
} else {
|
|
1924
|
+
throw new InconclusiveMatchError("The date provided ".concat(value, " must be a string, number, or date object"));
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1830
1928
|
var THIRTY_SECONDS = 30 * 1000;
|
|
1831
1929
|
var MAX_CACHE_SIZE = 50 * 1000;
|
|
1832
1930
|
|
|
@@ -1894,6 +1992,8 @@ function () {
|
|
|
1894
1992
|
options = {};
|
|
1895
1993
|
}
|
|
1896
1994
|
|
|
1995
|
+
var _a;
|
|
1996
|
+
|
|
1897
1997
|
this._sharedClient = new PostHogClient(apiKey, options);
|
|
1898
1998
|
|
|
1899
1999
|
if (options.personalApiKey) {
|
|
@@ -1901,7 +2001,7 @@ function () {
|
|
|
1901
2001
|
pollingInterval: typeof options.featureFlagsPollingInterval === 'number' ? options.featureFlagsPollingInterval : THIRTY_SECONDS,
|
|
1902
2002
|
personalApiKey: options.personalApiKey,
|
|
1903
2003
|
projectApiKey: apiKey,
|
|
1904
|
-
timeout: options.requestTimeout,
|
|
2004
|
+
timeout: (_a = options.requestTimeout) !== null && _a !== void 0 ? _a : 10,
|
|
1905
2005
|
host: this._sharedClient.host,
|
|
1906
2006
|
fetch: options.fetch
|
|
1907
2007
|
});
|