Skip to content

Commit 35156d2

Browse files
prazgaitisclaude
andcommitted
feat: add Supabase avatar migration query and mutation
Add findUsersWithSupabaseAvatars query and patchUserAvatar mutation to support migrating avatar URLs from Supabase to Cloudinary. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 03d894e commit 35156d2

3 files changed

Lines changed: 32 additions & 0 deletions

File tree

packages/backend/_generated/api.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import type * as actions_clear from "../actions/clear.js";
1818
import type * as actions_createChallengeFromConfig from "../actions/createChallengeFromConfig.js";
1919
import type * as actions_fix2025ActivityTypes from "../actions/fix2025ActivityTypes.js";
2020
import type * as actions_fixContributesToStreak from "../actions/fixContributesToStreak.js";
21+
import type * as actions_migrateSupabaseAvatars from "../actions/migrateSupabaseAvatars.js";
2122
import type * as actions_payments from "../actions/payments.js";
2223
import type * as actions_rescoreStravaActivities from "../actions/rescoreStravaActivities.js";
2324
import type * as actions_seed from "../actions/seed.js";
@@ -159,6 +160,7 @@ declare const fullApi: ApiFromModules<{
159160
"actions/createChallengeFromConfig": typeof actions_createChallengeFromConfig;
160161
"actions/fix2025ActivityTypes": typeof actions_fix2025ActivityTypes;
161162
"actions/fixContributesToStreak": typeof actions_fixContributesToStreak;
163+
"actions/migrateSupabaseAvatars": typeof actions_migrateSupabaseAvatars;
162164
"actions/payments": typeof actions_payments;
163165
"actions/rescoreStravaActivities": typeof actions_rescoreStravaActivities;
164166
"actions/seed": typeof actions_seed;

packages/backend/mutations/backfillCloudinary.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
import { internalMutation } from "../_generated/server";
22
import { v } from "convex/values";
33

4+
/**
5+
* Update a user's avatarUrl after migrating from Supabase to Cloudinary.
6+
*/
7+
export const patchUserAvatar = internalMutation({
8+
args: {
9+
userId: v.id("users"),
10+
avatarUrl: v.string(),
11+
},
12+
handler: async (ctx, args) => {
13+
await ctx.db.patch(args.userId, { avatarUrl: args.avatarUrl });
14+
},
15+
});
16+
417
/**
518
* Patch an activity with cloudinaryPublicIds after backfill upload.
619
*/

packages/backend/queries/backfillCloudinary.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
import { internalQuery } from "../_generated/server";
22
import { v } from "convex/values";
33

4+
/**
5+
* Find users whose avatarUrl points to Supabase storage.
6+
*/
7+
export const findUsersWithSupabaseAvatars = internalQuery({
8+
args: {},
9+
handler: async (ctx) => {
10+
const users = await ctx.db.query("users").collect();
11+
return users
12+
.filter((u) => u.avatarUrl?.includes("supabase.co"))
13+
.map((u) => ({
14+
_id: u._id,
15+
name: u.name,
16+
avatarUrl: u.avatarUrl!,
17+
}));
18+
},
19+
});
20+
421
/**
522
* Find activities that have Convex mediaIds but no cloudinaryPublicIds.
623
* Used by the backfill action to process existing media.

0 commit comments

Comments
 (0)