mysql.js
  1  const waitPort = require('wait-port');
  2  const fs = require('fs');
  3  const mysql = require('mysql2');
  4  
  5  const {
  6      MYSQL_HOST: HOST,
  7      MYSQL_HOST_FILE: HOST_FILE,
  8      MYSQL_USER: USER,
  9      MYSQL_USER_FILE: USER_FILE,
 10      MYSQL_PASSWORD: PASSWORD,
 11      MYSQL_PASSWORD_FILE: PASSWORD_FILE,
 12      MYSQL_DB: DB,
 13      MYSQL_DB_FILE: DB_FILE,
 14  } = process.env;
 15  
 16  let pool;
 17  
 18  async function init() {
 19      const host = HOST_FILE ? fs.readFileSync(HOST_FILE) : HOST;
 20      const user = USER_FILE ? fs.readFileSync(USER_FILE) : USER;
 21      const password = PASSWORD_FILE ? fs.readFileSync(PASSWORD_FILE) : PASSWORD;
 22      const database = DB_FILE ? fs.readFileSync(DB_FILE) : DB;
 23  
 24      await waitPort({ 
 25          host, 
 26          port: 3306,
 27          timeout: 10000,
 28          waitForDns: true,
 29      });
 30  
 31      pool = mysql.createPool({
 32          connectionLimit: 5,
 33          host,
 34          user,
 35          password,
 36          database,
 37          charset: 'utf8mb4',
 38      });
 39  
 40      return new Promise((acc, rej) => {
 41          pool.query(
 42              'CREATE TABLE IF NOT EXISTS todo_items (id varchar(36), name varchar(255), completed boolean) DEFAULT CHARSET utf8mb4',
 43              err => {
 44                  if (err) return rej(err);
 45  
 46                  console.log(`Connected to mysql db at host ${HOST}`);
 47                  acc();
 48              },
 49          );
 50      });
 51  }
 52  
 53  async function teardown() {
 54      return new Promise((acc, rej) => {
 55          pool.end(err => {
 56              if (err) rej(err);
 57              else acc();
 58          });
 59      });
 60  }
 61  
 62  async function getItems() {
 63      return new Promise((acc, rej) => {
 64          pool.query('SELECT * FROM todo_items', (err, rows) => {
 65              if (err) return rej(err);
 66              acc(
 67                  rows.map(item =>
 68                      Object.assign({}, item, {
 69                          completed: item.completed === 1,
 70                      }),
 71                  ),
 72              );
 73          });
 74      });
 75  }
 76  
 77  async function getItem(id) {
 78      return new Promise((acc, rej) => {
 79          pool.query('SELECT * FROM todo_items WHERE id=?', [id], (err, rows) => {
 80              if (err) return rej(err);
 81              acc(
 82                  rows.map(item =>
 83                      Object.assign({}, item, {
 84                          completed: item.completed === 1,
 85                      }),
 86                  )[0],
 87              );
 88          });
 89      });
 90  }
 91  
 92  async function storeItem(item) {
 93      return new Promise((acc, rej) => {
 94          pool.query(
 95              'INSERT INTO todo_items (id, name, completed) VALUES (?, ?, ?)',
 96              [item.id, item.name, item.completed ? 1 : 0],
 97              err => {
 98                  if (err) return rej(err);
 99                  acc();
100              },
101          );
102      });
103  }
104  
105  async function updateItem(id, item) {
106      return new Promise((acc, rej) => {
107          pool.query(
108              'UPDATE todo_items SET name=?, completed=? WHERE id=?',
109              [item.name, item.completed ? 1 : 0, id],
110              err => {
111                  if (err) return rej(err);
112                  acc();
113              },
114          );
115      });
116  }
117  
118  async function removeItem(id) {
119      return new Promise((acc, rej) => {
120          pool.query('DELETE FROM todo_items WHERE id = ?', [id], err => {
121              if (err) return rej(err);
122              acc();
123          });
124      });
125  }
126  
127  module.exports = {
128      init,
129      teardown,
130      getItems,
131      getItem,
132      storeItem,
133      updateItem,
134      removeItem,
135  };