🪻 distributed transcription service thistle.dunkirk.sh
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: make bun work in dev mode only in dev

+41 -31
+41 -31
src/index.ts
··· 175 175 email: string, 176 176 ): Promise<void> { 177 177 // Skip Polar sync in test mode 178 - if (process.env.NODE_ENV === "test" || process.env.SKIP_POLAR_SYNC === "true") { 178 + if ( 179 + process.env.NODE_ENV === "test" || 180 + process.env.SKIP_POLAR_SYNC === "true" 181 + ) { 179 182 return; 180 183 } 181 184 ··· 305 308 ); 306 309 307 310 const server = Bun.serve({ 308 - port: process.env.NODE_ENV === "test" 309 - ? 3001 310 - : (process.env.PORT ? Number.parseInt(process.env.PORT, 10) : 3000), 311 + port: 312 + process.env.NODE_ENV === "test" 313 + ? 3001 314 + : process.env.PORT 315 + ? Number.parseInt(process.env.PORT, 10) 316 + : 3000, 311 317 idleTimeout: 120, // 120 seconds for SSE connections 312 318 routes: { 313 319 "/": indexHTML, ··· 895 901 role: user.role, 896 902 has_subscription: !!subscription, 897 903 email_verified: isEmailVerified(user.id), 898 - email_notifications_enabled: prefs?.email_notifications_enabled === 1, 904 + email_notifications_enabled: 905 + prefs?.email_notifications_enabled === 1, 899 906 }); 900 907 } catch (err) { 901 908 return handleError(err); ··· 1092 1099 try { 1093 1100 const sessionId = getSessionFromRequest(req); 1094 1101 if (!sessionId) { 1095 - return Response.json({ error: "Not authenticated" }, { status: 401 }); 1102 + return Response.json( 1103 + { error: "Not authenticated" }, 1104 + { status: 401 }, 1105 + ); 1096 1106 } 1097 1107 const user = getUserBySession(sessionId); 1098 1108 if (!user) { ··· 1117 1127 try { 1118 1128 const currentSessionId = getSessionFromRequest(req); 1119 1129 if (!currentSessionId) { 1120 - return Response.json({ error: "Not authenticated" }, { status: 401 }); 1130 + return Response.json( 1131 + { error: "Not authenticated" }, 1132 + { status: 401 }, 1133 + ); 1121 1134 } 1122 1135 const user = getUserBySession(currentSessionId); 1123 1136 if (!user) { ··· 1301 1314 const body = await req.json(); 1302 1315 const { password } = body; 1303 1316 if (!password) { 1304 - return Response.json({ error: "Password required" }, { status: 400 }); 1317 + return Response.json( 1318 + { error: "Password required" }, 1319 + { status: 400 }, 1320 + ); 1305 1321 } 1306 1322 // Validate password format (client-side hashed PBKDF2) 1307 1323 const passwordValidation = validatePasswordHash(password); ··· 1646 1662 1647 1663 // Allow access if: owner, admin, or enrolled in the class 1648 1664 if (!isOwner && !isAdmin && !isClassMember) { 1649 - return Response.json( 1650 - { error: "Forbidden" }, 1651 - { status: 403 }, 1652 - ); 1665 + return Response.json({ error: "Forbidden" }, { status: 403 }); 1653 1666 } 1654 1667 1655 1668 // Require subscription only if accessing own transcription (not class) ··· 1889 1902 1890 1903 // Allow access if: owner, admin, or enrolled in the class 1891 1904 if (!isOwner && !isAdmin && !isClassMember) { 1892 - return Response.json( 1893 - { error: "Forbidden" }, 1894 - { status: 403 }, 1895 - ); 1905 + return Response.json({ error: "Forbidden" }, { status: 403 }); 1896 1906 } 1897 1907 1898 1908 // Require subscription only if accessing own transcription (not class) ··· 1997 2007 1998 2008 // Allow access if: owner, admin, or enrolled in the class 1999 2009 if (!isOwner && !isAdmin && !isClassMember) { 2000 - return Response.json( 2001 - { error: "Forbidden" }, 2002 - { status: 403 }, 2003 - ); 2010 + return Response.json({ error: "Forbidden" }, { status: 403 }); 2004 2011 } 2005 2012 2006 2013 // Require subscription only if accessing own transcription (not class) ··· 3359 3366 // Verify meeting exists 3360 3367 const existingMeeting = getMeetingById(meetingId); 3361 3368 if (!existingMeeting) { 3362 - return Response.json({ error: "Meeting not found" }, { status: 404 }); 3369 + return Response.json( 3370 + { error: "Meeting not found" }, 3371 + { status: 404 }, 3372 + ); 3363 3373 } 3364 3374 3365 3375 updateMeetingTime(meetingId, label); ··· 3376 3386 // Verify meeting exists 3377 3387 const existingMeeting = getMeetingById(meetingId); 3378 3388 if (!existingMeeting) { 3379 - return Response.json({ error: "Meeting not found" }, { status: 404 }); 3389 + return Response.json( 3390 + { error: "Meeting not found" }, 3391 + { status: 404 }, 3392 + ); 3380 3393 } 3381 3394 3382 3395 deleteMeetingTime(meetingId); ··· 3435 3448 }, 3436 3449 }, 3437 3450 }, 3438 - development: { 3439 - hmr: true, 3440 - console: true, 3441 - }, 3451 + development: process.env.NODE_ENV === "dev", 3442 3452 fetch(req, server) { 3443 3453 const response = server.fetch(req); 3444 - 3454 + 3445 3455 // Add security headers to all responses 3446 3456 if (response instanceof Response) { 3447 3457 const headers = new Headers(response.headers); ··· 3449 3459 headers.set("X-Content-Type-Options", "nosniff"); 3450 3460 headers.set("X-Frame-Options", "DENY"); 3451 3461 headers.set("Referrer-Policy", "strict-origin-when-cross-origin"); 3452 - 3462 + 3453 3463 // Set CSP that allows inline styles with unsafe-inline (needed for Lit components) 3454 3464 // and script-src 'self' for bundled scripts 3455 3465 headers.set( 3456 3466 "Content-Security-Policy", 3457 - "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://hostedboringavatars.vercel.app; font-src 'self'; connect-src 'self'; form-action 'self'; base-uri 'self'; frame-ancestors 'none'; object-src 'none';" 3467 + "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://hostedboringavatars.vercel.app; font-src 'self'; connect-src 'self'; form-action 'self'; base-uri 'self'; frame-ancestors 'none'; object-src 'none';", 3458 3468 ); 3459 - 3469 + 3460 3470 return new Response(response.body, { 3461 3471 status: response.status, 3462 3472 statusText: response.statusText, 3463 3473 headers, 3464 3474 }); 3465 3475 } 3466 - 3476 + 3467 3477 return response; 3468 3478 }, 3469 3479 });