import type { CheckRedirectResponse, EntriesResponse, EntryResponse, PageResponse, PublicBookingServicesResponse, PublicCoursesResponse, PublicFormResponse, PublicFormsResponse, PublicProductsResponse, PublicTeamMembersResponse, PublicMembershipsResponse, PublicPassesResponse, PublicEventDetailsResponse, PublicEventsResponse, ResolveEntrySubrouteResponse, ResolveEventOccurrenceResponse, RoutableContentResponse, SiteResponse, SitemapRoutesResponse, PublicProductCategorySelector } from '../public-api/contracts';
export type { CheckRedirectResponse, EntriesResponse, EntryResponse, PageResponse, PublicBookingServicesResponse, PublicCoursesResponse, PublicEventsResponse, PublicFormResponse, PublicFormsResponse, PublicProductsResponse, PublicTeamMembersResponse, PublicMembershipsResponse, PublicPassesResponse, PublicEventDetailsResponse, ResolveEntrySubrouteResponse, ResolveEventOccurrenceResponse, RoutableContentResponse, SiteResponse, SitemapRoutesResponse, } from '../public-api/contracts';
/**
 * Pagination metadata returned when `includeMeta: true`
 */
export interface PaginationMeta {
    /** Total number of entries matching the query (estimated if hasMore is true) */
    total: number;
    /** Whether there are more entries after this page */
    hasMore: boolean;
    /** Number of entries per page */
    limit: number;
    /** Number of entries skipped (offset) */
    offset: number;
    /** Total number of pages (estimated if hasMore is true) */
    totalPages: number;
    /** Current page number (1-indexed) */
    currentPage: number;
}
/**
 * Response type when includeMeta is true - includes pagination metadata
 */
export type EntriesResponseWithMeta = {
    entries: EntriesResponse['entries'];
} & PaginationMeta;
/**
 * Common options for all SDK methods
 */
export interface SdkMethodOptions {
    /** AbortSignal for cancelling the request */
    signal?: AbortSignal;
}
/**
 * Base parameters for getEntries - shared across all overloads
 */
export interface GetEntriesBaseParams extends SdkMethodOptions {
    /** The site ID */
    siteId: string;
    /** The content type key (e.g., 'blog-post', 'product') */
    contentType: string;
    /** Maximum number of entries to return (default: 10, max: 50) */
    limit?: number;
    /** Number of entries to skip for pagination */
    offset?: number;
    /** Sort order for entries. 'order' uses custom ordering (default behavior). */
    order?: 'newest' | 'oldest' | 'title' | 'order';
    /** If true, includes draft entries (requires API key with site access) */
    preview?: boolean;
    /** Selection mode: 'query' for automatic, 'manual' for specific entry IDs */
    mode?: 'query' | 'manual';
    /** Entry IDs to fetch when mode is 'manual' */
    entryIds?: string[];
}
/**
 * Source of the data returned by a resilient fetch
 */
export type ResilienceSource = 'live' | 'cache' | 'stale' | 'prebuild' | 'error';
/**
 * Status information from a resilient fetch operation
 */
export interface ResilienceStatus {
    /** Where the data came from */
    source: ResilienceSource;
    /** Whether this was a preview request */
    isPreview: boolean;
    /** Cache key used for this request */
    cacheKey?: string;
    /** Error details if fetch failed */
    error?: {
        code?: string;
        message: string;
    };
    /** Seconds since cache TTL expired (when source='stale') */
    staleAgeSec?: number;
    /** Seconds since prebuild was generated (when source='prebuild') */
    prebuildAgeSec?: number;
    /** Circuit breaker state at time of request */
    circuit: CircuitState;
    /** Correlation ID for debugging */
    requestId?: string;
    /** Total request duration including retries (ms) */
    durationMs?: number;
}
/**
 * Circuit breaker state information
 */
export interface CircuitState {
    state: 'closed' | 'open' | 'half-open';
    failureCount: number;
    /** Timestamp when circuit will transition from open to half-open */
    openUntil?: number;
}
/**
 * Retry configuration
 */
