import { ParseableResponse } from '../utils/parseResponse/parseResponse'; export type RequestOptions = Omit & { headers: { [name: string]: string; }; }; /** * Login credentials. Lives here (not auth/types) because AuthTransport.buildLoginBody references * it and adapters/types must not import from auth/types (that would cycle with AuthDependencies' * Adapters reference). auth/types.ts re-exports it. */ export interface SigninCredentials { username: string; password: string; } export interface StorageAdapter { get(key: string): Promise | string | null; set(key: string, value: string): Promise | void; remove(key: string): Promise | void; /** Optional reactivity. Web: the `storage` event. RN: an event emitter, or omitted. Returns an unsubscribe fn. */ subscribe?(key: string, cb: (value: string | null) => void): () => void; } export interface NetworkAdapter { /** Perform the request. Web: global `fetch`. Returns the DOM-free ParseableResponse (a raw Response satisfies it structurally). */ request(path: string, options: RequestOptions): Promise; } export interface AuthTransport { /** Path segment appended after `auth/`: 'login' (cookie) or 'jwt/login' (bearer). */ loginPath: string; /** Build the login request body. Both transports send urlencoded form today. */ buildLoginBody(creds: SigninCredentials): BodyInit; /** Cookie: set `credentials:'include'`. Bearer: add the Authorization header from the storage it was constructed with. */ decorateRequest(options: RequestOptions): RequestOptions | Promise; /** Bearer: read + store the JWT from the login response. Cookie: no-op. */ persistLogin(response: ParseableResponse): Promise | void; /** Bearer: drop the persisted JWT. Cookie: no-op. */ clearLogin(): Promise | void; } export interface FileDownloadAdapter { /** Web: anchor-navigate to `url` (cookie auth). RN: fetch the bytes with `headers`, then write/share as `filename`. */ save(source: { url: string; filename?: string; headers?: Record; }): Promise; /** Web: URL.createObjectURL. RN: a content/file uri. */ objectUrl(file: unknown): string; } export interface OAuthOpenerAdapter { /** Web: window.open (popup) / window.location (redirect) + a setInterval close-poll that calls onClose. */ open(url: string, opts: { popup: boolean; onClose?: () => void; }): void | Promise; } export interface FormDataAdapter { /** Web: `value instanceof File`. RN: shape check `{ uri, name, type }`. */ isFilePart(value: unknown): boolean; /** Append a file part. Web: `fd.append(key, file as File)`. */ appendFile(fd: FormData, key: string, file: unknown): void; } export interface LocalizationAdapter { /** * Language code -> lazy loader for that language's data-grid localization pack (a flat * key -> translated-string map). Web supplies mantine-react-table's de/en packs; platforms * without the grid omit this adapter. */ loaders: Record Promise>>; } export interface Adapters { storage: StorageAdapter; network: NetworkAdapter; authTransport: AuthTransport; fileDownload: FileDownloadAdapter; oauthOpener: OAuthOpenerAdapter; formData: FormDataAdapter; /** Optional data-grid localization loaders (web: mantine-react-table de/en). Omitted where there is no grid. */ localization?: LocalizationAdapter; }