Skip to content

Commit

Permalink
feat(graphql): propagate correct query types throughout paging
Browse files Browse the repository at this point in the history
  • Loading branch information
doug-martin committed Sep 7, 2021
1 parent d81e531 commit 348044f
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ export function getOrCreateArrayConnectionType<DTO>(
class AbstractConnection extends Array<DTO> {
static resolveType = [TItemClass];

static async createFromPromise(queryMany: QueryMany<DTO>, query: Query<DTO>): Promise<AbstractConnection> {
static async createFromPromise<Q extends Query<DTO>>(
queryMany: QueryMany<DTO, Q>,
query: Q,
): Promise<AbstractConnection> {
// remove paging from the query because the ArrayConnection does not support paging.
const { paging, ...rest } = query;
return queryMany(rest);
return queryMany(rest as Q);
}
}
return AbstractConnection;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ export function getOrCreateCursorConnectionType<DTO>(
return this;
}

static async createFromPromise(
queryMany: QueryMany<DTO>,
query: Query<DTO>,
static async createFromPromise<Q extends Query<DTO>>(
queryMany: QueryMany<DTO, Q>,
query: Q,
count?: Count<DTO>,
): Promise<AbstractConnection> {
const { pageInfo, edges, totalCount } = await pager.page(queryMany, query, count ?? DEFAULT_COUNT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ const DEFAULT_PAGING_META = <DTO>(query: Query<DTO>): PagingMeta<DTO, OffsetPagi
export class CursorPager<DTO> implements Pager<DTO, CursorPagerResult<DTO>> {
constructor(readonly strategy: PagerStrategy<DTO>) {}

async page(
queryMany: QueryMany<DTO>,
query: CursorQueryArgsType<DTO>,
async page<Q extends CursorQueryArgsType<DTO>>(
queryMany: QueryMany<DTO, Q>,
query: Q,
count: Count<DTO>,
): Promise<CursorPagerResult<DTO>> {
const pagingMeta = this.getPageMeta(query);
Expand All @@ -41,9 +41,9 @@ export class CursorPager<DTO> implements Pager<DTO, CursorPagerResult<DTO>> {
return pagingMeta.opts.limit > 0;
}

private async runQuery(
queryMany: QueryMany<DTO>,
query: Query<DTO>,
private async runQuery<Q extends Query<DTO>>(
queryMany: QueryMany<DTO, Q>,
query: Q,
pagingMeta: PagingMeta<DTO, CursorPagingOpts<DTO>>,
): Promise<QueryResults<DTO>> {
const { opts } = pagingMeta;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class KeysetPagerStrategy<DTO> implements PagerStrategy<DTO> {
return !opts.payload || !opts.payload.fields.length;
}

createQuery(query: Query<DTO>, opts: KeySetPagingOpts<DTO>, includeExtraNode: boolean): Query<DTO> {
createQuery<Q extends Query<DTO>>(query: Q, opts: KeySetPagingOpts<DTO>, includeExtraNode: boolean): Q {
const paging = { limit: opts.limit };
if (includeExtraNode) {
// Add 1 to the limit so we will fetch an additional node
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class LimitOffsetPagerStrategy<DTO> implements PagerStrategy<DTO> {
return opts.offset === 0;
}

createQuery(query: Query<DTO>, opts: OffsetPagingOpts, includeExtraNode: boolean): Query<DTO> {
createQuery<Q extends Query<DTO>>(query: Q, opts: OffsetPagingOpts, includeExtraNode: boolean): Q {
const { isBackward } = opts;
const paging = { limit: opts.limit, offset: opts.offset };
if (includeExtraNode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ export interface PagerStrategy<DTO> {
toCursor(dto: DTO, index: number, opts: CursorPagingOpts<DTO>, query: Query<DTO>): string;
fromCursorArgs(cursor: CursorPagingType): CursorPagingOpts<DTO>;
isEmptyCursor(opts: CursorPagingOpts<DTO>): boolean;
createQuery(query: Query<DTO>, opts: CursorPagingOpts<DTO>, includeExtraNode: boolean): Query<DTO>;
createQuery<Q extends Query<DTO>>(query: Q, opts: CursorPagingOpts<DTO>, includeExtraNode: boolean): Q;
checkForExtraNode(nodes: DTO[], opts: CursorPagingOpts<DTO>): DTO[];
}
10 changes: 5 additions & 5 deletions packages/query-graphql/src/types/connection/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export type InferConnectionTypeFromStrategy<DTO, S extends PagingStrategies> = S
? CursorConnectionType<DTO>
: never;

export type QueryMany<DTO> = (query: Query<DTO>) => Promise<DTO[]>;
export type QueryMany<DTO, Q extends Query<DTO>> = (query: Q) => Promise<DTO[]>;
export type Count<DTO> = (filter: Filter<DTO>) => Promise<number>;

export type CountFn = () => Promise<number>;
Expand All @@ -73,15 +73,15 @@ export type PagerResult = {
};

export interface Pager<DTO, R extends PagerResult> {
page(queryMany: QueryMany<DTO>, query: Query<DTO>, count: Count<DTO>): Promise<R>;
page<Q extends Query<DTO>>(queryMany: QueryMany<DTO, Q>, query: Q, count: Count<DTO>): Promise<R>;
}

export interface StaticConnectionType<DTO, S extends PagingStrategies>
extends Class<InferConnectionTypeFromStrategy<DTO, S>> {
resolveType: ReturnTypeFuncValue;
createFromPromise(
queryMany: QueryMany<DTO>,
query: Query<DTO> & Record<string, any>,
createFromPromise<Q extends Query<DTO>>(
queryMany: QueryMany<DTO, Q>,
query: Q,
count?: Count<DTO>,
): Promise<InferConnectionTypeFromStrategy<DTO, S>>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ export function getOrCreateOffsetConnectionType<DTO>(
return this;
}

static async createFromPromise(
queryMany: QueryMany<DTO>,
query: Query<DTO>,
static async createFromPromise<Q extends Query<DTO>>(
queryMany: QueryMany<DTO, Q>,
query: Q,
count?: Count<DTO>,
): Promise<AbstractConnection> {
const { pageInfo, nodes, totalCount } = await pager.page(queryMany, query, count ?? DEFAULT_COUNT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ const DEFAULT_PAGING_META = <DTO>(query: Query<DTO>): OffsetPagingMeta<DTO> => (
});

export class OffsetPager<DTO> implements Pager<DTO, OffsetPagerResult<DTO>> {
async page(queryMany: QueryMany<DTO>, query: Query<DTO>, count: Count<DTO>): Promise<OffsetPagerResult<DTO>> {
async page<Q extends Query<DTO>>(
queryMany: QueryMany<DTO, Q>,
query: Q,
count: Count<DTO>,
): Promise<OffsetPagerResult<DTO>> {
const pagingMeta = this.getPageMeta(query);
if (!this.isValidPaging(pagingMeta)) {
return EMPTY_PAGING_RESULTS();
Expand All @@ -28,9 +32,9 @@ export class OffsetPager<DTO> implements Pager<DTO, OffsetPagerResult<DTO>> {
return pagingMeta.opts.limit > 0;
}

private async runQuery(
queryMany: QueryMany<DTO>,
query: Query<DTO>,
private async runQuery<Q extends Query<DTO>>(
queryMany: QueryMany<DTO, Q>,
query: Q,
pagingMeta: OffsetPagingMeta<DTO>,
): Promise<QueryResults<DTO>> {
const windowedQuery = this.createQuery(query, pagingMeta);
Expand Down Expand Up @@ -63,7 +67,7 @@ export class OffsetPager<DTO> implements Pager<DTO, OffsetPagerResult<DTO>> {
return { nodes, pageInfo, totalCount };
}

private createQuery(query: OffsetQueryArgsType<DTO>, pagingMeta: OffsetPagingMeta<DTO>): Query<DTO> {
private createQuery<Q extends OffsetQueryArgsType<DTO>>(query: Q, pagingMeta: OffsetPagingMeta<DTO>): Q {
const { limit, offset } = pagingMeta.opts;
return { ...query, paging: { limit: limit + 1, offset } };
}
Expand Down

0 comments on commit 348044f

Please sign in to comment.