wolves-js-client 1.0.4 → 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.
@@ -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, api?: 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 - switch between local and production
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, api = exports.API_DEV) {
33
+ constructor(sdkKey, apiEnv = 'prod') {
21
34
  this.sdkKey = sdkKey;
22
- this.api = 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;
@@ -0,0 +1,6 @@
1
+ export type StatsigUser = {
2
+ userID?: string;
3
+ email?: string;
4
+ ip?: string;
5
+ custom?: Record<string, string | number | boolean | Array<string>>;
6
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/Store.d.ts CHANGED
@@ -9,7 +9,16 @@ export type InitializeResponse = {
9
9
  has_updates: boolean;
10
10
  time: number;
11
11
  };
12
- export type DataSource = 'Network' | 'Cache' | 'NetworkNotModified' | 'NoValues';
12
+ export type DataSource = 'Network' | 'Cache' | 'NetworkNotModified' | 'NoValues' | 'Uninitialized';
13
+ export type EvaluationDetails = {
14
+ source: DataSource;
15
+ reason: string;
16
+ isRecognized: boolean;
17
+ };
18
+ export type ExperimentEvaluation = {
19
+ config: ExperimentConfig | null;
20
+ details: EvaluationDetails;
21
+ };
13
22
  export type DataAdapterResult = {
14
23
  source: DataSource;
15
24
  data: string;
@@ -23,6 +32,7 @@ export type DataAdapterResult = {
23
32
  export declare class Store {
24
33
  private values;
25
34
  private source;
35
+ private isInitialized;
26
36
  private sdkKey;
27
37
  private cacheLimit;
28
38
  private inMemoryCache;
@@ -60,7 +70,23 @@ export declare class Store {
60
70
  * Reset the store for a new user.
61
71
  */
62
72
  reset(): void;
63
- getExperiment(name: string): ExperimentConfig | null;
73
+ /**
74
+ * Mark the store as initialized.
75
+ */
76
+ finalize(): void;
77
+ /**
78
+ * Get experiment with evaluation details including reason.
79
+ * Following Statsig SDK pattern for exposure reasons:
80
+ * - Uninitialized: API called before initialize
81
+ * - NoValues: No data available
82
+ * - Network:Recognized / Network:Unrecognized
83
+ * - Cache:Recognized / Cache:Unrecognized
84
+ */
85
+ getExperiment(name: string): ExperimentEvaluation;
86
+ /**
87
+ * Get the base source for building reason string.
88
+ */
89
+ private _getBaseSource;
64
90
  getValues(): InitializeResponse | null;
65
91
  getSource(): DataSource;
66
92
  getLastUpdateTime(): number | undefined;
package/dist/Store.js CHANGED
@@ -8,13 +8,13 @@ const CACHE_LIMIT = 10;
8
8
  const MAX_CACHE_WRITE_ATTEMPTS = 8;
9
9
  const LAST_MODIFIED_KEY = 'wolves.last_modified_time';
10
10
  /**
11
- * Generate a hash for user identity to create unique cache keys.
11
+ * Generate a user identifier for cache keys.
12
+ * Only uses userID as the unique identifier.
12
13
  */
13
- function _getUserHash(user) {
14
- if (!user)
14
+ function _getUserIdentifier(user) {
15
+ if (!user || !user.userID)
15
16
  return 'anonymous';
16
- const parts = [user.userID || '', user.email || ''];
17
- return parts.join('|');
17
+ return user.userID;
18
18
  }
19
19
  /**
20
20
  * Store class that manages experiment configurations with caching support.
@@ -24,6 +24,7 @@ class Store {
24
24
  constructor(sdkKey = '') {
25
25
  this.values = null;
26
26
  this.source = 'NoValues';
27
+ this.isInitialized = false;
27
28
  this.cacheLimit = CACHE_LIMIT;
28
29
  this.inMemoryCache = new Map();
29
30
  this.sdkKey = sdkKey;
@@ -32,7 +33,7 @@ class Store {
32
33
  * Get the cache key for a specific user.
33
34
  */
34
35
  getCacheKey(user) {
35
- const userHash = _getUserHash(user);
36
+ const userHash = _getUserIdentifier(user);
36
37
  return `${CACHE_KEY_PREFIX}.${this.sdkKey}.${userHash}`;
37
38
  }
38
39
  /**
@@ -109,7 +110,7 @@ class Store {
109
110
  source: 'Network',
110
111
  data: JSON.stringify(values),
111
112
  receivedAt: Date.now(),
112
- fullUserHash: _getUserHash(user),
113
+ fullUserHash: _getUserIdentifier(user),
113
114
  };
114
115
  const cacheKey = this.getCacheKey(user);
115
116
  this.inMemoryCache.set(cacheKey, result);
@@ -164,12 +165,67 @@ class Store {
164
165
  reset() {
165
166
  this.values = null;
166
167
  this.source = 'NoValues';
168
+ this.isInitialized = false;
167
169
  }
170
+ /**
171
+ * Mark the store as initialized.
172
+ */
173
+ finalize() {
174
+ this.isInitialized = true;
175
+ }
176
+ /**
177
+ * Get experiment with evaluation details including reason.
178
+ * Following Statsig SDK pattern for exposure reasons:
179
+ * - Uninitialized: API called before initialize
180
+ * - NoValues: No data available
181
+ * - Network:Recognized / Network:Unrecognized
182
+ * - Cache:Recognized / Cache:Unrecognized
183
+ */
168
184
  getExperiment(name) {
185
+ // Check if uninitialized
186
+ if (!this.isInitialized) {
187
+ return {
188
+ config: null,
189
+ details: {
190
+ source: 'Uninitialized',
191
+ reason: 'Uninitialized',
192
+ isRecognized: false,
193
+ },
194
+ };
195
+ }
196
+ // Check if no values
169
197
  if (!this.values || !this.values.dynamic_configs) {
170
- return null;
198
+ return {
199
+ config: null,
200
+ details: {
201
+ source: this.source,
202
+ reason: 'NoValues',
203
+ isRecognized: false,
204
+ },
205
+ };
171
206
  }
172
- return this.values.dynamic_configs[name] || null;
207
+ const config = this.values.dynamic_configs[name] || null;
208
+ const isRecognized = config !== null;
209
+ const baseSource = this._getBaseSource();
210
+ const subreason = isRecognized ? 'Recognized' : 'Unrecognized';
211
+ const reason = `${baseSource}:${subreason}`;
212
+ return {
213
+ config,
214
+ details: {
215
+ source: this.source,
216
+ reason,
217
+ isRecognized,
218
+ },
219
+ };
220
+ }
221
+ /**
222
+ * Get the base source for building reason string.
223
+ */
224
+ _getBaseSource() {
225
+ if (this.source === 'NetworkNotModified') {
226
+ return 'Network';
227
+ }
228
+ return this.source;
173
229
  }
174
230
  getValues() {
175
231
  return this.values;
@@ -1,5 +1,5 @@
1
1
  import { WolvesUser } from './WolvesUser';
2
- import { Store, DataSource } from './Store';
2
+ import { DataSource } from './Store';
3
3
  import { Experiment } from './Types';
4
4
  export type LoadingStatus = 'Uninitialized' | 'Loading' | 'Ready';
5
5
  export type WolvesUpdateDetails = {
@@ -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
  */
@@ -107,8 +107,4 @@ export declare class WolvesClient {
107
107
  logEvent(eventName: string, value?: string | number, metadata?: Record<string, string>): void;
108
108
  shutdown(): Promise<void>;
109
109
  private logExposure;
110
- /**
111
- * Get the underlying store (for testing purposes).
112
- */
113
- getStore(): Store;
114
110
  }
@@ -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
  }
@@ -147,6 +147,7 @@ class WolvesClient {
147
147
  }
148
148
  // Timeout case - return with cached values
149
149
  this.loadingStatus = 'Ready';
150
+ this.store.finalize();
150
151
  return createUpdateDetails(cachedResult != null, this.store.getSource(), performance.now() - startTime, cachedResult ? null : new Error('Timeout waiting for network'), warnings);
151
152
  });
152
153
  }
@@ -172,14 +173,17 @@ class WolvesClient {
172
173
  this.store.setValuesFromResult(notModifiedResult, user);
173
174
  }
174
175
  this.loadingStatus = 'Ready';
176
+ this.store.finalize();
175
177
  return createUpdateDetails(true, this.store.getSource(), performance.now() - startTime, null, warnings);
176
178
  }
177
179
  // Network fetch failed
178
180
  this.loadingStatus = 'Ready';
181
+ this.store.finalize();
179
182
  return createUpdateDetails(cachedResult != null, this.store.getSource(), performance.now() - startTime, cachedResult ? null : new Error('Failed to fetch config from network'), [...warnings, 'NetworkFetchFailed']);
180
183
  }
181
184
  catch (e) {
182
185
  this.loadingStatus = 'Ready';
186
+ this.store.finalize();
183
187
  const err = e instanceof Error ? e : new Error(String(e));
184
188
  return createUpdateDetails(cachedResult != null, this.store.getSource(), performance.now() - startTime, cachedResult ? null : err, [...warnings, 'NetworkFetchFailed']);
185
189
  }
@@ -221,6 +225,7 @@ class WolvesClient {
221
225
  }
222
226
  this.store.setValuesFromResult(cachedResult, user);
223
227
  this.loadingStatus = 'Ready';
228
+ this.store.finalize();
224
229
  // Trigger background refresh unless disabled
225
230
  if (options === null || options === void 0 ? void 0 : options.disableBackgroundCacheRefresh) {
226
231
  return createUpdateDetails(true, this.store.getSource(), performance.now() - startTime, null, warnings);
@@ -263,7 +268,7 @@ class WolvesClient {
263
268
  }
264
269
  getExperiment(experimentName) {
265
270
  var _a, _b, _c;
266
- const config = this.store.getExperiment(experimentName);
271
+ const { config, details } = this.store.getExperiment(experimentName);
267
272
  const experiment = {
268
273
  name: experimentName,
269
274
  value: (_a = config === null || config === void 0 ? void 0 : config.value) !== null && _a !== void 0 ? _a : {},
@@ -278,8 +283,8 @@ class WolvesClient {
278
283
  return val;
279
284
  }
280
285
  };
281
- // Log exposure
282
- this.logExposure(experimentName, config);
286
+ // Log exposure with reason
287
+ this.logExposure(experimentName, config, details);
283
288
  return experiment;
284
289
  }
285
290
  /**
@@ -289,7 +294,7 @@ class WolvesClient {
289
294
  */
290
295
  getExperimentForTest(experimentName, groupName) {
291
296
  var _a;
292
- const config = this.store.getExperiment(experimentName);
297
+ const { config, details } = this.store.getExperiment(experimentName);
293
298
  const experimentId = (_a = config === null || config === void 0 ? void 0 : config.experiment_id) !== null && _a !== void 0 ? _a : '';
294
299
  const experiment = {
295
300
  name: experimentName,
@@ -301,7 +306,7 @@ class WolvesClient {
301
306
  }
302
307
  };
303
308
  // Log exposure with the specified group and experiment ID from store
304
- this.logExposure(experimentName, { group: groupName, experiment_id: experimentId, value: {} });
309
+ this.logExposure(experimentName, { group: groupName, experiment_id: experimentId, value: {} }, details);
305
310
  return experiment;
306
311
  }
307
312
  logEvent(eventName, value, metadata) {
@@ -319,7 +324,7 @@ class WolvesClient {
319
324
  yield this.logger.stop();
320
325
  });
321
326
  }
322
- logExposure(experimentName, experiment) {
327
+ logExposure(experimentName, experiment, details) {
323
328
  var _a, _b, _c;
324
329
  const exposureEvent = {
325
330
  eventName: 'exposure',
@@ -330,15 +335,10 @@ class WolvesClient {
330
335
  experiment_id: (_a = experiment === null || experiment === void 0 ? void 0 : experiment.experiment_id) !== null && _a !== void 0 ? _a : '',
331
336
  group: (_b = experiment === null || experiment === void 0 ? void 0 : experiment.group) !== null && _b !== void 0 ? _b : '',
332
337
  value: JSON.stringify((_c = experiment === null || experiment === void 0 ? void 0 : experiment.value) !== null && _c !== void 0 ? _c : {}),
338
+ reason: details.reason,
333
339
  },
334
340
  };
335
341
  this.logger.enqueue(exposureEvent);
336
342
  }
337
- /**
338
- * Get the underlying store (for testing purposes).
339
- */
340
- getStore() {
341
- return this.store;
342
- }
343
343
  }
344
344
  exports.WolvesClient = WolvesClient;
@@ -1,4 +1,4 @@
1
- export declare const SDK_VERSION = "1.0.4";
1
+ export declare const SDK_VERSION = "1.0.6";
2
2
  export declare const SDK_TYPE = "wolves-js-client";
3
3
  export type WolvesMetadata = {
4
4
  readonly [key: string]: string | undefined | null;
@@ -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';
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';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wolves-js-client",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "A Wolves JavaScript Client SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",