import { ClientInstance } from '../client';
import { Request, RequestInstance } from '../request';
import { ExtractEndpointType, ExtractResponseType, ExtractPayloadType, ExtractQueryParamsType, ExtractLocalErrorType, ExtractHasPayloadType, ExtractHasParamsType, ExtractHasQueryParamsType, ExtractMutationContextType } from '../types';
export type RecursiveSchemaType = Record<string, // for example users / $userId / posts / $postId
any>;
/**
 * Recursively walks a schema and rebuilds every `Request` leaf with the SDK's actual client
 * type injected into the `Client` generic slot. Lets users omit `client` from their
 * `RequestModel<{...}>` declarations - the SDK fills it in from the client passed to
 * `createSdk(client)`.
 *
 * Non-Request leaves (primitive values, plain types) are passed through unchanged. Nested
 * schema objects are recursed into. Depth is guarded at 10 levels to keep the type checker
 * within reasonable bounds.
 */
export type InjectClient<T, TClient extends ClientInstance, Depth extends unknown[] = []> = Depth["length"] extends 10 ? T : T extends RequestInstance ? Request<ExtractResponseType<T>, ExtractPayloadType<T>, ExtractQueryParamsType<T>, ExtractLocalErrorType<T>, ExtractEndpointType<T> extends string ? ExtractEndpointType<T> : string, TClient, ExtractHasPayloadType<T> extends boolean ? ExtractHasPayloadType<T> : false, ExtractHasParamsType<T> extends boolean ? ExtractHasParamsType<T> : false, ExtractHasQueryParamsType<T> extends boolean ? ExtractHasQueryParamsType<T> : false, ExtractMutationContextType<T>> : T extends Record<string, any> ? {
    [K in keyof T]: InjectClient<T[K], TClient, [...Depth, unknown]>;
} : T;
/**
 * Per-request defaults that can be applied via SDK configuration.
 * These mirror the chainable setters on Request (headers, cache, retry, etc.).
 */
export type SdkRequestDefaults = {
    headers?: HeadersInit;
    auth?: boolean;
    cache?: boolean;
    cacheTime?: number;
    staleTime?: number;
    retry?: number;
    retryTime?: number;
    cancelable?: boolean;
    queued?: boolean;
    offline?: boolean;
    deduplicate?: boolean;
    deduplicateTime?: number | null;
};
/**
 * Configuration value: either a static property bag or a function that receives
 * the request and returns a modified request (full access to every Request setter).
 */
export type SdkConfigurationValue = SdkRequestDefaults | ((request: RequestInstance) => RequestInstance);
/**
 * Recursively extracts all endpoint strings from an SDK schema type.
 * Leaf nodes (keys starting with $) are RequestInstance — extract endpoint from those.
 * Other keys are nested schema segments to recurse into.
 */
type ExtractSdkEndpoints<T, Depth extends unknown[] = []> = Depth["length"] extends 10 ? never : {
    [K in keyof T]: K extends `$${string}` ? T[K] extends RequestInstance ? ExtractEndpointType<T[K]> : never : T[K] extends Record<string, any> ? ExtractSdkEndpoints<T[K], [...Depth, unknown]> : never;
}[keyof T];
/**
 * Recursively extracts dot-path accessor keys from an SDK schema.
 * These mirror the SDK property chain: "users.$get", "users.$userId.$get", etc.
 */
type ExtractSdkPaths<T, Prefix extends string = "", Depth extends unknown[] = []> = Depth["length"] extends 10 ? never : {
    [K in keyof T & string]: T[K] extends RequestInstance ? `${Prefix}${K}` : T[K] extends Record<string, any> ? ExtractSdkPaths<T[K], `${Prefix}${K}.`, [...Depth, unknown]> : never;
}[keyof T & string];
/**
 * Builds the set of valid configuration keys from an SDK schema:
 * - "*" (global wildcard)
 * - exact endpoint paths extracted from RequestInstance nodes (group keys)
 * - wildcard patterns like "/users/*" (group keys)
 * - dot-path accessor keys like "users.$get" (method-specific keys)
 */
type SdkConfigurationKeys<Schema extends RecursiveSchemaType> = "*" | ExtractSdkEndpoints<Schema> | `${ExtractSdkEndpoints<Schema> & string}/*` | ExtractSdkPaths<Schema>;
/**
 * Maps endpoint paths, wildcard patterns, or dot-path accessor keys to request defaults.
 * Keys are validated against the SDK schema.
 *
 * Values can be:
 * - A plain `SdkRequestDefaults` object (shorthand for common settings)
 * - A function `(request) => request` for full access to every Request setter
 */
export type SdkConfigurationMap<Schema extends RecursiveSchemaType = RecursiveSchemaType> = Partial<Record<SdkConfigurationKeys<Schema>, SdkConfigurationValue>>;
export type CreateSdkOptions<Schema extends RecursiveSchemaType = RecursiveSchemaType> = {
    /** @default true */
    camelCaseToKebabCase?: boolean;
    /** @default (method) => method.toUpperCase() */
    methodTransform?: (method: string) => string;
    /** Per-endpoint request defaults */
    defaults?: SdkConfigurationMap<Schema>;
};
/**
 * The fully-resolved SDK instance type returned by `createSdk`.
 *
 * The schema is rewritten via {@link InjectClient} so every `Request` leaf carries the
 * actual client type passed to `createSdk(client)` - users do not need to repeat
 * `client: AppClient` in every `RequestModel<{...}>` declaration.
 */
export type SdkInstance<Schema extends RecursiveSchemaType, TClient extends ClientInstance = ClientInstance> = InjectClient<Schema, TClient> & {
    /**
     * Apply request defaults to the SDK. Returns a new SDK instance with the configuration applied.
     * Use "*" to match all endpoints, or specific endpoint strings / wildcard patterns.
     */
    $configure: (defaults: SdkConfigurationMap<Schema>) => SdkInstance<Schema, TClient>;
};
export declare const createSdk: <Client extends ClientInstance, RecursiveSchema extends RecursiveSchemaType>(client: Client, options?: CreateSdkOptions<RecursiveSchema>) => SdkInstance<RecursiveSchema, Client>;
/**
 * Type-safe factory for creating SDK configuration maps.
 *
 * @example
 * const config = createConfiguration<MySdkSchema>()({ "*": { retry: 3 } })
 */
export declare const createConfiguration: <Schema extends RecursiveSchemaType>() => (defaults: SdkConfigurationMap<Schema>) => SdkConfigurationMap<Schema>;
export {};
//# sourceMappingURL=sdk.d.ts.map