build: temporary silence linter errors
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / OCPPResponseService.ts
1 import Ajv, { type JSONSchemaType, type ValidateFunction } from 'ajv';
2 import ajvFormats from 'ajv-formats';
3
4 import { OCPPServiceUtils } from './OCPPServiceUtils.js';
5 import type { ChargingStation } from '../../charging-station/index.js';
6 import { OCPPError } from '../../exception/index.js';
7 import type {
8 IncomingRequestCommand,
9 JsonType,
10 OCPPVersion,
11 RequestCommand,
12 } from '../../types/index.js';
13 import { logger } from '../../utils/index.js';
14
15 const moduleName = 'OCPPResponseService';
16
17 export abstract class OCPPResponseService {
18 private static instance: OCPPResponseService | null = null;
19
20 public jsonIncomingRequestResponseValidateFunctions: Map<
21 IncomingRequestCommand,
22 ValidateFunction<JsonType>
23 >;
24
25 private readonly version: OCPPVersion;
26 private readonly ajv: Ajv;
27 private jsonRequestValidateFunctions: Map<RequestCommand, ValidateFunction<JsonType>>;
28
29 public abstract jsonIncomingRequestResponseSchemas: Map<
30 IncomingRequestCommand,
31 JSONSchemaType<JsonType>
32 >;
33
34 protected constructor(version: OCPPVersion) {
35 this.version = version;
36 // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
37 this.ajv = new Ajv({
38 keywords: ['javaType'],
39 multipleOfPrecision: 2,
40 });
41 ajvFormats(this.ajv);
42 this.jsonRequestValidateFunctions = new Map<RequestCommand, ValidateFunction<JsonType>>();
43 this.jsonIncomingRequestResponseValidateFunctions = new Map<
44 IncomingRequestCommand,
45 ValidateFunction<JsonType>
46 >();
47 this.responseHandler = this.responseHandler.bind(this) as <
48 ReqType extends JsonType,
49 ResType extends JsonType,
50 >(
51 chargingStation: ChargingStation,
52 commandName: RequestCommand,
53 payload: ResType,
54 requestPayload: ReqType,
55 ) => Promise<void>;
56 this.validateResponsePayload = this.validateResponsePayload.bind(this) as <T extends JsonType>(
57 chargingStation: ChargingStation,
58 commandName: RequestCommand,
59 schema: JSONSchemaType<T>,
60 payload: T,
61 ) => boolean;
62 }
63
64 public static getInstance<T extends OCPPResponseService>(this: new () => T): T {
65 if (OCPPResponseService.instance === null) {
66 OCPPResponseService.instance = new this();
67 }
68 return OCPPResponseService.instance as T;
69 }
70
71 protected validateResponsePayload<T extends JsonType>(
72 chargingStation: ChargingStation,
73 commandName: RequestCommand,
74 schema: JSONSchemaType<T>,
75 payload: T,
76 ): boolean {
77 if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
78 return true;
79 }
80 const validate = this.getJsonRequestValidateFunction<T>(commandName, schema);
81 if (validate(payload)) {
82 return true;
83 }
84 logger.error(
85 `${chargingStation.logPrefix()} ${moduleName}.validateResponsePayload: Command '${commandName}' response PDU is invalid: %j`,
86 validate.errors,
87 );
88 throw new OCPPError(
89 OCPPServiceUtils.ajvErrorsToErrorType(validate.errors),
90 'Response PDU is invalid',
91 commandName,
92 JSON.stringify(validate.errors, undefined, 2),
93 );
94 }
95
96 protected emptyResponseHandler() {
97 /* This is intentional */
98 }
99
100 private getJsonRequestValidateFunction<T extends JsonType>(
101 commandName: RequestCommand,
102 schema: JSONSchemaType<T>,
103 ) {
104 if (this.jsonRequestValidateFunctions.has(commandName) === false) {
105 // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
106 this.jsonRequestValidateFunctions.set(commandName, this.ajv.compile<T>(schema).bind(this));
107 }
108 return this.jsonRequestValidateFunctions.get(commandName)!;
109 }
110
111 public abstract responseHandler<ReqType extends JsonType, ResType extends JsonType>(
112 chargingStation: ChargingStation,
113 commandName: RequestCommand,
114 payload: ResType,
115 requestPayload: ReqType,
116 ): Promise<void>;
117 }