Files
claudemesh/apps/web/src/modules/pdf/upload/hooks/use-upload.tsx
Alejandro Gutiérrez d3163a5bff feat(db): mesh data model — meshes, members, invites, audit log
- pgSchema "mesh" with 4 tables isolating the peer mesh domain
- Enums: visibility, transport, tier, role
- audit_log is metadata-only (E2E encryption enforced at broker/client)
- Cascade on mesh delete, soft-delete via archivedAt/revokedAt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 21:19:32 +01:00

45 lines
1.2 KiB
TypeScript

import { useMutation } from "@tanstack/react-query";
import { handle } from "@turbostarter/api/utils";
import { useTranslation } from "@turbostarter/i18n";
import { generateId } from "@turbostarter/shared/utils";
import { api } from "~/lib/api/client";
import { authClient } from "~/lib/auth/client";
import { readFile } from "~/modules/pdf/upload/utils";
import type { FileInput } from "~/modules/pdf/upload/utils";
export const useUpload = () => {
const { t } = useTranslation("ai");
const { data: session } = authClient.useSession();
return useMutation({
mutationFn: async (data: { file: FileInput }) => {
if (!session?.user.id) {
throw new Error(t("pdf.upload.error.unauthorized"));
}
const path = `documents/${session.user.id}/${generateId()}.pdf`;
const { url: uploadUrl } = await handle(api.storage.upload.$get)({
query: { path },
});
const response = await fetch(uploadUrl, {
method: "PUT",
body: await readFile(data.file),
headers: {
"Content-Type": "application/pdf",
},
});
if (!response.ok) {
throw new Error(t("pdf.upload.error.api"));
}
return { path };
},
});
};