Created
December 10, 2025 18:24
-
-
Save TCotton/2100117e0d34a817ef286b2c82ea78ef to your computer and use it in GitHub Desktop.
persistance-layer-files.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { promises as fs } from 'fs' | |
| import { join } from 'path' | |
| import type { UIMessage } from 'ai' | |
| export namespace DB { | |
| // Types for our persistence layer | |
| export interface Chat { | |
| id: string | |
| messages: UIMessage[] | |
| createdAt: string | |
| updatedAt: string | |
| } | |
| export interface PersistenceData { | |
| chats: DB.Chat[] | |
| } | |
| } | |
| // File path for storing the data | |
| const DATA_FILE_PATH = join(process.cwd(), 'data', 'chats.local.json') | |
| /** | |
| * Ensure the data directory exists | |
| */ | |
| async function ensureDataDirectory(): Promise<void> { | |
| const dataDir = join(process.cwd(), 'data') | |
| try { | |
| await fs.access(dataDir) | |
| } catch { | |
| await fs.mkdir(dataDir, { recursive: true }) | |
| } | |
| } | |
| /** | |
| * Load all chats from the JSON file | |
| */ | |
| export async function loadChats(): Promise<DB.Chat[]> { | |
| try { | |
| await ensureDataDirectory() | |
| const data = await fs.readFile(DATA_FILE_PATH, 'utf-8') | |
| const parsed: DB.PersistenceData = JSON.parse(data) | |
| return parsed.chats || [] | |
| } catch (error) { | |
| // If file doesn't exist or is invalid, return empty array | |
| return [] | |
| } | |
| } | |
| /** | |
| * Save all chats to the JSON file | |
| */ | |
| export async function saveChats(chats: DB.Chat[]): Promise<void> { | |
| await ensureDataDirectory() | |
| const data: DB.PersistenceData = { chats } | |
| await fs.writeFile(DATA_FILE_PATH, JSON.stringify(data, null, 2), 'utf-8') | |
| } | |
| /** | |
| * Create a new chat | |
| */ | |
| export async function createChat(id: string, initialMessages: UIMessage[] = []): Promise<DB.Chat> { | |
| const chats = await loadChats() | |
| const now = new Date().toISOString() | |
| const newChat: DB.Chat = { | |
| id, | |
| messages: initialMessages, | |
| createdAt: now, | |
| updatedAt: now, | |
| } | |
| chats.push(newChat) | |
| await saveChats(chats) | |
| return newChat | |
| } | |
| /** | |
| * Get a chat by ID | |
| */ | |
| export async function getChat(chatId: string): Promise<DB.Chat | null> { | |
| const chats = await loadChats() | |
| return chats.find((chat) => chat.id === chatId) || null | |
| } | |
| /** | |
| * Update a chat's messages | |
| */ | |
| export async function appendToChatMessages( | |
| chatId: string, | |
| messages: UIMessage[] | |
| ): Promise<DB.Chat | null> { | |
| const chats = await loadChats() | |
| const chatIndex = chats.findIndex((chat) => chat.id === chatId) | |
| if (chatIndex === -1) { | |
| return null | |
| } | |
| chats[chatIndex]!.messages = [...chats[chatIndex]!.messages, ...messages] | |
| chats[chatIndex]!.updatedAt = new Date().toISOString() | |
| await saveChats(chats) | |
| return chats[chatIndex]! | |
| } | |
| /** | |
| * Delete a chat | |
| */ | |
| export async function deleteChat(chatId: string): Promise<boolean> { | |
| const chats = await loadChats() | |
| const initialLength = chats.length | |
| const filteredChats = chats.filter((chat) => chat.id !== chatId) | |
| if (filteredChats.length === initialLength) { | |
| return false // Chat not found | |
| } | |
| await saveChats(filteredChats) | |
| return true | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment