node.js - Folosește ENUM cu Sequelize și Typescript
Încerc să creez un API cu o clasă USER care poate avea mai mult de o modalitate de a se autentifica cu API-ul.
Am reușit să îl fac să funcționeze cu 1 singur utilizator având doar 1 acreditiv, dar atunci când am încercat să extind pentru a permite mai multe acreditive am primit eroarea: UnhandledPromiseRejectionWarning: SequelizeDatabaseError: (conn=498, no: 1265, SQLState: 01000) Data truncated for column 'type' at row 1
Ceea ce am în prezent este acesta:
User.hasMany(Credential, { foreignKey: 'id', sourceKey: 'id' });
Și asta:
//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;
}
De asemenea, am acest model pentru a elimina aceste lucruri din toate celelalte modele ale mele.
//BaseModel.ts
export class BaseModel extends Model {
public id?: number;
public readonly createdAt?: Date;
public readonly updatedAt?: Date;
}
Ai vreo idee de ce primesc acest mesaj? L-am scris așa pentru că nu vreau să trebuiască să declar conținutul enum-ului de două ori.. Dacă se schimbă, vreau să se schimbe peste tot....
Răspuns #1
Deoarece un enum în TypeScript este o valoare, poți răspândi valorile enum în DataTypes.ENUM din Sequelize, astfel:
enum CredentialType {
EMAIL,
TOKEN
}
Credential.init({
// ...
type: {
type: DataTypes.ENUM(...Object.values(CredentialType)),
allowNull: false
}
}, {
sequelize: sequelize,
tableName: 'credentials'
});
Sau cu biblioteca sequelize-typescript, astfel:
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;
}
Rețineți că valorile implicite pentru un enum în TypeScript sunt indexate, dar pot fi suprascrise cu propriile valori, astfel:
enum CredentialType {
EMAIL = "EMAIL",
TOKEN = "TOKEN"
}
Răspunsul #2
Ok, după multe experimente am găsit o modalitate. Deoarece o opțiune de tip enum este reprezentată ca un număr în TypeScript/JavaScript, am schimbat tipul bazei de date corespunzător enumului:
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'
});
Când a fost salvat în baza de date ca integer, eroarea a dispărut.