export interface RetryConfig {
    /** Maximum number of attempts (including initial) */
    maxAttempts?: number;
    /** Base delay between retries in ms */
    baseDelayMs?: number;
    /** Maximum delay between retries in ms */
    maxDelayMs?: number;
    /** Jitter strategy: 'full' adds randomization, 'none' uses exact delays */
    jitter?: 'full' | 'none';
    /** Custom function to determine if an error should be retried */
    retryOn?: (error: Error, statusCode?: number) => boolean;
}
/**
 * Circuit breaker configuration
 */
export interface CircuitBreakerConfig {
    /** Number of failures before opening circuit */
    failureThreshold?: number;
    /** Time in ms before attempting to close circuit */
    resetTimeoutMs?: number;
    /** Number of successful requests needed to close from half-open */
    halfOpenMaxRequests?: number;
}
/**
 * Resilience configuration for the SDK client
 */
export interface ResilienceConfig {
    /** Enable resilience features (default: true) */
    enabled?: boolean;
    /** Serve stale data on fetch failure (default: true) */
    staleIfError?: boolean;
    /** Seconds AFTER cache TTL expires that stale data remains valid (default: 300) */
    staleTtlSec?: number;
    /** Request timeout in ms (default: 8000 server, 5000 browser) */
    requestTimeoutMs?: number;
    /** Retry configuration */
    retry?: RetryConfig;
    /** Circuit breaker configuration */
    circuitBreaker?: CircuitBreakerConfig;
    /**
     * Path to prebuild cache directory.
     * If set, enables prebuild fallback when live + stale cache both fail.
     * @example '.riverbank-cache'
     */
    prebuildDir?: string;
    /**
     * Maximum age in seconds for prebuild cache.
     * Prebuilds older than this are rejected.
     * @default 86400 (24 hours)
     */
    maxPrebuildAgeSec?: number;
    /** Callback fired on every request with status information */
    onStatusChange?: (status: ResilienceStatus) => void;
    /** Callback fired only when transitioning into/out of degraded mode */
    onDegradedMode?: (degraded: boolean, status: ResilienceStatus) => void;
}
/**
 * Type of API key based on prefix detection.
 * - 'content': bld_live_sk_* or bld_test_sk_* (for published content)
 * - 'preview': bld_preview_sk_* (for draft content)
 * - 'unknown': Unrecognized prefix
 */
export type ApiKeyType = 'content' | 'preview' | 'unknown';
/**
 * Authentication configuration for the SDK client.
 *
 * The SDK supports three authentication modes:
 *
 * - **none**: No authentication. Use for public endpoints only.
 *   Suitable for production frontends that only fetch published content.
 *
 * - **api-key**: API key authentication. Use for SDK sites that need
 *   to access content via API key (bld_live_sk_*, bld_test_sk_*).
 *
 * - **bearer**: Bearer token authentication. Use for preview mode
 *   with a JWT token from the preview session.
 *
 * @example
 * ```ts
 * // Production frontend (public endpoints, no auth needed)
 * createRiverbankClient({
 *   baseUrl: 'https://dashboard.example.com/api',
 *   auth: { type: 'none' },
 * });
 *
 * // SDK site with API key
 * createRiverbankClient({
 *   baseUrl: 'https://dashboard.example.com/api',
 *   auth: { type: 'api-key', key: 'bld_live_sk_...' },
 * });
 *
 * // Preview mode with bearer token
 * createRiverbankClient({
 *   baseUrl: 'https://dashboard.example.com/api',
 *   auth: { type: 'bearer', token: previewToken },
 * });
 * ```
 */
export type SdkAuthConfig = {
    type: 'none';
} | {
    type: 'api-key';
    key: string;
} | {
    type: 'bearer';
    token: string;
};
/**
 * Configuration for creating a Riverbank CMS client
 */
