const sqlite3 = require("sqlite3").verbose(); class SQLite3Repository { constructor(path) { this.db = new sqlite3.Database(path); } /** * @returns {Promise} */ setup() { return new Promise((resolve, reject) => { this.db.run(SQL_TABLE_BIKE, (err) => { if (err != null) { reject(err); } this.db.run(SQL_TABLE_PROGRAM, (err) => { if (err != null) { reject(err); } this.db.run(SQL_TABLE_WORKOUT, (err) => { if (err != null) { reject(err); } this.db.run(SQL_TABLE_MEASUREMENT, (err) => { if (err != null) { reject(err); } resolve(); }); }); }); }); }); } insert(obj, table, params) { return new Promise((resolve, reject) => { const query = `INSERT INTO ${table} (${params.join(", ")}) VALUES (${params.map(p => ':'+p).join(", ")});`; const values = params.map(p => obj[p]); this.db.run(query, values, function(err) { if (err != null) { return reject(err); } resolve(this.lastID); }); }); } update(obj, table, key, keys) { return new Promise((resolve, reject) => { const query = `UPDATE ${table} SET ${keys.map(k => `${k}=:${k}`).join(" AND ")} WHERE ${key}=:${key}`; const values = [ ...keys.map(k => obj[k]), obj[key], ]; this.db.run(query, values, function(err) { if (err != null) { return reject(err); } resolve(); }); }); } delete(obj, table, key) { return new Promise((resolve, reject) => { const query = `DELETE FROM ${table} WHERE ${key}=:${key};` this.db.run(query, [obj[key]], function(err) { if (err != null) { return reject(err); } resolve(this.changes); }); }); } findOne(table, match) { return this.find(table, match).then(res => res[0] || null) } find(table, match) { return new Promise((resolve, reject) => { const keys = Object.keys(match).filter(k => match[k] != null); const params = keys.map(k => match[k]); const query = `SELECT * FROM ${table}${keys.length > 0 ? ` WHERE ${keys.map(k => `${k}=:${k}`).join(" AND ")}` : ""};`; this.db.all(query, params, function(err, rows) { if (err != null) { return reject(err); } resolve(rows); }); }); } findBike(id) { return this.findOne("bike", {id}); } listBikes() { return this.find("bike", {}); } insertBike(bike) { return this.insert(bike, "bike", ["name", "driver", "connect", "maxLevel"]); } updateBike(bike) { return this.update(bike, "bike", "id", ["name"]); } deleteBike(bike) { return this.delete(bike, "bike", "id"); } findProgram(id) { return this.findOne("program", {id}); } listPrograms() { return this.find("program", {}); } insertProgram(program) { return this.insert(program, "program", ["name", "cpm", "warmupMin", "warmupCpm"]); } updateProgram(program) { return this.update(program, "program", "id", ["name"]); } deleteProgram(program) { return this.delete(program, "program", "id"); } findWorkout(id) { return this.findOne("workout", {id}).then(d => ({...d, date: new Date(d.date)})); } listWorkouts({programId, bikeId} = {}) { return this.find("workout", {programId, bikeId}).then(l => l.map(d => ({...d, date: new Date(d.date)}))); } insertWorkout(workout) { return this.insert(workout, "workout", ["bikeId","programId","date"]); } deleteWorkout(workout) { return this.delete(workout, "workout", "id"); } findMeasurement(id) { return this.findOne("measurement", {id}); } listMeasurements(workoutId) { return this.find("measurement", {workoutId}); } insertMeasurement(measurement) { return this.insert(measurement, "measurement", ["workoutId","minutes","seconds","speed","rpm","distance","calories","pulse","watt","level"]); } deleteMeasurement(measurement) { return this.delete(measurement, "measurement", "id"); } deleteMeasurements({workoutId}) { return this.delete({workoutId}, "measurement", "workoutId"); } } const SQL_TABLE_BIKE = ` CREATE TABLE IF NOT EXISTS bike ( id INTEGER PRIMARY KEY, name VARCHAR(255) NOT NULL, driver VARCHAR(255) NOT NULL, connect VARCHAR(255) NOT NULL, maxLevel INT ); `; const SQL_TABLE_PROGRAM = ` CREATE TABLE IF NOT EXISTS program ( id INTEGER PRIMARY KEY, name VARCHAR(255) NOT NULL, cpm INT NOT NULL, warmupMin INT NOT NULL, warmupCpm INT NOT NULL ); `; const SQL_TABLE_WORKOUT = ` CREATE TABLE IF NOT EXISTS workout ( id INTEGER PRIMARY KEY, bikeId INT NOT NULL, programId INT NOT NULL, date DATETIME NOT NULL ); `; const SQL_TABLE_MEASUREMENT = ` CREATE TABLE IF NOT EXISTS measurement ( id INTEGER PRIMARY KEY, workoutId INT NOT NULL, minutes INT, seconds INT, speed REAL, rpm REAL, distance REAL, calories REAL, pulse INT, watt REAL, level INT ); `; module.exports = SQLite3Repository;