powerhouse-inc / switchboard

Open-source API over the document model made to be developer- and analyst-friendly
https://switchboard-boilerplate.vercel.app
GNU Affero General Public License v3.0
2 stars 2 forks source link

Do not redefine db models for graphql #18

Closed valiafetisov closed 1 year ago

valiafetisov commented 1 year ago

Goal

Remove the need to define models again for nexus

Context

After merging https://github.com/makerdao-ses/switchboard-boilerplate/pull/15 the outstanding task was to explore possibility to derive nexus types from the prisma model definition. According to prisma graphql page, it should be easily integrable with graphql. To integrate with nexus, they recommend nexus-plugin-prisma generator.

Tasks

valiafetisov commented 1 year ago

Outcome

Unfortunately this doesn't seem possible.

Suggested nexus-plugin-prisma package was written by the nexus community, but currently deprecated and hasn't been updated for 1.5 years.

The replacement nexus-prisma package that they recommend instead doesn't have this feature. It generates something from the prisma types (ie an object with some values as in the model), but not a nexus type, nexus type still have to be defined by hand using those returned parameters:

import { User } from 'nexus-prisma'
import { objectType } from 'nexus'

objectType({
  name: User.$name
  description: User.$description
  definition(t) {
    t.field({
      type: User.id.type,
      description: User.id.description
    })
  }
})

Source: https://graphql-nexus.github.io/nexus-prisma/docs/features#type-safe-generated-library-code

After trying it out, generated CoreUnit object from the prisma model, logged into the console:

CoreUnit {
  '$name': 'CoreUnit',
  '$description': undefined,
  id: {
    name: 'id',
    type: NexusNonNullDef { ofNexusType: 'ID', _isNexusNonNullDef: true },
    description: undefined,
    resolve: undefined
  },
  code: {
    name: 'code',
    type: NexusNonNullDef { ofNexusType: 'String', _isNexusNonNullDef: true },
    description: undefined,
    resolve: undefined
  },
  shortCode: {
    name: 'shortCode',
    type: NexusNonNullDef { ofNexusType: 'String', _isNexusNonNullDef: true },
    description: undefined,
    resolve: undefined
  },
  name: {
    name: 'name',
    type: NexusNonNullDef { ofNexusType: 'String', _isNexusNonNullDef: true },
    description: undefined,
    resolve: undefined
  },
  imageSource: {
    name: 'imageSource',
    type: NexusNonNullDef { ofNexusType: 'String', _isNexusNonNullDef: true },
    description: undefined,
    resolve: undefined
  },
  descriptionSentence: {
    name: 'descriptionSentence',
    type: NexusNonNullDef { ofNexusType: 'String', _isNexusNonNullDef: true },
    description: undefined,
    resolve: undefined
  },
  descriptionParagraph: {
    name: 'descriptionParagraph',
    type: NexusNonNullDef { ofNexusType: 'String', _isNexusNonNullDef: true },
    description: undefined,
    resolve: undefined
  },
  descriptionParagraphImageSource: {
    name: 'descriptionParagraphImageSource',
    type: NexusNonNullDef { ofNexusType: 'String', _isNexusNonNullDef: true },
    description: undefined,
    resolve: undefined
  }
}

I even thought of transforming this object into the nexus type ourself, but the type produced by the objectType() function, that we actually need looks quite different and not directly convertible:

export const CoreUnit = objectType({
  name: 'CoreUnit',
  definition(t) {
    t.string('id');
    t.string('code');
    t.string('shortCode');
    t.string('name');
    t.string('imageSource');
    t.string('descriptionSentence');
    t.string('descriptionParagraph');
    t.string('descriptionParagraphImageSource');
  },
});

This package currently can only be useful for passing docstrings (eg description of the model) from prisma models to graphql types, but doesn't solve our main pain.