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

Problem when adding models #465

Closed
eBuccaneer opened this issue Oct 2, 2018 · 12 comments
Closed

Problem when adding models #465

eBuccaneer opened this issue Oct 2, 2018 · 12 comments

Comments

@eBuccaneer
Copy link

eBuccaneer commented Oct 2, 2018

Hi,

i have two models:

@Table
export default class User extends Model<User> {
    @Column
    name: string;

    @HasMany(() => Address)
    addresses: Address[];
}

and:

@Table
export default class Address extends Model<Address> {
    @Column
    street: string;

    @ForeignKey(() => User)
    @Column
    userId: number;

    @BelongsTo(() => User)
    user: User;

}

But when I start the app, it fails at sequelize.addModels([/** models */]) with:

Error: User.hasMany called with something that's not a subclass of Sequelize.Model
    at Function.hasMany (/node_modules/sequelize/lib/associations/mixin.js:19:13)

So I tracked it down to this inside of mixins.js hasMany() function:

target.prototype instanceof this.sequelize.Model

which is unfortunately false somehow.
Removing it inside of hasMany() and singleLinked() in mixins.js lets the application start normally without errors and the database tables are created correctly too, but thats pretty dirty and i assume future errors will pop up.

I would appreciate any help on how to solve this, thank you!



Update:

Used versions:

    "sequelize": "^4.39.0",
    "sequelize-typescript": "^0.6.6"
@RobinBuschmann
Copy link
Member

Hey @eBuccaneer, can you provide an example repo, which reproduces the issue? From what I can see , your model setup looks good.

@eBuccaneer
Copy link
Author

Hey, thanks for the quick reply @RobinBuschmann!

I have figured out my problem by now, it was that I have a shared module with own dependencies and node_modules that includes the sequelize model classes, and a server module, where I create the sequelize instance, add models (from the shared module), and sync the database.
After forcing the shared module and the server module to use the same sequelize-typescript package(from same node_modules directory), it worked again.
This problem only occurs when dealing with multiple related models, if there is only model class (without @HasMany etc.), everything is fine.

If you still need the repo to reproduce the error, just drop a message.

@RobinBuschmann
Copy link
Member

No, thanks, thats not necessary anymore. Good to here that you figured it out!

@franky47
Copy link

I ended up with the same problem: I'm building a shared module that initializes the Sequelize connection, whereas models are defined per-application in their respective app modules (that consume the shared module as a dependency).

As soon as I try adding associations between models (even though all models are defined in the same app module), I end up with the same error:

xxx.yyy called with something that's not a subclass of Sequelize.Model

From what the node_modules structure looks like, there are two different locations where the sequelize-typescript (and sequelize peer) modules are installed:

node_modules/
  sharedModule/
    node_modules/
      sequelize/
      sequelize-typescript/    // sharedModule uses this to setup the connection
  ...
  // Those are hoisted from the dependency on sharedModule:
  sequelize/
  sequelize-typescript/        // app-level models use this

This is what I had to do in order for associations in models to work:

- import { Model } from 'sequelize-typescript'
+ import { Model } from 'sharedModule/node_modules/sequelize-typescript'

