import Link from 'next/link' import { isEmpty } from 'lodash' import { useState } from 'react' import { useRouter } from 'next/router' import { observer } from 'mobx-react-lite' import { Button, Form, Input, IconArrowLeft, IconExternalLink, IconEdit, IconTrash } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' import { checkPermissions, useStore } from 'hooks' import { useParams } from 'common/hooks' import { FormPanel, FormActions, FormSection, FormsContainer, FormSectionLabel, FormSectionContent, } from 'components/ui/Forms' import { useFDWCreateMutation } from 'data/fdw/fdw-create-mutation' import InputField from './InputField' import { WRAPPERS } from './Wrappers.constants' import WrapperTableEditor from './WrapperTableEditor' import { makeValidateRequired } from './Wrappers.utils' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' const CreateWrapper = () => { const formId = 'create-wrapper-form' const router = useRouter() const { ui } = useStore() const { ref, type } = useParams() const { project } = useProjectContext() const { mutateAsync: createFDW } = useFDWCreateMutation() const [newTables, setNewTables] = useState([]) const [isEditingTable, setIsEditingTable] = useState(false) const [selectedTableToEdit, setSelectedTableToEdit] = useState() const [formErrors, setFormErrors] = useState<{ [k: string]: string }>({}) const canCreateWrapper = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'wrappers') const wrapperMeta = WRAPPERS.find((wrapper) => wrapper.name === type) const initialValues = wrapperMeta !== undefined ? { wrapper_name: '', server_name: '', ...Object.fromEntries( wrapperMeta.server.options.map((option) => [option.name, option.defaultValue ?? '']) ), } : {} if (wrapperMeta === undefined) { return (

Unsupported wrapper type

The wrapper type {type} not supported by the dashboard. Head back to create a different wrapper.

) } const onUpdateTable = (values: any) => { setNewTables((prev) => { // if the new values have tableIndex, we are editing an existing table if (values.tableIndex !== undefined) { const tableIndex = values.tableIndex const newTables = [...prev] delete values.tableIndex newTables[tableIndex] = values return newTables } return [...prev, values] }) setIsEditingTable(false) setSelectedTableToEdit(undefined) } const onSubmit = async (values: any, { setSubmitting }: any) => { const validate = makeValidateRequired(wrapperMeta.server.options) const errors: any = validate(values) const { wrapper_name } = values if (wrapper_name.length === 0) errors.name = 'Please provide a name for your wrapper' if (newTables.length === 0) errors.tables = 'Please add at least one table' if (!isEmpty(errors)) return setFormErrors(errors) setSubmitting(true) try { await createFDW({ projectRef: project?.ref, connectionString: project?.connectionString, wrapperMeta, formState: { ...values, server_name: `${wrapper_name}_server` }, tables: newTables, }) ui.setNotification({ category: 'success', message: `Successfully created ${wrapperMeta.label} foreign data wrapper`, }) setNewTables([]) router.push(`/project/${ref}/database/wrappers`) } catch (error: any) { ui.setNotification({ error, category: 'error', message: `Failed to create ${wrapperMeta.label} foreign data wrapper: ${error.message}`, }) } finally { setSubmitting(false) } } return (

Back

Create a {wrapperMeta?.label} Wrapper

{({ isSubmitting, handleReset, values, initialValues }: any) => { const hasChanges = JSON.stringify(values) !== JSON.stringify(initialValues) return (
} > Wrapper Configuration}> 0 ? ( <> Your wrapper's server name will be{' '} {values.wrapper_name}_server ) : ( '' ) } /> {wrapperMeta.label} Configuration} > {wrapperMeta.server.options.map((option) => ( ))}

Foreign Tables

You can query your data from these foreign tables after the wrapper is created

} > {newTables.length === 0 ? (
) : (
{newTables.map((table, i) => (

{table.schema_name}.{table.table_name}

{wrapperMeta.tables[table.index].label}: {table.columns.join(', ')}

))}
)} {newTables.length > 0 && (
)} {newTables.length === 0 && formErrors.tables && (

{formErrors.tables}

)}
) }} { setSelectedTableToEdit(undefined) setIsEditingTable(false) }} onSave={onUpdateTable} initialData={selectedTableToEdit} />
) } export default observer(CreateWrapper)