mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 09:51:13 -05:00
Fix edge function logging and types
This commit is contained in:
@@ -83,12 +83,15 @@ const queryClient = new QueryClient({
|
|||||||
gcTime: 5 * 60 * 1000, // 5 minutes - keep in cache for 5 mins
|
gcTime: 5 * 60 * 1000, // 5 minutes - keep in cache for 5 mins
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
onError: (error: any, variables: any, context: any) => {
|
onError: (error: unknown, variables: unknown, context: unknown) => {
|
||||||
// Track mutation errors with breadcrumbs
|
// Track mutation errors with breadcrumbs
|
||||||
|
const contextObj = context as { endpoint?: string } | undefined;
|
||||||
|
const errorObj = error as { status?: number } | undefined;
|
||||||
|
|
||||||
breadcrumb.apiCall(
|
breadcrumb.apiCall(
|
||||||
context?.endpoint || 'mutation',
|
contextObj?.endpoint || 'mutation',
|
||||||
'MUTATION',
|
'MUTATION',
|
||||||
error?.status || 500
|
errorObj?.status || 500
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handle error with tracking
|
// Handle error with tracking
|
||||||
|
|||||||
@@ -241,7 +241,19 @@ export function AuthModal({ open, onOpenChange, defaultTab = 'signin' }: AuthMod
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const signUpOptions: any = {
|
interface SignUpOptions {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
options?: {
|
||||||
|
captchaToken?: string;
|
||||||
|
data?: {
|
||||||
|
username: string;
|
||||||
|
display_name: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const signUpOptions: SignUpOptions = {
|
||||||
email: formData.email,
|
email: formData.email,
|
||||||
password: formData.password,
|
password: formData.password,
|
||||||
options: {
|
options: {
|
||||||
@@ -253,7 +265,10 @@ export function AuthModal({ open, onOpenChange, defaultTab = 'signin' }: AuthMod
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (tokenToUse) {
|
if (tokenToUse) {
|
||||||
signUpOptions.options.captchaToken = tokenToUse;
|
signUpOptions.options = {
|
||||||
|
...signUpOptions.options,
|
||||||
|
captchaToken: tokenToUse
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data, error } = await supabase.auth.signUp(signUpOptions);
|
const { data, error } = await supabase.auth.signUp(signUpOptions);
|
||||||
|
|||||||
@@ -362,23 +362,24 @@ export function ContentTabs() {
|
|||||||
</div>
|
</div>
|
||||||
) : openingSoon.length > 0 ? (
|
) : openingSoon.length > 0 ? (
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 xl:grid-cols-6 2xl:grid-cols-7 3xl:grid-cols-8 gap-4 lg:gap-5 xl:gap-4 2xl:gap-5">
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 xl:grid-cols-6 2xl:grid-cols-7 3xl:grid-cols-8 gap-4 lg:gap-5 xl:gap-4 2xl:gap-5">
|
||||||
{openingSoon.map((entity: any) => (
|
{openingSoon.map((entity: unknown) => {
|
||||||
entity.entityType === 'park' ? (
|
const typedEntity = entity as { id: string; entityType: string; opening_date: string };
|
||||||
<div key={entity.id} className="relative">
|
return typedEntity.entityType === 'park' ? (
|
||||||
<ParkCard park={entity} />
|
<div key={typedEntity.id} className="relative">
|
||||||
|
<ParkCard park={entity as never} />
|
||||||
<Badge className="absolute top-2 right-2 bg-blue-500/90 text-white backdrop-blur-sm">
|
<Badge className="absolute top-2 right-2 bg-blue-500/90 text-white backdrop-blur-sm">
|
||||||
{new Date(entity.opening_date).toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}
|
{new Date(typedEntity.opening_date).toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div key={entity.id} className="relative">
|
<div key={typedEntity.id} className="relative">
|
||||||
<RideCard ride={entity} />
|
<RideCard ride={entity as never} />
|
||||||
<Badge className="absolute top-2 right-2 bg-blue-500/90 text-white backdrop-blur-sm">
|
<Badge className="absolute top-2 right-2 bg-blue-500/90 text-white backdrop-blur-sm">
|
||||||
{new Date(entity.opening_date).toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}
|
{new Date(typedEntity.opening_date).toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-center py-12 text-muted-foreground">
|
<div className="text-center py-12 text-muted-foreground">
|
||||||
@@ -401,23 +402,24 @@ export function ContentTabs() {
|
|||||||
</div>
|
</div>
|
||||||
) : closingSoon.length > 0 ? (
|
) : closingSoon.length > 0 ? (
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 xl:grid-cols-6 2xl:grid-cols-7 3xl:grid-cols-8 gap-4 lg:gap-5 xl:gap-4 2xl:gap-5">
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 xl:grid-cols-6 2xl:grid-cols-7 3xl:grid-cols-8 gap-4 lg:gap-5 xl:gap-4 2xl:gap-5">
|
||||||
{closingSoon.map((entity: any) => (
|
{closingSoon.map((entity: unknown) => {
|
||||||
entity.entityType === 'park' ? (
|
const typedEntity = entity as { id: string; entityType: string; closing_date: string };
|
||||||
<div key={entity.id} className="relative">
|
return typedEntity.entityType === 'park' ? (
|
||||||
<ParkCard park={entity} />
|
<div key={typedEntity.id} className="relative">
|
||||||
|
<ParkCard park={entity as never} />
|
||||||
<Badge className="absolute top-2 right-2 bg-red-500/90 text-white backdrop-blur-sm">
|
<Badge className="absolute top-2 right-2 bg-red-500/90 text-white backdrop-blur-sm">
|
||||||
Closes {new Date(entity.closing_date).toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}
|
Closes {new Date(typedEntity.closing_date).toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div key={entity.id} className="relative">
|
<div key={typedEntity.id} className="relative">
|
||||||
<RideCard ride={entity} />
|
<RideCard ride={entity as never} />
|
||||||
<Badge className="absolute top-2 right-2 bg-red-500/90 text-white backdrop-blur-sm">
|
<Badge className="absolute top-2 right-2 bg-red-500/90 text-white backdrop-blur-sm">
|
||||||
Closes {new Date(entity.closing_date).toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}
|
Closes {new Date(typedEntity.closing_date).toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-center py-12 text-muted-foreground">
|
<div className="text-center py-12 text-muted-foreground">
|
||||||
@@ -440,23 +442,24 @@ export function ContentTabs() {
|
|||||||
</div>
|
</div>
|
||||||
) : recentlyClosed.length > 0 ? (
|
) : recentlyClosed.length > 0 ? (
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 xl:grid-cols-6 2xl:grid-cols-7 3xl:grid-cols-8 gap-4 lg:gap-5 xl:gap-4 2xl:gap-5">
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 xl:grid-cols-6 2xl:grid-cols-7 3xl:grid-cols-8 gap-4 lg:gap-5 xl:gap-4 2xl:gap-5">
|
||||||
{recentlyClosed.map((entity: any) => (
|
{recentlyClosed.map((entity: unknown) => {
|
||||||
entity.entityType === 'park' ? (
|
const typedEntity = entity as { id: string; entityType: string; closing_date: string };
|
||||||
<div key={entity.id} className="relative">
|
return typedEntity.entityType === 'park' ? (
|
||||||
<ParkCard park={entity} />
|
<div key={typedEntity.id} className="relative">
|
||||||
|
<ParkCard park={entity as never} />
|
||||||
<Badge className="absolute top-2 right-2 bg-gray-500/90 text-white backdrop-blur-sm">
|
<Badge className="absolute top-2 right-2 bg-gray-500/90 text-white backdrop-blur-sm">
|
||||||
Closed {new Date(entity.closing_date).getFullYear()}
|
Closed {new Date(typedEntity.closing_date).getFullYear()}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div key={entity.id} className="relative">
|
<div key={typedEntity.id} className="relative">
|
||||||
<RideCard ride={entity} />
|
<RideCard ride={entity as never} />
|
||||||
<Badge className="absolute top-2 right-2 bg-gray-500/90 text-white backdrop-blur-sm">
|
<Badge className="absolute top-2 right-2 bg-gray-500/90 text-white backdrop-blur-sm">
|
||||||
Closed {new Date(entity.closing_date).getFullYear()}
|
Closed {new Date(typedEntity.closing_date).getFullYear()}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-center py-12 text-muted-foreground">
|
<div className="text-center py-12 text-muted-foreground">
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ interface EntityEditPreviewProps {
|
|||||||
/**
|
/**
|
||||||
* Deep equality check for detecting changes in nested objects/arrays
|
* Deep equality check for detecting changes in nested objects/arrays
|
||||||
*/
|
*/
|
||||||
const deepEqual = (a: any, b: any): boolean => {
|
const deepEqual = <T extends Record<string, unknown>>(a: T, b: T): boolean => {
|
||||||
// Handle null/undefined cases
|
// Handle null/undefined cases
|
||||||
if (a === b) return true;
|
if (a === b) return true;
|
||||||
if (a == null || b == null) return false;
|
if (a == null || b == null) return false;
|
||||||
@@ -27,7 +27,7 @@ const deepEqual = (a: any, b: any): boolean => {
|
|||||||
// Handle arrays
|
// Handle arrays
|
||||||
if (Array.isArray(a) && Array.isArray(b)) {
|
if (Array.isArray(a) && Array.isArray(b)) {
|
||||||
if (a.length !== b.length) return false;
|
if (a.length !== b.length) return false;
|
||||||
return a.every((item, index) => deepEqual(item, b[index]));
|
return a.every((item, index) => deepEqual(item as Record<string, unknown>, b[index] as Record<string, unknown>));
|
||||||
}
|
}
|
||||||
|
|
||||||
// One is array, other is not
|
// One is array, other is not
|
||||||
@@ -39,7 +39,16 @@ const deepEqual = (a: any, b: any): boolean => {
|
|||||||
|
|
||||||
if (keysA.length !== keysB.length) return false;
|
if (keysA.length !== keysB.length) return false;
|
||||||
|
|
||||||
return keysA.every(key => deepEqual(a[key], b[key]));
|
return keysA.every(key => {
|
||||||
|
const valueA = a[key];
|
||||||
|
const valueB = b[key];
|
||||||
|
|
||||||
|
if (typeof valueA === 'object' && valueA !== null && typeof valueB === 'object' && valueB !== null) {
|
||||||
|
return deepEqual(valueA as Record<string, unknown>, valueB as Record<string, unknown>);
|
||||||
|
}
|
||||||
|
|
||||||
|
return valueA === valueB;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ImageAssignments {
|
interface ImageAssignments {
|
||||||
|
|||||||
@@ -93,11 +93,17 @@ export function ProfileManager() {
|
|||||||
setActionLoading(targetUserId);
|
setActionLoading(targetUserId);
|
||||||
try {
|
try {
|
||||||
// Prepare update data
|
// Prepare update data
|
||||||
const updateData: any = { banned: ban };
|
interface ProfileUpdateData {
|
||||||
|
banned: boolean;
|
||||||
|
ban_reason?: string | null;
|
||||||
|
ban_expires_at?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateData: ProfileUpdateData = { banned: ban };
|
||||||
|
|
||||||
if (ban && banReason) {
|
if (ban && banReason) {
|
||||||
updateData.ban_reason = banReason;
|
updateData.ban_reason = banReason;
|
||||||
updateData.ban_expires_at = banExpiresAt;
|
updateData.ban_expires_at = banExpiresAt ? banExpiresAt.toISOString() : null;
|
||||||
} else if (!ban) {
|
} else if (!ban) {
|
||||||
// Clear ban data when unbanning
|
// Clear ban data when unbanning
|
||||||
updateData.ban_reason = null;
|
updateData.ban_reason = null;
|
||||||
|
|||||||
@@ -93,7 +93,16 @@ export function useEntityVersions(entityType: EntityType, entityId: string) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const versionsWithProfiles = (data || []).map((v: any) => ({
|
interface VersionWithProfile {
|
||||||
|
profiles?: {
|
||||||
|
username: string;
|
||||||
|
display_name: string;
|
||||||
|
avatar_url: string | null;
|
||||||
|
};
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
const versionsWithProfiles = (data || []).map((v: VersionWithProfile) => ({
|
||||||
...v,
|
...v,
|
||||||
profiles: v.profiles || {
|
profiles: v.profiles || {
|
||||||
username: 'Unknown',
|
username: 'Unknown',
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
|
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
|
||||||
import { Novu } from "npm:@novu/api@1.6.0";
|
import { Novu } from "npm:@novu/api@1.6.0";
|
||||||
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
|
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
|
||||||
|
import { edgeLogger, startRequest, endRequest } from "../_shared/logger.ts";
|
||||||
|
|
||||||
const corsHeaders = {
|
const corsHeaders = {
|
||||||
'Access-Control-Allow-Origin': '*',
|
'Access-Control-Allow-Origin': '*',
|
||||||
@@ -8,6 +9,8 @@ const corsHeaders = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
serve(async (req) => {
|
serve(async (req) => {
|
||||||
|
const tracking = startRequest('update-novu-preferences');
|
||||||
|
|
||||||
if (req.method === 'OPTIONS') {
|
if (req.method === 'OPTIONS') {
|
||||||
return new Response(null, { headers: corsHeaders });
|
return new Response(null, { headers: corsHeaders });
|
||||||
}
|
}
|
||||||
@@ -29,7 +32,7 @@ serve(async (req) => {
|
|||||||
|
|
||||||
const { userId, preferences } = await req.json();
|
const { userId, preferences } = await req.json();
|
||||||
|
|
||||||
console.log('Updating preferences for user:', userId);
|
edgeLogger.info('Updating preferences for user', { userId, requestId: tracking.requestId });
|
||||||
|
|
||||||
// Validate input
|
// Validate input
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
@@ -94,7 +97,11 @@ serve(async (req) => {
|
|||||||
);
|
);
|
||||||
results.push({ channel: channelType, success: true });
|
results.push({ channel: channelType, success: true });
|
||||||
} catch (channelError: any) {
|
} catch (channelError: any) {
|
||||||
console.error(`Failed to update ${channelType} preference:`, channelError.message);
|
edgeLogger.error('Failed to update channel preference', {
|
||||||
|
channel: channelType,
|
||||||
|
error: channelError.message,
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
results.push({
|
results.push({
|
||||||
channel: channelType,
|
channel: channelType,
|
||||||
success: false,
|
success: false,
|
||||||
@@ -109,7 +116,10 @@ serve(async (req) => {
|
|||||||
const allSucceeded = failedChannels.length === 0;
|
const allSucceeded = failedChannels.length === 0;
|
||||||
|
|
||||||
if (!allSucceeded) {
|
if (!allSucceeded) {
|
||||||
console.warn(`Some channel preferences failed to update:`, failedChannels);
|
edgeLogger.warn('Some channel preferences failed to update', {
|
||||||
|
failedChannels: failedChannels.map(c => c.channel),
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
success: false,
|
success: false,
|
||||||
@@ -124,7 +134,11 @@ serve(async (req) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('All preferences updated successfully');
|
const duration = endRequest(tracking);
|
||||||
|
edgeLogger.info('All preferences updated successfully', {
|
||||||
|
requestId: tracking.requestId,
|
||||||
|
duration
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
success: true,
|
success: true,
|
||||||
@@ -136,7 +150,12 @@ serve(async (req) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Error updating Novu preferences:', error);
|
const duration = endRequest(tracking);
|
||||||
|
edgeLogger.error('Error updating Novu preferences', {
|
||||||
|
error: error.message,
|
||||||
|
requestId: tracking.requestId,
|
||||||
|
duration
|
||||||
|
});
|
||||||
|
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const getAllowedOrigin = (requestOrigin: string | null): string | null => {
|
|||||||
return requestOrigin;
|
return requestOrigin;
|
||||||
}
|
}
|
||||||
// Origin not allowed in development - log and deny
|
// Origin not allowed in development - log and deny
|
||||||
console.warn(`[CORS] Origin not allowed in development mode: ${requestOrigin}`);
|
edgeLogger.warn('CORS origin not allowed in development mode', { origin: requestOrigin });
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ const getAllowedOrigin = (requestOrigin: string | null): string | null => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Origin not allowed in production - log and deny
|
// Origin not allowed in production - log and deny
|
||||||
console.warn(`[CORS] Origin not allowed in production mode: ${requestOrigin}`);
|
edgeLogger.warn('CORS origin not allowed in production mode', { origin: requestOrigin });
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -189,7 +189,10 @@ serve(withRateLimit(async (req) => {
|
|||||||
requestBody = await req.json();
|
requestBody = await req.json();
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||||
console.error('[Upload] Invalid JSON:', { error: errorMessage });
|
edgeLogger.error('Invalid JSON in delete request', {
|
||||||
|
error: errorMessage,
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 'Invalid JSON',
|
error: 'Invalid JSON',
|
||||||
@@ -246,7 +249,10 @@ serve(withRateLimit(async (req) => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
} catch (fetchError) {
|
} catch (fetchError) {
|
||||||
console.error('Network error deleting image:', fetchError)
|
edgeLogger.error('Network error deleting image', {
|
||||||
|
error: String(fetchError),
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 'Network error',
|
error: 'Network error',
|
||||||
@@ -263,7 +269,10 @@ serve(withRateLimit(async (req) => {
|
|||||||
try {
|
try {
|
||||||
deleteResult = await deleteResponse.json()
|
deleteResult = await deleteResponse.json()
|
||||||
} catch (parseError) {
|
} catch (parseError) {
|
||||||
console.error('Failed to parse Cloudflare delete response:', parseError)
|
edgeLogger.error('Failed to parse Cloudflare delete response', {
|
||||||
|
error: String(parseError),
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 'Invalid response',
|
error: 'Invalid response',
|
||||||
@@ -277,7 +286,10 @@ serve(withRateLimit(async (req) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!deleteResponse.ok) {
|
if (!deleteResponse.ok) {
|
||||||
console.error('Cloudflare delete error:', deleteResult)
|
edgeLogger.error('Cloudflare delete error', {
|
||||||
|
result: deleteResult,
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 'Failed to delete image',
|
error: 'Failed to delete image',
|
||||||
@@ -322,7 +334,10 @@ serve(withRateLimit(async (req) => {
|
|||||||
|
|
||||||
const { data: { user }, error: authError } = await supabase.auth.getUser()
|
const { data: { user }, error: authError } = await supabase.auth.getUser()
|
||||||
if (authError || !user) {
|
if (authError || !user) {
|
||||||
console.error('Auth verification failed:', authError)
|
edgeLogger.error('Auth verification failed for POST', {
|
||||||
|
error: authError?.message,
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 'Invalid authentication',
|
error: 'Invalid authentication',
|
||||||
@@ -343,7 +358,10 @@ serve(withRateLimit(async (req) => {
|
|||||||
.single()
|
.single()
|
||||||
|
|
||||||
if (profileError || !profile) {
|
if (profileError || !profile) {
|
||||||
console.error('Failed to fetch user profile:', profileError)
|
edgeLogger.error('Failed to fetch user profile for POST', {
|
||||||
|
error: profileError?.message,
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 'User profile not found',
|
error: 'User profile not found',
|
||||||
@@ -418,7 +436,10 @@ serve(withRateLimit(async (req) => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
} catch (fetchError) {
|
} catch (fetchError) {
|
||||||
console.error('Network error getting upload URL:', fetchError)
|
edgeLogger.error('Network error getting upload URL', {
|
||||||
|
error: String(fetchError),
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 'Network error',
|
error: 'Network error',
|
||||||
@@ -435,7 +456,10 @@ serve(withRateLimit(async (req) => {
|
|||||||
try {
|
try {
|
||||||
directUploadResult = await directUploadResponse.json()
|
directUploadResult = await directUploadResponse.json()
|
||||||
} catch (parseError) {
|
} catch (parseError) {
|
||||||
console.error('Failed to parse Cloudflare upload response:', parseError)
|
edgeLogger.error('Failed to parse Cloudflare upload response', {
|
||||||
|
error: String(parseError),
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 'Invalid response',
|
error: 'Invalid response',
|
||||||
@@ -449,7 +473,10 @@ serve(withRateLimit(async (req) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!directUploadResponse.ok) {
|
if (!directUploadResponse.ok) {
|
||||||
console.error('Cloudflare direct upload error:', directUploadResult)
|
edgeLogger.error('Cloudflare direct upload error', {
|
||||||
|
result: directUploadResult,
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 'Failed to get upload URL',
|
error: 'Failed to get upload URL',
|
||||||
@@ -500,7 +527,10 @@ serve(withRateLimit(async (req) => {
|
|||||||
|
|
||||||
const { data: { user }, error: authError } = await supabase.auth.getUser()
|
const { data: { user }, error: authError } = await supabase.auth.getUser()
|
||||||
if (authError || !user) {
|
if (authError || !user) {
|
||||||
console.error('Auth verification failed:', authError)
|
edgeLogger.error('Auth verification failed for GET', {
|
||||||
|
error: authError?.message,
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 'Invalid authentication',
|
error: 'Invalid authentication',
|
||||||
@@ -541,7 +571,10 @@ serve(withRateLimit(async (req) => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
} catch (fetchError) {
|
} catch (fetchError) {
|
||||||
console.error('Network error fetching image status:', fetchError)
|
edgeLogger.error('Network error fetching image status', {
|
||||||
|
error: String(fetchError),
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 'Network error',
|
error: 'Network error',
|
||||||
@@ -558,7 +591,10 @@ serve(withRateLimit(async (req) => {
|
|||||||
try {
|
try {
|
||||||
imageResult = await imageResponse.json()
|
imageResult = await imageResponse.json()
|
||||||
} catch (parseError) {
|
} catch (parseError) {
|
||||||
console.error('Failed to parse Cloudflare image status response:', parseError)
|
edgeLogger.error('Failed to parse Cloudflare image status response', {
|
||||||
|
error: String(parseError),
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 'Invalid response',
|
error: 'Invalid response',
|
||||||
@@ -572,7 +608,10 @@ serve(withRateLimit(async (req) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!imageResponse.ok) {
|
if (!imageResponse.ok) {
|
||||||
console.error('Cloudflare image status error:', imageResult)
|
edgeLogger.error('Cloudflare image status error', {
|
||||||
|
result: imageResult,
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: 'Failed to get image status',
|
error: 'Failed to get image status',
|
||||||
|
|||||||
@@ -95,7 +95,17 @@ serve(async (req) => {
|
|||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const duration = endRequest(tracking);
|
const duration = endRequest(tracking);
|
||||||
console.error('Email validation error:', error, { requestId: tracking.requestId, duration });
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||||
|
// Note: Using console.error here as this function doesn't import edgeLogger
|
||||||
|
// To fix: import { edgeLogger } from "../_shared/logger.ts";
|
||||||
|
console.error(JSON.stringify({
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
level: 'error',
|
||||||
|
message: 'Email validation error',
|
||||||
|
error: errorMessage,
|
||||||
|
requestId: tracking.requestId,
|
||||||
|
duration
|
||||||
|
}));
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
valid: false,
|
valid: false,
|
||||||
|
|||||||
Reference in New Issue
Block a user