pothos icon indicating copy to clipboard operation
pothos copied to clipboard

wip - Pothos EdgeDB Plugin

Open baristikir opened this issue 2 years ago • 10 comments

WIP EdgeDB Plugin

Related Issue: https://github.com/hayes/pothos/issues/534

edgeDBObject

Naming Conventions

  • t.link(): Model property which is a relation to another model. (like prisma plugins t.relation()) Could be one or many relation to model.

Open for any feedback and reviews!

baristikir avatar Aug 19 '22 13:08 baristikir

⚠️ No Changeset found

Latest commit: 8ec9e25d91d12fa9059a8ec0314c8b493944444e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

changeset-bot[bot] avatar Aug 19 '22 13:08 changeset-bot[bot]

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated
pothos ✅ Ready (Inspect) Visit Preview Aug 22, 2022 at 2:40PM (UTC)

vercel[bot] avatar Aug 19 '22 13:08 vercel[bot]

Current work only covers the edgeDBObject api. Showcase of how the type system could look like for the edgeDB schema. Type system is constructed out of the EdgeDB Query Builder types, specifically from the default export type. Output shape looks pretty similar to the PrismaTypes shape

Bildschirmfoto 2022-08-19 um 16 09 54

baristikir avatar Aug 19 '22 14:08 baristikir

This looks like an awesome start! Getting the type system working is often one of the hardest parts, and it looks like you are making great progress!

I'll try to find some time today to dive a little deeper. Initial skim looks like there are lots of pieces that are unused or copied from the prisma plugin that don't quite make sense yet, so I'll just ignore those for now and try to look specifically at types for defining objects and links

hayes avatar Aug 19 '22 18:08 hayes

Curious about your goals here, and what you are looking for. Is this something you want to get merged in the not too distant future, or more just sharing/collecting feedback while you iterate?

Long term, is this something you want have live in the main repo and have maintained with the rest of the plugins, or something you want to own in your own repo. I have been meaning to create some docs pages for linking out to community maintained projects. It might also be interesting do have a model similar to https://github.com/opentracing-contrib where there is an official place for people to add their own plugins/packages/examples etc in a way that is discoverable.

Open to any ideas and suggestions here, and don't feel too strongly about it. I would say that the bar for what I would expect in this repo would likely be a lot higher, and include things like making sure that this works well with all the other plugins, thorough documentation, test coverage, and solutions for things like aliasing fields, or defining multiple fields that use the same link in the database.

Regardless of how you want to work on this, and where you would like it to live, I am happy to help out when I have time, and give feedback/reviews or answer any questions you have about how the internals of pothos work. Looks like you are already making a lot of progress and have figured out a lot of the weird patterns needed to make something like this work.

hayes avatar Aug 19 '22 19:08 hayes

Agreed, this is right now just not enough for a plugin imo. Long term I would love to see it in the main repo as a plugin. But also looking for more features, supporting other plugins and enabling integrations, like relay nodes and so on. A lot of work needs to be done, not finished at all.

I am not very familiar with the architecture and type system of Pothos, still learning the patterns and experimenting with the types :)

I was porting a lot of the prisma plugins system into this plugin therefore still unused and unnecessary code / type definitions around here. Will clean that up.

baristikir avatar Aug 19 '22 21:08 baristikir

Will need some feedback on this topic.

Edgedb queries return type depends on the select shape. Even ...e.User["*"] won't load the whole db schema. That would be a problem for edgeDBField resolve functions return type since Model["Shape"] won't be the return type at any time. Instead the return type needs to be composed of optional fields. We might not wanna loose the actual nullability of model properties in Model["Shape"], important for edgeDBObject field definitions. So defining another Shape type as the optional reflection looks like a solution.

Example

// EdgeDB Generated QueryBuilder
import e from '../../client';

builder.queryType({
  fields: (t) => ({
    users: t.edgeDBField({
      type: ['User'],
      nullable: true,
      resolve: async (_query, _parent, _args, ctx) => {
        const users = await e
          .select(e.User, (user) => ({
            id: true,
            email: true,
            name: true,
          }))
          .run(db);

        return users;
        //      ^? { id: string; email:string; name: string | null; }[]
        // This would not match with  Users Model["Shape"], comments | posts ... are missing
      },
    }),
  }),
});

interface EdgeDBModelTypes {
  User: {
    Shape: {
      "comments": Comment[];
      "posts": Post[];
      "email": string;
      "name"?: string | null;
      "followers": Follow[];
      "following": Follow[];
      "media": Media[];
      "profile"?: Profile | null;
    }
  }
}

baristikir avatar Aug 22 '22 11:08 baristikir

Added ReturnShape to reflect Shape props as optional fields.

https://github.com/hayes/pothos/blob/f853b76a8a0bc58ec6fa9b4578bb7aa706515958/packages/plugin-edgedb/src/types.ts#L80-L86

https://github.com/hayes/pothos/blob/f853b76a8a0bc58ec6fa9b4578bb7aa706515958/packages/plugin-edgedb/src/global-types.ts#L102-L104

baristikir avatar Aug 22 '22 11:08 baristikir

Added ReturnShape to EdgeDBModelTypes to reflect optional fields from Shape.

https://github.com/hayes/pothos/blob/f853b76a8a0bc58ec6fa9b4578bb7aa706515958/packages/plugin-edgedb/src/types.ts#L80-L86

Actually supposed to be a deep partial type, updated version:

https://github.com/baristikir/giraphql/blob/8ec9e25d91d12fa9059a8ec0314c8b493944444e/packages/plugin-edgedb/src/types.ts#L72-L88

baristikir avatar Aug 22 '22 14:08 baristikir

Edgedb queries return type depends on the select shape. Even ...e.User["*"] won't load the whole db schema. That would be a problem for edgeDBField resolve functions return type since Model["Shape"] won't be the return type at any time. Instead the return type needs to be composed of optional fields. We might not wanna loose the actual nullability of model properties in Model["Shape"], important for edgeDBObject field definitions. So defining another Shape type as the optional reflection looks like a solution.

I think the technically correct approach here would be to model this after the "select" mode from the prisma plugin. Basically the prisma plugin supports having a default set of selections defined on the "prismaObject", when you do this, the "parent" type for all resolvers is limited to that selection. You can still "expose" fields that are not part of the selection (which will automatically select them when the expsosed field is queried) . You can then also define selections on individual fields, which will extend the parent type in the resolver for that field.

You can see an example of this here: https://github.com/hayes/pothos/blob/main/packages/plugin-prisma/tests/example/schema/index.ts#L38-L59

The implementation for this gets a lot more complicated, so not sure if you need to explore this in the initial version. Took me a few iterations of the prisma plugin before I figured out how to make that work properly.

hayes avatar Aug 22 '22 16:08 hayes