Skip to content

Commit dfe8ccb

Browse files
waleedlatif1claude
andcommitted
refactor(workflows): merge lock-db.ts into utils.ts
Move isFolderEffectivelyLockedDb and isWorkflowEffectivelyLockedDb into utils.ts which already imports @sim/db and contains other server-side workflow helpers. Eliminates the non-standard -db suffix file naming and consolidates duplicate imports across 5 route files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent d4b2716 commit dfe8ccb

File tree

11 files changed

+76
-67
lines changed

11 files changed

+76
-67
lines changed

apps/sim/app/api/folders/[id]/duplicate/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
88
import { getSession } from '@/lib/auth'
99
import { generateRequestId } from '@/lib/core/utils/request'
1010
import { generateId } from '@/lib/core/utils/uuid'
11-
import { isFolderEffectivelyLockedDb } from '@/lib/workflows/lock-db'
1211
import { duplicateWorkflow } from '@/lib/workflows/persistence/duplicate'
12+
import { isFolderEffectivelyLockedDb } from '@/lib/workflows/utils'
1313
import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils'
1414

1515
const logger = createLogger('FolderDuplicateAPI')

apps/sim/app/api/folders/[id]/route.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ import { type NextRequest, NextResponse } from 'next/server'
66
import { z } from 'zod'
77
import { getSession } from '@/lib/auth'
88
import { captureServerEvent } from '@/lib/posthog/server'
9-
import { isFolderEffectivelyLockedDb } from '@/lib/workflows/lock-db'
109
import { performDeleteFolder } from '@/lib/workflows/orchestration'
11-
import { checkForCircularReference } from '@/lib/workflows/utils'
10+
import { checkForCircularReference, isFolderEffectivelyLockedDb } from '@/lib/workflows/utils'
1211
import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils'
1312

1413
const logger = createLogger('FoldersIDAPI')

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
88
import { getSession } from '@/lib/auth'
99
import { generateId } from '@/lib/core/utils/uuid'
1010
import { captureServerEvent } from '@/lib/posthog/server'
11-
import { isFolderEffectivelyLockedDb } from '@/lib/workflows/lock-db'
11+
import { isFolderEffectivelyLockedDb } from '@/lib/workflows/utils'
1212
import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils'
1313

1414
const logger = createLogger('FoldersAPI')

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
99
import { PlatformEvents } from '@/lib/core/telemetry'
1010
import { generateRequestId } from '@/lib/core/utils/request'
1111
import { captureServerEvent } from '@/lib/posthog/server'
12-
import { isFolderEffectivelyLockedDb } from '@/lib/workflows/lock-db'
1312
import { duplicateWorkflow } from '@/lib/workflows/persistence/duplicate'
13+
import { isFolderEffectivelyLockedDb } from '@/lib/workflows/utils'
1414

