@statsig/client-core 0.0.1-beta.4 → 0.0.1-beta.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -4
- package/package.json +1 -1
- package/src/$_StatsigGlobal.d.ts +8 -1
- package/src/$_StatsigGlobal.js +22 -12
- package/src/ClientInterfaces.d.ts +50 -14
- package/src/DataAdapterCore.d.ts +30 -0
- package/src/DataAdapterCore.js +169 -0
- package/src/Diagnostics.d.ts +1 -3
- package/src/Diagnostics.js +4 -49
- package/src/DownloadConfigSpecsResponse.d.ts +41 -0
- package/src/ErrorBoundary.d.ts +7 -2
- package/src/ErrorBoundary.js +79 -87
- package/src/EvaluationOptions.d.ts +20 -0
- package/src/EvaluationOptions.js +2 -0
- package/src/EvaluationTypes.d.ts +39 -0
- package/src/EvaluationTypes.js +2 -0
- package/src/EventLogger.d.ts +20 -9
- package/src/EventLogger.js +216 -232
- package/src/Hashing.d.ts +2 -1
- package/src/Hashing.js +25 -6
- package/src/InitializeResponse.d.ts +18 -0
- package/src/InitializeResponse.js +2 -0
- package/src/Log.js +15 -34
- package/src/NetworkConfig.d.ts +18 -0
- package/src/NetworkConfig.js +18 -0
- package/src/NetworkCore.d.ts +19 -6
- package/src/NetworkCore.js +137 -167
- package/src/OverrideAdapter.d.ts +9 -0
- package/src/OverrideAdapter.js +2 -0
- package/src/SDKType.d.ts +8 -0
- package/src/SDKType.js +19 -0
- package/src/SafeJs.d.ts +6 -0
- package/src/SafeJs.js +41 -0
- package/src/SessionID.d.ts +17 -1
- package/src/SessionID.js +89 -8
- package/src/StableID.js +24 -53
- package/src/StatsigClientBase.d.ts +57 -28
- package/src/StatsigClientBase.js +115 -238
- package/src/StatsigClientEventEmitter.d.ts +69 -28
- package/src/StatsigDataAdapter.d.ts +107 -0
- package/src/StatsigDataAdapter.js +4 -0
- package/src/StatsigEvent.d.ts +10 -19
- package/src/StatsigEvent.js +50 -41
- package/src/StatsigMetadata.d.ts +1 -1
- package/src/StatsigMetadata.js +7 -18
- package/src/StatsigOptionsCommon.d.ts +85 -17
- package/src/StatsigTypeFactories.d.ts +6 -0
- package/src/StatsigTypeFactories.js +50 -0
- package/src/StatsigTypes.d.ts +29 -18
- package/src/StatsigTypes.js +0 -29
- package/src/StatsigUser.d.ts +2 -5
- package/src/StatsigUser.js +10 -18
- package/src/StorageProvider.d.ts +13 -8
- package/src/StorageProvider.js +77 -73
- 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/VisibilityObserving.d.ts +8 -0
- package/src/VisibilityObserving.js +30 -0
- package/src/index.d.ts +20 -5
- package/src/index.js +30 -18
- package/src/Monitoring.d.ts +0 -3
- package/src/Monitoring.js +0 -33
- package/src/StatsigDataProvider.d.ts +0 -9
- package/src/VisibilityChangeObserver.d.ts +0 -13
- package/src/VisibilityChangeObserver.js +0 -48
- package/src/__tests__/MockLocalStorage.d.ts +0 -9
- package/src/__tests__/MockLocalStorage.js +0 -37
- /package/src/{StatsigDataProvider.js → DownloadConfigSpecsResponse.js} +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NetworkParam = exports.NetworkDefault = void 0;
|
|
4
|
+
exports.NetworkDefault = {
|
|
5
|
+
eventsApi: 'https://prodregistryv2.org/v1',
|
|
6
|
+
initializeApi: 'https://featureassets.org/v1',
|
|
7
|
+
specsApi: 'https://assetsconfigcdn.org/v1',
|
|
8
|
+
};
|
|
9
|
+
var NetworkParam;
|
|
10
|
+
(function (NetworkParam) {
|
|
11
|
+
NetworkParam["EventCount"] = "ec";
|
|
12
|
+
NetworkParam["SdkKey"] = "k";
|
|
13
|
+
NetworkParam["SdkType"] = "st";
|
|
14
|
+
NetworkParam["SdkVersion"] = "sv";
|
|
15
|
+
NetworkParam["Time"] = "t";
|
|
16
|
+
NetworkParam["SessionID"] = "sid";
|
|
17
|
+
NetworkParam["StatsigEncoded"] = "se";
|
|
18
|
+
})(NetworkParam || (exports.NetworkParam = NetworkParam = {}));
|
package/src/NetworkCore.d.ts
CHANGED
|
@@ -1,22 +1,35 @@
|
|
|
1
|
-
import
|
|
1
|
+
import './$_StatsigGlobal';
|
|
2
|
+
import { NetworkPriority } from './NetworkConfig';
|
|
3
|
+
import { StatsigClientEmitEventFunc } from './StatsigClientBase';
|
|
4
|
+
import { AnyStatsigOptions } from './StatsigOptionsCommon';
|
|
2
5
|
type RequestArgs = {
|
|
3
6
|
sdkKey: string;
|
|
4
7
|
url: string;
|
|
5
|
-
|
|
8
|
+
priority?: NetworkPriority;
|
|
6
9
|
retries?: number;
|
|
10
|
+
params?: Record<string, string>;
|
|
7
11
|
headers?: Record<string, string>;
|
|
8
12
|
};
|
|
9
13
|
type RequestArgsWithData = RequestArgs & {
|
|
10
14
|
data: Record<string, unknown>;
|
|
15
|
+
isStatsigEncodable?: boolean;
|
|
16
|
+
};
|
|
17
|
+
type NetworkResponse = {
|
|
18
|
+
body: string | null;
|
|
19
|
+
code: number;
|
|
11
20
|
};
|
|
12
21
|
export declare class NetworkCore {
|
|
13
22
|
private _options;
|
|
23
|
+
private _emitter?;
|
|
14
24
|
private readonly _timeout;
|
|
15
|
-
constructor(_options:
|
|
16
|
-
post(args: RequestArgsWithData): Promise<
|
|
17
|
-
get(args: RequestArgs): Promise<
|
|
18
|
-
|
|
25
|
+
constructor(_options: AnyStatsigOptions | null, _emitter?: StatsigClientEmitEventFunc | undefined);
|
|
26
|
+
post(args: RequestArgsWithData): Promise<NetworkResponse | null>;
|
|
27
|
+
get(args: RequestArgs): Promise<NetworkResponse | null>;
|
|
28
|
+
isBeaconSupported(): boolean;
|
|
29
|
+
beacon(args: RequestArgsWithData): Promise<boolean>;
|
|
19
30
|
private _sendRequest;
|
|
20
31
|
private _getPopulatedURL;
|
|
32
|
+
private _getPopulatedBody;
|
|
33
|
+
private _attemptToEncodeString;
|
|
21
34
|
}
|
|
22
35
|
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,154 +8,150 @@ 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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return NetworkError;
|
|
80
|
-
}(Error));
|
|
81
|
-
var NetworkCore = /** @class */ (function () {
|
|
82
|
-
function NetworkCore(_options) {
|
|
83
|
-
var _a;
|
|
13
|
+
require("./$_StatsigGlobal");
|
|
14
|
+
const Diagnostics_1 = require("./Diagnostics");
|
|
15
|
+
const Log_1 = require("./Log");
|
|
16
|
+
const NetworkConfig_1 = require("./NetworkConfig");
|
|
17
|
+
const SDKType_1 = require("./SDKType");
|
|
18
|
+
const SafeJs_1 = require("./SafeJs");
|
|
19
|
+
const SessionID_1 = require("./SessionID");
|
|
20
|
+
const StableID_1 = require("./StableID");
|
|
21
|
+
const StatsigMetadata_1 = require("./StatsigMetadata");
|
|
22
|
+
const DEFAULT_TIMEOUT_MS = 10000;
|
|
23
|
+
class NetworkCore {
|
|
24
|
+
constructor(_options, _emitter) {
|
|
25
|
+
var _a, _b;
|
|
84
26
|
this._options = _options;
|
|
85
|
-
this.
|
|
27
|
+
this._emitter = _emitter;
|
|
28
|
+
this._timeout =
|
|
29
|
+
(_b = (_a = _options === null || _options === void 0 ? void 0 : _options.networkConfig) === null || _a === void 0 ? void 0 : _a.networkTimeoutMs) !== null && _b !== void 0 ? _b : DEFAULT_TIMEOUT_MS;
|
|
86
30
|
}
|
|
87
|
-
|
|
88
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
89
|
-
|
|
90
|
-
return
|
|
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
|
-
});
|
|
31
|
+
post(args) {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
const body = yield this._getPopulatedBody(args);
|
|
34
|
+
return this._sendRequest(Object.assign({ method: 'POST', body: this._attemptToEncodeString(args, body) }, args));
|
|
102
35
|
});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
36
|
+
}
|
|
37
|
+
get(args) {
|
|
38
|
+
return this._sendRequest(Object.assign({ method: 'GET' }, args));
|
|
39
|
+
}
|
|
40
|
+
isBeaconSupported() {
|
|
41
|
+
return (typeof navigator !== 'undefined' &&
|
|
42
|
+
typeof (navigator === null || navigator === void 0 ? void 0 : navigator.sendBeacon) === 'function');
|
|
43
|
+
}
|
|
44
|
+
beacon(args) {
|
|
45
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
46
|
+
if (!_ensureValidSdkKey(args)) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
const url = yield this._getPopulatedURL(args);
|
|
50
|
+
const body = yield this._getPopulatedBody(args);
|
|
51
|
+
return navigator.sendBeacon(url, body);
|
|
109
52
|
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
var
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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*/];
|
|
53
|
+
}
|
|
54
|
+
_sendRequest(args) {
|
|
55
|
+
var _a, _b, _c, _d, _e, _f;
|
|
56
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
+
if (!_ensureValidSdkKey(args)) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
if ((_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.networkConfig) === null || _b === void 0 ? void 0 : _b.preventAllNetworkTraffic) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const { method, body, retries } = args;
|
|
64
|
+
const controller = new AbortController();
|
|
65
|
+
const handle = setTimeout(() => controller.abort(`Timeout of ${this._timeout}ms expired.`), this._timeout);
|
|
66
|
+
const url = yield this._getPopulatedURL(args);
|
|
67
|
+
let response = null;
|
|
68
|
+
try {
|
|
69
|
+
const config = {
|
|
70
|
+
method,
|
|
71
|
+
body,
|
|
72
|
+
headers: Object.assign({}, args.headers),
|
|
73
|
+
signal: controller.signal,
|
|
74
|
+
priority: args.priority,
|
|
75
|
+
keepalive: true,
|
|
76
|
+
};
|
|
77
|
+
const func = (_e = (_d = (_c = this._options) === null || _c === void 0 ? void 0 : _c.networkConfig) === null || _d === void 0 ? void 0 : _d.networkOverrideFunc) !== null && _e !== void 0 ? _e : fetch;
|
|
78
|
+
response = yield func(url, config);
|
|
79
|
+
clearTimeout(handle);
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
const text = yield response.text().catch(() => 'No Text');
|
|
82
|
+
const err = new Error(`Failed to fetch: ${url} ${text}`);
|
|
83
|
+
err.name = 'NetworkError';
|
|
84
|
+
throw err;
|
|
168
85
|
}
|
|
169
|
-
|
|
86
|
+
const text = yield response.text();
|
|
87
|
+
Diagnostics_1.Diagnostics.mark();
|
|
88
|
+
return {
|
|
89
|
+
body: text,
|
|
90
|
+
code: response.status,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
const errorMessage = _getErrorMessage(controller, error);
|
|
95
|
+
Diagnostics_1.Diagnostics.mark();
|
|
96
|
+
if (!retries || retries <= 0) {
|
|
97
|
+
(_f = this._emitter) === null || _f === void 0 ? void 0 : _f.call(this, { name: 'error', error });
|
|
98
|
+
Log_1.Log.error(`A networking error occured during ${method} request to ${url}.`, errorMessage, error);
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
return this._sendRequest(Object.assign(Object.assign({}, args), { retries: retries - 1 }));
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
_getPopulatedURL(args) {
|
|
106
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
107
|
+
const params = Object.assign({ [NetworkConfig_1.NetworkParam.SdkKey]: args.sdkKey, [NetworkConfig_1.NetworkParam.SdkType]: SDKType_1.SDKType._get(args.sdkKey), [NetworkConfig_1.NetworkParam.SdkVersion]: StatsigMetadata_1.SDK_VERSION, [NetworkConfig_1.NetworkParam.Time]: String(Date.now()), [NetworkConfig_1.NetworkParam.SessionID]: yield SessionID_1.SessionID.get(args.sdkKey) }, args.params);
|
|
108
|
+
const query = Object.entries(params)
|
|
109
|
+
.map(([key, value]) => {
|
|
110
|
+
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
|
111
|
+
})
|
|
112
|
+
.join('&');
|
|
113
|
+
return `${args.url}${query ? `?${query}` : ''}`;
|
|
170
114
|
});
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
115
|
+
}
|
|
116
|
+
_getPopulatedBody(args) {
|
|
117
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
118
|
+
const { data, sdkKey } = args;
|
|
119
|
+
const stableID = yield StableID_1.StableID.get(sdkKey);
|
|
120
|
+
const sessionID = yield SessionID_1.SessionID.get(sdkKey);
|
|
121
|
+
const sdkType = SDKType_1.SDKType._get(sdkKey);
|
|
122
|
+
return JSON.stringify(Object.assign(Object.assign({}, data), { statsigMetadata: Object.assign(Object.assign({}, StatsigMetadata_1.StatsigMetadataProvider.get()), { stableID,
|
|
123
|
+
sessionID,
|
|
124
|
+
sdkType }) }));
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
_attemptToEncodeString(args, input) {
|
|
128
|
+
var _a, _b, _c;
|
|
129
|
+
const win = (0, SafeJs_1._getWindowSafe)();
|
|
130
|
+
if (!(win === null || win === void 0 ? void 0 : win.btoa) ||
|
|
131
|
+
(__STATSIG__ === null || __STATSIG__ === void 0 ? void 0 : __STATSIG__['no-encode']) != null ||
|
|
132
|
+
((_a = this._options) === null || _a === void 0 ? void 0 : _a.disableStatsigEncoding) ||
|
|
133
|
+
!args.isStatsigEncodable) {
|
|
134
|
+
return input;
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const result = (_b = win.btoa(input).split('').reverse().join('')) !== null && _b !== void 0 ? _b : input;
|
|
138
|
+
args.params = Object.assign(Object.assign({}, ((_c = args.params) !== null && _c !== void 0 ? _c : {})), { [NetworkConfig_1.NetworkParam.StatsigEncoded]: '1' });
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
catch (_d) {
|
|
142
|
+
Log_1.Log.warn('/initialize request encoding failed');
|
|
143
|
+
return input;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
184
147
|
exports.NetworkCore = NetworkCore;
|
|
148
|
+
const _ensureValidSdkKey = (args) => {
|
|
149
|
+
if (!args.sdkKey) {
|
|
150
|
+
Log_1.Log.warn('Unable to make request without an SDK key');
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
return true;
|
|
154
|
+
};
|
|
185
155
|
function _getErrorMessage(controller, error) {
|
|
186
156
|
if (controller.signal.aborted &&
|
|
187
157
|
typeof controller.signal.reason === 'string') {
|
|
@@ -191,7 +161,7 @@ function _getErrorMessage(controller, error) {
|
|
|
191
161
|
return error;
|
|
192
162
|
}
|
|
193
163
|
if (error instanceof Error) {
|
|
194
|
-
return
|
|
164
|
+
return `${error.name}: ${error.message}`;
|
|
195
165
|
}
|
|
196
|
-
return
|
|
166
|
+
return 'Unknown Error';
|
|
197
167
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
};
|
package/src/SDKType.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type ClientType = 'javascript-client' | 'js-on-device-eval-client';
|
|
2
|
+
type BindingType = 'expo' | 'rn' | 'react';
|
|
3
|
+
export declare const SDKType: {
|
|
4
|
+
_get: (sdkKey: string) => string;
|
|
5
|
+
_setClientType(sdkKey: string, client: ClientType): void;
|
|
6
|
+
_setBindingType(binding: BindingType): void;
|
|
7
|
+
};
|
|
8
|
+
export {};
|
package/src/SDKType.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SDKType = void 0;
|
|
4
|
+
const SDK_CLIENT = {};
|
|
5
|
+
let suffix;
|
|
6
|
+
exports.SDKType = {
|
|
7
|
+
_get: (sdkKey) => {
|
|
8
|
+
var _a;
|
|
9
|
+
return ((_a = SDK_CLIENT[sdkKey]) !== null && _a !== void 0 ? _a : 'js-mono') + (suffix !== null && suffix !== void 0 ? suffix : '');
|
|
10
|
+
},
|
|
11
|
+
_setClientType(sdkKey, client) {
|
|
12
|
+
SDK_CLIENT[sdkKey] = client;
|
|
13
|
+
},
|
|
14
|
+
_setBindingType(binding) {
|
|
15
|
+
if (!suffix || suffix === '-react') {
|
|
16
|
+
suffix = '-' + binding;
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
};
|
package/src/SafeJs.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const _getWindowSafe: () => Window | null;
|
|
2
|
+
export declare const _getDocumentSafe: () => Document | null;
|
|
3
|
+
export declare const _isBrowserEnv: () => boolean;
|
|
4
|
+
export declare const _addWindowEventListenerSafe: (key: string, listener: () => void) => void;
|
|
5
|
+
export declare const _addDocumentEventListenerSafe: (key: string, listener: () => void) => void;
|
|
6
|
+
export declare const _getCurrentPageUrlSafe: () => string | undefined;
|
package/src/SafeJs.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports._getCurrentPageUrlSafe = exports._addDocumentEventListenerSafe = exports._addWindowEventListenerSafe = exports._isBrowserEnv = exports._getDocumentSafe = exports._getWindowSafe = void 0;
|
|
4
|
+
const _getWindowSafe = () => {
|
|
5
|
+
return typeof window !== 'undefined' ? window : null;
|
|
6
|
+
};
|
|
7
|
+
exports._getWindowSafe = _getWindowSafe;
|
|
8
|
+
const _getDocumentSafe = () => {
|
|
9
|
+
var _a;
|
|
10
|
+
const win = (0, exports._getWindowSafe)();
|
|
11
|
+
return (_a = win === null || win === void 0 ? void 0 : win.document) !== null && _a !== void 0 ? _a : null;
|
|
12
|
+
};
|
|
13
|
+
exports._getDocumentSafe = _getDocumentSafe;
|
|
14
|
+
const _isBrowserEnv = () => {
|
|
15
|
+
return (0, exports._getDocumentSafe)() != null;
|
|
16
|
+
};
|
|
17
|
+
exports._isBrowserEnv = _isBrowserEnv;
|
|
18
|
+
const _addWindowEventListenerSafe = (key, listener) => {
|
|
19
|
+
const win = (0, exports._getWindowSafe)();
|
|
20
|
+
if (typeof (win === null || win === void 0 ? void 0 : win.addEventListener) === 'function') {
|
|
21
|
+
win.addEventListener(key, listener);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
exports._addWindowEventListenerSafe = _addWindowEventListenerSafe;
|
|
25
|
+
const _addDocumentEventListenerSafe = (key, listener) => {
|
|
26
|
+
const doc = (0, exports._getDocumentSafe)();
|
|
27
|
+
if (typeof (doc === null || doc === void 0 ? void 0 : doc.addEventListener) === 'function') {
|
|
28
|
+
doc.addEventListener(key, listener);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
exports._addDocumentEventListenerSafe = _addDocumentEventListenerSafe;
|
|
32
|
+
const _getCurrentPageUrlSafe = () => {
|
|
33
|
+
var _a;
|
|
34
|
+
try {
|
|
35
|
+
return (_a = (0, exports._getWindowSafe)()) === null || _a === void 0 ? void 0 : _a.location.href.split(/[?#]/)[0];
|
|
36
|
+
}
|
|
37
|
+
catch (_b) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
exports._getCurrentPageUrlSafe = _getCurrentPageUrlSafe;
|
package/src/SessionID.d.ts
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
type SessionTimeoutID = ReturnType<typeof setTimeout>;
|
|
2
|
+
type SessionData = {
|
|
3
|
+
sessionID: string;
|
|
4
|
+
startTime: number;
|
|
5
|
+
lastUpdate: number;
|
|
6
|
+
};
|
|
7
|
+
export type StatsigSession = {
|
|
8
|
+
data: SessionData;
|
|
9
|
+
sdkKey: string;
|
|
10
|
+
ageTimeoutID?: SessionTimeoutID;
|
|
11
|
+
idleTimeoutID?: SessionTimeoutID;
|
|
12
|
+
};
|
|
1
13
|
export declare const SessionID: {
|
|
2
|
-
get: (sdkKey: string) => string
|
|
14
|
+
get: (sdkKey: string) => Promise<string>;
|
|
15
|
+
};
|
|
16
|
+
export declare const StatsigSession: {
|
|
17
|
+
get: (sdkKey: string) => Promise<StatsigSession>;
|
|
3
18
|
};
|
|
19
|
+
export {};
|
package/src/SessionID.js
CHANGED
|
@@ -1,13 +1,94 @@
|
|
|
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
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SessionID = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
12
|
+
exports.StatsigSession = exports.SessionID = void 0;
|
|
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 MAX_SESSION_IDLE_TIME = 30 * 60 * 1000; // 30 minutes
|
|
18
|
+
const MAX_SESSION_AGE = 4 * 60 * 60 * 1000; // 4 hours
|
|
19
|
+
const PROMISE_MAP = {};
|
|
6
20
|
exports.SessionID = {
|
|
7
|
-
get: function (
|
|
8
|
-
|
|
9
|
-
|
|
21
|
+
get: (sdkKey) => __awaiter(void 0, void 0, void 0, function* () {
|
|
22
|
+
return exports.StatsigSession.get(sdkKey).then((x) => x.data.sessionID);
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
exports.StatsigSession = {
|
|
26
|
+
get: (sdkKey) => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
if (PROMISE_MAP[sdkKey] == null) {
|
|
28
|
+
PROMISE_MAP[sdkKey] = _loadSession(sdkKey);
|
|
10
29
|
}
|
|
11
|
-
|
|
12
|
-
|
|
30
|
+
const session = yield PROMISE_MAP[sdkKey];
|
|
31
|
+
return _bumpSession(session);
|
|
32
|
+
}),
|
|
13
33
|
};
|
|
34
|
+
function _loadSession(sdkKey) {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
let data = yield _loadFromStorage(sdkKey);
|
|
37
|
+
const now = Date.now();
|
|
38
|
+
if (!data) {
|
|
39
|
+
data = {
|
|
40
|
+
sessionID: (0, UUID_1.getUUID)(),
|
|
41
|
+
startTime: now,
|
|
42
|
+
lastUpdate: now,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
data,
|
|
47
|
+
sdkKey,
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function _bumpSession(session) {
|
|
52
|
+
const now = Date.now();
|
|
53
|
+
const data = session.data;
|
|
54
|
+
if (_isIdle(data) || _hasRunTooLong(data)) {
|
|
55
|
+
data.sessionID = (0, UUID_1.getUUID)();
|
|
56
|
+
data.startTime = now;
|
|
57
|
+
}
|
|
58
|
+
data.lastUpdate = now;
|
|
59
|
+
_persistToStorage(data, session.sdkKey);
|
|
60
|
+
clearTimeout(session.idleTimeoutID);
|
|
61
|
+
clearTimeout(session.ageTimeoutID);
|
|
62
|
+
const lifetime = now - data.startTime;
|
|
63
|
+
const sdkKey = session.sdkKey;
|
|
64
|
+
session.idleTimeoutID = _createSessionTimeout(sdkKey, MAX_SESSION_IDLE_TIME);
|
|
65
|
+
session.ageTimeoutID = _createSessionTimeout(sdkKey, MAX_SESSION_AGE - lifetime);
|
|
66
|
+
return session;
|
|
67
|
+
}
|
|
68
|
+
function _createSessionTimeout(sdkKey, duration) {
|
|
69
|
+
return setTimeout(() => {
|
|
70
|
+
const client = __STATSIG__ === null || __STATSIG__ === void 0 ? void 0 : __STATSIG__.instance(sdkKey);
|
|
71
|
+
if (client) {
|
|
72
|
+
client.$emt({ name: 'session_expired' });
|
|
73
|
+
}
|
|
74
|
+
}, duration);
|
|
75
|
+
}
|
|
76
|
+
function _isIdle({ lastUpdate }) {
|
|
77
|
+
return Date.now() - lastUpdate > MAX_SESSION_IDLE_TIME;
|
|
78
|
+
}
|
|
79
|
+
function _hasRunTooLong({ startTime }) {
|
|
80
|
+
return Date.now() - startTime > MAX_SESSION_AGE;
|
|
81
|
+
}
|
|
82
|
+
function _getSessionIDStorageKey(sdkKey) {
|
|
83
|
+
return `statsig.session_id.${(0, Hashing_1.DJB2)(sdkKey)}`;
|
|
84
|
+
}
|
|
85
|
+
function _persistToStorage(session, sdkKey) {
|
|
86
|
+
const storageKey = _getSessionIDStorageKey(sdkKey);
|
|
87
|
+
(0, StorageProvider_1._setObjectInStorage)(storageKey, session).catch(() => {
|
|
88
|
+
Log_1.Log.warn('Failed to save SessionID');
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function _loadFromStorage(sdkKey) {
|
|
92
|
+
const storageKey = _getSessionIDStorageKey(sdkKey);
|
|
93
|
+
return (0, StorageProvider_1._getObjectFromStorage)(storageKey);
|
|
94
|
+
}
|