[Add User] Revamped db
This commit is contained in:
@@ -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] = [];
|
||||
}
|
||||
}
|
||||
return labelHandlers
|
||||
}
|
||||
|
||||
dbJson[superKey][key] = value;
|
||||
|
||||
await fs.writeFile(path.join(process.cwd(), 'db/db.json'), JSON.stringify(dbJson, null, 2), 'utf8')
|
||||
#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)
|
||||
}
|
||||
|
||||
generateUserID() {
|
||||
let id = this.#labels["User"].length + 1;
|
||||
while (this.get.user(`user-${id}`)) {
|
||||
id++;
|
||||
}
|
||||
return `user-${id}`; // O(1) most of the time
|
||||
model(entry);
|
||||
this.#labels[label].push(id);
|
||||
});
|
||||
}
|
||||
|
||||
async getAll() {
|
||||
|
||||
102
server/db/db.js
102
server/db/db.js
@@ -1,19 +1,83 @@
|
||||
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 = {
|
||||
@@ -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
43
server/db/model/Member.js
Normal 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
33
server/db/model/Title.js
Normal 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
39
server/db/model/Token.js
Normal 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
|
||||
}
|
||||
@@ -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]}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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' });
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
Sam Russell
|
||||
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.17.25.3 - Adding styles() and fixing dynamic function from earlier
|
||||
11.17.25.2 - Fixing onNavigate() and onAppear()
|
||||
@@ -219,6 +220,7 @@ HTMLElement.prototype.rerender = function() {
|
||||
|
||||
/* Styling */
|
||||
|
||||
window.pct = "%"
|
||||
window.vmin = "vmin"
|
||||
window.vmax = "vmax"
|
||||
window.vh = "vh"
|
||||
@@ -517,6 +519,36 @@ HTMLElement.prototype.centerY = function () {
|
||||
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 */
|
||||
|
||||
quill.setChildren = function(el, innerContent) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
class JoinForm extends Shadow {
|
||||
class SignupForm extends Shadow {
|
||||
|
||||
inputStyles(el) {
|
||||
return el
|
||||
@@ -82,4 +82,4 @@ class JoinForm extends Shadow {
|
||||
}
|
||||
}
|
||||
|
||||
register(JoinForm)
|
||||
register(SignupForm)
|
||||
@@ -1,5 +1,5 @@
|
||||
import "../components/NavBar.js"
|
||||
import "../components/JoinForm.js"
|
||||
import "../components/SignupForm.js"
|
||||
import "./Why.js"
|
||||
import "./Events.js"
|
||||
import "./Join.js"
|
||||
@@ -57,7 +57,7 @@ class Home extends Shadow {
|
||||
|
||||
default:
|
||||
if(window.location.pathname.startsWith("/signup")) {
|
||||
JoinForm()
|
||||
SignupForm()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user