UNPKG

popurelate

Version:

Easily populate and filter documents using data from related collections.

237 lines (236 loc) 9.54 kB
import { OptimizerHints } from "./optimizer"; import { PipeLineIsHelper } from "./optimizer/is"; interface DefaultEngines { name: string; } interface DefaultDb { modelName: string; } export interface Populeration<Engines extends DefaultEngines, Db extends DefaultDb> { addEngine: AddEngineFn<Engines, Db>; addDb: AddDbFn<Engines, Db>; addRelation: AddRelationsFn<Engines, Db>; model: <ModelName extends Db["modelName"]>(modelName: ModelName) => ModelQueryBuilder<ModelName, Engines, Db>; getModelsByEngine: (engineName: Engines["name"]) => Record<Db["modelName"], any>; getModelsByDb: (db: any) => Record<Db["modelName"], any>; newQueryBuilder: <Fn extends (queryBuilder: QueryBuilder<any, ModelName, Engines, Db>) => QueryBuilder<any, ModelName, Engines, Db>, ModelName extends Db["modelName"] = Db["modelName"]>(fn: Fn) => Fn; } interface ModelQueryBuilder<ModelName extends Db["modelName"], Engines extends DefaultEngines, Db extends DefaultDb> { findMany: <Doc = any>(query?: FilterQuery) => QueryBuilder<Doc[], ModelName, Engines, Db> & Promise<Doc[]>; findOne: <Doc = any>(query?: FilterQuery) => QueryBuilder<Doc, ModelName, Engines, Db>; fillPopulations: (populationObject: Populate<Db>) => FilledPopulations<Db>; } export interface AggregatorOptions extends IOptions<any> { db: any; model: any; } export interface EngineInfo<Name> { name: Name; aggregator: (options: AggregatorOptions) => Promise<any>; transformModelName?: ({ modelName, model, db, }: { modelName: string; model: any; db: any; }) => string; optimizer?: (useOptimizer: boolean, options: AggregatorOptions) => AggregatorOptions; useOptimizer?: boolean; pipeLineIsHelper?: PipeLineIsHelper; } interface AddEngineFn<Engines extends DefaultEngines, Db extends DefaultDb> { <EngineName extends string>(engine: EngineInfo<EngineName>): Populeration<Engines | { name: EngineName; }, Db>; } interface DbInfo<Engine, ModelNames extends string> { engine: Engine; db: any; idField: string; defaultRequired: boolean; models: Record<ModelNames, any>; } interface AddDbFn<Engines extends DefaultEngines, Db extends DefaultDb> { <ModelNames extends string>(options: DbInfo<Engines["name"], ModelNames>): Populeration<Engines, Db | { modelName: ModelNames; }>; } interface ModelThroughRelation<Db extends DefaultDb> { name: Db["modelName"]; model1Field: string; model2Field: string; } declare type ModelRelationsObject<Db extends DefaultDb> = { [field in string]: RelationOptions<Db> | Db["modelName"]; }; interface AddRelationsFn<Engines extends DefaultEngines, Db extends DefaultDb> { (modelName: Db["modelName"], relations: ModelRelationsObject<Db>): Populeration<Engines, Db>; } export declare function createPopurelation(): Populeration<never, never>; declare type AllProps = "query" | "sort" | "limit" | "skip" | "populate" | "project" | "withCount" | "rawPipeline" | "invisible" | "addFields" | "count"; declare type NullifyOthers<T> = T & { [key in Exclude<AllProps, keyof T>]?: undefined; }; export declare type QueryPipeline = NullifyOthers<{ query: FilterQuery; }>; export declare type SortPipeline = NullifyOthers<{ sort: SortQuery; }>; export declare type LimitPipeline = NullifyOthers<{ limit: number; }>; export declare type SkipPipeline = NullifyOthers<{ skip: number; }>; export declare type PopulatePipeline = NullifyOthers<{ parentIdField: string; myIdField: string; field: string; populate: PopulatePipelineOptions; }>; export declare type ProjectPipeline = NullifyOthers<{ project: Project; }>; export declare type WithCountPipeline = NullifyOthers<{ withCount: true; countKey: string; docsKey: string; docsPipelines: Pipeline[]; }>; export declare type RawPipeline = NullifyOthers<{ rawPipeline: any; }>; export declare type AddFieldsPipeline = NullifyOthers<{ addFields: AddFields; }>; export declare type CountPipeline = NullifyOthers<{ count: true; countKey: string; }>; export declare type OptimizerPipeline = NullifyOthers<{ invisible: true; optimizer: true; useOptimizer: boolean | undefined; hints: Partial<OptimizerHints> | undefined; }>; export declare type Pipeline = QueryPipeline | SortPipeline | LimitPipeline | SkipPipeline | PopulatePipeline | ProjectPipeline | WithCountPipeline | RawPipeline | AddFieldsPipeline | CountPipeline | OptimizerPipeline; interface IOptions<ModelName = any> { readonly modelName: ModelName; readonly transformedModelName: string; readonly findOne: boolean; readonly pipelines: Pipeline[]; } declare type FilterQuery = { [key in string]?: any; }; declare type Project = { [key in string]?: any; }; declare type SortQuery = { [key in string]?: any; }; declare type AddFields = { [key in string]?: any; }; export interface PopulatePipelineOptions { required: boolean; matchesMany: boolean; modelName: string; transformedModelName: string; alreadyPopulated?: boolean; foreignField: string; through?: ModelThroughRelation<any>; localField: string; globalPathPrefix: string; localPathPrefix: string; children?: Record<string, PopulatePipeline>; } interface PopulateOptions<Db extends DefaultDb> { required?: boolean; matchesMany?: boolean; model?: Db["modelName"]; /** * @deprecated Not supported yet */ through?: ModelThroughRelation<Db>; localField?: string; foreignField?: string; populate?: Populate<Db>; } export interface FilledPopulateOptions<Db extends DefaultDb> { required: boolean; matchesMany: boolean; model: Db["modelName"]; /** * @deprecated Not supported yet */ through?: ModelThroughRelation<Db>; localField: string; foreignField: string; populate?: FilledPopulations<Db>; } export declare type FilledPopulations<Db extends DefaultDb = DefaultDb> = Record<string, FilledPopulateOptions<Db>>; export interface RelationOptions<Db extends DefaultDb> { required?: boolean; matchesMany: boolean; model: Db["modelName"]; /** * @deprecated Not supported yet */ through?: ModelThroughRelation<Db>; localField?: string; foreignField?: string; } declare type Populate<Db extends DefaultDb> = { [key in string]: 1 | true | PopulateOptions<Db>; }; declare type WithCount<Doc, CountKey extends string = "count", DocsKey extends string = "docs"> = { [count in CountKey]: number; } & { [docs in DocsKey]: Doc; }; export interface QueryBuilder<Doc = any, ModelName = any, Engines extends DefaultEngines = any, Db extends DefaultDb = any> { where: (query?: FilterQuery) => QueryBuilder<Doc, ModelName, Engines, Db>; project: (project: Project) => QueryBuilder<Doc, ModelName, Engines, Db>; populate: { (field: string): QueryBuilder<Doc, ModelName, Engines, Db>; (field: string, options: PopulateOptions<Db>): QueryBuilder<Doc, ModelName, Engines, Db>; (bulkPopulate: Populate<Db>): QueryBuilder<Doc, ModelName, Engines, Db>; }; sort: (sort?: SortQuery) => QueryBuilder<Doc, ModelName, Engines, Db>; limit: (number?: number) => QueryBuilder<Doc, ModelName, Engines, Db>; skip: (number?: number) => QueryBuilder<Doc, ModelName, Engines, Db>; withCount: { <CountKey extends string, DocsKey extends string, NewDoc = Doc>(keys: { countKey: CountKey; docsKey: DocsKey; skip?: number; limit?: number; queryBuilder?: (queryBuilder: QueryBuilder<Doc, ModelName, Engines, Db>) => QueryBuilder<NewDoc, ModelName, Engines, Db>; }): QueryBuilder<WithCount<NewDoc, CountKey, DocsKey>, ModelName, Engines, Db>; <NewDoc = Doc>(keys: { skip?: number; limit?: number; queryBuilder?: (queryBuilder: QueryBuilder<Doc, ModelName, Engines, Db>) => QueryBuilder<NewDoc, ModelName, Engines, Db>; }): QueryBuilder<WithCount<NewDoc>, ModelName, Engines, Db>; (include?: true): QueryBuilder<WithCount<Doc>, ModelName, Engines, Db>; (include: false): QueryBuilder<Doc, ModelName, Engines, Db>; }; rawPipeline: (pipeline: any) => QueryBuilder<Doc, ModelName, Engines, Db>; addFields: (newFields?: AddFields) => QueryBuilder<Doc, ModelName, Engines, Db>; count: () => QueryBuilder<{ count: number; }, ModelName, Engines, Db>; as: <T>() => QueryBuilder<T, ModelName, Engines, Db>; queryBuilder: <Fn extends ((queryBuilder: QueryBuilder<any, ModelName, Engines, Db>) => QueryBuilder<any, ModelName, Engines, Db>) | undefined | null>(fn: Fn) => Fn extends undefined ? QueryBuilder<Doc, ModelName, Engines, Db> : ReturnType<NonNullable<Fn>>; optimizer: (options?: { use?: boolean; hints?: Partial<OptimizerHints>; } | boolean) => QueryBuilder<Doc, ModelName, Engines, Db>; inspect: (fn?: (aggregators: { optimizedOptions: AggregatorOptions; unoptimizedOptions: AggregatorOptions; }) => void) => QueryBuilder<Doc, ModelName, Engines, Db>; exec(): Promise<Doc>; } export declare const getLastSkipAndLimitIndex: (pipelines: Pipeline[]) => number; export {};