Skip to content

Commit 6a82081

Browse files
committed
some sonar fixes
1 parent 2008fa1 commit 6a82081

File tree

14 files changed

+134
-89
lines changed

14 files changed

+134
-89
lines changed

packages/react-native/src/lib/common/api.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { wrapThrowsAsync } from "@/lib/common/utils";
2-
import { ApiResponse, ApiSuccessResponse, CreateOrUpdateUserResponse } from "@/types/api";
2+
import {
3+
ApiResponse,
4+
ApiSuccessResponse,
5+
CreateOrUpdateUserResponse,
6+
} from "@/types/api";
37
import { TEnvironmentState } from "@/types/config";
48
import { ApiErrorResponse, Result, err, ok } from "@/types/error";
59

@@ -40,7 +44,9 @@ export const makeRequest = async <T>(
4044
status: response.status,
4145
message: errorResponse.message || "Something went wrong",
4246
url,
43-
...(Object.keys(errorResponse.details ?? {}).length > 0 && { details: errorResponse.details }),
47+
...(Object.keys(errorResponse.details ?? {}).length > 0 && {
48+
details: errorResponse.details,
49+
}),
4450
});
4551
}
4652

@@ -50,9 +56,9 @@ export const makeRequest = async <T>(
5056

5157
// Simple API client using fetch
5258
export class ApiClient {
53-
private appUrl: string;
54-
private environmentId: string;
55-
private isDebug: boolean;
59+
private readonly appUrl: string;
60+
private readonly environmentId: string;
61+
private readonly isDebug: boolean;
5662

5763
constructor({
5864
appUrl,
@@ -90,7 +96,9 @@ export class ApiClient {
9096
);
9197
}
9298

93-
async getEnvironmentState(): Promise<Result<TEnvironmentState, ApiErrorResponse>> {
99+
async getEnvironmentState(): Promise<
100+
Result<TEnvironmentState, ApiErrorResponse>
101+
> {
94102
return makeRequest(
95103
this.appUrl,
96104
`/api/v1/client/${this.environmentId}/environment`,

packages/react-native/src/lib/common/command-queue.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import { wrapThrowsAsync } from "@/lib/common/utils";
44
import type { Result } from "@/types/error";
55

66
export class CommandQueue {
7-
private queue: {
8-
command: (...args: any[]) => Promise<Result<void, unknown>> | Result<void, unknown> | Promise<void>;
7+
private readonly queue: {
8+
command: (
9+
...args: any[]
10+
) => Promise<Result<void, unknown>> | Result<void, unknown> | Promise<void>;
911
checkSetup: boolean;
1012
commandArgs: any[];
1113
}[] = [];
@@ -14,11 +16,17 @@ export class CommandQueue {
1416
private commandPromise: Promise<void> | null = null;
1517

1618
public add<A>(
17-
command: (...args: A[]) => Promise<Result<void, unknown>> | Result<void, unknown> | Promise<void>,
19+
command: (
20+
...args: A[]
21+
) => Promise<Result<void, unknown>> | Result<void, unknown> | Promise<void>,
1822
shouldCheckSetup = true,
1923
...args: A[]
2024
): void {
21-
this.queue.push({ command, checkSetup: shouldCheckSetup, commandArgs: args });
25+
this.queue.push({
26+
command,
27+
checkSetup: shouldCheckSetup,
28+
commandArgs: args,
29+
});
2230

2331
if (!this.running) {
2432
this.commandPromise = new Promise((resolve) => {
@@ -52,7 +60,10 @@ export class CommandQueue {
5260
}
5361

5462
const executeCommand = async (): Promise<Result<void, unknown>> => {
55-
return (await currentItem.command.apply(null, currentItem.commandArgs)) as Result<void, unknown>;
63+
return (await currentItem.command.apply(
64+
null,
65+
currentItem.commandArgs
66+
)) as Result<void, unknown>;
5667
};
5768

5869
const result = await wrapThrowsAsync(executeCommand)();

packages/react-native/src/lib/common/config.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ export class RNConfig {
2424
}
2525

2626
static getInstance(): RNConfig {
27-
if (!RNConfig.instance) {
28-
RNConfig.instance = new RNConfig();
29-
}
27+
RNConfig.instance ??= new RNConfig();
3028

3129
return RNConfig.instance;
3230
}
@@ -46,7 +44,9 @@ export class RNConfig {
4644

4745
public get(): TConfig {
4846
if (!this.config) {
49-
throw new Error("config is null, maybe the init function was not called?");
47+
throw new Error(
48+
"config is null, maybe the init function was not called?"
49+
);
5050
}
5151
return this.config;
5252
}
@@ -77,7 +77,10 @@ export class RNConfig {
7777

7878
private async saveToStorage(): Promise<Result<void>> {
7979
return wrapThrowsAsync(async () => {
80-
await AsyncStorage.setItem(RN_ASYNC_STORAGE_KEY, JSON.stringify(this.config));
80+
await AsyncStorage.setItem(
81+
RN_ASYNC_STORAGE_KEY,
82+
JSON.stringify(this.config)
83+
);
8184
})();
8285
}
8386

packages/react-native/src/lib/common/file-upload.ts

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
/* eslint-disable no-console -- used for error logging */
2-
import { type TUploadFileConfig, type TUploadFileResponse } from "@/types/storage";
2+
import {
3+
type TUploadFileConfig,
4+
type TUploadFileResponse,
5+
} from "@/types/storage";
36

47
export class StorageAPI {
5-
private appUrl: string;
6-
private environmentId: string;
8+
private readonly appUrl: string;
9+
private readonly environmentId: string;
710

811
constructor(appUrl: string, environmentId: string) {
912
this.appUrl = appUrl;
@@ -29,13 +32,16 @@ export class StorageAPI {
2932
surveyId,
3033
};
3134

32-
const response = await fetch(`${this.appUrl}/api/v1/client/${this.environmentId}/storage`, {
33-
method: "POST",
34-
headers: {
35-
"Content-Type": "application/json",
36-
},
37-
body: JSON.stringify(payload),
38-
});
35+
const response = await fetch(
36+
`${this.appUrl}/api/v1/client/${this.environmentId}/storage`,
37+
{
38+
method: "POST",
39+
headers: {
40+
"Content-Type": "application/json",
41+
},
42+
body: JSON.stringify(payload),
43+
}
44+
);
3945

4046
if (!response.ok) {
4147
throw new Error(`Upload failed with status: ${String(response.status)}`);
@@ -45,7 +51,13 @@ export class StorageAPI {
4551

4652
const { data } = json;
4753

48-
const { signedUrl, fileUrl, signingData, presignedFields, updatedFileName } = data;
54+
const {
55+
signedUrl,
56+
fileUrl,
57+
signingData,
58+
presignedFields,
59+
updatedFileName,
60+
} = data;
4961

5062
let localUploadDetails: Record<string, string> = {};
5163

@@ -86,7 +98,10 @@ export class StorageAPI {
8698

8799
let uploadResponse: Response = {} as Response;
88100

89-
const signedUrlCopy = signedUrl.replace("http://localhost:3000", this.appUrl);
101+
const signedUrlCopy = signedUrl.replace(
102+
"http://localhost:3000",
103+
this.appUrl
104+
);
90105

91106
try {
92107
uploadResponse = await fetch(signedUrlCopy, {
@@ -114,12 +129,16 @@ export class StorageAPI {
114129
// if s3 is used, we'll use the text response:
115130
const errorText = await uploadResponse.text();
116131
if (presignedFields && errorText.includes("EntityTooLarge")) {
117-
const error = new Error("File size exceeds the size limit for your plan");
132+
const error = new Error(
133+
"File size exceeds the size limit for your plan"
134+
);
118135
error.name = "FileTooLargeError";
119136
throw error;
120137
}
121138

122-
throw new Error(`Upload failed with status: ${String(uploadResponse.status)}`);
139+
throw new Error(
140+
`Upload failed with status: ${String(uploadResponse.status)}`
141+
);
123142
}
124143

125144
return fileUrl;

packages/react-native/src/lib/common/logger.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ export class Logger {
1010
private logLevel: LogLevel = "error";
1111

1212
static getInstance(): Logger {
13-
if (!Logger.instance) {
14-
Logger.instance = new Logger();
15-
}
13+
Logger.instance ??= new Logger();
1614
return Logger.instance;
1715
}
1816

packages/react-native/src/lib/common/storage.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import AsyncStorageModule from "@react-native-async-storage/async-storage";
22

3-
const AsyncStorageWithDefault = AsyncStorageModule as typeof AsyncStorageModule & {
4-
default?: typeof AsyncStorageModule;
5-
};
3+
const AsyncStorageWithDefault =
4+
AsyncStorageModule as typeof AsyncStorageModule & {
5+
default?: typeof AsyncStorageModule;
6+
};
67

78
const AsyncStorage = AsyncStorageWithDefault.default ?? AsyncStorageModule;
89

packages/react-native/src/lib/common/tests/command-queue.test.ts

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,24 @@ describe("CommandQueue", () => {
2121
test("executes commands in FIFO order", async () => {
2222
const executionOrder: string[] = [];
2323

24+
function delayedResult<T>(value: T, delayMs = 10): Promise<T> {
25+
return new Promise((resolve) =>
26+
setTimeout(() => resolve(value), delayMs)
27+
);
28+
}
29+
2430
// Mock commands with proper Result returns
2531
const cmdA = vi.fn(async (): Promise<Result<void, unknown>> => {
26-
return new Promise((resolve) => {
27-
setTimeout(() => {
28-
executionOrder.push("A");
29-
resolve({ ok: true, data: undefined });
30-
}, 10);
31-
});
32+
executionOrder.push("A");
33+
return delayedResult({ ok: true, data: undefined });
3234
});
3335
const cmdB = vi.fn(async (): Promise<Result<void, unknown>> => {
34-
return new Promise((resolve) => {
35-
setTimeout(() => {
36-
executionOrder.push("B");
37-
resolve({ ok: true, data: undefined });
38-
}, 10);
39-
});
36+
executionOrder.push("B");
37+
return delayedResult({ ok: true, data: undefined });
4038
});
4139
const cmdC = vi.fn(async (): Promise<Result<void, unknown>> => {
42-
return new Promise((resolve) => {
43-
setTimeout(() => {
44-
executionOrder.push("C");
45-
resolve({ ok: true, data: undefined });
46-
}, 10);
47-
});
40+
executionOrder.push("C");
41+
return delayedResult({ ok: true, data: undefined });
4842
});
4943

5044
// We'll assume checkSetup always ok for this test
@@ -107,12 +101,14 @@ describe("CommandQueue", () => {
107101

108102
test("logs errors if a command throws or returns error", async () => {
109103
// Spy on console.error to see if it's called
110-
const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {
111-
return {
112-
ok: true,
113-
data: undefined,
114-
};
115-
});
104+
const consoleErrorSpy = vi
105+
.spyOn(console, "error")
106+
.mockImplementation(() => {
107+
return {
108+
ok: true,
109+
data: undefined,
110+
};
111+
});
116112

117113
// Force checkSetup to succeed
118114
vi.mocked(checkSetup).mockReturnValue({ ok: true, data: undefined });
@@ -131,7 +127,10 @@ describe("CommandQueue", () => {
131127
queue.add(failingCmd, true);
132128
await queue.wait();
133129

134-
expect(consoleErrorSpy).toHaveBeenCalledWith("🧱 Formbricks - Global error: ", expect.any(Error));
130+
expect(consoleErrorSpy).toHaveBeenCalledWith(
131+
"🧱 Formbricks - Global error: ",
132+
expect.any(Error)
133+
);
135134
consoleErrorSpy.mockRestore();
136135
});
137136

packages/react-native/src/lib/common/tests/utils.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ const mockSurveyId2 = "qo9rwjmms42hoy3k85fp8vgu";
2525
const mockSegmentId1 = "p6yrnz3s2tvoe5r0l28unq7k";
2626
const mockSegmentId2 = "wz43zrxeddhb1uo9cicustar";
2727

28+
function delay(ms: number) {
29+
return new Promise((resolve) => setTimeout(resolve, ms));
30+
}
31+
2832
describe("utils.ts", () => {
2933
// ---------------------------------------------------------------------------------
3034
// diffInDays
@@ -54,9 +58,7 @@ describe("utils.ts", () => {
5458
describe("wrapThrowsAsync()", () => {
5559
test("returns ok on success", async () => {
5660
const fn = vi.fn(async (x: number) => {
57-
await new Promise((r) => {
58-
setTimeout(r, 10);
59-
});
61+
await delay(10);
6062
return x * 2;
6163
});
6264

@@ -71,9 +73,7 @@ describe("utils.ts", () => {
7173

7274
test("returns err on error", async () => {
7375
const fn = vi.fn(async () => {
74-
await new Promise((r) => {
75-
setTimeout(r, 10);
76-
});
76+
await delay(10);
7777
throw new Error("Something broke");
7878
});
7979
const wrapped = wrapThrowsAsync(fn);
@@ -359,7 +359,7 @@ describe("utils.ts", () => {
359359
const survey = {
360360
languages: [{ language: { code: "en" }, default: true, enabled: true }],
361361
} as unknown as TSurvey;
362-
const code = getLanguageCode(survey, undefined);
362+
const code = getLanguageCode(survey);
363363
expect(code).toBe("default");
364364
});
365365

packages/react-native/src/lib/common/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export const filterSurveys = (
9090

9191
// if survey has recontactDays, check if the last display was more than recontactDays ago
9292
// The previous approach checked the last display for each survey which is why we still have a surveyId in the displays array.
93+
// NOSONAR
9394
// TODO: Remove the surveyId from the displays array
9495
if (survey.recontactDays !== null) {
9596
return (

packages/react-native/src/lib/survey/store.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ type Listener = (state: TSurvey | null, prevSurvey: TSurvey | null) => void;
55
export class SurveyStore {
66
private static instance: SurveyStore | undefined;
77
private survey: TSurvey | null = null;
8-
private listeners = new Set<Listener>();
8+
private readonly listeners = new Set<Listener>();
99

1010
static getInstance(): SurveyStore {
11-
if (!SurveyStore.instance) {
12-
SurveyStore.instance = new SurveyStore();
13-
}
11+
SurveyStore.instance ??= new SurveyStore();
1412
return SurveyStore.instance;
1513
}
1614

0 commit comments

Comments
 (0)