import { Translations } from "./components/LajiForm";
import { Lang } from "./types";
import type { paths } from "./generated/api";
export declare class LajiApiError extends Error {
    statusCode: number;
    constructor(message: string, statusCode: number);
}
interface Query {
    [param: string]: any;
}
export interface ApiClientImplementation {
    fetch: (path: string, query: Query, options: any) => Promise<Response>;
}
type RelaxQuery<P, K extends string> = P extends {
    query: infer Q;
} ? Omit<P, "query"> & (Record<string, unknown> extends Omit<Q, Extract<keyof Q, K>> ? {
    query?: Omit<Q, Extract<keyof Q, K>> & Partial<Pick<Q, Extract<keyof Q, K>>>;
} : {
    query: Omit<Q, Extract<keyof Q, K>> & Partial<Pick<Q, Extract<keyof Q, K>>>;
}) : P;
type MiddlewareInjectedKeys = "collectionID" | "formID";
type Parameters<T> = "parameters" extends keyof T ? T["parameters"] : never;
type ExtractContentIfExists<R> = R extends {
    content: infer C;
} ? C[keyof C] : null;
type ExtractRequestBodyIfExists<R> = R extends {
    requestBody: {
        content: infer C;
    };
} | {
    requestBody?: {
        content: infer C;
    };
} ? C[keyof C] : never;
type HttpSuccessCodes = 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226;
type IntersectUnionTypes<A, B> = A extends B ? A : never;
type WithResponses<T> = T & {
    responses: unknown;
};
type Path = keyof paths & string;
type PathWithMethod<M extends string> = keyof {
    [P in keyof paths as paths[P] extends Record<M, any> ? P : never]: paths[P];
};
type Method<P extends Path> = Exclude<keyof {
    [K in keyof paths[P] as paths[P][K] extends undefined | never ? never : K]: paths[P][K];
}, "parameters">;
type Responses<P extends Path, M extends Method<P>> = WithResponses<paths[P][M]>["responses"];
type CacheNode = {
    branches: Map<string, CacheNode>;
    queries: Map<string, Promise<any>>;
    path: string;
};
/**
 * ApiClient with automatically generated typings for laji-api. An `ApiClientImplementation` must be provided, that will
 * perform the actual requests. The implementation acts as a middleware for injecting access token and person token.
 *
 * Get requests are automatically cached, and they will flush if the resource receives a POST/PUT/DELETE request.
 */
export default class ApiClient {
    apiClient: ApiClientImplementation;
    lang: Lang;
    translations: Translations;
    cacheTree: CacheNode;
    on: {
        [path: string]: (() => void)[];
    };
    constructor(apiClient: ApiClientImplementation, lang: Lang | undefined, translations: Translations);
    private flush;
    private getCacheNode;
    /** The response is cached until the resource receives a POST/PUT/DELETE request. */
    get<P extends PathWithMethod<"get">, R extends Responses<P, "get" extends Method<P> ? "get" : never>>(path: P, params?: RelaxQuery<Parameters<paths[P]["get"]>, MiddlewareInjectedKeys>, 
    /** Defaults to true */
    useCache?: boolean): Promise<ExtractContentIfExists<R[IntersectUnionTypes<keyof R, HttpSuccessCodes>]>>;
    /** Subscribe to a GET request. It re-emits when the resource receives a POST/PUT/DELETE request. */
    subscribe<P extends PathWithMethod<"get">, R extends Responses<P, "get" extends Method<P> ? "get" : never>>(path: P, params: RelaxQuery<Parameters<paths[P]["get"]>, MiddlewareInjectedKeys> | undefined, onFulfilled: (response: ExtractContentIfExists<R[IntersectUnionTypes<keyof R, HttpSuccessCodes>]>) => void, onError?: () => void, 
    /**
     * Store doesn't sync it's search indices right away after data is changed, so delaying the request can be useful
     */
    delay?: number): () => void;
    put<P extends PathWithMethod<"put">, R extends Responses<P, "put" extends Method<P> ? "put" : never>>(path: P, params?: RelaxQuery<Parameters<paths[P]["put"]>, MiddlewareInjectedKeys>, body?: ExtractRequestBodyIfExists<paths[P]["put"]>): Promise<ExtractContentIfExists<R[IntersectUnionTypes<keyof R, HttpSuccessCodes>]>>;
    post<P extends PathWithMethod<"post">, R extends Responses<P, "post" extends Method<P> ? "post" : never>>(path: P, params?: RelaxQuery<Parameters<paths[P]["post"]>, MiddlewareInjectedKeys>, body?: ExtractRequestBodyIfExists<paths[P]["post"]>): Promise<ExtractContentIfExists<R[IntersectUnionTypes<keyof R, HttpSuccessCodes>]>>;
    delete<P extends PathWithMethod<"delete">, R extends Responses<P, "delete" extends Method<P> ? "delete" : never>>(path: P, params?: RelaxQuery<Parameters<paths[P]["delete"]>, MiddlewareInjectedKeys>): Promise<ExtractContentIfExists<R[IntersectUnionTypes<keyof R, HttpSuccessCodes>]>>;
    /**
     * Implementing apiClient must return a promise that passes the raw response as 1st arg.
     * @param path URL for GET.
     * @param query Object, where keys are param names and values are param values.
     * @returns a Promise.
     */
    fetch<P extends Path, M extends Method<P>, R extends Responses<P, M>>(path: P, method: M, params?: Parameters<paths[P][M]>, body?: ExtractRequestBodyIfExists<paths[P][M]>, options?: any): Promise<ExtractContentIfExists<R[IntersectUnionTypes<keyof R, HttpSuccessCodes>]>>;
    setLang(lang: Lang): void;
}
export {};
