import { QueryWithHelpers, Schema, Model, Aggregate, PipelineStage, HydratedDocument } from "mongoose"; /** A default query used throughout this file to help our mongoose queries have an expected structure * that the relay specification relies on. */ type DefaultRelayQuery = QueryWithHelpers; /** This is the default Cursor type for this project. * * A cursor helps a server to find an item in a database. * * If you're not exactly sure what that means here's an analogy. * Its a lot like when you go to the library and have some information for * a specific book. This information you have about the book can help you locate it. * * A cursor (some information) can be turned into a database object (the book) by finding the first instance of * it in the database (the library). * * Below is a hypothetical example: * ``` * Cursor -> Some query from a cursor -> DB Object * {name: "bob"} -> Some query from a cursor -> {name: "bob", job: "something", location: "some place 123rd street"} * ``` * * An example of some query from a cursor, in MongoDB is: * * ```js * const {name, job, location} = await Employee.findOne({name: "bob"}); * ``` * * A database object can be turned into a cursor with a transform of some sort in our case it will be provided by the user. * * Below is a hypothetical example: * ``` * DB Object -> some transform to a cursor -> Cursor * { * name: "bob", * job: "something", * location: "some place 123rd street" * } -> some tranform to a cursor -> {name: "bob"} * ``` * * @public */ export type PagingCursor = { [P in keyof DocType]?: DocType[P] | undefined | null; }; /** Info about how to page forward and backward * * * `first` and `last` are alot like limit in a typical skip and limit scheme. * This is because first and last signify how many elements to return. * You should never supply both `first` and `last` at the same time. * You should either supply one or the other, but not both. * Supplying both will lead to unpredicted behaviour. * * `after` and `before` are more like the typical skip in skip and limit. * This is because after and before signify where the * collection starts and stops searching. * You may supply both the after and before, but your before cursor must be later * in your collection than your after cursor otherwise you will get 0 results. * * @public */ export type PagingInfo = { /** fetch the `first` given number of records */ first?: number; /** fetch the `last` given number of records */ last?: number; /** fetch `after` the given record's cursor */ after?: PagingCursor | null | undefined; /** fetch `before` the given record's cursor */ before?: PagingCursor | null | undefined; }; type ElementOfArray = Array extends (infer T)[] ? T : never; export interface RelayResult { edges: { node: ElementOfArray; cursor: PagingCursor>; }[]; nodes: Nodes; pageInfo: { hasNextPage: boolean; hasPreviousPage: boolean; endCursor?: PagingCursor> | null; startCursor?: PagingCursor> | null; }; } export interface TransformedRelayResult { edges: { node: ElementOfArray; cursor: PagingCursor>; }[]; nodes: NewNodes; pageInfo: { hasNextPage: boolean; hasPreviousPage: boolean; endCursor?: PagingCursor> | null; startCursor?: PagingCursor> | null; }; } /** A helper generic type which when given a DefaultRelayQuery will infer its RawDocType */ type QueryRawDocType = Q extends QueryWithHelpers ? RawDocType : never; /** A helper generic type which when given a DefaultRelayQuery will infer the DocType */ type QueryDocType = Q extends QueryWithHelpers ? DocType : never; /** A helper generic type which when given a DefaultRelayQuery will infer its QueryHelpers */ type QueryHelpers = Q extends QueryWithHelpers ? QueryHelpers : never; /** A helper generic type which when given a DefaultRelayQuery will infer the QueryResult */ type QueryResult = Q extends QueryWithHelpers ? QueryResult : never; type ModelRawDocType> = M extends Model ? RawDocType : never; /** A helper generic type which when given a {@link DefaultRelayQuery} will construct its corresponding document node that will be part of the return type of {@link relayPaginate}. */ type MongooseRelayDocument = HydratedDocument, QueryDocType, QueryHelpers>; /** A helper generic type which when given a {@link DefaultRelayQuery} and {@link PagingCursor} constructs the document type needed. */ type MongooseRelayPaginateInfo = MongooseRelayPaginateInfoOnModel ? DocType : never>; /** A helper generic type which when given a {@link Model} and {@link PagingCursor} construct its corresponding document type. */ type MongooseRelayPaginateInfoOnModel = PagingInfo; /** This is an implementation of the relay pagination algorithm for mongoose. This algorithm and pagination format * allows one to use cursor based pagination. * * For more on cursors see {@link PagingCursor} * * For more info on using cursor based pagination algorithms like relay see: * * {@link https://relay.dev/docs/guides/graphql-server-specification/ the documentation for relay's connection spec} (look at this one for docs in more laymans terms), * * {@link https://relay.dev/graphql/connections.htm the actual relay spec} (look at this one for very exact and concise, but possibly confusing language), * * @param query the query to add pagination to * @param paginationInfo the information to help with the paging * @returns */ export declare function relayPaginate(query: DefaultRelayQuery, { ...pagingInfo }?: MongooseRelayPaginateInfo>): QueryWithHelpers>[]>>, QueryDocType>, QueryHelpers>, QueryRawDocType>>; /** This is an implementation of the relay pagination algorithm for mongoose. This algorithm and pagination format * allows one to use cursor based pagination. * * For more on cursors see {@link PagingCursor} * * For more info on using cursor based pagination algorithms like relay see: * * {@link https://relay.dev/docs/guides/graphql-server-specification/ the documentation for relay's connection spec} (look at this one for docs in more laymans terms), * * {@link https://relay.dev/graphql/connections.htm the actual relay spec} (look at this one for very exact and concise, but possibly confusing language), * * @param Model the model to add pagination to * @param paginationInfo the information to help with the paging * @returns */ export declare function aggregateRelayPaginate(model: Model, aggregate: PipelineStage[], { ...pagingInfo }?: MongooseRelayPaginateInfoOnModel): { toNodesAggregate: () => Aggregate; then: Aggregate>["then"]; }; export declare function toCursorFromKeys(keys: (keyof NonNullable["after"]>)[], doc: Node): Partial; /** Creates a typed relay connection. This is what relay uses for it's cursor-based pagination algorithm. * It can be constructed using three things: a set of documents called nodes, a transform that turns a document/node into a cursor, * and finally some metadata about paging which is called the `pagingInfo`. * * * @param cursorKeys The way to turn a node into a cursor. Given certain props it will create a partial document node known as the cursor of the original document node with only those keys that are listed. For more info on cursors see {@link PagingCursor} * @param pagingInfo the metadata about paging information (such as cursors, number of documents returned, etc.) * used by the client to gain some insight into the query and to more easily re-query and fetch the next * and previous page. * @param nodes The nodes of the relay connection * @returns A {@link RelayResult} * @public */ export declare function relayResultFromNodes(cursorKeys: (keyof NonNullable["after"]>)[], { hasNextPage, hasPreviousPage, }: Pick["pageInfo"], "hasNextPage" | "hasPreviousPage">, nodes: Node[]): RelayResult; /** Alters a relay connection to have a different nodeType for each node in the nodes and edges property. * @param doc the relay style connection document to alter * @param transform a mapping transform to turn one thing into another * @returns An altered relay style connection with a new node type */ export declare function alterNodeOnResult(doc: RelayResult, transform: (doc: U, index?: number, arr?: U[], thisArg?: U[]) => Result): TransformedRelayResult; /** * * @example * * // 1. Create an interface representing a document in MongoDB. interface User { _id: mongoose.Types.ObjectId; myId: number; name: string; email: string; avatar?: string; } // 2. Setup various types. type UserModel = Model & RelayPaginateStatics; // 3. Create a Schema corresponding to the document interface. const schema = new Schema({ myId: Number, name: { type: String, required: true }, email: { type: String, required: true }, avatar: String, }); // 4. Create your Model. const UserModel = model("User", schema); * * @public */ export interface RelayPaginateQueryHelper { /** This is an implementation of the relay pagination algorithm for mongoose. This algorithm and pagination format * allows one to use cursor based pagination. * * For more on cursors see {@link PagingCursor} * * For more info on using cursor based pagination algorithms like relay see: * * {@link https://relay.dev/docs/guides/graphql-server-specification/ the documentation for relay's connection spec} (look at this one for docs in more laymans terms), * * {@link https://relay.dev/graphql/connections.htm the actual relay spec} (look at this one for very exact and concise, but possibly confusing language), * * @param this the query to add pagination to * @param paginationInfo the information to help with the paging * @returns */ relayPaginate(this: Q, paginateInfo?: Partial>): QueryWithHelpers[]>, QueryDocType, QueryHelpers, QueryRawDocType> & QueryHelpers; } /** * @example * // 1. Create an interface representing a document in MongoDB. interface User { _id: mongoose.Types.ObjectId; myId: number; name: string; email: string; avatar?: string; } // 2. Setup various types. type UserModel = Model & RelayPaginateStatics; // 3. Create a Schema corresponding to the document interface. const schema = new Schema({ myId: Number, name: { type: String, required: true }, email: { type: String, required: true }, avatar: String, }); // 4. Create your Model. const UserModel = model("User", schema); * @public */ export interface RelayPaginateStatics { /** This is an implementation of the relay pagination algorithm for mongoose. This algorithm and pagination format * allows one to use cursor based pagination. * * For more on cursors see {@link PagingCursor} * * For more info on using cursor based pagination algorithms like relay see: * * {@link https://relay.dev/docs/guides/graphql-server-specification/ the documentation for relay's connection spec} (look at this one for docs in more laymans terms), * * {@link https://relay.dev/graphql/connections.htm the actual relay spec} (look at this one for very exact and concise, but possibly confusing language), * * @param this the Model to add pagination through an aggregate to * @param paginationInfo the information to help with the paging * @returns */ aggregateRelayPaginate>(this: M, aggregate: PipelineStage[], paginateInfo?: Partial>>): { toNodesAggregate: []]>() => Aggregate; then: Aggregate[]>>["then"]; }; } /** Options for the relayPaginatePlugin * @public */ export interface PluginOptions { /** the maximum allowed limit for any query, * so that the client can't request over this * amount of items paged at a time. * * @default 100 **/ maxLimit?: number; } /** Creates the relay paginate plugin, so that you can use relayPaginate */ export declare function relayPaginatePlugin({ maxLimit }?: PluginOptions): (schema: Schema) => void; export {}; //# sourceMappingURL=index.d.ts.map