//? Deploy-time topology — added by `npx luckystack add router`. Single-instance //? projects can leave `environments` empty — only `resources` is consumed by the //? framework's synchronizedEnvHashes check. `environments` / `routing` / //? `development` are read by `@luckystack/router` for split/multi-instance //? deployments; populate them (per-service URL bindings, the router listen port //? via `routing.defaultRouterPort`, an optional `fallback` env) when you scale out. import { registerDeployConfig } from '@luckystack/core'; export type ResourceType = 'redis' | 'mongo'; export interface ResourceDefinition { type: ResourceType; /** * Name of the env var that identifies this resource instance. For Mongo this * is typically the full connection string (DATABASE_URL); for Redis this can * be REDIS_HOST when host+port+password are split across several env vars. */ urlEnvKey: string; /** * Env keys whose values MUST match across every environment that references * this resource (used by the router's boot handshake). */ synchronizedEnvKeys?: string[]; } export interface EnvironmentDefinition { /** Resource key from `resources` above. */ redis: string; /** Resource key from `resources` above. */ mongo: string; /** Optional fallback environment key. Must be a valid key of `environments`. */ fallback?: TEnvKey; /** Per-service URL bindings for this environment. */ bindings: Record; } export interface DeployConfig { resources: Record; environments: Record>; routing?: { onMissingService?: 'hard-error' | 'proxy-fallback'; missingServiceErrorCode?: string; enableUnhealthyFallback?: boolean; strictBootHandshake?: boolean; /** TCP port the router listens on (default 4000). Also overridable via ROUTER_PORT env. */ defaultRouterPort?: number; /** Immediate TLS proxy addresses/CIDRs trusted to set x-forwarded-proto. */ trustedProxyCidrs?: string[]; }; development?: { enableFallbackRouting?: boolean; healthPollMs?: number; switchNewTrafficToLocalWhenHealthy?: boolean; }; } const deployConfig: DeployConfig = { resources: { redisShared: { type: 'redis', urlEnvKey: 'REDIS_HOST', synchronizedEnvKeys: ['PROJECT_NAME'], }, mongoShared: { type: 'mongo', urlEnvKey: 'DATABASE_URL', }, }, //? The Docker scaffold routes the default system service to its private app //? container. Add development/staging/production entries and per-service //? bindings when you split presets across additional processes. Example: //? //? environments: { //? development: { //? redis: 'redisShared', mongo: 'mongoShared', //? bindings: { //? system: 'http://localhost:4100', //? settings: 'http://localhost:4100', //? 'reset-password': 'http://localhost:4100', //? }, //? }, //? }, //? routing: { //? defaultRouterPort: 4000, //? // Add ONLY the immediate TLS proxy/load-balancer subnet. Empty = trust none. //? // Such a proxy may also name the visitor in x-forwarded-for: the router //? // forwards the last hop that proxy appended. //? trustedProxyCidrs: ['127.0.0.1/32', '::1/128'], //? }, environments: { docker: { redis: 'redisShared', mongo: 'mongoShared', //? `settings` and `reset-password` ship in the same `default` preset as //? `system`, so they bind to the same backend. A service without a //? binding is unreachable through the router. bindings: { system: 'http://app:4100', settings: 'http://app:4100', 'reset-password': 'http://app:4100', }, }, }, }; registerDeployConfig(deployConfig); export default deployConfig;