Skip to content

Commit d1b1763

Browse files
authored
Removing cycle dependencies (#198)
* Removing cycle dependency: remote-auth and remote * Removing cycle dependency: switcher and client
1 parent f3c93c6 commit d1b1763

File tree

12 files changed

+165
-97
lines changed

12 files changed

+165
-97
lines changed

.github/workflows/master.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
SWITCHER_API_KEY: ${{ secrets.SWITCHER_API_KEY }}
3030

3131
- name: SonarCloud Scan
32-
uses: sonarsource/sonarqube-scan-action@v5.1.0
32+
uses: sonarsource/sonarqube-scan-action@v5.2.0
3333
env:
3434
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3535
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@
3030
"src/"
3131
],
3232
"devDependencies": {
33-
"@babel/eslint-parser": "^7.27.0",
34-
"@typescript-eslint/eslint-plugin": "^8.31.0",
35-
"@typescript-eslint/parser": "^8.31.0",
33+
"@babel/eslint-parser": "^7.27.1",
34+
"@typescript-eslint/eslint-plugin": "^8.32.1",
35+
"@typescript-eslint/parser": "^8.32.1",
3636
"c8": "^10.1.3",
3737
"chai": "^5.2.0",
3838
"env-cmd": "^10.1.0",
39-
"eslint": "^9.25.1",
40-
"mocha": "^11.1.0",
39+
"eslint": "^9.27.0",
40+
"mocha": "^11.4.0",
4141
"mocha-sonarqube-reporter": "^1.0.2",
4242
"sinon": "^20.0.0"
4343
},

src/client.js

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,28 @@ import SnapshotAutoUpdater from './lib/utils/snapshotAutoUpdater.js';
1818
import { SnapshotNotFoundError } from './lib/exceptions/index.js';
1919
import { loadDomain, validateSnapshot, checkSwitchersLocal } from './lib/snapshot.js';
2020
import { Switcher } from './switcher.js';
21-
import { Auth } from './lib/remote-auth.js';
21+
import { Auth } from './lib/remoteAuth.js';
22+
import { GlobalOptions } from './lib/globals/globalOptions.js';
23+
import { GlobalSnapshot } from './lib/globals/globalSnapshot.js';
2224

