Skip to content

breaking(postgrest): thread a real row type parameter through the query/rpc/stream builders #1581

Description

@spydon

Background

Enabling strict-raw-types in supabase_lints (the strict-raw-types enablement work) surfaced that several builders erase their generic type parameter to dynamic. The non-breaking pass made those dynamic arguments explicit so the rule can be enabled, but it deliberately did not change behavior. This issue tracks the follow-up breaking change: actually threading a real row type parameter through the builders.

Problem

The PostgREST/Supabase builder classes are already generic, but the public entry points throw the type away:

// postgrest: from() erases the row type
PostgrestQueryBuilder<void> from(String table) { ... }

// supabase: SupabaseQueryBuilder is hard-coded to dynamic
class SupabaseQueryBuilder extends PostgrestQueryBuilder<dynamic> { ... }

// rpc builder is fully raw
class PostgrestRpcBuilder extends RawPostgrestBuilder<dynamic, dynamic, dynamic> { ... }

// stream builder holds a dynamic query builder
final PostgrestQueryBuilder<dynamic> _queryBuilder;

As a result there is no way for a caller to say "this table's rows are MyModel" (or even Map<String, dynamic>) and get typed results back. Everything degrades to dynamic, which is exactly what strict-raw-types warns about, and it means no compile-time safety on .select() / .single() / .stream() results.

Proposed change (breaking)

Thread a real type parameter through the builder chain so the row type flows from the entry point to the result, similar to how supabase-js types from/rpc:

  • PostgrestClient.from(String table)from<T>(String table) (or a schema-typed variant), returning PostgrestQueryBuilder<T> instead of PostgrestQueryBuilder<void>.
  • SupabaseClient.from / SupabaseQueryBuilder carry T instead of being fixed to dynamic.
  • SupabaseStreamBuilder and PostgrestRpcBuilder carry the real type instead of dynamic.
  • Keep the idiomatic-Dart shape (no JS-mirrored surface); default T sensibly so the common untyped path stays ergonomic.

Why this is breaking

  • Changing from to from<T> and changing the fixed dynamic/void type arguments changes the public generic signatures.
  • Return types of chained calls change, so code relying on the current dynamic results may need explicit types or casts.
  • Any consumer extending SupabaseQueryBuilder / the builders sees a changed supertype arity.

Because of this it is scheduled for v3.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpostgrestThis issue or pull request is related to postgrestv3

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions