Update various configuration files, components, and assets; enhance notification system and API endpoints; improve documentation and styles across the application.

This commit is contained in:
Haqeem Solehan
2025-10-16 16:05:39 +08:00
commit b124ff8092
336 changed files with 94392 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
export default defineEventHandler(async (event) => {
try {
const { tableName } = getQuery(event);
if (!tableName) {
return {
statusCode: 400,
message: "Table name is required",
};
}
const result = await prisma.$queryRaw`SELECT DATABASE() AS db_name`;
// console.log(result[0].db_name);
if (result.length === 0) {
return {
statusCode: 500,
message: "Please check your database connection",
};
}
let sqlRaw = ` SELECT
c.COLUMN_NAME,
c.DATA_TYPE,
c.CHARACTER_MAXIMUM_LENGTH,
c.COLUMN_DEFAULT,
c.IS_NULLABLE,
c.COLUMN_KEY,
kcu.REFERENCED_TABLE_NAME,
kcu.REFERENCED_COLUMN_NAME
FROM
INFORMATION_SCHEMA.COLUMNS c
LEFT JOIN
INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON
c.TABLE_SCHEMA = kcu.TABLE_SCHEMA AND
c.TABLE_NAME = kcu.TABLE_NAME AND
c.COLUMN_NAME = kcu.COLUMN_NAME
WHERE
c.TABLE_SCHEMA = '${result[0].db_name}' AND
c.TABLE_NAME = '${tableName}';`;
// console.log(sqlRaw);
const getTableDetails = await prisma.$queryRawUnsafe(sqlRaw);
// console.log(getTableDetails);
/*
[{
"actions": "",
"defaultValue": "",
"length": "",
"name": "PID",
"nullable": "",
"primaryKey": true,
"type": "INT"
},
{
"actions": "",
"defaultValue": "",
"length": "",
"name": "Pproduct",
"nullable": true,
"primaryKey": "",
"type": "VARCHAR"
},
{
"actions": "",
"defaultValue": "",
"length": "",
"name": "userID",
"nullable": "",
"primaryKey": "",
"type": "[[user]]"
}]
*/
let tableDetailsData = [];
// Loop through the result and convert bigInt to number
for (let i = 0; i < getTableDetails.length; i++) {
const table = getTableDetails[i];
tableDetailsData.push({
name: table.COLUMN_NAME,
type: table.REFERENCED_TABLE_NAME
? `[[${table.REFERENCED_TABLE_NAME}]]`
: table.DATA_TYPE.toUpperCase(),
length: bigIntToNumber(table.CHARACTER_MAXIMUM_LENGTH),
defaultValue: table.COLUMN_DEFAULT,
nullable: table.IS_NULLABLE === "YES",
primaryKey: table.COLUMN_KEY === "PRI",
actions: {},
});
}
return {
statusCode: 200,
message: "Success",
data: tableDetailsData,
};
} catch (error) {
console.log(error.message);
return {
statusCode: 500,
message: "Internal Server Error",
};
}
});
function bigIntToNumber(bigInt) {
if (bigInt === null) return null;
return Number(bigInt.toString());
}

View File

