@statsig/client-core 0.0.1-beta.4 → 0.0.1-beta.40

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.
Files changed (73) hide show
  1. package/README.md +1 -4
  2. package/package.json +1 -1
  3. package/src/$_StatsigGlobal.d.ts +8 -1
  4. package/src/$_StatsigGlobal.js +22 -12
  5. package/src/ClientInterfaces.d.ts +50 -14
  6. package/src/DataAdapterCore.d.ts +30 -0
  7. package/src/DataAdapterCore.js +169 -0
  8. package/src/Diagnostics.d.ts +1 -3
  9. package/src/Diagnostics.js +4 -49
  10. package/src/DownloadConfigSpecsResponse.d.ts +41 -0
  11. package/src/ErrorBoundary.d.ts +7 -2
  12. package/src/ErrorBoundary.js +79 -87
  13. package/src/EvaluationOptions.d.ts +20 -0
  14. package/src/EvaluationOptions.js +2 -0
  15. package/src/EvaluationTypes.d.ts +39 -0
  16. package/src/EvaluationTypes.js +2 -0
  17. package/src/EventLogger.d.ts +20 -9
  18. package/src/EventLogger.js +216 -232
  19. package/src/Hashing.d.ts +2 -1
  20. package/src/Hashing.js +25 -6
  21. package/src/InitializeResponse.d.ts +18 -0
  22. package/src/InitializeResponse.js +2 -0
  23. package/src/Log.js +15 -34
  24. package/src/NetworkConfig.d.ts +18 -0
  25. package/src/NetworkConfig.js +18 -0
  26. package/src/NetworkCore.d.ts +19 -6
  27. package/src/NetworkCore.js +137 -167
  28. package/src/OverrideAdapter.d.ts +9 -0
  29. package/src/OverrideAdapter.js +2 -0
  30. package/src/SDKType.d.ts +8 -0
  31. package/src/SDKType.js +19 -0
  32. package/src/SafeJs.d.ts +6 -0
  33. package/src/SafeJs.js +41 -0
  34. package/src/SessionID.d.ts +17 -1
  35. package/src/SessionID.js +89 -8
  36. package/src/StableID.js +24 -53
  37. package/src/StatsigClientBase.d.ts +57 -28
  38. package/src/StatsigClientBase.js +115 -238
  39. package/src/StatsigClientEventEmitter.d.ts +69 -28
  40. package/src/StatsigDataAdapter.d.ts +107 -0
  41. package/src/StatsigDataAdapter.js +4 -0
  42. package/src/StatsigEvent.d.ts +10 -19
  43. package/src/StatsigEvent.js +50 -41
  44. package/src/StatsigMetadata.d.ts +1 -1
  45. package/src/StatsigMetadata.js +7 -18
  46. package/src/StatsigOptionsCommon.d.ts +85 -17
  47. package/src/StatsigTypeFactories.d.ts +6 -0
  48. package/src/StatsigTypeFactories.js +50 -0
  49. package/src/StatsigTypes.d.ts +29 -18
  50. package/src/StatsigTypes.js +0 -29
  51. package/src/StatsigUser.d.ts +2 -5
  52. package/src/StatsigUser.js +10 -18
  53. package/src/StorageProvider.d.ts +13 -8
  54. package/src/StorageProvider.js +77 -73
  55. package/src/TypedJsonParse.d.ts +8 -0
  56. package/src/TypedJsonParse.js +27 -0
  57. package/src/UUID.js +9 -5
  58. package/src/UrlOverrides.d.ts +1 -0
  59. package/src/UrlOverrides.js +15 -0
  60. package/src/UtitlityTypes.d.ts +3 -0
  61. package/src/UtitlityTypes.js +2 -0
  62. package/src/VisibilityObserving.d.ts +8 -0
  63. package/src/VisibilityObserving.js +30 -0
  64. package/src/index.d.ts +20 -5
  65. package/src/index.js +30 -18
  66. package/src/Monitoring.d.ts +0 -3
  67. package/src/Monitoring.js +0 -33
  68. package/src/StatsigDataProvider.d.ts +0 -9
  69. package/src/VisibilityChangeObserver.d.ts +0 -13
  70. package/src/VisibilityChangeObserver.js +0 -48
  71. package/src/__tests__/MockLocalStorage.d.ts +0 -9
  72. package/src/__tests__/MockLocalStorage.js +0 -37
  73. /package/src/{StatsigDataProvider.js → DownloadConfigSpecsResponse.js} +0 -0
