| const express = require("express"); |
| const axios = require("axios"); |
| const swaggerUi = require("swagger-ui-express"); |
| const swaggerJsdoc = require("swagger-jsdoc"); |
| require("dotenv").config(); |
|
|
| const app = express(); |
| app.use(express.json()); |
|
|
| |
| const swaggerOptions = { |
| definition: { |
| openapi: "3.0.0", |
| info: { |
| title: "SQLite Express API", |
| version: "1.0.0", |
| description: "Express.js server connected to remote SQLite database", |
| }, |
| servers: [ |
| { |
| url: `http://localhost:${process.env.PORT || 3000}`, |
| description: "Development server", |
| }, |
| ], |
| }, |
| apis: ["./server.js"], |
| }; |
|
|
| const swaggerSpec = swaggerJsdoc(swaggerOptions); |
| app.use("/swagger", swaggerUi.serve, swaggerUi.setup(swaggerSpec)); |
| app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerSpec)); |
|
|
| |
| const SQLITE_SERVER = process.env.DB_URL || "http://localhost:8000"; |
| const DATABASE = process.env.DATABASE || "default"; |
| const PORT = process.env.PORT || 3000; |
|
|
| console.log(`🔗 Connected to SQLite Server: ${SQLITE_SERVER}`); |
| console.log(`📦 Using Database: ${DATABASE}`); |
|
|
| |
| async function querySQLite(sql, method = "POST", endpoint = "/api/v1/query") { |
| try { |
| const payload = { sql, project: DATABASE }; |
| const response = await axios({ |
| method, |
| url: `${SQLITE_SERVER}${endpoint}`, |
| data: payload, |
| headers: { "Content-Type": "application/json" }, |
| }); |
|
|
| return response.data; |
| } catch (err) { |
| console.error("SQLite Query Error:", err.message); |
| throw err; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| app.get("/health", async (req, res) => { |
| try { |
| const response = await axios.get(`${SQLITE_SERVER}/api/v1/heartbeat`); |
| if (response.status === 200) { |
| res.status(200).json({ status: "healthy", database: DATABASE }); |
| } else { |
| res.status(500).json({ status: "unhealthy" }); |
| } |
| } catch (err) { |
| res.status(500).json({ status: "error", message: err.message }); |
| } |
| }); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| app.get("/api/products", async (req, res) => { |
| try { |
| const result = await querySQLite( |
| "SELECT * FROM products", |
| "POST", |
| "/api/v1/query", |
| ); |
| res.status(200).json(result.data || []); |
| } catch (err) { |
| console.error("GET /api/products error:", err.message); |
| res.status(500).json({ error: err.message || "Failed to fetch products" }); |
| } |
| }); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| app.get("/api/products/:id", async (req, res) => { |
| try { |
| const result = await querySQLite( |
| `SELECT * FROM products WHERE id = ${req.params.id}`, |
| "POST", |
| "/api/v1/query", |
| ); |
| if (result.data && result.data.length > 0) { |
| res.status(200).json(result.data[0]); |
| } else { |
| res.status(404).json({ error: "Product not found" }); |
| } |
| } catch (err) { |
| res.status(500).json({ error: "Database query failed" }); |
| } |
| }); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| app.post("/api/products", async (req, res) => { |
| try { |
| const { name, price, stock } = req.body; |
|
|
| if (!name || price === undefined) { |
| return res |
| .status(400) |
| .json({ error: "Missing required fields: name, price" }); |
| } |
|
|
| const sql = `INSERT INTO products (name, price, stock) VALUES ('${name}', ${price}, ${stock || 0})`; |
| const result = await querySQLite(sql, "POST", "/api/v1/execute"); |
|
|
| res.status(201).json({ |
| status: "created", |
| message: "Product created successfully", |
| rows_affected: result.rows_affected, |
| }); |
| } catch (err) { |
| res.status(500).json({ error: "Failed to create product" }); |
| } |
| }); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| app.put("/api/products/:id", async (req, res) => { |
| try { |
| const { name, price, stock } = req.body; |
| const updates = []; |
|
|
| if (name) updates.push(`name = '${name}'`); |
| if (price !== undefined) updates.push(`price = ${price}`); |
| if (stock !== undefined) updates.push(`stock = ${stock}`); |
|
|
| if (updates.length === 0) { |
| return res.status(400).json({ error: "No fields to update" }); |
| } |
|
|
| const sql = `UPDATE products SET ${updates.join(", ")} WHERE id = ${req.params.id}`; |
| const result = await querySQLite(sql, "POST", "/api/v1/execute"); |
|
|
| res.status(200).json({ |
| status: "updated", |
| message: "Product updated successfully", |
| rows_affected: result.rows_affected, |
| }); |
| } catch (err) { |
| res.status(500).json({ error: "Failed to update product" }); |
| } |
| }); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| app.delete("/api/products/:id", async (req, res) => { |
| try { |
| const sql = `DELETE FROM products WHERE id = ${req.params.id}`; |
| const result = await querySQLite(sql, "POST", "/api/v1/execute"); |
|
|
| res.status(200).json({ |
| status: "deleted", |
| message: "Product deleted successfully", |
| rows_affected: result.rows_affected, |
| }); |
| } catch (err) { |
| res.status(500).json({ error: "Failed to delete product" }); |
| } |
| }); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| app.get("/api/orders", async (req, res) => { |
| try { |
| const result = await querySQLite( |
| "SELECT * FROM orders", |
| "POST", |
| "/api/v1/query", |
| ); |
| res.status(200).json(result.data || []); |
| } catch (err) { |
| res.status(500).json({ error: "Failed to fetch orders" }); |
| } |
| }); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| app.post("/api/orders", async (req, res) => { |
| try { |
| const { customer_name, total, status } = req.body; |
|
|
| if (!customer_name) { |
| return res |
| .status(400) |
| .json({ error: "Missing required field: customer_name" }); |
| } |
|
|
| const sql = `INSERT INTO orders (customer_name, total, status) VALUES ('${customer_name}', ${total || 0}, '${status || "pending"}')`; |
| const result = await querySQLite(sql, "POST", "/api/v1/execute"); |
|
|
| res.status(201).json({ |
| status: "created", |
| message: "Order created successfully", |
| rows_affected: result.rows_affected, |
| }); |
| } catch (err) { |
| res.status(500).json({ error: "Failed to create order" }); |
| } |
| }); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| app.get("/api/info", async (req, res) => { |
| try { |
| const response = await axios.get( |
| `${SQLITE_SERVER}/api/v1/schema?project=${DATABASE}`, |
| ); |
| res.status(200).json({ |
| server: SQLITE_SERVER, |
| database: DATABASE, |
| schema: response.data.schema || {}, |
| }); |
| } catch (err) { |
| res.status(500).json({ error: "Failed to fetch database info" }); |
| } |
| }); |
|
|
| app.listen(PORT, () => { |
| console.log(`\n✅ Express Server running on port ${PORT}`); |
| console.log(`📍 API: http://localhost:${PORT}`); |
| console.log(`🔗 SQLite Server: ${SQLITE_SERVER}`); |
| console.log(`📦 Database: ${DATABASE}\n`); |
| }); |
|
|