@statsig/js-local-overrides 3.15.0 → 3.15.2
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/js-local-overrides",
|
|
3
|
-
"version": "3.15.
|
|
3
|
+
"version": "3.15.2",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"homepage": "https://github.com/statsig-io/js-client-monorepo",
|
|
6
6
|
"repository": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"directory": "packages/js-local-overrides"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@statsig/client-core": "3.15.
|
|
12
|
+
"@statsig/client-core": "3.15.2"
|
|
13
13
|
},
|
|
14
14
|
"type": "commonjs",
|
|
15
15
|
"main": "./src/index.js",
|
|
@@ -10,9 +10,10 @@ export declare class LocalOverrideAdapter implements OverrideAdapter {
|
|
|
10
10
|
private _sdkKey;
|
|
11
11
|
constructor(sdkKey?: string);
|
|
12
12
|
private _getLocalOverridesStorageKey;
|
|
13
|
-
|
|
13
|
+
loadFromStorage(): Promise<void>;
|
|
14
14
|
private _saveOverridesToStorage;
|
|
15
15
|
overrideGate(name: string, value: boolean): void;
|
|
16
|
+
private _warnIfStorageNotReady;
|
|
16
17
|
removeGateOverride(name: string): void;
|
|
17
18
|
getGateOverride(current: FeatureGate, _user: StatsigUser): FeatureGate | null;
|
|
18
19
|
overrideDynamicConfig(name: string, value: Record<string, unknown>): void;
|
|
@@ -27,4 +28,5 @@ export declare class LocalOverrideAdapter implements OverrideAdapter {
|
|
|
27
28
|
removeAllOverrides(): void;
|
|
28
29
|
getLayerOverride(current: Layer, _user: StatsigUser): Layer | null;
|
|
29
30
|
private _getConfigOverride;
|
|
31
|
+
private _hasInMemoryOverrides;
|
|
30
32
|
}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
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
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
exports.LocalOverrideAdapter = void 0;
|
|
4
13
|
const client_core_1 = require("@statsig/client-core");
|
|
@@ -11,25 +20,51 @@ function _makeEmptyStore() {
|
|
|
11
20
|
layer: {},
|
|
12
21
|
};
|
|
13
22
|
}
|
|
23
|
+
function _mergeOverrides(currentValues, newValues) {
|
|
24
|
+
return {
|
|
25
|
+
gate: Object.assign({}, currentValues.gate, newValues.gate),
|
|
26
|
+
dynamicConfig: Object.assign({}, currentValues.dynamicConfig, newValues.dynamicConfig),
|
|
27
|
+
experiment: Object.assign({}, currentValues.experiment, newValues.experiment),
|
|
28
|
+
layer: Object.assign({}, currentValues.layer, newValues.layer),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
14
31
|
class LocalOverrideAdapter {
|
|
15
32
|
constructor(sdkKey) {
|
|
16
33
|
this._overrides = _makeEmptyStore();
|
|
17
34
|
this._sdkKey = sdkKey !== null && sdkKey !== void 0 ? sdkKey : null;
|
|
18
|
-
this._overrides = this._loadOverridesFromStorage();
|
|
19
35
|
}
|
|
20
36
|
_getLocalOverridesStorageKey(sdkKey) {
|
|
21
37
|
return `statsig.local-overrides.${(0, client_core_1._getStorageKey)(sdkKey)}`;
|
|
22
38
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
39
|
+
loadFromStorage() {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
if (this._sdkKey == null) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (!client_core_1.Storage.isReady()) {
|
|
45
|
+
yield client_core_1.Storage.isReadyResolver();
|
|
46
|
+
}
|
|
47
|
+
const storageKey = this._getLocalOverridesStorageKey(this._sdkKey);
|
|
48
|
+
const storedOverrides = client_core_1.Storage.getItem(storageKey);
|
|
49
|
+
const overrides = storedOverrides
|
|
50
|
+
? (0, client_core_1._typedJsonParse)(storedOverrides, 'gate', 'LocalOverrideAdapter overrides')
|
|
51
|
+
: null;
|
|
52
|
+
const hasInMemoryOverrides = this._hasInMemoryOverrides();
|
|
53
|
+
if (overrides) {
|
|
54
|
+
// Merge overrides in memory with stored overrides.
|
|
55
|
+
// WARN: This is a union of overrides. Trying to remove an override
|
|
56
|
+
// before storage is ready won't remove the override in storage.
|
|
57
|
+
this._overrides = hasInMemoryOverrides
|
|
58
|
+
? _mergeOverrides(overrides, this._overrides)
|
|
59
|
+
: overrides;
|
|
60
|
+
}
|
|
61
|
+
if (hasInMemoryOverrides) {
|
|
62
|
+
this._saveOverridesToStorage();
|
|
63
|
+
}
|
|
64
|
+
});
|
|
30
65
|
}
|
|
31
66
|
_saveOverridesToStorage() {
|
|
32
|
-
if (this._sdkKey == null) {
|
|
67
|
+
if (this._sdkKey == null || !client_core_1.Storage.isReady()) {
|
|
33
68
|
return;
|
|
34
69
|
}
|
|
35
70
|
const storageKey = this._getLocalOverridesStorageKey(this._sdkKey);
|
|
@@ -40,7 +75,13 @@ class LocalOverrideAdapter {
|
|
|
40
75
|
this._overrides.gate[(0, client_core_1._DJB2)(name)] = value;
|
|
41
76
|
this._saveOverridesToStorage();
|
|
42
77
|
}
|
|
78
|
+
_warnIfStorageNotReady() {
|
|
79
|
+
if (!client_core_1.Storage.isReady()) {
|
|
80
|
+
client_core_1.Log.warn('Storage is not ready. Override removal may not persist.');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
43
83
|
removeGateOverride(name) {
|
|
84
|
+
this._warnIfStorageNotReady();
|
|
44
85
|
delete this._overrides.gate[name];
|
|
45
86
|
delete this._overrides.gate[(0, client_core_1._DJB2)(name)];
|
|
46
87
|
this._saveOverridesToStorage();
|
|
@@ -59,6 +100,7 @@ class LocalOverrideAdapter {
|
|
|
59
100
|
this._saveOverridesToStorage();
|
|
60
101
|
}
|
|
61
102
|
removeDynamicConfigOverride(name) {
|
|
103
|
+
this._warnIfStorageNotReady();
|
|
62
104
|
delete this._overrides.dynamicConfig[name];
|
|
63
105
|
delete this._overrides.dynamicConfig[(0, client_core_1._DJB2)(name)];
|
|
64
106
|
this._saveOverridesToStorage();
|
|
@@ -72,6 +114,7 @@ class LocalOverrideAdapter {
|
|
|
72
114
|
this._saveOverridesToStorage();
|
|
73
115
|
}
|
|
74
116
|
removeExperimentOverride(name) {
|
|
117
|
+
this._warnIfStorageNotReady();
|
|
75
118
|
delete this._overrides.experiment[name];
|
|
76
119
|
delete this._overrides.experiment[(0, client_core_1._DJB2)(name)];
|
|
77
120
|
this._saveOverridesToStorage();
|
|
@@ -85,6 +128,7 @@ class LocalOverrideAdapter {
|
|
|
85
128
|
this._saveOverridesToStorage();
|
|
86
129
|
}
|
|
87
130
|
removeLayerOverride(name) {
|
|
131
|
+
this._warnIfStorageNotReady();
|
|
88
132
|
delete this._overrides.layer[name];
|
|
89
133
|
delete this._overrides.layer[(0, client_core_1._DJB2)(name)];
|
|
90
134
|
this._saveOverridesToStorage();
|
|
@@ -93,6 +137,7 @@ class LocalOverrideAdapter {
|
|
|
93
137
|
return JSON.parse(JSON.stringify(this._overrides));
|
|
94
138
|
}
|
|
95
139
|
removeAllOverrides() {
|
|
140
|
+
this._warnIfStorageNotReady();
|
|
96
141
|
this._overrides = _makeEmptyStore();
|
|
97
142
|
this._saveOverridesToStorage();
|
|
98
143
|
}
|
|
@@ -112,5 +157,11 @@ class LocalOverrideAdapter {
|
|
|
112
157
|
}
|
|
113
158
|
return Object.assign(Object.assign({}, current), { value: overridden, get: (0, client_core_1._makeTypedGet)(current.name, overridden), details: Object.assign(Object.assign({}, current.details), { reason: LOCAL_OVERRIDE_REASON }) });
|
|
114
159
|
}
|
|
160
|
+
_hasInMemoryOverrides() {
|
|
161
|
+
return (Object.keys(this._overrides.gate).length > 0 ||
|
|
162
|
+
Object.keys(this._overrides.dynamicConfig).length > 0 ||
|
|
163
|
+
Object.keys(this._overrides.experiment).length > 0 ||
|
|
164
|
+
Object.keys(this._overrides.layer).length > 0);
|
|
165
|
+
}
|
|
115
166
|
}
|
|
116
167
|
exports.LocalOverrideAdapter = LocalOverrideAdapter;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StorageProvider } from '@statsig/client-core';
|
|
2
|
+
export declare class MockStorageProvider implements StorageProvider {
|
|
3
|
+
private ready;
|
|
4
|
+
data: Record<string, string>;
|
|
5
|
+
private _readyPromise;
|
|
6
|
+
private _resolveReady;
|
|
7
|
+
constructor(ready?: boolean);
|
|
8
|
+
getItem(key: string): string | null;
|
|
9
|
+
setItem(key: string, value: string): void;
|
|
10
|
+
isReady(): boolean;
|
|
11
|
+
getProviderName(): string;
|
|
12
|
+
removeItem(key: string): void;
|
|
13
|
+
getAllKeys(): readonly string[];
|
|
14
|
+
isReadyResolver(): Promise<void>;
|
|
15
|
+
setReady(ready: boolean): void;
|
|
16
|
+
reset(): void;
|
|
17
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MockStorageProvider = void 0;
|
|
4
|
+
class MockStorageProvider {
|
|
5
|
+
constructor(ready = true) {
|
|
6
|
+
this.ready = ready;
|
|
7
|
+
this.data = {};
|
|
8
|
+
this._resolveReady = null;
|
|
9
|
+
this._readyPromise = new Promise((resolve) => {
|
|
10
|
+
if (this.ready) {
|
|
11
|
+
resolve();
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
this._resolveReady = resolve;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
getItem(key) {
|
|
19
|
+
return this.data[key] || null;
|
|
20
|
+
}
|
|
21
|
+
setItem(key, value) {
|
|
22
|
+
this.data[key] = value;
|
|
23
|
+
}
|
|
24
|
+
isReady() {
|
|
25
|
+
return this.ready;
|
|
26
|
+
}
|
|
27
|
+
getProviderName() {
|
|
28
|
+
return 'MockStorage';
|
|
29
|
+
}
|
|
30
|
+
removeItem(key) {
|
|
31
|
+
delete this.data[key];
|
|
32
|
+
}
|
|
33
|
+
getAllKeys() {
|
|
34
|
+
return Object.keys(this.data);
|
|
35
|
+
}
|
|
36
|
+
isReadyResolver() {
|
|
37
|
+
return this._readyPromise;
|
|
38
|
+
}
|
|
39
|
+
setReady(ready) {
|
|
40
|
+
this.ready = ready;
|
|
41
|
+
if (ready && this._resolveReady) {
|
|
42
|
+
this._resolveReady();
|
|
43
|
+
this._resolveReady = null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
reset() {
|
|
47
|
+
this.data = {};
|
|
48
|
+
this.ready = true;
|
|
49
|
+
this._resolveReady = null;
|
|
50
|
+
this._readyPromise = Promise.resolve();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.MockStorageProvider = MockStorageProvider;
|