Vincit / objection-graphql

GraphQL schema generator for objection.js
MIT License
307 stars 34 forks source link

Problems with `build()`, relation class in Models are not being recognized #66

Closed Trellian closed 5 years ago

Trellian commented 5 years ago

Hi,

I have encountered a problem that I can't fathom. Please, if anyone can see what I did wrong, I would appreciate the help greatly.

I have two models, CvDevice and CvAccessMap, with a 1:M relation between them, as cv_device.id = cv_access_map.device_id

When I call build(), I get the following error: Error: relation type "BelongsToOneRelation" is not supported in SchemaBuilder.js, in function

 _relationField(modelData, relation) {
    if (relation instanceof objection.HasOneRelation
      || relation instanceof objection.BelongsToOneRelation
      || relation instanceof objection.HasOneThroughRelation) {
      return {
        type: this._typeForModel(modelData),
        args: _.omit(modelData.args, OMIT_FROM_RELATION_ARGS),
      }
    } else if (relation instanceof objection.HasManyRelation || relation instanceof objection.ManyToManyRelation) {
      return {
        type: new GraphQLList(this._typeForModel(modelData)),
        args: _.omit(modelData.args, OMIT_FROM_RELATION_ARGS),
      }
    }
    throw new Error(`relation type "${relation.constructor.name}" is not supported on ${modelData.modelClass.tableName}`)
  }

The two models look fine, I really can't see what could be causing this. I have tried several things, but it seems like the relation type is not correctly assigned a Model relation class as expected.

This was previously working with objection: ^0.9.4 and objection-graphql: ^0.2.3.
I've recently upgraded to objection: ^1.3.0 and objection-graphql: ^0.4.2.

Obviously something substantial has changed, but I can't see what.

Any and all help will be appreciated!

Here is the code for the build():

...
const graphQlBuilder = require('./objection-graphql').builder
const objection = require('objection')

// Initialize knex connection.
const knex = require('knex')({ 
  client: 'mysql',
  connection: {
    host: 'localhost',
    user: 'xxxxxxx',
    password: 'xxxxxxx',
    database: 'icam',
  },
})

const Model = objection.Model

// Give the connection to objection.
Model.knex(knex)

import { CvAccessMapBaseModel } from './schema/objection/base/CvAccessMapBaseModel.js'
import { CvDeviceBaseModel } from './schema/objection/base/CvDeviceBaseModel'

const graphQlSchema = graphQlBuilder()
  .model(CvAccessMapBaseModel)
  .model(CvDeviceBaseModel)
  .build()

and the two models:

// file: CvAccessMapBaseModel.js
const { Model } = require('objection')

export class CvAccessMapBaseModel extends Model {

  // Table name is the only required property.
  static get tableName() {
    return 'cv_access_map'
  }

  static get jsonSchema () {
    return {
      type: 'object',
      required: [
      ],

      properties: {
        id: {type: 'integer'},            
        user_id: {type: 'integer'},            
        group_id: {type: 'integer'},            
        device_id: {type: 'integer'},            
        location_id: {type: 'integer'},            
        b_excluded: {type: 'boolean'}
      }
    }
  }

  // This object defines the relations to other models.
  static get relationMappings() {

    return {

      // Parent Relations    

      cvDevice: {
        relation: Model.BelongsToOneRelation,   // **** Fails to recognize this assignment when build() is called ****
        modelClass: __dirname + '/CvDeviceBaseModel',
        join: {
          from: 'cv_access_map.device_id',
          to: 'cv_device.id'
        }
      },
    }
  }
}

and

// file: CvDeviceBaseModel.js

import {Model} from 'objection'

export class CvDeviceBaseModel extends Model {

  // Table name is the only required property.
  static get tableName() {
    return 'cv_device'
  }

    static get jsonSchema () {
    return {
      type: 'object',
      required: [

        'client_id',
        'location_id',
        'device_uid',
        'name',
        'sort_order',
        'device_type',
        'user_id'
      ],

      properties: {

        id: {type: 'integer'},            
        client_id: {type: 'integer'},            
        location_id: {type: 'integer'},            
        device_uid: {type: 'string'},            
        imei: {type: 'string'},            
        name: {type: 'string'},            
        sort_order: {type: 'number'},            
        placed_on: {type: 'string'},            
        device_type: {type: 'string'},            
        user_id: {type: 'integer'}
      }
    }
  }

  // This object defines the relations to other models.
  static get relationMappings() {

    return {

      cvAccessMaps: {
        relation: Model.HasManyRelation,
        modelClass: __dirname + '/CvAccessMapBaseModel',
        join: {
          from: 'cv_access_map.device_id',
          to: 'cv_device.id'                
        }    
      },
    }
  }
}

Thanks in advance, Adrian