Skip to main content
Glama
by Disturbing
repository.ts3.87 kB
export enum TodoStatus { TODO = 'TODO', IN_PROGRESS = 'IN_PROGRESS', COMPLETED = 'COMPLETED' } export interface Todo { id: string; title: string; description: string; status: TodoStatus; created_at: string; updated_at: string; } export class TodoRepository { private state: DurableObjectState; constructor(state: DurableObjectState) { this.state = state; } async initializeDatabase(): Promise<void> { // Create todos table with SQL using tagged template literals await this.state.storage.sql.exec(` CREATE TABLE IF NOT EXISTS todos ( id TEXT PRIMARY KEY, title TEXT NOT NULL, description TEXT NOT NULL, status TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL ) `); } async createTodo(todo: Omit<Todo, 'id' | 'created_at' | 'updated_at'>): Promise<Todo> { const id = crypto.randomUUID(); const now = new Date().toISOString(); const newTodo: Todo = { id, ...todo, created_at: now, updated_at: now }; this.state.storage.sql.exec(` INSERT INTO todos (id, title, description, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?) `,newTodo.id, newTodo.title, newTodo.description, newTodo.status, newTodo.created_at, newTodo.updated_at); return newTodo; } async getTodoById(id: string): Promise<Todo | null> { console.log('Getting todo by id:', id); // Query using SQL with parameterized query const cursor = await this.state.storage.sql.exec(` SELECT * FROM todos WHERE id = ? `, [id]); // Use the cursor as an iterator const result = cursor.next(); if (result.done) { return null; } // Use unknown as an intermediate type for safe type assertion return result.value as unknown as Todo; } async getAllTodos(): Promise<Todo[]> { console.log('Getting all todos'); // Query using SQL - no parameters needed for this query const cursor = await this.state.storage.sql.exec(` SELECT * FROM todos ORDER BY created_at DESC `); // Use the cursor as an iterable to collect all rows const todos: Todo[] = []; for (const row of cursor) { todos.push(row as unknown as Todo); } return todos; } async updateTodo(id: string, updates: Partial<Omit<Todo, 'id' | 'created_at'>>): Promise<Todo | null> { // First check if todo exists const todo = await this.getTodoById(id); if (!todo) { return null; } const now = new Date().toISOString(); const updatedTodo = { ...todo, ...updates, updated_at: now }; // Build the SQL query dynamically based on what fields are being updated let query = 'UPDATE todos SET updated_at = ?'; const params = [now]; // Only include fields that are actually being updated if (updates.title !== undefined) { query += ', title = ?'; params.push(updatedTodo.title); } if (updates.description !== undefined) { query += ', description = ?'; params.push(updatedTodo.description); } if (updates.status !== undefined) { query += ', status = ?'; params.push(updatedTodo.status); } // Add the WHERE clause and the ID parameter query += ' WHERE id = ?'; params.push(id); // Execute the query with the correct number of parameters await this.state.storage.sql.exec(query, params); return updatedTodo; } async deleteTodo(id: string): Promise<boolean> { console.log('Deleting todo:', id); const todo = await this.getTodoById(id); if (!todo) { return false; } // Delete todo using parameterized query await this.state.storage.sql.exec(` DELETE FROM todos WHERE id = ? `, [id]); return true; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Disturbing/mcp-live-code'

If you have feedback or need assistance with the MCP directory API, please join our Discord server