Improve error handling and input validation for notification preferences

Add input validation for userId and channelPreferences, and enhance error reporting for Novu API calls by returning detailed results for each channel update.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: a8c5cf3e-a80e-462f-b090-b081acdcf03a
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
This commit is contained in:
pac7
2025-10-08 14:05:36 +00:00
parent 94631fd31b
commit 012f2995fa

View File

@@ -31,6 +31,33 @@ serve(async (req) => {
console.log('Updating preferences for user:', userId);
// Validate input
if (!userId) {
return new Response(
JSON.stringify({
success: false,
error: 'userId is required',
}),
{
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: 400,
}
);
}
if (!preferences?.channelPreferences) {
return new Response(
JSON.stringify({
success: false,
error: 'channelPreferences is required in preferences object',
}),
{
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: 400,
}
);
}
// Get Novu subscriber ID from database
const { data: prefData, error: prefError } = await supabase
.from('user_notification_preferences')
@@ -49,38 +76,59 @@ serve(async (req) => {
const channelPrefs = preferences.channelPreferences;
const workflowId = preferences.workflowId || 'default';
try {
// Update each channel preference separately
const channelTypes = ['email', 'sms', 'in_app', 'push'] as const;
for (const channelType of channelTypes) {
if (channelPrefs[channelType] !== undefined) {
try {
await novu.subscribers.updatePreference(
subscriberId,
workflowId,
{
channel: {
type: channelType as any, // Cast to any to handle SDK type limitations
enabled: channelPrefs[channelType]
},
}
);
} catch (channelError: any) {
console.warn(`Failed to update ${channelType} preference:`, channelError.message);
// Continue with other channels even if one fails
}
const channelTypes = ['email', 'sms', 'in_app', 'push'] as const;
const results: { channel: string; success: boolean; error?: string }[] = [];
for (const channelType of channelTypes) {
if (channelPrefs[channelType] !== undefined) {
try {
await novu.subscribers.updatePreference(
subscriberId,
workflowId,
{
channel: {
type: channelType as any, // Cast to any to handle SDK type limitations
enabled: channelPrefs[channelType]
},
}
);
results.push({ channel: channelType, success: true });
} catch (channelError: any) {
console.error(`Failed to update ${channelType} preference:`, channelError.message);
results.push({
channel: channelType,
success: false,
error: channelError.message || 'Unknown error'
});
}
}
console.log('Preferences updated successfully');
} catch (novuError: any) {
console.error('Novu API error:', novuError);
throw new Error(`Failed to update Novu preferences: ${novuError.message || 'Unknown error'}`);
}
// Check if any updates failed
const failedChannels = results.filter(r => !r.success);
const allSucceeded = failedChannels.length === 0;
if (!allSucceeded) {
console.warn(`Some channel preferences failed to update:`, failedChannels);
return new Response(
JSON.stringify({
success: false,
error: 'Some channel preferences failed to update',
results,
failedChannels: failedChannels.map(c => c.channel),
}),
{
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: 502, // Bad Gateway - external service failure
}
);
}
console.log('All preferences updated successfully');
return new Response(
JSON.stringify({
success: true,
results,
}),
{
headers: { ...corsHeaders, 'Content-Type': 'application/json' },