Files
payload/packages/db-mongodb/src/queries/parseParams.ts
2024-07-11 15:27:01 -04:00

84 lines
2.6 KiB
TypeScript

import type { FilterQuery } from 'mongoose'
import type { Field, Operator, Payload, Where } from 'payload'
import deepmerge from 'deepmerge'
import { combineMerge } from 'payload'
import { validOperators } from 'payload/shared'
import { buildAndOrConditions } from './buildAndOrConditions.js'
import { buildSearchParam } from './buildSearchParams.js'
export async function parseParams({
collectionSlug,
fields,
globalSlug,
locale,
payload,
where,
}: {
collectionSlug?: string
fields: Field[]
globalSlug?: string
locale: string
payload: Payload
where: Where
}): Promise<Record<string, unknown>> {
let result = {} as FilterQuery<any>
if (typeof where === 'object') {
// We need to determine if the whereKey is an AND, OR, or a schema path
for (const relationOrPath of Object.keys(where)) {
const condition = where[relationOrPath]
let conditionOperator: '$and' | '$or'
if (relationOrPath.toLowerCase() === 'and') {
conditionOperator = '$and'
} else if (relationOrPath.toLowerCase() === 'or') {
conditionOperator = '$or'
}
if (Array.isArray(condition)) {
const builtConditions = await buildAndOrConditions({
collectionSlug,
fields,
globalSlug,
locale,
payload,
where: condition,
})
if (builtConditions.length > 0) result[conditionOperator] = builtConditions
} else {
// It's a path - and there can be multiple comparisons on a single path.
// For example - title like 'test' and title not equal to 'tester'
// So we need to loop on keys again here to handle each operator independently
const pathOperators = where[relationOrPath]
if (typeof pathOperators === 'object') {
for (const operator of Object.keys(pathOperators)) {
if (validOperators.includes(operator as Operator)) {
const searchParam = await buildSearchParam({
collectionSlug,
fields,
globalSlug,
incomingPath: relationOrPath,
locale,
operator,
payload,
val: pathOperators[operator],
})
if (searchParam?.value && searchParam?.path) {
result = {
...result,
[searchParam.path]: searchParam.value,
}
} else if (typeof searchParam?.value === 'object') {
result = deepmerge(result, searchParam.value, { arrayMerge: combineMerge })
}
}
}
}
}
}
}
return result
}