import { Request, Response, Router } from 'express'; import { http } from '@sapphirecode/consts'; import { ControlModel, DatabaseModel } from '@sapphirecode/modelling'; import { CrudHandler } from './CrudHandler'; import { HttpHandler } from './HttpHandler'; import { DatabaseCrudOptionsReader } from './DatabaseCrudOptionsReader'; import { DatabaseCrudOptions } from './DatabaseCrudOptions'; export class DatabaseCrudHandler extends HttpHandler implements CrudHandler { protected cm: new (object: Record) => ControlModel; protected dm: new (id?: number) => DatabaseModel; protected options: DatabaseCrudOptionsReader; public constructor ( cm: new (object: Record) => ControlModel, dm: new (id?: number) => DatabaseModel, options: DatabaseCrudOptions = {} ) { super (); this.cm = cm; this.dm = dm; this.options = new DatabaseCrudOptionsReader (options); } protected validate_body ( req: Request, res: Response ): Promise | null> | Record | null { if (typeof req.body === 'undefined') { res.status (http.status_bad_request); res.end ('body was undefined'); return null; } try { return JSON.parse (req.body); } catch (e) { res.status (http.status_bad_request); res.end ('invalid json input'); } return null; } public async create (req: Request, res: Response): Promise { if (!await this.options.create_authorization (req, res)) return; const body_data = await this.validate_body (req, res); if (body_data === null) return; const cm = new this.cm (body_data as Record); cm.update (); const dm = new this.dm; dm.assign (cm); await dm.write (); res.status (http.status_created) .end (dm.id); } public async read (req: Request, res: Response): Promise { if (!await this.options.read_authorization (req, res)) return; if (typeof req.headers.id === 'undefined') { res.status (http.status_bad_request) .end ('id undefined'); return; } const dm = new this.dm (parseInt (req.headers.id as string)); const found = await dm.read (); const cm = new this.cm (dm.get_data ()); cm.update (); res.status (found ? http.status_ok : http.status_not_found) .json (cm.get_data ()); } public async update (req: Request, res: Response): Promise { if (!await this.options.update_authorization (req, res)) return; const body_data = await this.validate_body (req, res); if (body_data === null) return; if (typeof req.headers.id === 'undefined') { res.status (http.status_bad_request) .end ('id undefined'); return; } const dm = new this.dm (parseInt (req.headers.id as string)); const found = await dm.read (); if (!found) { res.status (http.status_not_found) .end (); return; } const cm = new this.cm (dm.get_data ()); cm.update (); cm.assign_object (body_data); cm.update (); dm.assign (cm); const written = await dm.write (); res.status (written ? http.status_ok : http.status_internal_server_error) .end (); } public async delete (req: Request, res: Response): Promise { if (!await this.options.delete_authorization (req, res)) return; if (typeof req.headers.id === 'undefined') { res.status (http.status_bad_request) .end ('id undefined'); return; } const dm = new this.dm (parseInt (req.headers.id as string)); const found = await dm.read (); if (!found) { res.status (http.status_not_found) .end (); return; } const deleted = await dm.delete (); res.status (deleted ? http.status_ok : http.status_internal_server_error) .end (); } protected async create_or_update ( req: Request, res: Response ): Promise { if (typeof req.headers.id === 'undefined') await this.create (req, res); else await this.update (req, res); } public register_handlers (router: Router): void { router.post ('/', this.create_or_update); router.get ('/', this.read); router.delete ('/', this.delete); } }