style(13-03): apply Prettier formatting across repo

Mechanical reformat — no logic changes. 398 files changed, 19125
insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc
(singleQuote:true, semi:true, tabWidth:2, trailingComma:all,
printWidth:100). Isolated per D-13-08 for reviewability.
This commit is contained in:
Lucas Berger
2026-06-11 20:35:18 -04:00
parent 4bc0445173
commit 982438dc10
398 changed files with 19050 additions and 16382 deletions
+51 -51
View File
@@ -1,46 +1,44 @@
import { fileURLToPath } from 'node:url'
import { realpathSync } from 'node:fs'
import { serve } from '@hono/node-server'
import { serveStatic } from '@hono/node-server/serve-static'
import { Hono } from 'hono'
import { healthRouter } from './routes/health.js'
import { meRouter } from './routes/me.js'
import { eventsRouter } from './routes/events.js'
import { sseRouter } from './routes/sse.js'
import { listsRouter, listItemsRouter } from './routes/lists.js'
import { pushRouter } from './routes/push.js'
import { oidcAuthMiddleware, processOAuthCallback } from './auth/middleware.js'
import { devAuthBypass } from './auth/devBypass.js'
import { persistSessionCookie } from './auth/persistSessionCookie.js'
import { startBrokerPoller } from './broker/poller.js'
import { startOutboxWorker } from './broker/outboxWorker.js'
import { startReminderScheduler } from './broker/reminderScheduler.js'
import webpush from 'web-push'
import { fileURLToPath } from 'node:url';
import { realpathSync } from 'node:fs';
import { serve } from '@hono/node-server';
import { serveStatic } from '@hono/node-server/serve-static';
import { Hono } from 'hono';
import { healthRouter } from './routes/health.js';
import { meRouter } from './routes/me.js';
import { eventsRouter } from './routes/events.js';
import { sseRouter } from './routes/sse.js';
import { listsRouter, listItemsRouter } from './routes/lists.js';
import { pushRouter } from './routes/push.js';
import { oidcAuthMiddleware, processOAuthCallback } from './auth/middleware.js';
import { devAuthBypass } from './auth/devBypass.js';
import { persistSessionCookie } from './auth/persistSessionCookie.js';
import { startBrokerPoller } from './broker/poller.js';
import { startOutboxWorker } from './broker/outboxWorker.js';
import { startReminderScheduler } from './broker/reminderScheduler.js';
import webpush from 'web-push';
export const app = new Hono()
export const app = new Hono();
// Compute once at startup: bypass is active only in non-production with explicit opt-in.
// In production NODE_ENV='production' → devBypassActive=false → OIDC is always mounted.
const devBypassActive =
process.env.NODE_ENV !== 'production' && process.env.DEV_AUTH_BYPASS === 'true'
process.env.NODE_ENV !== 'production' && process.env.DEV_AUTH_BYPASS === 'true';
if (devBypassActive) {
console.warn(
'⚠ DEV_AUTH_BYPASS active — OIDC guard DISABLED. Never use in production.',
)
console.warn('⚠ DEV_AUTH_BYPASS active — OIDC guard DISABLED. Never use in production.');
}
// OIDC callback — must be registered BEFORE oidcAuthMiddleware so the
// authorization-code exchange is not itself intercepted by the auth check (T-02-02)
app.get('/callback', (c) => processOAuthCallback(c))
app.get('/callback', (c) => processOAuthCallback(c));
// GET /health — unauthenticated, mounted BEFORE the OIDC guard (T-01-03, T-02-05)
app.route('/health', healthRouter)
app.route('/health', healthRouter);
// Dev-auth bypass — no-op passthrough unless DEV_AUTH_BYPASS=true AND NODE_ENV!='production'.
// When active, injects DEV_USER into the Hono context and the OIDC guard is NOT mounted.
// Must be mounted BEFORE oidcAuthMiddleware (T-02-01 mitigation; see auth/devBypass.ts).
app.use('/api/*', devAuthBypass())
app.use('/api/*', devAuthBypass());
// Protect all /api/* routes with OIDC session middleware (AUTH-01, T-02-05).
// Skipped entirely when devBypassActive so that local dev works without Authelia.
@@ -49,9 +47,9 @@ app.use('/api/*', devAuthBypass())
// OIDC_AUTH_EXTERNAL_URL is MANDATORY behind Pangolin to construct the correct
// redirect_uri (Pitfall 1). Set it to https://familysync.<domain>.
if (!devBypassActive) {
app.use('/api/*', oidcAuthMiddleware())
app.use('/api/*', oidcAuthMiddleware());
// Re-issues the session-scoped oidc-auth cookie as persistent so PWA sessions survive close (AUTH-02).
app.use('/api/*', persistSessionCookie())
app.use('/api/*', persistSessionCookie());
}
// Protected API routes (behind oidcAuthMiddleware)
@@ -63,14 +61,14 @@ if (!devBypassActive) {
// browser follows it here — now authenticated. The handler then redirects to /
// so the SPA boots with a valid session. Under DEV_AUTH_BYPASS the guard is not
// mounted, so /api/login reaches this handler directly and still redirects to /.
app.get('/api/login', (c) => c.redirect('/'))
app.get('/api/login', (c) => c.redirect('/'));
app.route('/api/me', meRouter)
app.route('/api/events', eventsRouter)
app.route('/api/sse', sseRouter)
app.route('/api/lists', listsRouter)
app.route('/api/list-items', listItemsRouter)
app.route('/api/push', pushRouter)
app.route('/api/me', meRouter);
app.route('/api/events', eventsRouter);
app.route('/api/sse', sseRouter);
app.route('/api/lists', listsRouter);
app.route('/api/list-items', listItemsRouter);
app.route('/api/push', pushRouter);
// WR-04: background worker startup (cron schedules) moved into the isMainModule()
// guard below. Calling them at top level registered real node-cron schedules whenever
@@ -85,8 +83,8 @@ app.route('/api/push', pushRouter)
// apple-touch-icon.png) live at the root. serveStatic calls next() when a file
// is not found, so SPA routes fall through to the index.html catch-all below.
// (Registered AFTER /health, /api/*, and /callback, so those win.)
app.use('/*', serveStatic({ root: './public' }))
app.get('*', serveStatic({ path: './public/index.html' }))
app.use('/*', serveStatic({ root: './public' }));
app.get('*', serveStatic({ path: './public/index.html' }));
/**
* True only when this module is the process entrypoint (run directly), not when it
@@ -100,11 +98,11 @@ app.get('*', serveStatic({ path: './public/index.html' }))
* resolves symlinks on argv[1]; fileURLToPath turns the module URL into a real path.
*/
function isMainModule(): boolean {
if (!process.argv[1]) return false
if (!process.argv[1]) return false;
try {
return fileURLToPath(import.meta.url) === realpathSync(process.argv[1])
return fileURLToPath(import.meta.url) === realpathSync(process.argv[1]);
} catch {
return false
return false;
}
}
@@ -115,32 +113,34 @@ if (isMainModule()) {
// Configure VAPID credentials for web-push before starting background workers.
// VAPID_SUBJECT must be a mailto: or https: URL identifying the operator.
// The private key is NEVER served to clients; it signs push requests server-side only.
const vapidSubject = process.env.VAPID_SUBJECT ?? ''
const vapidPublicKey = process.env.VAPID_PUBLIC_KEY ?? ''
const vapidPrivateKey = process.env.VAPID_PRIVATE_KEY ?? ''
const vapidSubject = process.env.VAPID_SUBJECT ?? '';
const vapidPublicKey = process.env.VAPID_PUBLIC_KEY ?? '';
const vapidPrivateKey = process.env.VAPID_PRIVATE_KEY ?? '';
if (vapidSubject && vapidPublicKey && vapidPrivateKey) {
try {
webpush.setVapidDetails(vapidSubject, vapidPublicKey, vapidPrivateKey)
webpush.setVapidDetails(vapidSubject, vapidPublicKey, vapidPrivateKey);
} catch (err) {
console.warn(
'[startup] setVapidDetails failed — push notifications will not work:',
err instanceof Error ? err.message : String(err),
)
);
}
} else {
console.warn('[startup] VAPID env vars not set — push notifications will fail. Set VAPID_SUBJECT, VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY.')
console.warn(
'[startup] VAPID env vars not set — push notifications will fail. Set VAPID_SUBJECT, VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY.',
);
}
// Start the CalDAV broker poller (5-min cron, D-13 ctag change-detection).
// Runs in the background — errors are caught and logged per-credential (T-03-04).
startBrokerPoller()
startBrokerPoller();
// Drain the D-05 outbox every 15s: dispatches pending CalDAV writes to Fastmail.
startOutboxWorker()
startOutboxWorker();
// Start the 1-min reminder scan for shared timed events starting in ~15 min (NOTIF-01).
// VAPID must be configured (above) before this starts or push sends will fail.
startReminderScheduler()
startReminderScheduler();
serve({ fetch: app.fetch, port: 3000 }, (info) => {
console.log(`FamilySync API running on http://localhost:${info.port}`)
})
console.log(`FamilySync API running on http://localhost:${info.port}`);
});
}