// (C) 2007-2021 GoodData Corporation import { Application, Request } from "express"; import { IMockProject } from "../../model/MockProject"; import { IMetadataObject } from "../../model/MetadataObject"; import { getPage } from "../helpers/paging"; import { filterByAuthor, filterByTitle } from "../helpers/filtering"; import { getAuthor, getTitle, getWrappedMetadataObject } from "../helpers/metadataObjects"; import { WrappedMetadataObject } from "../../model"; type URIString = string; function getQueriedObjects( project: IMockProject, category: string, author: string, title: string, ): IMetadataObject[] { const selectors = { visualizationObject: project.visualizationObjects, kpiAlert: project.kpiAlerts, visualizationClass: project.visualizationClasses, dateFilterConfig: [project.dateFilterConfig], }; const filteredByAuthor = filterByAuthor(author, getAuthor, selectors[category]); return filterByTitle(title, getTitle, filteredByAuthor); } interface IObjectQueryResponse { objects: { items: WrappedMetadataObject[]; paging: { offset: number; count: number; totalCount?: number; next?: URIString; }; }; } const KNOWN_CATEGORIES = ["visualizationobject", "kpialert", "visualizationclass", "datefilterconfig"]; // in lowercase !!! function isUnknownCategory(category: string): boolean { return KNOWN_CATEGORIES.indexOf(category.toLowerCase()) === -1; } function validate(req: Request) { const category: string = req.query.category as string; if (isUnknownCategory(category)) { throw new Error("Uknown category"); } } function isNextLinkRequired(items: IMetadataObject[], offset: number, limit: number): boolean { return items.slice(offset + limit).length > 0; } function getNextLink(req: Request, offset: number, limit: number): string { const queryParams = { ...req.query, offset: offset + limit }; const queryString = Object.keys(queryParams) .map(key => `${key}=${encodeURIComponent(queryParams[key])}`) .join("&"); return `${req.path}?${queryString}`; } export const objects = { register(app: Application, project: IMockProject): Application { app.get(`/gdc/md/${project.project.meta.identifier}/objects/query`, (req, res) => { try { validate(req); const offset: number = Number(req.query.offset) || 0; const limit: number = Number(req.query.limit) || 50; const items = getQueriedObjects( project, req.query.category as string, req.query.author as string, req.query.title as string, ); const paged = getPage(items, offset, limit); const body: IObjectQueryResponse = { objects: { items: paged.map(getWrappedMetadataObject), paging: { offset, count: paged.length, }, }, }; if (req.query.getTotalCount) { body.objects.paging.totalCount = items.length; } if (isNextLinkRequired(items, offset, limit)) { body.objects.paging.next = getNextLink(req, offset, limit); } res.status(200).json(body); } catch { res.status(404).end(); } }); return app; }, };