/** Encryption mode for an attachment. */ export type AttachmentEncryptionType = 'E2EE' | 'CLEARTEXT'; /** Conversation scope used for download authorization on the server side. */ export type AttachmentConversationType = 'ONE_TO_ONE' | 'GROUP'; /** * Per-device wrapped AES-256-GCM file key for an E2EE attachment. * The wrapped bytes decrypt to a 32-byte raw AES key that decrypts the file. */ export interface DeviceWrappedKey { deviceId: string; wrappedKey: Uint8Array; senderPublicKey: Uint8Array; nonce: Uint8Array; } /** * Reference to an attachment hosted in the customer's storage bucket, * carried inside Envelope.attachments. After the SDK uploads the bytes * and finalizes, this is the structure the sender embeds in the message. */ export interface AttachmentRef { attachmentId: string; storageHint: string; mimeType: string; sizeBytes: number; /** Hex-encoded SHA-256 of stored bytes (ciphertext for E2EE, plaintext for CLEARTEXT). */ sha256: string; encryptionType: AttachmentEncryptionType; /** Empty for CLEARTEXT. One entry per recipient device for E2EE. */ wrappedKeys: DeviceWrappedKey[]; /** * Optional. The attachmentId of a separate attachment holding a preview * thumbnail. Present only when the sender chose to attach one. Download it * like any attachment via {@link DropOnAirClient.downloadAttachment}. */ thumbnailAttachmentId?: string; } /** Optional metadata for {@link DropOnAirClient.createUploadSession}. */ export interface CreateUploadSessionOptions { /** * Send the file in parts, so an upload broken by a dead connection carries on * with the parts that are missing. The SDK asks for this itself for big files. */ inParts?: boolean; mimeType?: string; sizeBytes: number; encryptionType?: AttachmentEncryptionType; conversationType?: AttachmentConversationType; /** For GROUP conversations: the groupId. For ONE_TO_ONE: omit. */ conversationId?: string; /** Recipient user IDs (used by the server for download authorization). */ recipientUserIds?: string[]; /** * How long this one file should live, in seconds. Optional, and never granted * longer than the app's own retention. An app that works out a window per file * sets it here instead of living with one number for everything. */ retentionSeconds?: number; /** * Delete the stored bytes as soon as every recipient has fetched them. The * file then exists only on the devices it was sent to. */ deleteWhenEveryoneHasIt?: boolean; } /** Result of reserving an upload session. */ export interface UploadSession { /** Set when the file goes up in parts: what the storage calls this upload. */ uploadId?: string; /** How big each part is, the last one apart. */ partSizeBytes?: number; attachmentId: string; storageHint: string; uploadUrl: string; uploadMethod: string; uploadHeaders: Record; expiresAt: string; } /** Options for the convenience method {@link DropOnAirClient.prepareAttachmentAndUpload}. */ export interface PrepareAttachmentOptions { /** Recipient user ID for ONE_TO_ONE conversations. */ toUserId?: string; /** Group ID for GROUP conversations. Mutually exclusive with toUserId. */ groupId?: string; /** * Roster of recipient user IDs the server should authorize for download. * For ONE_TO_ONE: defaults to {@code [toUserId]} if omitted. * For GROUP: required - the SDK does not infer group membership. */ recipientUserIds?: string[]; /** Defaults to {@code 'E2EE'}. Use {@code 'CLEARTEXT'} for public/unencrypted content. */ encryptionType?: AttachmentEncryptionType; /** Override the mime type detected from the File object. */ mimeType?: string; /** Progress callback called with bytes uploaded so far. */ onUploadProgress?: (bytesUploaded: number, totalBytes: number) => void; /** How long this one file should live, in seconds. Never granted longer than your own retention. */ retentionSeconds?: number; /** Delete the stored bytes as soon as every recipient has confirmed they have them. */ deleteWhenEveryoneHasIt?: boolean; /** * Optional preview thumbnail bytes. Entirely the developer's choice - if * provided, the SDK uploads it as a separate attachment (encrypted with the * same scheme as the main file) and links it via thumbnailAttachmentId. If * omitted, the AttachmentRef simply has no thumbnail. */ thumbnail?: Uint8Array; /** Mime type of the thumbnail bytes (defaults to 'image/jpeg'). */ thumbnailMimeType?: string; /** * Optional. Called once, as soon as the upload has somewhere to go, with * everything needed to take the same upload up again later. * * Keep it if a failed upload should carry on rather than start over: the parts * already stored are then skipped, which for a large file on a poor connection * is the difference between minutes and hours. It holds the file's key, so keep * it where the file itself is kept and nowhere else. */ onUploadStarted?: (handoff: UploadHandoff) => void; /** * Optional. A handoff from an upload that did not finish. The same bytes go * back up the same session, and whatever arrived last time is not sent again. */ resume?: UploadHandoff; } /** * Everything needed to take an unfinished upload up again. It carries the file's * own key, so it belongs wherever the file is kept and nowhere else. */ export interface UploadHandoff { attachmentId: string; storageHint: string; /** Set when the file goes up in parts. */ uploadId?: string; partSizeBytes?: number; /** Base64. Absent when the file is not encrypted. */ fileKey?: string; /** Base64. The one this file was encrypted with, so the bytes come out the same. */ nonce?: string; sha256: string; sizeBytes: number; } /** Options for downloadAttachment. */ export interface DownloadAttachmentOptions { /** Called as bytes arrive, with the bytes received so far and the total. */ onProgress?: (bytesReceived: number, totalBytes: number) => void; } /** * The file is not there to fetch: deleted once everybody had it, past its * deadline, revoked, or never existed. Nothing will bring it back, unlike a * failure worth trying again. `status` is the HTTP status that said so. */ export declare class AttachmentUnavailableError extends Error { readonly attachmentId: string; readonly status: number; constructor(attachmentId: string, status: number, message: string); } /** Bytes payload returned by downloadAttachment. */ export interface DownloadedAttachment { attachmentId: string; mimeType: string; sizeBytes: number; sha256: string; bytes: Uint8Array; }