공용 상수 backend/constants.js로 추출
DIFFICULTIES(난이도 enum), PARTY_SIZE(1~6), SYMBOL_MASTER_LEVEL(2~99), UPLOAD_FILE_SIZE_LIMIT(10MB)를 backend/constants.js로 추출하고 admin.js, boss-crystal.js, symbol.js, BossDifficulty 모델에서 참조. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1ee3f19f4f
commit
b3907ec48f
5 changed files with 26 additions and 8 deletions
11
backend/constants.js
Normal file
11
backend/constants.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// 난이도 ENUM — 모델과 validation 에서 공용
|
||||
export const DIFFICULTIES = ['easy', 'normal', 'hard', 'chaos', 'extreme'];
|
||||
|
||||
// 파티 인원수 범위
|
||||
export const PARTY_SIZE = { min: 1, max: 6 };
|
||||
|
||||
// 심볼 마스터 레벨 범위
|
||||
export const SYMBOL_MASTER_LEVEL = { min: 2, max: 99 };
|
||||
|
||||
// 업로드 파일 크기 상한 (10MB)
|
||||
export const UPLOAD_FILE_SIZE_LIMIT = 10 * 1024 * 1024;
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
import { DataTypes } from 'sequelize';
|
||||
import { sequelize } from '../../lib/db.js';
|
||||
import { DIFFICULTIES } from '../../constants.js';
|
||||
|
||||
export const BossCrystalBossDifficulty = sequelize.define('BossCrystalBossDifficulty', {
|
||||
id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true },
|
||||
boss_id: { type: DataTypes.INTEGER, allowNull: false },
|
||||
difficulty: {
|
||||
type: DataTypes.ENUM('easy', 'normal', 'hard', 'chaos', 'extreme'),
|
||||
type: DataTypes.ENUM(...DIFFICULTIES),
|
||||
allowNull: false,
|
||||
},
|
||||
crystal_price: { type: DataTypes.BIGINT, allowNull: false },
|
||||
|
|
|
|||
|
|
@ -6,11 +6,12 @@ import { getPublicUrl } from '../lib/s3.js';
|
|||
import { sequelize } from '../lib/db.js';
|
||||
import bossCrystalRouter from './admin/boss-crystal.js';
|
||||
import symbolRouter from './admin/symbol.js';
|
||||
import { UPLOAD_FILE_SIZE_LIMIT } from '../constants.js';
|
||||
|
||||
const router = Router();
|
||||
const upload = multer({
|
||||
storage: multer.memoryStorage(),
|
||||
limits: { fileSize: 10 * 1024 * 1024 }, // 10MB
|
||||
limits: { fileSize: UPLOAD_FILE_SIZE_LIMIT },
|
||||
});
|
||||
|
||||
// 관리자 인증 미들웨어
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ import { BossCrystalBoss, BossCrystalBossDifficulty } from '../../models/index.j
|
|||
import { uploadBossImage, deleteBossImage } from '../../services/boss-crystal/image.js';
|
||||
import { getPublicUrl } from '../../lib/s3.js';
|
||||
import { sequelize } from '../../lib/db.js';
|
||||
import { UPLOAD_FILE_SIZE_LIMIT, PARTY_SIZE, DIFFICULTIES } from '../../constants.js';
|
||||
|
||||
const router = Router();
|
||||
const upload = multer({
|
||||
storage: multer.memoryStorage(),
|
||||
limits: { fileSize: 10 * 1024 * 1024 },
|
||||
limits: { fileSize: UPLOAD_FILE_SIZE_LIMIT },
|
||||
});
|
||||
|
||||
function serialize(boss) {
|
||||
|
|
@ -39,9 +40,8 @@ function parseDifficulties(raw) {
|
|||
if (!Array.isArray(arr) || arr.length === 0) {
|
||||
throw new Error('하나 이상의 난이도가 필요합니다');
|
||||
}
|
||||
const valid = ['easy', 'normal', 'hard', 'chaos', 'extreme'];
|
||||
return arr.map((d) => {
|
||||
if (!valid.includes(d.difficulty)) throw new Error(`잘못된 난이도: ${d.difficulty}`);
|
||||
if (!DIFFICULTIES.includes(d.difficulty)) throw new Error(`잘못된 난이도: ${d.difficulty}`);
|
||||
const price = Number(d.crystal_price);
|
||||
if (isNaN(price) || price <= 0) throw new Error(`잘못된 가격: ${d.difficulty}`);
|
||||
return { difficulty: d.difficulty, crystal_price: price };
|
||||
|
|
@ -50,7 +50,9 @@ function parseDifficulties(raw) {
|
|||
|
||||
function parseMaxParty(raw) {
|
||||
const n = Number(raw);
|
||||
if (isNaN(n) || n < 1 || n > 6) throw new Error('인원수는 1~6이어야 합니다');
|
||||
if (isNaN(n) || n < PARTY_SIZE.min || n > PARTY_SIZE.max) {
|
||||
throw new Error(`인원수는 ${PARTY_SIZE.min}~${PARTY_SIZE.max}이어야 합니다`);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ import { Symbol, SymbolLevel } from '../../models/index.js';
|
|||
import { convertAndUploadTo, deleteFromS3 } from '../../services/image.js';
|
||||
import { getPublicUrl } from '../../lib/s3.js';
|
||||
import { sequelize } from '../../lib/db.js';
|
||||
import { UPLOAD_FILE_SIZE_LIMIT, SYMBOL_MASTER_LEVEL } from '../../constants.js';
|
||||
|
||||
const router = Router();
|
||||
const upload = multer({
|
||||
storage: multer.memoryStorage(),
|
||||
limits: { fileSize: 10 * 1024 * 1024 },
|
||||
limits: { fileSize: UPLOAD_FILE_SIZE_LIMIT },
|
||||
});
|
||||
|
||||
const VALID_TYPES = ['아케인', '어센틱', '그랜드 어센틱'];
|
||||
|
|
@ -70,7 +71,9 @@ function validateBasic({ type, region, max_level }) {
|
|||
const r = String(region || '').trim();
|
||||
if (!r) throw new Error('지역 이름을 입력해주세요');
|
||||
const ml = Number(max_level);
|
||||
if (!ml || ml < 2 || ml > 99) throw new Error('만렙은 2~99 사이여야 합니다');
|
||||
if (!ml || ml < SYMBOL_MASTER_LEVEL.min || ml > SYMBOL_MASTER_LEVEL.max) {
|
||||
throw new Error(`만렙은 ${SYMBOL_MASTER_LEVEL.min}~${SYMBOL_MASTER_LEVEL.max} 사이여야 합니다`);
|
||||
}
|
||||
return { type, region: r, max_level: ml };
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue