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>
</>
)
}
Domain
Subdomains
Calls
Source
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