@statsig/client-core 0.0.1-beta.2 → 0.0.1-beta.20

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.
Files changed (53) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/$_StatsigGlobal.js +8 -12
  4. package/src/ClientInterfaces.d.ts +20 -13
  5. package/src/DataAdapterCore.d.ts +32 -0
  6. package/src/DataAdapterCore.js +167 -0
  7. package/src/Diagnostics.js +21 -26
  8. package/src/ErrorBoundary.d.ts +1 -0
  9. package/src/ErrorBoundary.js +39 -86
  10. package/src/EvaluationOptions.d.ts +20 -0
  11. package/src/EvaluationTypes.d.ts +39 -0
  12. package/src/EvaluationTypes.js +2 -0
  13. package/src/EventLogger.d.ts +17 -4
  14. package/src/EventLogger.js +186 -225
  15. package/src/Hashing.d.ts +1 -0
  16. package/src/Hashing.js +23 -4
  17. package/src/Log.js +15 -34
  18. package/src/Monitoring.d.ts +1 -2
  19. package/src/Monitoring.js +68 -27
  20. package/src/NetworkCore.d.ts +13 -5
  21. package/src/NetworkCore.js +96 -164
  22. package/src/OverrideAdapter.d.ts +16 -0
  23. package/src/OverrideAdapter.js +24 -0
  24. package/src/SessionID.js +3 -3
  25. package/src/StableID.js +23 -52
  26. package/src/StatsigClientBase.d.ts +20 -29
  27. package/src/StatsigClientBase.js +57 -247
  28. package/src/StatsigClientEventEmitter.d.ts +55 -28
  29. package/src/StatsigDataAdapter.d.ts +89 -0
  30. package/src/StatsigDataAdapter.js +4 -0
  31. package/src/StatsigEvent.d.ts +9 -18
  32. package/src/StatsigEvent.js +40 -31
  33. package/src/StatsigMetadata.js +5 -16
  34. package/src/StatsigOptionsCommon.d.ts +42 -12
  35. package/src/StatsigTypes.d.ts +23 -15
  36. package/src/StatsigTypes.js +23 -16
  37. package/src/StatsigUser.d.ts +1 -0
  38. package/src/StatsigUser.js +12 -20
  39. package/src/StorageProvider.d.ts +7 -2
  40. package/src/StorageProvider.js +53 -62
  41. package/src/TypedJsonParse.d.ts +8 -0
  42. package/src/TypedJsonParse.js +27 -0
  43. package/src/UUID.js +5 -5
  44. package/src/UrlOverrides.d.ts +1 -0
  45. package/src/UrlOverrides.js +15 -0
  46. package/src/UtitlityTypes.d.ts +3 -0
  47. package/src/UtitlityTypes.js +2 -0
  48. package/src/VisibilityChangeObserver.js +18 -24
  49. package/src/__tests__/MockLocalStorage.js +18 -19
  50. package/src/index.d.ts +12 -3
  51. package/src/index.js +18 -16
  52. package/src/StatsigDataProvider.d.ts +0 -9
  53. /package/src/{StatsigDataProvider.js → EvaluationOptions.js} +0 -0
package/README.md CHANGED
@@ -5,4 +5,4 @@
5
5
 
6
6
  The package that contains all the common logic shared by the various Statsig Javascript packages.
7
7
 
8
- Learn more by visiting: https://docs.statsig.com/client/jsClientSDK
8
+ Learn more by visiting: https://docs.statsig.com/client/javascript-sdk
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statsig/client-core",
3
- "version": "0.0.1-beta.2",
3
+ "version": "0.0.1-beta.20",
4
4
  "dependencies": {},
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -1,14 +1,10 @@
1
1
  "use strict";
