mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 15:11:13 -05:00
157 lines
4.3 KiB
TypeScript
157 lines
4.3 KiB
TypeScript
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/api@0.0.7";
|
|
|
|
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({
|
|
apiKey: novuApiKey,
|
|
baseURL: 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 with usernames
|
|
let query = supabase
|
|
.from('profiles')
|
|
.select('user_id, username');
|
|
|
|
// 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,
|
|
firstName: profile.username,
|
|
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,
|
|
username: profile.username,
|
|
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,
|
|
}
|
|
);
|
|
}
|
|
});
|