@@ -2,7 +2,9 @@ import { useCallback, useEffect, useMemo, useState } from 'react'
22import { useParams } from 'next/navigation'
33import { createLogger } from '@/lib/logs/console/logger'
44import { getBaseUrl } from '@/lib/urls/utils'
5+ import { getBlock } from '@/blocks'
56import { useSubBlockStore } from '@/stores/workflows/subblock/store'
7+ import { useWorkflowStore } from '@/stores/workflows/workflow/store'
68import { getTrigger , isTriggerValid } from '@/triggers'
79import { populateTriggerFieldsFromConfig } from './use-trigger-config-aggregation'
810
@@ -78,15 +80,26 @@ export function useWebhookManagement({
7880 const store = useSubBlockStore . getState ( )
7981 const currentlyLoading = store . loadingWebhooks . has ( blockId )
8082 const alreadyChecked = store . checkedWebhooks . has ( blockId )
83+ const currentWebhookId = store . getValue ( blockId , 'webhookId' )
8184
8285 if ( currentlyLoading ) {
8386 return
8487 }
8588
86- if ( alreadyChecked ) {
89+ // If already checked and webhookId exists, skip fetching
90+ if ( alreadyChecked && currentWebhookId ) {
8791 return
8892 }
8993
94+ // If already checked but webhookId is null, allow re-checking (handles timing issues)
95+ if ( alreadyChecked && ! currentWebhookId ) {
96+ useSubBlockStore . setState ( ( state ) => {
97+ const newSet = new Set ( state . checkedWebhooks )
98+ newSet . delete ( blockId )
99+ return { checkedWebhooks : newSet }
100+ } )
101+ }
102+
90103 let isMounted = true
91104
92105 const loadWebhookOrGenerateUrl = async ( ) => {
@@ -101,11 +114,23 @@ export function useWebhookManagement({
101114
102115 try {
103116 const response = await fetch ( `/api/webhooks?workflowId=${ workflowId } &blockId=${ blockId } ` )
104- if ( response . ok && isMounted ) {
117+ const stillMounted = isMounted // Capture mount state at response time
118+
119+ // Process response even if component unmounted, since we're using Zustand (global store)
120+ // The webhookId should be set in the store regardless of component lifecycle
121+ if ( response . ok ) {
105122 const data = await response . json ( )
123+
106124 if ( data . webhooks && data . webhooks . length > 0 ) {
107125 const webhook = data . webhooks [ 0 ] . webhook
126+
108127 useSubBlockStore . getState ( ) . setValue ( blockId , 'webhookId' , webhook . id )
128+ logger . info ( 'Webhook loaded from API' , {
129+ blockId,
130+ webhookId : webhook . id ,
131+ hasProviderConfig : ! ! webhook . providerConfig ,
132+ wasMounted : stillMounted ,
133+ } )
109134
110135 if ( webhook . path ) {
111136 const currentPath = useSubBlockStore . getState ( ) . getValue ( blockId , 'triggerPath' )
@@ -115,27 +140,78 @@ export function useWebhookManagement({
115140 }
116141
117142 if ( webhook . providerConfig ) {
143+ // Determine triggerId from multiple sources
144+ let effectiveTriggerId : string | undefined = triggerId
145+ if ( ! effectiveTriggerId ) {
146+ // Try to get from stored value
147+ const storedTriggerId = useSubBlockStore . getState ( ) . getValue ( blockId , 'triggerId' )
148+ effectiveTriggerId =
149+ ( typeof storedTriggerId === 'string' ? storedTriggerId : undefined ) || undefined
150+ }
151+ if ( ! effectiveTriggerId && webhook . providerConfig . triggerId ) {
152+ effectiveTriggerId =
153+ typeof webhook . providerConfig . triggerId === 'string'
154+ ? webhook . providerConfig . triggerId
155+ : undefined
156+ }
157+ if ( ! effectiveTriggerId ) {
158+ // Try to determine from block config
159+ const workflowState = useWorkflowStore . getState ( )
160+ const block = workflowState . blocks ?. [ blockId ]
161+ if ( block ) {
162+ const blockConfig = getBlock ( block . type )
163+ if ( blockConfig ) {
164+ if ( blockConfig . category === 'triggers' ) {
165+ effectiveTriggerId = block . type
166+ } else if ( block . triggerMode && blockConfig . triggers ?. enabled ) {
167+ const triggerIdValue = block . subBlocks ?. triggerId ?. value
168+ effectiveTriggerId =
169+ ( typeof triggerIdValue === 'string' ? triggerIdValue : undefined ) ||
170+ blockConfig . triggers ?. available ?. [ 0 ]
171+ }
172+ }
173+ }
174+ }
175+
118176 const currentConfig = useSubBlockStore . getState ( ) . getValue ( blockId , 'triggerConfig' )
119177 if ( JSON . stringify ( webhook . providerConfig ) !== JSON . stringify ( currentConfig ) ) {
120178 useSubBlockStore
121179 . getState ( )
122180 . setValue ( blockId , 'triggerConfig' , webhook . providerConfig )
123181
124- populateTriggerFieldsFromConfig ( blockId , webhook . providerConfig , triggerId )
182+ if ( effectiveTriggerId ) {
183+ populateTriggerFieldsFromConfig (
184+ blockId ,
185+ webhook . providerConfig ,
186+ effectiveTriggerId
187+ )
188+ } else {
189+ logger . warn ( 'Cannot migrate - triggerId not available' , {
190+ blockId,
191+ propTriggerId : triggerId ,
192+ providerConfigTriggerId : webhook . providerConfig . triggerId ,
193+ } )
194+ }
125195 }
126196 }
127- } else if ( isMounted ) {
197+ } else {
128198 useSubBlockStore . getState ( ) . setValue ( blockId , 'webhookId' , null )
129199 }
130200
131- if ( isMounted ) {
132- useSubBlockStore . setState ( ( state ) => ( {
133- checkedWebhooks : new Set ( [ ...state . checkedWebhooks , blockId ] ) ,
134- } ) )
135- }
201+ // Mark as checked even if component unmounted, since Zustand state persists
202+ useSubBlockStore . setState ( ( state ) => ( {
203+ checkedWebhooks : new Set ( [ ...state . checkedWebhooks , blockId ] ) ,
204+ } ) )
205+ } else {
206+ logger . warn ( 'API response not OK' , {
207+ blockId,
208+ workflowId,
209+ status : response . status ,
210+ statusText : response . statusText ,
211+ } )
136212 }
137213 } catch ( error ) {
138- logger . error ( 'Error loading webhook:' , { error } )
214+ logger . error ( 'Error loading webhook:' , { error, blockId , workflowId } )
139215 } finally {
140216 useSubBlockStore . setState ( ( state ) => {
141217 const newSet = new Set ( state . loadingWebhooks )
@@ -150,6 +226,8 @@ export function useWebhookManagement({
150226 return ( ) => {
151227 isMounted = false
152228 }
229+ // Note: Intentionally not including webhookId in dependencies to avoid re-running when it changes
230+ // eslint-disable-next-line react-hooks/exhaustive-deps
153231 } , [ isPreview , triggerId , workflowId , blockId ] )
154232
155233 const saveConfig = async ( ) : Promise < boolean > => {
0 commit comments