Búsqueda de sitios web

node.js - Usar ENUM con Sequelize y Typescript


Estoy tratando de crear una API con una clase USER que pueda tener más de una forma de autenticarse con la API.

He logrado hacer que funcione con 1 usuario teniendo solo 1 credencial, pero al intentar expandir para permitir múltiples credenciales, obtuve el error: UnhandledPromiseRejectionWarning: SequelizeDatabaseError: (conn=498, no: 1265, SQLState: 01000) Datos truncados para la columna 'type' en la fila 1

Lo que tengo actualmente es esto:

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

Y esto:

//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;
}

También tengo este modelo para quitar estas cosas de todos mis otros modelos.

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

¿Alguna idea de por qué recibo este mensaje? Lo he escrito así porque no quiero tener que declarar el contenido del enum dos veces... Si cambio algo, quiero que cambie en todas partes...

Respuesta #1

Dado que un enum en TypeScript es un valor, puedes expandir los valores del enum en el DataTypes.ENUM de Sequelize, así:

enum CredentialType {
  EMAIL,
  TOKEN
}

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

O con la biblioteca sequelize-typescript, así:

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;
}

Nota, los valores predeterminados de un enum en TypeScript están indexados, pero se pueden sobrescribir con tus propios valores, así:

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

Respuesta #2

Está bien, después de muchos más experimentos encontré una manera. Dado que una opción de enum se representa como un número en TypeScript/JavaScript, cambié el tipo de base de datos correspondiente al 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'
});

Cuando se guardó en la base de datos como un entero, el error desapareció.

Artículos relacionados