cd78f72f33
Complete rename of all technical identifiers across the codebase: Package names (11 packages): - @planarchy/* → @capakraken/* in all package.json, tsconfig, imports Import statements: 277 files, 548 occurrences replaced Database & Docker: - PostgreSQL user/db: planarchy → capakraken - Docker volumes: planarchy_pgdata → capakraken_pgdata - Connection strings updated in docker-compose, .env, CI CI/CD: - GitHub Actions workflow: all filter commands updated - Test database credentials updated Infrastructure: - Redis channel: planarchy:sse → capakraken:sse - Logger service name: planarchy-api → capakraken-api - Anonymization seed updated - Start/stop/restart scripts updated Test data: - Seed emails: @planarchy.dev → @capakraken.dev - E2E test credentials: all 11 spec files updated - Email defaults: @planarchy.app → @capakraken.app - localStorage keys: planarchy_* → capakraken_* Documentation: 30+ .md files updated Verification: - pnpm install: workspace resolution works - TypeScript: only pre-existing TS2589 (no new errors) - Engine: 310/310 tests pass - Staffing: 37/37 tests pass Co-Authored-By: claude-flow <ruv@ruv.net>
66 lines
1.8 KiB
TypeScript
66 lines
1.8 KiB
TypeScript
import { eventBus } from "@capakraken/api/sse";
|
|
import { startReminderScheduler } from "@capakraken/api/lib/reminder-scheduler";
|
|
import { SSE_EVENT_TYPES } from "@capakraken/shared";
|
|
import { auth } from "~/server/auth.js";
|
|
|
|
// Start the reminder scheduler (idempotent — only starts once)
|
|
startReminderScheduler();
|
|
|
|
export const dynamic = "force-dynamic";
|
|
export const runtime = "nodejs";
|
|
|
|
export async function GET() {
|
|
const session = await auth();
|
|
|
|
if (!session) {
|
|
return new Response("Unauthorized", { status: 401 });
|
|
}
|
|
|
|
const encoder = new TextEncoder();
|
|
|
|
const stream = new ReadableStream({
|
|
start(controller) {
|
|
// Send initial connection confirmation
|
|
controller.enqueue(
|
|
encoder.encode(`data: ${JSON.stringify({ type: SSE_EVENT_TYPES.PING, timestamp: new Date().toISOString() })}\n\n`),
|
|
);
|
|
|
|
// Subscribe to event bus
|
|
const unsubscribe = eventBus.subscribe((event) => {
|
|
try {
|
|
controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}\n\n`));
|
|
} catch {
|
|
// Client disconnected
|
|
}
|
|
});
|
|
|
|
// Heartbeat every 30 seconds
|
|
const heartbeat = setInterval(() => {
|
|
try {
|
|
controller.enqueue(
|
|
encoder.encode(`data: ${JSON.stringify({ type: SSE_EVENT_TYPES.PING, timestamp: new Date().toISOString() })}\n\n`),
|
|
);
|
|
} catch {
|
|
clearInterval(heartbeat);
|
|
unsubscribe();
|
|
}
|
|
}, 30000);
|
|
|
|
// Cleanup on close
|
|
return () => {
|
|
clearInterval(heartbeat);
|
|
unsubscribe();
|
|
};
|
|
},
|
|
});
|
|
|
|
return new Response(stream, {
|
|
headers: {
|
|
"Content-Type": "text/event-stream",
|
|
"Cache-Control": "no-cache, no-transform",
|
|
Connection: "keep-alive",
|
|
"X-Accel-Buffering": "no",
|
|
},
|
|
});
|
|
}
|