import { IExpanderOptions , ILinkOptions , QueryBodyType , IReducerOption , IReducerOptions , IAstToQueryOptions , IQueryContext , } from "./defs" ; import { EXPANDER_STORAGE , LINK_STORAGE , REDUCER_STORAGE , SCHEMA_STORAGE , LINK_COLLECTION_OPTIONS_DEFAULTS , SCHEMA_AGGREGATE_STORAGE , SCHEMA_BSON_OBJECT_DECODER_STORAGE , SCHEMA_BSON_AGGREGATE_DECODER_STORAGE , SCHEMA_BSON_DOCUMENT_SERIALIZER , } from "./constants" ; import * as _ from "lodash" ; import Linker from "./query/Linker" ; import Query from "./query/Query" ; import astToQuery , { secureBody } from "./graphql/astToQuery" ; import { IGetLookupOperatorOptions } from "./query/Linker" ; import { Collection } from "mongodb" ; import { ClassSchema } from "@deepkit/type" ; import CollectionNode from "./query/nodes/CollectionNode" ; import { getBSONDecoder } from "@deepkit/bson" ; import { ISecureOptions } from "./defs" ; export { secureBody , Linker } ; export function query < T > ( collection , body , context ? ) { return new Query ( collection , body , context ) ; } query . securely = function securely < T = any > ( config , collection , body , context ? ) { return query ( collection , secureBody ( body , config ) , context ) ; } ; query . graphql = function graphql < T = any > ( collection , ast , options , context ? ) { return astToQuery ( collection , ast , options , context ) ; } ; export function clear ( collection ) { collection [ LINK_STORAGE ] = { } ; collection [ REDUCER_STORAGE ] = { } ; collection [ EXPANDER_STORAGE ] = { } ; collection [ SCHEMA_STORAGE ] = null ; } export function addSchema < T = any > ( collection , schema ) { collection [ SCHEMA_STORAGE ] = schema ; collection [ SCHEMA_AGGREGATE_STORAGE ] = CollectionNode . getAggregateSchema ( schema ) ; collection [ SCHEMA_BSON_AGGREGATE_DECODER_STORAGE ] = getBSONDecoder ( collection [ SCHEMA_AGGREGATE_STORAGE ] ) ; collection [ SCHEMA_BSON_OBJECT_DECODER_STORAGE ] = getBSONDecoder ( schema ) ; collection [ SCHEMA_BSON_DOCUMENT_SERIALIZER ] = CollectionNode . getSchemaSerializer ( schema ) ; } export function addLinks < T = any > ( collection , data ) { if ( ! collection [ LINK_STORAGE ] ) { collection [ LINK_STORAGE ] = { } ; } _ . forEach ( data , ( linkConfig , linkName ) => { if ( collection [ LINK_STORAGE ] [ linkName ] ) { throw new Error ( `You cannot add the link with name: ${ linkName } because it was already added to ${ this . collectionName } collection` ) ; } const linker = new Linker ( collection , linkName , { ... LINK_COLLECTION_OPTIONS_DEFAULTS , ... linkConfig , } ) ; Object . assign ( collection [ LINK_STORAGE ] , { [ linkName ] : linker , } ) ; } ) ; } export function addExpanders < T = any > ( collection , data ) { if ( ! collection [ EXPANDER_STORAGE ] ) { collection [ EXPANDER_STORAGE ] = { } ; } _ . forEach ( data , ( expanderConfig , expanderName ) => { if ( collection [ EXPANDER_STORAGE ] [ expanderName ] ) { throw new Error ( `This expander was already added.` ) ; } Object . assign ( collection [ EXPANDER_STORAGE ] , { [ expanderName ] : expanderConfig , } ) ; } ) ; } export function getLinker < T = any > ( collection , name ) { if ( collection [ LINK_STORAGE ] && collection [ LINK_STORAGE ] [ name ] ) { return collection [ LINK_STORAGE ] [ name ] ; } else { throw new Error ( `Link "${ name }" is not found in collection: "${ collection . collectionName }"` ) ; } } export function hasLinker < T = any > ( collection , name ) { if ( collection [ LINK_STORAGE ] ) { return Boolean ( collection [ LINK_STORAGE ] [ name ] ) ; } else { return false ; } } /**
 * This returns the correct aggregation pipeline operator
 * This is useful for complex searching and filtering
 */ export function lookup ( collection , linkName , options ? ) { return getLinker ( collection , linkName ) . getLookupAggregationPipeline ( options ) ; } export function getReducerConfig ( collection , name ) { if ( collection [ REDUCER_STORAGE ] ) { return collection [ REDUCER_STORAGE ] [ name ] ; } } export function getExpanderConfig ( collection , name ) { if ( collection [ EXPANDER_STORAGE ] ) { return collection [ EXPANDER_STORAGE ] [ name ] ; } } export function addReducers < T = any > ( collection , data ) { if ( ! collection [ REDUCER_STORAGE ] ) { collection [ REDUCER_STORAGE ] = { } ; } Object . keys ( data ) . forEach ( ( reducerName ) => { const reducerConfig = data [ reducerName ] ; if ( hasLinker ( collection , reducerName ) ) { throw new Error ( `You cannot add the reducer with name: ${ reducerName } because it is already defined as a link in ${ collection . collectionName } collection` ) ; } if ( collection [ REDUCER_STORAGE ] [ reducerName ] ) { throw new Error ( `You cannot add the reducer with name: ${ reducerName } because it was already added to ${ collection . collectionName } collection` ) ; } Object . assign ( collection [ REDUCER_STORAGE ] , { [ reducerName ] : reducerConfig , } ) ; } ) ; }