@statsig/js-local-overrides 0.0.1-beta.10

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/.eslintrc.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "extends": ["../../.eslintrc.json"],
3
+ "ignorePatterns": ["!**/*"],
4
+ "overrides": [
5
+ {
6
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7
+ "rules": {}
8
+ },
9
+ {
10
+ "files": ["*.ts", "*.tsx"],
11
+ "rules": {}
12
+ },
13
+ {
14
+ "files": ["*.js", "*.jsx"],
15
+ "rules": {}
16
+ },
17
+ {
18
+ "files": ["*.json"],
19
+ "parser": "jsonc-eslint-parser",
20
+ "rules": {
21
+ "@nx/dependency-checks": "error"
22
+ }
23
+ }
24
+ ]
25
+ }
package/jest.config.ts ADDED
@@ -0,0 +1,10 @@
1
+ /* eslint-disable */
2
+ export default {
3
+ displayName: 'js-local-overrides',
4
+ preset: '../../jest.preset.js',
5
+ transform: {
6
+ '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
7
+ },
8
+ moduleFileExtensions: ['ts', 'js', 'html'],
9
+ coverageDirectory: '../../coverage/packages/js-local-overrides',
10
+ };
package/package.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "@statsig/js-local-overrides",
3
+ "version": "0.0.1-beta.10",
4
+ "dependencies": {
5
+ "@statsig/client-core": "0.0.1-beta.10"
6
+ },
7
+ "type": "commonjs",
8
+ "main": "./src/index.js",
9
+ "typings": "./src/index.d.ts"
10
+ }
package/project.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "js-local-overrides",
3
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
+ "sourceRoot": "packages/js-local-overrides/src",
5
+ "projectType": "library",
6
+ "targets": {
7
+ "build": {
8
+ "executor": "@nx/js:tsc",
9
+ "outputs": ["{options.outputPath}"],
10
+ "options": {
11
+ "outputPath": "dist/packages/js-local-overrides",
12
+ "main": "packages/js-local-overrides/src/index.ts",
13
+ "tsConfig": "packages/js-local-overrides/tsconfig.lib.json",
14
+ "assets": []
15
+ }
16
+ },
17
+ "publish": {
18
+ "command": "node tools/scripts/publish.mjs js-local-overrides {args.ver} {args.tag}",
19
+ "dependsOn": ["build"]
20
+ },
21
+ "lint": {
22
+ "executor": "@nx/eslint:lint"
23
+ },
24
+ "test": {
25
+ "executor": "@nx/jest:jest",
26
+ "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
27
+ "options": {
28
+ "jestConfig": "packages/js-local-overrides/jest.config.ts"
29
+ }
30
+ }
31
+ },
32
+ "tags": []
33
+ }
@@ -0,0 +1,101 @@
1
+ import {
2
+ DynamicConfig,
3
+ Experiment,
4
+ FeatureGate,
5
+ Layer,
6
+ OverrideAdapter,
7
+ StatsigUser,
8
+ } from '@statsig/client-core';
9
+
10
+ const LOCAL_OVERRIDE_REASON = 'LocalOverride';
11
+
12
+ type OverrideStore = {
13
+ gate: Record<string, boolean>;
14
+ dynamicConfig: Record<string, Record<string, unknown>>;
15
+ experiment: OverrideStore['dynamicConfig'];
16
+ layer: OverrideStore['dynamicConfig'];
17
+ };
18
+
19
+ export class LocalOverrideAdapter implements OverrideAdapter {
20
+ private readonly _overrides: OverrideStore = {
21
+ gate: {},
22
+ dynamicConfig: {},
23
+ experiment: {},
24
+ layer: {},
25
+ };
26
+
27
+ overrideGate(name: string, value: boolean): void {
28
+ this._overrides.gate[name] = value;
29
+ }
30
+
31
+ getGateOverride(
32
+ current: FeatureGate,
33
+ _user: StatsigUser,
34
+ ): FeatureGate | null {
35
+ const overridden = this._overrides.gate[current.name];
36
+ if (overridden == null) {
37
+ return null;
38
+ }
39
+
40
+ return {
41
+ ...current,
42
+ value: overridden,
43
+ details: { ...current.details, reason: LOCAL_OVERRIDE_REASON },
44
+ };
45
+ }
46
+
47
+ overrideDynamicConfig(name: string, value: Record<string, unknown>): void {
48
+ this._overrides.dynamicConfig[name] = value;
49
+ }
50
+
51
+ getDynamicConfigOverride(
52
+ current: DynamicConfig,
53
+ _user: StatsigUser,
54
+ ): DynamicConfig | null {
55
+ return this._getConfigOverride(current, this._overrides.dynamicConfig);
56
+ }
57
+
58
+ overrideExperiment(name: string, value: Record<string, unknown>): void {
59
+ this._overrides.experiment[name] = value;
60
+ }
61
+
62
+ getExperimentOverride(
63
+ current: Experiment,
64
+ _user: StatsigUser,
65
+ ): Experiment | null {
66
+ return this._getConfigOverride(current, this._overrides.experiment);
67
+ }
68
+
69
+ overrideLayer(name: string, value: Record<string, unknown>): void {
70
+ this._overrides.layer[name] = value;
71
+ }
72
+
73
+ getLayerOverride(current: Layer, _user: StatsigUser): Layer | null {
74
+ const overridden = this._overrides.layer[current.name];
75
+ if (overridden == null) {
76
+ return null;
77
+ }
78
+
79
+ return {
80
+ ...current,
81
+ _value: overridden,
82
+ details: { ...current.details, reason: LOCAL_OVERRIDE_REASON },
83
+ };
84
+ }
85
+
86
+ private _getConfigOverride<T extends Experiment | DynamicConfig>(
87
+ current: T,
88
+ lookup: Record<string, Record<string, unknown>>,
89
+ ): T | null {
90
+ const overridden = lookup[current.name];
91
+ if (overridden == null) {
92
+ return null;
93
+ }
94
+
95
+ return {
96
+ ...current,
97
+ value: overridden,
98
+ details: { ...current.details, reason: LOCAL_OVERRIDE_REASON },
99
+ };
100
+ }
101
+ }
@@ -0,0 +1,45 @@
1
+ import {
2
+ makeDynamicConfig,
3
+ makeFeatureGate,
4
+ makeLayer,
5
+ } from '@statsig/client-core';
6
+
7
+ import { LocalOverrideAdapter } from '../LocalOverrideAdapter';
8
+
9
+ describe('Local Overrides', () => {
10
+ const user = { userID: 'a-user' };
11
+ const gate = makeFeatureGate('a_gate', { reason: '' }, null);
12
+ const dynamicConfig = makeDynamicConfig('a_config', { reason: '' }, null);
13
+ const experiment = makeDynamicConfig('an_experiment', { reason: '' }, null);
14
+ const layer = makeLayer('a_layer', { reason: '' }, null);
15
+
16
+ let provider: LocalOverrideAdapter;
17
+
18
+ beforeAll(() => {
19
+ provider = new LocalOverrideAdapter();
20
+ });
21
+
22
+ it('returns overidden gates', () => {
23
+ provider.overrideGate(gate.name, true);
24
+ const overridden = provider.getGateOverride(gate, user);
25
+ expect(overridden?.value).toBe(true);
26
+ });
27
+
28
+ it('returns overidden dynamic configs', () => {
29
+ provider.overrideDynamicConfig(dynamicConfig.name, { dc: 'value' });
30
+ const overridden = provider.getDynamicConfigOverride(dynamicConfig, user);
31
+ expect(overridden?.value).toEqual({ dc: 'value' });
32
+ });
33
+
34
+ it('returns overidden experiment', () => {
35
+ provider.overrideExperiment(experiment.name, { exp: 'value' });
36
+ const overridden = provider.getExperimentOverride(experiment, user);
37
+ expect(overridden?.value).toEqual({ exp: 'value' });
38
+ });
39
+
40
+ it('returns overidden layer', () => {
41
+ provider.overrideLayer(layer.name, { layer_key: 'value' });
42
+ const overridden = provider.getLayerOverride(layer, user);
43
+ expect(overridden?._value).toEqual({ layer_key: 'value' });
44
+ });
45
+ });
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './LocalOverrideAdapter';
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {},
4
+ "files": [],
5
+ "include": [],
6
+ "references": [
7
+ {
8
+ "path": "./tsconfig.lib.json"
9
+ },
10
+ {
11
+ "path": "./tsconfig.spec.json"
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../dist/out-tsc",
5
+ "declaration": true,
6
+ "types": ["node"]
7
+ },
8
+ "include": ["src/**/*.ts"],
9
+ "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
10
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../dist/out-tsc",
5
+ "module": "commonjs",
6
+ "types": ["jest", "node"],
7
+ "resolveJsonModule": true,
8
+ "esModuleInterop": true,
9
+ "sourceMap": true
10
+ },
11
+ "include": [
12
+ "jest.config.ts",
13
+ "src/**/*.test.ts",
14
+ "src/**/*.spec.ts",
15
+ "src/**/*.d.ts"
16
+ ]
17
+ }