2325
export class Client {
2426

25-
static #options;
2627
static #context;
27-
static #snapshot;
2828

2929
static buildContext(context, options) {
3030
this.testEnabled = DEFAULT_TEST_MODE;
3131

32-
this.#snapshot = undefined;
3332
this.#context = context;
3433
this.#context.environment = util.get(context.environment, DEFAULT_ENVIRONMENT);
3534

3635
// Default values
37-
this.#options = {
36+
GlobalSnapshot.clear();
37+
GlobalOptions.init({
3838
snapshotAutoUpdateInterval: 0,
3939
snapshotLocation: options?.snapshotLocation,
4040
local: util.get(options?.local, DEFAULT_LOCAL),
4141
logger: util.get(options?.logger, DEFAULT_LOGGER)
42-
};
42+
});
4343

4444
if (options) {
4545
Client.#buildOptions(options);
@@ -60,7 +60,7 @@ export class Client {
6060
}
6161

6262
if (SWITCHER_OPTIONS.SNAPSHOT_AUTO_UPDATE_INTERVAL in options) {
63-
this.#options.snapshotAutoUpdateInterval = options.snapshotAutoUpdateInterval;
63+
GlobalOptions.updateOptions({ snapshotAutoUpdateInterval: options.snapshotAutoUpdateInterval });
6464
this.scheduleSnapshotAutoUpdate();
6565
}
6666

@@ -70,7 +70,7 @@ export class Client {
7070
static #initSilentMode(silentMode) {
7171
Auth.setRetryOptions(silentMode);
7272

73-
Client.#options.silentMode = silentMode;
73+
GlobalOptions.updateOptions({ silentMode });
7474
Client.loadSnapshot();
7575
}
7676

@@ -94,7 +94,7 @@ export class Client {
9494
}
9595

9696
static async checkSnapshot() {
97-
if (!Client.#snapshot) {
97+
if (!GlobalSnapshot.snapshot) {
9898
throw new SnapshotNotFoundError('Snapshot is not loaded. Use Client.loadSnapshot()');
9999
}
100100

@@ -104,52 +104,52 @@ export class Client {
104104

105105
const snapshot = await validateSnapshot(
106106
Client.#context,
107-
Client.#snapshot.data.domain.version
107+
GlobalSnapshot.snapshot.data.domain.version
108108
);
109109

110110
if (snapshot) {
111-
if (Client.#options.snapshotLocation?.length) {
112-
writeFileSync(`${Client.#options.snapshotLocation}/${Client.#context.environment}.json`, snapshot);
111+
if (GlobalOptions.snapshotLocation?.length) {
112+
writeFileSync(`${GlobalOptions.snapshotLocation}/${Client.#context.environment}.json`, snapshot);
113113
}
114114

115-
Client.#snapshot = JSON.parse(snapshot);
115+
GlobalSnapshot.init(JSON.parse(snapshot));
116116
return true;
117117
}
118118

119119
return false;
120120
}
121121

122122
static async loadSnapshot(options = { fetchRemote: false, watchSnapshot: false }) {
123-
Client.#snapshot = loadDomain(
124-
util.get(Client.#options.snapshotLocation, ''),
123+
GlobalSnapshot.init(loadDomain(
124+
util.get(GlobalOptions.snapshotLocation, ''),
125125
util.get(Client.#context.environment, DEFAULT_ENVIRONMENT)
126-
);
126+
));
127127

128-
if (Client.#snapshot.data.domain.version == 0 &&
129-
(options.fetchRemote || !Client.#options.local)) {
128+
if (GlobalSnapshot.snapshot.data.domain.version == 0 &&
129+
(options.fetchRemote || !GlobalOptions.local)) {
130130
await Client.checkSnapshot();
131131
}
132132

133133
if (options.watchSnapshot) {
134134
Client.watchSnapshot();
135135
}
136136

137-
return Client.#snapshot?.data.domain.version || 0;
137+
return GlobalSnapshot.snapshot?.data.domain.version || 0;
138138
}
139139

140140
static watchSnapshot(callback = {}) {
141141
const { success = () => {}, reject = () => {} } = callback;
142142

143-
if (Client.testEnabled || !Client.#options.snapshotLocation?.length) {
143+
if (Client.testEnabled || !GlobalOptions.snapshotLocation?.length) {
144144
return reject(new Error('Watch Snapshot cannot be used in test mode or without a snapshot location'));
145145
}
146146

147-
const snapshotFile = `${Client.#options.snapshotLocation}/${Client.#context.environment}.json`;
147+
const snapshotFile = `${GlobalOptions.snapshotLocation}/${Client.#context.environment}.json`;
148148
let lastUpdate;
149149
watchFile(snapshotFile, (listener) => {
150150
try {
151151
if (!lastUpdate || listener.ctime > lastUpdate) {
152-
Client.#snapshot = loadDomain(Client.#options.snapshotLocation, Client.#context.environment);
152+
GlobalSnapshot.init(loadDomain(GlobalOptions.snapshotLocation, Client.#context.environment));
153153
success();
154154
}
155155
} catch (e) {
@@ -165,21 +165,21 @@ export class Client {
165165
return;
166166
}
167167

168-
const snapshotFile = `${Client.#options.snapshotLocation}${Client.#context.environment}.json`;
169-
Client.#snapshot = undefined;
168+
const snapshotFile = `${GlobalOptions.snapshotLocation}${Client.#context.environment}.json`;
169+
GlobalSnapshot.clear();
170170
unwatchFile(snapshotFile);
171171
}
172172

173173
static scheduleSnapshotAutoUpdate(interval, callback = {}) {
174174
const { success = () => {}, reject = () => {} } = callback;
175175

176176
if (interval) {
177-
Client.#options.snapshotAutoUpdateInterval = interval;
177+
GlobalOptions.updateOptions({ snapshotAutoUpdateInterval: interval });
178178
}
179179

180-
if (Client.#options.snapshotAutoUpdateInterval && Client.#options.snapshotAutoUpdateInterval > 0) {
180+
if (GlobalOptions.snapshotAutoUpdateInterval && GlobalOptions.snapshotAutoUpdateInterval > 0) {
181181
SnapshotAutoUpdater.schedule(
182-
Client.#options.snapshotAutoUpdateInterval,
182+
GlobalOptions.snapshotAutoUpdateInterval,
183183
this.checkSnapshot,
184184
success,
185185
reject
@@ -192,8 +192,8 @@ export class Client {
192192
}
193193

194194
static async checkSwitchers(switcherKeys) {
195-
if (Client.#options.local && Client.#snapshot) {
196-
checkSwitchersLocal(Client.#snapshot, switcherKeys);
195+
if (GlobalOptions.local && GlobalSnapshot.snapshot) {
196+
checkSwitchersLocal(GlobalSnapshot.snapshot, switcherKeys);
197197
} else {
198198
await Client._checkSwitchersRemote(switcherKeys);
199199
}
@@ -204,8 +204,8 @@ export class Client {
204204
await Auth.auth();
205205
await remote.checkSwitchers(switcherKeys);
206206
} catch (e) {
207-
if (Client.#options.silentMode) {
208-
checkSwitchersLocal(Client.#snapshot, switcherKeys);
207+
if (GlobalOptions.silentMode) {
208+
checkSwitchersLocal(GlobalSnapshot.snapshot, switcherKeys);
209209
} else {
210210
throw e;
211211
}
@@ -239,15 +239,6 @@ export class Client {
239239
static testMode(testEnabled = true) {
240240
Client.testEnabled = testEnabled;
241241
}
242-
243-
static get options() {
244-
return Client.#options;
245-
}
246-
247-
static get snapshot() {
248-
return Client.#snapshot;
249-
}
250-
251242
}
252243

253244
// Type export placeholders

src/lib/globals/globalAuth.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
export class GlobalAuth {
2+
static #token;
3+
static #exp;
4+
static #url;
5+
6+
static init(url) {
7+
this.#url = url;
8+
this.#token = undefined;
9+
this.#exp = undefined;
10+
}
11+
12+
static get token() {
13+
return this.#token;
14+
}
15+
16+
static set token(value) {
17+
this.#token = value;
18+
}
19+
20+
static get exp() {
21+
return this.#exp;
22+
}
23+
24+
static set exp(value) {
25+
this.#exp = value;
26+
}
27+
28+
static get url() {
29+
return this.#url;
30+
}
31+
}

src/lib/globals/globalOptions.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
export class GlobalOptions {
2+
static #options;
3+
4+
static init(options) {
5+
this.#options = {
6+
...options,
7+
};
8+
}
9+
10+
static updateOptions(options) {
11+
this.#options = {
12+
...this.#options,
13+
...options,
14+
};
15+
}
16+
17+
static get local() {
18+
return this.#options.local;
19+
}
20+
21+
static get logger() {
22+
return this.#options.logger;
23+
}
24+
25+
static get snapshotLocation() {
26+
return this.#options.snapshotLocation;
27+
}
28+
29+
static get snapshotAutoUpdateInterval() {
30+
return this.#options.snapshotAutoUpdateInterval;
31+
}
32+
33+
static get silentMode() {
34+
return this.#options.silentMode;
35+
}
36+
}

src/lib/globals/globalSnapshot.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export class GlobalSnapshot {
2+
static #snapshotStore;
3+
4+
static init(snapshot) {
5+
this.#snapshotStore = snapshot;
6+
}
7+
8+
static clear() {
9+
this.#snapshotStore = undefined;
10+
}
11+
12+
static get snapshot() {
13+
return this.#snapshotStore;
14+
}
15+
}

src/lib/remote.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { Agent } from 'node:https';
33

44
import { AuthError, CheckSwitcherError, CriteriaError, SnapshotServiceError } from './exceptions/index.js';
55
import FetchFacade from './utils/fetchFacade.js';
6-
import { Auth } from './remote-auth.js';
76
import * as util from './utils/index.js';
7+
import { GlobalAuth } from './globals/globalAuth.js';
88

99
let httpClient;
1010

@@ -85,10 +85,10 @@ export async function checkAPIHealth(url) {
8585
export async function checkCriteria(key, input, showDetail = false) {
8686
try {
8787
const entry = getEntry(input);
88-
const response = await FetchFacade.fetch(`${Auth.getURL()}/criteria?showReason=${showDetail}&key=${key}`, {
88+
const response = await FetchFacade.fetch(`${GlobalAuth.url}/criteria?showReason=${showDetail}&key=${key}`, {
8989
method: 'post',
9090
body: JSON.stringify({ entry }),
91-
headers: getHeader(Auth.getToken()),
91+
headers: getHeader(GlobalAuth.token),
9292
agent: httpClient
9393
});
9494

@@ -104,10 +104,10 @@ export async function checkCriteria(key, input, showDetail = false) {
104104

105105
export async function checkSwitchers(switcherKeys) {
106106
try {
107-
const response = await FetchFacade.fetch(`${Auth.getURL()}/criteria/switchers_check`, {
107+
const response = await FetchFacade.fetch(`${GlobalAuth.url}/criteria/switchers_check`, {
108108
method: 'post',
109109
body: JSON.stringify({ switchers: switcherKeys }),
110-
headers: getHeader(Auth.getToken()),
110+
headers: getHeader(GlobalAuth.token),
111111
agent: httpClient
112112
});
113113

@@ -126,9 +126,9 @@ export async function checkSwitchers(switcherKeys) {
126126

127127
export async function checkSnapshotVersion(version) {
128128
try {
129-
const response = await FetchFacade.fetch(`${Auth.getURL()}/criteria/snapshot_check/${version}`, {
129+
const response = await FetchFacade.fetch(`${GlobalAuth.url}/criteria/snapshot_check/${version}`, {
130130
method: 'get',
131-
headers: getHeader(Auth.getToken()),
131+
headers: getHeader(GlobalAuth.token),
132132
agent: httpClient
133133
});
134134

@@ -159,10 +159,10 @@ export async function resolveSnapshot(domain, environment, component) {
159159
};
160160

161161
try {
162-
const response = await FetchFacade.fetch(`${Auth.getURL()}/graphql`, {
162+
const response = await FetchFacade.fetch(`${GlobalAuth.url}/graphql`, {
163163
method: 'post',
164164
body: JSON.stringify(data),
165-
headers: getHeader(Auth.getToken()),
165+
headers: getHeader(GlobalAuth.token),
166166
agent: httpClient
167167
});
168168

0 commit comments

Comments
 (0)