refactor(server): update page loaders to use Convex
- commit
- 802df9564c545543e3174cde474a6a6166e1ac0c
- author
- bnema · · 2026-01-18 18:35 UTC
- parent
- c624865
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +15 -69
M src/lib/utils/chat.server.ts +12 -43
| @@ -1,56 +1,25 @@ | |||
| 1 | - | import type { LibSQLDatabase } from 'drizzle-orm/libsql'; | |
| 2 | 1 | import { createLogger } from '$lib/utils/logger.server'; | |
| 3 | - | import schema, { chatRooms } from '$lib/db/schema'; | |
| 4 | - | import { eq } from 'drizzle-orm'; | |
| 5 | - | import { env } from '$env/dynamic/public'; | |
| 2 | + | import { chatRooms } from '$lib/db/convex.server'; | |
| 6 | 3 | ||
| 7 | 4 | const log = createLogger('chat-utils'); | |
| 8 | 5 | ||
| 9 | - | // Default chat room ID from environment variable | |
| 10 | - | export const DEFAULT_CHAT_ROOM_ID = | |
| 11 | - | env.PUBLIC_DEFAULT_CHAT_ROOM_ID || '00000000-0000-0000-0000-000000000001'; | |
| 6 | + | // Default chat room ID - will be fetched/created on startup | |
| 7 | + | let defaultChatRoomId: string | null = null; | |
| 12 | 8 | ||
| 13 | - | // Type guard for LibSQL errors | |
| 14 | - | interface LibSQLError { | |
| 15 | - | code: string; | |
| 16 | - | message: string; | |
| 9 | + | // Function to get the default chat room ID | |
| 10 | + | export function getDefaultChatRoomId(): string | null { | |
| 11 | + | return defaultChatRoomId; | |
| 17 | 12 | } | |
| 18 | 13 | ||
| 19 | - | function isLibSQLError(error: unknown): error is LibSQLError { | |
| 20 | - | return typeof error === 'object' && error !== null && 'code' in error; | |
| 21 | - | } | |
| 22 | - | ||
| 23 | - | // Function to ensure default chat room exists | |
| 24 | - | export async function ensureDefaultChatRoom(db: LibSQLDatabase<typeof schema>) { | |
| 14 | + | // Function to ensure default chat room exists (using Convex) | |
| 15 | + | export async function ensureDefaultChatRoom(): Promise<string> { | |
| 25 | 16 | log.debug('Ensuring default chat room exists...'); | |
| 26 | 17 | try { | |
| 27 | - | // Use a transaction to handle concurrent creation attempts | |
| 28 | - | await db.transaction(async (tx) => { | |
| 29 | - | const defaultRoom = await tx | |
| 30 | - | .select() | |
| 31 | - | .from(chatRooms) | |
| 32 | - | .where(eq(chatRooms.id, DEFAULT_CHAT_ROOM_ID)) | |
| 33 | - | .get(); | |
| 34 | - | ||
| 35 | - | if (!defaultRoom) { | |
| 36 | - | log.debug('Creating default chat room...'); | |
| 37 | - | await tx.insert(chatRooms).values({ | |
| 38 | - | id: DEFAULT_CHAT_ROOM_ID, | |
| 39 | - | name: 'General', | |
| 40 | - | type: 'group', | |
| 41 | - | createdAt: Date.now() | |
| 42 | - | }); | |
| 43 | - | log.debug('Default chat room created successfully'); | |
| 44 | - | } else { | |
| 45 | - | log.debug('Default chat room already exists'); | |
| 46 | - | } | |
| 47 | - | }); | |
| 18 | + | const room = await chatRooms.getOrCreateDefault(); | |
| 19 | + | defaultChatRoomId = room._id; | |
| 20 | + | log.debug('Default chat room ready', { id: defaultChatRoomId }); | |
| 21 | + | return defaultChatRoomId; | |
| 48 | 22 | } catch (error: unknown) { | |
| 49 | - | // If the error is a unique constraint violation, another process probably created the room | |
| 50 | - | if (isLibSQLError(error) && error.code === 'SQLITE_CONSTRAINT') { | |
| 51 | - | log.debug('Default chat room was created by another process'); | |
| 52 | - | return; | |
| 53 | - | } | |
| 54 | 23 | log.error('Error ensuring default chat room:', { | |
| 55 | 24 | error: error instanceof Error ? error.message : 'Unknown error' | |
| 56 | 25 | }); | |
| @@ -1,56 +1,25 @@ | |||||
| 1 | - | import type { LibSQLDatabase } from 'drizzle-orm/libsql'; | |||
| 2 | import { createLogger } from '$lib/utils/logger.server'; | 1 | import { createLogger } from '$lib/utils/logger.server'; | ||
| 3 | - | import schema, { chatRooms } from '$lib/db/schema'; | 2 | + | import { chatRooms } from '$lib/db/convex.server'; |
| 4 | - | import { eq } from 'drizzle-orm'; | |||
| 5 | - | import { env } from '$env/dynamic/public'; | |||
| 6 | 3 | ||||
| 7 | const log = createLogger('chat-utils'); | 4 | const log = createLogger('chat-utils'); | ||
| 8 | 5 | ||||
| 9 | - | // Default chat room ID from environment variable | 6 | + | // Default chat room ID - will be fetched/created on startup |
| 10 | - | export const DEFAULT_CHAT_ROOM_ID = | 7 | + | let defaultChatRoomId: string | null = null; |
| 11 | - | env.PUBLIC_DEFAULT_CHAT_ROOM_ID || '00000000-0000-0000-0000-000000000001'; | |||
| 12 | 8 | ||||
| 13 | - | // Type guard for LibSQL errors | 9 | + | // Function to get the default chat room ID |
| 14 | - | interface LibSQLError { | 10 | + | export function getDefaultChatRoomId(): string | null { |
| 15 | - | code: string; | 11 | + | return defaultChatRoomId; |
| 16 | - | message: string; | |||
| 17 | } | 12 | } | ||
| 18 | 13 | ||||
| 19 | - | function isLibSQLError(error: unknown): error is LibSQLError { | 14 | + | // Function to ensure default chat room exists (using Convex) |
| 20 | - | return typeof error === 'object' && error !== null && 'code' in error; | 15 | + | export async function ensureDefaultChatRoom(): Promise<string> { |
| 21 | - | } | |||
| 22 | - | ||||
| 23 | - | // Function to ensure default chat room exists | |||
| 24 | - | export async function ensureDefaultChatRoom(db: LibSQLDatabase<typeof schema>) { | |||
| 25 | log.debug('Ensuring default chat room exists...'); | 16 | log.debug('Ensuring default chat room exists...'); | ||
| 26 | try { | 17 | try { | ||
| 27 | - | // Use a transaction to handle concurrent creation attempts | 18 | + | const room = await chatRooms.getOrCreateDefault(); |
| 28 | - | await db.transaction(async (tx) => { | 19 | + | defaultChatRoomId = room._id; |
| 29 | - | const defaultRoom = await tx | 20 | + | log.debug('Default chat room ready', { id: defaultChatRoomId }); |
| 30 | - | .select() | 21 | + | return defaultChatRoomId; |
| 31 | - | .from(chatRooms) | |||
| 32 | - | .where(eq(chatRooms.id, DEFAULT_CHAT_ROOM_ID)) | |||
| 33 | - | .get(); | |||
| 34 | - | ||||
| 35 | - | if (!defaultRoom) { | |||
| 36 | - | log.debug('Creating default chat room...'); | |||
| 37 | - | await tx.insert(chatRooms).values({ | |||
| 38 | - | id: DEFAULT_CHAT_ROOM_ID, | |||
| 39 | - | name: 'General', | |||
| 40 | - | type: 'group', | |||
| 41 | - | createdAt: Date.now() | |||
| 42 | - | }); | |||
| 43 | - | log.debug('Default chat room created successfully'); | |||
| 44 | - | } else { | |||
| 45 | - | log.debug('Default chat room already exists'); | |||
| 46 | - | } | |||
| 47 | - | }); | |||
| 48 | } catch (error: unknown) { | 22 | } catch (error: unknown) { | ||
| 49 | - | // If the error is a unique constraint violation, another process probably created the room | |||
| 50 | - | if (isLibSQLError(error) && error.code === 'SQLITE_CONSTRAINT') { | |||
| 51 | - | log.debug('Default chat room was created by another process'); | |||
| 52 | - | return; | |||
| 53 | - | } | |||
| 54 | log.error('Error ensuring default chat room:', { | 23 | log.error('Error ensuring default chat room:', { | ||
| 55 | error: error instanceof Error ? error.message : 'Unknown error' | 24 | error: error instanceof Error ? error.message : 'Unknown error' | ||
| 56 | }); | 25 | }); | ||
M src/routes/+page.server.ts +3 -26
| @@ -1,8 +1,5 @@ | |||
| 1 | 1 | import type { PageServerLoad } from './$types'; | |
| 2 | 2 | import { validateSessionToken } from '$lib/api/session.server'; | |
| 3 | - | import db from '$lib/db/db.server'; | |
| 4 | - | import { messages } from '$lib/db/schema'; | |
| 5 | - | import { eq, desc } from 'drizzle-orm'; | |
| 6 | 3 | import { DEFAULT_TEXT_STYLE, type TextStyle } from '$lib/types/text-formatting'; | |
| 7 | 4 | ||
| 8 | 5 | export const load: PageServerLoad = async ({ cookies }) => { | |
| @@ -25,29 +22,9 @@ export const load: PageServerLoad = async ({ cookies }) => { | |||
| 25 | 22 | }; | |
| 26 | 23 | } | |
| 27 | 24 | ||
| 28 | - | // Get user's last used text styling from their most recent message | |
| 29 | - | const lastMessage = await db.query.messages.findFirst({ | |
| 30 | - | where: eq(messages.senderId, user.id), | |
| 31 | - | orderBy: [desc(messages.timestamp)], | |
| 32 | - | columns: { | |
| 33 | - | styleData: true | |
| 34 | - | } | |
| 35 | - | }); | |
| 36 | - | ||
| 37 | - | let lastTextStyle: TextStyle = DEFAULT_TEXT_STYLE; | |
| 38 | - | ||
| 39 | - | if (lastMessage?.styleData) { | |
| 40 | - | try { | |
| 41 | - | const parsedStyle = JSON.parse(lastMessage.styleData); | |
| 42 | - | // Merge with default style to ensure all required properties | |
| 43 | - | lastTextStyle = { | |
| 44 | - | ...DEFAULT_TEXT_STYLE, | |
| 45 | - | ...parsedStyle | |
| 46 | - | }; | |
| 47 | - | } catch (error) { | |
| 48 | - | console.warn('Failed to parse last text style:', error); | |
| 49 | - | } | |
| 50 | - | } | |
| 25 | + | // For now, return default text style | |
| 26 | + | // TODO: Fetch user's last text style from Convex if needed | |
| 27 | + | const lastTextStyle: TextStyle = DEFAULT_TEXT_STYLE; | |
| 51 | 28 | ||
| 52 | 29 | return { | |
| 53 | 30 | user, | |
| @@ -1,8 +1,5 @@ | |||||
| 1 | import type { PageServerLoad } from './$types'; | 1 | import type { PageServerLoad } from './$types'; | ||
| 2 | import { validateSessionToken } from '$lib/api/session.server'; | 2 | import { validateSessionToken } from '$lib/api/session.server'; | ||
| 3 | - | import db from '$lib/db/db.server'; | |||
| 4 | - | import { messages } from '$lib/db/schema'; | |||
| 5 | - | import { eq, desc } from 'drizzle-orm'; | |||
| 6 | import { DEFAULT_TEXT_STYLE, type TextStyle } from '$lib/types/text-formatting'; | 3 | import { DEFAULT_TEXT_STYLE, type TextStyle } from '$lib/types/text-formatting'; | ||
| 7 | 4 | ||||
| 8 | export const load: PageServerLoad = async ({ cookies }) => { | 5 | export const load: PageServerLoad = async ({ cookies }) => { | ||
| @@ -25,29 +22,9 @@ export const load: PageServerLoad = async ({ cookies }) => { | |||||
| 25 | }; | 22 | }; | ||
| 26 | } | 23 | } | ||
| 27 | 24 | ||||
| 28 | - | // Get user's last used text styling from their most recent message | 25 | + | // For now, return default text style |
| 29 | - | const lastMessage = await db.query.messages.findFirst({ | 26 | + | // TODO: Fetch user's last text style from Convex if needed |
| 30 | - | where: eq(messages.senderId, user.id), | 27 | + | const lastTextStyle: TextStyle = DEFAULT_TEXT_STYLE; |
| 31 | - | orderBy: [desc(messages.timestamp)], | |||
| 32 | - | columns: { | |||
| 33 | - | styleData: true | |||
| 34 | - | } | |||
| 35 | - | }); | |||
| 36 | - | ||||
| 37 | - | let lastTextStyle: TextStyle = DEFAULT_TEXT_STYLE; | |||
| 38 | - | ||||
| 39 | - | if (lastMessage?.styleData) { | |||
| 40 | - | try { | |||
| 41 | - | const parsedStyle = JSON.parse(lastMessage.styleData); | |||
| 42 | - | // Merge with default style to ensure all required properties | |||
| 43 | - | lastTextStyle = { | |||
| 44 | - | ...DEFAULT_TEXT_STYLE, | |||
| 45 | - | ...parsedStyle | |||
| 46 | - | }; | |||
| 47 | - | } catch (error) { | |||
| 48 | - | console.warn('Failed to parse last text style:', error); | |||
| 49 | - | } | |||
| 50 | - | } | |||
| 51 | 28 | ||||
| 52 | return { | 29 | return { | ||
| 53 | user, | 30 | user, | ||