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
+7
View File
@@ -0,0 +1,7 @@
const { PrismaClient } = require('../../generated/prisma');
const prisma = new PrismaClient({
log: ['query', 'info', 'warn', 'error'],
});
module.exports = prisma
+24
View File
@@ -0,0 +1,24 @@
const { PrismaClient } = require("generated/prisma/index.js");
const prisma = new PrismaClient({
log: [
{
emit: 'event',
level: 'query',
},
{
emit: 'stdout',
level: 'error',
},
{
emit: 'stdout',
level: 'info',
},
{
emit: 'stdout',
level: 'warn',
},
],
})
module.exports = { prisma };
+9
View File
@@ -0,0 +1,9 @@
const CommonError = require('./common_error');
class BadRequestError extends CommonError {
constructor(message) {
super(message || 'Bad Request');
}
}
module.exports = BadRequestError;
+7
View File
@@ -0,0 +1,7 @@
class CommonError extends Error {
constructor(message) {
super(message);
}
}
module.exports = CommonError;
+9
View File
@@ -0,0 +1,9 @@
const CommonError = require('./common_error');
class ConflictError extends CommonError {
constructor(message) {
super(message || 'Conflict');
}
}
module.exports = ConflictError;
+9
View File
@@ -0,0 +1,9 @@
const CommonError = require('./common_error');
class ExpectationFailedError extends CommonError {
constructor(message) {
super(message || 'Expectation Failed');
}
}
module.exports = ExpectationFailedError;
+9
View File
@@ -0,0 +1,9 @@
const CommonError = require('./common_error');
class ForbiddenError extends CommonError {
constructor(message) {
super(message || 'Forbidden');
}
}
module.exports = ForbiddenError;
+9
View File
@@ -0,0 +1,9 @@
const CommonError = require('./common_error');
class GatewayTimeoutError extends CommonError {
constructor(message) {
super(message || 'Gateway Timeout');
}
}
module.exports = GatewayTimeoutError;
+23
View File
@@ -0,0 +1,23 @@
const ConflictError = require('./conflict_error');
const ExpectationFailedError = require('./expectation_failed_error');
const ForbiddenError = require('./forbidden_error');
const InternalServerError = require('./internal_server_error');
const NotFoundError = require('./not_found_error');
const UnauthorizedError = require('./unauthorized_error');
const ServiceUnavailableError = require('./service_unavailable_error');
const GatewayTimeoutError = require('./gateway_timeout_error');
const BadRequestError = require('./bad_request_error');
const ValidationError = require('./validation_error');
module.exports = {
ConflictError,
ExpectationFailedError,
ForbiddenError,
InternalServerError,
NotFoundError,
UnauthorizedError,
ServiceUnavailableError,
GatewayTimeoutError,
BadRequestError,
ValidationError
};
+9
View File
@@ -0,0 +1,9 @@
const CommonError = require('./common_error');
class InternalServerError extends CommonError {
constructor(message) {
super(message || 'Internal Server Error');
}
}
module.exports = InternalServerError;
+9
View File
@@ -0,0 +1,9 @@
const CommonError = require('./common_error');
class NotFoundError extends CommonError {
constructor(message) {
super(message || 'Not Found');
}
}
module.exports = NotFoundError;
+9
View File
@@ -0,0 +1,9 @@
const CommonError = require('./common_error');
class ServiceUnavailableError extends CommonError {
constructor(message) {
super(message || 'Service Unavailable');
}
}
module.exports = ServiceUnavailableError;
+9
View File
@@ -0,0 +1,9 @@
const CommonError = require('./common_error');
class Unauthorized extends CommonError {
constructor(message) {
super(message || 'Unauthorized');
}
}
module.exports = Unauthorized;
+8
View File
@@ -0,0 +1,8 @@
class ValidationError extends Error {
constructor(message, errors) {
super(message || 'Validation Error');
this.errors = errors
}
}
module.exports = ValidationError;
+21
View File
@@ -0,0 +1,21 @@
const ERROR = {
'BAD_REQUEST': 400,
'NOT_FOUND': 404,
'INTERNAL_ERROR': 500,
'CONFLICT': 409,
'EXPECTATION_FAILED': 417,
'FORBIDDEN': 403,
'UNAUTHORIZED': 401,
'SERVICE_UNAVAILABLE': 503,
'GATEWAY_TIMEOUT': 504
};
const SUCCESS = {
'OK': 200,
'CREATED': 201
};
module.exports = {
ERROR,
SUCCESS
};
+30
View File
@@ -0,0 +1,30 @@
const dotnev = require('dotenv');
dotnev.config({ path: '.env' })
const config = {
port: process.env.EXPRESS_PORT,
jwtPrivateKey: process.env.JWT_PRIVATE_KEY,
jwtPublicKey: process.env.JWT_PUBLIC_KEY,
nodeEnv: process.env.NODE_ENV,
mysqlConfig: {
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: process.env.MYSQL_DATABASE,
dialect: 'mysql',
logging: false
},
nodemailerConfig: {
email: process.env.NODEMAILER_EMAIL,
password: process.env.NODEMAILER_PASSWORD
},
cloudinaryConfig: {
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
secure: true
}
};
module.exports = { config };
+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
};