使用Sequelize-Typescript生命周期钩子哈希密码时遇导出错误
解决Sequelize-Typescript模型导出错误及密码哈希优化
先搞定模型导入/导出错误
你碰到的 Error: No default export defined for file "user.model" or export does not satisfy filename 问题,大概率是这几个原因之一:
- 文件名和导出类名不匹配:sequelize-typescript 默认要求模型文件名(不含后缀)和默认导出的类名严格对应(大小写敏感)。比如你的文件叫
user.model.ts,默认导出的类得是User(首字母大写),或者把文件名改成User.model.ts来匹配类名。 - 导入方式错了:如果在其他文件里导入这个模型时用了命名导入(比如
import { User } from './user.model'),但你代码里是默认导出,得改成默认导入:import User from './user.model'。 - 模型加载配置有问题:检查 Sequelize 初始化代码,确保模型目录路径正确,没禁用默认导出检测。举个例子:
import { Sequelize } from 'sequelize-typescript'; const sequelize = new Sequelize({ // 数据库连接配置 dialect: 'mysql', host: 'localhost', // ...其他配置 models: [__dirname + '/models'], // 确保这个路径指向你的模型文件夹 });
优化密码哈希的钩子逻辑
你的生命周期钩子逻辑方向是对的,但可以调整得更严谨:
- 抽公共哈希方法:避免重复写哈希代码,把逻辑抽成私有静态方法:
private static async hashPassword(password: string): Promise<string> { // 防止配置里的salt是字符串,转成数字类型的盐轮数 const saltRounds = typeof serverConfig.SALT === 'string' ? parseInt(serverConfig.SALT, 10) : serverConfig.SALT; return bcrypt.hash(password, saltRounds); }
- 完善BeforeUpdate钩子:只在password字段确实被修改且不为空时才哈希,避免无效操作:
@BeforeUpdate static async updatePassword(instance: User) { if (instance.changed('password') && instance.password) { instance.password = await this.hashPassword(instance.password); } }
- 给密码字段加验证:在Column装饰器里加规则,防止空密码存入:
@Column({ type: DataTypes.STRING(100), allowNull: false, // 密码不允许为空 validate: { notEmpty: true, }, }) password!: string;
修正后的完整代码
import { Table, Column, Model, PrimaryKey, AutoIncrement, BeforeCreate, BeforeUpdate } from 'sequelize-typescript'; import bcrypt from 'bcryptjs'; import { serverConfig } from '../config'; import { DataTypes } from 'sequelize'; @Table({ paranoid: true, timestamps: true }) export default class User extends Model<User> { @PrimaryKey @AutoIncrement @Column id!: number; @Column({ type: DataTypes.STRING(255), allowNull: true, }) email!: string; @Column({ type: DataTypes.STRING(100), allowNull: false, validate: { notEmpty: true, }, }) password!: string; @Column({ type: DataTypes.INTEGER, allowNull: true, defaultValue: 1, }) status!: number; private static async hashPassword(password: string): Promise<string> { const saltRounds = typeof serverConfig.SALT === 'string' ? parseInt(serverConfig.SALT, 10) : serverConfig.SALT; return bcrypt.hash(password, saltRounds); } @BeforeCreate public static async hash(instance: User) { if (instance.password) { instance.password = await this.hashPassword(instance.password); } } @BeforeUpdate static async updatePassword(instance: User) { if (instance.changed('password') && instance.password) { instance.password = await this.hashPassword(instance.password); } } }
内容的提问来源于stack exchange,提问作者Shahid Raza
相关产品推荐
相关产品推荐

