import type { Seconds, UnixTimestamp } from '@thermopylae/core.declarations';
import type { Subject, SessionId, DeviceBase, UserSessionOperationContext, ReadUserSessionHook } from '@thermopylae/lib.user-session.commons';
import type { UserSessionMetaData } from './session';
import type { UserSessionsStorage } from './storage';
/**
 * Hooks called when session is renewed. <br/>
 * Mainly can be used for logging purposes.
 */
interface RenewSessionHooks {
    /**
     * Hook called when making an attempt to renew user session, but it was
     * renewed already from current NodeJs process.
     *
     * @param sessionId		Id of the session that was tried to be renewed.
     */
    onRenewMadeAlreadyFromCurrentProcess(sessionId: string): void;
    /**
     * Hook called when making an attempt to renew user session, but it was
     * renewed already from another NodeJs process.
     *
     * @param sessionId		Id of the session that was tried to be renewed.
     */
    onRenewMadeAlreadyFromAnotherProcess(sessionId: string): void;
    /**
     * After successful renew operation, the deletion of old session will be scheduled to occur
     * after {@link UserSessionTimeouts.oldSessionAvailabilityAfterRenewal} seconds. <br/>
     * In case the deletion of the old session will fail, this hook will be called with that error.
     *
     * @param sessionId		Id of the session.
     * @param e				Error that caused failure of the old session deletion.
     */
    onOldSessionDeleteFailure(sessionId: string, e: Error): void;
}
interface UserSessionTimeouts {
    /**
     * This timeout defines the amount of time in seconds a session will remain active
     * in case there is no activity in the session, closing and invalidating the session
     * upon the defined idle period since the last HTTP request received by the web application. <br/>
     * If you do not need idle session feature, do not set this option. <br/>
     * **Defaults** to *undefined*.
     */
    readonly idle?: Seconds;
    /**
     * This timeout defines the amount of time in seconds since session creation
     * after which the session ID is automatically renewed.
     * Renewal happens automatically when user session is read by manager. <br/>
     * Renewal consists in deletion of the old session and creation of a new one. <br/>
     * If you do not need renewal session feature, do not set this option. <br/>
     * **Defaults** to *undefined*.
     */
    readonly renewal?: Seconds;
    /**
     * This timeout defines the amount of time the old session will still be available after it was renewed. <br/>
     * This timeout starts counting from renew session operation, and on elapse will delete the old session. <br/>
     * Usually you will want to keep this timeout as small as possible to give a chance to requests that
     * were issued before renew operation to finish successfully, and then invalidate old session.
     * If {@link UserSessionManagerOptions.timeouts.renewal} option is not set, this option is ignored. <br/>
     * **Required** when {@link UserSessionManagerOptions.timeouts.renewal} option is set.
     * **Recommended** value is *5*.
     */
    readonly oldSessionAvailabilityAfterRenewal?: Seconds;
}
interface UserSessionManagerOptions<Device extends DeviceBase, Location> {
    /**
     * Length of the generated session id. <br/>
     * Because base64 encoding is used underneath, this is not the string length.
     * For example, to create a token of length 24, you want a byte length of 18. <br/>
     * Value of this option should not be lower than 15. <br/>
     * > **Important!** To prevent brute forcing [create long enough session id's](https://security.stackexchange.com/questions/81519/session-hijacking-through-sessionid-brute-forcing-possible).
     */
    readonly idLength: number;
    /**
     * Time To Live of the user session (in seconds).
     */
    readonly sessionTtl: Seconds;
    /**
     * Storage where users sessions are stored.
     */
    readonly storage: UserSessionsStorage<Device, Location>;
    /**
     * User session lifetime timeouts.
     */
    readonly timeouts?: UserSessionTimeouts;
    /**
     * Read user session hook. <br/>
     * Defaults to hook which ensures that in case device is present in both context and session metadata,
     * their *name* and *type* needs to be equal.
     */
    readonly readUserSessionHook?: ReadUserSessionHook<Device, Location, UserSessionMetaData<Device, Location>>;
    /**
     * Hooks called on session renew. <br/>
     * Defaults to noop hooks.
     */
    readonly renewSessionHooks?: RenewSessionHooks;
}
/**
 * Mark session as being renewed.
 */
declare const RENEWED_SESSION_FLAG = -1;
/**
 * Stateful implementation of the user sessions. <br/>
 * Session data is stored in external storage and client receives only it's id. <br/>
 * Sessions are implemented in a such way, so that they can be used in cluster or single-node infrastructures.
 *
 * @template Device		Type of the device.
 * @template Location	Type of the location.
 */
