mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-09 23:17:59 -05:00
feat(duplicate): duplicate variables when duplicating a workflow (#1254)
* feat(duplicate): duplicate variables when duplicating a workflow * better typing
This commit is contained in:
@@ -7,6 +7,7 @@ import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { getUserEntityPermissions } from '@/lib/permissions/utils'
|
||||
import { db } from '@/db'
|
||||
import { workflow, workflowBlocks, workflowEdges, workflowSubflows } from '@/db/schema'
|
||||
import type { Variable } from '@/stores/panel/variables/types'
|
||||
import type { LoopConfig, ParallelConfig } from '@/stores/workflows/workflow/types'
|
||||
|
||||
const logger = createLogger('WorkflowDuplicateAPI')
|
||||
@@ -97,7 +98,20 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
|
||||
isDeployed: false,
|
||||
collaborators: [],
|
||||
runCount: 0,
|
||||
variables: source.variables || {},
|
||||
// Duplicate variables with new IDs and new workflowId
|
||||
variables: (() => {
|
||||
const sourceVars = (source.variables as Record<string, Variable>) || {}
|
||||
const remapped: Record<string, Variable> = {}
|
||||
for (const [, variable] of Object.entries(sourceVars) as [string, Variable][]) {
|
||||
const newVarId = crypto.randomUUID()
|
||||
remapped[newVarId] = {
|
||||
...variable,
|
||||
id: newVarId,
|
||||
workflowId: newWorkflowId,
|
||||
}
|
||||
}
|
||||
return remapped
|
||||
})(),
|
||||
isPublished: false,
|
||||
marketplaceData: null,
|
||||
})
|
||||
|
||||
@@ -97,6 +97,34 @@ export const useVariablesStore = create<VariablesStore>()(
|
||||
error: null,
|
||||
isEditing: null,
|
||||
|
||||
async loadForWorkflow(workflowId) {
|
||||
try {
|
||||
set({ isLoading: true, error: null })
|
||||
const res = await fetch(`/api/workflows/${workflowId}/variables`, { method: 'GET' })
|
||||
if (!res.ok) {
|
||||
const text = await res.text().catch(() => '')
|
||||
throw new Error(text || `Failed to load variables: ${res.statusText}`)
|
||||
}
|
||||
const data = await res.json()
|
||||
const variables = (data?.data as Record<string, Variable>) || {}
|
||||
set((state) => {
|
||||
const withoutWorkflow = Object.fromEntries(
|
||||
Object.entries(state.variables).filter(
|
||||
(entry): entry is [string, Variable] => entry[1].workflowId !== workflowId
|
||||
)
|
||||
)
|
||||
return {
|
||||
variables: { ...withoutWorkflow, ...variables },
|
||||
isLoading: false,
|
||||
error: null,
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
const message = e instanceof Error ? e.message : 'Unknown error'
|
||||
set({ isLoading: false, error: message })
|
||||
}
|
||||
},
|
||||
|
||||
addVariable: (variable, providedId?: string) => {
|
||||
const id = providedId || crypto.randomUUID()
|
||||
|
||||
|
||||
@@ -23,6 +23,11 @@ export interface VariablesStore {
|
||||
error: string | null
|
||||
isEditing: string | null
|
||||
|
||||
/**
|
||||
* Loads variables for a specific workflow from the API and hydrates the store.
|
||||
*/
|
||||
loadForWorkflow: (workflowId: string) => Promise<void>
|
||||
|
||||
/**
|
||||
* Adds a new variable with automatic name uniqueness validation
|
||||
* If a variable with the same name exists, it will be suffixed with a number
|
||||
|
||||
@@ -1190,7 +1190,11 @@ export const useWorkflowRegistry = create<WorkflowRegistry>()(
|
||||
}))
|
||||
}
|
||||
|
||||
// Workflow has already been persisted to the database via the duplication endpoint
|
||||
try {
|
||||
await useVariablesStore.getState().loadForWorkflow(id)
|
||||
} catch (error) {
|
||||
logger.warn(`Error hydrating variables for duplicated workflow ${id}:`, error)
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`Duplicated workflow ${sourceId} to ${id} in workspace ${workspaceId || 'none'}`
|
||||
|
||||
Reference in New Issue
Block a user