diff --git a/backend/internal/api/handlers.go b/backend/internal/api/handlers.go index db1adcb..d654c94 100644 --- a/backend/internal/api/handlers.go +++ b/backend/internal/api/handlers.go @@ -52,6 +52,11 @@ func (h *Handlers) ListFiles(w http.ResponseWriter, r *http.Request) { return } + // Ensure we always encode an array, never null + if files == nil { + files = []*storage.File{} + } + w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(files) } diff --git a/backend/internal/storage/storage.go b/backend/internal/storage/storage.go index 30032ad..d657ed2 100644 --- a/backend/internal/storage/storage.go +++ b/backend/internal/storage/storage.go @@ -44,23 +44,23 @@ func (s *Storage) List() ([]*File, error) { return nil, fmt.Errorf("failed to read directory: %w", err) } - var files []*File + files := make([]*File, 0) for _, entry := range entries { if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".md") { continue } - + info, err := entry.Info() if err != nil { continue } - + files = append(files, &File{ Name: entry.Name(), Modified: info.ModTime().Unix(), }) } - + logging.Logger.WithField("count", len(files)).Info("Listed files") return files, nil } diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ab09ef2..7f2b85c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -20,7 +20,7 @@ function App() { try { setError(null); const fetchedFiles = await api.list(); - setFiles(fetchedFiles); + setFiles(fetchedFiles ?? []); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load files'); } finally { @@ -56,7 +56,7 @@ function App() { try { setError(null); const file = await api.create(name, '# ' + name.replace('.md', '') + '\n\nStart writing here...'); - setFiles([...files, file]); + setFiles([...(files ?? []), file]); setSelectedFile(file); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to create file'); @@ -72,7 +72,7 @@ function App() { const updated = await api.update(selectedFile.name, content); setSelectedFile(updated); setOriginalContent(content); - setFiles(files.map((f) => (f.name === updated.name ? updated : f))); + setFiles((files ?? []).map((f) => (f.name === updated.name ? updated : f))); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to save file'); } finally { @@ -86,7 +86,7 @@ function App() { try { setError(null); await api.delete(name); - setFiles(files.filter((f) => f.name !== name)); + setFiles((files ?? []).filter((f) => f.name !== name)); if (selectedFile?.name === name) { setSelectedFile(null); } @@ -125,7 +125,7 @@ function App() {
setShowNewDialog(false)} onCreate={handleCreateFile} - existingNames={files.map((f) => f.name)} + existingNames={files?.map((f) => f.name) ?? []} /> {hasUnsavedChanges && (