export interface RiverbankClientConfig {
    /**
     * Authentication configuration.
     *
     * Supports three modes:
     * - `{ type: 'none' }` - No auth (for public endpoints)
     * - `{ type: 'api-key', key: '...' }` - API key auth
     * - `{ type: 'bearer', token: '...' }` - Bearer token auth (preview)
     *
     * @example
     * ```ts
     * // Production (public endpoints)
     * { auth: { type: 'none' } }
     *
     * // SDK site with API key
     * { auth: { type: 'api-key', key: 'bld_live_sk_...' } }
     *
     * // Preview mode
     * { auth: { type: 'bearer', token: previewToken } }
     * ```
     */
    auth?: SdkAuthConfig;
    /**
     * @deprecated Use `auth: { type: 'api-key', key: '...' }` instead.
     * This parameter will be removed in the next major version.
     *
     * API key for authentication (format: bld_live_... or bld_test_...)
     */
    apiKey?: string;
    /**
     * Base URL for the Riverbank CMS API (required; e.g. https://dashboard.example.com/api)
     */
    baseUrl: string;
    /**
     * Cache configuration
     */
    cache?: {
        /**
         * Enable caching (default: true)
         */
        enabled?: boolean;
        /**
         * Time-to-live for cached responses in seconds
         * @default 300 (5 minutes)
         */
        ttl?: number;
        /**
         * Maximum number of cached responses
         * @default 100
         */
        maxSize?: number;
    };
    /**
     * Resilience configuration for error handling, retries, and fallbacks
     */
    resilience?: ResilienceConfig;
}
/**
 * Riverbank CMS client interface
 */
