Query.ts 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import type { Query as PiniaOrmQuery } from 'pinia-orm'
  2. import type { ApiFilter } from '~/types/data'
  3. import type ApiResource from '~/models/ApiResource'
  4. import PageFilter from '~/services/data/Filters/PageFilter'
  5. import OrderBy from '~/services/data/Filters/OrderBy'
  6. /**
  7. * A Query to filter and sort ApiResources.
  8. * Pass it to the `fetchCollection` method of the EntityManager to apply these filters to both
  9. * API fetch and PiniaOrm query, which allow to maintain this collection reactivity.
  10. */
  11. export default class Query {
  12. protected filters: Array<ApiFilter> = []
  13. constructor(...filters: Array<ApiFilter>) {
  14. this.filters = filters
  15. }
  16. /**
  17. * Add an ApiFilter to the query
  18. *
  19. * @param filter
  20. */
  21. public add(filter: ApiFilter): this {
  22. this.filters.push(filter)
  23. return this
  24. }
  25. /**
  26. * Returns the URL's query in the Api Platform format.
  27. *
  28. * @see https://api-platform.com/docs/core/filters/
  29. */
  30. public getUrlQuery(): string {
  31. const queryParts: string[] = []
  32. this.filters.forEach((filter) => {
  33. const queryPart = filter.getApiQueryPart()
  34. if (queryPart) {
  35. queryParts.push(queryPart)
  36. }
  37. })
  38. return queryParts.filter((p) => !!p).join('&')
  39. }
  40. /**
  41. * Apply this query to the pinia orm query and return it.
  42. *
  43. * @see https://pinia-orm.codedredd.de/guide/repository/retrieving-data
  44. * @param query
  45. */
  46. public applyToPiniaOrmQuery(
  47. query: PiniaOrmQuery<ApiResource>,
  48. ): PiniaOrmQuery<ApiResource> {
  49. // 'Where' filters shall be applied first, then orderBy filters, and finally pagination
  50. const where: ApiFilter[] = []
  51. const orderBy: ApiFilter[] = []
  52. const pagination: ApiFilter[] = []
  53. this.filters.forEach((filter) => {
  54. if (filter instanceof PageFilter) {
  55. pagination.push(filter)
  56. } else if (filter instanceof OrderBy) {
  57. orderBy.push(filter)
  58. } else {
  59. where.push(filter)
  60. }
  61. })
  62. const filters = [...where, ...orderBy, ...pagination]
  63. filters.forEach((filter) => {
  64. query = filter.applyToPiniaOrmQuery(query)
  65. })
  66. return query
  67. }
  68. }