@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.
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/$_StatsigGlobal.d.ts +2 -1
- package/src/$_StatsigGlobal.js +10 -12
- package/src/ClientInterfaces.d.ts +20 -13
- package/src/DataAdapterCore.d.ts +32 -0
- package/src/DataAdapterCore.js +167 -0
- package/src/Diagnostics.js +21 -26
- package/src/ErrorBoundary.d.ts +1 -0
- package/src/ErrorBoundary.js +39 -86
- package/src/EvaluationOptions.d.ts +20 -0
- package/src/EvaluationTypes.d.ts +39 -0
- package/src/EvaluationTypes.js +2 -0
- package/src/EventLogger.d.ts +17 -4
- package/src/EventLogger.js +186 -225
- package/src/Hashing.d.ts +1 -0
- package/src/Hashing.js +23 -4
- package/src/Log.js +15 -34
- package/src/Monitoring.d.ts +1 -2
- package/src/Monitoring.js +68 -27
- package/src/NetworkCore.d.ts +13 -5
- package/src/NetworkCore.js +96 -164
- package/src/OverrideAdapter.d.ts +16 -0
- package/src/OverrideAdapter.js +24 -0
- package/src/SessionID.js +3 -3
- package/src/StableID.js +23 -52
- package/src/StatsigClientBase.d.ts +20 -29
- package/src/StatsigClientBase.js +58 -248
- package/src/StatsigClientEventEmitter.d.ts +55 -28
- package/src/StatsigDataAdapter.d.ts +89 -0
- package/src/StatsigDataAdapter.js +4 -0
- package/src/StatsigEvent.d.ts +9 -18
- package/src/StatsigEvent.js +40 -31
- package/src/StatsigMetadata.js +5 -16
- package/src/StatsigOptionsCommon.d.ts +42 -12
- package/src/StatsigTypes.d.ts +23 -15
- package/src/StatsigTypes.js +23 -16
- package/src/StatsigUser.d.ts +1 -0
- package/src/StatsigUser.js +12 -20
- package/src/StorageProvider.d.ts +7 -2
- package/src/StorageProvider.js +53 -62
- package/src/TypedJsonParse.d.ts +8 -0
- package/src/TypedJsonParse.js +27 -0
- package/src/UUID.js +9 -5
- package/src/UrlOverrides.d.ts +1 -0
- package/src/UrlOverrides.js +15 -0
- package/src/UtitlityTypes.d.ts +3 -0
- package/src/UtitlityTypes.js +2 -0
- package/src/VisibilityChangeObserver.js +18 -24
- package/src/__tests__/MockLocalStorage.js +18 -19
- package/src/index.d.ts +12 -3
- package/src/index.js +18 -16
- package/src/StatsigDataProvider.d.ts +0 -9
- /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.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
function monitorClass(errorBoundary,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
30
|
-
|
|
31
|
-
|
|
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;
|
package/src/NetworkCore.d.ts
CHANGED
|
@@ -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<
|
|
17
|
-
get(args: RequestArgs): Promise<
|
|
18
|
-
|
|
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 {};
|
package/src/NetworkCore.js
CHANGED
|
@@ -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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
88
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
89
|
-
|
|
90
|
-
return
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
|
|
105
|
-
return
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
112
|
-
var
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
return
|
|
181
|
-
}
|
|
182
|
-
|
|
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
|
|
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
|
-
|
|
5
|
-
|
|
4
|
+
const UUID_1 = require("./UUID");
|
|
5
|
+
const SESSION_ID_MAP = {};
|
|
6
6
|
exports.SessionID = {
|
|
7
|
-
get:
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|
38
|
+
return `statsig.stable_id.${(0, Hashing_1.DJB2)(sdkKey)}`;
|
|
68
39
|
}
|
|
69
40
|
function _persistToStorage(stableID, sdkKey) {
|
|
70
|
-
|
|
71
|
-
(0, StorageProvider_1.setObjectInStorage)(storageKey, stableID).catch(
|
|
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
|
-
|
|
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 {
|
|
6
|
-
import {
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
22
|
-
protected
|
|
23
|
-
protected
|
|
24
|
-
protected
|
|
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(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
protected
|
|
32
|
-
protected
|
|
33
|
-
protected
|
|
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 {};
|