2025-10-18 19:32:05 +00:00
|
|
|
import type { Id } from "@fileone/convex/dataModel"
|
2025-11-08 18:03:10 +00:00
|
|
|
import { ConvexError, v } from "convex/values"
|
2025-10-20 00:17:50 +00:00
|
|
|
import {
|
|
|
|
|
authenticatedMutation,
|
|
|
|
|
authenticatedQuery,
|
|
|
|
|
authorizedGet,
|
|
|
|
|
} from "./functions"
|
2025-09-13 22:02:27 +01:00
|
|
|
import * as Directories from "./model/directories"
|
2025-09-18 00:14:16 +00:00
|
|
|
import * as Files from "./model/files"
|
2025-11-02 18:12:33 +00:00
|
|
|
import * as User from "./model/user"
|
2025-11-08 18:03:10 +00:00
|
|
|
import { ErrorCode, error } from "./shared/error"
|
2025-09-13 22:02:27 +01:00
|
|
|
|
2025-09-15 21:44:41 +00:00
|
|
|
export const generateUploadUrl = authenticatedMutation({
|
2025-09-13 22:02:27 +01:00
|
|
|
handler: async (ctx) => {
|
2025-11-08 18:03:10 +00:00
|
|
|
const userInfo = await User.queryInfo(ctx)
|
|
|
|
|
if (!userInfo) {
|
|
|
|
|
throw new ConvexError({ message: "Internal server error" })
|
2025-11-02 18:12:33 +00:00
|
|
|
}
|
2025-11-08 18:03:10 +00:00
|
|
|
if (userInfo.storageUsageBytes >= userInfo.storageQuotaBytes) {
|
|
|
|
|
throw new ConvexError({
|
|
|
|
|
code: ErrorCode.StorageQuotaExceeded,
|
|
|
|
|
message: "Storage quota exceeded",
|
|
|
|
|
})
|
2025-11-02 18:12:33 +00:00
|
|
|
}
|
2025-09-13 22:02:27 +01:00
|
|
|
return await ctx.storage.generateUploadUrl()
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
2025-09-15 21:44:41 +00:00
|
|
|
export const fetchFiles = authenticatedQuery({
|
2025-09-13 22:02:27 +01:00
|
|
|
args: {
|
|
|
|
|
directoryId: v.optional(v.id("directories")),
|
|
|
|
|
},
|
|
|
|
|
handler: async (ctx, { directoryId }) => {
|
|
|
|
|
return await ctx.db
|
|
|
|
|
.query("files")
|
2025-09-16 22:36:26 +00:00
|
|
|
.withIndex("byDirectoryId", (q) =>
|
|
|
|
|
q.eq("userId", ctx.user._id).eq("directoryId", directoryId),
|
|
|
|
|
)
|
2025-09-13 22:02:27 +01:00
|
|
|
.collect()
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
2025-09-19 23:01:44 +00:00
|
|
|
export const fetchRootDirectory = authenticatedQuery({
|
|
|
|
|
handler: async (ctx) => {
|
|
|
|
|
return await Directories.fetchRoot(ctx)
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
export const fetchDirectory = authenticatedQuery({
|
|
|
|
|
args: {
|
|
|
|
|
directoryId: v.id("directories"),
|
|
|
|
|
},
|
|
|
|
|
handler: async (ctx, { directoryId }) => {
|
2025-10-16 21:43:23 +00:00
|
|
|
const directory = await authorizedGet(ctx, directoryId)
|
|
|
|
|
if (!directory) {
|
2025-11-08 18:03:10 +00:00
|
|
|
error({
|
|
|
|
|
code: ErrorCode.NotFound,
|
|
|
|
|
message: "Directory not found",
|
|
|
|
|
})
|
2025-10-16 21:43:23 +00:00
|
|
|
}
|
2025-09-19 23:01:44 +00:00
|
|
|
return await Directories.fetch(ctx, { directoryId })
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
2025-09-15 21:44:41 +00:00
|
|
|
export const createDirectory = authenticatedMutation({
|
2025-09-13 22:02:27 +01:00
|
|
|
args: {
|
|
|
|
|
name: v.string(),
|
2025-09-19 23:01:44 +00:00
|
|
|
directoryId: v.id("directories"),
|
2025-09-13 22:02:27 +01:00
|
|
|
},
|
|
|
|
|
handler: async (ctx, { name, directoryId }): Promise<Id<"directories">> => {
|
2025-10-16 21:43:23 +00:00
|
|
|
const parentDirectory = await authorizedGet(ctx, directoryId)
|
|
|
|
|
if (!parentDirectory) {
|
2025-11-08 18:03:10 +00:00
|
|
|
error({
|
|
|
|
|
code: ErrorCode.NotFound,
|
|
|
|
|
message: "Parent directory not found",
|
|
|
|
|
})
|
2025-10-16 21:43:23 +00:00
|
|
|
}
|
2025-10-20 00:17:50 +00:00
|
|
|
|
2025-09-15 21:44:41 +00:00
|
|
|
return await Directories.create(ctx, {
|
|
|
|
|
name,
|
|
|
|
|
parentId: directoryId,
|
|
|
|
|
})
|
2025-09-13 22:02:27 +01:00
|
|
|
},
|
|
|
|
|
})
|