mirror of
https://github.com/detleph/server.git
synced 2026-09-04 08:36:06 +02:00
Merge branch 'dev' into feature-email-verification
This commit is contained in:
@@ -19,13 +19,13 @@ export const getAllEvents = async (req: Request, res: Response) => {
|
||||
id: false,
|
||||
},
|
||||
});
|
||||
if (events.length > 0)
|
||||
res.status(200).json({
|
||||
type: "success",
|
||||
payload: {
|
||||
events,
|
||||
},
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
type: "success",
|
||||
payload: {
|
||||
events,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const getEvent = async (req: Request, res: Response) => {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import logger from "../error/logger";
|
||||
|
||||
export default function debugLogger(req: Request, res: Response, next: NextFunction) {
|
||||
// Only log when in development mode
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
logger.debug(`Request to: ${req.url}`);
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
export default class ForwardableError extends Error {
|
||||
// If in different context
|
||||
private readonly __id = "CUSTOM_ERROR";
|
||||
|
||||
public readonly status: number;
|
||||
|
||||
constructor(status: number, message: string) {
|
||||
super(message);
|
||||
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
static isForwardableError(error: any): error is ForwardableError {
|
||||
return error.__id === "CUSTOM_ERROR";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
import { PrismaClientUnknownRequestError } from "@prisma/client/runtime";
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import ForwardableError from "./ForwardableError";
|
||||
import logger from "./logger";
|
||||
|
||||
const env = process.env.NODE_ENV || "production";
|
||||
|
||||
type ErrorHandler = (err: any, req: Request, res: Response) => boolean;
|
||||
|
||||
const customHandlers: ErrorHandler[] = [];
|
||||
|
||||
export function addCustomHandler(handler: ErrorHandler) {
|
||||
customHandlers.push(handler);
|
||||
}
|
||||
|
||||
export function removeCustomHandler(handler: ErrorHandler): Boolean {
|
||||
const index = customHandlers.findIndex((h) => h === handler);
|
||||
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
customHandlers.splice(index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export default function defaultErrorHandler(err: any, req: Request, res: Response, next: NextFunction) {
|
||||
for (const handler of customHandlers) {
|
||||
// Run custom handler
|
||||
if (handler(err, req, res)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ForwardableError.isForwardableError(err)) {
|
||||
return res.status(err.status).json({
|
||||
type: "error",
|
||||
payload: {
|
||||
message: err.message,
|
||||
...(env === "development"
|
||||
? {
|
||||
stack: err.stack,
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (err instanceof PrismaClientUnknownRequestError) {
|
||||
logger.warning(err);
|
||||
|
||||
return res.status(404).json({
|
||||
type: "error",
|
||||
payload: {
|
||||
message: "An unknown error occured. This could be due to malformed IDs",
|
||||
...(env === "development"
|
||||
? {
|
||||
prisma: err.message,
|
||||
stack: err.stack,
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
logger.error("--- Unhandled error ---");
|
||||
logger.error(err);
|
||||
|
||||
return res.status(err.status).json({
|
||||
type: "error",
|
||||
payload: {
|
||||
message: err.message,
|
||||
...(env === "development"
|
||||
? {
|
||||
notice: "This error was not caught by any handler, please add handling!",
|
||||
stack: err.stack,
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import winston, { createLogger } from "winston";
|
||||
|
||||
const {
|
||||
format: { printf, colorize, combine, timestamp, json, errors, prettyPrint },
|
||||
} = winston;
|
||||
|
||||
const defaultJsonFormat = combine(errors({ stack: true }), timestamp(), json({ space: 2 }));
|
||||
|
||||
const customCLIFormat = printf(({ level, message, label, timestamp, stack }) => {
|
||||
let output = `${level}${stack ? `(1/2:message)` : ""} at ${timestamp}${label ? ` (#${label})` : ""}: ${message}${
|
||||
stack ? "\n" : ""
|
||||
}`;
|
||||
|
||||
if (stack) {
|
||||
output += `\n${level}(2/2:stack)${label ? ` (#${label})` : ""}: ${stack}\n\n`;
|
||||
}
|
||||
|
||||
return output;
|
||||
});
|
||||
|
||||
export default createLogger({
|
||||
levels: winston.config.syslog.levels,
|
||||
format: combine(errors({ stack: true }), timestamp()),
|
||||
transports: [
|
||||
new winston.transports.Console({
|
||||
level: "debug",
|
||||
format: combine(timestamp(), colorize(), customCLIFormat),
|
||||
}),
|
||||
new winston.transports.File({
|
||||
filename: "/app/error.log",
|
||||
level: "error",
|
||||
format: defaultJsonFormat,
|
||||
}),
|
||||
new winston.transports.File({
|
||||
level: "debug",
|
||||
filename: "/app/debug.log",
|
||||
format: defaultJsonFormat,
|
||||
silent: !(process.env.NODE_ENV === "development"), // Silent when not in development
|
||||
}),
|
||||
],
|
||||
});
|
||||
+23
-11
@@ -11,11 +11,21 @@ import argon2 from "argon2";
|
||||
import adminRouter from "./Routes/admin.routes";
|
||||
import organisationRouter from "./Routes/organisation.routes";
|
||||
import groupRouter from "./Routes/group.routes";
|
||||
import defaultErrorHandler from "./Middleware/error/handler";
|
||||
import logger from "./Middleware/error/logger";
|
||||
import debugLogger from "./Middleware/debug/logger";
|
||||
|
||||
// Set up async error handling
|
||||
require("express-async-errors");
|
||||
|
||||
require("dotenv").config(); // Load dotenv config
|
||||
|
||||
const app = express();
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
logger.info("Using development mode");
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// Dev
|
||||
await prisma.admin.upsert({
|
||||
@@ -34,16 +44,7 @@ async function main() {
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use(express.json());
|
||||
|
||||
app.use((err: any, req: Request, res: Response, next: NextFunction) => {
|
||||
if (err) {
|
||||
res.status(400).send({
|
||||
type: "error",
|
||||
payload: "The body of your request did not contain valid data",
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
app.use(debugLogger);
|
||||
|
||||
// Admin authentication endpoints
|
||||
app.use("/api/authentication", adminAuthRouter);
|
||||
@@ -56,13 +57,24 @@ async function main() {
|
||||
app.use("/api/organisations", organisationRouter);
|
||||
|
||||
app.use("/api/groups", groupRouter);
|
||||
|
||||
// Error handling
|
||||
app.use(defaultErrorHandler);
|
||||
|
||||
app.listen(process.env.PORT, () => {
|
||||
console.log(`Listening on Port: ${process.env.PORT}`);
|
||||
logger.info(`Listening on port ${process.env.PORT}`);
|
||||
});
|
||||
|
||||
logger.info("Server started");
|
||||
|
||||
process.on("exit", () => {
|
||||
logger.info("Server stopping...");
|
||||
});
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
logger.crit(e);
|
||||
throw e;
|
||||
})
|
||||
.finally(async () => {
|
||||
|
||||
Reference in New Issue
Block a user