import { TSBuffer } from 'tsbuffer' ; import { ApiService , TransportDataUtil } from "tsrpc-base-client" ; import { ApiReturn , BaseServiceType , ServerOutputData , TsrpcError , TsrpcErrorData , TsrpcErrorType } from "tsrpc-proto" ; import { PrefixLogger } from "../models/PrefixLogger" ; import { BaseCall , BaseCallOptions } from "./BaseCall" ; export interface ApiCallOptions < Req , ServiceType extends BaseServiceType > extends BaseCallOptions < ServiceType > { /** Which service the Call is belong to */ service : ApiService ; /** Only exists in long connection, it is used to associate request and response.
     * It is created by the client, and the server would return the same value in `ApiReturn`.
     */ sn ? : number ; /** Request Data */ req : Req ; } typeParam typeParam typeParam export abstract class ApiCall < Req = any , Res = any , ServiceType extends BaseServiceType = any > extends BaseCall < ServiceType > { readonly type = 'api' as const ; /**
     * Which `ApiService` the request is calling for
     */ readonly service ! : ApiService ; /** Only exists in long connection, it is used to associate request and response.
     * It is created by the client, and the server would return the same value in `ApiReturn`.
     */ readonly sn ? : number ; /**
     * Request data from the client, type of it is checked by the framework already.
     */ readonly req : Req ; constructor ( options , logger ? ) { super ( options , logger ?? new PrefixLogger ( { logger : options . conn . logger , prefixs : [ `[Api:${ options . service . name }]${ options . sn !== undefined ? ` SN=${ options . sn }` : '' }` ] } ) ) ; this . sn = options . sn ; this . req = options . req ; } protected _return ? : ApiReturn < Res > ; /**
     * Response Data that sent already.
     * `undefined` means no return data is sent yet. (Never `call.succ()` and `call.error()`)
     */ public get return ( ) : ApiReturn < Res > | undefined { return this . _return ; } protected _usedTime : number | undefined ; /** Time from received req to send return data */ public get usedTime ( ) : number | undefined { return this . _usedTime ; } param res returns succ ( res ) { return this . _prepareReturn ( { isSucc : true , res : res } ) ; } returns error ( message , info ? ) ; error ( err ) ; error ( errOrMsg , data ? ) { let error = typeof errOrMsg === 'string' ? new TsrpcError ( errOrMsg , data ) : errOrMsg ; return this . _prepareReturn ( { isSucc : false , err : error } ) ; } ; protected async _prepareReturn ( ret , sendReturn ? ) { if ( this . _return ) { return ; } this . _return = ret ; let preFlow = await this . server . flows . preApiReturnFlow . exec ( { call : this , return : ret } , this . logger ) ; if ( ! preFlow ) { return ; } ret = preFlow . return ; this . _return = ret ; let opSend = await ( sendReturn ? sendReturn ( ret ) : this . _sendReturn ( ret ) ) ; if ( ! opSend . isSucc ) { this . logger . error ( '[SendReturnErr]' , opSend . errMsg , ret ) ; if ( ret . isSucc || ret . err . type === TsrpcErrorType . ApiError ) { this . _return = undefined ; this . server . onInternalServerError ( { message : opSend . errMsg , name : 'SendReturnErr' } , this ) ; } return ; } this . _usedTime = Date . now ( ) - this . startTime ; if ( ret . isSucc ) { this . logger . log ( '[ApiRes]' , `${ this . usedTime }ms` , this . server . options . logResBody ? ret . res : '' ) ; } else { if ( ret . err . type === TsrpcErrorType . ApiError ) { this . logger . log ( '[ResErr]' , `${ this . usedTime }ms` , ret . err , 'req=' , this . req ) ; } else { this . logger . error ( `[ResErr]` , `${ this . usedTime }ms` , ret . err , 'req=' , this . req ) ; } } await this . server . flows . postApiReturnFlow . exec ( preFlow , this . logger ) ; } protected async _sendReturn ( ret ) { let opServerOutput = ApiCall . encodeApiReturn ( this . server . tsbuffer , this . service , ret , this . conn . dataType , this . sn ) ; ; if ( ! opServerOutput . isSucc ) { this . server . onInternalServerError ( { message : opServerOutput . errMsg , stack : '  |- TransportDataUtil.encodeApiReturn\n  |- ApiCall._sendReturn' } , this ) ; return opServerOutput ; } let opSend = await this . conn . sendData ( opServerOutput . output ) ; if ( ! opSend . isSucc ) { return opSend ; } return opSend ; } static encodeApiReturn ( tsbuffer , service , apiReturn , type , sn ? ) ; static encodeApiReturn ( tsbuffer , service , apiReturn , type , sn ? ) ; static encodeApiReturn ( tsbuffer , service , apiReturn , type , sn ? ) ; static encodeApiReturn ( tsbuffer , service , apiReturn , type , sn ? ) ; static encodeApiReturn ( tsbuffer , service , apiReturn , type , sn ? ) { if ( type === 'buffer' ) { let serverOutputData = { sn : sn , serviceId : sn !== undefined ? service . id : undefined } ; if ( apiReturn . isSucc ) { let op = tsbuffer . encode ( apiReturn . res , service . resSchemaId ) ; if ( ! op . isSucc ) { return op ; } serverOutputData . buffer = op . buf ; } else { serverOutputData . error = apiReturn . err ; } let op = TransportDataUtil . tsbuffer . encode ( serverOutputData , 'ServerOutputData' ) ; return op . isSucc ? { isSucc : true , output : op . buf } : { isSucc : false , errMsg : op . errMsg } ; } else { apiReturn = { ... apiReturn } ; if ( apiReturn . isSucc ) { let op = tsbuffer . encodeJSON ( apiReturn . res , service . resSchemaId ) ; if ( ! op . isSucc ) { return op ; } apiReturn . res = op . json ; } else { apiReturn . err = { ... apiReturn . err } ; } let json = sn == undefined ? apiReturn : [ service . name , apiReturn , sn ] ; return { isSucc : true , output : type === 'json' ? json : JSON . stringify ( json ) } ; } } } export type SendReturnMethod < Res > = ( ret : ApiReturn < Res > ) => Promise < { isSucc : true ; } | { isSucc : false ; errMsg : string ; } > ; export declare type EncodeApiReturnOutput < T > = { isSucc : true ; /** Encoded binary buffer */ output : T ; errMsg ? : undefined ; } | { isSucc : false ; /** Error message */ errMsg : string ; output ? : undefined ; } ;