@eBuccaneer is it how you solved it in your case ? It seems hackish, since some package managers might use a different layout for node_modules, but for app-level modules (which aren't usually depended upon and where the primary user controls the PM used), it seems to work.

@eBuccaneer
Copy link
Author

@franky47 I ended up installing the sequelize-typescript dependency only once in the project root and not in the specific module directories, so every module that depends on it uses the same.
And yes it feels hackish, but it suits our needs.

@rvalim
Copy link

rvalim commented Jun 18, 2019

Hi guys,

I am facing the same error here! When I use the sync method, it creates all the database with all the dependencies, normally and correct. But now I am using the cli-typescript to run migrations and seeders, which works, but when I try to instantiate the Sequelize get the same error.

Already tried the @canary, the @next version from sequelize-typescript, and nothing works, can you see what I am missing?

The error:

throw new Error(this.name + '.' + Utils.lowercaseFirst(Type.toString()) + ' called with something that's not a subclass of Sequelize.Model');
^
Error: Access.class BelongsTo extends Association

My package.json:

  • "sequelize": "^4.44.0",
  • "sequelize-cli-typescript": "^3.2.0-c",
  • "sequelize-typescript": "^0.6.11"

How it is being instantiate

const sequelizeconnection = new Sequelize({
      operatorsAliases: Sequelize.Op as any,
      name: env.database,
      username: env.username,
      password: env.password,
      dialect: env.dialect,
      host: env.host,
      modelPaths: [path.join(__dirname, '../../src/models/!(index).ts')]
    });

The code:

Access.ts

import {
  Table,
  Column,
  Model,
  CreatedAt,
  UpdatedAt,
  DeletedAt,
  BelongsTo,
  ForeignKey
} from "sequelize-typescript";
import { Action } from "./Action";
import { Resource } from "./Resource";

@Table
export class Access extends Model<Access> {
  @Column({
    allowNull: false
  })
  public route: string;

  @Column({
    allowNull: false
  })
  public method: string;

  @BelongsTo(() => Action, "actionId")
  public action: Action;

  @ForeignKey(() => Action)
  @Column({
    allowNull: false
  })
  public actionId: number;

  @BelongsTo(() => Resource, "resourceId")
  public resource: Resource;

  @ForeignKey(() => Resource)
  @Column({
    allowNull: false
  })
  public resourceId: number;

  @CreatedAt
  public creationDate: Date;

  @UpdatedAt
  public updatedOn: Date;

  @DeletedAt
  public deletionDate: Date;
}

Action.ts: Has references to another models

import {
  Table,
  Column,
  Model,
  HasMany,
  CreatedAt,
  UpdatedAt,
  DeletedAt
} from "sequelize-typescript";
import { Grant } from "./Grant";

@Table
export class Action extends Model<Action> { 
...
}

Resource.ts: Has references to another models

import {
  Table,
  Column,
  Model,
  HasMany,
  CreatedAt,
  UpdatedAt,
  DeletedAt
} from "sequelize-typescript";
import { Grant } from "./Grant";

@Table
export class Resource extends Model<Resource> {
...
}

Tks

@RobinBuschmann
Copy link
Member

Hey @rvalim, can you provide an example repo which reproduces the issue please?

@rvalim
Copy link

rvalim commented Jun 18, 2019

Hi @RobinBuschmann I copied the original branch to here

Using the project gama-auth, follow the instructions:

  • create a new postgres database
  • get the IP address, and substitute on DATABASE_URL from ./services/gama-auth/env/node.env

on the folder ./services/gama-auth run the bash bellow

cd ./services/gama-auth/db
npm i 
npx tsc
rm -rf node_modules

cd ..
npm i
bash ./scripts/run.sh

Sorry but it is a little bit verbose.

Thank you so much

@RobinBuschmann
Copy link
Member

Hey @rvalim I didn't get any errors. Can you provide a simpler example?

@rvalim
Copy link

rvalim commented Jun 21, 2019

When I run my application returns the mentioned error.

Just tried to use the sequelize-cli instead of sequelize-cli-typescript, everything worked just fine.

Bellow my package.json config, do you see any problem of doing like this? When I run sequelize model:generation it creates the js version, but I can create the models by myself.

    "sequelize": "^4.44.0",
    "sequelize-cli": "^5.5.0",
    "sequelize-typescript": "^0.6.11"

Tks

@RobinBuschmann
Copy link
Member

Since sequelize-cli-typescript doesn't seem to be maintained anymore, its definitely better to use sequelize-cli instead. In general I cannot recommend the one or the other, because I never used these tools. Sry

@rvalim
Copy link

rvalim commented Jun 21, 2019

thank you @RobinBuschmann

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

4 participants