young-taxes-swim/docs/TAYLORDB_ATTACHMENTS.md
2026-05-08 19:12:29 +05:00

127 lines
3.0 KiB
Markdown

# TaylorDB Attachments
Attachments are treated as **standard columns** and can be selected and written like other fields, using helper utilities for uploads.
This document covers:
- Selecting attachment fields
- Creating records with attachments
- Updating attachments
---
## Select Attachments
```typescript
// New Standard: Use regular .select() like any other field.
const expenses = await qb
.selectFrom("expenses")
.select(["id", "amount", "receipt"])
.execute();
```
---
## Create with Attachments
Use `qb.uploadAttachments` to upload files before inserting.
```typescript
await qb
.insertInto("customers")
.values({
firstName: "Jane",
lastName: "Doe",
avatar: await qb.uploadAttachments([
{ file: new Blob([""]), name: "test.png" },
]),
})
.execute();
```
---
## Update with Attachments
```typescript
await qb
.update("customers")
.set({
lastName: "Smith",
avatar: await qb.uploadAttachments([
{ file: new Blob([""]), name: "test.png" },
]),
})
.where("id", "=", 1)
.execute();
```
---
## Receiving Files via tRPC 11 Multipart FormData
tRPC 11 supports `multipart/form-data` natively using `z.instanceof(FormData)` as the procedure input. File objects arrive directly in the mutation — no separate upload endpoint needed.
**Server (tRPC router):**
```typescript
import { z } from "zod";
import { router, publicProcedure } from "../trpc";
export const myRouter = router({
submit: publicProcedure
.input(z.instanceof(FormData))
.mutation(async ({ input, ctx }) => {
const name = input.get("name") as string | null;
const files = input.getAll("files") as File[];
// Upload files directly to TaylorDB
const attachments = await ctx.queryBuilder.uploadAttachments(
files.map((file) => ({ file, name: file.name }))
);
await ctx.queryBuilder
.insertInto("submissions")
.values({ name, documents: attachments })
.execute();
}),
});
```
**Client (tRPC React Query):**
FormData mutations must bypass request batching. Use `splitLink` in your tRPC client setup:
```typescript
import { splitLink, httpLink, httpBatchLink } from "@trpc/client";
trpc.createClient({
links: [
splitLink({
condition: (op) => op.input instanceof FormData,
true: httpLink({ url: trpcUrl }),
false: httpBatchLink({ url: trpcUrl }),
}),
],
});
```
Then call the mutation with a `FormData` object:
```typescript
const formData = new FormData();
formData.append("name", name);
files.forEach((file) => formData.append("files", file));
await submitMutation.mutateAsync(formData);
```
For more topics, see:
- `TAYLORDB_BASIC_QUERIES.md` for basic reads and filtering
- `TAYLORDB_WRITE_OPERATIONS.md` for inserts, updates, and deletes
- `TAYLORDB_ADVANCED_PATTERNS.md` for aggregations, pagination, and conditional queries
- `TAYLORDB_FIELD_TYPES.md` for field type handling and enums
- `TAYLORDB_PITFALLS_BEST_PRACTICES.md` for pitfalls and best practices