এখন পর্যন্ত আমরা সব ডেটা JSON ফাইলে রেখেছি। এটা শেখার জন্য দারুণ ছিল, কিন্তু বাস্তব অ্যাপ্লিকেশনে JSON ফাইল ম্যানুয়ালি পড়া-লেখা ধীরগতির এবং জটিল। আজ আমরা SQLite ডাটাবেস ব্যবহার করা শিখবো—যেটা বাস্তব জগতের অ্যাপ্লিকেশনের জন্য স্ট্যান্ডার্ড, হালকা, এবং দ্রুত।

JSON vs SQLite — কেন SQLite শিখব?

ব্যাপারJSONSQLite
গতিধীর (পুরো ফাইল পড়তে হয়)দ্রুত (SQL ইঞ্জিন)
সার্চJavaScript দিয়ে ম্যানুয়ালিSQL কোয়েরি — SELECT, WHERE
একসাথে অনেক কাজকঠিন, ডেটা নষ্ট হতে পারেTransaction সাপোর্ট
প্রফেশনালশেখার জন্য ভালোইন্ডাস্ট্রি স্ট্যান্ডার্ড
মোবাইলেঠিক আছেএকেবারে পারফেক্ট

ঐচ্ছিক: npm ও sql.js ইন্সটল

Note: Termux-এর কিছু পুরোনো Node.js ভার্সনে country-code সমস্যার জন্য sql.js ইন্সটল নাও হতে পারে। সেক্ষেত্রে আমরা better-sqlite3 ইউজ করব।

# প্রথমে sql.js ট্রাই করি:
npm install sql.js
# যদি কাজ না করে, তাহলে:
npm install better-sqlite3

ধাপ ১: database.js মডিউল তৈরি করো

cd ~/shop-api
micro database.js

নিচের সম্পূর্ণ কোড পেস্ট করো—এটি ডাটাবেস ইন্সটল, টেবিল তৈরি ও সেভ করার সব কাজ করবে:

const initSqlJs = require('sql.js');
const fs = require('fs');
const path = require('path');
const dbPath = path.join(__dirname, 'shop.db');

async function setupDatabase() {
  const SQL = await initSqlJs();
  let db;
  if (fs.existsSync(dbPath)) {
    db = new SQL.Database(fs.readFileSync(dbPath));
  } else {
    db = new SQL.Database();
  }

  // পণ্যের টেবিল
  db.run(`CREATE TABLE IF NOT EXISTS products (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    price REAL NOT NULL,
    stock INTEGER DEFAULT 0,
    unit TEXT DEFAULT 'পিস'
  )`);

  // ইউজার টেবিল
  db.run(`CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT UNIQUE NOT NULL,
    password TEXT NOT NULL,
    role TEXT DEFAULT 'admin'
  )`);

  // সেলস টেবিল
  db.run(`CREATE TABLE IF NOT EXISTS sales (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    date TEXT NOT NULL,
    total REAL NOT NULL,
    payment_method TEXT DEFAULT 'cash'
  )`);

  // সেলস আইটেম টেবিল
  db.run(`CREATE TABLE IF NOT EXISTS sale_items (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    sale_id INTEGER,
    product_id INTEGER,
    product_name TEXT,
    price REAL,
    qty INTEGER,
    subtotal REAL
  )`);

  // একেবারে প্রথমবারের জন্য ডিফল্ট ইউজার
  const users = db.exec('SELECT COUNT(*) as count FROM users');
  if (users[0].values[0][0] === 0) {
    db.run("INSERT INTO users (username, password, role) VALUES ('admin', 'admin123', 'admin')");
  }

  return db;
}

function saveDatabase(db) {
  const data = db.export();
  const buffer = Buffer.from(data);
  fs.writeFileSync(dbPath, buffer);
}

module.exports = { setupDatabase, saveDatabase };

ধাপ ২: server.js আপডেট করো (SQLite ভার্সন)

cd ~/shop-api
micro server.js

সবার উপরে require গুলোতে এটি যোগ করো:

const { setupDatabase, saveDatabase } = require('./database');
let db;

এখন app.listen-এর জায়গায় এটি দাও:

