feat: Video Trimmer and more

This commit is contained in:
Yiannis Christodoulou
2025-05-15 10:43:26 +03:00
committed by GitHub
parent ab4d9d67df
commit a833b606f1
102 changed files with 13266 additions and 523 deletions
@@ -0,0 +1,70 @@
import express, { type Request, Response, NextFunction } from "express";
import { registerRoutes } from "./routes";
import { setupVite, serveStatic, log } from "./vite";
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use((req, res, next) => {
const start = Date.now();
const path = req.path;
let capturedJsonResponse: Record<string, any> | undefined = undefined;
const originalResJson = res.json;
res.json = function (bodyJson, ...args) {
capturedJsonResponse = bodyJson;
return originalResJson.apply(res, [bodyJson, ...args]);
};
res.on("finish", () => {
const duration = Date.now() - start;
if (path.startsWith("/api")) {
let logLine = `${req.method} ${path} ${res.statusCode} in ${duration}ms`;
if (capturedJsonResponse) {
logLine += ` :: ${JSON.stringify(capturedJsonResponse)}`;
}
if (logLine.length > 80) {
logLine = logLine.slice(0, 79) + "…";
}
log(logLine);
}
});
next();
});
(async () => {
const server = await registerRoutes(app);
app.use((err: any, _req: Request, res: Response, _next: NextFunction) => {
const status = err.status || err.statusCode || 500;
const message = err.message || "Internal Server Error";
res.status(status).json({ message });
throw err;
});
// importantly only setup vite in development and after
// setting up all the other routes so the catch-all route
// doesn't interfere with the other routes
if (app.get("env") === "development") {
await setupVite(app, server);
} else {
serveStatic(app);
}
// ALWAYS serve the app on port 5000
// this serves both the API and the client.
// It is the only port that is not firewalled.
const port = 5000;
server.listen({
port,
host: "0.0.0.0",
reusePort: true,
}, () => {
log(`serving on port ${port}`);
});
})();
@@ -0,0 +1,15 @@
import type { Express } from "express";
import { createServer, type Server } from "http";
import { storage } from "./storage";
export async function registerRoutes(app: Express): Promise<Server> {
// put application routes here
// prefix all routes with /api
// use storage to perform CRUD operations on the storage interface
// e.g. storage.insertUser(user) or storage.getUserByUsername(username)
const httpServer = createServer(app);
return httpServer;
}
@@ -0,0 +1,39 @@
import { users, type User, type InsertUser } from "@shared/schema";
// modify the interface with any CRUD methods
// you might need
export interface IStorage {
getUser(id: number): Promise<User | undefined>;
getUserByUsername(username: string): Promise<User | undefined>;
createUser(user: InsertUser): Promise<User>;
}
export class MemStorage implements IStorage {
private users: Map<number, User>;
currentId: number;
constructor() {
this.users = new Map();
this.currentId = 1;
}
async getUser(id: number): Promise<User | undefined> {
return this.users.get(id);
}
async getUserByUsername(username: string): Promise<User | undefined> {
return Array.from(this.users.values()).find(
(user) => user.username === username,
);
}
async createUser(insertUser: InsertUser): Promise<User> {
const id = this.currentId++;
const user: User = { ...insertUser, id };
this.users.set(id, user);
return user;
}
}
export const storage = new MemStorage();
@@ -0,0 +1,85 @@
import express, { type Express } from "express";
import fs from "fs";
import path from "path";
import { createServer as createViteServer, createLogger } from "vite";
import { type Server } from "http";
import viteConfig from "../vite.config";
import { nanoid } from "nanoid";
const viteLogger = createLogger();
export function log(message: string, source = "express") {
const formattedTime = new Date().toLocaleTimeString("en-US", {
hour: "numeric",
minute: "2-digit",
second: "2-digit",
hour12: true,
});
console.log(`${formattedTime} [${source}] ${message}`);
}
export async function setupVite(app: Express, server: Server) {
const serverOptions = {
middlewareMode: true,
hmr: { server },
allowedHosts: true,
};
const vite = await createViteServer({
...viteConfig,
configFile: false,
customLogger: {
...viteLogger,
error: (msg, options) => {
viteLogger.error(msg, options);
process.exit(1);
},
},
server: serverOptions,
appType: "custom",
});
app.use(vite.middlewares);
app.use("*", async (req, res, next) => {
const url = req.originalUrl;
try {
const clientTemplate = path.resolve(
import.meta.dirname,
"..",
"client",
"index.html",
);
// always reload the index.html file from disk incase it changes
let template = await fs.promises.readFile(clientTemplate, "utf-8");
template = template.replace(
`src="/src/main.tsx"`,
`src="/src/main.tsx?v=${nanoid()}"`,
);
const page = await vite.transformIndexHtml(url, template);
res.status(200).set({ "Content-Type": "text/html" }).end(page);
} catch (e) {
vite.ssrFixStacktrace(e as Error);
next(e);
}
});
}
export function serveStatic(app: Express) {
const distPath = path.resolve(import.meta.dirname, "public");
if (!fs.existsSync(distPath)) {
throw new Error(
`Could not find the build directory: ${distPath}, make sure to build the client first`,
);
}
app.use(express.static(distPath));
// fall through to index.html if the file doesn't exist
app.use("*", (_req, res) => {
res.sendFile(path.resolve(distPath, "index.html"));
});
}