import SQL , { SQLStatement } from 'sql-template-strings' ; import { Query } from 'express-serve-static-core' ; import { DbConnectionType } from '../db' ; import { InvalidRequestError } from '../errors' ; export interface ListRequest { limit ? : number ; offset ? : number ; where ? : SQLStatement ; } export interface ListResponse < Item > extends ListRequest { items : Item [ ] ; total : number ; } export type ListItemsGetter < Item > = ( conn : DbConnectionType , options : ListRequest ) => Promise < Item [ ] > ; export type ListTotalGetter = ( conn : DbConnectionType ) => Promise < number > ; export async function getListAsListResponse < Item > ( conn , options , itemsGetter , totalGetter ) { const [ items , total ] = await Promise . all ( [ itemsGetter ( conn , options ) , totalGetter ( conn ) , ] ) ; const { limit , offset } = options ; return { items , total , limit , offset } ; } export function listResponseFactory < Item > ( itemsGetter , totalGetter ) { return async ( conn , options ) => await getListAsListResponse ( conn , options , itemsGetter , totalGetter ) ; } export function listOptionsFromQuery ( query , defaultLimit = 25 , defaultOffset = 0 ) { const { limit : limitStr = defaultLimit , offset : offsetStr = defaultOffset , } = query ; const limit = + limitStr ; const offset = + offsetStr ; if ( isNaN ( limit ) ) throw new InvalidRequestError ( `limit must be a number.` ) ; if ( isNaN ( offset ) ) throw new InvalidRequestError ( `offset must be a number.` ) ; return { limit , offset } ; } export function addListRequestToQuery ( query , request ) { if ( typeof request . limit === 'number' ) query . append ( SQL `\nLIMIT ${ request . limit }` ) ; if ( typeof request . offset === 'number' ) query . append ( SQL `\nOFFSET ${ request . offset }` ) ; return query ; }