import { Request, Response } from "express" import { handleError } from "./http" import { LoadController, ViewService } from "./LoadController" import { Attribute, Attributes } from "./metadata" import { resources } from "./resources" import { buildArray, Filter, format, fromRequest, getMetadataFunc, getParameters, initializeConfig, jsonResult, SearchConfig, SearchResult } from "./search" export interface Search { search(req: Request, res: Response): void load(req: Request, res: Response): void } export interface Query extends ViewService { search: (s: S, limit: number, page?: number | string, fields?: string[]) => Promise> metadata?(): Attributes | undefined load(id: ID, ctx?: any): Promise } export interface SearchManager { search(req: Request, res: Response): void load(req: Request, res: Response): void } export function useSearchController( find: (s: S, limit: number, page?: number | string, fields?: string[]) => Promise>, viewService: ViewService | ((id: ID, ctx?: any) => Promise), array?: string[], dates?: string[], numbers?: string[], keys?: Attributes | Attribute[] | string[], config?: SearchConfig | boolean, ): Search { const c = new LoadSearchController(find, viewService, keys, config, dates, numbers) c.array = array return c } export const useSearchHandler = useSearchController export const createSearchController = useSearchController export const createSearchHandler = useSearchController export class LoadSearchController extends LoadController { config?: SearchConfig csv?: boolean dates?: string[] numbers?: string[] excluding?: string array?: string[] constructor( public find: (s: S, limit: number, page?: number | string, fields?: string[]) => Promise>, viewService: ViewService | ((id: ID, ctx?: any) => Promise), keys?: Attributes | Attribute[] | string[], config?: SearchConfig | boolean, dates?: string[], numbers?: string[], ) { super(viewService, keys) this.search = this.search.bind(this) if (config) { if (typeof config === "boolean") { this.csv = config } else { this.config = initializeConfig(config) if (this.config) { this.csv = this.config.csv this.excluding = this.config.excluding } } } const m = getMetadataFunc(viewService, dates, numbers, keys) if (m) { this.dates = m.dates this.numbers = m.numbers } } search(req: Request, res: Response): void { const s = fromRequest(req, buildArray(this.array, resources.fields, this.excluding)) const l = getParameters(s) const s2 = format(s, this.dates, this.numbers) this.find(s2, l.limit, l.pageOrNextPageToken, l.fields) .then((result) => jsonResult(res, result, this.csv, l.fields, this.config)) .catch((err) => handleError(err, res)) } } export class QueryController extends LoadController { config?: SearchConfig csv?: boolean dates?: string[] numbers?: string[] excluding?: string array?: string[] constructor( protected query: Query, config?: SearchConfig | boolean, dates?: string[], numbers?: string[], array?: string[], ) { super(query) this.search = this.search.bind(this) this.array = array if (config) { if (typeof config === "boolean") { this.csv = config } else { this.config = initializeConfig(config) if (this.config) { this.csv = this.config.csv this.excluding = this.config.excluding } } } const m = getMetadataFunc(query, dates, numbers) if (m) { this.dates = m.dates this.numbers = m.numbers } } search(req: Request, res: Response): void { const s = fromRequest(req, buildArray(this.array, resources.fields, this.excluding)) const l = getParameters(s) const s2 = format(s, this.dates, this.numbers) this.query .search(s2, l.limit, l.pageOrNextPageToken, l.fields) .then((result) => jsonResult(res, result, this.csv, l.fields, this.config)) .catch((err) => handleError(err, res)) } } export { QueryController as QueryHandler }