인프런 커뮤니티 질문&답변

Chang Su Lee님의 프로필 이미지
Chang Su Lee

작성한 질문수

Node.js에 TypeScript 적용하기(feat. NodeBird)

passport 설정하기

Sequelize constructor.primaryKeyAttributes 오류

작성

·

851

0

안녕하세요 제로초님 이전에 알려주신 Sequelize 타이핑 덕뿐에 문제 잘 해결했습니다.

[0] Executing (default): SELECT `id`, `email`, `nick`, `password`, `provider`, `snsId`, `createdAt`, `updatedAt`, `de
letedAt` FROM `users` AS `User` WHERE (`User`.`deletedAt` IS NULL AND `User`.`id` = 1);
[0] TypeError: Cannot read properties of undefined (reading 'length')
[0]     at Box._initValues (C:\workspace\Dev-Mark\server\node_modules\sequelize\lib\model.js:130:49)
[0]     at new Model (C:\workspace\Dev-Mark\server\node_modules\sequelize\lib\model.js:116:10)
[0]     at new Box (C:\workspace\Dev-Mark\server\models\box.js:31:1)
[0]     at Box.build (C:\workspace\Dev-Mark\server\node_modules\sequelize\lib\model.js:1326:12)
[0]     at Box.create (C:\workspace\Dev-Mark\server\node_modules\sequelize\lib\model.js:1344:23)
[0]     at C:\workspace\Dev-Mark\server\controller\box.js:36:44
[0]     at Generator.next (<anonymous>)
[0]     at C:\workspace\Dev-Mark\server\controller\box.js:8:71
[0]     at new Promise (<anonymous>)
[0]     at __awaiter (C:\workspace\Dev-Mark\server\controller\box.js:4:12)
[0] C:\workspace\Dev-Mark\server\node_modules\sequelize\lib\model.js:83
[0]         for (const key of Object.keys(this.constructor._attributeManipulation)) {
[0]                                  ^
[0]
[0] TypeError: Cannot convert undefined or null to object
[0]     at Function.keys (<anonymous>)
[0]     at Timeout._onTimeout (C:\workspace\Dev-Mark\server\node_modules\sequelize\lib\model.js:83:34)
[0]     at listOnTimeout (node:internal/timers:564:17)
[0]     at process.processTimers (node:internal/timers:507:7)
[0]
[0] Node.js v18.13.0
[1] [HPM] Error occurred while proxying request localhost:3000/api/box/ to http://localhost:5000/ [ECONNRESET] (https
://nodejs.org/api/errors.html#errors_common_system_errors)
[0] npm run server exited with code 1
--> Sending SIGTERM to other processes..
[1] npm run client exited with code 1

이번에는 라는 오류가 나오는데요,

stackoverflow를 읽어보니 default value를 지정하라는 말도 있고 init을 하지 않았다는 말도 있는데 둘 다 제 케이스에는 해당하지 않는 것 같습니다.

sequelize 공식문서에서도 읽어보았지만 문제가 뭔지 잘 모르겠습니다...

Box.js (변환)

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const sequelize_1 = __importStar(require("sequelize"));
const user_js_1 = __importDefault(require("./user.js"));
class Box extends sequelize_1.Model {
    static initiate(sequelize) {
        Box.init({
            id: {
                type: sequelize_1.default.INTEGER,
                primaryKey: true,
                autoIncrement: true,
            },
            box: {
                type: sequelize_1.default.STRING(15),
                allowNull: false,
            },
            img: {
                type: sequelize_1.default.STRING(200),
                allowNull: true,
            },
            createdAt: sequelize_1.default.DATE,
            updatedAt: sequelize_1.default.DATE,
        }, {
            sequelize,
            timestamps: true,
            underscored: false,
            modelName: "Box",
            tableName: "boxs",
            paranoid: false,
            charset: "utf8mb4",
            collate: "utf8mb4_general_ci",
        });
    }
    static associate() {
        Box.belongsTo(user_js_1.default);
    }
}
exports.default = Box;

 

box.ts

import Sequelize, {
  CreationOptional,
  InferAttributes,
  InferCreationAttributes,
  Model,
  ForeignKey,
} from "sequelize";
import User from "./user.js";

class Box extends Model<InferAttributes<Box>, InferCreationAttributes<Box>> {
  declare id: CreationOptional<number>;
  declare box: string;
  declare img: string;
  declare createdAt: CreationOptional<Date>;
  declare updatedAt: CreationOptional<Date>;

  declare UserId: ForeignKey<User["id"]>;

  static initiate(sequelize: Sequelize.Sequelize) {
    Box.init(
      {
        id: {
          type: Sequelize.INTEGER,
          primaryKey: true,
          autoIncrement: true,
        },
        box: {
          type: Sequelize.STRING(15),
          allowNull: false,
        },
        img: {
          type: Sequelize.STRING(200),
          allowNull: true,
        },
        createdAt: Sequelize.DATE,
        updatedAt: Sequelize.DATE,
      },
      {
        sequelize,
        timestamps: true,
        underscored: false,
        modelName: "Box",
        tableName: "boxs",
        paranoid: false,
        charset: "utf8mb4",
        collate: "utf8mb4_general_ci",
      }
    );
  }

  static associate() {
    Box.belongsTo(User);
  }
}

export default Box;

 

user.ts

import Sequelize, {
  CreationOptional,
  InferAttributes,
  InferCreationAttributes,
  Model,
  BelongsToManyAddAssociationMixin,
  NonAttribute,
} from "sequelize";

class User extends Model<InferAttributes<User>, InferCreationAttributes<User>> {
  declare id: CreationOptional<number>;
  // 'CreationOptional' is a special type that marks the field as optional
  // id can be undefined during creation when using `autoIncrement`
  declare email: string;
  declare nick: string;
  declare password: CreationOptional<string>;
  declare provider: CreationOptional<string>;
  declare snsId: CreationOptional<string>;
  declare createdAt: CreationOptional<Date>;
  // createdAt can be undefined during creation
  declare updatedAt: CreationOptional<Date>;
  // updatedAt can be undefined during creation
  declare deletedAt: CreationOptional<Date>;
  // ...


  static initiate(sequelize: Sequelize.Sequelize) {
    User.init(
      {
        id: {
          type: Sequelize.INTEGER,
          primaryKey: true,
          autoIncrement: true,
        },
        email: {
          type: Sequelize.STRING(40),
          allowNull: true,
          unique: true,
        },
        nick: {
          type: Sequelize.STRING(15),
          allowNull: false,
        },
        password: {
          type: Sequelize.STRING(100),
          allowNull: true,
        },
        provider: {
          type: Sequelize.ENUM("local", "kakao", "github"),
          allowNull: false,
          defaultValue: "local",
        },
        snsId: {
          type: Sequelize.STRING(30),
          allowNull: true,
        },
        createdAt: Sequelize.DATE,
        updatedAt: Sequelize.DATE,
        deletedAt: Sequelize.DATE,
      },
      {
        sequelize,
        timestamps: true,
        underscored: false,
        modelName: "User",
        tableName: "users",
        paranoid: true,
        charset: "utf8",
        collate: "utf8_general_ci",
      }
    );
  }

  static associate() {
  }
}

export default User;

 

index.ts

import Sequelize from 'sequelize';
import configObj from '../config/config.js';
import User from './user.js';
import Post from './post.js';
import Hashtag from './hashtag.js';
import Alarm from './alarm.js';
import Bookmark from './bookmark.js';
import Box from './Box.js';

const env = process.env.NODE_ENV as 'production' | 'test' || 'development';
const config = configObj[env];

export const sequelize = new Sequelize.Sequelize(
  config.database, config.username, config.password, config,
);

Alarm.initiate(sequelize);
Bookmark.initiate(sequelize);
Box.initiate(sequelize);
Hashtag.initiate(sequelize);
Post.initiate(sequelize);
User.initiate(sequelize);

Alarm.associate();
Bookmark.associate();
Box.associate();
Hashtag.associate();
Post.associate();
User.associate();

 

답변 1

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

app.js에서 sequelize.sync() 호출하셨나요?

Chang Su Lee님의 프로필 이미지
Chang Su Lee
질문자

/* Sequelize */
sequelize
  .sync({ force: true })
  .then(() => {
    console.log("데이터베이스 연결 성공");
  })
  .catch((err) => {
    console.error(err);
  });

넵 sync() 호출 했습니다.

로그인, OAuth까지는 멀쩡하게 동작하는데 Box를 만들면 오류가 나네요

https://github.com/ChangSuLee00/Dev-Mark

feat:auth 부분이 제일 최근까지 작업한 내용입니다

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

at C:\workspace\Dev-Mark\server\controller\box.js:36:44 [0] at Generator.next (<anonymous>) [0] at C:\workspace\Dev-Mark\server\controller\box.js:8:71

에러 위치가 여기로 되어있는데 확인해보세요.

Chang Su Lee님의 프로필 이미지
Chang Su Lee
질문자

감사합니다!! 해결되었습니다

box가 아니라 Box로 import 해오니까 되네요

tsc로 ts -> js로 만들면 다른 파일은 그대로 소문자로 변환되는데 models에 있던 box.js만 Box.js로 변환되네요 이건 그냥 오류인건가요?

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

네 이건 좀 이상하네요.

Chang Su Lee님의 프로필 이미지
Chang Su Lee

작성한 질문수

질문하기