setupDatabase().then(database => {
  db = database;
  console.log('✅ SQLite ডাটাবেস প্রস্তুত');
  app.listen(PORT, () => {
    console.log(`✅ সার্ভার চালু হয়েছে: http://localhost:${PORT}`);
  });
});

এখন GET ও POST রাউট এভাবে বদলাও:

// GET /products (SQLite)
app.get('/products', (req, res) => {
  const results = db.exec('SELECT * FROM products ORDER BY id');
  if (!results.length) return res.json([]);
  const cols = results[0].columns;
  const rows = results[0].values.map(row => {
    const obj = {};
    cols.forEach((c, i) => { obj[c] = row[i]; });
    return obj;
  });
  res.json(rows);
});

// POST /products (SQLite, প্রটেক্টেড)
app.post('/products', authMiddleware, (req, res) => {
  const { name, price, stock, unit } = req.body;
  if (!name || !price) {
    return res.status(400).json({ message: 'নাম ও মূল্য আবশ্যক' });
  }
  db.run('INSERT INTO products (name, price, stock, unit) VALUES (?, ?, ?, ?)',
    [name, price, stock || 0, unit || 'পিস']);
  saveDatabase(db);
  res.status(201).json({ message: 'প্রোডাক্ট যোগ হয়েছে' });
});

SQL বেসিক কমান্ড — তুমি এখন যা পারবে

কাজSQL কোয়েরিসহজ ভাষায়
সব প্রোডাক্টSELECT * FROM products"সব জিনিস দাও"
নির্দিষ্ট প্রোডাক্টSELECT * FROM products WHERE id = 1"শুধু ১ নম্বরটা দাও"
নতুন যোগINSERT INTO products (name, price) VALUES ('a', 10)"এটা রাখো"
আপডেটUPDATE products SET price = 20 WHERE id = 1"দাম বদলাও"
ডিলিটDELETE FROM products WHERE id = 1"এটা সরাও"
গণনাSELECT COUNT(*) FROM products"কয়টা জিনিস আছে?"

আজ তুমি কী শিখলে

  • SQLite — ফাইল-ভিত্তিক, হালকা ও দ্রুত ডাটাবেস
  • sql.js — জাভাস্ক্রিপ্টে SQLite চালানোর প্যাকেজ
  • db.run() — INSERT, UPDATE, DELETE চালানো
  • db.exec() — SELECT চালানো এবং ডেটা পড়া
  • saveDatabase() — ডাটাবেস ফাইলে স্থায়ীভাবে সেভ
  • SQL বেসিক — SELECT, INSERT, UPDATE, DELETE, WHERE, COUNT
  • টেবিল রিলেশন — sales ও sale_items টেবিলের ধারণা

শেষ পর্ব পর্ব ১৩: রিভিশন ও মাইন্ড ম্যাপ — যেখানে পুরো সিরিজের একটি সংক্ষিপ্ত রিভিশন টেবিল ও মাইন্ড ম্যাপ দিয়ে আমরা শেষ করব। 🎉

So far we've stored all data in JSON files. Today we'll learn SQLite — a real database that's faster, more reliable, and used in real-world applications.

JSON vs SQLite

AspectJSONSQLite
SpeedSlow (reads whole file)Fast (SQL engine)
SearchManual JavaScriptSQL Queries
ProfessionalGood for learningIndustry Standard

Step 1: Install sql.js or better-sqlite3

npm install sql.js
# or if that fails:
npm install better-sqlite3

Step 2: Create database.js module

const initSqlJs = require('sql.js');
// setupDatabase() and saveDatabase() functions

Step 3: Update server.js for SQLite

const { setupDatabase, saveDatabase } = require('./database');
// Use db.run() for INSERT, UPDATE, DELETE
// Use db.exec() for SELECT

Basic SQL Commands

TaskSQL Query
All productsSELECT * FROM products
InsertINSERT INTO products (name, price) VALUES ('a', 10)
UpdateUPDATE products SET price = 20 WHERE id = 1
DeleteDELETE FROM products WHERE id = 1

Final episode Part 13: Revision & Mind Map — where we'll summarize the entire series with a visual revision table and mind map. 🎉