Skip to content

Commit

Permalink
Merge branch 'rc-1.5.0' into feature/49-adding-type-definitions-to-op…
Browse files Browse the repository at this point in the history
…enapi-spec

Signed-off-by: Thana Paris <83840862+thanaParis@users.noreply.github.com>
  • Loading branch information
thanaParis authored Nov 7, 2024
2 parents c8e4b33 + db60045 commit a2247a6
Show file tree
Hide file tree
Showing 35 changed files with 774 additions and 61 deletions.
1 change: 1 addition & 0 deletions 00_Base/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,4 @@ export { assert, notNull, deepDirectionalEqual } from './assertion/assertion';
export { UnauthorizedError } from './interfaces/api/exception/UnauthorizedError';
export { AuthorizationSecurity } from './interfaces/api/AuthorizationSecurity';
export { Ajv };
export declare type Constructable<T> = new (...args: any[]) => T;
40 changes: 26 additions & 14 deletions 00_Base/src/interfaces/api/AbstractModuleApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ import {
METADATA_DATA_ENDPOINTS,
METADATA_MESSAGE_ENDPOINTS,
} from '.';
import { OcppRequest, OcppResponse, SystemConfig } from '../..';
import { OcppRequest, SystemConfig } from '../..';
import { Namespace } from '../../ocpp/persistence';
import { CallAction } from '../../ocpp/rpc/message';
import { IMessageConfirmation } from '../messages';
import { IModule } from '../modules';
import {
IMessageQuerystring,
IMessageQuerystringSchema,
} from './MessageQuerystring';
import { IModuleApi } from './ModuleApi';
Expand All @@ -29,8 +28,7 @@ import { AuthorizationSecurity } from './AuthorizationSecurity';
* Abstract module api class implementation.
*/
export abstract class AbstractModuleApi<T extends IModule>
implements IModuleApi
{
implements IModuleApi {
protected readonly _server: FastifyInstance;
protected readonly _module: T;
protected readonly _logger: Logger<ILogObj>;
Expand Down Expand Up @@ -62,6 +60,7 @@ export abstract class AbstractModuleApi<T extends IModule>
expose.action,
expose.method,
expose.bodySchema,
expose.optionalQuerystrings,
);
});
(
Expand Down Expand Up @@ -111,12 +110,14 @@ export abstract class AbstractModuleApi<T extends IModule>
* @param {CallAction} action - The action to be called.
* @param {Function} method - The method to be executed.
* @param {object} bodySchema - The schema for the route.
* @param {Record<string, any>} optionalQuerystrings - Optional querystrings for the route.
* @return {void}
*/
protected _addMessageRoute(
action: CallAction,
method: (...args: any[]) => any,
bodySchema: object,
optionalQuerystrings?: Record<string, any>
): void {
this._logger.debug(
`Adding message route for ${action}`,
Expand All @@ -126,28 +127,39 @@ export abstract class AbstractModuleApi<T extends IModule>
/**
* Executes the handler function for the given request.
*
* @param {FastifyRequest<{ Body: OcppRequest | OcppResponse, Querystring: IMessageQuerystring }>} request - The request object containing the body and querystring.
* @param {FastifyRequest<{ Body: OcppRequest, Querystring: IMessageQuerystring }>} request - The request object containing the body and querystring.
* @return {Promise<IMessageConfirmation>} The promise that resolves to the message confirmation.
*/
const _handler = async (
request: FastifyRequest<{
Body: OcppRequest | OcppResponse;
Querystring: IMessageQuerystring;
Body: OcppRequest;
Querystring: Record<string, any>;
}>,
): Promise<IMessageConfirmation> =>
method.call(
): Promise<IMessageConfirmation> => {
const { identifier, tenantId, callbackUrl, ...extraQueries } = request.query;
return method.call(
this,
request.query.identifier,
request.query.tenantId,
identifier,
tenantId,
request.body,
request.query.callbackUrl,
callbackUrl,
Object.keys(extraQueries).length > 0 ? extraQueries : undefined,
);
}

const mergedQuerySchema = {
...IMessageQuerystringSchema,
properties: {
...IMessageQuerystringSchema.properties,
...(optionalQuerystrings || {}),
},
};

const _opts = {
schema: {
body: bodySchema,
querystring: IMessageQuerystringSchema,
},
querystring: mergedQuerySchema,
} as const,
};

if (this._module.config.util.swagger?.exposeMessage) {
Expand Down
2 changes: 2 additions & 0 deletions 00_Base/src/interfaces/api/AsMessageEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { CallAction } from '../../ocpp/rpc/message';
export const AsMessageEndpoint = function (
action: CallAction,
bodySchema: object,
optionalQuerystrings?: Record<string, any>
) {
return (
target: any,
Expand All @@ -38,6 +39,7 @@ export const AsMessageEndpoint = function (
method: descriptor.value,
methodName: propertyKey,
bodySchema: bodySchema,
optionalQuerystrings: optionalQuerystrings
});
Reflect.defineMetadata(
METADATA_MESSAGE_ENDPOINTS,
Expand Down
1 change: 1 addition & 0 deletions 00_Base/src/interfaces/api/MessageEndpointDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export interface IMessageEndpointDefinition {
method: (...args: any[]) => any;
methodName: string;
bodySchema: object;
optionalQuerystrings?: Record<string, any>;
}
10 changes: 10 additions & 0 deletions 00_Base/src/interfaces/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ export abstract class CrudRepository<T> extends EventEmitter {
return result;
}

public async bulkCreate(
values: T[],
clazz: any, // todo: should Model be in base so it can be used here?
): Promise<T[]> {
const result = await this._bulkCreate(values, clazz);
this.emit('created', result);
return result;
}

/**
* Creates a new entry in the database with the specified value and key.
* If a namespace is provided, the entry will be created within that namespace.
Expand Down Expand Up @@ -250,6 +259,7 @@ export abstract class CrudRepository<T> extends EventEmitter {
abstract existByQuery(query: object, namespace?: string): Promise<number>;

protected abstract _create(value: T, namespace?: string): Promise<T>;
protected abstract _bulkCreate(value: T[], namespace?: string): Promise<T[]>;

protected abstract _createByKey(
value: T,
Expand Down
23 changes: 20 additions & 3 deletions 00_Base/src/ocpp/persistence/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ export { default as ReportDataTypeSchema } from './schemas/ReportDataTypeSchema.
export { default as SetVariableResultTypeSchema } from './schemas/SetVariableResultTypeSchema.json';
export { default as UpdateChargingStationPasswordSchema } from './schemas/UpdateChargingStationPasswordRequestSchema.json';

/**
* Utility function for creating querystring schemas for fastify route definitions
* @param properties An array of key-type pairs. Types ending in '[]' will be treated as arrays of that type.
* @param required An array of required keys.
* @returns
*/
export function QuerySchema(
name: string,
properties: [string, string][],
Expand All @@ -22,9 +28,20 @@ export function QuerySchema(
properties: {},
};
properties.forEach((property: [string, string]) => {
(schema['properties'] as Record<string, string | object>)[property[0]] = {
type: property[1],
};
const [key, type] = property;

// '[]' denotes an array
if (type.endsWith('[]')) {
(schema['properties'] as Record<string, object>)[key] = {
type: 'array',
items: { type: type.slice(0, -2) }, // Remove '[]' to get the base type
};
} else {
// non-array types
(schema['properties'] as Record<string, string | object>)[key] = {
type,
};
}
});
if (required) {
schema['required'] = required;
Expand Down
8 changes: 5 additions & 3 deletions 00_Base/src/ocpp/persistence/namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export enum Namespace {
AuthorizationRestrictions = 'AuthorizationRestrictions',
BootConfig = 'Boot',
Certificate = 'Certificate',
InstalledCertificate = 'InstalledCertificate',
CertificateChain = 'CertificateChain',
ChargingNeeds = 'ChargingNeeds',
ChargingProfile = 'ChargingProfile',
Expand All @@ -24,18 +25,20 @@ export enum Namespace {
EventDataType = 'EventData',
IdTokenInfoType = 'IdTokenInfo',
IdTokenType = 'IdToken',
LatestStatusNotification = 'LatestStatusNotification',
LocalListAuthorization = 'LocalListAuthorization',
LocalListVersion = 'LocalListVersion',
Location = 'Location',
MeterValueType = 'MeterValue',
MessageInfoType = 'MessageInfo',
PasswordType = 'Password',
ReserveNowRequest = 'Reservation',
RootCertificate = 'RootCertificate',
SalesTariff = 'SalesTariff',
SecurityEventNotificationRequest = 'SecurityEvent',
SendLocalListRequest = 'SendLocalList',
ServerNetworkProfile = 'ServerNetworkProfile',
StatusNotificationRequest = 'StatusNotification',
LatestStatusNotification = 'LatestStatusNotification',
Subscription = 'Subscription',
SystemConfig = 'SystemConfig',
TlsCertificates = 'TlsCertificates',
Expand All @@ -47,6 +50,5 @@ export enum Namespace {
VariableMonitoringType = 'VariableMonitoring',
VariableMonitoringStatus = 'VariableMonitoringStatus',
VariableStatus = 'VariableStatus',
VariableType = 'Variable',
PasswordType = 'Password',
VariableType = 'Variable'
}
6 changes: 6 additions & 0 deletions 01_Data/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// SPDX-License-Identifier: Apache 2.0

import { Transaction as SequelizeTransaction } from 'sequelize';

export { SequelizeTransaction };
export { IdTokenAdditionalInfo } from './layers/sequelize/model/Authorization/IdTokenAdditionalInfo';
export * as sequelize from './layers/sequelize';
Expand Down Expand Up @@ -31,6 +32,7 @@ export {
VariableCharacteristics,
VariableStatus,
Certificate,
InstalledCertificate,
CountryNameEnumType,
TransactionEvent,
IdToken,
Expand All @@ -39,13 +41,17 @@ export {
LocalListAuthorization,
LocalListVersion,
SendLocalList,
ServerNetworkProfile,
SetNetworkProfile,
StatusNotification,
ChargingStationSecurityInfo,
ChargingStationNetworkProfile,
SignatureAlgorithmEnumType,
SequelizeAuthorizationRepository,
SequelizeBootRepository,
SequelizeCallMessageRepository,
SequelizeCertificateRepository,
SequelizeInstalledCertificateRepository,
SequelizeChargingProfileRepository,
SequelizeChargingStationSecurityInfoRepository,
SequelizeDeviceModelRepository,
Expand Down
1 change: 1 addition & 0 deletions 01_Data/src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export { AuthorizationQuerystring, AuthorizationQuerySchema } from './queries/Au
export { TransactionEventQuerystring, TransactionEventQuerySchema } from './queries/TransactionEvent';
export { TariffQueryString, TariffQuerySchema } from './queries/Tariff';
export { ModelKeyQuerystring, ModelKeyQuerystringSchema } from './queries/Model';
export { NetworkProfileQuerystring, NetworkProfileQuerySchema, NetworkProfileDeleteQuerystring, NetworkProfileDeleteQuerySchema } from './queries/NetworkProfile';
export { UpdateTlsCertificateQueryString, TlsCertificateSchema, UpdateTlsCertificateQuerySchema } from './queries/TlsCertificate';
export { GenerateCertificateChainSchema, InstallRootCertificateSchema } from './queries/RootCertificate';
export { CreateSubscriptionSchema } from './queries/Subscription';
Expand Down
25 changes: 25 additions & 0 deletions 01_Data/src/interfaces/queries/NetworkProfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) 2023 S44, LLC
// Copyright Contributors to the CitrineOS Project
//
// SPDX-License-Identifier: Apache 2.0

import { QuerySchema } from '@citrineos/base';

export interface NetworkProfileQuerystring {
stationId: string;
}

export const NetworkProfileQuerySchema = QuerySchema([['stationId', 'string']], ['stationId']);

Check failure on line 12 in 01_Data/src/interfaces/queries/NetworkProfile.ts

View workflow job for this annotation

GitHub Actions / jest-tests

Argument of type 'string[][]' is not assignable to parameter of type 'string'.

export interface NetworkProfileDeleteQuerystring {
stationId: string;
configurationSlot: number[];
}

export const NetworkProfileDeleteQuerySchema = QuerySchema(
[

Check failure on line 20 in 01_Data/src/interfaces/queries/NetworkProfile.ts

View workflow job for this annotation

GitHub Actions / jest-tests

Argument of type 'string[][]' is not assignable to parameter of type 'string'.
['stationId', 'string'],
['configurationSlot', 'number[]']
],
['stationId', 'configurationSlot']
);
Loading

0 comments on commit a2247a6

Please sign in to comment.