EdgeFunctionRenderer.tsx127 lines · main
1// @ts-nocheck
2import { useParams } from 'common'
3import { useMemo, useState, type PropsWithChildren } from 'react'
4
5import { EdgeFunctionBlock } from '../EdgeFunctionBlock/EdgeFunctionBlock'
6import { ConfirmFooter } from './ConfirmFooter'
7import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query'
8import { useEdgeFunctionQuery } from '@/data/edge-functions/edge-function-query'
9import { useSendEventMutation } from '@/data/telemetry/send-event-mutation'
10import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
11
12interface EdgeFunctionRendererProps {
13 label: string
14 code: string
15 functionName: string
16 onApprove?: () => void
17 onDeny?: () => void
18 isDeploying?: boolean
19 initialIsDeployed?: boolean
20 showConfirmFooter?: boolean
21}
22
23export const EdgeFunctionRenderer = ({
24 label,
25 code,
26 functionName,
27 onApprove,
28 onDeny,
29 isDeploying = false,
30 initialIsDeployed,
31 showConfirmFooter = true,
32}: PropsWithChildren<EdgeFunctionRendererProps>) => {
33 const { ref } = useParams()
34 const { data: org } = useSelectedOrganizationQuery()
35 const { mutate: sendEvent } = useSendEventMutation()
36 const [showReplaceWarning, setShowReplaceWarning] = useState(false)
37
38 const { data: settings } = useProjectSettingsV2Query({ projectRef: ref }, { enabled: !!ref })
39 const { data: existingFunction } = useEdgeFunctionQuery(
40 { projectRef: ref, slug: functionName },
41 { enabled: !!ref && !!functionName && !initialIsDeployed }
42 )
43
44 const functionUrl = useMemo(() => {
45 const endpoint = settings?.app_config?.endpoint
46 if (!endpoint || !ref || !functionName) return undefined
47
48 try {
49 const url = new URL(`https://${endpoint}`)
50 const restUrlTld = url.hostname.split('.').pop()
51 return restUrlTld
52 ? `https://${ref}.briven.${restUrlTld}/functions/v1/${functionName}`
53 : undefined
54 } catch (error) {
55 return undefined
56 }
57 }, [settings?.app_config?.endpoint, ref, functionName])
58
59 const deploymentDetailsUrl = useMemo(() => {
60 if (!ref || !functionName) return undefined
61 return `/project/${ref}/functions/${functionName}/details`
62 }, [ref, functionName])
63
64 const downloadCommand = useMemo(() => {
65 if (!functionName) return undefined
66 return `briven functions download ${functionName}`
67 }, [functionName])
68
69 const approveDeploy = () => {
70 if (!code || isDeploying || !ref || !functionName) return
71
72 setShowReplaceWarning(false)
73 sendEvent({
74 action: 'edge_function_deploy_button_clicked',
75 properties: { origin: 'functions_ai_assistant' },
76 groups: {
77 project: ref ?? 'Unknown',
78 organization: org?.slug ?? 'Unknown',
79 },
80 })
81 onApprove?.()
82 }
83
84 const handleDeploy = () => {
85 if (!code || isDeploying || !ref || !functionName) return
86
87 if (existingFunction) {
88 setShowReplaceWarning(true)
89 return
90 }
91
92 approveDeploy()
93 }
94
95 return (
96 <div className="w-auto overflow-x-hidden my-4">
97 <EdgeFunctionBlock
98 label={label}
99 code={code}
100 functionName={functionName}
101 disabled={showConfirmFooter}
102 isDeploying={isDeploying}
103 isDeployed={initialIsDeployed}
104 functionUrl={functionUrl}
105 deploymentDetailsUrl={deploymentDetailsUrl}
106 downloadCommand={downloadCommand}
107 hideDeployButton={showConfirmFooter || initialIsDeployed}
108 showReplaceWarning={showReplaceWarning}
109 onCancelReplace={() => setShowReplaceWarning(false)}
110 onConfirmReplace={approveDeploy}
111 />
112 {showConfirmFooter && (
113 <div className="mx-4">
114 <ConfirmFooter
115 message="Assistant wants to deploy this Edge Function"
116 cancelLabel="Skip"
117 confirmLabel="Deploy"
118 confirmLabelLoading="Deploying..."
119 isLoading={isDeploying}
120 onCancel={() => onDeny?.()}
121 onConfirm={handleDeploy}
122 />
123 </div>
124 )}
125 </div>
126 )
127}