@@ -625,44 +625,74 @@ async function handleBlocksOperationTx(
625625
626626 logger . info ( `Batch removing ${ ids . length } blocks from workflow ${ workflowId } ` )
627627
628- // Collect all block IDs including children of subflows
629- const allBlocksToDelete = new Set < string > ( ids )
628+ // Fetch all blocks to check lock status and filter out protected blocks
629+ const allBlocks = await tx
630+ . select ( {
631+ id : workflowBlocks . id ,
632+ type : workflowBlocks . type ,
633+ locked : workflowBlocks . locked ,
634+ data : workflowBlocks . data ,
635+ } )
636+ . from ( workflowBlocks )
637+ . where ( eq ( workflowBlocks . workflowId , workflowId ) )
630638
631- for ( const id of ids ) {
632- const blockToRemove = await tx
633- . select ( { type : workflowBlocks . type } )
634- . from ( workflowBlocks )
635- . where ( and ( eq ( workflowBlocks . id , id ) , eq ( workflowBlocks . workflowId , workflowId ) ) )
636- . limit ( 1 )
639+ type BlockRecord = ( typeof allBlocks ) [ number ]
640+ const blocksById : Record < string , BlockRecord > = Object . fromEntries (
641+ allBlocks . map ( ( b : BlockRecord ) => [ b . id , b ] )
642+ )
637643
638- if ( blockToRemove . length > 0 && isSubflowBlockType ( blockToRemove [ 0 ] . type ) ) {
639- const childBlocks = await tx
640- . select ( { id : workflowBlocks . id } )
641- . from ( workflowBlocks )
642- . where (
643- and (
644- eq ( workflowBlocks . workflowId , workflowId ) ,
645- sql `${ workflowBlocks . data } ->>'parentId' = ${ id } `
646- )
647- )
644+ // Helper to check if a block is protected (locked or inside locked parent)
645+ const isProtected = ( blockId : string ) : boolean => {
646+ const block = blocksById [ blockId ]
647+ if ( ! block ) return false
648+ if ( block . locked ) return true
649+ const parentId = ( block . data as Record < string , unknown > | null ) ?. parentId as
650+ | string
651+ | undefined
652+ if ( parentId && blocksById [ parentId ] ?. locked ) return true
653+ return false
654+ }
648655
649- childBlocks . forEach ( ( child : { id : string } ) => allBlocksToDelete . add ( child . id ) )
656+ // Filter out protected blocks from deletion request
657+ const deletableIds = ids . filter ( ( id ) => ! isProtected ( id ) )
658+ if ( deletableIds . length === 0 ) {
659+ logger . info ( 'All requested blocks are protected, skipping deletion' )
660+ return
661+ }
662+
663+ if ( deletableIds . length < ids . length ) {
664+ logger . info (
665+ `Filtered out ${ ids . length - deletableIds . length } protected blocks from deletion`
666+ )
667+ }
668+
669+ // Collect all block IDs including children of subflows
670+ const allBlocksToDelete = new Set < string > ( deletableIds )
671+
672+ for ( const id of deletableIds ) {
673+ const block = blocksById [ id ]
674+ if ( block && isSubflowBlockType ( block . type ) ) {
675+ // Include all children of the subflow (they should be deleted with parent)
676+ for ( const b of allBlocks ) {
677+ const parentId = ( b . data as Record < string , unknown > | null ) ?. parentId
678+ if ( parentId === id ) {
679+ allBlocksToDelete . add ( b . id )
680+ }
681+ }
650682 }
651683 }
652684
653685 const blockIdsArray = Array . from ( allBlocksToDelete )
654686
655- // Collect parent IDs BEFORE deleting blocks
687+ // Collect parent IDs BEFORE deleting blocks (use blocksById, already fetched)
656688 const parentIds = new Set < string > ( )
657- for ( const id of ids ) {
658- const parentInfo = await tx
659- . select ( { parentId : sql < string | null > `${ workflowBlocks . data } ->>'parentId'` } )
660- . from ( workflowBlocks )
661- . where ( and ( eq ( workflowBlocks . id , id ) , eq ( workflowBlocks . workflowId , workflowId ) ) )
662- . limit ( 1 )
663-
664- if ( parentInfo . length > 0 && parentInfo [ 0 ] . parentId ) {
665- parentIds . add ( parentInfo [ 0 ] . parentId )
689+ for ( const id of deletableIds ) {
690+ const block = blocksById [ id ]
691+ const parentId = ( block ?. data as Record < string , unknown > | null ) ?. parentId as
692+ | string
693+ | undefined
694+ if ( parentId ) {
695+ parentIds . add ( parentId )
666696 }
667697 }
668698
0 commit comments