/**
 * {@link Laika | `Laika`} is the place where most of the magic happens.
 * All the operations are routed through its Apollo Link, and Laika can decide what happens to them along the way.
 * By default every connection is passed through and no additional action is taken.
 *
 * If you're using createGlobalLaikaLink, an instance of Laika is by default installed as `laika` property
 * on the global object (most likely `window`), accessible as `window.laika`
 * or simply as `laika`.
 *
 * Key functionality:
 *
 * - {@link Laika.intercept | `laika.intercept()`}:
 *
 *   If you use `jest`, you can think of laika like the `jest` global,
 *   where the equivalent of `jest.fn()` is {@link Laika.intercept | `laika.intercept()`}
 * - {@link Laika.LogApi | `laika.log`}
 *
 *   The other thing laika is responsible for is logging.
 *
 *   Logging functionality is behind a separate API available under {@link Laika.LogApi | `laika.log`}.
 *
 * @packageDocumentation
 * @module Laika
 */
import { ApolloLink, FetchResult, NextLink, Observer, Operation } from '@apollo/client/core';
import type { GenerateCodeOptions } from './codeGenerator';
import type { EventFilterFn, InterceptorFn, ManInTheMiddleFn, Matcher, OnSubscribeCallback, ResultOrFn, Variables } from './typedefs';
/**
 * Class responsible for managing interceptions.
 * By default a singleton is installed on `globalThis` (usually `window`) under `laika`.
 *
 * Read more in the {@link Laika | module page} or scroll down to see it's functionality.
 *
 * @example
 * ```js
 * laika.log.startLogging();
 * ```
 */
export declare class Laika {
    private readonly referenceName;
    constructor({ referenceName, }?: {
        referenceName?: string;
    });
    /**
     * Provides functionality to intercept, and optionally mock or modify each operation's subscription.
     * The API returned is heavily inspired on jest's mocking functionality (`jest.fn()`)
     * and is described in length here: {@link InterceptApi}.
     *
     * Every interceptor you create should be as specific as needed in a given session.
     * At the very least, ensure the order of creating interceptors is from most specific, to least specific.
     *
     * This is because any operations that are executed by your client will end up
     * being intercepted by the **first** interceptor that matches
     * the constraints of the {@link Matcher}.
     *
     * See [*Pitfalls*](pitfalls.md) for more information.
     *
     * @param matcher [[include:matcher.md]]
     * @param connectFutureLinksOrMitmFn If true, future links will still be called (e.g. reach the backend) and return responses. If set to a function, can serve for man-in-the-middle tinkering with the result.
     * @param keepNonSubscriptionConnectionsOpen If true, queries and mutations will behave a little like subscriptions, in that you will be able to fire updates even after the initial response. Experimental.
     * @example
     * ```js
     * const getActiveUsersInterceptor = laika.intercept({
     *   clientName: 'users',
     *   operationName: 'getActiveUsers',
     * });
     * ```
     */
    intercept(matcher?: Matcher | undefined, connectFutureLinksOrMitmFn?: (ManInTheMiddleFn | boolean) | undefined, keepNonSubscriptionConnectionsOpen?: boolean): InterceptApi;
    /**
     * Modify backend (or mocked) responses before they reach subscribers.
     *
     * @param matcher [[include:matcher.md]]
     * @param mapFn Mapping function to alter the responses.
     */
    modifyRemote(matcher: Matcher | undefined, mapFn: (result: FetchResult, operation: Operation) => FetchResult): {
        restore: () => void;
    };
    /**
     * A set of functions that controls logging and recording of all (or selected) operations.
     *
     * Read more on the {@link Laika.LogApi | LogApi} page.
     *
     * @example
     * ```js
     * laika.log.startLogging();
     * ```
     */
    log: LogApi;
    /**
     * Use this function to create an Apollo Link that uses this Laika instance.
     * Useful in unit tests.
     * @param onRequest
     */
    createLink(onRequest?: (operation: Operation, forward: NextLink) => void): ApolloLink;
    /**
     * @internal
     * */
    interceptor: InterceptorFn;
    private readonly behaviors;
    private readonly unmatchedOperationOptions;
    private readonly cleanupFnPerSubscribeMeta;
    /**
     * @param input
     */
    private getLogFunction;
    /**
     * @param data
     */
    private logSubscribe;
    private loggingMatcher;
    private firstCaptureTimestamp;
    private recording;
    private actionName;
    private isRecording;
}
export declare abstract class LogApi {
    /** @ignore */
    constructor();
    /**
     * Starts logging every matching operation and subscription to the console.
     * If you did not provide a matcher, it will log everything.
     * You will see queries, mutations, and subscription pushes along with their data.
     *
     * ![Example logging output](media://example-logging.png)
     */
    startLogging(matcher?: Matcher | undefined): void;
    /**
     * Stops logging to the console.
     */
    stopLogging(): void;
    /**
     * Starts the recording process. Every result will be saved until you run `log.stopRecording()`.
     *
     * ![Example recording output](media://example-recording.png)
     *
     * @param startingActionName Name what you are about to do. For example "opening a new ticket".
     * @param matcher A matcher object or function to record only the events that you are interested in, for example `{operationName: 'getColors', clientName: 'backend1'}` will record only `'getColors'` operations.
     */
    startRecording(startingActionName?: string | undefined, matcher?: Matcher | undefined): void;
    /**
     * Pauses recording without clearing what was recorded so far.
     */
    stopRecording(): void;
    /**
     * Resets the recording in preparation of another one.
     */
    resetRecording(): void;
    /**
     * Use this function to mark a new action if recording a sequence of events.
     *
     * These will show up when you generate mock code as comments,
     * so you can more easily orient yourself in it.
     *
     * @param actionName Describe what action you will be performing, e.g. 'opening the ticket'
     * @example
     * ```js
     * log.markAction('opening the ticket');
     * // click around the site
     * log.markAction('changing the assignee');
     * ```
     */
    markAction(actionName: string): void;
    /**
     * Returns a code snippet that will help you reproduce your recording without hitting actual backends.
     * @param eventFilter Optionally provide a function that will only keep the events you are interested in.
     * @param options Optionally provide code generation options to customize the output.
     */
    generateMockCode(eventFilter?: EventFilterFn, options?: GenerateCodeOptions): string;
}
/**
 * This is the mocking API that is returned after running {@link Laika.intercept | `intercept()`} on the {@link Laika | Laika}.
 *
 * The API is chainable, with the exception of `mockRestore()`.
 *
 * Inspired by `jest.fn()`.
 */
