Fix remaining JSONB references

This commit is contained in:
gpt-engineer-app[bot]
2025-11-03 21:36:08 +00:00
parent 22f4a68bd8
commit b5cbc42cdf
6 changed files with 308 additions and 52 deletions

View File

@@ -26,7 +26,11 @@ interface ErrorDetails {
duration_ms: number;
user_id?: string;
request_breadcrumbs?: Breadcrumb[];
environment_context?: Record<string, unknown>;
user_agent?: string;
client_version?: string;
timezone?: string;
referrer?: string;
ip_address_hash?: string;
}
interface ErrorDetailsModalProps {
@@ -173,13 +177,43 @@ ${error.error_stack ? `Stack Trace:\n${error.error_stack}` : ''}
</TabsContent>
<TabsContent value="environment">
{error.environment_context ? (
<pre className="bg-muted p-4 rounded-lg overflow-x-auto text-xs">
{JSON.stringify(error.environment_context, null, 2)}
</pre>
) : (
<p className="text-muted-foreground">No environment context available</p>
)}
<div className="space-y-4">
<div className="grid grid-cols-2 gap-4">
{error.user_agent && (
<div>
<label className="text-sm font-medium">User Agent</label>
<p className="text-xs font-mono break-all">{error.user_agent}</p>
</div>
)}
{error.client_version && (
<div>
<label className="text-sm font-medium">Client Version</label>
<p className="text-sm">{error.client_version}</p>
</div>
)}
{error.timezone && (
<div>
<label className="text-sm font-medium">Timezone</label>
<p className="text-sm">{error.timezone}</p>
</div>
)}
{error.referrer && (
<div>
<label className="text-sm font-medium">Referrer</label>
<p className="text-xs font-mono break-all">{error.referrer}</p>
</div>
)}
{error.ip_address_hash && (
<div>
<label className="text-sm font-medium">IP Hash</label>
<p className="text-xs font-mono">{error.ip_address_hash}</p>
</div>
)}
</div>
{!error.user_agent && !error.client_version && !error.timezone && !error.referrer && !error.ip_address_hash && (
<p className="text-muted-foreground">No environment data available</p>
)}
</div>
</TabsContent>
</Tabs>

View File

@@ -32,18 +32,6 @@ export function isReviewWithPhotos(content: any): boolean {
);
}
/**
* Type guard: Check if content is a photo submission with JSONB photos
*/
export function isPhotoSubmissionWithJsonb(content: any): boolean {
return (
content &&
typeof content === 'object' &&
content.content &&
Array.isArray(content.content.photos) &&
content.content.photos.length > 0
);
}
/**
* Normalize photo data from any source to PhotoItem[]

View File

@@ -73,9 +73,8 @@ export async function trackRequest<T>(
}
: { type: 'UnknownError', message: String(error), stack: undefined };
// Capture breadcrumbs and environment
// Capture breadcrumbs only (environment stored as direct columns)
const breadcrumbs = breadcrumbManager.getAll();
const environment = captureEnvironmentContext();
// Log error to database (fire and forget)
logRequestMetadata({
@@ -89,7 +88,6 @@ export async function trackRequest<T>(
errorMessage: errorInfo.message,
errorStack: errorInfo.stack,
breadcrumbs,
environmentContext: environment,
userAgent: context.userAgent,
clientVersion: context.clientVersion,
parentRequestId: options.parentRequestId,
@@ -116,7 +114,6 @@ interface RequestMetadata {
errorMessage?: string;
errorStack?: string;
breadcrumbs?: any[];
environmentContext?: any;
userAgent?: string;
clientVersion?: string;
parentRequestId?: string;
@@ -136,7 +133,7 @@ async function logRequestMetadata(metadata: RequestMetadata): Promise<void> {
p_error_message: metadata.errorMessage ?? undefined,
p_error_stack: metadata.errorStack ?? undefined,
p_breadcrumbs: metadata.breadcrumbs ? JSON.stringify(metadata.breadcrumbs) : '[]',
p_environment_context: metadata.environmentContext ? JSON.stringify(metadata.environmentContext) : '{}',
p_environment_context: '{}', // No longer used - environment stored as direct columns
p_user_agent: metadata.userAgent ?? undefined,
p_client_version: metadata.clientVersion ?? undefined,
p_parent_request_id: metadata.parentRequestId ?? undefined,

View File

@@ -218,33 +218,31 @@ export function generateRandomRideModel(manufacturerId: string, counter: number)
// Cleanup utilities
export async function clearTestData(): Promise<{ deleted: number }> {
try {
// Find all test submissions using proper JSON path query
const { data: testSubmissions, error: fetchError } = await supabase
.from('content_submissions')
.select('id')
.eq('status', 'pending')
.eq('content->metadata->>is_test_data', 'true');
// Find all test submissions by querying submission_metadata
const { data: testMetadata, error: metadataError } = await supabase
.from('submission_metadata')
.select('submission_id')
.eq('metadata_key', 'is_test_data')
.eq('metadata_value', 'true');
if (fetchError) throw fetchError;
if (metadataError) throw metadataError;
const submissionCount = testSubmissions?.length || 0;
const submissionIds = testMetadata?.map(m => m.submission_id) || [];
const submissionCount = submissionIds.length;
// Delete submissions if found
if (submissionCount > 0) {
const batchSize = 100;
let totalDeleted = 0;
for (let i = 0; i < testSubmissions.length; i += batchSize) {
const batch = testSubmissions.slice(i, i + batchSize);
const ids = batch.map(s => s.id);
for (let i = 0; i < submissionIds.length; i += batchSize) {
const batch = submissionIds.slice(i, i + batchSize);
const { error: deleteError } = await supabase
.from('content_submissions')
.delete()
.in('id', ids);
.in('id', batch);
if (deleteError) throw deleteError;
totalDeleted += ids.length;
}
}
@@ -277,13 +275,28 @@ export async function getTestDataStats(): Promise<{
rides: number;
ride_models: number;
}> {
// Use proper JSON path query for nested metadata
const { data, error } = await supabase
.from('content_submissions')
.select('status')
.eq('content->metadata->>is_test_data', 'true');
// Query submission_metadata to find test submissions
const { data: testMetadata, error: metadataError } = await supabase
.from('submission_metadata')
.select('submission_id')
.eq('metadata_key', 'is_test_data')
.eq('metadata_value', 'true');
if (error) throw error;
if (metadataError) throw metadataError;
const submissionIds = testMetadata?.map(m => m.submission_id) || [];
// Get statuses for test submissions
let data: Array<{ status: string }> = [];
if (submissionIds.length > 0) {
const { data: submissions, error } = await supabase
.from('content_submissions')
.select('status')
.in('id', submissionIds);
if (error) throw error;
data = submissions || [];
}
// Get registry counts for available dependencies
const { data: registryData } = await supabase
@@ -296,9 +309,9 @@ export async function getTestDataStats(): Promise<{
}, {} as Record<string, number>) || {};
const stats = {
total: data?.length || 0,
pending: data?.filter(s => s.status === 'pending').length || 0,
approved: data?.filter(s => s.status === 'approved').length || 0,
total: data.length,
pending: data.filter(s => s.status === 'pending').length,
approved: data.filter(s => s.status === 'approved').length,
operators: registryCounts['operator'] || 0,
property_owners: registryCounts['property_owner'] || 0,
manufacturers: registryCounts['manufacturer'] || 0,