Skip to content

Commit de2cfaf

Browse files
committed
added fuzzy search for search modal, tested and fixed calendly
1 parent 794bac0 commit de2cfaf

15 files changed

Lines changed: 419 additions & 176 deletions

File tree

apps/sim/app/api/webhooks/route.ts

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,31 @@ export async function POST(request: NextRequest) {
297297
}
298298
}
299299

300+
if (provider === 'calendly') {
301+
logger.info(`[${requestId}] Creating Calendly subscription before saving to database`)
302+
try {
303+
externalSubscriptionId = await createCalendlyWebhookSubscription(
304+
request,
305+
userId,
306+
createTempWebhookData(),
307+
requestId
308+
)
309+
if (externalSubscriptionId) {
310+
resolvedProviderConfig.externalId = externalSubscriptionId
311+
externalSubscriptionCreated = true
312+
}
313+
} catch (err) {
314+
logger.error(`[${requestId}] Error creating Calendly webhook subscription`, err)
315+
return NextResponse.json(
316+
{
317+
error: 'Failed to create webhook in Calendly',
318+
details: err instanceof Error ? err.message : 'Unknown error',
319+
},
320+
{ status: 500 }
321+
)
322+
}
323+
}
324+
300325
if (provider === 'microsoft-teams') {
301326
const { createTeamsSubscription } = await import('@/lib/webhooks/webhook-helpers')
302327
logger.info(`[${requestId}] Creating Teams subscription before saving to database`)
@@ -635,6 +660,140 @@ async function createAirtableWebhookSubscription(
635660
throw error
636661
}
637662
}
663+
664+
// Helper function to create the webhook subscription in Calendly
665+
async function createCalendlyWebhookSubscription(
666+
request: NextRequest,
667+
userId: string,
668+
webhookData: any,
669+
requestId: string
670+
): Promise<string | undefined> {
671+
try {
672+
const { path, providerConfig } = webhookData
673+
const { apiKey, organization, triggerId } = providerConfig || {}
674+
675+
if (!apiKey) {
676+
logger.warn(`[${requestId}] Missing apiKey for Calendly webhook creation.`, {
677+
webhookId: webhookData.id,
678+
})
679+
throw new Error(
680+
'Personal Access Token is required to create Calendly webhook. Please provide your Calendly Personal Access Token.'
681+
)
682+
}
683+
684+
if (!organization) {
685+
logger.warn(`[${requestId}] Missing organization URI for Calendly webhook creation.`, {
686+
webhookId: webhookData.id,
687+
})
688+
throw new Error(
689+
'Organization URI is required to create Calendly webhook. Please provide your Organization URI from the "Get Current User" operation.'
690+
)
691+
}
692+
693+
if (!triggerId) {
694+
logger.warn(`[${requestId}] Missing triggerId for Calendly webhook creation.`, {
695+
webhookId: webhookData.id,
696+
})
697+
throw new Error('Trigger ID is required to create Calendly webhook')
698+
}
699+
700+
const notificationUrl = `${getBaseUrl()}/api/webhooks/trigger/${path}`
701+
702+
// Map trigger IDs to Calendly event types
703+
const eventTypeMap: Record<string, string[]> = {
704+
calendly_invitee_created: ['invitee.created'],
705+
calendly_invitee_canceled: ['invitee.canceled'],
706+
calendly_routing_form_submitted: ['routing_form_submission.created'],
707+
calendly_webhook: ['invitee.created', 'invitee.canceled', 'routing_form_submission.created'],
708+
}
709+
710+
const events = eventTypeMap[triggerId] || ['invitee.created']
711+
712+
const calendlyApiUrl = 'https://api.calendly.com/webhook_subscriptions'
713+
714+
const requestBody = {
715+
url: notificationUrl,
716+
events,
717+
organization,
718+
scope: 'organization',
719+
}
720+
721+
const calendlyResponse = await fetch(calendlyApiUrl, {
722+
method: 'POST',
723+
headers: {
724+
Authorization: `Bearer ${apiKey}`,
725+
'Content-Type': 'application/json',
726+
},
727+
body: JSON.stringify(requestBody),
728+
})
729+
730+
if (!calendlyResponse.ok) {
731+
const errorBody = await calendlyResponse.json().catch(() => ({}))
732+
const errorMessage = errorBody.message || errorBody.title || 'Unknown Calendly API error'
733+
logger.error(
734+
`[${requestId}] Failed to create webhook in Calendly for webhook ${webhookData.id}. Status: ${calendlyResponse.status}`,
735+
{ response: errorBody }
736+
)
737+
738+
let userFriendlyMessage = 'Failed to create webhook subscription in Calendly'
739+
if (calendlyResponse.status === 401) {
740+
userFriendlyMessage =
741+
'Calendly authentication failed. Please verify your Personal Access Token is correct.'
742+
} else if (calendlyResponse.status === 403) {
743+
userFriendlyMessage =
744+
'Calendly access denied. Please ensure you have appropriate permissions and a paid Calendly subscription.'
745+
} else if (calendlyResponse.status === 404) {
746+
userFriendlyMessage =
747+
'Calendly organization not found. Please verify the Organization URI is correct.'
748+
} else if (errorMessage && errorMessage !== 'Unknown Calendly API error') {
749+
userFriendlyMessage = `Calendly error: ${errorMessage}`
750+
}
751+
752+
throw new Error(userFriendlyMessage)
753+
}
754+
755+
const responseBody = await calendlyResponse.json()
756+
const webhookUri = responseBody.resource?.uri
757+
758+
if (!webhookUri) {
759+
logger.error(
760+
`[${requestId}] Calendly webhook created but no webhook URI returned for webhook ${webhookData.id}`,
761+
{ response: responseBody }
762+
)
763+
throw new Error('Calendly webhook creation succeeded but no webhook URI was returned')
764+
}
765+
766+
// Extract the webhook ID from the URI (e.g., https://api.calendly.com/webhook_subscriptions/WEBHOOK_ID)
767+
const webhookId = webhookUri.split('/').pop()
768+
769+
if (!webhookId) {
770+
logger.error(`[${requestId}] Could not extract webhook ID from Calendly URI: ${webhookUri}`, {
771+
response: responseBody,
772+
})
773+
throw new Error('Failed to extract webhook ID from Calendly response')
774+
}
775+
776+
logger.info(
777+
`[${requestId}] Successfully created webhook in Calendly for webhook ${webhookData.id}.`,
778+
{
779+
calendlyWebhookUri: webhookUri,
780+
calendlyWebhookId: webhookId,
781+
}
782+
)
783+
return webhookId
784+
} catch (error: any) {
785+
logger.error(
786+
`[${requestId}] Exception during Calendly webhook creation for webhook ${webhookData.id}.`,
787+
{
788+
message: error.message,
789+
stack: error.stack,
790+
}
791+
)
792+
// Re-throw the error so it can be caught by the outer try-catch
793+
throw error
794+
}
795+
}
796+
638797
// Helper function to create the webhook subscription in Webflow
639798
async function createWebflowWebhookSubscription(
640799
request: NextRequest,

apps/sim/app/api/workflows/[id]/execute/route.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -577,10 +577,6 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
577577
if (isStreamClosed) return
578578

579579
try {
580-
logger.info(`[${requestId}] 📤 Sending SSE event:`, {
581-
type: event.type,
582-
data: event.data,
583-
})
584580
controller.enqueue(encodeSSEEvent(event))
585581
} catch {
586582
isStreamClosed = true

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,9 @@ export function DeploymentInfo({
172172
<ModalHeader>
173173
<ModalTitle>Undeploy API</ModalTitle>
174174
<ModalDescription>
175-
Are you sure you want to undeploy this workflow? This will remove the API endpoint and
176-
make it unavailable to external users.{' '}
175+
Are you sure you want to undeploy this workflow?{' '}
177176
<span className='text-[var(--text-error)] dark:text-[var(--text-error)]'>
178-
This action cannot be undone.
177+
This will remove the API endpoint and make it unavailable to external users.{' '}
179178
</span>
180179
</ModalDescription>
181180
</ModalHeader>

0 commit comments

Comments
 (0)