Payerl
Payerl

Reputation: 1090

Use ENUM with Sequelize and Typescript

I'm trying to create a API with a USER class that can have more then one way of authenticating itself with the API.

I have managed to get it working with 1 user only having 1 credential but when trying to expand to allow multiple credentials then I got error: UnhandledPromiseRejectionWarning: SequelizeDatabaseError: (conn=498, no: 1265, SQLState: 01000) Data truncated for column 'type' at row 1

What I currently have is this:

User.hasMany(Credential, { foreignKey: 'id', sourceKey: 'id' });

And this:

//Credential.ts
export function CredentialInit(sequelize: Sequelize) {
    let cred = Object.keys(CredentialType);
    let credArr: string[] = [];
    for(let i = 0; i < cred.length/2; i++) {
        credArr.push(`${i}`);
    };
    Credential.init({
        email: {
            type: DataTypes.STRING,
            allowNull: true
        },
        password: {
            type: DataTypes.STRING,
            allowNull: true
        },
        token: {
            type: DataTypes.STRING,
            allowNull: true
        },
        type: {
            type: DataTypes.ENUM,
            values: credArr,
            allowNull: false
        }
    }, {
        sequelize: sequelize,
        tableName: 'credentials'
    });
}

export enum CredentialType {
    EMAIL,
    TOKEN
}

export class Credential extends BaseModel {
    public type!: CredentialType;
    public token?: string;
    public email?: string;
    public password?: string;
}

Also have this Model to remove these stuff from all my other models.

//BaseModel.ts
export class BaseModel extends Model {
    public id?: number;
    public readonly createdAt?: Date;
    public readonly updatedAt?: Date;
}

Any clue why I get this message? I have written it like this because I do not want to have to declare the content of the enum twice.. If changed I want it to change everywhere....

Upvotes: 5

Views: 11389

Answers (2)

James Craig
James Craig

Reputation: 6864

Since an enum in TypeScript is a value, you can spread the enum values into the DataTypes.ENUM of Sequelize, like this:

enum CredentialType {
  EMAIL,
  TOKEN
}

Credential.init({
  // ...
  type: {
    type: DataTypes.ENUM(...Object.values(CredentialType)),
    allowNull: false
  }
}, {
  sequelize: sequelize,
  tableName: 'credentials'
});

Or with the sequelize-typescript library, like this:

import { Column, DataType, Model, Table } from "sequelize-typescript";

enum CredentialType {
  EMAIL = "EMAIL",
  TOKEN = "TOKEN",
}

@Table
class Credential extends Model {
  @Column({
    defaultValue: CredentialType.EMAIL,
    type: DataType.ENUM(...Object.values(CredentialType)),
  })
  type!: CredentialType;
}

Note, the default values for an enum in TypeScript are indexed, but can be overridden with your own values , like this:

enum CredentialType {
  EMAIL = "EMAIL",
  TOKEN = "TOKEN"
}

Upvotes: 5

Payerl
Payerl

Reputation: 1090

Okay so after alot more experimenting I found a way. Since a enum option is represented as a number in typescript/javascript I changed the database type corresponding to the enum:

Credential.init({
    email: {
        type: DataTypes.STRING,
        allowNull: true
    },
    password: {
        type: DataTypes.STRING,
        allowNull: true
    },
    token: {
        type: DataTypes.STRING,
        allowNull: true
    },
    type: {
        type: DataTypes.INTEGER,
        allowNull: false
    }
}, {
    sequelize: sequelize,
    tableName: 'credentials'
});

When it was saved to the database as a integer the error dissolved.

Upvotes: 3

Related Questions