Skip to content

parity(storage): preserve sortBy defaults when list() receives partial sortBy [from supabase-js] #266

Description

@grdsdev

Warning

Auto-generated parity issue — may be a false positive.

This issue was created automatically by /sync-sdk-parity from a heuristic
analysis of recent supabase-js commits. The tooling has limited insight
into language-specific idioms and may have:

  • misidentified a JS-only change as cross-language relevant,
  • missed an existing implementation in this SDK under a different name,
  • or proposed an API shape that doesn't fit this language's conventions.

It is the SDK author's responsibility to validate the need before
implementing.
If this change does not apply to this SDK, please close the
issue with a short note explaining why.


SDK Parity: C# implementation needed

A change was made in supabase-js that may need to be implemented in this repository for SDK parity. Please confirm applicability before starting work.

Reference Implementation (supabase-js)

What Changed

storage.from('bucket').list() has default search options including sortBy: { column: 'name', order: 'asc' }. When a caller provides a partial sortBy (e.g. only column, omitting order), the shallow merge replaced the entire sortBy default, losing the order field. The Storage server requires both column and order, so a missing order caused a 400 error.

The fix deep-merges sortBy so overriding only one of its keys preserves the default for the other.

Code Reference

// Before (JS) — shallow merge loses sortBy.order default
const body = { ...DEFAULT_SEARCH_OPTIONS, ...options, prefix: path || '' }

// After (JS) — deep-merge sortBy specifically
const sortBy = options?.sortBy
  ? { ...DEFAULT_SEARCH_OPTIONS.sortBy, ...options.sortBy }
  : DEFAULT_SEARCH_OPTIONS.sortBy
const body = { ...DEFAULT_SEARCH_OPTIONS, ...options, sortBy, prefix: path || '' }

Current C# behavior (potential bug)

In modules/storage-csharp/Storage/SearchOptions.cs:

public class SearchOptions
{
    [JsonProperty("sortBy")]
    public SortBy SortBy { get; set; } = new SortBy { Column = "name", Order = "asc" };
}

// SortBy.cs
public class SortBy
{
    [JsonProperty("column")]
    public string? Column { get; set; }

    [JsonProperty("order")]
    public string? Order { get; set; }
}

If a caller creates:

var options = new SearchOptions { SortBy = new SortBy { Column = "updated_at" } };
// SortBy.Order is null — serializes to { "column": "updated_at", "order": null }

The server may reject this with a 400 since order is required.

Implementation Guidance

Option 1: Default Order in SortBy

public class SortBy
{
    [JsonProperty("column")]
    public string? Column { get; set; }

    [JsonProperty("order")]
    public string? Order { get; set; } = "asc";  // default
}

Option 2: Deep-merge in List()

In StorageFileApi.cs, before building the request body, merge partial SortBy with defaults:

var defaultSortBy = new SortBy { Column = "name", Order = "asc" };
if (options?.SortBy != null)
{
    options.SortBy.Column ??= defaultSortBy.Column;
    options.SortBy.Order ??= defaultSortBy.Order;
}

Key Behaviors to Match

  • new SearchOptions { SortBy = new SortBy { Column = "updated_at" } } → sends sortBy: { column: "updated_at", order: "asc" }
  • new SearchOptions { SortBy = new SortBy { Order = "desc" } } → sends sortBy: { column: "name", order: "desc" }
  • new SearchOptions() (no SortBy override) → sends sortBy: { column: "name", order: "asc" } (unchanged)

Files Likely Affected

  • modules/storage-csharp/Storage/SortBy.cs
  • modules/storage-csharp/Storage/StorageFileApi.cs

Acceptance Criteria

  • Partial SortBy (only Column or only Order set) fills in the missing field from defaults
  • Full SortBy override still works correctly
  • Default SearchOptions() behavior unchanged
  • Unit tests cover partial SortBy cases
  • No breaking changes to existing API

Context

  • supabase-js version: v3.0.0-next.29
  • Parity tracking: This issue was auto-generated by SDK parity analysis
  • Related parity issues: SDK-1089 (dart), SDK-1090 (py), SDK-1091 (swift)

Generated with Claude Code /sync-sdk-parity

Metadata

Metadata

Assignees

Labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions