import passport , { AuthenticateOptions } from 'passport' ; import express from 'express' ; import { ExecutionParams } from 'subscriptions-transport-ws' ; import { AuthenticateReturn , InfoArgument } from './types' ; const promisifiedAuthentication = < UserObjectType extends Express . User > ( req , res , name , options ) => new Promise < AuthenticateReturn < UserObjectType > > ( ( resolve , reject ) => { const done = ( err , user , info ? ) => { if ( err ) reject ( err ) ; else resolve ( { user , info } ) ; } ; const authFn = passport . authenticate ( name , options , done ) ; return authFn ( req , res ) ; } ) ; const promisifiedLogin = < UserObjectType extends Express . User > ( req , user , options ? ) => new Promise < void > ( ( resolve , reject ) => { const done = ( err ) => { if ( err ) reject ( err ) ; else resolve ( ) ; } ; req . login ( user , options , done ) ; } ) ; interface CommonRequest < UserObjectType extends Express . User > extends Pick < Context < UserObjectType > , 'isAuthenticated' | 'isUnauthenticated' > { user ? : UserObjectType ; } export interface Context < UserObjectType extends Express . User > { isAuthenticated : ( ) => boolean ; isUnauthenticated : ( ) => boolean ; getUser : ( ) => UserObjectType ; authenticate : ( strategyName : string , options ? : object ) => Promise < AuthenticateReturn < UserObjectType > > ; login : ( user : UserObjectType , options ? : object ) => Promise < void > ; logout : ( ) => void ; res ? : express . Response ; req : CommonRequest < UserObjectType > ; } const buildCommonContext = < UserObjectType extends Express . User > ( req , additionalContext ) => ( { isAuthenticated : ( ) => req . isAuthenticated ( ) , isUnauthenticated : ( ) => req . isUnauthenticated ( ) , getUser : ( ) => req . user , authenticate : ( strategyName ) => { throw new Error ( `Authenticate (${ strategyName }) not implemented for subscriptions` ) ; } , login : ( ) => { throw new Error ( 'Not implemented for subscriptions' ) ; } , logout : ( ) => { throw new Error ( 'Not implemented for subscriptions' ) ; } , req , ... additionalContext , } ) ; export interface ContextParams { req : express . Request ; res : express . Response ; connection ? : ExecutionParams ; payload ? : unknown ; } const buildContext = < UserObjectType extends Express . User , R extends ContextParams = ContextParams > ( contextParams ) : Context < UserObjectType > => { const { req , res , connection , payload , ... additionalContext } = contextParams ; if ( connection ) { return buildCommonContext < UserObjectType > ( connection . context . req , additionalContext ) ; } const sharedContext = buildCommonContext < UserObjectType > ( req as any , additionalContext ) ; return { ... sharedContext , authenticate : ( name , options ) => promisifiedAuthentication ( req , res , name , options ) , login : ( user , options ) => promisifiedLogin < UserObjectType > ( req , user , options ) , logout : ( ) => req . logout ( ) , res , } ; } ; export default buildContext ;