build: properly workaround Ajv TS type definitions bug
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / OCPPResponseService.ts
CommitLineData
f5a1ff8c
JB
1import _Ajv, { type JSONSchemaType, type ValidateFunction } from 'ajv';
2import _ajvFormats from 'ajv-formats';
844e496b 3
a6ef1ece
JB
4import { OCPPServiceUtils } from './OCPPServiceUtils.js';
5import type { ChargingStation } from '../../charging-station/index.js';
6import { OCPPError } from '../../exception/index.js';
7import type {
8 IncomingRequestCommand,
9 JsonType,
10 OCPPVersion,
11 RequestCommand,
12} from '../../types/index.js';
13import { logger } from '../../utils/index.js';
f5a1ff8c
JB
14type Ajv = _Ajv.default;
15const Ajv = _Ajv.default;
16const ajvFormats = _ajvFormats.default;
c0560973 17
e3018bc4
JB
18const moduleName = 'OCPPResponseService';
19
268a74bb 20export abstract class OCPPResponseService {
08f130a0 21 private static instance: OCPPResponseService | null = null;
ec0eebcc
JB
22
23 public jsonIncomingRequestResponseValidateFunctions: Map<
24 IncomingRequestCommand,
291b5ec8 25 ValidateFunction<JsonType>
ec0eebcc
JB
26 >;
27
d270cc87 28 private readonly version: OCPPVersion;
012ae1a9 29 private readonly ajv: Ajv;
291b5ec8 30 private jsonRequestValidateFunctions: Map<RequestCommand, ValidateFunction<JsonType>>;
ec0eebcc 31
b3fc3ff5
JB
32 public abstract jsonIncomingRequestResponseSchemas: Map<
33 IncomingRequestCommand,
291b5ec8 34 JSONSchemaType<JsonType>
b3fc3ff5 35 >;
10068088 36
d270cc87
JB
37 protected constructor(version: OCPPVersion) {
38 this.version = version;
45988780 39 this.ajv = new Ajv({
98fc1389 40 keywords: ['javaType'],
45988780
JB
41 multipleOfPrecision: 2,
42 });
844e496b 43 ajvFormats(this.ajv);
291b5ec8 44 this.jsonRequestValidateFunctions = new Map<RequestCommand, ValidateFunction<JsonType>>();
ec0eebcc
JB
45 this.jsonIncomingRequestResponseValidateFunctions = new Map<
46 IncomingRequestCommand,
291b5ec8 47 ValidateFunction<JsonType>
ec0eebcc 48 >();
9429aa42
JB
49 this.responseHandler = this.responseHandler.bind(this) as <
50 ReqType extends JsonType,
51 ResType extends JsonType,
52 >(
31f59c6d
JB
53 chargingStation: ChargingStation,
54 commandName: RequestCommand,
9429aa42
JB
55 payload: ResType,
56 requestPayload: ReqType,
31f59c6d
JB
57 ) => Promise<void>;
58 this.validateResponsePayload = this.validateResponsePayload.bind(this) as <T extends JsonType>(
59 chargingStation: ChargingStation,
60 commandName: RequestCommand,
61 schema: JSONSchemaType<T>,
5edd8ba0 62 payload: T,
31f59c6d 63 ) => boolean;
c0560973
JB
64 }
65
08f130a0 66 public static getInstance<T extends OCPPResponseService>(this: new () => T): T {
1ca780f9 67 if (OCPPResponseService.instance === null) {
08f130a0 68 OCPPResponseService.instance = new this();
9f2e3130 69 }
08f130a0 70 return OCPPResponseService.instance as T;
9f2e3130
JB
71 }
72
844e496b
JB
73 protected validateResponsePayload<T extends JsonType>(
74 chargingStation: ChargingStation,
75 commandName: RequestCommand,
76 schema: JSONSchemaType<T>,
5edd8ba0 77 payload: T,
844e496b 78 ): boolean {
5398cecf 79 if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
844e496b
JB
80 return true;
81 }
0b0ca54f 82 const validate = this.getJsonRequestValidateFunction<T>(commandName, schema);
844e496b
JB
83 if (validate(payload)) {
84 return true;
85 }
86 logger.error(
45988780 87 `${chargingStation.logPrefix()} ${moduleName}.validateResponsePayload: Command '${commandName}' response PDU is invalid: %j`,
5edd8ba0 88 validate.errors,
844e496b
JB
89 );
90 throw new OCPPError(
9ff486f4 91 OCPPServiceUtils.ajvErrorsToErrorType(validate.errors),
844e496b
JB
92 'Response PDU is invalid',
93 commandName,
4ed03b6e 94 JSON.stringify(validate.errors, undefined, 2),
844e496b
JB
95 );
96 }
97
81e3cc38 98 protected emptyResponseHandler() {
bd770dde 99 /* This is intentional */
81e3cc38 100 }
b52c969d 101
0b0ca54f
JB
102 private getJsonRequestValidateFunction<T extends JsonType>(
103 commandName: RequestCommand,
104 schema: JSONSchemaType<T>,
105 ) {
106 if (this.jsonRequestValidateFunctions.has(commandName) === false) {
107 this.jsonRequestValidateFunctions.set(commandName, this.ajv.compile<T>(schema).bind(this));
108 }
109 return this.jsonRequestValidateFunctions.get(commandName)!;
110 }
111
9429aa42 112 public abstract responseHandler<ReqType extends JsonType, ResType extends JsonType>(
08f130a0 113 chargingStation: ChargingStation,
e7aeea18 114 commandName: RequestCommand,
9429aa42
JB
115 payload: ResType,
116 requestPayload: ReqType,
e7aeea18 117 ): Promise<void>;
c0560973 118}