import type { FilesPlugin } from "../index.js"; import type { FileEvent, FileEventType } from "../internal/events.js"; import type { EventFormat } from "./formats/index.js"; import type { EventsWebhookOptions, WebhookHandler } from "./webhook.js"; export type { FileEvent, FileEventSource, FileEventType, } from "../internal/events.js"; export type { EventFormat } from "./formats/index.js"; export { EVENT_FORMATS } from "./formats/index.js"; export type { EventsWebhookOptions, GoogleOidcOptions, SignatureVerifyOptions, SnsVerifyOptions, WebhookHandler, } from "./webhook.js"; /** Handles one event. Await anything that must finish before the delivery is acknowledged. */ export type EventHandler = (event: FileEvent) => void | Promise; /** Which events a handler receives: one type, or both. */ export type EventTypeFilter = FileEventType | "*"; /** * Drops repeated event ids, for handlers that can't be made idempotent. `has` * is checked before an event's handlers run; `add` is called once they all * succeed (a failed event stays eligible for its redelivery). A `Set`-backed * store works in one process; use Redis/KV/a table across instances. */ export interface EventDedupeStore { has: (id: string) => boolean | Promise; /** Remember `id` for `ttl` ms. */ add: (id: string, ttl: number) => void | Promise; } export interface EventsOptions { /** * The notification format `parse()` / `dispatch()` / `webhook()` read. * Defaults to the one the adapter declares (`files.capabilities.events`): * `"s3"` for `s3` and `s3-fetch` on AWS, `minio`, `rustfs`, `storj` and * `wasabi`; `"r2"` for every `r2` engine; `"gcs"` for `gcs` and * `firebase-storage`; `"azure"`, `"b2"` (`backblaze-b2`), `"tigris"`, * `"supabase"`, `"cloudinary"`, `"appwrite"`, `"box"` and `"memory"` for * their own adapters. Other adapters (`bun-s3`, `s3` on a custom endpoint, * unverified S3-compatible services) declare none; set it when you know the * provider sends one of {@link EVENT_FORMATS}. */ format?: EventFormat; /** * Only accept provider events for this bucket (container, for Azure). * Defaults to the adapter's own bucket when it exposes one * (`adapter.bucket`), so a queue, topic or webhook that also carries other * buckets' events (an EventBridge rule, an Azure system topic, a Supabase or * Appwrite project webhook) can't feed them in under the same keys. Events * whose delivery doesn't name a bucket pass. `false` accepts every bucket. */ bucket?: string | false; /** * Also raise events for successful `upload` / `delete` / `copy` / `move` * calls made through this instance (`source: "sdk"`). Off by default: on a * provider with notifications each write then arrives twice. Useful where a * provider has none. Delivered after the call settles and not awaited; a * failing handler goes to `onError`. `events()` must then come before any * plugin that maps storage events (`versioning`, `softDelete`, `dedup`, * `encryption`, `compression`, `tiering`) in `plugins`, or the instance * refuses to build: behind one, it would see that plugin's internal keys * and stored sizes. */ sdk?: boolean; /** Skip events whose `id` this store has seen. See {@link EventDedupeStore}. */ dedupe?: EventDedupeStore; /** How long a handled id is remembered, ms. Default 24 hours. */ dedupeTtl?: number; /** * Called for every handler that throws, whatever the source. `dispatch()`, * `emit()` and the webhook still reject (so the provider redelivers); events * nothing awaits (the memory adapter, the `sdk` source, gateway uploads) are * reported only here. Defaults to `console.error`. */ onError?: (cause: unknown, event: FileEvent) => void; } /** * `files.events`. `parse()` / `dispatch()` / `webhook()` read the provider's * deliveries; handlers registered with `on()` receive provider events, gateway * upload completions, and (with `sdk: true`) this instance's own writes. */ export interface FilesEvents { /** The notification format this instance reads, or `undefined` when its adapter has none. */ readonly format: EventFormat | undefined; /** * Handle events of `type` whose key matches `pattern` (a glob, `**` when * omitted; matched against the caller-facing key). Handlers run in * registration order. Returns a function that removes the handler. When the * instance reads a notification format, throws if a plugin refuses provider * events (as `webhook()` does), rather than dropping every one later. */ on: { (type: EventTypeFilter, handler: EventHandler): () => void; (type: EventTypeFilter, pattern: string, handler: EventHandler): () => void; }; /** * Normalize deliveries into events without running handlers: a webhook * `Request`, a message body (an SQS record body, a Queue message body, a * Pub/Sub message), a whole consumer batch (a Lambda event), a JSON string, * or an array of any of those. Events outside the instance `prefix`, or for * another `bucket`, are dropped. Doesn't authenticate a `Request`; use * `webhook()` for that. */ parse: (input: unknown) => Promise; /** * `parse()`, then run the matching handlers (sequentially, in order). Rejects * when a handler throws, after every event has been tried, so a queue * consumer can leave the message for redelivery. Resolves with the events * handled. */ dispatch: (input: unknown) => Promise; /** Run the matching handlers for events you already have (no parsing, no prefix mapping). */ emit: (events: FileEvent | readonly FileEvent[]) => Promise; /** * A webhook endpoint for providers that push over HTTP, with the same * `{ handle }` shape as the gateway, so every gateway binding mounts it * (`createRouteHandler(files.events.webhook({ verify }))`). Answers the * provider handshakes, authenticates, then dispatches: `401` on a bad * credential, `400` on a malformed delivery, `502` when fetching a signing * certificate or key fails and `500` when a handler throws (the provider * redelivers either), `200` otherwise. A handler's error message never * reaches the response; it goes to `onError`. */ webhook: (opts: EventsWebhookOptions) => WebhookHandler; /** * Resolves once every event delivered without an awaiting caller (memory * adapter changes, `sdk` writes) has been handled, including any those * handlers caused. For tests. */ settled: () => Promise; } /** What {@link events} adds to a `Files` instance (a `type`, for `createFiles`). */ export type EventsExtension = { events: FilesEvents; }; /** * React to files being created or deleted, however it happened: provider * bucket notifications, gateway uploads, and (opt-in) this instance's own * writes, normalized into one {@link FileEvent} and routed to handlers. * * ```ts * const files = createFiles({ adapter: s3({ bucket }), plugins: [events()] }); * files.events.on("created", "avatars/**", async (e) => { … }); * * // Lambda / SQS consumer * export const handler = (event) => files.events.dispatch(event); * ``` * * Install one `events()` per instance; put it first in `plugins` so the `sdk` * source sees the caller's keys. */ export declare const events: (options?: EventsOptions) => FilesPlugin; //# sourceMappingURL=index.d.ts.map