Skip to content
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

ValidationError: Employee entity is missing @PrimaryKey() #115

Closed
gustavopch opened this issue Sep 9, 2019 · 4 comments
Closed

ValidationError: Employee entity is missing @PrimaryKey() #115

gustavopch opened this issue Sep 9, 2019 · 4 comments

Comments

@gustavopch
Copy link

gustavopch commented Sep 9, 2019

I have three entities: Employee, which extends User, which extends StandardEntity. I'm getting the error: ValidationError: Employee entity is missing @PrimaryKey() when initializing mikro-orm. It seems that mikro-orm goes only to the first extends to look for the @PrimaryKey. It does work fine with other entities that directly extends StandardEntity but not when inheritance is nested in multiple levels.

standard-entity.ts:

import { IEntity, PrimaryKey, Property } from 'mikro-orm'
import { ObjectId } from 'mongodb'
import { Field, ID } from 'type-graphql'

export abstract class StandardEntity {
  @PrimaryKey()
  readonly _id: ObjectId

  @Field(type => ID)
  id: string

  @Property()
  @Field()
  createdAt: Date

  @Property({ onUpdate: () => new Date() })
  @Field()
  updatedAt: Date

  constructor() {
    const id = new ObjectId()
    this._id = id
    this.id = id.toHexString()

    const now = new Date()
    this.createdAt = now
    this.updatedAt = now
  }
}

export interface StandardEntity extends IEntity<string> {}

user.ts:

import { IsEmail } from 'class-validator'
import { Property } from 'mikro-orm'
import { Field, InterfaceType } from 'type-graphql'

import { Language, StandardEntity } from '@/shared'
import { UserType } from '@/user'

@InterfaceType({
  resolveType: value => (value.type === 'customer' ? 'Customer' : 'Employee'),
})
export abstract class User extends StandardEntity {
  @Property()
  @Field()
  blocked: boolean = false

  @Property()
  @Field()
  displayName: string

  @Property()
  @Field()
  fullName: string

  @Property()
  @Field()
  @IsEmail()
  email: string

  @Property()
  @Field({ nullable: true })
  phoneNumber?: string

  @Property()
  @Field({ nullable: true })
  photoUrl?: string

  @Property()
  @Field(type => Language)
  lang: Language

  @Property()
  @Field({ nullable: true })
  identityNumber?: string

  @Property()
  @Field(type => UserType)
  type: UserType

  constructor(
    displayName: string,
    fullName: string,
    email: string,
    phoneNumber: string | undefined,
    photoUrl: string | undefined,
    lang: Language,
    identityNumber: string | undefined,
    type: UserType,
  ) {
    super()
    this.displayName = displayName
    this.fullName = fullName
    this.email = email
    this.phoneNumber = phoneNumber
    this.photoUrl = photoUrl
    this.lang = lang
    this.identityNumber = identityNumber
    this.type = type
  }
}

employee.ts:

import { Entity, Property } from 'mikro-orm'
import { Field } from 'type-graphql'

import { Language } from '@/shared'
import { EmployeeRole, UserType } from '@/user'

import { User } from './user'


@Entity({ collection: 'users' })
export class Employee extends User {
  @Property()
  @Field(type => EmployeeRole)
  role: EmployeeRole

  constructor(
    displayName: string,
    fullName: string,
    email: string,
    phoneNumber: string | undefined,
    photoUrl: string | undefined,
    lang: Language,
    identityNumber: string | undefined,
    role: EmployeeRole,
  ) {
    super(
      displayName,
      fullName,
      email,
      phoneNumber,
      photoUrl,
      lang,
      identityNumber,
      UserType.EMPLOYEE,
    )

    this.role = role
  }
}
@B4nan
Copy link
Member

B4nan commented Sep 9, 2019

Currently only one level of abstraction is allowed. We can definitely support multi-level inheritance, but the result will still be multiple tables/collections (e.g. there will be employee collection and there won't be any user collection).

If you would like to have user collection and multiple possible entities (based on their role) all stored in that collection, we would need to implement single table inheritance. There is already issue for that #33, but I am not planning to work on that soon (other features like composite keys have higher priority). Although I would like to support it probably in one of v3.x feature releases.

@gustavopch
Copy link
Author

@B4nan Oh, that's bad. I'll try to find a workaround. Thanks for the explanation.

@B4nan
Copy link
Member

B4nan commented Sep 9, 2019

I'll close this one when multi-level inheritance itself will be supported. Feel free to subscribe to #33 for STI. Obviously I am open for PRs, but it won't be easy I guess...

@B4nan B4nan added bug Something isn't working and removed bug Something isn't working labels Sep 9, 2019
@B4nan
Copy link
Member

B4nan commented Sep 10, 2019

Tried to play with this for a while but it turns out it does not make much sense to support it without STI, so I will close this one in favour of #33.

@B4nan B4nan closed this as completed Sep 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants