@statsig/client-core 0.0.1-beta.2 → 0.0.1-beta.21

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 (54) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/$_StatsigGlobal.d.ts +2 -1
  4. package/src/$_StatsigGlobal.js +10 -12
  5. package/src/ClientInterfaces.d.ts +20 -13
  6. package/src/DataAdapterCore.d.ts +32 -0
  7. package/src/DataAdapterCore.js +167 -0
  8. package/src/Diagnostics.js +21 -26
  9. package/src/ErrorBoundary.d.ts +1 -0
  10. package/src/ErrorBoundary.js +39 -86
  11. package/src/EvaluationOptions.d.ts +20 -0
  12. package/src/EvaluationTypes.d.ts +39 -0
  13. package/src/EvaluationTypes.js +2 -0
  14. package/src/EventLogger.d.ts +17 -4
  15. package/src/EventLogger.js +186 -225
  16. package/src/Hashing.d.ts +1 -0
  17. package/src/Hashing.js +23 -4
  18. package/src/Log.js +15 -34
  19. package/src/Monitoring.d.ts +1 -2
  20. package/src/Monitoring.js +68 -27
  21. package/src/NetworkCore.d.ts +13 -5
  22. package/src/NetworkCore.js +96 -164
  23. package/src/OverrideAdapter.d.ts +16 -0
  24. package/src/OverrideAdapter.js +24 -0
  25. package/src/SessionID.js +3 -3
  26. package/src/StableID.js +23 -52
  27. package/src/StatsigClientBase.d.ts +20 -29
  28. package/src/StatsigClientBase.js +58 -248
  29. package/src/StatsigClientEventEmitter.d.ts +55 -28
  30. package/src/StatsigDataAdapter.d.ts +89 -0
  31. package/src/StatsigDataAdapter.js +4 -0
  32. package/src/StatsigEvent.d.ts +9 -18
  33. package/src/StatsigEvent.js +40 -31
  34. package/src/StatsigMetadata.js +5 -16
  35. package/src/StatsigOptionsCommon.d.ts +42 -12
  36. package/src/StatsigTypes.d.ts +23 -15
  37. package/src/StatsigTypes.js +23 -16
  38. package/src/StatsigUser.d.ts +1 -0
  39. package/src/StatsigUser.js +12 -20
  40. package/src/StorageProvider.d.ts +7 -2
  41. package/src/StorageProvider.js +53 -62
  42. package/src/TypedJsonParse.d.ts +8 -0
  43. package/src/TypedJsonParse.js +27 -0
  44. package/src/UUID.js +9 -5
  45. package/src/UrlOverrides.d.ts +1 -0
  46. package/src/UrlOverrides.js +15 -0
  47. package/src/UtitlityTypes.d.ts +3 -0
  48. package/src/UtitlityTypes.js +2 -0
  49. package/src/VisibilityChangeObserver.js +18 -24
  50. package/src/__tests__/MockLocalStorage.js +18 -19
  51. package/src/index.d.ts +12 -3
  52. package/src/index.js +18 -16
  53. package/src/StatsigDataProvider.d.ts +0 -9
  54. /package/src/{StatsigDataProvider.js → EvaluationOptions.js} +0 -0
