From 3ec77521162b0fd7e25bc51b70a17def54e4f8a4 Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Tue, 26 Nov 2024 00:02:33 -0800 Subject: [PATCH 01/16] added endpoints for creating & retrieving logbooks --- backend/index.js | 7 +- .../src/middlewares/__tests__/auth.test.js | 3 - backend/src/middlewares/auth.js | 3 +- .../routes/{authRoutes.js => auth-route.js} | 1 - backend/src/routes/logRoutes.js | 17 ----- backend/src/routes/logbooks-route.js | 27 +++++++ .../services/cardiacSurgeryAdultService.js | 76 ------------------- backend/src/services/logbooks-service.js | 58 ++++++++++++++ 8 files changed, 89 insertions(+), 103 deletions(-) delete mode 100644 backend/src/middlewares/__tests__/auth.test.js rename backend/src/routes/{authRoutes.js => auth-route.js} (95%) delete mode 100644 backend/src/routes/logRoutes.js create mode 100644 backend/src/routes/logbooks-route.js delete mode 100644 backend/src/services/cardiacSurgeryAdultService.js create mode 100644 backend/src/services/logbooks-service.js diff --git a/backend/index.js b/backend/index.js index fddd630d..056c2437 100644 --- a/backend/index.js +++ b/backend/index.js @@ -1,8 +1,8 @@ import cors from "cors"; import dotenv from "dotenv"; import express from "express"; -import authRoutes from "./src/routes/authRoutes.js"; -import logRoutes from "./src/routes/logRoutes.js"; +import authRoutes from "./src/routes/auth-route.js"; +import logRoutes from "./src/routes/logbooks-route.js"; dotenv.config(); @@ -15,9 +15,8 @@ const PORT = process.env.PORT || 8080; app.use(cors(corsOptions)); app.use(express.json()); -//Routes app.use('/api/auth', authRoutes); -app.use('/api/log', logRoutes); +app.use('/api/logbooks', logRoutes); app.listen(PORT, () => { console.log(`Server listening on ${PORT}`); diff --git a/backend/src/middlewares/__tests__/auth.test.js b/backend/src/middlewares/__tests__/auth.test.js deleted file mode 100644 index d8d52d4b..00000000 --- a/backend/src/middlewares/__tests__/auth.test.js +++ /dev/null @@ -1,3 +0,0 @@ -test("empty test", () => { - expect(true).toBe(true) -}) \ No newline at end of file diff --git a/backend/src/middlewares/auth.js b/backend/src/middlewares/auth.js index f758065c..e0596177 100644 --- a/backend/src/middlewares/auth.js +++ b/backend/src/middlewares/auth.js @@ -26,5 +26,4 @@ const auth = async (req, res, next) => { } }; -export default auth; - +export default auth; \ No newline at end of file diff --git a/backend/src/routes/authRoutes.js b/backend/src/routes/auth-route.js similarity index 95% rename from backend/src/routes/authRoutes.js rename to backend/src/routes/auth-route.js index b0474aac..a0f746f7 100644 --- a/backend/src/routes/authRoutes.js +++ b/backend/src/routes/auth-route.js @@ -3,7 +3,6 @@ import auth from "../middlewares/auth.js"; const router = express.Router(); -//auth test router.post("/check", auth, async (req, res) => { res.json({ message: "Auth Check Ok"}); }) diff --git a/backend/src/routes/logRoutes.js b/backend/src/routes/logRoutes.js deleted file mode 100644 index 4f7bca2f..00000000 --- a/backend/src/routes/logRoutes.js +++ /dev/null @@ -1,17 +0,0 @@ -import express from "express"; -import auth from "../middlewares/auth.js"; -import insertTable from "../services/cardiacSurgeryAdultService.js" - -const router = express.Router(); - -router.post("/cardiacSurgeryAdultService", auth, async (req, res) => { - try { - const result = await insertTable(req, res); - res.json(result); - } catch(error) { - console.error("Caught Error:", error.message); - res.status(500).json({message: error.message}); - } -}) - -export default router; \ No newline at end of file diff --git a/backend/src/routes/logbooks-route.js b/backend/src/routes/logbooks-route.js new file mode 100644 index 00000000..2793a793 --- /dev/null +++ b/backend/src/routes/logbooks-route.js @@ -0,0 +1,27 @@ +import express from "express"; +import auth from "../middlewares/auth.js"; +import { createLogbook, getUserLogbooks, getLogbook, createLog } from "../services/logbooks-service.js"; + +const router = express.Router(); + +router.post("/", auth, async (req, res) => { + const logbook = await createLogbook(req); + res.status(201).json({ data: logbook }); +}); + +router.get("/", auth, async (req, res) => { + const logbooks = await getUserLogbooks(req); + res.status(200).json({ data: logbooks }); +}); + +router.get("/:id", auth, async (req, res) => { + const logbook = await getLogbook(req); + res.status(200).json({ data: logbook }); +}); + +router.post("/logs", auth, async (req, res) => { + const log = await createLog(req); + res.status(201).json({ data: log }); +}); + +export default router; \ No newline at end of file diff --git a/backend/src/services/cardiacSurgeryAdultService.js b/backend/src/services/cardiacSurgeryAdultService.js deleted file mode 100644 index 5cc3ce69..00000000 --- a/backend/src/services/cardiacSurgeryAdultService.js +++ /dev/null @@ -1,76 +0,0 @@ - -async function insertTable(req) { - try{ - const supabase = req.supabase; - - const { - case_no, - patient_id, - type, - surgeon, - or_date, - age, - sex, - reason, - hpi, - social, - pmhx, - meds, - allergies, - exam, - veins, - allen_test, - pulses, - invx, - cxr, - ct, - cath, - surgical_plan, - operative_notes, - post_op_course, - learning_points - } = req.body; - - const error = await supabase.schema("user_info").from("cardiac_surgery_adult_log") - .insert({ - case_no: case_no, - patient_id: patient_id, - type: type, - surgeon: surgeon, - or_date: or_date, - age: age, - sex: sex, - reason: reason, - hpi: hpi, - social: social, - pmhx: pmhx, - meds: meds, - allergies: allergies, - exam: exam, - veins: veins, - allen_test: allen_test, - pulses: pulses, - invx: invx, - cxr: cxr, - ct: ct, - cath: cath, - surgical_plan: surgical_plan, - operative_notes: operative_notes, - post_op_course: post_op_course, - learning_points: learning_points }); - - if (error.error) { - console.log(error); - console.error("Insert Error:", error.error.message); - throw new Error("Failed to insert data: " + error.error.message); - } - - return {message: "Log Successful"}; - } catch (error) { - console.error("Error in insertTable:", error.message); - throw new Error(error.message); - } -} - -export default insertTable; - diff --git a/backend/src/services/logbooks-service.js b/backend/src/services/logbooks-service.js new file mode 100644 index 00000000..2973ea0d --- /dev/null +++ b/backend/src/services/logbooks-service.js @@ -0,0 +1,58 @@ +export async function createLogbook(req) { + try { + const supabase = req.supabase; + const { type } = req.body; + const { data, error } = await supabase.from("logbooks").insert({ type: type }).select(); + if (error) { + console.error("Error in createLogbook:", error.message); + throw new Error(error.message); + } else { + return data[0]; + } + } catch (error) { + console.error("Error in createLogbook:", error.message); + throw new Error(error.message); + } +} + +export async function getUserLogbooks(req) { + try { + const supabase = req.supabase; + const token = req.header("Authorization")?.split(" ")[1]; + const userID = parseUserID(token) + const { data, error } = await supabase.from("logbooks").select().eq("user_id", userID); + if (error) { + console.error("Error in getUserLogbooks:", error.message); + throw new Error(error.message); + } else { + return data; + } + } catch (error) { + console.error("Error in getUserLogbooks:", error.message); + throw new Error(error.message); + } +} + +function parseUserID(token) { + const parts = token.split('.'); + const decodedPayload = JSON.parse(atob(parts[1])); + const userID = decodedPayload["sub"] + return userID +} + +export async function getLogbook(req) { + try { + const supabase = req.supabase; + const { id } = req.params; + const { data, error } = await supabase.from("logbooks").select().eq("logbook_id", id); + if (error) { + console.error("Error in getLogbook:", error.message); + throw new Error(error.message); + } else { + return data[0]; + } + } catch (error) { + console.error("Error in getLogbook:", error.message); + throw new Error(error.message); + } +} \ No newline at end of file From b23c57b399206abdc441e8130b2aa9b8eadd48a5 Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Tue, 26 Nov 2024 01:32:48 -0800 Subject: [PATCH 02/16] added endpoints for creating & retrieving logs (adult cardiac) --- backend/src/routes/logbooks-route.js | 22 +++-- backend/src/services/logbooks-service.js | 104 +++++++++++++++++++---- 2 files changed, 102 insertions(+), 24 deletions(-) diff --git a/backend/src/routes/logbooks-route.js b/backend/src/routes/logbooks-route.js index 2793a793..add94897 100644 --- a/backend/src/routes/logbooks-route.js +++ b/backend/src/routes/logbooks-route.js @@ -1,6 +1,6 @@ import express from "express"; import auth from "../middlewares/auth.js"; -import { createLogbook, getUserLogbooks, getLogbook, createLog } from "../services/logbooks-service.js"; +import { createLogbook, getUserLogbooks, getLogbook, createLog, getLogbookLogs, getLog } from "../services/logbooks-service.js"; const router = express.Router(); @@ -10,18 +10,28 @@ router.post("/", auth, async (req, res) => { }); router.get("/", auth, async (req, res) => { - const logbooks = await getUserLogbooks(req); - res.status(200).json({ data: logbooks }); + const userLogbooks = await getUserLogbooks(req); + res.status(200).json({ data: userLogbooks }); }); -router.get("/:id", auth, async (req, res) => { +router.get("/:logbookID", auth, async (req, res) => { const logbook = await getLogbook(req); res.status(200).json({ data: logbook }); }); -router.post("/logs", auth, async (req, res) => { +router.post("/:logbookID/logs", auth, async (req, res) => { const log = await createLog(req); res.status(201).json({ data: log }); }); -export default router; \ No newline at end of file +router.get("/:logbookID/logs/", auth, async (req, res) => { + const logbookLogs = await getLogbookLogs(req) + res.status(200).json({ data: logbookLogs }); +}) + +router.get("/:logbookID/logs/:logID", auth, async (req, res) => { + const log = await getLog(req) + res.status(200).json({ data: log }); +}) + +export default router; diff --git a/backend/src/services/logbooks-service.js b/backend/src/services/logbooks-service.js index 2973ea0d..0acb7772 100644 --- a/backend/src/services/logbooks-service.js +++ b/backend/src/services/logbooks-service.js @@ -4,13 +4,10 @@ export async function createLogbook(req) { const { type } = req.body; const { data, error } = await supabase.from("logbooks").insert({ type: type }).select(); if (error) { - console.error("Error in createLogbook:", error.message); throw new Error(error.message); - } else { - return data[0]; } + return data[0]; } catch (error) { - console.error("Error in createLogbook:", error.message); throw new Error(error.message); } } @@ -19,40 +16,111 @@ export async function getUserLogbooks(req) { try { const supabase = req.supabase; const token = req.header("Authorization")?.split(" ")[1]; - const userID = parseUserID(token) + const userID = parseUserID(token); const { data, error } = await supabase.from("logbooks").select().eq("user_id", userID); if (error) { - console.error("Error in getUserLogbooks:", error.message); throw new Error(error.message); - } else { - return data; } + return data; } catch (error) { - console.error("Error in getUserLogbooks:", error.message); throw new Error(error.message); } } function parseUserID(token) { - const parts = token.split('.'); + const parts = token.split("."); const decodedPayload = JSON.parse(atob(parts[1])); - const userID = decodedPayload["sub"] - return userID + const userID = decodedPayload["sub"]; + return userID; } export async function getLogbook(req) { try { const supabase = req.supabase; - const { id } = req.params; - const { data, error } = await supabase.from("logbooks").select().eq("logbook_id", id); + const { logbookID } = req.params; + const { data, error } = await supabase.from("logbooks").select().eq("id", logbookID); if (error) { - console.error("Error in getLogbook:", error.message); throw new Error(error.message); - } else { - return data[0]; } + return data[0]; + } catch (error) { + throw new Error(error.message); + } +} + +export async function createLog(req) { + try { + const supabase = req.supabase; + const { logbookID } = req.params; + const { type } = req.body; + const logbookType = await getLogbookType(logbookID, supabase); + if (type !== logbookType) { + throw new Error("Error: Log does not match logbook type"); + } + let data; + switch (type) { + case "adult_cardiac_logs": + data = createAdultCardiacLog(req, supabase); + break; + default: + break; + } + return data; + } catch (error) { + throw new Error(error.message); + } +} + +async function createAdultCardiacLog(req, supabase) { + const { logbookID } = req.params; + const { caseNo } = req.body; + const { data, error } = await supabase + .from("adult_cardiac_logs") + .insert({ + logbook_id: logbookID, + case_no: Number(caseNo), + }) + .select(); + if (error) { + throw new Error(error.message); + } + return data[0]; +} + +async function getLogbookType(logbookID, supabase) { + const { data, error } = await supabase.from("logbooks").select().eq("id", logbookID); + if (error) { + throw new Error(error.message); + } + return data[0]["type"]; +} + +export async function getLogbookLogs(req) { + try { + const supabase = req.supabase; + const { logbookID } = req.params; + const logbookType = await getLogbookType(logbookID, supabase); + const { data, error } = await supabase.from(logbookType).select(); + if (error) { + throw new Error(error.message); + } + return data; + } catch (error) { + throw new Error(error.message); + } +} + +export async function getLog(req) { + try { + const supabase = req.supabase; + const { logbookID, logID } = req.params; + const logbookType = await getLogbookType(logbookID, supabase); + const { data, error } = await supabase.from(logbookType).select().eq("id", logID); + if (error) { + throw new Error(error.message); + } + return data[0]; } catch (error) { - console.error("Error in getLogbook:", error.message); throw new Error(error.message); } } \ No newline at end of file From ada1ac39f103dc9e1f02518bbfd54c3abd6e9d83 Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Tue, 26 Nov 2024 02:17:05 -0800 Subject: [PATCH 03/16] added backend linting --- backend/eslint.config.js | 45 ++++++++-------------------- backend/package.json | 2 +- backend/src/middlewares/auth.js | 2 -- backend/src/routes/logbooks-route.js | 8 ++--- 4 files changed, 18 insertions(+), 39 deletions(-) diff --git a/backend/eslint.config.js b/backend/eslint.config.js index e5eb2558..9ed74ac0 100644 --- a/backend/eslint.config.js +++ b/backend/eslint.config.js @@ -1,34 +1,15 @@ -import js from '@eslint/js' -import jest from 'eslint-plugin-jest' -import globals from 'globals' +import globals from "globals"; +import pluginJs from "@eslint/js"; +/** @type {import('eslint').Linter.Config[]} */ export default [ - { ignores: ['dist'] }, - { - files: ['**/*.{js,ts}'], - languageOptions: { - ecmaVersion: 'latest', - globals: globals.node, - parserOptions: { - ecmaVersion: 'latest', - ecmaFeatures: { jsx: true }, - sourceType: 'module', - }, - }, - rules: { - ...js.configs.recommended.rules, - }, - }, - { - files: ['**/__tests__/**/*.test.{js,ts}'], - plugins: { - jest, - }, - languageOptions: { - globals: jest.environments.globals.globals - }, - rules: { - ...jest.configs.recommended.rules, - } - } -] + { languageOptions: { globals: globals.node } }, + pluginJs.configs.recommended, + { + rules: { + camelcase: ["warn", { properties: "never", ignoreDestructuring: false }], + "max-len": ["warn", { code: 140 }], + "no-console": "warn", + }, + }, +]; diff --git a/backend/package.json b/backend/package.json index 9634e7a3..b7b01d00 100644 --- a/backend/package.json +++ b/backend/package.json @@ -6,7 +6,7 @@ "scripts": { "build": "babel index.js -d dist", "dev": "nodemon server", - "lint": "eslint .", + "lint": "eslint", "start": "node index.js", "test": "jest" }, diff --git a/backend/src/middlewares/auth.js b/backend/src/middlewares/auth.js index e0596177..b8d71ea2 100644 --- a/backend/src/middlewares/auth.js +++ b/backend/src/middlewares/auth.js @@ -16,12 +16,10 @@ const auth = async (req, res, next) => { }) req.supabase = supabase; } else { - console.error("No token: Authentication Denied"); return res.status(401).json({ message: "No token: Authentication Denied" }); } next(); } catch (err) { - console.error("Invalid token, authentication denied:", err.message); return res.status(400).json({ message: `Invalid token, authentication denied: ${err.message}`}); } }; diff --git a/backend/src/routes/logbooks-route.js b/backend/src/routes/logbooks-route.js index add94897..b86a059e 100644 --- a/backend/src/routes/logbooks-route.js +++ b/backend/src/routes/logbooks-route.js @@ -25,13 +25,13 @@ router.post("/:logbookID/logs", auth, async (req, res) => { }); router.get("/:logbookID/logs/", auth, async (req, res) => { - const logbookLogs = await getLogbookLogs(req) + const logbookLogs = await getLogbookLogs(req); res.status(200).json({ data: logbookLogs }); -}) +}); router.get("/:logbookID/logs/:logID", auth, async (req, res) => { - const log = await getLog(req) + const log = await getLog(req); res.status(200).json({ data: log }); -}) +}); export default router; From 75bfa22f26e4cf4b0080e1626cda53eaaa799b4e Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Tue, 26 Nov 2024 02:20:00 -0800 Subject: [PATCH 04/16] added dummy backend test --- backend/test/backend-test.js | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 backend/test/backend-test.js diff --git a/backend/test/backend-test.js b/backend/test/backend-test.js new file mode 100644 index 00000000..03139b78 --- /dev/null +++ b/backend/test/backend-test.js @@ -0,0 +1,3 @@ +test("empty test", () => { + expect(true).toBe(true) + }) \ No newline at end of file From 7de87c56e3580ca43acdd191ea13b5016211b603 Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Tue, 26 Nov 2024 02:26:08 -0800 Subject: [PATCH 05/16] fixed linting --- backend/eslint.config.js | 5 ++--- backend/test/{backend-test.js => backend.test.js} | 0 2 files changed, 2 insertions(+), 3 deletions(-) rename backend/test/{backend-test.js => backend.test.js} (100%) diff --git a/backend/eslint.config.js b/backend/eslint.config.js index 9ed74ac0..6dfc1ada 100644 --- a/backend/eslint.config.js +++ b/backend/eslint.config.js @@ -3,13 +3,12 @@ import pluginJs from "@eslint/js"; /** @type {import('eslint').Linter.Config[]} */ export default [ - { languageOptions: { globals: globals.node } }, + { languageOptions: { globals: { ...globals.node, ...globals.jest } } }, pluginJs.configs.recommended, { rules: { camelcase: ["warn", { properties: "never", ignoreDestructuring: false }], "max-len": ["warn", { code: 140 }], - "no-console": "warn", }, }, -]; +]; \ No newline at end of file diff --git a/backend/test/backend-test.js b/backend/test/backend.test.js similarity index 100% rename from backend/test/backend-test.js rename to backend/test/backend.test.js From c27acf2e8e0b19088abb39df476dcb430056c6b0 Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Tue, 26 Nov 2024 10:56:45 -0800 Subject: [PATCH 06/16] added remaining keys to adult cardiac logs request --- backend/src/middlewares/auth.js | 1 + backend/src/routes/logbooks-route.js | 8 +- backend/src/services/logbooks-service.js | 114 ++++++++++++++++++++++- 3 files changed, 115 insertions(+), 8 deletions(-) diff --git a/backend/src/middlewares/auth.js b/backend/src/middlewares/auth.js index b8d71ea2..90cccfb9 100644 --- a/backend/src/middlewares/auth.js +++ b/backend/src/middlewares/auth.js @@ -4,6 +4,7 @@ import { createClient } from "@supabase/supabase-js"; const auth = async (req, res, next) => { try { const token = req.header("Authorization")?.split(" ")[1]; + console.log(token) const supabaseSecret = process.env.SUPABASE_JWT_SECRET; if (token) { jwt.verify(token, supabaseSecret); diff --git a/backend/src/routes/logbooks-route.js b/backend/src/routes/logbooks-route.js index b86a059e..a846f795 100644 --- a/backend/src/routes/logbooks-route.js +++ b/backend/src/routes/logbooks-route.js @@ -4,12 +4,12 @@ import { createLogbook, getUserLogbooks, getLogbook, createLog, getLogbookLogs, const router = express.Router(); -router.post("/", auth, async (req, res) => { +router.post("", auth, async (req, res) => { const logbook = await createLogbook(req); res.status(201).json({ data: logbook }); }); -router.get("/", auth, async (req, res) => { +router.get("", auth, async (req, res) => { const userLogbooks = await getUserLogbooks(req); res.status(200).json({ data: userLogbooks }); }); @@ -24,7 +24,7 @@ router.post("/:logbookID/logs", auth, async (req, res) => { res.status(201).json({ data: log }); }); -router.get("/:logbookID/logs/", auth, async (req, res) => { +router.get("/:logbookID/logs", auth, async (req, res) => { const logbookLogs = await getLogbookLogs(req); res.status(200).json({ data: logbookLogs }); }); @@ -34,4 +34,4 @@ router.get("/:logbookID/logs/:logID", auth, async (req, res) => { res.status(200).json({ data: log }); }); -export default router; +export default router; \ No newline at end of file diff --git a/backend/src/services/logbooks-service.js b/backend/src/services/logbooks-service.js index 0acb7772..cdcba939 100644 --- a/backend/src/services/logbooks-service.js +++ b/backend/src/services/logbooks-service.js @@ -73,14 +73,120 @@ export async function createLog(req) { async function createAdultCardiacLog(req, supabase) { const { logbookID } = req.params; - const { caseNo } = req.body; + const { + type, + caseNo, + paitentID, + surgeon, + age, + gender, + orDate, + reason, + hpi, + socialEtOH, + socialDrugs, + socialSmoking, + socialMeds, + socialAllergies, + phmxHTN, + phmxDMII, + phmxDLP, + phmxCVA, + examWeight, + examHeight, + examBMI, + examVeins, + examAllenTest, + examPulsesSixtyTwo, + examPulsesSixtyFive, + examPulsesSixtyEight, + examPulsesSeventy, + cathLink, + invxEchoEF, + invxEchoRVFx, + invxWMA, + invxAorta, + invxValves, + invxCXR, + invxHb, + invxW, + invxPit, + invxCr, + ctLink, + surgicalPlan, + surgicalPlanFirstOperator, + surgicalPlanIssueOR, + surgicalPlanIssuePost, + surgicalPlanaFlagForFU, + operativeNotesCPBh, + operativeNotesCPBm, + operativeNotesXCh, + operativeNotesXCm, + operativeNotesCAh, + operativeNotesCAm, + myRole, + postOperativeCourse, + learningPointsKeyLessons, + } = req.body; const { data, error } = await supabase .from("adult_cardiac_logs") .insert({ logbook_id: logbookID, - case_no: Number(caseNo), + type: type, + case_no: caseNo, + paitent_id: paitentID, + surgeon: surgeon, + age: age, + gender: gender, + or_date: orDate, + reason: reason, + hpi: hpi, + social_etoh: socialEtOH, + social_drugs: socialDrugs, + social_smoking: socialSmoking, + social_meds: socialMeds, + social_allergies: socialAllergies, + pmhx_htn: phmxHTN, + pmhx_dmii: phmxDMII, + pmhx_dlp: phmxDLP, + pmhx_cva: phmxCVA, + exam_weight: examWeight, + exam_height: examHeight, + exam_bmi: examBMI, + exam_veins: examVeins, + exam_allen_test: examAllenTest, + exam_pulses_sixtytwo: examPulsesSixtyTwo, + exam_pulses_sixtyfive: examPulsesSixtyFive, + exam_pulses_sixtyeight: examPulsesSixtyEight, + exam_pulses_seventy: examPulsesSeventy, + cath: cathLink, + invx_echo_ef: invxEchoEF, + invx_echo_rvfx: invxEchoRVFx, + invx_wma: invxWMA, + invx_aorta: invxAorta, + invx_valves: invxValves, + invx_cxr: invxCXR, + invx_hb: invxHb, + invx_w: invxW, + invx_pit: invxPit, + invx_cr: invxCr, + ct: ctLink, + surgical_plan: surgicalPlan, + surgical_plan_first_operator: surgicalPlanFirstOperator, + surgical_plan_issue_or: surgicalPlanIssueOR, + surgical_plan_issue_post: surgicalPlanIssuePost, + surgical_plan_flag_for_fu: surgicalPlanaFlagForFU, + operative_notes_cpb_h: operativeNotesCPBh, + operative_notes_cpb_m: operativeNotesCPBm, + operative_notes_xc_h: operativeNotesXCh, + operative_notes_xc_m: operativeNotesXCm, + operative_notes_ca_h: operativeNotesCAh, + operative_notes_ca_m: operativeNotesCAm, + my_role: myRole, + post_operative_course: postOperativeCourse, + learning_points_key_lessons: learningPointsKeyLessons, }) - .select(); + .select(); if (error) { throw new Error(error.message); } @@ -123,4 +229,4 @@ export async function getLog(req) { } catch (error) { throw new Error(error.message); } -} \ No newline at end of file +} From 3bb78b93cb73f142900b95aaecc4789b2a042cf6 Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Tue, 26 Nov 2024 11:19:16 -0800 Subject: [PATCH 07/16] removed console.log in auth --- backend/src/middlewares/auth.js | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/middlewares/auth.js b/backend/src/middlewares/auth.js index 90cccfb9..b8d71ea2 100644 --- a/backend/src/middlewares/auth.js +++ b/backend/src/middlewares/auth.js @@ -4,7 +4,6 @@ import { createClient } from "@supabase/supabase-js"; const auth = async (req, res, next) => { try { const token = req.header("Authorization")?.split(" ")[1]; - console.log(token) const supabaseSecret = process.env.SUPABASE_JWT_SECRET; if (token) { jwt.verify(token, supabaseSecret); From 71af7f8fbee9a71ad70f6039ec3f216567be81e1 Mon Sep 17 00:00:00 2001 From: TONY LIU Date: Wed, 27 Nov 2024 12:49:00 -0800 Subject: [PATCH 08/16] add example error handling on controller side --- backend/src/routes/logbooks-route.js | 12 ++++++++++-- backend/src/services/logbooks-service.js | 6 ++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/backend/src/routes/logbooks-route.js b/backend/src/routes/logbooks-route.js index a846f795..ca8b116c 100644 --- a/backend/src/routes/logbooks-route.js +++ b/backend/src/routes/logbooks-route.js @@ -26,12 +26,20 @@ router.post("/:logbookID/logs", auth, async (req, res) => { router.get("/:logbookID/logs", auth, async (req, res) => { const logbookLogs = await getLogbookLogs(req); - res.status(200).json({ data: logbookLogs }); + if (logbookLogs.error) { + res.status(500).json({ error: logbookLogs.error }); + } else { + res.status(200).json({ data: logbookLogs }); + } }); router.get("/:logbookID/logs/:logID", auth, async (req, res) => { const log = await getLog(req); - res.status(200).json({ data: log }); + if (log.error) { + res.status(500).json({ error: log.error }); + } else { + res.status(200).json({ data: log }); + } }); export default router; \ No newline at end of file diff --git a/backend/src/services/logbooks-service.js b/backend/src/services/logbooks-service.js index cdcba939..ecf9b1c2 100644 --- a/backend/src/services/logbooks-service.js +++ b/backend/src/services/logbooks-service.js @@ -212,7 +212,8 @@ export async function getLogbookLogs(req) { } return data; } catch (error) { - throw new Error(error.message); + console.error(error.message); + return {error: error.message} } } @@ -227,6 +228,7 @@ export async function getLog(req) { } return data[0]; } catch (error) { - throw new Error(error.message); + console.error(error.message); + return {error: error.message} } } From 1b474390d2f52bbf38b979f4fa8840f0ea600180 Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Thu, 28 Nov 2024 12:03:24 -0800 Subject: [PATCH 09/16] added individual tests to routes --- backend/src/routes/test/auth-route.test.js | 3 +++ backend/src/routes/test/logbooks-route.test.js | 3 +++ backend/test/backend.test.js | 3 --- 3 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 backend/src/routes/test/auth-route.test.js create mode 100644 backend/src/routes/test/logbooks-route.test.js delete mode 100644 backend/test/backend.test.js diff --git a/backend/src/routes/test/auth-route.test.js b/backend/src/routes/test/auth-route.test.js new file mode 100644 index 00000000..06224af9 --- /dev/null +++ b/backend/src/routes/test/auth-route.test.js @@ -0,0 +1,3 @@ +test("empty test", () => { + expect(true).toBe(true); +}); diff --git a/backend/src/routes/test/logbooks-route.test.js b/backend/src/routes/test/logbooks-route.test.js new file mode 100644 index 00000000..06224af9 --- /dev/null +++ b/backend/src/routes/test/logbooks-route.test.js @@ -0,0 +1,3 @@ +test("empty test", () => { + expect(true).toBe(true); +}); diff --git a/backend/test/backend.test.js b/backend/test/backend.test.js deleted file mode 100644 index 03139b78..00000000 --- a/backend/test/backend.test.js +++ /dev/null @@ -1,3 +0,0 @@ -test("empty test", () => { - expect(true).toBe(true) - }) \ No newline at end of file From 9a7d61ee766564236c350288d42b412da050919a Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Thu, 28 Nov 2024 16:13:00 -0800 Subject: [PATCH 10/16] refactored code to add helpers & added better error handling --- backend/src/middlewares/auth.js | 1 + backend/src/routes/logbooks-route.js | 24 ++- backend/src/services/logbooks-service.js | 240 +++-------------------- backend/src/utils/get-logbook-type.js | 11 ++ backend/src/utils/get-table.js | 18 ++ backend/src/utils/insert-table.js | 12 ++ backend/src/utils/parse-user-id.js | 9 + 7 files changed, 103 insertions(+), 212 deletions(-) create mode 100644 backend/src/utils/get-logbook-type.js create mode 100644 backend/src/utils/get-table.js create mode 100644 backend/src/utils/insert-table.js create mode 100644 backend/src/utils/parse-user-id.js diff --git a/backend/src/middlewares/auth.js b/backend/src/middlewares/auth.js index b8d71ea2..90cccfb9 100644 --- a/backend/src/middlewares/auth.js +++ b/backend/src/middlewares/auth.js @@ -4,6 +4,7 @@ import { createClient } from "@supabase/supabase-js"; const auth = async (req, res, next) => { try { const token = req.header("Authorization")?.split(" ")[1]; + console.log(token) const supabaseSecret = process.env.SUPABASE_JWT_SECRET; if (token) { jwt.verify(token, supabaseSecret); diff --git a/backend/src/routes/logbooks-route.js b/backend/src/routes/logbooks-route.js index ca8b116c..5f7f4e59 100644 --- a/backend/src/routes/logbooks-route.js +++ b/backend/src/routes/logbooks-route.js @@ -6,22 +6,38 @@ const router = express.Router(); router.post("", auth, async (req, res) => { const logbook = await createLogbook(req); - res.status(201).json({ data: logbook }); + if (logbook.error) { + res.status(500).json({ error: logbook.error }); + } else { + res.status(201).json({ data: logbook }); + } }); router.get("", auth, async (req, res) => { const userLogbooks = await getUserLogbooks(req); - res.status(200).json({ data: userLogbooks }); + if (userLogbooks.error) { + res.status(500).json({ error: userLogbooks.error }); + } else { + res.status(200).json({ data: userLogbooks }); + } }); router.get("/:logbookID", auth, async (req, res) => { const logbook = await getLogbook(req); - res.status(200).json({ data: logbook }); + if (logbook.error) { + res.status(500).json({ error: logbook.error }); + } else { + res.status(200).json({ data: logbook }); + } }); router.post("/:logbookID/logs", auth, async (req, res) => { const log = await createLog(req); - res.status(201).json({ data: log }); + if (log.error) { + res.status(500).json({ error: log.error }); + } else { + res.status(201).json({ data: log }); + } }); router.get("/:logbookID/logs", auth, async (req, res) => { diff --git a/backend/src/services/logbooks-service.js b/backend/src/services/logbooks-service.js index ecf9b1c2..34ff3e4f 100644 --- a/backend/src/services/logbooks-service.js +++ b/backend/src/services/logbooks-service.js @@ -1,234 +1,58 @@ +import getLogbookType from "../utils/get-logbook-type.js"; +import getTable from "../utils/get-table.js"; +import insertTable from "../utils/insert-table.js"; +import parseUserID from "../utils/parse-user-id.js"; + export async function createLogbook(req) { - try { - const supabase = req.supabase; - const { type } = req.body; - const { data, error } = await supabase.from("logbooks").insert({ type: type }).select(); - if (error) { - throw new Error(error.message); - } - return data[0]; - } catch (error) { - throw new Error(error.message); - } + const supabase = req.supabase; + const body = req.body + return insertTable(supabase, "logbooks", body); } export async function getUserLogbooks(req) { - try { - const supabase = req.supabase; - const token = req.header("Authorization")?.split(" ")[1]; - const userID = parseUserID(token); - const { data, error } = await supabase.from("logbooks").select().eq("user_id", userID); - if (error) { - throw new Error(error.message); - } - return data; - } catch (error) { - throw new Error(error.message); - } -} - -function parseUserID(token) { - const parts = token.split("."); - const decodedPayload = JSON.parse(atob(parts[1])); - const userID = decodedPayload["sub"]; - return userID; + const supabase = req.supabase; + const token = req.header("Authorization")?.split(" ")[1]; + const userID = parseUserID(token); + return getTable(supabase, "logbooks", "user_id", userID, "collection"); } export async function getLogbook(req) { - try { - const supabase = req.supabase; - const { logbookID } = req.params; - const { data, error } = await supabase.from("logbooks").select().eq("id", logbookID); - if (error) { - throw new Error(error.message); - } - return data[0]; - } catch (error) { - throw new Error(error.message); - } + const supabase = req.supabase; + const { logbookID } = req.params; + return getTable(supabase, "logbooks", "id", logbookID, "resource"); } export async function createLog(req) { try { const supabase = req.supabase; const { logbookID } = req.params; - const { type } = req.body; + let body = req.body + body['logbook_id'] = logbookID const logbookType = await getLogbookType(logbookID, supabase); - if (type !== logbookType) { - throw new Error("Error: Log does not match logbook type"); + if (body['type'] !== logbookType) { + throw new Error(`log type '${body['type']}' does not match logbook type '${logbookType}'`); } - let data; - switch (type) { + switch (body['type']) { case "adult_cardiac_logs": - data = createAdultCardiacLog(req, supabase); - break; + return insertTable(supabase, "adult_cardiac_logs", body) default: - break; + throw new Error(`log and logbook type '${type}' are invalid`); } - return data; } catch (error) { - throw new Error(error.message); - } -} - -async function createAdultCardiacLog(req, supabase) { - const { logbookID } = req.params; - const { - type, - caseNo, - paitentID, - surgeon, - age, - gender, - orDate, - reason, - hpi, - socialEtOH, - socialDrugs, - socialSmoking, - socialMeds, - socialAllergies, - phmxHTN, - phmxDMII, - phmxDLP, - phmxCVA, - examWeight, - examHeight, - examBMI, - examVeins, - examAllenTest, - examPulsesSixtyTwo, - examPulsesSixtyFive, - examPulsesSixtyEight, - examPulsesSeventy, - cathLink, - invxEchoEF, - invxEchoRVFx, - invxWMA, - invxAorta, - invxValves, - invxCXR, - invxHb, - invxW, - invxPit, - invxCr, - ctLink, - surgicalPlan, - surgicalPlanFirstOperator, - surgicalPlanIssueOR, - surgicalPlanIssuePost, - surgicalPlanaFlagForFU, - operativeNotesCPBh, - operativeNotesCPBm, - operativeNotesXCh, - operativeNotesXCm, - operativeNotesCAh, - operativeNotesCAm, - myRole, - postOperativeCourse, - learningPointsKeyLessons, - } = req.body; - const { data, error } = await supabase - .from("adult_cardiac_logs") - .insert({ - logbook_id: logbookID, - type: type, - case_no: caseNo, - paitent_id: paitentID, - surgeon: surgeon, - age: age, - gender: gender, - or_date: orDate, - reason: reason, - hpi: hpi, - social_etoh: socialEtOH, - social_drugs: socialDrugs, - social_smoking: socialSmoking, - social_meds: socialMeds, - social_allergies: socialAllergies, - pmhx_htn: phmxHTN, - pmhx_dmii: phmxDMII, - pmhx_dlp: phmxDLP, - pmhx_cva: phmxCVA, - exam_weight: examWeight, - exam_height: examHeight, - exam_bmi: examBMI, - exam_veins: examVeins, - exam_allen_test: examAllenTest, - exam_pulses_sixtytwo: examPulsesSixtyTwo, - exam_pulses_sixtyfive: examPulsesSixtyFive, - exam_pulses_sixtyeight: examPulsesSixtyEight, - exam_pulses_seventy: examPulsesSeventy, - cath: cathLink, - invx_echo_ef: invxEchoEF, - invx_echo_rvfx: invxEchoRVFx, - invx_wma: invxWMA, - invx_aorta: invxAorta, - invx_valves: invxValves, - invx_cxr: invxCXR, - invx_hb: invxHb, - invx_w: invxW, - invx_pit: invxPit, - invx_cr: invxCr, - ct: ctLink, - surgical_plan: surgicalPlan, - surgical_plan_first_operator: surgicalPlanFirstOperator, - surgical_plan_issue_or: surgicalPlanIssueOR, - surgical_plan_issue_post: surgicalPlanIssuePost, - surgical_plan_flag_for_fu: surgicalPlanaFlagForFU, - operative_notes_cpb_h: operativeNotesCPBh, - operative_notes_cpb_m: operativeNotesCPBm, - operative_notes_xc_h: operativeNotesXCh, - operative_notes_xc_m: operativeNotesXCm, - operative_notes_ca_h: operativeNotesCAh, - operative_notes_ca_m: operativeNotesCAm, - my_role: myRole, - post_operative_course: postOperativeCourse, - learning_points_key_lessons: learningPointsKeyLessons, - }) - .select(); - if (error) { - throw new Error(error.message); - } - return data[0]; -} - -async function getLogbookType(logbookID, supabase) { - const { data, error } = await supabase.from("logbooks").select().eq("id", logbookID); - if (error) { - throw new Error(error.message); + return { error: error.message }; } - return data[0]["type"]; } export async function getLogbookLogs(req) { - try { - const supabase = req.supabase; - const { logbookID } = req.params; - const logbookType = await getLogbookType(logbookID, supabase); - const { data, error } = await supabase.from(logbookType).select(); - if (error) { - throw new Error(error.message); - } - return data; - } catch (error) { - console.error(error.message); - return {error: error.message} - } + const supabase = req.supabase; + const { logbookID } = req.params; + const logbookType = await getLogbookType(logbookID, supabase); + return getTable(supabase, logbookType, "logbook_id", logbookID, "collection"); } export async function getLog(req) { - try { - const supabase = req.supabase; - const { logbookID, logID } = req.params; - const logbookType = await getLogbookType(logbookID, supabase); - const { data, error } = await supabase.from(logbookType).select().eq("id", logID); - if (error) { - throw new Error(error.message); - } - return data[0]; - } catch (error) { - console.error(error.message); - return {error: error.message} - } -} + const supabase = req.supabase; + const { logbookID, logID } = req.params; + const logbookType = await getLogbookType(logbookID, supabase); + return getTable(supabase, logbookType, "id", logID, "resource"); +} \ No newline at end of file diff --git a/backend/src/utils/get-logbook-type.js b/backend/src/utils/get-logbook-type.js new file mode 100644 index 00000000..dc35e52d --- /dev/null +++ b/backend/src/utils/get-logbook-type.js @@ -0,0 +1,11 @@ +export default async function getLogbookType(logbookID, supabase) { + try { + const { data, error } = await supabase.from("logbooks").select().eq("id", logbookID); + if (error) { + throw new Error(error.message); + } + return data[0]['type']; + } catch (error) { + return { error: error.message }; + } +} \ No newline at end of file diff --git a/backend/src/utils/get-table.js b/backend/src/utils/get-table.js new file mode 100644 index 00000000..7e847b1f --- /dev/null +++ b/backend/src/utils/get-table.js @@ -0,0 +1,18 @@ +export default async function getTable(supabase, table, param, value, type) { + try { + let data, error; + if (param == null && value == null) { + ({ data, error } = await supabase.from(table).select()); + } else if (param !== null && value !== null) { + ({ data, error } = await supabase.from(table).select().eq(param, value)); + } else { + throw new Error(`${param == null ? "param" : "value"} is empty at getTable`); + } + if (error) { + throw new Error(error.message); + } + return type === "collection" ? data : data[0]; + } catch (error) { + return { error: error.message }; + } +} \ No newline at end of file diff --git a/backend/src/utils/insert-table.js b/backend/src/utils/insert-table.js new file mode 100644 index 00000000..796f3929 --- /dev/null +++ b/backend/src/utils/insert-table.js @@ -0,0 +1,12 @@ +export default async function insertTable(supabase, table, values) { + try { + const { data, error } = await supabase.from(table).insert(values).select(); + if (error) { + throw new Error(error.message); + } else { + return data[0]; + } + } catch (error) { + return { error: error.message }; + } +} \ No newline at end of file diff --git a/backend/src/utils/parse-user-id.js b/backend/src/utils/parse-user-id.js new file mode 100644 index 00000000..50012650 --- /dev/null +++ b/backend/src/utils/parse-user-id.js @@ -0,0 +1,9 @@ +export default function parseUserID(token) { + try { + const parts = token.split("."); + const decodedPayload = JSON.parse(atob(parts[1])); + return decodedPayload["sub"]; + } catch (error) { + return { error: error.message }; + } +} \ No newline at end of file From 8e5b3a469f653074a131a2d880e359beb2a4929c Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Thu, 28 Nov 2024 16:19:22 -0800 Subject: [PATCH 11/16] fixed linting --- backend/src/services/logbooks-service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/services/logbooks-service.js b/backend/src/services/logbooks-service.js index 34ff3e4f..3acd2001 100644 --- a/backend/src/services/logbooks-service.js +++ b/backend/src/services/logbooks-service.js @@ -36,7 +36,7 @@ export async function createLog(req) { case "adult_cardiac_logs": return insertTable(supabase, "adult_cardiac_logs", body) default: - throw new Error(`log and logbook type '${type}' are invalid`); + throw new Error(`log and logbook type '${body['type']}' are invalid`); } } catch (error) { return { error: error.message }; From 53d829b07960e6beba31f7954cb1e735271951ed Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Thu, 28 Nov 2024 16:45:49 -0800 Subject: [PATCH 12/16] removed console.log in auth --- backend/src/middlewares/auth.js | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/middlewares/auth.js b/backend/src/middlewares/auth.js index 90cccfb9..b8d71ea2 100644 --- a/backend/src/middlewares/auth.js +++ b/backend/src/middlewares/auth.js @@ -4,7 +4,6 @@ import { createClient } from "@supabase/supabase-js"; const auth = async (req, res, next) => { try { const token = req.header("Authorization")?.split(" ")[1]; - console.log(token) const supabaseSecret = process.env.SUPABASE_JWT_SECRET; if (token) { jwt.verify(token, supabaseSecret); From 30c8a74b04cb1e0893327278c30d3068c3194207 Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Thu, 28 Nov 2024 16:57:09 -0800 Subject: [PATCH 13/16] minor change to get-table --- backend/src/utils/get-table.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/src/utils/get-table.js b/backend/src/utils/get-table.js index 7e847b1f..4371cb90 100644 --- a/backend/src/utils/get-table.js +++ b/backend/src/utils/get-table.js @@ -11,7 +11,11 @@ export default async function getTable(supabase, table, param, value, type) { if (error) { throw new Error(error.message); } - return type === "collection" ? data : data[0]; + if (type === "collection") { + return data + } else if (type === "resource") { + return data[0] + } } catch (error) { return { error: error.message }; } From 5986f0445e4ebecd07005f2647e112c2615031c1 Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Tue, 3 Dec 2024 18:48:02 -0800 Subject: [PATCH 14/16] pr fixes --- backend/src/services/logbooks-service.js | 90 +++++++++++++++++------- backend/src/utils/get-logbook-type.js | 6 +- 2 files changed, 69 insertions(+), 27 deletions(-) diff --git a/backend/src/services/logbooks-service.js b/backend/src/services/logbooks-service.js index 3acd2001..22221eae 100644 --- a/backend/src/services/logbooks-service.js +++ b/backend/src/services/logbooks-service.js @@ -5,38 +5,59 @@ import parseUserID from "../utils/parse-user-id.js"; export async function createLogbook(req) { const supabase = req.supabase; - const body = req.body - return insertTable(supabase, "logbooks", body); + const body = req.body; + const logbook = await insertTable(supabase, "logbooks", body); + return logbook; } export async function getUserLogbooks(req) { - const supabase = req.supabase; - const token = req.header("Authorization")?.split(" ")[1]; - const userID = parseUserID(token); - return getTable(supabase, "logbooks", "user_id", userID, "collection"); + try { + const supabase = req.supabase; + const token = req.header("Authorization")?.split(" ")[1]; + const userID = parseUserID(token); + if (userID.error) { + throw new Error(userID.error.message) + } + const userLogbooks = await getTable(supabase, "logbooks", "user_id", userID, "collection"); + return userLogbooks; + } catch (error) { + return { error: error.message }; + } } export async function getLogbook(req) { - const supabase = req.supabase; - const { logbookID } = req.params; - return getTable(supabase, "logbooks", "id", logbookID, "resource"); + try { + const supabase = req.supabase; + const { logbookID } = req.params; + const logbook = await getTable(supabase, "logbooks", "id", logbookID, "resource"); + if (typeof logbook == "undefined") { + throw new Error(`logbook ${logbookID} does not exist`); + } + return logbook; + } catch (error) { + return { error: error.message }; + } } export async function createLog(req) { try { const supabase = req.supabase; const { logbookID } = req.params; - let body = req.body - body['logbook_id'] = logbookID + let body = req.body; + body["logbook_id"] = logbookID; const logbookType = await getLogbookType(logbookID, supabase); - if (body['type'] !== logbookType) { - throw new Error(`log type '${body['type']}' does not match logbook type '${logbookType}'`); + if (logbookType.error) { + throw new Error(logbookType.error.message); + } + if (body["type"] !== logbookType) { + throw new Error(`log type '${body["type"]}' does not match logbook type '${logbookType}'`); } - switch (body['type']) { + switch (body["type"]) { case "adult_cardiac_logs": - return insertTable(supabase, "adult_cardiac_logs", body) + const log = await insertTable(supabase, "adult_cardiac_logs", body); + return log; default: - throw new Error(`log and logbook type '${body['type']}' are invalid`); + throw new Error(`log and logbook type '${body["type"]}' are invalid`); } } catch (error) { return { error: error.message }; @@ -44,15 +65,34 @@ export async function createLog(req) { } export async function getLogbookLogs(req) { - const supabase = req.supabase; - const { logbookID } = req.params; - const logbookType = await getLogbookType(logbookID, supabase); - return getTable(supabase, logbookType, "logbook_id", logbookID, "collection"); + try { + const supabase = req.supabase; + const { logbookID } = req.params; + const logbookType = await getLogbookType(logbookID, supabase); + if (logbookType.error) { + throw new Error(logbookType.error.message); + } + const logbookLogs = await getTable(supabase, logbookType, "logbook_id", logbookID, "collection"); + return logbookLogs; + } catch (error) { + return { error: error.message }; + } } export async function getLog(req) { - const supabase = req.supabase; - const { logbookID, logID } = req.params; - const logbookType = await getLogbookType(logbookID, supabase); - return getTable(supabase, logbookType, "id", logID, "resource"); -} \ No newline at end of file + try { + const supabase = req.supabase; + const { logbookID, logID } = req.params; + const logbookType = await getLogbookType(logbookID, supabase); + if (logbookType.error) { + throw new Error(logbookType.error.message); + } + const log = await getTable(supabase, logbookType, "id", logID, "resource"); + if (typeof log == "undefined") { + throw new Error(`log ${logID} does not exist`); + } + return log; + } catch (error) { + return { error: error.message }; + } +} diff --git a/backend/src/utils/get-logbook-type.js b/backend/src/utils/get-logbook-type.js index dc35e52d..b43a7d25 100644 --- a/backend/src/utils/get-logbook-type.js +++ b/backend/src/utils/get-logbook-type.js @@ -1,10 +1,12 @@ export default async function getLogbookType(logbookID, supabase) { try { const { data, error } = await supabase.from("logbooks").select().eq("id", logbookID); - if (error) { + if (data.length == 0 && typeof error == "undefined") { + throw new Error(`logbook ${logbookID} does not exist`); + } else if (error) { throw new Error(error.message); } - return data[0]['type']; + return data[0]["type"]; } catch (error) { return { error: error.message }; } From aaeb5ee53cf33125d65a2d94537b646f2395559c Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Tue, 3 Dec 2024 18:53:38 -0800 Subject: [PATCH 15/16] fixed linting & changed file name to match naming convention --- .../routes/{transcriptionRoutes.js => transcription-route.js} | 0 backend/src/services/logbooks-service.js | 3 +-- 2 files changed, 1 insertion(+), 2 deletions(-) rename backend/src/routes/{transcriptionRoutes.js => transcription-route.js} (100%) diff --git a/backend/src/routes/transcriptionRoutes.js b/backend/src/routes/transcription-route.js similarity index 100% rename from backend/src/routes/transcriptionRoutes.js rename to backend/src/routes/transcription-route.js diff --git a/backend/src/services/logbooks-service.js b/backend/src/services/logbooks-service.js index 22221eae..abab688d 100644 --- a/backend/src/services/logbooks-service.js +++ b/backend/src/services/logbooks-service.js @@ -54,8 +54,7 @@ export async function createLog(req) { } switch (body["type"]) { case "adult_cardiac_logs": - const log = await insertTable(supabase, "adult_cardiac_logs", body); - return log; + return await insertTable(supabase, "adult_cardiac_logs", body); default: throw new Error(`log and logbook type '${body["type"]}' are invalid`); } From cbdbfde503c93664186c18937cd77ec9156d6a58 Mon Sep 17 00:00:00 2001 From: Rafael Park Date: Tue, 3 Dec 2024 19:27:14 -0800 Subject: [PATCH 16/16] minor bug fixes --- backend/index.js | 8 +++---- backend/package-lock.json | 28 ++++++++++++------------ backend/package.json | 1 + backend/src/services/logbooks-service.js | 8 +++---- backend/src/utils/get-logbook-type.js | 2 +- 5 files changed, 24 insertions(+), 23 deletions(-) diff --git a/backend/index.js b/backend/index.js index 0284af06..673ef126 100644 --- a/backend/index.js +++ b/backend/index.js @@ -1,9 +1,9 @@ import cors from "cors"; import dotenv from "dotenv"; import express from "express"; -import authRoutes from "./src/routes/authRoutes.js"; -import logRoutes from "./src/routes/logRoutes.js"; -import transcriptionRoutes from "./src/routes/transcriptionRoutes.js"; +import authRoutes from "./src/routes/auth-route.js"; +import logbookRoutes from "./src/routes/logbooks-route.js"; +import transcriptionRoutes from "./src/routes/transcription-route.js"; import fileUpload from "express-fileupload"; dotenv.config(); @@ -20,7 +20,7 @@ app.use(fileUpload()); //Routes app.use("/api/auth", authRoutes); -app.use("/api/log", logRoutes); +app.use("/api/logbooks", logbookRoutes); app.use("/api/transcriptions", transcriptionRoutes); app.listen(PORT, () => { diff --git a/backend/package-lock.json b/backend/package-lock.json index 6f56cc3a..e3630110 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -15,6 +15,7 @@ "dotenv": "^16.4.5", "express": "^4.21.0", "express-fileupload": "^1.5.1", + "form-data": "^4.0.1", "jsonwebtoken": "^9.0.2", "supabase": "^1.207.9" }, @@ -3026,20 +3027,6 @@ "proxy-from-env": "^1.1.0" } }, - "node_modules/axios/node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -4475,6 +4462,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", diff --git a/backend/package.json b/backend/package.json index 670f2542..9077ec29 100644 --- a/backend/package.json +++ b/backend/package.json @@ -20,6 +20,7 @@ "dotenv": "^16.4.5", "express": "^4.21.0", "express-fileupload": "^1.5.1", + "form-data": "^4.0.1", "jsonwebtoken": "^9.0.2", "supabase": "^1.207.9" }, diff --git a/backend/src/services/logbooks-service.js b/backend/src/services/logbooks-service.js index abab688d..6f30499e 100644 --- a/backend/src/services/logbooks-service.js +++ b/backend/src/services/logbooks-service.js @@ -16,7 +16,7 @@ export async function getUserLogbooks(req) { const token = req.header("Authorization")?.split(" ")[1]; const userID = parseUserID(token); if (userID.error) { - throw new Error(userID.error.message) + throw new Error(userID.error) } const userLogbooks = await getTable(supabase, "logbooks", "user_id", userID, "collection"); return userLogbooks; @@ -47,7 +47,7 @@ export async function createLog(req) { body["logbook_id"] = logbookID; const logbookType = await getLogbookType(logbookID, supabase); if (logbookType.error) { - throw new Error(logbookType.error.message); + throw new Error(logbookType.error); } if (body["type"] !== logbookType) { throw new Error(`log type '${body["type"]}' does not match logbook type '${logbookType}'`); @@ -69,7 +69,7 @@ export async function getLogbookLogs(req) { const { logbookID } = req.params; const logbookType = await getLogbookType(logbookID, supabase); if (logbookType.error) { - throw new Error(logbookType.error.message); + throw new Error(logbookType.error); } const logbookLogs = await getTable(supabase, logbookType, "logbook_id", logbookID, "collection"); return logbookLogs; @@ -84,7 +84,7 @@ export async function getLog(req) { const { logbookID, logID } = req.params; const logbookType = await getLogbookType(logbookID, supabase); if (logbookType.error) { - throw new Error(logbookType.error.message); + throw new Error(logbookType.error); } const log = await getTable(supabase, logbookType, "id", logID, "resource"); if (typeof log == "undefined") { diff --git a/backend/src/utils/get-logbook-type.js b/backend/src/utils/get-logbook-type.js index b43a7d25..a402b79a 100644 --- a/backend/src/utils/get-logbook-type.js +++ b/backend/src/utils/get-logbook-type.js @@ -1,7 +1,7 @@ export default async function getLogbookType(logbookID, supabase) { try { const { data, error } = await supabase.from("logbooks").select().eq("id", logbookID); - if (data.length == 0 && typeof error == "undefined") { + if (data.length == 0) { throw new Error(`logbook ${logbookID} does not exist`); } else if (error) { throw new Error(error.message);