2
+ var _a, _b, _c;
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
- var statsigGlobal = {};
4
- if (typeof window !== 'undefined') {
5
- window.__STATSIG__ = statsigGlobal;
6
- }
7
- if (typeof global !== 'undefined') {
8
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
9
- global.__STATSIG__ = statsigGlobal;
10
- }
11
- if (typeof globalThis !== 'undefined') {
12
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
13
- globalThis.__STATSIG__ = statsigGlobal;
14
- }
4
+ const _window = typeof window !== 'undefined' ? window : {};
5
+ const _global = typeof global !== 'undefined' ? global : {};
6
+ const _globalThis = typeof globalThis !== 'undefined' ? globalThis : {};
7
+ const statsigGlobal = (_c = (_b = (_a = _window.__STATSIG__) !== null && _a !== void 0 ? _a : _global.__STATSIG__) !== null && _b !== void 0 ? _b : _globalThis.__STATSIG__) !== null && _c !== void 0 ? _c : {};
8
+ _window.__STATSIG__ = statsigGlobal;
9
+ _global.__STATSIG__ = statsigGlobal;
10
+ _globalThis.__STATSIG__ = statsigGlobal;
@@ -1,28 +1,35 @@
1
- import { EvaluationOptions } from './StatsigClientBase';
1
+ import { DynamicConfigEvaluationOptions, ExperimentEvaluationOptions, FeatureGateEvaluationOptions, LayerEvaluationOptions } from './EvaluationOptions';
2
2
  import { StatsigClientEventEmitterInterface } from './StatsigClientEventEmitter';
3
+ import { EvaluationsDataAdapter, SpecsDataAdapter } from './StatsigDataAdapter';
3
4
  import { StatsigEvent } from './StatsigEvent';
5
+ import { StatsigRuntimeMutableOptions } from './StatsigOptionsCommon';
4
6
  import { DynamicConfig, Experiment, FeatureGate, Layer } from './StatsigTypes';
5
7
  import { StatsigUser } from './StatsigUser';
6
8
  export interface StatsigClientCommonInterface extends StatsigClientEventEmitterInterface {
7
- initialize(): Promise<void>;
9
+ initializeSync(): void;
10
+ initializeAsync(): Promise<void>;
8
11
  shutdown(): Promise<void>;
12
+ updateRuntimeOptions(options: StatsigRuntimeMutableOptions): void;
9
13
  }
10
14
  export interface OnDeviceEvaluationsInterface extends StatsigClientCommonInterface {
11
- checkGate(name: string, user: StatsigUser, options: EvaluationOptions): boolean;
12
- getFeatureGate(name: string, user: StatsigUser, options: EvaluationOptions): FeatureGate;
13
- getDynamicConfig(name: string, user: StatsigUser, options: EvaluationOptions): DynamicConfig;
14
- getExperiment(name: string, user: StatsigUser, options: EvaluationOptions): Experiment;
15
- getLayer(name: string, user: StatsigUser, options: EvaluationOptions): Layer;
15
+ readonly dataAdapter: SpecsDataAdapter;
16
+ checkGate(name: string, user: StatsigUser, options?: FeatureGateEvaluationOptions): boolean;
17
+ getFeatureGate(name: string, user: StatsigUser, options?: FeatureGateEvaluationOptions): FeatureGate;
18
+ getDynamicConfig(name: string, user: StatsigUser, options?: DynamicConfigEvaluationOptions): DynamicConfig;
19
+ getExperiment(name: string, user: StatsigUser, options?: ExperimentEvaluationOptions): Experiment;
20
+ getLayer(name: string, user: StatsigUser, options?: LayerEvaluationOptions): Layer;
16
21
  logEvent(event: StatsigEvent, user: StatsigUser): void;
17
22
  }
18
23
  export interface PrecomputedEvaluationsInterface extends StatsigClientCommonInterface {
24
+ readonly dataAdapter: EvaluationsDataAdapter;
19
25
  getCurrentUser(): StatsigUser;
20
- updateUser(user: StatsigUser): Promise<void>;
21
- checkGate(name: string, options: EvaluationOptions): boolean;
22
- getFeatureGate(name: string, options: EvaluationOptions): FeatureGate;
23
- getDynamicConfig(name: string, options: EvaluationOptions): DynamicConfig;
24
- getExperiment(name: string, options: EvaluationOptions): Experiment;
25
- getLayer(name: string, options: EvaluationOptions): Layer;
26
+ updateUserSync(user: StatsigUser): void;
27
+ updateUserAsync(user: StatsigUser): Promise<void>;
28
+ checkGate(name: string, options?: FeatureGateEvaluationOptions): boolean;
29
+ getFeatureGate(name: string, options?: FeatureGateEvaluationOptions): FeatureGate;
30
+ getDynamicConfig(name: string, options?: DynamicConfigEvaluationOptions): DynamicConfig;
31
+ getExperiment(name: string, options?: ExperimentEvaluationOptions): Experiment;
32
+ getLayer(name: string, options?: LayerEvaluationOptions): Layer;
26
33
  logEvent(event: StatsigEvent): void;
27
34
  }
