5

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....

3
  • 1
    why are looping over only ~half of the enum keys? Commented Dec 27, 2019 at 21:52
  • 1
    The first half is the index of the elements, or the assigned value ('0' ,'1' ) and the second half is the elements string representation('EMAIL', 'TOKEN') Commented Dec 27, 2019 at 22:06
  • 1
    Realised now that I could have done Object.keys(CredentialType).slice(0,Object.keys(CredentialType)/2) and skipped the for-loop.. Anyway... XD Commented Dec 27, 2019 at 22:20

2 Answers 2

5

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"
}
Sign up to request clarification or add additional context in comments.

Comments

3

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.

1 Comment

Or you can use string instead of the number export enum CredentialType { EMAIL = "EMAIL", TOKEN = "TOKEN" }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.