mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 13:51:13 -05:00
88 lines
2.5 KiB
TypeScript
88 lines
2.5 KiB
TypeScript
/**
|
|
* Submission Metadata Service
|
|
* Handles reading/writing submission metadata to relational tables
|
|
* Replaces content_submissions.content JSONB column
|
|
*/
|
|
|
|
import { supabase } from '@/lib/supabaseClient';
|
|
import { handleError, handleNonCriticalError } from './errorHandler';
|
|
|
|
export interface SubmissionMetadataInsert {
|
|
submission_id: string;
|
|
metadata_key: string;
|
|
metadata_value: string;
|
|
value_type?: 'string' | 'number' | 'boolean' | 'date' | 'url' | 'json';
|
|
display_order?: number;
|
|
}
|
|
|
|
/**
|
|
* Write submission metadata to relational table
|
|
*/
|
|
export async function writeSubmissionMetadata(
|
|
submissionId: string,
|
|
metadata: Record<string, unknown>
|
|
): Promise<void> {
|
|
if (!metadata || Object.keys(metadata).length === 0) return;
|
|
|
|
const entries: SubmissionMetadataInsert[] = Object.entries(metadata).map(([key, value], index) => ({
|
|
submission_id: submissionId,
|
|
metadata_key: key,
|
|
metadata_value: typeof value === 'object' ? JSON.stringify(value) : String(value),
|
|
value_type: inferValueType(value),
|
|
display_order: index,
|
|
}));
|
|
|
|
const { error } = await supabase
|
|
.from('submission_metadata')
|
|
.insert(entries);
|
|
|
|
if (error) {
|
|
handleError(error, {
|
|
action: 'Write submission metadata',
|
|
metadata: { submissionId }
|
|
});
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read submission metadata from relational table
|
|
* Returns as key-value object for backward compatibility
|
|
*/
|
|
export async function readSubmissionMetadata(
|
|
submissionId: string
|
|
): Promise<Record<string, string>> {
|
|
const { data, error } = await supabase
|
|
.from('submission_metadata')
|
|
.select('metadata_key, metadata_value')
|
|
.eq('submission_id', submissionId)
|
|
.order('display_order');
|
|
|
|
if (error) {
|
|
handleNonCriticalError(error, {
|
|
action: 'Read submission metadata',
|
|
metadata: { submissionId }
|
|
});
|
|
return {};
|
|
}
|
|
|
|
return data.reduce((acc, row) => {
|
|
acc[row.metadata_key] = row.metadata_value;
|
|
return acc;
|
|
}, {} as Record<string, string>);
|
|
}
|
|
|
|
/**
|
|
* Infer value type for metadata storage
|
|
*/
|
|
function inferValueType(value: unknown): 'string' | 'number' | 'boolean' | 'date' | 'url' | 'json' {
|
|
if (typeof value === 'number') return 'number';
|
|
if (typeof value === 'boolean') return 'boolean';
|
|
if (typeof value === 'object') return 'json';
|
|
if (typeof value === 'string') {
|
|
if (value.startsWith('http://') || value.startsWith('https://')) return 'url';
|
|
if (/^\d{4}-\d{2}-\d{2}/.test(value)) return 'date';
|
|
}
|
|
return 'string';
|
|
}
|