Files
thrilltrack-explorer/src/lib/versioningHelpers.ts
gpt-engineer-app[bot] badf3507de Implement Phase 2, Part 2
2025-10-06 15:43:50 +00:00

208 lines
5.0 KiB
TypeScript

import { supabase } from '@/integrations/supabase/client';
import { toast } from '@/hooks/use-toast';
export type EntityType = 'park' | 'ride' | 'company' | 'ride_model';
export type ChangeType = 'created' | 'updated' | 'deleted' | 'restored' | 'archived';
/**
* Get the table name for a given entity type
*/
export function getEntityTableName(entityType: EntityType): string {
const tableMap: Record<EntityType, string> = {
park: 'parks',
ride: 'rides',
company: 'companies',
ride_model: 'ride_models',
};
return tableMap[entityType];
}
/**
* Capture the current state of an entity
*/
export async function captureCurrentState(
entityType: EntityType,
entityId: string
): Promise<Record<string, any> | null> {
const tableName = getEntityTableName(entityType);
const { data, error } = await supabase
.from(tableName as any)
.select('*')
.eq('id', entityId)
.single();
if (error) {
console.error('Error capturing entity state:', error);
return null;
}
return data as Record<string, any>;
}
/**
* Create a new entity version with proper error handling
*/
export async function createEntityVersion(params: {
entityType: EntityType;
entityId: string;
versionData: Record<string, any>;
changedBy: string;
changeReason?: string;
submissionId?: string;
changeType?: ChangeType;
}): Promise<string | null> {
const {
entityType,
entityId,
versionData,
changedBy,
changeReason,
submissionId,
changeType = 'updated',
} = params;
try {
const { data, error } = await supabase.rpc('create_entity_version', {
p_entity_type: entityType,
p_entity_id: entityId,
p_version_data: versionData,
p_changed_by: changedBy,
p_change_reason: changeReason || null,
p_submission_id: submissionId || null,
p_change_type: changeType,
});
if (error) {
console.error('Error creating entity version:', error);
toast({
title: 'Version Creation Failed',
description: error.message,
variant: 'destructive',
});
return null;
}
return data;
} catch (err) {
console.error('Unexpected error creating entity version:', err);
toast({
title: 'Version Creation Failed',
description: 'An unexpected error occurred',
variant: 'destructive',
});
return null;
}
}
/**
* Create entity version with audit log entry
*/
export async function createEntityVersionWithAudit(
params: {
entityType: EntityType;
entityId: string;
versionData: Record<string, any>;
changedBy: string;
changeReason?: string;
submissionId?: string;
changeType?: ChangeType;
},
auditDetails?: Record<string, any>
): Promise<string | null> {
const versionId = await createEntityVersion(params);
if (versionId && auditDetails) {
// Log to admin audit log
const { error: auditError } = await supabase.rpc('log_admin_action', {
_admin_user_id: params.changedBy,
_target_user_id: params.changedBy, // Or entity owner if available
_action: `version_${params.changeType || 'updated'}`,
_details: {
version_id: versionId,
entity_type: params.entityType,
entity_id: params.entityId,
submission_id: params.submissionId,
...auditDetails,
},
});
if (auditError) {
console.warn('Failed to create audit log entry:', auditError);
}
}
return versionId;
}
/**
* Rollback an entity to a previous version
*/
export async function rollbackToVersion(
entityType: EntityType,
entityId: string,
targetVersionId: string,
userId: string,
reason: string
): Promise<boolean> {
try {
const { data, error } = await supabase.rpc('rollback_to_version', {
p_entity_type: entityType,
p_entity_id: entityId,
p_target_version_id: targetVersionId,
p_changed_by: userId,
p_reason: reason,
});
if (error) {
console.error('Error rolling back to version:', error);
toast({
title: 'Rollback Failed',
description: error.message,
variant: 'destructive',
});
return false;
}
toast({
title: 'Rollback Successful',
description: 'Entity has been restored to the selected version',
});
return true;
} catch (err) {
console.error('Unexpected error during rollback:', err);
toast({
title: 'Rollback Failed',
description: 'An unexpected error occurred',
variant: 'destructive',
});
return false;
}
}
/**
* Compare two versions and get the diff
*/
export async function compareVersions(
fromVersionId: string,
toVersionId: string
): Promise<Record<string, any> | null> {
try {
const { data, error } = await supabase.rpc('compare_versions', {
p_from_version_id: fromVersionId,
p_to_version_id: toVersionId,
});
if (error) {
console.error('Error comparing versions:', error);
return null;
}
return data as Record<string, any>;
} catch (err) {
console.error('Unexpected error comparing versions:', err);
return null;
}
}