refactor: rewrite ke codebase lama

This commit is contained in:
Muhammad Zhafran Ilham
2026-06-07 20:17:49 +07:00
parent ce5487dcbf
commit fe74b2213d
146 changed files with 14608 additions and 6686 deletions
+53
View File
@@ -0,0 +1,53 @@
const path = require('path');
const fs = require('fs').promises;
const fsSync = require('fs');
async function deleteFileIfExists(fileName) {
try {
const uploadDir = process.env.NODE_ENV === 'production'
? '/tmp/uploads'
: path.join(__dirname, '..', '..', 'uploads');
const fullPath = path.join(uploadDir, fileName);
await fs.access(fullPath);
await fs.unlink(fullPath);
console.log(`File dihapus: ${fullPath}`);
} catch (err) {
if (err.code === 'ENOENT') {
console.warn(`File tidak ditemukan: ${fileName}`);
} else {
console.error(`Gagal menghapus file (${fileName}):`, err.message);
}
}
}
function checkFileExists(filePath) {
try {
if (!filePath) return false;
const uploadDir = process.env.NODE_ENV === 'production'
? '/tmp/uploads'
: path.join(__dirname, '..', '..', 'uploads');
const fileName = path.basename(filePath);
const fullPath = path.join(uploadDir, fileName);
return fsSync.existsSync(fullPath);
} catch (err) {
console.error(`Error checking file existence: ${err.message}`);
return false;
}
}
function validateImagePath(imagePath) {
if (!imagePath) return null;
const fileExists = checkFileExists(imagePath);
return fileExists ? imagePath : null;
}
module.exports = {
deleteFileIfExists,
checkFileExists,
validateImagePath
};
+57
View File
@@ -0,0 +1,57 @@
const { BadRequestError } = require('../error');
class ImageUploadHelper {
uploadImage(file) {
if (!file) {
throw new BadRequestError('Please upload an image!');
}
return `/uploads/${file.filename}`;
}
uploadCV(file) {
if (!file) {
throw new BadRequestError('Please upload your CV');
}
return `/uploads/${file.filename}`;
}
uploadPortofolio(file) {
if (!file) {
throw new BadRequestError('Please upload your portfolio');
}
return `/uploads/${file.filename}`;
}
validateImage(file) {
if (!file) {
return false;
}
const allowedTypes = ['image/jpeg', 'image/png', 'image/jpg', 'image/webp'];
return allowedTypes.includes(file.mimetype);
}
validatePDF(file) {
if (!file) {
return false;
}
const allowedTypes = ['application/pdf'];
return allowedTypes.includes(file.mimetype);
}
validateDocument(file) {
if (!file) {
return false;
}
const allowedTypes = [
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
];
return allowedTypes.includes(file.mimetype);
}
}
module.exports = new ImageUploadHelper();
+20
View File
@@ -0,0 +1,20 @@
require('dotenv').config();
const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.AUTH_EMAIL,
pass: process.env.AUTH_PASSWORD,
},
});
transporter.verify((error) => {
if (error) {
console.log('Error setup email:', error);
} else {
console.log('Server siap mengirim email');
}
});
module.exports = transporter;
+25
View File
@@ -0,0 +1,25 @@
const wrapper = require('./wrapper');
const { ValidationError } = require('../error');
const isValidPayload = (payload, model) => {
const { value, error } = model.validate(payload, {
abortEarly: false,
allowUnknown: true,
stripUnknown: true,
});
if (error) {
let errors = {};
error.details.forEach(element => {
errors[element.path[0]] = element.message;
});
return wrapper.error(new ValidationError('Validation Error', errors));
}
return { err: null, data: value };
};
module.exports = {
isValidPayload,
};
+95
View File
@@ -0,0 +1,95 @@
const {
NotFoundError,
InternalServerError,
BadRequestError,
ConflictError,
ExpectationFailedError,
ForbiddenError,
GatewayTimeoutError,
ServiceUnavailableError,
UnauthorizedError,
ValidationError
} = require('../error');
const { ERROR: httpError } = require('../http-status/status_code');
const response = (res, type, result, message = '', code = 200) => {
let status = true;
let data = result?.data ?? null;
if (type === 'fail') {
status = false;
data = null;
message = result.err instanceof ValidationError ? result.err.errors : result.err?.message || message;
code = checkErrorCode(result.err);
}
res.status(code).json({
status,
data,
message,
code,
});
};
const paginationResponse = (res, type, result, message = '', code = 200) => {
let status = true;
let data = result?.data ?? null;
let meta = result?.meta ?? null;
if (type === 'fail') {
status = false;
data = '';
message = result.err instanceof ValidationError ? { errors: result.err.errors } : result.err?.message || message;
code = checkErrorCode(result.err);
}
console.log(typeof message)
res.status(code).json({
status: status,
data,
meta,
message,
code,
});
}
const checkErrorCode = (error) => {
switch (error.constructor) {
case BadRequestError:
return httpError.BAD_REQUEST;
case ConflictError:
return httpError.CONFLICT;
case ExpectationFailedError:
return httpError.EXPECTATION_FAILED;
case ForbiddenError:
return httpError.FORBIDDEN;
case GatewayTimeoutError:
return httpError.GATEWAY_TIMEOUT;
case InternalServerError:
return httpError.INTERNAL_ERROR;
case NotFoundError:
return httpError.NOT_FOUND;
case ServiceUnavailableError:
return httpError.SERVICE_UNAVAILABLE;
case UnauthorizedError:
return httpError.UNAUTHORIZED;
case ValidationError:
return httpError.BAD_REQUEST;
default:
return httpError.INTERNAL_ERROR;
}
};
const data = (data) => ({ err: null, data });
const paginationData = (data, meta) => ({ err: null, data, meta });
const error = (err) => ({ err, data: null });
module.exports = {
data,
paginationData,
error,
response,
paginationResponse
};