popurelate
Version:
Easily populate and filter documents using data from related collections.
237 lines (236 loc) • 9.54 kB
TypeScript
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 {};