import { Request, Response } from 'express'; import { DyFM_Error, DyFM_HttpCallType, DyFM_Metadata, DyFM_SearchResult, DyFM_StringCase } from '@futdevpro/fsm-dynamo'; import { DyNTS_DataService } from '../../../_services/base/data.service'; import { DyNTS_Endpoint_Params } from '../../../_models/control-models/endpoint-params.control-model'; import { DyNTS_global_settings } from '../../../_collections/global-settings.const'; /** * Alapértelmezett endpoint-ok létrehozásához használt utility class. * Az Organizer Modules mintáját követve generálja a standard CRUD endpoint-okat. * * @see {@link DyNTS_Controller} - A controller-ben használható a setupEndpoints metódusban */ export class DyNTS_DefaultEndpoints_Util { /** * GET endpoint létrehozása egy adott ID alapján történő adatlekéréshez. * * @param set.entityName - Az entitás neve (pl. "Task", "Note"), * ebből generálódik az endpoint neve és az ID paraméter neve * @param set.dataServiceClass - A DataService osztály konstruktora * @param set.endpointPath - Az endpoint path (pl. '/:userId/task/get/:taskId') * @param set.authService - Az auth service, amely tartalmazza az * authenticate_tokenSelf metódust * @param set.idParamName - Az ID paraméter neve a request-ben * (opcionális, alapértelmezetten: {entityName.toLowerCase()}Id) * @returns DyNTS_Endpoint_Params instance a GET endpoint-hoz * * @example * ```typescript * const getEndpoint = DyNTS_DefaultEndpoints_Util.getGetEndpoint({ * entityName: 'Task', * dataServiceClass: Task_DataService, * endpointPath: FDP_organizerApiEnv_endpoints.tasks.task.getTask, * authService: this.auth_CS, * }); * ``` */ static getGetEndpoint( set: { entityName: string; dataServiceClass: new (set: { data?: T_Data; issuer: string }) => DyNTS_DataService; endpointPath: string; authService: { authenticate_tokenSelf: (req: Request, res: Response) => Promise }; idParamName?: string; } ): DyNTS_Endpoint_Params { const idParamName: string = set.idParamName ?? `${set.entityName.toLowerCase()}Id`; const endpointName: string = `get${set.entityName}`; if (!set.endpointPath.includes(`:${idParamName}`)) { throw new DyFM_Error({ status: 406, errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DEU-GE0`, message: `endpoint path does not contain the ID parameter: ${idParamName}`, }); } if (!set.endpointPath.includes(`:userId`)) { throw new DyFM_Error({ status: 406, errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DEU-GME0`, message: `endpoint path does not contain the user ID parameter: userId`, }); } return new DyNTS_Endpoint_Params({ name: endpointName, type: DyFM_HttpCallType.get, endpoint: set.endpointPath, preProcesses: [set.authService.authenticate_tokenSelf], tasks: [ async (req: Request, res: Response, issuer: string): Promise => { const dataService: DyNTS_DataService = new set.dataServiceClass({ issuer: issuer, }); const data: T_Data = await dataService.getDataById(req.params[idParamName]); res.send(dataService.getProvidedData(data)); }, ], }); } static getGetMyEndpoint( set: { entityName: string; dataServiceClass: new (set: { data?: T_Data; issuer: string }) => DyNTS_DataService; endpointPath: string; authService: { authenticate_tokenSelf: (req: Request, res: Response) => Promise }; } ): DyNTS_Endpoint_Params { const endpointName: string = `getMy${set.entityName}s`; if (!set.endpointPath.includes(`:userId`)) { throw new DyFM_Error({ status: 406, errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DEU-GME0`, message: `endpoint path does not contain the user ID parameter: userId`, }); } return new DyNTS_Endpoint_Params({ name: endpointName, type: DyFM_HttpCallType.get, endpoint: set.endpointPath, preProcesses: [set.authService.authenticate_tokenSelf], tasks: [ async (req: Request, res: Response, issuer: string): Promise => { const dataService: DyNTS_DataService = new set.dataServiceClass({ issuer: issuer, }); const dataList: T_Data[] = await dataService.getDataListByDependencyId({ userId: req.params.userId }); res.send(dataService.getProvidedDataList(dataList)); }, ], }); } /** * POST endpoint létrehozása adatok kereséséhez. * * @param set.entityName - Az entitás neve (pl. "Task", "Note"), * ebből generálódik az endpoint neve * @param set.dataServiceClass - A DataService osztály konstruktora * @param set.endpointPath - Az endpoint path (pl. '/:userId/tasks/search') * @param set.authService - Az auth service, amely tartalmazza az * authenticate_tokenSelf metódust * @returns DyNTS_Endpoint_Params instance a POST search endpoint-hoz * * @example * ```typescript * const searchEndpoint = DyNTS_DefaultEndpoints_Util.getSearchEndpoint({ * entityName: 'Task', * dataServiceClass: Task_DataService, * endpointPath: FDP_organizerApiEnv_endpoints.tasks.task.searchTasks, * authService: this.auth_CS, * }); * ``` */ static getSearchEndpoint( set: { entityName: string; dataServiceClass: new (set: { data?: T_Data; issuer: string }) => DyNTS_DataService; endpointPath: string; authService: { authenticate_tokenSelf: (req: Request, res: Response) => Promise }; } ): DyNTS_Endpoint_Params { const endpointName: string = `search${set.entityName}s`; if (!set.endpointPath.includes(`:userId`)) { throw new DyFM_Error({ status: 406, errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DEU-SE0`, message: `endpoint path does not contain the user ID parameter: userId`, }); } return new DyNTS_Endpoint_Params({ name: endpointName, type: DyFM_HttpCallType.post, endpoint: set.endpointPath, preProcesses: [set.authService.authenticate_tokenSelf], tasks: [ async (req: Request, res: Response, issuer: string): Promise => { const dataService: DyNTS_DataService = new set.dataServiceClass({ issuer: issuer, }); const searchResults: DyFM_SearchResult = await dataService.searchData(req.body); searchResults.results = dataService.getProvidedDataList(searchResults.results); res.send(searchResults); }, ], }); } /** * POST endpoint létrehozása adatok módosításához vagy létrehozásához. * A modify végpontok mindig create végpontok is egyben. * * @param set.entityName - Az entitás neve (pl. "Task", "Note"), * ebből generálódik az endpoint neve * @param set.dataServiceClass - A DataService osztály konstruktora * @param set.endpointPath - Az endpoint path (pl. '/:userId/task/modify') * @param set.authService - Az auth service, amely tartalmazza az * authenticate_tokenSelf metódust * @returns DyNTS_Endpoint_Params instance a POST modify endpoint-hoz * * @example * ```typescript * const modifyEndpoint = DyNTS_DefaultEndpoints_Util.getModifyEndpoint({ * entityName: 'Task', * dataServiceClass: Task_DataService, * endpointPath: FDP_organizerApiEnv_endpoints.tasks.task.modifyTask, * authService: this.auth_CS, * }); * ``` */ static getModifyEndpoint( set: { entityName: string; dataServiceClass: new (set: { data?: T_Data; issuer: string }) => DyNTS_DataService; endpointPath: string; authService: { authenticate_tokenSelf: (req: Request, res: Response) => Promise }; } ): DyNTS_Endpoint_Params { const endpointName: string = `modify${set.entityName}`; if (!set.endpointPath.includes(`:userId`)) { throw new DyFM_Error({ status: 406, errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DEU-ME0`, message: `endpoint path does not contain the user ID parameter: userId`, }); } return new DyNTS_Endpoint_Params({ name: endpointName, type: DyFM_HttpCallType.post, endpoint: set.endpointPath, preProcesses: [set.authService.authenticate_tokenSelf], tasks: [ async (req: Request, res: Response, issuer: string): Promise => { const dataService: DyNTS_DataService = new set.dataServiceClass({ issuer: issuer, }); const data: T_Data = await dataService.saveData(req.body); res.send(dataService.getProvidedData(data)); }, ], }); } /** * DELETE endpoint létrehozása egy adott ID alapján történő adattörléshez. * * @param set.entityName - Az entitás neve (pl. "Task", "Note"), * ebből generálódik az endpoint neve és az ID paraméter neve * @param set.dataServiceClass - A DataService osztály konstruktora * @param set.endpointPath - Az endpoint path (pl. '/:userId/task/delete/:taskId') * @param set.authService - Az auth service, amely tartalmazza az * authenticate_tokenSelf metódust * @param set.idParamName - Az ID paraméter neve a request-ben * (opcionális, alapértelmezetten: {entityName.toLowerCase()}Id) * @returns DyNTS_Endpoint_Params instance a DELETE endpoint-hoz * * @example * ```typescript * const deleteEndpoint = DyNTS_DefaultEndpoints_Util.getDeleteEndpoint({ * entityName: 'Task', * dataServiceClass: Task_DataService, * endpointPath: FDP_organizerApiEnv_endpoints.tasks.task.deleteTask, * authService: this.auth_CS, * }); * ``` */ static getDeleteEndpoint( set: { entityName: string; dataServiceClass: new (set: { data?: T_Data; issuer: string }) => DyNTS_DataService; endpointPath: string; authService: { authenticate_tokenSelf: (req: Request, res: Response) => Promise }; idParamName?: string; } ): DyNTS_Endpoint_Params { const idParamName: string = set.idParamName ?? `${set.entityName.toLowerCase()}Id`; const endpointName: string = `delete${set.entityName}`; // Ellenőrizzük a casing-ignore módon, hogy az endpoint path tartalmazza-e az ID paramétert if (!DyFM_StringCase.includesIgnoreCase(set.endpointPath, idParamName)) { throw new DyFM_Error({ status: 406, errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DEU-DE0`, message: `endpoint path does not contain the ID parameter: ${idParamName}`, }); } if (!set.endpointPath.includes(`:userId`)) { throw new DyFM_Error({ status: 406, errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DEU-DE0`, message: `endpoint path does not contain the user ID parameter: userId`, }); } return new DyNTS_Endpoint_Params({ name: endpointName, type: DyFM_HttpCallType.delete, endpoint: set.endpointPath, preProcesses: [set.authService.authenticate_tokenSelf], tasks: [ async (req: Request, res: Response, issuer: string): Promise => { const dataService: DyNTS_DataService = new set.dataServiceClass({ issuer: issuer, }); await dataService.deleteData(req.params[idParamName]); res.send({ result: 'deleted' }); }, ], }); } /** * PATCH endpoint létrehozása részleges adatmódosításhoz. * A PATCH endpoint csak a megadott mezőket módosítja, nem cseréli le az egész objektumot. * * @param set.entityName - Az entitás neve (pl. "Task", "Note"), * ebből generálódik az endpoint neve * @param set.dataServiceClass - A DataService osztály konstruktora * @param set.endpointPath - Az endpoint path (pl. '/:userId/task/patch') * @param set.authService - Az auth service, amely tartalmazza az * authenticate_tokenSelf metódust * @returns DyNTS_Endpoint_Params instance a PATCH endpoint-hoz * * @example * ```typescript * const patchEndpoint = DyNTS_DefaultEndpoints_Util.getPatchEndpoint({ * entityName: 'Task', * dataServiceClass: Task_DataService, * endpointPath: '/:userId/task/patch', * authService: this.auth_CS, * }); * ``` */ static getPatchEndpoint( set: { entityName: string; dataServiceClass: new (set: { data?: T_Data; issuer: string }) => DyNTS_DataService; endpointPath: string; authService: { authenticate_tokenSelf: (req: Request, res: Response) => Promise }; } ): DyNTS_Endpoint_Params { const endpointName: string = `patch${set.entityName}`; if (!set.endpointPath.includes(`:userId`)) { throw new DyFM_Error({ status: 406, errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DEU-PE0`, message: `endpoint path does not contain the user ID parameter: userId`, }); } return new DyNTS_Endpoint_Params({ name: endpointName, type: DyFM_HttpCallType.patch, endpoint: set.endpointPath, preProcesses: [set.authService.authenticate_tokenSelf], tasks: [ async (req: Request, res: Response, issuer: string): Promise => { const dataService: DyNTS_DataService = new set.dataServiceClass({ issuer: issuer, }); const data: T_Data = await dataService.patchData(req.body); res.send(dataService.getProvidedData(data)); }, ], }); } /** * Összes alapértelmezett endpoint létrehozása egy lépésben. * Visszaadja a GET, SEARCH, MODIFY, PATCH és DELETE endpoint-okat egy tömbben. * * @param set.entityName - Az entitás neve (pl. "Task", "Note") * @param set.dataServiceClass - A DataService osztály konstruktora * @param set.endpoints - Az endpoint path-ek objektuma * @param set.endpoints.get - GET endpoint path * @param set.endpoints.search - SEARCH endpoint path * @param set.endpoints.modify - MODIFY endpoint path * @param set.endpoints.patch - PATCH endpoint path (opcionális) * @param set.endpoints.delete - DELETE endpoint path * @param set.authService - Az auth service, amely tartalmazza az * authenticate_tokenSelf metódust * @param set.idParamName - Az ID paraméter neve a request-ben * (opcionális, alapértelmezetten: {entityName.toLowerCase()}Id) * @returns DyNTS_Endpoint_Params tömb az összes alapértelmezett endpoint-tal * * @example * ```typescript * setupEndpoints(): void { * this.endpoints = [ * ...DyNTS_DefaultEndpoints_Util.getAllDefaultEndpoints({ * entityName: 'Task', * dataServiceClass: Task_DataService, * endpoints: { * get: FDP_organizerApiEnv_endpoints.tasks.task.getTask, * search: FDP_organizerApiEnv_endpoints.tasks.task.searchTasks, * modify: FDP_organizerApiEnv_endpoints.tasks.task.modifyTask, * patch: '/:userId/task/patch', * delete: FDP_organizerApiEnv_endpoints.tasks.task.deleteTask, * }, * authService: this.auth_CS, * }), * ]; * } * ``` */ static getAllDefaultEndpoints( set: { entityName: string; dataServiceClass: new (set: { data?: T_Data; issuer: string }) => DyNTS_DataService; endpoints: { get?: string; getMy?: string; search?: string; modify: string; patch?: string; delete?: string; }; authService: { authenticate_tokenSelf: (req: Request, res: Response) => Promise }; idParamName?: string; } ): DyNTS_Endpoint_Params[] { const endpoints: DyNTS_Endpoint_Params[] = []; if (set.endpoints.get) { endpoints.push(this.getGetEndpoint({ entityName: set.entityName, dataServiceClass: set.dataServiceClass, endpointPath: set.endpoints.get, authService: set.authService, idParamName: set.idParamName, })); } if (set.endpoints.getMy) { endpoints.push(this.getGetMyEndpoint({ entityName: set.entityName, dataServiceClass: set.dataServiceClass, endpointPath: set.endpoints.getMy, authService: set.authService, })); } if (set.endpoints.search) { endpoints.push(this.getSearchEndpoint({ entityName: set.entityName, dataServiceClass: set.dataServiceClass, endpointPath: set.endpoints.search, authService: set.authService, })); } if (set.endpoints.modify) { endpoints.push(this.getModifyEndpoint({ entityName: set.entityName, dataServiceClass: set.dataServiceClass, endpointPath: set.endpoints.modify, authService: set.authService, })); } if (set.endpoints.patch) { endpoints.push(this.getPatchEndpoint({ entityName: set.entityName, dataServiceClass: set.dataServiceClass, endpointPath: set.endpoints.patch, authService: set.authService, })); } if (set.endpoints.delete) { endpoints.push(this.getDeleteEndpoint({ entityName: set.entityName, dataServiceClass: set.dataServiceClass, endpointPath: set.endpoints.delete, authService: set.authService, idParamName: set.idParamName, })); } return endpoints; } }