CreateFunction() — supabase Function Reference
Architecture documentation for the CreateFunction() function in index.tsx from the supabase codebase.
Entity Profile
Dependency Diagram
graph TD d283a1cf_3e04_3f10_5eeb_b3619f3ec1c5["CreateFunction()"] 68822530_7542_9aea_3a82_46fc0e4af2a8["convertArgumentTypes()"] d283a1cf_3e04_3f10_5eeb_b3619f3ec1c5 -->|calls| 68822530_7542_9aea_3a82_46fc0e4af2a8 9f809b6d_69cf_8db9_9ba7_fc60782d791a["convertConfigParams()"] d283a1cf_3e04_3f10_5eeb_b3619f3ec1c5 -->|calls| 9f809b6d_69cf_8db9_9ba7_fc60782d791a style d283a1cf_3e04_3f10_5eeb_b3619f3ec1c5 fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx lines 73–409
export const CreateFunction = ({
func,
visible,
isDuplicating = false,
onClose,
}: CreateFunctionProps) => {
const { data: project } = useSelectedProjectQuery()
const [advancedSettingsShown, setAdvancedSettingsShown] = useState(false)
const [focusedEditor, setFocusedEditor] = useState(false)
const isEditing = !isDuplicating && !!func?.id
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
})
const language = form.watch('language')
const { confirmOnClose, modalProps: closeConfirmationModalProps } = useConfirmOnClose({
checkIsDirty: () => form.formState.isDirty,
onClose,
})
const { mutate: createDatabaseFunction, isPending: isCreating } =
useDatabaseFunctionCreateMutation()
const { mutate: updateDatabaseFunction, isPending: isUpdating } =
useDatabaseFunctionUpdateMutation()
const onSubmit: SubmitHandler<z.infer<typeof FormSchema>> = async (data) => {
if (!project) return console.error('Project is required')
const payload = {
...data,
args: data.args.map((x) => `${x.name} ${x.type}`),
config_params: mapValues(keyBy(data.config_params, 'name'), 'value') as Record<string, never>,
}
if (isEditing) {
updateDatabaseFunction(
{
func,
projectRef: project.ref,
connectionString: project.connectionString,
payload,
},
{
onSuccess: () => {
toast.success(`Successfully updated function ${data.name}`)
onClose()
},
}
)
} else {
createDatabaseFunction(
{
projectRef: project.ref,
connectionString: project.connectionString,
payload,
},
{
onSuccess: () => {
toast.success(`Successfully created function ${data.name}`)
onClose()
},
}
)
}
}
useEffect(() => {
if (visible) {
setFocusedEditor(false)
form.reset({
name: func?.name ?? '',
schema: func?.schema ?? 'public',
args: convertArgumentTypes(func?.argument_types || '').value,
behavior: func?.behavior ?? 'VOLATILE',
definition: func?.definition ?? '',
language: func?.language ?? 'plpgsql',
return_type: func?.return_type ?? 'void',
security_definer: func?.security_definer ?? false,
config_params: convertConfigParams(func?.config_params).value,
})
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [visible, func?.id])
const { data: protectedSchemas } = useProtectedSchemas()
return (
<Sheet open={visible} onOpenChange={confirmOnClose}>
<SheetContent
showClose={false}
size={'default'}
className={'p-0 flex flex-row gap-0 !min-w-screen lg:!min-w-[600px]'}
>
<div className="flex flex-col grow w-full">
<CreateFunctionHeader selectedFunction={func?.name} isDuplicating={isDuplicating} />
<Separator />
<Form_Shadcn_ {...form}>
<form
id={FORM_ID}
className="flex-grow overflow-auto"
onSubmit={form.handleSubmit(onSubmit)}
>
<SheetSection className={focusedEditor ? 'hidden' : ''}>
<FormField_Shadcn_
control={form.control}
name="name"
render={({ field }) => (
<FormItemLayout
label="Name of function"
description="Name will also be used for the function name in postgres"
layout="horizontal"
>
<FormControl_Shadcn_>
<Input_Shadcn_ {...field} placeholder="Name of function" />
</FormControl_Shadcn_>
</FormItemLayout>
)}
/>
</SheetSection>
<Separator className={focusedEditor ? 'hidden' : ''} />
<SheetSection className={focusedEditor ? 'hidden' : 'space-y-4'}>
<FormField_Shadcn_
control={form.control}
name="schema"
render={({ field }) => (
<FormItemLayout
label="Schema"
description="Tables made in the table editor will be in 'public'"
layout="horizontal"
>
<FormControl_Shadcn_>
<SchemaSelector
selectedSchemaName={field.value}
excludedSchemas={protectedSchemas?.map((s) => s.name)}
size="small"
onSelectSchema={(name) => field.onChange(name)}
/>
</FormControl_Shadcn_>
</FormItemLayout>
)}
/>
{!isEditing && (
<FormField_Shadcn_
control={form.control}
name="return_type"
render={({ field }) => (
<FormItemLayout label="Return type" layout="horizontal">
{/* Form selects don't need form controls, otherwise the CSS gets weird */}
<Select_Shadcn_ onValueChange={field.onChange} defaultValue={field.value}>
<SelectTrigger_Shadcn_ className="col-span-8">
<SelectValue_Shadcn_ />
</SelectTrigger_Shadcn_>
<SelectContent_Shadcn_>
<ScrollArea className="h-52">
{['void', 'record', 'trigger', 'integer', ...POSTGRES_DATA_TYPES].map(
(option) => (
<SelectItem_Shadcn_ value={option} key={option}>
{option}
</SelectItem_Shadcn_>
)
)}
</ScrollArea>
</SelectContent_Shadcn_>
</Select_Shadcn_>
</FormItemLayout>
)}
/>
)}
</SheetSection>
<Separator className={focusedEditor ? 'hidden' : ''} />
<SheetSection className={focusedEditor ? 'hidden' : ''}>
<FormFieldArgs readonly={isEditing} />
</SheetSection>
<Separator className={focusedEditor ? 'hidden' : ''} />
<SheetSection className={`${focusedEditor ? 'h-full' : ''} !px-0`}>
<FormField_Shadcn_
control={form.control}
name="definition"
render={({ field }) => (
<FormItem_Shadcn_ className="space-y-4 flex flex-col h-full">
<div className="px-content">
<FormLabel_Shadcn_ className="text-base text-foreground">
Definition
</FormLabel_Shadcn_>
<FormDescription_Shadcn_ className="text-sm text-foreground-light">
<p>
The language below should be written in <code>{language}</code>.
</p>
{!isEditing && <p>Change the language in the Advanced Settings below.</p>}
</FormDescription_Shadcn_>
</div>
<div
className={cn(
'border border-default flex',
focusedEditor ? 'flex-grow ' : 'h-72'
)}
>
<FunctionEditor
field={field}
language={language}
focused={focusedEditor}
setFocused={setFocusedEditor}
/>
</div>
<FormMessage_Shadcn_ className="px-content" />
</FormItem_Shadcn_>
)}
/>
</SheetSection>
<Separator className={focusedEditor ? 'hidden' : ''} />
{isEditing ? (
<></>
) : (
<>
<SheetSection className={focusedEditor ? 'hidden' : ''}>
<div className="space-y-8 rounded bg-studio py-4 px-6 border border-overlay">
<Toggle
onChange={() => setAdvancedSettingsShown(!advancedSettingsShown)}
label="Show advanced settings"
checked={advancedSettingsShown}
labelOptional="These are settings that might be familiar for Postgres developers"
/>
</div>
</SheetSection>
{advancedSettingsShown && (
<>
<SheetSection className={focusedEditor ? 'hidden' : 'space-y-2 pt-0'}>
<FormFieldLanguage />
<FormField_Shadcn_
control={form.control}
name="behavior"
render={({ field }) => (
<FormItemLayout label="Behavior" layout="horizontal">
{/* Form selects don't need form controls, otherwise the CSS gets weird */}
<Select_Shadcn_
defaultValue={field.value}
onValueChange={field.onChange}
>
<SelectTrigger_Shadcn_ className="col-span-8">
<SelectValue_Shadcn_ />
</SelectTrigger_Shadcn_>
<SelectContent_Shadcn_>
<SelectItem_Shadcn_ value="IMMUTABLE" key="IMMUTABLE">
immutable
</SelectItem_Shadcn_>
<SelectItem_Shadcn_ value="STABLE" key="STABLE">
stable
</SelectItem_Shadcn_>
<SelectItem_Shadcn_ value="VOLATILE" key="VOLATILE">
volatile
</SelectItem_Shadcn_>
</SelectContent_Shadcn_>
</Select_Shadcn_>
</FormItemLayout>
)}
/>
</SheetSection>
<Separator className={focusedEditor ? 'hidden' : ''} />
<SheetSection className={focusedEditor ? 'hidden' : ''}>
<FormFieldConfigParams readonly={isEditing} />
</SheetSection>
<Separator className={focusedEditor ? 'hidden' : ''} />
<SheetSection className={focusedEditor ? 'hidden' : ''}>
<h5 className="text-base text-foreground mb-4">Type of Security</h5>
<FormField_Shadcn_
control={form.control}
name="security_definer"
render={({ field }) => (
<FormItem_Shadcn_>
<FormControl_Shadcn_ className="col-span-8">
{/* TODO: This RadioGroup imports Formik state, replace it with a clean component */}
<Radio.Group
type="cards"
layout="vertical"
onChange={(event) =>
field.onChange(event.target.value == 'SECURITY_DEFINER')
}
value={field.value ? 'SECURITY_DEFINER' : 'SECURITY_INVOKER'}
>
<Radio
id="SECURITY_INVOKER"
label="SECURITY INVOKER"
value="SECURITY_INVOKER"
checked={!field.value}
description={
<>
Function is to be executed with the privileges of the user
that <span className="text-foreground">calls it</span>.
</>
}
/>
<Radio
id="SECURITY_DEFINER"
label="SECURITY DEFINER"
value="SECURITY_DEFINER"
checked={field.value}
description={
<>
Function is to be executed with the privileges of the user
that <span className="text-foreground">created it</span>.
</>
}
/>
</Radio.Group>
</FormControl_Shadcn_>
<FormMessage_Shadcn_ />
</FormItem_Shadcn_>
)}
/>
</SheetSection>
</>
)}
</>
)}
</form>
</Form_Shadcn_>
<SheetFooter>
<Button disabled={isCreating || isUpdating} type="default" onClick={confirmOnClose}>
Cancel
</Button>
<Button
form={FORM_ID}
htmlType="submit"
disabled={isCreating || isUpdating}
loading={isCreating || isUpdating}
>
{isEditing ? 'Save' : 'Create'} function
</Button>
</SheetFooter>
</div>
<CloseConfirmationModal {...closeConfirmationModalProps} />
</SheetContent>
</Sheet>
)
}
Domain
Subdomains
Source
Frequently Asked Questions
What does CreateFunction() do?
CreateFunction() is a function in the supabase codebase.
What does CreateFunction() call?
CreateFunction() calls 2 function(s): convertArgumentTypes, convertConfigParams.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free