build: switch to NodeNext module resolution
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / OCPPRequestService.ts
CommitLineData
ec0eebcc 1import Ajv, { type JSONSchemaType, type ValidateFunction } from 'ajv';
b52c969d
JB
2import ajvFormats from 'ajv-formats';
3
a6ef1ece
JB
4import { OCPPConstants } from './OCPPConstants.js';
5import type { OCPPResponseService } from './OCPPResponseService.js';
6import { OCPPServiceUtils } from './OCPPServiceUtils.js';
7import type { ChargingStation } from '../../charging-station/index.js';
8import { OCPPError } from '../../exception/index.js';
9import { PerformanceStatistics } from '../../performance/index.js';
e7aeea18 10import {
8baae8ee 11 ChargingStationEvents,
27782dbc 12 type ErrorCallback,
268a74bb
JB
13 type ErrorResponse,
14 ErrorType,
27782dbc 15 type IncomingRequestCommand,
268a74bb
JB
16 type JsonType,
17 MessageType,
18 type OCPPVersion,
27782dbc 19 type OutgoingRequest,
e7aeea18 20 RequestCommand,
27782dbc 21 type RequestParams,
268a74bb 22 type Response,
27782dbc 23 type ResponseCallback,
e0b0ee21 24 type ResponseType,
a6ef1ece 25} from '../../types/index.js';
2b94ad12
JB
26import {
27 cloneObject,
28 formatDurationMilliSeconds,
29 handleSendMessageError,
30 isNullOrUndefined,
31 logger,
a6ef1ece 32} from '../../utils/index.js';
c0560973 33
e3018bc4
JB
34const moduleName = 'OCPPRequestService';
35
b9da1bc2
JB
36const defaultRequestParams: RequestParams = {
37 skipBufferingOnError: false,
38 triggerMessage: false,
39 throwError: false,
40};
41
268a74bb 42export abstract class OCPPRequestService {
08f130a0 43 private static instance: OCPPRequestService | null = null;
d270cc87 44 private readonly version: OCPPVersion;
012ae1a9 45 private readonly ajv: Ajv;
9f2e3130 46 private readonly ocppResponseService: OCPPResponseService;
291b5ec8
JB
47 private readonly jsonValidateFunctions: Map<RequestCommand, ValidateFunction<JsonType>>;
48 protected abstract jsonSchemas: Map<RequestCommand, JSONSchemaType<JsonType>>;
c0560973 49
d270cc87
JB
50 protected constructor(version: OCPPVersion, ocppResponseService: OCPPResponseService) {
51 this.version = version;
45988780 52 this.ajv = new Ajv({
98fc1389 53 keywords: ['javaType'],
45988780
JB
54 multipleOfPrecision: 2,
55 });
9952c548 56 ajvFormats(this.ajv);
291b5ec8 57 this.jsonValidateFunctions = new Map<RequestCommand, ValidateFunction<JsonType>>();
d270cc87 58 this.ocppResponseService = ocppResponseService;
31f59c6d 59 this.requestHandler = this.requestHandler.bind(this) as <
e1d9a0f4 60 // eslint-disable-next-line @typescript-eslint/no-unused-vars
31f59c6d 61 ReqType extends JsonType,
5edd8ba0 62 ResType extends JsonType,
31f59c6d
JB
63 >(
64 chargingStation: ChargingStation,
65 commandName: RequestCommand,
66 commandParams?: JsonType,
5edd8ba0 67 params?: RequestParams,
31f59c6d
JB
68 ) => Promise<ResType>;
69 this.sendMessage = this.sendMessage.bind(this) as (
70 chargingStation: ChargingStation,
71 messageId: string,
72 messagePayload: JsonType,
73 commandName: RequestCommand,
5edd8ba0 74 params?: RequestParams,
31f59c6d
JB
75 ) => Promise<ResponseType>;
76 this.sendResponse = this.sendResponse.bind(this) as (
77 chargingStation: ChargingStation,
78 messageId: string,
79 messagePayload: JsonType,
5edd8ba0 80 commandName: IncomingRequestCommand,
31f59c6d
JB
81 ) => Promise<ResponseType>;
82 this.sendError = this.sendError.bind(this) as (
83 chargingStation: ChargingStation,
84 messageId: string,
85 ocppError: OCPPError,
5edd8ba0 86 commandName: RequestCommand | IncomingRequestCommand,
31f59c6d
JB
87 ) => Promise<ResponseType>;
88 this.internalSendMessage = this.internalSendMessage.bind(this) as (
89 chargingStation: ChargingStation,
90 messageId: string,
91 messagePayload: JsonType | OCPPError,
92 messageType: MessageType,
93 commandName: RequestCommand | IncomingRequestCommand,
5edd8ba0 94 params?: RequestParams,
31f59c6d
JB
95 ) => Promise<ResponseType>;
96 this.buildMessageToSend = this.buildMessageToSend.bind(this) as (
97 chargingStation: ChargingStation,
98 messageId: string,
99 messagePayload: JsonType | OCPPError,
100 messageType: MessageType,
101 commandName: RequestCommand | IncomingRequestCommand,
31f59c6d 102 ) => string;
291b5ec8 103 this.validateRequestPayload = this.validateRequestPayload.bind(this) as <T extends JsonType>(
31f59c6d
JB
104 chargingStation: ChargingStation,
105 commandName: RequestCommand | IncomingRequestCommand,
5edd8ba0 106 payload: T,
31f59c6d
JB
107 ) => boolean;
108 this.validateIncomingRequestResponsePayload = this.validateIncomingRequestResponsePayload.bind(
5edd8ba0 109 this,
291b5ec8 110 ) as <T extends JsonType>(
31f59c6d
JB
111 chargingStation: ChargingStation,
112 commandName: RequestCommand | IncomingRequestCommand,
5edd8ba0 113 payload: T,
31f59c6d 114 ) => boolean;
c0560973
JB
115 }
116
e7aeea18 117 public static getInstance<T extends OCPPRequestService>(
08f130a0 118 this: new (ocppResponseService: OCPPResponseService) => T,
5edd8ba0 119 ocppResponseService: OCPPResponseService,
e7aeea18 120 ): T {
1ca780f9 121 if (OCPPRequestService.instance === null) {
08f130a0 122 OCPPRequestService.instance = new this(ocppResponseService);
9f2e3130 123 }
08f130a0 124 return OCPPRequestService.instance as T;
9f2e3130
JB
125 }
126
c75a6675 127 public async sendResponse(
08f130a0 128 chargingStation: ChargingStation,
e7aeea18 129 messageId: string,
5cc4b63b 130 messagePayload: JsonType,
5edd8ba0 131 commandName: IncomingRequestCommand,
5eaabe90 132 ): Promise<ResponseType> {
5e0c67e8 133 try {
c75a6675 134 // Send response message
e7aeea18 135 return await this.internalSendMessage(
08f130a0 136 chargingStation,
e7aeea18
JB
137 messageId,
138 messagePayload,
139 MessageType.CALL_RESULT_MESSAGE,
5edd8ba0 140 commandName,
e7aeea18 141 );
5e0c67e8 142 } catch (error) {
fa5995d6 143 handleSendMessageError(chargingStation, commandName, error as Error, {
07561812 144 throwError: true,
dc922667 145 });
e1d9a0f4 146 return null;
5e0c67e8
JB
147 }
148 }
149
e7aeea18 150 public async sendError(
08f130a0 151 chargingStation: ChargingStation,
e7aeea18
JB
152 messageId: string,
153 ocppError: OCPPError,
5edd8ba0 154 commandName: RequestCommand | IncomingRequestCommand,
e7aeea18 155 ): Promise<ResponseType> {
5e0c67e8
JB
156 try {
157 // Send error message
e7aeea18 158 return await this.internalSendMessage(
08f130a0 159 chargingStation,
e7aeea18
JB
160 messageId,
161 ocppError,
162 MessageType.CALL_ERROR_MESSAGE,
5edd8ba0 163 commandName,
e7aeea18 164 );
5e0c67e8 165 } catch (error) {
fa5995d6 166 handleSendMessageError(chargingStation, commandName, error as Error);
e1d9a0f4 167 return null;
5e0c67e8
JB
168 }
169 }
170
e7aeea18 171 protected async sendMessage(
08f130a0 172 chargingStation: ChargingStation,
e7aeea18 173 messageId: string,
5cc4b63b 174 messagePayload: JsonType,
e7aeea18 175 commandName: RequestCommand,
7f3decca 176 params?: RequestParams,
e7aeea18 177 ): Promise<ResponseType> {
7b5dbe91 178 params = {
b9da1bc2 179 ...defaultRequestParams,
7b5dbe91
JB
180 ...params,
181 };
5e0c67e8 182 try {
e7aeea18 183 return await this.internalSendMessage(
08f130a0 184 chargingStation,
e7aeea18
JB
185 messageId,
186 messagePayload,
187 MessageType.CALL_MESSAGE,
188 commandName,
5edd8ba0 189 params,
e7aeea18 190 );
5e0c67e8 191 } catch (error) {
fa5995d6 192 handleSendMessageError(chargingStation, commandName, error as Error, {
8ec8e3d0
JB
193 throwError: params.throwError,
194 });
e1d9a0f4 195 return null;
5e0c67e8
JB
196 }
197 }
198
291b5ec8 199 private validateRequestPayload<T extends JsonType>(
b52c969d 200 chargingStation: ChargingStation,
45988780 201 commandName: RequestCommand | IncomingRequestCommand,
5edd8ba0 202 payload: T,
b52c969d 203 ): boolean {
5398cecf 204 if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
b52c969d
JB
205 return true;
206 }
b3fc3ff5
JB
207 if (this.jsonSchemas.has(commandName as RequestCommand) === false) {
208 logger.warn(
5edd8ba0 209 `${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: No JSON schema found for command '${commandName}' PDU validation`,
b3fc3ff5 210 );
45988780
JB
211 return true;
212 }
0b0ca54f 213 const validate = this.getJsonRequestValidateFunction<T>(commandName as RequestCommand);
9bf0ef23 214 payload = cloneObject<T>(payload);
1799761a 215 OCPPServiceUtils.convertDateToISOString<T>(payload);
b52c969d
JB
216 if (validate(payload)) {
217 return true;
218 }
219 logger.error(
45988780 220 `${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: Command '${commandName}' request PDU is invalid: %j`,
5edd8ba0 221 validate.errors,
b52c969d 222 );
e909d2a7 223 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
b52c969d 224 throw new OCPPError(
9ff486f4 225 OCPPServiceUtils.ajvErrorsToErrorType(validate.errors),
b52c969d
JB
226 'Request PDU is invalid',
227 commandName,
4ed03b6e 228 JSON.stringify(validate.errors, undefined, 2),
b52c969d
JB
229 );
230 }
231
0b0ca54f
JB
232 private getJsonRequestValidateFunction<T extends JsonType>(commandName: RequestCommand) {
233 if (this.jsonValidateFunctions.has(commandName) === false) {
234 this.jsonValidateFunctions.set(
235 commandName,
236 this.ajv.compile<T>(this.jsonSchemas.get(commandName)!).bind(this),
237 );
238 }
239 return this.jsonValidateFunctions.get(commandName)!;
240 }
241
291b5ec8 242 private validateIncomingRequestResponsePayload<T extends JsonType>(
b3fc3ff5
JB
243 chargingStation: ChargingStation,
244 commandName: RequestCommand | IncomingRequestCommand,
5edd8ba0 245 payload: T,
b3fc3ff5 246 ): boolean {
5398cecf 247 if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
b3fc3ff5
JB
248 return true;
249 }
250 if (
251 this.ocppResponseService.jsonIncomingRequestResponseSchemas.has(
5edd8ba0 252 commandName as IncomingRequestCommand,
b3fc3ff5
JB
253 ) === false
254 ) {
255 logger.warn(
5edd8ba0 256 `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: No JSON schema found for command '${commandName}' PDU validation`,
b3fc3ff5
JB
257 );
258 return true;
259 }
0b0ca54f 260 const validate = this.getJsonRequestResponseValidateFunction<T>(
ec0eebcc 261 commandName as IncomingRequestCommand,
0b0ca54f 262 );
9bf0ef23 263 payload = cloneObject<T>(payload);
b3fc3ff5
JB
264 OCPPServiceUtils.convertDateToISOString<T>(payload);
265 if (validate(payload)) {
266 return true;
267 }
268 logger.error(
02887891 269 `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: Command '${commandName}' reponse PDU is invalid: %j`,
5edd8ba0 270 validate.errors,
b3fc3ff5
JB
271 );
272 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
273 throw new OCPPError(
9ff486f4 274 OCPPServiceUtils.ajvErrorsToErrorType(validate.errors),
b3fc3ff5
JB
275 'Response PDU is invalid',
276 commandName,
4ed03b6e 277 JSON.stringify(validate.errors, undefined, 2),
b3fc3ff5
JB
278 );
279 }
280
0b0ca54f
JB
281 private getJsonRequestResponseValidateFunction<T extends JsonType>(
282 commandName: IncomingRequestCommand,
283 ) {
284 if (
285 this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.has(commandName) ===
286 false
287 ) {
288 this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.set(
289 commandName,
290 this.ajv
291 .compile<T>(this.ocppResponseService.jsonIncomingRequestResponseSchemas.get(commandName)!)
292 .bind(this),
293 );
294 }
295 return this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.get(commandName)!;
296 }
297
e7aeea18 298 private async internalSendMessage(
08f130a0 299 chargingStation: ChargingStation,
e7aeea18 300 messageId: string,
5cc4b63b 301 messagePayload: JsonType | OCPPError,
e7aeea18 302 messageType: MessageType,
72092cfc 303 commandName: RequestCommand | IncomingRequestCommand,
7f3decca 304 params?: RequestParams,
e7aeea18 305 ): Promise<ResponseType> {
7b5dbe91 306 params = {
b9da1bc2 307 ...defaultRequestParams,
7b5dbe91
JB
308 ...params,
309 };
e7aeea18 310 if (
f7c2994d 311 (chargingStation.inUnknownState() === true &&
3a13fc92 312 commandName === RequestCommand.BOOT_NOTIFICATION) ||
5398cecf 313 (chargingStation.stationInfo?.ocppStrictCompliance === false &&
f7c2994d
JB
314 chargingStation.inUnknownState() === true) ||
315 chargingStation.inAcceptedState() === true ||
316 (chargingStation.inPendingState() === true &&
3a13fc92 317 (params.triggerMessage === true || messageType === MessageType.CALL_RESULT_MESSAGE))
e7aeea18 318 ) {
caad9d6b
JB
319 // eslint-disable-next-line @typescript-eslint/no-this-alias
320 const self = this;
321 // Send a message through wsConnection
5b2721db 322 return new Promise<ResponseType>((resolve, reject) => {
1b2acf4e
JB
323 /**
324 * Function that will receive the request's response
325 *
326 * @param payload -
327 * @param requestPayload -
328 */
329 const responseCallback = (payload: JsonType, requestPayload: JsonType): void => {
330 if (chargingStation.stationInfo?.enableStatistics === true) {
331 chargingStation.performanceStatistics?.addRequestStatistic(
332 commandName,
333 MessageType.CALL_RESULT_MESSAGE,
e8a92d57 334 );
1b2acf4e
JB
335 }
336 // Handle the request's response
337 self.ocppResponseService
338 .responseHandler(
339 chargingStation,
340 commandName as RequestCommand,
341 payload,
342 requestPayload,
343 )
344 .then(() => {
345 resolve(payload);
346 })
b7ee97c1 347 .catch(reject)
1b2acf4e
JB
348 .finally(() => {
349 chargingStation.requests.delete(messageId);
8baae8ee 350 chargingStation.emit(ChargingStationEvents.updated);
1b2acf4e
JB
351 });
352 };
e8a92d57 353
1b2acf4e
JB
354 /**
355 * Function that will receive the request's error response
356 *
9d7b5fa3 357 * @param ocppError -
1b2acf4e
JB
358 * @param requestStatistic -
359 */
9d7b5fa3 360 const errorCallback = (ocppError: OCPPError, requestStatistic = true): void => {
1b2acf4e
JB
361 if (requestStatistic === true && chargingStation.stationInfo?.enableStatistics === true) {
362 chargingStation.performanceStatistics?.addRequestStatistic(
363 commandName,
364 MessageType.CALL_ERROR_MESSAGE,
365 );
764d2c91 366 }
1b2acf4e
JB
367 logger.error(
368 `${chargingStation.logPrefix()} Error occurred at ${OCPPServiceUtils.getMessageTypeString(
369 messageType,
370 )} command ${commandName} with PDU %j:`,
e7aeea18 371 messagePayload,
9d7b5fa3 372 ocppError,
e7aeea18 373 );
1b2acf4e 374 chargingStation.requests.delete(messageId);
8baae8ee 375 chargingStation.emit(ChargingStationEvents.updated);
9d7b5fa3
JB
376 reject(ocppError);
377 };
378
3c80de96
JB
379 const handleSendError = (ocppError: OCPPError): void => {
380 if (params?.skipBufferingOnError === false) {
381 // Buffer
382 chargingStation.bufferMessage(messageToSend);
383 if (messageType === MessageType.CALL_MESSAGE) {
384 this.cacheRequestPromise(
385 chargingStation,
386 messageId,
387 messagePayload as JsonType,
388 commandName,
389 responseCallback,
390 errorCallback,
391 );
392 }
9aa1a33f
JB
393 } else if (
394 params?.skipBufferingOnError === true &&
395 messageType === MessageType.CALL_MESSAGE
396 ) {
2b94ad12
JB
397 // Remove request from the cache
398 chargingStation.requests.delete(messageId);
d42379d8 399 }
2b94ad12 400 return reject(ocppError);
d42379d8
JB
401 };
402
1b2acf4e
JB
403 if (chargingStation.stationInfo?.enableStatistics === true) {
404 chargingStation.performanceStatistics?.addRequestStatistic(commandName, messageType);
405 }
406 const messageToSend = this.buildMessageToSend(
407 chargingStation,
408 messageId,
409 messagePayload,
410 messageType,
411 commandName,
1b2acf4e 412 );
1b2acf4e 413 // Check if wsConnection opened
1a32c36b 414 if (chargingStation.isWebSocketConnectionOpened() === true) {
1b2acf4e 415 const beginId = PerformanceStatistics.beginMeasure(commandName);
1a32c36b 416 const sendTimeout = setTimeout(() => {
2b94ad12 417 return handleSendError(
1a32c36b
JB
418 new OCPPError(
419 ErrorType.GENERIC_ERROR,
2b94ad12
JB
420 `Timeout ${formatDurationMilliSeconds(
421 OCPPConstants.OCPP_WEBSOCKET_TIMEOUT,
422 )} reached for ${
423 params?.skipBufferingOnError === false ? '' : 'non '
42b8cf5c 424 }buffered message id '${messageId}' with content '${messageToSend}'`,
1a32c36b 425 commandName,
7375968c 426 (messagePayload as OCPPError).details,
1a32c36b 427 ),
1a32c36b
JB
428 );
429 }, OCPPConstants.OCPP_WEBSOCKET_TIMEOUT);
430 chargingStation.wsConnection?.send(messageToSend, (error?: Error) => {
d42379d8 431 PerformanceStatistics.endMeasure(commandName, beginId);
82fa1110 432 clearTimeout(sendTimeout);
d42379d8
JB
433 if (isNullOrUndefined(error)) {
434 logger.debug(
435 `${chargingStation.logPrefix()} >> Command '${commandName}' sent ${OCPPServiceUtils.getMessageTypeString(
436 messageType,
437 )} payload: ${messageToSend}`,
438 );
439 if (messageType === MessageType.CALL_MESSAGE) {
440 this.cacheRequestPromise(
441 chargingStation,
442 messageId,
443 messagePayload as JsonType,
444 commandName,
445 responseCallback,
446 errorCallback,
447 );
69dae411
JB
448 } else {
449 // Resolve response
d42379d8
JB
450 return resolve(messagePayload);
451 }
452 } else if (error) {
3c80de96
JB
453 return handleSendError(
454 new OCPPError(
455 ErrorType.GENERIC_ERROR,
456 `WebSocket errored for ${
457 params?.skipBufferingOnError === false ? '' : 'non '
458 }buffered message id '${messageId}' with content '${messageToSend}'`,
459 commandName,
460 { name: error.name, message: error.message, stack: error.stack },
461 ),
1a32c36b 462 );
1a32c36b 463 }
1a32c36b 464 });
82fa1110 465 } else {
3c80de96
JB
466 return handleSendError(
467 new OCPPError(
468 ErrorType.GENERIC_ERROR,
469 `WebSocket closed for ${
470 params?.skipBufferingOnError === false ? '' : 'non '
471 }buffered message id '${messageId}' with content '${messageToSend}'`,
472 commandName,
e3fd8f6d 473 (messagePayload as OCPPError).details,
3c80de96 474 ),
9d7b5fa3 475 );
1b2acf4e 476 }
1b2acf4e 477 });
caad9d6b 478 }
e7aeea18
JB
479 throw new OCPPError(
480 ErrorType.SECURITY_ERROR,
05e2446f 481 `Cannot send command ${commandName} PDU when the charging station is in ${chargingStation?.bootNotificationResponse?.status} state on the central server`,
5edd8ba0 482 commandName,
e7aeea18 483 );
c0560973
JB
484 }
485
e7aeea18 486 private buildMessageToSend(
08f130a0 487 chargingStation: ChargingStation,
e7aeea18 488 messageId: string,
5cc4b63b 489 messagePayload: JsonType | OCPPError,
e7aeea18 490 messageType: MessageType,
72092cfc 491 commandName: RequestCommand | IncomingRequestCommand,
e7aeea18 492 ): string {
e7accadb
JB
493 let messageToSend: string;
494 // Type of message
495 switch (messageType) {
496 // Request
497 case MessageType.CALL_MESSAGE:
498 // Build request
291b5ec8 499 this.validateRequestPayload(chargingStation, commandName, messagePayload as JsonType);
b3ec7bc1
JB
500 messageToSend = JSON.stringify([
501 messageType,
502 messageId,
503 commandName,
504 messagePayload,
505 ] as OutgoingRequest);
e7accadb
JB
506 break;
507 // Response
508 case MessageType.CALL_RESULT_MESSAGE:
509 // Build response
02887891
JB
510 this.validateIncomingRequestResponsePayload(
511 chargingStation,
512 commandName,
291b5ec8 513 messagePayload as JsonType,
02887891 514 );
b3ec7bc1 515 messageToSend = JSON.stringify([messageType, messageId, messagePayload] as Response);
e7accadb
JB
516 break;
517 // Error Message
518 case MessageType.CALL_ERROR_MESSAGE:
519 // Build Error Message
e7aeea18
JB
520 messageToSend = JSON.stringify([
521 messageType,
522 messageId,
7375968c
JB
523 (messagePayload as OCPPError).code,
524 (messagePayload as OCPPError).message,
525 (messagePayload as OCPPError).details ?? {
526 command: (messagePayload as OCPPError).command ?? commandName,
527 },
b3ec7bc1 528 ] as ErrorResponse);
e7accadb
JB
529 break;
530 }
531 return messageToSend;
532 }
533
82fa1110
JB
534 private cacheRequestPromise(
535 chargingStation: ChargingStation,
82fa1110
JB
536 messageId: string,
537 messagePayload: JsonType,
538 commandName: RequestCommand | IncomingRequestCommand,
54a8fbc7
JB
539 responseCallback: ResponseCallback,
540 errorCallback: ErrorCallback,
82fa1110
JB
541 ): void {
542 chargingStation.requests.set(messageId, [
543 responseCallback,
544 errorCallback,
545 commandName,
546 messagePayload,
547 ]);
548 }
549
ef6fa3fb 550 // eslint-disable-next-line @typescript-eslint/no-unused-vars
e0b0ee21 551 public abstract requestHandler<ReqType extends JsonType, ResType extends JsonType>(
08f130a0 552 chargingStation: ChargingStation,
94a464f9 553 commandName: RequestCommand,
e1d9a0f4 554 // FIXME: should be ReqType
5cc4b63b 555 commandParams?: JsonType,
5edd8ba0 556 params?: RequestParams,
e0b0ee21 557 ): Promise<ResType>;
c0560973 558}