posthog-node 2.0.0-alpha9 → 2.0.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 +12 -0
- package/README.md +0 -2
- package/lib/index.cjs.js +857 -60
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +68 -9
- package/lib/index.esm.js +858 -61
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-core/src/index.d.ts +19 -6
- package/lib/posthog-core/src/types.d.ts +3 -1
- package/lib/posthog-node/src/feature-flags.d.ts +48 -0
- package/lib/posthog-node/src/posthog-node.d.ts +29 -3
- package/lib/posthog-node/src/types.d.ts +69 -6
- package/package.json +1 -1
- package/src/feature-flags.ts +396 -0
- package/src/posthog-node.ts +180 -25
- package/src/types.ts +72 -8
- package/test/feature-flags.spec.ts +3192 -0
- package/test/posthog-node.spec.ts +300 -24
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import undici from 'undici';
|
|
1
|
+
import undici, { request } from 'undici';
|
|
2
|
+
import { createHash } from 'crypto';
|
|
2
3
|
|
|
3
4
|
/******************************************************************************
|
|
4
5
|
Copyright (c) Microsoft Corporation.
|
|
@@ -129,9 +130,20 @@ function __generator(thisArg, body) {
|
|
|
129
130
|
throw op[1];
|
|
130
131
|
return { value: op[0] ? op[1] : void 0, done: true };
|
|
131
132
|
}
|
|
133
|
+
}
|
|
134
|
+
function __spreadArray(to, from, pack) {
|
|
135
|
+
if (pack || arguments.length === 2)
|
|
136
|
+
for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
137
|
+
if (ar || !(i in from)) {
|
|
138
|
+
if (!ar)
|
|
139
|
+
ar = Array.prototype.slice.call(from, 0, i);
|
|
140
|
+
ar[i] = from[i];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
132
144
|
}
|
|
133
145
|
|
|
134
|
-
var version = "2.0.
|
|
146
|
+
var version = "2.0.1";
|
|
135
147
|
|
|
136
148
|
var PostHogPersistedProperty;
|
|
137
149
|
(function (PostHogPersistedProperty) {
|
|
@@ -144,6 +156,8 @@ var PostHogPersistedProperty;
|
|
|
144
156
|
PostHogPersistedProperty["OptedOut"] = "opted_out";
|
|
145
157
|
PostHogPersistedProperty["SessionId"] = "session_id";
|
|
146
158
|
PostHogPersistedProperty["SessionLastTimestamp"] = "session_timestamp";
|
|
159
|
+
PostHogPersistedProperty["PersonProperties"] = "person_properties";
|
|
160
|
+
PostHogPersistedProperty["GroupProperties"] = "group_properties";
|
|
147
161
|
})(PostHogPersistedProperty || (PostHogPersistedProperty = {}));
|
|
148
162
|
|
|
149
163
|
function assert(truthyValue, message) {
|
|
@@ -717,12 +731,14 @@ var PostHogCore = /** @class */ (function () {
|
|
|
717
731
|
}
|
|
718
732
|
PostHogCore.prototype.getCommonEventProperties = function () {
|
|
719
733
|
var featureFlags = this.getFeatureFlags();
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
734
|
+
var featureVariantProperties = {};
|
|
735
|
+
if (featureFlags) {
|
|
736
|
+
for (var _i = 0, _a = Object.entries(featureFlags); _i < _a.length; _i++) {
|
|
737
|
+
var _b = _a[_i], feature = _b[0], variant = _b[1];
|
|
738
|
+
featureVariantProperties["$feature/".concat(feature)] = variant;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return __assign({ $lib: this.getLibraryId(), $lib_version: this.getLibraryVersion(), $active_feature_flags: featureFlags ? Object.keys(featureFlags) : undefined }, featureVariantProperties);
|
|
726
742
|
};
|
|
727
743
|
Object.defineProperty(PostHogCore.prototype, "props", {
|
|
728
744
|
// NOTE: Props are lazy loaded from localstorage hence the complex getter setter logic
|
|
@@ -738,6 +754,9 @@ var PostHogCore = /** @class */ (function () {
|
|
|
738
754
|
enumerable: false,
|
|
739
755
|
configurable: true
|
|
740
756
|
});
|
|
757
|
+
PostHogCore.prototype.clearProps = function () {
|
|
758
|
+
this.props = undefined;
|
|
759
|
+
};
|
|
741
760
|
Object.defineProperty(PostHogCore.prototype, "optedOut", {
|
|
742
761
|
get: function () {
|
|
743
762
|
var _a, _b;
|
|
@@ -755,9 +774,15 @@ var PostHogCore = /** @class */ (function () {
|
|
|
755
774
|
PostHogCore.prototype.on = function (event, cb) {
|
|
756
775
|
return this._events.on(event, cb);
|
|
757
776
|
};
|
|
758
|
-
PostHogCore.prototype.reset = function () {
|
|
759
|
-
|
|
760
|
-
|
|
777
|
+
PostHogCore.prototype.reset = function (propertiesToKeep) {
|
|
778
|
+
var allPropertiesToKeep = __spreadArray([PostHogPersistedProperty.Queue], (propertiesToKeep || []), true);
|
|
779
|
+
// clean up props
|
|
780
|
+
this.clearProps();
|
|
781
|
+
for (var _i = 0, _a = Object.keys(PostHogPersistedProperty); _i < _a.length; _i++) {
|
|
782
|
+
var key = _a[_i];
|
|
783
|
+
if (!allPropertiesToKeep.includes(PostHogPersistedProperty[key])) {
|
|
784
|
+
this.setPersistedProperty(PostHogPersistedProperty[key], null);
|
|
785
|
+
}
|
|
761
786
|
}
|
|
762
787
|
};
|
|
763
788
|
PostHogCore.prototype.debug = function (enabled) {
|
|
@@ -832,12 +857,18 @@ var PostHogCore = /** @class */ (function () {
|
|
|
832
857
|
this.enqueue('identify', payload);
|
|
833
858
|
return this;
|
|
834
859
|
};
|
|
835
|
-
PostHogCore.prototype.capture = function (event, properties) {
|
|
860
|
+
PostHogCore.prototype.capture = function (event, properties, forceSendFeatureFlags) {
|
|
861
|
+
if (forceSendFeatureFlags === void 0) { forceSendFeatureFlags = false; }
|
|
836
862
|
if (properties === null || properties === void 0 ? void 0 : properties.$groups) {
|
|
837
863
|
this.groups(properties.$groups);
|
|
838
864
|
}
|
|
839
|
-
|
|
840
|
-
|
|
865
|
+
if (forceSendFeatureFlags) {
|
|
866
|
+
this._sendFeatureFlags(event, properties);
|
|
867
|
+
}
|
|
868
|
+
else {
|
|
869
|
+
var payload = this.buildPayload({ event: event, properties: properties });
|
|
870
|
+
this.enqueue('capture', payload);
|
|
871
|
+
}
|
|
841
872
|
return this;
|
|
842
873
|
};
|
|
843
874
|
PostHogCore.prototype.alias = function (alias) {
|
|
@@ -867,7 +898,6 @@ var PostHogCore = /** @class */ (function () {
|
|
|
867
898
|
PostHogCore.prototype.groups = function (groups) {
|
|
868
899
|
// Get persisted groups
|
|
869
900
|
var existingGroups = this.props.$groups || {};
|
|
870
|
-
// NOTE: Should we do the same for groups listed in identify / capture?
|
|
871
901
|
this.register({
|
|
872
902
|
$groups: __assign(__assign({}, existingGroups), groups),
|
|
873
903
|
});
|
|
@@ -895,31 +925,58 @@ var PostHogCore = /** @class */ (function () {
|
|
|
895
925
|
this.enqueue('capture', payload);
|
|
896
926
|
return this;
|
|
897
927
|
};
|
|
928
|
+
/***
|
|
929
|
+
* PROPERTIES
|
|
930
|
+
***/
|
|
931
|
+
PostHogCore.prototype.personProperties = function (properties) {
|
|
932
|
+
// Get persisted person properties
|
|
933
|
+
var existingProperties = this.getPersistedProperty(PostHogPersistedProperty.PersonProperties) || {};
|
|
934
|
+
this.setPersistedProperty(PostHogPersistedProperty.PersonProperties, __assign(__assign({}, existingProperties), properties));
|
|
935
|
+
return this;
|
|
936
|
+
};
|
|
937
|
+
PostHogCore.prototype.groupProperties = function (properties) {
|
|
938
|
+
// Get persisted group properties
|
|
939
|
+
var existingProperties = this.getPersistedProperty(PostHogPersistedProperty.GroupProperties) || {};
|
|
940
|
+
if (Object.keys(existingProperties).length !== 0) {
|
|
941
|
+
Object.keys(existingProperties).forEach(function (groupType) {
|
|
942
|
+
existingProperties[groupType] = __assign(__assign({}, existingProperties[groupType]), properties[groupType]);
|
|
943
|
+
delete properties[groupType];
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
this.setPersistedProperty(PostHogPersistedProperty.GroupProperties, __assign(__assign({}, existingProperties), properties));
|
|
947
|
+
return this;
|
|
948
|
+
};
|
|
898
949
|
/***
|
|
899
950
|
*** FEATURE FLAGS
|
|
900
951
|
***/
|
|
901
|
-
PostHogCore.prototype.decideAsync = function () {
|
|
952
|
+
PostHogCore.prototype.decideAsync = function (sendAnonDistinctId) {
|
|
953
|
+
if (sendAnonDistinctId === void 0) { sendAnonDistinctId = true; }
|
|
902
954
|
if (this._decideResponsePromise) {
|
|
903
955
|
return this._decideResponsePromise;
|
|
904
956
|
}
|
|
905
|
-
return this._decideAsync();
|
|
957
|
+
return this._decideAsync(sendAnonDistinctId);
|
|
906
958
|
};
|
|
907
|
-
PostHogCore.prototype._decideAsync = function () {
|
|
959
|
+
PostHogCore.prototype._decideAsync = function (sendAnonDistinctId) {
|
|
960
|
+
if (sendAnonDistinctId === void 0) { sendAnonDistinctId = true; }
|
|
908
961
|
return __awaiter(this, void 0, void 0, function () {
|
|
909
|
-
var url, distinctId, groups, fetchOptions;
|
|
962
|
+
var url, distinctId, groups, personProperties, groupProperties, fetchOptions;
|
|
910
963
|
var _this = this;
|
|
911
964
|
return __generator(this, function (_a) {
|
|
912
965
|
url = "".concat(this.host, "/decide/?v=2");
|
|
913
966
|
distinctId = this.getDistinctId();
|
|
914
967
|
groups = this.props.$groups || {};
|
|
968
|
+
personProperties = this.getPersistedProperty(PostHogPersistedProperty.PersonProperties) || {};
|
|
969
|
+
groupProperties = this.getPersistedProperty(PostHogPersistedProperty.GroupProperties) || {};
|
|
915
970
|
fetchOptions = {
|
|
916
971
|
method: 'POST',
|
|
917
972
|
headers: { 'Content-Type': 'application/json' },
|
|
918
973
|
body: JSON.stringify({
|
|
919
974
|
token: this.apiKey,
|
|
920
975
|
distinct_id: distinctId,
|
|
921
|
-
$anon_distinct_id: this.getAnonymousId(),
|
|
976
|
+
$anon_distinct_id: sendAnonDistinctId ? this.getAnonymousId() : undefined,
|
|
922
977
|
groups: groups,
|
|
978
|
+
person_properties: personProperties,
|
|
979
|
+
group_properties: groupProperties,
|
|
923
980
|
}),
|
|
924
981
|
};
|
|
925
982
|
this._decideResponsePromise = this.fetchWithRetry(url, fetchOptions)
|
|
@@ -938,23 +995,26 @@ var PostHogCore = /** @class */ (function () {
|
|
|
938
995
|
});
|
|
939
996
|
});
|
|
940
997
|
};
|
|
941
|
-
PostHogCore.prototype.getFeatureFlag = function (key
|
|
942
|
-
var _a;
|
|
943
|
-
if (defaultResult === void 0) { defaultResult = false; }
|
|
998
|
+
PostHogCore.prototype.getFeatureFlag = function (key) {
|
|
944
999
|
var featureFlags = this.getFeatureFlags();
|
|
945
1000
|
if (!featureFlags) {
|
|
946
|
-
// If we haven't loaded flags yet we respond undefined
|
|
1001
|
+
// If we haven't loaded flags yet, or errored out, we respond with undefined
|
|
947
1002
|
return undefined;
|
|
948
1003
|
}
|
|
1004
|
+
var response = featureFlags[key];
|
|
1005
|
+
if (response === undefined) {
|
|
1006
|
+
// `/decide` returns nothing for flags which are false.
|
|
1007
|
+
response = false;
|
|
1008
|
+
}
|
|
949
1009
|
if (this.sendFeatureFlagEvent && !this.flagCallReported[key]) {
|
|
950
1010
|
this.flagCallReported[key] = true;
|
|
951
1011
|
this.capture('$feature_flag_called', {
|
|
952
1012
|
$feature_flag: key,
|
|
953
|
-
$feature_flag_response:
|
|
1013
|
+
$feature_flag_response: response,
|
|
954
1014
|
});
|
|
955
1015
|
}
|
|
956
|
-
// If we have flags we either return the value (true or string) or
|
|
957
|
-
return
|
|
1016
|
+
// If we have flags we either return the value (true or string) or false
|
|
1017
|
+
return response;
|
|
958
1018
|
};
|
|
959
1019
|
PostHogCore.prototype.getFeatureFlags = function () {
|
|
960
1020
|
var flags = this.getPersistedProperty(PostHogPersistedProperty.FeatureFlags);
|
|
@@ -973,17 +1033,19 @@ var PostHogCore = /** @class */ (function () {
|
|
|
973
1033
|
}
|
|
974
1034
|
return flags;
|
|
975
1035
|
};
|
|
976
|
-
PostHogCore.prototype.isFeatureEnabled = function (key
|
|
977
|
-
var
|
|
978
|
-
if (
|
|
979
|
-
|
|
980
|
-
|
|
1036
|
+
PostHogCore.prototype.isFeatureEnabled = function (key) {
|
|
1037
|
+
var response = this.getFeatureFlag(key);
|
|
1038
|
+
if (response === undefined) {
|
|
1039
|
+
return undefined;
|
|
1040
|
+
}
|
|
1041
|
+
return !!response;
|
|
981
1042
|
};
|
|
982
|
-
PostHogCore.prototype.reloadFeatureFlagsAsync = function () {
|
|
1043
|
+
PostHogCore.prototype.reloadFeatureFlagsAsync = function (sendAnonDistinctId) {
|
|
1044
|
+
if (sendAnonDistinctId === void 0) { sendAnonDistinctId = true; }
|
|
983
1045
|
return __awaiter(this, void 0, void 0, function () {
|
|
984
1046
|
return __generator(this, function (_a) {
|
|
985
1047
|
switch (_a.label) {
|
|
986
|
-
case 0: return [4 /*yield*/, this.decideAsync()];
|
|
1048
|
+
case 0: return [4 /*yield*/, this.decideAsync(sendAnonDistinctId)];
|
|
987
1049
|
case 1: return [2 /*return*/, (_a.sent()).featureFlags];
|
|
988
1050
|
}
|
|
989
1051
|
});
|
|
@@ -1021,6 +1083,14 @@ var PostHogCore = /** @class */ (function () {
|
|
|
1021
1083
|
}
|
|
1022
1084
|
return this.setPersistedProperty(PostHogPersistedProperty.OverrideFeatureFlags, flags);
|
|
1023
1085
|
};
|
|
1086
|
+
PostHogCore.prototype._sendFeatureFlags = function (event, properties) {
|
|
1087
|
+
var _this = this;
|
|
1088
|
+
this.reloadFeatureFlagsAsync(false).finally(function () {
|
|
1089
|
+
// Try to enqueue message irrespective of errors during feature flag fetching
|
|
1090
|
+
var payload = _this.buildPayload({ event: event, properties: properties });
|
|
1091
|
+
_this.enqueue('capture', payload);
|
|
1092
|
+
});
|
|
1093
|
+
};
|
|
1024
1094
|
/***
|
|
1025
1095
|
*** QUEUEING AND FLUSHING
|
|
1026
1096
|
***/
|
|
@@ -1049,13 +1119,15 @@ var PostHogCore = /** @class */ (function () {
|
|
|
1049
1119
|
PostHogCore.prototype.flushAsync = function () {
|
|
1050
1120
|
var _this = this;
|
|
1051
1121
|
return new Promise(function (resolve, reject) {
|
|
1052
|
-
_this.flush(function (err, data) {
|
|
1122
|
+
_this.flush(function (err, data) {
|
|
1123
|
+
return err ? reject(err) : resolve(data);
|
|
1124
|
+
});
|
|
1053
1125
|
});
|
|
1054
1126
|
};
|
|
1055
1127
|
PostHogCore.prototype.flush = function (callback) {
|
|
1056
1128
|
var _this = this;
|
|
1057
1129
|
if (this.optedOut) {
|
|
1058
|
-
return callback
|
|
1130
|
+
return callback === null || callback === void 0 ? void 0 : callback();
|
|
1059
1131
|
}
|
|
1060
1132
|
if (this._flushTimer) {
|
|
1061
1133
|
clearTimeout(this._flushTimer);
|
|
@@ -1063,7 +1135,7 @@ var PostHogCore = /** @class */ (function () {
|
|
|
1063
1135
|
}
|
|
1064
1136
|
var queue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1065
1137
|
if (!queue.length) {
|
|
1066
|
-
return callback
|
|
1138
|
+
return callback === null || callback === void 0 ? void 0 : callback();
|
|
1067
1139
|
}
|
|
1068
1140
|
var items = queue.splice(0, this.flushAt);
|
|
1069
1141
|
this.setPersistedProperty(PostHogPersistedProperty.Queue, queue);
|
|
@@ -1150,6 +1222,553 @@ var PostHogMemoryStorage = /** @class */ (function () {
|
|
|
1150
1222
|
return PostHogMemoryStorage;
|
|
1151
1223
|
}());
|
|
1152
1224
|
|
|
1225
|
+
var LONG_SCALE = 0xfffffffffffffff;
|
|
1226
|
+
|
|
1227
|
+
var ClientError =
|
|
1228
|
+
/** @class */
|
|
1229
|
+
function (_super) {
|
|
1230
|
+
__extends(ClientError, _super);
|
|
1231
|
+
|
|
1232
|
+
function ClientError(message) {
|
|
1233
|
+
var _this = _super.call(this) || this;
|
|
1234
|
+
|
|
1235
|
+
Error.captureStackTrace(_this, _this.constructor);
|
|
1236
|
+
_this.name = 'ClientError';
|
|
1237
|
+
_this.message = message;
|
|
1238
|
+
Object.setPrototypeOf(_this, ClientError.prototype);
|
|
1239
|
+
return _this;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
return ClientError;
|
|
1243
|
+
}(Error);
|
|
1244
|
+
|
|
1245
|
+
var InconclusiveMatchError =
|
|
1246
|
+
/** @class */
|
|
1247
|
+
function (_super) {
|
|
1248
|
+
__extends(InconclusiveMatchError, _super);
|
|
1249
|
+
|
|
1250
|
+
function InconclusiveMatchError(message) {
|
|
1251
|
+
var _this = _super.call(this, message) || this;
|
|
1252
|
+
|
|
1253
|
+
_this.name = _this.constructor.name;
|
|
1254
|
+
Error.captureStackTrace(_this, _this.constructor); // instanceof doesn't work in ES3 or ES5
|
|
1255
|
+
// https://www.dannyguo.com/blog/how-to-fix-instanceof-not-working-for-custom-errors-in-typescript/
|
|
1256
|
+
// this is the workaround
|
|
1257
|
+
|
|
1258
|
+
Object.setPrototypeOf(_this, InconclusiveMatchError.prototype);
|
|
1259
|
+
return _this;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
return InconclusiveMatchError;
|
|
1263
|
+
}(Error);
|
|
1264
|
+
|
|
1265
|
+
var FeatureFlagsPoller =
|
|
1266
|
+
/** @class */
|
|
1267
|
+
function () {
|
|
1268
|
+
function FeatureFlagsPoller(_a) {
|
|
1269
|
+
var pollingInterval = _a.pollingInterval,
|
|
1270
|
+
personalApiKey = _a.personalApiKey,
|
|
1271
|
+
projectApiKey = _a.projectApiKey,
|
|
1272
|
+
timeout = _a.timeout,
|
|
1273
|
+
host = _a.host;
|
|
1274
|
+
this.pollingInterval = pollingInterval;
|
|
1275
|
+
this.personalApiKey = personalApiKey;
|
|
1276
|
+
this.featureFlags = [];
|
|
1277
|
+
this.groupTypeMapping = {};
|
|
1278
|
+
this.loadedSuccessfullyOnce = false;
|
|
1279
|
+
this.timeout = timeout;
|
|
1280
|
+
this.projectApiKey = projectApiKey;
|
|
1281
|
+
this.host = host;
|
|
1282
|
+
this.poller = undefined;
|
|
1283
|
+
void this.loadFeatureFlags();
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
FeatureFlagsPoller.prototype.getFeatureFlag = function (key, distinctId, groups, personProperties, groupProperties) {
|
|
1287
|
+
if (groups === void 0) {
|
|
1288
|
+
groups = {};
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
if (personProperties === void 0) {
|
|
1292
|
+
personProperties = {};
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
if (groupProperties === void 0) {
|
|
1296
|
+
groupProperties = {};
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1300
|
+
var response, featureFlag, _i, _a, flag;
|
|
1301
|
+
|
|
1302
|
+
return __generator(this, function (_b) {
|
|
1303
|
+
switch (_b.label) {
|
|
1304
|
+
case 0:
|
|
1305
|
+
return [4
|
|
1306
|
+
/*yield*/
|
|
1307
|
+
, this.loadFeatureFlags()];
|
|
1308
|
+
|
|
1309
|
+
case 1:
|
|
1310
|
+
_b.sent();
|
|
1311
|
+
|
|
1312
|
+
response = undefined;
|
|
1313
|
+
featureFlag = undefined;
|
|
1314
|
+
|
|
1315
|
+
if (!this.loadedSuccessfullyOnce) {
|
|
1316
|
+
return [2
|
|
1317
|
+
/*return*/
|
|
1318
|
+
, response];
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
for (_i = 0, _a = this.featureFlags; _i < _a.length; _i++) {
|
|
1322
|
+
flag = _a[_i];
|
|
1323
|
+
|
|
1324
|
+
if (key === flag.key) {
|
|
1325
|
+
featureFlag = flag;
|
|
1326
|
+
break;
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
if (featureFlag !== undefined) {
|
|
1331
|
+
try {
|
|
1332
|
+
response = this.computeFlagLocally(featureFlag, distinctId, groups, personProperties, groupProperties);
|
|
1333
|
+
console.debug("Successfully computed flag locally: ".concat(key, " -> ").concat(response));
|
|
1334
|
+
} catch (e) {
|
|
1335
|
+
if (e instanceof InconclusiveMatchError) {
|
|
1336
|
+
console.debug("Can't compute flag locally: ".concat(key, ": ").concat(e));
|
|
1337
|
+
} else if (e instanceof Error) {
|
|
1338
|
+
console.error("Error computing flag locally: ".concat(key, ": ").concat(e));
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
return [2
|
|
1344
|
+
/*return*/
|
|
1345
|
+
, response];
|
|
1346
|
+
}
|
|
1347
|
+
});
|
|
1348
|
+
});
|
|
1349
|
+
};
|
|
1350
|
+
|
|
1351
|
+
FeatureFlagsPoller.prototype.getAllFlags = function (distinctId, groups, personProperties, groupProperties) {
|
|
1352
|
+
if (groups === void 0) {
|
|
1353
|
+
groups = {};
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
if (personProperties === void 0) {
|
|
1357
|
+
personProperties = {};
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
if (groupProperties === void 0) {
|
|
1361
|
+
groupProperties = {};
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1365
|
+
var response, fallbackToDecide;
|
|
1366
|
+
|
|
1367
|
+
var _this = this;
|
|
1368
|
+
|
|
1369
|
+
return __generator(this, function (_a) {
|
|
1370
|
+
switch (_a.label) {
|
|
1371
|
+
case 0:
|
|
1372
|
+
return [4
|
|
1373
|
+
/*yield*/
|
|
1374
|
+
, this.loadFeatureFlags()];
|
|
1375
|
+
|
|
1376
|
+
case 1:
|
|
1377
|
+
_a.sent();
|
|
1378
|
+
|
|
1379
|
+
response = {};
|
|
1380
|
+
fallbackToDecide = this.featureFlags.length == 0;
|
|
1381
|
+
this.featureFlags.map(function (flag) {
|
|
1382
|
+
try {
|
|
1383
|
+
response[flag.key] = _this.computeFlagLocally(flag, distinctId, groups, personProperties, groupProperties);
|
|
1384
|
+
} catch (e) {
|
|
1385
|
+
if (e instanceof InconclusiveMatchError) ; else if (e instanceof Error) {
|
|
1386
|
+
console.error("Error computing flag locally: ".concat(flag.key, ": ").concat(e));
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
fallbackToDecide = true;
|
|
1390
|
+
}
|
|
1391
|
+
});
|
|
1392
|
+
return [2
|
|
1393
|
+
/*return*/
|
|
1394
|
+
, {
|
|
1395
|
+
response: response,
|
|
1396
|
+
fallbackToDecide: fallbackToDecide
|
|
1397
|
+
}];
|
|
1398
|
+
}
|
|
1399
|
+
});
|
|
1400
|
+
});
|
|
1401
|
+
};
|
|
1402
|
+
|
|
1403
|
+
FeatureFlagsPoller.prototype.computeFlagLocally = function (flag, distinctId, groups, personProperties, groupProperties) {
|
|
1404
|
+
if (groups === void 0) {
|
|
1405
|
+
groups = {};
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
if (personProperties === void 0) {
|
|
1409
|
+
personProperties = {};
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
if (groupProperties === void 0) {
|
|
1413
|
+
groupProperties = {};
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
if (flag.ensure_experience_continuity) {
|
|
1417
|
+
throw new InconclusiveMatchError('Flag has experience continuity enabled');
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
if (!flag.active) {
|
|
1421
|
+
return false;
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
var flagFilters = flag.filters || {};
|
|
1425
|
+
var aggregation_group_type_index = flagFilters.aggregation_group_type_index;
|
|
1426
|
+
|
|
1427
|
+
if (aggregation_group_type_index != undefined) {
|
|
1428
|
+
var groupName = this.groupTypeMapping[String(aggregation_group_type_index)];
|
|
1429
|
+
|
|
1430
|
+
if (!groupName) {
|
|
1431
|
+
console.warn("[FEATURE FLAGS] Unknown group type index ".concat(aggregation_group_type_index, " for feature flag ").concat(flag.key));
|
|
1432
|
+
throw new InconclusiveMatchError('Flag has unknown group type index');
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
if (!(groupName in groups)) {
|
|
1436
|
+
console.warn("[FEATURE FLAGS] Can't compute group feature flag: ".concat(flag.key, " without group names passed in"));
|
|
1437
|
+
return false;
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
var focusedGroupProperties = groupProperties[groupName];
|
|
1441
|
+
return this.matchFeatureFlagProperties(flag, groups[groupName], focusedGroupProperties);
|
|
1442
|
+
} else {
|
|
1443
|
+
return this.matchFeatureFlagProperties(flag, distinctId, personProperties);
|
|
1444
|
+
}
|
|
1445
|
+
};
|
|
1446
|
+
|
|
1447
|
+
FeatureFlagsPoller.prototype.matchFeatureFlagProperties = function (flag, distinctId, properties) {
|
|
1448
|
+
var _this = this;
|
|
1449
|
+
|
|
1450
|
+
var flagFilters = flag.filters || {};
|
|
1451
|
+
var flagConditions = flagFilters.groups || [];
|
|
1452
|
+
var isInconclusive = false;
|
|
1453
|
+
var result = undefined;
|
|
1454
|
+
flagConditions.forEach(function (condition) {
|
|
1455
|
+
try {
|
|
1456
|
+
if (_this.isConditionMatch(flag, distinctId, condition, properties)) {
|
|
1457
|
+
result = _this.getMatchingVariant(flag, distinctId) || true;
|
|
1458
|
+
}
|
|
1459
|
+
} catch (e) {
|
|
1460
|
+
if (e instanceof InconclusiveMatchError) {
|
|
1461
|
+
isInconclusive = true;
|
|
1462
|
+
} else {
|
|
1463
|
+
throw e;
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
});
|
|
1467
|
+
|
|
1468
|
+
if (result !== undefined) {
|
|
1469
|
+
return result;
|
|
1470
|
+
} else if (isInconclusive) {
|
|
1471
|
+
throw new InconclusiveMatchError("Can't determine if feature flag is enabled or not with given properties");
|
|
1472
|
+
} // We can only return False when all conditions are False
|
|
1473
|
+
|
|
1474
|
+
|
|
1475
|
+
return false;
|
|
1476
|
+
};
|
|
1477
|
+
|
|
1478
|
+
FeatureFlagsPoller.prototype.isConditionMatch = function (flag, distinctId, condition, properties) {
|
|
1479
|
+
var rolloutPercentage = condition.rollout_percentage;
|
|
1480
|
+
|
|
1481
|
+
if ((condition.properties || []).length > 0) {
|
|
1482
|
+
var matchAll = condition.properties.every(function (property) {
|
|
1483
|
+
return matchProperty(property, properties);
|
|
1484
|
+
});
|
|
1485
|
+
|
|
1486
|
+
if (!matchAll) {
|
|
1487
|
+
return false;
|
|
1488
|
+
} else if (rolloutPercentage == undefined) {
|
|
1489
|
+
// == to include `null` as a match, not just `undefined`
|
|
1490
|
+
return true;
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
if (rolloutPercentage != undefined && _hash(flag.key, distinctId) > rolloutPercentage / 100.0) {
|
|
1495
|
+
return false;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
return true;
|
|
1499
|
+
};
|
|
1500
|
+
|
|
1501
|
+
FeatureFlagsPoller.prototype.getMatchingVariant = function (flag, distinctId) {
|
|
1502
|
+
var hashValue = _hash(flag.key, distinctId, 'variant');
|
|
1503
|
+
|
|
1504
|
+
var matchingVariant = this.variantLookupTable(flag).find(function (variant) {
|
|
1505
|
+
return hashValue >= variant.valueMin && hashValue < variant.valueMax;
|
|
1506
|
+
});
|
|
1507
|
+
|
|
1508
|
+
if (matchingVariant) {
|
|
1509
|
+
return matchingVariant.key;
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
return undefined;
|
|
1513
|
+
};
|
|
1514
|
+
|
|
1515
|
+
FeatureFlagsPoller.prototype.variantLookupTable = function (flag) {
|
|
1516
|
+
var _a;
|
|
1517
|
+
|
|
1518
|
+
var lookupTable = [];
|
|
1519
|
+
var valueMin = 0;
|
|
1520
|
+
var valueMax = 0;
|
|
1521
|
+
var flagFilters = flag.filters || {};
|
|
1522
|
+
var multivariates = ((_a = flagFilters.multivariate) === null || _a === void 0 ? void 0 : _a.variants) || [];
|
|
1523
|
+
multivariates.forEach(function (variant) {
|
|
1524
|
+
valueMax = valueMin + variant.rollout_percentage / 100.0;
|
|
1525
|
+
lookupTable.push({
|
|
1526
|
+
valueMin: valueMin,
|
|
1527
|
+
valueMax: valueMax,
|
|
1528
|
+
key: variant.key
|
|
1529
|
+
});
|
|
1530
|
+
valueMin = valueMax;
|
|
1531
|
+
});
|
|
1532
|
+
return lookupTable;
|
|
1533
|
+
};
|
|
1534
|
+
|
|
1535
|
+
FeatureFlagsPoller.prototype.loadFeatureFlags = function (forceReload) {
|
|
1536
|
+
if (forceReload === void 0) {
|
|
1537
|
+
forceReload = false;
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1541
|
+
return __generator(this, function (_a) {
|
|
1542
|
+
switch (_a.label) {
|
|
1543
|
+
case 0:
|
|
1544
|
+
if (!(!this.loadedSuccessfullyOnce || forceReload)) return [3
|
|
1545
|
+
/*break*/
|
|
1546
|
+
, 2];
|
|
1547
|
+
return [4
|
|
1548
|
+
/*yield*/
|
|
1549
|
+
, this._loadFeatureFlags()];
|
|
1550
|
+
|
|
1551
|
+
case 1:
|
|
1552
|
+
_a.sent();
|
|
1553
|
+
|
|
1554
|
+
_a.label = 2;
|
|
1555
|
+
|
|
1556
|
+
case 2:
|
|
1557
|
+
return [2
|
|
1558
|
+
/*return*/
|
|
1559
|
+
];
|
|
1560
|
+
}
|
|
1561
|
+
});
|
|
1562
|
+
});
|
|
1563
|
+
};
|
|
1564
|
+
|
|
1565
|
+
FeatureFlagsPoller.prototype._loadFeatureFlags = function () {
|
|
1566
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1567
|
+
var res, responseJson, err_1;
|
|
1568
|
+
|
|
1569
|
+
var _this = this;
|
|
1570
|
+
|
|
1571
|
+
return __generator(this, function (_a) {
|
|
1572
|
+
switch (_a.label) {
|
|
1573
|
+
case 0:
|
|
1574
|
+
if (this.poller) {
|
|
1575
|
+
clearTimeout(this.poller);
|
|
1576
|
+
this.poller = undefined;
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
this.poller = setTimeout(function () {
|
|
1580
|
+
return _this._loadFeatureFlags();
|
|
1581
|
+
}, this.pollingInterval);
|
|
1582
|
+
_a.label = 1;
|
|
1583
|
+
|
|
1584
|
+
case 1:
|
|
1585
|
+
_a.trys.push([1, 4,, 5]);
|
|
1586
|
+
|
|
1587
|
+
return [4
|
|
1588
|
+
/*yield*/
|
|
1589
|
+
, this._requestFeatureFlagDefinitions()];
|
|
1590
|
+
|
|
1591
|
+
case 2:
|
|
1592
|
+
res = _a.sent();
|
|
1593
|
+
|
|
1594
|
+
if (res && res.statusCode === 401) {
|
|
1595
|
+
throw new ClientError("Your personalApiKey is invalid. Are you sure you're not using your Project API key? More information: https://posthog.com/docs/api/overview");
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
return [4
|
|
1599
|
+
/*yield*/
|
|
1600
|
+
, res.body.json()];
|
|
1601
|
+
|
|
1602
|
+
case 3:
|
|
1603
|
+
responseJson = _a.sent();
|
|
1604
|
+
|
|
1605
|
+
if (!('flags' in responseJson)) {
|
|
1606
|
+
console.error("Invalid response when getting feature flags: ".concat(JSON.stringify(responseJson)));
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
this.featureFlags = responseJson.flags || [];
|
|
1610
|
+
this.groupTypeMapping = responseJson.group_type_mapping || {};
|
|
1611
|
+
this.loadedSuccessfullyOnce = true;
|
|
1612
|
+
return [3
|
|
1613
|
+
/*break*/
|
|
1614
|
+
, 5];
|
|
1615
|
+
|
|
1616
|
+
case 4:
|
|
1617
|
+
err_1 = _a.sent(); // if an error that is not an instance of ClientError is thrown
|
|
1618
|
+
// we silently ignore the error when reloading feature flags
|
|
1619
|
+
|
|
1620
|
+
if (err_1 instanceof ClientError) {
|
|
1621
|
+
throw err_1;
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
return [3
|
|
1625
|
+
/*break*/
|
|
1626
|
+
, 5];
|
|
1627
|
+
|
|
1628
|
+
case 5:
|
|
1629
|
+
return [2
|
|
1630
|
+
/*return*/
|
|
1631
|
+
];
|
|
1632
|
+
}
|
|
1633
|
+
});
|
|
1634
|
+
});
|
|
1635
|
+
};
|
|
1636
|
+
|
|
1637
|
+
FeatureFlagsPoller.prototype._requestFeatureFlagDefinitions = function () {
|
|
1638
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1639
|
+
var url, headers, options, res, err_2;
|
|
1640
|
+
return __generator(this, function (_a) {
|
|
1641
|
+
switch (_a.label) {
|
|
1642
|
+
case 0:
|
|
1643
|
+
url = "".concat(this.host, "/api/feature_flag/local_evaluation?token=").concat(this.projectApiKey);
|
|
1644
|
+
headers = {
|
|
1645
|
+
'Content-Type': 'application/json',
|
|
1646
|
+
Authorization: "Bearer ".concat(this.personalApiKey),
|
|
1647
|
+
'user-agent': "posthog-node/".concat(version)
|
|
1648
|
+
};
|
|
1649
|
+
options = {
|
|
1650
|
+
method: 'GET',
|
|
1651
|
+
headers: headers
|
|
1652
|
+
};
|
|
1653
|
+
|
|
1654
|
+
if (this.timeout && typeof this.timeout === 'number') {
|
|
1655
|
+
options.bodyTimeout = this.timeout;
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
_a.label = 1;
|
|
1659
|
+
|
|
1660
|
+
case 1:
|
|
1661
|
+
_a.trys.push([1, 3,, 4]);
|
|
1662
|
+
|
|
1663
|
+
return [4
|
|
1664
|
+
/*yield*/
|
|
1665
|
+
, request(url, options)];
|
|
1666
|
+
|
|
1667
|
+
case 2:
|
|
1668
|
+
res = _a.sent();
|
|
1669
|
+
return [3
|
|
1670
|
+
/*break*/
|
|
1671
|
+
, 4];
|
|
1672
|
+
|
|
1673
|
+
case 3:
|
|
1674
|
+
err_2 = _a.sent();
|
|
1675
|
+
throw new Error("Request failed with error: ".concat(err_2));
|
|
1676
|
+
|
|
1677
|
+
case 4:
|
|
1678
|
+
return [2
|
|
1679
|
+
/*return*/
|
|
1680
|
+
, res];
|
|
1681
|
+
}
|
|
1682
|
+
});
|
|
1683
|
+
});
|
|
1684
|
+
};
|
|
1685
|
+
|
|
1686
|
+
FeatureFlagsPoller.prototype.stopPoller = function () {
|
|
1687
|
+
clearTimeout(this.poller);
|
|
1688
|
+
};
|
|
1689
|
+
|
|
1690
|
+
return FeatureFlagsPoller;
|
|
1691
|
+
}(); // # This function takes a distinct_id and a feature flag key and returns a float between 0 and 1.
|
|
1692
|
+
// # Given the same distinct_id and key, it'll always return the same float. These floats are
|
|
1693
|
+
// # uniformly distributed between 0 and 1, so if we want to show this feature to 20% of traffic
|
|
1694
|
+
// # we can do _hash(key, distinct_id) < 0.2
|
|
1695
|
+
|
|
1696
|
+
|
|
1697
|
+
function _hash(key, distinctId, salt) {
|
|
1698
|
+
if (salt === void 0) {
|
|
1699
|
+
salt = '';
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
var sha1Hash = createHash('sha1');
|
|
1703
|
+
sha1Hash.update("".concat(key, ".").concat(distinctId).concat(salt));
|
|
1704
|
+
return parseInt(sha1Hash.digest('hex').slice(0, 15), 16) / LONG_SCALE;
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
function matchProperty(property, propertyValues) {
|
|
1708
|
+
var key = property.key;
|
|
1709
|
+
var value = property.value;
|
|
1710
|
+
var operator = property.operator || 'exact';
|
|
1711
|
+
|
|
1712
|
+
if (!(key in propertyValues)) {
|
|
1713
|
+
throw new InconclusiveMatchError("Property ".concat(key, " not found in propertyValues"));
|
|
1714
|
+
} else if (operator === 'is_not_set') {
|
|
1715
|
+
throw new InconclusiveMatchError("Operator is_not_set is not supported");
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
var overrideValue = propertyValues[key];
|
|
1719
|
+
|
|
1720
|
+
switch (operator) {
|
|
1721
|
+
case 'exact':
|
|
1722
|
+
return Array.isArray(value) ? value.indexOf(overrideValue) !== -1 : value === overrideValue;
|
|
1723
|
+
|
|
1724
|
+
case 'is_not':
|
|
1725
|
+
return Array.isArray(value) ? value.indexOf(overrideValue) === -1 : value !== overrideValue;
|
|
1726
|
+
|
|
1727
|
+
case 'is_set':
|
|
1728
|
+
return key in propertyValues;
|
|
1729
|
+
|
|
1730
|
+
case 'icontains':
|
|
1731
|
+
return String(overrideValue).toLowerCase().includes(String(value).toLowerCase());
|
|
1732
|
+
|
|
1733
|
+
case 'not_icontains':
|
|
1734
|
+
return !String(overrideValue).toLowerCase().includes(String(value).toLowerCase());
|
|
1735
|
+
|
|
1736
|
+
case 'regex':
|
|
1737
|
+
return isValidRegex(String(value)) && String(overrideValue).match(String(value)) !== null;
|
|
1738
|
+
|
|
1739
|
+
case 'not_regex':
|
|
1740
|
+
return isValidRegex(String(value)) && String(overrideValue).match(String(value)) === null;
|
|
1741
|
+
|
|
1742
|
+
case 'gt':
|
|
1743
|
+
return typeof overrideValue == typeof value && overrideValue > value;
|
|
1744
|
+
|
|
1745
|
+
case 'gte':
|
|
1746
|
+
return typeof overrideValue == typeof value && overrideValue >= value;
|
|
1747
|
+
|
|
1748
|
+
case 'lt':
|
|
1749
|
+
return typeof overrideValue == typeof value && overrideValue < value;
|
|
1750
|
+
|
|
1751
|
+
case 'lte':
|
|
1752
|
+
return typeof overrideValue == typeof value && overrideValue <= value;
|
|
1753
|
+
|
|
1754
|
+
default:
|
|
1755
|
+
console.error("Unknown operator: ".concat(operator));
|
|
1756
|
+
return false;
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
function isValidRegex(regex) {
|
|
1761
|
+
try {
|
|
1762
|
+
new RegExp(regex);
|
|
1763
|
+
return true;
|
|
1764
|
+
} catch (err) {
|
|
1765
|
+
return false;
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
var THIRTY_SECONDS = 30 * 1000;
|
|
1770
|
+
var MAX_CACHE_SIZE = 50 * 1000;
|
|
1771
|
+
|
|
1153
1772
|
var PostHog =
|
|
1154
1773
|
/** @class */
|
|
1155
1774
|
function (_super) {
|
|
@@ -1165,6 +1784,8 @@ function (_super) {
|
|
|
1165
1784
|
options.captureMode = (options === null || options === void 0 ? void 0 : options.captureMode) || 'json';
|
|
1166
1785
|
options.preloadFeatureFlags = false; // Don't preload as this makes no sense without a distinctId
|
|
1167
1786
|
|
|
1787
|
+
options.sendFeatureFlagEvent = false; // Let `posthog-node` handle this on its own, since we're dealing with multiple distinctIDs
|
|
1788
|
+
|
|
1168
1789
|
_this = _super.call(this, apiKey, options) || this;
|
|
1169
1790
|
_this._memoryStorage = new PostHogMemoryStorage();
|
|
1170
1791
|
return _this;
|
|
@@ -1212,17 +1833,24 @@ function () {
|
|
|
1212
1833
|
}
|
|
1213
1834
|
|
|
1214
1835
|
this._sharedClient = new PostHog(apiKey, options);
|
|
1836
|
+
|
|
1837
|
+
if (options.personalApiKey) {
|
|
1838
|
+
this.featureFlagsPoller = new FeatureFlagsPoller({
|
|
1839
|
+
pollingInterval: typeof options.featureFlagsPollingInterval === 'number' ? options.featureFlagsPollingInterval : THIRTY_SECONDS,
|
|
1840
|
+
personalApiKey: options.personalApiKey,
|
|
1841
|
+
projectApiKey: apiKey,
|
|
1842
|
+
timeout: options.requestTimeout,
|
|
1843
|
+
host: this._sharedClient.host
|
|
1844
|
+
});
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
this.distinctIdHasSentFlagCalls = {};
|
|
1848
|
+
this.maxCacheSize = options.maxCacheSize || MAX_CACHE_SIZE;
|
|
1215
1849
|
}
|
|
1216
1850
|
|
|
1217
1851
|
PostHogGlobal.prototype.reInit = function (distinctId) {
|
|
1218
|
-
// Certain properties we want to persist
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
for (var key in PostHogPersistedProperty) {
|
|
1222
|
-
if (!propertiesToKeep.includes(key)) {
|
|
1223
|
-
this._sharedClient.setPersistedProperty(PostHogPersistedProperty[key], null);
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1852
|
+
// Certain properties we want to persist. Queue is persisted always by default.
|
|
1853
|
+
this._sharedClient.reset([PostHogPersistedProperty.OptedOut]);
|
|
1226
1854
|
|
|
1227
1855
|
this._sharedClient.setPersistedProperty(PostHogPersistedProperty.DistinctId, distinctId);
|
|
1228
1856
|
};
|
|
@@ -1239,14 +1867,15 @@ function () {
|
|
|
1239
1867
|
var distinctId = _a.distinctId,
|
|
1240
1868
|
event = _a.event,
|
|
1241
1869
|
properties = _a.properties,
|
|
1242
|
-
groups = _a.groups
|
|
1870
|
+
groups = _a.groups,
|
|
1871
|
+
sendFeatureFlags = _a.sendFeatureFlags;
|
|
1243
1872
|
this.reInit(distinctId);
|
|
1244
1873
|
|
|
1245
1874
|
if (groups) {
|
|
1246
1875
|
this._sharedClient.groups(groups);
|
|
1247
1876
|
}
|
|
1248
1877
|
|
|
1249
|
-
this._sharedClient.capture(event, properties);
|
|
1878
|
+
this._sharedClient.capture(event, properties, sendFeatureFlags || false);
|
|
1250
1879
|
};
|
|
1251
1880
|
|
|
1252
1881
|
PostHogGlobal.prototype.identify = function (_a) {
|
|
@@ -1263,33 +1892,95 @@ function () {
|
|
|
1263
1892
|
this._sharedClient.alias(data.alias);
|
|
1264
1893
|
};
|
|
1265
1894
|
|
|
1266
|
-
PostHogGlobal.prototype.getFeatureFlag = function (key, distinctId,
|
|
1895
|
+
PostHogGlobal.prototype.getFeatureFlag = function (key, distinctId, options) {
|
|
1896
|
+
var _a;
|
|
1897
|
+
|
|
1267
1898
|
return __awaiter(this, void 0, void 0, function () {
|
|
1268
|
-
|
|
1269
|
-
|
|
1899
|
+
var _b, groups, personProperties, groupProperties, _c, onlyEvaluateLocally, sendFeatureFlagEvents, response, flagWasLocallyEvaluated, featureFlagReportedKey;
|
|
1900
|
+
|
|
1901
|
+
return __generator(this, function (_d) {
|
|
1902
|
+
switch (_d.label) {
|
|
1270
1903
|
case 0:
|
|
1904
|
+
_b = options || {}, groups = _b.groups, personProperties = _b.personProperties, groupProperties = _b.groupProperties;
|
|
1905
|
+
_c = options || {}, onlyEvaluateLocally = _c.onlyEvaluateLocally, sendFeatureFlagEvents = _c.sendFeatureFlagEvents; // set defaults
|
|
1906
|
+
|
|
1907
|
+
if (onlyEvaluateLocally == undefined) {
|
|
1908
|
+
onlyEvaluateLocally = false;
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
if (sendFeatureFlagEvents == undefined) {
|
|
1912
|
+
sendFeatureFlagEvents = true;
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
return [4
|
|
1916
|
+
/*yield*/
|
|
1917
|
+
, (_a = this.featureFlagsPoller) === null || _a === void 0 ? void 0 : _a.getFeatureFlag(key, distinctId, groups, personProperties, groupProperties)];
|
|
1918
|
+
|
|
1919
|
+
case 1:
|
|
1920
|
+
response = _d.sent();
|
|
1921
|
+
flagWasLocallyEvaluated = response !== undefined;
|
|
1922
|
+
if (!(!flagWasLocallyEvaluated && !onlyEvaluateLocally)) return [3
|
|
1923
|
+
/*break*/
|
|
1924
|
+
, 3];
|
|
1271
1925
|
this.reInit(distinctId);
|
|
1272
1926
|
|
|
1273
|
-
if (groups) {
|
|
1927
|
+
if (groups != undefined) {
|
|
1274
1928
|
this._sharedClient.groups(groups);
|
|
1275
1929
|
}
|
|
1276
1930
|
|
|
1931
|
+
if (personProperties) {
|
|
1932
|
+
this._sharedClient.personProperties(personProperties);
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
if (groupProperties) {
|
|
1936
|
+
this._sharedClient.groupProperties(groupProperties);
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1277
1939
|
return [4
|
|
1278
1940
|
/*yield*/
|
|
1279
|
-
, this._sharedClient.reloadFeatureFlagsAsync()];
|
|
1941
|
+
, this._sharedClient.reloadFeatureFlagsAsync(false)];
|
|
1280
1942
|
|
|
1281
|
-
case
|
|
1282
|
-
|
|
1943
|
+
case 2:
|
|
1944
|
+
_d.sent();
|
|
1945
|
+
|
|
1946
|
+
response = this._sharedClient.getFeatureFlag(key);
|
|
1947
|
+
_d.label = 3;
|
|
1948
|
+
|
|
1949
|
+
case 3:
|
|
1950
|
+
featureFlagReportedKey = "".concat(key, "_").concat(response);
|
|
1951
|
+
|
|
1952
|
+
if (sendFeatureFlagEvents && (!(distinctId in this.distinctIdHasSentFlagCalls) || !this.distinctIdHasSentFlagCalls[distinctId].includes(featureFlagReportedKey))) {
|
|
1953
|
+
if (Object.keys(this.distinctIdHasSentFlagCalls).length >= this.maxCacheSize) {
|
|
1954
|
+
this.distinctIdHasSentFlagCalls = {};
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
if (Array.isArray(this.distinctIdHasSentFlagCalls[distinctId])) {
|
|
1958
|
+
this.distinctIdHasSentFlagCalls[distinctId].push(featureFlagReportedKey);
|
|
1959
|
+
} else {
|
|
1960
|
+
this.distinctIdHasSentFlagCalls[distinctId] = [featureFlagReportedKey];
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
this.capture({
|
|
1964
|
+
distinctId: distinctId,
|
|
1965
|
+
event: '$feature_flag_called',
|
|
1966
|
+
properties: {
|
|
1967
|
+
$feature_flag: key,
|
|
1968
|
+
$feature_flag_response: response,
|
|
1969
|
+
locally_evaluated: flagWasLocallyEvaluated
|
|
1970
|
+
},
|
|
1971
|
+
groups: groups
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1283
1974
|
|
|
1284
1975
|
return [2
|
|
1285
1976
|
/*return*/
|
|
1286
|
-
,
|
|
1977
|
+
, response];
|
|
1287
1978
|
}
|
|
1288
1979
|
});
|
|
1289
1980
|
});
|
|
1290
1981
|
};
|
|
1291
1982
|
|
|
1292
|
-
PostHogGlobal.prototype.isFeatureEnabled = function (key, distinctId,
|
|
1983
|
+
PostHogGlobal.prototype.isFeatureEnabled = function (key, distinctId, options) {
|
|
1293
1984
|
return __awaiter(this, void 0, void 0, function () {
|
|
1294
1985
|
var feat;
|
|
1295
1986
|
return __generator(this, function (_a) {
|
|
@@ -1297,13 +1988,88 @@ function () {
|
|
|
1297
1988
|
case 0:
|
|
1298
1989
|
return [4
|
|
1299
1990
|
/*yield*/
|
|
1300
|
-
, this.getFeatureFlag(key, distinctId,
|
|
1991
|
+
, this.getFeatureFlag(key, distinctId, options)];
|
|
1301
1992
|
|
|
1302
1993
|
case 1:
|
|
1303
1994
|
feat = _a.sent();
|
|
1995
|
+
|
|
1996
|
+
if (feat === undefined) {
|
|
1997
|
+
return [2
|
|
1998
|
+
/*return*/
|
|
1999
|
+
, undefined];
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
return [2
|
|
2003
|
+
/*return*/
|
|
2004
|
+
, !!feat || false];
|
|
2005
|
+
}
|
|
2006
|
+
});
|
|
2007
|
+
});
|
|
2008
|
+
};
|
|
2009
|
+
|
|
2010
|
+
PostHogGlobal.prototype.getAllFlags = function (distinctId, options) {
|
|
2011
|
+
var _a;
|
|
2012
|
+
|
|
2013
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2014
|
+
var _b, groups, personProperties, groupProperties, onlyEvaluateLocally, localEvaluationResult, response, fallbackToDecide, remoteEvaluationResult;
|
|
2015
|
+
|
|
2016
|
+
return __generator(this, function (_c) {
|
|
2017
|
+
switch (_c.label) {
|
|
2018
|
+
case 0:
|
|
2019
|
+
_b = options || {}, groups = _b.groups, personProperties = _b.personProperties, groupProperties = _b.groupProperties;
|
|
2020
|
+
onlyEvaluateLocally = (options || {}).onlyEvaluateLocally; // set defaults
|
|
2021
|
+
|
|
2022
|
+
if (onlyEvaluateLocally == undefined) {
|
|
2023
|
+
onlyEvaluateLocally = false;
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
return [4
|
|
2027
|
+
/*yield*/
|
|
2028
|
+
, (_a = this.featureFlagsPoller) === null || _a === void 0 ? void 0 : _a.getAllFlags(distinctId, groups, personProperties, groupProperties)];
|
|
2029
|
+
|
|
2030
|
+
case 1:
|
|
2031
|
+
localEvaluationResult = _c.sent();
|
|
2032
|
+
response = {};
|
|
2033
|
+
fallbackToDecide = true;
|
|
2034
|
+
|
|
2035
|
+
if (localEvaluationResult) {
|
|
2036
|
+
response = localEvaluationResult.response;
|
|
2037
|
+
fallbackToDecide = localEvaluationResult.fallbackToDecide;
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
if (!(fallbackToDecide && !onlyEvaluateLocally)) return [3
|
|
2041
|
+
/*break*/
|
|
2042
|
+
, 3];
|
|
2043
|
+
this.reInit(distinctId);
|
|
2044
|
+
|
|
2045
|
+
if (groups) {
|
|
2046
|
+
this._sharedClient.groups(groups);
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
if (personProperties) {
|
|
2050
|
+
this._sharedClient.personProperties(personProperties);
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
if (groupProperties) {
|
|
2054
|
+
this._sharedClient.groupProperties(groupProperties);
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
return [4
|
|
2058
|
+
/*yield*/
|
|
2059
|
+
, this._sharedClient.reloadFeatureFlagsAsync(false)];
|
|
2060
|
+
|
|
2061
|
+
case 2:
|
|
2062
|
+
_c.sent();
|
|
2063
|
+
|
|
2064
|
+
remoteEvaluationResult = this._sharedClient.getFeatureFlags();
|
|
1304
2065
|
return [2
|
|
1305
2066
|
/*return*/
|
|
1306
|
-
,
|
|
2067
|
+
, __assign(__assign({}, response), remoteEvaluationResult)];
|
|
2068
|
+
|
|
2069
|
+
case 3:
|
|
2070
|
+
return [2
|
|
2071
|
+
/*return*/
|
|
2072
|
+
, response];
|
|
1307
2073
|
}
|
|
1308
2074
|
});
|
|
1309
2075
|
});
|
|
@@ -1318,15 +2084,46 @@ function () {
|
|
|
1318
2084
|
};
|
|
1319
2085
|
|
|
1320
2086
|
PostHogGlobal.prototype.reloadFeatureFlags = function () {
|
|
1321
|
-
|
|
2087
|
+
var _a;
|
|
2088
|
+
|
|
2089
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2090
|
+
return __generator(this, function (_b) {
|
|
2091
|
+
switch (_b.label) {
|
|
2092
|
+
case 0:
|
|
2093
|
+
return [4
|
|
2094
|
+
/*yield*/
|
|
2095
|
+
, (_a = this.featureFlagsPoller) === null || _a === void 0 ? void 0 : _a.loadFeatureFlags(true)];
|
|
2096
|
+
|
|
2097
|
+
case 1:
|
|
2098
|
+
_b.sent();
|
|
2099
|
+
|
|
2100
|
+
return [2
|
|
2101
|
+
/*return*/
|
|
2102
|
+
];
|
|
2103
|
+
}
|
|
2104
|
+
});
|
|
2105
|
+
});
|
|
2106
|
+
};
|
|
2107
|
+
|
|
2108
|
+
PostHogGlobal.prototype.flush = function () {
|
|
2109
|
+
this._sharedClient.flush();
|
|
1322
2110
|
};
|
|
1323
2111
|
|
|
1324
2112
|
PostHogGlobal.prototype.shutdown = function () {
|
|
1325
|
-
void this.
|
|
2113
|
+
void this.shutdownAsync();
|
|
1326
2114
|
};
|
|
1327
2115
|
|
|
1328
2116
|
PostHogGlobal.prototype.shutdownAsync = function () {
|
|
1329
|
-
|
|
2117
|
+
var _a;
|
|
2118
|
+
|
|
2119
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2120
|
+
return __generator(this, function (_b) {
|
|
2121
|
+
(_a = this.featureFlagsPoller) === null || _a === void 0 ? void 0 : _a.stopPoller();
|
|
2122
|
+
return [2
|
|
2123
|
+
/*return*/
|
|
2124
|
+
, this._sharedClient.shutdownAsync()];
|
|
2125
|
+
});
|
|
2126
|
+
});
|
|
1330
2127
|
};
|
|
1331
2128
|
|
|
1332
2129
|
PostHogGlobal.prototype.debug = function (enabled) {
|