@statsig/client-core 3.13.0 → 3.14.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statsig/client-core",
3
- "version": "3.13.0",
3
+ "version": "3.14.1",
4
4
  "dependencies": {},
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -93,7 +93,7 @@ class ErrorBoundary {
93
93
  const sdkType = SDKType_1.SDKType._get(this._sdkKey);
94
94
  const statsigMetadata = StatsigMetadata_1.StatsigMetadataProvider.get();
95
95
  const info = isError ? unwrapped.stack : _getDescription(unwrapped);
96
- const body = JSON.stringify(Object.assign({ tag, exception: name, info }, Object.assign(Object.assign({}, statsigMetadata), { sdkType })));
96
+ const body = Object.assign({ tag, exception: name, info, statsigOptions: _getStatsigOptionLoggingCopy(this._options) }, Object.assign(Object.assign({}, statsigMetadata), { sdkType }));
97
97
  const func = (_f = (_e = (_d = this._options) === null || _d === void 0 ? void 0 : _d.networkConfig) === null || _e === void 0 ? void 0 : _e.networkOverrideFunc) !== null && _f !== void 0 ? _f : fetch;
98
98
  yield func(exports.EXCEPTION_ENDPOINT, {
99
99
  method: 'POST',
@@ -103,7 +103,7 @@ class ErrorBoundary {
103
103
  'STATSIG-SDK-VERSION': String(statsigMetadata.sdkVersion),
104
104
  'Content-Type': 'application/json',
105
105
  },
106
- body,
106
+ body: JSON.stringify(body),
107
107
  });
108
108
  (_g = this._emitter) === null || _g === void 0 ? void 0 : _g.call(this, {
109
109
  name: 'error',
@@ -155,3 +155,41 @@ function _getAllInstanceMethodNames(instance) {
155
155
  }
156
156
  return Array.from(names);
157
157
  }
158
+ function _getStatsigOptionLoggingCopy(options) {
159
+ if (!options) {
160
+ return {};
161
+ }
162
+ const loggingCopy = {};
163
+ Object.entries(options).forEach(([option, value]) => {
164
+ const valueType = typeof value;
165
+ switch (valueType) {
166
+ case 'number':
167
+ case 'bigint':
168
+ case 'boolean':
169
+ loggingCopy[String(option)] = value;
170
+ break;
171
+ case 'string':
172
+ if (value.length < 50) {
173
+ loggingCopy[String(option)] = value;
174
+ }
175
+ else {
176
+ loggingCopy[String(option)] = 'set';
177
+ }
178
+ break;
179
+ case 'object':
180
+ if (option === 'environment') {
181
+ loggingCopy['environment'] = value;
182
+ }
183
+ else if (option === 'networkConfig') {
184
+ loggingCopy['networkConfig'] = value;
185
+ }
186
+ else {
187
+ loggingCopy[String(option)] = value != null ? 'set' : 'unset';
188
+ }
189
+ break;
190
+ default:
191
+ // Ignore other fields
192
+ }
193
+ });
194
+ return loggingCopy;
195
+ }
@@ -230,13 +230,7 @@ class NetworkCore {
230
230
  var _a;
231
231
  return __awaiter(this, void 0, void 0, function* () {
232
232
  const body = args.body;
233
- if (!args.isCompressable ||
234
- this._options.disableCompression ||
235
- typeof body !== 'string' ||
236
- SDKFlags_1.SDKFlags.get(args.sdkKey, 'enable_log_event_compression') !== true ||
237
- (0, __StatsigGlobal_1._getStatsigGlobalFlag)('no-compress') != null ||
238
- typeof CompressionStream === 'undefined' ||
239
- typeof TextEncoder === 'undefined') {
233
+ if (typeof body !== 'string' || !_allowCompression(args, this._options)) {
240
234
  return;
241
235
  }
242
236
  try {
@@ -295,6 +289,24 @@ const _populateRequestBody = (args, data) => {
295
289
  sdkType,
296
290
  fallbackUrl }) }));
297
291
  };
292
+ function _allowCompression(args, options) {
293
+ if (!args.isCompressable) {
294
+ return false;
295
+ }
296
+ if (options.disableCompression) {
297
+ return false;
298
+ }
299
+ if ((args.urlConfig.customUrl != null || args.urlConfig.fallbackUrls != null) &&
300
+ SDKFlags_1.SDKFlags.get(args.sdkKey, 'enable_log_event_compression') !== true) {
301
+ return false;
302
+ }
303
+ if ((0, __StatsigGlobal_1._getStatsigGlobalFlag)('no-compress') != null ||
304
+ typeof CompressionStream === 'undefined' ||
305
+ typeof TextEncoder === 'undefined') {
306
+ return false;
307
+ }
308
+ return true;
309
+ }
298
310
  function _getErrorMessage(controller, error) {
299
311
  if ((controller === null || controller === void 0 ? void 0 : controller.signal.aborted) &&
300
312
  typeof controller.signal.reason === 'string') {
@@ -13,7 +13,6 @@ export declare class NetworkFallbackResolver {
13
13
  setErrorBoundary(errorBoundary: ErrorBoundary): void;
14
14
  tryBumpExpiryTime(sdkKey: string, urlConfig: UrlConfiguration): void;
15
15
  getActiveFallbackUrl(sdkKey: string, urlConfig: UrlConfiguration): string | null;
16
- getFallbackFromProvided(url: string): string | null;
17
16
  tryFetchUpdatedFallbackInfo(sdkKey: string, urlConfig: UrlConfiguration, errorMessage: string | null, timedOut: boolean): Promise<boolean>;
18
17
  private _updateFallbackInfoWithNewUrl;
19
18
  private _tryFetchFallbackUrlsFromNetwork;
@@ -38,13 +38,18 @@ class NetworkFallbackResolver {
38
38
  }
39
39
  getActiveFallbackUrl(sdkKey, urlConfig) {
40
40
  var _a, _b;
41
+ if (urlConfig.customUrl != null && urlConfig.fallbackUrls != null) {
42
+ return null;
43
+ }
41
44
  let info = this._fallbackInfo;
42
45
  if (info == null) {
43
46
  info = (_a = _readFallbackInfoFromCache(sdkKey)) !== null && _a !== void 0 ? _a : {};
44
47
  this._fallbackInfo = info;
45
48
  }
46
49
  const entry = info[urlConfig.endpoint];
47
- if (!entry || Date.now() > ((_b = entry.expiryTime) !== null && _b !== void 0 ? _b : 0)) {
50
+ if (!entry ||
51
+ Date.now() > ((_b = entry.expiryTime) !== null && _b !== void 0 ? _b : 0) ||
52
+ urlConfig.getChecksum() !== entry.urlConfigChecksum) {
48
53
  delete info[urlConfig.endpoint];
49
54
  this._fallbackInfo = info;
50
55
  _tryWriteFallbackInfoToCache(sdkKey, this._fallbackInfo);
@@ -55,13 +60,6 @@ class NetworkFallbackResolver {
55
60
  }
56
61
  return null;
57
62
  }
58
- getFallbackFromProvided(url) {
59
- const path = _extractPathFromUrl(url);
60
- if (path) {
61
- return url.replace(path, '');
62
- }
63
- return null;
64
- }
65
63
  tryFetchUpdatedFallbackInfo(sdkKey, urlConfig, errorMessage, timedOut) {
66
64
  var _a, _b;
67
65
  return __awaiter(this, void 0, void 0, function* () {
@@ -77,7 +75,7 @@ class NetworkFallbackResolver {
77
75
  if (!newUrl) {
78
76
  return false;
79
77
  }
80
- this._updateFallbackInfoWithNewUrl(sdkKey, urlConfig.endpoint, newUrl);
78
+ this._updateFallbackInfoWithNewUrl(sdkKey, urlConfig, newUrl);
81
79
  return true;
82
80
  }
83
81
  catch (error) {
@@ -86,13 +84,15 @@ class NetworkFallbackResolver {
86
84
  }
87
85
  });
88
86
  }
89
- _updateFallbackInfoWithNewUrl(sdkKey, endpoint, newUrl) {
87
+ _updateFallbackInfoWithNewUrl(sdkKey, urlConfig, newUrl) {
90
88
  var _a, _b, _c;
91
89
  const newFallbackInfo = {
90
+ urlConfigChecksum: urlConfig.getChecksum(),
92
91
  url: newUrl,
93
92
  expiryTime: Date.now() + DEFAULT_TTL_MS,
94
93
  previous: [],
95
94
  };
95
+ const endpoint = urlConfig.endpoint;
96
96
  const previousInfo = (_a = this._fallbackInfo) === null || _a === void 0 ? void 0 : _a[endpoint];
97
97
  if (previousInfo) {
98
98
  newFallbackInfo.previous.push(...previousInfo.previous);
package/src/SafeJs.d.ts CHANGED
@@ -4,3 +4,4 @@ export declare const _isServerEnv: () => boolean;
4
4
  export declare const _addWindowEventListenerSafe: (key: string, listener: () => void) => void;
5
5
  export declare const _addDocumentEventListenerSafe: (key: string, listener: () => void) => void;
6
6
  export declare const _getCurrentPageUrlSafe: () => string | undefined;
7
+ export declare const _getUnloadEvent: () => string;
package/src/SafeJs.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports._getCurrentPageUrlSafe = exports._addDocumentEventListenerSafe = exports._addWindowEventListenerSafe = exports._isServerEnv = exports._getDocumentSafe = exports._getWindowSafe = void 0;
3
+ exports._getUnloadEvent = exports._getCurrentPageUrlSafe = exports._addDocumentEventListenerSafe = exports._addWindowEventListenerSafe = exports._isServerEnv = exports._getDocumentSafe = exports._getWindowSafe = void 0;
4
4
  const _getWindowSafe = () => {
5
5
  return typeof window !== 'undefined' ? window : null;
6
6
  };
@@ -46,3 +46,12 @@ const _getCurrentPageUrlSafe = () => {
46
46
  }
47
47
  };
48
48
  exports._getCurrentPageUrlSafe = _getCurrentPageUrlSafe;
49
+ const _getUnloadEvent = () => {
50
+ const win = (0, exports._getWindowSafe)();
51
+ if (!win) {
52
+ return 'beforeunload';
53
+ }
54
+ const eventType = 'onpagehide' in win ? 'pagehide' : 'beforeunload';
55
+ return eventType;
56
+ };
57
+ exports._getUnloadEvent = _getUnloadEvent;
@@ -1,4 +1,4 @@
1
- export declare const SDK_VERSION = "3.13.0";
1
+ export declare const SDK_VERSION = "3.14.1";
2
2
  export type StatsigMetadata = {
3
3
  readonly [key: string]: string | undefined;
4
4
  readonly appVersion?: string;
@@ -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 = '3.13.0';
4
+ exports.SDK_VERSION = '3.14.1';
5
5
  let metadata = {
6
6
  sdkVersion: exports.SDK_VERSION,
7
7
  sdkType: 'js-mono', // js-mono is overwritten by Precomp and OnDevice clients
@@ -8,4 +8,5 @@ export declare class UrlConfiguration {
8
8
  readonly fallbackUrls: string[] | null;
9
9
  constructor(endpoint: Endpoint, customUrl: string | undefined | null, customApi: string | undefined | null, fallbackUrls: string[] | undefined | null);
10
10
  getUrl(): string;
11
+ getChecksum(): string;
11
12
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UrlConfiguration = void 0;
4
+ const Hashing_1 = require("./Hashing");
4
5
  const NetworkConfig_1 = require("./NetworkConfig");
5
6
  const ENDPOINT_DNS_KEY_MAP = {
6
7
  [NetworkConfig_1.Endpoint._initialize]: 'i',
@@ -31,5 +32,10 @@ class UrlConfiguration {
31
32
  var _a;
32
33
  return (_a = this.customUrl) !== null && _a !== void 0 ? _a : this.defaultUrl;
33
34
  }
35
+ getChecksum() {
36
+ var _a;
37
+ const fallbacks = ((_a = this.fallbackUrls) !== null && _a !== void 0 ? _a : []).sort().join(',');
38
+ return (0, Hashing_1._DJB2)(this.customUrl + fallbacks);
39
+ }
34
40
  }
35
41
  exports.UrlConfiguration = UrlConfiguration;
@@ -30,14 +30,10 @@ exports._notifyVisibilityChanged = _notifyVisibilityChanged;
30
30
  (0, exports._notifyVisibilityChanged)(FOREGROUND);
31
31
  });
32
32
  (0, SafeJs_1._addWindowEventListenerSafe)('blur', () => (0, exports._notifyVisibilityChanged)(BACKGROUND));
33
- (0, SafeJs_1._addWindowEventListenerSafe)('beforeunload', () => {
34
- isUnloading = true;
35
- (0, exports._notifyVisibilityChanged)(BACKGROUND);
36
- });
37
33
  (0, SafeJs_1._addDocumentEventListenerSafe)('visibilitychange', () => {
38
34
  (0, exports._notifyVisibilityChanged)(document.visibilityState === 'visible' ? FOREGROUND : BACKGROUND);
39
35
  });
40
- (0, SafeJs_1._addDocumentEventListenerSafe)('pagehide', () => {
36
+ (0, SafeJs_1._addWindowEventListenerSafe)((0, SafeJs_1._getUnloadEvent)(), () => {
41
37
  isUnloading = true;
42
38
  (0, exports._notifyVisibilityChanged)(BACKGROUND);
43
39
  });
@@ -0,0 +1,16 @@
1
+ import { DynamicConfigEvaluationOptions, ExperimentEvaluationOptions, FeatureGateEvaluationOptions, LayerEvaluationOptions, ParameterStoreEvaluationOptions } from '../EvaluationOptions';
2
+ import { EvaluationDetails } from '../EvaluationTypes';
3
+ import { OverrideAdapter } from '../OverrideAdapter';
4
+ import { ParamStoreConfig } from '../ParamStoreTypes';
5
+ import { DynamicConfig, Experiment, FeatureGate, Layer, ParameterStore } from '../StatsigTypes';
6
+ import { StatsigUser } from '../StatsigUser';
7
+ export declare class MockOverrideAdapter implements OverrideAdapter {
8
+ getGateOverride(_current: FeatureGate, _user: StatsigUser, _options?: FeatureGateEvaluationOptions): FeatureGate | null;
9
+ getDynamicConfigOverride(_current: DynamicConfig, _user: StatsigUser, _options?: DynamicConfigEvaluationOptions): DynamicConfig | null;
10
+ getExperimentOverride(_current: Experiment, _user: StatsigUser, _options?: ExperimentEvaluationOptions): Experiment | null;
11
+ getLayerOverride(_current: Layer, _user: StatsigUser, _options?: LayerEvaluationOptions): Layer | null;
12
+ getParamStoreOverride(_current: ParameterStore, _options?: ParameterStoreEvaluationOptions): {
13
+ config: ParamStoreConfig;
14
+ details: EvaluationDetails;
15
+ } | null;
16
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MockOverrideAdapter = void 0;
4
+ class MockOverrideAdapter {
5
+ getGateOverride(_current, _user, _options) {
6
+ return null;
7
+ }
8
+ getDynamicConfigOverride(_current, _user, _options) {
9
+ return null;
10
+ }
11
+ getExperimentOverride(_current, _user, _options) {
12
+ return null;
13
+ }
14
+ getLayerOverride(_current, _user, _options) {
15
+ return null;
16
+ }
17
+ getParamStoreOverride(_current, _options) {
18
+ return null;
19
+ }
20
+ }
21
+ exports.MockOverrideAdapter = MockOverrideAdapter;