(userId: string, updates: UpdateCommunityProfileInput)
| 154 | // ===================================================== |
| 155 | |
| 156 | async updateProfile(userId: string, updates: UpdateCommunityProfileInput): Promise<CommunityProfile | null> { |
| 157 | const COLUMN_MAP: Record<keyof UpdateCommunityProfileInput, string> = { |
| 158 | slug: 'slug', |
| 159 | headline: 'headline', |
| 160 | bio: 'bio', |
| 161 | avatar_url: 'avatar_url', |
| 162 | expertise: 'expertise', |
| 163 | interests: 'interests', |
| 164 | linkedin_url: 'linkedin_url', |
| 165 | twitter_url: 'twitter_url', |
| 166 | github_username: 'github_username', |
| 167 | is_public: 'is_public', |
| 168 | open_to_coffee_chat: 'open_to_coffee_chat', |
| 169 | open_to_intros: 'open_to_intros', |
| 170 | city: 'city', |
| 171 | }; |
| 172 | |
| 173 | const setClauses: string[] = []; |
| 174 | const params: unknown[] = []; |
| 175 | let paramIndex = 1; |
| 176 | |
| 177 | // Normalize tag arrays: lowercase, trim, deduplicate |
| 178 | if (updates.expertise) { |
| 179 | updates.expertise = [...new Set(updates.expertise.map(t => t.trim().toLowerCase()).filter(Boolean))]; |
| 180 | } |
| 181 | if (updates.interests) { |
| 182 | updates.interests = [...new Set(updates.interests.map(t => t.trim().toLowerCase()).filter(Boolean))]; |
| 183 | } |
| 184 | |
| 185 | for (const [key, value] of Object.entries(updates)) { |
| 186 | const columnName = COLUMN_MAP[key as keyof UpdateCommunityProfileInput]; |
| 187 | if (!columnName) continue; |
| 188 | setClauses.push(`${columnName} = $${paramIndex++}`); |
| 189 | params.push(value); |
| 190 | } |
| 191 | |
| 192 | if (setClauses.length === 0) { |
| 193 | return this.getProfile(userId); |
| 194 | } |
| 195 | |
| 196 | params.push(userId); |
| 197 | const sql = ` |
| 198 | UPDATE users |
| 199 | SET ${setClauses.join(', ')}, updated_at = NOW() |
| 200 | WHERE workos_user_id = $${paramIndex} |
| 201 | RETURNING workos_user_id, slug, headline, bio, avatar_url, expertise, interests, |
| 202 | linkedin_url, twitter_url, github_username, is_public, open_to_coffee_chat, open_to_intros, city |
| 203 | `; |
| 204 | |
| 205 | const result = await query<CommunityProfile>(sql, params); |
| 206 | return result.rows[0] || null; |
| 207 | } |
| 208 | |
| 209 | async getProfile(userId: string): Promise<CommunityProfile | null> { |
| 210 | const result = await query<CommunityProfile>( |
nothing calls this directly
no test coverage detected