Home / Function/ FormContents() — supabase Function Reference

FormContents() — supabase Function Reference

Architecture documentation for the FormContents() function in FormContents.tsx from the supabase codebase.

Entity Profile

Dependency Diagram

graph TD
  93eaf812_5506_abc1_9cec_a4ad05017e49["FormContents()"]
  a16bda06_09eb_3b5e_0a88_01a55a9f527f["isEdgeFunction()"]
  93eaf812_5506_abc1_9cec_a4ad05017e49 -->|calls| a16bda06_09eb_3b5e_0a88_01a55a9f527f
  style 93eaf812_5506_abc1_9cec_a4ad05017e49 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

apps/studio/components/interfaces/Database/Hooks/FormContents.tsx lines 48–290

export const FormContents = ({ form, selectedHook }: FormContentsProps) => {
  const { ref } = useParams()
  const { data: project } = useSelectedProjectQuery()

  const restUrl = project?.restUrl
  const restUrlTld = restUrl ? new URL(restUrl).hostname.split('.').pop() : 'co'

  const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
  const { data: keys = [] } = useAPIKeysQuery(
    { projectRef: ref, reveal: true },
    { enabled: canReadAPIKeys }
  )
  const { data: functions = [], isSuccess: isSuccessEdgeFunctions } = useEdgeFunctionsQuery({
    projectRef: ref,
  })

  const legacyServiceRole = keys.find((x) => x.name === 'service_role')?.api_key ?? '[YOUR API KEY]'

  const httpUrl = useWatch_Shadcn_({ control: form.control, name: 'http_url' })
  const httpHeaders = useWatch_Shadcn_({ control: form.control, name: 'httpHeaders' })

  const { data } = useTablesQuery({
    projectRef: project?.ref,
    connectionString: project?.connectionString,
  })

  const tables = useMemo(
    () => [...(data ?? [])].sort((a, b) => (a.schema > b.schema ? 0 : -1)),
    [data]
  )

  // Handle auth header auto-add for edge functions
  useEffect(() => {
    if (!isSuccessEdgeFunctions) return

    const isEdgeFunctionSelected = isEdgeFunction({ ref, restUrlTld, url: httpUrl })

    if (httpUrl && isEdgeFunctionSelected) {
      const fnSlug = httpUrl.split('/').at(-1)
      const fn = functions.find((x) => x.slug === fnSlug)
      const authorizationHeader = httpHeaders.find((x) => x.name === 'Authorization')
      const edgeFunctionAuthHeaderVal = `Bearer ${legacyServiceRole}`

      if (fn?.verify_jwt && authorizationHeader == null) {
        const newAuthHeader = {
          id: uuidv4(),
          name: 'Authorization',
          value: edgeFunctionAuthHeaderVal,
        }
        form.setValue('httpHeaders', [...httpHeaders, newAuthHeader])
      } else if (fn?.verify_jwt && authorizationHeader?.value !== edgeFunctionAuthHeaderVal) {
        const updatedHttpHeaders = httpHeaders.map((x) => {
          if (x.name === 'Authorization') return { ...x, value: edgeFunctionAuthHeaderVal }
          else return x
        })
        form.setValue('httpHeaders', updatedHttpHeaders)
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [httpUrl, isSuccessEdgeFunctions])

  return (
    <div>
      <FormSection header={<FormSectionLabel className="lg:!col-span-4">General</FormSectionLabel>}>
        <FormSectionContent loading={false} className="lg:!col-span-8">
          <FormField_Shadcn_
            control={form.control}
            name="name"
            render={({ field }) => (
              <FormItemLayout label="Name" layout="vertical" className="gap-1">
                <FormControl_Shadcn_>
                  <Input_Shadcn_ {...field} placeholder="my_webhook" />
                </FormControl_Shadcn_>
                <p className="text-xs text-foreground-lighter">Do not use spaces/whitespaces</p>
              </FormItemLayout>
            )}
          />
        </FormSectionContent>
      </FormSection>
      <SidePanel.Separator />
      <FormSection
        header={
          <FormSectionLabel
            className="lg:!col-span-4"
            description={
              <p className="text-sm text-foreground-light">
                Select which table and events will trigger your webhook
              </p>
            }
          >
            Conditions to fire webhook
          </FormSectionLabel>
        }
      >
        <FormSectionContent loading={false} className="lg:!col-span-8">
          <FormField_Shadcn_
            control={form.control}
            name="table_id"
            render={({ field }) => (
              <FormItemLayout
                label="Table"
                layout="vertical"
                className="gap-1"
                description="This is the table the trigger will watch for changes. You can only select 1 table for a trigger."
              >
                <Select_Shadcn_ value={field.value} onValueChange={field.onChange}>
                  <FormControl_Shadcn_>
                    <SelectTrigger_Shadcn_>
                      <SelectValue_Shadcn_ placeholder="Select a table" />
                    </SelectTrigger_Shadcn_>
                  </FormControl_Shadcn_>
                  <SelectContent_Shadcn_>
                    {tables.map((table) => (
                      <SelectItem_Shadcn_ key={table.id} value={table.id.toString()}>
                        <div className="flex items-center space-x-2">
                          <span className="text-foreground-light">{table.schema}</span>
                          <span className="text-foreground">{table.name}</span>
                        </div>
                      </SelectItem_Shadcn_>
                    ))}
                  </SelectContent_Shadcn_>
                </Select_Shadcn_>
              </FormItemLayout>
            )}
          />

          <FormField_Shadcn_
            control={form.control}
            name="events"
            render={({ field }) => (
              <FormItemLayout
                label="Events"
                layout="vertical"
                className="gap-1"
                description="These are the events that are watched by the webhook, only the events selected above will fire the webhook on the table you've selected."
              >
                <div className="space-y-3">
                  {HOOK_EVENTS.map((event) => (
                    <div key={event.value} className="flex items-start space-x-3">
                      <Checkbox_Shadcn_
                        id={`event-${event.value}`}
                        checked={field.value.includes(event.value)}
                        onCheckedChange={(checked) => {
                          if (checked) {
                            field.onChange([...field.value, event.value])
                          } else {
                            field.onChange(field.value.filter((v) => v !== event.value))
                          }
                        }}
                      />
                      <div className="grid gap-1.5 leading-none">
                        <Label_Shadcn_
                          htmlFor={`event-${event.value}`}
                          className="text-sm font-normal cursor-pointer"
                        >
                          {event.label}
                        </Label_Shadcn_>
                        <p className="text-xs text-foreground-lighter">{event.description}</p>
                      </div>
                    </div>
                  ))}
                </div>
              </FormItemLayout>
            )}
          />
        </FormSectionContent>
      </FormSection>
      <SidePanel.Separator />
      <FormSection
        header={
          <FormSectionLabel className="lg:!col-span-4">Webhook configuration</FormSectionLabel>
        }
      >
        <FormSectionContent loading={false} className="lg:!col-span-8">
          <FormField_Shadcn_
            control={form.control}
            name="function_type"
            render={({ field }) => (
              <FormItemLayout label="Type of webhook" layout="vertical" className="gap-1">
                <FormControl_Shadcn_>
                  <RadioGroupStacked
                    value={field.value}
                    onValueChange={(functionType) => {
                      if (functionType === 'http_request') {
                        if (selectedHook !== undefined) {
                          const [url] = selectedHook.function_args
                          form.setValue('http_url', url, { shouldDirty: false })
                        } else {
                          form.setValue('http_url', '', { shouldDirty: false })
                        }
                      } else if (functionType === 'supabase_function') {
                        // Default to first edge function in the list
                        const fnSlug = functions[0]?.slug
                        const defaultFunctionUrl = `https://${ref}.supabase.${restUrlTld}/functions/v1/${fnSlug}`
                        const currentUrl = form.getValues('http_url')
                        if (!isEdgeFunction({ ref, restUrlTld, url: currentUrl })) {
                          form.setValue('http_url', defaultFunctionUrl, { shouldDirty: false })
                        }
                      }
                      field.onChange(functionType)
                    }}
                  >
                    {AVAILABLE_WEBHOOK_TYPES.map((webhook) => (
                      <RadioGroupStackedItem
                        key={webhook.value}
                        id={webhook.value}
                        value={webhook.value}
                        label=""
                        showIndicator={false}
                      >
                        <div className="flex items-center space-x-5">
                          <Image
                            alt={webhook.label}
                            src={webhook.icon}
                            layout="fixed"
                            width="32"
                            height="32"
                          />
                          <div className="flex-col space-y-0">
                            <div className="flex space-x-2">
                              <p className="text-foreground">{webhook.label}</p>
                            </div>
                            <p className="text-foreground-light">{webhook.description}</p>
                          </div>
                        </div>
                      </RadioGroupStackedItem>
                    ))}
                  </RadioGroupStacked>
                </FormControl_Shadcn_>
              </FormItemLayout>
            )}
          />
        </FormSectionContent>
      </FormSection>
      <SidePanel.Separator />
      <HTTPRequestConfig form={form} />
      <SidePanel.Separator />
      <HTTPHeaders form={form} />
      <SidePanel.Separator />
      <HTTPParameters form={form} />
    </div>
  )
}

Subdomains

Frequently Asked Questions

What does FormContents() do?
FormContents() is a function in the supabase codebase.
What does FormContents() call?
FormContents() calls 1 function(s): isEdgeFunction.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free