Files
thrilltrack-explorer/src-old/lib/slugUtils.ts

83 lines
2.1 KiB
TypeScript

import { supabase } from '@/lib/supabaseClient';
import { handleError } from './errorHandler';
/**
* Generate a URL-safe slug from a name
* This is the canonical slug generation function used throughout the app
*/
export function generateSlugFromName(name: string): string {
if (!name) return '';
return name
.toLowerCase()
.replace(/[^a-z0-9\s-]/g, '') // Remove non-alphanumeric except spaces and hyphens
.replace(/\s+/g, '-') // Replace spaces with hyphens
.replace(/-+/g, '-') // Replace multiple hyphens with single hyphen
.replace(/^-+|-+$/g, '') // Remove leading/trailing hyphens
.trim();
}
/**
* Validate that a user has permission to edit slugs
* Only moderators should be able to manually edit slugs
*/
export function canEditSlug(isModerator: boolean): boolean {
return isModerator;
}
/**
* Ensure slug is unique by checking database and appending number if needed
*/
export async function ensureUniqueSlug(
baseSlug: string,
tableName: 'parks' | 'rides' | 'companies' | 'ride_models',
excludeId?: string
): Promise<string> {
let slug = baseSlug;
let counter = 1;
while (true) {
// Check if slug exists
let query = supabase
.from(tableName)
.select('id')
.eq('slug', slug);
// Exclude current record when editing
if (excludeId) {
query = query.neq('id', excludeId);
}
const { data, error } = await query.limit(1);
if (error) {
handleError(error, {
action: 'Check Slug Uniqueness',
metadata: { tableName, slug }
});
throw error;
}
// If no match found, slug is unique
if (!data || data.length === 0) {
return slug;
}
// Append counter and try again
counter++;
slug = `${baseSlug}-${counter}`;
}
}
/**
* Generate and ensure unique slug in one operation
*/
export async function generateUniqueSlug(
name: string,
tableName: 'parks' | 'rides' | 'companies' | 'ride_models',
excludeId?: string
): Promise<string> {
const baseSlug = generateSlugFromName(name);
return ensureUniqueSlug(baseSlug, tableName, excludeId);
}