package/src/Monitoring.js CHANGED
@@ -1,33 +1,74 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.monitorFunction = exports.monitorClass = void 0;
4
- var Diagnostics_1 = require("./Diagnostics");
5
- var StatsigClientBase_1 = require("./StatsigClientBase");
6
- function monitorClass(errorBoundary, target, instance) {
7
- var methods = Object.getOwnPropertyNames(target.prototype);
8
- var obj = instance;
9
- var _loop_1 = function (method) {
10
- if (method === 'constructor' || typeof obj[method] !== 'function') {
11
- return "continue";
12
- }
13
- var original = obj[method];
14
- obj[method] = function () {
15
- var _this = this;
16
- var args = [];
17
- for (var _i = 0; _i < arguments.length; _i++) {
18
- args[_i] = arguments[_i];
19
- }
20
- return monitorFunction(errorBoundary, method, function () { return original.apply(_this, args); }, instance);
21
- };
22
- };
23
- for (var _i = 0, methods_1 = methods; _i < methods_1.length; _i++) {
24
- var method = methods_1[_i];
25
- _loop_1(method);
3
+ exports.monitorClass = void 0;
4
+ const Diagnostics_1 = require("./Diagnostics");
5
+ const StatsigClientBase_1 = require("./StatsigClientBase");
6
+ function monitorClass(errorBoundary, instance) {
7
+ try {
8
+ _monitorClassImpl(errorBoundary, instance);
9
+ }
10
+ catch (error) {
11
+ errorBoundary.logError('monitorClass', error);
26
12
  }
27
13
  }
28
14
  exports.monitorClass = monitorClass;
29
- function monitorFunction(errorBoundary, tag, func, instance) {
30
- var client = instance instanceof StatsigClientBase_1.StatsigClientBase ? instance['emit'] : undefined;
31
- return errorBoundary.capture(tag, function () { return (0, Diagnostics_1.captureDiagnostics)(tag, function () { return func.apply(instance); }); }, client);
15
+ function _monitorFunction(errorBoundary, tag, func, instance) {
16
+ const emitFunc = instance instanceof StatsigClientBase_1.StatsigClientBase
17
+ ? instance['_emit'].bind(instance)
18
+ : undefined;
19
+ return errorBoundary.capture(tag, () => (0, Diagnostics_1.captureDiagnostics)(tag, () => func.apply(instance)), emitFunc);
20
+ }
21
+ function _getProtoSafe(instance) {
22
+ if (typeof instance === 'object') {
23
+ const proto = Object.getPrototypeOf(instance);
24
+ return proto && typeof proto === 'object'
25
+ ? proto
26
+ : null;
27
+ }
28
+ return null;
29
+ }
30
+ function _getAllInstanceMethodNames(instance) {
31
+ const names = new Set();
32
+ let proto = _getProtoSafe(instance);
33
+ while (proto && proto !== Object.prototype) {
34
+ Object.getOwnPropertyNames(proto)
35
+ .filter((prop) => typeof (proto === null || proto === void 0 ? void 0 : proto[prop]) === 'function')
36
+ .forEach((name) => names.add(name));
37
+ proto = Object.getPrototypeOf(proto);
38
+ }
39
+ return Array.from(names);
40
+ }
41
+ function _getAllStaticMethodNames(instance) {
42
+ const names = new Set();
43
+ const proto = _getProtoSafe(instance);
44
+ Object.getOwnPropertyNames((proto === null || proto === void 0 ? void 0 : proto.constructor) || {})
45
+ .filter((prop) => {
46
+ var _a;
47
+ if (prop === 'caller' || prop === 'arguments' || prop === 'callee') {
48
+ return false;
49
+ }
50
+ return (typeof ((_a = proto === null || proto === void 0 ? void 0 : proto.constructor) === null || _a === void 0 ? void 0 : _a[prop]) === 'function');
51
+ })
52
+ .forEach((name) => names.add(name));
53
+ return Array.from(names);
54
+ }
55
+ function _monitorClassImpl(errorBoundary, instance) {
56
+ var _a;
57
+ const obj = instance;
58
+ for (const method of _getAllInstanceMethodNames(obj)) {
59
+ if (method === 'constructor') {
60
+ continue;
61
+ }
62
+ const original = obj[method];
63
+ obj[method] = function (...args) {
64
+ return _monitorFunction(errorBoundary, method, () => original.apply(this, args), instance);
65
+ };
66
+ }
67
+ for (const method of _getAllStaticMethodNames(obj)) {
68
+ const original = (_a = obj === null || obj === void 0 ? void 0 : obj.constructor) === null || _a === void 0 ? void 0 : _a[method];
69
+ (obj === null || obj === void 0 ? void 0 : obj.constructor)[method] =
70
+ function (...args) {
71
+ return _monitorFunction(errorBoundary, `${obj.constructor.name}.${method}`, () => original.apply(obj.constructor, args), instance);
72
+ };
73
+ }
32
74
  }
33
- exports.monitorFunction = monitorFunction;
@@ -1,22 +1,30 @@
1
+ import { StatsigClientEmitEventFunc } from './StatsigClientBase';
1
2
  import { StatsigOptionsCommon } from './StatsigOptionsCommon';
2
3
  type RequestArgs = {
3
4
  sdkKey: string;
4
5
  url: string;
5
- timeoutMs?: number;
6
6
  retries?: number;
7
+ params?: Record<string, string>;
7
8
  headers?: Record<string, string>;
8
9
  };
9
10
  type RequestArgsWithData = RequestArgs & {
10
11
  data: Record<string, unknown>;
11
12
  };
13
+ type NetworkResponse = {
14
+ body: string | null;
15
+ code: number;
16
+ };
12
17
  export declare class NetworkCore {
13
18
  private _options;
19
+ private _emitter?;
14
20
  private readonly _timeout;
15
- constructor(_options: StatsigOptionsCommon | null);
16
- post(args: RequestArgsWithData): Promise<string | null>;
17
- get(args: RequestArgs): Promise<string | null>;
18
- beacon(args: RequestArgsWithData): boolean;
21
+ constructor(_options: StatsigOptionsCommon | null, _emitter?: StatsigClientEmitEventFunc | undefined);
22
+ post(args: RequestArgsWithData): Promise<NetworkResponse | null>;
23
+ get(args: RequestArgs): Promise<NetworkResponse | null>;
24
+ isBeaconSupported(): boolean;
25
+ beacon(args: RequestArgsWithData): Promise<boolean>;
19
26
  private _sendRequest;
20
27
  private _getPopulatedURL;
28
+ private _getPopulatedBody;
21
29
  }
22
30
  export {};
@@ -1,30 +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
- var __assign = (this && this.__assign) || function () {
18
- __assign = Object.assign || function(t) {
19
- for (var s, i = 1, n = arguments.length; i < n; i++) {
20
- s = arguments[i];
21
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
22
- t[p] = s[p];
23
- }
24
- return t;
25
- };
26
- return __assign.apply(this, arguments);
27
- };
28
2
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
29
3
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
30
4
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -34,153 +8,111 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
34
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
35
9
  });
36
10
  };
