sequelize-typescript icon indicating copy to clipboard operation
sequelize-typescript copied to clipboard

belongsToMany and converting circular structure to JSON

Open ivan-ionin opened this issue 4 years ago • 2 comments

Issue

Versions

  • sequelize: 6.1.1
  • sequelize-typescript: 2.1.0
  • typescript: 4.2.3

Issue type

  • [x] bug report
  • [ ] feature request

Actual behavior

I use dialect postgres.

I try to release RBAC and it is my defined models:

// primitive.model.ts
export abstract class PrimitiveModel extends Model {
    
    @PrimaryKey
    @AutoIncrement
    @Column({ field: 'id', type: DataType.INTEGER, comment: 'Идентификатор записи в таблице', })
    id;

    @CreatedAt
    @Column({ field: 'created_at', type: DataType.DATE, comment: 'Дата создания записи', })
    createdAt;

    @UpdatedAt
    @Column({ field: 'updated_at', type: DataType.DATE, comment: 'Дата обновления записи', })
    updatedAt;
}
// dictionary.model.ts
export abstract class DictionaryModel extends PrimitiveModel {
    
    @Column({ field: 'code', type: DataType.STRING(64), allowNull: true, comment: 'Код записи в словаре', })
    code;

    @Column({ field: 'name', type: DataType.STRING(128), allowNull: true, comment: 'Название записи в словаре', })
    name;

    @Column({ field: 'description', type: DataType.TEXT, allowNull: true, comment: 'Описание записи в словаре', })
    description;

    @Column({ field: 'active', type: DataType.BOOLEAN, defaultValue: true, comment: 'Флаг активности записи в словаре', })
    active;

    @Column({ field: 'weight', type: DataType.SMALLINT, defaultValue: 0, comment: 'Сортировочный вес записи в словаре', })
    weight;
}

// And next my rbac models

// roles.model.ts
@Table({
    modelName: 'roles',
    tableName: genTableName('roles'),
    schema: DATABASE_CONNECTION[process.env.NODE_ENV].schema,
    charset: 'utf8'
})
export class RolesModel extends DictionaryModel {

    @BelongsToMany(() => PermissionsModel, () => RolesToPermissionsModel)
    permissions: PermissionsModel[];
}
// permissions.model.ts
@Table({
    modelName: 'permissions',
    tableName: genTableName('permissions'),
    schema: DATABASE_CONNECTION[process.env.NODE_ENV].schema,
    charset: 'utf8'
})
export class PermissionsModel extends DictionaryModel {

    @BelongsToMany(() => RolesModel, () => RolesToPermissionsModel)
    roles: RolesModel[];
}
// roles.to.permissions.model.ts
@Table({
    modelName: 'rolesToPermissions',
    tableName: genTableName('roles_to_permissions'),
    schema: DATABASE_CONNECTION[process.env.NODE_ENV].schema,
    charset: 'utf8'
})
export class RolesToPermissionsModel extends PrimitiveModel {
    
    @ForeignKey(() => RolesModel)
    @Column({ field: 'role_id', type: DataType.INTEGER })
    roleId;

    @ForeignKey(() => PermissionsModel)
    @Column({ field: 'permission_id', type: DataType.INTEGER })
    permissionId;
}

Steps to reproduce

So, i define these models and now i want to get data:

this.db = new Sequelize({
  ...connection,
  models: [
        RolesToPermissionsModel,
        PermissionsModel,
        RolesModel,
        ...,
    ],
});
Promise.all([
    this.db.model('roles').findAll({
        where: { active: true },
        order: [[ 'weight', 'ASC' ]],
        include: [{
            model: this.db.model('permissions'),
            as: 'permissions',
        }],
    }),
]).then((results: any[]) => {
    //
}).catch((error) => {
    //
});

... and i catch error:

(node:25860) UnhandledPromiseRejectionWarning: TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Array'
    |     index 0 -> object with constructor 'Object'
    |     property 'parent' -> object with constructor 'Object'
    --- property 'include' closes the circle
    at SequelizeClass.log (***\node_modules\sequelize\lib\sequelize.js:1171:15)

Expected behavior

I think i need to get roles list with permissions inside.

I take belongsToMany example from docs and change only tables names (+/-). Maybe i do something wrong?

I got result, but exception to. Exception disappear if i remove include. But permissions disappear to )))

Thanks for help!

ivan-ionin avatar Jul 13 '21 22:07 ivan-ionin

Hey, did you manage to solve this issue ? Have the same problem right now...

r-guerin avatar Sep 06 '22 13:09 r-guerin

So, I had this issue and spent almost a day until I found out the issue was with my custom logging framework which does a JSON.stringify in order to print some Sequelize models... and because they're linked (@ HasMany and @BelongsTo) the object passed inside the Sequelize's guts (which was being intercepted by my logging library) had this circular reference. I only realised that after disabling my logging (I was going to use a console.log in order to get more info - because I've already thought my logging library could be hiding some useful info).

So, in practice, nothing wrong with Sequelize or Sequelize-Typescript.. make sure you're not using JSON.stringify messing with you somewhere.

mariojunior avatar Jan 23 '24 03:01 mariojunior