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

View File

@@ -1,21 +1,85 @@
import QuillDB from "../_/quilldb.js" import QuillDB from "../_/quilldb.js"
import fs from 'fs/promises' import fs from 'fs/promises'
import path from 'path' 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 { export default class Database {
tokens; nodes = [];
types = [
{
validate: Title,
start: 0,
end: null,
},
{
validate: Member,
start: null,
end: null,
},
{
validate: Token,
start: null,
end: null,
},
]
constructor() { constructor() {
super() this.loadData()
this.loadTokens()
} }
async loadTokens() { async loadData() {
const tokenData = await fs.readFile(path.join(process.cwd(), 'db/tokens.json'), 'utf8'); const dbData = await fs.readFile(path.join(process.cwd(), 'db/db.json'), 'utf8');
let tokenJSON = JSON.parse(tokenData); let dbJson;
this.tokens = tokenJSON 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 = { get = {
user: (id) => { user: (id) => {
return this.nodes[id] return this.nodes[id]
@@ -30,10 +94,26 @@ export default class Database extends QuillDB {
return null; return null;
}, },
token: (id) => { 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() { generateUserID() {
let id = this.labels["User"].length + 1; let id = this.labels["User"].length + 1;
while (this.get.user(`user-${id}`)) { 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 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) => { newUserSubmission = (req, res) => {
const { token } = req.query;
db.submitNewUser(token, req.body)
return res.status(400).json({ error: 'Haven\t finished this bruh' }); return res.status(400).json({ error: 'Haven\t finished this bruh' });
} }

View File

@@ -1,6 +1,7 @@
/* /*
Sam Russell Sam Russell
Captured Sun Captured Sun
11.20.25 - Added "pct" style unit, added alignVertical and alignHorizontal for flex boxes
11.19.25 - Allowing for "auto" values in otherwise numeric styles, adding vmin and vmax units 11.19.25 - Allowing for "auto" values in otherwise numeric styles, adding vmin and vmax units
11.17.25.3 - Adding styles() and fixing dynamic function from earlier 11.17.25.3 - Adding styles() and fixing dynamic function from earlier
11.17.25.2 - Fixing onNavigate() and onAppear() 11.17.25.2 - Fixing onNavigate() and onAppear()
@@ -219,6 +220,7 @@ HTMLElement.prototype.rerender = function() {
/* Styling */ /* Styling */
window.pct = "%"
window.vmin = "vmin" window.vmin = "vmin"
window.vmax = "vmax" window.vmax = "vmax"
window.vh = "vh" window.vh = "vh"
@@ -517,6 +519,36 @@ HTMLElement.prototype.centerY = function () {
return this; return this;
}; };
HTMLElement.prototype.alignVertical = function (value) {
const direction = getComputedStyle(this).flexDirection;
if(!direction) {
throw new Error("alignVertical can be only be used on HStacks or VStacks!")
}
if (direction === "column" || direction === "column-reverse") {
console.log("using justify")
this.style.justifyContent = value;
} else {
this.style.alignItems = value;
}
return this
}
HTMLElement.prototype.alignHorizontal = function (value) {
const direction = getComputedStyle(this).flexDirection;
if(!direction) {
throw new Error("alignHorizontal can be only be used on HStacks or VStacks!")
}
if (direction === "column" || direction === "column-reverse") {
this.style.alignItems = value;
} else {
this.style.justifyContent = value;
}
return this
}
/* Elements */ /* Elements */
quill.setChildren = function(el, innerContent) { quill.setChildren = function(el, innerContent) {

View File

@@ -1,4 +1,4 @@
class JoinForm extends Shadow { class SignupForm extends Shadow {
inputStyles(el) { inputStyles(el) {
return el return el
@@ -82,4 +82,4 @@ class JoinForm extends Shadow {
} }
} }
register(JoinForm) register(SignupForm)

View File

@@ -1,5 +1,5 @@
import "../components/NavBar.js" import "../components/NavBar.js"
import "../components/JoinForm.js" import "../components/SignupForm.js"
import "./Why.js" import "./Why.js"
import "./Events.js" import "./Events.js"
import "./Join.js" import "./Join.js"
@@ -57,7 +57,7 @@ class Home extends Shadow {
default: default:
if(window.location.pathname.startsWith("/signup")) { if(window.location.pathname.startsWith("/signup")) {
JoinForm() SignupForm()
} }
} }