fix: nil slice -> empty slice in list API responses

Backend:
- ListStorageJobs, ListSambaShares, ListNFSExports, ListUsers,
  ListDirty, ListApplyLog, ListWatchedMounts: initialize with
  make([]T, 0) instead of var x []T to avoid JSON null on empty.
  Fixes "Cannot read properties of null" crash on /storage.

Frontend:
- Storage.tsx: defensive setJobs(res.jobs ?? []) to guard against
  API returning null.

Tests:
- Add TestListStorageJobsEmptyReturnsSlice.

Version: 0.7.1
This commit is contained in:
2026-07-06 23:31:03 -04:00
parent 27a52d2986
commit d3d59b4e45
9 changed files with 37 additions and 9 deletions
+3 -3
View File
@@ -114,7 +114,7 @@ func (d *DB) ListDirty() ([]DirtyModule, error) {
}
defer rows.Close()
var modules []DirtyModule
modules := make([]DirtyModule, 0)
for rows.Next() {
var module DirtyModule
var markedAt string
@@ -158,7 +158,7 @@ func (d *DB) ListApplyLog(limit int) ([]ApplyLogEntry, error) {
}
defer rows.Close()
var entries []ApplyLogEntry
entries := make([]ApplyLogEntry, 0)
for rows.Next() {
var entry ApplyLogEntry
var success int
@@ -182,7 +182,7 @@ func (d *DB) ListSambaShares() ([]SambaShare, error) {
}
defer rows.Close()
var shares []SambaShare
shares := make([]SambaShare, 0)
for rows.Next() {
share, err := scanSambaShare(rows)
if err != nil {
+1 -1
View File
@@ -77,7 +77,7 @@ func (d *DB) ListNFSExports() ([]NFSExport, error) {
}
defer rows.Close()
var exports []NFSExport
exports := make([]NFSExport, 0)
for rows.Next() {
export, err := scanNFSExport(rows)
if err != nil {
+1 -1
View File
@@ -170,7 +170,7 @@ func (d *DB) ListStorageJobs(limit int) ([]StorageJob, error) {
}
defer rows.Close()
var jobs []StorageJob
jobs := make([]StorageJob, 0)
for rows.Next() {
j, err := scanStorageJob(rows)
if err != nil {
+27
View File
@@ -0,0 +1,27 @@
package db
import (
"testing"
)
func TestListStorageJobsEmptyReturnsSlice(t *testing.T) {
d, err := Open(":memory:")
if err != nil {
t.Fatalf("open db: %v", err)
}
defer d.Close()
if err := d.Migrate(); err != nil {
t.Fatalf("migrate: %v", err)
}
jobs, err := d.ListStorageJobs(50)
if err != nil {
t.Fatalf("ListStorageJobs: %v", err)
}
if jobs == nil {
t.Error("ListStorageJobs returned nil, want empty slice")
}
if len(jobs) != 0 {
t.Errorf("len(jobs) = %d, want 0", len(jobs))
}
}
+1 -1
View File
@@ -53,7 +53,7 @@ func (d *DB) ListUsers() ([]User, error) {
}
defer rows.Close()
var users []User
users := make([]User, 0)
for rows.Next() {
user, err := scanUser(rows)
if err != nil {
+1 -1
View File
@@ -24,7 +24,7 @@ func (d *DB) ListWatchedMounts() ([]WatchedMount, error) {
}
defer rows.Close()
var mounts []WatchedMount
mounts := make([]WatchedMount, 0)
for rows.Next() {
m, err := scanWatchedMount(rows)
if err != nil {