Files
openstapps/src/protocol/route.ts
2022-01-18 09:50:46 +01:00

241 lines
7.3 KiB
TypeScript

/*
* Copyright (C) 2019 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {SCMap} from '../general/map';
import {SCErrorResponse} from './error';
import {SCIndexRequest, SCIndexResponse, SCIndexRoute} from './routes';
import {
SCBookAvailabilityRequest,
SCBookAvailabilityResponse,
SCBookAvailabilityRoute,
} from './routes/book-availability';
import {SCBulkAddRequest, SCBulkAddResponse, SCBulkAddRoute} from './routes/bulk-add';
import {SCBulkDoneRequest, SCBulkDoneResponse, SCBulkDoneRoute} from './routes/bulk-done';
import {SCBulkRequest, SCBulkResponse, SCBulkRoute} from './routes/bulk-request';
import {SCFeedbackRequest, SCFeedbackResponse, SCFeedbackRoute} from './routes/feedback';
import {SCSearchRequest, SCSearchResponse, SCSearchRoute} from './routes/search';
import {SCMultiSearchRequest, SCMultiSearchResponse, SCMultiSearchRoute} from './routes/search-multi';
import {SCThingUpdateRequest, SCThingUpdateResponse, SCThingUpdateRoute} from './routes/thing-update';
/**
* Possible Verbs for HTTP requests
*/
export enum SCRouteHttpVerbs {
GET = 'GET',
POST = 'POST',
PUT = 'PUT',
}
/**
* The constructor of an error response
*/
// tslint:disable-next-line:no-any
export type SCErrorResponseConstructor = new (...args: any[]) => SCErrorResponse;
/**
* A description of a route
*/
export interface SCRoute {
/**
* A map of names of possible errors that can be returned by the route with their appropriate status codes
*/
errorNames: SCErrorResponseConstructor[];
/**
* HTTP verb to use to request the route
*/
method: SCRouteHttpVerbs;
/**
* Map of obligatory parameters and their type that have to be set via the requested path
*/
obligatoryParameters?: SCMap<string>;
/**
* Name of the type of the request body
*/
requestBodyName: string;
/**
* Name of the type of the response body
*/
responseBodyName: string;
/**
* Status code for success
*/
statusCodeSuccess: number;
/**
* URL path of the route
*/
urlPath: string;
}
/**
* An abstract route
*/
export abstract class SCAbstractRoute implements SCRoute {
/**
* @see SCRoute.errorNames
*/
errorNames: SCErrorResponseConstructor[] = [];
/**
* @see SCRoute.method
*/
method: SCRouteHttpVerbs = SCRouteHttpVerbs.GET;
/**
* @see SCRoute.obligatoryParameters
*/
obligatoryParameters?: SCMap<string>;
/**
* @see SCRoute.requestBodyName
*/
requestBodyName = 'any';
/**
* @see SCRoute.responseBodyName
*/
responseBodyName = 'any';
/**
* @see SCRoute.statusCodeSuccess
*/
statusCodeSuccess = 200;
/**
* @see SCRoute.urlPath
*/
urlPath = '/';
/**
* Get "compiled" URL path
*
* @param parameters Parameters to compile URL path with
*/
public getUrlPath(parameters: SCMap<string> = {}): string {
let obligatoryParameters: string[] = [];
if (typeof this.obligatoryParameters === 'object') {
obligatoryParameters = Object.keys(this.obligatoryParameters);
}
if (Object.keys(parameters).length > obligatoryParameters.length) {
throw new Error('Extraneous parameters provided.');
}
return this.urlPath
.split('/')
.map((part) => {
if (part.indexOf(':') !== 0) {
return part;
}
const parameter = part.substr(1);
if (typeof parameters[parameter] === 'undefined') {
throw new Error(`Parameter '${parameter}' not provided.`);
}
return parameters[parameter];
})
.join('/');
}
}
/**
* Possible requests
*/
export type SCRequests =
SCBookAvailabilityRequest
| SCBulkRequest
| SCBulkAddRequest
| SCBulkDoneRequest
| SCFeedbackRequest
| SCIndexRequest
| SCMultiSearchRequest
| SCSearchRequest
| SCThingUpdateRequest;
/**
* Possible responses
*/
export type SCResponses =
SCBookAvailabilityResponse
| SCBulkResponse
| SCBulkAddResponse
| SCBulkDoneResponse
| SCFeedbackResponse
| SCIndexResponse
| SCMultiSearchResponse
| SCSearchResponse
| SCThingUpdateResponse;
/**
* Associated response for a request
*/
export type SCAssociatedResponse<REQUEST> =
REQUEST extends SCBookAvailabilityRequest ? SCBookAvailabilityResponse :
REQUEST extends SCBulkRequest ? SCBulkResponse :
REQUEST extends SCBulkAddRequest ? SCBulkAddResponse :
REQUEST extends SCBulkDoneRequest ? SCBulkDoneResponse :
REQUEST extends SCFeedbackRequest ? SCFeedbackResponse :
REQUEST extends SCIndexRequest ? SCIndexResponse :
REQUEST extends SCMultiSearchRequest ? SCMultiSearchResponse :
REQUEST extends SCSearchRequest ? SCSearchResponse :
REQUEST extends SCThingUpdateRequest ? SCThingUpdateResponse :
never;
/**
* Associated request for a response
*/
export type SCAssociatedRequest<RESPONSE> =
RESPONSE extends SCBookAvailabilityResponse ? SCBookAvailabilityRequest :
RESPONSE extends SCBulkResponse ? SCBulkRequest :
RESPONSE extends SCBulkAddResponse ? SCBulkAddRequest :
RESPONSE extends SCBulkDoneResponse ? SCBulkDoneRequest :
RESPONSE extends SCFeedbackResponse ? SCFeedbackRequest :
RESPONSE extends SCIndexResponse ? SCIndexRequest :
RESPONSE extends SCMultiSearchResponse ? SCMultiSearchRequest :
RESPONSE extends SCSearchResponse ? SCSearchRequest :
RESPONSE extends SCThingUpdateResponse ? SCThingUpdateRequest :
never;
/**
* Associated request for a route
*/
export type SCAssignedRequest<ROUTE extends SCAbstractRoute> =
ROUTE extends SCBookAvailabilityRoute ? SCBookAvailabilityRequest :
ROUTE extends SCBulkRoute ? SCBulkRequest :
ROUTE extends SCBulkAddRoute ? SCBulkAddRequest :
ROUTE extends SCBulkDoneRoute ? SCBulkDoneRequest :
ROUTE extends SCFeedbackRoute ? SCFeedbackRequest :
ROUTE extends SCIndexRoute ? SCIndexRequest :
ROUTE extends SCMultiSearchRoute ? SCMultiSearchRequest :
ROUTE extends SCSearchRoute ? SCSearchRequest :
ROUTE extends SCThingUpdateRoute ? SCThingUpdateRequest :
never;
/**
* Associated response for a route
*/
export type SCAssignedResponse<ROUTE extends SCAbstractRoute> =
ROUTE extends SCBookAvailabilityRoute ? SCBookAvailabilityResponse :
ROUTE extends SCBulkRoute ? SCBulkResponse :
ROUTE extends SCBulkAddRoute ? SCBulkAddResponse :
ROUTE extends SCBulkDoneRoute ? SCBulkDoneResponse :
ROUTE extends SCFeedbackRoute ? SCFeedbackResponse :
ROUTE extends SCIndexRoute ? SCIndexResponse :
ROUTE extends SCMultiSearchRoute ? SCMultiSearchResponse :
ROUTE extends SCSearchRoute ? SCSearchResponse :
ROUTE extends SCThingUpdateRoute ? SCThingUpdateResponse :
never;