303 lines
8.6 KiB
TypeScript
303 lines
8.6 KiB
TypeScript
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
||
|
||
import { serve } from "@hono/node-server";
|
||
import { serveStatic } from "@hono/node-server/serve-static";
|
||
import { OpenAPIHono } from "@hono/zod-openapi";
|
||
import { cors } from "hono/cors";
|
||
import { html } from "hono/html";
|
||
import { logger } from "hono/logger";
|
||
import os from "os";
|
||
import auth from "./services/auth/authService.js";
|
||
import dataMart from "./services/dataMart/dataMartService.js";
|
||
import eom from "./services/eom/eomService.js";
|
||
// custom routes
|
||
import scalar from "./services/general/route/scalar.js";
|
||
import { createLog } from "./services/logger/logger.js";
|
||
import loggerService from "./services/logger/loggerService.js";
|
||
import logistics from "./services/logistics/logisticsService.js";
|
||
import { sendEmail } from "./services/notifications/controller/sendMail.js";
|
||
import notify from "./services/notifications/notifyService.js";
|
||
import ocme from "./services/ocme/ocmeService.js";
|
||
import ocpService from "./services/ocp/ocpService.js";
|
||
import printers from "./services/printers/printerService.js";
|
||
import produser from "./services/prodUser/prodUser.js";
|
||
import qualityRequest from "./services/quality/qualityService.js";
|
||
import rfid from "./services/rfid/rfidService.js";
|
||
import {
|
||
getSettings,
|
||
serverSettings,
|
||
} from "./services/server/controller/settings/getSettings.js";
|
||
import system from "./services/server/systemServer.js";
|
||
import sqlService from "./services/sqlServer/sqlService.js";
|
||
import tcpServer from "./services/tcpServer/tcpServer.js";
|
||
|
||
// create the main prodlogin here
|
||
const username = "lst_user";
|
||
const password = "Alpla$$Prod";
|
||
export const lstAuth = btoa(`${username}:${password}`);
|
||
|
||
// checking to make sure we have the settings intialized
|
||
// const { data: settingsData, error: settingError } = await tryCatch(
|
||
// db.select().from(settings)
|
||
// );
|
||
|
||
// if (settingError) {
|
||
// throw Error("Error getting settings from the db. critical error.");
|
||
// }
|
||
|
||
const serverIntialized: any = await getSettings();
|
||
|
||
export const installed =
|
||
serverIntialized.length === 0 && process.env.NODE_ENV !== "development"
|
||
? false
|
||
: true;
|
||
createLog("info", "LST", "server", `Server is installed: ${installed}`);
|
||
|
||
const app = new OpenAPIHono({ strict: false });
|
||
|
||
// middle ware
|
||
if (process.env.NODE_ENV === "development") {
|
||
app.use("*", logger());
|
||
}
|
||
|
||
app.use(
|
||
"*",
|
||
cors({
|
||
origin: [
|
||
"http://localhost:3000",
|
||
"http://localhost:5173",
|
||
"http://localhost:4000",
|
||
"http://localhost:4200",
|
||
], // Allow all origins
|
||
allowHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
|
||
allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
|
||
//exposeHeaders: ["Content-Length", "X-Kuma-Revision"],
|
||
credentials: true, // Allow credentials if needed
|
||
maxAge: 600,
|
||
}),
|
||
);
|
||
|
||
// Middleware to normalize route case
|
||
// app.use("*", async (c, next) => {
|
||
// // const lowercasedUrl = c.req.url.toLowerCase();
|
||
// console.log("Incoming Request:", c.req.url, c.req.method);
|
||
// // // If the URL is already lowercase, continue as usual
|
||
// // if (c.req.url === lowercasedUrl) {
|
||
// await next();
|
||
// // }
|
||
|
||
// // // Otherwise, re-route internally
|
||
// // return c.redirect(lowercasedUrl, 308); // 308 preserves the HTTP method
|
||
// });
|
||
|
||
app.doc("/api/ref", {
|
||
openapi: "3.0.0",
|
||
info: {
|
||
version: "2.0.0",
|
||
title: "LST API",
|
||
},
|
||
});
|
||
|
||
const routes = [
|
||
scalar,
|
||
auth,
|
||
// apiHits,
|
||
system,
|
||
tcpServer,
|
||
sqlService,
|
||
logistics,
|
||
rfid,
|
||
printers,
|
||
loggerService,
|
||
ocpService,
|
||
notify,
|
||
eom,
|
||
dataMart,
|
||
qualityRequest,
|
||
produser,
|
||
] as const;
|
||
|
||
const appRoutes = routes.forEach((route) => {
|
||
app.route("/api/", route);
|
||
});
|
||
|
||
app.route("/ocme/", ocme);
|
||
|
||
//--------------- lst v1 proxy ----------------------\\
|
||
// app.all("/api/v1/*", (c) => {
|
||
// const path = c.req.path.replace("/api/v1/", ""); // Extract the subpath
|
||
// const query = c.req.query() ? "?" + new URLSearchParams(c.req.query()).toString() : ""; // Get query params
|
||
// return proxy(`http://localhost:4900/${path}${query}`, {
|
||
// headers: {
|
||
// ...c.req.header(),
|
||
// "X-Forwarded-For": "127.0.0.1",
|
||
// "X-Forwarded-Host": c.req.header("host"),
|
||
// },
|
||
// });
|
||
// });
|
||
|
||
// app.all("/system/*", (c) => {
|
||
// const path = c.req.path.replace("/system/", ""); // Extract the subpath
|
||
// const query = c.req.query() ? "?" + new URLSearchParams(c.req.query()).toString() : ""; // Get query params
|
||
// return proxy(`http://localhost:4200/${path}${query}`, {
|
||
// headers: {
|
||
// ...c.req.header(),
|
||
// "X-Forwarded-For": "127.0.0.1",
|
||
// "X-Forwarded-Host": c.req.header("host"),
|
||
// },
|
||
// });
|
||
// });
|
||
|
||
//---------------------------------------------------\\
|
||
|
||
// the catch all api route
|
||
app.all("/api/*", (c) => c.json({ error: "API route not found" }, 404));
|
||
|
||
const newPageDoc = `
|
||
<!doctype html>
|
||
<h1>Hello!</h1>
|
||
`;
|
||
|
||
app.all("*", (c) => {
|
||
const testServers = ["test1", "test2", "test3"];
|
||
const server = serverIntialized.filter((n: any) => n.name === "plantToken");
|
||
|
||
let url = "";
|
||
|
||
if (c.req.url.includes("localhost")) {
|
||
url = `http://localhost:5500/lst/app/old${c.req.path}`;
|
||
} else if (testServers.includes(server[0].value)) {
|
||
const dbServer = serverIntialized.filter((n: any) => n.name === "dbServer");
|
||
url = `https://${dbServer[0].value}.alpla.net/lst/app/old${c.req.path}`;
|
||
} else {
|
||
url = `https://${server[0].value}prod.alpla.net/lst/app/old${c.req.path}`;
|
||
}
|
||
const target = url;
|
||
const waitSeconds = 10;
|
||
return c.html(html`<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8"/>
|
||
<title>Lst Moved</title>
|
||
<style>
|
||
body{font-family:sans-serif;display:flex;flex-direction:column;
|
||
align-items:center;justify-content:center;height:100vh;}
|
||
button{margin-top:1rem;padding:0.6rem 1.2rem;font-size:1rem;cursor:pointer;}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h1>We’ve moved!</h1>
|
||
<p>With new security and updating to mobile version the app had to be moved. You will be redirected to.</p>
|
||
<p><a href="${target}">${target}</a></p>
|
||
<p>Redirecting in <span id="countdown">${waitSeconds}</span> seconds…</p>
|
||
<button id="goNow">Go now</button>
|
||
<script>
|
||
let s = ${waitSeconds};
|
||
const el = document.getElementById('countdown');
|
||
const btn = document.getElementById('goNow');
|
||
const timer = setInterval(()=>{
|
||
s--;
|
||
el.textContent = s;
|
||
if(s <= 0){ clearInterval(timer); window.location.href='${target}'; }
|
||
},1000);
|
||
btn.addEventListener('click',()=>{
|
||
clearInterval(timer); window.location.href='${target}';
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>`);
|
||
});
|
||
|
||
// app.all("/*", (c) => {
|
||
// console.log(c.req.path);
|
||
// return c.html(html`${newPageDoc}`);
|
||
// });
|
||
|
||
// front end static files
|
||
//app.use("/*", serveStatic({ root: "./frontend/dist" }));
|
||
//app.use("*", serveStatic({ path: "./frontend/dist/index.html" }));
|
||
|
||
// Handle app exit signals
|
||
process.on("SIGINT", async () => {
|
||
console.log("\nGracefully shutting down...");
|
||
//await closePool();
|
||
process.exit(0);
|
||
});
|
||
|
||
process.on("SIGTERM", async () => {
|
||
console.log("Received termination signal, closing database...");
|
||
//await closePool();
|
||
process.exit(0);
|
||
});
|
||
|
||
process.on("uncaughtException", async (err) => {
|
||
console.log("Uncaught Exception:", err);
|
||
//await closePool();
|
||
const emailData = {
|
||
email: "blake.matthes@alpla.com", // should be moved to the db so it can be reused.
|
||
subject: `${os.hostname()} has just encountered a crash.`,
|
||
template: "serverCrash",
|
||
context: {
|
||
error: err,
|
||
plant: `${os.hostname()}`,
|
||
},
|
||
};
|
||
|
||
await sendEmail(emailData);
|
||
//process.exit(1);
|
||
});
|
||
|
||
process.on("beforeExit", async () => {
|
||
console.log("Process is about to exit...");
|
||
//await closePool();
|
||
process.exit(0);
|
||
});
|
||
|
||
const port =
|
||
process.env.NODE_ENV === "development"
|
||
? process.env.VITE_SERVER_PORT
|
||
: process.env.PROD_PORT;
|
||
|
||
const ocmeport = process.env.OCME_PORT;
|
||
serve(
|
||
{
|
||
fetch: app.fetch,
|
||
port: Number(port),
|
||
hostname: "0.0.0.0",
|
||
},
|
||
(info) => {
|
||
createLog(
|
||
"info",
|
||
"LST",
|
||
"server",
|
||
`Server is running on http://${info.address}:${info.port}`,
|
||
);
|
||
},
|
||
);
|
||
|
||
/**
|
||
* Only for ocme until we get them switched over to the single port setup.
|
||
*/
|
||
// const setting = await db.select().from(settings);
|
||
const setting = serverSettings;
|
||
const isActive = setting.filter((n) => n.name === "ocmeService");
|
||
if (ocmeport && isActive[0]?.value === "1") {
|
||
serve(
|
||
{
|
||
fetch: app.fetch,
|
||
port: Number(ocmeport),
|
||
hostname: "0.0.0.0",
|
||
},
|
||
(info) => {
|
||
createLog(
|
||
"info",
|
||
"LST",
|
||
"server",
|
||
`Ocme section is listening on http://${info.address}:${info.port}`,
|
||
);
|
||
},
|
||
);
|
||
}
|
||
|
||
export type AppRoutes = typeof appRoutes;
|