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

Undefined metadata when persisting a collection #3180

Closed
jwaaang opened this issue Jun 3, 2022 · 16 comments
Closed

Undefined metadata when persisting a collection #3180

jwaaang opened this issue Jun 3, 2022 · 16 comments

Comments

@jwaaang
Copy link

jwaaang commented Jun 3, 2022

Describe the bug
A clear and concise description of what the bug is.

Stack trace

    console.log
      [query] rollback

      at DefaultLogger.log (../../../.yarn/__virtual__/@mikro-orm-core-virtual-ba48361820/0/cache/@mikro-orm-core-npm-5.1.5-782f2c15b5-c670518c62.zip/node_modules/@mikro-orm/core/logging/DefaultLogger.js:31:14)

  ● test › create execution

    Error: Error: TypeError: Cannot read properties of undefined (reading 'properties')

      at Collection.get property [as property] (../../../.yarn/__virtual__/@mikro-orm-core-virtual-ba48361820/0/cache/@mikro-orm-core-npm-5.1.5-782f2c15b5-c670518c62.zip/node_modules/@mikro-orm/core/entity/ArrayCollection.js:140:44)
      at Collection.[nodejs.util.inspect.custom] (../../../.yarn/__virtual__/@mikro-orm-core-virtual-ba48361820/0/cache/@mikro-orm-core-npm-5.1.5-782f2c15b5-c670518c62.zip/node_modules/@mikro-orm/core/entity/ArrayCollection.js:196:55)
      at PipelineStage.meta.<computed> (../../../.yarn/__virtual__/@mikro-orm-core-virtual-ba48361820/0/cache/@mikro-orm-core-npm-5.1.5-782f2c15b5-c670518c62.zip/node_modules/@mikro-orm/core/entity/EntityHelper.js:119:48)
      This is caused by either a bug in Node.js or incorrect usage of Node.js internals.
      Please open an issue with this stack trace at https://github.com/nodejs/node/issues
      at PipelineStage.meta.<computed> (../../../.yarn/__virtual__/@mikro-orm-core-virtual-ba48361820/0/cache/@mikro-orm-core-npm-5.1.5-782f2c15b5-c670518c62.zip/node_modules/@mikro-orm/core/entity/EntityHelper.js:119:48)
      This is caused by either a bug in Node.js or incorrect usage of Node.js internals.
      Please open an issue with this stack trace at https://github.com/nodejs/node/issues
      at Collection.[nodejs.util.inspect.custom] (../../../.yarn/__virtual__/@mikro-orm-core-virtual-ba48361820/0/cache/@mikro-orm-core-npm-5.1.5-782f2c15b5-c670518c62.zip/node_modules/@mikro-orm/core/entity/ArrayCollection.js:195:40)
      This is caused by either a bug in Node.js or incorrect usage of Node.js internals.
      Please open an issue with this stack trace at https://github.com/nodejs/node/issues
      at PipelineExecution.meta.<computed> (../../../.yarn/__virtual__/@mikro-orm-core-virtual-ba48361820/0/cache/@mikro-orm-core-npm-5.1.5-782f2c15b5-c670518c62.zip/node_modules/@mikro-orm/core/entity/EntityHelper.js:119:48)
      at Function.propertyRequired (../../../.yarn/__virtual__/@mikro-orm-core-virtual-ba48361820/0/cache/@mikro-orm-core-npm-5.1.5-782f2c15b5-c670518c62.zip/node_modules/@mikro-orm/core/errors.js:64:154)

To Reproduce
Steps to reproduce the behavior:
I have two entities:

@Entity()
export class Execution extends BaseEntity {
  @ManyToOne()
  task?: Task;

  @ManyToMany(() => Stage, Stage => Stage.executions)
  stages = new Collection<Stage>(this);

  @Property()
  active?: boolean = false;

  constructor(id?: string) {
    super(id);
  }
}

and

@Entity()
export class Stage extends BaseEntity {
  @Property()
  project?: string;

  @ManyToMany(() => Execution, execution => Execution.stages, {
    owner: true,
  })
  executions = new Collection<Execution>(this);
}

when i try to persist a new Execution entity:

execution = new Execution(executionId);
const exec = this.em.create(Execution, execution);
this.em.persist(exec);
await this.em.flush();

I get the above error.

Expected behavior
I expect the flush to go thru.

Additional context
https://github.com/mikro-orm/mikro-orm/blob/master/packages/core/src/entity/ArrayCollection.ts#L170
seems like this is the LoC that's breaking.

Also this is being run inside a nestJS service using "@mikro-orm/nestjs": "^5.0.1".

