-
-
Notifications
You must be signed in to change notification settings - Fork 158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Drizzle integration. #1027
Comments
There is some initial experimentation around this here: #1028 but you can always just use drizzle manually, you don't need a plugin to use drizzle |
@hayes thanks so much for the time you put into pothos. I just moved to Pothos and Drizzle and was really happy how easy builder.objectRef made things. Awesome there might be even tighter integration one day but it certainly is very nice even as it is.
|
Nice, glad it's working well for you! If you've got any advanced cases where you are doing joins/dataloading/nested selects or anything like that, id be curious to see how you're doing it or what the pain points there are. The current plan with the drizzle plugin is to lean on a combination of drizzles relational query builder, and data-loaders similar to what Prisma does. This kinda gets away from being close to SQL which is one of the things that makes drizzle interesting, but it's a lot easier to build out that way. |
@hayes I am currently only using it in simple cases but happy to share what I am doing. Here are some helpers I am currently prototyping which make it more prisma like and make the service code a bit cleaner when dealing with things like pagination: https://github.com/Enalmada/drizzle-helpers Here is a demo project where this can be seen in action: https://github.com/Enalmada/nextjs-boilerplate |
I would love to see the Drizzle plugin make it out. Prisma leaves a lot to be desired regarding performance. N+1 queries with Prisma will add exponentially more round trips to your database, which is a problem Drizzle simply doesn't have. Properly transforming a GraphQL query's relations to left joins in a single SQL statement is the dream. As of 10/14/23, Prisma is part of the way there now lol https://github.com/prisma/prisma/releases/tag/5.4.0 |
FWIW, I got it working using drizzle-graphql and AddGraphQLPlugin import { buildSchema } from 'drizzle-graphql';
import AddGraphQLPlugin from '@pothos/plugin-add-graphql';
const conn = postgres(env.DATABASE_URL);
const db = drizzle(conn, { schema });
const { entities } = buildSchema(db);
const builder = new SchemaBuilder({
plugins: [AddGraphQLPlugin],
});
const User = builder.addGraphQLObject(entities.types.UsersItem, {
name: 'User',
description: 'description for User',
fields: (t) => ({
id: t.exposeID('id'),
}),
});
const UserUpdate = builder.addGraphQLObject(entities.types.UsersSelectItem, {
name: 'UserUpdate',
fields: (t) => ({
id: null,
}),
});
builder.queryType({
fields: (t) => ({
users: t.field({
type: [User],
resolve: async (_root, _args, { db }) => {
const users = await db.query.users.findMany();
return users;
},
}),
}),
});
export const schema = builder.toSchema(); |
I know this issue has been open for a long time, but I finally got the initial version of the plugin published! https://pothos-graphql.dev/docs/plugins/drizzle It's not production ready, but I'd love to get some people to try it out, and give me some feedback. If you are using Pothos with drizzle already, or have any interest in playing with this, let me know! I am more than happy to help get things set up for some testing! |
@hayes this is so awesome, thanks for all your efforts! Some quick feedback for you: I went to try the plugin out on a project that uses Cloudflare D1. For this I have to construct the Drizzle client in the request context in order to have access to the "Binding". I then pass it into the context for use in resolvers. With the Drizzle plugin it seems I must pass the Drizzle client when constructing the Builder. Could there be a way to tell the plugin to get it from the context instead? |
Added an option so you can do something like this: export const builder = new SchemaBuilder<PothosTypes>({
plugins: [RelayPlugin, DrizzlePlugin],
drizzle: {
client: (_ctx) => drizzle(client, { schema }),
schema,
},
}); |
Finally had a chance to give the plugin a go! The option to use the Drizzle client from context worked great. Some observations for you:
Hope this helps! |
Thanks for the feedback @dantrain I don't have a good suggestion to fix to co-location thing. There are hacky workarounds, but they probably aren't worth it.
I'm curious if this is generally going in the right direction, and if its an improvement over using drizzle manually. |
Brilliant, the fixes work great thank you! I think the relations and connections are definitely a nice improvement for me over using Drizzle manually. A few years back before I discovered Pothos I used Nexus and I tried out Drizzle to have more control over the queries than Prisma and retain the type safety, and really liked it. Defining the database schema in code is great, and unlike Prisma it works on an edge runtime like Cloudflare Workers etc. I was missing some of the convenience though. I think it's getting to a good middle ground with Drizzle's relational API and this new plugin. Once the Drizzle relational API v2 comes out it would be useful to have some helpers to create input types, similar to your "Prisma Utils". Excited for the future! |
It's not documented and I am not sure I want to keep it, but there you this already exists (sortof). Using https://orm.drizzle.team/docs/graphql you can do something like My experience was that this made type-checking very slow, and it was WAY too easy to create dangerous DB queries, but its there if you want to try it (but I might remove it before creating a stable release) |
@hayes Typescript will not work correctly when using drizzleFieldWithInput. I am installing both @pothos/plugin-with-input and drizzle plugin. builterconfig import SchemaBuilder from "@pothos/core";
import DrizzlePlugin from "@pothos/plugin-drizzle";
import { buildSchema } from "drizzle-graphql";
import RelayPlugin from "@pothos/plugin-relay";
import { DateResolver, DateTimeISOResolver } from "graphql-scalars";
import WithInputPlugin from "@pothos/plugin-with-input";
import ZodPlugin from "@pothos/plugin-zod";
import ErrorsPlugin from "@pothos/plugin-errors";
import { db } from "./db/db";
import * as schema from "./db/schema";
const { entities } = buildSchema(db);
export interface PothosTypes {
DrizzleSchema: typeof schema;
Scalars: {
Date: {
Input: Date;
Output: Date;
};
DateTime: {
Input: Date;
Output: Date;
};
};
}
const builder = new SchemaBuilder<PothosTypes>({
plugins: [
RelayPlugin,
// ZodPlugin,
WithInputPlugin,
ErrorsPlugin,
DrizzlePlugin,
],
drizzle: {
client: db,
schema,
},
relay: {},
withInput: {
typeOptions: {},
argOptions: {},
},
// zod: {
// validationError: (zodError, args, context, info) => {
// return zodError;
// },
// },
errors: {
defaultTypes: [],
},
});
builder.objectType(Error, {
name: "Error",
fields: (t) => ({
message: t.exposeString("message"),
}),
});
builder.addScalarType("Date", DateResolver);
builder.addScalarType("DateTime", DateTimeISOResolver);
builder.queryType();
builder.mutationType({
fields: (t) => ({
createUser: t.fieldWithInput({
input: {
email: t.input.string({ required: true }),
name: t.input.string({ required: true }),
},
type: "String",
resolve: async (parent, args, ctx) => {
return "Hello World";
},
}),
}),
});
export { builder, entities };
Can you document this with an example. import { db } from "../db/db";
import { builder, entities } from "../builder";
import { users } from "../db/schema";
import { z } from "zod";
import { emailZodSchema, stringZodSchema } from "../lib/zod-schema";
const usersRef = builder.drizzleObject("users", {
name: "User",
description: "User field",
fields: (t) => ({
id: t.exposeID("id"),
email: t.exposeString("email"),
name: t.exposeString("name"),
createdAt: t.expose("createdAt", {
type: "DateTime",
}),
updatedAt: t.expose("updatedAt", { type: "DateTime" }),
}),
});
builder.mutationFields((t) => ({
createUser: t.drizzleFieldWithInput({
type: usersRef,
input: {
email: t.input.string({ required: true }),
name: t.input.string({ required: true }),
},
resolve: (parent, { input }, ctx) =>
db.insert(users).values(args).returning(),
}),
}));
|
@RajaARK99 you are missing the query arg, it's query, parent, arga, ctx, info for drizzle fields |
@hayes I also update it before but it not work |
thanks for reporting this! I've identified and fixed the issue, I'll have the release out in a minute |
@RajaARK99 fix should be available in 0.4.3 |
What is the issue with co-location here, I'm just planning to adopt Pothos, and was trying to come up with a concept, where Drizzle schema and Pothos builder code is co-located, would that still work? And if not why, and what are the alternatives? |
We need support drizzle integration.
The text was updated successfully, but these errors were encountered: