Skip to content

Commit 56fc1b6

Browse files
fix: sonar issues (#26)
* fix: sonar issues * fixes sonarqube issues * feedback * feedback --------- Co-authored-by: pandeymangg <[email protected]>
1 parent 38d1455 commit 56fc1b6

File tree

6 files changed

+142
-100
lines changed

6 files changed

+142
-100
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import type {
22
TEnvironmentState,
33
TEnvironmentStateProject,
4-
TProjectStyling,
54
TUserState,
65
} from "@/types/config";
76
import type { Result } from "@/types/error";
7+
import type { TProjectStyling } from "@/types/project";
88
import type { TSurvey } from "@/types/survey";
99

1010
// Helper function to calculate difference in days between two dates
@@ -77,7 +77,7 @@ export const filterSurveys = (
7777
);
7878

7979
default:
80-
throw Error("Invalid displayOption");
80+
throw new Error("Invalid displayOption");
8181
}
8282
});
8383

packages/react-native/src/lib/user/update-queue.ts

Lines changed: 103 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ export class UpdateQueue {
2121
}
2222

2323
public updateUserId(userId: string): void {
24-
if (!this.updates) {
24+
if (this.updates) {
2525
this.updates = {
26+
...this.updates,
2627
userId,
27-
attributes: {},
2828
};
2929
} else {
3030
this.updates = {
31-
...this.updates,
3231
userId,
32+
attributes: {},
3333
};
3434
}
3535
}
@@ -39,16 +39,16 @@ export class UpdateQueue {
3939
// Get userId from updates first, then fallback to config
4040
const userId = this.updates?.userId ?? config.get().user.data.userId ?? "";
4141

42-
if (!this.updates) {
42+
if (this.updates) {
4343
this.updates = {
44+
...this.updates,
4445
userId,
45-
attributes,
46+
attributes: { ...this.updates.attributes, ...attributes },
4647
};
4748
} else {
4849
this.updates = {
49-
...this.updates,
5050
userId,
51-
attributes: { ...this.updates.attributes, ...attributes },
51+
attributes,
5252
};
5353
}
5454
}
@@ -65,6 +65,81 @@ export class UpdateQueue {
6565
return !this.updates;
6666
}
6767

68+
private handleLanguageWithoutUserId(
69+
currentUpdates: Partial<TUpdates> & { attributes?: TAttributes },
70+
config: RNConfig
71+
): Partial<TUpdates> & { attributes?: TAttributes } {
72+
if (!currentUpdates.attributes?.language) {
73+
return currentUpdates;
74+
}
75+
76+
// Update language in local config
77+
config.update({
78+
...config.get(),
79+
user: {
80+
...config.get().user,
81+
data: {
82+
...config.get().user.data,
83+
language: currentUpdates.attributes.language,
84+
},
85+
},
86+
});
87+
88+
logger.debug("Updated language successfully");
89+
90+
// Remove language from attributes
91+
const { language: _, ...remainingAttributes } = currentUpdates.attributes;
92+
return {
93+
...currentUpdates,
94+
attributes: remainingAttributes,
95+
};
96+
}
97+
98+
private validateAttributesWithUserId(
99+
currentUpdates: Partial<TUpdates> & { attributes?: TAttributes },
100+
effectiveUserId: string | null | undefined
101+
): void {
102+
const hasAttributes =
103+
Object.keys(currentUpdates.attributes ?? {}).length > 0;
104+
105+
if (hasAttributes && !effectiveUserId) {
106+
const errorMessage =
107+
"Formbricks can't set attributes without a userId! Please set a userId first with the setUserId function";
108+
logger.error(errorMessage);
109+
this.clearUpdates();
110+
throw new Error(errorMessage);
111+
}
112+
}
113+
114+
private async sendUpdatesIfNeeded(
115+
effectiveUserId: string | null | undefined,
116+
currentUpdates: Partial<TUpdates> & { attributes?: TAttributes }
117+
): Promise<void> {
118+
if (!effectiveUserId) {
119+
return;
120+
}
121+
122+
const result = await sendUpdates({
123+
updates: {
124+
userId: effectiveUserId,
125+
attributes: currentUpdates.attributes ?? {},
126+
},
127+
});
128+
129+
if (result.ok) {
130+
logger.debug("Updates sent successfully");
131+
} else {
132+
const err = result.error as {
133+
status?: number;
134+
code?: string;
135+
message?: string;
136+
};
137+
logger.error(
138+
`Failed to send updates: ${err?.message ?? "unknown error"}`
139+
);
140+
}
141+
}
142+
68143
public async processUpdates(): Promise<void> {
69144
if (!this.updates) {
70145
return;
@@ -80,66 +155,29 @@ export class UpdateQueue {
80155
let currentUpdates = { ...this.updates };
81156
const config = await RNConfig.getInstance();
82157

83-
if (Object.keys(currentUpdates).length > 0) {
84-
// Get userId from either updates or config
85-
const effectiveUserId =
86-
currentUpdates.userId ?? config.get().user.data.userId;
87-
const isLanguageInUpdates = currentUpdates.attributes?.language;
88-
89-
if (!effectiveUserId && isLanguageInUpdates) {
90-
// no user id set but the updates contain a language
91-
// we need to set this language in the local config:
92-
config.update({
93-
...config.get(),
94-
user: {
95-
...config.get().user,
96-
data: {
97-
...config.get().user.data,
98-
language: currentUpdates.attributes?.language,
99-
},
100-
},
101-
});
102-
103-
logger.debug("Updated language successfully");
104-
105-
const { language: _, ...remainingAttributes } =
106-
currentUpdates.attributes ?? {};
107-
108-
// remove language from attributes
109-
currentUpdates = {
110-
...currentUpdates,
111-
attributes: remainingAttributes,
112-
};
113-
}
114-
115-
if (
116-
Object.keys(currentUpdates.attributes ?? {}).length > 0 &&
117-
!effectiveUserId
118-
) {
119-
const errorMessage =
120-
"Formbricks can't set attributes without a userId! Please set a userId first with the setUserId function";
121-
logger.error(errorMessage);
122-
this.clearUpdates();
123-
throw new Error(errorMessage);
124-
}
125-
126-
// Only send updates if we have a userId (either from updates or local storage)
127-
if (effectiveUserId) {
128-
const result = await sendUpdates({
129-
updates: {
130-
userId: effectiveUserId,
131-
attributes: currentUpdates.attributes ?? {},
132-
},
133-
});
134-
135-
if (result.ok) {
136-
logger.debug("Updates sent successfully");
137-
} else {
138-
logger.error("Failed to send updates");
139-
}
140-
}
158+
if (Object.keys(currentUpdates).length === 0) {
159+
this.clearUpdates();
160+
resolve();
161+
return;
141162
}
142163

164+
const effectiveUserId =
165+
currentUpdates.userId ?? config.get().user.data.userId;
166+
167+
// Handle language updates without userId
168+
if (!effectiveUserId) {
169+
currentUpdates = this.handleLanguageWithoutUserId(
170+
currentUpdates,
171+
config
172+
);
173+
}
174+
175+
// Validate attributes require userId
176+
this.validateAttributesWithUserId(currentUpdates, effectiveUserId);
177+
178+
// Send updates if we have a userId
179+
await this.sendUpdatesIfNeeded(effectiveUserId, currentUpdates);
180+
143181
this.clearUpdates();
144182
resolve();
145183
} catch (error: unknown) {

packages/react-native/src/types/config.ts

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { type TResponseUpdate } from "@/types/response";
33
import { type TFileUploadParams } from "@/types/storage";
44
import { z } from "zod";
55
import { type TActionClass } from "./action-class";
6-
import { type TProject } from "./project";
7-
import { type TSurvey } from "./survey";
6+
import type { TProject, TProjectStyling } from "./project";
7+
import type { TSurvey } from "./survey";
88

99
export type TEnvironmentStateProject = Pick<
1010
TProject,
@@ -71,38 +71,8 @@ export interface TConfigInput {
7171
appUrl: string;
7272
}
7373

74-
export interface TStylingColor {
75-
light: string;
76-
dark?: string | null;
77-
}
7874

79-
export interface TBaseStyling {
80-
brandColor?: TStylingColor | null;
81-
questionColor?: TStylingColor | null;
82-
inputColor?: TStylingColor | null;
83-
inputBorderColor?: TStylingColor | null;
84-
cardBackgroundColor?: TStylingColor | null;
85-
cardBorderColor?: TStylingColor | null;
86-
cardShadowColor?: TStylingColor | null;
87-
highlightBorderColor?: TStylingColor | null;
88-
isDarkModeEnabled?: boolean | null;
89-
roundness?: number | null;
90-
cardArrangement?: {
91-
linkSurveys: "casual" | "straight" | "simple";
92-
appSurveys: "casual" | "straight" | "simple";
93-
} | null;
94-
background?: {
95-
bg?: string | null;
96-
bgType?: "animation" | "color" | "image" | "upload" | null;
97-
brightness?: number | null;
98-
} | null;
99-
hideProgressBar?: boolean | null;
100-
isLogoHidden?: boolean | null;
101-
}
10275

103-
export interface TProjectStyling extends TBaseStyling {
104-
allowStyleOverwrite: boolean;
105-
}
10676

10777
export interface TWebViewOnMessageData {
10878
onFinished?: boolean | null;

packages/react-native/src/types/project.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { TBaseStyling } from "./styling";
2+
13
export type TProject = {
24
id: string;
35
createdAt: Date;
@@ -24,3 +26,7 @@ export type TProject = {
2426
bgColor?: string;
2527
} | null;
2628
};
29+
30+
export interface TProjectStyling extends TBaseStyling {
31+
allowStyleOverwrite: boolean;
32+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
export interface TStylingColor {
2+
light: string;
3+
dark?: string | null;
4+
}
5+
6+
export interface TBaseStyling {
7+
brandColor?: TStylingColor | null;
8+
questionColor?: TStylingColor | null;
9+
inputColor?: TStylingColor | null;
10+
inputBorderColor?: TStylingColor | null;
11+
cardBackgroundColor?: TStylingColor | null;
12+
cardBorderColor?: TStylingColor | null;
13+
cardShadowColor?: TStylingColor | null;
14+
highlightBorderColor?: TStylingColor | null;
15+
isDarkModeEnabled?: boolean | null;
16+
roundness?: number | null;
17+
cardArrangement?: {
18+
linkSurveys: "casual" | "straight" | "simple";
19+
appSurveys: "casual" | "straight" | "simple";
20+
} | null;
21+
background?: {
22+
bg?: string | null;
23+
bgType?: "animation" | "color" | "image" | "upload" | null;
24+
brightness?: number | null;
25+
} | null;
26+
hideProgressBar?: boolean | null;
27+
isLogoHidden?: boolean | null;
28+
}

packages/react-native/src/types/survey.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import type { TProjectStyling } from "@/types/config";
21
import type { TResponseData, TResponseUpdate } from "@/types/response";
32
import type { TFileUploadParams, TUploadFileConfig } from "@/types/storage";
3+
import type { TProjectStyling } from "./project";
44

55
export type TJsFileUploadParams = {
66
file: {

0 commit comments

Comments
 (0)