{"version":3,"file":"infra.mjs","names":[],"sources":["../../src/cli/infra.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { config as loadDotenv } from \"dotenv\";\nimport type { RuntimeConfig } from \"../types\";\n\nconst POSTGRES_USER = \"everythingdev\";\nconst POSTGRES_PASSWORD = \"everythingdev\";\nconst API_DATABASE_SECRET = \"API_DATABASE_URL\";\nconst AUTH_DATABASE_SECRET = \"AUTH_DATABASE_URL\";\nconst HOST_SECRET = \"CORS_ORIGIN\";\nconst BASE_POSTGRES_PORT = 5434;\nconst BASE_REDIS_PORT = 6379;\n\ninterface DatabaseSecretConfig {\n  secret: string;\n  slug: string;\n  fromKey: string;\n  port: number;\n  serviceName: string;\n  containerName: string;\n  databaseName: string;\n  volumeName: string;\n  url: string;\n}\n\ninterface RedisSecretConfig {\n  secret: string;\n  slug: string;\n  fromKey: string;\n  port: number;\n  serviceName: string;\n  containerName: string;\n  volumeName: string;\n  url: string;\n}\n\ninterface SecretGroup {\n  section: string;\n  secrets: string[];\n}\n\ninterface PortState {\n  postgresPorts: Record<string, number>;\n  redisPorts: Record<string, number>;\n}\n\ninterface GeneratedInfraSpec {\n  groups: SecretGroup[];\n  databases: DatabaseSecretConfig[];\n  redis: RedisSecretConfig[];\n}\n\ninterface SyncGeneratedInfraResult {\n  secrets: string[];\n  envExampleChanged: boolean;\n  dockerComposeChanged: boolean;\n  staleEnvWarnings: string[];\n}\n\nfunction uniqueSecrets(values: Array<string | undefined>): string[] {\n  const secrets: string[] = [];\n  const seen = new Set<string>();\n\n  for (const value of values) {\n    if (!value || seen.has(value)) continue;\n    seen.add(value);\n    secrets.push(value);\n  }\n\n  return secrets;\n}\n\nfunction loadPortState(configDir?: string): PortState {\n  if (!configDir) return { postgresPorts: {}, redisPorts: {} };\n  const statePath = join(configDir, \".bos\", \"infra-state.json\");\n  if (!existsSync(statePath)) return { postgresPorts: {}, redisPorts: {} };\n  try {\n    const raw = JSON.parse(readFileSync(statePath, \"utf-8\")) as Partial<PortState>;\n    return {\n      postgresPorts: raw.postgresPorts ?? {},\n      redisPorts: raw.redisPorts ?? {},\n    };\n  } catch {\n    return { postgresPorts: {}, redisPorts: {} };\n  }\n}\n\nfunction savePortState(configDir: string, state: PortState): void {\n  const statePath = join(configDir, \".bos\", \"infra-state.json\");\n  mkdirSync(dirname(statePath), { recursive: true });\n  writeFileSync(statePath, `${JSON.stringify(state, null, 2)}\\n`);\n}\n\nfunction resolvePort(slug: string, portMap: Record<string, number>, basePort: number): number {\n  if (portMap[slug] !== undefined) return portMap[slug];\n  const assigned = Object.values(portMap);\n  const next = assigned.length > 0 ? Math.max(...assigned) + 1 : basePort;\n  portMap[slug] = next;\n  return next;\n}\n\nfunction normalizeRedisSlug(secret: string): string {\n  return secret.replace(/_REDIS_URL$/, \"\").toLowerCase();\n}\n\nfunction getSecretGroups(runtimeConfig: RuntimeConfig): SecretGroup[] {\n  const groups: SecretGroup[] = [];\n  const seen = new Set<string>();\n\n  const addGroup = (section: string, secrets: string[]) => {\n    const filtered = secrets.filter((s) => {\n      if (seen.has(s)) return false;\n      seen.add(s);\n      return true;\n    });\n    if (filtered.length > 0) {\n      groups.push({ section, secrets: filtered });\n    }\n  };\n\n  addGroup(\"app.host\", uniqueSecrets([...(runtimeConfig.host.secrets ?? []), HOST_SECRET]));\n\n  addGroup(\"app.api\", uniqueSecrets(runtimeConfig.api.secrets ?? []));\n\n  if (runtimeConfig.auth) {\n    addGroup(\"app.auth\", uniqueSecrets(runtimeConfig.auth.secrets ?? []));\n  }\n\n  if (runtimeConfig.plugins) {\n    for (const [pluginKey, plugin] of Object.entries(runtimeConfig.plugins)) {\n      if (plugin.secrets && plugin.secrets.length > 0) {\n        addGroup(`plugins.${pluginKey}`, plugin.secrets);\n      }\n    }\n  }\n\n  return groups;\n}\n\nfunction buildGeneratedInfraSpec(\n  runtimeConfig: RuntimeConfig,\n  configDir?: string,\n): { spec: GeneratedInfraSpec; portState: PortState } {\n  const groups = getSecretGroups(runtimeConfig);\n  const allSecrets = groups.flatMap((group) => group.secrets);\n  const originMap = configDir ? buildOriginMap(configDir, runtimeConfig) : new Map();\n  const portState = loadPortState(configDir);\n\n  const databases = buildDatabaseConfigs(allSecrets, originMap, portState.postgresPorts);\n  const redis = buildRedisConfigs(allSecrets, originMap, portState.redisPorts);\n\n  return { spec: { groups, databases, redis }, portState };\n}\n\nfunction normalizeDatabaseSlug(secret: string): string {\n  return secret.replace(/_DATABASE_URL$/, \"\").toLowerCase();\n}\n\nfunction buildOriginMap(configDir: string, runtimeConfig: RuntimeConfig): Map<string, string> {\n  const configPath = join(configDir, \"bos.config.json\");\n\n  const originMap = new Map<string, string>();\n  const account = runtimeConfig.account;\n\n  const resolveOrigin = (extendsRef: unknown): string | null => {\n    if (typeof extendsRef === \"string\") {\n      const match = extendsRef.match(/^bos:\\/\\/([^/]+)\\//);\n      return match?.[1] ?? null;\n    }\n    return null;\n  };\n\n  const rawConfig = existsSync(configPath)\n    ? (JSON.parse(readFileSync(configPath, \"utf-8\")) as Record<string, unknown>)\n    : null;\n  const rawPlugins = rawConfig?.plugins as Record<string, unknown> | undefined;\n\n  for (const secret of runtimeConfig.api.secrets ?? []) {\n    if (!originMap.has(secret)) originMap.set(secret, account);\n  }\n\n  const rawApp = rawConfig?.app as Record<string, unknown> | undefined;\n  const authExtends = (rawApp?.auth as Record<string, unknown> | undefined)?.extends;\n  const authOrigin = resolveOrigin(authExtends) ?? account;\n  for (const secret of runtimeConfig.auth?.secrets ?? []) {\n    if (!originMap.has(secret)) originMap.set(secret, authOrigin);\n  }\n\n  for (const [pluginKey, pluginEntry] of Object.entries(runtimeConfig.plugins ?? {})) {\n    const rawPlugin = rawPlugins?.[pluginKey];\n    let pluginOrigin: string;\n    if (typeof rawPlugin === \"string\") {\n      pluginOrigin = resolveOrigin(rawPlugin) ?? account;\n    } else if (rawPlugin && typeof rawPlugin === \"object\") {\n      pluginOrigin = resolveOrigin((rawPlugin as Record<string, unknown>).extends) ?? account;\n    } else {\n      pluginOrigin = account;\n    }\n    for (const secret of pluginEntry.secrets ?? []) {\n      if (!originMap.has(secret)) originMap.set(secret, pluginOrigin);\n    }\n  }\n\n  for (const secret of runtimeConfig.host.secrets ?? []) {\n    if (!originMap.has(secret)) originMap.set(secret, account);\n  }\n\n  return originMap;\n}\n\nfunction buildDatabaseConfigs(\n  secrets: string[],\n  originMap: Map<string, string>,\n  portMap: Record<string, number>,\n): DatabaseSecretConfig[] {\n  const databaseSecrets = uniqueSecrets(\n    secrets.filter((secret) => secret.endsWith(\"_DATABASE_URL\")),\n  );\n\n  const orderedSecrets = [...databaseSecrets];\n\n  for (const secret of orderedSecrets) {\n    const slug = normalizeDatabaseSlug(secret);\n    if (secret === API_DATABASE_SECRET) {\n      portMap[slug] = 5432;\n    } else if (secret === AUTH_DATABASE_SECRET) {\n      portMap[slug] = 5433;\n    } else {\n      resolvePort(slug, portMap, BASE_POSTGRES_PORT);\n    }\n  }\n\n  return orderedSecrets.map((secret) => {\n    const slug = normalizeDatabaseSlug(secret);\n    const fromKey = originMap.get(secret) ?? \"\";\n    const port = portMap[slug];\n\n    const volumeName = fromKey\n      ? `${fromKey.replace(/\\./g, \"_\")}_postgres_${slug}_data`\n      : `postgres_${slug}_data`;\n\n    const containerName = fromKey ? `${fromKey}-postgres-${slug}` : `postgres-${slug}`;\n\n    return {\n      secret,\n      slug,\n      fromKey,\n      port,\n      serviceName: `postgres-${slug.replace(/_/g, \"-\")}`,\n      containerName,\n      databaseName: `${slug}_db`,\n      volumeName,\n      url: `postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:${port}/${slug}_db`,\n    };\n  });\n}\n\nfunction buildRedisConfigs(\n  secrets: string[],\n  originMap: Map<string, string>,\n  portMap: Record<string, number>,\n): RedisSecretConfig[] {\n  const redisSecrets = uniqueSecrets(secrets.filter((secret) => secret.endsWith(\"_REDIS_URL\")));\n\n  for (const secret of redisSecrets) {\n    const slug = normalizeRedisSlug(secret);\n    resolvePort(slug, portMap, BASE_REDIS_PORT);\n  }\n\n  return redisSecrets.map((secret) => {\n    const slug = normalizeRedisSlug(secret);\n    const fromKey = originMap.get(secret) ?? \"\";\n    const port = portMap[slug];\n\n    const volumeName = fromKey\n      ? `${fromKey.replace(/\\./g, \"_\")}_redis_${slug}_data`\n      : `redis_${slug}_data`;\n\n    const containerName = fromKey ? `${fromKey}-redis-${slug}` : `redis-${slug}`;\n\n    return {\n      secret,\n      slug,\n      fromKey,\n      port,\n      serviceName: `redis-${slug.replace(/_/g, \"-\")}`,\n      containerName,\n      volumeName,\n      url: `redis://localhost:${port}`,\n    };\n  });\n}\n\nfunction extractPortFromUrl(url: string): string | null {\n  const match = url.match(/:(\\d{4,5})(?:\\/|$)/);\n  return match?.[1] ?? null;\n}\n\nfunction defaultSecretValue(\n  secret: string,\n  databases: Map<string, DatabaseSecretConfig>,\n  redisConfigs: Map<string, RedisSecretConfig>,\n  options: { forExample: boolean },\n): string {\n  if (secret === \"BETTER_AUTH_SECRET\") {\n    return options.forExample ? \"\" : randomBytes(32).toString(\"base64url\");\n  }\n\n  if (secret === \"CORS_ORIGIN\") {\n    return \"http://localhost:3000\";\n  }\n\n  return databases.get(secret)?.url ?? redisConfigs.get(secret)?.url ?? \"\";\n}\n\nfunction renderEnvFile(\n  groups: SecretGroup[],\n  databases: DatabaseSecretConfig[],\n  redisConfigs: RedisSecretConfig[],\n  options: { forExample: boolean },\n): string {\n  const databaseMap = new Map(databases.map((entry) => [entry.secret, entry]));\n  const redisMap = new Map(redisConfigs.map((entry) => [entry.secret, entry]));\n  const lines: string[] = [\n    \"# Generated from configured bos secrets\",\n    \"# Update values as needed for your local environment\",\n    \"\",\n  ];\n\n  for (const group of groups) {\n    lines.push(`# ${group.section}`);\n    for (const secret of group.secrets) {\n      lines.push(`${secret}=${defaultSecretValue(secret, databaseMap, redisMap, options)}`);\n    }\n    lines.push(\"\");\n  }\n\n  return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction renderDockerCompose(\n  databases: DatabaseSecretConfig[],\n  redisConfigs: RedisSecretConfig[],\n  projectName: string,\n): string {\n  const lines = [`name: ${projectName}`, \"\"];\n\n  if (databases.length > 0) {\n    lines.push(\n      \"x-pg-common: &pg-common\",\n      \"  image: postgres:17-alpine\",\n      \"  environment: &pg-env\",\n      `    POSTGRES_USER: ${POSTGRES_USER}`,\n      `    POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}`,\n      \"  healthcheck:\",\n      '    test: [\"CMD-SHELL\", \"pg_isready -U everythingdev\"]',\n      \"    interval: 3s\",\n      \"    timeout: 3s\",\n      \"    retries: 5\",\n      \"\",\n    );\n  }\n\n  if (redisConfigs.length > 0) {\n    lines.push(\n      \"x-redis-common: &redis-common\",\n      \"  image: redis:7-alpine\",\n      \"  command: redis-server --appendonly yes\",\n      \"  healthcheck:\",\n      '    test: [\"CMD\", \"redis-cli\", \"ping\"]',\n      \"    interval: 3s\",\n      \"    timeout: 3s\",\n      \"    retries: 5\",\n      \"\",\n    );\n  }\n\n  lines.push(\"services:\");\n\n  for (const database of databases) {\n    lines.push(`  ${database.serviceName}:`);\n    lines.push(\"    <<: *pg-common\");\n    lines.push(`    container_name: ${database.containerName}`);\n    lines.push(\"    environment:\");\n    lines.push(\"      <<: *pg-env\");\n    lines.push(`      POSTGRES_DB: ${database.databaseName}`);\n    lines.push(\"    ports:\");\n    lines.push(`      - \"${database.port}:5432\"`);\n    lines.push(\"    volumes:\");\n    lines.push(`      - ${database.volumeName}:/var/lib/postgresql/data`);\n    lines.push(\"\");\n  }\n\n  for (const redis of redisConfigs) {\n    lines.push(`  ${redis.serviceName}:`);\n    lines.push(\"    <<: *redis-common\");\n    lines.push(`    container_name: ${redis.containerName}`);\n    lines.push(\"    ports:\");\n    lines.push(`      - \"${redis.port}:6379\"`);\n    lines.push(\"    volumes:\");\n    lines.push(`      - ${redis.volumeName}:/data`);\n    lines.push(\"\");\n  }\n\n  lines.push(\"volumes:\");\n  for (const database of databases) {\n    lines.push(`  ${database.volumeName}:`);\n    lines.push(`    name: ${database.volumeName}`);\n  }\n  for (const redis of redisConfigs) {\n    lines.push(`  ${redis.volumeName}:`);\n    lines.push(`    name: ${redis.volumeName}`);\n  }\n\n  return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction syncTextFile(filePath: string, nextContent: string): boolean {\n  if (existsSync(filePath) && readFileSync(filePath, \"utf-8\") === nextContent) {\n    return false;\n  }\n\n  writeFileSync(filePath, nextContent);\n  return true;\n}\n\nexport function writeGeneratedInfra(configDir: string, runtimeConfig: RuntimeConfig): string[] {\n  const result = syncGeneratedInfra(configDir, runtimeConfig);\n\n  if (result.staleEnvWarnings.length > 0) {\n    p.log.warn(\n      `.env has ${result.staleEnvWarnings.length} stale value(s) compared to .env.example:`,\n    );\n    for (const warning of result.staleEnvWarnings) {\n      p.log.message(`  ${warning}`);\n    }\n  }\n\n  return result.secrets;\n}\n\nexport function syncGeneratedInfra(\n  configDir: string,\n  runtimeConfig: RuntimeConfig,\n): SyncGeneratedInfraResult {\n  const { spec, portState } = buildGeneratedInfraSpec(runtimeConfig, configDir);\n  const secrets = spec.groups.flatMap((group) => group.secrets);\n  const newEnvContent = renderEnvFile(spec.groups, spec.databases, spec.redis, {\n    forExample: true,\n  });\n  const newDockerContent = renderDockerCompose(spec.databases, spec.redis, runtimeConfig.account);\n\n  const envExamplePath = join(configDir, \".env.example\");\n  const dockerComposePath = join(configDir, \"docker-compose.yml\");\n\n  const staleWarnings = checkEnvStaleness(configDir, spec.databases, spec.redis);\n\n  if (configDir) {\n    savePortState(configDir, portState);\n  }\n\n  return {\n    secrets,\n    envExampleChanged: syncTextFile(envExamplePath, newEnvContent),\n    dockerComposeChanged: syncTextFile(dockerComposePath, newDockerContent),\n    staleEnvWarnings: staleWarnings,\n  };\n}\n\nfunction checkEnvStaleness(\n  configDir: string,\n  databases: DatabaseSecretConfig[],\n  redisConfigs: RedisSecretConfig[],\n): string[] {\n  const envPath = join(configDir, \".env\");\n  if (!existsSync(envPath)) return [];\n\n  const existingEnv = readFileSync(envPath, \"utf-8\");\n  const envMap = new Map<string, string>();\n  for (const line of existingEnv.split(\"\\n\")) {\n    const match = line.match(/^([A-Z_]+)=(.*)$/);\n    if (match) envMap.set(match[1], match[2]);\n  }\n\n  const stale: string[] = [];\n\n  for (const db of databases) {\n    const existing = envMap.get(db.secret);\n    if (existing && existing !== db.url) {\n      const oldPort = extractPortFromUrl(existing) ?? \"?\";\n      stale.push(`${db.secret}: port ${oldPort} → ${db.port}`);\n    }\n  }\n\n  for (const redis of redisConfigs) {\n    const existing = envMap.get(redis.secret);\n    if (existing && existing !== redis.url) {\n      const oldPort = extractPortFromUrl(existing) ?? \"?\";\n      stale.push(`${redis.secret}: port ${oldPort} → ${redis.port}`);\n    }\n  }\n\n  return stale;\n}\n\nexport function ensureEnvFile(configDir: string): void {\n  const envPath = join(configDir, \".env\");\n  const examplePath = join(configDir, \".env.example\");\n\n  if (existsSync(envPath) || !existsSync(examplePath)) return;\n\n  const content = readFileSync(examplePath, \"utf-8\");\n  const lines = content.split(\"\\n\");\n  const secret = randomBytes(32).toString(\"base64url\");\n  const updated = lines\n    .map((line) => {\n      if (/^BETTER_AUTH_SECRET=/.test(line)) {\n        return `BETTER_AUTH_SECRET=${secret}`;\n      }\n      return line;\n    })\n    .join(\"\\n\");\n\n  writeFileSync(envPath, updated);\n  p.log.info(\"Created .env from generated .env.example with generated BETTER_AUTH_SECRET\");\n}\n\nexport function loadProjectEnv(configDir: string): void {\n  const envPath = join(configDir, \".env\");\n  if (!existsSync(envPath)) return;\n\n  loadDotenv({ path: envPath, processEnv: process.env, quiet: true });\n}\n"],"mappings":"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"}