37
- var __generator = (this && this.__generator) || function (thisArg, body) {
38
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
39
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
40
- function verb(n) { return function (v) { return step([n, v]); }; }
41
- function step(op) {
42
- if (f) throw new TypeError("Generator is already executing.");
43
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
44
- 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;
45
- if (y = 0, t) op = [op[0] & 2, t.value];
46
- switch (op[0]) {
47
- case 0: case 1: t = op; break;
48
- case 4: _.label++; return { value: op[1], done: false };
49
- case 5: _.label++; y = op[1]; op = [0]; continue;
50
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
51
- default:
52
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
53
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
54
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
55
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
56
- if (t[2]) _.ops.pop();
57
- _.trys.pop(); continue;
58
- }
59
- op = body.call(thisArg, _);
60
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
61
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
62
- }
63
- };
64
11
  Object.defineProperty(exports, "__esModule", { value: true });
65
12
  exports.NetworkCore = void 0;
66
- var Diagnostics_1 = require("./Diagnostics");
67
- var Log_1 = require("./Log");
68
- var SessionID_1 = require("./SessionID");
69
- var StableID_1 = require("./StableID");
70
- var StatsigMetadata_1 = require("./StatsigMetadata");
71
- 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
- var NetworkCore = /** @class */ (function () {
82
- function NetworkCore(_options) {
13
+ const Diagnostics_1 = require("./Diagnostics");
14
+ const Log_1 = require("./Log");
15
+ const SessionID_1 = require("./SessionID");
16
+ const StableID_1 = require("./StableID");
17
+ const StatsigMetadata_1 = require("./StatsigMetadata");
18
+ const DEFAULT_TIMEOUT_MS = 10000;
19
+ class NetworkCore {
20
+ constructor(_options, _emitter) {
83
21
  var _a;
84
22
  this._options = _options;
23
+ this._emitter = _emitter;
85
24
  this._timeout = (_a = _options === null || _options === void 0 ? void 0 : _options.networkTimeoutMs) !== null && _a !== void 0 ? _a : DEFAULT_TIMEOUT_MS;
86
25
  }
87
- NetworkCore.prototype.post = function (args) {
88
- return __awaiter(this, void 0, void 0, function () {
89
- var data, stableID, sessionID, body;
90
- return __generator(this, function (_a) {
91
- switch (_a.label) {
92
- case 0:
93
- data = args.data;
94
- return [4 /*yield*/, StableID_1.StableID.get(args.sdkKey)];
95
- 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 }) }));
99
- return [2 /*return*/, this._sendRequest(__assign({ method: 'POST', body: body }, args))];
100
- }
101
- });
26
+ post(args) {
27
+ return __awaiter(this, void 0, void 0, function* () {
28
+ const body = yield this._getPopulatedBody(args);
29
+ return this._sendRequest(Object.assign({ method: 'POST', body }, args));
30
+ });
31
+ }
32
+ get(args) {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ return this._sendRequest(Object.assign({ method: 'GET' }, args));
102
35
  });
103
- };
104
- NetworkCore.prototype.get = function (args) {
105
- return __awaiter(this, void 0, void 0, function () {
106
- return __generator(this, function (_a) {
107
- return [2 /*return*/, this._sendRequest(__assign({ method: 'GET' }, args))];
108
- });
36
+ }
37
+ isBeaconSupported() {
38
+ return (typeof navigator !== 'undefined' &&
39
+ typeof (navigator === null || navigator === void 0 ? void 0 : navigator.sendBeacon) === 'function');
40
+ }
41
+ beacon(args) {
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ const url = this._getPopulatedURL(args);
44
+ const body = yield this._getPopulatedBody(args);
45
+ return navigator.sendBeacon(url, body);
109
46
  });
110
- };
111
- 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));
115
- };
116
- NetworkCore.prototype._sendRequest = function (args) {
117
- return __awaiter(this, void 0, void 0, function () {
118
- var method, body, retries, controller, handle, response, fullUrl, text, error_1, errorMessage;
119
- var _this = this;
120
- return __generator(this, function (_a) {
121
- switch (_a.label) {
122
- case 0:
123
- method = args.method, body = args.body, retries = args.retries;
124
- controller = new AbortController();
125
- handle = setTimeout(function () { return controller.abort("Timeout of ".concat(_this._timeout, "ms expired.")); }, this._timeout);
126
- response = null;
127
- _a.label = 1;
128
- case 1:
129
- _a.trys.push([1, 4, , 5]);
130
- fullUrl = this._getPopulatedURL(args);
131
- return [4 /*yield*/, fetch(fullUrl, {
132
- method: method,
133
- 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),
138
- signal: controller.signal,
139
- })];
140
- case 2:
141
- response = _a.sent();
142
- clearTimeout(handle);
143
- return [4 /*yield*/, response.text()];
144
- case 3:
145
- text = _a.sent();
146
- if (!response.ok) {
147
- throw new NetworkError('Fetch Failure', text);
148
- }
149
- Diagnostics_1.Diagnostics.mark('_sendRequest:response-received', {
150
- status: response.status,
151
- contentLength: response.headers.get('content-length'),
152
- });
153
- return [2 /*return*/, text];
154
- case 4:
155
- error_1 = _a.sent();
156
- errorMessage = _getErrorMessage(controller, error_1);
157
- Diagnostics_1.Diagnostics.mark('_sendRequest:error', {
158
- error: errorMessage,
159
- status: response === null || response === void 0 ? void 0 : response.status,
160
- contentLength: response === null || response === void 0 ? void 0 : response.headers.get('content-length'),
161
- });
162
- if (!retries || retries <= 0) {
163
- Log_1.Log.error('A networking error occured.', errorMessage);
164
- return [2 /*return*/, null];
165
- }
166
- return [2 /*return*/, this._sendRequest(__assign(__assign({}, args), { retries: retries - 1 }))];
167
- case 5: return [2 /*return*/];
47
+ }
48
+ _sendRequest(args) {
49
+ var _a;
50
+ return __awaiter(this, void 0, void 0, function* () {
51
+ const { method, body, retries } = args;
52
+ const controller = new AbortController();
53
+ const handle = setTimeout(() => controller.abort(`Timeout of ${this._timeout}ms expired.`), this._timeout);
54
+ const url = this._getPopulatedURL(args);
55
+ let response = null;
56
+ try {
57
+ response = yield fetch(url, {
58
+ method,
59
+ body,
60
+ headers: Object.assign({}, args.headers),
61
+ signal: controller.signal,
62
+ });
63
+ clearTimeout(handle);
64
+ if (!response.ok) {
65
+ const text = yield response.text().catch(() => 'No Text');
66
+ const err = new Error(`Failed to fetch: ${url} ${text}`);
67
+ err.name = 'NetworkError';
68
+ throw err;
168
69
  }
169
- });
70
+ const text = yield response.text();
71
+ Diagnostics_1.Diagnostics.mark('_sendRequest:response-received', {
72
+ status: response.status,
73
+ contentLength: response.headers.get('content-length'),
74
+ });
75
+ return {
76
+ body: text,
77
+ code: response.status,
78
+ };
79
+ }
80
+ catch (error) {
81
+ const errorMessage = _getErrorMessage(controller, error);
82
+ Diagnostics_1.Diagnostics.mark('_sendRequest:error', {
83
+ error: errorMessage,
84
+ status: response === null || response === void 0 ? void 0 : response.status,
85
+ contentLength: response === null || response === void 0 ? void 0 : response.headers.get('content-length'),
86
+ });
87
+ if (!retries || retries <= 0) {
88
+ (_a = this._emitter) === null || _a === void 0 ? void 0 : _a.call(this, { name: 'error', error });
89
+ Log_1.Log.error(`A networking error occured during ${method} request to ${url}.`, errorMessage, error);
90
+ return null;
91
+ }
92
+ return this._sendRequest(Object.assign(Object.assign({}, args), { retries: retries - 1 }));
93
+ }
170
94
  });
171
- };
172
- 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();
181
- };
182
- return NetworkCore;
183
- }());
95
+ }
96
+ _getPopulatedURL(args) {
97
+ const metadata = StatsigMetadata_1.StatsigMetadataProvider.get();
98
+ const params = Object.assign({ k: args.sdkKey, st: metadata.sdkType, sv: metadata.sdkVersion, t: String(Date.now()), sid: SessionID_1.SessionID.get(args.sdkKey) }, args.params);
99
+ const query = Object.entries(params)
100
+ .map(([key, value]) => {
101
+ return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
102
+ })
103
+ .join('&');
104
+ return `${args.url}${query ? `?${query}` : ''}`;
105
+ }
106
+ _getPopulatedBody(args) {
107
+ return __awaiter(this, void 0, void 0, function* () {
108
+ const { data } = args;
109
+ const stableID = yield StableID_1.StableID.get(args.sdkKey);
110
+ const sessionID = SessionID_1.SessionID.get(args.sdkKey);
111
+ return JSON.stringify(Object.assign(Object.assign({}, data), { statsigMetadata: Object.assign(Object.assign({}, StatsigMetadata_1.StatsigMetadataProvider.get()), { stableID,
112
+ sessionID }) }));
113
+ });
114
+ }
115
+ }
184
116
  exports.NetworkCore = NetworkCore;
