@@ -317,6 +317,8 @@ interface WebhookMetadata {
317317 providerConfig : Record < string , any >
318318}
319319
320+ const CREDENTIAL_SET_PREFIX = 'credentialSet:'
321+
320322function buildWebhookMetadata ( block : BlockState ) : WebhookMetadata | null {
321323 const triggerId =
322324 getSubBlockValue < string > ( block , 'triggerId' ) ||
@@ -328,9 +330,17 @@ function buildWebhookMetadata(block: BlockState): WebhookMetadata | null {
328330 const triggerDef = triggerId ? getTrigger ( triggerId ) : undefined
329331 const provider = triggerDef ?. provider || null
330332
333+ // Handle credential sets vs individual credentials
334+ const isCredentialSet = triggerCredentials ?. startsWith ( CREDENTIAL_SET_PREFIX )
335+ const credentialSetId = isCredentialSet
336+ ? triggerCredentials . slice ( CREDENTIAL_SET_PREFIX . length )
337+ : undefined
338+ const credentialId = isCredentialSet ? undefined : triggerCredentials
339+
331340 const providerConfig = {
332341 ...( typeof triggerConfig === 'object' ? triggerConfig : { } ) ,
333- ...( triggerCredentials ? { credentialId : triggerCredentials } : { } ) ,
342+ ...( credentialId ? { credentialId } : { } ) ,
343+ ...( credentialSetId ? { credentialSetId } : { } ) ,
334344 ...( triggerId ? { triggerId } : { } ) ,
335345 }
336346
@@ -347,6 +357,54 @@ async function upsertWebhookRecord(
347357 webhookId : string ,
348358 metadata : WebhookMetadata
349359) : Promise < void > {
360+ const providerConfig = metadata . providerConfig as Record < string , unknown >
361+ const credentialSetId = providerConfig ?. credentialSetId as string | undefined
362+
363+ // For credential sets, delegate to the sync function which handles fan-out
364+ if ( credentialSetId && metadata . provider ) {
365+ const { syncWebhooksForCredentialSet } = await import ( '@/lib/webhooks/utils.server' )
366+ const { getProviderIdFromServiceId } = await import ( '@/lib/oauth' )
367+
368+ const oauthProviderId = getProviderIdFromServiceId ( metadata . provider )
369+ const requestId = crypto . randomUUID ( ) . slice ( 0 , 8 )
370+
371+ // Extract base config (without credential-specific fields)
372+ const {
373+ credentialId : _cId ,
374+ credentialSetId : _csId ,
375+ userId : _uId ,
376+ ...baseConfig
377+ } = providerConfig
378+
379+ try {
380+ await syncWebhooksForCredentialSet ( {
381+ workflowId,
382+ blockId : block . id ,
383+ provider : metadata . provider ,
384+ basePath : metadata . triggerPath ,
385+ credentialSetId,
386+ oauthProviderId,
387+ providerConfig : baseConfig as Record < string , any > ,
388+ requestId,
389+ } )
390+
391+ logger . info ( 'Synced credential set webhooks during workflow save' , {
392+ workflowId,
393+ blockId : block . id ,
394+ credentialSetId,
395+ } )
396+ } catch ( error ) {
397+ logger . error ( 'Failed to sync credential set webhooks during workflow save' , {
398+ workflowId,
399+ blockId : block . id ,
400+ credentialSetId,
401+ error,
402+ } )
403+ }
404+ return
405+ }
406+
407+ // For individual credentials, use the existing single webhook logic
350408 const [ existing ] = await db . select ( ) . from ( webhook ) . where ( eq ( webhook . id , webhookId ) ) . limit ( 1 )
351409
352410 if ( existing ) {
@@ -374,15 +432,14 @@ async function upsertWebhookRecord(
374432 return
375433 }
376434
377- const providerConfig = metadata . providerConfig as Record < string , unknown >
378435 await db . insert ( webhook ) . values ( {
379436 id : webhookId ,
380437 workflowId,
381438 blockId : block . id ,
382439 path : metadata . triggerPath ,
383440 provider : metadata . provider ,
384441 providerConfig : metadata . providerConfig ,
385- credentialSetId : ( providerConfig ?. credentialSetId as string | null ) || null ,
442+ credentialSetId : null ,
386443 isActive : true ,
387444 createdAt : new Date ( ) ,
388445 updatedAt : new Date ( ) ,
0 commit comments