@statsig/client-core 0.0.1-beta.37 → 0.0.1-beta.39
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/package.json +1 -1
- package/src/DataAdapterCore.d.ts +2 -4
- package/src/DataAdapterCore.js +5 -6
- package/src/ErrorBoundary.d.ts +3 -1
- package/src/ErrorBoundary.js +8 -3
- package/src/NetworkConfig.d.ts +1 -0
- package/src/NetworkCore.d.ts +2 -0
- package/src/NetworkCore.js +23 -10
- package/src/SessionID.js +3 -7
- package/src/StatsigClientBase.js +1 -1
- package/src/StatsigDataAdapter.d.ts +11 -2
- package/src/StatsigMetadata.d.ts +1 -1
- package/src/StatsigMetadata.js +1 -1
- package/src/StatsigOptionsCommon.d.ts +4 -0
- package/src/StorageProvider.js +9 -8
package/package.json
CHANGED
package/src/DataAdapterCore.d.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { ErrorBoundary } from './ErrorBoundary';
|
|
2
1
|
import { DataAdapterAsyncOptions, DataAdapterResult } from './StatsigDataAdapter';
|
|
3
2
|
import { AnyStatsigOptions } from './StatsigOptionsCommon';
|
|
4
3
|
import { StatsigUser } from './StatsigUser';
|
|
5
4
|
export declare abstract class DataAdapterCore {
|
|
6
5
|
private _adapterName;
|
|
7
6
|
private _cacheSuffix;
|
|
8
|
-
protected _errorBoundary: ErrorBoundary | null;
|
|
9
7
|
private _sdkKey;
|
|
10
8
|
private _inMemoryCache;
|
|
11
9
|
private _lastModifiedStoreKey;
|
|
@@ -21,8 +19,8 @@ export declare abstract class DataAdapterCore {
|
|
|
21
19
|
__primeInMemoryCache(cache: Record<string, DataAdapterResult>): void;
|
|
22
20
|
protected _getDataAsyncImpl(current: DataAdapterResult | null, user?: StatsigUser, options?: DataAdapterAsyncOptions): Promise<DataAdapterResult | null>;
|
|
23
21
|
protected _prefetchDataImpl(user?: StatsigUser, options?: DataAdapterAsyncOptions): Promise<void>;
|
|
24
|
-
protected abstract _fetchFromNetwork(current: string | null, user?: StatsigUser): Promise<string | null>;
|
|
25
|
-
private
|
|
22
|
+
protected abstract _fetchFromNetwork(current: string | null, user?: StatsigUser, options?: DataAdapterAsyncOptions): Promise<string | null>;
|
|
23
|
+
private _fetchAndPrepFromNetwork;
|
|
26
24
|
protected _getSdkKey(): string;
|
|
27
25
|
protected _getCacheKey(user?: StatsigUser): string;
|
|
28
26
|
protected _addToInMemoryCache(cacheKey: string, result: DataAdapterResult): void;
|
package/src/DataAdapterCore.js
CHANGED
|
@@ -10,7 +10,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.DataAdapterCore = void 0;
|
|
13
|
-
const ErrorBoundary_1 = require("./ErrorBoundary");
|
|
14
13
|
const Log_1 = require("./Log");
|
|
15
14
|
const StatsigDataAdapter_1 = require("./StatsigDataAdapter");
|
|
16
15
|
const StatsigUser_1 = require("./StatsigUser");
|
|
@@ -21,14 +20,12 @@ class DataAdapterCore {
|
|
|
21
20
|
constructor(_adapterName, _cacheSuffix) {
|
|
22
21
|
this._adapterName = _adapterName;
|
|
23
22
|
this._cacheSuffix = _cacheSuffix;
|
|
24
|
-
this._errorBoundary = null;
|
|
25
23
|
this._sdkKey = null;
|
|
26
24
|
this._inMemoryCache = {};
|
|
27
25
|
this._lastModifiedStoreKey = `statsig.last_modified_time.${_cacheSuffix}`;
|
|
28
26
|
}
|
|
29
27
|
attach(sdkKey, _options) {
|
|
30
28
|
this._sdkKey = sdkKey;
|
|
31
|
-
this._errorBoundary = new ErrorBoundary_1.ErrorBoundary(sdkKey);
|
|
32
29
|
}
|
|
33
30
|
getDataSync(user) {
|
|
34
31
|
const cacheKey = this._getCacheKey(user);
|
|
@@ -63,7 +60,9 @@ class DataAdapterCore {
|
|
|
63
60
|
var _a;
|
|
64
61
|
return __awaiter(this, void 0, void 0, function* () {
|
|
65
62
|
const cache = current !== null && current !== void 0 ? current : this.getDataSync(user);
|
|
66
|
-
const ops = [
|
|
63
|
+
const ops = [
|
|
64
|
+
this._fetchAndPrepFromNetwork((_a = cache === null || cache === void 0 ? void 0 : cache.data) !== null && _a !== void 0 ? _a : null, user, options),
|
|
65
|
+
];
|
|
67
66
|
if (options === null || options === void 0 ? void 0 : options.timeoutMs) {
|
|
68
67
|
ops.push(new Promise((r) => setTimeout(r, options.timeoutMs)).then(() => {
|
|
69
68
|
Log_1.Log.debug('Fetching latest value timed out');
|
|
@@ -82,9 +81,9 @@ class DataAdapterCore {
|
|
|
82
81
|
}
|
|
83
82
|
});
|
|
84
83
|
}
|
|
85
|
-
|
|
84
|
+
_fetchAndPrepFromNetwork(current, user, options) {
|
|
86
85
|
return __awaiter(this, void 0, void 0, function* () {
|
|
87
|
-
const latest = yield this._fetchFromNetwork(current, user);
|
|
86
|
+
const latest = yield this._fetchFromNetwork(current, user, options);
|
|
88
87
|
if (!latest) {
|
|
89
88
|
Log_1.Log.debug('No response returned for latest value');
|
|
90
89
|
return null;
|
package/src/ErrorBoundary.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { StatsigClientEmitEventFunc } from './StatsigClientBase';
|
|
2
|
+
import { AnyStatsigOptions } from './StatsigOptionsCommon';
|
|
2
3
|
export declare const EXCEPTION_ENDPOINT = "https://statsigapi.net/v1/sdk_exception";
|
|
3
4
|
export declare class ErrorBoundary {
|
|
4
5
|
private _sdkKey;
|
|
6
|
+
private _options;
|
|
5
7
|
private _emitter?;
|
|
6
8
|
private _seen;
|
|
7
|
-
constructor(_sdkKey: string, _emitter?: StatsigClientEmitEventFunc | undefined);
|
|
9
|
+
constructor(_sdkKey: string, _options: AnyStatsigOptions | null, _emitter?: StatsigClientEmitEventFunc | undefined);
|
|
8
10
|
wrap(instance: unknown): void;
|
|
9
11
|
capture(tag: string, task: () => unknown): unknown;
|
|
10
12
|
logError(tag: string, error: unknown): void;
|
package/src/ErrorBoundary.js
CHANGED
|
@@ -15,8 +15,9 @@ const SDKType_1 = require("./SDKType");
|
|
|
15
15
|
const StatsigMetadata_1 = require("./StatsigMetadata");
|
|
16
16
|
exports.EXCEPTION_ENDPOINT = 'https://statsigapi.net/v1/sdk_exception';
|
|
17
17
|
class ErrorBoundary {
|
|
18
|
-
constructor(_sdkKey, _emitter) {
|
|
18
|
+
constructor(_sdkKey, _options, _emitter) {
|
|
19
19
|
this._sdkKey = _sdkKey;
|
|
20
|
+
this._options = _options;
|
|
20
21
|
this._emitter = _emitter;
|
|
21
22
|
this._seen = new Set();
|
|
22
23
|
}
|
|
@@ -58,7 +59,7 @@ class ErrorBoundary {
|
|
|
58
59
|
try {
|
|
59
60
|
Log_1.Log.warn(`Caught error in ${tag}`, { error });
|
|
60
61
|
const impl = () => __awaiter(this, void 0, void 0, function* () {
|
|
61
|
-
var _a;
|
|
62
|
+
var _a, _b, _c, _d;
|
|
62
63
|
const unwrapped = (error !== null && error !== void 0 ? error : Error('[Statsig] Error was empty'));
|
|
63
64
|
const isError = unwrapped instanceof Error;
|
|
64
65
|
const name = isError ? unwrapped.name : 'No Name';
|
|
@@ -66,6 +67,10 @@ class ErrorBoundary {
|
|
|
66
67
|
return;
|
|
67
68
|
}
|
|
68
69
|
this._seen.add(name);
|
|
70
|
+
if ((_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.networkConfig) === null || _b === void 0 ? void 0 : _b.preventAllNetworkTraffic) {
|
|
71
|
+
(_c = this._emitter) === null || _c === void 0 ? void 0 : _c.call(this, { name: 'error', error });
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
69
74
|
const sdkType = SDKType_1.SDKType._get(this._sdkKey);
|
|
70
75
|
const statsigMetadata = StatsigMetadata_1.StatsigMetadataProvider.get();
|
|
71
76
|
const info = isError ? unwrapped.stack : _getDescription(unwrapped);
|
|
@@ -80,7 +85,7 @@ class ErrorBoundary {
|
|
|
80
85
|
},
|
|
81
86
|
body,
|
|
82
87
|
});
|
|
83
|
-
(
|
|
88
|
+
(_d = this._emitter) === null || _d === void 0 ? void 0 : _d.call(this, { name: 'error', error });
|
|
84
89
|
});
|
|
85
90
|
impl()
|
|
86
91
|
.then(() => {
|
package/src/NetworkConfig.d.ts
CHANGED
package/src/NetworkCore.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import './$_StatsigGlobal';
|
|
2
|
+
import { NetworkPriority } from './NetworkConfig';
|
|
2
3
|
import { StatsigClientEmitEventFunc } from './StatsigClientBase';
|
|
3
4
|
import { AnyStatsigOptions } from './StatsigOptionsCommon';
|
|
4
5
|
type RequestArgs = {
|
|
5
6
|
sdkKey: string;
|
|
6
7
|
url: string;
|
|
8
|
+
priority?: NetworkPriority;
|
|
7
9
|
retries?: number;
|
|
8
10
|
params?: Record<string, string>;
|
|
9
11
|
headers?: Record<string, string>;
|
package/src/NetworkCore.js
CHANGED
|
@@ -15,6 +15,7 @@ const Diagnostics_1 = require("./Diagnostics");
|
|
|
15
15
|
const Log_1 = require("./Log");
|
|
16
16
|
const NetworkConfig_1 = require("./NetworkConfig");
|
|
17
17
|
const SDKType_1 = require("./SDKType");
|
|
18
|
+
const SafeJs_1 = require("./SafeJs");
|
|
18
19
|
const SessionID_1 = require("./SessionID");
|
|
19
20
|
const StableID_1 = require("./StableID");
|
|
20
21
|
const StatsigMetadata_1 = require("./StatsigMetadata");
|
|
@@ -51,23 +52,28 @@ class NetworkCore {
|
|
|
51
52
|
});
|
|
52
53
|
}
|
|
53
54
|
_sendRequest(args) {
|
|
54
|
-
var _a;
|
|
55
|
+
var _a, _b, _c;
|
|
55
56
|
return __awaiter(this, void 0, void 0, function* () {
|
|
56
57
|
if (!_ensureValidSdkKey(args)) {
|
|
57
58
|
return null;
|
|
58
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
|
+
}
|
|
59
63
|
const { method, body, retries } = args;
|
|
60
64
|
const controller = new AbortController();
|
|
61
65
|
const handle = setTimeout(() => controller.abort(`Timeout of ${this._timeout}ms expired.`), this._timeout);
|
|
62
66
|
const url = yield this._getPopulatedURL(args);
|
|
63
67
|
let response = null;
|
|
64
68
|
try {
|
|
65
|
-
|
|
69
|
+
const config = {
|
|
66
70
|
method,
|
|
67
71
|
body,
|
|
68
72
|
headers: Object.assign({}, args.headers),
|
|
69
73
|
signal: controller.signal,
|
|
70
|
-
|
|
74
|
+
priority: args.priority,
|
|
75
|
+
};
|
|
76
|
+
response = yield fetch(url, config);
|
|
71
77
|
clearTimeout(handle);
|
|
72
78
|
if (!response.ok) {
|
|
73
79
|
const text = yield response.text().catch(() => 'No Text');
|
|
@@ -86,7 +92,7 @@ class NetworkCore {
|
|
|
86
92
|
const errorMessage = _getErrorMessage(controller, error);
|
|
87
93
|
Diagnostics_1.Diagnostics.mark();
|
|
88
94
|
if (!retries || retries <= 0) {
|
|
89
|
-
(
|
|
95
|
+
(_c = this._emitter) === null || _c === void 0 ? void 0 : _c.call(this, { name: 'error', error });
|
|
90
96
|
Log_1.Log.error(`A networking error occured during ${method} request to ${url}.`, errorMessage, error);
|
|
91
97
|
return null;
|
|
92
98
|
}
|
|
@@ -118,15 +124,22 @@ class NetworkCore {
|
|
|
118
124
|
}
|
|
119
125
|
_attemptToEncodeString(args, input) {
|
|
120
126
|
var _a, _b, _c;
|
|
121
|
-
|
|
127
|
+
const win = (0, SafeJs_1._getWindowSafe)();
|
|
128
|
+
if (!(win === null || win === void 0 ? void 0 : win.btoa) ||
|
|
129
|
+
(__STATSIG__ === null || __STATSIG__ === void 0 ? void 0 : __STATSIG__['no-encode']) != null ||
|
|
122
130
|
((_a = this._options) === null || _a === void 0 ? void 0 : _a.disableStatsigEncoding) ||
|
|
123
|
-
!args.isStatsigEncodable
|
|
124
|
-
|
|
125
|
-
|
|
131
|
+
!args.isStatsigEncodable) {
|
|
132
|
+
return input;
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
const result = (_b = win.btoa(input).split('').reverse().join('')) !== null && _b !== void 0 ? _b : input;
|
|
136
|
+
args.params = Object.assign(Object.assign({}, ((_c = args.params) !== null && _c !== void 0 ? _c : {})), { [NetworkConfig_1.NetworkParam.StatsigEncoded]: '1' });
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
catch (_d) {
|
|
140
|
+
Log_1.Log.warn('/initialize request encoding failed');
|
|
126
141
|
return input;
|
|
127
142
|
}
|
|
128
|
-
args.params = Object.assign(Object.assign({}, ((_b = args.params) !== null && _b !== void 0 ? _b : {})), { [NetworkConfig_1.NetworkParam.StatsigEncoded]: '1' });
|
|
129
|
-
return (_c = window.btoa(input).split('').reverse().join('')) !== null && _c !== void 0 ? _c : input;
|
|
130
143
|
}
|
|
131
144
|
}
|
|
132
145
|
exports.NetworkCore = NetworkCore;
|
package/src/SessionID.js
CHANGED
|
@@ -57,17 +57,13 @@ function _bumpSession(session) {
|
|
|
57
57
|
}
|
|
58
58
|
data.lastUpdate = now;
|
|
59
59
|
_persistToStorage(data, session.sdkKey);
|
|
60
|
-
session.data = data;
|
|
61
60
|
clearTimeout(session.idleTimeoutID);
|
|
62
61
|
clearTimeout(session.ageTimeoutID);
|
|
63
62
|
const lifetime = now - data.startTime;
|
|
64
63
|
const sdkKey = session.sdkKey;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// idleTimeoutID: _createSessionTimeout(sdkKey, MAX_SESSION_IDLE_TIME),
|
|
69
|
-
ageTimeoutID: _createSessionTimeout(sdkKey, MAX_SESSION_AGE - lifetime),
|
|
70
|
-
};
|
|
64
|
+
session.idleTimeoutID = _createSessionTimeout(sdkKey, MAX_SESSION_IDLE_TIME);
|
|
65
|
+
session.ageTimeoutID = _createSessionTimeout(sdkKey, MAX_SESSION_AGE - lifetime);
|
|
66
|
+
return session;
|
|
71
67
|
}
|
|
72
68
|
function _createSessionTimeout(sdkKey, duration) {
|
|
73
69
|
return setTimeout(() => {
|
package/src/StatsigClientBase.js
CHANGED
|
@@ -31,7 +31,7 @@ class StatsigClientBase {
|
|
|
31
31
|
(options === null || options === void 0 ? void 0 : options.disableStorage) && StorageProvider_1.Storage._setDisabled(true);
|
|
32
32
|
(options === null || options === void 0 ? void 0 : options.overrideStableID) &&
|
|
33
33
|
StableID_1.StableID.setOverride(options.overrideStableID, sdkKey);
|
|
34
|
-
this._errorBoundary = new ErrorBoundary_1.ErrorBoundary(sdkKey, emitter);
|
|
34
|
+
this._errorBoundary = new ErrorBoundary_1.ErrorBoundary(sdkKey, options, emitter);
|
|
35
35
|
this._errorBoundary.wrap(this);
|
|
36
36
|
this._errorBoundary.wrap(network);
|
|
37
37
|
this._errorBoundary.wrap(adapter);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NetworkPriority } from './NetworkConfig';
|
|
1
2
|
import type { AnyStatsigOptions, NetworkConfigCommon } from './StatsigOptionsCommon';
|
|
2
3
|
import { StatsigUser } from './StatsigUser';
|
|
3
4
|
export type DataSource = 'Uninitialized' | 'Loading' | 'NoValues' | 'Cache' | 'Network' | 'NetworkNotModified' | 'Bootstrap' | 'Prefetch';
|
|
@@ -14,15 +15,23 @@ export type DataAdapterAsyncOptions = {
|
|
|
14
15
|
* Note: If no timeout is given, the {@link NetworkConfigCommon.networkTimeoutMs|StatsigOptions.networkConfig.networkTimeoutMs} is used.
|
|
15
16
|
*/
|
|
16
17
|
readonly timeoutMs?: NetworkConfigCommon['networkTimeoutMs'];
|
|
18
|
+
/**
|
|
19
|
+
* The priority that should be applied to the Http request that is fired.
|
|
20
|
+
*
|
|
21
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/fetch#priority
|
|
22
|
+
*
|
|
23
|
+
* default: 'auto'
|
|
24
|
+
*/
|
|
25
|
+
readonly priority?: NetworkPriority;
|
|
17
26
|
};
|
|
18
27
|
export declare const DataAdapterCachePrefix = "statsig.cached";
|
|
19
28
|
/**
|
|
20
29
|
* Describes a type that is used during intialize/update operations of a Statsig client.
|
|
21
30
|
*
|
|
22
31
|
* See below to find the default adapters, but know that it is possible to create your
|
|
23
|
-
* own StatsigDataAdapter and provide it via
|
|
32
|
+
* own StatsigDataAdapter and provide it via `StatsigOptions.dataAdapter`.
|
|
24
33
|
*
|
|
25
|
-
*
|
|
34
|
+
* defaults:
|
|
26
35
|
*
|
|
27
36
|
* - {@link StatsigClient} uses {@link EvaluationsDataAdapter}
|
|
28
37
|
*
|
package/src/StatsigMetadata.d.ts
CHANGED
package/src/StatsigMetadata.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StatsigMetadataProvider = exports.SDK_VERSION = void 0;
|
|
4
|
-
exports.SDK_VERSION = '0.0.1-beta.
|
|
4
|
+
exports.SDK_VERSION = '0.0.1-beta.39';
|
|
5
5
|
let metadata = {
|
|
6
6
|
sdkVersion: exports.SDK_VERSION,
|
|
7
7
|
sdkType: 'js-mono', // js-mono is overwritten by Precomp and OnDevice clients
|
|
@@ -38,6 +38,10 @@ export type NetworkConfigCommon = {
|
|
|
38
38
|
* default: `10,000 ms` (10 seconds)
|
|
39
39
|
*/
|
|
40
40
|
networkTimeoutMs?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Intended for testing purposes. Prevents any network requests being made.
|
|
43
|
+
*/
|
|
44
|
+
preventAllNetworkTraffic?: boolean;
|
|
41
45
|
};
|
|
42
46
|
/** Options for configuring a Statsig client. */
|
|
43
47
|
export type StatsigOptionsCommon<NetworkConfig extends NetworkConfigCommon> = StatsigRuntimeMutableOptions & {
|
package/src/StorageProvider.js
CHANGED
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports._setObjectInStorage = exports._getObjectFromStorage = exports.Storage = void 0;
|
|
13
13
|
const Log_1 = require("./Log");
|
|
14
14
|
const inMemoryStore = {};
|
|
15
|
+
const _resolve = (input) => Promise.resolve(input);
|
|
15
16
|
const _inMemoryProvider = {
|
|
16
17
|
_getProviderName: () => 'InMemory',
|
|
17
18
|
_getItemSync(key) {
|
|
@@ -20,18 +21,18 @@ const _inMemoryProvider = {
|
|
|
20
21
|
},
|
|
21
22
|
_getItem(key) {
|
|
22
23
|
var _a;
|
|
23
|
-
return
|
|
24
|
+
return _resolve((_a = inMemoryStore[key]) !== null && _a !== void 0 ? _a : null);
|
|
24
25
|
},
|
|
25
26
|
_setItem(key, value) {
|
|
26
27
|
inMemoryStore[key] = value;
|
|
27
|
-
return
|
|
28
|
+
return _resolve();
|
|
28
29
|
},
|
|
29
30
|
_removeItem(key) {
|
|
30
31
|
delete inMemoryStore[key];
|
|
31
|
-
return
|
|
32
|
+
return _resolve();
|
|
32
33
|
},
|
|
33
34
|
_getAllKeys() {
|
|
34
|
-
return
|
|
35
|
+
return _resolve(Object.keys(inMemoryStore));
|
|
35
36
|
},
|
|
36
37
|
};
|
|
37
38
|
let _localStorageProvider = null;
|
|
@@ -43,19 +44,19 @@ try {
|
|
|
43
44
|
return localStorage.getItem(key);
|
|
44
45
|
},
|
|
45
46
|
_getItem(key) {
|
|
46
|
-
return
|
|
47
|
+
return _resolve(localStorage.getItem(key));
|
|
47
48
|
},
|
|
48
49
|
_setItem(key, value) {
|
|
49
50
|
localStorage.setItem(key, value);
|
|
50
|
-
return
|
|
51
|
+
return _resolve();
|
|
51
52
|
},
|
|
52
53
|
_removeItem(key) {
|
|
53
54
|
localStorage.removeItem(key);
|
|
54
|
-
return
|
|
55
|
+
return _resolve();
|
|
55
56
|
},
|
|
56
57
|
_getAllKeys() {
|
|
57
58
|
const keys = Object.keys(localStorage);
|
|
58
|
-
return
|
|
59
|
+
return _resolve(keys);
|
|
59
60
|
},
|
|
60
61
|
};
|
|
61
62
|
}
|