Files
payload/packages/drizzle/src/find/findMany.ts
Dan Ribbens 09ad6e4280 feat(drizzle): abstract shared sql code to new package (#7320)
- Abstract shared sql code to a new drizzle package
- Adds sqlite package, not ready to publish until drizzle patches some
issues
- Add `transactionOptions` to allow customizing or disabling db
transactions
- Adds "experimental" label to the `schemaName` property until drizzle
patches an issue
2024-07-24 12:43:29 -04:00

170 lines
3.9 KiB
TypeScript

import type { Field, FindArgs, PayloadRequest, TypeWithID } from 'payload'
import { inArray } from 'drizzle-orm'
import type { DrizzleAdapter } from '../types.js'
import type { ChainedMethods } from './chainMethods.js'
import buildQuery from '../queries/buildQuery.js'
import { selectDistinct } from '../queries/selectDistinct.js'
import { transform } from '../transform/read/index.js'
import { buildFindManyArgs } from './buildFindManyArgs.js'
type Args = {
adapter: DrizzleAdapter
fields: Field[]
tableName: string
} & Omit<FindArgs, 'collection'>
export const findMany = async function find({
adapter,
fields,
limit: limitArg,
locale,
page = 1,
pagination,
req = {} as PayloadRequest,
skip,
sort,
tableName,
where: whereArg,
}: Args) {
const db = adapter.sessions[await req.transactionID]?.db || adapter.drizzle
let limit = limitArg
let totalDocs: number
let totalPages: number
let hasPrevPage: boolean
let hasNextPage: boolean
let pagingCounter: number
const offset = skip || (page - 1) * limit
if (limit === 0) {
limit = undefined
}
const { joins, orderBy, selectFields, where } = await buildQuery({
adapter,
fields,
locale,
sort,
tableName,
where: whereArg,
})
const orderedIDMap: Record<number | string, number> = {}
let orderedIDs: (number | string)[]
const selectDistinctMethods: ChainedMethods = []
if (orderBy?.order && orderBy?.column) {
selectDistinctMethods.push({
args: [orderBy.order(orderBy.column)],
method: 'orderBy',
})
}
const findManyArgs = buildFindManyArgs({
adapter,
depth: 0,
fields,
tableName,
})
selectDistinctMethods.push({ args: [offset], method: 'offset' })
selectDistinctMethods.push({ args: [limit], method: 'limit' })
const selectDistinctResult = await selectDistinct({
adapter,
chainedMethods: selectDistinctMethods,
db,
joins,
selectFields,
tableName,
where,
})
if (selectDistinctResult) {
if (selectDistinctResult.length === 0) {
return {
docs: [],
hasNextPage: false,
hasPrevPage: false,
limit,
nextPage: null,
page: 1,
pagingCounter: 0,
prevPage: null,
totalDocs: 0,
totalPages: 0,
}
} else {
// set the id in an object for sorting later
selectDistinctResult.forEach(({ id }, i) => {
orderedIDMap[id] = i
})
orderedIDs = Object.keys(orderedIDMap)
findManyArgs.where = inArray(adapter.tables[tableName].id, orderedIDs)
}
} else {
findManyArgs.limit = limit
findManyArgs.offset = offset
findManyArgs.orderBy = orderBy.order(orderBy.column)
if (where) {
findManyArgs.where = where
}
}
const findPromise = db.query[tableName].findMany(findManyArgs)
if (pagination !== false && (orderedIDs ? orderedIDs?.length <= limit : true)) {
totalDocs = await adapter.countDistinct({
db,
joins,
tableName,
where,
})
totalPages = typeof limit === 'number' && limit !== 0 ? Math.ceil(totalDocs / limit) : 1
hasPrevPage = page > 1
hasNextPage = totalPages > page
pagingCounter = (page - 1) * limit + 1
}
const rawDocs = await findPromise
// sort rawDocs from selectQuery
if (Object.keys(orderedIDMap).length > 0) {
rawDocs.sort((a, b) => orderedIDMap[a.id] - orderedIDMap[b.id])
}
if (pagination === false || !totalDocs) {
totalDocs = rawDocs.length
totalPages = 1
pagingCounter = 1
hasPrevPage = false
hasNextPage = false
}
const docs = rawDocs.map((data: TypeWithID) => {
return transform({
adapter,
config: adapter.payload.config,
data,
fields,
})
})
return {
docs,
hasNextPage,
hasPrevPage,
limit: limitArg,
nextPage: hasNextPage ? page + 1 : null,
page,
pagingCounter,
prevPage: hasPrevPage ? page - 1 : null,
totalDocs,
totalPages,
}
}