@@ -65,6 +65,74 @@ 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+ logger . error ( "Failed to send updates" ) ;
133+ }
134+ }
135+
68136 public async processUpdates ( ) : Promise < void > {
69137 if ( ! this . updates ) {
70138 return ;
@@ -80,66 +148,29 @@ export class UpdateQueue {
80148 let currentUpdates = { ...this . updates } ;
81149 const config = await RNConfig . getInstance ( ) ;
82150
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- }
151+ if ( Object . keys ( currentUpdates ) . length === 0 ) {
152+ this . clearUpdates ( ) ;
153+ resolve ( ) ;
154+ return ;
155+ }
156+
157+ const effectiveUserId =
158+ currentUpdates . userId ?? config . get ( ) . user . data . userId ;
159+
160+ // Handle language updates without userId
161+ if ( ! effectiveUserId ) {
162+ currentUpdates = this . handleLanguageWithoutUserId (
163+ currentUpdates ,
164+ config
165+ ) ;
141166 }
142167
168+ // Validate attributes require userId
169+ this . validateAttributesWithUserId ( currentUpdates , effectiveUserId ) ;
170+
171+ // Send updates if we have a userId
172+ await this . sendUpdatesIfNeeded ( effectiveUserId , currentUpdates ) ;
173+
143174 this . clearUpdates ( ) ;
144175 resolve ( ) ;
145176 } catch ( error : unknown ) {
0 commit comments