-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from jdf18/switching-to-json
Switching to json instead of sqlite for storing data
- Loading branch information
Showing
7 changed files
with
363 additions
and
336 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -134,3 +134,6 @@ dist | |
|
||
# Runtime data | ||
data/ | ||
|
||
# Testing | ||
test-data/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"watch": ["src"], | ||
"ext": "js", | ||
"ignore": ["data", "test-data", "coverage", "node_modules", "static", "test"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,162 +1,103 @@ | ||
const fs = require('fs'); | ||
|
||
const sqlite3 = require('sqlite3').verbose(); | ||
function returnUserFromRow(user) { | ||
return { | ||
user_id: user.user_id, | ||
username: user.username, | ||
display_name: user.display_name, | ||
bio: user.bio, | ||
pfp_link: user.pfp_link, | ||
password_hash: user.password_hash, | ||
}; | ||
} | ||
|
||
let db; | ||
class Datastore { | ||
constructor(path) { | ||
if (!fs.existsSync(path)) { | ||
throw new Error(`Database directory "${path}" does not exist.`); | ||
} | ||
this.path = path; | ||
|
||
// Try to connect to the database file | ||
function connect(databasePath) { | ||
// Check that the file exists | ||
if (!(fs.existsSync(databasePath) || databasePath === ':memory:')) { | ||
return new Promise((resolve, reject) => { | ||
reject(new Error(`Database file "${databasePath}" does not exist.`)); | ||
}); | ||
this.users = null; | ||
this.recipes = null; | ||
this.comments = null; | ||
|
||
this.initialised = false; | ||
|
||
this.init_datastore(); | ||
} | ||
|
||
return new Promise((resolve, reject) => { | ||
// Connect to the database | ||
db = new sqlite3.Database(databasePath, sqlite3.OPEN_READWRITE, (err) => { | ||
if (err) { | ||
console.log('Error connecting to database:', err.message); | ||
return reject(new Error(`Error connecting to database: ${err.message}`)); | ||
} | ||
console.log(`Connected to the ForkedFlavors database. ${databasePath}`); | ||
return resolve(); | ||
}); | ||
|
||
// Create tables if they don’t exist | ||
db.serialize(() => { | ||
// Users Table | ||
db.run(` | ||
CREATE TABLE IF NOT EXISTS users ( | ||
user_id INTEGER PRIMARY KEY AUTOINCREMENT, | ||
username TEXT UNIQUE NOT NULL, | ||
display_name TEXT UNIQUE NOT NULL, | ||
bio TEXT, | ||
pfp_link TEXT, | ||
password_hash TEXT NOT NULL | ||
); | ||
`); | ||
|
||
// Recipes Table with JSON column | ||
db.run(` | ||
CREATE TABLE IF NOT EXISTS recipes ( | ||
recipe_id INTEGER PRIMARY KEY AUTOINCREMENT, | ||
user_id INTEGER NOT NULL, | ||
title TEXT NOT NULL, | ||
recipe_data TEXT NOT NULL, -- JSON stored as TEXT | ||
forked_from INTEGER DEFAULT NULL, | ||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP, | ||
FOREIGN KEY (user_id) REFERENCES users(user_id), | ||
FOREIGN KEY (forked_from) REFERENCES recipes(forked_from) | ||
); | ||
`); | ||
|
||
// Comments Table | ||
db.run(` | ||
CREATE TABLE IF NOT EXISTS comments ( | ||
comment_id INTEGER PRIMARY KEY AUTOINCREMENT, | ||
recipe_id INTEGER NOT NULL, | ||
user_id INTEGER NOT NULL, | ||
comment_text TEXT NOT NULL, | ||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP, | ||
FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id), | ||
FOREIGN KEY (user_id) REFERENCES users(user_id) | ||
); | ||
`); | ||
resolve(); | ||
}); | ||
}); | ||
} | ||
load() { | ||
const usersJson = fs.readFileSync( | ||
`${this.path}users.json`, | ||
); | ||
this.users = JSON.parse(usersJson.toString('utf8')); | ||
} | ||
|
||
function getDb() { | ||
if (!db) { | ||
throw new Error('Database not yet initialized. Call `connect() first.`'); | ||
init_datastore() { | ||
// Check required files all exist, load into object | ||
if (!fs.existsSync(`${this.path}users.json`)) { | ||
console.log('Datastore users.json does not exist: Creating'); | ||
fs.writeFileSync(`${this.path}users.json`, JSON.stringify([])); | ||
} | ||
this.load(); | ||
this.initialised = true; | ||
} | ||
return db; | ||
} | ||
|
||
function close() { | ||
if (!db) { | ||
throw new Error('Database not yet initialized. Call `connect() first.`'); | ||
save() { | ||
const usersJson = JSON.stringify(this.users); | ||
fs.writeFileSync( | ||
`${this.path}users.json`, | ||
usersJson, | ||
); | ||
} | ||
db.close(); | ||
db = undefined; | ||
} | ||
|
||
function returnUserFromRow(row) { | ||
return { | ||
user_id: row.user_id, | ||
username: row.username, | ||
display_name: row.display_name, | ||
bio: row.bio, | ||
pfp_link: row.pfp_link, | ||
password_hash: row.password_hash, | ||
}; | ||
} | ||
close() { | ||
if (!this.initialised) throw new Error('Database not initialized.'); | ||
|
||
async function getUserFromUserId(userId) { | ||
return new Promise((resolve, reject) => { | ||
if (!db) { | ||
reject(new Error('Database not yet initialized. Call `connect() first.`')); | ||
return; | ||
} | ||
this.save(); | ||
this.initialised = false; | ||
delete this; | ||
} | ||
|
||
const query = 'SELECT * FROM users WHERE user_id = ?'; | ||
|
||
db.get(query, [userId], (err, row) => { | ||
if (err) { | ||
reject(new Error(`Error querying the database: ${err.message}`)); | ||
} else if (!row) { // If no user is found, `row` will be null | ||
resolve(null); | ||
} else { | ||
resolve(returnUserFromRow(row)); | ||
} | ||
}); | ||
}); | ||
} | ||
getUserFromUserId(userId) { | ||
if (!this.initialised) { | ||
throw new Error('Database not initialized.'); | ||
} | ||
const index = this.users.findIndex((user) => user.user_id === userId); | ||
if (index === -1) return null; | ||
|
||
async function getUserFromUsername(username) { | ||
if (!db) { | ||
throw new Error('Database not yet initialized. Call `connect() first.`'); | ||
return returnUserFromRow(this.users[index]); | ||
} | ||
|
||
return new Promise((resolve, reject) => { | ||
const query = 'SELECT * FROM users WHERE username = ?'; | ||
|
||
db.get(query, [username], (err, row) => { | ||
if (err) { | ||
return reject(new Error(`Error querying the database: ${err.message}`)); | ||
} if (!row) { // If no user is found, `row` will be null | ||
return resolve(null); | ||
} | ||
return resolve(returnUserFromRow(row)); // If no user is found, `row` will be null | ||
}); | ||
}); | ||
} | ||
getUserFromUsername(username) { | ||
if (!this.initialised) { | ||
throw new Error('Database not initialized.'); | ||
} | ||
|
||
async function modifyUser(userId, displayName, bio) { | ||
if (!db) { | ||
throw new Error('Database not yet initialized. Call `connect() first.`'); | ||
const index = this.users.findIndex((user) => user.username === username); | ||
if (index === -1) return null; | ||
|
||
return returnUserFromRow(this.users[index]); | ||
} | ||
|
||
return new Promise((resolve, reject) => { | ||
const query = 'UPDATE users SET display_name = ?, bio = ? WHERE user_id = ?'; | ||
modifyUser(userId, displayName, bio) { | ||
if (!this.initialised) { | ||
throw new Error('Database not initialized.'); | ||
} | ||
|
||
const index = this.users.findIndex((user) => user.user_id === userId); | ||
if (index === -1) return false; | ||
|
||
db.run(query, [displayName, bio, userId], (err, res) => { | ||
if (err) { | ||
return reject(new Error(`Error querying the database: ${err.message}`)); | ||
} | ||
return resolve(res); | ||
}); | ||
}); | ||
this.users[index].display_name = displayName; | ||
this.users[index].bio = bio; | ||
|
||
this.save(); | ||
|
||
return true; | ||
} | ||
} | ||
|
||
module.exports = { | ||
connect, | ||
getDb, | ||
close, | ||
getUserFromUserId, | ||
getUserFromUsername, | ||
modifyUser, | ||
Datastore, | ||
}; |
Oops, something went wrong.