Closed enyo closed 2 years ago
As a workaround this works well for now:
interface DatabaseWithViews extends Database {
public: Database['public'] & {
Tables: Database['public']['Tables'] & {
my_view_name: {
Row: {
view_column: string
// etc...
}
}
}
}
}
const supabase = createClient<DatabaseWithViews>(url, anonKey);
EDIT: actually, strike that. I don't know why, but extending the interface doesn't work. It always returns any
It's not feasible to generate types for views since view definitions are dynamic - e.g. we don't know the column information for a view, since columns are tied to tables, not views.
I'll see if I can extend supabase-js to allow you to add additional Tables
in the near future.
Excellent @soedirgo . I think it's fine if they need to be added manually, but atm I don't think it's possible? I don't understand why extending the Database the way I did in my previous post didn't work.
I think I figured it out - can you do this instead?
import { Database } from './types'
type DatabaseWithViews = Database & {
public: {
Tables: {
my_view_name: {
Row: { ... }
...
}
}
}
}
I don't think it's necessary to modify supabase-js to support this after all, though we should document this in our docs.
PostgREST successfully generates types for views in the OpenAPI endpoint (http://localhost:54321/rest/v1/?apikey=
). Can't this be used?
I haven't looked at the code but would have expected that this OpenAPI definition would be used for generating the TypeScript types. Given that there's already the requirement that a supabase instance has to be running it should be possible to use the OpenAPI information for views.
In my current situation (not yet upgraded to V2) it makes more sense to just use any OpenAPI generator.
It doesn't seem to be perfect - e.g. if I create a view with a column now() as now_col
, the OpenAPI description will say you can insert and supply the now_col
, but it'll return an error if you actually do that. Also, it doesn't take into account table fields that must not be supplied, e.g. for generated columns.
But the choice to use a separate tool (supabase/postgres-meta) is because of development velocity - it's much faster to release a fix on postgres-meta & update the image version in the CLI, than it is to release a fix on PostgREST and wait for it to be deployed on the hosted platform.
I think I figured it out - can you do this instead?
import { Database } from './types' type DatabaseWithViews = Database & { [...]
I didn't get this to work. It's the same issue as with my attempt of extending the interface. When I use this type, all the type inference breaks. The data objects returned by the supabase calls are any
.
Needs support from the postgrest-js side for views - will loop back here once that's updated
postgrest-js has been updated to support views.
@soedirgo so does this mean that views are now included in the generated output, or that creating this union type now works?
Views are now included in the generated types. I believe you need CLI v1.3.0+ and postgrest-js@2.0.0-rc.5+ for it (npm update @supabase/postgrest-js
should do it).
Very cool. Just in case anybody else was looking for this: I needed to restart supabase locally for this to work. Simply upgrading the cli wasn't enough.
@soedirgo at the moment, all fields in views are type | null
. Is there anything we can do to avoid all fields being nullable?
I don't think so - this is a limitation on the Postgres side, it doesn't store column nullability accurately for views. I believe you get the same thing from PostgREST's OpenAPI.
It's possible to manually set the nullability for views to make the generated types work. This, however, doesn't check if what you're doing is actually correct so make sure that the columns you are setting to not null
are actually definitely not null.
I don't know if there are other implications of changing these values so make sure you understand it better than I do before using this in an important project.
UPDATE pg_catalog.pg_attribute
SET attnotnull = TRUE
WHERE (attrelid, attname) IN
(('view_name'::regclass, 'column_1'),
('view_name'::regclass, 'column_2'),
('view_name'::regclass, 'column_3'));
@profiluefter Thanks! We actually implicitly assume view columns are nullable in the typegen, so that needs to be updated as well.
When running
supabase gen types typescript
only types for tables are generated. This makes it difficult to select data from views.