Skip to content

Commit 8668622

Browse files
authored
feat(duplicate): duplicate variables when duplicating a workflow (#1254)
* feat(duplicate): duplicate variables when duplicating a workflow * better typing
1 parent 53dd277 commit 8668622

File tree

4 files changed

+53
-2
lines changed

4 files changed

+53
-2
lines changed

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { createLogger } from '@/lib/logs/console/logger'
77
import { getUserEntityPermissions } from '@/lib/permissions/utils'
88
import { db } from '@/db'
99
import { workflow, workflowBlocks, workflowEdges, workflowSubflows } from '@/db/schema'
10+
import type { Variable } from '@/stores/panel/variables/types'
1011
import type { LoopConfig, ParallelConfig } from '@/stores/workflows/workflow/types'
1112

1213
const logger = createLogger('WorkflowDuplicateAPI')
@@ -97,7 +98,20 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
9798
isDeployed: false,
9899
collaborators: [],
99100
runCount: 0,
100-
variables: source.variables || {},
101+
// Duplicate variables with new IDs and new workflowId
102+
variables: (() => {
103+
const sourceVars = (source.variables as Record<string, Variable>) || {}
104+
const remapped: Record<string, Variable> = {}
105+
for (const [, variable] of Object.entries(sourceVars) as [string, Variable][]) {
106+
const newVarId = crypto.randomUUID()
107+
remapped[newVarId] = {
108+
...variable,
109+
id: newVarId,
110+
workflowId: newWorkflowId,
111+
}
112+
}
113+
return remapped
114+
})(),
101115
isPublished: false,
102116
marketplaceData: null,
103117
})

apps/sim/stores/panel/variables/store.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,34 @@ export const useVariablesStore = create<VariablesStore>()(
9797
error: null,
9898
isEditing: null,
9999

100+
async loadForWorkflow(workflowId) {
101+
try {
102+
set({ isLoading: true, error: null })
103+
const res = await fetch(`/api/workflows/${workflowId}/variables`, { method: 'GET' })
104+
if (!res.ok) {
105+
const text = await res.text().catch(() => '')
106+
throw new Error(text || `Failed to load variables: ${res.statusText}`)
107+
}
108+
const data = await res.json()
109+
const variables = (data?.data as Record<string, Variable>) || {}
110+
set((state) => {
111+
const withoutWorkflow = Object.fromEntries(
112+
Object.entries(state.variables).filter(
113+
(entry): entry is [string, Variable] => entry[1].workflowId !== workflowId
114+
)
115+
)
116+
return {
117+
variables: { ...withoutWorkflow, ...variables },
118+
isLoading: false,
119+
error: null,
120+
}
121+
})
122+
} catch (e) {
123+
const message = e instanceof Error ? e.message : 'Unknown error'
124+
set({ isLoading: false, error: message })
125+
}
126+
},
127+
100128
addVariable: (variable, providedId?: string) => {
101129
const id = providedId || crypto.randomUUID()
102130

apps/sim/stores/panel/variables/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ export interface VariablesStore {
2323
error: string | null
2424
isEditing: string | null
2525

26+
/**
27+
* Loads variables for a specific workflow from the API and hydrates the store.
28+
*/
29+
loadForWorkflow: (workflowId: string) => Promise<void>
30+
2631
/**
2732
* Adds a new variable with automatic name uniqueness validation
2833
* If a variable with the same name exists, it will be suffixed with a number

apps/sim/stores/workflows/registry/store.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,11 @@ export const useWorkflowRegistry = create<WorkflowRegistry>()(
11901190
}))
11911191
}
11921192

1193-
// Workflow has already been persisted to the database via the duplication endpoint
1193+
try {
1194+
await useVariablesStore.getState().loadForWorkflow(id)
1195+
} catch (error) {
1196+
logger.warn(`Error hydrating variables for duplicated workflow ${id}:`, error)
1197+
}
11941198

11951199
logger.info(
11961200
`Duplicated workflow ${sourceId} to ${id} in workspace ${workspaceId || 'none'}`

0 commit comments

Comments
 (0)