package note import ( "context" "encoding/json" "log/slog" filehandling "github.com/KristianJBorgwarth/dendrite.daemon/core/file_handling" "github.com/KristianJBorgwarth/dendrite.daemon/core/models" "github.com/KristianJBorgwarth/dendrite.daemon/core/services" "github.com/KristianJBorgwarth/dendrite.daemon/persistence" "github.com/KristianJBorgwarth/dendrite.daemon/persistence/repositories" ) type saveNoteCommand struct { Path string `json:"path"` } type SaveNoteHandler struct { uow *repositories.UnitOfWork linkRepo repositories.ILinkRepository tagService services.ITagService noteService services.INoteService noteRepo repositories.NoteRepository } func NewSaveNoteHandler( uow *repositories.UnitOfWork, linkRepo repositories.ILinkRepository, tagService services.ITagService, noteService services.INoteService, noteRepo repositories.NoteRepository, ) *SaveNoteHandler { return &SaveNoteHandler{uow, linkRepo, tagService, noteService, noteRepo} } func (h *SaveNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (any, error) { var cmd saveNoteCommand slog.Debug("Handling SaveNoteCommand", "raw", string(raw)) if err := json.Unmarshal(raw, &cmd); err != nil { return nil, err } file, err := filehandling.ReadFile(cmd.Path) if err != nil { slog.Debug("Failed to read file", "path", cmd.Path, "error", err) return nil, err } tx, err := h.uow.Begin() if err != nil { return nil, err } defer h.uow.Rollback() note, err := h.noteRepo.GetBySlug(ctx, tx, file.Slug) if err != nil { slog.Debug("Failed to get note by slug", "slug", file.Slug, "error", err) return nil, err } if note == nil { if err := h.handleNewNote(ctx, tx, file); err != nil { return nil, err } } else { if err := h.handleExistingNote(ctx, tx, note, file); err != nil { return nil, err } } if err := h.uow.Commit(); err != nil { return nil, err } return nil, nil } func (h *SaveNoteHandler) handleNewNote( ctx context.Context, dbCtx persistence.IDbContext, file *filehandling.File, ) error { note := models.CreateNote(file.Path, file.Title, file.Slug) slog.Debug("EXTRACTED FILE", "path", file.Path, "title", file.Title, "slug", file.Slug, "links", file.ExtractedLinks, "tags", file.FrontMatter.Tags) if err := h.noteRepo.Insert(ctx, dbCtx, note); err != nil { slog.Debug("Failed to insert new note", "noteID", note.ID(), "error", err) return err } links := models.MapToLinkModel(note.ID(), file.ExtractedLinks) if err := h.linkRepo.Insert(ctx, dbCtx, links); err != nil { slog.Debug("Failed to insert links for new note", "noteID", note.ID(), "error", err) return err } tagModels, err := h.tagService.CreateTags(ctx, dbCtx, file.FrontMatter.Tags) if err != nil { slog.Debug("Failed to create tags for new note", "noteID", note.ID(), "error", err) return err } if err := h.tagService.CreateNoteTags(ctx, dbCtx, note.ID(), tagModels); err != nil { slog.Debug("Failed to insert note tags for new note", "noteID", note.ID(), "error", err) return err } return nil } func (h *SaveNoteHandler) handleExistingNote( ctx context.Context, dbCtx persistence.IDbContext, note *models.Note, file *filehandling.File, ) error { err := h.noteService.DeleteNote(ctx, dbCtx, note.ID()) if err != nil { slog.Debug("Failed to delete existing note relations", "noteID", note.ID(), "error", err) return err } links := models.MapToLinkModel(note.ID(), file.ExtractedLinks) if err = h.linkRepo.Insert(ctx, dbCtx, links); err != nil { slog.Debug("Failed to insert links for existing note", "noteID", note.ID(), "error", err) return err } tagModels, err := h.tagService.CreateTags(ctx, dbCtx, file.FrontMatter.Tags) if err != nil { slog.Debug("Failed to create tags for existing note", "noteID", note.ID(), "error", err) return err } if err = h.tagService.CreateNoteTags(ctx, dbCtx, note.ID(), tagModels); err != nil { slog.Debug("Failed to insert note tags for existing note", "noteID", note.ID(), "error", err) return err } return nil }