import * as api from '../../client/src/api'; import { EndpointError, EndpointHandler, catchUnhandledErrors } from './types'; enum QueryType { Song = 0, Artist, Tag, } // const sequelizeOps: any = { // [api.QueryFilterOp.Eq]: Op.eq, // [api.QueryFilterOp.Ne]: Op.ne, // [api.QueryFilterOp.In]: Op.in, // [api.QueryFilterOp.NotIn]: Op.notIn, // [api.QueryFilterOp.Like]: Op.like, // [api.QueryElemOp.And]: Op.and, // [api.QueryElemOp.Or]: Op.or, // }; // const sequelizeProps: any = { // [QueryType.Song]: { // [api.QueryElemProperty.songTitle]: "title", // [api.QueryElemProperty.songId]: "id", // [api.QueryElemProperty.artistName]: "$Artists.name$", // [api.QueryElemProperty.artistId]: "$Artists.id$", // [api.QueryElemProperty.albumName]: "$Albums.name$", // }, // [QueryType.Artist]: { // [api.QueryElemProperty.songTitle]: "$Songs.title$", // [api.QueryElemProperty.songId]: "$Songs.id$", // [api.QueryElemProperty.artistName]: "name", // [api.QueryElemProperty.artistId]: "id", // [api.QueryElemProperty.albumName]: "$Albums.name$", // }, // [QueryType.Tag]: { // [api.QueryElemProperty.songTitle]: "$Songs.title$", // [api.QueryElemProperty.songId]: "$Songs.id$", // [api.QueryElemProperty.artistName]: "$Artists.name$", // [api.QueryElemProperty.artistId]: "$Artists.id$", // [api.QueryElemProperty.albumName]: "$Albums.name$", // } // }; // const sequelizeOrderColumns: any = { // [QueryType.Song]: { // [api.OrderByType.Name]: 'title', // [api.OrderByType.ArtistRanking]: '$Rankings.rank$', // [api.OrderByType.TagRanking]: '$Rankings.rank$', // }, // [QueryType.Artist]: { // [api.OrderByType.Name]: 'name' // }, // [QueryType.Tag]: { // [api.OrderByType.Name]: 'name' // }, // } // // Returns the "where" clauses for Sequelize, per object type. // const getSequelizeWhere = (queryElem: api.QueryElem, type: QueryType) => { // var where: any = { // [Op.and]: [] // }; // if (queryElem.prop && queryElem.propOperator && queryElem.propOperand) { // // Visit a filter-like subquery leaf. // where[Op.and].push({ // [sequelizeProps[type][queryElem.prop]]: { // [sequelizeOps[queryElem.propOperator]]: queryElem.propOperand // } // }); // } // if (queryElem.childrenOperator && queryElem.children) { // // Recursively visit a nested subquery. // const children = queryElem.children.map((child: api.QueryElem) => getSequelizeWhere(child, type)); // where[Op.and].push({ // [sequelizeOps[queryElem.childrenOperator]]: children // }); // } // return where; // } // function getSequelizeOrder(order: api.Ordering, type: QueryType) { // const ascstring = order.ascending ? 'ASC' : 'DESC'; // return [ // [ sequelizeOrderColumns[type][order.orderBy.type], ascstring ] // ]; // } export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any) => { if (!api.checkQueryRequest(req.body)) { const e: EndpointError = { internalMessage: 'Invalid Query request: ' + JSON.stringify(req.body), httpStatus: 400 }; throw e; } const reqObject: api.QueryRequest = req.body; // try { // const songLimit = reqObject.offsetsLimits.songLimit; // const songOffset = reqObject.offsetsLimits.songOffset; // const tagLimit = reqObject.offsetsLimits.tagLimit; // const tagOffset = reqObject.offsetsLimits.tagOffset; // const artistLimit = reqObject.offsetsLimits.artistLimit; // const artistOffset = reqObject.offsetsLimits.artistOffset; // const songs = (songLimit && songLimit > 0) && await models.Song.findAll({ // // NOTE: have to disable limit and offset because of bug: https://github.com/sequelize/sequelize/issues/11938. // // Custom pagination is implemented before responding. // where: getSequelizeWhere(reqObject.query, QueryType.Song), // order: getSequelizeOrder(reqObject.ordering, QueryType.Song), // include: [ models.Artist, models.Album, models.Tag, models.Ranking ], // //limit: reqObject.limit, // //offset: reqObject.offset, // }) // const artists = (artistLimit && artistLimit > 0) && await models.Artist.findAll({ // // NOTE: have to disable limit and offset because of bug: https://github.com/sequelize/sequelize/issues/11938. // // Custom pagination is implemented before responding. // where: getSequelizeWhere(reqObject.query, QueryType.Artist), // order: getSequelizeOrder(reqObject.ordering, QueryType.Artist), // include: [models.Song, models.Album, models.Tag], // //limit: reqObject.limit, // //offset: reqObject.offset, // }) // const tags = (tagLimit && tagLimit > 0) && await models.Tag.findAll({ // // NOTE: have to disable limit and offset because of bug: https://github.com/sequelize/sequelize/issues/11938. // // Custom pagination is implemented before responding. // where: getSequelizeWhere(reqObject.query, QueryType.Tag), // order: getSequelizeOrder(reqObject.ordering, QueryType.Tag), // include: [models.Song, models.Album, models.Artist], // //limit: reqObject.limit, // //offset: reqObject.offset, // }) // const response: api.QueryResponse = { // songs: ((songLimit || -1) <= 0) ? [] : await Promise.all(songs.map(async (song: any) => { // const artists = song.getArtists(); // const tags = song.getTags(); // const rankings = song.getRankings(); // return { // songId: song.id, // title: song.title, // storeLinks: song.storeLinks, // artists: (await artists).map((artist: any) => { // return { // artistId: artist.id, // name: artist.name, // } // }), // tags: (await tags).map((tag: any) => { // return { // tagId: tag.id, // name: tag.name, // } // }), // rankings: await (await rankings).map(async (ranking: any) => { // const maybeTagContext: api.TagDetails | undefined = await ranking.getTagContext(); // const maybeArtistContext: api.ArtistDetails | undefined = await ranking.getArtistContext(); // const maybeContext = maybeTagContext || maybeArtistContext; // return { // rankingId: ranking.id, // type: api.ItemType.Song, // rankedId: song.id, // context: maybeContext, // value: ranking.value, // } // }) // }; // }).slice(songOffset || 0, (songOffset || 0) + (songLimit || 10))), // // TODO: custom pagination due to bug mentioned above // artists: ((artistLimit || -1) <= 0) ? [] : await Promise.all(artists.map(async (artist: any) => { // return { // artistId: artist.id, // name: artist.name, // }; // }).slice(artistOffset || 0, (artistOffset || 0) + (artistLimit || 10))), // tags: ((tagLimit || -1) <= 0) ? [] : await Promise.all(tags.map(async (tag: any) => { // return { // tagId: tag.id, // name: tag.name, // }; // }).slice(tagOffset || 0, (tagOffset || 0) + (tagLimit || 10))), // }; // res.send(response); // } catch (e) { // catchUnhandledErrors(e); // } throw "NOTIMPLEMENTED"; }