/**
 * Copyright (c) "Neo4j"
 * Neo4j Sweden AB [https://neo4j.com]
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import ConnectionProvider from './connection-provider';
import { Bookmarks } from './internal/bookmarks';
import ConfiguredCustomResolver from './internal/resolver/configured-custom-resolver';
import { Logger } from './internal/logger';
import Session, { TransactionConfig } from './session';
import { ServerInfo } from './result-summary';
import { EncryptionLevel, LoggingConfig, TrustStrategy, SessionMode, Query, AuthToken } from './types';
import { ServerAddress } from './internal/server-address';
import BookmarkManager from './bookmark-manager';
import EagerResult from './result-eager';
import { ResultTransformer } from './result-transformers';
import QueryExecutor from './internal/query-executor';
import NotificationFilter from './notification-filter';
import { ProtocolVersion } from './protocol-version';
import { Rules } from './mapping.highlevel';
/**
 * Constant that represents read session access mode.
 * Should be used like this: `driver.session({ defaultAccessMode: neo4j.session.READ })`.
 * @type {string}
 */
declare const READ: SessionMode;
/**
 * Constant that represents write session access mode.
 * Should be used like this: `driver.session({ defaultAccessMode: neo4j.session.WRITE })`.
 * @type {string}
 */
declare const WRITE: SessionMode;
interface MetaInfo {
    routing: boolean;
    typename: string;
    address: string | ServerAddress;
}
type CreateConnectionProvider = (id: number, config: Object, log: Logger, hostNameResolver: ConfiguredCustomResolver) => ConnectionProvider;
type CreateSession = (args: {
    mode: SessionMode;
    connectionProvider: ConnectionProvider;
    bookmarks?: Bookmarks;
    database: string;
    config: any;
    reactive: boolean;
    fetchSize: number;
    impersonatedUser?: string;
    bookmarkManager?: BookmarkManager;
    notificationFilter?: NotificationFilter;
    auth?: AuthToken;
    log: Logger;
    homeDatabaseCallback?: (user: string, database: any) => void;
    disableAutoCommitRetries?: boolean;
}) => Session;
type CreateQueryExecutor = (createSession: (config: {
    database?: string;
    bookmarkManager?: BookmarkManager;
}) => Session) => QueryExecutor;
interface DriverConfig {
    encrypted?: EncryptionLevel | boolean;
    trust?: TrustStrategy;
    fetchSize?: number;
    logging?: LoggingConfig;
    notificationFilter?: NotificationFilter;
    connectionLivenessCheckTimeout?: number;
    disableAutoCommitRetries?: boolean;
}
/**
 * The session configuration
 *
 * @interface
 */
declare class SessionConfig {
    defaultAccessMode?: SessionMode;
    bookmarks?: string | string[];
    database?: string;
    impersonatedUser?: string;
    fetchSize?: number;
    bookmarkManager?: BookmarkManager;
    notificationFilter?: NotificationFilter;
    auth?: AuthToken;
    disableAutoCommitRetries?: boolean;
    /**
     * @constructor
     * @private
     */
    constructor();
}
type RoutingControl = 'WRITE' | 'READ';
/**
 * @typedef {'WRITE'|'READ'} RoutingControl
 */
/**
 * Constants that represents routing modes.
 *
 * @example
 * driver.executeQuery("<QUERY>", <PARAMETERS>, { routing: neo4j.routing.WRITE })
 */
declare const routing: {
    WRITE: "WRITE";
    READ: "READ";
};
/**
 * The query configuration
 * @interface
 */
declare class QueryConfig<T = EagerResult> {
    routing?: RoutingControl;
    database?: string;
    impersonatedUser?: string;
    bookmarkManager?: BookmarkManager | null;
    resultTransformer?: ResultTransformer<T>;
    transactionConfig?: TransactionConfig;
    auth?: AuthToken;
    signal?: AbortSignal;
    /**
     * @constructor
     * @private
     */
    private constructor();
}
/**
 * A driver maintains one or more {@link Session}s with a remote
 * Neo4j instance. Through the {@link Session}s you can send queries
 * and retrieve results from the database.
 *
 * Drivers are reasonably expensive to create - you should strive to keep one
 * driver instance around per Neo4j Instance you connect to.
 *
 * @access public
 */