185
117
  function _getErrorMessage(controller, error) {
186
118
  if (controller.signal.aborted &&
@@ -191,7 +123,7 @@ function _getErrorMessage(controller, error) {
191
123
  return error;
192
124
  }
193
125
  if (error instanceof Error) {
194
- return "".concat(error.name, ": ").concat(error.message);
126
+ return `${error.name}: ${error.message}`;
195
127
  }
196
128
  return null;
197
129
  }
@@ -0,0 +1,16 @@
1
+ import { DynamicConfigEvaluationOptions, ExperimentEvaluationOptions, FeatureGateEvaluationOptions, LayerEvaluationOptions } from './EvaluationOptions';
2
+ import { DynamicConfig, Experiment, FeatureGate, Layer } from './StatsigTypes';
3
+ import { StatsigUser } from './StatsigUser';
4
+ export type OverrideAdapter = {
5
+ getGateOverride?(current: FeatureGate, user: StatsigUser, options?: FeatureGateEvaluationOptions): FeatureGate | null;
6
+ getDynamicConfigOverride?(current: DynamicConfig, user: StatsigUser, options?: DynamicConfigEvaluationOptions): DynamicConfig | null;
7
+ getExperimentOverride?(current: Experiment, user: StatsigUser, options?: ExperimentEvaluationOptions): Experiment | null;
8
+ getLayerOverride?(current: Layer, user: StatsigUser, options?: LayerEvaluationOptions): Layer | null;
9
+ };
10
+ export declare class CombinationOverrideAdapter implements OverrideAdapter {
11
+ readonly providers: OverrideAdapter[];
12
+ constructor(providers: OverrideAdapter[]);
13
+ getGateOverride(current: FeatureGate, user: StatsigUser): FeatureGate | null;
14
+ getDynamicConfigOverride(current: DynamicConfig, user: StatsigUser): DynamicConfig | null;
15
+ private _getOverride;
16
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CombinationOverrideAdapter = void 0;
4
+ class CombinationOverrideAdapter {
5
+ constructor(providers) {
6
+ this.providers = providers;
7
+ }
8
+ getGateOverride(current, user) {
9
+ return this._getOverride((provider) => { var _a, _b; return (_b = (_a = provider.getGateOverride) === null || _a === void 0 ? void 0 : _a.call(provider, current, user)) !== null && _b !== void 0 ? _b : null; });
10
+ }
11
+ getDynamicConfigOverride(current, user) {
12
+ return this._getOverride((provider) => { var _a, _b; return (_b = (_a = provider.getDynamicConfigOverride) === null || _a === void 0 ? void 0 : _a.call(provider, current, user)) !== null && _b !== void 0 ? _b : null; });
13
+ }
14
+ _getOverride(fn) {
15
+ for (const provider of this.providers) {
16
+ const override = fn(provider);
17
+ if (override) {
18
+ return override;
19
+ }
20
+ }
21
+ return null;
22
+ }
23
+ }
24
+ exports.CombinationOverrideAdapter = CombinationOverrideAdapter;
package/src/SessionID.js CHANGED
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SessionID = void 0;
4
- var UUID_1 = require("./UUID");
5
- var SESSION_ID_MAP = {};
4
+ const UUID_1 = require("./UUID");
5
+ const SESSION_ID_MAP = {};
6
6
  exports.SessionID = {
7
- get: function (sdkKey) {
7
+ get: (sdkKey) => {
8
8
  if (SESSION_ID_MAP[sdkKey] == null) {
9
9
  SESSION_ID_MAP[sdkKey] = (0, UUID_1.getUUID)();
10
10
  }
package/src/StableID.js CHANGED
@@ -8,71 +8,42 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
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
11
  Object.defineProperty(exports, "__esModule", { value: true });
39
12
  exports.StableID = void 0;
40
- var Hashing_1 = require("./Hashing");
41
- var Log_1 = require("./Log");
42
- var StorageProvider_1 = require("./StorageProvider");
43
- var UUID_1 = require("./UUID");
44
- var PROMISE_MAP = {};
13
+ const Hashing_1 = require("./Hashing");
14
+ const Log_1 = require("./Log");
15
+ const StorageProvider_1 = require("./StorageProvider");
16
+ const UUID_1 = require("./UUID");
17
+ const PROMISE_MAP = {};
45
18
  exports.StableID = {
46
- get: function (sdkKey) { return __awaiter(void 0, void 0, void 0, function () {
47
- return __generator(this, function (_a) {
48
- if (PROMISE_MAP[sdkKey] == null) {
49
- PROMISE_MAP[sdkKey] = _loadFromStorage(sdkKey).then(function (stableID) {
50
- if (stableID != null) {
51
- return stableID;
52
- }
53
- var newStableID = (0, UUID_1.getUUID)();
54
- _persistToStorage(newStableID, sdkKey);
55
- return newStableID;
56
- });
57
- }
58
- return [2 /*return*/, PROMISE_MAP[sdkKey]];
59
- });
60
- }); },
61
- setOverride: function (override, sdkKey) {
19
+ get: (sdkKey) => __awaiter(void 0, void 0, void 0, function* () {
20
+ if (PROMISE_MAP[sdkKey] == null) {
21
+ PROMISE_MAP[sdkKey] = _loadFromStorage(sdkKey).then((stableID) => {
22
+ if (stableID != null) {
23
+ return stableID;
24
+ }
25
+ const newStableID = (0, UUID_1.getUUID)();
26
+ _persistToStorage(newStableID, sdkKey);
27
+ return newStableID;
28
+ });
29
+ }
30
+ return PROMISE_MAP[sdkKey];
31
+ }),
32
+ setOverride: (override, sdkKey) => {
62
33
  PROMISE_MAP[sdkKey] = Promise.resolve(override);
63
34
  _persistToStorage(override, sdkKey);
64
35
  },
65
36
  };
66
37
  function _getStableIDStorageKey(sdkKey) {
67
- return "STATSIG_STABLE_ID:".concat((0, Hashing_1.DJB2)(sdkKey));
38
+ return `statsig.stable_id.${(0, Hashing_1.DJB2)(sdkKey)}`;
68
39
  }
69
40
  function _persistToStorage(stableID, sdkKey) {
70
- var storageKey = _getStableIDStorageKey(sdkKey);
71
- (0, StorageProvider_1.setObjectInStorage)(storageKey, stableID).catch(function () {
41
+ const storageKey = _getStableIDStorageKey(sdkKey);
42
+ (0, StorageProvider_1.setObjectInStorage)(storageKey, stableID).catch(() => {
72
43
  Log_1.Log.warn('Failed to save StableID');
73
44
  });
74
45
  }
75
46
  function _loadFromStorage(sdkKey) {
76
- var storageKey = _getStableIDStorageKey(sdkKey);
47
+ const storageKey = _getStableIDStorageKey(sdkKey);
77
48
  return (0, StorageProvider_1.getObjectFromStorage)(storageKey);
78
49
  }
@@ -1,37 +1,28 @@
1
1
  import './$_StatsigGlobal';
2
2
  import { ErrorBoundary } from './ErrorBoundary';
3
+ import { EvaluationOptionsCommon } from './EvaluationOptions';
3
4
  import { EventLogger } from './EventLogger';
4
5
  import { NetworkCore } from './NetworkCore';
5
- import { StatsigClientEvent, StatsigClientEventCallback, StatsigClientEventData, StatsigClientEventEmitterInterface, StatsigLoadingStatus } from './StatsigClientEventEmitter';
6
- import { DataSource, StatsigDataProvider } from './StatsigDataProvider';
6
+ import { OverrideAdapter } from './OverrideAdapter';
7
+ import { StatsigClientEvent, StatsigClientEventCallback, StatsigClientEventEmitterInterface, StatsigClientEventName, StatsigLoadingStatus } from './StatsigClientEventEmitter';
8
+ import { DataAdapterResult, EvaluationsDataAdapter, SpecsDataAdapter } from './StatsigDataAdapter';
7
9
  import { StatsigEventInternal } from './StatsigEvent';
8
- import { StatsigOptionsCommon } from './StatsigOptionsCommon';
9
- import { StatsigUser } from './StatsigUser';
10
- type DataProviderResult = {
11
- data: string | null;
12
- source: DataSource;
13
- };
14
- export type EvaluationOptions = {
15
- disableExposureLog?: boolean;
16
- };
17
- export declare const DEFAULT_EVAL_OPTIONS: EvaluationOptions;
18
- export type StatsigClientEmitEventFunc = (data: StatsigClientEventData) => void;
19
- export declare class StatsigClientBase implements StatsigClientEventEmitterInterface {
10
+ import { StatsigOptionsCommon, StatsigRuntimeMutableOptions } from './StatsigOptionsCommon';
11
+ export type StatsigClientEmitEventFunc = (event: StatsigClientEvent) => void;
12
+ export declare abstract class StatsigClientBase<TAdapter extends EvaluationsDataAdapter | SpecsDataAdapter> implements StatsigClientEventEmitterInterface {
13
+ protected readonly _sdkKey: string;
20
14
  loadingStatus: StatsigLoadingStatus;
21
- protected _errorBoundary: ErrorBoundary;
22
- protected _logger: EventLogger;
23
- protected _sdkKey: string;
24
- protected _dataProviders: StatsigDataProvider[];
15
+ readonly dataAdapter: TAdapter;
16
+ protected readonly _errorBoundary: ErrorBoundary;
17
+ protected readonly _logger: EventLogger;
18
+ protected readonly _overrideAdapter: OverrideAdapter | null;
25
19
  private _listeners;
26
- constructor(sdkKey: string, network: NetworkCore, options: StatsigOptionsCommon | null, dataProviders: StatsigDataProvider[]);
27
- on(event: StatsigClientEvent | '*', listener: StatsigClientEventCallback): void;
28
- off(event: StatsigClientEvent | '*', listener: StatsigClientEventCallback): void;
29
- 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;
35
- protected _enqueueExposure(options: EvaluationOptions, exposure: StatsigEventInternal): void;
20
+ constructor(_sdkKey: string, adapter: TAdapter, network: NetworkCore, options: StatsigOptionsCommon | null);
21
+ updateRuntimeOptions(options: StatsigRuntimeMutableOptions): void;
22
+ flush(): Promise<void>;
23
+ on<T extends StatsigClientEventName>(event: T, listener: StatsigClientEventCallback<T>): void;
24
+ off<T extends StatsigClientEventName>(event: T, listener: StatsigClientEventCallback<T>): void;
25
+ protected _emit(event: StatsigClientEvent): void;
26
+ protected _setStatus(newStatus: StatsigLoadingStatus, values: DataAdapterResult | null): void;
27
+ protected _enqueueExposure(name: string, exposure: StatsigEventInternal, options?: EvaluationOptionsCommon): void;
36
28
  }
37
- export {};