export interface RiverbankClient {
    /**
     * Fetch site data by slug, domain, or ID
     */
    getSite(params: {
        slug?: string;
        domain?: string;
        id?: string;
        /**
         * Bypass SDK in-memory cache and Next.js fetch caching (uses `cache: 'no-store'`).
         *
         * Useful right after `riverbankcms push-config` in development to avoid waiting
         * for cache revalidation.
         */
        force?: boolean;
        currentPath?: string;
    } & SdkMethodOptions): Promise<SiteResponse>;
    /**
     * Fetch a specific page by path
     *
     * @param params.preview - If true, returns draft content instead of published content (requires API key with site access)
     */
    getPage(params: {
        siteId: string;
        path: string;
        preview?: boolean;
    } & SdkMethodOptions): Promise<PageResponse>;
    /**
     * Fetch published content entries with optional pagination, sorting, and preview mode
     *
     * @param params.siteId - The site ID
     * @param params.contentType - The content type key (e.g., 'blog-post', 'product')
     * @param params.limit - Maximum number of entries to return (default: 10, max: 50)
     * @param params.offset - Number of entries to skip for pagination (default: 0)
     * @param params.order - Sort order: 'newest' (published_at desc) or 'oldest' (published_at asc)
     * @param params.preview - If true, includes draft entries (requires API key with site access)
     * @param params.mode - 'query' for automatic fetching, 'manual' for specific entry IDs
     * @param params.entryIds - Array of entry IDs to fetch (only used when mode is 'manual')
     * @param params.includeMeta - If true, returns pagination metadata with the response
     *
     * @example
     * ```ts
     * // Fetch latest 10 blog posts
     * const entries = await client.getEntries({
     *   siteId: 'site-id',
     *   contentType: 'blog-post',
     *   limit: 10,
     *   order: 'newest',
     * });
     *
     * // Fetch page 3 with pagination metadata
     * const page3 = await client.getEntries({
     *   siteId: 'site-id',
     *   contentType: 'blog-post',
     *   limit: 10,
     *   offset: 20,
     *   includeMeta: true,
     * });
     * // page3.entries, page3.total, page3.hasMore, page3.currentPage
     *
     * // Fetch specific entries by ID (manual mode)
     * const specific = await client.getEntries({
     *   siteId: 'site-id',
     *   contentType: 'blog-post',
     *   mode: 'manual',
     *   entryIds: ['uuid-1', 'uuid-2'],
     * });
     * ```
     */
    getEntries(params: GetEntriesBaseParams & {
        /** If true, returns pagination metadata with the response */
        includeMeta?: false;
    }): Promise<EntriesResponse>;
    getEntries(params: GetEntriesBaseParams & {
        /** If true, returns pagination metadata with the response */
        includeMeta: true;
    }): Promise<EntriesResponseWithMeta>;
    getEntries(params: GetEntriesBaseParams & {
        includeMeta?: boolean;
    }): Promise<EntriesResponse | EntriesResponseWithMeta>;
    /**
     * Fetch a specific content entry by slug
     */
    getEntry(params: {
        siteId: string;
        contentType: string;
        slug: string;
    } & SdkMethodOptions): Promise<EntryResponse>;
    /**
     * Fetch a public form definition by ID or slug.
     * When using slug, siteId is required for lookup.
     */
    getPublicFormById(params: {
        formId: string;
        siteId: string;
    } & SdkMethodOptions): Promise<PublicFormResponse>;
    /**
     * Fetch all forms for a site (used for prebuild cache)
     */
    getForms(params: {
        siteId: string;
    } & SdkMethodOptions): Promise<PublicFormsResponse>;
    /**
     * Fetch public booking services for a site
     */
    getPublicBookingServices(params: {
        siteId: string;
        ids?: string;
    } & SdkMethodOptions): Promise<PublicBookingServicesResponse>;
    /**
     * List public events for a site (optionally time-filtered)
     */
    listPublicEvents(params: {
        siteId: string;
        limit?: number;
        from?: string;
        to?: string;
        stage?: string;
        categoryIds?: string;
        venueId?: string;
        kind?: 'all' | 'courses' | 'events';
        /** Optional: filter to a specific content entry (event series) */
        entryId?: string;
        /** Optional: filter to a specific seriesId */
        seriesId?: string;
        /** Optional: force-include a specific occurrenceId even if outside date range */
        includeOccurrenceId?: string;
    } & SdkMethodOptions): Promise<PublicEventsResponse>;
    /**
     * Load the consolidated public event-details payload for a scoped event selection.
     */
    getPublicEventDetails(params: {
        siteId: string;
        limit?: number;
        from?: string;
        to?: string;
        afterStartsAt?: string;
        afterId?: string;
        stage?: string;
        categoryIds?: string;
        venueId?: string;
        staffMemberId?: string;
        kind?: string;
        entryId?: string;
        seriesId?: string;
        includeOccurrenceId?: string;
    } & SdkMethodOptions): Promise<PublicEventDetailsResponse>;
    /**
     * List public courses for a site (for course registration block)
     */
    listPublicCourses(params: {
        siteId: string;
        limit?: number;
        stage?: string;
    } & SdkMethodOptions): Promise<PublicCoursesResponse>;
    /**
     * List public team members for a site (for Team Members block)
     */
    listPublicTeamMembers(params: {
        siteId: string;
        stage?: string;
    } & SdkMethodOptions): Promise<PublicTeamMembersResponse>;
    /**
     * List public products for a site (for product list/detail blocks)
     */
    listPublicProducts(params: {
        siteId: string;
        stage?: 'published' | 'preview';
        categorySelector?: PublicProductCategorySelector;
    } & SdkMethodOptions): Promise<PublicProductsResponse>;
    /**
     * List public passes for a site (for shop block)
     */
    listPublicPasses(params: {
        siteId: string;
        categories?: string;
    } & SdkMethodOptions): Promise<PublicPassesResponse>;
    /**
     * List public memberships for a site (for shop block)
     */
    listPublicMemberships(params: {
        siteId: string;
        categories?: string;
    } & SdkMethodOptions): Promise<PublicMembershipsResponse>;
    /**
     * Resolve an entry subroute by kind and segment.
     *
     * Generic resolver used by SDK routing for URLs like:
     * - Event occurrence: /events/yoga-class/2026-01-15
     * - Course run: /courses/beginners/spring-2026
     */
    resolveEntrySubroute(params: {
        siteId: string;
        entryId: string;
        kind: 'event-occurrence' | 'course-run';
        segment: string;
        stage?: 'preview' | 'published';
    } & SdkMethodOptions): Promise<ResolveEntrySubrouteResponse>;
    /**
     * Resolve an event occurrence by URL segment (date or UUID)
     *
     * @param params.siteId - The site ID
     * @param params.entryId - The parent content entry ID
     * @param params.segment - URL segment - either a date (YYYY-MM-DD) or UUID
     *
     * @example
     * ```ts
     * // Resolve occurrence by date
     * const result = await client.resolveEventOccurrence({
     *   siteId: 'site-id',
     *   entryId: 'entry-id',
     *   segment: '2025-01-15',
     * });
     *
     * // Resolve occurrence by UUID
     * const result = await client.resolveEventOccurrence({
     *   siteId: 'site-id',
     *   entryId: 'entry-id',
     *   segment: 'abc123-...',
     * });
     * ```
     */
    resolveEventOccurrence(params: {
        siteId: string;
        entryId: string;
        segment: string;
    } & SdkMethodOptions): Promise<ResolveEventOccurrenceResponse>;
    /**
     * Check if a path has a configured redirect rule
     *
     * @param params.siteId - The site ID
     * @param params.path - The URL path to check
     *
     * @example
     * ```ts
     * const redirect = await client.checkRedirect({
     *   siteId: 'site-id',
     *   path: '/old-page',
     * });
     * if (redirect.redirect) {
     *   // Handle redirect to redirect.redirect.destination
     * }
     * ```
     */
    checkRedirect(params: {
        siteId: string;
        path: string;
    } & SdkMethodOptions): Promise<CheckRedirectResponse>;
    /**
     * Get all published routes for a site.
     * Useful for static site generation (SSG) to enumerate all pages.
     *
     * @param params.siteId - The site ID
     *
     * @example
     * ```ts
     * const routes = await client.getAllPublishedRoutes({ siteId: 'site-id' });
     * // routes.items contains all published pages and content entries with routes
     * ```
     */
    getAllPublishedRoutes(params: {
        siteId: string;
    } & SdkMethodOptions): Promise<RoutableContentResponse>;
    /**
     * Get sitemap route candidates for a site.
     * Used by Next sitemap/robots helpers.
     */
    getSitemapRoutes(params: {
        siteId: string;
        page?: number;
        pageSize?: number;
    } & SdkMethodOptions): Promise<SitemapRoutesResponse>;
    /**
     * Force clear the cache
     */
    clearCache(): void;
    /**
     * Get the detected API key type based on the key prefix.
     *
     * This allows SDK helpers like `createCatchAllPage` to automatically
     * determine whether to fetch preview or published content based on
     * which key the client was configured with.
     *
     * @returns The detected key type: 'content', 'preview', or 'unknown'
     *
     * @example
     * ```ts
     * const client = createRiverbankClient({ apiKey: 'bld_live_sk_...' });
     * client.getKeyType(); // 'content'
     *
     * const previewClient = createRiverbankClient({ apiKey: 'bld_preview_sk_...' });
     * previewClient.getKeyType(); // 'preview'
     * ```
     */
    getKeyType(): ApiKeyType;
    /**
     * Get the status from the most recently emitted request
     *
     * Note: With concurrent requests, this returns the last status emitted,
     * which may not be from the request you're interested in. For reliable
     * per-request status, use the onStatusChange callback instead.
     */
    getLastEmittedStatus(): ResilienceStatus | null;
    /**
     * Get the current circuit breaker state
     */
    getCircuitState(): CircuitState;
    /**
     * Get the API base URL configured for this client.
     *
     * This is useful for passing to client-side components that need to make
     * API calls but can't access server-only environment variables.
     *
     * @returns The base URL (e.g., 'https://dashboard.example.com/api')
     */
    getBaseUrl(): string;
}
