Files
skills/docs/api-stack/api/api-plugin-file-upload/README.md
2026-05-29 08:20:56 +01:00

101 lines
9.0 KiB
Markdown

# @suaveplan/api-plugin-file-upload - Hono plugin for @suaveplan/api: multipart and chunked file uploads with size + MIME validation, SHA-256 hash verification, resumable sessions, per-principal isolation, pluggable UploadStorage + UploadSessionStore, 11 UPLOAD_* error codes, OpenTelemetry counters/histogram, and 6 typed OpenAPI routes. Builds on @suaveplan/api-plugin-auth so every route is requireAuth-gated and scoped to the current principal (and optional tenant). Ships MemoryUploadStorage (test-only) and FileSystemUploadStorage (production) adapters out of the box.
Multipart and chunked file-upload plugin for `@suaveplan/api`. Ships six OpenAPI-typed Hono routes, a pluggable storage + session-store contract, SHA-256 hash verification, MIME spoof detection via `@suaveplan/mime`, eleven stable error codes, and full OpenTelemetry instrumentation. Every route is `requireAuth()`-gated through `@suaveplan/api-plugin-auth` and scoped to the calling principal (and optional tenant) so cross-user enumeration is impossible — foreign upload IDs return 404.
<!-- begin:auto-docs -->
## Documentation tree
- [assembler](./src/assembler/assembler.md) — Owns the chunked-upload assembly + integrity-verification pipeline. `assembleChunks` pulls every chunk from a caller-su…
- [assembler](./src/assembler/assembler.md) — Owns the chunked-upload assembly + integrity-verification pipeline. `assembleChunks` pulls every chunk from a caller-su…
- [error-codes](./src/error-codes/error-codes.md) — Defines the stable error-code registry for `@suaveplan/api-plugin-file-upload`. Each failure path in the plugin throws…
- [error-codes](./src/error-codes/error-codes.md) — Defines the stable error-code registry for `@suaveplan/api-plugin-file-upload`. Each failure path in the plugin throws…
- [otel](./src/otel/instruments.md) — Owns the OpenTelemetry instrument bundle for `@suaveplan/api-plugin-file-upload`: four counters and one histogram. Ever…
- [instruments](./src/otel/instruments.md) — Owns the OpenTelemetry instrument bundle for `@suaveplan/api-plugin-file-upload`: four counters and one histogram. Ever…
- [plugin](./src/plugin/plugin.md) — Authoritative `createFileUploadPlugin` factory. Wraps the resolved configuration in a `PluginDescriptor<FileUploadPlugi…
- [plugin](./src/plugin/plugin.md) — Authoritative `createFileUploadPlugin` factory. Wraps the resolved configuration in a `PluginDescriptor<FileUploadPlugi…
- [build-routes](./src/routes/build-routes.md) — Builds the 6 OpenAPI route entries the plugin mounts on the host Hono app: single-shot `POST /`, chunked-init `POST /in…
- [handlers](./src/routes/handlers.md) — Per-route Hono handler implementations consumed by `buildUploadRoutes`. Each handler reads the auth principal from `c.g…
- [schemas](./src/schemas/options.md) — Defines the Zod schema validating caller-supplied `FileUploadPluginOptions`. Invalid input — wrong type, malformed `bas…
- [initiate](./src/schemas/routes/initiate.md) — Defines the request body and response shape for `POST /uploads/initiate`, the chunked upload bootstrap endpoint. The cl…
- [single-shot](./src/schemas/routes/single-shot.md) — Defines the typed JSON response returned by both `POST /uploads` (single-shot) and `POST /uploads/{uploadId}/complete`…
- [status](./src/schemas/routes/status.md) — Defines the path-parameter and response shapes for the remaining chunked-upload routes: `PUT /uploads/{uploadId}/chunks…
- [options](./src/schemas/options.md) — Defines the Zod schema validating caller-supplied `FileUploadPluginOptions`. Invalid input — wrong type, malformed `bas…
- [complete-chunked](./src/services/complete-chunked.md) — Internal back-end implementing the `complete` operation of `FileUploadService`. Extracted from the main service file so…
- [file-upload-helpers](./src/services/file-upload-helpers.md) — Internal helpers shared by `file-upload-service.ts`: the storage-key naming convention (`CHUNK_KEY`, `RECORD_KEY`) and…
- [file-upload-service](./src/services/file-upload-service.md) — Canonical `FileUploadService` factory consumed by the plugin's route handlers and registered as the typed `fileUploadSe…
- [registry-augmentation](./src/services/registry-augmentation.md) — Augments the cross-package `ServiceRegistry` interface declared in `@suaveplan/api-plugin/service-registry` so consumer…
- [single-shot](./src/services/single-shot.md) — Internal back-end implementing the `singleShot` operation of `FileUploadService`. Extracted from the main service file…
- [session-store](./src/session-store/memory.md) — In-memory `UploadSessionStore` adapter. Tracks both in-flight `UploadSession` state (sessions Map) and completed `Uploa…
- [memory](./src/session-store/memory.md) — In-memory `UploadSessionStore` adapter. Tracks both in-flight `UploadSession` state (sessions Map) and completed `Uploa…
- [file-system](./src/storage/file-system.md) — Production-grade `UploadStorage` adapter backed by `node:fs/promises`. Stores bytes as flat files under a configurable…
- [memory](./src/storage/memory.md) — In-memory `UploadStorage` adapter. Stores raw bytes in a process-local `Map<string, Uint8Array>` for fast unit tests an…
- [types](./src/types/types.md) — Defines the public TypeScript surface of `@suaveplan/api-plugin-file-upload`: the caller-facing `FileUploadPluginOption…
- [types](./src/types/types.md) — Defines the public TypeScript surface of `@suaveplan/api-plugin-file-upload`: the caller-facing `FileUploadPluginOption…
- [mime](./src/validators/mime.md) — Cross-checks the declared `Content-Type` against the plugin's configured allow/deny lists AND (optionally) against the…
- [size](./src/validators/size.md) — Tiny but central pair of helpers that enforce upload size limits and compute chunked-upload geometry. `enforceSizeLimit…
<!-- end:auto-docs -->
## Install
```sh
bun add @suaveplan/api-plugin-file-upload
```
## Quick start
```ts
import { createApi } from "@suaveplan/api";
import { createAuthPlugin } from "@suaveplan/api-plugin-auth";
import {
createFileUploadPlugin,
FileSystemUploadStorage,
} from "@suaveplan/api-plugin-file-upload";
const api = createApi({ port: 3000 });
await api.registry.register(createAuthPlugin({ betterAuth: { /* … */ } }));
await api.registry.register(
createFileUploadPlugin({
basePath: "/uploads",
singleShotLimitBytes: 32 * 1024 * 1024,
maxFileSizeBytes: 4 * 1024 * 1024 * 1024,
storage: new FileSystemUploadStorage({ rootDir: "/var/lib/uploads" }),
})
);
await api.start();
```
## Routes
| Method | Path | Description |
|--------|---------------------------------------|--------------------------------------|
| POST | `/uploads` | Single-shot multipart upload |
| POST | `/uploads/initiate` | Begin a chunked session |
| PUT | `/uploads/{uploadId}/chunks/{index}` | Upload a single chunk |
| POST | `/uploads/{uploadId}/complete` | Assemble + verify + finalise |
| DELETE | `/uploads/{uploadId}` | Abort and reclaim partial state |
| GET | `/uploads/{uploadId}` | Status / resume |
## Modules
- [`plugin/plugin`](./src/plugin/plugin.md) — `createFileUploadPlugin` factory + lifecycle.
- [`error-codes/error-codes`](./src/error-codes/error-codes.md) — 11 `UPLOAD_*` codes + `FileUploadError`.
- [`otel/instruments`](./src/otel/instruments.md) — 4 counters + 1 histogram.
- [`storage/memory`](./src/storage/memory.md) — test-only `UploadStorage`.
- [`storage/file-system`](./src/storage/file-system.md) — production filesystem-backed `UploadStorage`.
- [`session-store/memory`](./src/session-store/memory.md) — default `UploadSessionStore`.
- [`services/file-upload-service`](./src/services/file-upload-service.md) — `FileUploadService` factory.
- [`services/file-upload-helpers`](./src/services/file-upload-helpers.md) — ownership / key helpers.
- [`services/single-shot`](./src/services/single-shot.md) — single-shot back-end.
- [`services/complete-chunked`](./src/services/complete-chunked.md) — chunked-complete back-end.
- [`assembler/assembler`](./src/assembler/assembler.md) — chunk concat + SHA-256.
- [`validators/mime`](./src/validators/mime.md) — allow/deny + sniff cross-check.
- [`validators/size`](./src/validators/size.md) — size limits + chunk math.
- [`routes/build-routes`](./src/routes/build-routes.md) — 6-route OpenAPI builder.
- [`routes/handlers`](./src/routes/handlers.md) — per-route Hono handlers.
- [`schemas/options`](./src/schemas/options.md) — plugin options schema.
- [`schemas/routes/single-shot`](./src/schemas/routes/single-shot.md) — `SingleShotResponseSchema`.
- [`schemas/routes/initiate`](./src/schemas/routes/initiate.md) — chunked-init request/response.
- [`schemas/routes/status`](./src/schemas/routes/status.md) — chunk / complete / status / abort schemas.
- [`types/types`](./src/types/types.md) — public data model.