declare class UserSessionManager<Device extends DeviceBase = DeviceBase, Location = string> {
    /**
     * Manager options.
     */
    private readonly options;
    /**
     * Sessions that were renewed and are about to expire very soon. <br/>
     * This acts as *atomic flag* at the NodeJS process level,
     * to mark the session as being renewed and prevent further renews on it. <br/>
     */
    private readonly renewedSessions;
    /**
     * @param options		Options object. <br/>
     * 						It should not be modified after, as it will be used without being cloned.
     */
    constructor(options: UserSessionManagerOptions<Device, Location>);
    /**
     * Create new user session for `subject`.
     *
     * @param subject		Subject the session will belong to.
     * @param context		Operation context.
     * @param sessionTtl	Session ttl. Takes precedence over the default one.
     *
     * @returns				User session id.
     */
    create(subject: Subject, context: UserSessionOperationContext<Device, Location>, sessionTtl?: Seconds): Promise<SessionId>;
    /**
     * Read user session from external storage. <br/>
     * When idle functionality is activated, this method might delete user session and throw an error to notify about this,
     * if it was idle for more than {@link UserSessionManagerOptions.timeouts.idle} seconds. <br/>
     * When renew functionality is activated, this method might create a new user session, and return it's id as the second part of the tuple.
     * In case renewed session id is returned, it needs to be sent to application clients via 'Set-Cookie' header to replace the old session cookie.
     * The old session will still be available for {@link UserSessionManagerOptions.timeouts.oldSessionAvailabilityAfterRenewal} seconds,
     * so that older requests might complete successfully and client has time to refresh session id on it's side.
     *
     * @param subject		Subject.
     * @param sessionId		Session id.
     * @param context		Operation context.
     *
     * @throws {Exception}	With the following error codes:
     * 						- {@link ErrorCodes.USER_SESSION_NOT_FOUND}		- session wasn't found in the storage
     * 						- {@link ErrorCodes.USER_SESSION_EXPIRED} 		- session is accessed from a device which differs from the one it was created
     * 						- {@link ErrorCodes.USER_SESSION_EXPIRED}		- session was expired because of the idle timeout
     *
     * @returns		A tuple with the following parts:
     * 				- session metadata
     * 				- renewed session id (if renewal took place)
     */
    read(subject: Subject, sessionId: SessionId, context: UserSessionOperationContext<Device, Location>): Promise<[Readonly<UserSessionMetaData<Device, Location>>, string | null]>;
    /**
     * Read all active sessions of the subject.
     *
     * @param subject	Subject.
     *
     * @returns		Active sessions of the subject.
     */
    readAll(subject: Subject): Promise<ReadonlyMap<SessionId, Readonly<UserSessionMetaData<Device, Location>>>>;
    /**
     * Renew user session. <br/>
     * Renewing consist from the following actions:
     * 	1. scheduling deletion of the old session in a very short amount of time
     * 	2. creating a new user session
     *
     * @param subject				Subject.
     * @param sessionId				Id of the session to be renewed.
     * @param sessionMetaData		Metadata of that session.
     * @param context				Operation context.
     *
     * @returns		The new user session id. <br/>
     * 				When renew can't be performed, a log message is printed and *null* is returned.
     */
    renew(subject: Subject, sessionId: SessionId, sessionMetaData: UserSessionMetaData<Device, Location>, context: UserSessionOperationContext<Device, Location>): Promise<string | null>;
    /**
     * Delete user session.
     *
     * @param subject		Subject.
     * @param sessionId		Id of the user session.
     */
    delete(subject: Subject, sessionId: SessionId): Promise<void>;
    /**
     * Delete all of the user sessions.
     *
     * @param subject	Subject.
     *
     * @returns		Number of deleted sessions.
     */
    deleteAll(subject: Subject): Promise<number>;
    /**
     * Hashes session id. <br/>
     * Useful for logging purposes.
     *
     * @param sessionId		Session id.
     *
     * @returns				Hashed session id.
     */
    static hash(sessionId: SessionId): string;
    private static fillWithDefaults;
    static currentTimestamp(): UnixTimestamp;
    private static readUserSessionHook;
    private static renewSessionHooks;
}
export { UserSessionManager, UserSessionManagerOptions, UserSessionTimeouts, RenewSessionHooks, RENEWED_SESSION_FLAG };
