MCPcopy Index your code
hub / github.com/simstudioai/sim / planForkFileCopies

Function planForkFileCopies

apps/sim/lib/workspaces/fork/copy/copy-files.ts:68–136  ·  view source on GitHub ↗
(params: {
  tx: DbOrTx
  sourceWorkspaceId: string
  childWorkspaceId: string
  userId: string
  fileIds?: string[]
  fileKeys?: string[]
  now: Date
})

Source from the content-addressed store, hash-verified

66 * least one of the two must be non-empty; both may be supplied (their matched rows union).
67 */
68export async function planForkFileCopies(params: {
69 tx: DbOrTx
70 sourceWorkspaceId: string
71 childWorkspaceId: string
72 userId: string
73 fileIds?: string[]
74 fileKeys?: string[]
75 now: Date
76}): Promise<PlanForkFileCopiesResult> {
77 const { tx, sourceWorkspaceId, childWorkspaceId, userId, now } = params
78 const fileIds = params.fileIds ?? []
79 const fileKeys = params.fileKeys ?? []
80 const keyMap = new Map<string, string>()
81 const idMap = new Map<string, string>()
82 const blobTasks: BlobCopyTask[] = []
83 if (fileIds.length === 0 && fileKeys.length === 0) return { keyMap, idMap, blobTasks }
84
85 // Match by id and/or storage key (OR'd) so either selection shape resolves to the same
86 // source rows. Batch the metadata read (one query for all selected files): non-deleted,
87 // scoped to the source workspace, and restricted to durable `workspace` files. Only
88 // workspace files are forkable - chat/copilot/mothership uploads are session-scoped and
89 // their chat-bound unique index can't be duplicated - so any non-workspace id/key passed
90 // here is ignored rather than copied.
91 const selectors = [
92 fileIds.length > 0 ? inArray(workspaceFiles.id, fileIds) : undefined,
93 fileKeys.length > 0 ? inArray(workspaceFiles.key, fileKeys) : undefined,
94 ].filter((clause): clause is NonNullable<typeof clause> => clause !== undefined)
95 const metas = await tx
96 .select()
97 .from(workspaceFiles)
98 .where(
99 and(
100 selectors.length === 1 ? selectors[0] : or(...selectors),
101 eq(workspaceFiles.workspaceId, sourceWorkspaceId),
102 eq(workspaceFiles.context, 'workspace'),
103 isNull(workspaceFiles.deletedAt)
104 )
105 )
106
107 for (const meta of metas) {
108 const childFileId = generateId()
109 // Use the canonical workspace-file key (`workspace/{id}/...`) so the file-serve
110 // API can infer the storage context; a bare `{id}/...` key has no context prefix.
111 const targetKey = generateWorkspaceFileKey(childWorkspaceId, meta.originalName)
112 await tx.insert(workspaceFiles).values({
113 ...meta,
114 id: childFileId,
115 key: targetKey,
116 workspaceId: childWorkspaceId,
117 userId,
118 folderId: null,
119 deletedAt: null,
120 uploadedAt: now,
121 })
122 keyMap.set(meta.key, targetKey)
123 idMap.set(meta.id, childFileId)
124 blobTasks.push({
125 sourceKey: meta.key,

Callers 2

createForkFunction · 0.90

Calls 5

generateIdFunction · 0.90
generateWorkspaceFileKeyFunction · 0.90
setMethod · 0.65
eqFunction · 0.50
pushMethod · 0.45

Tested by

no test coverage detected