Running it on debug mode shows all the entities being discovered properly.

Versions

Dependency Version
node 16.13.0
typescript 4.2.3
mikro-orm 5.1.4
your-driver 5.7.25-TiDB-v6.1.0
@jwaaang
Copy link
Author

jwaaang commented Jun 3, 2022

I changed the metadata provider to:

metadataProvider: TsMorphMetadataProvider,

and it now works. Strange that the ReflectMetadataProvider did not work

@B4nan
Copy link
Member

B4nan commented Jun 3, 2022

You should pass a POJO to em.create, not entity instance. Moreover that error seems to be coming from serializing/logging, not flushing.

@B4nan B4nan closed this as completed Jun 3, 2022
@B4nan
Copy link
Member

B4nan commented Jun 3, 2022

actually not, its coming from validation of required properties, your task property is missing entity option:

  @ManyToOne(() => Task)
  task?: Task;

I will add better error handling around this, you should get a "missing metadata error" instead.

ts-morph works fine because it extracts the target entity name from TS compiler API directly. your entity definition is missing many things, like nullable: true as well, those things can be extracted from TS only with ts-morph, reflect-metadata wont allow it

B4nan added a commit that referenced this issue Jun 3, 2022
@jwaaang
Copy link
Author

jwaaang commented Jun 6, 2022

Hi. Thanks for the response. That makes sense.

Also, on the topic of em.create, I'm actually having some trouble understanding what should happen here.

Originally I had:

execution = new Execution(params.executionId);
await em.persistAndFlush(execution);

but doing this i get this error:

ValidationError: Trying to persist not discovered entity of type Execution. Entity with this name was discovered, but not the prototype you are passing to the ORM. If using EntitySchema, be sure to point to the implementation via `class`.

so i started doing the .create

but looking at the docs it should be totally fine for me to just persist the entity class no?

@B4nan
Copy link
Member

B4nan commented Jun 6, 2022

You are using different class than the one that was discovered, exactly as that error says. How does your config look like? Do you set the tsNode option explicitly?

@jwaaang
Copy link
Author

jwaaang commented Jun 6, 2022

this is what i have in my config:

const config: Options = {
  entities: ['./dist/**/*.entity.js'],
  entitiesTs: ['./src/**/*.entity.ts'],
  dbName: 'task-pipeline',
  type: 'mysql',
  port: 4000, // TiDB default port
  migrations: {
    path: 'dist/migrations',
    pathTs: 'src/migrations',
  },
  autoLoadEntities: true,
  debug: true,
  metadataProvider: TsMorphMetadataProvider,
};

moreover it looks like entity is discovered fine:

console.log
      [discovery] - processing entity Execution

@B4nan
Copy link
Member

B4nan commented Jun 6, 2022

moreover it looks like entity is discovered fine:

yes it is, but its not the same class as you use in your code. maybe you import it from dist or something like that?

@jwaaang
Copy link
Author

jwaaang commented Jun 6, 2022

ah i see what's happening. the entity that is discovered is actually from dist instead of src and is the js file.

how do i make it discover from src instead?

@B4nan
Copy link
Member

B4nan commented Jun 6, 2022

you can force that via tsNode: true but keep in mind you should not have that in your production config

@B4nan
Copy link
Member

B4nan commented Jun 6, 2022

it should be detected automatically, how do you run your app?

@jwaaang
Copy link
Author

jwaaang commented Jun 6, 2022

using nest. i am testing right now using jest.

so should i have a different config for prod and testing? and in prod it should automatically pick up the .ts entities?

@jwaaang
Copy link
Author

jwaaang commented Jun 6, 2022

using tsNode: true made the test work!

@B4nan
Copy link
Member

B4nan commented Jun 6, 2022

ts-jest should be detected if you are on latest versions, or do you use something else for TS support?

@jwaaang
Copy link
Author

jwaaang commented Jun 6, 2022

i am using "ts-jest": "^26.5.4", and have this for my jest config:

"jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".*\\.spec\\.ts$",
    "transform": {
      "^.+\\.ts$": "ts-jest"
    },
    "collectCoverageFrom": [
      "**/*.(t|j)s"
    ],
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  },

@B4nan
Copy link
Member

B4nan commented Jun 6, 2022

yes, thats quite old version, upgrade and it should work automatically, you need 27.0.4+ i guess

kulshekhar/ts-jest#2717

@jwaaang
Copy link
Author

jwaaang commented Jun 6, 2022

ah that did it! works now even without the tsnode config

thanks so much @B4nan

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