declare class Driver {
    private readonly _id;
    private readonly _meta;
    private readonly _config;
    private readonly _log;
    private readonly _createConnectionProvider;
    private _connectionProvider;
    private readonly _createSession;
    private readonly _defaultExecuteQueryBookmarkManager;
    private readonly _queryExecutor;
    private readonly homeDatabaseCache;
    /**
     * You should not be calling this directly, instead use {@link driver}.
     * @constructor
     * @protected
     * @param {Object} meta Metainformation about the driver
     * @param {Object} config
     * @param {function(id: number, config:Object, log:Logger, hostNameResolver: ConfiguredCustomResolver): ConnectionProvider } createConnectionProvider Creates the connection provider
     * @param {function(args): Session } createSession Creates the a session
    */
    constructor(meta: MetaInfo, config: DriverConfig | undefined, createConnectionProvider: CreateConnectionProvider, createSession?: CreateSession, createQueryExecutor?: CreateQueryExecutor);
    /**
     * The bookmark managed used by {@link Driver.executeQuery}
     *
     * @type {BookmarkManager}
     */
    get executeQueryBookmarkManager(): BookmarkManager;
    /**
     * Executes a query in a retryable context and returns a {@link EagerResult}.
     *
     * This method is a shortcut for a {@link Session#executeRead} and {@link Session#executeWrite}.
     *
     * NOTE: Because it is an explicit transaction from the server point of view, Cypher queries using
     * "CALL {} IN TRANSACTIONS" or the older "USING PERIODIC COMMIT" construct will not work (call
     * {@link Session#run} for these).
     *
     * @example
     * // Run a simple write query
     * const { keys, records, summary } = await driver.executeQuery('CREATE (p:Person{ name: $name }) RETURN p', { name: 'Person1'})
     *
     * @example
     * // Run a read query
     * const { keys, records, summary } = await driver.executeQuery(
     *    'MATCH (p:Person{ name: $name }) RETURN p',
     *    { name: 'Person1'},
     *    { routing: neo4j.routing.READ})
     *
     * @example
     * // Run a read query returning a Person Nodes per elementId
     * const peopleMappedById = await driver.executeQuery(
     *    'MATCH (p:Person{ name: $name }) RETURN p',
     *    { name: 'Person1'},
     *    {
     *      resultTransformer: neo4j.resultTransformers.mapped({
     *        map(record) {
     *          const p = record.get('p')
     *          return [p.elementId, p]
     *        },
     *        collect(elementIdPersonPairArray) {
     *          return new Map(elementIdPersonPairArray)
     *        }
     *      })
     *    }
     * )
     *
     * const person = peopleMappedById.get("<ELEMENT_ID>")
     *
     * @example
     * // these lines
     * const transformedResult = await driver.executeQuery(
     *    "<QUERY>",
     *    <PARAMETERS>,
     *    {
     *       routing: neo4j.routing.WRITE,
     *       resultTransformer: transformer,
     *       database: "<DATABASE>",
     *       impersonatedUser: "<USER>",
     *       bookmarkManager: bookmarkManager
     *    })
     * // are equivalent to those
     * const session = driver.session({
     *    database: "<DATABASE>",
     *    impersonatedUser: "<USER>",
     *    bookmarkManager: bookmarkManager
     * })
     *
     * try {
     *    const transformedResult = await session.executeWrite(tx => {
     *        const result = tx.run("<QUERY>", <PARAMETERS>)
     *        return transformer(result)
     *    })
     * } finally {
     *    await session.close()
     * }
     *
     * @public
     * @param {string | {text: string, parameters?: object, parameterRules?: Rules}} query - Cypher query to execute
     * @param {Object} parameters - Map with parameters to use in the query
     * @param {QueryConfig<T>} config - The query configuration
     * @param {Rules} parameterRules - Rules to typecheck and/or map the parameter object. Must not be provided as a separate argument if an Object is passed as first argument
     * @returns {Promise<T>}
     *
     * @see {@link resultTransformers} for provided result transformers.
     */
    executeQuery<T = EagerResult>(query: Query, parameters?: any, config?: QueryConfig<T>, parameterRules?: Rules): Promise<T>;
    /**
     * Verifies connectivity of this driver by trying to open a connection with the provided driver options.
     *
     * @public
     * @param {Object} param - The object parameter
     * @param {string} param.database - The target database to verify connectivity for.
     * @returns {Promise<void>} promise resolved with void or rejected with error.
     */
    verifyConnectivity({ database }?: {
        database?: string;
    }): Promise<void>;
    /**
     * This method verifies the authorization credentials work by trying to acquire a connection
     * to one of the servers with the given credentials.
     *
     * @param {object} param - object parameter
     * @property {AuthToken} param.auth - the target auth for the to-be-acquired connection
     * @property {string} param.database - the target database for the to-be-acquired connection
     *
     * @returns {Promise<boolean>} promise resolved with true if succeed, false if failed with
     *  authentication issue and rejected with error if non-authentication error happens.
     */
    verifyAuthentication({ database, auth }?: {
        auth?: AuthToken;
        database?: string;
    }): Promise<boolean>;
    /**
     * Get ServerInfo for the giver database.
     *
     * @param {Object} param - The object parameter
     * @param {string} param.database - The target database to verify connectivity for.
     * @returns {Promise<ServerInfo>} promise resolved with the ServerInfo or rejected with error.
     */
    getServerInfo({ database }?: {
        database?: string;
    }): Promise<ServerInfo>;
    /**
     * Returns whether the server supports multi database capabilities based on the protocol
     * version negotiated via handshake.
     *
     * Note that this function call _always_ causes a round-trip to the server.
     *
     * @returns {Promise<boolean>} promise resolved with a boolean or rejected with error.
     */
    supportsMultiDb(): Promise<boolean>;
    /**
     * Returns whether the server supports transaction config capabilities based on the protocol
     * version negotiated via handshake.
     *
     * Note that this function call _always_ causes a round-trip to the server.
     *
     * @returns {Promise<boolean>} promise resolved with a boolean or rejected with error.
     */
    supportsTransactionConfig(): Promise<boolean>;
    /**
     * Returns whether the server supports user impersonation capabilities based on the protocol
     * version negotiated via handshake.
     *
     * Note that this function call _always_ causes a round-trip to the server.
     *
     * @returns {Promise<boolean>} promise resolved with a boolean or rejected with error.
     */
    supportsUserImpersonation(): Promise<boolean>;
    /**
     * Returns whether the driver session re-auth functionality capabilities based on the protocol
     * version negotiated via handshake.
     *
     * Note that this function call _always_ causes a round-trip to the server.
     *
     * @returns {Promise<boolean>} promise resolved with a boolean or rejected with error.
     */
    supportsSessionAuth(): Promise<boolean>;
    /**
     * Returns the protocol version negotiated via handshake.
     *
     * Note that this function call _always_ causes a round-trip to the server.
     *
     * @returns {Promise<number>} the protocol version negotiated via handshake.
     * @throws {Error} When protocol negotiation fails
     */
    getNegotiatedProtocolVersion(): Promise<ProtocolVersion>;
    /**
     * Returns boolean to indicate if driver has been configured with encryption enabled.
     *
     * @returns {boolean}
     */
    isEncrypted(): boolean;
    /**
     * @protected
     * @returns {boolean}
     */
    _supportsRouting(): boolean;
    /**
     * Returns boolean to indicate if driver has been configured with encryption enabled.
     *
     * @protected
     * @returns {boolean}
     */
    _isEncrypted(): boolean;
    /**
     * Returns the configured trust strategy that the driver has been configured with.
     *
     * @protected
     * @returns {TrustStrategy}
     */
    _getTrust(): TrustStrategy | undefined;
    /**
     * Acquire a session to communicate with the database. The session will
     * borrow connections from the underlying connection pool as required and
     * should be considered lightweight and disposable.
     *
     * This comes with some responsibility - make sure you always call
     * {@link close} when you are done using a session, and likewise,
     * make sure you don't close your session before you are done using it. Once
     * it is closed, the underlying connection will be released to the connection
     * pool and made available for others to use.
     *
     * @public
     * @param {SessionConfig} param - The session configuration
     * @return {Session} new session.
     */
    session({ defaultAccessMode, bookmarks: bookmarkOrBookmarks, database, impersonatedUser, fetchSize, bookmarkManager, notificationFilter, auth, disableAutoCommitRetries }?: SessionConfig): Session;
    /**
     * Close all open sessions and other associated resources. You should
     * make sure to use this when you are done with this driver instance.
     *
     * This will interrupt any running connections.
     * Make sure you are done using the driver object and any resources
     * spawned from it (such as sessions or transactions) while calling
     * this method. Failing to do so will result in unspecified behavior.
     *
     * @public
     * @return {Promise<void>} promise resolved when the driver is closed.
     */
    close(): Promise<void>;
    [Symbol.asyncDispose](): Promise<void>;
    /**
     * @protected
     * @returns {void}
     */
    _afterConstruction(): void;
    _homeDatabaseCallback(cacheKey: string, database: any): void;
    /**
     * @private
     */
    _newSession({ defaultAccessMode, bookmarkOrBookmarks, database, reactive, impersonatedUser, fetchSize, bookmarkManager, notificationFilter, auth, disableAutoCommitRetries }: {
        defaultAccessMode: SessionMode;
        bookmarkOrBookmarks?: string | string[];
        database: string;
        reactive: boolean;
        impersonatedUser?: string;
        fetchSize: number;
        bookmarkManager?: BookmarkManager;
        notificationFilter?: NotificationFilter;
        auth?: AuthToken;
        disableAutoCommitRetries?: boolean;
    }): Session;
    /**
     * @private
     */
    _getOrCreateConnectionProvider(): ConnectionProvider;
}
export { Driver, READ, WRITE, routing, SessionConfig, QueryConfig };
export type { RoutingControl };
export default Driver;
