Open FluorescentHallucinogen opened 4 years ago
It comes from Prisma 2. For now TypeGraphQL uses schema and operations definitions directly from Prisma, there's not transform or translation layer.
However adding Node resolver and other relay's stuff would be a nice to have feature 👍
Ok, adding the Node
interface looks achievable, but what about things like Cursor Connections, Edges, PageInfo, etc.? This looks not easy.
Yes, that's why it's a nice to have feature but requires more time and has lower priority for now.
Just here to bump this feature request for pagination within the generated resolvers! I think what you guys are doing here is great and will greatly speed up development. I would heavily consider using this in my next project if pagination came right out of the box!
There is also https://github.com/johnsonjo4531/typegraphql-relay-connections but this one manually requires me to add the types using TypeGraphQL, which works great, but then I lose orderBy
, where
and etc (unless I implement it).
Seems like https://github.com/devoxa/prisma-relay-cursor-connection leverages this by extending findMany, but then it does not generate the object types and resolvers, so either way we are stuck implementing relay style pagination.
Actually by using https://github.com/johnsonjo4531/typegraphql-relay-connections it is possible to have something, even if it is not automatically generated. So for anyone interested here is how I did it. In my example, I removed backward pagination because my app does not need it.
Relay style pagination by passing findManyArgs:
import { Args, Ctx, ObjectType, Query, Resolver } from 'type-graphql';
import {
ConnectionType,
Cursor,
EdgeType,
ForwardPaginationArgs,
NodesType,
serializeCursor
} from 'typegraphql-relay-connections';
import { FindManyJobArgs, Job } from '@generated/type-graphql';
import { Context } from './context';
/*
* Inspired from:
* https://johnsonjo4531.github.io/typegraphql-relay-connections/docs/intro
*
* For now, backward pagination was removed.
*/
declare module 'typegraphql-relay-connections' {
interface Cursor {
id: string;
}
}
@ObjectType()
export class JobEdge extends EdgeType(Job) {
}
@ObjectType()
export class JobConnection extends ConnectionType({
edge: JobEdge,
node: Job
}) {
}
@Resolver(Job)
export class PaginatedJobsResolver {
@Query(() => JobConnection)
async jobs(@Ctx() ctx: Context, @Args() paging: ForwardPaginationArgs, @Args() findManyArgs: FindManyJobArgs): Promise<JobConnection> {
return getJobs(ctx, { paging, findManyArgs });
}
}
export const getJobs = async ({ prisma }: Context, {
paging,
findManyArgs
}: { paging: ForwardPaginationArgs, findManyArgs: FindManyJobArgs }) => {
const edges = edgesToReturn(
(
await prisma.job.findMany({
...findManyArgs,
take: paging.first,
cursor: paging.after
})
).map((node) => ({
node,
cursor: {
id: node.id
}
})),
paging
);
return {
edges,
nodes: edges.map((e) => e.node),
pageInfo: {
hasNextPage: false, // todo
hasPreviousPage: false, // todo
endCursor: edges[edges.length - 1].cursor,
startCursor: edges[0].cursor,
count: edges.length
}
};
};
export function edgesToReturn<CursorType extends Cursor = Cursor, NodeType extends NodesType = unknown>(
allEdges: {
cursor: CursorType;
node: NodeType;
}[],
{ first, after }: ForwardPaginationArgs
) {
const edges = applyCursorsToEdges(allEdges, { after });
if (first !== null && typeof first !== 'undefined') {
if (first < 0) {
throw new Error('ForwardPagingArg property first cannot be less than 0');
}
if (edges.length > first) {
// Yes that first parameter is negative on purpose, so that it splices from the end of the array.
const numToDelete = Math.abs(edges.length - first);
edges.splice(-numToDelete, numToDelete);
}
}
return edges;
}
export function applyCursorsToEdges<CursorType extends Cursor = Cursor, NodeType extends NodesType = unknown>(
allEdges: {
cursor: CursorType;
node: NodeType;
}[],
{ after }: Pick<ForwardPaginationArgs, 'after'>
) {
const edges = allEdges;
if (after) {
const afterEdge = edges.findIndex((x) => serializeCursor(x.cursor) === serializeCursor(after));
if (afterEdge !== -1) {
edges.splice(0, afterEdge + 1);
}
}
return edges;
}
I'm sorry to hijack this conversation, but it seems related. How's everyone handling the Relay node resolver? We don't have global ids with Prisma so how do you know what model to fetch when a node is queried?
I'm talking about the Query.node resolver that only takes the id as argument
I'm thinking about migrating from Prisma 1 to Prisma 2 + TypeGraphQL, but just found that generated GraphQL schema (see e.g. generated-schema.graphql) is not Relay-compliant, e.g. there is no the interface called
Node
.Is it comes from Prisma 2 or TypeGraphQL? Is it fixable?