import type { Query as PiniaOrmQuery } from 'pinia-orm' import type { ApiFilter } from '~/types/data' import type ApiResource from '~/models/ApiResource' import PageFilter from '~/services/data/Filters/PageFilter' import OrderBy from '~/services/data/Filters/OrderBy' /** * A Query to filter and sort ApiResources. * Pass it to the `fetchCollection` method of the EntityManager to apply these filters to both * API fetch and PiniaOrm query, which allow to maintain this collection reactivity. */ export default class Query { protected filters: Array = [] constructor(...filters: Array) { this.filters = filters } /** * Add an ApiFilter to the query * * @param filter */ public add(filter: ApiFilter): this { this.filters.push(filter) return this } /** * Clear the query filters */ public clear(): this { this.filters = [] return this } /** * Returns the URL's query in the Api Platform format. * * @see https://api-platform.com/docs/core/filters/ */ public getUrlQuery(): string { const queryParts: string[] = [] this.filters.forEach((filter) => { const queryPart = filter.getApiQueryPart() if (queryPart) { queryParts.push(queryPart) } }) return queryParts.filter((p) => !!p).join('&') } /** * Apply this query to the pinia orm query and return it. * * @see https://pinia-orm.codedredd.de/guide/repository/retrieving-data * @param query */ public applyToPiniaOrmQuery( query: PiniaOrmQuery, ): PiniaOrmQuery { // 'Where' filters shall be applied first, then orderBy filters, and finally pagination const where: ApiFilter[] = [] const orderBy: ApiFilter[] = [] const pagination: ApiFilter[] = [] this.filters.forEach((filter) => { if (filter instanceof PageFilter) { pagination.push(filter) } else if (filter instanceof OrderBy) { orderBy.push(filter) } else { where.push(filter) } }) const filters = [...where, ...orderBy, ...pagination] filters.forEach((filter) => { query = filter.applyToPiniaOrmQuery(query) }) return query } }