Home / Function/ CreateIcebergWrapperSheet() — supabase Function Reference

CreateIcebergWrapperSheet() — supabase Function Reference

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

Entity Profile

Dependency Diagram

graph TD
  8da2fdba_0ae6_da34_b6db_e886f1354db0["CreateIcebergWrapperSheet()"]
  f17778f0_0474_c6f9_6004_6763d2604934["makeValidateRequired()"]
  8da2fdba_0ae6_da34_b6db_e886f1354db0 -->|calls| f17778f0_0474_c6f9_6004_6763d2604934
  style 8da2fdba_0ae6_da34_b6db_e886f1354db0 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

apps/studio/components/interfaces/Integrations/Wrappers/CreateIcebergWrapperSheet.tsx lines 58–361

export const CreateIcebergWrapperSheet = ({
  wrapperMeta: wrapperMetaOriginal,
  onDirty,
  onClose,
  onCloseWithConfirmation,
}: CreateWrapperSheetProps) => {
  const { data: project } = useSelectedProjectQuery()
  const { data: org } = useSelectedOrganizationQuery()
  const { mutate: sendEvent } = useSendEventMutation()

  const [selectedTarget, setSelectedTarget] = useState<Target>('S3Tables')

  const [formErrors, setFormErrors] = useState<{ [k: string]: string }>({})

  const { mutateAsync: createFDW, isPending: isCreatingWrapper } = useFDWCreateMutation({
    onSuccess: () => {
      toast.success(`Successfully created ${wrapperMeta?.label} foreign data wrapper`)
      onClose()
    },
  })

  const wrapperMeta = useMemo(() => {
    const fields = requiredFields[selectedTarget]

    return {
      ...wrapperMetaOriginal,
      server: {
        options: wrapperMetaOriginal.server.options
          // when the target changes, change the wrapperMeta field
          .filter((option) => fields.find((field) => field.name === option.name))
          .map((option) => {
            const field = fields.find((field) => field.name === option.name)
            return {
              ...option,
              required: field?.required ?? false,
            }
          }),
      },
    }
  }, [wrapperMetaOriginal, selectedTarget])

  const { data: schemas } = useSchemasQuery({
    projectRef: project?.ref!,
    connectionString: project?.connectionString,
  })

  const initialValues = {
    wrapper_name: '',
    server_name: '',
    source_schema: wrapperMeta.sourceSchemaOption?.defaultValue ?? '',
    target_schema: '',
    ...Object.fromEntries(
      wrapperMeta.server.options.map((option) => [option.name, option.defaultValue ?? ''])
    ),
  }

  const { mutateAsync: createSchema, isPending: isCreatingSchema } = useSchemaCreateMutation()

  const onSubmit = async (values: any) => {
    const validate = makeValidateRequired(wrapperMeta.server.options)
    const errors: any = validate(values)

    if (values.source_schema.length === 0) {
      errors.source_schema = 'Please provide a namespace name'
    }
    if (values.wrapper_name.length === 0) {
      errors.wrapper_name = 'Please provide a name for your wrapper'
    }

    if (values.target_schema.length === 0) {
      errors.target_schema = 'Please provide an unique target schema'
    }
    const foundSchema = schemas?.find((s) => s.name === values.target_schema)
    if (foundSchema) {
      errors.target_schema = 'This schema already exists. Please specify a unique schema name.'
    }

    setFormErrors(errors)
    if (!isEmpty(errors)) {
      return
    }

    try {
      await createSchema({
        projectRef: project?.ref,
        connectionString: project?.connectionString,
        name: values.target_schema,
      })

      await createFDW({
        projectRef: project?.ref,
        connectionString: project?.connectionString,
        wrapperMeta,
        formState: {
          ...values,
          server_name: `${values.wrapper_name}_server`,
          supabase_target_schema: values.target_schema,
        },
        mode: 'schema',
        tables: [],
        sourceSchema: values.source_schema,
        targetSchema: values.target_schema,
      })

      sendEvent({
        action: 'foreign_data_wrapper_created',
        properties: {
          wrapperType: wrapperMeta.label,
        },
        groups: {
          project: project?.ref ?? 'Unknown',
          organization: org?.slug ?? 'Unknown',
        },
      })
    } catch (error) {
      console.error(error)
      // The error will be handled by the mutation onError callback (toast.error)
    }
  }

  const isLoading = isCreatingWrapper || isCreatingSchema

  return (
    <>
      <div className="h-full" tabIndex={-1}>
        <Form
          id={FORM_ID}
          initialValues={initialValues}
          onSubmit={onSubmit}
          className="flex-grow flex flex-col h-full"
        >
          {({ values, initialValues }: any) => {
            const hasChanges = JSON.stringify(values) !== JSON.stringify(initialValues)
            onDirty(hasChanges)

            return (
              <>
                <SheetHeader>
                  <SheetTitle>Create a {wrapperMeta.label} wrapper</SheetTitle>
                </SheetHeader>
                <div className="flex-grow overflow-y-auto">
                  <FormSection header={<FormSectionLabel>Wrapper Configuration</FormSectionLabel>}>
                    <FormSectionContent loading={false}>
                      <Input
                        id="wrapper_name"
                        label="Wrapper Name"
                        error={formErrors.wrapper_name}
                        descriptionText={
                          (values?.wrapper_name ?? '').length > 0 ? (
                            <>
                              Your wrapper's server name will be{' '}
                              <code className="text-code-inline">{values.wrapper_name}_server</code>
                            </>
                          ) : (
                            ''
                          )
                        }
                      />
                    </FormSectionContent>
                  </FormSection>
                  <Separator />
                  <FormSection header={<FormSectionLabel>Data target</FormSectionLabel>}>
                    <FormSectionContent loading={false} className="text-sm">
                      <RadioGroupStacked
                        value={selectedTarget}
                        onValueChange={(value) => setSelectedTarget(value as Target)}
                      >
                        <RadioGroupStackedItem
                          key="S3Tables"
                          value="S3Tables"
                          label="AWS S3 Tables"
                          showIndicator={false}
                        >
                          <div className="flex gap-x-5">
                            <div className="flex flex-col">
                              <p className="text-foreground-light text-left">
                                AWS S3 storage that's optimized for analytics workloads.
                              </p>
                            </div>
                          </div>
                        </RadioGroupStackedItem>
                        <RadioGroupStackedItem
                          key="R2Catalog"
                          value="R2Catalog"
                          label="Cloudflare R2 Catalog"
                          showIndicator={false}
                        >
                          <div className="flex gap-x-5">
                            <div className="flex flex-col">
                              <p className="text-foreground-light text-left">
                                Managed Apache Iceberg built directly into your R2 bucket.
                              </p>
                            </div>
                          </div>
                        </RadioGroupStackedItem>
                        <RadioGroupStackedItem
                          key="IcebergRestCatalog"
                          value="IcebergRestCatalog"
                          label="Iceberg REST Catalog"
                          showIndicator={false}
                        >
                          <div className="flex gap-x-5">
                            <div className="flex flex-col">
                              <p className="text-foreground-light text-left">
                                Can be used with any S3-compatible storage.
                              </p>
                            </div>
                          </div>
                        </RadioGroupStackedItem>
                      </RadioGroupStacked>
                    </FormSectionContent>
                  </FormSection>
                  <FormSection
                    header={<FormSectionLabel>{wrapperMeta.label} Configuration</FormSectionLabel>}
                  >
                    <FormSectionContent loading={false}>
                      {wrapperMeta.server.options
                        .filter((option) => !option.hidden)
                        .map((option) => (
                          <InputField
                            key={option.name}
                            option={option}
                            loading={false}
                            error={formErrors[option.name]}
                          />
                        ))}
                    </FormSectionContent>
                  </FormSection>
                  <Separator />
                  <FormSection
                    header={
                      <FormSectionLabel>
                        <p>Foreign Schema</p>
                        <p className="text-foreground-light mt-2 w-[90%]">
                          You can query your data from the foreign tables in the specified schema
                          after the wrapper is created.
                        </p>
                      </FormSectionLabel>
                    }
                  >
                    <FormSectionContent loading={false}>
                      {wrapperMeta.sourceSchemaOption && (
                        <div>
                          <InputField
                            key="source_schema"
                            option={wrapperMeta.sourceSchemaOption}
                            loading={false}
                            error={formErrors['source_schema']}
                          />
                          <p className="text-foreground-lighter text-sm">
                            {wrapperMeta.sourceSchemaOption.description}
                          </p>
                        </div>
                      )}
                      <div className="flex flex-col gap-2">
                        <InputField
                          key="target_schema"
                          option={{
                            name: 'target_schema',
                            label: 'Specify a new schema to create all wrapper tables in',
                            required: true,
                            encrypted: false,
                            secureEntry: false,
                          }}
                          loading={false}
                          error={formErrors['target_schema']}
                        />
                        <p className="text-foreground-lighter text-sm">
                          A new schema will be created. For security purposes, the wrapper tables
                          from the foreign schema cannot be created within an existing schema.
                        </p>
                      </div>
                    </FormSectionContent>
                  </FormSection>
                </div>

                <SheetFooter>
                  <Button
                    size="tiny"
                    type="default"
                    htmlType="button"
                    onClick={onCloseWithConfirmation}
                    disabled={isLoading}
                  >
                    Cancel
                  </Button>
                  <Button
                    size="tiny"
                    type="primary"
                    form={FORM_ID}
                    htmlType="submit"
                    loading={isLoading}
                  >
                    Create wrapper
                  </Button>
                </SheetFooter>
              </>
            )
          }}
        </Form>
      </div>
    </>
  )
}

Subdomains

Frequently Asked Questions

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

Analyze Your Own Codebase

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

Try Supermodel Free