import type { Application, Params } from '@feathersjs/feathers' import type { KeyOf } from '../../internal.utils.js' import type { InferFindParams, InferFindResultSingle, } from '../../utility-types/infer-service-methods.js' type PaginateOption = { default?: number; max?: number } type ChunkFindOptions

= { params?: P & { paginate?: PaginateOption } } /** * Use `for await` to iterate over chunks (pages) of results from a `find` method. * * This function is useful for processing large datasets in batches without loading everything into memory at once. * It uses pagination to fetch results in chunks, yielding each page's data array. * * @example * ```ts * import { chunkFind } from 'feathers-utils/utils' * * const app = feathers() * * // Assuming 'users' service has many records * for await (const users of chunkFind(app, 'users', { * params: { query: { active: true }, // Custom query parameters * } })) { * console.log(users) // Process each chunk of user records * } * ``` * * @see https://utils.feathersjs.com/utils/chunk-find.html */ export async function* chunkFind< Services, Path extends KeyOf, Service extends Services[Path] = Services[Path], P extends Params = InferFindParams, Item = InferFindResultSingle, >( app: Application, servicePath: Path, options?: ChunkFindOptions

, ): AsyncGenerator { const service = app.service(servicePath) if (!service || !('find' in service)) { throw new Error(`Service '${servicePath}' does not have a 'find' method.`) } const params = { ...options?.params, query: { ...(options?.params?.query ?? {}), $limit: options?.params?.query?.$limit ?? 10, $skip: options?.params?.query?.$skip ?? 0, }, paginate: { default: options?.params?.paginate?.default ?? 10, max: options?.params?.paginate?.max ?? 100, }, } let result do { result = await (service as any).find(params) // Guard against an infinite loop: an empty page never advances $skip, so // `total > $skip` could stay true forever (e.g. $limit:0, or a stale total // when items are concurrently removed / filtered out by hooks). if (!result.data.length) { break } yield result.data params.query.$skip = (params.query.$skip ?? 0) + result.data.length } while (result.total > params.query.$skip) }