// https://www.sqlitetutorial.net/sqlite-nodejs/ // https://github.com/JoshuaWise/better-sqlite3/blob/HEAD/docs/api.md export default { GetDB, AddColumn, TableInfo, Update, Delete, CreateTable, SelectAll, Select, Insert, CloseDB, } import Sqlite from 'better-sqlite3' import logger from '../utils/logger' import utils from '../utils/utils' const debugLog = process.env.NS_SQL_DEBUG_LOG // { asd: 'asd', basd: 4 } => asd = 'asd', basd = 4 function GetSqlQuerry(conditions, type) { const res = Object.keys(conditions).reduce((acc, key) => { const item = conditions[key] if (typeof item === 'string') { acc.push(`${key} = '${conditions[key]}'`) } else { acc.push(`${key} = ${conditions[key]}`) } return acc }, []) if (type === 'where') { return res.join(' AND ') } else { return res.join(', ') } } // ------------------------------------------------------------------------- function GetDB(path: string): any { utils.CreatePath(path) const res = new Sqlite(path) res.pragma('synchronous = OFF') return res } function DebugLog(msg) { if (debugLog) { logger.DebugLog(msg, 'sql', 0) } } function AddColumn(db: any, table: any, col: any): any { try { const colName = Object.keys(col)[0] const colType = col.type const command = `ALTER TABLE ${table} ADD COLUMN ${colName} ${colType}` const stmt = PrepareStatement(db, command) return stmt.run() } catch (err) { console.error(err) } } function TableInfo(db: any, table: any): any { try { const command = `PRAGMA table_info(${table})` const stmt = PrepareStatement(db, command) const infoRes = stmt.all() const s2 = `SELECT COUNT(*) FROM ${table}` const stmt2 = PrepareStatement(db, s2) const countRes = stmt2.get() return { columns: infoRes, dataCount: countRes[Object.keys(countRes)[0]], } } catch (err) { console.error(err) } } function Update(db: any, table: any, newData: any, conditions: any): any { try { const command = `UPDATE ${table} SET ${GetSqlQuerry( newData, 'set' )} WHERE ${GetSqlQuerry(conditions, 'where')}` const stmt = PrepareStatement(db, command) return stmt.run() } catch (err) { console.error(err) } } function Delete(db: any, table: any, conditions: any): any { try { const command = `DELETE FROM ${table} WHERE ${GetSqlQuerry( conditions, 'where' )}` const stmt = PrepareStatement(db, command) return stmt.run() } catch (err) { console.error(err) } } function CreateTable(db: any, name: any, columns: any, foreignKeys: any): any { // CREATE TABLE users(pw text PRIMARY KEY NOT NULL, id number, lastIP text, notes text, loginCount // number, lastLogin text, lastAccess text // // FOREIGN KEY(songartist, songalbum) REFERENCES album(albumartist, albumname) ) try { const cols = Object.keys(columns) .reduce((acc, key) => { const item = columns[key] const flags = [] const toCheck = { primary: 'PRIMARY KEY', notNull: 'NOT NULL', unique: 'UNIQUE', autoIncrement: 'AUTOINCREMENT', defaultZero: 'DEFAULT 0', } Object.keys(toCheck).forEach((key) => { if (item[key]) { flags.push(toCheck[key]) } }) acc.push(`${key} ${item.type} ${flags.join(' ')}`) return acc }, []) .join(', ') const fKeys = [] if (foreignKeys) { foreignKeys.forEach((foreignKey) => { const { keysFrom, table, keysTo } = foreignKey fKeys.push( `, FOREIGN KEY(${keysFrom.join( ', ' )}) REFERENCES ${table}(${keysTo.join(', ')})` ) }) } // IF NOT EXISTS const command = `CREATE TABLE ${name}(${cols}${fKeys.join(', ')})` const stmt = PrepareStatement(db, command) return stmt.run() } catch (err) { console.error(err) } } function SelectAll(db: any, from: any): any { try { const command = `SELECT * from ${from}` const stmt = PrepareStatement(db, command) return stmt.all() } catch (err) { console.error(err) } } function Select(db: any, from: any, conditions: any): any { try { const command = `SELECT * from ${from} WHERE ${GetSqlQuerry( conditions, 'where' )}` const stmt = PrepareStatement(db, command) return stmt.all() } catch (err) { console.error(err) } } function Insert(db: any, table: any, data: any): any { try { const cols = Object.keys(data) .reduce((acc, key) => { acc.push(`${key}`) return acc }, []) .join(', ') const values = Object.keys(data) .reduce((acc, key) => { const item = data[key] if (typeof item === 'string') { acc.push(`'${item}'`) } else { acc.push(`${item}`) } return acc }, []) .join(', ') const command = `INSERT INTO ${table} (${cols}) VALUES (${values})` const stmt = PrepareStatement(db, command) return stmt.run() } catch (err) { console.error(err) } } function CloseDB(db: any): void { db.close((err) => { if (err) { return console.error(err.message) } DebugLog('Close the database connection.') }) } // ------------------------------------------------------------------------- function PrepareStatement(db, command) { if (!db) { throw new Error( 'DB is undefined in prepare statement! DB action called with undefined db' ) } DebugLog(command) return db.prepare(command) }