Merge pull request #13 from KristianJBorgwarth/feat/improve-crud-api

feat: improve create api
This commit is contained in:
Kristian 2026-04-06 16:19:47 +02:00 committed by GitHub
commit f9b9a06b70
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 51 additions and 28 deletions

View file

@ -3,6 +3,7 @@ package handlers
import (
"context"
"encoding/json"
"path/filepath"
"github.com/KristianJBorgwarth/dendrite.daemon/core/frontmatter"
"github.com/KristianJBorgwarth/dendrite.daemon/core/models"
@ -35,7 +36,12 @@ func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (an
slug := frontmatter.Slugify(cmd.Title)
templatePath := store.GetVaultStore().GetTemplatePath(cmd.TemplateName)
var templatePath string
if cmd.TemplateName != "" {
templatePath = store.GetVaultStore().GetTemplatePath(cmd.TemplateName)
}
notePath := filepath.Join(store.GetVaultStore().Config.VaultPath(), cmd.Directory, slug+".md")
data, err := template.RenderTemplate(templatePath, cmd.Title, slug)
if err != nil {
@ -82,7 +88,7 @@ func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (an
tagModels = append(tagModels, dbTags...)
note := models.CreateNote(cmd.Directory, cmd.Title, slug)
note := models.CreateNote(notePath, cmd.Title, slug)
if err = noteRepo.Upsert(ctx, note); err != nil {
return nil, err
@ -92,11 +98,11 @@ func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (an
return nil, err
}
h.uow.FileStore.Stage(cmd.Directory, data)
h.uow.FileStore.Stage(notePath, data)
if err = h.uow.Commit(); err != nil {
return nil, err
}
return cmd.Directory, nil
return notePath, nil
}

BIN
dendrite

Binary file not shown.

View file

@ -1,6 +1,8 @@
package store
import "os"
import (
"os"
)
type FileStore struct {
staged []stagedFile
@ -28,7 +30,6 @@ func (fs *FileStore) Flush() error {
if fs.fileExists(file.path) {
continue
}
if err := os.WriteFile(file.path, file.data, 0o644); err != nil {
for _, path := range writtenPaths {
_ = os.Remove(path)
@ -58,4 +59,3 @@ func (fs *FileStore) fileExists(path string) bool {
_, err := os.Stat(path)
return err == nil
}

View file

@ -15,10 +15,12 @@ func TestCreateNoteHandler_NoTemplate_CreatesNoteFileAndReturnsPath(t *testing.T
// Arrange
handler := handlers.NewCreateNoteHandler()
notePath := filepath.Join(t.TempDir(), "my-note.md")
vaultPath := Fixture.VaultStore.Config.VaultPath()
notePath := filepath.Join(vaultPath, "my-note.md")
params, _ := json.Marshal(map[string]any{
"title": "My Note",
"path": notePath,
"templateName": "",
"directory": "",
})
// Act
@ -39,16 +41,23 @@ func TestCreateNoteHandler_NoTemplate_CreatesNoteFileAndReturnsPath(t *testing.T
func TestCreateNoteHandler_WithTemplate_CreatesNoteFileWithTagsAndReturnsPath(t *testing.T) {
// Arrange
handler := handlers.NewCreateNoteHandler()
dir := t.TempDir()
templatePath := filepath.Join(dir, "template.md")
vaultPath := Fixture.VaultStore.Config.VaultPath()
templateDir := Fixture.VaultStore.Config.TemplateDirectory()
require.NoError(t, os.MkdirAll(templateDir, 0o755))
templatePath := filepath.Join(templateDir, "template.md")
require.NoError(t, os.WriteFile(templatePath, []byte("---\ntitle: Template\ntags: [go, testing]\n---\n"), 0o644))
defer os.Remove(templatePath)
notePath := filepath.Join(dir, "templated-note.md")
subDir := "subdir"
require.NoError(t, os.MkdirAll(filepath.Join(vaultPath, subDir), 0o755))
defer os.RemoveAll(filepath.Join(vaultPath, subDir))
notePath := filepath.Join(vaultPath, subDir, "templated-note.md")
params, _ := json.Marshal(map[string]any{
"title": "Templated Note",
"path": notePath,
"templatePath": templatePath,
"templateName": "template.md",
"directory": subDir,
})
// Act
@ -80,17 +89,21 @@ func TestCreateNoteHandler_WithTemplate_CreatesNoteFileWithTagsAndReturnsPath(t
func TestCreateNoteHandler_DuplicateSlug_Upserts(t *testing.T) {
// Arrange
dir := t.TempDir()
handler := handlers.NewCreateNoteHandler()
vaultPath := Fixture.VaultStore.Config.VaultPath()
subDir := "dup-dir"
require.NoError(t, os.MkdirAll(filepath.Join(vaultPath, subDir), 0o755))
defer os.RemoveAll(filepath.Join(vaultPath, subDir))
path1 := filepath.Join(dir, "dup-note.md")
params1, _ := json.Marshal(map[string]any{"title": "Dup Note", "path": path1})
params1, _ := json.Marshal(map[string]any{"title": "Dup Note", "templateName": "", "directory": subDir})
_, err := handler.Handle(Fixture.TestContext, params1)
require.NoError(t, err)
path2 := filepath.Join(dir, "dup-note-moved.md")
params2, _ := json.Marshal(map[string]any{"title": "Dup Note", "path": path2})
subDir2 := "dup-dir-moved"
require.NoError(t, os.MkdirAll(filepath.Join(vaultPath, subDir2), 0o755))
defer os.RemoveAll(filepath.Join(vaultPath, subDir2))
params2, _ := json.Marshal(map[string]any{"title": "Dup Note", "templateName": "", "directory": subDir2})
// Act
_, err = handler.Handle(Fixture.TestContext, params2)
@ -102,16 +115,16 @@ func TestCreateNoteHandler_DuplicateSlug_Upserts(t *testing.T) {
require.NoError(t, Fixture.DB.QueryRow(`SELECT COUNT(*) FROM notes WHERE slug = ?`, "dup-note").Scan(&count))
assert.Equal(t, 1, count)
expectedPath := filepath.Join(vaultPath, subDir2, "dup-note.md")
var path string
require.NoError(t, Fixture.DB.QueryRow(`SELECT path FROM notes WHERE slug = ?`, "dup-note").Scan(&path))
assert.Equal(t, path2, path)
assert.Equal(t, expectedPath, path)
}
func TestCreateNoteHandler_InvalidJSON_ReturnsError(t *testing.T) {
// Arrange
handler := handlers.NewCreateNoteHandler()
// Act
_, err := handler.Handle(Fixture.TestContext, json.RawMessage(`{invalid json}`))
@ -119,14 +132,14 @@ func TestCreateNoteHandler_InvalidJSON_ReturnsError(t *testing.T) {
assert.Error(t, err)
}
func TestCreateNoteHandler_NonExistentTemplatePath_ReturnsError(t *testing.T) {
func TestCreateNoteHandler_NonExistentTemplateName_ReturnsError(t *testing.T) {
// Arrange
handler := handlers.NewCreateNoteHandler()
params, _ := json.Marshal(map[string]any{
"title": "Ghost Note",
"path": filepath.Join(t.TempDir(), "ghost.md"),
"templatePath": "/non/existent/template.md",
"templateName": "non-existent-template",
"directory": "",
})
// Act

View file

@ -5,11 +5,13 @@ import (
"database/sql"
"encoding/json"
"os"
"path"
"path/filepath"
"testing"
"github.com/KristianJBorgwarth/dendrite.daemon/core/rpc"
"github.com/KristianJBorgwarth/dendrite.daemon/persistence"
"github.com/KristianJBorgwarth/dendrite.daemon/persistence/store"
_ "modernc.org/sqlite"
)
@ -17,6 +19,7 @@ type DBFixture struct {
DB *sql.DB
DBPath string
TestContext context.Context
VaultStore *store.VaultStore
}
func NewDBFixture() *DBFixture {
@ -35,6 +38,7 @@ func NewDBFixture() *DBFixture {
DB: dbContext.DB,
DBPath: dbPath,
TestContext: context.Background(),
VaultStore: store.NewVaultStore(vaultPath, path.Join(vaultPath, "templates")),
}
}