From 01d137efcfa0958863d836c3eb7a804177dc36ef Mon Sep 17 00:00:00 2001 From: Alex Mickelson Date: Tue, 22 Jul 2025 10:05:55 -0600 Subject: [PATCH] moving to a global config --- build.sh | 4 +- docker-compose.dev.yml | 1 + globalSettings.yml | 3 ++ src/app/api/trpc/[trpc]/route.ts | 2 - src/models/local/globalSettings.ts | 14 +++++++ src/models/local/globalSettingsUtils.ts | 17 ++++++++ .../tests/globalSettingsMarkdown.test.ts | 26 +++++++++++++ .../assignmentsFileStorageService.ts | 22 ++++++----- .../courseItemFileStorageService.ts | 27 +++++++------ .../fileStorage/fileStorageService.ts | 3 +- .../globalSettingsFileStorageService.ts | 36 +++++++++++++++++ .../fileStorage/lectureFileStorageService.ts | 11 ++++-- .../fileStorage/moduleFileStorageService.ts | 6 +-- .../fileStorage/pageFileStorageService.ts | 12 +++--- .../fileStorage/quizFileStorageService.ts | 12 +++--- .../fileStorage/settingsFileStorageService.ts | 27 +++++++------ .../fileStorage/utils/fileSystemUtils.ts | 39 +++---------------- src/services/tests/fileStorage.test.ts | 12 ++++-- .../tests/fileStorageParsingErrors.test.ts | 3 ++ src/services/utils/queryClient.tsx | 12 +++++- 20 files changed, 190 insertions(+), 99 deletions(-) create mode 100644 globalSettings.yml create mode 100644 src/models/local/globalSettings.ts create mode 100644 src/models/local/globalSettingsUtils.ts create mode 100644 src/models/local/tests/globalSettingsMarkdown.test.ts create mode 100644 src/services/fileStorage/globalSettingsFileStorageService.ts diff --git a/build.sh b/build.sh index 892b14b..9133ba3 100755 --- a/build.sh +++ b/build.sh @@ -1,7 +1,7 @@ #!/bin/bash -MAJOR_VERSION="2" -MINOR_VERSION="8" +MAJOR_VERSION="3" +MINOR_VERSION="0" VERSION="$MAJOR_VERSION.$MINOR_VERSION" TAG_FLAG=false diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index f8e4ee1..9dd7e60 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -15,6 +15,7 @@ services: - NEXT_PUBLIC_ENABLE_FILE_SYNC=true - REDIS_URL=redis://redis:6379 volumes: + - ./globalSettings.yml:/app/globalSettings.yml - .:/app - ~/projects/faculty/1810/2025-spring-alex/in-person:/app/storage/intro_to_web_old - ~/projects/faculty/1810/2025-fall-alex/modules:/app/storage/intro_to_web diff --git a/globalSettings.yml b/globalSettings.yml new file mode 100644 index 0000000..dd2a690 --- /dev/null +++ b/globalSettings.yml @@ -0,0 +1,3 @@ +courses: + - path: "./intro_to_web_old" + name: "Intro to Web (Old)" diff --git a/src/app/api/trpc/[trpc]/route.ts b/src/app/api/trpc/[trpc]/route.ts index 452eccf..84c8004 100644 --- a/src/app/api/trpc/[trpc]/route.ts +++ b/src/app/api/trpc/[trpc]/route.ts @@ -3,8 +3,6 @@ import { trpcAppRouter } from "@/services/serverFunctions/router/app"; import { fetchRequestHandler } from "@trpc/server/adapters/fetch"; const handler = async (request: Request) => { - - // await new Promise(r => setTimeout(r, 1000)); // delay for testing return fetchRequestHandler({ endpoint: "/api/trpc", req: request, diff --git a/src/models/local/globalSettings.ts b/src/models/local/globalSettings.ts new file mode 100644 index 0000000..f8f7e2b --- /dev/null +++ b/src/models/local/globalSettings.ts @@ -0,0 +1,14 @@ +import z from "zod"; + +export const zodGlobalSettingsCourse = z.object({ + path: z.string(), + name: z.string(), +}); + +export const zodGlobalSettings = z.object({ + courses: z.array(zodGlobalSettingsCourse), +}); + + +export type GlobalSettings = z.infer; +export type GlobalSettingsCourse = z.infer; \ No newline at end of file diff --git a/src/models/local/globalSettingsUtils.ts b/src/models/local/globalSettingsUtils.ts new file mode 100644 index 0000000..7474bfd --- /dev/null +++ b/src/models/local/globalSettingsUtils.ts @@ -0,0 +1,17 @@ +import { GlobalSettings, zodGlobalSettings } from "./globalSettings"; +import { parse, stringify } from "yaml"; + +export const globalSettingsToYaml = (settings: GlobalSettings) => { + return stringify(settings); +}; + +export const parseGlobalSettingsYaml = (yaml: string): GlobalSettings => { + const parsed = parse(yaml); + try { + return zodGlobalSettings.parse(parsed); + } catch (e) { + console.error("Error parsing global settings YAML:", e); + throw new Error(`Error parsing global settings, got ${yaml}, ${e}`); + } +}; + diff --git a/src/models/local/tests/globalSettingsMarkdown.test.ts b/src/models/local/tests/globalSettingsMarkdown.test.ts new file mode 100644 index 0000000..e75ec7b --- /dev/null +++ b/src/models/local/tests/globalSettingsMarkdown.test.ts @@ -0,0 +1,26 @@ +import { describe, it, expect } from "vitest"; +import { GlobalSettings } from "../globalSettings"; +import { + globalSettingsToYaml, + parseGlobalSettingsYaml, +} from "../globalSettingsUtils"; + +describe("GlobalSettingsMarkdownTests", () => { + it("can parse global settings", () => { + const globalSettings: GlobalSettings = { + courses: [ + { + path: "./distributed/2025-alex/modules", + name: "distributed", + }, + ], + }; + + const globalSettingsMarkdown = globalSettingsToYaml(globalSettings); + const parsedGlobalSettings = parseGlobalSettingsYaml( + globalSettingsMarkdown + ); + + expect(parsedGlobalSettings).toEqual(globalSettings); + }); +}); diff --git a/src/services/fileStorage/assignmentsFileStorageService.ts b/src/services/fileStorage/assignmentsFileStorageService.ts index afc3d0c..7ab6830 100644 --- a/src/services/fileStorage/assignmentsFileStorageService.ts +++ b/src/services/fileStorage/assignmentsFileStorageService.ts @@ -4,12 +4,14 @@ import { } from "@/models/local/assignment/localAssignment"; import { assignmentMarkdownSerializer } from "@/models/local/assignment/utils/assignmentMarkdownSerializer"; import path from "path"; -import { basePath, directoryOrFileExists } from "./utils/fileSystemUtils"; +import { directoryOrFileExists } from "./utils/fileSystemUtils"; import { promises as fs } from "fs"; import { courseItemFileStorageService } from "./courseItemFileStorageService"; +import { getCoursePathByName } from "./globalSettingsFileStorageService"; const getAssignmentNames = async (courseName: string, moduleName: string) => { - const filePath = path.join(basePath, courseName, moduleName, "assignments"); + const courseDirectory = await getCoursePathByName(courseName); + const filePath = path.join(courseDirectory, moduleName, "assignments"); if (!(await directoryOrFileExists(filePath))) { console.log( `Error loading course by name, assignments folder does not exist in ${filePath}` @@ -26,9 +28,9 @@ const getAssignment = async ( moduleName: string, assignmentName: string ) => { + const courseDirectory = await getCoursePathByName(courseName); const filePath = path.join( - basePath, - courseName, + courseDirectory, moduleName, "assignments", assignmentName + ".md" @@ -58,12 +60,12 @@ export const assignmentsFileStorageService = { assignmentName: string; assignment: LocalAssignment; }) { - const folder = path.join(basePath, courseName, moduleName, "assignments"); + const courseDirectory = await getCoursePathByName(courseName); + const folder = path.join(courseDirectory, moduleName, "assignments"); await fs.mkdir(folder, { recursive: true }); const filePath = path.join( - basePath, - courseName, + courseDirectory, moduleName, "assignments", assignmentName + ".md" @@ -75,7 +77,7 @@ export const assignmentsFileStorageService = { await fs.writeFile(filePath, assignmentMarkdown); }, - + async delete({ courseName, moduleName, @@ -85,9 +87,9 @@ export const assignmentsFileStorageService = { moduleName: string; assignmentName: string; }) { + const courseDirectory = await getCoursePathByName(courseName); const filePath = path.join( - basePath, - courseName, + courseDirectory, moduleName, "assignments", assignmentName + ".md" diff --git a/src/services/fileStorage/courseItemFileStorageService.ts b/src/services/fileStorage/courseItemFileStorageService.ts index ffb0353..7899be4 100644 --- a/src/services/fileStorage/courseItemFileStorageService.ts +++ b/src/services/fileStorage/courseItemFileStorageService.ts @@ -1,5 +1,5 @@ import path from "path"; -import { basePath, directoryOrFileExists } from "./utils/fileSystemUtils"; +import { directoryOrFileExists } from "./utils/fileSystemUtils"; import fs from "fs/promises"; import { LocalAssignment, @@ -20,14 +20,16 @@ import { CourseItemType, typeToFolder, } from "@/models/local/courseItemTypes"; +import { getCoursePathByName } from "./globalSettingsFileStorageService"; const getItemFileNames = async ( courseName: string, moduleName: string, type: CourseItemType ) => { + const courseDirectory = await getCoursePathByName(courseName); const folder = typeToFolder[type]; - const filePath = path.join(basePath, courseName, moduleName, folder); + const filePath = path.join(courseDirectory, moduleName, folder); if (!(await directoryOrFileExists(filePath))) { console.log( `Error loading ${type}, ${folder} folder does not exist in ${filePath}` @@ -45,14 +47,9 @@ const getItem = async ( name: string, type: T ): Promise> => { + const courseDirectory = await getCoursePathByName(courseName); const folder = typeToFolder[type]; - const filePath = path.join( - basePath, - courseName, - moduleName, - folder, - name + ".md" - ); + const filePath = path.join(courseDirectory, moduleName, folder, name + ".md"); const rawFile = (await fs.readFile(filePath, "utf-8")).replace(/\r\n/g, "\n"); if (type === "Assignment") { return localAssignmentMarkdown.parseMarkdown( @@ -61,11 +58,13 @@ const getItem = async ( ) as CourseItemReturnType; } else if (type === "Quiz") { return localQuizMarkdownUtils.parseMarkdown( - rawFile, name + rawFile, + name ) as CourseItemReturnType; } else if (type === "Page") { return localPageMarkdownUtils.parseMarkdown( - rawFile, name + rawFile, + name ) as CourseItemReturnType; } @@ -107,13 +106,13 @@ export const courseItemFileStorageService = { item: LocalAssignment | LocalQuiz | LocalCoursePage; type: CourseItemType; }) { + const courseDirectory = await getCoursePathByName(courseName); const typeFolder = typeToFolder[type]; - const folder = path.join(basePath, courseName, moduleName, typeFolder); + const folder = path.join(courseDirectory, moduleName, typeFolder); await fs.mkdir(folder, { recursive: true }); const filePath = path.join( - basePath, - courseName, + courseDirectory, moduleName, typeFolder, name + ".md" diff --git a/src/services/fileStorage/fileStorageService.ts b/src/services/fileStorage/fileStorageService.ts index e0d48dd..12516e7 100644 --- a/src/services/fileStorage/fileStorageService.ts +++ b/src/services/fileStorage/fileStorageService.ts @@ -6,6 +6,7 @@ import { quizFileStorageService } from "./quizFileStorageService"; import { pageFileStorageService } from "./pageFileStorageService"; import { moduleFileStorageService } from "./moduleFileStorageService"; import { settingsFileStorageService } from "./settingsFileStorageService"; +import { getCoursePathByName } from "./globalSettingsFileStorageService"; export const fileStorageService = { settings: settingsFileStorageService, @@ -42,7 +43,7 @@ export const fileStorageService = { }, async createCourseFolderForTesting(courseName: string) { - const courseDirectory = path.join(basePath, courseName); + const courseDirectory = await getCoursePathByName(courseName); await fs.mkdir(courseDirectory, { recursive: true }); }, diff --git a/src/services/fileStorage/globalSettingsFileStorageService.ts b/src/services/fileStorage/globalSettingsFileStorageService.ts new file mode 100644 index 0000000..369fddf --- /dev/null +++ b/src/services/fileStorage/globalSettingsFileStorageService.ts @@ -0,0 +1,36 @@ +import { GlobalSettings } from "@/models/local/globalSettings"; +import { parseGlobalSettingsYaml } from "@/models/local/globalSettingsUtils"; +import { promises as fs } from "fs"; +import path from "path"; +import { basePath } from "./utils/fileSystemUtils"; + +const SETTINGS_FILE_PATH = + process.env.SETTINGS_FILE_PATH || "./globalSettings.yml"; + +export const getGlobalSettings = async (): Promise => { + try { + await fs.access(SETTINGS_FILE_PATH); + } catch (err) { + throw new Error( + `Global Settings file does not exist at path: ${SETTINGS_FILE_PATH}` + ); + } + + const globalSettingsString = process.env.GLOBAL_SETTINGS + ? process.env.GLOBAL_SETTINGS + : await fs.readFile(SETTINGS_FILE_PATH, "utf-8"); + const globalSettings = parseGlobalSettingsYaml(globalSettingsString); + + return globalSettings; +}; + +export const getCoursePathByName = async (courseName: string) => { + const globalSettings = await getGlobalSettings(); + const course = globalSettings.courses.find((c) => c.name === courseName); + if (!course) { + throw new Error( + `Course with name ${courseName} not found in global settings` + ); + } + return path.join(basePath, course.path); +}; diff --git a/src/services/fileStorage/lectureFileStorageService.ts b/src/services/fileStorage/lectureFileStorageService.ts index 45aea98..fe25f27 100644 --- a/src/services/fileStorage/lectureFileStorageService.ts +++ b/src/services/fileStorage/lectureFileStorageService.ts @@ -1,6 +1,5 @@ import path from "path"; -import { basePath } from "./utils/fileSystemUtils"; import fs from "fs/promises"; import { getLectureWeekName, @@ -14,9 +13,11 @@ import { LocalCourseSettings, } from "@/models/local/localCourseSettings"; import { getDateFromStringOrThrow } from "@/models/local/utils/timeUtils"; +import { getCoursePathByName } from "./globalSettingsFileStorageService"; export async function getLectures(courseName: string) { - const courseLectureRoot = path.join(basePath, courseName, lectureFolderName); + const courseDirectory = await getCoursePathByName(courseName); + const courseLectureRoot = path.join(courseDirectory, lectureFolderName); if (!(await directoryExists(courseLectureRoot))) { return []; } @@ -53,7 +54,8 @@ export async function updateLecture( courseSettings: LocalCourseSettings, lecture: Lecture ) { - const courseLectureRoot = path.join(basePath, courseName, lectureFolderName); + const courseDirectory = await getCoursePathByName(courseName); + const courseLectureRoot = path.join(courseDirectory, lectureFolderName); const lectureDate = getDateFromStringOrThrow( lecture.date, "lecture start date in update lecture" @@ -92,7 +94,8 @@ export async function deleteLecture( dayAsString ); - const courseLectureRoot = path.join(basePath, courseName, lectureFolderName); + const courseDirectory = await getCoursePathByName(courseName); + const courseLectureRoot = path.join(courseDirectory, lectureFolderName); const weekPath = path.join(courseLectureRoot, weekFolderName); const lecturePath = path.join( weekPath, diff --git a/src/services/fileStorage/moduleFileStorageService.ts b/src/services/fileStorage/moduleFileStorageService.ts index ba6dc8a..060c6f9 100644 --- a/src/services/fileStorage/moduleFileStorageService.ts +++ b/src/services/fileStorage/moduleFileStorageService.ts @@ -1,11 +1,11 @@ import { promises as fs } from "fs"; import path from "path"; -import { basePath } from "./utils/fileSystemUtils"; import { lectureFolderName } from "./utils/lectureUtils"; +import { getCoursePathByName } from "./globalSettingsFileStorageService"; export const moduleFileStorageService = { async getModuleNames(courseName: string) { - const courseDirectory = path.join(basePath, courseName); + const courseDirectory = await getCoursePathByName(courseName); const moduleDirectories = await fs.readdir(courseDirectory, { withFileTypes: true, }); @@ -21,7 +21,7 @@ export const moduleFileStorageService = { return modulesWithoutLectures.sort((a, b) => a.localeCompare(b)); }, async createModule(courseName: string, moduleName: string) { - const courseDirectory = path.join(basePath, courseName); + const courseDirectory = await getCoursePathByName(courseName); await fs.mkdir(courseDirectory + "/" + moduleName, { recursive: true }); }, diff --git a/src/services/fileStorage/pageFileStorageService.ts b/src/services/fileStorage/pageFileStorageService.ts index 645839a..c955833 100644 --- a/src/services/fileStorage/pageFileStorageService.ts +++ b/src/services/fileStorage/pageFileStorageService.ts @@ -4,8 +4,8 @@ import { } from "@/models/local/page/localCoursePage"; import { promises as fs } from "fs"; import path from "path"; -import { basePath } from "./utils/fileSystemUtils"; import { courseItemFileStorageService } from "./courseItemFileStorageService"; +import { getCoursePathByName } from "./globalSettingsFileStorageService"; export const pageFileStorageService = { getPage: async (courseName: string, moduleName: string, name: string) => @@ -29,12 +29,12 @@ export const pageFileStorageService = { pageName: string; page: LocalCoursePage; }) { - const folder = path.join(basePath, courseName, moduleName, "pages"); + const courseDirectory = await getCoursePathByName(courseName); + const folder = path.join(courseDirectory, moduleName, "pages"); await fs.mkdir(folder, { recursive: true }); const filePath = path.join( - basePath, - courseName, + courseDirectory, moduleName, "pages", pageName + ".md" @@ -53,9 +53,9 @@ export const pageFileStorageService = { moduleName: string; pageName: string; }) { + const courseDirectory = await getCoursePathByName(courseName); const filePath = path.join( - basePath, - courseName, + courseDirectory, moduleName, "pages", pageName + ".md" diff --git a/src/services/fileStorage/quizFileStorageService.ts b/src/services/fileStorage/quizFileStorageService.ts index e371859..585d12c 100644 --- a/src/services/fileStorage/quizFileStorageService.ts +++ b/src/services/fileStorage/quizFileStorageService.ts @@ -1,9 +1,9 @@ import { LocalQuiz } from "@/models/local/quiz/localQuiz"; import { quizMarkdownUtils } from "@/models/local/quiz/utils/quizMarkdownUtils"; import path from "path"; -import { basePath } from "./utils/fileSystemUtils"; import { promises as fs } from "fs"; import { courseItemFileStorageService } from "./courseItemFileStorageService"; +import { getCoursePathByName } from "./globalSettingsFileStorageService"; export const quizFileStorageService = { getQuiz: async (courseName: string, moduleName: string, quizName: string) => @@ -27,11 +27,11 @@ export const quizFileStorageService = { quizName: string; quiz: LocalQuiz; }) { - const folder = path.join(basePath, courseName, moduleName, "quizzes"); + const courseDirectory = await getCoursePathByName(courseName); + const folder = path.join(courseDirectory, moduleName, "quizzes"); await fs.mkdir(folder, { recursive: true }); const filePath = path.join( - basePath, - courseName, + courseDirectory, moduleName, "quizzes", quizName + ".md" @@ -50,9 +50,9 @@ export const quizFileStorageService = { moduleName: string; quizName: string; }) { + const courseDirectory = await getCoursePathByName(courseName); const filePath = path.join( - basePath, - courseName, + courseDirectory, moduleName, "quizzes", quizName + ".md" diff --git a/src/services/fileStorage/settingsFileStorageService.ts b/src/services/fileStorage/settingsFileStorageService.ts index 5c2a4a2..410f369 100644 --- a/src/services/fileStorage/settingsFileStorageService.ts +++ b/src/services/fileStorage/settingsFileStorageService.ts @@ -4,20 +4,21 @@ import { } from "@/models/local/localCourseSettings"; import { promises as fs } from "fs"; import path from "path"; -import { - basePath, - directoryOrFileExists, - getCourseNames, -} from "./utils/fileSystemUtils"; +import { basePath, directoryOrFileExists } from "./utils/fileSystemUtils"; import { AssignmentSubmissionType } from "@/models/local/assignment/assignmentSubmissionType"; +import { + getCoursePathByName, + getGlobalSettings, +} from "./globalSettingsFileStorageService"; +import { GlobalSettingsCourse } from "@/models/local/globalSettings"; const getCourseSettings = async ( - courseName: string + course: GlobalSettingsCourse ): Promise => { - const courseDirectory = path.join(basePath, courseName); + const courseDirectory = await getCoursePathByName(course.name); const settingsPath = path.join(courseDirectory, "settings.yml"); if (!(await directoryOrFileExists(settingsPath))) { - const errorMessage = `could not find settings for ${courseName}, settings file ${settingsPath}`; + const errorMessage = `could not find settings for ${course.name}, settings file ${settingsPath}`; console.log(errorMessage); throw new Error(errorMessage); } @@ -29,8 +30,7 @@ const getCourseSettings = async ( const settings: LocalCourseSettings = populateDefaultValues(settingsFromFile); - const folderName = path.basename(courseDirectory); - return { ...settings, name: folderName }; + return { ...settings, name: course.name }; }; const populateDefaultValues = (settingsFromFile: LocalCourseSettings) => { @@ -60,7 +60,10 @@ const populateDefaultValues = (settingsFromFile: LocalCourseSettings) => { export const settingsFileStorageService = { getCourseSettings, async getAllCoursesSettings() { - const courses = await getCourseNames(); + const globalSettings = await getGlobalSettings(); + + // const courses = await getCourseNames(); + const courses = globalSettings.courses; const courseSettings = await Promise.all( courses.map(async (c) => await getCourseSettings(c)) @@ -72,7 +75,7 @@ export const settingsFileStorageService = { courseName: string, settings: LocalCourseSettings ) { - const courseDirectory = path.join(basePath, courseName); + const courseDirectory = await getCoursePathByName(courseName); const settingsPath = path.join(courseDirectory, "settings.yml"); const { name: _, ...settingsWithoutName } = settings; diff --git a/src/services/fileStorage/utils/fileSystemUtils.ts b/src/services/fileStorage/utils/fileSystemUtils.ts index cc025ae..6bac2f3 100644 --- a/src/services/fileStorage/utils/fileSystemUtils.ts +++ b/src/services/fileStorage/utils/fileSystemUtils.ts @@ -1,17 +1,10 @@ import { promises as fs } from "fs"; import path from "path"; +import { getGlobalSettings } from "../globalSettingsFileStorageService"; -export const hasFileSystemEntries = async ( +export const directoryOrFileExists = async ( directoryPath: string ): Promise => { - try { - const entries = await fs.readdir(directoryPath); - return entries.length > 0; - } catch { - return false; - } -}; -export const directoryOrFileExists = async (directoryPath: string): Promise => { try { await fs.access(directoryPath); return true; @@ -22,31 +15,9 @@ export const directoryOrFileExists = async (directoryPath: string): Promise dirent.isDirectory()) - .map(async (dirent) => { - const coursePath = path.join(basePath, dirent.name); - const settingsPath = path.join(coursePath, "settings.yml"); - const hasSettings = await directoryOrFileExists(settingsPath); - return { - dirent, - hasSettings, - }; - }) - ); - - const courseNamesFromDirectories = coursePromises - .filter(({ hasSettings }) => hasSettings) - .map(({ dirent }) => dirent.name); - - return courseNamesFromDirectories; + const globalSettings = await getGlobalSettings(); + return globalSettings.courses.map((course) => course.name); } - - export const basePath = process.env.STORAGE_DIRECTORY ?? "./storage"; -console.log("base path", basePath); \ No newline at end of file +console.log("base path", basePath); diff --git a/src/services/tests/fileStorage.test.ts b/src/services/tests/fileStorage.test.ts index 235a6c2..7e3da50 100644 --- a/src/services/tests/fileStorage.test.ts +++ b/src/services/tests/fileStorage.test.ts @@ -10,6 +10,9 @@ describe("FileStorageTests", () => { beforeEach(async () => { const storageDirectory = process.env.STORAGE_DIRECTORY ?? "/tmp/canvasManagerTests"; + process.env.GLOBAL_SETTINGS = `courses: + - path: test empty course + name: test empty course`; try { await fs.access(storageDirectory); await fs.rm(storageDirectory, { recursive: true }); @@ -31,14 +34,15 @@ describe("FileStorageTests", () => { defaultAssignmentSubmissionTypes: [], defaultFileUploadTypes: [], holidays: [], - assets: [] + assets: [], }; await fileStorageService.settings.updateCourseSettings(name, settings); - const loadedSettings = await fileStorageService.settings.getCourseSettings( - name - ); + const loadedSettings = await fileStorageService.settings.getCourseSettings({ + name, + path: name, + }); expect(loadedSettings).toEqual(settings); }); diff --git a/src/services/tests/fileStorageParsingErrors.test.ts b/src/services/tests/fileStorageParsingErrors.test.ts index 3ec76b1..246976b 100644 --- a/src/services/tests/fileStorageParsingErrors.test.ts +++ b/src/services/tests/fileStorageParsingErrors.test.ts @@ -7,6 +7,9 @@ describe("FileStorageTests", () => { beforeEach(async () => { const storageDirectory = process.env.STORAGE_DIRECTORY ?? "/tmp/canvasManagerTests"; + process.env.GLOBAL_SETTINGS = `courses: + - path: testCourse + name: testCourse`; try { await fs.access(storageDirectory); await fs.rm(storageDirectory, { recursive: true }); diff --git a/src/services/utils/queryClient.tsx b/src/services/utils/queryClient.tsx index eaf3858..d1a444b 100644 --- a/src/services/utils/queryClient.tsx +++ b/src/services/utils/queryClient.tsx @@ -1,5 +1,7 @@ import toast, { CheckmarkIcon } from "react-hot-toast"; import { ReactNode } from "react"; +import { getHTTPStatusCodeFromError } from "@trpc/server/http"; +import { TRPCError } from "@trpc/server"; // const addErrorAsToast = async (error: unknown) => { // console.error("error from toast", error); @@ -41,6 +43,12 @@ import { ReactNode } from "react"; // eslint-disable-next-line @typescript-eslint/no-explicit-any export function getErrorMessage(error: any) { + if (error instanceof TRPCError) { + const httpCode = getHTTPStatusCodeFromError(error); + console.log("trpc error", httpCode, error); // 400 + return `TRPC Error: ${error.message} (HTTP ${httpCode})`; + } + if (error?.response?.status === 422) { console.log(error.response.data.detail); const serializationMessages = error.response.data.detail.map( @@ -59,7 +67,9 @@ export function getErrorMessage(error: any) { return error.response?.data.detail; } else return JSON.stringify(error.response?.data.detail); } - console.log(error); + console.log("error message: ", error); + if(error.message ) + return error.message; return "Error With Request"; }