2024-04-23 15:29:38 +00:00
|
|
|
import { config } from "@/config";
|
|
|
|
|
import rTracer from "cls-rtracer";
|
|
|
|
|
import { DataTypes, Sequelize } from "sequelize";
|
|
|
|
|
|
|
|
|
|
import { initLogger } from "@/infrastructure/logger";
|
|
|
|
|
import * as glob from "glob";
|
|
|
|
|
import * as path from "path";
|
|
|
|
|
import { IAdapter } from "../../domain";
|
|
|
|
|
import { InfrastructureError } from "../InfrastructureError";
|
|
|
|
|
import {
|
|
|
|
|
SequelizeBusinessTransaction,
|
|
|
|
|
SequelizeBusinessTransactionType,
|
|
|
|
|
} from "./SequelizeBusinessTransaction";
|
|
|
|
|
import { ISequelizeModels } from "./SequelizeModel.interface";
|
|
|
|
|
import { ISequelizeQueryBuilder } from "./queryBuilder/SequelizeQueryBuilder";
|
|
|
|
|
|
|
|
|
|
//import * as dotenv from "dotenv";
|
|
|
|
|
//dotenv.config();
|
|
|
|
|
|
|
|
|
|
export interface ISequelizeAdapter extends IAdapter {
|
|
|
|
|
queryBuilder: ISequelizeQueryBuilder;
|
2024-04-24 10:48:49 +00:00
|
|
|
startTransaction: () => SequelizeBusinessTransactionType;
|
2024-04-23 15:29:38 +00:00
|
|
|
getModel: (modelName: string) => any;
|
|
|
|
|
hasModel: (modelName: string) => boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class SequelizeAdapter implements ISequelizeAdapter {
|
|
|
|
|
// eslint-disable-next-line no-use-before-define
|
|
|
|
|
private static instance: SequelizeAdapter;
|
|
|
|
|
|
|
|
|
|
public static getInstance(params: {
|
|
|
|
|
queryBuilder: ISequelizeQueryBuilder;
|
|
|
|
|
}): SequelizeAdapter {
|
|
|
|
|
if (!SequelizeAdapter.instance) {
|
|
|
|
|
SequelizeAdapter.instance = SequelizeAdapter.create(params);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SequelizeAdapter.instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static create(params: { queryBuilder: ISequelizeQueryBuilder }) {
|
|
|
|
|
const { queryBuilder } = params;
|
|
|
|
|
|
|
|
|
|
const connection = initConnection();
|
2024-05-16 11:56:46 +00:00
|
|
|
const models = registerModels(connection);
|
|
|
|
|
|
|
|
|
|
return new SequelizeAdapter(connection, models, queryBuilder);
|
2024-04-23 15:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _connection: Sequelize;
|
|
|
|
|
private _models: ISequelizeModels;
|
|
|
|
|
private _queryBuilder: ISequelizeQueryBuilder;
|
|
|
|
|
|
|
|
|
|
protected constructor(
|
|
|
|
|
connection: Sequelize,
|
|
|
|
|
models: ISequelizeModels,
|
|
|
|
|
queryBuilder: ISequelizeQueryBuilder,
|
|
|
|
|
) {
|
|
|
|
|
this._connection = connection;
|
|
|
|
|
this._models = models;
|
|
|
|
|
this._queryBuilder = queryBuilder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get queryBuilder(): ISequelizeQueryBuilder {
|
|
|
|
|
return this._queryBuilder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public startTransaction(): SequelizeBusinessTransactionType {
|
|
|
|
|
return new SequelizeBusinessTransaction(this._connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public sync(params) {
|
|
|
|
|
return this._connection.sync(params);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-19 22:04:23 +00:00
|
|
|
public getModel(modelName: string): any {
|
2024-04-23 15:29:38 +00:00
|
|
|
if (this.hasModel(modelName)) {
|
|
|
|
|
return this._models[modelName];
|
|
|
|
|
}
|
|
|
|
|
throw InfrastructureError.create(
|
|
|
|
|
InfrastructureError.RESOURCE_NOT_FOUND_ERROR,
|
2024-05-16 11:56:46 +00:00
|
|
|
`[SequelizeAdapter] ${modelName} sequelize model not exists!`,
|
2024-04-23 15:29:38 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public hasModel(modelName: string): boolean {
|
|
|
|
|
return !!this._models[modelName];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function initConnection(): Sequelize {
|
|
|
|
|
const { username, password, database, host, dialect, port } = config.database;
|
|
|
|
|
const logger = initLogger(rTracer);
|
|
|
|
|
|
|
|
|
|
logger.debug("=========================> CONECTO A SEQUELIZE");
|
|
|
|
|
|
|
|
|
|
return new Sequelize(database, username, password, {
|
|
|
|
|
host,
|
|
|
|
|
dialect,
|
|
|
|
|
port,
|
|
|
|
|
dialectOptions: {
|
|
|
|
|
multipleStatements: true,
|
|
|
|
|
dateStrings: true,
|
|
|
|
|
typeCast: true,
|
|
|
|
|
//timezone: "Z",
|
|
|
|
|
},
|
|
|
|
|
pool: {
|
|
|
|
|
max: 5,
|
|
|
|
|
min: 0,
|
|
|
|
|
acquire: 60000,
|
|
|
|
|
idle: 10000,
|
|
|
|
|
},
|
|
|
|
|
logQueryParameters: true,
|
|
|
|
|
logging: (sql, timing) => console.debug(sql), //logger.debug(sql, timing),
|
|
|
|
|
|
|
|
|
|
define: {
|
|
|
|
|
charset: "utf8mb4",
|
|
|
|
|
collate: "utf8mb4_unicode_ci",
|
|
|
|
|
//freezeTableName: true,
|
|
|
|
|
underscored: true,
|
|
|
|
|
timestamps: true,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-16 11:56:46 +00:00
|
|
|
function registerModels(connection: Sequelize): ISequelizeModels {
|
2024-04-23 15:29:38 +00:00
|
|
|
const cwd = path.resolve(`${__dirname}/../../../`);
|
|
|
|
|
const models: ISequelizeModels = {};
|
|
|
|
|
|
|
|
|
|
// Get all models
|
|
|
|
|
const globOptions = {
|
|
|
|
|
cwd,
|
|
|
|
|
nocase: true,
|
|
|
|
|
nodir: true,
|
|
|
|
|
absolute: true,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
glob.sync("**/*.model.{js,ts}", globOptions).forEach(function (file) {
|
|
|
|
|
console.log(`>> ${file}`);
|
|
|
|
|
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
|
|
|
const modelDef = require(path.join(file)).default;
|
|
|
|
|
const model =
|
|
|
|
|
typeof modelDef === "function" ? modelDef(connection, DataTypes) : false;
|
|
|
|
|
if (model) models[model.name] = model;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
for (const modelName in models) {
|
|
|
|
|
const model = models[modelName];
|
|
|
|
|
|
|
|
|
|
if (model.associate) {
|
|
|
|
|
model.associate(connection, models);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (model.hooks) {
|
|
|
|
|
model.hooks(connection);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return models;
|
|
|
|
|
}
|