add blog editor

This commit is contained in:
2026-08-31 16:39:56 +00:00
parent d793400336
commit 4822125787
13 changed files with 447 additions and 60 deletions

View File

@@ -5,7 +5,7 @@ import { sveltekitCookies } from 'better-auth/svelte-kit';
import { getRequestEvent } from '$app/server';
import { db } from '$lib/server/db';
import * as schema from '$lib/server/db/schema';
import type { RequestEvent } from '@sveltejs/kit';
import { error, type RequestEvent } from '@sveltejs/kit';
export const auth = betterAuth({
baseURL: env.ORIGIN ?? 'http://localhost:3000',
@@ -30,9 +30,6 @@ export function isAdmin(event: RequestEvent): boolean {
export function requireAdmin(event: RequestEvent): void {
if (!isAdmin(event)) {
throw new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
error(401, { message: 'Unauthorized' });
}
}

View File

@@ -69,14 +69,21 @@ export const publications = pgTable('publications', {
// Legacy ^
// New
export const blogArticles = pgTable('blog_articles', {
id: serial('id').primaryKey(),
title: varchar('title', { length: 256 }),
slug: varchar('slug', { length: 256 }),
content: varchar('content', { length: 8192 }),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow()
});
export const blogArticleStatus = pgEnum('blog_article_status', ['draft', 'published']);
export const blogArticles = pgTable(
'blog_articles',
{
id: serial('id').primaryKey(),
title: varchar('title', { length: 256 }).notNull(),
slug: varchar('slug', { length: 256 }).notNull(),
content: text('content').default(''),
status: blogArticleStatus('status').notNull().default('draft'),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow()
},
(table) => [unique().on(table.slug)]
);
// CatchEmAll

29
src/lib/server/slugify.ts Normal file
View File

@@ -0,0 +1,29 @@
import { db } from '$lib/server/db';
import { blogArticles } from '$lib/server/db/schema';
import { eq } from 'drizzle-orm';
export function slugify(title: string): string {
return (
title
.toLowerCase()
.trim()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '') || 'article'
);
}
export async function uniqueSlug(title: string): Promise<string> {
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;
}