import type { PGTable } from '@supabase/pg-meta' import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' import { useQuery, useQueryClient } from '@tanstack/react-query' import { sortBy } from 'lodash' import { useCallback } from 'react' import { tableKeys } from './keys' import { get, handleError } from '@/data/fetchers' import type { SafePostgresTable } from '@/lib/postgres-types' import type { ResponseError, UseCustomQueryOptions } from '@/types' export type TablesVariables = { projectRef?: string connectionString?: string | null schema?: string /** * Defaults to false */ includeColumns?: boolean sortByProperty?: keyof PGTable } export async function getTables( { projectRef, connectionString, schema, includeColumns = false, sortByProperty = 'name', }: TablesVariables, signal?: AbortSignal ) { if (!projectRef) { throw new Error('projectRef is required') } let headers = new Headers() if (connectionString) headers.set('x-connection-encrypted', connectionString) let queryParams: Record = { //include_columns is a string, even though it's true or false include_columns: `${includeColumns}`, } if (schema) { queryParams.included_schemas = schema } const { data, error } = await get('/platform/pg-meta/{ref}/tables', { params: { header: { 'x-connection-encrypted': connectionString!, 'x-pg-application-name': DEFAULT_PLATFORM_APPLICATION_NAME, }, path: { ref: projectRef }, query: queryParams as any, }, headers, signal, }) if (!Array.isArray(data) && error) handleError(error) // Sort the data if the sortByName option is true if (Array.isArray(data) && sortByProperty) { return sortBy(data, (t) => t[sortByProperty]) as SafePostgresTable[] } return data as SafePostgresTable[] } export type TablesData = Awaited> export type TablesError = ResponseError export const useTablesQuery = ( { projectRef, connectionString, schema, includeColumns }: TablesVariables, { enabled = true, ...options }: UseCustomQueryOptions = {} ) => { return useQuery({ queryKey: tableKeys.list(projectRef, schema, includeColumns), queryFn: ({ signal }) => getTables({ projectRef, connectionString, schema, includeColumns }, signal), enabled: enabled && typeof projectRef !== 'undefined', ...options, }) } /** * useGetTables * Tries to get tables from the react-query cache, or loads it from the server if it's not cached. */ export function useGetTables({ projectRef, connectionString, }: Pick) { const queryClient = useQueryClient() return useCallback( (schema?: TablesVariables['schema'], includeColumns?: TablesVariables['includeColumns']) => { return queryClient.fetchQuery({ queryKey: tableKeys.list(projectRef, schema, includeColumns), queryFn: ({ signal }) => getTables({ projectRef, connectionString, schema, includeColumns }, signal), }) }, [connectionString, projectRef, queryClient] ) } export function usePrefetchTables({ projectRef, connectionString, }: Pick) { const queryClient = useQueryClient() return useCallback( (schema?: TablesVariables['schema'], includeColumns?: TablesVariables['includeColumns']) => { return queryClient.prefetchQuery({ queryKey: tableKeys.list(projectRef, schema, includeColumns), queryFn: ({ signal }) => getTables({ projectRef, connectionString, schema, includeColumns }, signal), }) }, [connectionString, projectRef, queryClient] ) }