From a9e76ee3db22578410b803e20ba822f9419f2e95 Mon Sep 17 00:00:00 2001 From: masterelmar <18119527+masterElmar@users.noreply.github.com> Date: Wed, 27 Dec 2023 18:20:17 +0100 Subject: [PATCH 01/11] feat:#150 rewrote error handling for backend --- backend/service/db/dbEvents.go | 13 +++---------- backend/service/db/dbRooms.go | 28 +++++++++++---------------- backend/service/ical/ical.go | 7 ++++++- backend/service/room/roomService.go | 30 ++++++++++++++++++++++------- 4 files changed, 43 insertions(+), 35 deletions(-) diff --git a/backend/service/db/dbEvents.go b/backend/service/db/dbEvents.go index e301f00..5042c2d 100644 --- a/backend/service/db/dbEvents.go +++ b/backend/service/db/dbEvents.go @@ -151,7 +151,7 @@ func buildIcalQueryForModules(modules []model.FeedCollection) dbx.Expression { // GetPlanForModules returns all events for the given modules with the given course // used for the ical feed -func GetPlanForModules(app *pocketbase.PocketBase, modules map[string]model.FeedCollection) model.Events { +func GetPlanForModules(app *pocketbase.PocketBase, modules map[string]model.FeedCollection) (model.Events, error) { var events model.Events @@ -174,12 +174,11 @@ func GetPlanForModules(app *pocketbase.PocketBase, modules map[string]model.Feed // get all events from event records in the events collection err := app.Dao().DB().Select("*").From("events").Where(selectedModulesQuery).All(&events) if err != nil { - print("Error while getting events from database: ", err) - return nil + return nil, err } } - return events + return events, nil } func GetAllModulesForCourse(app *pocketbase.PocketBase, course string, semester string) (model.Events, error) { @@ -200,7 +199,6 @@ func GetAllModulesDistinctByNameAndCourse(app *pocketbase.PocketBase) (model.Eve err := app.Dao().DB().Select("*").From("events").GroupBy("Name").Distinct(true).All(&events) if err != nil { - print("Error while getting events from database: ", err) return nil, err } @@ -211,10 +209,8 @@ func DeleteAllEventsForCourse(app *pocketbase.PocketBase, course string, semeste _, err := app.Dao().DB().Delete("events", dbx.NewExp("course = {:course} AND semester = {:semester}", dbx.Params{"course": course, "semester": semester})).Execute() if err != nil { - print("Error while deleting events from database: ", err) return err } - return nil } @@ -234,7 +230,6 @@ func FindModuleByUUID(app *pocketbase.PocketBase, uuid string) (model.Module, er err := app.Dao().DB().Select("*").From("events").Where(dbx.NewExp("uuid = {:uuid}", dbx.Params{"uuid": uuid})).One(&module) if err != nil { - print("Error while getting events from database: ", err) return model.Module{}, err } @@ -246,7 +241,6 @@ func FindAllEventsByModule(app *pocketbase.PocketBase, module model.Module) (mod err := app.Dao().DB().Select("*").From("events").Where(dbx.NewExp("Name = {:moduleName} AND course = {:course}", dbx.Params{"moduleName": module.Name, "course": module.Course})).All(&events) if err != nil { - print("Error while getting events from database: ", err) return nil, err } @@ -258,7 +252,6 @@ func GetAllModulesByNameAndDateRange(app *pocketbase.PocketBase, name string, st err := app.Dao().DB().Select("*").From("events").Where(dbx.NewExp("Name = {:name} AND Start >= {:startDate} AND End <= {:endDate}", dbx.Params{"name": name, "startDate": startDate, "endDate": endDate})).All(&events) if err != nil { - print("Error while getting events from database: ", err) return nil, err } diff --git a/backend/service/db/dbRooms.go b/backend/service/db/dbRooms.go index 6d6aebe..be2ee41 100644 --- a/backend/service/db/dbRooms.go +++ b/backend/service/db/dbRooms.go @@ -1,7 +1,6 @@ package db import ( - "fmt" "htwkalender/model" "htwkalender/service/functions" "strings" @@ -11,7 +10,7 @@ import ( "github.com/pocketbase/pocketbase" ) -func GetRooms(app *pocketbase.PocketBase) []string { +func GetRooms(app *pocketbase.PocketBase) ([]string, error) { var events []struct { Rooms string `db:"Rooms" json:"Rooms"` @@ -20,8 +19,7 @@ func GetRooms(app *pocketbase.PocketBase) []string { // get all rooms from event records in the events collection err := app.Dao().DB().Select("Rooms").From("events").All(&events) if err != nil { - print("Error while getting rooms from database: ", err) - return nil + return nil, err } var roomArray []string @@ -38,10 +36,10 @@ func GetRooms(app *pocketbase.PocketBase) []string { } } } - return roomArray + return roomArray, nil } -func GetRoomScheduleForDay(app *pocketbase.PocketBase, room string, date string) []model.Event { +func GetRoomScheduleForDay(app *pocketbase.PocketBase, room string, date string) ([]model.Event, error) { var events []model.Event // get all events from event records in the events collection @@ -51,24 +49,21 @@ func GetRoomScheduleForDay(app *pocketbase.PocketBase, room string, date string) GroupBy("Week", "Start", "End", "Rooms"). All(&events) if err != nil { - print("Error while getting events from database: ", err) - return nil + return nil, err } - return events + return events, nil } -func GetRoomSchedule(app *pocketbase.PocketBase, room string, from string, to string) []model.Event { +func GetRoomSchedule(app *pocketbase.PocketBase, room string, from string, to string) ([]model.Event, error) { var events []model.Event fromDate, err := time.Parse("2006-01-02", from) if err != nil { - fmt.Println("Error parsing date 'from':", err) - return nil + return nil, err } toDate, err := time.Parse("2006-01-02", to) if err != nil { - fmt.Println("Error parsing date 'to':", err) - return nil + return nil, err } // get all events from event records in the events collection @@ -79,8 +74,7 @@ func GetRoomSchedule(app *pocketbase.PocketBase, room string, from string, to st All(&events) if err != nil { - print("Error while getting events from database: ", err) - return nil + return nil, err } - return events + return events, nil } diff --git a/backend/service/ical/ical.go b/backend/service/ical/ical.go index 4fa472b..ad788e6 100644 --- a/backend/service/ical/ical.go +++ b/backend/service/ical/ical.go @@ -48,7 +48,12 @@ func Feed(c echo.Context, app *pocketbase.PocketBase, token string) error { } func createFeedForToken(app *pocketbase.PocketBase, modules map[string]model.FeedCollection) (*model.FeedModel, error) { - res := db.GetPlanForModules(app, modules) + res, err := db.GetPlanForModules(app, modules) + + if err != nil { + return nil, apis.NewNotFoundError("Could not fetch events", err) + } + b := bytes.Buffer{} goics.NewICalEncode(&b).Encode(IcalModel{Events: res, Mapping: modules}) feed := &model.FeedModel{Content: b.String(), ExpiresAt: time.Now().Add(expirationTime)} diff --git a/backend/service/room/roomService.go b/backend/service/room/roomService.go index 320bfea..5fcc80b 100644 --- a/backend/service/room/roomService.go +++ b/backend/service/room/roomService.go @@ -10,23 +10,39 @@ import ( ) func GetRooms(c echo.Context, app *pocketbase.PocketBase) error { - rooms := db.GetRooms(app) - return c.JSON(http.StatusOK, rooms) + rooms, err := db.GetRooms(app) + + if err != nil { + return c.JSON(http.StatusNotFound, err) + } else { + return c.JSON(http.StatusOK, rooms) + } } func GetRoomScheduleForDay(c echo.Context, app *pocketbase.PocketBase, room string, date string) error { - events := db.GetRoomScheduleForDay(app, room, date) - return c.JSON(http.StatusOK, anonymizeRooms(events)) + + events, err := db.GetRoomScheduleForDay(app, room, date) + + if err != nil { + return c.JSON(http.StatusInternalServerError, err) + } else { + return c.JSON(http.StatusOK, anonymizeRooms(events)) + } } func GetRoomSchedule(c echo.Context, app *pocketbase.PocketBase, room string, from string, to string) error { - events := db.GetRoomSchedule(app, room, from, to) - return c.JSON(http.StatusOK, anonymizeRooms(events)) + events, err := db.GetRoomSchedule(app, room, from, to) + + if err != nil { + return c.JSON(http.StatusInternalServerError, err) + } else { + return c.JSON(http.StatusOK, anonymizeRooms(events)) + } } // Transform the events to anonymized events throwing away all unnecessary information func anonymizeRooms(events []model.Event) []model.AnonymizedEventDTO { - var anonymizedEvents = []model.AnonymizedEventDTO{} + var anonymizedEvents []model.AnonymizedEventDTO for _, event := range events { anonymizedEvents = append(anonymizedEvents, event.AnonymizeEvent()) } From 031fa717d7dbbc9e8fd7834dc1a0c04ac032384e Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Sun, 21 Jan 2024 17:53:49 +0100 Subject: [PATCH 02/11] feature:#150 added slog and changed signatures --- backend/service/addRoute.go | 9 ++- backend/service/addSchedule.go | 4 ++ backend/service/course/courseFunctions.go | 10 +-- backend/service/db/dbEvents.go | 9 ++- backend/service/events/eventService.go | 29 ++++---- .../fetch/v1/fetchSeminarEventService.go | 2 +- backend/service/fetch/v2/fetcher.go | 67 ++++++++++--------- backend/service/logger/logger.go | 1 + frontend/package-lock.json | 6 +- 9 files changed, 77 insertions(+), 60 deletions(-) create mode 100644 backend/service/logger/logger.go diff --git a/backend/service/addRoute.go b/backend/service/addRoute.go index 422021e..1202c87 100644 --- a/backend/service/addRoute.go +++ b/backend/service/addRoute.go @@ -9,6 +9,7 @@ import ( "htwkalender/service/ical" "htwkalender/service/room" "io" + "log/slog" "net/http" "github.com/labstack/echo/v5" @@ -24,7 +25,13 @@ func AddRoutes(app *pocketbase.PocketBase) { Method: http.MethodGet, Path: "/api/fetch/events", Handler: func(c echo.Context) error { - return v2.ParseEventsFromRemote(c, app) + savedEvents, err := v2.ParseEventsFromRemote(app) + if err != nil { + slog.Error("Failed to parse events from remote: %v", err) + return c.JSON(http.StatusInternalServerError, "Failed to parse events from remote") + } else { + return c.JSON(http.StatusOK, savedEvents) + } }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), diff --git a/backend/service/addSchedule.go b/backend/service/addSchedule.go index b1263c5..8f85500 100644 --- a/backend/service/addSchedule.go +++ b/backend/service/addSchedule.go @@ -8,6 +8,7 @@ import ( "htwkalender/service/feed" "htwkalender/service/fetch/sport" "htwkalender/service/functions/time" + "log/slog" ) func AddSchedules(app *pocketbase.PocketBase) { @@ -19,17 +20,20 @@ func AddSchedules(app *pocketbase.PocketBase) { // Every three hours update all courses (5 segments - minute, hour, day, month, weekday) "0 */3 * * *" // Every 10 minutes update all courses (5 segments - minute, hour, day, month, weekday) "*/10 * * * *" scheduler.MustAdd("updateCourse", "0 */3 * * *", func() { + slog.Info("Started updating courses schedule") course.UpdateCourse(app) }) // Every sunday at 3am clean all courses (5 segments - minute, hour, day, month, weekday) "0 3 * * 0" scheduler.MustAdd("cleanFeeds", "0 3 * * 0", func() { // clean feeds older than 6 months + slog.Info("Started cleaning feeds schedule") feed.ClearFeeds(app.Dao(), 6, time.RealClock{}) }) // Every sunday at 2am fetch all sport events (5 segments - minute, hour, day, month, weekday) "0 2 * * 0" scheduler.MustAdd("fetchEvents", "0 2 * * 0", func() { + slog.Info("Started fetching sport events schedule") sport.FetchAndUpdateSportEvents(app) }) diff --git a/backend/service/course/courseFunctions.go b/backend/service/course/courseFunctions.go index 0d24700..144bd26 100644 --- a/backend/service/course/courseFunctions.go +++ b/backend/service/course/courseFunctions.go @@ -3,18 +3,18 @@ package course import ( "github.com/pocketbase/pocketbase" "htwkalender/service/events" - "log" + "log/slog" + "strconv" ) func UpdateCourse(app *pocketbase.PocketBase) { courses := events.GetAllCourses(app) for _, course := range courses { - err := events.UpdateModulesForCourse(app, course) + savedEvents, err := events.UpdateModulesForCourse(app, course) if err != nil { - log.Println("Update Course: " + course + " failed") - log.Println(err) + slog.Warn("Update Course: "+course+" failed: ", err.Error()) } else { - log.Println("Update Course: " + course + " successful") + slog.Info("Updated Course: " + course + " with " + strconv.FormatInt(int64(len(savedEvents)), 10) + " events") } } } diff --git a/backend/service/db/dbEvents.go b/backend/service/db/dbEvents.go index 5042c2d..10124c4 100644 --- a/backend/service/db/dbEvents.go +++ b/backend/service/db/dbEvents.go @@ -1,7 +1,9 @@ package db import ( + "fmt" "htwkalender/model" + "log/slog" "time" "github.com/pocketbase/dbx" @@ -187,8 +189,8 @@ func GetAllModulesForCourse(app *pocketbase.PocketBase, course string, semester // get all events from event records in the events collection err := app.Dao().DB().Select("*").From("events").Where(dbx.NewExp("course = {:course} AND semester = {:semester}", dbx.Params{"course": course, "semester": semester})).GroupBy("Name").Distinct(true).All(&events) if err != nil { - print("Error while getting events from database: ", err) - return nil, err + slog.Error("Error while getting events from database: ", err) + return nil, fmt.Errorf("error while getting events from database for course %s and semester %s", course, semester) } return events, nil @@ -199,7 +201,8 @@ func GetAllModulesDistinctByNameAndCourse(app *pocketbase.PocketBase) (model.Eve err := app.Dao().DB().Select("*").From("events").GroupBy("Name").Distinct(true).All(&events) if err != nil { - return nil, err + slog.Error("Error while getting events from database: ", err) + return nil, fmt.Errorf("error while getting events distinct by name and course from data") } return events, nil diff --git a/backend/service/events/eventService.go b/backend/service/events/eventService.go index d6dc97b..86eb613 100644 --- a/backend/service/events/eventService.go +++ b/backend/service/events/eventService.go @@ -3,7 +3,6 @@ package events import ( "github.com/labstack/echo/v5" "github.com/pocketbase/pocketbase" - "github.com/pocketbase/pocketbase/apis" "htwkalender/model" "htwkalender/service/db" "htwkalender/service/fetch/v1" @@ -89,7 +88,7 @@ func DeleteAllEvents(app *pocketbase.PocketBase) error { // 3. Save all events for the course and the semester // If the update was successful, nil is returned // If the update was not successful, an error is returned -func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) error { +func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) (model.Events, error) { //new string array with one element (course) var courses []string @@ -109,29 +108,32 @@ func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) error { //get all events for the course and the semester events, err := db.GetAllModulesForCourse(app, course, "ws") if err != nil { - return apis.NewNotFoundError("Events for winter semester could not be found", err) + return nil, err } // append all events for the course and the semester to the events array for ss summerEvents, err := db.GetAllModulesForCourse(app, course, "ss") if err != nil { - return apis.NewNotFoundError("Events for summer semester could not be found", err) + return nil, err } events = append(events, summerEvents...) //if there are no events in the database, save the new events if len(events) == 0 { - _, dbError := db.SaveSeminarGroupEvents(seminarGroups, app) + events, dbError := db.SaveSeminarGroupEvents(seminarGroups, app) if dbError != nil { - return apis.NewNotFoundError("Events could not be saved", dbError) + return nil, dbError } - return nil + return events, nil } //check if events in the seminarGroups Events are already in the database //if yes, keep the database as it is //if no, delete all events for the course and the semester and save the new events + + var savedEvents model.Events + for _, seminarGroup := range seminarGroups { for _, event := range seminarGroup.Events { // if the event is not in the database, delete all events for the course and the semester and save the new events @@ -139,25 +141,24 @@ func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) error { err = DeleteAllEventsByCourseAndSemester(app, course, "ws") if err != nil { - return err + return nil, err } err = DeleteAllEventsByCourseAndSemester(app, course, "ss") if err != nil { - return err + return nil, err } //save the new events - _, dbError := db.SaveSeminarGroupEvents(seminarGroups, app) + savedEvent, dbError := db.SaveSeminarGroupEvents(seminarGroups, app) if dbError != nil { - return apis.NewNotFoundError("Events could not be saved", dbError) + return nil, dbError } - return nil + savedEvents = append(savedEvents, savedEvent...) } } } - - return nil + return savedEvents, nil } func ContainsEvent(events model.Events, event model.Event) bool { diff --git a/backend/service/fetch/v1/fetchSeminarEventService.go b/backend/service/fetch/v1/fetchSeminarEventService.go index 6238c44..6fac5a3 100644 --- a/backend/service/fetch/v1/fetchSeminarEventService.go +++ b/backend/service/fetch/v1/fetchSeminarEventService.go @@ -30,7 +30,7 @@ func GetSeminarEvents(c echo.Context, app *pocketbase.PocketBase) error { seminarGroups = ReplaceEmptyEventNames(seminarGroups) - savedRecords, dbError := db.SaveSeminarGroupEvents(seminarGroups, app) + dbError, savedRecords := db.SaveSeminarGroupEvents(seminarGroups, app) if dbError != nil { return apis.NewNotFoundError("Events could not be saved", dbError.Error()) diff --git a/backend/service/fetch/v2/fetcher.go b/backend/service/fetch/v2/fetcher.go index 6cafd63..93044c8 100644 --- a/backend/service/fetch/v2/fetcher.go +++ b/backend/service/fetch/v2/fetcher.go @@ -1,51 +1,54 @@ package v2 import ( + "fmt" "github.com/google/uuid" - "github.com/labstack/echo/v5" "github.com/pocketbase/pocketbase" "golang.org/x/net/html" "htwkalender/model" "htwkalender/service/db" "htwkalender/service/fetch" - "strconv" + localTime "htwkalender/service/functions/time" "strings" - "time" ) -func ParseEventsFromRemote(c echo.Context, app *pocketbase.PocketBase) error { - - err, savedRecords := FetchAllEventsAndSave(app) - +func ParseEventsFromRemote(app *pocketbase.PocketBase) (model.Events, error) { + savedRecords, err := FetchAllEventsAndSave(app, localTime.RealClock{}) if err != nil { - return err - } else { - savedRecordsLength := strconv.FormatInt(int64(len(savedRecords)), 10) - return c.JSON(200, "Successfully saved "+savedRecordsLength+" events") + return nil, err } + return savedRecords, nil } -func FetchAllEventsAndSave(app *pocketbase.PocketBase) (error, []model.Event) { - var err error +func FetchAllEventsAndSave(app *pocketbase.PocketBase, clock localTime.Clock) ([]model.Event, error) { var savedRecords []model.Event - var events []model.Event - if (time.Now().Month() >= 3) && (time.Now().Month() <= 10) { + if (clock.Now().Month() >= 3) && (clock.Now().Month() <= 10) { url := "https://stundenplan.htwk-leipzig.de/ss/Berichte/Text-Listen;Veranstaltungsarten;name;Vp%0AVw%0AV%0ASp%0ASw%0AS%0APp%0APw%0AP%0AZV%0ATut%0ASperr%0Apf%0Awpf%0Afak%0A%0A?&template=sws_modul&weeks=1-65&combined=yes" - events, err = parseEventForOneSemester(url) + events, err := parseEventForOneSemester(url) + if err != nil { + return nil, fmt.Errorf("failed to parse events for summmer semester: %w", err) + } savedEvents, dbError := db.SaveEvents(events, app) - err = dbError + if dbError != nil { + return nil, fmt.Errorf("failed to save events: %w", dbError) + } savedRecords = append(savedEvents, events...) } - if (time.Now().Month() >= 9) || (time.Now().Month() <= 4) { + if (clock.Now().Month() >= 9) || (clock.Now().Month() <= 4) { url := "https://stundenplan.htwk-leipzig.de/ws/Berichte/Text-Listen;Veranstaltungsarten;name;Vp%0AVw%0AV%0ASp%0ASw%0AS%0APp%0APw%0AP%0AZV%0ATut%0ASperr%0Apf%0Awpf%0Afak%0A%0A?&template=sws_modul&weeks=1-65&combined=yes" - events, err = parseEventForOneSemester(url) + events, err := parseEventForOneSemester(url) + if err != nil { + return nil, fmt.Errorf("failed to parse events for winter semester: %w", err) + } savedEvents, dbError := db.SaveEvents(events, app) - err = dbError + if dbError != nil { + return nil, fmt.Errorf("failed to save events: %w", dbError) + } savedRecords = append(savedEvents, events...) } - return err, savedRecords + return savedRecords, nil } func parseEventForOneSemester(url string) ([]model.Event, error) { @@ -56,25 +59,18 @@ func parseEventForOneSemester(url string) ([]model.Event, error) { } // Parse HTML to Node Tree - doc, err2 := parseHTML(err, webpage) - if err2 != nil { - return nil, err2 + var doc *html.Node + doc, err = parseHTML(webpage, err) + if err != nil { + return nil, err } // Get all event tables and all day labels eventTables := getEventTables(doc) allDayLabels := getAllDayLabels(doc) - if eventTables == nil || allDayLabels == nil { - return nil, err - } - eventsWithCombinedWeeks := toEvents(eventTables, allDayLabels) - if eventsWithCombinedWeeks == nil { - return nil, err - } - splitEventsByWeekVal := splitEventsByWeek(eventsWithCombinedWeeks) events := splitEventsBySingleWeek(splitEventsByWeekVal) @@ -83,6 +79,11 @@ func parseEventForOneSemester(url string) ([]model.Event, error) { } table := findFirstTable(doc) + + if table == nil { + return nil, fmt.Errorf("failed to find first table") + } + semesterString := findFirstSpanWithClass(table, "header-0-2-0").FirstChild.Data semester, year := extractSemesterAndYear(semesterString) events = convertWeeksToDates(events, semester, year) @@ -101,7 +102,7 @@ func parseEventForOneSemester(url string) ([]model.Event, error) { return events, nil } -func parseHTML(err error, webpage string) (*html.Node, error) { +func parseHTML(webpage string, err error) (*html.Node, error) { doc, err := html.Parse(strings.NewReader(webpage)) if err != nil { return nil, err diff --git a/backend/service/logger/logger.go b/backend/service/logger/logger.go new file mode 100644 index 0000000..90c66f6 --- /dev/null +++ b/backend/service/logger/logger.go @@ -0,0 +1 @@ +package logger diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b27fcd7..24a2a23 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -3588,9 +3588,9 @@ "dev": true }, "node_modules/vite": { - "version": "4.4.12", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.12.tgz", - "integrity": "sha512-KtPlUbWfxzGVul8Nut8Gw2Qe8sBzWY+8QVc5SL8iRFnpnrcoCaNlzO40c1R6hPmcdTwIPEDkq0Y9+27a5tVbdQ==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", + "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", "dev": true, "dependencies": { "esbuild": "^0.18.10", From 23c9794c10eca44579a495604b87fdfac7d95e32 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Sun, 21 Jan 2024 18:33:01 +0100 Subject: [PATCH 03/11] fix:#150 update frontend deps and schedule --- backend/service/addSchedule.go | 8 +- frontend/package-lock.json | 1748 +++++++++++++++++++++++--------- package-lock.json | 6 - 3 files changed, 1273 insertions(+), 489 deletions(-) delete mode 100644 package-lock.json diff --git a/backend/service/addSchedule.go b/backend/service/addSchedule.go index fb0897d..9eb1a89 100644 --- a/backend/service/addSchedule.go +++ b/backend/service/addSchedule.go @@ -11,8 +11,8 @@ import ( v2 "htwkalender/service/fetch/v2" "htwkalender/service/functions/time" "log" - "strconv" "log/slog" + "strconv" ) func AddSchedules(app *pocketbase.PocketBase) { @@ -35,10 +35,8 @@ func AddSchedules(app *pocketbase.PocketBase) { feed.ClearFeeds(app.Dao(), 6, time.RealClock{}) }) - // Every sunday at 3am fetch all sport events (5 segments - minute, hour, day, month, weekday) "0 2 * * 0" - scheduler.MustAdd("fetchSportEvents", "0 3 * * 0", func() { // Every sunday at 2am fetch all sport events (5 segments - minute, hour, day, month, weekday) "0 2 * * 0" - scheduler.MustAdd("fetchEvents", "0 2 * * 0", func() { + scheduler.MustAdd("fetchSportEvents", "0 3 * * 0", func() { slog.Info("Started fetching sport events schedule") sport.FetchAndUpdateSportEvents(app) }) @@ -50,7 +48,7 @@ func AddSchedules(app *pocketbase.PocketBase) { log.Println(err) } - err, savedEvents := v2.FetchAllEventsAndSave(app) + savedEvents, err := v2.FetchAllEventsAndSave(app, time.RealClock{}) if err != nil { log.Println(err) } else { diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 24a2a23..145d50a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,34 +8,36 @@ "name": "htwkalender", "version": "0.0.0", "dependencies": { - "@fullcalendar/core": "^6.1.9", - "@fullcalendar/daygrid": "^6.1.9", - "@fullcalendar/interaction": "^6.1.9", - "@fullcalendar/timegrid": "^6.1.9", - "@fullcalendar/vue3": "^6.1.9", - "@vueuse/core": "^10.6.1", - "pinia": "^2.1.6", + "@fullcalendar/core": "^6.1.10", + "@fullcalendar/daygrid": "^6.1.10", + "@fullcalendar/interaction": "^6.1.10", + "@fullcalendar/timegrid": "^6.1.10", + "@fullcalendar/vue3": "^6.1.10", + "@vueuse/core": "^10.7.1", + "pinia": "^2.1.7", "primeflex": "^3.3.1", "primeicons": "^6.0.1", - "primevue": "^3.32.2", - "vue": "^3.3.4", - "vue-i18n": "^9.4.1", - "vue-router": "^4.2.4" + "primevue": "^3.46.0", + "source-sans-pro": "^3.6.0", + "vue": "^3.4.11", + "vue-i18n": "^9.9.0", + "vue-router": "^4.2.5" }, "devDependencies": { - "@types/node": "^20.5.9", - "@vitejs/plugin-vue": "^4.2.3", + "@types/node": "^20.11.0", + "@vitejs/plugin-vue": "^5.0.3", "@vue/eslint-config-typescript": "^12.0.0", - "eslint": "^8.48.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-vue": "^9.17.0", - "moment-timezone": "^0.5.43", - "prettier": "3.0.2", - "sass": "^1.69.5", - "sass-loader": "^13.3.2", - "typescript": "^5.0.2", - "vite": "^4.4.12", - "vue-tsc": "^1.8.5" + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-vue": "^9.20.0", + "moment-timezone": "^0.5.44", + "prettier": "3.2.1", + "sass": "^1.69.7", + "sass-loader": "^13.3.3", + "typescript": "^5.3.3", + "vite": "^5.0.11", + "vitest": "^1.2.0", + "vue-tsc": "^1.8.27" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -48,9 +50,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.11.tgz", - "integrity": "sha512-R5zb8eJIBPJriQtbH/htEQy4k7E2dHWlD2Y2VT07JCzwYZHBxV5ZYtM0UhXSNMT74LyxuM+b1jdL7pSesXbC/g==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", "bin": { "parser": "bin/babel-parser.js" }, @@ -58,10 +60,26 @@ "node": ">=6.0.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz", + "integrity": "sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.11.tgz", + "integrity": "sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==", "cpu": [ "arm" ], @@ -75,9 +93,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz", + "integrity": "sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==", "cpu": [ "arm64" ], @@ -91,9 +109,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.11.tgz", + "integrity": "sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==", "cpu": [ "x64" ], @@ -107,9 +125,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz", + "integrity": "sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==", "cpu": [ "arm64" ], @@ -123,9 +141,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz", + "integrity": "sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==", "cpu": [ "x64" ], @@ -139,9 +157,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz", + "integrity": "sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==", "cpu": [ "arm64" ], @@ -155,9 +173,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz", + "integrity": "sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==", "cpu": [ "x64" ], @@ -171,9 +189,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz", + "integrity": "sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==", "cpu": [ "arm" ], @@ -187,9 +205,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz", + "integrity": "sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==", "cpu": [ "arm64" ], @@ -203,9 +221,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz", + "integrity": "sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==", "cpu": [ "ia32" ], @@ -219,9 +237,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz", + "integrity": "sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==", "cpu": [ "loong64" ], @@ -235,9 +253,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz", + "integrity": "sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==", "cpu": [ "mips64el" ], @@ -251,9 +269,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz", + "integrity": "sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==", "cpu": [ "ppc64" ], @@ -267,9 +285,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz", + "integrity": "sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==", "cpu": [ "riscv64" ], @@ -283,9 +301,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz", + "integrity": "sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==", "cpu": [ "s390x" ], @@ -299,9 +317,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz", + "integrity": "sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==", "cpu": [ "x64" ], @@ -315,9 +333,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz", + "integrity": "sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==", "cpu": [ "x64" ], @@ -331,9 +349,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz", + "integrity": "sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==", "cpu": [ "x64" ], @@ -347,9 +365,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz", + "integrity": "sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==", "cpu": [ "x64" ], @@ -363,9 +381,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz", + "integrity": "sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==", "cpu": [ "arm64" ], @@ -379,9 +397,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz", + "integrity": "sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==", "cpu": [ "ia32" ], @@ -395,9 +413,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz", + "integrity": "sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==", "cpu": [ "x64" ], @@ -435,9 +453,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -457,117 +475,73 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@eslint/js": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", - "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@fullcalendar/core": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.9.tgz", - "integrity": "sha512-eeG+z9BWerdsU9Ac6j16rpYpPnE0wxtnEHiHrh/u/ADbGTR3hCOjCD9PxQOfhOTHbWOVs7JQunGcksSPu5WZBQ==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.10.tgz", + "integrity": "sha512-oTXGJSAGpCf1oY+CKp5qYjMHkJCPBkJ3SHitl63n8Q6xKeiwQ4EF6Au451euUovREwJpLmD1AyZrCnWmtB9AVg==", "dependencies": { "preact": "~10.12.1" } }, "node_modules/@fullcalendar/daygrid": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.9.tgz", - "integrity": "sha512-o/6joH/7lmVHXAkbaa/tUbzWYnGp/LgfdiFyYPkqQbjKEeivNZWF1WhHqFbhx0zbFONSHtrvkjY2bjr+Ef2quQ==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.10.tgz", + "integrity": "sha512-Z4GRm1IyHKgxXFTWGcEI0nTsvYOIkpE0aMt3/o3ER2SZkF+hfwcDFhtj0c9+WhMjXFIWYeoTnA9rUOY7Zl/nxA==", "peerDependencies": { - "@fullcalendar/core": "~6.1.9" + "@fullcalendar/core": "~6.1.10" } }, "node_modules/@fullcalendar/interaction": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.9.tgz", - "integrity": "sha512-I3FGnv0kKZpIwujg3HllbKrciNjTqeTYy3oJG226oAn7lV6wnrrDYMmuGmA0jPJAGN46HKrQqKN7ItxQRDec4Q==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.10.tgz", + "integrity": "sha512-aZRlwCpmDasq2RNeWV0ub20Uevare9Cb6iMlxCacx0fhOC14H28G9d1FsduJIecInL84SPGwt5ItqAYMsWv7zw==", "peerDependencies": { - "@fullcalendar/core": "~6.1.9" + "@fullcalendar/core": "~6.1.10" } }, "node_modules/@fullcalendar/timegrid": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.9.tgz", - "integrity": "sha512-le7UV05wVE1Trdr054kgJXTwa+A1pEI8nlCBnPWdcyrL+dTLoPvQ4AWEVCnV7So+4zRYaCqnqGXfCJsj0RQa0g==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.10.tgz", + "integrity": "sha512-hFKyQXJaPbNyq1reZmvkCmM64O99krHoIcJAbDS+dntCm3FzZUcDtAcRKIbMiantHrezCG/1MEYk3m9e3aKvIQ==", "dependencies": { - "@fullcalendar/daygrid": "~6.1.9" + "@fullcalendar/daygrid": "~6.1.10" }, "peerDependencies": { - "@fullcalendar/core": "~6.1.9" + "@fullcalendar/core": "~6.1.10" } }, "node_modules/@fullcalendar/vue3": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/vue3/-/vue3-6.1.9.tgz", - "integrity": "sha512-nuEEb/6uRhD0AH3PzU4Mtod3dD7S729nA1oYorMdCYMgUvXoHJlz2wOKK8w4LGZIn6K2R8Yzo8ol33ElBjHo3A==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@fullcalendar/vue3/-/vue3-6.1.10.tgz", + "integrity": "sha512-YMYBQx0TlWNuN4G6ra2dkf5cCF5aVi/2zDLGLvLqe2Nk2o7uNbTkrCSG40061OepWQlJv+hYqm1JukLRmyqi4Q==", "peerDependencies": { - "@fullcalendar/core": "~6.1.9", + "@fullcalendar/core": "~6.1.10", "vue": "^3.0.11" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -582,18 +556,18 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "node_modules/@intlify/core-base": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.4.1.tgz", - "integrity": "sha512-WIwx+elsZbxSMxRG5+LC+utRohFvmZMoDevfKOfnYMLbpCjCSavqTfHJAtfsY6ruowzqXeKkeLhRHbYbjoJx5g==", + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.9.0.tgz", + "integrity": "sha512-C7UXPymDIOlMGSNjAhNLtKgzITc/8BjINK5gNKXg8GiWCTwL6n3MWr55czksxn8RM5wTMz0qcLOFT+adtaVQaA==", "dependencies": { - "@intlify/message-compiler": "9.4.1", - "@intlify/shared": "9.4.1" + "@intlify/message-compiler": "9.9.0", + "@intlify/shared": "9.9.0" }, "engines": { "node": ">= 16" @@ -603,11 +577,11 @@ } }, "node_modules/@intlify/message-compiler": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.4.1.tgz", - "integrity": "sha512-aN2N+dUx320108QhH51Ycd2LEpZ+NKbzyQ2kjjhqMcxhHdxtOnkgdx+MDBhOy/CObwBmhC3Nygzc6hNlfKvPNw==", + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.9.0.tgz", + "integrity": "sha512-yDU/jdUm9KuhEzYfS+wuyja209yXgdl1XFhMlKtXEgSFTxz4COZQCRXXbbH8JrAjMsaJ7bdoPSLsKlY6mXG2iA==", "dependencies": { - "@intlify/shared": "9.4.1", + "@intlify/shared": "9.9.0", "source-map-js": "^1.0.2" }, "engines": { @@ -618,9 +592,9 @@ } }, "node_modules/@intlify/shared": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.4.1.tgz", - "integrity": "sha512-A51elBmZWf1FS80inf/32diO9DeXoqg9GR9aUDHFcfHoNDuT46Q+fpPOdj8jiJnSHSBh8E1E+6qWRhAZXdK3Ng==", + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.9.0.tgz", + "integrity": "sha512-1ECUyAHRrzOJbOizyGufYP2yukqGrWXtkmTu4PcswVnWbkcjzk3YQGmJ0bLkM7JZ0ZYAaohLGdYvBYnTOGYJ9g==", "engines": { "node": ">= 16" }, @@ -628,6 +602,18 @@ "url": "https://github.com/sponsors/kazupon" } }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -725,6 +711,181 @@ "node": ">= 8" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz", + "integrity": "sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.6.tgz", + "integrity": "sha512-T14aNLpqJ5wzKNf5jEDpv5zgyIqcpn1MlwCrUXLrwoADr2RkWA0vOWP4XxbO9aiO3dvMCQICZdKeDrFl7UMClw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.6.tgz", + "integrity": "sha512-CqNNAyhRkTbo8VVZ5R85X73H3R5NX9ONnKbXuHisGWC0qRbTTxnF1U4V9NafzJbgGM0sHZpdO83pLPzq8uOZFw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.6.tgz", + "integrity": "sha512-zRDtdJuRvA1dc9Mp6BWYqAsU5oeLixdfUvkTHuiYOHwqYuQ4YgSmi6+/lPvSsqc/I0Omw3DdICx4Tfacdzmhog==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.6.tgz", + "integrity": "sha512-oNk8YXDDnNyG4qlNb6is1ojTOGL/tRhbbKeE/YuccItzerEZT68Z9gHrY3ROh7axDc974+zYAPxK5SH0j/G+QQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.6.tgz", + "integrity": "sha512-Z3O60yxPtuCYobrtzjo0wlmvDdx2qZfeAWTyfOjEDqd08kthDKexLpV97KfAeUXPosENKd8uyJMRDfFMxcYkDQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.6.tgz", + "integrity": "sha512-gpiG0qQJNdYEVad+1iAsGAbgAnZ8j07FapmnIAQgODKcOTjLEWM9sRb+MbQyVsYCnA0Im6M6QIq6ax7liws6eQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.6.tgz", + "integrity": "sha512-+uCOcvVmFUYvVDr27aiyun9WgZk0tXe7ThuzoUTAukZJOwS5MrGbmSlNOhx1j80GdpqbOty05XqSl5w4dQvcOA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.6.tgz", + "integrity": "sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.6.tgz", + "integrity": "sha512-ch7M+9Tr5R4FK40FHQk8VnML0Szi2KRujUgHXd/HjuH9ifH72GUmw6lStZBo3c3GB82vHa0ZoUfjfcM7JiiMrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.6.tgz", + "integrity": "sha512-VD6qnR99dhmTQ1mJhIzXsRcTBvTjbfbGGwKAHcu+52cVl15AC/kplkhxzW/uT0Xl62Y/meBKDZvoJSJN+vTeGA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.6.tgz", + "integrity": "sha512-J9AFDq/xiRI58eR2NIDfyVmTYGyIZmRcvcAoJ48oDld/NTR8wyiPUu2X/v1navJ+N/FGg68LEbX3Ejd6l8B7MQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.6.tgz", + "integrity": "sha512-jqzNLhNDvIZOrt69Ce4UjGRpXJBzhUBzawMwnaDAwyHriki3XollsewxWzOzz+4yOFDkuJHtTsZFwMxhYJWmLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, "node_modules/@types/eslint": { "version": "8.44.6", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", @@ -748,11 +909,10 @@ } }, "node_modules/@types/estree": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", - "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==", - "dev": true, - "peer": true + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true }, "node_modules/@types/json-schema": { "version": "7.0.12", @@ -761,10 +921,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.5.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", - "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==", - "dev": true + "version": "20.11.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz", + "integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/semver": { "version": "7.5.2", @@ -966,90 +1129,203 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/@vitejs/plugin-vue": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.3.3.tgz", - "integrity": "sha512-ssxyhIAZqB0TrpUg6R0cBpCuMk9jTIlO1GNSKKQD6S8VjnXi6JXKfUXjSsxey9IwQiaRGsO1WnW9Rkl1L6AJVw==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.3.tgz", + "integrity": "sha512-b8S5dVS40rgHdDrw+DQi/xOM9ed+kSRZzfm1T74bMmBDCd8XO87NKlFYInzCtwvtWwXZvo1QxE2OSspTATWrbA==", "dev": true, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.0.0 || >=20.0.0" }, "peerDependencies": { - "vite": "^4.0.0", + "vite": "^5.0.0", "vue": "^3.2.25" } }, - "node_modules/@volar/language-core": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.10.1.tgz", - "integrity": "sha512-JnsM1mIPdfGPxmoOcK1c7HYAsL6YOv0TCJ4aW3AXPZN/Jb4R77epDyMZIVudSGjWMbvv/JfUa+rQ+dGKTmgwBA==", + "node_modules/@vitest/expect": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.2.1.tgz", + "integrity": "sha512-/bqGXcHfyKgFWYwIgFr1QYDaR9e64pRKxgBNWNXPefPFRhgm+K3+a/dS0cUGEreWngets3dlr8w8SBRw2fCfFQ==", "dev": true, "dependencies": { - "@volar/source-map": "1.10.1" + "@vitest/spy": "1.2.1", + "@vitest/utils": "1.2.1", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.2.1.tgz", + "integrity": "sha512-zc2dP5LQpzNzbpaBt7OeYAvmIsRS1KpZQw4G3WM/yqSV1cQKNKwLGmnm79GyZZjMhQGlRcSFMImLjZaUQvNVZQ==", + "dev": true, + "dependencies": { + "@vitest/utils": "1.2.1", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/snapshot": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.2.1.tgz", + "integrity": "sha512-Tmp/IcYEemKaqAYCS08sh0vORLJkMr0NRV76Gl8sHGxXT5151cITJCET20063wk0Yr/1koQ6dnmP6eEqezmd/Q==", + "dev": true, + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.2.1.tgz", + "integrity": "sha512-vG3a/b7INKH7L49Lbp0IWrG6sw9j4waWAucwnksPB1r1FTJgV7nkBByd9ufzu6VWya/QTvQW4V9FShZbZIB2UQ==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-bsH6WVZYe/J2v3+81M5LDU8kW76xWObKIURpPrOXm2pjBniBu2MERI/XP60GpS4PHU3jyK50LUutOwrx4CyHUg==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@volar/language-core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.11.1.tgz", + "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==", + "dev": true, + "dependencies": { + "@volar/source-map": "1.11.1" } }, "node_modules/@volar/source-map": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.10.1.tgz", - "integrity": "sha512-3/S6KQbqa7pGC8CxPrg69qHLpOvkiPHGJtWPkI/1AXCsktkJ6gIk/5z4hyuMp8Anvs6eS/Kvp/GZa3ut3votKA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.11.1.tgz", + "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==", "dev": true, "dependencies": { "muggle-string": "^0.3.1" } }, "node_modules/@volar/typescript": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.10.1.tgz", - "integrity": "sha512-+iiO9yUSRHIYjlteT+QcdRq8b44qH19/eiUZtjNtuh6D9ailYM7DVR0zO2sEgJlvCaunw/CF9Ov2KooQBpR4VQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.11.1.tgz", + "integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==", "dev": true, "dependencies": { - "@volar/language-core": "1.10.1" + "@volar/language-core": "1.11.1", + "path-browserify": "^1.0.1" } }, "node_modules/@vue/compiler-core": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz", - "integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.15.tgz", + "integrity": "sha512-XcJQVOaxTKCnth1vCxEChteGuwG6wqnUHxAm1DO3gCz0+uXKaJNx8/digSz4dLALCy8n2lKq24jSUs8segoqIw==", "dependencies": { - "@babel/parser": "^7.21.3", - "@vue/shared": "3.3.4", + "@babel/parser": "^7.23.6", + "@vue/shared": "3.4.15", + "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" } }, + "node_modules/@vue/compiler-core/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, "node_modules/@vue/compiler-dom": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz", - "integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.15.tgz", + "integrity": "sha512-wox0aasVV74zoXyblarOM3AZQz/Z+OunYcIHe1OsGclCHt8RsRm04DObjefaI82u6XDzv+qGWZ24tIsRAIi5MQ==", "dependencies": { - "@vue/compiler-core": "3.3.4", - "@vue/shared": "3.3.4" + "@vue/compiler-core": "3.4.15", + "@vue/shared": "3.4.15" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz", - "integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.15.tgz", + "integrity": "sha512-LCn5M6QpkpFsh3GQvs2mJUOAlBQcCco8D60Bcqmf3O3w5a+KWS5GvYbrrJBkgvL1BDnTp+e8q0lXCLgHhKguBA==", "dependencies": { - "@babel/parser": "^7.20.15", - "@vue/compiler-core": "3.3.4", - "@vue/compiler-dom": "3.3.4", - "@vue/compiler-ssr": "3.3.4", - "@vue/reactivity-transform": "3.3.4", - "@vue/shared": "3.3.4", + "@babel/parser": "^7.23.6", + "@vue/compiler-core": "3.4.15", + "@vue/compiler-dom": "3.4.15", + "@vue/compiler-ssr": "3.4.15", + "@vue/shared": "3.4.15", "estree-walker": "^2.0.2", - "magic-string": "^0.30.0", - "postcss": "^8.1.10", + "magic-string": "^0.30.5", + "postcss": "^8.4.33", "source-map-js": "^1.0.2" } }, + "node_modules/@vue/compiler-sfc/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, "node_modules/@vue/compiler-ssr": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz", - "integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.15.tgz", + "integrity": "sha512-1jdeQyiGznr8gjFDadVmOJqZiLNSsMa5ZgqavkPZ8O2wjHv0tVuAEsw5hTdUoUW4232vpBbL/wJhzVW/JwY1Uw==", "dependencies": { - "@vue/compiler-dom": "3.3.4", - "@vue/shared": "3.3.4" + "@vue/compiler-dom": "3.4.15", + "@vue/shared": "3.4.15" } }, "node_modules/@vue/devtools-api": { @@ -1082,18 +1358,19 @@ } }, "node_modules/@vue/language-core": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.8.tgz", - "integrity": "sha512-i4KMTuPazf48yMdYoebTkgSOJdFraE4pQf0B+FTOFkbB+6hAfjrSou/UmYWRsWyZV6r4Rc6DDZdI39CJwL0rWw==", + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz", + "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", "dev": true, "dependencies": { - "@volar/language-core": "~1.10.0", - "@volar/source-map": "~1.10.0", + "@volar/language-core": "~1.11.1", + "@volar/source-map": "~1.11.1", "@vue/compiler-dom": "^3.3.0", - "@vue/reactivity": "^3.3.0", "@vue/shared": "^3.3.0", - "minimatch": "^9.0.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", "muggle-string": "^0.3.1", + "path-browserify": "^1.0.1", "vue-template-compiler": "^2.7.14" }, "peerDependencies": { @@ -1105,80 +1382,82 @@ } } }, - "node_modules/@vue/reactivity": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz", - "integrity": "sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==", + "node_modules/@vue/language-core/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { - "@vue/shared": "3.3.4" + "balanced-match": "^1.0.0" } }, - "node_modules/@vue/reactivity-transform": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz", - "integrity": "sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==", + "node_modules/@vue/language-core/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, "dependencies": { - "@babel/parser": "^7.20.15", - "@vue/compiler-core": "3.3.4", - "@vue/shared": "3.3.4", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.0" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.15.tgz", + "integrity": "sha512-55yJh2bsff20K5O84MxSvXKPHHt17I2EomHznvFiJCAZpJTNW8IuLj1xZWMLELRhBK3kkFV/1ErZGHJfah7i7w==", + "dependencies": { + "@vue/shared": "3.4.15" } }, "node_modules/@vue/runtime-core": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.4.tgz", - "integrity": "sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.15.tgz", + "integrity": "sha512-6E3by5m6v1AkW0McCeAyhHTw+3y17YCOKG0U0HDKDscV4Hs0kgNT5G+GCHak16jKgcCDHpI9xe5NKb8sdLCLdw==", "dependencies": { - "@vue/reactivity": "3.3.4", - "@vue/shared": "3.3.4" + "@vue/reactivity": "3.4.15", + "@vue/shared": "3.4.15" } }, "node_modules/@vue/runtime-dom": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz", - "integrity": "sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.15.tgz", + "integrity": "sha512-EVW8D6vfFVq3V/yDKNPBFkZKGMFSvZrUQmx196o/v2tHKdwWdiZjYUBS+0Ez3+ohRyF8Njwy/6FH5gYJ75liUw==", "dependencies": { - "@vue/runtime-core": "3.3.4", - "@vue/shared": "3.3.4", - "csstype": "^3.1.1" + "@vue/runtime-core": "3.4.15", + "@vue/shared": "3.4.15", + "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.4.tgz", - "integrity": "sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.15.tgz", + "integrity": "sha512-3HYzaidu9cHjrT+qGUuDhFYvF/j643bHC6uUN9BgM11DVy+pM6ATsG6uPBLnkwOgs7BpJABReLmpL3ZPAsUaqw==", "dependencies": { - "@vue/compiler-ssr": "3.3.4", - "@vue/shared": "3.3.4" + "@vue/compiler-ssr": "3.4.15", + "@vue/shared": "3.4.15" }, "peerDependencies": { - "vue": "3.3.4" + "vue": "3.4.15" } }, "node_modules/@vue/shared": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz", - "integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==" - }, - "node_modules/@vue/typescript": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/@vue/typescript/-/typescript-1.8.8.tgz", - "integrity": "sha512-jUnmMB6egu5wl342eaUH236v8tdcEPXXkPgj+eI/F6JwW/lb+yAU6U07ZbQ3MVabZRlupIlPESB7ajgAGixhow==", - "dev": true, - "dependencies": { - "@volar/typescript": "~1.10.0", - "@vue/language-core": "1.8.8" - } + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz", + "integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==" }, "node_modules/@vueuse/core": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.6.1.tgz", - "integrity": "sha512-Pc26IJbqgC9VG1u6VY/xrXXfxD33hnvxBnKrLlA2LJlyHII+BSrRoTPJgGYq7qZOu61itITFUnm6QbacwZ4H8Q==", + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.7.2.tgz", + "integrity": "sha512-AOyAL2rK0By62Hm+iqQn6Rbu8bfmbgaIMXcE3TSr7BdQ42wnSFlwIdPjInO62onYsEMK/yDMU8C6oGfDAtZ2qQ==", "dependencies": { "@types/web-bluetooth": "^0.0.20", - "@vueuse/metadata": "10.6.1", - "@vueuse/shared": "10.6.1", + "@vueuse/metadata": "10.7.2", + "@vueuse/shared": "10.7.2", "vue-demi": ">=0.14.6" }, "funding": { @@ -1211,17 +1490,17 @@ } }, "node_modules/@vueuse/metadata": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.6.1.tgz", - "integrity": "sha512-qhdwPI65Bgcj23e5lpGfQsxcy0bMjCAsUGoXkJ7DsoeDUdasbZ2DBa4dinFCOER3lF4gwUv+UD2AlA11zdzMFw==", + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.7.2.tgz", + "integrity": "sha512-kCWPb4J2KGrwLtn1eJwaJD742u1k5h6v/St5wFe8Quih90+k2a0JP8BS4Zp34XUuJqS2AxFYMb1wjUL8HfhWsQ==", "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/shared": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.6.1.tgz", - "integrity": "sha512-TECVDTIedFlL0NUfHWncf3zF9Gc4VfdxfQc8JFwoVZQmxpONhLxFrlm0eHQeidHj4rdTPL3KXJa0TZCk1wnc5Q==", + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.7.2.tgz", + "integrity": "sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==", "dependencies": { "vue-demi": ">=0.14.6" }, @@ -1430,9 +1709,9 @@ "peer": true }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -1460,6 +1739,15 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1538,6 +1826,15 @@ "node": ">=8" } }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1560,12 +1857,13 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/braces": { @@ -1620,6 +1918,15 @@ "dev": true, "peer": true }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1650,6 +1957,24 @@ ], "peer": true }, + "node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1666,6 +1991,18 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -1740,6 +2077,12 @@ "dev": true, "peer": true }, + "node_modules/computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1773,9 +2116,9 @@ } }, "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/de-indent": { "version": "1.0.2", @@ -1800,12 +2143,33 @@ } } }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1851,6 +2215,17 @@ "node": ">=10.13.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es-module-lexer": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", @@ -1859,9 +2234,9 @@ "peer": true }, "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.11.tgz", + "integrity": "sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==", "dev": true, "hasInstallScript": true, "bin": { @@ -1871,28 +2246,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" + "@esbuild/aix-ppc64": "0.19.11", + "@esbuild/android-arm": "0.19.11", + "@esbuild/android-arm64": "0.19.11", + "@esbuild/android-x64": "0.19.11", + "@esbuild/darwin-arm64": "0.19.11", + "@esbuild/darwin-x64": "0.19.11", + "@esbuild/freebsd-arm64": "0.19.11", + "@esbuild/freebsd-x64": "0.19.11", + "@esbuild/linux-arm": "0.19.11", + "@esbuild/linux-arm64": "0.19.11", + "@esbuild/linux-ia32": "0.19.11", + "@esbuild/linux-loong64": "0.19.11", + "@esbuild/linux-mips64el": "0.19.11", + "@esbuild/linux-ppc64": "0.19.11", + "@esbuild/linux-riscv64": "0.19.11", + "@esbuild/linux-s390x": "0.19.11", + "@esbuild/linux-x64": "0.19.11", + "@esbuild/netbsd-x64": "0.19.11", + "@esbuild/openbsd-x64": "0.19.11", + "@esbuild/sunos-x64": "0.19.11", + "@esbuild/win32-arm64": "0.19.11", + "@esbuild/win32-ia32": "0.19.11", + "@esbuild/win32-x64": "0.19.11" } }, "node_modules/escalade": { @@ -1918,18 +2294,19 @@ } }, "node_modules/eslint": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", - "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.48.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -1972,9 +2349,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", - "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -1984,9 +2361,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "9.17.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.17.0.tgz", - "integrity": "sha512-r7Bp79pxQk9I5XDP0k2dpUC7Ots3OSWgvGZNu3BxmKK6Zg7NgVtcOB6OCna5Kb9oQwJPl5hq183WD0SY5tZtIQ==", + "version": "9.20.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.20.1.tgz", + "integrity": "sha512-GyCs8K3lkEvoyC1VV97GJhP1SvqsKCiWGHnbn0gVUYiUhaH2+nB+Dv1uekv1THFMPbBfYxukrzQdltw950k+LQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", @@ -1994,7 +2371,7 @@ "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.13", "semver": "^7.5.4", - "vue-eslint-parser": "^9.3.1", + "vue-eslint-parser": "^9.4.0", "xml-name-validator": "^4.0.0" }, "engines": { @@ -2032,28 +2409,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -2105,9 +2460,13 @@ } }, "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } }, "node_modules/esutils": { "version": "2.0.3", @@ -2128,6 +2487,29 @@ "node": ">=0.8.x" } }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2263,6 +2645,27 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -2302,32 +2705,10 @@ "dev": true, "peer": true }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -2390,6 +2771,15 @@ "he": "bin/he" } }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -2497,6 +2887,18 @@ "node": ">=8" } }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2571,6 +2973,12 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "node_modules/keyv": { "version": "4.5.3", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", @@ -2603,6 +3011,22 @@ "node": ">=6.11.5" } }, + "node_modules/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "dev": true, + "dependencies": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2630,6 +3054,15 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2643,9 +3076,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.3.tgz", - "integrity": "sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==", + "version": "0.30.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", + "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, @@ -2657,8 +3090,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "peer": true + "dev": true }, "node_modules/merge2": { "version": "1.4.1", @@ -2705,19 +3137,40 @@ "node": ">= 0.6" } }, - "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mlly": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.5.0.tgz", + "integrity": "sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.0.3", + "ufo": "^1.3.2" } }, "node_modules/moment": { @@ -2730,9 +3183,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.43", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz", - "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==", + "version": "0.5.44", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.44.tgz", + "integrity": "sha512-nv3YpzI/8lkQn0U6RkLd+f0W/zy/JnoR5/EyPz/dNkPTBjA2jNLCVxaiQ8QpeLymhSZvX0wCL5s27NQWdOPwAw==", "dev": true, "dependencies": { "moment": "^2.29.4" @@ -2754,9 +3207,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -2798,6 +3251,33 @@ "node": ">=0.10.0" } }, + "node_modules/npm-run-path": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", + "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -2819,6 +3299,21 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -2878,6 +3373,12 @@ "node": ">=6" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2914,6 +3415,21 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -2932,9 +3448,9 @@ } }, "node_modules/pinia": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.6.tgz", - "integrity": "sha512-bIU6QuE5qZviMmct5XwCesXelb5VavdOWKWaB17ggk++NUwQWWbP5YnsONTk3b752QkW9sACiR81rorpeOMSvQ==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz", + "integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==", "dependencies": { "@vue/devtools-api": "^6.5.0", "vue-demi": ">=0.14.5" @@ -2981,10 +3497,21 @@ } } }, + "node_modules/pkg-types": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", + "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.2.0", + "mlly": "^1.2.0", + "pathe": "^1.1.0" + } + }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.33", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", + "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", "funding": [ { "type": "opencollective", @@ -3000,7 +3527,7 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -3040,9 +3567,9 @@ } }, "node_modules/prettier": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz", - "integrity": "sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.1.tgz", + "integrity": "sha512-qSUWshj1IobVbKc226Gw2pync27t0Kf0EdufZa9j7uBSJay1CC+B3K5lAAZoqgX3ASiKuWsk6OmzKRetXNObWg==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -3054,6 +3581,32 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/primeflex": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/primeflex/-/primeflex-3.3.1.tgz", @@ -3065,9 +3618,9 @@ "integrity": "sha512-KDeO94CbWI4pKsPnYpA1FPjo79EsY9I+M8ywoPBSf9XMXoe/0crjbUK7jcQEDHuc0ZMRIZsxH3TYLv4TUtHmAA==" }, "node_modules/primevue": { - "version": "3.32.2", - "resolved": "https://registry.npmjs.org/primevue/-/primevue-3.32.2.tgz", - "integrity": "sha512-BEDhIb+VqfjjIF9+G+dCRsE542afz5Xl01XHbViYR13T7ZreBMWsPcJCCTyKzouwJHr6HTskJXJnrkTmOI1vKg==", + "version": "3.46.0", + "resolved": "https://registry.npmjs.org/primevue/-/primevue-3.46.0.tgz", + "integrity": "sha512-WGprXj9HA+j6gLLDaSxcRRSChIF99ld5fg1D3hYFA7hNiEuON1aqe83gf52vUSw8yjVMtFQ3CMPQSTYhooNwIg==", "peerDependencies": { "vue": "^3.0.0" } @@ -3111,6 +3664,12 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3158,18 +3717,34 @@ } }, "node_modules/rollup": { - "version": "3.28.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.1.tgz", - "integrity": "sha512-R9OMQmIHJm9znrU3m3cpE8uhN0fGdXiawME7aZIpQqvpS/85+Vt1Hq1/yVIcYfOmaQiHjvXkQAoJukvLpau6Yw==", + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.6.tgz", + "integrity": "sha512-05lzkCS2uASX0CiLFybYfVkwNbKZG5NFQ6Go0VWyogFTXXbR039UVsegViTntkk4OglHBdF54ccApXRRuXRbsg==", "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=14.18.0", + "node": ">=18.0.0", "npm": ">=8.0.0" }, "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.9.6", + "@rollup/rollup-android-arm64": "4.9.6", + "@rollup/rollup-darwin-arm64": "4.9.6", + "@rollup/rollup-darwin-x64": "4.9.6", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.6", + "@rollup/rollup-linux-arm64-gnu": "4.9.6", + "@rollup/rollup-linux-arm64-musl": "4.9.6", + "@rollup/rollup-linux-riscv64-gnu": "4.9.6", + "@rollup/rollup-linux-x64-gnu": "4.9.6", + "@rollup/rollup-linux-x64-musl": "4.9.6", + "@rollup/rollup-win32-arm64-msvc": "4.9.6", + "@rollup/rollup-win32-ia32-msvc": "4.9.6", + "@rollup/rollup-win32-x64-msvc": "4.9.6", "fsevents": "~2.3.2" } }, @@ -3218,9 +3793,9 @@ "peer": true }, "node_modules/sass": { - "version": "1.69.5", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.5.tgz", - "integrity": "sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==", + "version": "1.70.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz", + "integrity": "sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -3235,9 +3810,9 @@ } }, "node_modules/sass-loader": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.2.tgz", - "integrity": "sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==", + "version": "13.3.3", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.3.tgz", + "integrity": "sha512-mt5YN2F1MOZr3d/wBRcZxeFgwgkH44wVc2zohO2YF6JiOMkiXe4BYRZpSu2sO1g71mo/j16txzUhsKZlqjVGzA==", "dev": true, "dependencies": { "neo-async": "^2.6.2" @@ -3336,6 +3911,24 @@ "node": ">=8" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -3374,6 +3967,24 @@ "source-map": "^0.6.0" } }, + "node_modules/source-sans-pro": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/source-sans-pro/-/source-sans-pro-3.6.0.tgz", + "integrity": "sha512-C1RFUGu+YASuqpgDRInTM7Y6OwqeWNOuKn7v0P/4Kh66epTI4PYWwPWP5kdA4l/VqzBAWiqoz5dk0trof73R7w==", + "deprecated": "WARNING: This project has been renamed to source-sans. Install using source-sans instead." + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -3386,6 +3997,18 @@ "node": ">=8" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3398,6 +4021,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", + "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==", + "dev": true, + "dependencies": { + "acorn": "^8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3480,6 +4115,30 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/tinybench": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.6.0.tgz", + "integrity": "sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.2.tgz", + "integrity": "sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz", + "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3516,6 +4175,15 @@ "node": ">= 0.8.0" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -3529,9 +4197,9 @@ } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "devOptional": true, "bin": { "tsc": "bin/tsc", @@ -3541,6 +4209,18 @@ "node": ">=14.17" } }, + "node_modules/ufo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", + "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", + "dev": true + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -3588,29 +4268,29 @@ "dev": true }, "node_modules/vite": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", - "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz", + "integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==", "dev": true, "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" + "esbuild": "^0.19.3", + "postcss": "^8.4.32", + "rollup": "^4.2.0" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.0.0 || >=20.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": ">= 14", + "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", @@ -3642,22 +4322,118 @@ } } }, - "node_modules/vue": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz", - "integrity": "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==", + "node_modules/vite-node": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.2.1.tgz", + "integrity": "sha512-fNzHmQUSOY+y30naohBvSW7pPn/xn3Ib/uqm+5wAJQJiqQsU0NBR78XdRJb04l4bOFKjpTWld0XAfkKlrDbySg==", + "dev": true, "dependencies": { - "@vue/compiler-dom": "3.3.4", - "@vue/compiler-sfc": "3.3.4", - "@vue/runtime-dom": "3.3.4", - "@vue/server-renderer": "3.3.4", - "@vue/shared": "3.3.4" + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.2.1.tgz", + "integrity": "sha512-TRph8N8rnSDa5M2wKWJCMnztCZS9cDcgVTQ6tsTFTG/odHJ4l5yNVqvbeDJYJRZ6is3uxaEpFs8LL6QM+YFSdA==", + "dev": true, + "dependencies": { + "@vitest/expect": "1.2.1", + "@vitest/runner": "1.2.1", + "@vitest/snapshot": "1.2.1", + "@vitest/spy": "1.2.1", + "@vitest/utils": "1.2.1", + "acorn-walk": "^8.3.2", + "cac": "^6.7.14", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^1.3.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.1", + "vite": "^5.0.0", + "vite-node": "1.2.1", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "^1.0.0", + "@vitest/ui": "^1.0.0", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.15.tgz", + "integrity": "sha512-jC0GH4KkWLWJOEQjOpkqU1bQsBwf4R1rsFtw5GQJbjHVKWDzO6P0nWWBTmjp1xSemAioDFj1jdaK1qa3DnMQoQ==", + "dependencies": { + "@vue/compiler-dom": "3.4.15", + "@vue/compiler-sfc": "3.4.15", + "@vue/runtime-dom": "3.4.15", + "@vue/server-renderer": "3.4.15", + "@vue/shared": "3.4.15" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/vue-eslint-parser": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.1.tgz", - "integrity": "sha512-Clr85iD2XFZ3lJ52/ppmUDG/spxQu6+MAeHXjjyI4I1NUYZ9xmenQp4N0oaHJhrA8OOxltCVxMRfANGa70vU0g==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.0.tgz", + "integrity": "sha512-7KsNBb6gHFA75BtneJsoK/dbZ281whUIwFYdQxA68QrCrGMXYzUMbPDHGcOQ0OocIVKrWSKWXZ4mL7tonCXoUw==", "dev": true, "dependencies": { "debug": "^4.3.4", @@ -3679,12 +4455,12 @@ } }, "node_modules/vue-i18n": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.4.1.tgz", - "integrity": "sha512-vnQyYE9LBuNOqPpETIcCaGnAyLEqfeIvDcyZ9T+WBCWFTqWw1J8FuF1jfeDwpHBi5JKgAwgXyq1mt8jp/x/GPA==", + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.9.0.tgz", + "integrity": "sha512-xQ5SxszUAqK5n84N+uUyHH/PiQl9xZ24FOxyAaNonmOQgXeN+rD9z/6DStOpOxNFQn4Cgcquot05gZc+CdOujA==", "dependencies": { - "@intlify/core-base": "9.4.1", - "@intlify/shared": "9.4.1", + "@intlify/core-base": "9.9.0", + "@intlify/shared": "9.9.0", "@vue/devtools-api": "^6.5.0" }, "engines": { @@ -3698,9 +4474,9 @@ } }, "node_modules/vue-router": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.2.4.tgz", - "integrity": "sha512-9PISkmaCO02OzPVOMq2w82ilty6+xJmQrarYZDkjZBfl4RvYAlt4PKnEX21oW4KTtWfa9OuO/b3qk1Od3AEdCQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.2.5.tgz", + "integrity": "sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==", "dependencies": { "@vue/devtools-api": "^6.5.0" }, @@ -3712,9 +4488,9 @@ } }, "node_modules/vue-template-compiler": { - "version": "2.7.14", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.14.tgz", - "integrity": "sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==", + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", + "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", "dev": true, "dependencies": { "de-indent": "^1.0.2", @@ -3722,14 +4498,14 @@ } }, "node_modules/vue-tsc": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.8.tgz", - "integrity": "sha512-bSydNFQsF7AMvwWsRXD7cBIXaNs/KSjvzWLymq/UtKE36697sboX4EccSHFVxvgdBlI1frYPc/VMKJNB7DFeDQ==", + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz", + "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", "dev": true, "dependencies": { - "@vue/language-core": "1.8.8", - "@vue/typescript": "1.8.8", - "semver": "^7.3.8" + "@volar/typescript": "~1.11.1", + "@vue/language-core": "1.8.27", + "semver": "^7.5.4" }, "bin": { "vue-tsc": "bin/vue-tsc.js" @@ -3849,6 +4625,22 @@ "node": ">= 8" } }, + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index e28da59..0000000 --- a/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "htwkalender", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} From d7ba571ec725efc480ee1461ccaf6fd307a5f262 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Sun, 21 Jan 2024 18:39:25 +0100 Subject: [PATCH 04/11] fix:#150 removed unused function --- .../fetch/v1/fetchSeminarEventService.go | 31 ++----------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/backend/service/fetch/v1/fetchSeminarEventService.go b/backend/service/fetch/v1/fetchSeminarEventService.go index 6fac5a3..eace23c 100644 --- a/backend/service/fetch/v1/fetchSeminarEventService.go +++ b/backend/service/fetch/v1/fetchSeminarEventService.go @@ -2,43 +2,18 @@ package v1 import ( "fmt" + "github.com/google/uuid" + "github.com/pocketbase/pocketbase/tools/types" + "golang.org/x/net/html" "htwkalender/model" "htwkalender/service/date" - "htwkalender/service/db" "htwkalender/service/fetch" - "net/http" "regexp" "strconv" "strings" "time" - - "github.com/google/uuid" - "github.com/labstack/echo/v5" - "github.com/pocketbase/pocketbase" - "github.com/pocketbase/pocketbase/apis" - "github.com/pocketbase/pocketbase/tools/types" - "golang.org/x/net/html" ) -func GetSeminarEvents(c echo.Context, app *pocketbase.PocketBase) error { - - seminarGroupsLabel := db.GetAllCourses(app) - - seminarGroups := GetSeminarGroupsEventsFromHTML(seminarGroupsLabel) - - seminarGroups = ClearEmptySeminarGroups(seminarGroups) - - seminarGroups = ReplaceEmptyEventNames(seminarGroups) - - dbError, savedRecords := db.SaveSeminarGroupEvents(seminarGroups, app) - - if dbError != nil { - return apis.NewNotFoundError("Events could not be saved", dbError.Error()) - } - - return c.JSON(http.StatusOK, savedRecords) -} - func ReplaceEmptyEventNames(groups []model.SeminarGroup) []model.SeminarGroup { for i, group := range groups { for j, event := range group.Events { From fbf99de175c266b3ee50501fdc89cc44fdadee51 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Sun, 21 Jan 2024 18:46:09 +0100 Subject: [PATCH 05/11] feat:#150 added slog for course fetch --- backend/service/db/dbGroups.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/service/db/dbGroups.go b/backend/service/db/dbGroups.go index 5714f88..40965e4 100644 --- a/backend/service/db/dbGroups.go +++ b/backend/service/db/dbGroups.go @@ -5,6 +5,7 @@ import ( "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/models" "htwkalender/model" + "log/slog" ) func SaveGroups(seminarGroup []model.SeminarGroup, collection *models.Collection, app *pocketbase.PocketBase) ([]*models.Record, error) { @@ -67,8 +68,8 @@ func GetAllCourses(app *pocketbase.PocketBase) []string { // get all rooms from event records in the events collection err := app.Dao().DB().Select("course").From("groups").All(&courses) if err != nil { - print("Error while getting groups from database: ", err) - return nil + slog.Error("Error while getting groups from database: ", err) + return []string{} } var courseArray []string From 32c6f962d560a5e46b8fb2a244c5c89014c9e884 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Sun, 21 Jan 2024 18:51:02 +0100 Subject: [PATCH 06/11] fix:#150 fixed return --- backend/service/db/dbRooms.go | 10 +++++++--- backend/service/room/roomService.go | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/backend/service/db/dbRooms.go b/backend/service/db/dbRooms.go index c344b16..1c49a54 100644 --- a/backend/service/db/dbRooms.go +++ b/backend/service/db/dbRooms.go @@ -23,18 +23,22 @@ func GetRooms(app *pocketbase.PocketBase) ([]string, error) { return nil, err } - roomArray := clearAndSeparateRooms([]struct { + roomArray, err := clearAndSeparateRooms([]struct { Rooms string Course string }(events)) - return roomArray + if err != nil { + return nil, err + } + + return roomArray, nil } func clearAndSeparateRooms(events []struct { Rooms string Course string -}) []string { +}) ([]string, error) { var roomArray []string for _, event := range events { diff --git a/backend/service/room/roomService.go b/backend/service/room/roomService.go index 5fcc80b..e8ff456 100644 --- a/backend/service/room/roomService.go +++ b/backend/service/room/roomService.go @@ -3,6 +3,7 @@ package room import ( "htwkalender/model" "htwkalender/service/db" + "log/slog" "net/http" "github.com/labstack/echo/v5" @@ -13,7 +14,8 @@ func GetRooms(c echo.Context, app *pocketbase.PocketBase) error { rooms, err := db.GetRooms(app) if err != nil { - return c.JSON(http.StatusNotFound, err) + slog.Error("Error getting rooms: ", err) + return c.JSON(http.StatusNotFound, "No rooms found") } else { return c.JSON(http.StatusOK, rooms) } From 95a256929dbfcfc77b188a477f33451184737bc4 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Sun, 21 Jan 2024 19:03:00 +0100 Subject: [PATCH 07/11] fix:#150 fixed anonym test --- backend/service/course/courseFunctions.go | 2 +- backend/service/room/roomService_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/service/course/courseFunctions.go b/backend/service/course/courseFunctions.go index 144bd26..6142dee 100644 --- a/backend/service/course/courseFunctions.go +++ b/backend/service/course/courseFunctions.go @@ -12,7 +12,7 @@ func UpdateCourse(app *pocketbase.PocketBase) { for _, course := range courses { savedEvents, err := events.UpdateModulesForCourse(app, course) if err != nil { - slog.Warn("Update Course: "+course+" failed: ", err.Error()) + slog.Warn("Update Course: "+course+" failed: %v", err) } else { slog.Info("Updated Course: " + course + " with " + strconv.FormatInt(int64(len(savedEvents)), 10) + " events") } diff --git a/backend/service/room/roomService_test.go b/backend/service/room/roomService_test.go index 34345b8..eefd163 100644 --- a/backend/service/room/roomService_test.go +++ b/backend/service/room/roomService_test.go @@ -55,7 +55,7 @@ func Test_anonymizeRooms(t *testing.T) { args: args{ events: []model.Event{}, }, - want: []model.AnonymizedEventDTO{}, + want: nil, }, { name: "anonymize multiple events", From 70170054e8293e5727dadda2151e3aa038205a19 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Mon, 22 Jan 2024 12:17:53 +0100 Subject: [PATCH 08/11] feat:#150 added slog for more functions and improved return signature --- backend/service/addRoute.go | 6 +++- backend/service/fetch/sport/sportFetcher.go | 34 +++++++++++++------ .../fetch/v1/fetchSeminarGroupService.go | 26 ++++++++++---- backend/service/logger/logger.go | 1 - 4 files changed, 48 insertions(+), 19 deletions(-) delete mode 100644 backend/service/logger/logger.go diff --git a/backend/service/addRoute.go b/backend/service/addRoute.go index 1202c87..2e0f4b5 100644 --- a/backend/service/addRoute.go +++ b/backend/service/addRoute.go @@ -49,7 +49,11 @@ func AddRoutes(app *pocketbase.PocketBase) { Method: http.MethodGet, Path: "/api/fetch/groups", Handler: func(c echo.Context) error { - return v1.SeminarGroups(c, app) + groups, err := v1.FetchSeminarGroups(app) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Failed to fetch seminar groups") + } + return c.JSON(http.StatusOK, groups) }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), diff --git a/backend/service/fetch/sport/sportFetcher.go b/backend/service/fetch/sport/sportFetcher.go index 1bff08a..6f7dbb8 100644 --- a/backend/service/fetch/sport/sportFetcher.go +++ b/backend/service/fetch/sport/sportFetcher.go @@ -8,6 +8,8 @@ import ( "htwkalender/model" "htwkalender/service/db" "htwkalender/service/functions" + "io" + "log/slog" "net/http" "regexp" "strconv" @@ -21,9 +23,14 @@ import ( // FetchAndUpdateSportEvents fetches all sport events from the HTWK sport website // it deletes them first and then saves them to the database // It returns all saved events -func FetchAndUpdateSportEvents(app *pocketbase.PocketBase) []model.Event { +func FetchAndUpdateSportEvents(app *pocketbase.PocketBase) ([]model.Event, error) { + + sportCourseLinks, err := fetchAllAvailableSportCourses() + + if err != nil { + return nil, err + } - var sportCourseLinks = fetchAllAvailableSportCourses() sportEntries := fetchHTWKSportCourses(sportCourseLinks) events := formatEntriesToEvents(sportEntries) @@ -43,7 +50,7 @@ func FetchAndUpdateSportEvents(app *pocketbase.PocketBase) []model.Event { // get all events from database where name = Feiertage und lehrveranstaltungsfreie Tage holidays, err := db.GetAllModulesByNameAndDateRange(app, "Feiertage und lehrveranstaltungsfreie Tage", earliestDate, latestDate) if err != nil { - return nil + return nil, err } // remove all events that have same year, month and day as items in holidays @@ -60,17 +67,17 @@ func FetchAndUpdateSportEvents(app *pocketbase.PocketBase) []model.Event { // @TODO: delete and save events in one transaction and it only should delete events that are not in the new events list and save events that are not in the database err = db.DeleteAllEventsForCourse(app, "Sport", functions.GetCurrentSemesterString()) if err != nil { - return nil + return nil, err } // save events to database savedEvents, err := db.SaveEvents(events, app) if err != nil { - return nil + return nil, err } - return savedEvents + return savedEvents, nil } @@ -305,13 +312,14 @@ func checkSemester(date time.Time) string { } // fetch the main page where all sport courses are listed and extract all links to the sport courses -func fetchAllAvailableSportCourses() []string { +func fetchAllAvailableSportCourses() ([]string, error) { var url = "https://sport.htwk-leipzig.de/sportangebote" var doc, err = htmlRequest(url) if err != nil { - return nil + slog.Error("Error while fetching sport courses from webpage", err) + return nil, err } // link list of all sport courses @@ -325,7 +333,7 @@ func fetchAllAvailableSportCourses() []string { } }) - return links + return links, nil } // fetchAllHTWKSportCourses fetches all sport courses from the given links. @@ -372,7 +380,13 @@ func htmlRequest(url string) (*goquery.Document, error) { if err != nil { return nil, err } - defer resp.Body.Close() + defer func(Body io.ReadCloser) { + readErr := Body.Close() + if readErr != nil { + slog.Error("Error while closing response body from html request", readErr) + return + } + }(resp.Body) doc, err := goquery.NewDocumentFromReader(resp.Body) if err != nil { diff --git a/backend/service/fetch/v1/fetchSeminarGroupService.go b/backend/service/fetch/v1/fetchSeminarGroupService.go index 0d39595..2baf0f9 100644 --- a/backend/service/fetch/v1/fetchSeminarGroupService.go +++ b/backend/service/fetch/v1/fetchSeminarGroupService.go @@ -3,13 +3,12 @@ package v1 import ( "encoding/xml" "fmt" - "github.com/labstack/echo/v5" "github.com/pocketbase/pocketbase" - "github.com/pocketbase/pocketbase/apis" "github.com/pocketbase/pocketbase/models" "htwkalender/model" "htwkalender/service/db" "io" + "log/slog" "net/http" ) @@ -41,12 +40,23 @@ func getSeminarHTML(semester string) (string, error) { } -func SeminarGroups(c echo.Context, app *pocketbase.PocketBase) error { +func FetchSeminarGroups(app *pocketbase.PocketBase) ([]*models.Record, error) { var groups []model.SeminarGroup - resultSummer, _ := getSeminarHTML("ss") + resultSummer, err := getSeminarHTML("ss") + + if err != nil { + slog.Error("Error while fetching seminar groups for winter semester", err) + return nil, err + } + resultWinter, _ := getSeminarHTML("ws") + if err != nil { + slog.Error("Error while fetching seminar groups for summer semester", err) + return nil, err + } + groups = parseSeminarGroups(resultSummer) groups = append(groups, parseSeminarGroups(resultWinter)...) @@ -55,16 +65,18 @@ func SeminarGroups(c echo.Context, app *pocketbase.PocketBase) error { collection, dbError := db.FindCollection(app, "groups") if dbError != nil { - return apis.NewNotFoundError("Collection not found", dbError) + slog.Error("Error while searching collection groups", dbError) + return nil, err } var insertedGroups []*models.Record insertedGroups, dbError = db.SaveGroups(groups, collection, app) if dbError != nil { - return apis.NewNotFoundError("Records could not be saved", dbError) + slog.Error("Error while saving groups", dbError) + return nil, err } - return c.JSON(http.StatusOK, insertedGroups) + return insertedGroups, nil } func removeDuplicates(groups []model.SeminarGroup) []model.SeminarGroup { diff --git a/backend/service/logger/logger.go b/backend/service/logger/logger.go deleted file mode 100644 index 90c66f6..0000000 --- a/backend/service/logger/logger.go +++ /dev/null @@ -1 +0,0 @@ -package logger From 1582154d5fa08fee19caa2b5b36fd873e2af811f Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Mon, 22 Jan 2024 15:04:50 +0100 Subject: [PATCH 09/11] feat:#150 extracted functions rewrote error pipe for feed routes --- backend/service/addCalDavRoutes.go | 183 ++++++++++++++++++++++++++++ backend/service/addRoute.go | 111 ++++------------- backend/service/addSchedule.go | 16 +-- backend/service/ical/ical.go | 26 +--- backend/service/room/roomService.go | 37 +++--- 5 files changed, 234 insertions(+), 139 deletions(-) create mode 100644 backend/service/addCalDavRoutes.go diff --git a/backend/service/addCalDavRoutes.go b/backend/service/addCalDavRoutes.go new file mode 100644 index 0000000..04ca9af --- /dev/null +++ b/backend/service/addCalDavRoutes.go @@ -0,0 +1,183 @@ +package service + +import ( + "github.com/labstack/echo/v5" + "github.com/pocketbase/pocketbase" + "github.com/pocketbase/pocketbase/apis" + "github.com/pocketbase/pocketbase/core" + "htwkalender/service/db" + "htwkalender/service/ical" + "io" + "net/http" +) + +func addFeedRoutes(app *pocketbase.PocketBase) { + app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + _, err := e.Router.AddRoute(echo.Route{ + Method: http.MethodPost, + Path: "/api/createFeed", + Handler: func(c echo.Context) error { + requestBody, _ := io.ReadAll(c.Request().Body) + result, err := ical.CreateIndividualFeed(requestBody, app) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Failed to create individual feed") + } + return c.JSON(http.StatusOK, result) + }, + Middlewares: []echo.MiddlewareFunc{ + apis.ActivityLogger(app), + }, + }) + if err != nil { + return err + } + return nil + }) + + app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + _, err := e.Router.AddRoute(echo.Route{ + Method: http.MethodGet, + Path: "/api/feed", + Handler: func(c echo.Context) error { + token := c.QueryParam("token") + result, err := ical.Feed(app, token) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Failed to get feed") + } + var responseWriter = c.Response().Writer + responseWriter.Header().Set("Content-type", "text/calendar") + responseWriter.Header().Set("charset", "utf-8") + responseWriter.Header().Set("Content-Disposition", "inline") + responseWriter.Header().Set("filename", "calendar.ics") + + responseWriter.WriteHeader(http.StatusOK) + _, err = responseWriter.Write([]byte(result)) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Failed to write feed") + } + c.Response().Writer = responseWriter + return nil + }, + Middlewares: []echo.MiddlewareFunc{ + apis.ActivityLogger(app), + }, + }) + if err != nil { + return err + } + return nil + }) + + app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + _, err := e.Router.AddRoute(echo.Route{ + Method: http.MethodHead, + Path: "/api/feed", + Handler: func(c echo.Context) error { + return c.JSON(http.StatusOK, "") + }, + Middlewares: []echo.MiddlewareFunc{ + apis.ActivityLogger(app), + }, + }) + if err != nil { + return err + } + return nil + }) + + app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + _, err := e.Router.AddRoute(echo.Route{ + Method: "PROPFIND", + Path: "/api/feed", + Handler: func(c echo.Context) error { + return c.JSON(http.StatusOK, "") + }, + Middlewares: []echo.MiddlewareFunc{ + apis.ActivityLogger(app), + }, + }) + if err != nil { + return err + } + return nil + }) + + app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + _, err := e.Router.AddRoute(echo.Route{ + Method: http.MethodDelete, + Path: "/api/feed", + Handler: func(c echo.Context) error { + token := c.QueryParam("token") + err := db.DeleteFeed(app.Dao(), token) + if err != nil { + return c.JSON(http.StatusNotFound, err) + } else { + return c.JSON(http.StatusOK, "Feed deleted") + } + }, + Middlewares: []echo.MiddlewareFunc{ + apis.ActivityLogger(app), + }, + }) + if err != nil { + return err + } + return nil + }) + + app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + _, err := e.Router.AddRoute(echo.Route{ + Method: http.MethodPut, + Path: "/api/feed", + Handler: func(c echo.Context) error { + token := c.QueryParam("token") + return c.JSON(http.StatusOK, "token: "+token) + }, + Middlewares: []echo.MiddlewareFunc{ + apis.ActivityLogger(app), + }, + }) + if err != nil { + return err + } + return nil + }) + + // Route for Thunderbird to get calendar server information + // Response is a 200 OK without additional content + app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + _, err := e.Router.AddRoute(echo.Route{ + Method: "PROPFIND", + Path: "/", + Handler: func(c echo.Context) error { + return c.JSON(http.StatusOK, "") + }, + Middlewares: []echo.MiddlewareFunc{ + apis.ActivityLogger(app), + }, + }) + if err != nil { + return err + } + return nil + }) + + // Route for Thunderbird to get calendar server information + // Response is a 200 OK without additional content + app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + _, err := e.Router.AddRoute(echo.Route{ + Method: "PROPFIND", + Path: "/.well-known/caldav", + Handler: func(c echo.Context) error { + return c.JSON(http.StatusOK, "") + }, + Middlewares: []echo.MiddlewareFunc{ + apis.ActivityLogger(app), + }, + }) + if err != nil { + return err + } + return nil + }) +} diff --git a/backend/service/addRoute.go b/backend/service/addRoute.go index 2e0f4b5..35ef5e7 100644 --- a/backend/service/addRoute.go +++ b/backend/service/addRoute.go @@ -1,14 +1,12 @@ package service import ( - "htwkalender/service/db" "htwkalender/service/events" "htwkalender/service/fetch/sport" v1 "htwkalender/service/fetch/v1" v2 "htwkalender/service/fetch/v2" "htwkalender/service/ical" "htwkalender/service/room" - "io" "log/slog" "net/http" @@ -72,8 +70,11 @@ func AddRoutes(app *pocketbase.PocketBase) { Path: "/api/fetch/sports", Handler: func(c echo.Context) error { - sportEvents := sport.FetchAndUpdateSportEvents(app) - return c.JSON(200, sportEvents) + sportEvents, err := sport.FetchAndUpdateSportEvents(app) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Failed to fetch sport events") + } + return c.JSON(http.StatusOK, sportEvents) }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), @@ -91,7 +92,11 @@ func AddRoutes(app *pocketbase.PocketBase) { Method: http.MethodDelete, Path: "/api/modules", Handler: func(c echo.Context) error { - return events.DeleteAllEvents(app) + err := events.DeleteAllEvents(app) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Failed to delete events") + } + return c.JSON(http.StatusOK, "Events deleted") }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), @@ -109,7 +114,11 @@ func AddRoutes(app *pocketbase.PocketBase) { Method: http.MethodGet, Path: "/api/rooms", Handler: func(c echo.Context) error { - return room.GetRooms(c, app) + rooms, err := room.GetRooms(app) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Failed to get rooms") + } + return c.JSON(http.StatusOK, rooms) }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), @@ -129,7 +138,11 @@ func AddRoutes(app *pocketbase.PocketBase) { Handler: func(c echo.Context) error { roomParam := c.QueryParam("room") date := c.QueryParam("date") - return room.GetRoomScheduleForDay(c, app, roomParam, date) + roomSchedule, err := room.GetRoomScheduleForDay(app, roomParam, date) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Failed to get room schedule for day") + } + return c.JSON(http.StatusOK, roomSchedule) }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), @@ -150,30 +163,11 @@ func AddRoutes(app *pocketbase.PocketBase) { roomParam := c.QueryParam("room") to := c.QueryParam("to") from := c.QueryParam("from") - return room.GetRoomSchedule(c, app, roomParam, from, to) - }, - Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), - }, - }) - if err != nil { - return err - } - return nil - }) - - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { - _, err := e.Router.AddRoute(echo.Route{ - Method: http.MethodPost, - Path: "/api/createFeed", - Handler: func(c echo.Context) error { - requestBody, _ := io.ReadAll(c.Request().Body) - result, err := ical.CreateIndividualFeed(requestBody, app) + roomSchedule, err := room.GetRoomSchedule(app, roomParam, from, to) if err != nil { - return c.JSON(http.StatusInternalServerError, err) + return c.JSON(http.StatusInternalServerError, "Failed to get room schedule") } - return c.JSON(http.StatusOK, result) - + return c.JSON(http.StatusOK, roomSchedule) }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), @@ -185,64 +179,7 @@ func AddRoutes(app *pocketbase.PocketBase) { return nil }) - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { - _, err := e.Router.AddRoute(echo.Route{ - Method: http.MethodGet, - Path: "/api/feed", - Handler: func(c echo.Context) error { - token := c.QueryParam("token") - return ical.Feed(c, app, token) - }, - Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), - }, - }) - if err != nil { - return err - } - return nil - }) - - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { - _, err := e.Router.AddRoute(echo.Route{ - Method: http.MethodDelete, - Path: "/api/feed", - Handler: func(c echo.Context) error { - token := c.QueryParam("token") - err := db.DeleteFeed(app.Dao(), token) - if err != nil { - return c.JSON(http.StatusNotFound, err) - } else { - return c.JSON(http.StatusOK, "Feed deleted") - } - }, - Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), - }, - }) - if err != nil { - return err - } - return nil - }) - - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { - _, err := e.Router.AddRoute(echo.Route{ - Method: http.MethodPut, - Path: "/api/feed", - Handler: func(c echo.Context) error { - token := c.QueryParam("token") - return c.JSON(http.StatusOK, "token: "+token) - }, - Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), - }, - }) - if err != nil { - return err - } - return nil - }) + addFeedRoutes(app) app.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ diff --git a/backend/service/addSchedule.go b/backend/service/addSchedule.go index 9eb1a89..3c56d8b 100644 --- a/backend/service/addSchedule.go +++ b/backend/service/addSchedule.go @@ -10,7 +10,6 @@ import ( "htwkalender/service/fetch/sport" v2 "htwkalender/service/fetch/v2" "htwkalender/service/functions/time" - "log" "log/slog" "strconv" ) @@ -38,27 +37,28 @@ func AddSchedules(app *pocketbase.PocketBase) { // Every sunday at 2am fetch all sport events (5 segments - minute, hour, day, month, weekday) "0 2 * * 0" scheduler.MustAdd("fetchSportEvents", "0 3 * * 0", func() { slog.Info("Started fetching sport events schedule") - sport.FetchAndUpdateSportEvents(app) + sportEvents, err := sport.FetchAndUpdateSportEvents(app) + if err != nil { + slog.Error("Failed to fetch and save sport events: %v", err) + } + slog.Info("Successfully fetched " + strconv.FormatInt(int64(len(sportEvents)), 10) + " sport events") }) //delete all events and then fetch all events from remote this should be done every sunday at 2am scheduler.MustAdd("fetchEvents", "0 2 * * 0", func() { err := events.DeleteAllEvents(app) if err != nil { - log.Println(err) + slog.Error("Failed to delete all events: %v", err) } savedEvents, err := v2.FetchAllEventsAndSave(app, time.RealClock{}) if err != nil { - log.Println(err) + slog.Error("Failed to fetch and save events: %v", err) } else { - log.Println("Successfully saved: " + strconv.FormatInt(int64(len(savedEvents)), 10) + " events") + slog.Info("Successfully fetched " + strconv.FormatInt(int64(len(savedEvents)), 10) + " events") } - }) - scheduler.Start() return nil }) - } diff --git a/backend/service/ical/ical.go b/backend/service/ical/ical.go index ad788e6..7377f4b 100644 --- a/backend/service/ical/ical.go +++ b/backend/service/ical/ical.go @@ -5,23 +5,21 @@ import ( "encoding/json" "htwkalender/model" "htwkalender/service/db" - "net/http" "time" "github.com/jordic/goics" - "github.com/labstack/echo/v5" "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/apis" ) const expirationTime = 5 * time.Minute -func Feed(c echo.Context, app *pocketbase.PocketBase, token string) error { +func Feed(app *pocketbase.PocketBase, token string) (string, error) { var result string - var responseWriter = c.Response().Writer + feed, err := db.FindFeedByToken(token, app) if feed == nil && err != nil { - return c.JSON(http.StatusNotFound, err) + return "", err } modules := make(map[string]model.FeedCollection) @@ -34,17 +32,11 @@ func Feed(c echo.Context, app *pocketbase.PocketBase, token string) error { newFeed, err := createFeedForToken(app, modules) if err != nil { - return c.JSON(http.StatusInternalServerError, err) + return "", err } result = newFeed.Content - responseWriter.Header().Set("Content-type", "text/calendar") - responseWriter.Header().Set("charset", "utf-8") - responseWriter.Header().Set("Content-Disposition", "inline") - responseWriter.Header().Set("filename", "calendar.ics") - writeSuccess(result, responseWriter) - c.Response().Writer = responseWriter - return nil + return result, nil } func createFeedForToken(app *pocketbase.PocketBase, modules map[string]model.FeedCollection) (*model.FeedModel, error) { @@ -60,14 +52,6 @@ func createFeedForToken(app *pocketbase.PocketBase, modules map[string]model.Fee return feed, nil } -func writeSuccess(message string, w http.ResponseWriter) { - w.WriteHeader(http.StatusOK) - _, err := w.Write([]byte(message)) - if err != nil { - return - } -} - func CreateIndividualFeed(requestBody []byte, app *pocketbase.PocketBase) (string, error) { var modules []model.FeedCollection diff --git a/backend/service/room/roomService.go b/backend/service/room/roomService.go index e8ff456..47e6bad 100644 --- a/backend/service/room/roomService.go +++ b/backend/service/room/roomService.go @@ -1,45 +1,36 @@ package room import ( + "github.com/pocketbase/pocketbase" "htwkalender/model" "htwkalender/service/db" - "log/slog" - "net/http" - - "github.com/labstack/echo/v5" - "github.com/pocketbase/pocketbase" ) -func GetRooms(c echo.Context, app *pocketbase.PocketBase) error { +func GetRooms(app *pocketbase.PocketBase) ([]string, error) { rooms, err := db.GetRooms(app) - if err != nil { - slog.Error("Error getting rooms: ", err) - return c.JSON(http.StatusNotFound, "No rooms found") + return nil, err } else { - return c.JSON(http.StatusOK, rooms) + return rooms, nil } } -func GetRoomScheduleForDay(c echo.Context, app *pocketbase.PocketBase, room string, date string) error { - - events, err := db.GetRoomScheduleForDay(app, room, date) - +func GetRoomScheduleForDay(app *pocketbase.PocketBase, room string, date string) ([]model.AnonymizedEventDTO, error) { + roomSchedule, err := db.GetRoomScheduleForDay(app, room, date) if err != nil { - return c.JSON(http.StatusInternalServerError, err) - } else { - return c.JSON(http.StatusOK, anonymizeRooms(events)) + return nil, err } + anonymizedRoomSchedule := anonymizeRooms(roomSchedule) + return anonymizedRoomSchedule, nil } -func GetRoomSchedule(c echo.Context, app *pocketbase.PocketBase, room string, from string, to string) error { - events, err := db.GetRoomSchedule(app, room, from, to) - +func GetRoomSchedule(app *pocketbase.PocketBase, room string, from string, to string) ([]model.AnonymizedEventDTO, error) { + roomSchedule, err := db.GetRoomSchedule(app, room, from, to) if err != nil { - return c.JSON(http.StatusInternalServerError, err) - } else { - return c.JSON(http.StatusOK, anonymizeRooms(events)) + return nil, err } + anonymizedRoomSchedule := anonymizeRooms(roomSchedule) + return anonymizedRoomSchedule, nil } // Transform the events to anonymized events throwing away all unnecessary information From 0198e74652a68fd6a3260a85428d82697bca2fbf Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Tue, 23 Jan 2024 18:16:12 +0100 Subject: [PATCH 10/11] feat:#150 rewrite error handling for routes --- backend/service/addCalDavRoutes.go | 68 +++++++++++++------------- backend/service/addRoute.go | 43 ++++++++++------ backend/service/events/eventService.go | 15 ++---- 3 files changed, 66 insertions(+), 60 deletions(-) diff --git a/backend/service/addCalDavRoutes.go b/backend/service/addCalDavRoutes.go index 04ca9af..81fbb3f 100644 --- a/backend/service/addCalDavRoutes.go +++ b/backend/service/addCalDavRoutes.go @@ -68,40 +68,6 @@ func addFeedRoutes(app *pocketbase.PocketBase) { return nil }) - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { - _, err := e.Router.AddRoute(echo.Route{ - Method: http.MethodHead, - Path: "/api/feed", - Handler: func(c echo.Context) error { - return c.JSON(http.StatusOK, "") - }, - Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), - }, - }) - if err != nil { - return err - } - return nil - }) - - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { - _, err := e.Router.AddRoute(echo.Route{ - Method: "PROPFIND", - Path: "/api/feed", - Handler: func(c echo.Context) error { - return c.JSON(http.StatusOK, "") - }, - Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), - }, - }) - if err != nil { - return err - } - return nil - }) - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodDelete, @@ -180,4 +146,38 @@ func addFeedRoutes(app *pocketbase.PocketBase) { } return nil }) + + app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + _, err := e.Router.AddRoute(echo.Route{ + Method: "PROPFIND", + Path: "/api/feed", + Handler: func(c echo.Context) error { + return c.JSON(http.StatusOK, "") + }, + Middlewares: []echo.MiddlewareFunc{ + apis.ActivityLogger(app), + }, + }) + if err != nil { + return err + } + return nil + }) + + app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + _, err := e.Router.AddRoute(echo.Route{ + Method: http.MethodHead, + Path: "/api/feed", + Handler: func(c echo.Context) error { + return c.JSON(http.StatusOK, "") + }, + Middlewares: []echo.MiddlewareFunc{ + apis.ActivityLogger(app), + }, + }) + if err != nil { + return err + } + return nil + }) } diff --git a/backend/service/addRoute.go b/backend/service/addRoute.go index 35ef5e7..da1dcc7 100644 --- a/backend/service/addRoute.go +++ b/backend/service/addRoute.go @@ -26,7 +26,7 @@ func AddRoutes(app *pocketbase.PocketBase) { savedEvents, err := v2.ParseEventsFromRemote(app) if err != nil { slog.Error("Failed to parse events from remote: %v", err) - return c.JSON(http.StatusInternalServerError, "Failed to parse events from remote") + return c.JSON(http.StatusBadRequest, "Failed to parse events from remote") } else { return c.JSON(http.StatusOK, savedEvents) } @@ -49,7 +49,7 @@ func AddRoutes(app *pocketbase.PocketBase) { Handler: func(c echo.Context) error { groups, err := v1.FetchSeminarGroups(app) if err != nil { - return c.JSON(http.StatusInternalServerError, "Failed to fetch seminar groups") + return c.JSON(http.StatusBadRequest, "Failed to fetch seminar groups") } return c.JSON(http.StatusOK, groups) }, @@ -72,7 +72,7 @@ func AddRoutes(app *pocketbase.PocketBase) { sportEvents, err := sport.FetchAndUpdateSportEvents(app) if err != nil { - return c.JSON(http.StatusInternalServerError, "Failed to fetch sport events") + return c.JSON(http.StatusBadRequest, "Failed to fetch sport events") } return c.JSON(http.StatusOK, sportEvents) }, @@ -94,7 +94,7 @@ func AddRoutes(app *pocketbase.PocketBase) { Handler: func(c echo.Context) error { err := events.DeleteAllEvents(app) if err != nil { - return c.JSON(http.StatusInternalServerError, "Failed to delete events") + return c.JSON(http.StatusBadRequest, "Failed to delete events") } return c.JSON(http.StatusOK, "Events deleted") }, @@ -116,7 +116,7 @@ func AddRoutes(app *pocketbase.PocketBase) { Handler: func(c echo.Context) error { rooms, err := room.GetRooms(app) if err != nil { - return c.JSON(http.StatusInternalServerError, "Failed to get rooms") + return c.JSON(http.StatusBadRequest, "Failed to get rooms") } return c.JSON(http.StatusOK, rooms) }, @@ -140,7 +140,8 @@ func AddRoutes(app *pocketbase.PocketBase) { date := c.QueryParam("date") roomSchedule, err := room.GetRoomScheduleForDay(app, roomParam, date) if err != nil { - return c.JSON(http.StatusInternalServerError, "Failed to get room schedule for day") + slog.Error("Failed to get room schedule for day: %v", err) + return c.JSON(http.StatusBadRequest, "Failed to get room schedule for day") } return c.JSON(http.StatusOK, roomSchedule) }, @@ -165,7 +166,8 @@ func AddRoutes(app *pocketbase.PocketBase) { from := c.QueryParam("from") roomSchedule, err := room.GetRoomSchedule(app, roomParam, from, to) if err != nil { - return c.JSON(http.StatusInternalServerError, "Failed to get room schedule") + slog.Error("Failed to get room schedule: %v", err) + return c.JSON(http.StatusBadRequest, "Failed to get room schedule") } return c.JSON(http.StatusOK, roomSchedule) }, @@ -191,9 +193,10 @@ func AddRoutes(app *pocketbase.PocketBase) { modules, err := events.GetModulesForCourseDistinct(app, course, semester) if err != nil { - return c.JSON(400, err) + slog.Error("Failed to get modules for course and semester: %v", err) + return c.JSON(http.StatusBadRequest, "Failed to get modules for course and semester") } else { - return c.JSON(200, modules) + return c.JSON(http.StatusOK, modules) } }, Middlewares: []echo.MiddlewareFunc{ @@ -211,7 +214,12 @@ func AddRoutes(app *pocketbase.PocketBase) { Method: http.MethodGet, Path: "/api/modules", Handler: func(c echo.Context) error { - return events.GetAllModulesDistinct(app, c) + modules, err := events.GetAllModulesDistinct(app) + if err != nil { + slog.Error("Failed to get modules: %v", err) + return c.JSON(http.StatusBadRequest, "Failed to get modules") + } + return c.JSON(http.StatusOK, modules) }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), @@ -231,9 +239,10 @@ func AddRoutes(app *pocketbase.PocketBase) { requestModule := c.QueryParam("uuid") module, err := events.GetModuleByUUID(app, requestModule) if err != nil { - return c.JSON(400, err) + slog.Error("Failed to get module: %v", err) + return c.JSON(http.StatusBadRequest, "Failed to get module") } else { - return c.JSON(200, module) + return c.JSON(http.StatusOK, module) } }, Middlewares: []echo.MiddlewareFunc{ @@ -273,9 +282,10 @@ func AddRoutes(app *pocketbase.PocketBase) { semester := c.QueryParam("semester") err := events.DeleteAllEventsByCourseAndSemester(app, course, semester) if err != nil { - return c.JSON(400, err) + slog.Error("Failed to delete events: %v", err) + return c.JSON(http.StatusBadRequest, "Failed to delete events") } else { - return c.JSON(200, "Events deleted") + return c.JSON(http.StatusBadRequest, "Events deleted") } }, Middlewares: []echo.MiddlewareFunc{ @@ -297,9 +307,10 @@ func AddRoutes(app *pocketbase.PocketBase) { err := ical.MigrateFeedJson(app) if err != nil { - return c.JSON(500, err) + slog.Error("Failed to migrate feeds: %v", err) + return c.JSON(http.StatusInternalServerError, "Failed to migrate feeds") } else { - return c.JSON(200, "Migrated") + return c.JSON(http.StatusOK, "Migrated") } }, Middlewares: []echo.MiddlewareFunc{ diff --git a/backend/service/events/eventService.go b/backend/service/events/eventService.go index d217ffa..f649d22 100644 --- a/backend/service/events/eventService.go +++ b/backend/service/events/eventService.go @@ -1,7 +1,6 @@ package events import ( - "github.com/labstack/echo/v5" "github.com/pocketbase/pocketbase" "htwkalender/model" "htwkalender/service/db" @@ -40,21 +39,17 @@ func replaceEmptyEntry(namedList []Named, replacement string) { // GetAllModulesDistinct returns all modules distinct by name and course from the database // That means you get all modules with duplicates if they have different courses -func GetAllModulesDistinct(app *pocketbase.PocketBase, c echo.Context) error { +func GetAllModulesDistinct(app *pocketbase.PocketBase) ([]model.ModuleDTO, error) { modules, err := db.GetAllModulesDistinctByNameAndCourse(app) - + if err != nil { + return nil, err + } var namedModules []Named for _, module := range modules { namedModules = append(namedModules, &module) } - replaceEmptyEntry(namedModules, "Sonderveranstaltungen") - - if err != nil { - return c.JSON(400, err) - } else { - return c.JSON(200, modules) - } + return modules, nil } func GetModuleByUUID(app *pocketbase.PocketBase, uuid string) (model.Module, error) { From 8a47c1bc21c7bff6d9cb7fc934718981147de115 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Tue, 23 Jan 2024 19:07:12 +0100 Subject: [PATCH 11/11] feat:#150 updated log messages --- backend/main.go | 4 ++-- backend/service/feed/feedFunctions.go | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/backend/main.go b/backend/main.go index 272cba2..9d67b7d 100644 --- a/backend/main.go +++ b/backend/main.go @@ -5,7 +5,7 @@ import ( "github.com/pocketbase/pocketbase/plugins/migratecmd" _ "htwkalender/migrations" "htwkalender/service" - "log" + "log/slog" "os" "strings" ) @@ -27,6 +27,6 @@ func main() { service.AddSchedules(app) if err := app.Start(); err != nil { - log.Fatal(err) + slog.Error("Failed to start app: %v", err) } } diff --git a/backend/service/feed/feedFunctions.go b/backend/service/feed/feedFunctions.go index 853a144..906e36d 100644 --- a/backend/service/feed/feedFunctions.go +++ b/backend/service/feed/feedFunctions.go @@ -1,17 +1,18 @@ package feed import ( + "database/sql" "github.com/pocketbase/dbx" "github.com/pocketbase/pocketbase/daos" database "htwkalender/service/db" localTime "htwkalender/service/functions/time" - "log" + "log/slog" ) func ClearFeeds(db *daos.Dao, months int, clock localTime.Clock) { feeds, err := database.GetAllFeeds(db) if err != nil { - log.Println("CleanFeeds: get all feeds failed") + slog.Error("CleanFeeds: failed to get all feeds", err) return } for _, feed := range feeds { @@ -22,13 +23,13 @@ func ClearFeeds(db *daos.Dao, months int, clock localTime.Clock) { if feedRetrievedTime.Before(timeShift) { // delete feed - sqlResult, err := db.DB().Delete("feeds", dbx.NewExp("id = {:id}", dbx.Params{"id": feed.GetId()})).Execute() + var sqlResult sql.Result + sqlResult, err = db.DB().Delete("feeds", dbx.NewExp("id = {:id}", dbx.Params{"id": feed.GetId()})).Execute() if err != nil { - log.Println("CleanFeeds: delete feed " + feed.GetId() + " failed") - log.Println(err) - log.Println(sqlResult) + slog.Error("CleanFeeds: delete feed "+feed.GetId()+" failed", err) + slog.Error("SQL Result: ", sqlResult) } else { - log.Println("CleanFeeds: delete feed " + feed.GetId() + " successful") + slog.Info("CleanFeeds: delete feed " + feed.GetId() + " successful") } } }