28
35
  export type StatsigClientInterface = OnDeviceEvaluationsInterface | PrecomputedEvaluationsInterface;
@@ -0,0 +1,32 @@
1
+ import { ErrorBoundary } from './ErrorBoundary';
2
+ import { DataAdapterResult } from './StatsigDataAdapter';
3
+ import { StatsigOptionsCommon } from './StatsigOptionsCommon';
4
+ import { StatsigUser } from './StatsigUser';
5
+ export declare abstract class DataAdapterCore {
6
+ private _adapterName;
7
+ private _cacheSuffix;
8
+ protected _errorBoundary: ErrorBoundary | null;
9
+ private _sdkKey;
10
+ private _inMemoryCache;
11
+ private _lastModifiedStoreKey;
12
+ protected constructor(_adapterName: string, _cacheSuffix: string);
13
+ attach(sdkKey: string, _options: StatsigOptionsCommon | null): void;
14
+ getDataSync(user?: StatsigUser | undefined): DataAdapterResult | null;
15
+ getDataAsync(current: DataAdapterResult | null, user?: StatsigUser): Promise<DataAdapterResult | null>;
16
+ prefetchData(user?: StatsigUser | undefined): Promise<void>;
17
+ setData(data: string, user?: StatsigUser): void;
18
+ /**
19
+ * (Internal Use Only) - Used by \@statsig/react-native-bindings to prime the cache from AsyncStorage
20
+ *
21
+ * @param {Record<string, DataAdapterResult>} cache The values to merge into _inMemoryCache
22
+ */
23
+ __primeInMemoryCache(cache: Record<string, DataAdapterResult>): void;
24
+ protected abstract _fetchFromNetwork(current: string | null, user?: StatsigUser): Promise<string | null>;
25
+ private _fetchLatest;
26
+ protected _getSdkKey(): string;
27
+ protected _getCacheKey(user?: StatsigUser): string;
28
+ protected _addToInMemoryCache(cacheKey: string, result: DataAdapterResult): void;
29
+ private _loadFromCache;
30
+ private _writeToCache;
31
+ private _runLocalStorageCacheEviction;
32
+ }
@@ -0,0 +1,167 @@
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.DataAdapterCore = void 0;
13
+ const ErrorBoundary_1 = require("./ErrorBoundary");
14
+ const Log_1 = require("./Log");
15
+ const Monitoring_1 = require("./Monitoring");
16
+ const StatsigDataAdapter_1 = require("./StatsigDataAdapter");
17
+ const StatsigUser_1 = require("./StatsigUser");
18
+ const StorageProvider_1 = require("./StorageProvider");
19
+ const TypedJsonParse_1 = require("./TypedJsonParse");
20
+ const CACHE_LIMIT = 10;
21
+ class DataAdapterCore {
22
+ constructor(_adapterName, _cacheSuffix) {
23
+ this._adapterName = _adapterName;
24
+ this._cacheSuffix = _cacheSuffix;
25
+ this._errorBoundary = null;
26
+ this._sdkKey = null;
27
+ this._inMemoryCache = {};
28
+ this._lastModifiedStoreKey = `statsig.last_modified_time.${_cacheSuffix}`;
29
+ }
30
+ attach(sdkKey, _options) {
31
+ this._sdkKey = sdkKey;
32
+ this._errorBoundary = new ErrorBoundary_1.ErrorBoundary(sdkKey);
33
+ (0, Monitoring_1.monitorClass)(this._errorBoundary, this);
34
+ }
35
+ getDataSync(user) {
36
+ const cacheKey = this._getCacheKey(user);
37
+ const result = this._inMemoryCache[cacheKey];
38
+ if (result) {
39
+ return result;
40
+ }
41
+ const cache = this._loadFromCache(cacheKey);
42
+ if (cache) {
43
+ this._addToInMemoryCache(cacheKey, cache);
44
+ return this._inMemoryCache[cacheKey];
45
+ }
46
+ return null;
47
+ }
48
+ getDataAsync(current, user) {
49
+ var _a;
50
+ return __awaiter(this, void 0, void 0, function* () {
51
+ const cache = current !== null && current !== void 0 ? current : this.getDataSync(user);
52
+ const latest = yield this._fetchLatest((_a = cache === null || cache === void 0 ? void 0 : cache.data) !== null && _a !== void 0 ? _a : null, user);
53
+ const cacheKey = this._getCacheKey(user);
54
+ if (latest) {
55
+ this._addToInMemoryCache(cacheKey, latest);
56
+ }
57
+ if ((latest === null || latest === void 0 ? void 0 : latest.source) === 'Network' ||
58
+ (latest === null || latest === void 0 ? void 0 : latest.source) === 'NetworkNotModified') {
59
+ yield this._writeToCache(cacheKey, latest);
60
+ }
61
+ return latest;
62
+ });
63
+ }
64
+ prefetchData(user) {
65
+ return __awaiter(this, void 0, void 0, function* () {
66
+ const cacheKey = this._getCacheKey(user);
67
+ const result = yield this.getDataAsync(null, user);
68
+ if (result) {
69
+ this._addToInMemoryCache(cacheKey, Object.assign(Object.assign({}, result), { source: 'Prefetch' }));
70
+ }
71
+ });
72
+ }
73
+ setData(data, user) {
74
+ const cacheKey = this._getCacheKey(user);
75
+ this._addToInMemoryCache(cacheKey, {
76
+ source: 'Bootstrap',
77
+ data,
78
+ receivedAt: Date.now(),
79
+ });
80
+ }
81
+ /**
82
+ * (Internal Use Only) - Used by \@statsig/react-native-bindings to prime the cache from AsyncStorage
83
+ *
84
+ * @param {Record<string, DataAdapterResult>} cache The values to merge into _inMemoryCache
85
+ */
86
+ __primeInMemoryCache(cache) {
87
+ this._inMemoryCache = Object.assign(Object.assign({}, this._inMemoryCache), cache);
88
+ }
89
+ _fetchLatest(current, user) {
90
+ return __awaiter(this, void 0, void 0, function* () {
91
+ const latest = yield this._fetchFromNetwork(current, user);
92
+ if (!latest) {
93
+ Log_1.Log.debug('No response returned for latest value');
94
+ return null;
95
+ }
96
+ const response = (0, TypedJsonParse_1.typedJsonParse)(latest, 'has_updates', 'Failure while attempting to persist latest value');
97
+ if (current && (response === null || response === void 0 ? void 0 : response.has_updates) === false) {
98
+ return {
99
+ source: 'NetworkNotModified',
100
+ data: current,
101
+ receivedAt: Date.now(),
102
+ };
103
+ }
104
+ if ((response === null || response === void 0 ? void 0 : response.has_updates) !== true) {
105
+ return null;
106
+ }
107
+ return { source: 'Network', data: latest, receivedAt: Date.now() };
108
+ });
109
+ }
110
+ _getSdkKey() {
111
+ if (this._sdkKey != null) {
112
+ return this._sdkKey;
113
+ }
114
+ Log_1.Log.error(`${this._adapterName} is not attached to a Client`);
115
+ return '';
116
+ }
117
+ _getCacheKey(user) {
118
+ const key = (0, StatsigUser_1.getUserStorageKey)(this._getSdkKey(), user);
119
+ return `${StatsigDataAdapter_1.DataAdapterCachePrefix}.${this._cacheSuffix}.${key}`;
120
+ }
121
+ _addToInMemoryCache(cacheKey, result) {
122
+ const entries = Object.entries(this._inMemoryCache);
123
+ if (entries.length < CACHE_LIMIT) {
124
+ this._inMemoryCache[cacheKey] = result;
125
+ return;
126
+ }
127
+ const [oldest] = entries.reduce((acc, curr) => {
128
+ return curr[1] < acc[1] ? curr : acc;
129
+ });
130
+ delete this._inMemoryCache[oldest];
131
+ this._inMemoryCache[cacheKey] = result;
132
+ }
133
+ _loadFromCache(cacheKey) {
134
+ var _a;
135
+ const cache = (_a = StorageProvider_1.Storage.getItemSync) === null || _a === void 0 ? void 0 : _a.call(StorageProvider_1.Storage, cacheKey);
136
+ if (cache == null) {
137
+ return null;
138
+ }
139
+ const result = (0, TypedJsonParse_1.typedJsonParse)(cache, 'source', 'Failed to parse cached result');
140
+ return result ? Object.assign(Object.assign({}, result), { source: 'Cache' }) : null;
141
+ }
142
+ _writeToCache(cacheKey, result) {
143
+ return __awaiter(this, void 0, void 0, function* () {
144
+ yield StorageProvider_1.Storage.setItem(cacheKey, JSON.stringify(result));
145
+ yield this._runLocalStorageCacheEviction(cacheKey);
146
+ });
147
+ }
148
+ _runLocalStorageCacheEviction(cacheKey) {
149
+ var _a;
150
+ return __awaiter(this, void 0, void 0, function* () {
151
+ const lastModifiedTimeMap = (_a = (yield (0, StorageProvider_1.getObjectFromStorage)(this._lastModifiedStoreKey))) !== null && _a !== void 0 ? _a : {};
152
+ lastModifiedTimeMap[cacheKey] = Date.now();
153
+ const entries = Object.entries(lastModifiedTimeMap);
154
+ if (entries.length <= CACHE_LIMIT) {
155
+ yield (0, StorageProvider_1.setObjectInStorage)(this._lastModifiedStoreKey, lastModifiedTimeMap);
156
+ return;
157
+ }
158
+ const oldest = entries.reduce((acc, current) => {
159
+ return current[1] < acc[1] ? current : acc;
160
+ });
161
+ delete lastModifiedTimeMap[oldest[0]];
162
+ yield StorageProvider_1.Storage.removeItem(oldest[0]);
163
+ yield (0, StorageProvider_1.setObjectInStorage)(this._lastModifiedStoreKey, lastModifiedTimeMap);
164
+ });
165
+ }
166
+ }
167
+ exports.DataAdapterCore = DataAdapterCore;
@@ -1,18 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Diagnostics = exports.captureDiagnostics = void 0;
4
- var Log_1 = require("./Log");
5
- var SUPPORTS_PERFORMANCE_API = typeof performance !== 'undefined' && typeof performance.mark !== 'undefined';
6
- var markers = [];
4
+ const Log_1 = require("./Log");
5
+ const SUPPORTS_PERFORMANCE_API = typeof performance !== 'undefined' && typeof performance.mark !== 'undefined';
6
+ let markers = [];
7
7
  function captureDiagnostics(func, task) {
8
- Diagnostics.mark("".concat(func, ":start"));
9
- var result = task();
10
- var markEnd = function () {
11
- Diagnostics.mark("".concat(func, ":end"));
12
- maybeFlush("".concat(func, ":end"));
8
+ Diagnostics.mark(`${func}:start`);
9
+ const result = task();
10
+ const markEnd = () => {
11
+ Diagnostics.mark(`${func}:end`);
12
+ maybeFlush(`${func}:end`);
13
13
  };
14
14
  if (result && result instanceof Promise) {
15
- return result.finally(function () { return markEnd(); });
15
+ return result.finally(() => markEnd());
16
16
  }
17
17
  else {
18
18
  markEnd();
@@ -20,32 +20,27 @@ function captureDiagnostics(func, task) {
20
20
  return result;
21
21
  }
22
22
  exports.captureDiagnostics = captureDiagnostics;
23
- var Diagnostics = /** @class */ (function () {
24
- function Diagnostics() {
25
- }
26
- Diagnostics.mark = function (tag, metadata) {
23
+ class Diagnostics {
24
+ static mark(tag, metadata) {
27
25
  if (!SUPPORTS_PERFORMANCE_API) {
28
26
  return;
29
27
  }
30
- var marker = performance.mark(tag, { detail: metadata });
28
+ const marker = performance.mark(tag, { detail: metadata });
31
29
  markers.push(marker);
32
- };
33
- Diagnostics.flush = function () {
34
- var resources = performance
30
+ }
31
+ static flush() {
32
+ const resources = performance
35
33
  .getEntriesByType('resource')
36
- .filter(function (resource) {
37
- return resource.name.startsWith('https://api.statsig.com');
38
- });
39
- var payload = {
40
- markers: markers,
41
- resources: resources,
34
+ .filter((resource) => resource.name.startsWith('https://api.statsig.com'));
35
+ const payload = {
36
+ markers,
37
+ resources,
42
38
  };
43
39
  // TODO: Send as log to Statsig
44
40
  Log_1.Log.debug('Diagnostics', payload, JSON.stringify(payload));
45
41
  markers = [];
46
- };
47
- return Diagnostics;
48
- }());
42
+ }
43
+ }
49
44
  exports.Diagnostics = Diagnostics;
50
45
  function maybeFlush(tag) {
51
46
  if (tag.startsWith('initialize:')) {
@@ -5,5 +5,6 @@ export declare class ErrorBoundary {
5
5
  private _seen;
6
6
  constructor(_sdkKey: string);
7
7
  capture(tag: string, task: () => unknown, emitter?: StatsigClientEmitEventFunc): unknown;
8
+ logError(tag: string, error: unknown): void;
8
9
  private _onError;
9
10
  }
@@ -1,15 +1,4 @@
1
1
  "use strict";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
2
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
3
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
4
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -19,49 +8,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
19
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
20
9
  });
21
10
  };
22
- var __generator = (this && this.__generator) || function (thisArg, body) {
23
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
- function verb(n) { return function (v) { return step([n, v]); }; }
26
- function step(op) {
27
- if (f) throw new TypeError("Generator is already executing.");
28
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
- 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;
30
- if (y = 0, t) op = [op[0] & 2, t.value];
31
- switch (op[0]) {
32
- case 0: case 1: t = op; break;
33
- case 4: _.label++; return { value: op[1], done: false };
34
- case 5: _.label++; y = op[1]; op = [0]; continue;
35
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
- default:
37
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
- if (t[2]) _.ops.pop();
42
- _.trys.pop(); continue;
43
- }
44
- op = body.call(thisArg, _);
45
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
- }
48
- };
49
11
  Object.defineProperty(exports, "__esModule", { value: true });
50
12
  exports.ErrorBoundary = exports.EXCEPTION_ENDPOINT = void 0;
51
- var Log_1 = require("./Log");
52
- var StatsigMetadata_1 = require("./StatsigMetadata");
13
+ const Log_1 = require("./Log");
14
+ const StatsigMetadata_1 = require("./StatsigMetadata");
53
15
  exports.EXCEPTION_ENDPOINT = 'https://statsigapi.net/v1/sdk_exception';
54
- var ErrorBoundary = /** @class */ (function () {
55
- function ErrorBoundary(_sdkKey) {
16
+ class ErrorBoundary {
17
+ constructor(_sdkKey) {
56
18
  this._sdkKey = _sdkKey;
57
19
  this._seen = new Set();
58
20
  }
59
- ErrorBoundary.prototype.capture = function (tag, task, emitter) {
60
- var _this = this;
21
+ capture(tag, task, emitter) {
61
22
  try {
62
- var res = task();
23
+ const res = task();
63
24
  if (res && res instanceof Promise) {
64
- return res.catch(function (err) { return _this._onError(tag, err, emitter); });
25
+ return res.catch((err) => this._onError(tag, err, emitter));
65
26
  }
66
27
  return res;
67
28
  }
@@ -69,57 +30,49 @@ var ErrorBoundary = /** @class */ (function () {
69
30
  this._onError(tag, error, emitter);
70
31
  return null;
71
32
  }
72
- };
73
- ErrorBoundary.prototype._onError = function (tag, error, emitter) {
74
- var _this = this;
33
+ }
34
+ logError(tag, error) {
35
+ this._onError(tag, error);
36
+ }
37
+ _onError(tag, error, emitter) {
75
38
  try {
76
- Log_1.Log.warn("Caught error in ".concat(tag), { error: error });
77
- var impl = function () { return __awaiter(_this, void 0, void 0, function () {
78
- var unwrapped, isError, name, statsigMetadata, info, body;
79
- return __generator(this, function (_a) {
80
- switch (_a.label) {
81
- case 0:
82
- unwrapped = (error !== null && error !== void 0 ? error : Error('[Statsig] Error was empty'));
83
- isError = unwrapped instanceof Error;
84
- name = isError ? unwrapped.name : 'No Name';
85
- if (this._seen.has(name)) {
86
- return [2 /*return*/];
87
- }
88
- this._seen.add(name);
89
- statsigMetadata = StatsigMetadata_1.StatsigMetadataProvider.get();
90
- info = isError ? unwrapped.stack : _getDescription(unwrapped);
91
- body = JSON.stringify(__assign({ tag: tag, exception: name, info: info }, statsigMetadata));
92
- return [4 /*yield*/, fetch(exports.EXCEPTION_ENDPOINT, {
93
- method: 'POST',
94
- headers: {
95
- 'STATSIG-API-KEY': this._sdkKey,
96
- 'STATSIG-SDK-TYPE': String(statsigMetadata.sdkType),
97
- 'STATSIG-SDK-VERSION': String(statsigMetadata.sdkVersion),
98
- 'Content-Type': 'application/json',
99
- },
100
- body: body,
101
- })];
102
- case 1:
103
- _a.sent();
104
- emitter === null || emitter === void 0 ? void 0 : emitter({ event: 'error', error: error });
105
- return [2 /*return*/];
106
- }
39
+ Log_1.Log.warn(`Caught error in ${tag}`, { error });
40
+ const impl = () => __awaiter(this, void 0, void 0, function* () {
41
+ const unwrapped = (error !== null && error !== void 0 ? error : Error('[Statsig] Error was empty'));
42
+ const isError = unwrapped instanceof Error;
43
+ const name = isError ? unwrapped.name : 'No Name';
44
+ if (this._seen.has(name)) {
45
+ return;
46
+ }
47
+ this._seen.add(name);
48
+ const statsigMetadata = StatsigMetadata_1.StatsigMetadataProvider.get();
49
+ const info = isError ? unwrapped.stack : _getDescription(unwrapped);
50
+ const body = JSON.stringify(Object.assign({ tag, exception: name, info }, statsigMetadata));
51
+ yield fetch(exports.EXCEPTION_ENDPOINT, {
52
+ method: 'POST',
53
+ headers: {
54
+ 'STATSIG-API-KEY': this._sdkKey,
55
+ 'STATSIG-SDK-TYPE': String(statsigMetadata.sdkType),
56
+ 'STATSIG-SDK-VERSION': String(statsigMetadata.sdkVersion),
57
+ 'Content-Type': 'application/json',
58
+ },
59
+ body,
107
60
  });
108
- }); };
61
+ emitter === null || emitter === void 0 ? void 0 : emitter({ name: 'error', error });
62
+ });
109
63
  impl()
110
- .then(function () {
64
+ .then(() => {
111
65
  /* noop */
112
66
  })
113
- .catch(function () {
67
+ .catch(() => {
114
68
  /* noop */
115
69
  });
116
70
  }
117
71
  catch (_error) {
118
72
  /* noop */
119
73
  }
120
- };
121
- return ErrorBoundary;
122
- }());
74
+ }
75
+ }
123
76
  exports.ErrorBoundary = ErrorBoundary;
124
77
  function _getDescription(obj) {
125
78
  try {
@@ -0,0 +1,20 @@
1
+ export type EvaluationOptionsCommon = {
2
+ /**
3
+ * Prevents an exposure log being created for this check.
4
+ *
5
+ * default: `false`
6
+ */
7
+ disableExposureLog?: boolean;
8
+ };
9
+ export type FeatureGateEvaluationOptions = EvaluationOptionsCommon & {};
10
+ export type DynamicConfigEvaluationOptions = EvaluationOptionsCommon & {};
11
+ export type ExperimentEvaluationOptions = EvaluationOptionsCommon & {
12
+ /**
13
+ * Provide a map of values to be used across checks
14
+ *
15
+ * @requires {@link @statsig/js-user-persisted-storage}
16
+ * @see {@link https://docs.statsig.com/client/concepts/persistent_assignment#example-usage}
17
+ */
18
+ userPersistedValues?: unknown;
19
+ };
20
+ export type LayerEvaluationOptions = EvaluationOptionsCommon & {};
@@ -0,0 +1,39 @@
1
+ import { Flatten } from './UtitlityTypes';
2
+ type EvaluationBase<T> = {
3
+ id_type: string;
4
+ name: string;
5
+ rule_id: string;
6
+ secondary_exposures: SecondaryExposure[];
7
+ value: T;
8
+ };
9
+ export type SecondaryExposure = {
10
+ gate: string;
11
+ gateValue: string;
12
+ ruleID: string;
13
+ };
14
+ export type GateEvaluation = EvaluationBase<boolean>;
15
+ export type ExperimentEvaluation = Flatten<EvaluationBase<Record<string, unknown>> & {
16
+ group_name?: string;
17
+ group: string;
18
+ id_type: string;
19
+ is_device_based: boolean;
20
+ is_experiment_active?: boolean;
21
+ is_user_in_experiment?: boolean;
22
+ }>;
23
+ export type DynamicConfigEvaluation = ExperimentEvaluation;
24
+ export type LayerEvaluation = Flatten<Omit<ExperimentEvaluation, 'id_type'> & {
25
+ allocated_experiment_name: string;
26
+ explicit_parameters: string[];
27
+ undelegated_secondary_exposures?: SecondaryExposure[];
28
+ }>;
29
+ export type AnyEvaluation = GateEvaluation | ExperimentEvaluation | DynamicConfigEvaluation | LayerEvaluation;
30
+ export type EvaluationDetails = {
31
+ reason: string;
32
+ lcut?: number;
33
+ receivedAt?: number;
34
+ };
35
+ export type DetailedEvaluation<T extends AnyEvaluation> = {
36
+ evaluation: T | null;
37
+ details: EvaluationDetails;
38
+ };
39
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -10,22 +10,35 @@ export declare class EventLogger {
10
10
  private _options;
11
11
  private _queue;
12
12
  private _flushTimer;
13
- private _lastExposureMap;
13
+ private _lastExposureTimeMap;
14
+ private _nonExposedChecks;
14
15
  private _maxQueueSize;
15
- private _failedLogs;
16
+ private _hasRunQuickFlush;
17
+ private _creationTime;
18
+ private _isLoggingDisabled;
19
+ private _logEventUrl;
20
+ private _logEventBeaconUrl;
16
21
  constructor(_sdkKey: string, _emitter: StatsigClientEmitEventFunc, _network: NetworkCore, _options: StatsigOptionsCommon | null);
22
+ setLoggingDisabled(isDisabled: boolean): void;
17
23
  enqueue(event: StatsigEventInternal): void;
24
+ incrementNonExposureCount(name: string): void;
18
25
  reset(): void;
19
26
  onVisibilityChanged(visibility: Visibility): void;
20
27
  shutdown(): Promise<void>;
28
+ flush(): Promise<void>;
29
+ /**
30
+ * We 'Quick Flush' following the very first event enqueued
31
+ * within the quick flush window
32
+ */
33
+ private _quickFlushIfNeeded;
21
34
  private _shouldLogEvent;
22
35
  private _flushAndForget;
23
- private _flush;
24
36
  private _sendEvents;
25
37
  private _sendEventsViaPost;
26
38
  private _sendEventsViaBeacon;
27
- private _isBeaconSupported;
28
39
  private _saveFailedLogsToStorage;
29
40
  private _retryFailedLogs;
30
41
  private _getStorageKey;
42
+ private _normalizeAndAppendEvent;
43
+ private _appendAndResetNonExposedChecks;
31
44
  }