1515
const logger = createLogger('WorkflowDuplicateAPI')
1616

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ import { z } from 'zod'
77
import { AuthType, checkHybridAuth, checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
88
import { generateRequestId } from '@/lib/core/utils/request'
99
import { captureServerEvent } from '@/lib/posthog/server'
10-
import { isWorkflowEffectivelyLockedDb } from '@/lib/workflows/lock-db'
1110
import { performDeleteWorkflow } from '@/lib/workflows/orchestration'
1211
import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils'
13-
import { authorizeWorkflowByWorkspacePermission, getWorkflowById } from '@/lib/workflows/utils'
12+
import {
13+
authorizeWorkflowByWorkspacePermission,
14+
getWorkflowById,
15+
isWorkflowEffectivelyLockedDb,
16+
} from '@/lib/workflows/utils'
1417

1518
const logger = createLogger('WorkflowByIdAPI')
1619

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ import { z } from 'zod'
77
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
88
import { env } from '@/lib/core/config/env'
99
import { generateRequestId } from '@/lib/core/utils/request'
10-
import { isWorkflowEffectivelyLockedDb } from '@/lib/workflows/lock-db'
1110
import { extractAndPersistCustomTools } from '@/lib/workflows/persistence/custom-tools-persistence'
1211
import {
1312
loadWorkflowFromNormalizedTables,
1413
saveWorkflowToNormalizedTables,
1514
} from '@/lib/workflows/persistence/utils'
1615
import { sanitizeAgentToolsInBlocks } from '@/lib/workflows/sanitization/validation'
17-
import { authorizeWorkflowByWorkspacePermission } from '@/lib/workflows/utils'
16+
import {
17+
authorizeWorkflowByWorkspacePermission,
18+
isWorkflowEffectivelyLockedDb,
19+
} from '@/lib/workflows/utils'
1820
import { validateEdges } from '@/stores/workflows/workflow/edge-validation'
1921
import type { BlockState, WorkflowState } from '@/stores/workflows/workflow/types'
2022
import { generateLoopBlocks, generateParallelBlocks } from '@/stores/workflows/workflow/utils'

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ import { z } from 'zod'
77
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
88
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
99
import { generateRequestId } from '@/lib/core/utils/request'
10-
import { isWorkflowEffectivelyLockedDb } from '@/lib/workflows/lock-db'
11-
import { authorizeWorkflowByWorkspacePermission } from '@/lib/workflows/utils'
10+
import {
11+
authorizeWorkflowByWorkspacePermission,
12+
isWorkflowEffectivelyLockedDb,
13+
} from '@/lib/workflows/utils'
1214
import type { Variable } from '@/stores/variables/types'
1315

1416
const logger = createLogger('WorkflowVariablesAPI')

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ import { generateId } from '@/lib/core/utils/uuid'
1111
import { captureServerEvent } from '@/lib/posthog/server'
1212
import { getNextWorkflowColor } from '@/lib/workflows/colors'
1313
import { buildDefaultWorkflowArtifacts } from '@/lib/workflows/defaults'
14-
import { isFolderEffectivelyLockedDb } from '@/lib/workflows/lock-db'
1514
import { saveWorkflowToNormalizedTables } from '@/lib/workflows/persistence/utils'
16-
import { deduplicateWorkflowName, listWorkflows, type WorkflowScope } from '@/lib/workflows/utils'
15+
import {
16+
deduplicateWorkflowName,
17+
isFolderEffectivelyLockedDb,
18+
listWorkflows,
19+
type WorkflowScope,
20+
} from '@/lib/workflows/utils'
1721
import { getUserEntityPermissions, workspaceExists } from '@/lib/workspaces/permissions/utils'
1822
import { verifyWorkspaceMembership } from '@/app/api/workflows/utils'
1923

apps/sim/lib/workflows/lock-db.ts

Lines changed: 0 additions & 53 deletions
This file was deleted.

apps/sim/lib/workflows/utils.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,58 @@ export async function setWorkflowVariables(workflowId: string, variables: Record
544544
.where(eq(workflowTable.id, workflowId))
545545
}
546546

547+
// ── Lock checks ──
548+
549+
/**
550+
* DB-backed cascade lock check for folders.
551+
* Walks up the folder tree via DB queries, checking isLocked at each level.
552+
* Uses a visited set to guard against circular references.
553+
*/
554+
export async function isFolderEffectivelyLockedDb(folderId: string): Promise<boolean> {
555+
let currentId: string | null = folderId
556+
const visited = new Set<string>()
557+
558+
while (currentId) {
559+
if (visited.has(currentId)) return false
560+
visited.add(currentId)
561+
562+
const [folder] = await db
563+
.select({
564+
isLocked: workflowFolder.isLocked,
565+
parentId: workflowFolder.parentId,
566+
})
567+
.from(workflowFolder)
568+
.where(eq(workflowFolder.id, currentId))
569+
.limit(1)
570+
571+
if (!folder) return false
572+
if (folder.isLocked) return true
573+
currentId = folder.parentId
574+
}
575+
576+
return false
577+
}
578+
579+
/**
580+
* DB-backed cascade lock check for workflows.
581+
* Checks the workflow's own isLocked flag, then walks its folder chain.
582+
*/
583+
export async function isWorkflowEffectivelyLockedDb(workflowId: string): Promise<boolean> {
584+
const [wf] = await db
585+
.select({
586+
isLocked: workflowTable.isLocked,
587+
folderId: workflowTable.folderId,
588+
})
589+
.from(workflowTable)
590+
.where(eq(workflowTable.id, workflowId))
591+
.limit(1)
592+
593+
if (!wf) return false
594+
if (wf.isLocked) return true
595+
if (wf.folderId) return isFolderEffectivelyLockedDb(wf.folderId)
596+
return false
597+
}
598+
547599
// ── Folder CRUD ──
548600

549601
export interface CreateFolderInput {

0 commit comments

Comments
 (0)