diff --git a/cmd/main.go b/cmd/main.go index d210d4e..a6e1d1d 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -42,6 +42,7 @@ func main() { server.RegisterHandler("completion/link", completion.NewCompleteLinkHandler(linkRepo)) server.RegisterHandler("completion/tag", completion.NewCompleteTagHandler(tagRepo)) + server.RegisterHandler("completion/slug", completion.NewCompleteSlugHandler(noteRepo)) if err := server.Run(os.Stdin, os.Stdout); err != nil { slog.Error("server error", "error", err) diff --git a/core/handlers/completion/complete_slug_handler.go b/core/handlers/completion/complete_slug_handler.go new file mode 100644 index 0000000..4d6deb5 --- /dev/null +++ b/core/handlers/completion/complete_slug_handler.go @@ -0,0 +1,42 @@ +package completion + +import ( + "context" + "encoding/json" + + "github.com/KristianJBorgwarth/dendrite.daemon/persistence/repositories" +) + +type completeSlugCommand struct { + Query string `json:"query"` +} + +type CompleteSlugHandler struct { + noteRepo repositories.INoteRepository +} + +func NewCompleteSlugHandler(nr repositories.INoteRepository) *CompleteSlugHandler { + return &CompleteSlugHandler{noteRepo: nr} +} + +func (h *CompleteSlugHandler) Handle(ctx context.Context, raw json.RawMessage) (any, error) { + var cmd completeSlugCommand + + if err := json.Unmarshal(raw, &cmd); err != nil { + return nil, err + } + + notes, err := h.noteRepo.Search(ctx, cmd.Query) + if err != nil { + return nil, err + } + + slugs := make([]string, len(notes)) + for i, note := range notes { + slugs[i] = note.Slug() + } + + return slugs, nil +} + + diff --git a/dendrite b/dendrite index 7fef66d..26f6b2a 100755 Binary files a/dendrite and b/dendrite differ diff --git a/persistence/repositories/note_repository.go b/persistence/repositories/note_repository.go index 0838b0c..e2f3d9d 100644 --- a/persistence/repositories/note_repository.go +++ b/persistence/repositories/note_repository.go @@ -13,6 +13,7 @@ type INoteRepository interface { Insert(ctx context.Context, dbContext persistence.IDbContext, note *models.Note) error InsertRange(ctx context.Context, dbContext persistence.IDbContext, note []*models.Note) error Update(ctx context.Context, dbContext persistence.IDbContext, noteID, path, title, slug string) error + Search(ctx context.Context, query string) ([]*models.Note, error) GetBySlug(ctx context.Context, slug string) (*models.Note, error) GetByPath(ctx context.Context, path string) (*models.Note, error) GetByTag(ctx context.Context, tag string) ([]*models.Note, error) @@ -162,3 +163,26 @@ func (r *noteRepository) GetAll(ctx context.Context, skip, top int) ([]*models.N return notes, nil } + +func (r *noteRepository) Search(ctx context.Context, query string) ([]*models.Note, error) { + rows, err := r.readDBContext.QueryContext(ctx, ` + SELECT id, title, path, slug, created_at, updated_at + FROM note + WHERE title LIKE ? OR path LIKE ? OR slug LIKE ? + ORDER BY created_at DESC`, "%"+query+"%", "%"+query+"%", "%"+query+"%") + if err != nil { + return nil, err + } + defer rows.Close() + + notes := make([]*models.Note, 0) + for rows.Next() { + var id, title, path, slug, createdAt, updatedAt string + if err := rows.Scan(&id, &title, &path, &slug, &createdAt, &updatedAt); err != nil { + return nil, err + } + notes = append(notes, models.NewNote(id, path, title, slug, createdAt, updatedAt)) + } + + return notes, nil +}