diff --git a/cmd/main.go b/cmd/main.go index 2c2a0a5..9bfb1c8 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -26,18 +26,19 @@ func main() { linkRepo := repositories.NewLinkRepository(persistence.NewReadContext()) tagRepo := repositories.NewTagRepository(persistence.NewReadContext()) noteRepo := repositories.NewNoteRepository(persistence.NewReadContext()) + cfeRepo := repositories.NewCfeRepository(persistence.NewReadContext()) tagService := services.NewTagService(tagRepo) linkService := services.NewLinkService(linkRepo) - noteService := services.NewNoteService(tagRepo, linkRepo, noteRepo) - cfeSvc := services.NewCfeService(repositories.NewCfeRepository(persistence.NewReadContext())) - idxr := services.NewIndexRebuilder(uow, noteRepo, linkRepo, tagRepo, indexRepo ) + noteService := services.NewNoteService(tagRepo, linkRepo, noteRepo, cfeRepo) + cfeSvc := services.NewCfeService(cfeRepo) + idxr := services.NewIndexRebuilder(uow, noteRepo, linkRepo, tagRepo, indexRepo, cfeRepo) server.RegisterHandler("vault/init", vault.NewInitializeHandler(idxr, noteService)) server.RegisterHandler("vault/rebuild", vault.NewRebuildIndexHandler(idxr)) server.RegisterHandler("note/create", note.NewCreateNoteHandler(uow, tagService, noteRepo, cfeSvc)) - server.RegisterHandler("note/save", note.NewSaveNoteHandler(uow, noteRepo, tagService, noteService, linkService)) + server.RegisterHandler("note/save", note.NewSaveNoteHandler(uow, noteRepo, tagService, noteService, linkService, cfeSvc)) server.RegisterHandler("note/delete", note.NewDeleteNoteHandler(uow, tagService, noteService)) server.RegisterHandler("note/goto", note.NewGotoNoteHandler(noteRepo)) server.RegisterHandler("note/backlinks", note.NewGetBackLinksHandler(linkRepo, noteRepo)) diff --git a/core/handlers/note/save_note_handler.go b/core/handlers/note/save_note_handler.go index 1156ba6..37da6e9 100644 --- a/core/handlers/note/save_note_handler.go +++ b/core/handlers/note/save_note_handler.go @@ -20,6 +20,7 @@ type SaveNoteHandler struct { tagService services.ITagService noteService services.INoteService linkService services.ILinkService + cfeSvc services.ICfeService } func NewSaveNoteHandler( @@ -28,8 +29,9 @@ func NewSaveNoteHandler( ts services.ITagService, ns services.INoteService, ls services.ILinkService, + cfs services.ICfeService, ) *SaveNoteHandler { - return &SaveNoteHandler{uow, nr, ts, ns, ls} + return &SaveNoteHandler{uow, nr, ts, ns, ls, cfs} } func (h *SaveNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (any, error) { @@ -84,6 +86,10 @@ func (h *SaveNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (any, return nil, err } + if err = h.cfeSvc.AddCfe(ctx, tx, note.ID(), file.FrontMatter.Custom); err != nil { + return nil, err + } + if err := h.uow.Commit(); err != nil { return nil, err } diff --git a/core/models/mappers.go b/core/models/mappers.go index 0f0c21e..7aa9a22 100644 --- a/core/models/mappers.go +++ b/core/models/mappers.go @@ -1,6 +1,11 @@ package models -import filehandling "github.com/KristianJBorgwarth/dendrite.daemon/core/file_handling" +import ( + "errors" + "log/slog" + + filehandling "github.com/KristianJBorgwarth/dendrite.daemon/core/file_handling" +) func MapToLinkModel(noteID string, extractedLinks []*filehandling.ExtractedLink) []*Link { var links []*Link @@ -10,20 +15,23 @@ func MapToLinkModel(noteID string, extractedLinks []*filehandling.ExtractedLink) return links } -func MapToCfe(noteID string, extractedCfe map[string]any) []*CustomFronMatter { +func MapToCfe(noteID string, extractedCfe map[string]any) ([]*CustomFronMatter, error) { var cfe []*CustomFronMatter for key, value := range extractedCfe { if valueStr, ok := value.(string); ok { cfe = append(cfe, NewCustomFrontMatter(noteID, key, valueStr)) continue - } else if valueArr, ok := value.([]string); ok { + } else if valueArr, ok := value.([]any); ok { for _, v := range valueArr { - cfe = append(cfe, NewCustomFrontMatter(noteID, key, v)) + if s, ok := v.(string); ok { + cfe = append(cfe, NewCustomFrontMatter(noteID, key, s)) + } } continue } else { - cfe = append(cfe, NewCustomFrontMatter(noteID, key, "")) + slog.Warn("Unsupported CFE value type, skipping", "key", key, "value", value) + return nil, errors.New("unsupported CFE value type") } } - return cfe + return cfe, nil } diff --git a/core/services/cfe_service.go b/core/services/cfe_service.go index 53c0316..c86c691 100644 --- a/core/services/cfe_service.go +++ b/core/services/cfe_service.go @@ -29,6 +29,9 @@ func (s *cfeService) AddCfe( if len(cfe) == 0 { return nil } - cfeModels := models.MapToCfe(noteID, cfe) + cfeModels, err := models.MapToCfe(noteID, cfe) + if err != nil { + return err + } return s.cfeRepo.InsertRange(ctx, dbCtx, cfeModels) } diff --git a/core/services/index_rebuilder.go b/core/services/index_rebuilder.go index e810b91..18423af 100644 --- a/core/services/index_rebuilder.go +++ b/core/services/index_rebuilder.go @@ -15,6 +15,14 @@ import ( "github.com/KristianJBorgwarth/dendrite.daemon/persistence/store" ) +type index struct { + notes []*models.Note + links []*models.Link + cfe []*models.CustomFronMatter + tags []*models.Tag + noteTags []*models.NoteTag +} + type IIndexRebuilder interface { RebuildIndex(ctx context.Context, vaultRoot string) error } @@ -25,6 +33,7 @@ type indexRebuilder struct { linkRepo repositories.ILinkRepository tagRepo repositories.ITagRepository indexRepo repositories.IIndexRepository + cfeRepo repositories.ICfeRepository } func NewIndexRebuilder( @@ -33,6 +42,7 @@ func NewIndexRebuilder( linkRepo repositories.ILinkRepository, tagRepo repositories.ITagRepository, indexRepo repositories.IIndexRepository, + cfeRepo repositories.ICfeRepository, ) *indexRebuilder { return &indexRebuilder{ uow: uow, @@ -40,6 +50,7 @@ func NewIndexRebuilder( linkRepo: linkRepo, tagRepo: tagRepo, indexRepo: indexRepo, + cfeRepo: cfeRepo, } } @@ -54,13 +65,16 @@ func (r *indexRebuilder) RebuildIndex(ctx context.Context, vaultRoot string) err return err } - notes, links, tags, noteTags := r.buildDBModels(files) + index, err := r.buildDBModels(files) + if err != nil { + return err + } if err = r.indexRepo.WipeIndex(ctx, dbctx); err != nil { return err } - if err = r.buildIndex(ctx, dbctx, notes, links, tags, noteTags); err != nil { + if err = r.buildIndex(ctx, dbctx, index); err != nil { return err } @@ -74,24 +88,25 @@ func (r *indexRebuilder) RebuildIndex(ctx context.Context, vaultRoot string) err func (r *indexRebuilder) buildIndex( ctx context.Context, dbctx persistence.IDbContext, - notes []*models.Note, - links []*models.Link, - tags []*models.Tag, - noteTags []*models.NoteTag, + index *index, ) error { - if err := r.noteRepo.InsertRange(ctx, dbctx, notes); err != nil { + if err := r.noteRepo.InsertRange(ctx, dbctx, index.notes); err != nil { return err } - if err := r.linkRepo.InsertRange(ctx, dbctx, links); err != nil { + if err := r.linkRepo.InsertRange(ctx, dbctx, index.links); err != nil { return err } - if err := r.tagRepo.InsertRange(ctx, dbctx, tags); err != nil { + if err := r.tagRepo.InsertRange(ctx, dbctx, index.tags); err != nil { return err } - if err := r.tagRepo.InsertNoteTags(ctx, dbctx, noteTags); err != nil { + if err := r.tagRepo.InsertNoteTags(ctx, dbctx, index.noteTags); err != nil { + return err + } + + if err := r.cfeRepo.InsertRange(ctx, dbctx, index.cfe); err != nil { return err } @@ -146,9 +161,10 @@ func (r *indexRebuilder) IsValidDirectory(path string) bool { return true } -func (r *indexRebuilder) buildDBModels(files []*filehandling.File) ([]*models.Note, []*models.Link, []*models.Tag, []*models.NoteTag) { +func (r *indexRebuilder) buildDBModels(files []*filehandling.File) (*index, error) { var notes []*models.Note var links []*models.Link + var cfe []*models.CustomFronMatter tagMap := make(map[string]*models.Tag) var noteTags []*models.NoteTag @@ -160,6 +176,12 @@ func (r *indexRebuilder) buildDBModels(files []*filehandling.File) ([]*models.No } noteTags = append(noteTags, models.CreateNoteTags(note.ID(), file.FrontMatter.Tags)...) links = append(links, models.MapToLinkModel(note.ID(), file.ExtractedLinks)...) + + mappedCfe, err := models.MapToCfe(note.ID(), file.FrontMatter.Custom) + if err != nil { + return nil, err + } + cfe = append(cfe, mappedCfe...) } tags := make([]*models.Tag, 0, len(tagMap)) @@ -167,5 +189,11 @@ func (r *indexRebuilder) buildDBModels(files []*filehandling.File) ([]*models.No tags = append(tags, tag) } - return notes, links, tags, noteTags + return &index{ + notes: notes, + links: links, + tags: tags, + noteTags: noteTags, + cfe: cfe, + }, nil } diff --git a/core/services/note_service.go b/core/services/note_service.go index 513050b..18a3a09 100644 --- a/core/services/note_service.go +++ b/core/services/note_service.go @@ -21,14 +21,16 @@ type noteService struct { tagRepo repositories.ITagRepository linkRepo repositories.ILinkRepository noteRepo repositories.INoteRepository + cfeRepo repositories.ICfeRepository } func NewNoteService( tagRepo repositories.ITagRepository, linkRepo repositories.ILinkRepository, noteRepo repositories.INoteRepository, + cfeRepo repositories.ICfeRepository, ) INoteService { - return ¬eService{tagRepo, linkRepo, noteRepo} + return ¬eService{tagRepo, linkRepo, noteRepo, cfeRepo} } func (s *noteService) CreateNote(ctx context.Context, dbCtx persistence.IDbContext, path, title, slug string) (*models.Note, error) { @@ -56,6 +58,10 @@ func (s *noteService) DeleteNoteMetaData(ctx context.Context, dbCtx persistence. return err } + if err := s.cfeRepo.Delete(ctx, dbCtx, noteID); err != nil { + return err + } + return nil } diff --git a/persistence/repositories/cfe_repository.go b/persistence/repositories/cfe_repository.go index ed704b1..bc9f59c 100644 --- a/persistence/repositories/cfe_repository.go +++ b/persistence/repositories/cfe_repository.go @@ -9,6 +9,7 @@ import ( type ICfeRepository interface { InsertRange(ctx context.Context, dbContext persistence.IDbContext, cfe []*models.CustomFronMatter) error + Delete(ctx context.Context, dbContext persistence.IDbContext, noteID string) error } type cfeRepository struct { @@ -26,7 +27,7 @@ func (r *cfeRepository) InsertRange( ) error { statement, err := dbCtx.Prepare( `INSERT INTO custom_frontmatter (note_id, key, value) - VALUES (?, ?, ?) ON CONFLICT DO NOTHING;`,) + VALUES (?, ?, ?) ON CONFLICT DO NOTHING;`) if err != nil { return err } @@ -39,3 +40,20 @@ func (r *cfeRepository) InsertRange( return nil } + +func (r *cfeRepository) Delete( + ctx context.Context, + dbCtx persistence.IDbContext, + noteID string, +) error { + statement, err := dbCtx.Prepare(`DELETE FROM custom_frontmatter WHERE note_id = ?;`) + if err != nil { + return err + } + + if _, err := statement.ExecContext(ctx, noteID); err != nil { + return err + } + + return nil +} diff --git a/persistence/repositories/index_repository.go b/persistence/repositories/index_repository.go index e587a0c..dd53b81 100644 --- a/persistence/repositories/index_repository.go +++ b/persistence/repositories/index_repository.go @@ -22,7 +22,8 @@ func (r *indexRepository) WipeIndex(ctx context.Context, dbContext persistence.I cmd := `DELETE FROM note; DELETE FROM tag; DELETE FROM note_tag; - DELETE FROM link;` + DELETE FROM link; + DELETE FROM custom_frontmatter;` _, err := dbContext.ExecContext(ctx, cmd) return err