Simple Upload
Single-request file upload. FormData is auto-detected by courier.
import { caller } from "@/lib/caller"
const formData = new FormData()
formData.append("file", file)
formData.append("description", "My upload")
// FormData is auto-detected — courier sends multipart/form-data
const result = await caller.files.upload(formData)// run the request to see the responseUpload with Progress
A browser reports an upload's progress over XMLHttpRequest, since fetch has none — every 100 ms or so, a step of several percent each on a slow link. smoothProgress moves the bar between the reports: never ahead of the upload, never back, and at rest at 100%.
import { smoothProgress } from "@noverax/courier"
import { caller } from "@/lib/caller"
const formData = new FormData()
formData.append("file", file)
// The browser reports progress in steps: smoothProgress moves the bar between them
const result = await caller.files.with({
onUploadProgress: smoothProgress((progress) => {
setProgress(progress.percent * 100)
}),
}).upload(formData)Both bars follow the same upload. On localhost it is near instant: throttle the network in DevTools, or send one in the upload guide's lab, which reads it at the pace you pick.
// run the request to see the responseSource Definition
FormData is automatically detected. No special configuration needed.
import { courier, defineGroup } from "@noverax/courier/define"
const { endpoint } = courier()
const files = defineGroup({
prefix: "upload",
endpoints: {
// FormData auto-detected — no bodySerializer needed
// Empty files are automatically removed before sending
upload: endpoint.post("").variables<FormData>().response<UploadResponse>(),
},
})When variables is FormData, courier skips JSON encoding and sends it as multipart/form-data. Empty files are automatically removed before sending.