Skip to content

Instantly share code, notes, and snippets.

@hayes
Last active July 23, 2021 18:27
Show Gist options
  • Save hayes/c9cdcbcd9b38991eaafdb4c2f237a148 to your computer and use it in GitHub Desktop.
Save hayes/c9cdcbcd9b38991eaafdb4c2f237a148 to your computer and use it in GitHub Desktop.
Prisma plugin idea for giraphql

Prisma plugin idea

const User = builder.prismaObject('User', {
    // Used as a fallback when loading relations that are not pre-loaded (explained more later)
    findUnique: (user) => ({ id: user.id }),
    fields: (t) => ({
        id: t.exposeID('id'),
        name: t.exposeString('name'),
        posts: t.relation('posts', {
            args: {
                includeDrafts: t.arg.boolean()
            },
            orderBy: { date: 'desc' }, // can also be function that accepts args
            where: (args) => args.includeDrafts ? {} : { draft: false }
        }),
    }),
});

const Post = builder.prismaObject('Post', {
    findUnique: (post) => ({ id: post.id }),
    fields: (t) => ({
        id: t.exposeID('id'),
        title: t.exposeString('title'),
        author: t.relation('author'),
    }),
});

builder.queryType({
    fields: (t) => ({
        // first arg is include/select needed for queried relations
        me: t.primaField({
            type: 'User',
            resolve: (query, root, args, ctx, info) => prisma.user.findUnique({
                ...query,
                where: {
                    id: ctx.user.id,
                },
            }),
        }),
        // normal field that doesn't automatically query for relations
        post: t.field({
            type: Post,
            resolve: (root, args, ctx, info) => prisma.post.findUnique({
                where: {
                    id: ctx.user.id,
                },
            }),
        }),
    }),
});

Queries:

query a prisma type with a basic relation

query {
    me {
        id
        name
        posts {
            title
        }
    }
}

generated query:

prisma.user.findUnique({
    include: {
        post: {
            where: { draft: false }
        },
    },
    where: {
        id: ctx.user.id,
    },
})

Nested relation

query {
    me {
        id
        posts {
            title
            author {
                name
            }
        }
    }
}

generated query:

prisma.user.findUnique({
    include: {
        post: {
            where: { draft: false },
            include: {
                author: true,
            },
        },
    },
    where: {
        id: ctx.user.id,
    },
})

Query the same relation multiple times

query {
    me {
        id
        name
        posts {
            title
            author {
                name
            }
        }
        withDrafts: posts(includeDrafts: true ) {
            title
            author {
                name
            }
        }
    }
}

generates 2 queries:

prisma.user.findUnique({
    include: {
        post: {
            where: { draft: false },
            include: {
                author: true,
            },
        },
    },
    where: {
        id: ctx.user.id,
    },
});

// generated for drafts.  The where in this query is derived from the findUinique defined on the object.
// We can't include posts twice, since the posts relation is queried twice, for the second field we use a
// generated findUnique based on the user returned by the first query.  This does mean this query won't
// fire until after the other query completes.
prisma.user.findUnique({
    include: {
        post: {
            include: {
                author: true,
            },
        },
    },
    where: {
        id: 123, // id of current user (extracted from first query result)
    },
});

Query that does not use prismaField helper (and can't auto-load relations)

query {
    post(id: 123) {
        title
        author {
            name
        }
    }
}

Results in 2 queries, firs the query defined in the field, then the following query for the author:

prisma.post.findUnique({
    where: { id: 123 }, // created by findUnique on post type
    include: {
        author: true,
    },    
});
@hayes
Copy link
Author

hayes commented Jul 23, 2021

I have most of the types working correctly, but need to figure out how this will play with relay and data-loader plugins.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment