( tx: any, workflowId: string, operation: string, payload: any )
| 1763 | |
| 1764 | // Subblock operations - targeted value updates without replacing workflow state |
| 1765 | async function handleSubblockOperationTx( |
| 1766 | tx: any, |
| 1767 | workflowId: string, |
| 1768 | operation: string, |
| 1769 | payload: any |
| 1770 | ) { |
| 1771 | switch (operation) { |
| 1772 | case SUBBLOCK_OPERATIONS.BATCH_UPDATE: { |
| 1773 | const updates = payload.updates |
| 1774 | if (!Array.isArray(updates) || updates.length === 0) { |
| 1775 | return |
| 1776 | } |
| 1777 | |
| 1778 | const allBlocks = await tx |
| 1779 | .select({ |
| 1780 | id: workflowBlocks.id, |
| 1781 | subBlocks: workflowBlocks.subBlocks, |
| 1782 | locked: workflowBlocks.locked, |
| 1783 | data: workflowBlocks.data, |
| 1784 | }) |
| 1785 | .from(workflowBlocks) |
| 1786 | .where(eq(workflowBlocks.workflowId, workflowId)) |
| 1787 | |
| 1788 | type SubblockUpdateBlockRecord = (typeof allBlocks)[number] |
| 1789 | const blocksById: Record<string, SubblockUpdateBlockRecord> = Object.fromEntries( |
| 1790 | allBlocks.map((block: SubblockUpdateBlockRecord) => [block.id, block]) |
| 1791 | ) |
| 1792 | |
| 1793 | for (const update of updates) { |
| 1794 | const { blockId, subblockId, value, expectedValue } = update |
| 1795 | if (!blockId || !subblockId) { |
| 1796 | throw new Error('Missing required fields for subblock batch update') |
| 1797 | } |
| 1798 | |
| 1799 | const block = blocksById[blockId] |
| 1800 | if (!block) { |
| 1801 | throw new Error(`Block ${blockId} not found`) |
| 1802 | } |
| 1803 | |
| 1804 | if (isWorkflowBlockProtected(blockId, blocksById)) { |
| 1805 | throw new Error(`Block ${blockId} is locked or inside a locked container`) |
| 1806 | } |
| 1807 | |
| 1808 | const subBlocks = { ...((block.subBlocks as Record<string, any>) || {}) } |
| 1809 | const currentSubBlock = subBlocks[subblockId] |
| 1810 | const currentValue = currentSubBlock?.value |
| 1811 | if (expectedValue !== undefined && !valuesEqual(currentValue, expectedValue)) { |
| 1812 | throw new Error(`Subblock ${blockId}.${subblockId} changed since replacement was planned`) |
| 1813 | } |
| 1814 | |
| 1815 | subBlocks[subblockId] = currentSubBlock |
| 1816 | ? { ...currentSubBlock, value } |
| 1817 | : { id: subblockId, type: 'unknown', value } |
| 1818 | |
| 1819 | await tx |
| 1820 | .update(workflowBlocks) |
| 1821 | .set({ |
| 1822 | subBlocks, |
no test coverage detected