wolves-js-client 1.0.5 → 1.0.6
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/dist/DeviceInfo.d.ts +22 -0
- package/dist/DeviceInfo.js +98 -0
- package/dist/Network.d.ts +3 -1
- package/dist/Network.js +17 -4
- package/dist/StatsigClient.d.ts +15 -0
- package/dist/StatsigClient.js +92 -0
- package/dist/StatsigUser.d.ts +6 -0
- package/dist/StatsigUser.js +2 -0
- package/dist/WolvesClient.d.ts +1 -1
- package/dist/WolvesClient.js +2 -2
- package/dist/WolvesMetadata.d.ts +1 -1
- package/dist/WolvesMetadata.js +1 -1
- package/dist/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DeviceInfo - Collects device and environment information for event metadata
|
|
3
|
+
* Aligns with Statsig SDK's approach: sends raw user_agent for server-side parsing
|
|
4
|
+
*
|
|
5
|
+
* Note: Browser/OS parsing is done server-side from user_agent, not client-side
|
|
6
|
+
*/
|
|
7
|
+
export type DeviceInfoData = {
|
|
8
|
+
user_agent: string;
|
|
9
|
+
locale: string;
|
|
10
|
+
screen_width: number | null;
|
|
11
|
+
screen_height: number | null;
|
|
12
|
+
viewport_width: number | null;
|
|
13
|
+
viewport_height: number | null;
|
|
14
|
+
timezone: string;
|
|
15
|
+
timezone_offset: number | null;
|
|
16
|
+
};
|
|
17
|
+
export declare function getDeviceInfo(): DeviceInfoData;
|
|
18
|
+
/**
|
|
19
|
+
* Get device info as a flat record suitable for event metadata
|
|
20
|
+
* Only includes non-null values
|
|
21
|
+
*/
|
|
22
|
+
export declare function getDeviceInfoForMetadata(): Record<string, string | number>;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* DeviceInfo - Collects device and environment information for event metadata
|
|
4
|
+
* Aligns with Statsig SDK's approach: sends raw user_agent for server-side parsing
|
|
5
|
+
*
|
|
6
|
+
* Note: Browser/OS parsing is done server-side from user_agent, not client-side
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.getDeviceInfo = getDeviceInfo;
|
|
10
|
+
exports.getDeviceInfoForMetadata = getDeviceInfoForMetadata;
|
|
11
|
+
function getWindowSafe() {
|
|
12
|
+
if (typeof window !== 'undefined') {
|
|
13
|
+
return window;
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
function getNavigatorSafe() {
|
|
18
|
+
var _a;
|
|
19
|
+
const win = getWindowSafe();
|
|
20
|
+
return (_a = win === null || win === void 0 ? void 0 : win.navigator) !== null && _a !== void 0 ? _a : null;
|
|
21
|
+
}
|
|
22
|
+
function getSafeTimezone() {
|
|
23
|
+
try {
|
|
24
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || '';
|
|
25
|
+
}
|
|
26
|
+
catch (_a) {
|
|
27
|
+
return '';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function getSafeTimezoneOffset() {
|
|
31
|
+
try {
|
|
32
|
+
return new Date().getTimezoneOffset();
|
|
33
|
+
}
|
|
34
|
+
catch (_a) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
let cachedDeviceInfo = null;
|
|
39
|
+
function getDeviceInfo() {
|
|
40
|
+
var _a, _b, _c, _d, _e, _f;
|
|
41
|
+
// Return cached info if available
|
|
42
|
+
if (cachedDeviceInfo) {
|
|
43
|
+
return cachedDeviceInfo;
|
|
44
|
+
}
|
|
45
|
+
const win = getWindowSafe();
|
|
46
|
+
const nav = getNavigatorSafe();
|
|
47
|
+
if (!win || !nav) {
|
|
48
|
+
// Return empty values for server-side or non-browser environments
|
|
49
|
+
return {
|
|
50
|
+
user_agent: '',
|
|
51
|
+
locale: '',
|
|
52
|
+
screen_width: null,
|
|
53
|
+
screen_height: null,
|
|
54
|
+
viewport_width: null,
|
|
55
|
+
viewport_height: null,
|
|
56
|
+
timezone: '',
|
|
57
|
+
timezone_offset: null,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const userAgent = nav.userAgent || '';
|
|
61
|
+
cachedDeviceInfo = {
|
|
62
|
+
// Send raw user_agent - server will parse browser/os info
|
|
63
|
+
user_agent: userAgent.length > 500 ? userAgent.substring(0, 500) : userAgent,
|
|
64
|
+
locale: nav.language || '',
|
|
65
|
+
screen_width: (_b = (_a = win.screen) === null || _a === void 0 ? void 0 : _a.width) !== null && _b !== void 0 ? _b : null,
|
|
66
|
+
screen_height: (_d = (_c = win.screen) === null || _c === void 0 ? void 0 : _c.height) !== null && _d !== void 0 ? _d : null,
|
|
67
|
+
viewport_width: (_e = win.innerWidth) !== null && _e !== void 0 ? _e : null,
|
|
68
|
+
viewport_height: (_f = win.innerHeight) !== null && _f !== void 0 ? _f : null,
|
|
69
|
+
timezone: getSafeTimezone(),
|
|
70
|
+
timezone_offset: getSafeTimezoneOffset(),
|
|
71
|
+
};
|
|
72
|
+
return cachedDeviceInfo;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get device info as a flat record suitable for event metadata
|
|
76
|
+
* Only includes non-null values
|
|
77
|
+
*/
|
|
78
|
+
function getDeviceInfoForMetadata() {
|
|
79
|
+
const info = getDeviceInfo();
|
|
80
|
+
const result = {};
|
|
81
|
+
if (info.user_agent)
|
|
82
|
+
result['user_agent'] = info.user_agent;
|
|
83
|
+
if (info.locale)
|
|
84
|
+
result['locale'] = info.locale;
|
|
85
|
+
if (info.screen_width !== null)
|
|
86
|
+
result['screen_width'] = info.screen_width;
|
|
87
|
+
if (info.screen_height !== null)
|
|
88
|
+
result['screen_height'] = info.screen_height;
|
|
89
|
+
if (info.viewport_width !== null)
|
|
90
|
+
result['viewport_width'] = info.viewport_width;
|
|
91
|
+
if (info.viewport_height !== null)
|
|
92
|
+
result['viewport_height'] = info.viewport_height;
|
|
93
|
+
if (info.timezone)
|
|
94
|
+
result['timezone'] = info.timezone;
|
|
95
|
+
if (info.timezone_offset !== null)
|
|
96
|
+
result['timezone_offset'] = info.timezone_offset;
|
|
97
|
+
return result;
|
|
98
|
+
}
|
package/dist/Network.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { WolvesUser } from './WolvesUser';
|
|
2
2
|
export declare const API_LOCAL = "http://localhost:8000/api";
|
|
3
3
|
export declare const API_DEV = "https://wolves-nova-dev.azurewebsites.net/api";
|
|
4
|
+
export declare const API_PROD = "https://wolves-nova.azurewebsites.net/api";
|
|
5
|
+
export type ApiEnvironment = 'local' | 'dev' | 'prod';
|
|
4
6
|
export declare class Network {
|
|
5
7
|
private sdkKey;
|
|
6
8
|
private api;
|
|
7
|
-
constructor(sdkKey: string,
|
|
9
|
+
constructor(sdkKey: string, apiEnv?: ApiEnvironment);
|
|
8
10
|
fetchConfig(user: WolvesUser, sinceTime?: number, retries?: number, backoff?: number): Promise<any>;
|
|
9
11
|
sendEvents(events: any[], retries?: number, backoff?: number): Promise<void>;
|
|
10
12
|
}
|
package/dist/Network.js
CHANGED
|
@@ -9,17 +9,30 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.Network = exports.API_DEV = exports.API_LOCAL = void 0;
|
|
12
|
+
exports.Network = exports.API_PROD = exports.API_DEV = exports.API_LOCAL = void 0;
|
|
13
13
|
const Log_1 = require("./Log");
|
|
14
14
|
const WolvesMetadata_1 = require("./WolvesMetadata");
|
|
15
15
|
const RETRYABLE_CODES = [408, 500, 502, 503, 504, 522, 524, 599];
|
|
16
|
-
// API endpoints
|
|
16
|
+
// API endpoints
|
|
17
17
|
exports.API_LOCAL = 'http://localhost:8000/api';
|
|
18
18
|
exports.API_DEV = 'https://wolves-nova-dev.azurewebsites.net/api';
|
|
19
|
+
exports.API_PROD = 'https://wolves-nova.azurewebsites.net/api';
|
|
20
|
+
const API_ENDPOINTS = {
|
|
21
|
+
local: exports.API_LOCAL,
|
|
22
|
+
dev: exports.API_DEV,
|
|
23
|
+
prod: exports.API_PROD,
|
|
24
|
+
};
|
|
25
|
+
const VALID_ENVIRONMENTS = ['local', 'dev', 'prod'];
|
|
26
|
+
function validateAndGetEndpoint(apiEnv) {
|
|
27
|
+
if (!VALID_ENVIRONMENTS.includes(apiEnv)) {
|
|
28
|
+
throw new Error(`Invalid apiEnv: "${apiEnv}". Must be one of: ${VALID_ENVIRONMENTS.join(', ')}`);
|
|
29
|
+
}
|
|
30
|
+
return API_ENDPOINTS[apiEnv];
|
|
31
|
+
}
|
|
19
32
|
class Network {
|
|
20
|
-
constructor(sdkKey,
|
|
33
|
+
constructor(sdkKey, apiEnv = 'prod') {
|
|
21
34
|
this.sdkKey = sdkKey;
|
|
22
|
-
this.api =
|
|
35
|
+
this.api = validateAndGetEndpoint(apiEnv);
|
|
23
36
|
}
|
|
24
37
|
fetchConfig(user_1, sinceTime_1) {
|
|
25
38
|
return __awaiter(this, arguments, void 0, function* (user, sinceTime, retries = 2, backoff = 1000) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { StatsigUser } from './StatsigUser';
|
|
2
|
+
import { Experiment, StatsigUpdateDetails } from './Types';
|
|
3
|
+
export declare class StatsigClient {
|
|
4
|
+
private sdkKey;
|
|
5
|
+
private user;
|
|
6
|
+
private network;
|
|
7
|
+
private store;
|
|
8
|
+
private initialized;
|
|
9
|
+
constructor(sdkKey: string, user: StatsigUser);
|
|
10
|
+
initializeAsync(): Promise<StatsigUpdateDetails>;
|
|
11
|
+
initializeSync(): StatsigUpdateDetails;
|
|
12
|
+
getExperiment(experimentName: string): Experiment;
|
|
13
|
+
logEvent(eventName: string, value?: string | number, metadata?: Record<string, string>): void;
|
|
14
|
+
private logExposure;
|
|
15
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.StatsigClient = void 0;
|
|
13
|
+
const Network_1 = require("./Network");
|
|
14
|
+
const Store_1 = require("./Store");
|
|
15
|
+
class StatsigClient {
|
|
16
|
+
constructor(sdkKey, user) {
|
|
17
|
+
this.initialized = false;
|
|
18
|
+
this.sdkKey = sdkKey;
|
|
19
|
+
this.user = user;
|
|
20
|
+
this.network = new Network_1.Network(sdkKey);
|
|
21
|
+
this.store = new Store_1.Store();
|
|
22
|
+
}
|
|
23
|
+
initializeAsync() {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
const config = yield this.network.fetchConfig(this.user);
|
|
26
|
+
if (config) {
|
|
27
|
+
this.store.setValues(config);
|
|
28
|
+
this.initialized = true;
|
|
29
|
+
return { success: true };
|
|
30
|
+
}
|
|
31
|
+
return { success: false, errorMessage: 'Failed to fetch config' };
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
initializeSync() {
|
|
35
|
+
// In a real implementation, this might load from local storage or cache.
|
|
36
|
+
// For this minimal implementation, we trigger a background fetch.
|
|
37
|
+
this.network.fetchConfig(this.user).then((config) => {
|
|
38
|
+
if (config) {
|
|
39
|
+
this.store.setValues(config);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
this.initialized = true;
|
|
43
|
+
return { success: true };
|
|
44
|
+
}
|
|
45
|
+
getExperiment(experimentName) {
|
|
46
|
+
var _a, _b, _c;
|
|
47
|
+
const config = this.store.getExperiment(experimentName);
|
|
48
|
+
const experiment = {
|
|
49
|
+
name: experimentName,
|
|
50
|
+
value: (_a = config === null || config === void 0 ? void 0 : config.value) !== null && _a !== void 0 ? _a : {},
|
|
51
|
+
ruleID: (_b = config === null || config === void 0 ? void 0 : config.rule_id) !== null && _b !== void 0 ? _b : '',
|
|
52
|
+
groupName: (_c = config === null || config === void 0 ? void 0 : config.group) !== null && _c !== void 0 ? _c : null,
|
|
53
|
+
get: (key, defaultValue) => {
|
|
54
|
+
var _a;
|
|
55
|
+
const val = (_a = config === null || config === void 0 ? void 0 : config.value) === null || _a === void 0 ? void 0 : _a[key];
|
|
56
|
+
if (val === undefined || val === null) {
|
|
57
|
+
return defaultValue;
|
|
58
|
+
}
|
|
59
|
+
return val;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
// Log exposure
|
|
63
|
+
this.logExposure(experimentName, config);
|
|
64
|
+
return experiment;
|
|
65
|
+
}
|
|
66
|
+
logEvent(eventName, value, metadata) {
|
|
67
|
+
const event = {
|
|
68
|
+
eventName,
|
|
69
|
+
value,
|
|
70
|
+
metadata,
|
|
71
|
+
user: this.user,
|
|
72
|
+
time: Date.now(),
|
|
73
|
+
};
|
|
74
|
+
this.network.sendEvents([event]);
|
|
75
|
+
}
|
|
76
|
+
logExposure(experimentName, experiment) {
|
|
77
|
+
var _a, _b, _c;
|
|
78
|
+
const exposureEvent = {
|
|
79
|
+
eventName: 'statsig::exposure',
|
|
80
|
+
user: this.user,
|
|
81
|
+
time: Date.now(),
|
|
82
|
+
metadata: {
|
|
83
|
+
config: experimentName,
|
|
84
|
+
ruleID: (_a = experiment === null || experiment === void 0 ? void 0 : experiment.rule_id) !== null && _a !== void 0 ? _a : '',
|
|
85
|
+
group: (_b = experiment === null || experiment === void 0 ? void 0 : experiment.group) !== null && _b !== void 0 ? _b : '',
|
|
86
|
+
value: JSON.stringify((_c = experiment === null || experiment === void 0 ? void 0 : experiment.value) !== null && _c !== void 0 ? _c : {}),
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
this.network.sendEvents([exposureEvent]);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.StatsigClient = StatsigClient;
|
package/dist/WolvesClient.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export declare class WolvesClient {
|
|
|
23
23
|
private logger;
|
|
24
24
|
private loadingStatus;
|
|
25
25
|
private initializePromise;
|
|
26
|
-
constructor(sdkKey: string, user: WolvesUser);
|
|
26
|
+
constructor(sdkKey: string, user: WolvesUser, apiEnv?: string);
|
|
27
27
|
/**
|
|
28
28
|
* Returns the current loading status of the client.
|
|
29
29
|
*/
|
package/dist/WolvesClient.js
CHANGED
|
@@ -22,12 +22,12 @@ function createUpdateDetails(success, source, duration, error, warnings = []) {
|
|
|
22
22
|
return { success, source, duration, error, warnings };
|
|
23
23
|
}
|
|
24
24
|
class WolvesClient {
|
|
25
|
-
constructor(sdkKey, user) {
|
|
25
|
+
constructor(sdkKey, user, apiEnv = 'prod') {
|
|
26
26
|
this.loadingStatus = 'Uninitialized';
|
|
27
27
|
this.initializePromise = null;
|
|
28
28
|
this.sdkKey = sdkKey;
|
|
29
29
|
this.user = user;
|
|
30
|
-
this.network = new Network_1.Network(sdkKey);
|
|
30
|
+
this.network = new Network_1.Network(sdkKey, apiEnv);
|
|
31
31
|
this.store = new Store_1.Store(sdkKey);
|
|
32
32
|
this.logger = new EventLogger_1.EventLogger(this.network);
|
|
33
33
|
}
|
package/dist/WolvesMetadata.d.ts
CHANGED
package/dist/WolvesMetadata.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WolvesMetadataProvider = exports.SDK_TYPE = exports.SDK_VERSION = void 0;
|
|
4
|
-
exports.SDK_VERSION = '1.0.
|
|
4
|
+
exports.SDK_VERSION = '1.0.6';
|
|
5
5
|
exports.SDK_TYPE = 'wolves-js-client';
|
|
6
6
|
let metadata = {
|
|
7
7
|
sdk_version: exports.SDK_VERSION,
|
package/dist/index.d.ts
CHANGED
|
@@ -8,3 +8,4 @@ export type { WolvesMetadata } from './WolvesMetadata';
|
|
|
8
8
|
export { Storage } from './StorageProvider';
|
|
9
9
|
export type { StorageProvider } from './StorageProvider';
|
|
10
10
|
export type { DataSource, DataAdapterResult } from './Store';
|
|
11
|
+
export type { ApiEnvironment } from './Network';
|