@statsig/client-core 0.0.1-beta.9 → 1.0.0
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 +0 -3
- package/package.json +1 -1
- package/src/$_StatsigGlobal.d.ts +9 -1
- package/src/$_StatsigGlobal.js +29 -12
- package/src/CacheKey.d.ts +4 -0
- package/src/CacheKey.js +27 -0
- package/src/ClientInterfaces.d.ts +46 -12
- package/src/DataAdapterCore.d.ts +31 -0
- package/src/DataAdapterCore.js +192 -0
- package/src/Diagnostics.d.ts +1 -3
- package/src/Diagnostics.js +4 -49
- package/src/DownloadConfigSpecsResponse.d.ts +41 -0
- package/src/DownloadConfigSpecsResponse.js +2 -0
- package/src/ErrorBoundary.d.ts +7 -2
- package/src/ErrorBoundary.js +81 -88
- 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 +15 -10
- package/src/EventLogger.js +216 -256
- package/src/Hashing.d.ts +2 -1
- package/src/Hashing.js +26 -7
- package/src/InitializeResponse.d.ts +20 -0
- package/src/InitializeResponse.js +2 -0
- package/src/Log.js +15 -34
- package/src/NetworkConfig.d.ts +19 -0
- package/src/NetworkConfig.js +19 -0
- package/src/NetworkCore.d.ts +17 -7
- package/src/NetworkCore.js +173 -196
- 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 +56 -19
- package/src/StatsigClientBase.js +126 -48
- package/src/StatsigClientEventEmitter.d.ts +54 -33
- package/src/StatsigDataAdapter.d.ts +103 -17
- package/src/StatsigDataAdapter.js +2 -0
- package/src/StatsigEvent.d.ts +10 -18
- package/src/StatsigEvent.js +41 -39
- package/src/StatsigMetadata.d.ts +1 -1
- package/src/StatsigMetadata.js +7 -18
- package/src/StatsigOptionsCommon.d.ts +84 -20
- package/src/StatsigTypeFactories.d.ts +6 -0
- package/src/StatsigTypeFactories.js +50 -0
- package/src/StatsigTypes.d.ts +28 -22
- package/src/StatsigTypes.js +0 -29
- package/src/StatsigUser.d.ts +7 -8
- package/src/StatsigUser.js +11 -24
- package/src/StorageProvider.d.ts +13 -8
- package/src/StorageProvider.js +66 -85
- 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 +9 -0
- package/src/VisibilityObserving.js +39 -0
- package/src/index.d.ts +20 -4
- package/src/index.js +26 -18
- package/src/Monitoring.d.ts +0 -3
- package/src/Monitoring.js +0 -33
- 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/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 CacheKey_1 = require("./CacheKey");
|
|
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, CacheKey_1._getStorageKey)(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
|
+
}
|
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 CacheKey_1 = require("./CacheKey");
|
|
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, CacheKey_1._getStorageKey)(sdkKey)}`;
|
|
68
39
|
}
|
|
69
40
|
function _persistToStorage(stableID, sdkKey) {
|
|
70
|
-
|
|
71
|
-
(0, StorageProvider_1.
|
|
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
|
-
|
|
77
|
-
return (0, StorageProvider_1.
|
|
47
|
+
const storageKey = _getStableIDStorageKey(sdkKey);
|
|
48
|
+
return (0, StorageProvider_1._getObjectFromStorage)(storageKey);
|
|
78
49
|
}
|
|
@@ -1,30 +1,67 @@
|
|
|
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 { AnyStatsigClientEvent, StatsigClientEventCallback, StatsigClientEventEmitterInterface, StatsigClientEventName, StatsigLoadingStatus } from './StatsigClientEventEmitter';
|
|
8
|
+
import { DataAdapterResult, EvaluationsDataAdapter, SpecsDataAdapter } from './StatsigDataAdapter';
|
|
7
9
|
import { StatsigEventInternal } from './StatsigEvent';
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
export type
|
|
11
|
-
|
|
10
|
+
import { AnyStatsigOptions, StatsigRuntimeMutableOptions } from './StatsigOptionsCommon';
|
|
11
|
+
export type StatsigClientEmitEventFunc = (event: AnyStatsigClientEvent) => void;
|
|
12
|
+
export type StatsigContext = {
|
|
13
|
+
sdkKey: string;
|
|
14
|
+
options: AnyStatsigOptions;
|
|
15
|
+
sessionID: string;
|
|
16
|
+
values: unknown;
|
|
12
17
|
};
|
|
13
|
-
export declare
|
|
14
|
-
export type StatsigClientEmitEventFunc = (data: StatsigClientEventData) => void;
|
|
15
|
-
export declare abstract class StatsigClientBase implements StatsigClientEventEmitterInterface {
|
|
16
|
-
protected readonly _sdkKey: string;
|
|
17
|
-
protected readonly _adapter: StatsigDataAdapter;
|
|
18
|
+
export declare abstract class StatsigClientBase<TAdapter extends EvaluationsDataAdapter | SpecsDataAdapter> implements StatsigClientEventEmitterInterface {
|
|
18
19
|
loadingStatus: StatsigLoadingStatus;
|
|
20
|
+
readonly dataAdapter: TAdapter;
|
|
21
|
+
protected readonly _sdkKey: string;
|
|
22
|
+
protected readonly _options: AnyStatsigOptions;
|
|
19
23
|
protected readonly _errorBoundary: ErrorBoundary;
|
|
20
24
|
protected readonly _logger: EventLogger;
|
|
25
|
+
protected readonly _overrideAdapter: OverrideAdapter | null;
|
|
21
26
|
private _listeners;
|
|
22
|
-
constructor(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
constructor(sdkKey: string, adapter: TAdapter, network: NetworkCore, options: AnyStatsigOptions | null);
|
|
28
|
+
/**
|
|
29
|
+
* Updates runtime configuration options for the SDK, allowing toggling of certain behaviors such as logging and storage to comply with user preferences or regulations such as GDPR.
|
|
30
|
+
*
|
|
31
|
+
* @param {StatsigRuntimeMutableOptions} options - The configuration options that dictate the runtime behavior of the SDK.
|
|
32
|
+
*/
|
|
33
|
+
updateRuntimeOptions(options: StatsigRuntimeMutableOptions): void;
|
|
34
|
+
/**
|
|
35
|
+
* Flushes any currently queued events.
|
|
36
|
+
*/
|
|
37
|
+
flush(): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Gracefully shuts down the SDK, ensuring that all pending events are send before the SDK stops.
|
|
40
|
+
* This function emits a 'pre_shutdown' event and then waits for the logger to complete its shutdown process.
|
|
41
|
+
*
|
|
42
|
+
* @returns {Promise<void>} A promise that resolves when all shutdown procedures, including logging shutdown, have been completed.
|
|
43
|
+
*/
|
|
44
|
+
shutdown(): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Subscribes a callback function to a specific {@link StatsigClientEvent} or all StatsigClientEvents if the wildcard '*' is used.
|
|
47
|
+
* Once subscribed, the listener callback will be invoked whenever the specified event is emitted.
|
|
48
|
+
*
|
|
49
|
+
* @param {StatsigClientEventName} event - The name of the event to subscribe to, or '*' to subscribe to all events.
|
|
50
|
+
* @param {StatsigClientEventCallback<T>} listener - The callback function to execute when the event occurs. The function receives event-specific data as its parameter.
|
|
51
|
+
* @see {@link off} for unsubscribing from events.
|
|
52
|
+
*/
|
|
53
|
+
on<T extends StatsigClientEventName>(event: T, listener: StatsigClientEventCallback<T>): void;
|
|
54
|
+
/**
|
|
55
|
+
* Unsubscribes a previously registered callback function from a specific {@link StatsigClientEvent} or all StatsigClientEvents if the wildcard '*' is used.
|
|
56
|
+
*
|
|
57
|
+
* @param {StatsigClientEventName} event - The name of the event from which to unsubscribe, or '*' to unsubscribe from all events.
|
|
58
|
+
* @param {StatsigClientEventCallback<T>} listener - The callback function to remove from the event's notification list.
|
|
59
|
+
* @see {@link on} for subscribing to events.
|
|
60
|
+
*/
|
|
61
|
+
off<T extends StatsigClientEventName>(event: T, listener: StatsigClientEventCallback<T>): void;
|
|
62
|
+
$on<T extends StatsigClientEventName>(event: T, listener: StatsigClientEventCallback<T>): void;
|
|
63
|
+
$emt(event: AnyStatsigClientEvent): void;
|
|
64
|
+
protected _setStatus(newStatus: StatsigLoadingStatus, values: DataAdapterResult | null): void;
|
|
65
|
+
protected _enqueueExposure(name: string, exposure: StatsigEventInternal, options?: EvaluationOptionsCommon): void;
|
|
66
|
+
protected abstract _primeReadyRipcord(): void;
|
|
30
67
|
}
|
package/src/StatsigClientBase.js
CHANGED
|
@@ -1,72 +1,150 @@
|
|
|
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.StatsigClientBase =
|
|
12
|
+
exports.StatsigClientBase = void 0;
|
|
4
13
|
require("./$_StatsigGlobal");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
function StatsigClientBase(_sdkKey, _adapter, network, options) {
|
|
14
|
+
const __StatsigGlobal_1 = require("./$_StatsigGlobal");
|
|
15
|
+
const ErrorBoundary_1 = require("./ErrorBoundary");
|
|
16
|
+
const EventLogger_1 = require("./EventLogger");
|
|
17
|
+
const Log_1 = require("./Log");
|
|
18
|
+
const SafeJs_1 = require("./SafeJs");
|
|
19
|
+
const StorageProvider_1 = require("./StorageProvider");
|
|
20
|
+
class StatsigClientBase {
|
|
21
|
+
constructor(sdkKey, adapter, network, options) {
|
|
14
22
|
var _a, _b;
|
|
15
|
-
this._sdkKey = _sdkKey;
|
|
16
|
-
this._adapter = _adapter;
|
|
17
23
|
this.loadingStatus = 'Uninitialized';
|
|
18
24
|
this._listeners = {};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
const emitter = this.$emt.bind(this);
|
|
26
|
+
(options === null || options === void 0 ? void 0 : options.logLevel) != null && (Log_1.Log.level = options.logLevel);
|
|
27
|
+
(options === null || options === void 0 ? void 0 : options.disableStorage) && StorageProvider_1.Storage._setDisabled(true);
|
|
28
|
+
this._sdkKey = sdkKey;
|
|
29
|
+
this._options = options !== null && options !== void 0 ? options : {};
|
|
30
|
+
this._overrideAdapter = (_a = options === null || options === void 0 ? void 0 : options.overrideAdapter) !== null && _a !== void 0 ? _a : null;
|
|
31
|
+
this._logger = new EventLogger_1.EventLogger(sdkKey, emitter, network, options);
|
|
32
|
+
this._errorBoundary = new ErrorBoundary_1.ErrorBoundary(sdkKey, options, emitter);
|
|
33
|
+
this._errorBoundary.wrap(this);
|
|
34
|
+
this._errorBoundary.wrap(network);
|
|
35
|
+
this._errorBoundary.wrap(adapter);
|
|
36
|
+
this._errorBoundary.wrap(this._logger);
|
|
37
|
+
if ((0, SafeJs_1._isBrowserEnv)()) {
|
|
38
|
+
const statsigGlobal = (0, __StatsigGlobal_1._getStatsigGlobal)();
|
|
39
|
+
const instances = (_b = statsigGlobal.instances) !== null && _b !== void 0 ? _b : {};
|
|
40
|
+
const inst = this;
|
|
41
|
+
if (instances[sdkKey] != null) {
|
|
42
|
+
Log_1.Log.warn('Creating multiple Statsig clients with the same SDK key can lead to unexpected behavior. Multi-instance support requires different SDK keys.');
|
|
43
|
+
}
|
|
44
|
+
instances[sdkKey] = inst;
|
|
45
|
+
statsigGlobal.lastInstance = inst;
|
|
46
|
+
statsigGlobal.instances = instances;
|
|
47
|
+
__STATSIG__ = statsigGlobal;
|
|
48
|
+
}
|
|
49
|
+
this.dataAdapter = adapter;
|
|
50
|
+
this.dataAdapter.attach(sdkKey, options);
|
|
51
|
+
this._primeReadyRipcord();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Updates runtime configuration options for the SDK, allowing toggling of certain behaviors such as logging and storage to comply with user preferences or regulations such as GDPR.
|
|
55
|
+
*
|
|
56
|
+
* @param {StatsigRuntimeMutableOptions} options - The configuration options that dictate the runtime behavior of the SDK.
|
|
57
|
+
*/
|
|
58
|
+
updateRuntimeOptions(options) {
|
|
59
|
+
if (options.disableLogging != null) {
|
|
60
|
+
this._options.disableLogging = options.disableLogging;
|
|
61
|
+
this._logger.setLoggingDisabled(options.disableLogging);
|
|
24
62
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
63
|
+
if (options.disableStorage != null) {
|
|
64
|
+
this._options.disableStorage = options.disableStorage;
|
|
65
|
+
StorageProvider_1.Storage._setDisabled(options.disableStorage);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Flushes any currently queued events.
|
|
70
|
+
*/
|
|
71
|
+
flush() {
|
|
72
|
+
return this._logger.flush();
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Gracefully shuts down the SDK, ensuring that all pending events are send before the SDK stops.
|
|
76
|
+
* This function emits a 'pre_shutdown' event and then waits for the logger to complete its shutdown process.
|
|
77
|
+
*
|
|
78
|
+
* @returns {Promise<void>} A promise that resolves when all shutdown procedures, including logging shutdown, have been completed.
|
|
79
|
+
*/
|
|
80
|
+
shutdown() {
|
|
81
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
this.$emt({ name: 'pre_shutdown' });
|
|
83
|
+
yield this._logger.shutdown();
|
|
84
|
+
});
|
|
30
85
|
}
|
|
31
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Subscribes a callback function to a specific {@link StatsigClientEvent} or all StatsigClientEvents if the wildcard '*' is used.
|
|
88
|
+
* Once subscribed, the listener callback will be invoked whenever the specified event is emitted.
|
|
89
|
+
*
|
|
90
|
+
* @param {StatsigClientEventName} event - The name of the event to subscribe to, or '*' to subscribe to all events.
|
|
91
|
+
* @param {StatsigClientEventCallback<T>} listener - The callback function to execute when the event occurs. The function receives event-specific data as its parameter.
|
|
92
|
+
* @see {@link off} for unsubscribing from events.
|
|
93
|
+
*/
|
|
94
|
+
on(event, listener) {
|
|
32
95
|
if (!this._listeners[event]) {
|
|
33
96
|
this._listeners[event] = [];
|
|
34
97
|
}
|
|
35
98
|
this._listeners[event].push(listener);
|
|
36
|
-
}
|
|
37
|
-
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Unsubscribes a previously registered callback function from a specific {@link StatsigClientEvent} or all StatsigClientEvents if the wildcard '*' is used.
|
|
102
|
+
*
|
|
103
|
+
* @param {StatsigClientEventName} event - The name of the event from which to unsubscribe, or '*' to unsubscribe from all events.
|
|
104
|
+
* @param {StatsigClientEventCallback<T>} listener - The callback function to remove from the event's notification list.
|
|
105
|
+
* @see {@link on} for subscribing to events.
|
|
106
|
+
*/
|
|
107
|
+
off(event, listener) {
|
|
38
108
|
if (this._listeners[event]) {
|
|
39
|
-
|
|
109
|
+
const index = this._listeners[event].indexOf(listener);
|
|
40
110
|
if (index !== -1) {
|
|
41
111
|
this._listeners[event].splice(index, 1);
|
|
42
112
|
}
|
|
43
113
|
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
114
|
+
}
|
|
115
|
+
$on(event, listener) {
|
|
116
|
+
listener.__isInternal = true;
|
|
117
|
+
this.on(event, listener);
|
|
118
|
+
}
|
|
119
|
+
$emt(event) {
|
|
49
120
|
var _a;
|
|
50
|
-
|
|
51
|
-
|
|
121
|
+
const barrier = (listener) => {
|
|
122
|
+
try {
|
|
123
|
+
listener(event);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
if (listener.__isInternal === true) {
|
|
127
|
+
this._errorBoundary.logError(`__emit:${event.name}`, error);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
Log_1.Log.error(`An error occurred in a StatsigClientEvent listener. This is not an issue with Statsig.`, event);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
if (this._listeners[event.name]) {
|
|
134
|
+
this._listeners[event.name].forEach((l) => barrier(l));
|
|
52
135
|
}
|
|
53
|
-
(_a = this._listeners['*']) === null || _a === void 0 ? void 0 : _a.forEach(
|
|
54
|
-
}
|
|
55
|
-
|
|
136
|
+
(_a = this._listeners['*']) === null || _a === void 0 ? void 0 : _a.forEach(barrier);
|
|
137
|
+
}
|
|
138
|
+
_setStatus(newStatus, values) {
|
|
56
139
|
this.loadingStatus = newStatus;
|
|
57
|
-
this
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (options.disableExposureLog === true) {
|
|
140
|
+
this.$emt({ name: 'values_updated', status: newStatus, values });
|
|
141
|
+
}
|
|
142
|
+
_enqueueExposure(name, exposure, options) {
|
|
143
|
+
if ((options === null || options === void 0 ? void 0 : options.disableExposureLog) === true) {
|
|
144
|
+
this._logger.incrementNonExposureCount(name);
|
|
61
145
|
return;
|
|
62
146
|
}
|
|
63
147
|
this._logger.enqueue(exposure);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
this._adapter.getDataAsync(current, user).catch(function (err) {
|
|
67
|
-
Log_1.Log.error('An error occurred after update.', err);
|
|
68
|
-
});
|
|
69
|
-
};
|
|
70
|
-
return StatsigClientBase;
|
|
71
|
-
}());
|
|
148
|
+
}
|
|
149
|
+
}
|
|
72
150
|
exports.StatsigClientBase = StatsigClientBase;
|
|
@@ -1,14 +1,44 @@
|
|
|
1
|
+
import { DataAdapterResult } from './StatsigDataAdapter';
|
|
1
2
|
import { DynamicConfig, Experiment, FeatureGate, Layer } from './StatsigTypes';
|
|
3
|
+
import { Flatten } from './UtitlityTypes';
|
|
2
4
|
export type StatsigLoadingStatus = 'Uninitialized' | 'Loading' | 'Ready';
|
|
5
|
+
type EventNameToEventDataMap = {
|
|
6
|
+
values_updated: {
|
|
7
|
+
status: StatsigLoadingStatus;
|
|
8
|
+
values: DataAdapterResult | null;
|
|
9
|
+
};
|
|
10
|
+
session_expired: object;
|
|
11
|
+
error: {
|
|
12
|
+
error: unknown;
|
|
13
|
+
};
|
|
14
|
+
logs_flushed: {
|
|
15
|
+
events: Record<string, unknown>[];
|
|
16
|
+
};
|
|
17
|
+
pre_shutdown: object;
|
|
18
|
+
gate_evaluation: {
|
|
19
|
+
gate: FeatureGate;
|
|
20
|
+
};
|
|
21
|
+
dynamic_config_evaluation: {
|
|
22
|
+
dynamicConfig: DynamicConfig;
|
|
23
|
+
};
|
|
24
|
+
experiment_evaluation: {
|
|
25
|
+
experiment: Experiment;
|
|
26
|
+
};
|
|
27
|
+
layer_evaluation: {
|
|
28
|
+
layer: Layer;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
3
31
|
/**
|
|
4
|
-
*
|
|
32
|
+
* Type representing various events emitted by a Statsig client.
|
|
5
33
|
*
|
|
6
|
-
* `
|
|
34
|
+
* `values_updated` - When the Statsig clients internal values change as the result of an initialize/update operation.
|
|
7
35
|
*
|
|
8
36
|
* `error` - When an unexpected error occurs within the Statsig client.
|
|
9
37
|
*
|
|
10
38
|
* `logs_flushed` - When queued StatsigEvents are flushed to Statsig servers.
|
|
11
39
|
*
|
|
40
|
+
* `pre_shutdown` - Fired just before the SDK is shutdown
|
|
41
|
+
*
|
|
12
42
|
* `gate_evaluation` - Fired when any gate is checked from the Statsig client.
|
|
13
43
|
*
|
|
14
44
|
* `dynamic_config_evaluation` - Fired when any dyanamic config is checked from the Statsig client.
|
|
@@ -17,37 +47,28 @@ export type StatsigLoadingStatus = 'Uninitialized' | 'Loading' | 'Ready';
|
|
|
17
47
|
*
|
|
18
48
|
* `layer_evaluation` - Fired when any layer is checked from the Statsig client.
|
|
19
49
|
*/
|
|
20
|
-
export type
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
error: unknown;
|
|
32
|
-
} | {
|
|
33
|
-
event: 'logs_flushed';
|
|
34
|
-
events: Record<string, unknown>[];
|
|
35
|
-
} | {
|
|
36
|
-
event: 'gate_evaluation';
|
|
37
|
-
gate: FeatureGate;
|
|
38
|
-
} | {
|
|
39
|
-
event: 'dynamic_config_evaluation';
|
|
40
|
-
dynamicConfig: DynamicConfig;
|
|
41
|
-
} | {
|
|
42
|
-
event: 'experiment_evaluation';
|
|
43
|
-
experiment: Experiment;
|
|
44
|
-
} | {
|
|
45
|
-
event: 'layer_evaluation';
|
|
46
|
-
layer: Layer;
|
|
47
|
-
};
|
|
48
|
-
export type StatsigClientEventCallback = (data: StatsigClientEventData) => void;
|
|
50
|
+
export type AnyStatsigClientEvent = Flatten<{
|
|
51
|
+
[K in keyof EventNameToEventDataMap]: {
|
|
52
|
+
name: K;
|
|
53
|
+
} & EventNameToEventDataMap[K];
|
|
54
|
+
}[keyof EventNameToEventDataMap]>;
|
|
55
|
+
export type StatsigClientEvent<T> = Extract<AnyStatsigClientEvent, {
|
|
56
|
+
name: T;
|
|
57
|
+
}>;
|
|
58
|
+
export type AnyStatsigClientEventListener = StatsigClientEventCallback<StatsigClientEventName>;
|
|
59
|
+
export type StatsigClientEventName = AnyStatsigClientEvent['name'] | '*';
|
|
60
|
+
export type StatsigClientEventCallback<T extends StatsigClientEventName> = (event: T extends '*' ? AnyStatsigClientEvent : StatsigClientEvent<T>) => void;
|
|
49
61
|
export interface StatsigClientEventEmitterInterface {
|
|
50
62
|
readonly loadingStatus: StatsigLoadingStatus;
|
|
51
|
-
on(event:
|
|
52
|
-
off(event:
|
|
63
|
+
on<T extends StatsigClientEventName>(event: T, listener: StatsigClientEventCallback<T>): void;
|
|
64
|
+
off<T extends StatsigClientEventName>(event: T, listener: StatsigClientEventCallback<T>): void;
|
|
65
|
+
/**
|
|
66
|
+
* (Statsig Use Only) - Same as .on() but logs errors to sdk_exception
|
|
67
|
+
*/
|
|
68
|
+
$on<T extends StatsigClientEventName>(event: T, listener: StatsigClientEventCallback<T>): void;
|
|
69
|
+
/**
|
|
70
|
+
* (Statsig Use Only) - Emit StatsigClientEvents
|
|
71
|
+
*/
|
|
72
|
+
$emt(event: AnyStatsigClientEvent): void;
|
|
53
73
|
}
|
|
74
|
+
export {};
|