Sequelize 抛出“TypeError:无法读取未定义的属性(读取'constructor')”

Sequelize throws "TypeError: Cannot read properties of undefined (reading 'constructor')"

提问人:Vitomir 提问时间:11/10/2023 更新时间:11/13/2023 访问量:63

问:

我遇到了续集的问题,不明白问题到底来自哪里。我收到以下错误: 这是堆栈:TypeError: Cannot read properties of undefined (reading 'constructor')

TypeError: Cannot read properties of undefined (reading 'constructor')\n" +
    '    at Function.findOne (/.../node_modules/sequelize/src/model.js:1977:61)\n' +
    '    at /.../src/api/controllers/execution.ts:22:31\n'

这是我在执行控制器中的内容:

let user = await User.findOne({ where: { id: req.body.externalCustomerId } });
if (!user) {
   throw new NotFoundError('No such user found');
}

我只是无法理解为什么 sequelize 会抛出这个错误。我有其他 2 个服务正在运行,此调用没有问题。我在包含数据库的单独项目中有用户模型,我在那里有以下代码:

import argon2 from 'argon2';
import { Sequelize, Model, DataTypes, Op, QueryTypes } from 'sequelize';

export enum Role {
  admin = 'Admin',
  user = 'User',
  business = 'Business'
}

const validateEmailRegExp = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

export function validateEmailFormat(candidateEmail: string): boolean {
    return validateEmailRegExp.test(candidateEmail);
}

export function checkPasswordRequirements(candidatePassword: string): boolean {
    let valid = true;
  
    if (candidatePassword.length < 8) {
      valid = false;
    }
  
    // check if password contains a digit
    if (/\d/.test(candidatePassword) !== true) {
      valid = false;
    }
  
    // check if password contains a lowercase character
    if (/[a-z]/.test(candidatePassword) !== true) {
      valid = false;
    }
  
    // check if password contains an uppercase character
    if (/[A-Z]/.test(candidatePassword) !== true) {
      valid = false;
    }
  
    return valid;
}

class User extends Model {
  declare id: number;
  declare role: string;
  declare firstName: string;
  declare lastName: string;
  declare email: string;
  declare passcode: string;
  declare birthdate: string;
  declare country: string;
  declare phone: string;
  declare createdAt: string;
  declare active: boolean;

  static async initModel(sequelize: Sequelize) {
    console.log('Syncing user model...');
    this.init({
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true
      },
      role: {
        type: DataTypes.ENUM(...Object.values(Role)),
        allowNull: false,
        defaultValue: Role.user,
        validate: {
          isIn: [ Object.values(Role) ]
        }
      },
      firstName: {
        type: DataTypes.STRING,
        allowNull: false
      },
      lastName: {
        type: DataTypes.STRING,
        allowNull: false
      },
      email: {
        type: DataTypes.STRING,
        allowNull: false,
        unique: true,
        validate: {
          isEmail: true
        }
      },
      passcode: {
        type: DataTypes.STRING,
        allowNull: false
      },
      birthdate: {
        type: DataTypes.STRING,
        allowNull: false
      },
      country: {
        type: DataTypes.STRING,
        allowNull: false
      },
      phone: {
        type: DataTypes.STRING,
        allowNull: false
      }
      active: {
        type: DataTypes.BOOLEAN,
        allowNull: false
      }
    }, {
      sequelize,
      indexes: [{ unique: true, fields: ['email'] }],
    }
    });

    User.beforeCreate(async (user, options) => {
      // always lowercase user email before saving
      user.email = user.email.toLowerCase();

      const hashedPassword = await argon2.hash(user.passcode as string);
      user.passcode = hashedPassword;
    });

    User.beforeUpdate(async (user, options) => {
      // hash user password if it was changed
      if (user.changed('passcode')) {
        const hashedPassword = await argon2.hash(user.passcode as string);
        user.passcode = hashedPassword;
      }
    });
  }
}

export default User;

此外,这是我连接到数据库的方式:

import { Sequelize } from 'sequelize';

import User from '../models/user';

export let sequelize: Sequelize | null = null;

export async function connectToDb(
    dbName: string,
    dbUser: string,
    dbPass: string,
    dbOptions: any
  ): Promise<Sequelize | null> {
    
    try {
      if (sequelize !== null) {
        // return existing instance
        return sequelize;
      }
      
      console.log(`Connecting to database ${dbName} on host ${dbOptions.host}`);
      sequelize = new Sequelize(dbName, dbUser, dbPass, dbOptions);
  
      try {
        await sequelize.authenticate();
        console.log(`Successfully connected to databse, syncing models...`);
        await initDbModels(sequelize);
        console.log('All DB models initialised.');
      } catch (error) {
        console.error(`Error connecting to database ${dbName}`);
        console.error(error);
      }
  
      return sequelize;
    } catch (err) {
      console.error(`Could not connect to database ${dbName}`);
      console.error(err);
  
      return null;
    }
}

export async function initDbModels(sequelize: Sequelize) {
    await User.initModel(sequelize);
    ...

    await sequelize.sync();
}

最后,这是我的:app.ts

import cors from 'cors';
import path from 'path';
import dotenv from 'dotenv';
import express from 'express';

import router from './routes/router';
import { morgan } from "./middleware/morgan";

import { connectToDb } from '../modules/commons/tools/db-helper';
import { apiErrorHandler } from '../modules/commons/error-handling/error-handler';
import { dbName, dbUser, dbPass, dbOptions } from '../modules/commons/database/database';

require('ts-node/register');

dotenv.config({
  path: `.env.${process.env.NODE_ENV}`
});

var corsOptions: cors.CorsOptions = {
  origin: function (origin, callback) {
    callback(null, true)
  }
}

if (process.env.NODE_ENV !== 'production') {
  corsOptions.origin = '*';
}

var app = express();

const originalSend = app.response.send;
app.response.send = function sendOverride(body) {
  this.responseBody = body;
  return originalSend.call(this, body);
};

connectToDb(dbName, dbUser, dbPass, dbOptions);

app.use(cors(corsOptions));
app.use(morgan(':remote-addr [:date[clf]] ":method :url HTTP/:http-version" Input :input Response :status :response-body'));
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ limit: '10mb', extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(router);
app.use(apiErrorHandler);
app.set('trust proxy', true);

export default app;
节点 .js 打字稿 PostgreSQL Express 续集 .js

评论

0赞 Anatoly 11/11/2023
请展示您如何导入模型,其中调用Userlet user = await User.findOne({ where: { id: req.body.externalCustomerId } });
0赞 Vitomir 11/13/2023
嘿,我发现了问题。在 commons 子模块中,我没有安装软件包,所以 sequelize 有问题。此外,其他 2 个服务运行良好,因为它们的软件包中安装了。pgpg

答:

0赞 Vitomir 11/13/2023 #1

我发现了这个问题,它非常明显,但由于其他 2 项服务运行良好,我感到困惑。此外,我无法在日志中看到错误。

几天前,我创建了一个负责 db 连接的通用子模块,在那里我安装了包,但我忘了安装那个。另一方面,在数据库连接工作正常的 2 个服务中,我已经安装了该软件包,这就是它们一直在工作的原因。sequelizepgpg

所以,我刚刚在我的commons子模块中安装了它,一切正常。此外,我已经从服务中卸载了它,因为它已经安装在子模块中。pgpg