Files
WRNexusJS/packages/uploader/src/driver.ts
T
2026-07-12 15:55:18 +05:30

89 lines
3.1 KiB
TypeScript

/**
* Storage driver contract + config types.
*
* A `StorageDriver` is the low-level object store (local disk, S3, …). It knows
* how to put/get/delete raw bytes under a key — nothing about HTTP, multipart
* parsing, validation, or URLs. The registry (`client.ts`) builds one driver per
* configured store and the upload layer (`upload.ts`) drives them. This mirrors
* `@wrnexus/db`'s driver/adapter split.
*/
/** Whether a store's objects are world-readable or served behind app auth. */
export type StoreAccess = "public" | "private";
/** An object read back from a store. */
export interface StoredObject {
/** Object bytes as a web stream (preferred) or a buffer. */
body: ReadableStream<Uint8Array> | Uint8Array;
/** MIME type to serve with. */
contentType: string;
/** Size in bytes, when known. */
size?: number;
}
/** Metadata passed alongside the bytes on `put`. */
export interface PutMeta {
contentType: string;
/** Original client filename (informational only — NEVER used as a path). */
filename?: string;
}
/** The low-level object store. Implementations: `adapters/local.ts`, `adapters/s3.ts`. */
export interface StorageDriver {
/** Persist `data` under `key` (overwrites). */
put(key: string, data: Uint8Array, meta: PutMeta): Promise<void>;
/** Fetch an object, or `null` if it doesn't exist. */
get(key: string): Promise<StoredObject | null>;
/** Remove an object. No error if it's already gone. */
delete(key: string): Promise<void>;
/**
* A directly-servable absolute URL for a PUBLIC object (e.g. an S3/CDN URL), or
* `null` when the framework should serve it (local public stores). Private
* stores always return `null`.
*/
publicUrl(key: string): string | null;
}
/** Local-disk store. `dir` is resolved against the app root when relative. */
export interface LocalStoreConfig {
driver: "local";
access: StoreAccess;
/** Directory the files live under (e.g. "uploads/public"). */
dir: string;
/** Reject files larger than this many bytes (per file). */
maxBytes?: number;
/** Allowed types: MIME (`"image/*"`, `"application/pdf"`) and/or extensions (`".pdf"`). */
accept?: string[];
}
/** S3 / S3-compatible store (AWS, Cloudflare R2, Backblaze B2, MinIO, DO Spaces). */
export interface S3StoreConfig {
driver: "s3";
access: StoreAccess;
bucket: string;
region: string;
accessKeyId: string;
secretAccessKey: string;
/**
* Custom endpoint for non-AWS services, e.g.
* `https://<acct>.r2.cloudflarestorage.com`. Omit for AWS S3.
*/
endpoint?: string;
/** Force path-style URLs (`/bucket/key`). Defaults on for custom endpoints. */
forcePathStyle?: boolean;
/** Public base URL for `publicUrl()` (a CDN or public bucket domain). */
publicBaseUrl?: string;
maxBytes?: number;
accept?: string[];
}
export type StoreConfig = LocalStoreConfig | S3StoreConfig;
/** The `storage` block in `wrnexus.config.ts`. */
export interface StorageConfig {
/** Name of the store used when a call omits one. Defaults to the first store. */
default?: string;
/** Named stores, reached with `getStore("<name>")` / `upload("<name>", …)`. */
stores: Record<string, StoreConfig>;
}