import * as api from '../../client/src/api'; import { EndpointError, EndpointHandler, catchUnhandledErrors } from './types'; import Knex from 'knex'; async function getChildrenRecursive(id: number, trx: any) { const directChildren = (await trx.select('id') .from('tags') .where({ 'parentId': id })).map((r: any) => r.id); const indirectChildrenPromises = directChildren.map( (child: number) => getChildrenRecursive(child, trx) ); const indirectChildrenNested = await Promise.all(indirectChildrenPromises); const indirectChildren = indirectChildrenNested.flat(); return [ ...directChildren, ...indirectChildren, ] } export const DeleteTagEndpointHandler: EndpointHandler = async (req: any, res: any, knex: Knex) => { if (!api.checkDeleteTagRequest(req)) { const e: EndpointError = { internalMessage: 'Invalid DeleteTag request: ' + JSON.stringify(req.body), httpStatus: 400 }; throw e; } const reqObject: api.DeleteTagRequest = req.body; console.log("Delete Tag:", reqObject); await knex.transaction(async (trx) => { try { // Start retrieving any child tags. const childTagsPromise = getChildrenRecursive(req.params.id, trx); // Start retrieving the tag itself. const tagPromise = trx.select('id') .from('tags') .where({ id: req.params.id }) .then((r: any) => (r && r[0]) ? r[0]['id'] : undefined) // Wait for the requests to finish. var [tag, children] = await Promise.all([tagPromise, childTagsPromise]); // Merge all IDs. const toDelete = [ tag, ...children ]; console.log ("deleting tags: ", toDelete); // Check that we found all objects we need. if (!tag) { const e: EndpointError = { internalMessage: 'Tag or parent does not exist for DeleteTag request: ' + JSON.stringify(req.body), httpStatus: 400 }; throw e; } // Delete the tag and its children. await trx('tags') .whereIn('id', toDelete) .del(); // Respond to the request. res.status(200).send(); } catch (e) { catchUnhandledErrors(e); trx.rollback(); } }) }