supabase / postgrest-js

Isomorphic JavaScript client for PostgREST.
https://supabase.com
MIT License
964 stars 128 forks source link

bug: (count) relation types cause TypeScript SelectQueryError #489

Closed wbhob closed 4 months ago

wbhob commented 8 months ago

Bug report

Describe the bug

The bug is a mismatch between generated types and code behavior. The code below causes a TypeScript error despite functioning correctly.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Create tables using Supabase hosted with the following schemas:

    
    create table
    public.organizations (
    id uuid not null default gen_random_uuid (),
    created_at timestamp with time zone null default now(),
    human_name text null,
    slug text not null,
    owner_user_id uuid not null default auth.uid (),
    account_type text not null default 'pro'::text,
    feature_flags jsonb null,
    stripe_customer_id text null,
    stripe_subscription_status text null,
    stripe_seats_billed bigint null,
    constraint organizations_pkey primary key (id, slug),
    constraint organizations_id_key unique (id),
    constraint organizations_stripe_customer_id_key unique (stripe_customer_id),
    constraint organizations_owner_user_id_fkey foreign key (owner_user_id) references auth.users (id)
    ) tablespace pg_default;
    
    create table
    public.organization_members (
    id bigint generated by default as identity,
    created_at timestamp with time zone null default now(),
    user_id uuid not null,
    organization_id uuid not null,
    scopes text[] null,
    constraint organization_members_pkey primary key (id, user_id, organization_id),
    constraint organization_members_user_id_key unique (user_id),
    constraint organization_members_organization_id_fkey foreign key (organization_id) references organizations (id),
    constraint organization_members_user_id_fkey foreign key (user_id) references auth.users (id)
    ) tablespace pg_default;

create index if not exists organization_members_user_id_idx on public.organization_members using btree (user_id) tablespace pg_default;

create index if not exists organization_members_organization_id_idx on public.organization_members using hash (organization_id) tablespace pg_default;


2. Use supabase CLI to generate types
3. Using the client in `supabase.from('organizations').select('*, organization_members(count)')` leads to type error, SelectQueryError, even though the behavior works as expected and a array with {count} is returned.

## Expected behavior

I expect TypeScript to reflect this query with [{ count: number }] since the relation exists. The logic executes correctly and a count is returned, so the problem appears to be only with types. It is possible that because Supabase hosted puts the relations on separate lines from their corresponding column definitions that is throwing the schema builder off.

## Screenshots

![CleanShot 2023-10-18 at 12 28 15@2x](https://github.com/supabase/supabase-js/assets/4442130/a6cbeb5b-d272-435e-951f-5b4aec44d2c5)
![CleanShot 2023-10-18 at 12 28 24@2x](https://github.com/supabase/supabase-js/assets/4442130/c59bb6b4-1dab-42b2-87d2-ac03d623991a)

## System information

- OS: macOs
- Browser (if applies) N/A
- Version of supabase-js: 2.38.1
- Version of Node.js: 18.18.2
- Version of TypeScript: 5.2.2

## Additional context

Also using SvelteKit, if that helps.
ndoherty-xyz commented 8 months ago

+1

Running into this with a similar schema setup as well

Quatton commented 6 months ago

Not a fix but for the time being you can use this util for type-safety.

export function getCountFromForeignTable(column: unknown) {
  const _column = (Array.isArray(column) ? column[0] : column) as {
    count?: number;
  };

  return _column.count ?? null;
}
jamescqcampbell commented 6 months ago

+1, seeing this too

bnjmnt4n commented 6 months ago

Note: This is a duplicate of #447 and #479.

encima commented 4 months ago

Let's close this in favour of #447 and track there.