env.ts46 lines · main
| 1 | import { loadEnv } from '@briven/shared'; |
| 2 | import { z } from 'zod'; |
| 3 | |
| 4 | const envSchema = z.object({ |
| 5 | BRIVEN_ENV: z.enum(['development', 'staging', 'production']).default('development'), |
| 6 | BRIVEN_REALTIME_PORT: z.coerce.number().int().positive().default(3004), |
| 7 | BRIVEN_LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'), |
| 8 | |
| 9 | // Where to dispatch invokes — same internal apps/api hostname the runtime |
| 10 | // hits. Realtime never talks to the runtime directly; the api owns the |
| 11 | // auth + project resolution chain. |
| 12 | BRIVEN_API_INTERNAL_URL: z.string().url().default('http://localhost:3001'), |
| 13 | |
| 14 | // Shared with apps/api so realtime can call internal endpoints; also used |
| 15 | // to validate the bearer token on the WebSocket upgrade. |
| 16 | BRIVEN_RUNTIME_SHARED_SECRET: z.string().min(32).optional(), |
| 17 | |
| 18 | // @README-BRIVEN ADR 0001 — DoltGres data-plane DSN (postgres:// wire). |
| 19 | // The shared data-plane cluster where each project lives in its own |
| 20 | // DoltGres database (proj_<id>). Phase 1 stubs out LISTEN/NOTIFY; |
| 21 | // Phase 2 PollManager opens a per-project postgres.js client against |
| 22 | // this DSN for commit-diff polling. Mirrors apps/api's |
| 23 | // BRIVEN_DATA_PLANE_URL — optional so local dev can boot without a |
| 24 | // data plane; polling stays disabled until it is set. |
| 25 | BRIVEN_DATA_PLANE_URL: z.string().url().optional(), |
| 26 | |
| 27 | // Poll interval in ms for commit-diff change detection. Lower = less |
| 28 | // latency but more database load. Default 500 ms, floor 100 ms, cap 5000 ms. |
| 29 | BRIVEN_REALTIME_POLL_MS: z.coerce.number().int().min(100).max(5000).default(500), |
| 30 | |
| 31 | // Per-WebSocket subscription cap. A single client opening more than |
| 32 | // this many concurrent subs gets `error: subscription_limit_ws`. Sized |
| 33 | // so a normal app (one page, ~dozens of useQuery hooks) is well under, |
| 34 | // but a bug or malicious loop is bounded before it OOMs realtime. |
| 35 | BRIVEN_REALTIME_MAX_SUBS_PER_WS: z.coerce.number().int().positive().default(200), |
| 36 | |
| 37 | // Per-project hard cap on concurrent subs across all WS connections. |
| 38 | // Defaults to the team-tier cap from services/tiers.ts so a misconfig |
| 39 | // doesn't accidentally clamp Team customers. Tier-aware enforcement |
| 40 | // (free=100/pro=1000/team=10000) waits for the realtime → api tier |
| 41 | // RPC; this single ceiling is the Phase 1 backstop. |
| 42 | BRIVEN_REALTIME_MAX_SUBS_PER_PROJECT: z.coerce.number().int().positive().default(10_000), |
| 43 | }); |
| 44 | |
| 45 | export type Env = z.infer<typeof envSchema>; |
| 46 | export const env = loadEnv(envSchema); |