mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-22 11:11:14 -05:00
Fix Novu migration utility query
This commit is contained in:
153
supabase/functions/migrate-novu-users/index.ts
Normal file
153
supabase/functions/migrate-novu-users/index.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
|
||||
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
|
||||
import { Novu } from "npm:@novu/node@2.0.2";
|
||||
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
|
||||
};
|
||||
|
||||
serve(async (req) => {
|
||||
if (req.method === 'OPTIONS') {
|
||||
return new Response(null, { headers: corsHeaders });
|
||||
}
|
||||
|
||||
try {
|
||||
const supabaseUrl = Deno.env.get('SUPABASE_URL')!;
|
||||
const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
|
||||
const novuApiKey = Deno.env.get('NOVU_API_KEY');
|
||||
|
||||
if (!novuApiKey) {
|
||||
throw new Error('NOVU_API_KEY is not configured');
|
||||
}
|
||||
|
||||
// Create Supabase client with service role for admin access
|
||||
const supabase = createClient(supabaseUrl, supabaseServiceKey);
|
||||
|
||||
const novu = new Novu(novuApiKey, {
|
||||
backendUrl: Deno.env.get('VITE_NOVU_API_URL') || 'https://api.novu.co',
|
||||
});
|
||||
|
||||
// Fetch users who don't have Novu subscriber IDs
|
||||
const { data: existingPrefs, error: prefsError } = await supabase
|
||||
.from('user_notification_preferences')
|
||||
.select('user_id')
|
||||
.not('novu_subscriber_id', 'is', null);
|
||||
|
||||
if (prefsError) throw prefsError;
|
||||
|
||||
const existingUserIds = existingPrefs?.map(p => p.user_id) || [];
|
||||
|
||||
// Fetch all profiles
|
||||
let query = supabase
|
||||
.from('profiles')
|
||||
.select('user_id');
|
||||
|
||||
// Only add the not filter if there are existing user IDs
|
||||
if (existingUserIds.length > 0) {
|
||||
query = query.not('user_id', 'in', `(${existingUserIds.join(',')})`);
|
||||
}
|
||||
|
||||
const { data: profiles, error: profilesError } = await query;
|
||||
|
||||
if (profilesError) throw profilesError;
|
||||
|
||||
if (!profiles || profiles.length === 0) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
message: 'No users to migrate',
|
||||
results: [],
|
||||
}),
|
||||
{
|
||||
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
|
||||
status: 200,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Fetch user emails from auth.users using service role
|
||||
const userIds = profiles.map(p => p.user_id);
|
||||
const { data: authUsers, error: authError } = await supabase.auth.admin.listUsers();
|
||||
|
||||
if (authError) throw authError;
|
||||
|
||||
const userEmails = new Map(
|
||||
authUsers.users
|
||||
.filter(u => userIds.includes(u.id))
|
||||
.map(u => [u.id, u.email])
|
||||
);
|
||||
|
||||
// Migrate users
|
||||
const results = [];
|
||||
for (const profile of profiles) {
|
||||
const email = userEmails.get(profile.user_id);
|
||||
|
||||
if (!email) {
|
||||
results.push({
|
||||
userId: profile.user_id,
|
||||
email: 'No email found',
|
||||
success: false,
|
||||
error: 'User email not found',
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const subscriber = await novu.subscribers.identify(profile.user_id, {
|
||||
email,
|
||||
data: { userId: profile.user_id },
|
||||
});
|
||||
|
||||
// Update the user's notification preferences with the Novu subscriber ID
|
||||
await supabase
|
||||
.from('user_notification_preferences')
|
||||
.upsert({
|
||||
user_id: profile.user_id,
|
||||
novu_subscriber_id: subscriber.data._id,
|
||||
});
|
||||
|
||||
results.push({
|
||||
userId: profile.user_id,
|
||||
email,
|
||||
success: true,
|
||||
});
|
||||
} catch (error: any) {
|
||||
results.push({
|
||||
userId: profile.user_id,
|
||||
email,
|
||||
success: false,
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
|
||||
// Small delay to avoid overwhelming the API
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
total: profiles.length,
|
||||
results,
|
||||
}),
|
||||
{
|
||||
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
|
||||
status: 200,
|
||||
}
|
||||
);
|
||||
} catch (error: any) {
|
||||
console.error('Error migrating Novu users:', error);
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
success: false,
|
||||
error: error.message,
|
||||
}),
|
||||
{
|
||||
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
|
||||
status: 500,
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user