[DocumentComparison] Node Express Server Example

Follow the API request/response shapes shown in server.js. The DB schema is just a starting point — adapt as needed.

server.js

const express    = require('express');
const bodyParser = require('body-parser');
const mysql      = require('mysql2/promise');
const _          = require('lodash');

const app    = express();
const router = express.Router();

// Table name
const TABLE_NAME = '';

// DB connection
const pool = mysql.createPool({
  host:     'localhost',
  user:     '',
  password: '',
  database: ''
});

const controller = {
  // List versions for a document
  getDocumentVersionList: async (req, res) => {
    const docId    = _.get(req, ['body', 'docId']);
    const domainId = _.get(req, ['body', 'domainId']);
    const userId   = _.get(req, ['body', 'userId']);
    try {
      const [results] = await pool.query(`SELECT * FROM ${TABLE_NAME} WHERE doc_id = ?`, [docId]);
      const userName  = getUserName(domainId, userId); // your own resolver
      const formatted = results.map(row => ({
        id:     row.id,
        date:   row.created_at,
        author: userName
      }));
      res.json(formatted);
    } catch (error) {
      res.status(500).json({ message: 'Internal server error', error: error.message });
    }
  },

  // Fetch one version's data
  getDocumentVersionData: async (req, res) => {
    const id = _.get(req, ['body', 'id']);
    try {
      const [rows] = await pool.query(`SELECT json FROM ${TABLE_NAME} WHERE id = ?`, [id]);
      if (rows.length > 0) {
        res.json(rows[0].json);
      } else {
        res.status(400).json({ message: 'Document not found.' });
      }
    } catch (error) {
      res.status(500).json({ message: 'Internal server error', error: error.message });
    }
  },

  // Delete a version
  deleteDocumentVersionData: async (req, res) => {
    const id = _.get(req, ['body', 'id']);
    try {
      const [result] = await pool.query(`DELETE FROM ${TABLE_NAME} WHERE id = ?`, [id]);
      if (result.affectedRows > 0) {
        res.status(200).json({ message: 'Document deleted successfully.' });
      } else {
        res.status(400).json({ message: 'Document not found.' });
      }
    } catch (error) {
      res.status(500).json({ message: 'Internal server error', error: error.message });
    }
  },

  // Save a version
  saveDocumentVersionData: async (req, res) => {
    const docId    = _.get(req, ['body', 'docId']);
    const userId   = _.get(req, ['body', 'userId']);
    const domainId = _.get(req, ['body', 'domainId']);
    const json     = _.get(req, ['body', 'json']);
    try {
      const [result] = await pool.query(
        `INSERT INTO ${TABLE_NAME} (user_id, domain_id, doc_id, json) VALUES (?, ?, ?, ?)`,
        [userId, domainId, docId, json]
      );
      if (result.affectedRows > 0) {
        res.status(200).json({ message: 'Document saved successfully.' });
      } else {
        res.status(400).json({ message: 'No document was inserted.' });
      }
    } catch (error) {
      res.status(500).json({ message: 'Internal server error', error: error.message });
    }
  }
};

// Routes
router.post  ('/getDocumentVersionList',   controller.getDocumentVersionList);
router.post  ('/getDocumentVersionData',   controller.getDocumentVersionData);
router.delete('/getDocumentVersionData',   controller.deleteDocumentVersionData);
router.post  ('/saveDocumentVersionData',  controller.saveDocumentVersionData);

app.use(bodyParser.json());
app.use('/', router);
app.listen(8080);

Example Table

CREATE TABLE TABLE_NAME (
  `id`         bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id`    varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
  `domain_id`  int(11)      NOT NULL DEFAULT 1,
  `doc_id`     bigint(20)   NOT NULL,
  `json`       longtext     COLLATE utf8mb4_unicode_ci NOT NULL,
  `created_at` datetime     NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=671 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;