2.6 KiB
2.6 KiB
handlers.ts
Purpose
Per-route Hono handler implementations consumed by buildUploadRoutes. Each handler reads the auth principal from c.get("user"), optionally narrows to a tenant via c.get("tenant"), parses the request body / params with the per-route Zod schemas, delegates to FileUploadService, and projects the service's UploadSession/UploadRecord return value onto the wire response shape.
Features
- Single
readScope(c)helper produces aPrincipalScopefrom the augmented Hono context. Missing principal raisesUPLOAD.INVALID_INPUT(the siblingrequireAuth()middleware should have already replied 401, so reaching this path indicates plugin misconfiguration). toStatusprojects either anUploadSession(in-progress) or anUploadRecord(complete) onto the uniformUploadStatusResponseshape so theGETroute serves both phases through a single schema.- Multipart parsing for
POST /uploadsreads viac.req.parseBody(); chunk PUT reads viac.req.raw.arrayBuffer()so binary payloads are preserved byte-for-byte.
Usage: Basic
import { buildHandlers } from "@suaveplan/api-plugin-file-upload";
const handlers = buildHandlers(service);
// `handlers.singleShot`, `handlers.initiate`, …, `handlers.status`
Usage: Advanced
import { buildHandlers, FileUploadError } from "@suaveplan/api-plugin-file-upload";
const handlers = buildHandlers(service);
app.post("/uploads", async (c) => {
try {
return await handlers.singleShot(c);
} catch (err) {
if (err instanceof FileUploadError && err.uploadCode === "UPLOAD.TOO_LARGE") {
return c.json({ retry: false }, 413);
}
throw err;
}
});
API Reference
buildHandlers(service: FileUploadService): { singleShot, initiate, chunk, complete, abort, status }— each value is a(c: Context) => Promise<Response>.
Implementation Notes
- The
readScopehelper checks fornullandundefinedso the same code runs whether or not the host installedapi-plugin-auth(e.g. for integration tests that synthesise a principal directly). parseBodymay throw if the client did not send multipart — we translate that toUPLOAD.INVALID_INPUT(400) rather than letting a raw runtime error escape.- The chunk PUT handler does NOT cap chunk size at the handler layer because the assembler+service already enforce the session's
chunkSizeoncompletetime (a mismatched chunk would fail hash verification). - The abort handler returns a static
state: "complete"response shape for idempotency — calling abort twice returns success both times.