diff --git a/cmd/main.go b/cmd/main.go index 247dcd4..c7369c7 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -21,10 +21,10 @@ func main() { uow := repositories.NewUnitOfWork(); - indexRepo := repositories.NewIndexRepository(*persistence.NewReadContext()) - linkRepo := repositories.NewLinkRepository(*persistence.NewReadContext()) - tagRepo := repositories.NewTagRepository() - noteRepo := repositories.NewNoteRepository(*persistence.NewReadContext()) + indexRepo := repositories.NewIndexRepository(persistence.NewReadContext()) + linkRepo := repositories.NewLinkRepository(persistence.NewReadContext()) + tagRepo := repositories.NewTagRepository(persistence.NewReadContext()) + noteRepo := repositories.NewNoteRepository(persistence.NewReadContext()) tagService := services.NewTagService(tagRepo) linkService := services.NewLinkService(linkRepo) @@ -33,10 +33,13 @@ func main() { server.RegisterHandler("vault/init", vault.NewInitializeHandler(idxr, noteService)) server.RegisterHandler("vault/rebuild", vault.NewRebuildIndexHandler(idxr)) + server.RegisterHandler("note/create", note.NewCreateNoteHandler(uow, tagService, noteRepo)) server.RegisterHandler("note/save", note.NewSaveNoteHandler(uow, noteRepo, tagService, noteService, linkService)) server.RegisterHandler("note/goto", note.NewGotoNoteHandler(noteRepo)) + server.RegisterHandler("completion/link", completion.NewCompleteLinkHandler(linkRepo)) + server.RegisterHandler("completion/tag", completion.NewCompleteTagHandler(tagRepo)) if err := server.Run(os.Stdin, os.Stdout); err != nil { slog.Error("server error", "error", err) diff --git a/core/handlers/completion/complete_tag_handler.go b/core/handlers/completion/complete_tag_handler.go new file mode 100644 index 0000000..b6befaa --- /dev/null +++ b/core/handlers/completion/complete_tag_handler.go @@ -0,0 +1,41 @@ +package completion + +import ( + "context" + "encoding/json" + "log/slog" + + "github.com/KristianJBorgwarth/dendrite.daemon/persistence/repositories" +) + +type completeTagCommand struct { + Query string `json:"query"` +} + +type CompleteTagHandler struct { + tagRepo repositories.ITagRepository +} + +func NewCompleteTagHandler(tr repositories.ITagRepository) *CompleteTagHandler { + return &CompleteTagHandler{tagRepo: tr} +} + +func (h *CompleteTagHandler) Handle(ctx context.Context, raw json.RawMessage) (any, error) { + var cmd completeTagCommand + if err := json.Unmarshal(raw, &cmd); err != nil { + return nil, err + } + + tags, err := h.tagRepo.GetByName(ctx, cmd.Query) + slog.Debug("Got tags", "query", cmd.Query, "count", len(tags)) + if err != nil { + return nil, err + } + + results := make([]string, len(tags)) + for i, tag := range tags { + results[i] = tag.Name() + } + + return results, nil +} diff --git a/dendrite b/dendrite index b3577fe..7a84465 100755 Binary files a/dendrite and b/dendrite differ diff --git a/persistence/read_context.go b/persistence/read_context.go index debbc35..6e2d59a 100644 --- a/persistence/read_context.go +++ b/persistence/read_context.go @@ -7,8 +7,8 @@ import ( type ReadContext struct{} -func NewReadContext() *ReadContext { - return &ReadContext{} +func NewReadContext() ReadContext { + return ReadContext{} } func (r *ReadContext) ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error) { diff --git a/persistence/repositories/tag_repository.go b/persistence/repositories/tag_repository.go index cd0c6f3..b6ba079 100644 --- a/persistence/repositories/tag_repository.go +++ b/persistence/repositories/tag_repository.go @@ -14,12 +14,15 @@ type ITagRepository interface { InsertNoteTags(ctx context.Context, dbCtx persistence.IDbContext, noteTags []*models.NoteTag) error GetByNames(ctx context.Context, dbCtx persistence.IDbContext, names []string) ([]*models.Tag, error) DeleteNoteTags(ctx context.Context, dbCtx persistence.IDbContext, noteID string) error + GetByName(ctx context.Context, tagName string) ([]*models.Tag, error) } -type tagRepository struct{} +type tagRepository struct { + readDBContext persistence.ReadContext +} -func NewTagRepository() ITagRepository { - return &tagRepository{} +func NewTagRepository(rdb persistence.ReadContext) ITagRepository { + return &tagRepository{readDBContext: rdb} } func (r *tagRepository) Insert(ctx context.Context, dbCtx persistence.IDbContext, tags []*models.Tag) error { @@ -56,9 +59,9 @@ func (r *tagRepository) InsertRange(ctx context.Context, dbCtx persistence.IDbCo return err } } - + return nil -} +} func (r *tagRepository) InsertNoteTags(ctx context.Context, dbCtx persistence.IDbContext, noteTags []*models.NoteTag) error { noteTagStmt, err := dbCtx.Prepare(`INSERT INTO note_tag (note_id, tag_id) VALUES (?, ?)`) @@ -108,6 +111,25 @@ func (r *tagRepository) GetByNames(ctx context.Context, dbCtx persistence.IDbCon return tags, nil } +func (r *tagRepository) GetByName(ctx context.Context, tagName string) ([]*models.Tag, error) { + rows, err := r.readDBContext.QueryContext(ctx, `SELECT * FROM tag WHERE name LIKE ?`, "%"+tagName+"%") + if err != nil { + return nil, err + } + defer rows.Close() + + var tags []*models.Tag + for rows.Next() { + var name string + if err := rows.Scan(&name); err != nil { + return nil, err + } + tags = append(tags, models.NewTag(name)) + } + + return tags, nil +} + func (r *tagRepository) DeleteNoteTags(ctx context.Context, dbCtx persistence.IDbContext, noteID string) error { query := "DELETE FROM note_tag WHERE note_id = ?" _, err := dbCtx.ExecContext(ctx, query, noteID) diff --git a/test/test_integration/create_note_handler_test.go b/test/test_integration/create_note_handler_test.go index 66a607d..aeeca2d 100644 --- a/test/test_integration/create_note_handler_test.go +++ b/test/test_integration/create_note_handler_test.go @@ -17,8 +17,8 @@ import ( func newCreateNoteHandler() *note.CreateNoteHandler { return note.NewCreateNoteHandler( repositories.NewUnitOfWork(), - services.NewTagService(repositories.NewTagRepository()), - repositories.NewNoteRepository(*persistence.NewReadContext()), + services.NewTagService(repositories.NewTagRepository(persistence.NewReadContext())), + repositories.NewNoteRepository(persistence.NewReadContext()), ) }