@@ -1,15 +1,4 @@
1
1
  "use strict";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
2
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
3
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
4
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -19,267 +8,262 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
19
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
20
9
  });
21
10
  };
22
- var __generator = (this && this.__generator) || function (thisArg, body) {
23
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
- function verb(n) { return function (v) { return step([n, v]); }; }
26
- function step(op) {
27
- if (f) throw new TypeError("Generator is already executing.");
28
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
- if (y = 0, t) op = [op[0] & 2, t.value];
31
- switch (op[0]) {
32
- case 0: case 1: t = op; break;
33
- case 4: _.label++; return { value: op[1], done: false };
34
- case 5: _.label++; y = op[1]; op = [0]; continue;
35
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
- default:
37
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
- if (t[2]) _.ops.pop();
42
- _.trys.pop(); continue;
43
- }
44
- op = body.call(thisArg, _);
45
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
- }
48
- };
49
11
  Object.defineProperty(exports, "__esModule", { value: true });
50
12
  exports.EventLogger = void 0;
51
- var Hashing_1 = require("./Hashing");
52
- var Log_1 = require("./Log");
53
- var StatsigEvent_1 = require("./StatsigEvent");
54
- var StatsigMetadata_1 = require("./StatsigMetadata");
55
- var StorageProvider_1 = require("./StorageProvider");
56
- var VisibilityChangeObserver_1 = require("./VisibilityChangeObserver");
57
- var DEFAULT_QUEUE_SIZE = 50;
58
- var DEFAULT_FLUSH_INTERVAL_MS = 10000;
59
- var MAX_DEDUPER_KEYS = 1000;
60
- var DEDUPER_WINDOW_DURATION_MS = 60000;
61
- var MAX_FAILED_LOGS = 500;
62
- var DEFAULT_API = 'https://api.statsig.com/v1';
63
- var EventLogger = /** @class */ (function () {
64
- function EventLogger(_sdkKey, _emitter, _network, _options) {
65
- var _this = this;
13
+ const Hashing_1 = require("./Hashing");
14
+ const Log_1 = require("./Log");
15
+ const NetworkConfig_1 = require("./NetworkConfig");
16
+ const SafeJs_1 = require("./SafeJs");
17
+ const StatsigEvent_1 = require("./StatsigEvent");
18
+ const StorageProvider_1 = require("./StorageProvider");
19
+ const TypedJsonParse_1 = require("./TypedJsonParse");
20
+ const UrlOverrides_1 = require("./UrlOverrides");
21
+ const VisibilityObserving_1 = require("./VisibilityObserving");
22
+ const DEFAULT_QUEUE_SIZE = 50;
23
+ const DEFAULT_FLUSH_INTERVAL_MS = 10000;
24
+ const MAX_DEDUPER_KEYS = 1000;
25
+ const DEDUPER_WINDOW_DURATION_MS = 60000;
26
+ const MAX_FAILED_LOGS = 500;
27
+ const QUICK_FLUSH_WINDOW_MS = 200;
28
+ const EVENT_LOGGER_MAP = {};
29
+ const _safeFlushAndForget = (sdkKey) => {
30
+ var _a;
31
+ (_a = EVENT_LOGGER_MAP[sdkKey]) === null || _a === void 0 ? void 0 : _a.flush().catch(() => {
32
+ // noop
33
+ });
34
+ };
35
+ class EventLogger {
36
+ constructor(_sdkKey, _emitter, _network, _options) {
66
37
  var _a, _b;
67
38
  this._sdkKey = _sdkKey;
68
39
  this._emitter = _emitter;
69
40
  this._network = _network;
70
41
  this._options = _options;
71
42
  this._queue = [];
72
- this._lastExposureMap = {};
43
+ this._lastExposureTimeMap = {};
44
+ this._nonExposedChecks = {};
45
+ this._hasRunQuickFlush = false;
46
+ this._creationTime = Date.now();
47
+ EVENT_LOGGER_MAP[_sdkKey] = this;
48
+ this._isLoggingDisabled = (_options === null || _options === void 0 ? void 0 : _options.disableLogging) === true;
73
49
  this._maxQueueSize = (_a = _options === null || _options === void 0 ? void 0 : _options.loggingBufferMaxSize) !== null && _a !== void 0 ? _a : DEFAULT_QUEUE_SIZE;
74
- var flushInterval = (_b = _options === null || _options === void 0 ? void 0 : _options.loggingIntervalMs) !== null && _b !== void 0 ? _b : DEFAULT_FLUSH_INTERVAL_MS;
75
- this._flushTimer = setInterval(function () { return _this._flushAndForget(); }, flushInterval);
76
- VisibilityChangeObserver_1.VisibilityChangeObserver.add(this);
77
- this._failedLogs = [];
50
+ const flushInterval = (_b = _options === null || _options === void 0 ? void 0 : _options.loggingIntervalMs) !== null && _b !== void 0 ? _b : DEFAULT_FLUSH_INTERVAL_MS;
51
+ const intervalId = setInterval(() => {
52
+ const logger = EVENT_LOGGER_MAP[_sdkKey];
53
+ if (!logger) {
54
+ clearInterval(intervalId);
55
+ return;
56
+ }
57
+ _safeFlushAndForget(_sdkKey);
58
+ }, flushInterval);
59
+ this._flushTimer = intervalId;
60
+ const config = _options === null || _options === void 0 ? void 0 : _options.networkConfig;
61
+ this._logEventUrl = (0, UrlOverrides_1._getOverridableUrl)(config === null || config === void 0 ? void 0 : config.logEventUrl, config === null || config === void 0 ? void 0 : config.api, '/rgstr', NetworkConfig_1.NetworkDefault.eventsApi);
62
+ this._logEventBeaconUrl = (0, UrlOverrides_1._getOverridableUrl)(config === null || config === void 0 ? void 0 : config.logEventBeaconUrl, config === null || config === void 0 ? void 0 : config.api, '/log_event_beacon', NetworkConfig_1.NetworkDefault.eventsApi);
63
+ (0, VisibilityObserving_1._subscribeToVisiblityChanged)((visibility) => {
64
+ if (visibility === 'background') {
65
+ _safeFlushAndForget(_sdkKey);
66
+ }
67
+ });
78
68
  this._retryFailedLogs();
79
69
  }
80
- EventLogger.prototype.enqueue = function (event) {
70
+ setLoggingDisabled(isDisabled) {
71
+ this._isLoggingDisabled = isDisabled;
72
+ }
73
+ enqueue(event) {
81
74
  if (!this._shouldLogEvent(event)) {
82
75
  return;
83
76
  }
84
- if (event.user) {
85
- event.user = __assign({}, event.user);
86
- delete event.user.privateAttributes;
87
- }
88
- var _a = StatsigMetadata_1.StatsigMetadataProvider.get(), sdkType = _a.sdkType, sdkVersion = _a.sdkVersion;
89
- this._queue.push(__assign(__assign({}, event), { statsigMetadata: { sdkType: sdkType, sdkVersion: sdkVersion } }));
77
+ this._normalizeAndAppendEvent(event);
78
+ this._quickFlushIfNeeded();
90
79
  if (this._queue.length > this._maxQueueSize) {
91
- this._flushAndForget();
80
+ _safeFlushAndForget(this._sdkKey);
92
81
  }
93
- };
94
- EventLogger.prototype.reset = function () {
95
- this._lastExposureMap = {};
96
- };
97
- EventLogger.prototype.onVisibilityChanged = function (visibility) {
98
- if (visibility === 'background') {
99
- this._flushAndForget();
100
- }
101
- };
102
- EventLogger.prototype.shutdown = function () {
103
- return __awaiter(this, void 0, void 0, function () {
104
- return __generator(this, function (_a) {
105
- switch (_a.label) {
106
- case 0:
107
- if (this._flushTimer) {
108
- clearInterval(this._flushTimer);
109
- this._flushTimer = null;
110
- }
111
- return [4 /*yield*/, this._flush()];
112
- case 1:
113
- _a.sent();
114
- return [2 /*return*/];
115
- }
116
- });
82
+ }
83
+ incrementNonExposureCount(name) {
84
+ var _a;
85
+ const current = (_a = this._nonExposedChecks[name]) !== null && _a !== void 0 ? _a : 0;
86
+ this._nonExposedChecks[name] = current + 1;
87
+ }
88
+ reset() {
89
+ this._lastExposureTimeMap = {};
90
+ }
91
+ shutdown() {
92
+ return __awaiter(this, void 0, void 0, function* () {
93
+ if (this._flushTimer) {
94
+ clearInterval(this._flushTimer);
95
+ this._flushTimer = null;
96
+ }
97
+ yield this.flush();
117
98
  });
118
- };
119
- EventLogger.prototype._shouldLogEvent = function (event) {
99
+ }
100
+ flush() {
101
+ return __awaiter(this, void 0, void 0, function* () {
102
+ this._appendAndResetNonExposedChecks();
103
+ if (this._queue.length === 0) {
104
+ return;
105
+ }
106
+ const events = this._queue;
107
+ this._queue = [];
108
+ yield this._sendEvents(events);
109
+ });
110
+ }
111
+ /**
112
+ * We 'Quick Flush' following the very first event enqueued
113
+ * within the quick flush window
114
+ */
115
+ _quickFlushIfNeeded() {
116
+ if (this._hasRunQuickFlush) {
117
+ return;
118
+ }
119
+ this._hasRunQuickFlush = true;
120
+ if (Date.now() - this._creationTime > QUICK_FLUSH_WINDOW_MS) {
121
+ return;
122
+ }
123
+ setTimeout(() => _safeFlushAndForget(this._sdkKey), QUICK_FLUSH_WINDOW_MS);
124
+ }
125
+ _shouldLogEvent(event) {
120
126
  var _a, _b, _c, _d;
121
- if (!(0, StatsigEvent_1.isExposureEvent)(event)) {
127
+ if (!(0, StatsigEvent_1._isExposureEvent)(event)) {
122
128
  return true;
123
129
  }
124
- var key = [
130
+ const key = [
125
131
  event.eventName,
126
132
  (_a = event.user) === null || _a === void 0 ? void 0 : _a.userID,
127
133
  (_b = event.metadata) === null || _b === void 0 ? void 0 : _b['gate'],
128
134
  (_c = event.metadata) === null || _c === void 0 ? void 0 : _c['config'],
129
135
  (_d = event.metadata) === null || _d === void 0 ? void 0 : _d['ruleID'],
130
136
  ].join('|');
131
- var previous = this._lastExposureMap[key];
132
- var now = Date.now();
137
+ const previous = this._lastExposureTimeMap[key];
138
+ const now = Date.now();
133
139
  if (previous && now - previous < DEDUPER_WINDOW_DURATION_MS) {
134
140
  return false;
135
141
  }
136
- if (Object.keys(this._lastExposureMap).length > MAX_DEDUPER_KEYS) {
137
- this._lastExposureMap = {};
142
+ if (Object.keys(this._lastExposureTimeMap).length > MAX_DEDUPER_KEYS) {
143
+ this._lastExposureTimeMap = {};
138
144
  }
139
- this._lastExposureMap[key] = now;
145
+ this._lastExposureTimeMap[key] = now;
140
146
  return true;
141
- };
142
- EventLogger.prototype._flushAndForget = function () {
143
- this._flush().catch(function () {
144
- // noop
145
- });
146
- };
147
- EventLogger.prototype._flush = function () {
148
- return __awaiter(this, void 0, void 0, function () {
149
- var events;
150
- return __generator(this, function (_a) {
151
- switch (_a.label) {
152
- case 0:
153
- if (this._queue.length === 0) {
154
- return [2 /*return*/];
155
- }
156
- events = this._queue;
157
- this._queue = [];
158
- return [4 /*yield*/, this._sendEvents(events)];
159
- case 1:
160
- _a.sent();
161
- return [2 /*return*/];
162
- }
163
- });
164
- });
165
- };
166
- EventLogger.prototype._sendEvents = function (events) {
147
+ }
148
+ _sendEvents(events) {
167
149
  var _a, _b;
168
- return __awaiter(this, void 0, void 0, function () {
169
- var isInForeground, api, response, _c, _d;
170
- return __generator(this, function (_e) {
171
- switch (_e.label) {
172
- case 0:
173
- _e.trys.push([0, 4, , 5]);
174
- isInForeground = VisibilityChangeObserver_1.VisibilityChangeObserver.isCurrentlyVisible();
175
- api = (_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.api) !== null && _b !== void 0 ? _b : DEFAULT_API;
176
- if (!(!isInForeground && this._isBeaconSupported())) return [3 /*break*/, 1];
177
- _c = this._sendEventsViaBeacon(api, events);
178
- return [3 /*break*/, 3];
179
- case 1: return [4 /*yield*/, this._sendEventsViaPost(api, events)];
180
- case 2:
181
- _c = _e.sent();
182
- _e.label = 3;
183
- case 3:
184
- response = _c;
185
- if (response.success) {
186
- this._emitter({
187
- event: 'logs_flushed',
188
- events: events,
189
- });
190
- }
191
- else {
192
- this._saveFailedLogsToStorage(events);
193
- }
194
- return [3 /*break*/, 5];
195
- case 4:
196
- _d = _e.sent();
197
- Log_1.Log.warn('Failed to flush events.');
198
- return [3 /*break*/, 5];
199
- case 5: return [2 /*return*/];
150
+ return __awaiter(this, void 0, void 0, function* () {
151
+ if (this._isLoggingDisabled) {
152
+ this._saveFailedLogsToStorage(events);
153
+ return;
154
+ }
155
+ try {
156
+ const isInBackground = !(0, VisibilityObserving_1._isCurrentlyVisible)();
157
+ const shouldUseBeacon = isInBackground &&
158
+ this._network.isBeaconSupported() &&
159
+ ((_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.networkConfig) === null || _b === void 0 ? void 0 : _b.networkOverrideFunc) == null;
160
+ const response = shouldUseBeacon
161
+ ? yield this._sendEventsViaBeacon(events)
162
+ : yield this._sendEventsViaPost(events);
163
+ if (response.success) {
164
+ this._emitter({
165
+ name: 'logs_flushed',
166
+ events,
167
+ });
200
168
  }
201
- });
202
- });
203
- };
204
- EventLogger.prototype._sendEventsViaPost = function (api, events) {
205
- return __awaiter(this, void 0, void 0, function () {
206
- var result;
207
- return __generator(this, function (_a) {
208
- switch (_a.label) {
209
- case 0: return [4 /*yield*/, this._network.post({
210
- sdkKey: this._sdkKey,
211
- data: {
212
- events: events,
213
- },
214
- url: "".concat(api, "/rgstr"),
215
- retries: 3,
216
- headers: {
217
- 'Content-Type': 'application/json',
218
- 'STATSIG-EVENT-COUNT': String(events.length),
219
- },
220
- })];
221
- case 1:
222
- result = _a.sent();
223
- if (result) {
224
- return [2 /*return*/, JSON.parse(result)];
225
- }
226
- return [2 /*return*/, { success: false }];
169
+ else {
170
+ this._saveFailedLogsToStorage(events);
227
171
  }
228
- });
172
+ }
173
+ catch (_c) {
174
+ Log_1.Log.warn('Failed to flush events.');
175
+ }
229
176
  });
230
- };
231
- EventLogger.prototype._sendEventsViaBeacon = function (api, events) {
232
- return {
233
- success: this._network.beacon({
177
+ }
178
+ _sendEventsViaPost(events) {
179
+ return __awaiter(this, void 0, void 0, function* () {
180
+ const result = yield this._network.post({
234
181
  sdkKey: this._sdkKey,
235
182
  data: {
236
- events: events,
183
+ events,
237
184
  },
238
- url: "".concat(api, "/log_event_beacon"),
239
- }),
240
- };
241
- };
242
- EventLogger.prototype._isBeaconSupported = function () {
243
- return (typeof navigator !== 'undefined' &&
244
- typeof (navigator === null || navigator === void 0 ? void 0 : navigator.sendBeacon) === 'function');
245
- };
246
- EventLogger.prototype._saveFailedLogsToStorage = function (events) {
247
- var _a;
248
- (_a = this._failedLogs).push.apply(_a, events);
249
- while (this._failedLogs.length > MAX_FAILED_LOGS) {
250
- this._failedLogs.shift();
185
+ url: this._logEventUrl,
186
+ retries: 3,
187
+ params: {
188
+ [NetworkConfig_1.NetworkParam.EventCount]: String(events.length),
189
+ },
190
+ });
191
+ const response = (result === null || result === void 0 ? void 0 : result.body)
192
+ ? (0, TypedJsonParse_1.typedJsonParse)(result.body, 'success', 'Failed to parse SendEventsResponse')
193
+ : null;
194
+ return { success: (response === null || response === void 0 ? void 0 : response.success) === true };
195
+ });
196
+ }
197
+ _sendEventsViaBeacon(events) {
198
+ return __awaiter(this, void 0, void 0, function* () {
199
+ return {
200
+ success: yield this._network.beacon({
201
+ sdkKey: this._sdkKey,
202
+ data: {
203
+ events,
204
+ },
205
+ url: this._logEventBeaconUrl,
206
+ }),
207
+ };
208
+ });
209
+ }
210
+ _saveFailedLogsToStorage(events) {
211
+ while (events.length > MAX_FAILED_LOGS) {
212
+ events.shift();
251
213
  }
252
- var storageKey = this._getStorageKey();
253
- (0, StorageProvider_1.setObjectInStorage)(storageKey, this._failedLogs).catch(function () {
214
+ const storageKey = this._getStorageKey();
215
+ (0, StorageProvider_1._setObjectInStorage)(storageKey, events).catch(() => {
254
216
  Log_1.Log.warn('Unable to save failed logs to storage');
255
217
  });
256
- };
257
- EventLogger.prototype._retryFailedLogs = function () {
258
- var _this = this;
259
- var storageKey = this._getStorageKey();
260
- (function () { return __awaiter(_this, void 0, void 0, function () {
261
- var events;
262
- return __generator(this, function (_a) {
263
- switch (_a.label) {
264
- case 0: return [4 /*yield*/, (0, StorageProvider_1.getObjectFromStorage)(storageKey)];
265
- case 1:
266
- events = _a.sent();
267
- if (!events) {
268
- return [2 /*return*/];
269
- }
270
- return [4 /*yield*/, this._sendEvents(events)];
271
- case 2:
272
- _a.sent();
273
- return [2 /*return*/];
274
- }
275
- });
276
- }); })().catch(function () {
277
- Log_1.Log.warn('Unable to flush stored logs');
218
+ }
219
+ _retryFailedLogs() {
220
+ const storageKey = this._getStorageKey();
221
+ (() => __awaiter(this, void 0, void 0, function* () {
222
+ const events = yield (0, StorageProvider_1._getObjectFromStorage)(storageKey);
223
+ if (!events) {
224
+ return;
225
+ }
226
+ yield StorageProvider_1.Storage._removeItem(storageKey);
227
+ yield this._sendEvents(events);
228
+ }))().catch(() => {
229
+ Log_1.Log.warn('Failed to flush stored logs');
278
230
  });
279
- };
280
- EventLogger.prototype._getStorageKey = function () {
281
- return "STATSIG_FAILED_LOG:".concat((0, Hashing_1.DJB2)(this._sdkKey));
282
- };
283
- return EventLogger;
284
- }());
231
+ }
232
+ _getStorageKey() {
233
+ return `statsig.failed_logs.${(0, Hashing_1.DJB2)(this._sdkKey)}`;
234
+ }
235
+ _normalizeAndAppendEvent(event) {
236
+ if (event.user) {
237
+ event.user = Object.assign({}, event.user);
238
+ delete event.user.privateAttributes;
239
+ }
240
+ const extras = {};
241
+ const currentPage = this._getCurrentPageUrl();
242
+ if (currentPage) {
243
+ extras.statsigMetadata = { currentPage };
244
+ }
245
+ this._queue.push(Object.assign(Object.assign({}, event), extras));
246
+ }
247
+ _appendAndResetNonExposedChecks() {
248
+ if (Object.keys(this._nonExposedChecks).length === 0) {
249
+ return;
250
+ }
251
+ this._normalizeAndAppendEvent({
252
+ eventName: 'statsig::non_exposed_checks',
253
+ user: null,
254
+ time: Date.now(),
255
+ metadata: {
256
+ checks: Object.assign({}, this._nonExposedChecks),
257
+ },
258
+ });
259
+ this._nonExposedChecks = {};
260
+ }
261
+ _getCurrentPageUrl() {
262
+ var _a;
263
+ if (((_a = this._options) === null || _a === void 0 ? void 0 : _a.includeCurrentPageUrlWithEvents) === false) {
264
+ return;
265
+ }
266
+ return (0, SafeJs_1._getCurrentPageUrlSafe)();
267
+ }
268
+ }
285
269
  exports.EventLogger = EventLogger;
package/src/Hashing.d.ts CHANGED
@@ -1 +1,2 @@
1
- export declare function DJB2(value: string): string;
1
+ export declare const DJB2: (value: string) => string;
2
+ export declare const DJB2Object: (value: Record<string, unknown> | null) => string;
package/src/Hashing.js CHANGED
@@ -1,13 +1,32 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DJB2 = void 0;
4
- function DJB2(value) {
5
- var hash = 0;
6
- for (var i = 0; i < value.length; i++) {
7
- var character = value.charCodeAt(i);
3
+ exports.DJB2Object = exports.DJB2 = void 0;
4
+ const DJB2 = (value) => {
5
+ let hash = 0;
6
+ for (let i = 0; i < value.length; i++) {
7
+ const character = value.charCodeAt(i);
8
8
  hash = (hash << 5) - hash + character;
9
9
  hash = hash & hash; // Convert to 32bit integer
10
10
  }
11
11
  return String(hash >>> 0);
12
- }
12
+ };
13
13
  exports.DJB2 = DJB2;
14
+ const DJB2Object = (value) => {
15
+ return (0, exports.DJB2)(JSON.stringify(_getSortedObject(value)));
16
+ };
17
+ exports.DJB2Object = DJB2Object;
18
+ const _getSortedObject = (object) => {
19
+ if (object == null) {
20
+ return null;
21
+ }
22
+ const keys = Object.keys(object).sort();
23
+ const sortedObject = {};
24
+ keys.forEach((key) => {
25
+ let value = object[key];
26
+ if (value instanceof Object) {
27
+ value = _getSortedObject(value);
28
+ }
29
+ sortedObject[key] = value;
30
+ });
31
+ return sortedObject;
32
+ };
@@ -0,0 +1,18 @@
1
+ import { DynamicConfigEvaluation, GateEvaluation, LayerEvaluation } from './EvaluationTypes';
2
+ type SessionReplayFields = {
3
+ can_record_session?: boolean;
4
+ session_recording_rate?: number;
5
+ };
6
+ export type InitializeResponseWithUpdates = SessionReplayFields & {
7
+ feature_gates: Record<string, GateEvaluation>;
8
+ dynamic_configs: Record<string, DynamicConfigEvaluation>;
9
+ layer_configs: Record<string, LayerEvaluation>;
10
+ time: number;
11
+ has_updates: true;
12
+ hash_used: 'none' | 'sha256' | 'djb2';
13
+ derived_fields?: Record<string, unknown>;
14
+ };
15
+ export type InitializeResponse = InitializeResponseWithUpdates | {
16
+ has_updates: false;
17
+ };
18
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/src/Log.js CHANGED
@@ -14,46 +14,27 @@ var LogLevel;
14
14
  LogLevel[LogLevel["Info"] = 3] = "Info";
15
15
  LogLevel[LogLevel["Debug"] = 4] = "Debug";
16
16
  })(LogLevel || (exports.LogLevel = LogLevel = {}));
17
- var Log = /** @class */ (function () {
18
- function Log() {
19
- }
20
- Log.info = function () {
21
- var args = [];
22
- for (var _i = 0; _i < arguments.length; _i++) {
23
- args[_i] = arguments[_i];
24
- }
17
+ class Log {
18
+ static info(...args) {
25
19
  if (this.level >= LogLevel.Info) {
26
- console.info.apply(console, addTag(args));
27
- }
28
- };
29
- Log.debug = function () {
30
- var args = [];
31
- for (var _i = 0; _i < arguments.length; _i++) {
32
- args[_i] = arguments[_i];
20
+ console.info(...addTag(args));
33
21
  }
22
+ }
23
+ static debug(...args) {
34
24
  if (this.level >= LogLevel.Debug) {
35
- console.debug.apply(console, addTag(args));
36
- }
37
- };
38
- Log.warn = function () {
39
- var args = [];
40
- for (var _i = 0; _i < arguments.length; _i++) {
41
- args[_i] = arguments[_i];
25
+ console.debug(...addTag(args));
42
26
  }
27
+ }
28
+ static warn(...args) {
43
29
  if (this.level >= LogLevel.Warn) {
44
- console.warn.apply(console, addTag(args));
45
- }
46
- };
47
- Log.error = function () {
48
- var args = [];
49
- for (var _i = 0; _i < arguments.length; _i++) {
50
- args[_i] = arguments[_i];
30
+ console.warn(...addTag(args));
51
31
  }
32
+ }
33
+ static error(...args) {
52
34
  if (this.level >= LogLevel.Error) {
53
- console.error.apply(console, addTag(args));
35
+ console.error(...addTag(args));
54
36
  }
55
- };
56
- Log.level = LogLevel.Error;
57
- return Log;
58
- }());
37
+ }
38
+ }
59
39
  exports.Log = Log;
40
+ Log.level = LogLevel.Error;
@@ -0,0 +1,18 @@
1
+ export declare const NetworkDefault: {
2
+ eventsApi: "https://prodregistryv2.org/v1";
3
+ initializeApi: "https://featureassets.org/v1";
4
+ specsApi: "https://assetsconfigcdn.org/v1";
5
+ };
6
+ export type NetworkPriority = 'high' | 'low' | 'auto';
7
+ export type NetworkArgs = RequestInit & {
8
+ priority?: NetworkPriority;
9
+ };
10
+ export declare enum NetworkParam {
11
+ EventCount = "ec",
12
+ SdkKey = "k",
13
+ SdkType = "st",
14
+ SdkVersion = "sv",
15
+ Time = "t",
16
+ SessionID = "sid",
17
+ StatsigEncoded = "se"
18
+ }