Merge pull request #20 from KristianJBorgwarth/ref/fix-di
ref(di): improve di with manual setup and injection in main
This commit is contained in:
commit
a55289f745
10 changed files with 118 additions and 95 deletions
10
cmd/main.go
10
cmd/main.go
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/KristianJBorgwarth/dendrite.daemon/core/handlers/vault"
|
"github.com/KristianJBorgwarth/dendrite.daemon/core/handlers/vault"
|
||||||
"github.com/KristianJBorgwarth/dendrite.daemon/core/logging"
|
"github.com/KristianJBorgwarth/dendrite.daemon/core/logging"
|
||||||
"github.com/KristianJBorgwarth/dendrite.daemon/core/server"
|
"github.com/KristianJBorgwarth/dendrite.daemon/core/server"
|
||||||
|
"github.com/KristianJBorgwarth/dendrite.daemon/persistence/repositories"
|
||||||
_ "modernc.org/sqlite"
|
_ "modernc.org/sqlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -16,9 +17,14 @@ func main() {
|
||||||
logging.Init()
|
logging.Init()
|
||||||
server := server.NewServer()
|
server := server.NewServer()
|
||||||
|
|
||||||
|
uow := repositories.NewUnitOfWork();
|
||||||
|
linkRepo := repositories.NewLinkRepository()
|
||||||
|
tagRepo := repositories.NewTagRepository()
|
||||||
|
noteRepo := repositories.NewNoteRepository()
|
||||||
|
|
||||||
server.RegisterHandler("vault/init", vault.NewInitializeHandler())
|
server.RegisterHandler("vault/init", vault.NewInitializeHandler())
|
||||||
server.RegisterHandler("note/create", note.NewCreateNoteHandler())
|
server.RegisterHandler("note/create", note.NewCreateNoteHandler(uow, tagRepo, noteRepo))
|
||||||
server.RegisterHandler("note/save", note.NewSaveNoteHandler())
|
server.RegisterHandler("note/save", note.NewSaveNoteHandler(uow, linkRepo, tagRepo, noteRepo))
|
||||||
server.RegisterHandler("completion/link", completion.NewCompleteLinkHandler())
|
server.RegisterHandler("completion/link", completion.NewCompleteLinkHandler())
|
||||||
|
|
||||||
if err := server.Run(os.Stdin, os.Stdout); err != nil {
|
if err := server.Run(os.Stdin, os.Stdout); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,17 @@ type createNoteCommand struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateNoteHandler struct {
|
type CreateNoteHandler struct {
|
||||||
uow *repositories.UnitOfWork
|
uow *repositories.UnitOfWork
|
||||||
|
tagRepo repositories.ITagRepository
|
||||||
|
noteRepo repositories.NoteRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCreateNoteHandler() *CreateNoteHandler {
|
func NewCreateNoteHandler(
|
||||||
return &CreateNoteHandler{repositories.NewUnitOfWork()}
|
uow *repositories.UnitOfWork,
|
||||||
|
tagRepo repositories.ITagRepository,
|
||||||
|
noteRepo repositories.NoteRepository,
|
||||||
|
) *CreateNoteHandler {
|
||||||
|
return &CreateNoteHandler{uow, tagRepo, noteRepo}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (any, error) {
|
func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (any, error) {
|
||||||
|
|
@ -47,10 +53,7 @@ func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (an
|
||||||
|
|
||||||
defer h.uow.Rollback()
|
defer h.uow.Rollback()
|
||||||
|
|
||||||
tagRepo := repositories.NewTagRepository(dbCtx)
|
dbTags, err := h.tagRepo.GetByNames(ctx, dbCtx, template.FrontMatter.Tags)
|
||||||
noteRepo := repositories.NewNoteRepository(dbCtx)
|
|
||||||
|
|
||||||
dbTags, err := tagRepo.GetByNames(ctx, template.FrontMatter.Tags)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +72,7 @@ func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (an
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = tagRepo.Insert(ctx, tagModels); err != nil {
|
if err = h.tagRepo.Insert(ctx, dbCtx, tagModels); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,11 +80,11 @@ func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (an
|
||||||
|
|
||||||
note := models.CreateNote(notePath, cmd.Title, template.Slug)
|
note := models.CreateNote(notePath, cmd.Title, template.Slug)
|
||||||
|
|
||||||
if err = noteRepo.Insert(ctx, note); err != nil {
|
if err = h.noteRepo.Insert(ctx, dbCtx, note); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = tagRepo.InsertNoteTags(ctx, note.ID(), utils.Select(tagModels, func(t *models.Tag) string { return t.ID() })); err != nil {
|
if err = h.tagRepo.InsertNoteTags(ctx, dbCtx, note.ID(), utils.Select(tagModels, func(t *models.Tag) string { return t.ID() })); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
filehandling "github.com/KristianJBorgwarth/dendrite.daemon/core/file_handling"
|
filehandling "github.com/KristianJBorgwarth/dendrite.daemon/core/file_handling"
|
||||||
"github.com/KristianJBorgwarth/dendrite.daemon/core/models"
|
"github.com/KristianJBorgwarth/dendrite.daemon/core/models"
|
||||||
|
"github.com/KristianJBorgwarth/dendrite.daemon/persistence"
|
||||||
"github.com/KristianJBorgwarth/dendrite.daemon/persistence/repositories"
|
"github.com/KristianJBorgwarth/dendrite.daemon/persistence/repositories"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -15,11 +16,19 @@ type saveNoteCommand struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SaveNoteHandler struct {
|
type SaveNoteHandler struct {
|
||||||
uow *repositories.UnitOfWork
|
uow *repositories.UnitOfWork
|
||||||
|
linkRepo repositories.ILinkRepository
|
||||||
|
tagRepo repositories.ITagRepository
|
||||||
|
noteRepo repositories.NoteRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSaveNoteHandler() *SaveNoteHandler {
|
func NewSaveNoteHandler(
|
||||||
return &SaveNoteHandler{repositories.NewUnitOfWork()}
|
uow *repositories.UnitOfWork,
|
||||||
|
linkRepo repositories.ILinkRepository,
|
||||||
|
tagRepo repositories.ITagRepository,
|
||||||
|
noteRepo repositories.NoteRepository,
|
||||||
|
) *SaveNoteHandler {
|
||||||
|
return &SaveNoteHandler{uow, linkRepo, tagRepo, noteRepo}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SaveNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (any, error) {
|
func (h *SaveNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (any, error) {
|
||||||
|
|
@ -42,22 +51,19 @@ func (h *SaveNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (any,
|
||||||
}
|
}
|
||||||
|
|
||||||
defer h.uow.Rollback()
|
defer h.uow.Rollback()
|
||||||
noteRepo := repositories.NewNoteRepository(tx)
|
|
||||||
linkRepo := repositories.NewLinkRepository(tx)
|
|
||||||
tagRepo := repositories.NewTagRepository(tx)
|
|
||||||
|
|
||||||
note, err := noteRepo.GetBySlug(ctx, file.Slug)
|
note, err := h.noteRepo.GetBySlug(ctx, tx, file.Slug)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Debug("Failed to get note by slug", "slug", file.Slug, "error", err)
|
slog.Debug("Failed to get note by slug", "slug", file.Slug, "error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if note == nil {
|
if note == nil {
|
||||||
if err := h.handleNewNote(ctx, noteRepo, linkRepo, tagRepo, file); err != nil {
|
if err := h.handleNewNote(ctx, tx, file); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := h.handleExistingNote(ctx, linkRepo, tagRepo, note, file); err != nil {
|
if err := h.handleExistingNote(ctx, tx, note, file); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -70,27 +76,25 @@ func (h *SaveNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (any,
|
||||||
|
|
||||||
func (h *SaveNoteHandler) handleNewNote(
|
func (h *SaveNoteHandler) handleNewNote(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
noteRepo repositories.NoteRepository,
|
dbCtx persistence.IDbContext,
|
||||||
linkRepo repositories.ILinkRepository,
|
|
||||||
tagRepo repositories.ITagRepository,
|
|
||||||
file *filehandling.File,
|
file *filehandling.File,
|
||||||
) error {
|
) error {
|
||||||
note := models.CreateNote(file.Path, file.Title, file.Slug)
|
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)
|
slog.Debug("EXTRACTED FILE", "path", file.Path, "title", file.Title, "slug", file.Slug, "links", file.ExtractedLinks, "tags", file.FrontMatter.Tags)
|
||||||
|
|
||||||
if err := noteRepo.Insert(ctx, note); err != nil {
|
if err := h.noteRepo.Insert(ctx, dbCtx, note); err != nil {
|
||||||
slog.Debug("Failed to insert new note", "noteID", note.ID(), "error", err)
|
slog.Debug("Failed to insert new note", "noteID", note.ID(), "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
links := models.MapToLinkModel(note.ID(), file.ExtractedLinks)
|
links := models.MapToLinkModel(note.ID(), file.ExtractedLinks)
|
||||||
|
|
||||||
if err := linkRepo.Insert(ctx, links); err != nil {
|
if err := h.linkRepo.Insert(ctx, dbCtx, links); err != nil {
|
||||||
slog.Debug("Failed to insert links for new note", "noteID", note.ID(), "error", err)
|
slog.Debug("Failed to insert links for new note", "noteID", note.ID(), "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tagRepo.InsertNoteTags(ctx, note.ID(), file.FrontMatter.Tags); err != nil {
|
if err := h.tagRepo.InsertNoteTags(ctx, dbCtx, note.ID(), file.FrontMatter.Tags); err != nil {
|
||||||
slog.Debug("Failed to insert tags for new note", "noteID", note.ID(), "error", err)
|
slog.Debug("Failed to insert tags for new note", "noteID", note.ID(), "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -98,13 +102,13 @@ func (h *SaveNoteHandler) handleNewNote(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SaveNoteHandler) handleExistingNote(ctx context.Context,
|
func (h *SaveNoteHandler) handleExistingNote(
|
||||||
linkRepo repositories.ILinkRepository,
|
ctx context.Context,
|
||||||
tagRepo repositories.ITagRepository,
|
dbCtx persistence.IDbContext,
|
||||||
note *models.Note,
|
note *models.Note,
|
||||||
file *filehandling.File,
|
file *filehandling.File,
|
||||||
) error {
|
) error {
|
||||||
err := h.deleteExistingNoteRelations(ctx, linkRepo, tagRepo, note.ID())
|
err := h.deleteExistingNoteRelations(ctx, dbCtx, note.ID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Debug("Failed to delete existing note relations", "noteID", note.ID(), "error", err)
|
slog.Debug("Failed to delete existing note relations", "noteID", note.ID(), "error", err)
|
||||||
return err
|
return err
|
||||||
|
|
@ -112,12 +116,12 @@ func (h *SaveNoteHandler) handleExistingNote(ctx context.Context,
|
||||||
|
|
||||||
links := models.MapToLinkModel(note.ID(), file.ExtractedLinks)
|
links := models.MapToLinkModel(note.ID(), file.ExtractedLinks)
|
||||||
|
|
||||||
if err = linkRepo.Insert(ctx, links); err != nil {
|
if err = h.linkRepo.Insert(ctx, dbCtx, links); err != nil {
|
||||||
slog.Debug("Failed to insert links for existing note", "noteID", note.ID(), "error", err)
|
slog.Debug("Failed to insert links for existing note", "noteID", note.ID(), "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = tagRepo.InsertNoteTags(ctx, note.ID(), file.FrontMatter.Tags); err != nil {
|
if err = h.tagRepo.InsertNoteTags(ctx, dbCtx, note.ID(), file.FrontMatter.Tags); err != nil {
|
||||||
slog.Debug("Failed to insert tags for existing note", "noteID", note.ID(), "error", err)
|
slog.Debug("Failed to insert tags for existing note", "noteID", note.ID(), "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -125,11 +129,15 @@ func (h *SaveNoteHandler) handleExistingNote(ctx context.Context,
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SaveNoteHandler) deleteExistingNoteRelations(ctx context.Context, linkRepo repositories.ILinkRepository, tagRepo repositories.ITagRepository, noteID string) error {
|
func (h *SaveNoteHandler) deleteExistingNoteRelations(
|
||||||
if err := linkRepo.Delete(ctx, noteID); err != nil {
|
ctx context.Context,
|
||||||
|
dbCtx persistence.IDbContext,
|
||||||
|
noteID string,
|
||||||
|
) error {
|
||||||
|
if err := h.linkRepo.Delete(ctx, dbCtx, noteID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := tagRepo.DeleteNoteTags(ctx, noteID); err != nil {
|
if err := h.tagRepo.DeleteNoteTags(ctx, dbCtx, noteID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
2
core/services/doc.go
Normal file
2
core/services/doc.go
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
// Package services provides the implementation of the services defined in the API specification.
|
||||||
|
package services
|
||||||
1
core/services/tag_service.go
Normal file
1
core/services/tag_service.go
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
package services
|
||||||
BIN
dendrite
BIN
dendrite
Binary file not shown.
|
|
@ -1,30 +1,28 @@
|
||||||
package repositories
|
package repositories
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/KristianJBorgwarth/dendrite.daemon/core/models"
|
"github.com/KristianJBorgwarth/dendrite.daemon/core/models"
|
||||||
"github.com/KristianJBorgwarth/dendrite.daemon/persistence"
|
"github.com/KristianJBorgwarth/dendrite.daemon/persistence"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ILinkRepository interface {
|
type ILinkRepository interface {
|
||||||
Insert(ctx context.Context, links []*models.Link) error
|
Insert(ctx context.Context, dbContext persistence.IDbContext, links []*models.Link) error
|
||||||
GetByNoteID(ctx context.Context, fromNoteID string) ([]*models.Link, error)
|
GetByNoteID(ctx context.Context, dbContext persistence.IDbContext, fromNoteID string) ([]*models.Link, error)
|
||||||
GetBySlug(ctx context.Context, targetSlug string) ([]*models.Link, error)
|
GetBySlug(ctx context.Context, dbContext persistence.IDbContext, targetSlug string) ([]*models.Link, error)
|
||||||
Search(ctx context.Context, query string) ([]*models.Link, error)
|
Search(ctx context.Context, dbContext persistence.IDbContext, query string) ([]*models.Link, error)
|
||||||
Delete(ctx context.Context, fromNoteID string) error
|
Delete(ctx context.Context, dbContext persistence.IDbContext, fromNoteID string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type linkRepository struct {
|
type linkRepository struct{}
|
||||||
dbContext persistence.IDbContext
|
|
||||||
|
func NewLinkRepository() ILinkRepository {
|
||||||
|
return &linkRepository{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLinkRepository(ctx persistence.IDbContext) ILinkRepository {
|
func (r *linkRepository) Insert(ctx context.Context, dbContext persistence.IDbContext, links []*models.Link) error {
|
||||||
return &linkRepository{dbContext: ctx}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *linkRepository) Insert(ctx context.Context, links []*models.Link) error {
|
|
||||||
if len(links) == 0 {
|
if len(links) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -37,14 +35,14 @@ func (r *linkRepository) Insert(ctx context.Context, links []*models.Link) error
|
||||||
args = append(args, link.ID(), link.FromNoteID(), link.TargetSlug(), link.Raw(), link.Display(), link.Line(), link.Col())
|
args = append(args, link.ID(), link.FromNoteID(), link.TargetSlug(), link.Raw(), link.Display(), link.Line(), link.Col())
|
||||||
}
|
}
|
||||||
|
|
||||||
query := "INSERT OR IGNORE INTO link(id, from_note_id, target_slug, raw, display, line, col) VALUES " + strings.Join(placeholders, ",")
|
query := "INSERT OR IGNORE INTO link(id, from_note_id, target_slug, raw, display, line, col) VALUES " + strings.Join(placeholders, ",")
|
||||||
|
|
||||||
_, err := r.dbContext.ExecContext(ctx, query, args...)
|
_, err := dbContext.ExecContext(ctx, query, args...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *linkRepository) GetByNoteID(ctx context.Context, fromNoteID string) ([]*models.Link, error) {
|
func (r *linkRepository) GetByNoteID(ctx context.Context, dbContext persistence.IDbContext, fromNoteID string) ([]*models.Link, error) {
|
||||||
rows, err := r.dbContext.QueryContext(ctx, "SELECT id, from_note_id, target_slug, raw, display, line, col FROM link WHERE from_note_id = ?", fromNoteID)
|
rows, err := dbContext.QueryContext(ctx, "SELECT id, from_note_id, target_slug, raw, display, line, col FROM link WHERE from_note_id = ?", fromNoteID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -63,8 +61,8 @@ func (r *linkRepository) GetByNoteID(ctx context.Context, fromNoteID string) ([]
|
||||||
return links, nil
|
return links, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *linkRepository) GetBySlug(ctx context.Context, targetSlug string) ([]*models.Link, error) {
|
func (r *linkRepository) GetBySlug(ctx context.Context, dbContext persistence.IDbContext, targetSlug string) ([]*models.Link, error) {
|
||||||
rows, err := r.dbContext.QueryContext(ctx, `SELECT id, from_note_id, target_slug, raw, display, line, col FROM link WHERE target_slug = ?`, targetSlug)
|
rows, err := dbContext.QueryContext(ctx, `SELECT id, from_note_id, target_slug, raw, display, line, col FROM link WHERE target_slug = ?`, targetSlug)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -83,8 +81,8 @@ func (r *linkRepository) GetBySlug(ctx context.Context, targetSlug string) ([]*m
|
||||||
return links, nil
|
return links, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *linkRepository) Search(ctx context.Context, query string) ([]*models.Link, error) {
|
func (r *linkRepository) Search(ctx context.Context, dbContext persistence.IDbContext, query string) ([]*models.Link, error) {
|
||||||
rows, err := r.dbContext.QueryContext(ctx, `SELECT id, from_note_id, target_slug, raw, display, line, col FROM link WHERE raw LIKE ?`, "%"+query+"%")
|
rows, err := dbContext.QueryContext(ctx, `SELECT id, from_note_id, target_slug, raw, display, line, col FROM link WHERE raw LIKE ?`, "%"+query+"%")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -103,7 +101,7 @@ func (r *linkRepository) Search(ctx context.Context, query string) ([]*models.Li
|
||||||
return links, nil
|
return links, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *linkRepository) Delete(ctx context.Context, fromNoteID string) error {
|
func (r *linkRepository) Delete(ctx context.Context, dbContext persistence.IDbContext, fromNoteID string) error {
|
||||||
_, err := r.dbContext.ExecContext(ctx, "DELETE FROM link WHERE from_note_id = ?", fromNoteID)
|
_, err := dbContext.ExecContext(ctx, "DELETE FROM link WHERE from_note_id = ?", fromNoteID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,19 +10,17 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type NoteRepository interface {
|
type NoteRepository interface {
|
||||||
Insert(ctx context.Context, note *models.Note) error
|
Insert(ctx context.Context, dbContext persistence.IDbContext, note *models.Note) error
|
||||||
GetBySlug(ctx context.Context, slug string) (*models.Note, error)
|
GetBySlug(ctx context.Context, dbContext persistence.IDbContext, slug string) (*models.Note, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type noteRepository struct {
|
type noteRepository struct{}
|
||||||
dbContext persistence.IDbContext
|
|
||||||
|
func NewNoteRepository() NoteRepository {
|
||||||
|
return ¬eRepository{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNoteRepository(ctx persistence.IDbContext) NoteRepository {
|
func (r *noteRepository) Insert(ctx context.Context, dbContext persistence.IDbContext, note *models.Note) error {
|
||||||
return ¬eRepository{dbContext: ctx}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *noteRepository) Insert(ctx context.Context, note *models.Note) error {
|
|
||||||
query := `
|
query := `
|
||||||
INSERT INTO note (id, title, path, slug, created_at, updated_at)
|
INSERT INTO note (id, title, path, slug, created_at, updated_at)
|
||||||
VALUES (?, ?, ?, ?, datetime('now'), datetime('now'))
|
VALUES (?, ?, ?, ?, datetime('now'), datetime('now'))
|
||||||
|
|
@ -30,19 +28,19 @@ func (r *noteRepository) Insert(ctx context.Context, note *models.Note) error {
|
||||||
SET title = EXCLUDED.title,
|
SET title = EXCLUDED.title,
|
||||||
path = EXCLUDED.path;
|
path = EXCLUDED.path;
|
||||||
`
|
`
|
||||||
_, err := r.dbContext.ExecContext(ctx, query, note.ID(), note.Title(), note.Path(), note.Slug())
|
_, err := dbContext.ExecContext(ctx, query, note.ID(), note.Title(), note.Path(), note.Slug())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *noteRepository) GetBySlug(ctx context.Context, slug string) (*models.Note, error) {
|
func (r *noteRepository) GetBySlug(ctx context.Context, dbContext persistence.IDbContext, slug string) (*models.Note, error) {
|
||||||
query := `SELECT id, title, path, slug, created_at, updated_at FROM note WHERE slug = ?`
|
query := `SELECT id, title, path, slug, created_at, updated_at FROM note WHERE slug = ?`
|
||||||
row := r.dbContext.QueryRowContext(ctx, query, slug)
|
row := dbContext.QueryRowContext(ctx, query, slug)
|
||||||
|
|
||||||
var id, title, path, createdAt, updatedAt string
|
var id, title, path, createdAt, updatedAt string
|
||||||
err := row.Scan(&id, &title, &path, &slug, &createdAt, &updatedAt)
|
err := row.Scan(&id, &title, &path, &slug, &createdAt, &updatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,21 +9,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type ITagRepository interface {
|
type ITagRepository interface {
|
||||||
Insert(ctx context.Context, tags []*models.Tag) error
|
Insert(ctx context.Context, dbCtx persistence.IDbContext, tags []*models.Tag) error
|
||||||
InsertNoteTags(ctx context.Context, noteID string, tagIDs []string) error
|
InsertNoteTags(ctx context.Context, dbCtx persistence.IDbContext, noteID string, tagIDs []string) error
|
||||||
GetByNames(ctx context.Context, names []string) ([]*models.Tag, error)
|
GetByNames(ctx context.Context, dbCtx persistence.IDbContext, names []string) ([]*models.Tag, error)
|
||||||
DeleteNoteTags(ctx context.Context, noteID string) error
|
DeleteNoteTags(ctx context.Context, dbCtx persistence.IDbContext, noteID string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type tagRepository struct {
|
type tagRepository struct{}
|
||||||
dbContext persistence.IDbContext
|
|
||||||
|
func NewTagRepository() ITagRepository {
|
||||||
|
return &tagRepository{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTagRepository(ctx persistence.IDbContext) ITagRepository {
|
func (r *tagRepository) Insert(ctx context.Context, dbCtx persistence.IDbContext, tags []*models.Tag) error {
|
||||||
return &tagRepository{dbContext: ctx}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *tagRepository) Insert(ctx context.Context, tags []*models.Tag) error {
|
|
||||||
if len(tags) == 0 {
|
if len(tags) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -38,11 +36,11 @@ func (r *tagRepository) Insert(ctx context.Context, tags []*models.Tag) error {
|
||||||
|
|
||||||
query := "INSERT OR IGNORE INTO tag(id, name) VALUES " + strings.Join(placeholders, ",")
|
query := "INSERT OR IGNORE INTO tag(id, name) VALUES " + strings.Join(placeholders, ",")
|
||||||
|
|
||||||
_, err := r.dbContext.ExecContext(ctx, query, args...)
|
_, err := dbCtx.ExecContext(ctx, query, args...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *tagRepository) InsertNoteTags(ctx context.Context ,noteID string, tagIDs []string) error {
|
func (r *tagRepository) InsertNoteTags(ctx context.Context, dbCtx persistence.IDbContext, noteID string, tagIDs []string) error {
|
||||||
if len(tagIDs) == 0 {
|
if len(tagIDs) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +55,7 @@ func (r *tagRepository) InsertNoteTags(ctx context.Context ,noteID string, tagID
|
||||||
|
|
||||||
query := "INSERT OR IGNORE INTO note_tag(note_id, tag_id) VALUES " + strings.Join(placeholders, ",")
|
query := "INSERT OR IGNORE INTO note_tag(note_id, tag_id) VALUES " + strings.Join(placeholders, ",")
|
||||||
|
|
||||||
_, err := r.dbContext.ExecContext(ctx, query, args...)
|
_, err := dbCtx.ExecContext(ctx, query, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +63,7 @@ func (r *tagRepository) InsertNoteTags(ctx context.Context ,noteID string, tagID
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *tagRepository) GetByNames(ctx context.Context, names []string) ([]*models.Tag, error) {
|
func (r *tagRepository) GetByNames(ctx context.Context, dbCtx persistence.IDbContext, names []string) ([]*models.Tag, error) {
|
||||||
if len(names) == 0 {
|
if len(names) == 0 {
|
||||||
return []*models.Tag{}, nil
|
return []*models.Tag{}, nil
|
||||||
}
|
}
|
||||||
|
|
@ -80,7 +78,7 @@ func (r *tagRepository) GetByNames(ctx context.Context, names []string) ([]*mode
|
||||||
|
|
||||||
query := "SELECT id, name FROM tag WHERE name IN (" + strings.Join(placeholders, ",") + ")"
|
query := "SELECT id, name FROM tag WHERE name IN (" + strings.Join(placeholders, ",") + ")"
|
||||||
|
|
||||||
rows, err := r.dbContext.QueryContext(ctx, query, args...)
|
rows, err := dbCtx.QueryContext(ctx, query, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -99,8 +97,8 @@ func (r *tagRepository) GetByNames(ctx context.Context, names []string) ([]*mode
|
||||||
return tags, nil
|
return tags, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *tagRepository) DeleteNoteTags(ctx context.Context, noteID string) error {
|
func (r *tagRepository) DeleteNoteTags(ctx context.Context, dbCtx persistence.IDbContext, noteID string) error {
|
||||||
query := "DELETE FROM note_tag WHERE note_id = ?"
|
query := "DELETE FROM note_tag WHERE note_id = ?"
|
||||||
_, err := r.dbContext.ExecContext(ctx, query, noteID)
|
_, err := dbCtx.ExecContext(ctx, query, noteID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,22 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/KristianJBorgwarth/dendrite.daemon/core/handlers/note"
|
"github.com/KristianJBorgwarth/dendrite.daemon/core/handlers/note"
|
||||||
|
"github.com/KristianJBorgwarth/dendrite.daemon/persistence/repositories"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func newCreateNoteHandler() *note.CreateNoteHandler {
|
||||||
|
return note.NewCreateNoteHandler(
|
||||||
|
repositories.NewUnitOfWork(),
|
||||||
|
repositories.NewTagRepository(),
|
||||||
|
repositories.NewNoteRepository(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func TestCreateNoteHandler_NoTemplate_CreatesNoteFileAndReturnsPath(t *testing.T) {
|
func TestCreateNoteHandler_NoTemplate_CreatesNoteFileAndReturnsPath(t *testing.T) {
|
||||||
// Arrange
|
// Arrange
|
||||||
handler := note.NewCreateNoteHandler()
|
handler := newCreateNoteHandler()
|
||||||
|
|
||||||
vaultPath := Fixture.VaultStore.Config.VaultPath()
|
vaultPath := Fixture.VaultStore.Config.VaultPath()
|
||||||
notePath := filepath.Join(vaultPath, "my-note.md")
|
notePath := filepath.Join(vaultPath, "my-note.md")
|
||||||
|
|
@ -40,7 +49,7 @@ func TestCreateNoteHandler_NoTemplate_CreatesNoteFileAndReturnsPath(t *testing.T
|
||||||
|
|
||||||
func TestCreateNoteHandler_WithTemplate_CreatesNoteFileWithTagsAndReturnsPath(t *testing.T) {
|
func TestCreateNoteHandler_WithTemplate_CreatesNoteFileWithTagsAndReturnsPath(t *testing.T) {
|
||||||
// Arrange
|
// Arrange
|
||||||
handler := note.NewCreateNoteHandler()
|
handler := newCreateNoteHandler()
|
||||||
|
|
||||||
vaultPath := Fixture.VaultStore.Config.VaultPath()
|
vaultPath := Fixture.VaultStore.Config.VaultPath()
|
||||||
templateDir := Fixture.VaultStore.Config.TemplateDirectory()
|
templateDir := Fixture.VaultStore.Config.TemplateDirectory()
|
||||||
|
|
@ -89,7 +98,7 @@ func TestCreateNoteHandler_WithTemplate_CreatesNoteFileWithTagsAndReturnsPath(t
|
||||||
|
|
||||||
func TestCreateNoteHandler_DuplicateSlug_Upserts(t *testing.T) {
|
func TestCreateNoteHandler_DuplicateSlug_Upserts(t *testing.T) {
|
||||||
// Arrange
|
// Arrange
|
||||||
handler := note.NewCreateNoteHandler()
|
handler := newCreateNoteHandler()
|
||||||
|
|
||||||
vaultPath := Fixture.VaultStore.Config.VaultPath()
|
vaultPath := Fixture.VaultStore.Config.VaultPath()
|
||||||
subDir := "dup-dir"
|
subDir := "dup-dir"
|
||||||
|
|
@ -123,7 +132,7 @@ func TestCreateNoteHandler_DuplicateSlug_Upserts(t *testing.T) {
|
||||||
|
|
||||||
func TestCreateNoteHandler_InvalidJSON_ReturnsError(t *testing.T) {
|
func TestCreateNoteHandler_InvalidJSON_ReturnsError(t *testing.T) {
|
||||||
// Arrange
|
// Arrange
|
||||||
handler := note.NewCreateNoteHandler()
|
handler := newCreateNoteHandler()
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
_, err := handler.Handle(Fixture.TestContext, json.RawMessage(`{invalid json}`))
|
_, err := handler.Handle(Fixture.TestContext, json.RawMessage(`{invalid json}`))
|
||||||
|
|
@ -134,7 +143,7 @@ func TestCreateNoteHandler_InvalidJSON_ReturnsError(t *testing.T) {
|
||||||
|
|
||||||
func TestCreateNoteHandler_NonExistentTemplateName_ReturnsError(t *testing.T) {
|
func TestCreateNoteHandler_NonExistentTemplateName_ReturnsError(t *testing.T) {
|
||||||
// Arrange
|
// Arrange
|
||||||
handler := note.NewCreateNoteHandler()
|
handler := newCreateNoteHandler()
|
||||||
|
|
||||||
params, _ := json.Marshal(map[string]any{
|
params, _ := json.Marshal(map[string]any{
|
||||||
"title": "Ghost Note",
|
"title": "Ghost Note",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue