import { db } from '#lib/server/db/index.js'; import { blogArticles, metaTables } from '#lib/server/db/schema/index.js'; import { eq } from 'drizzle-orm'; export function slugify(title: string, fallback = 'article'): string { return ( title .toLowerCase() .trim() .replace(/[^a-z0-9]+/g, '-') .replace(/^-+|-+$/g, '') || fallback ); } export async function uniqueSlug(title: string): Promise { const base = slugify(title); let slug = base; let suffix = 2; while ( (await db.select({ id: blogArticles.id }).from(blogArticles).where(eq(blogArticles.slug, slug))) .length > 0 ) { slug = `${base}-${suffix}`; suffix += 1; } return slug; } /** /lists/db is the database browser, so no list may use that slug. */ export const RESERVED_LIST_SLUGS = new Set(['db']); export async function uniqueListSlug(name: string): Promise { const base = slugify(name, 'list'); let slug = RESERVED_LIST_SLUGS.has(base) ? `${base}-2` : base; let suffix = RESERVED_LIST_SLUGS.has(base) ? 3 : 2; while ( (await db.select({ id: metaTables.id }).from(metaTables).where(eq(metaTables.slug, slug))) .length > 0 ) { slug = `${base}-${suffix++}`; } return slug; } export function validSlug(slug: string): boolean { return slug.length <= 120 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug); }