@habeetat/cli 0.1.0-dev.20260323164114.3a5aac3 → 0.1.0-dev.20260324154244.f7ef1fb

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/logger.ts","../src/constants.ts","../src/utils/config.ts","../src/utils/docker.ts","../src/commands/up.ts","../src/commands/down.ts","../src/commands/status.ts","../src/commands/logs.ts","../src/commands/restart.ts","../src/commands/doctor.ts","../src/bin.ts"],"names":["chalk","path","fs","execaCommand","ora","readFileSync","Command"],"mappings":"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","file":"bin.js","sourcesContent":["import chalk from 'chalk';\n\nconst prefix = chalk.cyan('[habeetat]');\n\nexport const logger = {\n info: (msg: string) => console.log(`${prefix} ${msg}`),\n success: (msg: string) => console.log(`${prefix} ${chalk.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(`${prefix} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${prefix} ${chalk.red('✗')} ${msg}`),\n phase: (msg: string) => {\n console.log('');\n console.log(chalk.cyan('═'.repeat(56)));\n console.log(chalk.cyan(` ${msg}`));\n console.log(chalk.cyan('═'.repeat(56)));\n console.log('');\n },\n banner: () => {\n console.log('');\n console.log(chalk.cyan('╔══════════════════════════════════════════════╗'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('║ Habeetat Platform CLI ║'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('╚══════════════════════════════════════════════╝'));\n console.log('');\n },\n};\n","export const CONFIG_FILE = 'habeetat.json';\nexport const ENV_FILE = '.env';\nexport const COMPOSE_FILE = 'docker-compose.yml';\n\nexport const DOCKER_REGISTRY = 'docker.io/capriisland';\n\nexport const IMAGES = {\n backend: 'capriisland/habeetat-backend',\n launcher: 'capriisland/habeetat-launcher',\n orgManager: 'capriisland/habeetat-org-manager',\n platformManager: 'capriisland/habeetat-platform-manager',\n sampleCrm: 'capriisland/habeetat-sample-crm',\n logtoConfig: 'capriisland/habeetat-logto-config',\n} as const;\n\nexport const THIRD_PARTY_IMAGES = {\n postgres: 'postgres:15-alpine',\n logto: 'svhd/logto:1.33',\n nginx: 'nginx:1.25-alpine',\n certbot: 'certbot/certbot',\n} as const;\n\nexport const DEFAULT_PORTS = {\n http: 80,\n https: 443,\n} as const;\n\nexport const SERVICES = [\n 'logto-db',\n 'platform-db',\n 'logto-core',\n 'backend',\n 'launcher',\n 'organization-manager',\n 'platform-manager',\n 'sample-crm',\n 'nginx',\n] as const;\n\nexport type ServiceName = (typeof SERVICES)[number];\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE } from '../constants.js';\nimport type { HabeetatConfig } from '../types.js';\n\nexport function findProjectRoot(startDir: string = process.cwd()): string | null {\n let dir = startDir;\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, CONFIG_FILE))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nexport function loadConfig(projectDir?: string): HabeetatConfig {\n const dir = projectDir || findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n const configPath = path.join(dir, CONFIG_FILE);\n const raw = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as HabeetatConfig;\n}\n\nexport function saveConfig(config: HabeetatConfig, projectDir: string): void {\n const configPath = path.join(projectDir, CONFIG_FILE);\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function getProjectDir(): string {\n const dir = findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n return dir;\n}\n","import { execaCommand } from 'execa';\nimport { logger } from './logger.js';\n\nexport async function checkDocker(): Promise<boolean> {\n try {\n const { stdout } = await execaCommand('docker --version');\n const match = stdout.match(/Docker version (\\d+)/);\n if (match && parseInt(match[1], 10) >= 20) {\n return true;\n }\n logger.error(`Docker >= 20.0 required. Found: ${stdout.trim()}`);\n return false;\n } catch {\n logger.error('Docker is not installed or not in PATH');\n logger.info('Install Docker: https://docs.docker.com/get-docker/');\n return false;\n }\n}\n\nexport async function checkDockerCompose(): Promise<boolean> {\n try {\n await execaCommand('docker compose version');\n return true;\n } catch {\n logger.error('Docker Compose V2 is not available');\n logger.info('Docker Compose V2 is included with Docker Desktop');\n return false;\n }\n}\n\nexport async function checkPrerequisites(): Promise<boolean> {\n const docker = await checkDocker();\n const compose = await checkDockerCompose();\n return docker && compose;\n}\n\nexport interface ComposeExecOptions {\n cwd: string;\n composeFile?: string;\n silent?: boolean;\n}\n\nexport async function composeUp(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} up -d`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeDown(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composePs(opts: ComposeExecOptions): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(`docker compose -f ${file} ps`, {\n cwd: opts.cwd,\n });\n return stdout;\n}\n\nexport async function composeLogs(\n opts: ComposeExecOptions & { service?: string; follow?: boolean; tail?: number },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const parts = ['docker', 'compose', '-f', file, 'logs'];\n if (opts.follow) parts.push('-f');\n if (opts.tail) parts.push('--tail', String(opts.tail));\n if (opts.service) parts.push(opts.service);\n\n await execaCommand(parts.join(' '), {\n cwd: opts.cwd,\n stdio: 'inherit',\n });\n}\n\nexport async function composeRestart(\n opts: ComposeExecOptions & { service?: string },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const cmd = opts.service\n ? `docker compose -f ${file} restart ${opts.service}`\n : `docker compose -f ${file} restart`;\n\n await execaCommand(cmd, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeExec(\n opts: ComposeExecOptions & { service: string; command: string },\n): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(\n `docker compose -f ${file} exec -T ${opts.service} ${opts.command}`,\n { cwd: opts.cwd },\n );\n return stdout;\n}\n\nexport async function dockerPull(image: string): Promise<void> {\n await execaCommand(`docker pull ${image}`, { stdio: 'inherit' });\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composeUp, checkPrerequisites } from '../utils/docker.js';\n\nexport async function upCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n\n logger.info(`Starting Habeetat Platform (${config.platform.domain})...`);\n\n if (!(await checkPrerequisites())) {\n process.exit(1);\n }\n\n const spinner = ora('Starting services...').start();\n\n try {\n await composeUp({ cwd: projectDir });\n spinner.succeed('All services started');\n\n const proto = config.platform.protocol;\n const domain = config.platform.domain;\n\n console.log('');\n logger.info('Platform URLs:');\n console.log(` Launcher: ${proto}://launcher.${domain}`);\n console.log(` Organization Manager: ${proto}://organization-manager.${domain}`);\n console.log(` Platform Manager: ${proto}://platform-manager.${domain}`);\n console.log(` Backend API: ${proto}://api.${domain}`);\n console.log(` Logto IAM: ${proto}://iam.${domain}`);\n console.log(` Logto Admin Console: ${proto}://iam-console.${domain}`);\n console.log('');\n logger.info('Run `habeetat status` to check service health');\n } catch (err) {\n spinner.fail('Failed to start services');\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeDown } from '../utils/docker.js';\n\nexport async function downCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const spinner = ora('Stopping services...').start();\n\n try {\n await composeDown({ cwd: projectDir });\n spinner.succeed('All services stopped');\n } catch (err) {\n spinner.fail('Failed to stop services');\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composePs } from '../utils/docker.js';\n\nexport async function statusCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n\n logger.info(`Habeetat Platform — ${config.platform.domain}`);\n logger.info(`Version: ${config.version}`);\n logger.info(`Image tag: ${config.docker.imageTag}`);\n console.log('');\n\n try {\n const output = await composePs({ cwd: projectDir });\n console.log(output);\n } catch (err) {\n logger.error('Could not get service status. Is the platform running?');\n logger.info('Run `habeetat up` to start the platform');\n process.exit(1);\n }\n}\n","import { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeLogs } from '../utils/docker.js';\nimport { SERVICES } from '../constants.js';\n\nexport async function logsCommand(\n service?: string,\n options?: { follow?: boolean; tail?: number },\n): Promise<void> {\n const projectDir = getProjectDir();\n\n if (service && !(SERVICES as readonly string[]).includes(service)) {\n logger.error(`Unknown service: ${service}`);\n logger.info(`Available services: ${SERVICES.join(', ')}`);\n process.exit(1);\n }\n\n try {\n await composeLogs({\n cwd: projectDir,\n service,\n follow: options?.follow,\n tail: options?.tail,\n });\n } catch {\n // User interrupted with Ctrl+C — that's fine\n }\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeRestart } from '../utils/docker.js';\nimport { SERVICES } from '../constants.js';\n\nexport async function restartCommand(service?: string): Promise<void> {\n const projectDir = getProjectDir();\n\n if (service && !(SERVICES as readonly string[]).includes(service)) {\n logger.error(`Unknown service: ${service}`);\n logger.info(`Available services: ${SERVICES.join(', ')}`);\n process.exit(1);\n }\n\n const label = service || 'all services';\n const spinner = ora(`Restarting ${label}...`).start();\n\n try {\n await composeRestart({ cwd: projectDir, service });\n spinner.succeed(`Restarted ${label}`);\n } catch (err) {\n spinner.fail(`Failed to restart ${label}`);\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { logger } from '../utils/logger.js';\nimport { checkDocker, checkDockerCompose } from '../utils/docker.js';\nimport { findProjectRoot, loadConfig } from '../utils/config.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE, COMPOSE_FILE, ENV_FILE } from '../constants.js';\n\nexport async function doctorCommand(): Promise<void> {\n logger.phase('Habeetat Doctor — Diagnostics');\n let issues = 0;\n\n // Check Docker\n const dockerOk = await checkDocker();\n console.log(` Docker: ${dockerOk ? chalk.green('✓ Installed') : chalk.red('✗ Not found')}`);\n if (!dockerOk) issues++;\n\n // Check Docker Compose\n const composeOk = await checkDockerCompose();\n console.log(` Docker Compose: ${composeOk ? chalk.green('✓ Available') : chalk.red('✗ Not found')}`);\n if (!composeOk) issues++;\n\n // Check project directory\n const projectDir = findProjectRoot();\n console.log(` Project dir: ${projectDir ? chalk.green(`✓ ${projectDir}`) : chalk.yellow('⚠ Not in a Habeetat project')}`);\n if (!projectDir) {\n issues++;\n console.log('');\n logger.info(`Run \\`npm create habeetat my-platform\\` to create a new project`);\n return;\n }\n\n // Check config file\n const configExists = fs.existsSync(path.join(projectDir, CONFIG_FILE));\n console.log(` ${CONFIG_FILE}: ${configExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!configExists) issues++;\n\n // Check compose file\n const composeExists = fs.existsSync(path.join(projectDir, COMPOSE_FILE));\n console.log(` ${COMPOSE_FILE}: ${composeExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!composeExists) issues++;\n\n // Check env file\n const envExists = fs.existsSync(path.join(projectDir, ENV_FILE));\n console.log(` ${ENV_FILE}: ${envExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!envExists) issues++;\n\n // Check nginx config\n const nginxExists = fs.existsSync(path.join(projectDir, 'nginx', 'platform.conf'));\n console.log(` nginx/platform.conf: ${nginxExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!nginxExists) issues++;\n\n // Load config and check images\n if (configExists) {\n try {\n const config = loadConfig(projectDir);\n console.log(` Version: ${chalk.cyan(config.version)}`);\n console.log(` Domain: ${chalk.cyan(config.platform.domain)}`);\n console.log(` Protocol: ${chalk.cyan(config.platform.protocol)}`);\n } catch (err) {\n console.log(` Config: ${chalk.red('✗ Invalid JSON')}`);\n issues++;\n }\n }\n\n console.log('');\n if (issues === 0) {\n logger.success('No issues found');\n } else {\n logger.warn(`${issues} issue(s) found`);\n }\n}\n","import { Command } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport path from 'node:path';\nimport { upCommand } from './commands/up.js';\nimport { downCommand } from './commands/down.js';\nimport { statusCommand } from './commands/status.js';\nimport { logsCommand } from './commands/logs.js';\nimport { restartCommand } from './commands/restart.js';\nimport { doctorCommand } from './commands/doctor.js';\n\nconst pkg = JSON.parse(\n readFileSync(path.resolve(__dirname, '..', 'package.json'), 'utf-8'),\n);\n\nconst program = new Command();\n\nprogram\n .name('habeetat')\n .description('Habeetat Platform CLI — manage your platform instances')\n .version(pkg.version);\n\nprogram\n .command('up')\n .description('Start the platform')\n .action(upCommand);\n\nprogram\n .command('down')\n .description('Stop the platform')\n .action(downCommand);\n\nprogram\n .command('status')\n .description('Show platform service status')\n .action(statusCommand);\n\nprogram\n .command('logs [service]')\n .description('View service logs')\n .option('-f, --follow', 'Follow log output')\n .option('-n, --tail <lines>', 'Number of lines to show', parseInt)\n .action((service: string | undefined, options: { follow?: boolean; tail?: number }) => {\n return logsCommand(service, options);\n });\n\nprogram\n .command('restart [service]')\n .description('Restart services')\n .action(restartCommand);\n\nprogram\n .command('doctor')\n .description('Diagnose common issues')\n .action(doctorCommand);\n\nprogram.parse();\n"]}
1
+ {"version":3,"sources":["../src/utils/logger.ts","../src/constants.ts","../src/utils/config.ts","../src/utils/docker.ts","../src/commands/up.ts","../src/commands/down.ts","../src/commands/status.ts","../src/commands/logs.ts","../src/commands/restart.ts","../src/commands/doctor.ts","../src/bin.ts"],"names":["chalk","path","fs","execaCommand","ora","readFileSync","Command"],"mappings":"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","file":"bin.js","sourcesContent":["import chalk from 'chalk';\n\nconst prefix = chalk.cyan('[habeetat]');\n\nexport const logger = {\n info: (msg: string) => console.log(`${prefix} ${msg}`),\n success: (msg: string) => console.log(`${prefix} ${chalk.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(`${prefix} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${prefix} ${chalk.red('✗')} ${msg}`),\n phase: (msg: string) => {\n console.log('');\n console.log(chalk.cyan('═'.repeat(56)));\n console.log(chalk.cyan(` ${msg}`));\n console.log(chalk.cyan('═'.repeat(56)));\n console.log('');\n },\n banner: () => {\n console.log('');\n console.log(chalk.cyan('╔══════════════════════════════════════════════╗'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('║ Habeetat Platform CLI ║'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('╚══════════════════════════════════════════════╝'));\n console.log('');\n },\n};\n","export const CONFIG_FILE = 'habeetat.json';\nexport const ENV_FILE = '.env';\nexport const COMPOSE_FILE = 'docker-compose.yml';\n\nexport const DOCKER_REGISTRY = 'docker.io/capriisland';\n\nexport const IMAGES = {\n backend: 'capriisland/habeetat-backend',\n launcher: 'capriisland/habeetat-launcher',\n orgManager: 'capriisland/habeetat-org-manager',\n platformManager: 'capriisland/habeetat-platform-manager',\n sampleCrm: 'capriisland/habeetat-sample-crm',\n logtoConfig: 'capriisland/habeetat-logto-config',\n} as const;\n\nexport const THIRD_PARTY_IMAGES = {\n postgres: 'postgres:15-alpine',\n logto: 'svhd/logto:1.33',\n nginx: 'nginx:1.25-alpine',\n certbot: 'certbot/certbot',\n} as const;\n\nexport const DEFAULT_PORTS = {\n http: 80,\n https: 443,\n hostNginx: 8080,\n} as const;\n\nexport const SERVICES = [\n 'logto-db',\n 'platform-db',\n 'logto-core',\n 'backend',\n 'launcher',\n 'organization-manager',\n 'platform-manager',\n 'sample-crm',\n 'nginx',\n] as const;\n\nexport type ServiceName = (typeof SERVICES)[number];\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE } from '../constants.js';\nimport type { HabeetatConfig } from '../types.js';\n\nexport function findProjectRoot(startDir: string = process.cwd()): string | null {\n let dir = startDir;\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, CONFIG_FILE))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nexport function loadConfig(projectDir?: string): HabeetatConfig {\n const dir = projectDir || findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n const configPath = path.join(dir, CONFIG_FILE);\n const raw = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as HabeetatConfig;\n}\n\nexport function saveConfig(config: HabeetatConfig, projectDir: string): void {\n const configPath = path.join(projectDir, CONFIG_FILE);\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function getProjectDir(): string {\n const dir = findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n return dir;\n}\n","import { execaCommand } from 'execa';\nimport { logger } from './logger.js';\n\nexport async function checkDocker(): Promise<boolean> {\n try {\n const { stdout } = await execaCommand('docker --version');\n const match = stdout.match(/Docker version (\\d+)/);\n if (match && parseInt(match[1], 10) >= 20) {\n return true;\n }\n logger.error(`Docker >= 20.0 required. Found: ${stdout.trim()}`);\n return false;\n } catch {\n logger.error('Docker is not installed or not in PATH');\n logger.info('Install Docker: https://docs.docker.com/get-docker/');\n return false;\n }\n}\n\nexport async function checkDockerCompose(): Promise<boolean> {\n try {\n await execaCommand('docker compose version');\n return true;\n } catch {\n logger.error('Docker Compose V2 is not available');\n logger.info('Docker Compose V2 is included with Docker Desktop');\n return false;\n }\n}\n\nexport async function checkPrerequisites(): Promise<boolean> {\n const docker = await checkDocker();\n const compose = await checkDockerCompose();\n return docker && compose;\n}\n\nexport interface ComposeExecOptions {\n cwd: string;\n composeFile?: string;\n silent?: boolean;\n}\n\nexport async function composeUp(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} up -d`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeDown(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composePs(opts: ComposeExecOptions): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(`docker compose -f ${file} ps`, {\n cwd: opts.cwd,\n });\n return stdout;\n}\n\nexport async function composeLogs(\n opts: ComposeExecOptions & { service?: string; follow?: boolean; tail?: number },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const parts = ['docker', 'compose', '-f', file, 'logs'];\n if (opts.follow) parts.push('-f');\n if (opts.tail) parts.push('--tail', String(opts.tail));\n if (opts.service) parts.push(opts.service);\n\n await execaCommand(parts.join(' '), {\n cwd: opts.cwd,\n stdio: 'inherit',\n });\n}\n\nexport async function composeRestart(\n opts: ComposeExecOptions & { service?: string },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const cmd = opts.service\n ? `docker compose -f ${file} restart ${opts.service}`\n : `docker compose -f ${file} restart`;\n\n await execaCommand(cmd, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeExec(\n opts: ComposeExecOptions & { service: string; command: string },\n): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(\n `docker compose -f ${file} exec -T ${opts.service} ${opts.command}`,\n { cwd: opts.cwd },\n );\n return stdout;\n}\n\nexport async function dockerPull(image: string): Promise<void> {\n await execaCommand(`docker pull ${image}`, { stdio: 'inherit' });\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composeUp, checkPrerequisites } from '../utils/docker.js';\n\nexport async function upCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n\n logger.info(`Starting Habeetat Platform (${config.platform.domain})...`);\n\n if (!(await checkPrerequisites())) {\n process.exit(1);\n }\n\n const spinner = ora('Starting services...').start();\n\n try {\n await composeUp({ cwd: projectDir });\n spinner.succeed('All services started');\n\n const proto = config.platform.protocol;\n const domain = config.platform.domain;\n\n console.log('');\n logger.info('Platform URLs:');\n console.log(` Launcher: ${proto}://launcher.${domain}`);\n console.log(` Organization Manager: ${proto}://organization-manager.${domain}`);\n console.log(` Platform Manager: ${proto}://platform-manager.${domain}`);\n console.log(` Backend API: ${proto}://api.${domain}`);\n console.log(` Logto IAM: ${proto}://iam.${domain}`);\n console.log(` Logto Admin Console: ${proto}://iam-console.${domain}`);\n console.log('');\n logger.info('Run `habeetat status` to check service health');\n } catch (err) {\n spinner.fail('Failed to start services');\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeDown } from '../utils/docker.js';\n\nexport async function downCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const spinner = ora('Stopping services...').start();\n\n try {\n await composeDown({ cwd: projectDir });\n spinner.succeed('All services stopped');\n } catch (err) {\n spinner.fail('Failed to stop services');\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composePs } from '../utils/docker.js';\n\nexport async function statusCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n\n logger.info(`Habeetat Platform — ${config.platform.domain}`);\n logger.info(`Version: ${config.version}`);\n logger.info(`Image tag: ${config.docker.imageTag}`);\n console.log('');\n\n try {\n const output = await composePs({ cwd: projectDir });\n console.log(output);\n } catch (err) {\n logger.error('Could not get service status. Is the platform running?');\n logger.info('Run `habeetat up` to start the platform');\n process.exit(1);\n }\n}\n","import { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeLogs } from '../utils/docker.js';\nimport { SERVICES } from '../constants.js';\n\nexport async function logsCommand(\n service?: string,\n options?: { follow?: boolean; tail?: number },\n): Promise<void> {\n const projectDir = getProjectDir();\n\n if (service && !(SERVICES as readonly string[]).includes(service)) {\n logger.error(`Unknown service: ${service}`);\n logger.info(`Available services: ${SERVICES.join(', ')}`);\n process.exit(1);\n }\n\n try {\n await composeLogs({\n cwd: projectDir,\n service,\n follow: options?.follow,\n tail: options?.tail,\n });\n } catch {\n // User interrupted with Ctrl+C — that's fine\n }\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeRestart } from '../utils/docker.js';\nimport { SERVICES } from '../constants.js';\n\nexport async function restartCommand(service?: string): Promise<void> {\n const projectDir = getProjectDir();\n\n if (service && !(SERVICES as readonly string[]).includes(service)) {\n logger.error(`Unknown service: ${service}`);\n logger.info(`Available services: ${SERVICES.join(', ')}`);\n process.exit(1);\n }\n\n const label = service || 'all services';\n const spinner = ora(`Restarting ${label}...`).start();\n\n try {\n await composeRestart({ cwd: projectDir, service });\n spinner.succeed(`Restarted ${label}`);\n } catch (err) {\n spinner.fail(`Failed to restart ${label}`);\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { logger } from '../utils/logger.js';\nimport { checkDocker, checkDockerCompose } from '../utils/docker.js';\nimport { findProjectRoot, loadConfig } from '../utils/config.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE, COMPOSE_FILE, ENV_FILE } from '../constants.js';\n\nexport async function doctorCommand(): Promise<void> {\n logger.phase('Habeetat Doctor — Diagnostics');\n let issues = 0;\n\n // Check Docker\n const dockerOk = await checkDocker();\n console.log(` Docker: ${dockerOk ? chalk.green('✓ Installed') : chalk.red('✗ Not found')}`);\n if (!dockerOk) issues++;\n\n // Check Docker Compose\n const composeOk = await checkDockerCompose();\n console.log(` Docker Compose: ${composeOk ? chalk.green('✓ Available') : chalk.red('✗ Not found')}`);\n if (!composeOk) issues++;\n\n // Check project directory\n const projectDir = findProjectRoot();\n console.log(` Project dir: ${projectDir ? chalk.green(`✓ ${projectDir}`) : chalk.yellow('⚠ Not in a Habeetat project')}`);\n if (!projectDir) {\n issues++;\n console.log('');\n logger.info(`Run \\`npm create habeetat my-platform\\` to create a new project`);\n return;\n }\n\n // Check config file\n const configExists = fs.existsSync(path.join(projectDir, CONFIG_FILE));\n console.log(` ${CONFIG_FILE}: ${configExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!configExists) issues++;\n\n // Check compose file\n const composeExists = fs.existsSync(path.join(projectDir, COMPOSE_FILE));\n console.log(` ${COMPOSE_FILE}: ${composeExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!composeExists) issues++;\n\n // Check env file\n const envExists = fs.existsSync(path.join(projectDir, ENV_FILE));\n console.log(` ${ENV_FILE}: ${envExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!envExists) issues++;\n\n // Check nginx config\n const nginxExists = fs.existsSync(path.join(projectDir, 'nginx', 'platform.conf'));\n console.log(` nginx/platform.conf: ${nginxExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!nginxExists) issues++;\n\n // Load config and check images\n if (configExists) {\n try {\n const config = loadConfig(projectDir);\n console.log(` Version: ${chalk.cyan(config.version)}`);\n console.log(` Domain: ${chalk.cyan(config.platform.domain)}`);\n console.log(` Protocol: ${chalk.cyan(config.platform.protocol)}`);\n } catch (err) {\n console.log(` Config: ${chalk.red('✗ Invalid JSON')}`);\n issues++;\n }\n }\n\n console.log('');\n if (issues === 0) {\n logger.success('No issues found');\n } else {\n logger.warn(`${issues} issue(s) found`);\n }\n}\n","import { Command } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport path from 'node:path';\nimport { upCommand } from './commands/up.js';\nimport { downCommand } from './commands/down.js';\nimport { statusCommand } from './commands/status.js';\nimport { logsCommand } from './commands/logs.js';\nimport { restartCommand } from './commands/restart.js';\nimport { doctorCommand } from './commands/doctor.js';\n\nconst pkg = JSON.parse(\n readFileSync(path.resolve(__dirname, '..', 'package.json'), 'utf-8'),\n);\n\nconst program = new Command();\n\nprogram\n .name('habeetat')\n .description('Habeetat Platform CLI — manage your platform instances')\n .version(pkg.version);\n\nprogram\n .command('up')\n .description('Start the platform')\n .action(upCommand);\n\nprogram\n .command('down')\n .description('Stop the platform')\n .action(downCommand);\n\nprogram\n .command('status')\n .description('Show platform service status')\n .action(statusCommand);\n\nprogram\n .command('logs [service]')\n .description('View service logs')\n .option('-f, --follow', 'Follow log output')\n .option('-n, --tail <lines>', 'Number of lines to show', parseInt)\n .action((service: string | undefined, options: { follow?: boolean; tail?: number }) => {\n return logsCommand(service, options);\n });\n\nprogram\n .command('restart [service]')\n .description('Restart services')\n .action(restartCommand);\n\nprogram\n .command('doctor')\n .description('Diagnose common issues')\n .action(doctorCommand);\n\nprogram.parse();\n"]}
package/dist/index.d.mts CHANGED
@@ -10,6 +10,10 @@ interface HabeetatConfig {
10
10
  registry: string;
11
11
  imageTag: string;
12
12
  };
13
+ nginx: {
14
+ hostPort: number;
15
+ setupHostNginx: boolean;
16
+ };
13
17
  services: {
14
18
  backend: boolean;
15
19
  launcher: boolean;
@@ -54,6 +58,8 @@ interface CreateOptions {
54
58
  ssl: boolean;
55
59
  tag: string;
56
60
  skipStart: boolean;
61
+ hostPort: number;
62
+ setupHostNginx: boolean;
57
63
  }
58
64
 
59
65
  declare const CONFIG_FILE = "habeetat.json";
@@ -74,12 +80,19 @@ declare const THIRD_PARTY_IMAGES: {
74
80
  readonly nginx: "nginx:1.25-alpine";
75
81
  readonly certbot: "certbot/certbot";
76
82
  };
83
+ declare const DEFAULT_PORTS: {
84
+ readonly http: 80;
85
+ readonly https: 443;
86
+ readonly hostNginx: 8080;
87
+ };
77
88
  declare const SERVICES: readonly ["logto-db", "platform-db", "logto-core", "backend", "launcher", "organization-manager", "platform-manager", "sample-crm", "nginx"];
78
89
 
79
90
  declare function generateDockerCompose(config: HabeetatConfig): string;
80
91
 
81
92
  declare function generateNginxConf(config: HabeetatConfig): string;
82
93
 
94
+ declare function generateHostNginxConf(config: HabeetatConfig): string;
95
+
83
96
  declare function generateEnvFile(opts: CreateOptions): string;
84
97
 
85
98
  declare const logger: {
@@ -104,4 +117,4 @@ declare function generateSecrets(): {
104
117
  logtoM2mAppSecret: string;
105
118
  };
106
119
 
107
- export { COMPOSE_FILE, CONFIG_FILE, type CreateOptions, DOCKER_REGISTRY, ENV_FILE, type HabeetatConfig, IMAGES, type PlatformEnv, SERVICES, THIRD_PARTY_IMAGES, checkPrerequisites, findProjectRoot, generateDockerCompose, generateEnvFile, generateNginxConf, generateSecrets, loadConfig, logger, saveConfig };
120
+ export { COMPOSE_FILE, CONFIG_FILE, type CreateOptions, DEFAULT_PORTS, DOCKER_REGISTRY, ENV_FILE, type HabeetatConfig, IMAGES, type PlatformEnv, SERVICES, THIRD_PARTY_IMAGES, checkPrerequisites, findProjectRoot, generateDockerCompose, generateEnvFile, generateHostNginxConf, generateNginxConf, generateSecrets, loadConfig, logger, saveConfig };
package/dist/index.d.ts CHANGED
@@ -10,6 +10,10 @@ interface HabeetatConfig {
10
10
  registry: string;
11
11
  imageTag: string;
12
12
  };
13
+ nginx: {
14
+ hostPort: number;
15
+ setupHostNginx: boolean;
16
+ };
13
17
  services: {
14
18
  backend: boolean;
15
19
  launcher: boolean;
@@ -54,6 +58,8 @@ interface CreateOptions {
54
58
  ssl: boolean;
55
59
  tag: string;
56
60
  skipStart: boolean;
61
+ hostPort: number;
62
+ setupHostNginx: boolean;
57
63
  }
58
64
 
59
65
  declare const CONFIG_FILE = "habeetat.json";
@@ -74,12 +80,19 @@ declare const THIRD_PARTY_IMAGES: {
74
80
  readonly nginx: "nginx:1.25-alpine";
75
81
  readonly certbot: "certbot/certbot";
76
82
  };
83
+ declare const DEFAULT_PORTS: {
84
+ readonly http: 80;
85
+ readonly https: 443;
86
+ readonly hostNginx: 8080;
87
+ };
77
88
  declare const SERVICES: readonly ["logto-db", "platform-db", "logto-core", "backend", "launcher", "organization-manager", "platform-manager", "sample-crm", "nginx"];
78
89
 
79
90
  declare function generateDockerCompose(config: HabeetatConfig): string;
80
91
 
81
92
  declare function generateNginxConf(config: HabeetatConfig): string;
82
93
 
94
+ declare function generateHostNginxConf(config: HabeetatConfig): string;
95
+
83
96
  declare function generateEnvFile(opts: CreateOptions): string;
84
97
 
85
98
  declare const logger: {
@@ -104,4 +117,4 @@ declare function generateSecrets(): {
104
117
  logtoM2mAppSecret: string;
105
118
  };
106
119
 
107
- export { COMPOSE_FILE, CONFIG_FILE, type CreateOptions, DOCKER_REGISTRY, ENV_FILE, type HabeetatConfig, IMAGES, type PlatformEnv, SERVICES, THIRD_PARTY_IMAGES, checkPrerequisites, findProjectRoot, generateDockerCompose, generateEnvFile, generateNginxConf, generateSecrets, loadConfig, logger, saveConfig };
120
+ export { COMPOSE_FILE, CONFIG_FILE, type CreateOptions, DEFAULT_PORTS, DOCKER_REGISTRY, ENV_FILE, type HabeetatConfig, IMAGES, type PlatformEnv, SERVICES, THIRD_PARTY_IMAGES, checkPrerequisites, findProjectRoot, generateDockerCompose, generateEnvFile, generateHostNginxConf, generateNginxConf, generateSecrets, loadConfig, logger, saveConfig };
package/dist/index.js CHANGED
@@ -32,6 +32,11 @@ var THIRD_PARTY_IMAGES = {
32
32
  nginx: "nginx:1.25-alpine",
33
33
  certbot: "certbot/certbot"
34
34
  };
35
+ var DEFAULT_PORTS = {
36
+ http: 80,
37
+ https: 443,
38
+ hostNginx: 8080
39
+ };
35
40
  var SERVICES = [
36
41
  "logto-db",
37
42
  "platform-db",
@@ -86,7 +91,7 @@ function generateDockerCompose(config) {
86
91
  "logto-core": {
87
92
  image: THIRD_PARTY_IMAGES.logto,
88
93
  entrypoint: ["sh", "-c"],
89
- command: ["npm run cli -- db seed -- --swe || true\nnpm run start"],
94
+ command: ["npm run cli -- db seed -- --swe && npm run start || npm run start"],
90
95
  depends_on: {
91
96
  "logto-db": { condition: "service_healthy" }
92
97
  },
@@ -208,33 +213,16 @@ function generateDockerCompose(config) {
208
213
  if (config.services.organizationManager) nginxDependsOn.push("organization-manager");
209
214
  if (config.services.platformManager) nginxDependsOn.push("platform-manager");
210
215
  if (config.services.sampleCrm) nginxDependsOn.push("sample-crm");
211
- const nginxVolumes = ["./nginx/platform.conf:/etc/nginx/conf.d/default.conf:ro"];
212
- const nginxPorts = ["80:80"];
213
- if (config.platform.protocol === "https") {
214
- nginxVolumes.push("./certbot/conf:/etc/letsencrypt:ro");
215
- nginxVolumes.push("./certbot/www:/var/www/certbot:ro");
216
- nginxPorts.push("443:443");
217
- }
216
+ const hostPort = config.nginx.hostPort;
218
217
  services["nginx"] = {
219
218
  image: THIRD_PARTY_IMAGES.nginx,
220
219
  depends_on: nginxDependsOn,
221
- volumes: nginxVolumes,
222
- ports: nginxPorts,
220
+ volumes: ["./nginx/platform.conf:/etc/nginx/conf.d/default.conf:ro"],
221
+ ports: [`127.0.0.1:${hostPort}:80`],
223
222
  networks: ["habeetat-network"],
224
223
  restart: "unless-stopped",
225
224
  command: `/bin/sh -c 'while :; do sleep 6h & wait $\${!}; nginx -s reload; done & nginx -g "daemon off;"'`
226
225
  };
227
- if (config.platform.protocol === "https") {
228
- services["certbot"] = {
229
- image: THIRD_PARTY_IMAGES.certbot,
230
- volumes: [
231
- "./certbot/conf:/etc/letsencrypt",
232
- "./certbot/www:/var/www/certbot"
233
- ],
234
- entrypoint: `/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $\${!}; done;'`,
235
- networks: ["habeetat-network"]
236
- };
237
- }
238
226
  const compose = {
239
227
  name: "habeetat",
240
228
  services,
@@ -307,7 +295,6 @@ ${nested}`;
307
295
  // src/templates/nginx.ts
308
296
  function generateNginxConf(config) {
309
297
  const domain = config.platform.domain;
310
- const ssl = config.platform.protocol === "https";
311
298
  const upstreams = [
312
299
  "upstream logto { server logto-core:3001; }",
313
300
  "upstream logto_admin { server logto-core:3002; }",
@@ -322,42 +309,27 @@ function generateNginxConf(config) {
322
309
  proxy_set_header X-Real-IP $remote_addr;
323
310
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
324
311
  proxy_set_header X-Forwarded-Proto $scheme;`;
325
- const sslBlock = ssl ? `
326
- ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
327
- ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
328
- include /etc/letsencrypt/options-ssl-nginx.conf;
329
- ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;` : "";
330
- const listenDirective = ssl ? "listen 443 ssl" : "listen 80";
331
312
  const serverBlocks = [];
332
- if (ssl) {
333
- serverBlocks.push(`
334
- server {
335
- listen 80;
336
- server_name ${domain} *.${domain};
337
- location /.well-known/acme-challenge/ { root /var/www/certbot; }
338
- location / { return 301 https://$host$request_uri; }
339
- }`);
340
- }
341
313
  serverBlocks.push(`
342
314
  server {
343
- ${listenDirective};
344
- server_name iam.${domain};${sslBlock}
315
+ listen 80;
316
+ server_name iam.${domain};
345
317
  location / {
346
318
  proxy_pass http://logto;${proxyHeaders}
347
319
  }
348
320
  }`);
349
321
  serverBlocks.push(`
350
322
  server {
351
- ${listenDirective};
352
- server_name iam-console.${domain};${sslBlock}
323
+ listen 80;
324
+ server_name iam-console.${domain};
353
325
  location / {
354
326
  proxy_pass http://logto_admin;${proxyHeaders}
355
327
  }
356
328
  }`);
357
329
  serverBlocks.push(`
358
330
  server {
359
- ${listenDirective};
360
- server_name api.${domain};${sslBlock}
331
+ listen 80;
332
+ server_name api.${domain};
361
333
  location / {
362
334
  limit_req zone=api_limit burst=20 nodelay;
363
335
  proxy_pass http://api;${proxyHeaders}
@@ -366,8 +338,8 @@ server {
366
338
  if (config.services.launcher) {
367
339
  serverBlocks.push(`
368
340
  server {
369
- ${listenDirective};
370
- server_name launcher.${domain};${sslBlock}
341
+ listen 80;
342
+ server_name launcher.${domain};
371
343
  location / {
372
344
  proxy_pass http://launcher;${proxyHeaders}
373
345
  }
@@ -376,8 +348,8 @@ server {
376
348
  if (config.services.organizationManager) {
377
349
  serverBlocks.push(`
378
350
  server {
379
- ${listenDirective};
380
- server_name organization-manager.${domain};${sslBlock}
351
+ listen 80;
352
+ server_name organization-manager.${domain};
381
353
  location / {
382
354
  proxy_pass http://organization-manager;${proxyHeaders}
383
355
  }
@@ -386,8 +358,8 @@ server {
386
358
  if (config.services.platformManager) {
387
359
  serverBlocks.push(`
388
360
  server {
389
- ${listenDirective};
390
- server_name platform-manager.${domain};${sslBlock}
361
+ listen 80;
362
+ server_name platform-manager.${domain};
391
363
  location / {
392
364
  proxy_pass http://platform-manager;${proxyHeaders}
393
365
  }
@@ -396,15 +368,17 @@ server {
396
368
  if (config.services.sampleCrm) {
397
369
  serverBlocks.push(`
398
370
  server {
399
- ${listenDirective};
400
- server_name sample-crm.${domain};${sslBlock}
371
+ listen 80;
372
+ server_name sample-crm.${domain};
401
373
  location / {
402
374
  proxy_pass http://sample-crm;${proxyHeaders}
403
375
  }
404
376
  }`);
405
377
  }
406
- return `# Habeetat Platform - Nginx Configuration
378
+ return `# Habeetat Platform - Container Nginx Configuration
407
379
  # Auto-generated by @habeetat/cli for domain: ${domain}
380
+ # This handles internal routing between Docker services.
381
+ # SSL is handled by the host nginx (see /etc/nginx/sites-enabled/).
408
382
 
409
383
  ${upstreams.join("\n")}
410
384
 
@@ -412,6 +386,70 @@ limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
412
386
  ${serverBlocks.join("\n")}
413
387
  `;
414
388
  }
389
+
390
+ // src/templates/host-nginx.ts
391
+ function generateHostNginxConf(config) {
392
+ const domain = config.platform.domain;
393
+ const port = config.nginx.hostPort;
394
+ const subdomains = [
395
+ "iam",
396
+ "iam-console",
397
+ "api"
398
+ ];
399
+ if (config.services.launcher) subdomains.push("launcher");
400
+ if (config.services.organizationManager) subdomains.push("organization-manager");
401
+ if (config.services.platformManager) subdomains.push("platform-manager");
402
+ if (config.services.sampleCrm) subdomains.push("sample-crm");
403
+ const allServerNames = subdomains.map((s) => `${s}.${domain}`).join(" ");
404
+ const proxyHeaders = `
405
+ proxy_set_header Host $host;
406
+ proxy_set_header X-Real-IP $remote_addr;
407
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
408
+ proxy_set_header X-Forwarded-Proto $scheme;
409
+ proxy_set_header X-Forwarded-Host $host;
410
+ proxy_http_version 1.1;
411
+ proxy_set_header Upgrade $http_upgrade;
412
+ proxy_set_header Connection "upgrade";`;
413
+ return `# Habeetat Platform - Host Nginx Configuration
414
+ # Auto-generated by @habeetat/cli for domain: ${domain}
415
+ # This file should be placed in /etc/nginx/sites-available/habeetat-${sanitize(domain)}
416
+ # and symlinked to /etc/nginx/sites-enabled/
417
+
418
+ # HTTP \u2192 HTTPS redirect
419
+ server {
420
+ listen 80;
421
+ server_name ${allServerNames};
422
+
423
+ location /.well-known/acme-challenge/ {
424
+ root /var/www/certbot;
425
+ }
426
+
427
+ location / {
428
+ return 301 https://$host$request_uri;
429
+ }
430
+ }
431
+
432
+ # HTTPS \u2014 proxy all Habeetat subdomains to the container nginx
433
+ server {
434
+ listen 443 ssl;
435
+ server_name ${allServerNames};
436
+
437
+ ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
438
+ ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
439
+ include /etc/letsencrypt/options-ssl-nginx.conf;
440
+ ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
441
+
442
+ client_max_body_size 50M;
443
+
444
+ location / {
445
+ proxy_pass http://127.0.0.1:${port};${proxyHeaders}
446
+ }
447
+ }
448
+ `;
449
+ }
450
+ function sanitize(domain) {
451
+ return domain.replace(/[^a-zA-Z0-9.-]/g, "-");
452
+ }
415
453
  function randomHex(bytes) {
416
454
  return crypto__default.default.randomBytes(bytes).toString("hex");
417
455
  }
@@ -574,6 +612,7 @@ function saveConfig(config, projectDir) {
574
612
 
575
613
  exports.COMPOSE_FILE = COMPOSE_FILE;
576
614
  exports.CONFIG_FILE = CONFIG_FILE;
615
+ exports.DEFAULT_PORTS = DEFAULT_PORTS;
577
616
  exports.DOCKER_REGISTRY = DOCKER_REGISTRY;
578
617
  exports.ENV_FILE = ENV_FILE;
579
618
  exports.IMAGES = IMAGES;
@@ -583,6 +622,7 @@ exports.checkPrerequisites = checkPrerequisites;
583
622
  exports.findProjectRoot = findProjectRoot;
584
623
  exports.generateDockerCompose = generateDockerCompose;
585
624
  exports.generateEnvFile = generateEnvFile;
625
+ exports.generateHostNginxConf = generateHostNginxConf;
586
626
  exports.generateNginxConf = generateNginxConf;
587
627
  exports.generateSecrets = generateSecrets;
588
628
  exports.loadConfig = loadConfig;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/templates/docker-compose.ts","../src/templates/nginx.ts","../src/utils/crypto.ts","../src/templates/env.ts","../src/utils/logger.ts","../src/utils/docker.ts","../src/utils/config.ts"],"names":["crypto","chalk","execaCommand","path","fs"],"mappings":"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","file":"index.js","sourcesContent":["export const CONFIG_FILE = 'habeetat.json';\nexport const ENV_FILE = '.env';\nexport const COMPOSE_FILE = 'docker-compose.yml';\n\nexport const DOCKER_REGISTRY = 'docker.io/capriisland';\n\nexport const IMAGES = {\n backend: 'capriisland/habeetat-backend',\n launcher: 'capriisland/habeetat-launcher',\n orgManager: 'capriisland/habeetat-org-manager',\n platformManager: 'capriisland/habeetat-platform-manager',\n sampleCrm: 'capriisland/habeetat-sample-crm',\n logtoConfig: 'capriisland/habeetat-logto-config',\n} as const;\n\nexport const THIRD_PARTY_IMAGES = {\n postgres: 'postgres:15-alpine',\n logto: 'svhd/logto:1.33',\n nginx: 'nginx:1.25-alpine',\n certbot: 'certbot/certbot',\n} as const;\n\nexport const DEFAULT_PORTS = {\n http: 80,\n https: 443,\n} as const;\n\nexport const SERVICES = [\n 'logto-db',\n 'platform-db',\n 'logto-core',\n 'backend',\n 'launcher',\n 'organization-manager',\n 'platform-manager',\n 'sample-crm',\n 'nginx',\n] as const;\n\nexport type ServiceName = (typeof SERVICES)[number];\n","import type { HabeetatConfig } from '../types.js';\nimport { THIRD_PARTY_IMAGES } from '../constants.js';\n\nexport function generateDockerCompose(config: HabeetatConfig): string {\n const tag = config.docker.imageTag;\n const registry = config.docker.registry;\n\n const services: Record<string, unknown> = {\n 'logto-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${LOGTO_DB_USER}',\n POSTGRES_PASSWORD: '${LOGTO_DB_PASSWORD}',\n POSTGRES_DB: '${LOGTO_DB_NAME}',\n },\n volumes: ['logto-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${LOGTO_DB_USER} -d ${LOGTO_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'platform-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${PLATFORM_DB_USER}',\n POSTGRES_PASSWORD: '${PLATFORM_DB_PASSWORD}',\n POSTGRES_DB: '${PLATFORM_DB_NAME}',\n },\n volumes: ['platform-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${PLATFORM_DB_USER} -d ${PLATFORM_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'logto-core': {\n image: THIRD_PARTY_IMAGES.logto,\n entrypoint: ['sh', '-c'],\n command: ['npm run cli -- db seed -- --swe || true\\nnpm run start'],\n depends_on: {\n 'logto-db': { condition: 'service_healthy' },\n },\n environment: {\n DB_URL: 'postgres://${LOGTO_DB_USER}:${LOGTO_DB_PASSWORD}@logto-db:5432/${LOGTO_DB_NAME}',\n ENDPOINT: '${LOGTO_ENDPOINT}',\n ADMIN_ENDPOINT: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_CONSOLE_URL: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_PORT: '3002',\n TRUST_PROXY_HEADER: '1',\n COOKIE_KEYS: '${ENCRYPTION_KEY}',\n ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n CORS_ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n ADMIN_CONSOLE_ALLOWED_ORIGINS: '${LOGTO_ADMIN_ENDPOINT}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'wget -q --spider http://localhost:3001/oidc/.well-known/openid-configuration || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '90s',\n },\n },\n\n backend: {\n image: `${registry}/habeetat-backend:${tag}`,\n depends_on: {\n 'logto-core': { condition: 'service_healthy' },\n 'platform-db': { condition: 'service_healthy' },\n },\n environment: {\n NODE_ENV: 'production',\n DATABASE_URL: 'postgres://${PLATFORM_DB_USER}:${PLATFORM_DB_PASSWORD}@platform-db:5432/${PLATFORM_DB_NAME}',\n IAM_ISSUER_URL: '${LOGTO_ENDPOINT}/oidc',\n IAM_JWKS_URL: 'http://logto-core:3001',\n IAM_AUDIENCE: '${IAM_AUDIENCE}',\n LOGTO_ENDPOINT: 'http://logto-core:3001',\n LOGTO_EXTERNAL_ENDPOINT: '${LOGTO_ENDPOINT}',\n SDK_API_RESOURCE: '${IAM_AUDIENCE}',\n LOGTO_M2M_APP_ID: 'nhp-m2m-config',\n LOGTO_M2M_APP_SECRET: '${LOGTO_M2M_APP_SECRET}',\n ENCRYPTION_KEY: '${ENCRYPTION_KEY}',\n LAUNCHER_URL: '${LAUNCHER_URL}',\n CORS_ORIGINS: '${CORS_ORIGINS}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD', 'curl', '-f', 'http://localhost:3001/platform/status'],\n interval: '30s',\n timeout: '10s',\n retries: 3,\n start_period: '60s',\n },\n },\n };\n\n if (config.services.launcher) {\n services['launcher'] = {\n image: `${registry}/habeetat-launcher:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_IAM_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_IAM_AUDIENCE: '${IAM_AUDIENCE}',\n VITE_IAM_APP_ID: 'nhp-launcher',\n VITE_APP_BASE_URL: '${LAUNCHER_URL}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.organizationManager) {\n services['organization-manager'] = {\n image: `${registry}/habeetat-org-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-org-manager',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${ORG_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.platformManager) {\n services['platform-manager'] = {\n image: `${registry}/habeetat-platform-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-plat-mgr',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${PLATFORM_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.sampleCrm) {\n services['sample-crm'] = {\n image: `${registry}/habeetat-sample-crm:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n VITE_APP_BASE_URL: '${SAMPLE_CRM_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n // Nginx reverse proxy\n const nginxDependsOn = ['logto-core', 'backend'];\n if (config.services.launcher) nginxDependsOn.push('launcher');\n if (config.services.organizationManager) nginxDependsOn.push('organization-manager');\n if (config.services.platformManager) nginxDependsOn.push('platform-manager');\n if (config.services.sampleCrm) nginxDependsOn.push('sample-crm');\n\n const nginxVolumes = ['./nginx/platform.conf:/etc/nginx/conf.d/default.conf:ro'];\n const nginxPorts = ['80:80'];\n\n if (config.platform.protocol === 'https') {\n nginxVolumes.push('./certbot/conf:/etc/letsencrypt:ro');\n nginxVolumes.push('./certbot/www:/var/www/certbot:ro');\n nginxPorts.push('443:443');\n }\n\n services['nginx'] = {\n image: THIRD_PARTY_IMAGES.nginx,\n depends_on: nginxDependsOn,\n volumes: nginxVolumes,\n ports: nginxPorts,\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n command: `/bin/sh -c 'while :; do sleep 6h & wait $\\${!}; nginx -s reload; done & nginx -g \"daemon off;\"'`,\n };\n\n if (config.platform.protocol === 'https') {\n services['certbot'] = {\n image: THIRD_PARTY_IMAGES.certbot,\n volumes: [\n './certbot/conf:/etc/letsencrypt',\n './certbot/www:/var/www/certbot',\n ],\n entrypoint: `/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $\\${!}; done;'`,\n networks: ['habeetat-network'],\n };\n }\n\n const compose = {\n name: 'habeetat',\n services,\n volumes: {\n 'logto-db-data': null,\n 'platform-db-data': null,\n },\n networks: {\n 'habeetat-network': {\n driver: 'bridge',\n },\n },\n };\n\n return toYaml(compose);\n}\n\n// Minimal YAML serializer — avoids adding a dependency for simple structure\nfunction toYaml(obj: unknown, indent = 0): string {\n const pad = ' '.repeat(indent);\n\n if (obj === null || obj === undefined) return '';\n if (typeof obj === 'string') {\n if (obj.includes('\\n') || obj.includes(\"'\") || obj.includes('\"') || obj.includes(':') || obj.includes('#') || obj.includes('{') || obj.includes('}') || obj.includes('$')) {\n return `'${obj.replace(/'/g, \"''\")}'`;\n }\n return obj;\n }\n if (typeof obj === 'number' || typeof obj === 'boolean') return String(obj);\n\n if (Array.isArray(obj)) {\n if (obj.length === 0) return '[]';\n // Check if all items are scalars\n const allScalar = obj.every(\n (item) => typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean',\n );\n if (allScalar) {\n return obj\n .map((item) => `\\n${pad}- ${toYaml(item, indent + 2)}`)\n .join('');\n }\n return obj\n .map((item) => {\n const val = toYaml(item, indent + 2);\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n // Object inside array — inline the first key after the dash\n const lines = val.split('\\n').filter((l) => l.trim());\n if (lines.length > 0) {\n const first = lines[0].trimStart();\n const rest = lines.slice(1).map((l) => `${pad} ${l.trimStart()}`).join('\\n');\n return `\\n${pad}- ${first}${rest ? '\\n' + rest : ''}`;\n }\n }\n return `\\n${pad}- ${val}`;\n })\n .join('');\n }\n\n if (typeof obj === 'object') {\n const entries = Object.entries(obj as Record<string, unknown>);\n if (entries.length === 0) return '{}';\n return entries\n .map(([key, value]) => {\n if (value === null || value === undefined) return `${pad}${key}:`;\n if (typeof value === 'object' && !Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:\\n${nested}`;\n }\n if (Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:${nested}`;\n }\n return `${pad}${key}: ${toYaml(value, indent)}`;\n })\n .join('\\n');\n }\n\n return String(obj);\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n const ssl = config.platform.protocol === 'https';\n\n const upstreams = [\n 'upstream logto { server logto-core:3001; }',\n 'upstream logto_admin { server logto-core:3002; }',\n 'upstream api { server backend:3001; }',\n ];\n\n if (config.services.launcher) upstreams.push('upstream launcher { server launcher:80; }');\n if (config.services.organizationManager) upstreams.push('upstream organization-manager { server organization-manager:80; }');\n if (config.services.platformManager) upstreams.push('upstream platform-manager { server platform-manager:80; }');\n if (config.services.sampleCrm) upstreams.push('upstream sample-crm { server sample-crm:80; }');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;`;\n\n const sslBlock = ssl\n ? `\n ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;\n ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;\n include /etc/letsencrypt/options-ssl-nginx.conf;\n ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;`\n : '';\n\n const listenDirective = ssl ? 'listen 443 ssl' : 'listen 80';\n\n const serverBlocks: string[] = [];\n\n // HTTP → HTTPS redirect (only if SSL)\n if (ssl) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name ${domain} *.${domain};\n location /.well-known/acme-challenge/ { root /var/www/certbot; }\n location / { return 301 https://$host$request_uri; }\n}`);\n }\n\n // Logto IAM\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name iam.${domain};${sslBlock}\n location / {\n proxy_pass http://logto;${proxyHeaders}\n }\n}`);\n\n // Logto Admin Console\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name iam-console.${domain};${sslBlock}\n location / {\n proxy_pass http://logto_admin;${proxyHeaders}\n }\n}`);\n\n // Backend API\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name api.${domain};${sslBlock}\n location / {\n limit_req zone=api_limit burst=20 nodelay;\n proxy_pass http://api;${proxyHeaders}\n }\n}`);\n\n // Launcher\n if (config.services.launcher) {\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name launcher.${domain};${sslBlock}\n location / {\n proxy_pass http://launcher;${proxyHeaders}\n }\n}`);\n }\n\n // Organization Manager\n if (config.services.organizationManager) {\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name organization-manager.${domain};${sslBlock}\n location / {\n proxy_pass http://organization-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Platform Manager\n if (config.services.platformManager) {\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name platform-manager.${domain};${sslBlock}\n location / {\n proxy_pass http://platform-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Sample CRM\n if (config.services.sampleCrm) {\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name sample-crm.${domain};${sslBlock}\n location / {\n proxy_pass http://sample-crm;${proxyHeaders}\n }\n}`);\n }\n\n return `# Habeetat Platform - Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n\n${upstreams.join('\\n')}\n\nlimit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;\n${serverBlocks.join('\\n')}\n`;\n}\n","import crypto from 'node:crypto';\n\nexport function randomHex(bytes: number): string {\n return crypto.randomBytes(bytes).toString('hex');\n}\n\nexport function generateSecrets() {\n return {\n logtoDbPassword: randomHex(16),\n platformDbPassword: randomHex(16),\n encryptionKey: randomHex(32),\n logtoM2mAppSecret: randomHex(32),\n };\n}\n","import type { CreateOptions } from '../types.js';\nimport { generateSecrets } from '../utils/crypto.js';\n\nexport function generateEnvFile(opts: CreateOptions): string {\n const protocol = opts.ssl ? 'https' : 'http';\n const domain = opts.domain;\n const secrets = generateSecrets();\n\n return `# Habeetat Platform - Environment Configuration\n# Generated by @habeetat/cli on ${new Date().toISOString()}\n\n# ============================================\n# Domain Configuration\n# ============================================\nDOMAIN=${domain}\nPROTOCOL=${protocol}\n\n# ============================================\n# Service URLs (External - Browser-facing)\n# ============================================\nLOGTO_ENDPOINT=${protocol}://iam.${domain}\nLOGTO_ADMIN_ENDPOINT=${protocol}://iam-console.${domain}\nLAUNCHER_URL=${protocol}://launcher.${domain}\nORG_MANAGER_URL=${protocol}://organization-manager.${domain}\nPLATFORM_MANAGER_URL=${protocol}://platform-manager.${domain}\nSAMPLE_CRM_URL=${protocol}://sample-crm.${domain}\nBACKEND_API_URL=${protocol}://api.${domain}\nCORS_ORIGINS=${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain},${protocol}://sample-crm.${domain}\n\n# ============================================\n# Database Configuration\n# ============================================\nLOGTO_DB_USER=logto\nLOGTO_DB_PASSWORD=${secrets.logtoDbPassword}\nLOGTO_DB_NAME=logto\n\nPLATFORM_DB_USER=habeetat\nPLATFORM_DB_PASSWORD=${secrets.platformDbPassword}\nPLATFORM_DB_NAME=habeetat_platform\n\n# ============================================\n# Logto IAM Configuration\n# ============================================\nLOGTO_ADMIN_USERNAME=${opts.adminEmail}\nLOGTO_ADMIN_PASSWORD=${opts.adminPassword}\n\nIAM_ISSUER_URL=${protocol}://iam.${domain}/oidc\nIAM_AUDIENCE=${protocol}://api.${domain}/api\nSDK_API_RESOURCE=${protocol}://api.${domain}/api\n\nLOGTO_M2M_APP_ID=nhp-m2m-config\nLOGTO_M2M_APP_SECRET=${secrets.logtoM2mAppSecret}\n\n# ============================================\n# Platform Configuration\n# ============================================\nPLATFORM_ADMIN_EMAIL=${opts.adminEmail}\nPLATFORM_ADMIN_PASSWORD=${opts.adminPassword}\nORGANIZATION_NAME=${opts.organizationName}\n\n# ============================================\n# Security\n# ============================================\nENCRYPTION_KEY=${secrets.encryptionKey}\n\n# ============================================\n# CORS Configuration\n# ============================================\nALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\nCORS_ALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\n`;\n}\n","import chalk from 'chalk';\n\nconst prefix = chalk.cyan('[habeetat]');\n\nexport const logger = {\n info: (msg: string) => console.log(`${prefix} ${msg}`),\n success: (msg: string) => console.log(`${prefix} ${chalk.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(`${prefix} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${prefix} ${chalk.red('✗')} ${msg}`),\n phase: (msg: string) => {\n console.log('');\n console.log(chalk.cyan('═'.repeat(56)));\n console.log(chalk.cyan(` ${msg}`));\n console.log(chalk.cyan('═'.repeat(56)));\n console.log('');\n },\n banner: () => {\n console.log('');\n console.log(chalk.cyan('╔══════════════════════════════════════════════╗'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('║ Habeetat Platform CLI ║'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('╚══════════════════════════════════════════════╝'));\n console.log('');\n },\n};\n","import { execaCommand } from 'execa';\nimport { logger } from './logger.js';\n\nexport async function checkDocker(): Promise<boolean> {\n try {\n const { stdout } = await execaCommand('docker --version');\n const match = stdout.match(/Docker version (\\d+)/);\n if (match && parseInt(match[1], 10) >= 20) {\n return true;\n }\n logger.error(`Docker >= 20.0 required. Found: ${stdout.trim()}`);\n return false;\n } catch {\n logger.error('Docker is not installed or not in PATH');\n logger.info('Install Docker: https://docs.docker.com/get-docker/');\n return false;\n }\n}\n\nexport async function checkDockerCompose(): Promise<boolean> {\n try {\n await execaCommand('docker compose version');\n return true;\n } catch {\n logger.error('Docker Compose V2 is not available');\n logger.info('Docker Compose V2 is included with Docker Desktop');\n return false;\n }\n}\n\nexport async function checkPrerequisites(): Promise<boolean> {\n const docker = await checkDocker();\n const compose = await checkDockerCompose();\n return docker && compose;\n}\n\nexport interface ComposeExecOptions {\n cwd: string;\n composeFile?: string;\n silent?: boolean;\n}\n\nexport async function composeUp(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} up -d`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeDown(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composePs(opts: ComposeExecOptions): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(`docker compose -f ${file} ps`, {\n cwd: opts.cwd,\n });\n return stdout;\n}\n\nexport async function composeLogs(\n opts: ComposeExecOptions & { service?: string; follow?: boolean; tail?: number },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const parts = ['docker', 'compose', '-f', file, 'logs'];\n if (opts.follow) parts.push('-f');\n if (opts.tail) parts.push('--tail', String(opts.tail));\n if (opts.service) parts.push(opts.service);\n\n await execaCommand(parts.join(' '), {\n cwd: opts.cwd,\n stdio: 'inherit',\n });\n}\n\nexport async function composeRestart(\n opts: ComposeExecOptions & { service?: string },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const cmd = opts.service\n ? `docker compose -f ${file} restart ${opts.service}`\n : `docker compose -f ${file} restart`;\n\n await execaCommand(cmd, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeExec(\n opts: ComposeExecOptions & { service: string; command: string },\n): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(\n `docker compose -f ${file} exec -T ${opts.service} ${opts.command}`,\n { cwd: opts.cwd },\n );\n return stdout;\n}\n\nexport async function dockerPull(image: string): Promise<void> {\n await execaCommand(`docker pull ${image}`, { stdio: 'inherit' });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE } from '../constants.js';\nimport type { HabeetatConfig } from '../types.js';\n\nexport function findProjectRoot(startDir: string = process.cwd()): string | null {\n let dir = startDir;\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, CONFIG_FILE))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nexport function loadConfig(projectDir?: string): HabeetatConfig {\n const dir = projectDir || findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n const configPath = path.join(dir, CONFIG_FILE);\n const raw = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as HabeetatConfig;\n}\n\nexport function saveConfig(config: HabeetatConfig, projectDir: string): void {\n const configPath = path.join(projectDir, CONFIG_FILE);\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function getProjectDir(): string {\n const dir = findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n return dir;\n}\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/templates/docker-compose.ts","../src/templates/nginx.ts","../src/templates/host-nginx.ts","../src/utils/crypto.ts","../src/templates/env.ts","../src/utils/logger.ts","../src/utils/docker.ts","../src/utils/config.ts"],"names":["crypto","chalk","execaCommand","path","fs"],"mappings":"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","file":"index.js","sourcesContent":["export const CONFIG_FILE = 'habeetat.json';\nexport const ENV_FILE = '.env';\nexport const COMPOSE_FILE = 'docker-compose.yml';\n\nexport const DOCKER_REGISTRY = 'docker.io/capriisland';\n\nexport const IMAGES = {\n backend: 'capriisland/habeetat-backend',\n launcher: 'capriisland/habeetat-launcher',\n orgManager: 'capriisland/habeetat-org-manager',\n platformManager: 'capriisland/habeetat-platform-manager',\n sampleCrm: 'capriisland/habeetat-sample-crm',\n logtoConfig: 'capriisland/habeetat-logto-config',\n} as const;\n\nexport const THIRD_PARTY_IMAGES = {\n postgres: 'postgres:15-alpine',\n logto: 'svhd/logto:1.33',\n nginx: 'nginx:1.25-alpine',\n certbot: 'certbot/certbot',\n} as const;\n\nexport const DEFAULT_PORTS = {\n http: 80,\n https: 443,\n hostNginx: 8080,\n} as const;\n\nexport const SERVICES = [\n 'logto-db',\n 'platform-db',\n 'logto-core',\n 'backend',\n 'launcher',\n 'organization-manager',\n 'platform-manager',\n 'sample-crm',\n 'nginx',\n] as const;\n\nexport type ServiceName = (typeof SERVICES)[number];\n","import type { HabeetatConfig } from '../types.js';\nimport { THIRD_PARTY_IMAGES } from '../constants.js';\n\nexport function generateDockerCompose(config: HabeetatConfig): string {\n const tag = config.docker.imageTag;\n const registry = config.docker.registry;\n\n const services: Record<string, unknown> = {\n 'logto-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${LOGTO_DB_USER}',\n POSTGRES_PASSWORD: '${LOGTO_DB_PASSWORD}',\n POSTGRES_DB: '${LOGTO_DB_NAME}',\n },\n volumes: ['logto-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${LOGTO_DB_USER} -d ${LOGTO_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'platform-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${PLATFORM_DB_USER}',\n POSTGRES_PASSWORD: '${PLATFORM_DB_PASSWORD}',\n POSTGRES_DB: '${PLATFORM_DB_NAME}',\n },\n volumes: ['platform-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${PLATFORM_DB_USER} -d ${PLATFORM_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'logto-core': {\n image: THIRD_PARTY_IMAGES.logto,\n entrypoint: ['sh', '-c'],\n command: ['npm run cli -- db seed -- --swe && npm run start || npm run start'],\n depends_on: {\n 'logto-db': { condition: 'service_healthy' },\n },\n environment: {\n DB_URL: 'postgres://${LOGTO_DB_USER}:${LOGTO_DB_PASSWORD}@logto-db:5432/${LOGTO_DB_NAME}',\n ENDPOINT: '${LOGTO_ENDPOINT}',\n ADMIN_ENDPOINT: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_CONSOLE_URL: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_PORT: '3002',\n TRUST_PROXY_HEADER: '1',\n COOKIE_KEYS: '${ENCRYPTION_KEY}',\n ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n CORS_ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n ADMIN_CONSOLE_ALLOWED_ORIGINS: '${LOGTO_ADMIN_ENDPOINT}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'wget -q --spider http://localhost:3001/oidc/.well-known/openid-configuration || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '90s',\n },\n },\n\n backend: {\n image: `${registry}/habeetat-backend:${tag}`,\n depends_on: {\n 'logto-core': { condition: 'service_healthy' },\n 'platform-db': { condition: 'service_healthy' },\n },\n environment: {\n NODE_ENV: 'production',\n DATABASE_URL: 'postgres://${PLATFORM_DB_USER}:${PLATFORM_DB_PASSWORD}@platform-db:5432/${PLATFORM_DB_NAME}',\n IAM_ISSUER_URL: '${LOGTO_ENDPOINT}/oidc',\n IAM_JWKS_URL: 'http://logto-core:3001',\n IAM_AUDIENCE: '${IAM_AUDIENCE}',\n LOGTO_ENDPOINT: 'http://logto-core:3001',\n LOGTO_EXTERNAL_ENDPOINT: '${LOGTO_ENDPOINT}',\n SDK_API_RESOURCE: '${IAM_AUDIENCE}',\n LOGTO_M2M_APP_ID: 'nhp-m2m-config',\n LOGTO_M2M_APP_SECRET: '${LOGTO_M2M_APP_SECRET}',\n ENCRYPTION_KEY: '${ENCRYPTION_KEY}',\n LAUNCHER_URL: '${LAUNCHER_URL}',\n CORS_ORIGINS: '${CORS_ORIGINS}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD', 'curl', '-f', 'http://localhost:3001/platform/status'],\n interval: '30s',\n timeout: '10s',\n retries: 3,\n start_period: '60s',\n },\n },\n };\n\n if (config.services.launcher) {\n services['launcher'] = {\n image: `${registry}/habeetat-launcher:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_IAM_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_IAM_AUDIENCE: '${IAM_AUDIENCE}',\n VITE_IAM_APP_ID: 'nhp-launcher',\n VITE_APP_BASE_URL: '${LAUNCHER_URL}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.organizationManager) {\n services['organization-manager'] = {\n image: `${registry}/habeetat-org-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-org-manager',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${ORG_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.platformManager) {\n services['platform-manager'] = {\n image: `${registry}/habeetat-platform-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-plat-mgr',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${PLATFORM_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.sampleCrm) {\n services['sample-crm'] = {\n image: `${registry}/habeetat-sample-crm:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n VITE_APP_BASE_URL: '${SAMPLE_CRM_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n // Nginx reverse proxy (internal routing only — SSL handled by host nginx)\n const nginxDependsOn = ['logto-core', 'backend'];\n if (config.services.launcher) nginxDependsOn.push('launcher');\n if (config.services.organizationManager) nginxDependsOn.push('organization-manager');\n if (config.services.platformManager) nginxDependsOn.push('platform-manager');\n if (config.services.sampleCrm) nginxDependsOn.push('sample-crm');\n\n const hostPort = config.nginx.hostPort;\n\n services['nginx'] = {\n image: THIRD_PARTY_IMAGES.nginx,\n depends_on: nginxDependsOn,\n volumes: ['./nginx/platform.conf:/etc/nginx/conf.d/default.conf:ro'],\n ports: [`127.0.0.1:${hostPort}:80`],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n command: `/bin/sh -c 'while :; do sleep 6h & wait $\\${!}; nginx -s reload; done & nginx -g \"daemon off;\"'`,\n };\n\n const compose = {\n name: 'habeetat',\n services,\n volumes: {\n 'logto-db-data': null,\n 'platform-db-data': null,\n },\n networks: {\n 'habeetat-network': {\n driver: 'bridge',\n },\n },\n };\n\n return toYaml(compose);\n}\n\n// Minimal YAML serializer — avoids adding a dependency for simple structure\nfunction toYaml(obj: unknown, indent = 0): string {\n const pad = ' '.repeat(indent);\n\n if (obj === null || obj === undefined) return '';\n if (typeof obj === 'string') {\n if (obj.includes('\\n') || obj.includes(\"'\") || obj.includes('\"') || obj.includes(':') || obj.includes('#') || obj.includes('{') || obj.includes('}') || obj.includes('$')) {\n return `'${obj.replace(/'/g, \"''\")}'`;\n }\n return obj;\n }\n if (typeof obj === 'number' || typeof obj === 'boolean') return String(obj);\n\n if (Array.isArray(obj)) {\n if (obj.length === 0) return '[]';\n // Check if all items are scalars\n const allScalar = obj.every(\n (item) => typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean',\n );\n if (allScalar) {\n return obj\n .map((item) => `\\n${pad}- ${toYaml(item, indent + 2)}`)\n .join('');\n }\n return obj\n .map((item) => {\n const val = toYaml(item, indent + 2);\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n // Object inside array — inline the first key after the dash\n const lines = val.split('\\n').filter((l) => l.trim());\n if (lines.length > 0) {\n const first = lines[0].trimStart();\n const rest = lines.slice(1).map((l) => `${pad} ${l.trimStart()}`).join('\\n');\n return `\\n${pad}- ${first}${rest ? '\\n' + rest : ''}`;\n }\n }\n return `\\n${pad}- ${val}`;\n })\n .join('');\n }\n\n if (typeof obj === 'object') {\n const entries = Object.entries(obj as Record<string, unknown>);\n if (entries.length === 0) return '{}';\n return entries\n .map(([key, value]) => {\n if (value === null || value === undefined) return `${pad}${key}:`;\n if (typeof value === 'object' && !Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:\\n${nested}`;\n }\n if (Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:${nested}`;\n }\n return `${pad}${key}: ${toYaml(value, indent)}`;\n })\n .join('\\n');\n }\n\n return String(obj);\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n\n const upstreams = [\n 'upstream logto { server logto-core:3001; }',\n 'upstream logto_admin { server logto-core:3002; }',\n 'upstream api { server backend:3001; }',\n ];\n\n if (config.services.launcher) upstreams.push('upstream launcher { server launcher:80; }');\n if (config.services.organizationManager) upstreams.push('upstream organization-manager { server organization-manager:80; }');\n if (config.services.platformManager) upstreams.push('upstream platform-manager { server platform-manager:80; }');\n if (config.services.sampleCrm) upstreams.push('upstream sample-crm { server sample-crm:80; }');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;`;\n\n const serverBlocks: string[] = [];\n\n // Logto IAM\n serverBlocks.push(`\nserver {\n listen 80;\n server_name iam.${domain};\n location / {\n proxy_pass http://logto;${proxyHeaders}\n }\n}`);\n\n // Logto Admin Console\n serverBlocks.push(`\nserver {\n listen 80;\n server_name iam-console.${domain};\n location / {\n proxy_pass http://logto_admin;${proxyHeaders}\n }\n}`);\n\n // Backend API\n serverBlocks.push(`\nserver {\n listen 80;\n server_name api.${domain};\n location / {\n limit_req zone=api_limit burst=20 nodelay;\n proxy_pass http://api;${proxyHeaders}\n }\n}`);\n\n // Launcher\n if (config.services.launcher) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name launcher.${domain};\n location / {\n proxy_pass http://launcher;${proxyHeaders}\n }\n}`);\n }\n\n // Organization Manager\n if (config.services.organizationManager) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name organization-manager.${domain};\n location / {\n proxy_pass http://organization-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Platform Manager\n if (config.services.platformManager) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name platform-manager.${domain};\n location / {\n proxy_pass http://platform-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Sample CRM\n if (config.services.sampleCrm) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name sample-crm.${domain};\n location / {\n proxy_pass http://sample-crm;${proxyHeaders}\n }\n}`);\n }\n\n return `# Habeetat Platform - Container Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n# This handles internal routing between Docker services.\n# SSL is handled by the host nginx (see /etc/nginx/sites-enabled/).\n\n${upstreams.join('\\n')}\n\nlimit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;\n${serverBlocks.join('\\n')}\n`;\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateHostNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n const port = config.nginx.hostPort;\n\n const subdomains = [\n 'iam',\n 'iam-console',\n 'api',\n ];\n\n if (config.services.launcher) subdomains.push('launcher');\n if (config.services.organizationManager) subdomains.push('organization-manager');\n if (config.services.platformManager) subdomains.push('platform-manager');\n if (config.services.sampleCrm) subdomains.push('sample-crm');\n\n const allServerNames = subdomains.map((s) => `${s}.${domain}`).join(' ');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_set_header X-Forwarded-Host $host;\n proxy_http_version 1.1;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection \"upgrade\";`;\n\n return `# Habeetat Platform - Host Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n# This file should be placed in /etc/nginx/sites-available/habeetat-${sanitize(domain)}\n# and symlinked to /etc/nginx/sites-enabled/\n\n# HTTP → HTTPS redirect\nserver {\n listen 80;\n server_name ${allServerNames};\n\n location /.well-known/acme-challenge/ {\n root /var/www/certbot;\n }\n\n location / {\n return 301 https://$host$request_uri;\n }\n}\n\n# HTTPS — proxy all Habeetat subdomains to the container nginx\nserver {\n listen 443 ssl;\n server_name ${allServerNames};\n\n ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;\n ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;\n include /etc/letsencrypt/options-ssl-nginx.conf;\n ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;\n\n client_max_body_size 50M;\n\n location / {\n proxy_pass http://127.0.0.1:${port};${proxyHeaders}\n }\n}\n`;\n}\n\nfunction sanitize(domain: string): string {\n return domain.replace(/[^a-zA-Z0-9.-]/g, '-');\n}\n","import crypto from 'node:crypto';\n\nexport function randomHex(bytes: number): string {\n return crypto.randomBytes(bytes).toString('hex');\n}\n\nexport function generateSecrets() {\n return {\n logtoDbPassword: randomHex(16),\n platformDbPassword: randomHex(16),\n encryptionKey: randomHex(32),\n logtoM2mAppSecret: randomHex(32),\n };\n}\n","import type { CreateOptions } from '../types.js';\nimport { generateSecrets } from '../utils/crypto.js';\n\nexport function generateEnvFile(opts: CreateOptions): string {\n const protocol = opts.ssl ? 'https' : 'http';\n const domain = opts.domain;\n const secrets = generateSecrets();\n\n return `# Habeetat Platform - Environment Configuration\n# Generated by @habeetat/cli on ${new Date().toISOString()}\n\n# ============================================\n# Domain Configuration\n# ============================================\nDOMAIN=${domain}\nPROTOCOL=${protocol}\n\n# ============================================\n# Service URLs (External - Browser-facing)\n# ============================================\nLOGTO_ENDPOINT=${protocol}://iam.${domain}\nLOGTO_ADMIN_ENDPOINT=${protocol}://iam-console.${domain}\nLAUNCHER_URL=${protocol}://launcher.${domain}\nORG_MANAGER_URL=${protocol}://organization-manager.${domain}\nPLATFORM_MANAGER_URL=${protocol}://platform-manager.${domain}\nSAMPLE_CRM_URL=${protocol}://sample-crm.${domain}\nBACKEND_API_URL=${protocol}://api.${domain}\nCORS_ORIGINS=${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain},${protocol}://sample-crm.${domain}\n\n# ============================================\n# Database Configuration\n# ============================================\nLOGTO_DB_USER=logto\nLOGTO_DB_PASSWORD=${secrets.logtoDbPassword}\nLOGTO_DB_NAME=logto\n\nPLATFORM_DB_USER=habeetat\nPLATFORM_DB_PASSWORD=${secrets.platformDbPassword}\nPLATFORM_DB_NAME=habeetat_platform\n\n# ============================================\n# Logto IAM Configuration\n# ============================================\nLOGTO_ADMIN_USERNAME=${opts.adminEmail}\nLOGTO_ADMIN_PASSWORD=${opts.adminPassword}\n\nIAM_ISSUER_URL=${protocol}://iam.${domain}/oidc\nIAM_AUDIENCE=${protocol}://api.${domain}/api\nSDK_API_RESOURCE=${protocol}://api.${domain}/api\n\nLOGTO_M2M_APP_ID=nhp-m2m-config\nLOGTO_M2M_APP_SECRET=${secrets.logtoM2mAppSecret}\n\n# ============================================\n# Platform Configuration\n# ============================================\nPLATFORM_ADMIN_EMAIL=${opts.adminEmail}\nPLATFORM_ADMIN_PASSWORD=${opts.adminPassword}\nORGANIZATION_NAME=${opts.organizationName}\n\n# ============================================\n# Security\n# ============================================\nENCRYPTION_KEY=${secrets.encryptionKey}\n\n# ============================================\n# CORS Configuration\n# ============================================\nALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\nCORS_ALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\n`;\n}\n","import chalk from 'chalk';\n\nconst prefix = chalk.cyan('[habeetat]');\n\nexport const logger = {\n info: (msg: string) => console.log(`${prefix} ${msg}`),\n success: (msg: string) => console.log(`${prefix} ${chalk.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(`${prefix} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${prefix} ${chalk.red('✗')} ${msg}`),\n phase: (msg: string) => {\n console.log('');\n console.log(chalk.cyan('═'.repeat(56)));\n console.log(chalk.cyan(` ${msg}`));\n console.log(chalk.cyan('═'.repeat(56)));\n console.log('');\n },\n banner: () => {\n console.log('');\n console.log(chalk.cyan('╔══════════════════════════════════════════════╗'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('║ Habeetat Platform CLI ║'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('╚══════════════════════════════════════════════╝'));\n console.log('');\n },\n};\n","import { execaCommand } from 'execa';\nimport { logger } from './logger.js';\n\nexport async function checkDocker(): Promise<boolean> {\n try {\n const { stdout } = await execaCommand('docker --version');\n const match = stdout.match(/Docker version (\\d+)/);\n if (match && parseInt(match[1], 10) >= 20) {\n return true;\n }\n logger.error(`Docker >= 20.0 required. Found: ${stdout.trim()}`);\n return false;\n } catch {\n logger.error('Docker is not installed or not in PATH');\n logger.info('Install Docker: https://docs.docker.com/get-docker/');\n return false;\n }\n}\n\nexport async function checkDockerCompose(): Promise<boolean> {\n try {\n await execaCommand('docker compose version');\n return true;\n } catch {\n logger.error('Docker Compose V2 is not available');\n logger.info('Docker Compose V2 is included with Docker Desktop');\n return false;\n }\n}\n\nexport async function checkPrerequisites(): Promise<boolean> {\n const docker = await checkDocker();\n const compose = await checkDockerCompose();\n return docker && compose;\n}\n\nexport interface ComposeExecOptions {\n cwd: string;\n composeFile?: string;\n silent?: boolean;\n}\n\nexport async function composeUp(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} up -d`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeDown(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composePs(opts: ComposeExecOptions): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(`docker compose -f ${file} ps`, {\n cwd: opts.cwd,\n });\n return stdout;\n}\n\nexport async function composeLogs(\n opts: ComposeExecOptions & { service?: string; follow?: boolean; tail?: number },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const parts = ['docker', 'compose', '-f', file, 'logs'];\n if (opts.follow) parts.push('-f');\n if (opts.tail) parts.push('--tail', String(opts.tail));\n if (opts.service) parts.push(opts.service);\n\n await execaCommand(parts.join(' '), {\n cwd: opts.cwd,\n stdio: 'inherit',\n });\n}\n\nexport async function composeRestart(\n opts: ComposeExecOptions & { service?: string },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const cmd = opts.service\n ? `docker compose -f ${file} restart ${opts.service}`\n : `docker compose -f ${file} restart`;\n\n await execaCommand(cmd, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeExec(\n opts: ComposeExecOptions & { service: string; command: string },\n): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(\n `docker compose -f ${file} exec -T ${opts.service} ${opts.command}`,\n { cwd: opts.cwd },\n );\n return stdout;\n}\n\nexport async function dockerPull(image: string): Promise<void> {\n await execaCommand(`docker pull ${image}`, { stdio: 'inherit' });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE } from '../constants.js';\nimport type { HabeetatConfig } from '../types.js';\n\nexport function findProjectRoot(startDir: string = process.cwd()): string | null {\n let dir = startDir;\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, CONFIG_FILE))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nexport function loadConfig(projectDir?: string): HabeetatConfig {\n const dir = projectDir || findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n const configPath = path.join(dir, CONFIG_FILE);\n const raw = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as HabeetatConfig;\n}\n\nexport function saveConfig(config: HabeetatConfig, projectDir: string): void {\n const configPath = path.join(projectDir, CONFIG_FILE);\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function getProjectDir(): string {\n const dir = findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n return dir;\n}\n"]}
package/dist/index.mjs CHANGED
@@ -23,6 +23,11 @@ var THIRD_PARTY_IMAGES = {
23
23
  nginx: "nginx:1.25-alpine",
24
24
  certbot: "certbot/certbot"
25
25
  };
26
+ var DEFAULT_PORTS = {
27
+ http: 80,
28
+ https: 443,
29
+ hostNginx: 8080
30
+ };
26
31
  var SERVICES = [
27
32
  "logto-db",
28
33
  "platform-db",
@@ -77,7 +82,7 @@ function generateDockerCompose(config) {
77
82
  "logto-core": {
78
83
  image: THIRD_PARTY_IMAGES.logto,
79
84
  entrypoint: ["sh", "-c"],
80
- command: ["npm run cli -- db seed -- --swe || true\nnpm run start"],
85
+ command: ["npm run cli -- db seed -- --swe && npm run start || npm run start"],
81
86
  depends_on: {
82
87
  "logto-db": { condition: "service_healthy" }
83
88
  },
@@ -199,33 +204,16 @@ function generateDockerCompose(config) {
199
204
  if (config.services.organizationManager) nginxDependsOn.push("organization-manager");
200
205
  if (config.services.platformManager) nginxDependsOn.push("platform-manager");
201
206
  if (config.services.sampleCrm) nginxDependsOn.push("sample-crm");
202
- const nginxVolumes = ["./nginx/platform.conf:/etc/nginx/conf.d/default.conf:ro"];
203
- const nginxPorts = ["80:80"];
204
- if (config.platform.protocol === "https") {
205
- nginxVolumes.push("./certbot/conf:/etc/letsencrypt:ro");
206
- nginxVolumes.push("./certbot/www:/var/www/certbot:ro");
207
- nginxPorts.push("443:443");
208
- }
207
+ const hostPort = config.nginx.hostPort;
209
208
  services["nginx"] = {
210
209
  image: THIRD_PARTY_IMAGES.nginx,
211
210
  depends_on: nginxDependsOn,
212
- volumes: nginxVolumes,
213
- ports: nginxPorts,
211
+ volumes: ["./nginx/platform.conf:/etc/nginx/conf.d/default.conf:ro"],
212
+ ports: [`127.0.0.1:${hostPort}:80`],
214
213
  networks: ["habeetat-network"],
215
214
  restart: "unless-stopped",
216
215
  command: `/bin/sh -c 'while :; do sleep 6h & wait $\${!}; nginx -s reload; done & nginx -g "daemon off;"'`
217
216
  };
218
- if (config.platform.protocol === "https") {
219
- services["certbot"] = {
220
- image: THIRD_PARTY_IMAGES.certbot,
221
- volumes: [
222
- "./certbot/conf:/etc/letsencrypt",
223
- "./certbot/www:/var/www/certbot"
224
- ],
225
- entrypoint: `/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $\${!}; done;'`,
226
- networks: ["habeetat-network"]
227
- };
228
- }
229
217
  const compose = {
230
218
  name: "habeetat",
231
219
  services,
@@ -298,7 +286,6 @@ ${nested}`;
298
286
  // src/templates/nginx.ts
299
287
  function generateNginxConf(config) {
300
288
  const domain = config.platform.domain;
301
- const ssl = config.platform.protocol === "https";
302
289
  const upstreams = [
303
290
  "upstream logto { server logto-core:3001; }",
304
291
  "upstream logto_admin { server logto-core:3002; }",
@@ -313,42 +300,27 @@ function generateNginxConf(config) {
313
300
  proxy_set_header X-Real-IP $remote_addr;
314
301
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
315
302
  proxy_set_header X-Forwarded-Proto $scheme;`;
316
- const sslBlock = ssl ? `
317
- ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
318
- ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
319
- include /etc/letsencrypt/options-ssl-nginx.conf;
320
- ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;` : "";
321
- const listenDirective = ssl ? "listen 443 ssl" : "listen 80";
322
303
  const serverBlocks = [];
323
- if (ssl) {
324
- serverBlocks.push(`
325
- server {
326
- listen 80;
327
- server_name ${domain} *.${domain};
328
- location /.well-known/acme-challenge/ { root /var/www/certbot; }
329
- location / { return 301 https://$host$request_uri; }
330
- }`);
331
- }
332
304
  serverBlocks.push(`
333
305
  server {
334
- ${listenDirective};
335
- server_name iam.${domain};${sslBlock}
306
+ listen 80;
307
+ server_name iam.${domain};
336
308
  location / {
337
309
  proxy_pass http://logto;${proxyHeaders}
338
310
  }
339
311
  }`);
340
312
  serverBlocks.push(`
341
313
  server {
342
- ${listenDirective};
343
- server_name iam-console.${domain};${sslBlock}
314
+ listen 80;
315
+ server_name iam-console.${domain};
344
316
  location / {
345
317
  proxy_pass http://logto_admin;${proxyHeaders}
346
318
  }
347
319
  }`);
348
320
  serverBlocks.push(`
349
321
  server {
350
- ${listenDirective};
351
- server_name api.${domain};${sslBlock}
322
+ listen 80;
323
+ server_name api.${domain};
352
324
  location / {
353
325
  limit_req zone=api_limit burst=20 nodelay;
354
326
  proxy_pass http://api;${proxyHeaders}
@@ -357,8 +329,8 @@ server {
357
329
  if (config.services.launcher) {
358
330
  serverBlocks.push(`
359
331
  server {
360
- ${listenDirective};
361
- server_name launcher.${domain};${sslBlock}
332
+ listen 80;
333
+ server_name launcher.${domain};
362
334
  location / {
363
335
  proxy_pass http://launcher;${proxyHeaders}
364
336
  }
@@ -367,8 +339,8 @@ server {
367
339
  if (config.services.organizationManager) {
368
340
  serverBlocks.push(`
369
341
  server {
370
- ${listenDirective};
371
- server_name organization-manager.${domain};${sslBlock}
342
+ listen 80;
343
+ server_name organization-manager.${domain};
372
344
  location / {
373
345
  proxy_pass http://organization-manager;${proxyHeaders}
374
346
  }
@@ -377,8 +349,8 @@ server {
377
349
  if (config.services.platformManager) {
378
350
  serverBlocks.push(`
379
351
  server {
380
- ${listenDirective};
381
- server_name platform-manager.${domain};${sslBlock}
352
+ listen 80;
353
+ server_name platform-manager.${domain};
382
354
  location / {
383
355
  proxy_pass http://platform-manager;${proxyHeaders}
384
356
  }
@@ -387,15 +359,17 @@ server {
387
359
  if (config.services.sampleCrm) {
388
360
  serverBlocks.push(`
389
361
  server {
390
- ${listenDirective};
391
- server_name sample-crm.${domain};${sslBlock}
362
+ listen 80;
363
+ server_name sample-crm.${domain};
392
364
  location / {
393
365
  proxy_pass http://sample-crm;${proxyHeaders}
394
366
  }
395
367
  }`);
396
368
  }
397
- return `# Habeetat Platform - Nginx Configuration
369
+ return `# Habeetat Platform - Container Nginx Configuration
398
370
  # Auto-generated by @habeetat/cli for domain: ${domain}
371
+ # This handles internal routing between Docker services.
372
+ # SSL is handled by the host nginx (see /etc/nginx/sites-enabled/).
399
373
 
400
374
  ${upstreams.join("\n")}
401
375
 
@@ -403,6 +377,70 @@ limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
403
377
  ${serverBlocks.join("\n")}
404
378
  `;
405
379
  }
380
+
381
+ // src/templates/host-nginx.ts
382
+ function generateHostNginxConf(config) {
383
+ const domain = config.platform.domain;
384
+ const port = config.nginx.hostPort;
385
+ const subdomains = [
386
+ "iam",
387
+ "iam-console",
388
+ "api"
389
+ ];
390
+ if (config.services.launcher) subdomains.push("launcher");
391
+ if (config.services.organizationManager) subdomains.push("organization-manager");
392
+ if (config.services.platformManager) subdomains.push("platform-manager");
393
+ if (config.services.sampleCrm) subdomains.push("sample-crm");
394
+ const allServerNames = subdomains.map((s) => `${s}.${domain}`).join(" ");
395
+ const proxyHeaders = `
396
+ proxy_set_header Host $host;
397
+ proxy_set_header X-Real-IP $remote_addr;
398
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
399
+ proxy_set_header X-Forwarded-Proto $scheme;
400
+ proxy_set_header X-Forwarded-Host $host;
401
+ proxy_http_version 1.1;
402
+ proxy_set_header Upgrade $http_upgrade;
403
+ proxy_set_header Connection "upgrade";`;
404
+ return `# Habeetat Platform - Host Nginx Configuration
405
+ # Auto-generated by @habeetat/cli for domain: ${domain}
406
+ # This file should be placed in /etc/nginx/sites-available/habeetat-${sanitize(domain)}
407
+ # and symlinked to /etc/nginx/sites-enabled/
408
+
409
+ # HTTP \u2192 HTTPS redirect
410
+ server {
411
+ listen 80;
412
+ server_name ${allServerNames};
413
+
414
+ location /.well-known/acme-challenge/ {
415
+ root /var/www/certbot;
416
+ }
417
+
418
+ location / {
419
+ return 301 https://$host$request_uri;
420
+ }
421
+ }
422
+
423
+ # HTTPS \u2014 proxy all Habeetat subdomains to the container nginx
424
+ server {
425
+ listen 443 ssl;
426
+ server_name ${allServerNames};
427
+
428
+ ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
429
+ ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
430
+ include /etc/letsencrypt/options-ssl-nginx.conf;
431
+ ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
432
+
433
+ client_max_body_size 50M;
434
+
435
+ location / {
436
+ proxy_pass http://127.0.0.1:${port};${proxyHeaders}
437
+ }
438
+ }
439
+ `;
440
+ }
441
+ function sanitize(domain) {
442
+ return domain.replace(/[^a-zA-Z0-9.-]/g, "-");
443
+ }
406
444
  function randomHex(bytes) {
407
445
  return crypto.randomBytes(bytes).toString("hex");
408
446
  }
@@ -563,6 +601,6 @@ function saveConfig(config, projectDir) {
563
601
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
564
602
  }
565
603
 
566
- export { COMPOSE_FILE, CONFIG_FILE, DOCKER_REGISTRY, ENV_FILE, IMAGES, SERVICES, THIRD_PARTY_IMAGES, checkPrerequisites, findProjectRoot, generateDockerCompose, generateEnvFile, generateNginxConf, generateSecrets, loadConfig, logger, saveConfig };
604
+ export { COMPOSE_FILE, CONFIG_FILE, DEFAULT_PORTS, DOCKER_REGISTRY, ENV_FILE, IMAGES, SERVICES, THIRD_PARTY_IMAGES, checkPrerequisites, findProjectRoot, generateDockerCompose, generateEnvFile, generateHostNginxConf, generateNginxConf, generateSecrets, loadConfig, logger, saveConfig };
567
605
  //# sourceMappingURL=index.mjs.map
568
606
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/templates/docker-compose.ts","../src/templates/nginx.ts","../src/utils/crypto.ts","../src/templates/env.ts","../src/utils/logger.ts","../src/utils/docker.ts","../src/utils/config.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export const CONFIG_FILE = 'habeetat.json';\nexport const ENV_FILE = '.env';\nexport const COMPOSE_FILE = 'docker-compose.yml';\n\nexport const DOCKER_REGISTRY = 'docker.io/capriisland';\n\nexport const IMAGES = {\n backend: 'capriisland/habeetat-backend',\n launcher: 'capriisland/habeetat-launcher',\n orgManager: 'capriisland/habeetat-org-manager',\n platformManager: 'capriisland/habeetat-platform-manager',\n sampleCrm: 'capriisland/habeetat-sample-crm',\n logtoConfig: 'capriisland/habeetat-logto-config',\n} as const;\n\nexport const THIRD_PARTY_IMAGES = {\n postgres: 'postgres:15-alpine',\n logto: 'svhd/logto:1.33',\n nginx: 'nginx:1.25-alpine',\n certbot: 'certbot/certbot',\n} as const;\n\nexport const DEFAULT_PORTS = {\n http: 80,\n https: 443,\n} as const;\n\nexport const SERVICES = [\n 'logto-db',\n 'platform-db',\n 'logto-core',\n 'backend',\n 'launcher',\n 'organization-manager',\n 'platform-manager',\n 'sample-crm',\n 'nginx',\n] as const;\n\nexport type ServiceName = (typeof SERVICES)[number];\n","import type { HabeetatConfig } from '../types.js';\nimport { THIRD_PARTY_IMAGES } from '../constants.js';\n\nexport function generateDockerCompose(config: HabeetatConfig): string {\n const tag = config.docker.imageTag;\n const registry = config.docker.registry;\n\n const services: Record<string, unknown> = {\n 'logto-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${LOGTO_DB_USER}',\n POSTGRES_PASSWORD: '${LOGTO_DB_PASSWORD}',\n POSTGRES_DB: '${LOGTO_DB_NAME}',\n },\n volumes: ['logto-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${LOGTO_DB_USER} -d ${LOGTO_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'platform-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${PLATFORM_DB_USER}',\n POSTGRES_PASSWORD: '${PLATFORM_DB_PASSWORD}',\n POSTGRES_DB: '${PLATFORM_DB_NAME}',\n },\n volumes: ['platform-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${PLATFORM_DB_USER} -d ${PLATFORM_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'logto-core': {\n image: THIRD_PARTY_IMAGES.logto,\n entrypoint: ['sh', '-c'],\n command: ['npm run cli -- db seed -- --swe || true\\nnpm run start'],\n depends_on: {\n 'logto-db': { condition: 'service_healthy' },\n },\n environment: {\n DB_URL: 'postgres://${LOGTO_DB_USER}:${LOGTO_DB_PASSWORD}@logto-db:5432/${LOGTO_DB_NAME}',\n ENDPOINT: '${LOGTO_ENDPOINT}',\n ADMIN_ENDPOINT: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_CONSOLE_URL: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_PORT: '3002',\n TRUST_PROXY_HEADER: '1',\n COOKIE_KEYS: '${ENCRYPTION_KEY}',\n ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n CORS_ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n ADMIN_CONSOLE_ALLOWED_ORIGINS: '${LOGTO_ADMIN_ENDPOINT}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'wget -q --spider http://localhost:3001/oidc/.well-known/openid-configuration || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '90s',\n },\n },\n\n backend: {\n image: `${registry}/habeetat-backend:${tag}`,\n depends_on: {\n 'logto-core': { condition: 'service_healthy' },\n 'platform-db': { condition: 'service_healthy' },\n },\n environment: {\n NODE_ENV: 'production',\n DATABASE_URL: 'postgres://${PLATFORM_DB_USER}:${PLATFORM_DB_PASSWORD}@platform-db:5432/${PLATFORM_DB_NAME}',\n IAM_ISSUER_URL: '${LOGTO_ENDPOINT}/oidc',\n IAM_JWKS_URL: 'http://logto-core:3001',\n IAM_AUDIENCE: '${IAM_AUDIENCE}',\n LOGTO_ENDPOINT: 'http://logto-core:3001',\n LOGTO_EXTERNAL_ENDPOINT: '${LOGTO_ENDPOINT}',\n SDK_API_RESOURCE: '${IAM_AUDIENCE}',\n LOGTO_M2M_APP_ID: 'nhp-m2m-config',\n LOGTO_M2M_APP_SECRET: '${LOGTO_M2M_APP_SECRET}',\n ENCRYPTION_KEY: '${ENCRYPTION_KEY}',\n LAUNCHER_URL: '${LAUNCHER_URL}',\n CORS_ORIGINS: '${CORS_ORIGINS}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD', 'curl', '-f', 'http://localhost:3001/platform/status'],\n interval: '30s',\n timeout: '10s',\n retries: 3,\n start_period: '60s',\n },\n },\n };\n\n if (config.services.launcher) {\n services['launcher'] = {\n image: `${registry}/habeetat-launcher:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_IAM_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_IAM_AUDIENCE: '${IAM_AUDIENCE}',\n VITE_IAM_APP_ID: 'nhp-launcher',\n VITE_APP_BASE_URL: '${LAUNCHER_URL}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.organizationManager) {\n services['organization-manager'] = {\n image: `${registry}/habeetat-org-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-org-manager',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${ORG_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.platformManager) {\n services['platform-manager'] = {\n image: `${registry}/habeetat-platform-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-plat-mgr',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${PLATFORM_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.sampleCrm) {\n services['sample-crm'] = {\n image: `${registry}/habeetat-sample-crm:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n VITE_APP_BASE_URL: '${SAMPLE_CRM_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n // Nginx reverse proxy\n const nginxDependsOn = ['logto-core', 'backend'];\n if (config.services.launcher) nginxDependsOn.push('launcher');\n if (config.services.organizationManager) nginxDependsOn.push('organization-manager');\n if (config.services.platformManager) nginxDependsOn.push('platform-manager');\n if (config.services.sampleCrm) nginxDependsOn.push('sample-crm');\n\n const nginxVolumes = ['./nginx/platform.conf:/etc/nginx/conf.d/default.conf:ro'];\n const nginxPorts = ['80:80'];\n\n if (config.platform.protocol === 'https') {\n nginxVolumes.push('./certbot/conf:/etc/letsencrypt:ro');\n nginxVolumes.push('./certbot/www:/var/www/certbot:ro');\n nginxPorts.push('443:443');\n }\n\n services['nginx'] = {\n image: THIRD_PARTY_IMAGES.nginx,\n depends_on: nginxDependsOn,\n volumes: nginxVolumes,\n ports: nginxPorts,\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n command: `/bin/sh -c 'while :; do sleep 6h & wait $\\${!}; nginx -s reload; done & nginx -g \"daemon off;\"'`,\n };\n\n if (config.platform.protocol === 'https') {\n services['certbot'] = {\n image: THIRD_PARTY_IMAGES.certbot,\n volumes: [\n './certbot/conf:/etc/letsencrypt',\n './certbot/www:/var/www/certbot',\n ],\n entrypoint: `/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $\\${!}; done;'`,\n networks: ['habeetat-network'],\n };\n }\n\n const compose = {\n name: 'habeetat',\n services,\n volumes: {\n 'logto-db-data': null,\n 'platform-db-data': null,\n },\n networks: {\n 'habeetat-network': {\n driver: 'bridge',\n },\n },\n };\n\n return toYaml(compose);\n}\n\n// Minimal YAML serializer — avoids adding a dependency for simple structure\nfunction toYaml(obj: unknown, indent = 0): string {\n const pad = ' '.repeat(indent);\n\n if (obj === null || obj === undefined) return '';\n if (typeof obj === 'string') {\n if (obj.includes('\\n') || obj.includes(\"'\") || obj.includes('\"') || obj.includes(':') || obj.includes('#') || obj.includes('{') || obj.includes('}') || obj.includes('$')) {\n return `'${obj.replace(/'/g, \"''\")}'`;\n }\n return obj;\n }\n if (typeof obj === 'number' || typeof obj === 'boolean') return String(obj);\n\n if (Array.isArray(obj)) {\n if (obj.length === 0) return '[]';\n // Check if all items are scalars\n const allScalar = obj.every(\n (item) => typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean',\n );\n if (allScalar) {\n return obj\n .map((item) => `\\n${pad}- ${toYaml(item, indent + 2)}`)\n .join('');\n }\n return obj\n .map((item) => {\n const val = toYaml(item, indent + 2);\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n // Object inside array — inline the first key after the dash\n const lines = val.split('\\n').filter((l) => l.trim());\n if (lines.length > 0) {\n const first = lines[0].trimStart();\n const rest = lines.slice(1).map((l) => `${pad} ${l.trimStart()}`).join('\\n');\n return `\\n${pad}- ${first}${rest ? '\\n' + rest : ''}`;\n }\n }\n return `\\n${pad}- ${val}`;\n })\n .join('');\n }\n\n if (typeof obj === 'object') {\n const entries = Object.entries(obj as Record<string, unknown>);\n if (entries.length === 0) return '{}';\n return entries\n .map(([key, value]) => {\n if (value === null || value === undefined) return `${pad}${key}:`;\n if (typeof value === 'object' && !Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:\\n${nested}`;\n }\n if (Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:${nested}`;\n }\n return `${pad}${key}: ${toYaml(value, indent)}`;\n })\n .join('\\n');\n }\n\n return String(obj);\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n const ssl = config.platform.protocol === 'https';\n\n const upstreams = [\n 'upstream logto { server logto-core:3001; }',\n 'upstream logto_admin { server logto-core:3002; }',\n 'upstream api { server backend:3001; }',\n ];\n\n if (config.services.launcher) upstreams.push('upstream launcher { server launcher:80; }');\n if (config.services.organizationManager) upstreams.push('upstream organization-manager { server organization-manager:80; }');\n if (config.services.platformManager) upstreams.push('upstream platform-manager { server platform-manager:80; }');\n if (config.services.sampleCrm) upstreams.push('upstream sample-crm { server sample-crm:80; }');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;`;\n\n const sslBlock = ssl\n ? `\n ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;\n ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;\n include /etc/letsencrypt/options-ssl-nginx.conf;\n ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;`\n : '';\n\n const listenDirective = ssl ? 'listen 443 ssl' : 'listen 80';\n\n const serverBlocks: string[] = [];\n\n // HTTP → HTTPS redirect (only if SSL)\n if (ssl) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name ${domain} *.${domain};\n location /.well-known/acme-challenge/ { root /var/www/certbot; }\n location / { return 301 https://$host$request_uri; }\n}`);\n }\n\n // Logto IAM\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name iam.${domain};${sslBlock}\n location / {\n proxy_pass http://logto;${proxyHeaders}\n }\n}`);\n\n // Logto Admin Console\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name iam-console.${domain};${sslBlock}\n location / {\n proxy_pass http://logto_admin;${proxyHeaders}\n }\n}`);\n\n // Backend API\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name api.${domain};${sslBlock}\n location / {\n limit_req zone=api_limit burst=20 nodelay;\n proxy_pass http://api;${proxyHeaders}\n }\n}`);\n\n // Launcher\n if (config.services.launcher) {\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name launcher.${domain};${sslBlock}\n location / {\n proxy_pass http://launcher;${proxyHeaders}\n }\n}`);\n }\n\n // Organization Manager\n if (config.services.organizationManager) {\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name organization-manager.${domain};${sslBlock}\n location / {\n proxy_pass http://organization-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Platform Manager\n if (config.services.platformManager) {\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name platform-manager.${domain};${sslBlock}\n location / {\n proxy_pass http://platform-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Sample CRM\n if (config.services.sampleCrm) {\n serverBlocks.push(`\nserver {\n ${listenDirective};\n server_name sample-crm.${domain};${sslBlock}\n location / {\n proxy_pass http://sample-crm;${proxyHeaders}\n }\n}`);\n }\n\n return `# Habeetat Platform - Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n\n${upstreams.join('\\n')}\n\nlimit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;\n${serverBlocks.join('\\n')}\n`;\n}\n","import crypto from 'node:crypto';\n\nexport function randomHex(bytes: number): string {\n return crypto.randomBytes(bytes).toString('hex');\n}\n\nexport function generateSecrets() {\n return {\n logtoDbPassword: randomHex(16),\n platformDbPassword: randomHex(16),\n encryptionKey: randomHex(32),\n logtoM2mAppSecret: randomHex(32),\n };\n}\n","import type { CreateOptions } from '../types.js';\nimport { generateSecrets } from '../utils/crypto.js';\n\nexport function generateEnvFile(opts: CreateOptions): string {\n const protocol = opts.ssl ? 'https' : 'http';\n const domain = opts.domain;\n const secrets = generateSecrets();\n\n return `# Habeetat Platform - Environment Configuration\n# Generated by @habeetat/cli on ${new Date().toISOString()}\n\n# ============================================\n# Domain Configuration\n# ============================================\nDOMAIN=${domain}\nPROTOCOL=${protocol}\n\n# ============================================\n# Service URLs (External - Browser-facing)\n# ============================================\nLOGTO_ENDPOINT=${protocol}://iam.${domain}\nLOGTO_ADMIN_ENDPOINT=${protocol}://iam-console.${domain}\nLAUNCHER_URL=${protocol}://launcher.${domain}\nORG_MANAGER_URL=${protocol}://organization-manager.${domain}\nPLATFORM_MANAGER_URL=${protocol}://platform-manager.${domain}\nSAMPLE_CRM_URL=${protocol}://sample-crm.${domain}\nBACKEND_API_URL=${protocol}://api.${domain}\nCORS_ORIGINS=${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain},${protocol}://sample-crm.${domain}\n\n# ============================================\n# Database Configuration\n# ============================================\nLOGTO_DB_USER=logto\nLOGTO_DB_PASSWORD=${secrets.logtoDbPassword}\nLOGTO_DB_NAME=logto\n\nPLATFORM_DB_USER=habeetat\nPLATFORM_DB_PASSWORD=${secrets.platformDbPassword}\nPLATFORM_DB_NAME=habeetat_platform\n\n# ============================================\n# Logto IAM Configuration\n# ============================================\nLOGTO_ADMIN_USERNAME=${opts.adminEmail}\nLOGTO_ADMIN_PASSWORD=${opts.adminPassword}\n\nIAM_ISSUER_URL=${protocol}://iam.${domain}/oidc\nIAM_AUDIENCE=${protocol}://api.${domain}/api\nSDK_API_RESOURCE=${protocol}://api.${domain}/api\n\nLOGTO_M2M_APP_ID=nhp-m2m-config\nLOGTO_M2M_APP_SECRET=${secrets.logtoM2mAppSecret}\n\n# ============================================\n# Platform Configuration\n# ============================================\nPLATFORM_ADMIN_EMAIL=${opts.adminEmail}\nPLATFORM_ADMIN_PASSWORD=${opts.adminPassword}\nORGANIZATION_NAME=${opts.organizationName}\n\n# ============================================\n# Security\n# ============================================\nENCRYPTION_KEY=${secrets.encryptionKey}\n\n# ============================================\n# CORS Configuration\n# ============================================\nALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\nCORS_ALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\n`;\n}\n","import chalk from 'chalk';\n\nconst prefix = chalk.cyan('[habeetat]');\n\nexport const logger = {\n info: (msg: string) => console.log(`${prefix} ${msg}`),\n success: (msg: string) => console.log(`${prefix} ${chalk.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(`${prefix} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${prefix} ${chalk.red('✗')} ${msg}`),\n phase: (msg: string) => {\n console.log('');\n console.log(chalk.cyan('═'.repeat(56)));\n console.log(chalk.cyan(` ${msg}`));\n console.log(chalk.cyan('═'.repeat(56)));\n console.log('');\n },\n banner: () => {\n console.log('');\n console.log(chalk.cyan('╔══════════════════════════════════════════════╗'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('║ Habeetat Platform CLI ║'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('╚══════════════════════════════════════════════╝'));\n console.log('');\n },\n};\n","import { execaCommand } from 'execa';\nimport { logger } from './logger.js';\n\nexport async function checkDocker(): Promise<boolean> {\n try {\n const { stdout } = await execaCommand('docker --version');\n const match = stdout.match(/Docker version (\\d+)/);\n if (match && parseInt(match[1], 10) >= 20) {\n return true;\n }\n logger.error(`Docker >= 20.0 required. Found: ${stdout.trim()}`);\n return false;\n } catch {\n logger.error('Docker is not installed or not in PATH');\n logger.info('Install Docker: https://docs.docker.com/get-docker/');\n return false;\n }\n}\n\nexport async function checkDockerCompose(): Promise<boolean> {\n try {\n await execaCommand('docker compose version');\n return true;\n } catch {\n logger.error('Docker Compose V2 is not available');\n logger.info('Docker Compose V2 is included with Docker Desktop');\n return false;\n }\n}\n\nexport async function checkPrerequisites(): Promise<boolean> {\n const docker = await checkDocker();\n const compose = await checkDockerCompose();\n return docker && compose;\n}\n\nexport interface ComposeExecOptions {\n cwd: string;\n composeFile?: string;\n silent?: boolean;\n}\n\nexport async function composeUp(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} up -d`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeDown(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composePs(opts: ComposeExecOptions): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(`docker compose -f ${file} ps`, {\n cwd: opts.cwd,\n });\n return stdout;\n}\n\nexport async function composeLogs(\n opts: ComposeExecOptions & { service?: string; follow?: boolean; tail?: number },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const parts = ['docker', 'compose', '-f', file, 'logs'];\n if (opts.follow) parts.push('-f');\n if (opts.tail) parts.push('--tail', String(opts.tail));\n if (opts.service) parts.push(opts.service);\n\n await execaCommand(parts.join(' '), {\n cwd: opts.cwd,\n stdio: 'inherit',\n });\n}\n\nexport async function composeRestart(\n opts: ComposeExecOptions & { service?: string },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const cmd = opts.service\n ? `docker compose -f ${file} restart ${opts.service}`\n : `docker compose -f ${file} restart`;\n\n await execaCommand(cmd, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeExec(\n opts: ComposeExecOptions & { service: string; command: string },\n): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(\n `docker compose -f ${file} exec -T ${opts.service} ${opts.command}`,\n { cwd: opts.cwd },\n );\n return stdout;\n}\n\nexport async function dockerPull(image: string): Promise<void> {\n await execaCommand(`docker pull ${image}`, { stdio: 'inherit' });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE } from '../constants.js';\nimport type { HabeetatConfig } from '../types.js';\n\nexport function findProjectRoot(startDir: string = process.cwd()): string | null {\n let dir = startDir;\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, CONFIG_FILE))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nexport function loadConfig(projectDir?: string): HabeetatConfig {\n const dir = projectDir || findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n const configPath = path.join(dir, CONFIG_FILE);\n const raw = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as HabeetatConfig;\n}\n\nexport function saveConfig(config: HabeetatConfig, projectDir: string): void {\n const configPath = path.join(projectDir, CONFIG_FILE);\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function getProjectDir(): string {\n const dir = findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n return dir;\n}\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/templates/docker-compose.ts","../src/templates/nginx.ts","../src/templates/host-nginx.ts","../src/utils/crypto.ts","../src/templates/env.ts","../src/utils/logger.ts","../src/utils/docker.ts","../src/utils/config.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export const CONFIG_FILE = 'habeetat.json';\nexport const ENV_FILE = '.env';\nexport const COMPOSE_FILE = 'docker-compose.yml';\n\nexport const DOCKER_REGISTRY = 'docker.io/capriisland';\n\nexport const IMAGES = {\n backend: 'capriisland/habeetat-backend',\n launcher: 'capriisland/habeetat-launcher',\n orgManager: 'capriisland/habeetat-org-manager',\n platformManager: 'capriisland/habeetat-platform-manager',\n sampleCrm: 'capriisland/habeetat-sample-crm',\n logtoConfig: 'capriisland/habeetat-logto-config',\n} as const;\n\nexport const THIRD_PARTY_IMAGES = {\n postgres: 'postgres:15-alpine',\n logto: 'svhd/logto:1.33',\n nginx: 'nginx:1.25-alpine',\n certbot: 'certbot/certbot',\n} as const;\n\nexport const DEFAULT_PORTS = {\n http: 80,\n https: 443,\n hostNginx: 8080,\n} as const;\n\nexport const SERVICES = [\n 'logto-db',\n 'platform-db',\n 'logto-core',\n 'backend',\n 'launcher',\n 'organization-manager',\n 'platform-manager',\n 'sample-crm',\n 'nginx',\n] as const;\n\nexport type ServiceName = (typeof SERVICES)[number];\n","import type { HabeetatConfig } from '../types.js';\nimport { THIRD_PARTY_IMAGES } from '../constants.js';\n\nexport function generateDockerCompose(config: HabeetatConfig): string {\n const tag = config.docker.imageTag;\n const registry = config.docker.registry;\n\n const services: Record<string, unknown> = {\n 'logto-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${LOGTO_DB_USER}',\n POSTGRES_PASSWORD: '${LOGTO_DB_PASSWORD}',\n POSTGRES_DB: '${LOGTO_DB_NAME}',\n },\n volumes: ['logto-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${LOGTO_DB_USER} -d ${LOGTO_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'platform-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${PLATFORM_DB_USER}',\n POSTGRES_PASSWORD: '${PLATFORM_DB_PASSWORD}',\n POSTGRES_DB: '${PLATFORM_DB_NAME}',\n },\n volumes: ['platform-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${PLATFORM_DB_USER} -d ${PLATFORM_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'logto-core': {\n image: THIRD_PARTY_IMAGES.logto,\n entrypoint: ['sh', '-c'],\n command: ['npm run cli -- db seed -- --swe && npm run start || npm run start'],\n depends_on: {\n 'logto-db': { condition: 'service_healthy' },\n },\n environment: {\n DB_URL: 'postgres://${LOGTO_DB_USER}:${LOGTO_DB_PASSWORD}@logto-db:5432/${LOGTO_DB_NAME}',\n ENDPOINT: '${LOGTO_ENDPOINT}',\n ADMIN_ENDPOINT: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_CONSOLE_URL: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_PORT: '3002',\n TRUST_PROXY_HEADER: '1',\n COOKIE_KEYS: '${ENCRYPTION_KEY}',\n ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n CORS_ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n ADMIN_CONSOLE_ALLOWED_ORIGINS: '${LOGTO_ADMIN_ENDPOINT}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'wget -q --spider http://localhost:3001/oidc/.well-known/openid-configuration || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '90s',\n },\n },\n\n backend: {\n image: `${registry}/habeetat-backend:${tag}`,\n depends_on: {\n 'logto-core': { condition: 'service_healthy' },\n 'platform-db': { condition: 'service_healthy' },\n },\n environment: {\n NODE_ENV: 'production',\n DATABASE_URL: 'postgres://${PLATFORM_DB_USER}:${PLATFORM_DB_PASSWORD}@platform-db:5432/${PLATFORM_DB_NAME}',\n IAM_ISSUER_URL: '${LOGTO_ENDPOINT}/oidc',\n IAM_JWKS_URL: 'http://logto-core:3001',\n IAM_AUDIENCE: '${IAM_AUDIENCE}',\n LOGTO_ENDPOINT: 'http://logto-core:3001',\n LOGTO_EXTERNAL_ENDPOINT: '${LOGTO_ENDPOINT}',\n SDK_API_RESOURCE: '${IAM_AUDIENCE}',\n LOGTO_M2M_APP_ID: 'nhp-m2m-config',\n LOGTO_M2M_APP_SECRET: '${LOGTO_M2M_APP_SECRET}',\n ENCRYPTION_KEY: '${ENCRYPTION_KEY}',\n LAUNCHER_URL: '${LAUNCHER_URL}',\n CORS_ORIGINS: '${CORS_ORIGINS}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD', 'curl', '-f', 'http://localhost:3001/platform/status'],\n interval: '30s',\n timeout: '10s',\n retries: 3,\n start_period: '60s',\n },\n },\n };\n\n if (config.services.launcher) {\n services['launcher'] = {\n image: `${registry}/habeetat-launcher:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_IAM_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_IAM_AUDIENCE: '${IAM_AUDIENCE}',\n VITE_IAM_APP_ID: 'nhp-launcher',\n VITE_APP_BASE_URL: '${LAUNCHER_URL}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.organizationManager) {\n services['organization-manager'] = {\n image: `${registry}/habeetat-org-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-org-manager',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${ORG_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.platformManager) {\n services['platform-manager'] = {\n image: `${registry}/habeetat-platform-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-plat-mgr',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${PLATFORM_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.sampleCrm) {\n services['sample-crm'] = {\n image: `${registry}/habeetat-sample-crm:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n VITE_APP_BASE_URL: '${SAMPLE_CRM_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n // Nginx reverse proxy (internal routing only — SSL handled by host nginx)\n const nginxDependsOn = ['logto-core', 'backend'];\n if (config.services.launcher) nginxDependsOn.push('launcher');\n if (config.services.organizationManager) nginxDependsOn.push('organization-manager');\n if (config.services.platformManager) nginxDependsOn.push('platform-manager');\n if (config.services.sampleCrm) nginxDependsOn.push('sample-crm');\n\n const hostPort = config.nginx.hostPort;\n\n services['nginx'] = {\n image: THIRD_PARTY_IMAGES.nginx,\n depends_on: nginxDependsOn,\n volumes: ['./nginx/platform.conf:/etc/nginx/conf.d/default.conf:ro'],\n ports: [`127.0.0.1:${hostPort}:80`],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n command: `/bin/sh -c 'while :; do sleep 6h & wait $\\${!}; nginx -s reload; done & nginx -g \"daemon off;\"'`,\n };\n\n const compose = {\n name: 'habeetat',\n services,\n volumes: {\n 'logto-db-data': null,\n 'platform-db-data': null,\n },\n networks: {\n 'habeetat-network': {\n driver: 'bridge',\n },\n },\n };\n\n return toYaml(compose);\n}\n\n// Minimal YAML serializer — avoids adding a dependency for simple structure\nfunction toYaml(obj: unknown, indent = 0): string {\n const pad = ' '.repeat(indent);\n\n if (obj === null || obj === undefined) return '';\n if (typeof obj === 'string') {\n if (obj.includes('\\n') || obj.includes(\"'\") || obj.includes('\"') || obj.includes(':') || obj.includes('#') || obj.includes('{') || obj.includes('}') || obj.includes('$')) {\n return `'${obj.replace(/'/g, \"''\")}'`;\n }\n return obj;\n }\n if (typeof obj === 'number' || typeof obj === 'boolean') return String(obj);\n\n if (Array.isArray(obj)) {\n if (obj.length === 0) return '[]';\n // Check if all items are scalars\n const allScalar = obj.every(\n (item) => typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean',\n );\n if (allScalar) {\n return obj\n .map((item) => `\\n${pad}- ${toYaml(item, indent + 2)}`)\n .join('');\n }\n return obj\n .map((item) => {\n const val = toYaml(item, indent + 2);\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n // Object inside array — inline the first key after the dash\n const lines = val.split('\\n').filter((l) => l.trim());\n if (lines.length > 0) {\n const first = lines[0].trimStart();\n const rest = lines.slice(1).map((l) => `${pad} ${l.trimStart()}`).join('\\n');\n return `\\n${pad}- ${first}${rest ? '\\n' + rest : ''}`;\n }\n }\n return `\\n${pad}- ${val}`;\n })\n .join('');\n }\n\n if (typeof obj === 'object') {\n const entries = Object.entries(obj as Record<string, unknown>);\n if (entries.length === 0) return '{}';\n return entries\n .map(([key, value]) => {\n if (value === null || value === undefined) return `${pad}${key}:`;\n if (typeof value === 'object' && !Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:\\n${nested}`;\n }\n if (Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:${nested}`;\n }\n return `${pad}${key}: ${toYaml(value, indent)}`;\n })\n .join('\\n');\n }\n\n return String(obj);\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n\n const upstreams = [\n 'upstream logto { server logto-core:3001; }',\n 'upstream logto_admin { server logto-core:3002; }',\n 'upstream api { server backend:3001; }',\n ];\n\n if (config.services.launcher) upstreams.push('upstream launcher { server launcher:80; }');\n if (config.services.organizationManager) upstreams.push('upstream organization-manager { server organization-manager:80; }');\n if (config.services.platformManager) upstreams.push('upstream platform-manager { server platform-manager:80; }');\n if (config.services.sampleCrm) upstreams.push('upstream sample-crm { server sample-crm:80; }');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;`;\n\n const serverBlocks: string[] = [];\n\n // Logto IAM\n serverBlocks.push(`\nserver {\n listen 80;\n server_name iam.${domain};\n location / {\n proxy_pass http://logto;${proxyHeaders}\n }\n}`);\n\n // Logto Admin Console\n serverBlocks.push(`\nserver {\n listen 80;\n server_name iam-console.${domain};\n location / {\n proxy_pass http://logto_admin;${proxyHeaders}\n }\n}`);\n\n // Backend API\n serverBlocks.push(`\nserver {\n listen 80;\n server_name api.${domain};\n location / {\n limit_req zone=api_limit burst=20 nodelay;\n proxy_pass http://api;${proxyHeaders}\n }\n}`);\n\n // Launcher\n if (config.services.launcher) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name launcher.${domain};\n location / {\n proxy_pass http://launcher;${proxyHeaders}\n }\n}`);\n }\n\n // Organization Manager\n if (config.services.organizationManager) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name organization-manager.${domain};\n location / {\n proxy_pass http://organization-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Platform Manager\n if (config.services.platformManager) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name platform-manager.${domain};\n location / {\n proxy_pass http://platform-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Sample CRM\n if (config.services.sampleCrm) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name sample-crm.${domain};\n location / {\n proxy_pass http://sample-crm;${proxyHeaders}\n }\n}`);\n }\n\n return `# Habeetat Platform - Container Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n# This handles internal routing between Docker services.\n# SSL is handled by the host nginx (see /etc/nginx/sites-enabled/).\n\n${upstreams.join('\\n')}\n\nlimit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;\n${serverBlocks.join('\\n')}\n`;\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateHostNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n const port = config.nginx.hostPort;\n\n const subdomains = [\n 'iam',\n 'iam-console',\n 'api',\n ];\n\n if (config.services.launcher) subdomains.push('launcher');\n if (config.services.organizationManager) subdomains.push('organization-manager');\n if (config.services.platformManager) subdomains.push('platform-manager');\n if (config.services.sampleCrm) subdomains.push('sample-crm');\n\n const allServerNames = subdomains.map((s) => `${s}.${domain}`).join(' ');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_set_header X-Forwarded-Host $host;\n proxy_http_version 1.1;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection \"upgrade\";`;\n\n return `# Habeetat Platform - Host Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n# This file should be placed in /etc/nginx/sites-available/habeetat-${sanitize(domain)}\n# and symlinked to /etc/nginx/sites-enabled/\n\n# HTTP → HTTPS redirect\nserver {\n listen 80;\n server_name ${allServerNames};\n\n location /.well-known/acme-challenge/ {\n root /var/www/certbot;\n }\n\n location / {\n return 301 https://$host$request_uri;\n }\n}\n\n# HTTPS — proxy all Habeetat subdomains to the container nginx\nserver {\n listen 443 ssl;\n server_name ${allServerNames};\n\n ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;\n ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;\n include /etc/letsencrypt/options-ssl-nginx.conf;\n ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;\n\n client_max_body_size 50M;\n\n location / {\n proxy_pass http://127.0.0.1:${port};${proxyHeaders}\n }\n}\n`;\n}\n\nfunction sanitize(domain: string): string {\n return domain.replace(/[^a-zA-Z0-9.-]/g, '-');\n}\n","import crypto from 'node:crypto';\n\nexport function randomHex(bytes: number): string {\n return crypto.randomBytes(bytes).toString('hex');\n}\n\nexport function generateSecrets() {\n return {\n logtoDbPassword: randomHex(16),\n platformDbPassword: randomHex(16),\n encryptionKey: randomHex(32),\n logtoM2mAppSecret: randomHex(32),\n };\n}\n","import type { CreateOptions } from '../types.js';\nimport { generateSecrets } from '../utils/crypto.js';\n\nexport function generateEnvFile(opts: CreateOptions): string {\n const protocol = opts.ssl ? 'https' : 'http';\n const domain = opts.domain;\n const secrets = generateSecrets();\n\n return `# Habeetat Platform - Environment Configuration\n# Generated by @habeetat/cli on ${new Date().toISOString()}\n\n# ============================================\n# Domain Configuration\n# ============================================\nDOMAIN=${domain}\nPROTOCOL=${protocol}\n\n# ============================================\n# Service URLs (External - Browser-facing)\n# ============================================\nLOGTO_ENDPOINT=${protocol}://iam.${domain}\nLOGTO_ADMIN_ENDPOINT=${protocol}://iam-console.${domain}\nLAUNCHER_URL=${protocol}://launcher.${domain}\nORG_MANAGER_URL=${protocol}://organization-manager.${domain}\nPLATFORM_MANAGER_URL=${protocol}://platform-manager.${domain}\nSAMPLE_CRM_URL=${protocol}://sample-crm.${domain}\nBACKEND_API_URL=${protocol}://api.${domain}\nCORS_ORIGINS=${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain},${protocol}://sample-crm.${domain}\n\n# ============================================\n# Database Configuration\n# ============================================\nLOGTO_DB_USER=logto\nLOGTO_DB_PASSWORD=${secrets.logtoDbPassword}\nLOGTO_DB_NAME=logto\n\nPLATFORM_DB_USER=habeetat\nPLATFORM_DB_PASSWORD=${secrets.platformDbPassword}\nPLATFORM_DB_NAME=habeetat_platform\n\n# ============================================\n# Logto IAM Configuration\n# ============================================\nLOGTO_ADMIN_USERNAME=${opts.adminEmail}\nLOGTO_ADMIN_PASSWORD=${opts.adminPassword}\n\nIAM_ISSUER_URL=${protocol}://iam.${domain}/oidc\nIAM_AUDIENCE=${protocol}://api.${domain}/api\nSDK_API_RESOURCE=${protocol}://api.${domain}/api\n\nLOGTO_M2M_APP_ID=nhp-m2m-config\nLOGTO_M2M_APP_SECRET=${secrets.logtoM2mAppSecret}\n\n# ============================================\n# Platform Configuration\n# ============================================\nPLATFORM_ADMIN_EMAIL=${opts.adminEmail}\nPLATFORM_ADMIN_PASSWORD=${opts.adminPassword}\nORGANIZATION_NAME=${opts.organizationName}\n\n# ============================================\n# Security\n# ============================================\nENCRYPTION_KEY=${secrets.encryptionKey}\n\n# ============================================\n# CORS Configuration\n# ============================================\nALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\nCORS_ALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\n`;\n}\n","import chalk from 'chalk';\n\nconst prefix = chalk.cyan('[habeetat]');\n\nexport const logger = {\n info: (msg: string) => console.log(`${prefix} ${msg}`),\n success: (msg: string) => console.log(`${prefix} ${chalk.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(`${prefix} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${prefix} ${chalk.red('✗')} ${msg}`),\n phase: (msg: string) => {\n console.log('');\n console.log(chalk.cyan('═'.repeat(56)));\n console.log(chalk.cyan(` ${msg}`));\n console.log(chalk.cyan('═'.repeat(56)));\n console.log('');\n },\n banner: () => {\n console.log('');\n console.log(chalk.cyan('╔══════════════════════════════════════════════╗'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('║ Habeetat Platform CLI ║'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('╚══════════════════════════════════════════════╝'));\n console.log('');\n },\n};\n","import { execaCommand } from 'execa';\nimport { logger } from './logger.js';\n\nexport async function checkDocker(): Promise<boolean> {\n try {\n const { stdout } = await execaCommand('docker --version');\n const match = stdout.match(/Docker version (\\d+)/);\n if (match && parseInt(match[1], 10) >= 20) {\n return true;\n }\n logger.error(`Docker >= 20.0 required. Found: ${stdout.trim()}`);\n return false;\n } catch {\n logger.error('Docker is not installed or not in PATH');\n logger.info('Install Docker: https://docs.docker.com/get-docker/');\n return false;\n }\n}\n\nexport async function checkDockerCompose(): Promise<boolean> {\n try {\n await execaCommand('docker compose version');\n return true;\n } catch {\n logger.error('Docker Compose V2 is not available');\n logger.info('Docker Compose V2 is included with Docker Desktop');\n return false;\n }\n}\n\nexport async function checkPrerequisites(): Promise<boolean> {\n const docker = await checkDocker();\n const compose = await checkDockerCompose();\n return docker && compose;\n}\n\nexport interface ComposeExecOptions {\n cwd: string;\n composeFile?: string;\n silent?: boolean;\n}\n\nexport async function composeUp(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} up -d`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeDown(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composePs(opts: ComposeExecOptions): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(`docker compose -f ${file} ps`, {\n cwd: opts.cwd,\n });\n return stdout;\n}\n\nexport async function composeLogs(\n opts: ComposeExecOptions & { service?: string; follow?: boolean; tail?: number },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const parts = ['docker', 'compose', '-f', file, 'logs'];\n if (opts.follow) parts.push('-f');\n if (opts.tail) parts.push('--tail', String(opts.tail));\n if (opts.service) parts.push(opts.service);\n\n await execaCommand(parts.join(' '), {\n cwd: opts.cwd,\n stdio: 'inherit',\n });\n}\n\nexport async function composeRestart(\n opts: ComposeExecOptions & { service?: string },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const cmd = opts.service\n ? `docker compose -f ${file} restart ${opts.service}`\n : `docker compose -f ${file} restart`;\n\n await execaCommand(cmd, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeExec(\n opts: ComposeExecOptions & { service: string; command: string },\n): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(\n `docker compose -f ${file} exec -T ${opts.service} ${opts.command}`,\n { cwd: opts.cwd },\n );\n return stdout;\n}\n\nexport async function dockerPull(image: string): Promise<void> {\n await execaCommand(`docker pull ${image}`, { stdio: 'inherit' });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE } from '../constants.js';\nimport type { HabeetatConfig } from '../types.js';\n\nexport function findProjectRoot(startDir: string = process.cwd()): string | null {\n let dir = startDir;\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, CONFIG_FILE))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nexport function loadConfig(projectDir?: string): HabeetatConfig {\n const dir = projectDir || findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n const configPath = path.join(dir, CONFIG_FILE);\n const raw = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as HabeetatConfig;\n}\n\nexport function saveConfig(config: HabeetatConfig, projectDir: string): void {\n const configPath = path.join(projectDir, CONFIG_FILE);\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function getProjectDir(): string {\n const dir = findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n return dir;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@habeetat/cli",
3
- "version": "0.1.0-dev.20260323164114.3a5aac3",
3
+ "version": "0.1.0-dev.20260324154244.f7ef1fb",
4
4
  "description": "Habeetat Platform CLI — manage your platform instances",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",