import fs from "fs"; import path from "path"; import { Dialect, Sequelize, Transaction } from "sequelize"; import { Config, Logger } from "."; export class DBConfig { public dialect: Dialect = "mysql"; public host: string = "127.0.0.1"; public port: number = 3306; public define: any = { timestamps: false, freezeTableName: true }; public maxPoolSize: number = 5; public minPoolSize: number = 1; public database: string; public username: string; public password: string; constructor(database: string, username: string, password: string) { this.database = database; this.username = username; this.password = password; } } export class Repository { private sequelize!: Sequelize; private modelMap = new Map(); constructor(config: DBConfig, modelPath: string) { this.sequelize = new Sequelize( config.database, config.username, config.password, { dialect: config.dialect, host: config.host, port: config.port, define: config.define, timezone: "+09:00", pool: { max: config.maxPoolSize, min: config.minPoolSize, acquire: 3000, idle: 10000 } } ); fs.readdirSync(modelPath) .filter(file => { return file.indexOf(".") !== 0 && file.slice(-3) === ".js"; }) .forEach(file => { Logger.getInstance().info( `read model info: ${path.join(modelPath, file)}` ); const model = this.sequelize.import(path.join(modelPath, file)); this.modelMap.set(model.name, model); }); } public async insert(tableName: string, info: any, t?: Transaction) { this.hasModel(tableName); if (t) { return await this.modelMap .get(tableName) .build(info) .save({ transaction: t }); } return await this.modelMap .get(tableName) .build(info) .save(); } public async update(tableName: string, set: any, condition: any) { this.hasModel(tableName); return await this.modelMap.get(tableName).update(set, condition); } public async upsert(tableName: string, info: any, option?: any) { this.hasModel(tableName); return await this.modelMap.get(tableName).upsert(info, option); } public async select(tableName: string, condition: any) { this.hasModel(tableName); return await this.modelMap.get(tableName).findAll(condition); } public async exists(tableName: string, condition: any) { this.hasModel(tableName); const result = await this.modelMap.get(tableName).findOne(condition); if (result === null) { return false; } return true; } public async query(sql: string, condition: any) { return await this.sequelize.query(sql, { replacements: condition }); } public async transaction() { return this.sequelize.transaction(); } private hasModel(tableName: string) { if (!this.modelMap.has(tableName)) { throw new Error("model not found"); } } } export class SingletonRepository { public static modelPath: string = "models"; public static getInstance() { if (!this.instance) { const config = Config.getInstance(); const dbConf = new DBConfig( config.database.master.schema, config.database.master.username, config.database.master.password ); dbConf.host = config.database.master.host; dbConf.port = config.database.master.port; this.instance = new Repository( dbConf, path.join(process.cwd(), this.modelPath) ); Logger.getInstance().info( `created a singleton repository: ${dbConf.host}:${dbConf.port}` ); } return this.instance; } private static instance: Repository; }