@statsig/client-core 0.0.1-beta.1 → 0.0.1-beta.10

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.
@@ -1,19 +1,4 @@
1
1
  "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- if (typeof b !== "function" && b !== null)
11
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
- extendStatics(d, b);
13
- function __() { this.constructor = d; }
14
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
- };
16
- })();
17
2
  var __assign = (this && this.__assign) || function () {
18
3
  __assign = Object.assign || function(t) {
19
4
  for (var s, i = 1, n = arguments.length; i < n; i++) {
@@ -69,33 +54,21 @@ var SessionID_1 = require("./SessionID");
69
54
  var StableID_1 = require("./StableID");
70
55
  var StatsigMetadata_1 = require("./StatsigMetadata");
71
56
  var DEFAULT_TIMEOUT_MS = 10000;
72
- var NetworkError = /** @class */ (function (_super) {
73
- __extends(NetworkError, _super);
74
- function NetworkError(message, errorDescription) {
75
- var _this = _super.call(this, message) || this;
76
- _this.errorDescription = errorDescription;
77
- return _this;
78
- }
79
- return NetworkError;
80
- }(Error));
81
57
  var NetworkCore = /** @class */ (function () {
82
- function NetworkCore(_options) {
58
+ function NetworkCore(_options, _emitter) {
83
59
  var _a;
84
60
  this._options = _options;
61
+ this._emitter = _emitter;
85
62
  this._timeout = (_a = _options === null || _options === void 0 ? void 0 : _options.networkTimeoutMs) !== null && _a !== void 0 ? _a : DEFAULT_TIMEOUT_MS;
86
63
  }
87
64
  NetworkCore.prototype.post = function (args) {
88
65
  return __awaiter(this, void 0, void 0, function () {
89
- var data, stableID, sessionID, body;
66
+ var body;
90
67
  return __generator(this, function (_a) {
91
68
  switch (_a.label) {
92
- case 0:
93
- data = args.data;
94
- return [4 /*yield*/, StableID_1.StableID.get(args.sdkKey)];
69
+ case 0: return [4 /*yield*/, this._getPopulatedBody(args)];
95
70
  case 1:
96
- stableID = _a.sent();
97
- sessionID = SessionID_1.SessionID.get(args.sdkKey);
98
- body = JSON.stringify(__assign(__assign({}, data), { statsigMetadata: __assign(__assign({}, StatsigMetadata_1.StatsigMetadataProvider.get()), { stableID: stableID, sessionID: sessionID }) }));
71
+ body = _a.sent();
99
72
  return [2 /*return*/, this._sendRequest(__assign({ method: 'POST', body: body }, args))];
100
73
  }
101
74
  });
@@ -108,51 +81,68 @@ var NetworkCore = /** @class */ (function () {
108
81
  });
109
82
  });
110
83
  };
84
+ NetworkCore.prototype.isBeaconSupported = function () {
85
+ return (typeof navigator !== 'undefined' &&
86
+ typeof (navigator === null || navigator === void 0 ? void 0 : navigator.sendBeacon) === 'function');
87
+ };
111
88
  NetworkCore.prototype.beacon = function (args) {
112
- var url = new URL(args.url);
113
- url.searchParams.append('k', args.sdkKey);
114
- return navigator.sendBeacon(url, JSON.stringify(args.data));
89
+ return __awaiter(this, void 0, void 0, function () {
90
+ var url, body;
91
+ return __generator(this, function (_a) {
92
+ switch (_a.label) {
93
+ case 0:
94
+ url = this._getPopulatedURL(args);
95
+ return [4 /*yield*/, this._getPopulatedBody(args)];
96
+ case 1:
97
+ body = _a.sent();
98
+ return [2 /*return*/, navigator.sendBeacon(url, body)];
99
+ }
100
+ });
101
+ });
115
102
  };
116
103
  NetworkCore.prototype._sendRequest = function (args) {
104
+ var _a;
117
105
  return __awaiter(this, void 0, void 0, function () {
118
- var method, body, retries, controller, handle, response, fullUrl, text, error_1, errorMessage;
106
+ var method, body, retries, controller, handle, response, url, text, err, error_1, errorMessage;
119
107
  var _this = this;
120
- return __generator(this, function (_a) {
121
- switch (_a.label) {
108
+ return __generator(this, function (_b) {
109
+ switch (_b.label) {
122
110
  case 0:
123
111
  method = args.method, body = args.body, retries = args.retries;
124
112
  controller = new AbortController();
125
113
  handle = setTimeout(function () { return controller.abort("Timeout of ".concat(_this._timeout, "ms expired.")); }, this._timeout);
126
114
  response = null;
127
- _a.label = 1;
115
+ _b.label = 1;
128
116
  case 1:
129
- _a.trys.push([1, 4, , 5]);
130
- fullUrl = this._getPopulatedURL(args);
131
- return [4 /*yield*/, fetch(fullUrl, {
117
+ _b.trys.push([1, 4, , 5]);
118
+ url = this._getPopulatedURL(args);
119
+ return [4 /*yield*/, fetch(url, {
132
120
  method: method,
133
121
  body: body,
134
- headers: __assign({
135
- // Must set this content type to bypass cors
136
- // can override via headers if necessary (recommended for logevent)
137
- 'Content-Type': 'text/plain' }, args.headers),
122
+ headers: __assign({}, args.headers),
138
123
  signal: controller.signal,
139
124
  })];
140
125
  case 2:
141
- response = _a.sent();
126
+ response = _b.sent();
142
127
  clearTimeout(handle);
143
128
  return [4 /*yield*/, response.text()];
144
129
  case 3:
145
- text = _a.sent();
130
+ text = _b.sent();
146
131
  if (!response.ok) {
147
- throw new NetworkError('Fetch Failure', text);
132
+ err = new Error("Failed to fetch: ".concat(url, " ").concat(text));
133
+ err.name = 'NetworkError';
134
+ throw err;
148
135
  }
149
136
  Diagnostics_1.Diagnostics.mark('_sendRequest:response-received', {
150
137
  status: response.status,
151
138
  contentLength: response.headers.get('content-length'),
152
139
  });
153
- return [2 /*return*/, text];
140
+ return [2 /*return*/, {
141
+ body: text,
142
+ code: response.status,
143
+ }];
154
144
  case 4:
155
- error_1 = _a.sent();
145
+ error_1 = _b.sent();
156
146
  errorMessage = _getErrorMessage(controller, error_1);
157
147
  Diagnostics_1.Diagnostics.mark('_sendRequest:error', {
158
148
  error: errorMessage,
@@ -160,7 +150,8 @@ var NetworkCore = /** @class */ (function () {
160
150
  contentLength: response === null || response === void 0 ? void 0 : response.headers.get('content-length'),
161
151
  });
162
152
  if (!retries || retries <= 0) {
163
- Log_1.Log.error('A networking error occured.', errorMessage);
153
+ (_a = this._emitter) === null || _a === void 0 ? void 0 : _a.call(this, { event: 'error', error: error_1 });
154
+ Log_1.Log.error('A networking error occured.', errorMessage, error_1);
164
155
  return [2 /*return*/, null];
165
156
  }
166
157
  return [2 /*return*/, this._sendRequest(__assign(__assign({}, args), { retries: retries - 1 }))];
@@ -170,14 +161,31 @@ var NetworkCore = /** @class */ (function () {
170
161
  });
171
162
  };
172
163
  NetworkCore.prototype._getPopulatedURL = function (args) {
173
- var statsigMetadata = StatsigMetadata_1.StatsigMetadataProvider.get();
174
- var fullUrl = new URL(args.url);
175
- fullUrl.searchParams.append('k', args.sdkKey);
176
- fullUrl.searchParams.append('st', statsigMetadata.sdkType);
177
- fullUrl.searchParams.append('sv', statsigMetadata.sdkVersion);
178
- fullUrl.searchParams.append('t', String(Date.now()));
179
- fullUrl.searchParams.append('sid', SessionID_1.SessionID.get(args.sdkKey));
180
- return fullUrl.toString();
164
+ var metadata = StatsigMetadata_1.StatsigMetadataProvider.get();
165
+ var params = __assign(__assign({}, args.params), { k: args.sdkKey, st: metadata.sdkType, sv: metadata.sdkVersion, t: String(Date.now()), sid: SessionID_1.SessionID.get(args.sdkKey) });
166
+ var query = Object.entries(params)
167
+ .map(function (_a) {
168
+ var key = _a[0], value = _a[1];
169
+ return "".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(value));
170
+ })
171
+ .join('&');
172
+ return "".concat(args.url).concat(query ? "?".concat(query) : '');
173
+ };
174
+ NetworkCore.prototype._getPopulatedBody = function (args) {
175
+ return __awaiter(this, void 0, void 0, function () {
176
+ var data, stableID, sessionID;
177
+ return __generator(this, function (_a) {
178
+ switch (_a.label) {
179
+ case 0:
180
+ data = args.data;
181
+ return [4 /*yield*/, StableID_1.StableID.get(args.sdkKey)];
182
+ case 1:
183
+ stableID = _a.sent();
184
+ sessionID = SessionID_1.SessionID.get(args.sdkKey);
185
+ return [2 /*return*/, JSON.stringify(__assign(__assign({}, data), { statsigMetadata: __assign(__assign({}, StatsigMetadata_1.StatsigMetadataProvider.get()), { stableID: stableID, sessionID: sessionID }) }))];
186
+ }
187
+ });
188
+ });
181
189
  };
182
190
  return NetworkCore;
183
191
  }());
package/src/StableID.js CHANGED
@@ -64,7 +64,7 @@ exports.StableID = {
64
64
  },
65
65
  };
66
66
  function _getStableIDStorageKey(sdkKey) {
67
- return "STATSIG_STABLE_ID:".concat((0, Hashing_1.DJB2)(sdkKey));
67
+ return "statsig.stable_id.".concat((0, Hashing_1.DJB2)(sdkKey));
68
68
  }
69
69
  function _persistToStorage(stableID, sdkKey) {
70
70
  var storageKey = _getStableIDStorageKey(sdkKey);
@@ -3,35 +3,28 @@ import { ErrorBoundary } from './ErrorBoundary';
3
3
  import { EventLogger } from './EventLogger';
4
4
  import { NetworkCore } from './NetworkCore';
5
5
  import { StatsigClientEvent, StatsigClientEventCallback, StatsigClientEventData, StatsigClientEventEmitterInterface, StatsigLoadingStatus } from './StatsigClientEventEmitter';
6
- import { DataSource, StatsigDataProvider } from './StatsigDataProvider';
6
+ import { StatsigDataAdapter, StatsigDataAdapterResult } from './StatsigDataAdapter';
7
7
  import { StatsigEventInternal } from './StatsigEvent';
8
8
  import { StatsigOptionsCommon } from './StatsigOptionsCommon';
9
9
  import { StatsigUser } from './StatsigUser';
10
- type DataProviderResult = {
11
- data: string | null;
12
- source: DataSource;
13
- };
14
10
  export type EvaluationOptions = {
15
11
  disableExposureLog?: boolean;
16
12
  };
17
13
  export declare const DEFAULT_EVAL_OPTIONS: EvaluationOptions;
18
14
  export type StatsigClientEmitEventFunc = (data: StatsigClientEventData) => void;
19
- export declare class StatsigClientBase implements StatsigClientEventEmitterInterface {
15
+ export declare abstract class StatsigClientBase implements StatsigClientEventEmitterInterface {
16
+ protected readonly _sdkKey: string;
17
+ protected readonly _adapter: StatsigDataAdapter;
20
18
  loadingStatus: StatsigLoadingStatus;
21
- protected _errorBoundary: ErrorBoundary;
22
- protected _logger: EventLogger;
23
- protected _sdkKey: string;
24
- protected _dataProviders: StatsigDataProvider[];
19
+ protected readonly _errorBoundary: ErrorBoundary;
20
+ protected readonly _logger: EventLogger;
25
21
  private _listeners;
26
- constructor(sdkKey: string, network: NetworkCore, options: StatsigOptionsCommon | null, dataProviders: StatsigDataProvider[]);
22
+ constructor(_sdkKey: string, _adapter: StatsigDataAdapter, network: NetworkCore, options: StatsigOptionsCommon | null);
27
23
  on(event: StatsigClientEvent | '*', listener: StatsigClientEventCallback): void;
28
24
  off(event: StatsigClientEvent | '*', listener: StatsigClientEventCallback): void;
25
+ getDataAdapter(): StatsigDataAdapter;
29
26
  protected emit(data: StatsigClientEventData): void;
30
- protected _setStatus(newStatus: StatsigLoadingStatus): void;
31
- protected _getDataFromProviders(user?: StatsigUser): DataProviderResult;
32
- protected _getDataFromProvidersAsync(user?: StatsigUser): Promise<DataProviderResult>;
33
- protected _getDataPostInitFromProviders(user?: StatsigUser): Promise<DataProviderResult>;
34
- protected _saveToDataProviders(data: string | null, user?: StatsigUser): void;
27
+ protected _setStatus(newStatus: StatsigLoadingStatus, values: StatsigDataAdapterResult | null): void;
35
28
  protected _enqueueExposure(options: EvaluationOptions, exposure: StatsigEventInternal): void;
29
+ protected _runPostUpdate(current: StatsigDataAdapterResult | null, user?: StatsigUser): void;
36
30
  }
37
- export {};
@@ -1,47 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
- 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;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
- var __asyncValues = (this && this.__asyncValues) || function (o) {
39
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
40
- var m = o[Symbol.asyncIterator], i;
41
- return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
42
- function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
43
- function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
44
- };
45
2
  Object.defineProperty(exports, "__esModule", { value: true });
46
3
  exports.StatsigClientBase = exports.DEFAULT_EVAL_OPTIONS = void 0;
47
4
  require("./$_StatsigGlobal");
@@ -53,22 +10,23 @@ exports.DEFAULT_EVAL_OPTIONS = {
53
10
  disableExposureLog: false,
54
11
  };
55
12
  var StatsigClientBase = /** @class */ (function () {
56
- function StatsigClientBase(sdkKey, network, options, dataProviders) {
13
+ function StatsigClientBase(_sdkKey, _adapter, network, options) {
57
14
  var _a, _b;
15
+ this._sdkKey = _sdkKey;
16
+ this._adapter = _adapter;
58
17
  this.loadingStatus = 'Uninitialized';
59
18
  this._listeners = {};
60
- this._logger = new EventLogger_1.EventLogger(sdkKey, this.emit.bind(this), network, options);
61
- this._sdkKey = sdkKey;
62
- this._errorBoundary = new ErrorBoundary_1.ErrorBoundary(sdkKey);
19
+ Log_1.Log.level = (_a = options === null || options === void 0 ? void 0 : options.logLevel) !== null && _a !== void 0 ? _a : Log_1.LogLevel.Warn;
20
+ this._logger = new EventLogger_1.EventLogger(_sdkKey, this.emit.bind(this), network, options);
21
+ this._errorBoundary = new ErrorBoundary_1.ErrorBoundary(_sdkKey);
63
22
  if (options === null || options === void 0 ? void 0 : options.overrideStableID) {
64
- StableID_1.StableID.setOverride(options.overrideStableID, sdkKey);
23
+ StableID_1.StableID.setOverride(options.overrideStableID, _sdkKey);
65
24
  }
66
25
  __STATSIG__ = __STATSIG__ !== null && __STATSIG__ !== void 0 ? __STATSIG__ : {};
67
- var instances = (_a = __STATSIG__.instances) !== null && _a !== void 0 ? _a : new Set();
26
+ var instances = (_b = __STATSIG__.instances) !== null && _b !== void 0 ? _b : new Set();
68
27
  instances.add(this);
69
28
  __STATSIG__.instances = instances;
70
- Log_1.Log.level = (_b = options === null || options === void 0 ? void 0 : options.logLevel) !== null && _b !== void 0 ? _b : Log_1.LogLevel.Error;
71
- this._dataProviders = dataProviders;
29
+ this._adapter.attach(_sdkKey, options);
72
30
  }
73
31
  StatsigClientBase.prototype.on = function (event, listener) {
74
32
  if (!this._listeners[event]) {
@@ -84,6 +42,9 @@ var StatsigClientBase = /** @class */ (function () {
84
42
  }
85
43
  }
86
44
  };
45
+ StatsigClientBase.prototype.getDataAdapter = function () {
46
+ return this._adapter;
47
+ };
87
48
  StatsigClientBase.prototype.emit = function (data) {
88
49
  var _a;
89
50
  if (this._listeners[data.event]) {
@@ -91,175 +52,9 @@ var StatsigClientBase = /** @class */ (function () {
91
52
  }
92
53
  (_a = this._listeners['*']) === null || _a === void 0 ? void 0 : _a.forEach(function (listener) { return listener(data); });
93
54
  };
94
- StatsigClientBase.prototype._setStatus = function (newStatus) {
55
+ StatsigClientBase.prototype._setStatus = function (newStatus, values) {
95
56
  this.loadingStatus = newStatus;
96
- this.emit({ event: 'status_change', loadingStatus: newStatus });
97
- };
98
- StatsigClientBase.prototype._getDataFromProviders = function (user) {
99
- var _a;
100
- for (var _i = 0, _b = this._dataProviders; _i < _b.length; _i++) {
101
- var provider = _b[_i];
102
- var data = (_a = provider.getData) === null || _a === void 0 ? void 0 : _a.call(provider, this._sdkKey, user);
103
- if (data) {
104
- return { data: data, source: provider.source };
105
- }
106
- }
107
- return { data: null, source: 'NoValues' };
108
- };
109
- StatsigClientBase.prototype._getDataFromProvidersAsync = function (user) {
110
- var _a, e_1, _b, _c;
111
- var _d;
112
- return __awaiter(this, void 0, void 0, function () {
113
- var _e, _f, _g, provider, data, e_1_1;
114
- return __generator(this, function (_h) {
115
- switch (_h.label) {
116
- case 0:
117
- _h.trys.push([0, 6, 7, 12]);
118
- _e = true, _f = __asyncValues(this._dataProviders);
119
- _h.label = 1;
120
- case 1: return [4 /*yield*/, _f.next()];
121
- case 2:
122
- if (!(_g = _h.sent(), _a = _g.done, !_a)) return [3 /*break*/, 5];
123
- _c = _g.value;
124
- _e = false;
125
- provider = _c;
126
- return [4 /*yield*/, ((_d = provider.getDataAsync) === null || _d === void 0 ? void 0 : _d.call(provider, this._sdkKey, user))];
127
- case 3:
128
- data = _h.sent();
129
- if (data) {
130
- return [2 /*return*/, { data: data, source: provider.source }];
131
- }
132
- _h.label = 4;
133
- case 4:
134
- _e = true;
135
- return [3 /*break*/, 1];
136
- case 5: return [3 /*break*/, 12];
137
- case 6:
138
- e_1_1 = _h.sent();
139
- e_1 = { error: e_1_1 };
140
- return [3 /*break*/, 12];
141
- case 7:
142
- _h.trys.push([7, , 10, 11]);
143
- if (!(!_e && !_a && (_b = _f.return))) return [3 /*break*/, 9];
144
- return [4 /*yield*/, _b.call(_f)];
145
- case 8:
146
- _h.sent();
147
- _h.label = 9;
148
- case 9: return [3 /*break*/, 11];
149
- case 10:
150
- if (e_1) throw e_1.error;
151
- return [7 /*endfinally*/];
152
- case 11: return [7 /*endfinally*/];
153
- case 12: return [2 /*return*/, { data: null, source: 'NoValues' }];
154
- }
155
- });
156
- });
157
- };
158
- StatsigClientBase.prototype._getDataPostInitFromProviders = function (user) {
159
- var _a, e_2, _b, _c;
160
- var _d;
161
- return __awaiter(this, void 0, void 0, function () {
162
- var _e, _f, _g, provider, data, e_2_1;
163
- return __generator(this, function (_h) {
164
- switch (_h.label) {
165
- case 0:
166
- _h.trys.push([0, 6, 7, 12]);
167
- _e = true, _f = __asyncValues(this._dataProviders);
168
- _h.label = 1;
169
- case 1: return [4 /*yield*/, _f.next()];
170
- case 2:
171
- if (!(_g = _h.sent(), _a = _g.done, !_a)) return [3 /*break*/, 5];
172
- _c = _g.value;
173
- _e = false;
174
- provider = _c;
175
- return [4 /*yield*/, ((_d = provider.getDataPostInit) === null || _d === void 0 ? void 0 : _d.call(provider, this._sdkKey, user))];
176
- case 3:
177
- data = _h.sent();
178
- if (data) {
179
- return [2 /*return*/, { data: data, source: provider.source }];
180
- }
181
- _h.label = 4;
182
- case 4:
183
- _e = true;
184
- return [3 /*break*/, 1];
185
- case 5: return [3 /*break*/, 12];
186
- case 6:
187
- e_2_1 = _h.sent();
188
- e_2 = { error: e_2_1 };
189
- return [3 /*break*/, 12];
190
- case 7:
191
- _h.trys.push([7, , 10, 11]);
192
- if (!(!_e && !_a && (_b = _f.return))) return [3 /*break*/, 9];
193
- return [4 /*yield*/, _b.call(_f)];
194
- case 8:
195
- _h.sent();
196
- _h.label = 9;
197
- case 9: return [3 /*break*/, 11];
198
- case 10:
199
- if (e_2) throw e_2.error;
200
- return [7 /*endfinally*/];
201
- case 11: return [7 /*endfinally*/];
202
- case 12: return [2 /*return*/, { data: null, source: 'NoValues' }];
203
- }
204
- });
205
- });
206
- };
207
- StatsigClientBase.prototype._saveToDataProviders = function (data, user) {
208
- var _this = this;
209
- (function () { return __awaiter(_this, void 0, void 0, function () {
210
- var localResult, _a, _b, _c, provider, e_3_1;
211
- var _d, e_3, _e, _f;
212
- var _g, _h;
213
- return __generator(this, function (_j) {
214
- switch (_j.label) {
215
- case 0: return [4 /*yield*/, this._getDataPostInitFromProviders(user)];
216
- case 1:
217
- localResult = _j.sent();
218
- data = (_g = localResult.data) !== null && _g !== void 0 ? _g : data;
219
- if (!data) {
220
- return [2 /*return*/];
221
- }
222
- _j.label = 2;
223
- case 2:
224
- _j.trys.push([2, 8, 9, 14]);
225
- _a = true, _b = __asyncValues(this._dataProviders);
226
- _j.label = 3;
227
- case 3: return [4 /*yield*/, _b.next()];
228
- case 4:
229
- if (!(_c = _j.sent(), _d = _c.done, !_d)) return [3 /*break*/, 7];
230
- _f = _c.value;
231
- _a = false;
232
- provider = _f;
233
- return [4 /*yield*/, ((_h = provider.setDataPostInit) === null || _h === void 0 ? void 0 : _h.call(provider, this._sdkKey, data, user))];
234
- case 5:
235
- _j.sent();
236
- _j.label = 6;
237
- case 6:
238
- _a = true;
239
- return [3 /*break*/, 3];
240
- case 7: return [3 /*break*/, 14];
241
- case 8:
242
- e_3_1 = _j.sent();
243
- e_3 = { error: e_3_1 };
244
- return [3 /*break*/, 14];
245
- case 9:
246
- _j.trys.push([9, , 12, 13]);
247
- if (!(!_a && !_d && (_e = _b.return))) return [3 /*break*/, 11];
248
- return [4 /*yield*/, _e.call(_b)];
249
- case 10:
250
- _j.sent();
251
- _j.label = 11;
252
- case 11: return [3 /*break*/, 13];
253
- case 12:
254
- if (e_3) throw e_3.error;
255
- return [7 /*endfinally*/];
256
- case 13: return [7 /*endfinally*/];
257
- case 14: return [2 /*return*/];
258
- }
259
- });
260
- }); })().catch(function (error) {
261
- _this.emit({ event: 'error', error: error });
262
- });
57
+ this.emit({ event: 'values_updated', status: newStatus, values: values });
263
58
  };
264
59
  StatsigClientBase.prototype._enqueueExposure = function (options, exposure) {
265
60
  if (options.disableExposureLog === true) {
@@ -267,6 +62,11 @@ var StatsigClientBase = /** @class */ (function () {
267
62
  }
268
63
  this._logger.enqueue(exposure);
269
64
  };
65
+ StatsigClientBase.prototype._runPostUpdate = function (current, user) {
66
+ this._adapter.getDataAsync(current, user).catch(function (err) {
67
+ Log_1.Log.error('An error occurred after update.', err);
68
+ });
69
+ };
270
70
  return StatsigClientBase;
271
71
  }());
272
72
  exports.StatsigClientBase = StatsigClientBase;
@@ -1,11 +1,33 @@
1
+ import { StatsigDataAdapterResult } from './StatsigDataAdapter';
1
2
  import { DynamicConfig, Experiment, FeatureGate, Layer } from './StatsigTypes';
2
- export type StatsigLoadingStatus = 'Uninitialized' | 'Loading' | 'Ready' | 'Error';
3
- export type StatsigClientEvent = 'status_change' | 'error' | 'logs_flushed' | 'gate_evaluation' | 'dynamic_config_evaluation' | 'experiment_evaluation' | 'layer_evaluation';
3
+ export type StatsigLoadingStatus = 'Uninitialized' | 'Loading' | 'Ready';
4
+ /**
5
+ * All the possible events emitted from a Statsig client.
6
+ *
7
+ * `values_updated` - When the Statsig clients internal values change as the result of an initialize/update operation.
8
+ *
9
+ * `error` - When an unexpected error occurs within the Statsig client.
10
+ *
11
+ * `logs_flushed` - When queued StatsigEvents are flushed to Statsig servers.
12
+ *
13
+ * `gate_evaluation` - Fired when any gate is checked from the Statsig client.
14
+ *
15
+ * `dynamic_config_evaluation` - Fired when any dyanamic config is checked from the Statsig client.
16
+ *
17
+ * `experiment_evaluation` - Fired when any experiment is checked from the Statsig client.
18
+ *
19
+ * `layer_evaluation` - Fired when any layer is checked from the Statsig client.
20
+ */
21
+ export type StatsigClientEvent = 'values_updated' | 'error' | 'logs_flushed' | 'gate_evaluation' | 'dynamic_config_evaluation' | 'experiment_evaluation' | 'layer_evaluation';
22
+ /**
23
+ * Type representing various events emitted by a Statsig client.
24
+ */
4
25
  export type StatsigClientEventData = {
5
26
  event: StatsigClientEvent;
6
27
  } | {
7
- event: 'status_change';
8
- loadingStatus: StatsigLoadingStatus;
28
+ event: 'values_updated';
29
+ status: StatsigLoadingStatus;
30
+ values: StatsigDataAdapterResult | null;
9
31
  } | {
10
32
  event: 'error';
11
33
  error: unknown;
@@ -0,0 +1,43 @@
1
+ import { StatsigOptionsCommon } from './StatsigOptionsCommon';
2
+ import { StatsigUser } from './StatsigUser';
3
+ export type DataSource = 'Uninitialized' | 'Loading' | 'NoValues' | 'Cache' | 'Network' | 'NetworkNotModified' | 'Bootstrap' | 'Prefetch';
4
+ export type StatsigDataAdapterResult = {
5
+ readonly source: DataSource;
6
+ readonly data: string;
7
+ readonly receivedAt: number;
8
+ };
9
+ export declare const DataAdapterCachePrefix = "statsig.cached";
10
+ /**
11
+ * Describes a type that is used during intialize/update operations of a Statsig client.
12
+ *
13
+ * See below to find the default adapters, but know that it is possible to create your
14
+ * own StatsigDataAdapter and provide it via {@link StatsigOptionsCommon.dataAdapter}.
15
+ *
16
+ * Defaults:
17
+ *
18
+ * - {@link PrecomputedEvaluationsClient} uses {@link EvaluationsDataAdapter}
19
+ *
20
+ * - {@link OnDeviceEvaluationsClient} uses {@link SpecsDataAdapter}
21
+ */
22
+ export type StatsigDataAdapter = {
23
+ readonly _setInMemoryCache: (cache: Record<string, StatsigDataAdapterResult>) => void;
24
+ /**
25
+ * Called when the StatsigDataAdapter is attached to the Statsig client instance during construction.
26
+ * @param {string} sdkKey The SDK key being used by the Statsig client.
27
+ * @param {StatsigOptionsCommon | null} options The StatsigOptions being used by the Statsig client.
28
+ */
29
+ readonly attach: (sdkKey: string, options: StatsigOptionsCommon | null) => void;
30
+ /**
31
+ * Synchronously get data for the given user (if any). Called during initializeSync and/or updateUserSync.
32
+ * It is also called during async update operations before StatsigDataAdapter.getDataAsync is called.
33
+ * @param {StatsigUser | undefined} user The StatsigUser to get data for.
34
+ * @returns {StatsigDataAdapterResult | null} The data that was found for the given StatsigUser.
35
+ */
36
+ readonly getDataSync: (user?: StatsigUser) => StatsigDataAdapterResult | null;
37
+ /**
38
+ * Asynchronously get data for the given user (if any). Called during initializeAsync and/or updateUserAsync.
39
+ * @param {StatsigUser | undefined} user The StatsigUser to get data for.
40
+ * @returns {StatsigDataAdapterResult | null} The data that was found for the given StatsigUser.
41
+ */
42
+ readonly getDataAsync: (current: StatsigDataAdapterResult | null, user?: StatsigUser) => Promise<StatsigDataAdapterResult | null>;
43
+ };
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataAdapterCachePrefix = void 0;
4
+ exports.DataAdapterCachePrefix = 'statsig.cached';
@@ -1,5 +1,4 @@
1
- import { DataSource } from './StatsigDataProvider';
2
- import { DynamicConfig, FeatureGate } from './StatsigTypes';
1
+ import { DynamicConfig, EvaluationDetails, FeatureGate } from './StatsigTypes';
3
2
  import { StatsigUser } from './StatsigUser';
4
3
  export type SecondaryExposure = {
5
4
  gate: string;
@@ -27,5 +26,5 @@ export declare function createLayerParameterExposure(user: StatsigUser, layerNam
27
26
  undelegated_secondary_exposures?: SecondaryExposure[];
28
27
  secondary_exposures: SecondaryExposure[];
29
28
  allocated_experiment_name: string;
30
- source: DataSource;
29
+ details: EvaluationDetails;
31
30
  }): StatsigEventInternal;