import process from "node:process"; import type { IDbBrand } from "@interfaces/database/IDbBrand"; import type { IDbCategory } from "@interfaces/database/IDbCategory"; import type { IDbFactorizeInput, IDbFactorizeOutput, } from "@interfaces/database/IDbFactorize"; import type { IDbModel } from "@interfaces/database/IDbModel"; import type IDbRent from "@interfaces/database/IDbRent"; import type { IDbStatusResult } from "@interfaces/database/IDbStatusResult"; import type { IDbUser } from "@interfaces/database/IDbUser"; import type { IDbVehicle } from "@interfaces/database/IDbVehicle"; import type { IUserUpdate } from "@interfaces/services/IUserUpdate"; import { isDebugMode } from "@utils/debugState"; import mysql, { type Connection, type ConnectionOptions } from "mysql2"; import { Logger } from "tslog"; const access: ConnectionOptions = { host: `${process.env["MYSQL_HOST"]}`, port: Number.parseInt(`${process.env["MYSQL_PORT"]}`), user: `${process.env["MYSQL_USER"]}`, database: `${process.env["MYSQL_DATABASE"]}`, password: `${process.env["MYSQL_PASS"]}`, }; class MysqlHandler { private readonly handlerName: string; Logger: Logger; private Connection: Connection; constructor(handlerName?: string) { this.handlerName = handlerName || "Unknown"; this.Logger = new Logger({ name: `DB>> ${this.handlerName}`, }); this.Connection = mysql.createConnection(access); this.Connection.connect((err) => { if (err) { this.Logger.error(`\n\n> Error connecting to MySQL: \n${err}\n`); process.exit(1); } if (isDebugMode()) this.Logger.debug( `\n\n> Connected to MySQL database (${access.database})\n`, ); }); } closeConnection() { this.Connection.end(); } query(queryString: string) { return new Promise((resolve, reject) => { this.Connection.query(queryString, (err, results) => { if (err) { this.Logger.error(`\n\n> Error executing query: \n${err}\n`); reject(err); } else { resolve(results); } }); }); } /** * Factorize the input data values into a database query. * `id` field will not be injected in result to avoid problems. * * @param {IDbFactorizeInput} data - The input data containing values to factorize. * @return {Promise} - A promise resolving to the factorized output. */ factorize(data: IDbFactorizeInput): Promise { return new Promise((resolve, reject) => { try { let _id = ""; // @ts-ignore if (data.values.id) { // @ts-ignore _id = data.values.id; // @ts-ignore delete data.values.id; } const _sqlQueryKeys = Object.keys(data.values).map( (key: string) => `${key}`, ); const values = Object.values(data.values).map((val) => val); if (isDebugMode()) this.Logger.debug( `\n\n>-> Factorized ${_sqlQueryKeys.length} keys for a prepare Query.\n>-> Action: ${data.actionName}\n`, ); const sqlQueryKeys = _sqlQueryKeys.join(", "); if (_id && _id.length > 2) { if (isDebugMode()) this.Logger.trace( `\n\n> Id post-pushed in factorized data.\n ${_id}`, ); values.push(_id); } const questionMarksFields = Array(values.length) .fill("?") .join(", ") .toString(); const factorizedOutput: IDbFactorizeOutput = { _keysTemplate: sqlQueryKeys, _questionMarksFields: questionMarksFields, totalFields: _sqlQueryKeys.length, _valuesArray: values, }; resolve(factorizedOutput); } catch (err) { if (data.throwOnError) throw new Error(`${err}`); this.Logger.error(`\n|\n${err}\n|`); reject(`${err}`); } }); } /** * Executes a query using the provided queryString and values. * @param {string} queryString - The SQL query string to execute. * @param {Array} values - The values to be inserted into the query. * @returns {Promise} - A promise that resolves with the query results or rejects with an error. */ execute( queryString: string, values: Array, ): Promise { return new Promise((resolve, reject) => { this.Connection.execute( queryString, values, (err: mysql.QueryError | null, results: mysql.QueryResult) => { if (err) { this.Logger.error(`Error executing query: ${err}`); reject(err); } else { resolve(results); } }, ); }); } /** * Unprepare a previously prepared SQL query. * * @param {string} queryString * - The SQL query string to unprepare. * @return {Promise} * - A promise that resolves if the unprepare operation is successful, * or rejects with an error if there was an error unpreparing the query. */ unprepare(queryString: string): Promise { return new Promise((resolve, reject) => { try { resolve(this.Connection.unprepare(queryString)); } catch (err) { reject(err); } }); } } const MySqlService = { Handler: MysqlHandler, //ToTest all User: { /** * Inserts a new user into the database. * * @param {MysqlHandler} handler - The MySQL database handler. * @param {IDbUser} data - The user data to insert. * @returns {Promise} A promise that resolves with the database status result. * @throws {Error} If an error occurs during the execution. * @throws {string} If the `id` field is undefined or invalid. */ insert(handler: MysqlHandler, data: IDbUser): Promise { return new Promise((resolve, reject) => { if (!data.id) return reject("Id is undefined"); if (data.id.length !== 36) return reject("Id invalid"); handler .factorize({ values: data, actionName: "Inserting new user", }) .then((result) => { const valuesArray = result._valuesArray; const template = result._keysTemplate; const _sql = `INSERT INTO users (${template + `, id`}) VALUES(${ result._questionMarksFields })`; try { if (isDebugMode()) handler.Logger.trace(_sql); if (isDebugMode()) handler.Logger.trace(valuesArray); //ToTest handler.execute(_sql, valuesArray).then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); }); }, /** * Updates a user in the database. * @param {MysqlHandler} handler - The MySQL handler object. * @param {IUserUpdate} data - The updated user data. * @returns {Promise} - A promise that resolves to the result of the update operation. * @throws {Error} If an error occurs during the update operation. */ update(handler: MysqlHandler, data: IUserUpdate): Promise { return new Promise((resolve, reject) => { if (data.gdpr && typeof data.gdpr !== typeof Date) { return reject("Invalid gdpr date."); } if (!data.id) return reject("Id is undefined"); if (data.id.length !== 36) return reject("Id invalid"); try { handler .factorize({ values: data, actionName: "Update user..", }) .then((factorizeResult) => { const _sql = `UPDATE users SET (${factorizeResult._keysTemplate}) WERE id VALUES(${factorizeResult._questionMarksFields})`; try { if (isDebugMode()) handler.Logger.trace(_sql); if (isDebugMode()) handler.Logger.trace(factorizeResult._valuesArray); //ToTest handler .execute(_sql, factorizeResult._valuesArray) .then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); } catch (err: unknown) { reject(err as Error); } }); }, //ToTest /** * Retrieves user information from the database based on the provided user ID. * * @param {MysqlHandler} handler - The MySQL handler instance. * @param {string} userId - The user ID used to locate the user in the database. * @returns {Promise>} A promise that resolves with an array of user objects matching the provided user ID. * @throws {string} Throws an error if the provided user ID is invalid. * @throws {Error} Throws*/ getById(handler: MysqlHandler, userId: string): Promise> { return new Promise((resolve, reject) => { if (userId.length !== 36) return reject("Id invalid"); const _sql = "SELECT * FROM users WHERE id VALUES(?)"; const _values = [userId]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as Array); }); } catch (err: unknown) { reject(err as Error); } }); }, //ToTest /** * Retrieves all users from the database. * * @param {MysqlHandler} handler - The MySQL handler object used to query the database. * @return {Promise>} - A promise that resolves with an array of user objects from the database. * @throws {Error} - If an error occurs while querying the database. */ getAll(handler: MysqlHandler): Promise> { return new Promise((resolve, reject) => { const _sql = "SELECT * FROM users"; try { handler.query(_sql).then((result) => { return resolve(result as unknown as Array); }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Retrieves a user from the database by email. * * @param {MysqlHandler} handler - The MySQL database handler instance. * @param {string} email - The email of the user to retrieve. * @return {Promise>} - A promise that resolves to the retrieved user object. * @throws {Error} - If an error occurs while retrieving the user. */ getByEmail(handler: MysqlHandler, email: string): Promise> { return new Promise((resolve, reject) => { if (!email) return reject("email is undefined"); const _sql = "SELECT * FROM users WHERE email VALUES(?)"; const _values = [email]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as Array); }); } catch (err: unknown) { reject(err as Error); } }); }, //ToTest /** * Retrieves the admin state for a given user ID. * * @param {MysqlHandler} handler - The MySQL handler object used for executing the query. * @param {string} userId - The ID of the user to get the admin state for. * @return {Promise} A Promise that resolves to a boolean value indicating whether the user is an admin or not. * @throws {Error} if an error occurs during the execution of the query. */ getAdminStateForId( handler: MysqlHandler, userId: string, ): Promise { return new Promise((resolve, reject) => { const _sql = "SELECT is_admin FROM users WHERE id VALUES(?)"; const _values = [userId]; try { //FIX Output type const isAdmin = handler.execute( _sql, _values, ) as unknown as Promise; isAdmin.then((result: boolean) => { if (!result) return resolve(false); return resolve(true); }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Deletes a user from the database. * @param {MysqlHandler} handler - The MySQL handler object. * @param {string} userId - The ID of the user to delete. * @return {Promise} - A Promise that resolves when the deletion is successful, or rejects with an error. */ delete(handler: MysqlHandler, userId: string): Promise { return new Promise((resolve, reject) => { if (!userId) return reject("Id is undefined"); if (userId.length !== 36) return reject("Id invalid"); const _sql = "DELETE FROM users WHERE id VALUES(?)"; const _values = [userId]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); }, }, Brand: { /** * Inserts a new record into the `brands` table. * * @param {MysqlHandler} handler - The MySQL handler object used to execute the SQL query. * @param {IDbBrand} data - The data to be inserted into the table. * @returns {Promise} - A Promise that resolves to the status result of the insert operation. * @throws {Error} - If an error occurs during the execution of the SQL query. */ insert(handler: MysqlHandler, data: IDbBrand): Promise { return new Promise((resolve, reject) => { if (!data.id) return reject("Id is undefined"); if (data.id.length !== 36) return reject("Id invalid"); handler .factorize({ values: data, actionName: "Inserting new brand", }) .then((result) => { const valuesArray = result._valuesArray; const template = result._keysTemplate; const _sql = `INSERT INTO brands (${template + `, id`}) VALUES(${ result._questionMarksFields })`; try { if (isDebugMode()) handler.Logger.trace(_sql); if (isDebugMode()) handler.Logger.trace(valuesArray); //ToTest handler.execute(_sql, valuesArray).then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); }); }, /** * Update the brand information in the database. * * @param {MysqlHandler} handler - The MySQL handler object used for executing the SQL query. * @param {IDbBrand} data - The data object containing the updated brand information. * @returns {Promise} - A promise that resolves to the status result of the update operation. * @throws {Error} - If any error occurs during the process. */ update(handler: MysqlHandler, data: IDbBrand): Promise { return new Promise((resolve, reject) => { if (!data.id) return reject("Id is undefined"); if (data.id.length !== 36) return reject("Id invalid"); try { handler .factorize({ values: data, actionName: "Update brand..", }) .then((factorizeResult) => { const _sql = `UPDATE brands SET (${factorizeResult._keysTemplate}) WERE id VALUES(${factorizeResult._questionMarksFields})`; try { if (isDebugMode()) handler.Logger.trace(_sql); if (isDebugMode()) handler.Logger.trace(factorizeResult._valuesArray); //ToTest handler .execute(_sql, factorizeResult._valuesArray) .then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Retrieves all records from the `brands` table. * * @param {MysqlHandler} handler - The MySQL handler object to execute the query. * * @return {Promise>} A promise that resolves to an array of IDbBrand objects representing the retrieved records. If an error occurs during the query execution, the promise will be rejected with an Error object. */ getAll(handler: MysqlHandler): Promise> { return new Promise((resolve, reject) => { const _sql = "SELECT * FROM brands"; try { handler.query(_sql).then((result) => { return resolve(result as unknown as Array); }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Fetches a category by its Id * * @param {MysqlHandler} handler - The instance of the MysqlHandler used for executing the query * @param {string} brandId - The Id of the category to be fetched * @return {Promise} - A promise that, when resolved, returns the category matching the Id * @throws {Error} - If an error occurs during execution * @throws {string} - If brandId is undefined or invalid */ getById(handler: MysqlHandler, brandId: string): Promise { return new Promise((resolve, reject) => { if (!brandId) return reject("Id is undefined"); if (brandId.length !== 36) return reject("Id invalid"); const _sql = "SELECT * FROM brands WHERE id VALUES(?)"; const _values = [brandId]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as IDbBrand); }); } catch (err: unknown) { //TODO Reject with null and logger error reject(err as Error); } }); }, /** * Retrieves a brand from the database by its slug. * * @param {MysqlHandler} handler - The MySQL handler object used to connect to the database. * @param {string} brandSlug - The slug of the brand to retrieve. * @returns {Promise} - A promise that resolves with the brand object if found, or rejects with an error message. */ getBySlug(handler: MysqlHandler, brandSlug: string): Promise { return new Promise((resolve, reject) => { if (!brandSlug) return reject("slug is undefined"); const _sql = "SELECT * FROM brands WHERE slug_name VALUES(?)"; const _values = [brandSlug]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as IDbBrand); }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Deletes a brand from the database. * * @param {MysqlHandler} handler - The database handler object. * @param {string} brandId - The ID of the brand to delete. * @returns {Promise} A promise that resolves to the database status result. * @throws {Error} If an error occurs while deleting the brand. */ delete(handler: MysqlHandler, brandId: string): Promise { //TODO check if has models linked before actions return new Promise((resolve, reject) => { if (!brandId) return reject("Id is undefined"); if (brandId.length !== 36) return reject("Id invalid"); const _sql = "DELETE FROM brands WHERE id VALUES(?)"; const _values = [brandId]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); }, //TODO Get models of the brand }, Model: { /** * Retrieves all records from the 'models' table. * * @param {MysqlHandler} handler - The MySQL handler object used to execute the query. * @return {Promise>} - A promise that resolves to an array of IDbModel objects representing the retrieved records from the 'models' table. * @throws {Error} - If there is an error executing the query. */ getAll(handler: MysqlHandler): Promise> { return new Promise((resolve, reject) => { const _sql = "SELECT * FROM models"; try { handler.query(_sql).then((result) => { return resolve(result as unknown as Array); }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Retrieves a database model by slug from a given MySQL handler. * * @param {MysqlHandler} handler - The MySQL handler instance. * @param {string} modelSlug - The slug of the model to retrieve. * @return {Promise} A promise that resolves with the retrieved model. * @throws {Error} If there was an error executing the query. */ getBySlug(handler: MysqlHandler, modelSlug: string): Promise { return new Promise((resolve, reject) => { const _sql = "SELECT * FROM models WHERE slug_name VALUES(?)"; const _values = [modelSlug]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as IDbModel); }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Retrieves a model by its ID from the database. * * @param {MysqlHandler} handler - The MySQL handler object used to execute the SQL query. * @param {string} modelId - The ID of the model to retrieve. * @return {Promise} - A promise that resolves with the retrieved model, or rejects with an error. */ getById(handler: MysqlHandler, modelId: string): Promise { return new Promise((resolve, reject) => { const _sql = "SELECT * FROM models WHERE id VALUES(?)"; const _values = [modelId]; try { resolve(handler.execute(_sql, _values) as unknown as IDbModel); } catch (err: unknown) { reject(err as Error); } }); }, /** * Inserts a record into the `models` table. * * @param {MysqlHandler} handler - The MySQL handler object. * @param {IDbModel} data - The data object containing the record properties. * @throws {string} - Throws an error message if the id is undefined or invalid. * @returns {Promise} - A promise that resolves to the status result of the insert operation. */ insert(handler: MysqlHandler, data: IDbModel): Promise { return new Promise((resolve, reject) => { if (!data.id) return reject("Id is undefined"); if (data.id.length !== 36) return reject("Id invalid"); handler .factorize({ values: data, actionName: "Inserting new model", }) .then((factorizedResult) => { const valuesArray = factorizedResult._valuesArray; const template = factorizedResult._keysTemplate; const _sql = `INSERT INTO users (${template + `, id`}) VALUES(${ factorizedResult._questionMarksFields })`; try { if (isDebugMode()) handler.Logger.trace(_sql); if (isDebugMode()) handler.Logger.trace(valuesArray); //ToTest handler.execute(_sql, valuesArray).then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); }); }, //TODO get linked vehicles /** * Updates a database model in the "models" table. * * @param {MysqlHandler} handler - The MySQL handler object. * @param {IDbModel} data - The data object containing the updated model details. * @return {Promise} - A promise that resolves to the status result of the update operation. * @throws {Error} - If an error occurs during the update process. */ update(handler: MysqlHandler, data: IDbModel): Promise { return new Promise((resolve, reject) => { if (!data.id) return reject("Id is undefined"); if (data.id.length !== 36) return reject("Id invalid"); try { handler .factorize({ values: data, actionName: "Update model..", }) .then((factorizeResult) => { const _sql = `UPDATE models SET (${factorizeResult._keysTemplate}) WERE id VALUES(${factorizeResult._questionMarksFields})`; try { if (isDebugMode()) handler.Logger.trace(_sql); if (isDebugMode()) handler.Logger.trace(factorizeResult._valuesArray); //ToTest handler .execute(_sql, factorizeResult._valuesArray) .then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Deletes a model from the database. * * @param {MysqlHandler} handler - The MySQL handler object. * @param {string} modelId - The ID of the model to delete. * @returns {Promise} A promise that resolves to the result of the delete operation. * @throws {Error} If an error occurs during the delete operation. */ delete(handler: MysqlHandler, modelId: string): Promise { //TODO check if has models linked before actions return new Promise((resolve, reject) => { if (!modelId) return reject("Id is undefined"); if (modelId.length !== 36) return reject("Id invalid"); const _sql = "DELETE FROM models WHERE id VALUES(?)"; const _values = [modelId]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); }, }, Vehicle: { /** * Inserts a new record into the `vehicles` table. * @param {MysqlHandler} handler - The MySQL handler object. * @param {IDbVehicle} data - The vehicle data to be inserted. * @throws Throws an error if the provided `data` object does not contain the `id` property or if the `id` is not a valid UUID. * @returns {Promise} A promise that resolves to the result of the insert operation. */ insert(handler: MysqlHandler, data: IDbVehicle): Promise { return new Promise((resolve, reject) => { if (!data.id) return reject("Id is undefined"); if (data.id.length !== 36) return reject("Id invalid"); handler .factorize({ values: data, actionName: "Inserting new vehicle", }) .then((factorizedResult) => { const valuesArray = factorizedResult._valuesArray; const template = factorizedResult._keysTemplate; const _sql = `INSERT INTO models (${template + `, id`}) VALUES(${ factorizedResult._questionMarksFields })`; try { if (isDebugMode()) handler.Logger.trace(_sql); if (isDebugMode()) handler.Logger.trace(valuesArray); //ToTest handler.execute(_sql, valuesArray).then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); }); }, /** * Update a vehicle record in the database. * * @param {MysqlHandler} handler - The MySQL handler object for executing the SQL query. * @param {IDbVehicle} data - The updated vehicle data. * @throws {string} Throws an error if the id is undefined or invalid. * @returns {Promise} Returns a Promise that resolves to the status result of the update operation. */ update(handler: MysqlHandler, data: IDbVehicle): Promise { return new Promise((resolve, reject) => { if (!data.id) return reject("Id is undefined"); if (data.id.length !== 36) return reject("Id invalid"); try { handler .factorize({ values: data, actionName: "Update vehicle..", }) .then((factorizeResult) => { const _sql = `UPDATE vehicles SET (${factorizeResult._keysTemplate}) WERE id VALUES(${factorizeResult._questionMarksFields})`; try { if (isDebugMode()) handler.Logger.trace(_sql); if (isDebugMode()) handler.Logger.trace(factorizeResult._valuesArray); //ToTest handler .execute(_sql, factorizeResult._valuesArray) .then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Retrieves a vehicle from the database by its ID. * * @param {MysqlHandler} handler - The instance of the MySQL handler. * @param {string} vehicleId - The ID of the vehicle to retrieve. * @returns {Promise} - A promise that resolves to the retrieved vehicle. * @throws {Error} - If an error occurs while retrieving the vehicle. */ getById(handler: MysqlHandler, vehicleId: string): Promise { return new Promise((resolve, reject) => { if (!vehicleId) return reject("Id is undefined"); if (vehicleId.length !== 36) return reject("Id invalid"); const _sql = "SELECT * FROM vehicles WHERE id VALUES(?)"; const _values = [vehicleId]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as IDbVehicle); }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Retrieves all vehicles from the database. * * @param {MysqlHandler} handler - The MySQL handler for executing queries. * @return {Promise>} A promise that resolves with an array of database vehicles. * @throws {Error} If an error occurs during the database query. */ getAll(handler: MysqlHandler): Promise> { return new Promise((resolve, reject) => { const _sql = "SELECT * FROM models"; try { handler.query(_sql).then((result) => { return resolve(result as unknown as Array); }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Retrieves the available vehicles from the database. * * @param {MysqlHandler} handler - The MySQL handler object used to execute the query. * @returns {Promise>} A promise that resolves to an array of available vehicles. * @throws {Error} If an error occurs while executing the query. */ getAvailable(handler: MysqlHandler): Promise> { return new Promise((resolve, reject) => { const _sql = "SELECT * FROM vehicles WERE isAvailable = 1"; try { handler.query(_sql).then((result) => { return resolve(result as unknown as Array); }); } catch (err: unknown) { reject(err as Error); } }); }, delete(handler: MysqlHandler, vehicleId: string): Promise { return new Promise((resolve, reject) => { if (!vehicleId) return reject("Id is undefined"); if (vehicleId.length !== 36) return reject("Id invalid"); const _sql = "DELETE FROM vehicle WHERE id VALUES(?)"; const _values = [vehicleId]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); }, }, Category: { /** * Insert a category into the database. * * @param {MysqlHandler} handler - The MySQL handler instance. * @param {IDbCategory} data - The category data to insert. * @returns {Promise} A promise that resolves to the status result of the insertion. * @throws {Error} If an error occurs during the execution of the insertion. */ insert(handler: MysqlHandler, data: IDbCategory): Promise { return new Promise((resolve, reject) => { if (!data.id) return reject("Id is undefined"); if (data.id.length !== 36) return reject("Id invalid"); handler .factorize({ values: data, actionName: "Inserting new category", }) .then((factorizedResult) => { const valuesArray = factorizedResult._valuesArray; const template = factorizedResult._keysTemplate; const _sql = `INSERT INTO categories (${ template + `, id` }) VALUES(${factorizedResult._questionMarksFields})`; try { if (isDebugMode()) handler.Logger.trace(_sql); if (isDebugMode()) handler.Logger.trace(valuesArray); //ToTest handler.execute(_sql, valuesArray).then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); }); }, /** * Updates a category in the database. * * @param {MysqlHandler} handler - The MySQL handler for executing database queries. * @param {IDbCategory} data - The category data to be updated. * @returns {Promise} - A promise that resolves to the status result of the update operation. */ update(handler: MysqlHandler, data: IDbCategory): Promise { return new Promise((resolve, reject) => { if (!data.id) return reject("Id is undefined"); if (data.id.length !== 36) return reject("Id invalid"); try { handler .factorize({ values: data, actionName: "Update brand..", }) .then((factorizeResult) => { const _sql = `UPDATE categories SET (${factorizeResult._keysTemplate}) WERE id VALUES(${factorizeResult._questionMarksFields})`; try { if (isDebugMode()) handler.Logger.trace(_sql); if (isDebugMode()) handler.Logger.trace(factorizeResult._valuesArray); //ToTest handler .execute(_sql, factorizeResult._valuesArray) .then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Retrieves all categories from the database. * * @param {MysqlHandler} handler - The MySQL handler used for executing the query. * * @return {Promise>} * - A promise that resolves with an array of category objects from the database. * - The category objects are of type IDbCategory. * - If an error occurs, the promise will be rejected with an Error object. */ getAll(handler: MysqlHandler): Promise> { return new Promise((resolve, reject) => { const _sql = "SELECT * FROM categories"; try { resolve(handler.query(_sql) as unknown as Array); } catch (err: unknown) { reject(err as Error); } }); }, /** * Retrieves a category from the database by its slug. * * @param {MysqlHandler} handler - The MySQL handler object to execute the query. * @param {string} categorySlug - The slug of the category to retrieve. * @returns {Promise} - A promise that resolves with the retrieved category object. * @throws {Error} - If an error occurs while executing the query. */ getBySlug( handler: MysqlHandler, categorySlug: string, ): Promise { return new Promise((resolve, reject) => { if (!categorySlug) return reject("slug is undefined"); const _sql = "SELECT * FROM categories WHERE slug_name VALUES(?)"; const _values = [categorySlug]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as IDbCategory); }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Retrieves a category from the database by its ID. * * @param {MysqlHandler} handler - The MySQL handler object used for execution. * @param {string} categoryId - The ID of the category to retrieve. * @returns {Promise} - A Promise that resolves with the category object. * @throws {Error} - If an error occurs during execution. */ getById(handler: MysqlHandler, categoryId: string): Promise { return new Promise((resolve, reject) => { if (!categoryId) return reject("slug is undefined"); if (categoryId.length !== 36) return reject("Id invalid"); const _sql = "SELECT * FROM categories WHERE id VALUES(?)"; const _values = [categoryId]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as IDbCategory); }); } catch (err: unknown) { reject(err as Error); } }); }, /** * Deletes a category from the database based on the given categoryId. * * @param {MysqlHandler} handler - The MysqlHandler object for executing database queries. * @param {string} categoryId - The ID of the category to be deleted. * * @returns {Promise} - A promise that resolves to the database status result after deletion. * @throws {Error} - If an error occurs while executing the deletion query. */ delete( handler: MysqlHandler, categoryId: string, ): Promise { return new Promise((resolve, reject) => { if (!categoryId) return reject("Id is undefined"); if (categoryId.length !== 36) return reject("Id invalid"); const _sql = "DELETE FROM categories WHERE id VALUES(?)"; const _values = [categoryId]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); }, //ToTest /** * Retrieves all models from a specific category. * * @param {MysqlHandler} handler - The MySQL handler object used for executing the query. * @param {string} categoryId - The ID of the category. * @return {Promise>} - A promise that resolves to an array of database models belonging to the specified category. */ getAllModelsFromCategory( handler: MysqlHandler, categoryId: string, ): Promise> { return new Promise((resolve, reject) => { const _sql = "SELECT models.* FROM models INNER JOIN categories ON models.category_id = categories.id WHERE categories.id VALUES(?)"; try { handler.execute(_sql, [categoryId]).then((result) => { return resolve(result as unknown as Array); }); } catch (err: unknown) { reject(err as Error); } }); }, }, Rent: { //ToTest insert(handler: MysqlHandler, data: IDbRent): Promise { return new Promise((resolve, reject) => { if (!data.id) return reject("Id is undefined"); if (data.id.length !== 36) return reject("Id invalid"); handler .factorize({ values: data, actionName: "Inserting new rent", }) .then((factorizedResult) => { const valuesArray = factorizedResult._valuesArray; const template = factorizedResult._keysTemplate; const _sql = `INSERT INTO rents (${template + `, id`}) VALUES(${ factorizedResult._questionMarksFields })`; try { if (isDebugMode()) handler.Logger.trace(_sql); if (isDebugMode()) handler.Logger.trace(valuesArray); //ToTest handler.execute(_sql, valuesArray).then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); }); }, //ToTest /** * Retrieves the assigned vehicles for a given user. * * @param {MysqlHandler} handler - The MySQL handler used to execute the database query. * @param {string} userId - The ID of the user. * @returns {Promise>} A promise that resolves to an array of assigned vehicles. * @throws {Error} If an error occurs during the execution of the query. * @throws {string} If the user ID is undefined or invalid. */ getAssignedToUser( handler: MysqlHandler, userId: string, ): Promise> { return new Promise((resolve, reject) => { if (!userId) return reject("Id is undefined"); if (userId.length !== 36) return reject("Id invalid"); const _sql = "SELECT vehicle.* FROM rent JOIN vehicles ON rent.vehicle_id = vehicles.id WHERE user_id AND active = 1 VALUES(?)"; const _values = [userId]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as Array); }); } catch (err: unknown) { reject(err as Error); } }); }, //ToTest /** * Retrieves all assigned vehicles from the database. * * @param {MysqlHandler} handler - The MySQL handler object used for executing the query. * * @returns {Promise>} A Promise that resolves with an array of assigned vehicles. * @throws {Error} If an error occurs during query execution or result conversion. */ getAllAssigned(handler: MysqlHandler): Promise> { return new Promise((resolve, reject) => { const _sql = "SELECT vehicle.* FROM rent JOIN vehicles ON rent.vehicle_id = vehicles.id WHERE active = 1"; try { handler.query(_sql).then((result) => { return resolve(result as unknown as Array); }); } catch (err: unknown) { reject(err as Error); } }); }, //ToTest /** * Updates a rent record in the database. * * @param {MysqlHandler} handler - The database handler object. * @param {IDbRent} data - The rent object containing the updated data. * @returns {Promise} - A promise that resolves to the status result of the update operation. * @throws {Error} - If an error occurs during the update operation. */ update(handler: MysqlHandler, data: IDbRent): Promise { return new Promise((resolve, reject) => { if (!data.id) return reject("Id is undefined"); if (data.id.length !== 36) return reject("Id invalid"); try { handler .factorize({ values: data, actionName: "Update rent..", }) .then((factorizeResult) => { const _sql = `UPDATE rents SET (${factorizeResult._keysTemplate}) WERE id = ? VALUES(${factorizeResult._questionMarksFields})`; try { if (isDebugMode()) handler.Logger.trace(_sql); if (isDebugMode()) handler.Logger.trace(factorizeResult._valuesArray); //ToTest handler .execute(_sql, factorizeResult._valuesArray) .then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); } catch (err: unknown) { reject(err as Error); } }); }, delete(handler: MysqlHandler, rentId: string): Promise { return new Promise((resolve, reject) => { if (!rentId) return reject("Id is undefined"); if (rentId.length !== 36) return reject("Id invalid"); const _sql = "DELETE FROM rents WHERE id VALUES(?)"; const _values = [rentId]; try { handler.execute(_sql, _values).then((result) => { return resolve(result as unknown as IDbStatusResult); }); } catch (err: unknown) { reject(err as Error); } }); }, }, }; export default MySqlService;