import { type FactoryWithInput, type Maybe, type PromiseOrValue } from '@dereekb/util'; import { type HttpsCallable } from 'firebase/functions'; /** * Configuration for mapping input/output values when wrapping an `HttpsCallable`. * * @template I - the external input type (what callers provide) * @template O - the external output type (what callers receive) * @template A - the internal input type (what the callable expects) * @template B - the internal output type (what the callable returns) */ export interface MapHttpsCallable { /** * Transforms the caller's input into the format expected by the underlying callable. */ readonly mapInput?: FactoryWithInput, Maybe>; /** * Transforms the callable's raw output into the format returned to callers. */ readonly mapOutput?: FactoryWithInput, Maybe>; } /** * Wraps an `HttpsCallable` with input/output transformations and error conversion. * * Supports both standard mode (returns `HttpsCallableResult`) and direct-data mode * (returns just `O`) depending on the `directData` parameter. Errors from the callable * are converted to readable errors via {@link convertHttpsCallableErrorToReadableError}. * * @param callable - the underlying Firebase `HttpsCallable` to wrap * @param wrap - input/output mapping functions * @param directData - when `true`, returns the unwrapped data instead of `HttpsCallableResult` * @returns a wrapped callable that applies input/output transformations and converts errors to readable forms * * @example * ```ts * const wrapped = mapHttpsCallable(httpsCallable(functions, 'myFn'), { * mapInput: (params) => ({ ...params, timestamp: Date.now() }), * mapOutput: (result) => result?.items ?? [] * }, true); * const items = await wrapped({ query: 'test' }); * ``` */ export declare function mapHttpsCallable(callable: HttpsCallable, wrap: MapHttpsCallable): HttpsCallable; export declare function mapHttpsCallable(callable: HttpsCallable, wrap: MapHttpsCallable, directData: false): HttpsCallable; export declare function mapHttpsCallable(callable: HttpsCallable, wrap: MapHttpsCallable, directData: true): DirectDataHttpsCallable>; export declare function mapHttpsCallable(callable: HttpsCallable, wrap: MapHttpsCallable, directData?: boolean): HttpsCallable | DirectDataHttpsCallable>; /** * Unwraps an `HttpsCallable` so it returns the response data directly (`O`) instead of * `HttpsCallableResult`. Simplifies consumption when only the data payload is needed. */ export type DirectDataHttpsCallable> = C extends HttpsCallable ? (data?: I | null) => Promise : never; /** * Wraps an `HttpsCallable` to return the data payload directly, stripping the `HttpsCallableResult` wrapper. * * Errors are converted to readable errors via {@link convertHttpsCallableErrorToReadableError}. * * @param callable - the `HttpsCallable` to wrap * @returns a {@link DirectDataHttpsCallable} that resolves to the response data directly * * @example * ```ts * const fn = directDataHttpsCallable(httpsCallable(functions, 'myFn')); * const output: Output = await fn(input); * ``` */ export declare function directDataHttpsCallable = HttpsCallable>(callable: C): DirectDataHttpsCallable; /** * Converts errors from `HttpsCallable` calls into more readable error types. * * If the error is a client-side {@link FirebaseError} with `details`, wraps it as a {@link FirebaseServerError} * to preserve server-side error context. Otherwise, converts it to a generic readable error via `toReadableError`. * * @param error - the caught error from an `HttpsCallable` invocation * @returns a {@link FirebaseServerError} if the error has structured details, or a generic readable error otherwise */ export declare function convertHttpsCallableErrorToReadableError(error: unknown): unknown;