Files
drive/packages/convex/filesystem.ts
2025-10-03 21:23:51 +00:00

103 lines
2.5 KiB
TypeScript

import { v } from "convex/values"
import { authenticatedMutation } from "./functions"
import * as Directories from "./model/directories"
import * as Err from "./model/error"
import * as Files from "./model/files"
import type { DirectoryHandle, FileHandle } from "./model/filesystem"
import {
type FileSystemHandle,
FileType,
VDirectoryHandle,
VFileSystemHandle,
} from "./model/filesystem"
export const moveItems = authenticatedMutation({
args: {
targetDirectory: VDirectoryHandle,
items: v.array(VFileSystemHandle),
},
handler: async (ctx, { targetDirectory: targetDirectoryHandle, items }) => {
const targetDirectory = await Directories.fetchHandle(
ctx,
targetDirectoryHandle,
)
if (!targetDirectory) {
throw Err.create(
Err.Code.DirectoryNotFound,
`Directory ${targetDirectoryHandle.id} not found`,
)
}
const directoryHandles: DirectoryHandle[] = []
const fileHandles: FileHandle[] = []
for (const item of items) {
switch (item.kind) {
case FileType.Directory:
directoryHandles.push(item)
break
case FileType.File:
fileHandles.push(item)
break
}
}
const [fileMoveResult, directoryMoveResult] = await Promise.all([
Files.move(ctx, {
targetDirectory: targetDirectoryHandle,
items: fileHandles,
}),
Directories.move(ctx, {
targetDirectory: targetDirectoryHandle,
sourceDirectories: directoryHandles,
}),
])
return {
moved: [...directoryMoveResult.moved, ...fileMoveResult.moved],
errors: [...fileMoveResult.errors, ...directoryMoveResult.errors],
}
},
})
export const moveToTrash = authenticatedMutation({
args: {
handles: v.array(VFileSystemHandle),
},
handler: async (ctx, { handles }) => {
// biome-ignore lint/suspicious/useIterableCallbackReturn: switch statement is exhaustive
const promises = handles.map((handle) => {
switch (handle.kind) {
case FileType.File:
return ctx.db
.patch(handle.id, {
deletedAt: Date.now(),
})
.then(() => handle)
case FileType.Directory:
return Directories.moveToTrashRecursive(ctx, handle).then(
() => handle,
)
}
})
const results = await Promise.allSettled(promises)
const errors: Err.ApplicationErrorData[] = []
const okHandles: FileSystemHandle[] = []
for (const result of results) {
switch (result.status) {
case "fulfilled":
okHandles.push(result.value)
break
case "rejected":
errors.push(Err.createJson(Err.Code.Internal))
break
}
}
return {
deleted: okHandles,
errors,
}
},
})