import { useContext, FC, useEffect } from 'react' import { indexOf } from 'lodash' import { observer } from 'mobx-react-lite' import { Input, Form, IconAlertCircle, InputNumber } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' import { checkPermissions, useStore } from 'hooks' import { useParams } from 'common/hooks' import { useProjectPostgrestConfigQuery } from 'data/config/project-postgrest-config-query' import { useProjectPostgrestConfigUpdateMutation } from 'data/config/project-postgrest-config-update-mutation' import MultiSelect from 'components/ui/MultiSelect' import { PageContext } from 'pages/project/[ref]/settings/api' import { FormActions, FormPanel, FormSection, FormSectionContent, FormSectionLabel, } from 'components/ui/Forms' interface Props {} const PostgrestConfig: FC = ({}) => { const PageState: any = useContext(PageContext) const { ui } = useStore() const { meta } = PageState const { ref: projectRef } = useParams() const formId = 'project-postgres-config' const { data: config, isError } = useProjectPostgrestConfigQuery({ projectRef }) const initialValues = { db_schema: '', max_rows: '', db_extra_search_path: '', } const canUpdatePostgrestConfig = checkPermissions( PermissionAction.UPDATE, 'custom_config_postgrest' ) const { mutateAsync: updatePostgrestConfig } = useProjectPostgrestConfigUpdateMutation() const updateConfig = async (updatedConfig: typeof initialValues) => { if (!projectRef) return try { await updatePostgrestConfig({ projectRef, dbSchema: updatedConfig.db_schema, maxRows: updatedConfig.max_rows, dbExtraSearchPath: updatedConfig.db_extra_search_path, }) ui.setNotification({ category: 'success', message: 'Successfully saved settings' }) } catch (error: any) { ui.setNotification({ error, category: 'error', message: `Failed to update config: ${error.message}`, }) } } const permanentSchema = ['public', 'storage'] const hiddenSchema = ['auth', 'pgbouncer', 'hooks', 'extensions'] const schema = meta.schemas .list( (x: any) => { const find = indexOf(hiddenSchema, x.name) if (find < 0) return x }, { allSchemas: true } ) .map((x: any) => { return { id: x.id, value: x.name, name: x.name, disabled: indexOf(permanentSchema, x.name) >= 0 ? true : false, } }) ?? [] return (
{}} onSubmit={updateConfig}> {({ isSubmitting, handleReset, resetForm, values, initialValues }: any) => { const hasChanges = JSON.stringify(values) !== JSON.stringify(initialValues) // [Alaister] although this "technically" is breaking the rules of React hooks // it won't error because the hooks are always rendered in the same order // eslint-disable-next-line react-hooks/rules-of-hooks useEffect(() => { if (config) { const values = { db_schema: config.db_schema, max_rows: config.max_rows, db_extra_search_path: config.db_extra_search_path ?? '', } resetForm({ values, initialValues: values }) } }, [config]) return ( <> API settings

} footer={
} > {isError ? (

Failed to retrieve API settings

) : ( <> Exposed schemas}> {schema.length >= 1 && ( The schemas to expose in your API. Tables, views and stored procedures in these schemas will get API endpoints. public and{' '} storage are protected by default. } emptyMessage={ <>

No schema available to choose

New schemas you create will appear here

} // value must be passed as array of strings value={(values?.db_schema ?? '').replace(/ /g, '').split(',')} // onChange returns array of strings onChange={(event) => { let updatedValues: any = values updatedValues.db_schema = event.join(', ') resetForm({ values: updatedValues, initialValues: updatedValues }) updateConfig({ ...updatedValues }) }} /> )}
Extra search path}> Max rows}> )}
) }}
) } export default observer(PostgrestConfig)