[Add User] Revamped db

This commit is contained in:
metacryst
2025-11-21 00:04:11 -06:00
parent 30faf12b20
commit 525642d04e
10 changed files with 269 additions and 81 deletions

View File

@@ -23,37 +23,6 @@ export default class QuillDB {
this.loadData()
}
#checkLabelSchemas(id, entry, labelModels) {
entry.labels.forEach(label => {
const model = labelModels[label];
if (!model) {
throw new Error("Data has unknown label or missing model: " + label)
}
model(entry);
this.#labels[label].push(id);
});
}
async getLabelModels() {
const labelHandlers = {};
const labelDir = path.join(process.cwd(), 'server/db/model');
const files = await fs.readdir(labelDir);
for (const file of files) {
if (!file.endsWith('.js')) continue;
const label = path.basename(file, '.js');
const modulePath = path.join(labelDir, file);
const module = await import(pathToFileURL(modulePath).href);
labelHandlers[label] = module.default;
if (!this.#labels[label]) {
this.#labels[label] = [];
}
}
return labelHandlers
}
async loadData() {
const dbData = await fs.readFile(path.join(process.cwd(), 'db/db.json'), 'utf8');
let dbJson;
@@ -81,27 +50,35 @@ export default class QuillDB {
Object.preventExtensions(this);
}
// superKey = "nodes" || "edges"
async writeData(superKey, key, value) {
const dbData = await fs.readFile(path.join(process.cwd(), 'db/db.json'), 'utf8');
let dbJson;
try {
dbJson = JSON.parse(dbData);
} catch {
dbJson = []
async getLabelModels() {
const labelHandlers = {};
const labelDir = path.join(process.cwd(), 'server/db/model');
const files = await fs.readdir(labelDir);
for (const file of files) {
if (!file.endsWith('.js')) continue;
const label = path.basename(file, '.js');
const modulePath = path.join(labelDir, file);
const module = await import(pathToFileURL(modulePath).href);
labelHandlers[label] = module.default;
if (!this.#labels[label]) {
this.#labels[label] = [];
}
}
dbJson[superKey][key] = value;
await fs.writeFile(path.join(process.cwd(), 'db/db.json'), JSON.stringify(dbJson, null, 2), 'utf8')
return labelHandlers
}
generateUserID() {
let id = this.#labels["User"].length + 1;
while (this.get.user(`user-${id}`)) {
id++;
}
return `user-${id}`; // O(1) most of the time
#checkLabelSchemas(id, entry, labelModels) {
entry.labels.forEach(label => {
const model = labelModels[label];
if (!model) {
throw new Error("Data has unknown label or missing model: " + label)
}
model(entry);
this.#labels[label].push(id);
});
}
async getAll() {

View File

@@ -1,21 +1,85 @@
import QuillDB from "../_/quilldb.js"
import fs from 'fs/promises'
import path from 'path'
import Title from "./model/Title.js"
import Member from './model/Member.js'
import Token from './model/Token.js'
export default class Database extends QuillDB {
tokens;
export default class Database {
nodes = [];
types = [
{
validate: Title,
start: 0,
end: null,
},
{
validate: Member,
start: null,
end: null,
},
{
validate: Token,
start: null,
end: null,
},
]
constructor() {
super()
this.loadTokens()
this.loadData()
}
async loadTokens() {
const tokenData = await fs.readFile(path.join(process.cwd(), 'db/tokens.json'), 'utf8');
let tokenJSON = JSON.parse(tokenData);
this.tokens = tokenJSON
async loadData() {
const dbData = await fs.readFile(path.join(process.cwd(), 'db/db.json'), 'utf8');
let dbJson;
try {
dbJson = JSON.parse(dbData);
} catch {
dbJson = []
}
let nodes = dbJson["nodes"];
this.validateNodes(nodes)
}
validateNodes(nodes) {
nodes = Object.entries(nodes)
let t = 0
let currentType = () => {return this.types[t]}
let nextType = () => {return this.types[t+1]}
let selectNextType = () => {
currentType().end = t
t += 1;
currentType().start = t
}
let lastNode = (i=null) => {
if(i == null) throw new Error("must pass a param to lastNode()")
return i+1 === nodes.length
}
for(let i=0; i<nodes.length; i++) {
if(this.validateNode(currentType(), nodes[i])) {
if(lastNode(i)) {
currentType().end = i
break;
} else {
continue;
}
} else if(this.validateNode(nextType(), nodes[i])) {
selectNextType()
continue;
} else {
throw new Error("Nodes are out of order or corrupted!")
}
}
}
validateNode(type, node) {
let [key, value] = node
return type.validate(key, value)
}
get = {
user: (id) => {
return this.nodes[id]
@@ -30,10 +94,26 @@ export default class Database extends QuillDB {
return null;
},
token: (id) => {
return this.tokens[id]
return this.nodes[`TOKEN-${id}`]
}
}
add = {
user: (node) => {
let lastUser = {}
}
}
submitNewUser(qrCodeID, userInfo) {
let newUser = {
labels: ["User"],
...userInfo
}
if(User(newUser))
this.add.user(newUser)
}
generateUserID() {
let id = this.labels["User"].length + 1;
while (this.get.user(`user-${id}`)) {
@@ -41,8 +121,4 @@ export default class Database extends QuillDB {
}
return `user-${id}`; // O(1) most of the time
}
async getAll() {
return { nodes: this.nodes }
}
}

43
server/db/model/Member.js Normal file
View File

@@ -0,0 +1,43 @@
export default function Member(id, node) {
let idTraits = {
firstWord: "MEMBER",
length: 2
}
let fields = [
"firstName",
"lastName",
"email",
"password"
]
let checkID = () => {
let split = id.split("-")
return (
split.length === idTraits.length
&& split[0] === idTraits.firstWord
&& !isNaN(Number(split[1]))
)
}
let idres = checkID()
if(!idres) {
return false
}
let checkFields = () => {
for(let i = 0; i < fields.length; i++) {
if(!node[fields[i]]) {
throw new Error(`Member ${node.email} is missing trait ${fields[i]}`)
return false
} else {
return true
}
}
}
let fieldres = checkFields()
if(!fieldres) {
return false
}
return true
}

33
server/db/model/Title.js Normal file
View File

@@ -0,0 +1,33 @@
export default function Title(id, node) {
let checkID = () => {
let split = id.split("-")
return (
split.length === 2
&& split[0] === "HY"
&& !isNaN(Number(split[1]))
)
}
let idres = checkID()
if(!idres) {
return false
}
let checkFields = () => {
let fields = [
"fullName",
]
for(let i = 0; i < fields.length; i++) {
if(!node[fields[i]]) {
throw new Error(`Title ${id} is missing trait ${fields[i]}`)
return false
}
}
return true
}
let fieldres = checkFields()
if(!fieldres) {
return false
}
return true
}

39
server/db/model/Token.js Normal file
View File

@@ -0,0 +1,39 @@
export default function Token(id, node) {
let idTraits = {
firstWord: "TOKEN"
}
let fields = [
"index",
"url",
"used"
]
let checkID = () => {
let split = id.split("-")
return (
split[0] === idTraits.firstWord
)
}
let idres = checkID()
if(!idres) {
return false
}
let checkFields = () => {
for(let i = 0; i < fields.length; i++) {
if(!node[fields[i]]) {
throw new Error(`Token ${node.email} is missing trait ${fields[i]}`)
return false
} else {
return true
}
}
}
let fieldres = checkFields()
if(!fieldres) {
return false
}
return true
}

View File

@@ -1,14 +0,0 @@
export default function User(node) {
let traits = [
"firstName",
"lastName",
"email",
"password"
]
for(let i = 0; i < traits.length; i++) {
if(!node[traits[i]]) {
if (traits[i] == "lastName") { continue; } // Ignores optional Last Name
throw new Error(`User ${node.email} is missing trait ${traits[i]}`)
}
}
}

View File

@@ -49,6 +49,8 @@ class Server {
}
newUserSubmission = (req, res) => {
const { token } = req.query;
db.submitNewUser(token, req.body)
return res.status(400).json({ error: 'Haven\t finished this bruh' });
}