rework pwa cc
Build and Publish Docker Image / build-and-push-image (push) Successful in 1m48s

This commit is contained in:
Zed
2026-07-11 02:01:08 +02:00
parent 9ae37f98ed
commit ce1db937f2
52 changed files with 5210 additions and 48 deletions
+29
View File
@@ -0,0 +1,29 @@
import type { Request, Response, NextFunction } from "express";
import { verifyAccessToken } from "../utils/jwt.js";
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Express {
interface Request {
userId?: string;
}
}
}
export function requireAuth(
req: Request,
res: Response,
next: NextFunction,
): void {
const header = req.headers.authorization;
const token = header?.startsWith("Bearer ") ? header.slice(7) : null;
const userId = token ? verifyAccessToken(token) : null;
if (!userId) {
res.status(401).json({ error: "unauthorized" });
return;
}
req.userId = userId;
next();
}
+39
View File
@@ -0,0 +1,39 @@
import type { Request, Response, NextFunction } from "express";
import { ZodError } from "zod";
export class HttpError extends Error {
constructor(
public status: number,
message: string,
) {
super(message);
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function errorHandler(
err: unknown,
_req: Request,
res: Response,
_next: NextFunction,
): void {
if (err instanceof ZodError) {
res.status(400).json({ error: "validation_error", details: err.issues });
return;
}
if (err instanceof HttpError) {
res.status(err.status).json({ error: err.message });
return;
}
console.error("[error]", err);
res.status(500).json({ error: "internal_error" });
}
// Wraps async route handlers so thrown errors reach the error handler.
export function asyncHandler<
T extends (req: Request, res: Response, next: NextFunction) => Promise<unknown>,
>(fn: T) {
return (req: Request, res: Response, next: NextFunction) => {
fn(req, res, next).catch(next);
};
}