@statsig/client-core
Advanced tools
Comparing version 0.0.1-beta.36 to 0.0.1-beta.37
{ | ||
"name": "@statsig/client-core", | ||
"version": "0.0.1-beta.36", | ||
"version": "0.0.1-beta.37", | ||
"dependencies": {}, | ||
@@ -5,0 +5,0 @@ "type": "commonjs", |
# Statsig - Core | ||
> [!IMPORTANT] | ||
> This version of the SDK is still in beta. The non-beta version can be found [here](https://github.com/statsig-io/js-client). | ||
The package that contains all the common logic shared by the various Statsig Javascript packages. | ||
Learn more by visiting: https://docs.statsig.com/client/javascript-sdk |
@@ -5,2 +5,3 @@ import { DownloadConfigSpecsResponse } from './DownloadConfigSpecsResponse'; | ||
import { InitializeResponseWithUpdates } from './InitializeResponse'; | ||
import { StatsigSession } from './SessionID'; | ||
import { StatsigClientEventEmitterInterface } from './StatsigClientEventEmitter'; | ||
@@ -26,3 +27,3 @@ import { EvaluationsDataAdapter, SpecsDataAdapter } from './StatsigDataAdapter'; | ||
export type AsyncCommonContext = { | ||
sessionID: string; | ||
session: StatsigSession; | ||
stableID: string; | ||
@@ -29,0 +30,0 @@ }; |
@@ -1,12 +0,19 @@ | ||
type SessionState = { | ||
emitFunction: () => void; | ||
ageTimeoutID: ReturnType<typeof setTimeout> | null; | ||
idleTimeoutID: ReturnType<typeof setTimeout> | null; | ||
type SessionTimeoutID = ReturnType<typeof setTimeout>; | ||
type SessionData = { | ||
sessionID: string; | ||
startTime: number; | ||
lastUpdate: number; | ||
}; | ||
export type StatsigSession = { | ||
data: SessionData; | ||
sdkKey: string; | ||
ageTimeoutID?: SessionTimeoutID; | ||
idleTimeoutID?: SessionTimeoutID; | ||
}; | ||
export declare const SessionID: { | ||
get: (sdkKey: string) => Promise<string>; | ||
_getPromise: (sdkKey: string) => Promise<string>; | ||
_setEmitFunction: (eFunction: () => void, sdkKey: string) => void; | ||
_resetTimeout: (sessionState: SessionState, timeoutID: ReturnType<typeof setTimeout> | null, duration: number) => ReturnType<typeof setTimeout> | null; | ||
}; | ||
export declare const StatsigSession: { | ||
get: (sdkKey: string) => Promise<StatsigSession>; | ||
}; | ||
export {}; |
@@ -12,3 +12,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SessionID = void 0; | ||
exports.StatsigSession = exports.SessionID = void 0; | ||
const Hashing_1 = require("./Hashing"); | ||
@@ -18,66 +18,71 @@ const Log_1 = require("./Log"); | ||
const UUID_1 = require("./UUID"); | ||
const SESSION_ID_MAP = {}; | ||
const SESSION_STATE_MAP = {}; | ||
const PROMISE_MAP = {}; | ||
const MAX_SESSION_IDLE_TIME = 30 * 60 * 1000; // 30 minutes | ||
const MAX_SESSION_AGE = 4 * 60 * 60 * 1000; // 4 hours | ||
const PROMISE_MAP = {}; | ||
exports.SessionID = { | ||
get: (sdkKey) => { | ||
if (PROMISE_MAP[sdkKey] != null) { | ||
return PROMISE_MAP[sdkKey]; | ||
get: (sdkKey) => __awaiter(void 0, void 0, void 0, function* () { | ||
return exports.StatsigSession.get(sdkKey).then((x) => x.data.sessionID); | ||
}), | ||
}; | ||
exports.StatsigSession = { | ||
get: (sdkKey) => __awaiter(void 0, void 0, void 0, function* () { | ||
if (PROMISE_MAP[sdkKey] == null) { | ||
PROMISE_MAP[sdkKey] = _loadSession(sdkKey); | ||
} | ||
return (PROMISE_MAP[sdkKey] = exports.SessionID._getPromise(sdkKey)); | ||
}, | ||
_getPromise: (sdkKey) => __awaiter(void 0, void 0, void 0, function* () { | ||
var _a; | ||
let session = SESSION_ID_MAP[sdkKey]; | ||
const session = yield PROMISE_MAP[sdkKey]; | ||
return _bumpSession(session); | ||
}), | ||
}; | ||
function _loadSession(sdkKey) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let data = yield _loadFromStorage(sdkKey); | ||
const now = Date.now(); | ||
if (session == null) { | ||
let tempSession = yield _loadFromStorage(sdkKey); | ||
if (tempSession == null) { | ||
tempSession = { | ||
sessionID: (0, UUID_1.getUUID)(), | ||
startTime: now, | ||
lastUpdate: now, | ||
}; | ||
} | ||
session = tempSession; | ||
SESSION_ID_MAP[sdkKey] = session; | ||
if (!data) { | ||
data = { | ||
sessionID: (0, UUID_1.getUUID)(), | ||
startTime: now, | ||
lastUpdate: now, | ||
}; | ||
} | ||
const sessionState = (_a = SESSION_STATE_MAP[sdkKey]) !== null && _a !== void 0 ? _a : { | ||
ageTimeoutID: null, | ||
idleTimeoutID: null, | ||
emitFunction: () => { | ||
return; | ||
}, | ||
return { | ||
data, | ||
sdkKey, | ||
}; | ||
if (now - session.startTime > MAX_SESSION_AGE || | ||
now - session.lastUpdate > MAX_SESSION_IDLE_TIME) { | ||
session.sessionID = (0, UUID_1.getUUID)(); | ||
session.startTime = now; | ||
}); | ||
} | ||
function _bumpSession(session) { | ||
const now = Date.now(); | ||
const data = session.data; | ||
if (_isIdle(data) || _hasRunTooLong(data)) { | ||
data.sessionID = (0, UUID_1.getUUID)(); | ||
data.startTime = now; | ||
} | ||
data.lastUpdate = now; | ||
_persistToStorage(data, session.sdkKey); | ||
session.data = data; | ||
clearTimeout(session.idleTimeoutID); | ||
clearTimeout(session.ageTimeoutID); | ||
const lifetime = now - data.startTime; | ||
const sdkKey = session.sdkKey; | ||
return { | ||
data, | ||
sdkKey, | ||
// idleTimeoutID: _createSessionTimeout(sdkKey, MAX_SESSION_IDLE_TIME), | ||
ageTimeoutID: _createSessionTimeout(sdkKey, MAX_SESSION_AGE - lifetime), | ||
}; | ||
} | ||
function _createSessionTimeout(sdkKey, duration) { | ||
return setTimeout(() => { | ||
const client = __STATSIG__ === null || __STATSIG__ === void 0 ? void 0 : __STATSIG__.instance(sdkKey); | ||
if (client) { | ||
client.$emt({ name: 'session_expired' }); | ||
} | ||
session.lastUpdate = now; | ||
_persistToStorage(session, sdkKey); | ||
sessionState.idleTimeoutID = exports.SessionID._resetTimeout(sessionState, sessionState.idleTimeoutID, MAX_SESSION_IDLE_TIME); | ||
sessionState.ageTimeoutID = exports.SessionID._resetTimeout(sessionState, sessionState.ageTimeoutID, MAX_SESSION_AGE - (now - session.startTime)); | ||
SESSION_ID_MAP[sdkKey] = session; | ||
SESSION_STATE_MAP[sdkKey] = sessionState; | ||
PROMISE_MAP[sdkKey] = null; | ||
return session.sessionID; | ||
}), | ||
_setEmitFunction: (eFunction, sdkKey) => { | ||
var _a; | ||
const sessionState = (_a = SESSION_STATE_MAP[sdkKey]) !== null && _a !== void 0 ? _a : { | ||
ageTimeoutID: null, | ||
idleTimeoutID: null, | ||
emitFunction: eFunction, | ||
}; | ||
sessionState.emitFunction = eFunction; | ||
SESSION_STATE_MAP[sdkKey] = sessionState; | ||
}, | ||
_resetTimeout: (sessionState, timeoutID, duration) => { | ||
clearTimeout(timeoutID !== null && timeoutID !== void 0 ? timeoutID : undefined); | ||
return setTimeout(sessionState.emitFunction, duration); | ||
}, | ||
}; | ||
}, duration); | ||
} | ||
function _isIdle({ lastUpdate }) { | ||
return Date.now() - lastUpdate > MAX_SESSION_IDLE_TIME; | ||
} | ||
function _hasRunTooLong({ startTime }) { | ||
return Date.now() - startTime > MAX_SESSION_AGE; | ||
} | ||
function _getSessionIDStorageKey(sdkKey) { | ||
@@ -84,0 +89,0 @@ return `statsig.session_id.${(0, Hashing_1.DJB2)(sdkKey)}`; |
@@ -62,6 +62,6 @@ import './$_StatsigGlobal'; | ||
off<T extends StatsigClientEventName>(event: T, listener: StatsigClientEventCallback<T>): void; | ||
__on<T extends StatsigClientEventName>(event: T, listener: StatsigClientEventCallback<T>): void; | ||
protected _emit(event: AnyStatsigClientEvent): void; | ||
$on<T extends StatsigClientEventName>(event: T, listener: StatsigClientEventCallback<T>): void; | ||
$emt(event: AnyStatsigClientEvent): void; | ||
protected _setStatus(newStatus: StatsigLoadingStatus, values: DataAdapterResult | null): void; | ||
protected _enqueueExposure(name: string, exposure: StatsigEventInternal, options?: EvaluationOptionsCommon): void; | ||
} |
@@ -19,3 +19,2 @@ "use strict"; | ||
const SafeJs_1 = require("./SafeJs"); | ||
const SessionID_1 = require("./SessionID"); | ||
const StableID_1 = require("./StableID"); | ||
@@ -28,3 +27,3 @@ const StorageProvider_1 = require("./StorageProvider"); | ||
this._listeners = {}; | ||
const emitter = this._emit.bind(this); | ||
const emitter = this.$emt.bind(this); | ||
const statsigGlobal = (0, __StatsigGlobal_1._getStatsigGlobal)(); | ||
@@ -45,5 +44,2 @@ const instances = (_a = statsigGlobal.instances) !== null && _a !== void 0 ? _a : {}; | ||
this._logger = new EventLogger_1.EventLogger(sdkKey, emitter, network, options); | ||
SessionID_1.SessionID._setEmitFunction(() => { | ||
this._emit({ name: 'session_expired' }); | ||
}, sdkKey); | ||
if (instances[sdkKey] != null && (0, SafeJs_1._isBrowserEnv)()) { | ||
@@ -88,3 +84,3 @@ 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.'); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this._emit({ name: 'pre_shutdown' }); | ||
this.$emt({ name: 'pre_shutdown' }); | ||
yield this._logger.shutdown(); | ||
@@ -122,7 +118,7 @@ }); | ||
} | ||
__on(event, listener) { | ||
$on(event, listener) { | ||
listener.__isInternal = true; | ||
this.on(event, listener); | ||
} | ||
_emit(event) { | ||
$emt(event) { | ||
var _a; | ||
@@ -135,3 +131,3 @@ const barrier = (listener) => { | ||
if (listener.__isInternal === true) { | ||
this._errorBoundary.logError(`_emit:${event.name}`, error); | ||
this._errorBoundary.logError(`__emit:${event.name}`, error); | ||
return; | ||
@@ -149,3 +145,3 @@ } | ||
this.loadingStatus = newStatus; | ||
this._emit({ name: 'values_updated', status: newStatus, values }); | ||
this.$emt({ name: 'values_updated', status: newStatus, values }); | ||
} | ||
@@ -152,0 +148,0 @@ _enqueueExposure(name, exposure, options) { |
@@ -68,4 +68,8 @@ import { DataAdapterResult } from './StatsigDataAdapter'; | ||
*/ | ||
__on<T extends StatsigClientEventName>(event: T, listener: StatsigClientEventCallback<T>): void; | ||
$on<T extends StatsigClientEventName>(event: T, listener: StatsigClientEventCallback<T>): void; | ||
/** | ||
* (Statsig Use Only) - Emit StatsigClientEvents | ||
*/ | ||
$emt(event: AnyStatsigClientEvent): void; | ||
} | ||
export {}; |
@@ -1,2 +0,2 @@ | ||
export declare const SDK_VERSION = "0.0.1-beta.36"; | ||
export declare const SDK_VERSION = "0.0.1-beta.37"; | ||
export type StatsigMetadata = { | ||
@@ -3,0 +3,0 @@ readonly [key: string]: string | undefined; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.StatsigMetadataProvider = exports.SDK_VERSION = void 0; | ||
exports.SDK_VERSION = '0.0.1-beta.36'; | ||
exports.SDK_VERSION = '0.0.1-beta.37'; | ||
let metadata = { | ||
@@ -6,0 +6,0 @@ sdkVersion: exports.SDK_VERSION, |
2543
108748
6