export declare abstract class InterceptApi {
    /** @ignore */
    constructor();
    /**
     * An array containing the `variables` from subsequent operations that passed through this intercept.
     *
     * Similar to `jest.fn().mock.calls`.
     */
    readonly calls: readonly Variables[];
    /**
     * Sets the mock data that will be used as a default response to intercepted queries and mutations.
     * If used for subscriptions, will push data immediately.
     *
     * Similar to `jest.fn().mockReturnValue(...)`.
     *
     * @param resultOrFn [[include:result-or-fn.md]]
     * @param matcher [[include:mock-matcher.md]]
     * @example
     * Always respond with the mock to all queries/mutations intercepted
     * ```js
     * const intercept = laika.intercept({operationName: 'getUsers'});
     * intercept.mockResult(
     *   {result: {data: {users: [{id: 1, name: 'Mouse'}, {id: 2, name: 'Bamboo'}]}}},
     * );
     * ```
     * @example
     * Respond with an error, but only when the operations's variables contain `{userGroup: 'elephants'}`
     * ```js
     * const intercept = laika.intercept({operationName: 'getUsers'});
     * intercept.mockResult(
     *   {error: new Error(`oops, server blew up from all the elephants stomping!`)},
     *   {variables: {userGroup: 'elephants'}}
     * );
     * ```
     * @example
     * Respond with a customized error based on the variables:
     * ```js
     * const intercept = laika.intercept({operationName: 'getUsers'});
     * intercept.mockResult(
     *   ({variables}) => ({error: new Error(`oops, server blew up from all the ${variables.userGroup} stomping!`)})
     * );
     * ```
     */
    mockResult(resultOrFn: ResultOrFn, matcher?: Matcher | undefined): InterceptApi;
    /**
     * Sets the mock data that will be used as the *next* response to matching intercepted queries/mutations.
     * If used for subscription operations, will immediately push provided data to the next matching request.
     * Works the same as {@link InterceptApi.mockResult | `mockResult`},
     * except that as soon as a matching result is found in the queue of mocks, it will not be sent again.
     *
     * Can be run multiple times and will send responses in order in which `mockResultOnce` was called.
     *
     * @param resultOrFn [[include:result-or-fn.md]]
     * @param matcher [[include:mock-matcher.md]]
     * @example
     * Respond with the mock to the first intercepted operation with the name `getUsers`,
     * then with a different mock the second time that operation is intercepted.
     * ```js
     * const intercept = laika.intercept({operationName: 'getUsers'});
     * intercept
     *   .mockResultOnce(
     *     {result: {data: {users: [{id: 1, name: 'Mouse'}, {id: 2, name: 'Bamboo'}]}}},
     *   );
     *   .mockResultOnce(
     *     {result: {data: {users: [{id: 9, name: 'Ox'}, {id: 10, name: 'Fox'}]}}},
     *   );
     * ```
     */
    mockResultOnce(resultOrFn: ResultOrFn, matcher?: Matcher | undefined): InterceptApi;
    /**
     * In case of GraphQL subscriptions, will return synchronously if at least
     * one intercepted subscription is already active.
     * In other cases returns a `Promise` and behaves the same way as {@link InterceptApi.waitForNextSubscription | `waitForNextSubscription()`}.
     */
    waitForActiveSubscription(): Promise<void> | undefined;
    /**
     * Returns a Promise that will resolve when the *next* operation is run.
     * This translates to whenever a query/mutation is run, or whenever the *next* subscription is made.
     */
    waitForNextSubscription(): Promise<{
        operation: Operation;
        observer: Observer<FetchResult>;
    }>;
    /**
     * Push data to an already active `subscription`-type operation.
     * Will throw if there are no subscribers (e.g. active `useQuery` hooks).
     *
     * Works similarly to {@link InterceptApi.mockResult | `mockResult(...)`}, but the listener
     * is being fed the new data upon execution.
     *
     * Combine with {@link InterceptApi.waitForActiveSubscription | `waitForActiveSubscription()`}
     * to ensure a subscription is active before calling.
     *
     * @param resultOrFn [[include:result-or-fn.md]]
     * @param fireMatcher [[include:mock-matcher.md]]
     * @example
     * Push new information to a live feed:
     * ```js
     * const intercept = laika.intercept({operationName: 'getActiveUsersCount'});
     * await intercept.waitForActiveSubscription();
     * intercept.fireSubscriptionUpdate(
     *   {result: {data: {count: 10}}},
     * );
     * // e.g. assert the count displayed on the page is in fact 10
     * intercept.fireSubscriptionUpdate(
     *   {result: {data: {count: 0}}},
     * );
     * // e.g. assert the page shows "there are no active users currently on the page"
     * ```
     */
    fireSubscriptionUpdate(resultOrFn: ResultOrFn, fireMatcher?: Matcher): InterceptApi;
    /**
     * Add a callback that will fire every time a component connects to the query (i.e. mounts).
     * You may return a clean-up function which will be run when the query disconnects.
     */
    onSubscribe(callback: OnSubscribeCallback): (() => void) | void;
    /**
     * If you invoke this and do not setup any mocked results, your intercepted queries will not respond,
     * i.e. hang in a "loading" state, until you fire the data event manually
     * (e.g. in a custom callback defined in {@link InterceptApi.onSubscribe `onSubscribe(callback)`}.
     *
     * Does not affect `subscription` operations which will not reach the backend regardless of this setting (unless the `connectFutureLinksOrMitmFn` argument was set).
     *
     * Opposite of {@link InterceptApi.allowNetworkFallback `allowNetworkFallback()`}.
     */
    disableNetworkFallback(): void;
    /**
     * This restores the default behavior: both queries and mutations
     * will be passed to future links (e.g. your backend) and back to the components.
     *
     * Does not affect `subscription` operations which will not reach the backend regardless of this setting (unless the `connectFutureLinksOrMitmFn` argument was set).
     *
     * Opposite of {@link InterceptApi.disableNetworkFallback `disableNetworkFallback()`}.
     */
    allowNetworkFallback(): void;
    /**
     * Resets the mock configuration to its initial state and reenables the intercept if disabled by {@link InterceptApi.mockRestore `mockRestore()`}.
     */
    mockReset(): InterceptApi;
    /**
     * Removes the intercept completely and re-establishes connectivity in current and _future_ intercepted operations.
     * Note the word _future_. Any connections that were established prior to running this command,
     * will not automatically switch over to other mocks. This will mostly affect subscriptions.
     * Ideally, keep a reference to the original intercept throughout the duration of your session
     * and simply `intercept.reset()` if you need to restore connectivity or setup a different scenario.
     */
    mockRestore(): void;
}
