fix(validator): corrections to no leak like crazy
This commit is contained in:
@@ -7,15 +7,17 @@ import path, { dirname, join } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { db } from "./pkg/db/db.js";
|
||||
import { settings, type Setting } from "./pkg/db/schema/settings.js";
|
||||
import { env } from "./pkg/utils/envValidator.js";
|
||||
import { validateEnv } from "./pkg/utils/envValidator.js";
|
||||
import { createLogger } from "./pkg/logger/logger.js";
|
||||
import { returnFunc } from "./pkg/utils/return.js";
|
||||
import { initializeProdPool } from "./pkg/prodSql/prodSqlConnect.js";
|
||||
import { closePool, initializeProdPool } from "./pkg/prodSql/prodSqlConnect.js";
|
||||
import { tryCatch } from "./pkg/utils/tryCatch.js";
|
||||
|
||||
const PORT = Number(env.VITE_PORT) || 4200;
|
||||
import os, { hostname } from "os";
|
||||
import { sendNotify } from "./pkg/utils/notify.js";
|
||||
|
||||
const main = async () => {
|
||||
const env = validateEnv(process.env);
|
||||
const PORT = Number(env.VITE_PORT) || 4200;
|
||||
//create the logger
|
||||
const log = createLogger({ module: "system", subModule: "main start" });
|
||||
|
||||
@@ -94,28 +96,16 @@ const main = async () => {
|
||||
// start the server up
|
||||
server.listen(PORT, "0.0.0.0", () =>
|
||||
log.info(
|
||||
{ stack: { name: "test" } },
|
||||
`Server running in ${
|
||||
process.env.NODE_ENV ? process.env.NODE_ENV : "dev"
|
||||
}, on http://0.0.0.0:${PORT}${basePath}`
|
||||
)
|
||||
);
|
||||
|
||||
// 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();
|
||||
//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.`,
|
||||
@@ -126,15 +116,40 @@ const main = async () => {
|
||||
// },
|
||||
// };
|
||||
|
||||
// await sendEmail(emailData);
|
||||
if (!process.env.WEBHOOK_URL) {
|
||||
// await sendEmail(emailData);
|
||||
} else {
|
||||
await sendNotify({
|
||||
module: "system",
|
||||
subModule: "fatalCrash",
|
||||
hostname: os.hostname(),
|
||||
message: err.message,
|
||||
stack: err?.stack,
|
||||
});
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
process.on("beforeExit", async () => {
|
||||
console.log("Process is about to exit...");
|
||||
//await closePool();
|
||||
process.exit(0);
|
||||
});
|
||||
// setInterval(() => {
|
||||
// const used = process.memoryUsage();
|
||||
// console.log(
|
||||
// `Heap: ${(used.heapUsed / 1024 / 1024).toFixed(2)} MB / RSS: ${(
|
||||
// used.rss /
|
||||
// 1024 /
|
||||
// 1024
|
||||
// ).toFixed(2)} MB`
|
||||
// );
|
||||
// }, 10000);
|
||||
};
|
||||
|
||||
main();
|
||||
|
||||
// .catch((err) => {
|
||||
// const log = createLogger({ module: "system", subModule: "main" });
|
||||
// log.fatal(
|
||||
// { notify: true },
|
||||
// "There was a crash that occured and caused the app to restart."
|
||||
// );
|
||||
// process.exit(1);
|
||||
// });
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { drizzle } from "drizzle-orm/postgres-js";
|
||||
import postgres from "postgres";
|
||||
import { env } from "../utils/envValidator.js";
|
||||
import { validateEnv } from "../utils/envValidator.js";
|
||||
|
||||
const env = validateEnv(process.env);
|
||||
const dbURL = `postgres://${env.DATABASE_USER}:${env.DATABASE_PASSWORD}@${env.DATABASE_HOST}:${env.DATABASE_PORT}/${env.DATABASE_DB}`;
|
||||
|
||||
const queryClient = postgres(dbURL, {
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
import { boolean, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
|
||||
import {
|
||||
boolean,
|
||||
jsonb,
|
||||
pgTable,
|
||||
text,
|
||||
timestamp,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -8,7 +15,7 @@ export const logs = pgTable("logs", {
|
||||
module: text("module").notNull(),
|
||||
subModule: text("subModule"),
|
||||
message: text("message").notNull(),
|
||||
stack: text("stack"),
|
||||
stack: jsonb("stack").default([]),
|
||||
checked: boolean("checked").default(false),
|
||||
hostname: text("hostname"),
|
||||
createdAt: timestamp("createdAt").defaultNow(),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import build from "pino-abstract-transport";
|
||||
import { db } from "../db/db.js";
|
||||
import { logs, type Log } from "../db/schema/logs.js";
|
||||
import { checkENV } from "../utils/envValidator.js";
|
||||
import { tryCatch } from "../utils/tryCatch.js";
|
||||
|
||||
const pinoLogLevels: any = {
|
||||
10: "trace",
|
||||
@@ -19,14 +19,21 @@ export default async function (log: Log) {
|
||||
for await (let obj of source) {
|
||||
// convert to the name to make it more easy to find later :P
|
||||
const levelName = pinoLogLevels[obj.level] || "unknown";
|
||||
await db.insert(logs).values({
|
||||
level: levelName,
|
||||
module: obj?.module.toLowerCase(),
|
||||
subModule: obj?.subModule.toLowerCase(),
|
||||
hostname: obj?.hostname.toLowerCase(),
|
||||
message: obj.msg,
|
||||
stack: obj?.stack,
|
||||
});
|
||||
|
||||
const res = await tryCatch(
|
||||
db.insert(logs).values({
|
||||
level: levelName,
|
||||
module: obj?.module?.toLowerCase(),
|
||||
subModule: obj?.subModule?.toLowerCase(),
|
||||
hostname: obj?.hostname?.toLowerCase(),
|
||||
message: obj.msg,
|
||||
stack: obj?.stack,
|
||||
})
|
||||
);
|
||||
|
||||
if (res.error) {
|
||||
console.log(res.error);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import pino, { type Logger } from "pino";
|
||||
import { env } from "../utils/envValidator.js";
|
||||
|
||||
export let logLevel = process.env.LOG_LEVEL || "info";
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import build from "pino-abstract-transport";
|
||||
import { db } from "../db/db.js";
|
||||
import { logs, type Log } from "../db/schema/logs.js";
|
||||
import { env } from "../utils/envValidator.js";
|
||||
import { type Log } from "../db/schema/logs.js";
|
||||
import { validateEnv } from "../utils/envValidator.js";
|
||||
import { sendNotify } from "../utils/notify.js";
|
||||
const env = validateEnv(process.env);
|
||||
|
||||
const pinoLogLevels: any = {
|
||||
10: "trace",
|
||||
@@ -12,49 +13,6 @@ const pinoLogLevels: any = {
|
||||
60: "fatal",
|
||||
};
|
||||
// discord function
|
||||
async function sendFatal(log: Log) {
|
||||
const webhookUrl = process.env.WEBHOOK_URL!;
|
||||
let payload = {
|
||||
embeds: [
|
||||
{
|
||||
title: `🚨 ${env.PROD_PLANT_TOKEN}: encounter a critical error `,
|
||||
description: `Where was the error: ${log.module}${
|
||||
log.subModule ? `-${log.subModule}` : ""
|
||||
}`,
|
||||
color: 0xff0000, // red
|
||||
fields: [
|
||||
{
|
||||
name: "Message",
|
||||
value: log.message,
|
||||
inline: false,
|
||||
},
|
||||
{
|
||||
name: "Hostname",
|
||||
value: log.hostname,
|
||||
inline: false,
|
||||
},
|
||||
{
|
||||
name: "Stack",
|
||||
value:
|
||||
"```" +
|
||||
(log.stack?.slice(0, 1000) ?? "no stack") +
|
||||
"```",
|
||||
},
|
||||
],
|
||||
footer: {
|
||||
text: "LST Logger 💀",
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
await fetch(webhookUrl, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export default async function (log: Log) {
|
||||
//const {username, service, level, msg, ...extra} = log;
|
||||
@@ -76,14 +34,15 @@ export default async function (log: Log) {
|
||||
? String(obj.hostname).toLowerCase()
|
||||
: undefined,
|
||||
message: obj.msg,
|
||||
stack: obj.stack ? obj.stack : undefined,
|
||||
};
|
||||
if (!process.env.WEBHOOK_URL) {
|
||||
console.log("webhook missing?");
|
||||
console.log("WebHook is missing we wont move foward.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj.level >= 60 && obj.notify) {
|
||||
sendFatal(newlog as Log);
|
||||
sendNotify(newlog as Log);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { env } from "../utils/envValidator.js";
|
||||
import { returnFunc } from "../utils/return.js";
|
||||
import { connected, pool } from "./prodSqlConnect.js";
|
||||
import { validateEnv } from "../utils/envValidator.js";
|
||||
|
||||
const env = validateEnv(process.env);
|
||||
/**
|
||||
* Run a prod query
|
||||
* just pass over the query as a string and the name of the query.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import sql from "mssql";
|
||||
import { env } from "../utils/envValidator.js";
|
||||
import { validateEnv } from "../utils/envValidator.js";
|
||||
|
||||
const env = validateEnv(process.env);
|
||||
export const sqlConfig: sql.config = {
|
||||
server: env.PROD_SERVER,
|
||||
database: `AlplaPROD_${env.PROD_PLANT_TOKEN}_cus`,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import sql from "mssql";
|
||||
import { checkHostnamePort } from "../utils/checkHostNamePort.js";
|
||||
import { sqlConfig } from "./prodSqlConfig.js";
|
||||
import { env } from "../utils/envValidator.js";
|
||||
import { createLogger } from "../logger/logger.js";
|
||||
import { returnFunc } from "../utils/return.js";
|
||||
import { validateEnv } from "../utils/envValidator.js";
|
||||
|
||||
const env = validateEnv(process.env);
|
||||
|
||||
export let pool: any;
|
||||
export let connected: boolean = false;
|
||||
|
||||
@@ -1,55 +1,37 @@
|
||||
import { z } from "zod";
|
||||
import { createLogger } from "../logger/logger.js";
|
||||
/**
|
||||
* This is where we will validate the required ENV parapmeters.
|
||||
*
|
||||
*/
|
||||
|
||||
const envSchema = z.object({
|
||||
//Server stuff
|
||||
// server stuff
|
||||
VITE_PORT: z.string().default("4200"),
|
||||
LOG_LEVEL: z.string().default("info"),
|
||||
// app db stuff
|
||||
|
||||
// db stuff
|
||||
DATABASE_HOST: z.string(),
|
||||
DATABASE_PORT: z.string(),
|
||||
DATABASE_USER: z.string(),
|
||||
DATABASE_PASSWORD: z.string(),
|
||||
DATABASE_DB: z.string().default("lst"),
|
||||
// prod server checks
|
||||
|
||||
// prod stuff
|
||||
PROD_SERVER: z.string(),
|
||||
PROD_PLANT_TOKEN: z.string(),
|
||||
PROD_USER: z.string(),
|
||||
PROD_PASSWORD: z.string(),
|
||||
|
||||
// docker specifc
|
||||
RUNNING_IN_DOCKER: z.string().default("false"),
|
||||
});
|
||||
|
||||
// use safeParse instead of parse
|
||||
const parsed = envSchema.safeParse(process.env);
|
||||
export type Env = z.infer<typeof envSchema>;
|
||||
|
||||
export const checkENV = () => {
|
||||
return envSchema.safeParse(process.env);
|
||||
};
|
||||
|
||||
const log = createLogger({ module: "envValidation" });
|
||||
|
||||
if (!parsed.success) {
|
||||
log.fatal(
|
||||
`Environment validation failed: Missing: ${parsed.error.issues
|
||||
.map((e) => {
|
||||
return e.path[0];
|
||||
})
|
||||
.join(", ")}`
|
||||
);
|
||||
// 🔔 Send a notification (e.g., email, webhook, Slack)
|
||||
// sendNotification(parsed.error.format());
|
||||
|
||||
// gracefully exit if in production
|
||||
//process.exit(1);
|
||||
throw Error(
|
||||
`Environment validation failed: Missing: ${parsed.error.issues
|
||||
.map((e) => {
|
||||
return e.path[0];
|
||||
})
|
||||
.join(", ")}`
|
||||
);
|
||||
export function validateEnv(raw: NodeJS.ProcessEnv): Env {
|
||||
const parsed = envSchema.safeParse(raw);
|
||||
if (!parsed.success) {
|
||||
throw new Error(
|
||||
`Environment validation failed. Missing: ${parsed.error.issues
|
||||
.map((e) => e.path[0])
|
||||
.join(", ")}`
|
||||
);
|
||||
}
|
||||
return parsed.data;
|
||||
}
|
||||
|
||||
export const env = parsed.data;
|
||||
|
||||
Reference in New Issue
Block a user