Files
growqr-backend/src/config.ts
2026-06-05 00:40:28 +05:30

134 lines
5.7 KiB
TypeScript

import "dotenv/config";
function required(name: string, fallback?: string): string {
const v = process.env[name] ?? fallback;
if (!v) {
throw new Error(`Missing required env var: ${name}`);
}
return v;
}
export const config = {
port: Number(process.env.PORT ?? 4000),
logLevel: process.env.LOG_LEVEL ?? "info",
nodeEnv: process.env.NODE_ENV ?? "development",
// Postgres metadata DB (users, registry, container mappings).
databaseUrl:
process.env.DATABASE_URL ??
"***************************************/growqr",
// Clerk auth.
clerkSecretKey: process.env.CLERK_SECRET_KEY ?? "",
clerkPublishableKey: process.env.CLERK_PUBLISHABLE_KEY ?? "",
// Optional: lock service-to-service calls (actor → backend).
serviceToken: process.env.SERVICE_TOKEN ?? "",
a2aAllowedKey: process.env.A2A_ALLOWED_KEY ?? "dev-a2a-key",
// Service → backend event stream. Redis is optional; HTTP /events/ingest/service is always available.
growEventsRedisUrl: process.env.GROW_EVENTS_REDIS_URL ?? process.env.REDIS_URL ?? "",
growEventsStream: process.env.GROW_EVENTS_STREAM ?? "grow.events.raw",
growEventsConsumerGroup: process.env.GROW_EVENTS_CONSUMER_GROUP ?? "growqr-backend",
growEventsConsumerName: process.env.GROW_EVENTS_CONSUMER_NAME ?? `backend-${process.pid}`,
// Legacy service Redis surfaces. These let backend observe existing service A2A traffic
// without changing the services. Defaults fall back to GROW_EVENTS_REDIS_URL/REDIS_URL.
interviewRedisUrl: process.env.INTERVIEW_REDIS_URL ?? process.env.GROW_EVENTS_REDIS_URL ?? process.env.REDIS_URL ?? "",
roleplayRedisUrl: process.env.ROLEPLAY_REDIS_URL ?? process.env.GROW_EVENTS_REDIS_URL ?? process.env.REDIS_URL ?? "",
resumeRedisUrl: process.env.RESUME_REDIS_URL ?? process.env.GROW_EVENTS_REDIS_URL ?? process.env.REDIS_URL ?? "",
legacyServiceTaskObserverGroup: process.env.LEGACY_SERVICE_TASK_OBSERVER_GROUP ?? "growqr-backend-observer",
// LLM gateway for the unified user agent.
llmProvider: process.env.LLM_PROVIDER ?? "opencode",
llmApiKey:
process.env.LLM_API_KEY ??
process.env.OPENCODE_API_KEY ??
"",
llmBaseUrl:
process.env.LLM_BASE_URL ??
process.env.OPENCODE_BASE_URL ??
"https://opencode.ai/zen/v1",
opencodeApiKey: process.env.OPENCODE_API_KEY ?? "",
agentModel:
process.env.GROW_AGENT_MODEL ??
process.env.LLM_MODEL ??
"kimi-k2.6",
// Rivet Kit engine endpoint (self-hosted in docker-compose).
rivetEndpoint: process.env.RIVET_ENDPOINT ?? "http://localhost:6420",
rivetClientEndpoint:
process.env.RIVET_CLIENT_ENDPOINT ??
`http://127.0.0.1:${Number(process.env.PORT ?? 4000)}/api/rivet`,
// Product microservices exposed as sub-agent surfaces.
interviewServiceUrl:
process.env.INTERVIEW_SERVICE_URL ?? "http://localhost:8007",
interviewPublicUrl:
process.env.INTERVIEW_PUBLIC_URL ?? process.env.INTERVIEW_SERVICE_URL ?? "http://localhost:8007",
roleplayServiceUrl:
process.env.ROLEPLAY_SERVICE_URL ?? "http://localhost:8008",
roleplayPublicUrl:
process.env.ROLEPLAY_PUBLIC_URL ?? process.env.ROLEPLAY_SERVICE_URL ?? "http://localhost:8008",
qscoreServiceUrl:
process.env.QSCORE_SERVICE_URL ?? "http://localhost:8000",
resumeServiceUrl:
process.env.RESUME_SERVICE_URL ?? "http://localhost:8002",
userServiceUrl:
process.env.USER_SERVICE_URL ?? "http://localhost:8003",
resumePublicUrl:
process.env.RESUME_PUBLIC_URL ?? process.env.RESUME_SERVICE_URL ?? "http://localhost:8002",
matchmakingServiceUrl:
process.env.MATCHMAKING_SERVICE_URL ?? "http://localhost:8006",
socialBrandingServiceUrl:
process.env.SOCIAL_BRANDING_SERVICE_URL ?? "http://localhost:8005",
workflowsDashboardUrl:
process.env.WORKFLOWS_DASHBOARD_URL ??
process.env.FRONTEND_ORIGIN ??
"http://localhost:3000",
// ── Central Gitea (one org-wide instance, changes.md §2A) ──
// Public URL is what Git remotes should use and what OpenCode containers see.
// Internal URL is only for backend-to-Gitea API calls on a private network.
giteaPublicUrl:
process.env.GITEA_PUBLIC_URL ??
process.env.GITEA_URL ??
"http://127.0.0.1:3001",
giteaInternalUrl:
process.env.GITEA_INTERNAL_URL ??
process.env.GITEA_URL ??
process.env.GITEA_PUBLIC_URL ??
"http://127.0.0.1:3001",
giteaAdminUser: process.env.GITEA_ADMIN_USER ?? "growqr-admin",
giteaAdminPassword: process.env.GITEA_ADMIN_PASSWORD ?? "growqr-admin-dev",
giteaAdminToken: process.env.GITEA_ADMIN_TOKEN ?? "",
giteaOrgName: process.env.GITEA_ORG_NAME ?? "growqr",
// ── Shared OpenCode runtime image (built once, changes.md §3) ──
opencodeImage:
process.env.OPENCODE_IMAGE ?? "growqr/opencode:dev",
// Version tracking for rollout (changes.md §9)
opencodeImageVersion: process.env.OPENCODE_IMAGE_VERSION ?? "dev",
migrationVersion: process.env.MIGRATION_VERSION ?? "1",
promptVersion: process.env.PROMPT_VERSION ?? "4",
// Host that user containers expose ports on (the host running Docker).
userContainerHost: process.env.USER_CONTAINER_HOST ?? "127.0.0.1",
userDataRoot: process.env.USER_DATA_ROOT ?? "./.data/users",
// Port range for per-user OpenCode containers only (Gitea is shared).
userPortRangeStart: Number(process.env.USER_PORT_RANGE_START ?? 20000),
userPortRangeEnd: Number(process.env.USER_PORT_RANGE_END ?? 29999),
// CORS for the Next.js frontend.
frontendOrigin:
process.env.FRONTEND_ORIGIN ?? "http://localhost:3000",
adminUserIds: (process.env.ADMIN_USER_IDS ?? "")
.split(",")
.map((s) => s.trim())
.filter(Boolean),
// Used by LLM requests.
maxAgentTokens: Number(process.env.MAX_AGENT_TOKENS ?? 4096),
required, // exported so other modules can fail fast on boot
} as const;