Add skeleton
This commit is contained in:
24
helpers/error.js
Normal file
24
helpers/error.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
const { logger } = require("../utils/logger");
|
||||||
|
class ErrorHandler extends Error {
|
||||||
|
constructor(statusCode, message) {
|
||||||
|
super();
|
||||||
|
this.status = "error";
|
||||||
|
this.statusCode = statusCode;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleError = (err, req, res, next) => {
|
||||||
|
const { statusCode, message } = err;
|
||||||
|
logger.error(err);
|
||||||
|
res.status(statusCode || 500).json({
|
||||||
|
status: "error",
|
||||||
|
statusCode: statusCode || 500,
|
||||||
|
message: statusCode === 500 ? "An error occurred" : message,
|
||||||
|
});
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
module.exports = {
|
||||||
|
ErrorHandler,
|
||||||
|
handleError,
|
||||||
|
};
|
||||||
12
helpers/hashPassword.js
Normal file
12
helpers/hashPassword.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
const bcrypt = require("bcrypt");
|
||||||
|
|
||||||
|
const hashPassword = async (password) => {
|
||||||
|
const salt = await bcrypt.genSalt();
|
||||||
|
const hashedPassword = await bcrypt.hash(password, salt);
|
||||||
|
return hashedPassword;
|
||||||
|
};
|
||||||
|
|
||||||
|
const comparePassword = async (password, passwordHash) =>
|
||||||
|
await bcrypt.compare(password, passwordHash);
|
||||||
|
|
||||||
|
module.exports = { hashPassword, comparePassword };
|
||||||
13
helpers/test_helper.js
Normal file
13
helpers/test_helper.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
const pool = require("../config");
|
||||||
|
|
||||||
|
const usersInDb = async () => {
|
||||||
|
const users = await pool.query("SELECT * FROM USERS");
|
||||||
|
return users.rows;
|
||||||
|
};
|
||||||
|
|
||||||
|
const productsInDb = async () => {
|
||||||
|
const products = await pool.query("SELECT * FROM products");
|
||||||
|
return products.rows;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { usersInDb, productsInDb };
|
||||||
89
helpers/utils.js
Normal file
89
helpers/utils.js
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
const setResponse = async (data = [], message = "success", statusCode = 200) => {
|
||||||
|
const response = {
|
||||||
|
data,
|
||||||
|
total: data.length,
|
||||||
|
message,
|
||||||
|
statusCode
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
};
|
||||||
|
|
||||||
|
const setResponsePaging = async (data = [], total, limit, page, message = "success", statusCode = 200) => {
|
||||||
|
|
||||||
|
const totalPages = Math.ceil(total / limit);
|
||||||
|
|
||||||
|
const response = {
|
||||||
|
message,
|
||||||
|
statusCode,
|
||||||
|
data,
|
||||||
|
total: data.length,
|
||||||
|
paging: {
|
||||||
|
total,
|
||||||
|
limit,
|
||||||
|
page,
|
||||||
|
page_total: totalPages
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
};
|
||||||
|
|
||||||
|
const setPaging = async (total, limit, page) => {
|
||||||
|
|
||||||
|
const totalPages = Math.ceil(total / limit);
|
||||||
|
|
||||||
|
const response = {
|
||||||
|
total,
|
||||||
|
limit,
|
||||||
|
page,
|
||||||
|
page_total: totalPages
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
};
|
||||||
|
|
||||||
|
function convertId(items, id, fieldId = "id", fieldName = "name") {
|
||||||
|
var match = ""
|
||||||
|
items.forEach(element => {
|
||||||
|
if (element[fieldId] == id) {
|
||||||
|
match = element[fieldName]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatToYYYYMMDD(date) {
|
||||||
|
return new Intl.DateTimeFormat('id-ID', {
|
||||||
|
timeZone: 'Asia/Jakarta',
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
}).format(date).split('/').reverse().join('-'); // Ubah format dari dd/mm/yyyy ke yyyy-mm-dd
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureArray(param) {
|
||||||
|
return Array.isArray(param) ? param : [param];
|
||||||
|
}
|
||||||
|
|
||||||
|
function orderByClauseQuery(orderParams) {
|
||||||
|
orderParams = ensureArray(orderParams)
|
||||||
|
|
||||||
|
// Transform order parameters to SQL ORDER BY syntax
|
||||||
|
const validDirections = ['ASC', 'DESC'];
|
||||||
|
const orderConditions = orderParams.map(param => {
|
||||||
|
const [field, direction] = param.split(':');
|
||||||
|
if (!validDirections.includes(direction.toUpperCase())) {
|
||||||
|
throw new Error(`Invalid direction: ${direction}`);
|
||||||
|
}
|
||||||
|
return `${field} ${direction}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Gabungkan dengan koma untuk digunakan dalam query
|
||||||
|
const orderByClause = orderConditions.join(', ');
|
||||||
|
|
||||||
|
return orderByClause
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { setResponse, setResponsePaging, setPaging, convertId, formatToYYYYMMDD, orderByClauseQuery };
|
||||||
9
helpers/validateUser.js
Normal file
9
helpers/validateUser.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
const validateUser = (email, password) => {
|
||||||
|
const validEmail = typeof email === "string" && email.trim() !== "";
|
||||||
|
const validPassword =
|
||||||
|
typeof password === "string" && password.trim().length >= 6;
|
||||||
|
|
||||||
|
return validEmail && validPassword;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = validateUser;
|
||||||
Reference in New Issue
Block a user