diff --git a/server/db.js b/server/db.js index cb43384..34d408a 100644 --- a/server/db.js +++ b/server/db.js @@ -1,9 +1,38 @@ const initSqlJs = require('sql.js'); const fs = require('fs'); +const { resourceUsage } = require('process'); let db = null; const DB_PATH = './ka.db'; +// Helper functions + +function getNextKANumber() { + const result = db.exec('SELECT ka_number FROM articles ORDER BY id DESC LIMIT 1') + + if (result.length > 0 && result[0].values.length > 0) { + const lastKANumber = result[0].values[0][0]; + const number = parseInt(lastKANumber.replace('KA', '')) + 1; + return `KA${String(number).padStart(3, '0')}`; + } + + return 'KA001'; +} + +function getArtcileById(id) { + const stmt = db.prepare("SELECT * FROM articles WHERE id = ?"); + stmt.bind([id]); + + if (stmt.step()) { + const article = stmt.getAsObject(); + stmt.free(); + return article; + } + + stmt.free(); + return null; +} + async function initDb() { const SQL = await initSqlJs(); @@ -27,10 +56,13 @@ async function initDb() { ka_number TEXT UNIQUE, title TEXT, content TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME ) `); + db.run("CREATE INDEX idx_ka_number ON articles(ka_number)"); + // Saving the created db to file const data = db.export(); fs.writeFileSync(DB_PATH, Buffer.from(data)); @@ -40,4 +72,105 @@ async function initDb() { return db; } -module.exports = {initDb}; \ No newline at end of file +// Get all articles from the DB +function getAllArticles() { + const result = db.exec("SELECT * FROM articles ORDER BY created_at DESC"); + + if (result.length === 0) { + return []; + } + + const columns = result[0].columns; + const rows = result[0].values; + + const articles = rows.map(row => { + const article = {}; + + columns.forEach((col, index) => { + article[col] = row[index]; + }); + + return article; + }) + + return articles; +} + +// Get a specific article from the DB +function getArticle(ka_num) { + const stmt = db.prepare('SELECT * FROM articles where ka_number = ?'); + stmt.bind([ka_num]); + + if (stmt.step()) { + const article = stmt.getAsObject(); + stmt.free(); + return article; + } + + stmt.free(); + return null; +} + +// Create a new article +function createArticle(title, content) { + const ka_num = getNextKANumber(); + + db.run( + "INSERT INTO artciles (ka_number, title, content) VALUES (?, ?, ?)", + [ka_num, title, content] + ); + + // Saving updated DB to file + const data = db.export(); + fs.writeFileSync(DB_PATH, Buffer.from(data)); + + // Getting id and returning the newly created artcle + const result = db.exec("SELECT last_insert_rowId()"); + const id = result[0].values[0][0]; + return getArtcileById(id); +} + +function updateArticle(ka_num, title, content) { + db.run( + "UPDATE articles SET title = ?, content = ?, updated_at = CURRENT_TIMESTAMP WHERE ka_number = ?", + [title, content, ka_num] + ); + + // Saving updated DB to file + const data = db.export(); + fs.writeFileSync(DB_PATH, Buffer.from(data)); + + return getArticle(ka_num); +} + +// Delete the article from the DB +function deleteArticle(ka_num) { + db.run( + "DELETE FROM articles WHERE ka_number = ?", + [ka_num] + ); + + // Saving updated DB to file + const data = db.export(); + fs.writeFileSync(DB_PATH, Buffer.from(data)); +} + +// Simple search to look for matching terms or KA number +function searchArticles(query) { + const searchTerm = `%${query}%`; + const stmt = db.prepare( + "SELECT * FROM articles WHERE title LIKE ? OR content LIKE ? or ka_number LIKE ? ORDER BY created_at DESC" + ); + stmt.bind([searchTerm, searchTerm, searchTerm]); + stmt.free(); + + const results = []; + while (stmt.step()) { + results.push(stmt.getAsObject()); + } + stmt.free(); + + return results; +} + +module.exports = { initDb, getAllArticles, getArticle, createArticle, updateArticle, deleteArticle, searchArticles }; \ No newline at end of file diff --git a/server/server.js b/server/server.js index dc524aa..e40f34c 100644 --- a/server/server.js +++ b/server/server.js @@ -1,5 +1,5 @@ const express = require('express'); -const { initDb } = require('./db'); +const { initDb, getAllArticles, getArticle, createArticle, updateArticle, deleteArticle, searchArticles } = require('./db'); const app = express(); const PORT = 9000; @@ -11,6 +11,96 @@ initDb().then(() => { res.json({message : 'Server is running'}); }); + app.get('/api/articles', (req, res) => { + try { + const articles = getAllArticles(); + res.json(articles); + } catch (error) { + console.error('Error fetching articles:', error); + res.status(500).json({error: 'Failed to fetch articles', 'details': String(error)}); + } + }); + + app.get('/api/articles/:ka_number', (req, res) => { + try { + const article = getArticle(req.params.ka_number); + + if (!article) { + return res.status(404).json({ error: 'Article not found' }); + } + + res.json(article); + } catch (error) { + console.error('Error fetching article:', error); + res.status(500).json({error: 'Failed to fetch article', 'details': String(error)}); + } + }); + + app.post('/api/articles', (req, res) => { + try { + const { title, content } = req.body; + + if (!title) { + return res.status(400).json({error: 'Title is required' }); + } + + const article = createArticle(title, content || ''); + res.status(201).json(article); + + } catch (error) { + console.error('Error creating article:', error); + res.status(500).json({error: 'Failed to create article', 'details': String(error)}); + } + }); + + app.put('/api/articles/:ka_number', (req, res) => { + try { + const { title, content } = req.body; + + if (!title) { + return res.status(400).json({error: 'Title is required' }); + } + + const article = updateArticle(req.params.ka_number, title, content); + + if (!article) { + return res.status(404).json({error: 'Article not found'}); + } + + res.json(article); + } catch (error) { + console.error('Error updating article:', error); + return res.status(500).json({error: 'Error while updating article', 'details': String(error)}); + } + }); + + app.delete('/api/articles/:ka_number', (req, res) => { + try { + deleteArticle(req.params.ka_number); + return res.status(200).json({'message': 'Successfully deleted article'}); + + } catch (error) { + console.error('Error when deleting article:', error); + return res.status(500).json({error: 'Failed to delete article', 'details': String(error)}); + } + }); + + app.get('/api/search', (req, res) => { + try { + const query = req.query.q; + + if (!query) { + return res.status(400).json({error: 'Search query is required'}); + } + + const results = searchArticles(query); + res.json(results); + } catch (error) { + console.error('Error when searching articles:', error); + return res.status(500).json({error: 'Failed to search articles', 'details': String(error)}); + } + }); + app.listen(PORT, () => { console.log(`Server running on http://localhost:${PORT}`); });