first commit
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# `plugin.ts`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Authoritative `createFileUploadPlugin` factory. Wraps the resolved configuration in a `PluginDescriptor<FileUploadPluginConfig>` and executes a 6-step `onInit` lifecycle: resolve required `app` service → construct default storage + session-store → build the `FileUploadService` and register it in the host `ServiceRegistry` → install `requireAuth()` on `basePath/*` → register the 6 OpenAPI routes via `definePluginRoutes` → schedule the cleanup-expired interval. The descriptor's `onClose` clears the interval so plugin teardown leaves no dangling timers.
|
||||
|
||||
## Features
|
||||
|
||||
- Zod-validated factory boundary — invalid options throw `FileUploadError(UPLOAD.INVALID_INPUT)` carrying the `ZodError` as `cause`.
|
||||
- Default storage (`MemoryUploadStorage`) and session store (`MemoryUploadSessionStore`) when none supplied; production callers swap in `FileSystemUploadStorage` or a Surreal-backed adapter via options.
|
||||
- Cleanup interval auto-tuned to `sessionTtlMs / 4` (minimum 1 s) so expired sessions are reclaimed within one quarter-TTL of expiry.
|
||||
- `requireAuth()` middleware installed on the configured `basePath/*` so every route is principal-gated without per-handler boilerplate.
|
||||
- Falls back to direct Hono mounting (and logs a warning) when no `OpenAPIRegistry` is in the host `ServiceRegistry`.
|
||||
- `setInterval` handle is `unref`'d so plugin lifecycle does not pin the event loop after `onClose`.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { createFileUploadPlugin } from "@suaveplan/api-plugin-file-upload";
|
||||
|
||||
const plugin = createFileUploadPlugin();
|
||||
await pluginRegistry.register(plugin);
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import {
|
||||
createFileUploadPlugin,
|
||||
FileSystemUploadStorage,
|
||||
} from "@suaveplan/api-plugin-file-upload";
|
||||
|
||||
const plugin = createFileUploadPlugin({
|
||||
basePath: "/api/v1/uploads",
|
||||
singleShotLimitBytes: 32 * 1024 * 1024,
|
||||
maxFileSizeBytes: 4 * 1024 * 1024 * 1024,
|
||||
defaultChunkSize: 8 * 1024 * 1024,
|
||||
sessionTtlMs: 6 * 60 * 60 * 1000,
|
||||
allowedMimeTypes: ["image/png", "image/jpeg", "application/pdf"],
|
||||
storage: new FileSystemUploadStorage({ rootDir: "/var/lib/uploads" }),
|
||||
});
|
||||
await pluginRegistry.register(plugin);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `createFileUploadPlugin(options?: FileUploadPluginOptions): PluginDescriptor<FileUploadPluginConfig>` — see file-level JSDoc for the full lifecycle.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The Zod schema validates structurally — a misshapen `storage` or `sessionStore` value is rejected before the descriptor is constructed, not at first request time.
|
||||
- The route-rebase step rewrites every route entry's `path` to include `basePath` so `definePluginRoutes` and the served OpenAPI doc share a single ground truth.
|
||||
- `requireAuth()` is imported from `@suaveplan/api-plugin-auth` so the plugin gains the same anonymous→401 contract every other auth-aware plugin uses.
|
||||
- `cleanupExpired` is invoked with the current wall clock; if a test injects a `clock` override into `createFileUploadService` directly, the interval should be paused (tests do not exercise the scheduler).
|
||||
Reference in New Issue
Block a user