import { RemoteGraphQLDataSource, GraphQLDataSourceProcessOptions } from '@apollo/gateway';
import { GatewayGraphQLResponse } from '@apollo/server-gateway-interface';
import * as jose from 'jose';
import { ApolloServerPlugin, GraphQLRequestListener, GraphQLRequestContext } from '@apollo/server';

type FederatedTokenContext = {
    federatedToken?: FederatedToken;
};
interface AccessToken {
    token: string;
    exp: number;
}
declare class FederatedToken {
    tokens: Record<string, AccessToken>;
    refreshTokens: Record<string, string>;
    values: Record<string, any>;
    private _accessTokenModified;
    private _refreshTokenModified;
    constructor();
    setAccessToken(name: string, token: AccessToken): void;
    setRefreshToken(name: string, token: string): void;
    isAccessTokenModified(): boolean;
    isRefreshTokenModified(): boolean;
    loadAccessToken(at: string, trackModified?: boolean): void;
    dumpAccessToken(): string | undefined;
    loadRefreshToken(value: string, trackModified?: boolean): void;
    dumpRefreshToken(): string | undefined;
}

type PublicFederatedTokenContext = {
    federatedToken?: PublicFederatedToken;
};
type TokenSignerOptions = {
    encryptKey: string;
    signKey: string;
    audience: string;
    issuer: string;
};
declare class TokenSigner {
    private config;
    private _encryptKey;
    private _signKey;
    constructor(config: TokenSignerOptions);
    encryptString(value: string): string;
    decryptString(value: string): string;
    signJWT(payload: any, exp: number): Promise<string>;
    verifyJWT(value: string): Promise<jose.JWTVerifyResult>;
    encryptJWT(payload: any, exp: number): Promise<string>;
    decryptJWT(jwt: string): Promise<jose.JWTDecryptResult>;
}
declare class PublicFederatedToken extends FederatedToken {
    createAccessJWT(signer: TokenSigner): Promise<string>;
    loadAccessJWT(signer: TokenSigner, value: string): Promise<void>;
    createRefreshJWT(signer: TokenSigner): Promise<string>;
    loadRefreshJWT(signer: TokenSigner, value: string): Promise<void>;
    encryptTokens(signer: TokenSigner): string;
    decryptTokens(signer: TokenSigner, value: string): any;
}

declare class FederatedGraphQLDataSource extends RemoteGraphQLDataSource<PublicFederatedTokenContext> {
    private name;
    constructor({ name, url }: {
        name: string;
        url: string;
    });
    willSendRequest(options: GraphQLDataSourceProcessOptions): void | Promise<void>;
    didReceiveResponse({ response, context, }: {
        response: GatewayGraphQLResponse;
        context: PublicFederatedTokenContext;
    }): Promise<GatewayGraphQLResponse>;
}

declare class GatewayAuthPlugin<TContext extends PublicFederatedTokenContext> implements ApolloServerPlugin, GraphQLRequestListener<TContext> {
    private signer;
    constructor(signer: TokenSigner);
    requestDidStart(requestContext: GraphQLRequestContext<TContext>): Promise<void | GraphQLRequestListener<TContext>>;
    didResolveOperation(requestContext: GraphQLRequestContext<TContext>): Promise<void>;
    willSendResponse(requestContext: GraphQLRequestContext<TContext>): Promise<void>;
}

declare class FederatedAuthPlugin<TContext extends FederatedTokenContext> implements ApolloServerPlugin, GraphQLRequestListener<TContext> {
    requestDidStart(requestContext: GraphQLRequestContext<TContext>): Promise<void | GraphQLRequestListener<TContext>>;
    willSendResponse(requestContext: GraphQLRequestContext<TContext>): Promise<void>;
}

export { FederatedAuthPlugin, FederatedGraphQLDataSource, FederatedToken, GatewayAuthPlugin, PublicFederatedToken, TokenSigner };