@@ -0,0 +1,191 @@
import { spawn } from "node:child_process";
import { fileURLToPath } from "url";
import { dirname, resolve } from "path";
import os from "os";
export default defineEventHandler(async (event) => {
try {
const { tableName, tableSchema, autoIncrementColumn } =
await readBody(event);
if (!tableName || !tableSchema) {
return {
statusCode: 400,
message: "Bad Request",
};
}
// Get existing table structure
const existingColumns = await prisma.$queryRaw`
SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ${tableName}
`;
// Compare and modify table structure
for (const column of tableSchema) {
const existingColumn = existingColumns.find(
(c) => c.COLUMN_NAME === column.name
);
if (existingColumn) {
// Modify existing column
await modifyColumn(tableName, column, existingColumn);
} else {
// Add new column
await addColumn(tableName, column);
}
}
// Remove columns that are not in the new schema
for (const existingColumn of existingColumns) {
if (!tableSchema.find((c) => c.name === existingColumn.COLUMN_NAME)) {
await removeColumn(tableName, existingColumn.COLUMN_NAME);
}
}
// Update auto-increment column if necessary
if (autoIncrementColumn) {
await updateAutoIncrement(tableName, autoIncrementColumn);
}
// Run Prisma Command to update the schema
const isPrismaCommandRun = await runPrismaCommand();
if (!isPrismaCommandRun) {
return {
statusCode: 500,
message: "Prisma Command Failed",
};
}
return {
statusCode: 200,
message: "Table modified successfully",
};
} catch (error) {
console.error(error);
return {
statusCode: 500,
message: "Internal Server Error",
};
}
});
async function modifyColumn(tableName, newColumn, existingColumn) {
let alterStatement = `ALTER TABLE ${tableName} MODIFY COLUMN ${newColumn.name} ${newColumn.type}`;
if (newColumn.length) {
alterStatement += `(${newColumn.length})`;
}
alterStatement += newColumn.nullable ? " NULL" : " NOT NULL";
if (newColumn.defaultValue) {
alterStatement += ` DEFAULT ${newColumn.defaultValue}`;
}
await prisma.$executeRawUnsafe(alterStatement);
}
async function addColumn(tableName, column) {
let alterStatement = `ALTER TABLE ${tableName} ADD COLUMN ${column.name} ${column.type}`;
if (column.length) {
alterStatement += `(${column.length})`;
}
alterStatement += column.nullable ? " NULL" : " NOT NULL";
if (column.defaultValue) {
alterStatement += ` DEFAULT ${column.defaultValue}`;
}
await prisma.$executeRawUnsafe(alterStatement);
}
async function removeColumn(tableName, columnName) {
await prisma.$executeRawUnsafe(
`ALTER TABLE ${tableName} DROP COLUMN ${columnName}`
);
}
async function updateAutoIncrement(tableName, autoIncrementColumn) {
await prisma.$executeRawUnsafe(
`ALTER TABLE ${tableName} MODIFY ${autoIncrementColumn} INT AUTO_INCREMENT`
);
}
async function runPrismaCommand(retries = 3) {
try {
console.log("---------- Run Prisma Command ----------");
const __dirname = dirname(fileURLToPath(import.meta.url));
const directory = resolve(__dirname, "../..");
// Command to execute
const command = "npx prisma db pull && npx prisma generate";
// Determine the appropriate shell command based on the platform
let shellCommand;
let spawnOptions;
switch (os.platform()) {
case "win32":
shellCommand = `Start-Process cmd -ArgumentList '/c cd "${directory}" && ${command}' -Verb RunAs`;
spawnOptions = {
shell: "powershell.exe",
args: ["-Command", shellCommand],
};
break;
case "darwin":
case "linux":
shellCommand = `cd "${directory}" && ${command}`;
spawnOptions = {
shell: "sh",
args: ["-c", shellCommand],
};
break;
default:
console.error("Unsupported platform:", os.platform());
return false;
}
// Spawn child process using the appropriate shell command
const childProcess = spawn(spawnOptions.shell, spawnOptions.args, {
stdio: "inherit",
});
// Listen for child process events
return new Promise((resolve, reject) => {
childProcess.on("close", (code) => {
if (code === 0) {
console.log("Prisma commands executed successfully");
resolve(true);
} else {
console.error(`Child process exited with code ${code}`);
reject(new Error(`Child process exited with code ${code}`));
}
});
});
} catch (error) {
console.error("Error running Prisma commands:", error);
return false;
}
}
function spawnCommand(command, args, cwd) {
return new Promise((resolve, reject) => {
const process = spawn(command, args, {
cwd,
stdio: "inherit",
shell: true,
});
process.on("close", (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`Command failed with exit code ${code}`));
}
});
});
}