mirror of
https://github.com/supabase/supabase.git
synced 2026-06-20 23:06:06 +08:00
* Replace all usage of useProjectContext with useSelectedProjectQuery * Replace all usage of useSelectedProject with useSelectedProjectQuery * Replace all usage of useProjectByRef with useProjectByRefQuery * Replace all usage of useSelectedOrganization with useSelectedOrganizationQuery * Deprecate useSelectedProject, useSelectedOrganization, and useProjectByRef hooks * Deprecate ProjecContext
277 lines
11 KiB
TypeScript
277 lines
11 KiB
TypeScript
import { zodResolver } from '@hookform/resolvers/zod'
|
|
import { useForm } from 'react-hook-form'
|
|
import { toast } from 'sonner'
|
|
import * as z from 'zod'
|
|
|
|
import { FormActions } from 'components/ui/Forms/FormActions'
|
|
import type {
|
|
EnvironmentTargets,
|
|
Integration,
|
|
IntegrationProjectConnection,
|
|
} from 'data/integrations/integrations.types'
|
|
import { useVercelConnectionUpdateMutation } from 'data/integrations/vercel-connection-update-mutate'
|
|
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
|
import Link from 'next/link'
|
|
import {
|
|
AlertDescription_Shadcn_,
|
|
AlertTitle_Shadcn_,
|
|
Alert_Shadcn_,
|
|
FormControl_Shadcn_,
|
|
FormDescription_Shadcn_,
|
|
FormField_Shadcn_,
|
|
FormItem_Shadcn_,
|
|
FormLabel_Shadcn_,
|
|
FormMessage_Shadcn_,
|
|
Form_Shadcn_,
|
|
Input_Shadcn_,
|
|
Switch,
|
|
} from 'ui'
|
|
|
|
const VercelIntegrationConnectionForm = ({
|
|
disabled,
|
|
connection,
|
|
integration,
|
|
}: {
|
|
disabled?: boolean
|
|
connection: IntegrationProjectConnection
|
|
integration: Integration
|
|
}) => {
|
|
// NOTE(kamil): Ignore sync targets for Vercel Marketplace as it's not synchronized using integration,
|
|
// but through a separate marketplace mechanism. It's not theoretically necessary, but we might have some stale data.
|
|
const { data: org } = useSelectedOrganizationQuery()
|
|
const envSyncTargets =
|
|
org?.managed_by === 'vercel-marketplace' ? [] : connection.env_sync_targets ?? []
|
|
|
|
const FormSchema = z.object({
|
|
environmentVariablesProduction: z.boolean().default(envSyncTargets.includes('production')),
|
|
environmentVariablesPreview: z.boolean().default(envSyncTargets.includes('preview')),
|
|
environmentVariablesDevelopment: z.boolean().default(envSyncTargets.includes('development')),
|
|
publicEnvVarPrefix: z.string().optional(),
|
|
})
|
|
|
|
const form = useForm<z.infer<typeof FormSchema>>({
|
|
resolver: zodResolver(FormSchema),
|
|
defaultValues: {
|
|
environmentVariablesProduction: envSyncTargets.includes('production'),
|
|
environmentVariablesPreview: envSyncTargets.includes('preview'),
|
|
environmentVariablesDevelopment: envSyncTargets.includes('development'),
|
|
publicEnvVarPrefix: connection.public_env_var_prefix,
|
|
},
|
|
})
|
|
|
|
const { mutate: updateVercelConnection, isLoading } = useVercelConnectionUpdateMutation({
|
|
onSuccess: () => {
|
|
form.reset(form.getValues())
|
|
toast.success(`Updated Vercel connection`)
|
|
},
|
|
})
|
|
|
|
function onSubmit(data: z.infer<typeof FormSchema>) {
|
|
const {
|
|
environmentVariablesProduction,
|
|
environmentVariablesPreview,
|
|
environmentVariablesDevelopment,
|
|
} = data
|
|
|
|
const envSyncTargets: string[] = []
|
|
|
|
if (environmentVariablesProduction) envSyncTargets.push('production')
|
|
if (environmentVariablesPreview) envSyncTargets.push('preview')
|
|
if (environmentVariablesDevelopment) envSyncTargets.push('development')
|
|
|
|
updateVercelConnection({
|
|
id: connection.id,
|
|
envSyncTargets: envSyncTargets as EnvironmentTargets[],
|
|
publicEnvVarPrefix: data.publicEnvVarPrefix?.trim(),
|
|
organizationIntegrationId: integration.id,
|
|
})
|
|
}
|
|
|
|
const vercelConnectionFormId = `vercel-connection-form-${connection.id}`
|
|
|
|
return (
|
|
<Form_Shadcn_ {...form}>
|
|
<form
|
|
id={vercelConnectionFormId}
|
|
onSubmit={form.handleSubmit(onSubmit)}
|
|
className={'w-full space-y-6'}
|
|
>
|
|
<div className="px-6 py-4 flex flex-col gap-y-4">
|
|
<div className="flex flex-col gap-4">
|
|
{org?.managed_by === 'vercel-marketplace' ? (
|
|
<Alert_Shadcn_>
|
|
<AlertTitle_Shadcn_ className="text-sm">
|
|
Vercel Marketplace managed project
|
|
</AlertTitle_Shadcn_>
|
|
<AlertDescription_Shadcn_ className="text-xs">
|
|
This project is managed via Vercel Marketplace. Environment variables are
|
|
automatically synchronized for your connected Vercel projects. This integration
|
|
purpose is synchronizing preview deployments environment variables with our{' '}
|
|
<Link
|
|
target="_blank"
|
|
rel="noreferrer"
|
|
href="https://supabase.com/docs/guides/platform/branching"
|
|
className="underline"
|
|
>
|
|
Branching
|
|
</Link>{' '}
|
|
feature.
|
|
</AlertDescription_Shadcn_>
|
|
</Alert_Shadcn_>
|
|
) : (
|
|
<div>
|
|
<h5 className="text-foreground ">
|
|
Sync environment variables for selected target environments
|
|
</h5>
|
|
|
|
<FormField_Shadcn_
|
|
control={form.control}
|
|
name="environmentVariablesProduction"
|
|
render={({ field }) => (
|
|
<FormItem_Shadcn_ className="space-y-0 flex gap-x-4">
|
|
<FormControl_Shadcn_>
|
|
<Switch
|
|
disabled={disabled}
|
|
className="mt-1"
|
|
checked={field.value}
|
|
onCheckedChange={field.onChange}
|
|
/>
|
|
</FormControl_Shadcn_>
|
|
<div>
|
|
<FormLabel_Shadcn_ className="!text">Production</FormLabel_Shadcn_>
|
|
<FormDescription_Shadcn_ className="text-xs text-foreground-lighter">
|
|
Sync environment variables for <code>production</code> environment.
|
|
</FormDescription_Shadcn_>
|
|
</div>
|
|
</FormItem_Shadcn_>
|
|
)}
|
|
/>
|
|
<FormField_Shadcn_
|
|
control={form.control}
|
|
name="environmentVariablesPreview"
|
|
render={({ field }) => (
|
|
<FormItem_Shadcn_ className="space-y-0 flex gap-x-4">
|
|
<FormControl_Shadcn_>
|
|
<Switch
|
|
disabled={disabled}
|
|
className="mt-1"
|
|
checked={field.value}
|
|
onCheckedChange={field.onChange}
|
|
/>
|
|
</FormControl_Shadcn_>
|
|
<div>
|
|
<FormLabel_Shadcn_ className="!text">Preview</FormLabel_Shadcn_>
|
|
<FormDescription_Shadcn_ className="text-xs text-foreground-lighter">
|
|
Sync environment variables for <code>preview</code> environment.
|
|
</FormDescription_Shadcn_>
|
|
</div>
|
|
</FormItem_Shadcn_>
|
|
)}
|
|
/>
|
|
<FormField_Shadcn_
|
|
control={form.control}
|
|
name="environmentVariablesDevelopment"
|
|
render={({ field }) => (
|
|
<FormItem_Shadcn_ className="space-y-0 flex gap-x-4">
|
|
<FormControl_Shadcn_>
|
|
<Switch
|
|
disabled={disabled}
|
|
className="mt-1"
|
|
checked={field.value}
|
|
onCheckedChange={field.onChange}
|
|
/>
|
|
</FormControl_Shadcn_>
|
|
<div>
|
|
<FormLabel_Shadcn_ className="!text">Development</FormLabel_Shadcn_>
|
|
<FormDescription_Shadcn_ className="text-xs text-foreground-lighter">
|
|
Sync environment variables for <code>development</code> environment.
|
|
</FormDescription_Shadcn_>
|
|
</div>
|
|
</FormItem_Shadcn_>
|
|
)}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
<h5 className="mt-2 text-foreground">Customize public environment variable prefix</h5>
|
|
<div className="flex flex-col gap-4">
|
|
<FormField_Shadcn_
|
|
control={form.control}
|
|
name="publicEnvVarPrefix"
|
|
render={({ field }) => (
|
|
<FormItem_Shadcn_ className="grid gap-2 md:grid md:grid-cols-12 space-y-0">
|
|
<FormLabel_Shadcn_ className="flex flex-col space-y-2 col-span-4 text-sm justify-center text-foreground-light">
|
|
Prefix
|
|
</FormLabel_Shadcn_>
|
|
<FormControl_Shadcn_ className="col-span-8">
|
|
<Input_Shadcn_
|
|
{...field}
|
|
className="w-full"
|
|
disabled={disabled}
|
|
placeholder="An empty prefix will result in no public env vars"
|
|
/>
|
|
</FormControl_Shadcn_>
|
|
<FormDescription_Shadcn_ className="col-start-5 col-span-8 text-xs">
|
|
e.g.{' '}
|
|
<code
|
|
className="cursor-pointer"
|
|
role="button"
|
|
onClick={() => {
|
|
field.onChange('NEXT_PUBLIC_')
|
|
}}
|
|
>
|
|
NEXT_PUBLIC_
|
|
</code>
|
|
,{' '}
|
|
<code
|
|
className="cursor-pointer"
|
|
role="button"
|
|
onClick={() => {
|
|
field.onChange('VITE_PUBLIC_')
|
|
}}
|
|
>
|
|
VITE_PUBLIC_
|
|
</code>
|
|
,{' '}
|
|
<code
|
|
className="cursor-pointer"
|
|
role="button"
|
|
onClick={() => {
|
|
field.onChange('PUBLIC_')
|
|
}}
|
|
>
|
|
PUBLIC_
|
|
</code>
|
|
, etc.
|
|
</FormDescription_Shadcn_>
|
|
|
|
<FormMessage_Shadcn_ className="col-start-5 col-span-8" />
|
|
</FormItem_Shadcn_>
|
|
)}
|
|
/>
|
|
</div>
|
|
|
|
{form.formState.isDirty ? (
|
|
<p className="mt-2 text-sm text-warning-600">
|
|
Note: Changing these settings will <strong>not</strong> trigger a resync of
|
|
environment variables.
|
|
</p>
|
|
) : (
|
|
<div className="mt-2 h-5 w-full" />
|
|
)}
|
|
|
|
<FormActions
|
|
disabled={disabled}
|
|
form={vercelConnectionFormId}
|
|
hasChanges={form.formState.isDirty}
|
|
isSubmitting={isLoading}
|
|
handleReset={() => form.reset()}
|
|
/>
|
|
</div>
|
|
</form>
|
|
</Form_Shadcn_>
|
|
)
|
|
}
|
|
|
|
export default VercelIntegrationConnectionForm
|