@habeetat/cli 0.1.0-dev.20260325113236.a098d49 → 0.1.0-dev.20260325114836.5178446

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/index.js CHANGED
@@ -1028,14 +1028,16 @@ processors:
1028
1028
 
1029
1029
  exporters:
1030
1030
  clickhouselogsexporter:
1031
- dsn: tcp://clickhouse:9000/?database=signoz_logs&username=default
1031
+ dsn: tcp://clickhouse:9000/
1032
1032
  timeout: 10s
1033
+ docker_multi_node_cluster: false
1033
1034
  clickhousetraces:
1034
- dsn: tcp://clickhouse:9000/?database=signoz_traces&username=default
1035
- timeout: 10s
1035
+ datasource: tcp://clickhouse:9000/
1036
+ docker_multi_node_cluster: false
1036
1037
  clickhousemetricswrite:
1037
- dsn: tcp://clickhouse:9000/?database=signoz_metrics&username=default
1038
- timeout: 10s
1038
+ endpoint: tcp://clickhouse:9000/
1039
+ resource_to_telemetry_conversion:
1040
+ enabled: true
1039
1041
 
1040
1042
  service:
1041
1043
  pipelines:
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/templates/host-nginx.ts","../src/utils/crypto.ts","../src/templates/env.ts","../src/utils/logger.ts","../src/utils/docker.ts","../src/utils/config.ts","../src/templates/bootstrap-script.ts","../src/templates/otel-collector-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 clickhouse: 'clickhouse/clickhouse-server:24.1.2-alpine',\n signozOtelCollector: 'signoz/signoz-otel-collector:0.88.22',\n signozQuery: 'signoz/query-service:0.45.0',\n signozFrontend: 'signoz/frontend:0.45.0',\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 'clickhouse',\n 'otel-collector',\n 'signoz-query-service',\n 'signoz-frontend',\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 ...(config.services.signoz && {\n OTEL_COLLECTOR_ENDPOINT: '${OTEL_COLLECTOR_ENDPOINT}',\n }),\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 // SigNoz observability stack (ClickHouse + OTel Collector + Query Service + Frontend)\n if (config.services.signoz) {\n services['clickhouse'] = {\n image: THIRD_PARTY_IMAGES.clickhouse,\n volumes: [\n 'clickhouse-data:/var/lib/clickhouse',\n 'clickhouse-logs:/var/log/clickhouse-server',\n './signoz/clickhouse-config.xml:/etc/clickhouse-server/config.d/habeetat-listen.xml:ro',\n ],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'clickhouse-client --host=127.0.0.1 --query=\"SELECT 1\" || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '60s',\n },\n };\n\n services['otel-collector'] = {\n image: THIRD_PARTY_IMAGES.signozOtelCollector,\n command: ['--config=/etc/otel-collector-config.yaml'],\n depends_on: {\n clickhouse: { condition: 'service_healthy' },\n },\n volumes: ['./signoz/otel-collector-config.yaml:/etc/otel-collector-config.yaml:ro'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n\n services['signoz-query-service'] = {\n image: THIRD_PARTY_IMAGES.signozQuery,\n depends_on: {\n clickhouse: { condition: 'service_healthy' },\n 'otel-collector': { condition: 'service_started' },\n },\n volumes: ['signoz-data:/var/lib/signoz'],\n environment: {\n ClickHouseUrl: 'tcp://clickhouse:9000',\n STORAGE: 'clickhouse',\n GODEBUG: 'netdns=go',\n SIGNOZ_LOCAL_DB_PATH: '/var/lib/signoz/signoz.db',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'wget -O- http://localhost:8080/api/v1/health 2>&1 | grep -q \"status\" || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '60s',\n },\n };\n\n services['signoz-frontend'] = {\n image: THIRD_PARTY_IMAGES.signozFrontend,\n depends_on: {\n 'signoz-query-service': { condition: 'service_healthy' },\n },\n environment: {\n FRONTEND_API_URL: 'http://signoz-query-service:8080',\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 if (config.services.signoz) nginxDependsOn.push('signoz-frontend');\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 ...(config.services.signoz && {\n 'clickhouse-data': null,\n 'clickhouse-logs': null,\n 'signoz-data': null,\n }),\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 if (config.services.signoz) upstreams.push('upstream signoz_frontend { server signoz-frontend:3301; }');\n\n const proto = config.platform.protocol;\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 ${proto};`;\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 // SigNoz Dashboard\n if (config.services.signoz) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name logs.${domain};\n location / {\n proxy_pass http://signoz_frontend;${proxyHeaders}\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection \"upgrade\";\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 if (config.services.signoz) subdomains.push('logs');\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# SSL will be added automatically by certbot --nginx\n\nserver {\n listen 80;\n server_name ${allServerNames};\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 clickhousePassword: randomHex(16),\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# SigNoz / OpenTelemetry (Observability)\n# ============================================\nSIGNOZ_URL=${protocol}://logs.${domain}\nOTEL_COLLECTOR_ENDPOINT=http://otel-collector:4317\nCLICKHOUSE_PASSWORD=${secrets.clickhousePassword}\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 composeDestroy(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down -v --remove-orphans`, {\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","// Logto IAM bootstrap seed script — embedded for scaffolding\n// This is the content of scripts/nhp-seed-logto-bootstrap.mjs\n// It runs inside a temporary Node container on the Docker network\n\nexport function getBootstrapScript(): string {\n return `#!/usr/bin/env node\nimport crypto from 'node:crypto';\n\nimport { argon2i } from 'hash-wasm';\nimport { customAlphabet } from 'nanoid';\nimport { Pool } from 'pg';\n\nconst alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst shortId = customAlphabet(alphabet, 12);\nconst longId = customAlphabet(alphabet, 21);\n\nconst connectionString =\n process.env.NHP_LOGTO_DB_URL ?? 'postgres://logto:logto@localhost:5434/logto';\n\nconst pool = new Pool({ connectionString });\n\nconst log = (message) => console.log(\\`[NHP][iam-seed] \\${message}\\`);\nconst json = (value) => JSON.stringify(value ?? {});\n\nasync function hashPassword(password) {\n return argon2i({\n password,\n salt: crypto.randomBytes(16),\n iterations: 256,\n parallelism: 1,\n memorySize: 4096,\n hashLength: 32,\n outputType: 'encoded',\n });\n}\n\nasync function ensureOrganization({ tenantId, id, name, description, customData }) {\n const orgId = id ?? longId();\n const { rows } = await pool.query(\n \\`insert into organizations (tenant_id, id, name, description, custom_data)\n values ($1, $2, $3, $4, $5::jsonb)\n on conflict (id) do update\n set tenant_id = excluded.tenant_id,\n name = excluded.name,\n description = excluded.description,\n custom_data = excluded.custom_data\n returning id\\`,\n [tenantId, orgId, name, description ?? name, json(customData)]\n );\n return rows[0].id;\n}\n\nasync function ensureOrganizationMembership({ tenantId, organizationId, userId }) {\n await pool.query(\n \\`insert into organization_user_relations (tenant_id, organization_id, user_id)\n values ($1, $2, $3)\n on conflict (tenant_id, organization_id, user_id) do nothing\\`,\n [tenantId, organizationId, userId]\n );\n}\n\nasync function ensureOrganizationRole({ tenantId, id, name, description }) {\n const roleId = id ?? longId();\n const { rows } = await pool.query(\n \\`insert into organization_roles (tenant_id, id, name, description)\n values ($1, $2, $3, $4)\n on conflict (id) do update\n set tenant_id = excluded.tenant_id,\n name = excluded.name,\n description = excluded.description\n returning id\\`,\n [tenantId, roleId, name, description ?? name]\n );\n return rows[0].id;\n}\n\nasync function ensureOrganizationRoleAssignment({ tenantId, organizationId, organizationRoleId, userId }) {\n await pool.query(\n \\`insert into organization_role_user_relations (tenant_id, organization_id, organization_role_id, user_id)\n values ($1, $2, $3, $4)\n on conflict (tenant_id, organization_id, organization_role_id, user_id) do nothing\\`,\n [tenantId, organizationId, organizationRoleId, userId]\n );\n}\n\nasync function ensureUser({ tenantId, username, email, password, displayName, customData, preferredId }) {\n let existingId;\n\n if (preferredId) {\n const byId = await pool.query('select id from users where id = $1 limit 1', [preferredId]);\n if (byId.rows.length > 0) existingId = byId.rows[0].id;\n }\n\n if (!existingId) {\n const byTenant = await pool.query(\n 'select id from users where tenant_id = $1 and (username = $2 or primary_email = $3) limit 1',\n [tenantId, username, email]\n );\n if (byTenant.rows.length > 0) existingId = byTenant.rows[0].id;\n }\n\n const passwordEncrypted = await hashPassword(password);\n const targetId = existingId ?? preferredId ?? shortId();\n\n if (existingId) {\n await pool.query(\n \\`update users\n set tenant_id = $1, username = $3, primary_email = $4,\n password_encrypted = $5, password_encryption_method = 'Argon2i',\n name = $6, custom_data = $7::jsonb\n where id = $2\\`,\n [tenantId, targetId, username, email, passwordEncrypted, displayName ?? username, json(customData)]\n );\n return targetId;\n }\n\n await pool.query(\n \\`insert into users (\n tenant_id, id, username, primary_email, password_encrypted, password_encryption_method,\n name, is_suspended, custom_data, profile, identities, logto_config, mfa_verifications\n ) values (\n $1, $2, $3, $4, $5, 'Argon2i', $6, false,\n $7::jsonb, '{}'::jsonb, '{}'::jsonb, '{}'::jsonb, '[]'::jsonb\n )\\`,\n [tenantId, targetId, username, email, passwordEncrypted, displayName ?? username, json(customData)]\n );\n return targetId;\n}\n\nasync function ensureAdminConsoleInitialized(tenantId) {\n const payload = { organizationCreated: true, signInExperienceCustomized: true };\n await pool.query(\n \\`insert into logto_configs (tenant_id, key, value)\n values ($1, 'adminConsole', $2::jsonb)\n on conflict (tenant_id, key) do update set value = excluded.value\\`,\n [tenantId, json(payload)]\n );\n}\n\nasync function ensureAdminTenantSignInMode() {\n await pool.query(\\`update sign_in_experiences set sign_in_mode = 'SignIn' where tenant_id = 'admin'\\`);\n log('Configured admin tenant sign-in mode.');\n}\n\nasync function ensureDefaultTenantSignInExperience() {\n await pool.query(\n \\`update sign_in_experiences\n set sign_in_mode = 'SignIn',\n sign_in = jsonb_build_object(\n 'methods', jsonb_build_array(\n jsonb_build_object('identifier', 'username', 'password', true, 'verificationCode', false, 'isPasswordPrimary', true),\n jsonb_build_object('identifier', 'email', 'password', true, 'verificationCode', false, 'isPasswordPrimary', true)\n )\n )\n where tenant_id = 'default'\\`\n );\n log('Configured default tenant sign-in experience.');\n}\n\nasync function ensureAdminAccountViaApi() {\n const username = process.env.NHP_PLATFORM_ADMIN_USERNAME ?? 'admin';\n const password = process.env.NHP_PLATFORM_ADMIN_PASSWORD ?? 'Habeetat_01';\n\n const { rows } = await pool.query(\n \\`select id from users where tenant_id = 'admin' and username = $1 limit 1\\`,\n [username]\n );\n\n const passwordEncrypted = await hashPassword(password);\n let adminUserId;\n\n if (rows.length === 0) {\n adminUserId = shortId();\n await pool.query(\n \\`INSERT INTO users (\n tenant_id, id, username, password_encrypted, password_encryption_method,\n name, is_suspended, custom_data, profile, identities, logto_config, mfa_verifications\n ) VALUES (\n 'admin', $1, $2, $3, 'Argon2i',\n $2, false, '{}'::jsonb, '{}'::jsonb, '{}'::jsonb, '{}'::jsonb, '[]'::jsonb\n )\\`,\n [adminUserId, username, passwordEncrypted]\n );\n log(\\`Created admin user via SQL (username: \\${username}, id: \\${adminUserId}).\\`);\n } else {\n adminUserId = rows[0].id;\n await pool.query(\n \\`UPDATE users SET password_encrypted = $1, password_encryption_method = 'Argon2i' WHERE id = $2\\`,\n [passwordEncrypted, adminUserId]\n );\n log(\\`Updated password for admin user \\${username} (id: \\${adminUserId}).\\`);\n }\n\n await pool.query(\n \\`INSERT INTO organization_user_relations (tenant_id, organization_id, user_id)\n VALUES ('admin', 't-default', $1) ON CONFLICT DO NOTHING\\`,\n [adminUserId]\n );\n\n await pool.query(\n \\`INSERT INTO organization_role_user_relations (tenant_id, organization_id, organization_role_id, user_id)\n VALUES ('admin', 't-default', 'admin', $1) ON CONFLICT DO NOTHING\\`,\n [adminUserId]\n );\n\n const { rows: allRoles } = await pool.query(\n \\`SELECT id FROM roles WHERE tenant_id = 'admin' AND type = 'User'\\`\n );\n\n for (const role of allRoles) {\n await pool.query(\n \\`INSERT INTO users_roles (tenant_id, id, user_id, role_id)\n VALUES ('admin', $1, $2, $3) ON CONFLICT (tenant_id, user_id, role_id) DO NOTHING\\`,\n [longId(), adminUserId, role.id]\n );\n }\n\n log('Admin account bootstrap via SQL completed.');\n}\n\nasync function main() {\n log('Starting IAM bootstrap seed...');\n\n const platformAdminUsername = process.env.NHP_PLATFORM_ADMIN_USERNAME ?? 'admin';\n const platformAdminEmail = process.env.NHP_PLATFORM_ADMIN_EMAIL ?? 'admin@habeetat.local';\n const platformAdminPassword = process.env.NHP_PLATFORM_ADMIN_PASSWORD ?? 'Habeetat_01';\n const platformAdminDisplayName = process.env.NHP_PLATFORM_ADMIN_DISPLAY_NAME ?? 'Platform Admin';\n const defaultTenantName = process.env.NHP_DEFAULT_TENANT_NAME ?? 'Default';\n const defaultTenantSlug = process.env.NHP_DEFAULT_TENANT_SLUG ?? 'default';\n\n const habeetatAdminOrgId = await ensureOrganization({\n tenantId: 'default',\n id: 'org_habeetat_admin',\n name: 'Habeetat Admin',\n description: 'Internal organization for Habeetat platform administrators',\n customData: { slug: 'habeetat-admin', type: 'internal' },\n });\n\n const defaultTenantOrgId = await ensureOrganization({\n tenantId: 'default',\n id: \\`org_\\${defaultTenantSlug}\\`,\n name: defaultTenantName,\n description: \\`Tenant organization: \\${defaultTenantName}\\`,\n customData: { slug: defaultTenantSlug, type: 'tenant' },\n });\n\n log(\\`Organizations ensured: Habeetat Admin (\\${habeetatAdminOrgId}), \\${defaultTenantName} (\\${defaultTenantOrgId})\\`);\n\n const orgTenantAdminRoleId = await ensureOrganizationRole({\n tenantId: 'default', id: 'org_role_tenant_admin', name: 'TENANT_ADMIN',\n description: 'Tenant administrator with full access to organization management',\n });\n\n const orgTenantUserRoleId = await ensureOrganizationRole({\n tenantId: 'default', id: 'org_role_tenant_user', name: 'TENANT_USER',\n description: 'Regular tenant user with launcher access',\n });\n\n const orgPlatformAdminRoleId = await ensureOrganizationRole({\n tenantId: 'default', id: 'org_role_plat_adm', name: 'PLATFORM_ADMIN',\n description: 'Platform administrator with access to Platform Manager',\n });\n\n log(\\`Organization roles ensured: TENANT_ADMIN=\\${orgTenantAdminRoleId}, TENANT_USER=\\${orgTenantUserRoleId}, PLATFORM_ADMIN=\\${orgPlatformAdminRoleId}\\`);\n\n await ensureAdminConsoleInitialized('default');\n await ensureAdminConsoleInitialized('admin');\n await ensureAdminTenantSignInMode();\n await ensureDefaultTenantSignInExperience();\n await ensureAdminAccountViaApi();\n\n const platformAdminUserId = await ensureUser({\n tenantId: 'default',\n preferredId: 'usr_admin01',\n username: platformAdminUsername,\n email: platformAdminEmail,\n password: platformAdminPassword,\n displayName: platformAdminDisplayName,\n customData: { tenantSlug: defaultTenantSlug },\n });\n\n await ensureOrganizationMembership({ tenantId: 'default', organizationId: habeetatAdminOrgId, userId: platformAdminUserId });\n await ensureOrganizationMembership({ tenantId: 'default', organizationId: defaultTenantOrgId, userId: platformAdminUserId });\n\n await ensureOrganizationRoleAssignment({ tenantId: 'default', organizationId: defaultTenantOrgId, organizationRoleId: orgTenantAdminRoleId, userId: platformAdminUserId });\n await ensureOrganizationRoleAssignment({ tenantId: 'default', organizationId: defaultTenantOrgId, organizationRoleId: orgTenantUserRoleId, userId: platformAdminUserId });\n await ensureOrganizationRoleAssignment({ tenantId: 'default', organizationId: habeetatAdminOrgId, organizationRoleId: orgPlatformAdminRoleId, userId: platformAdminUserId });\n\n log(\\`Ensured user \\${platformAdminUsername} (\\${platformAdminEmail}, id: \\${platformAdminUserId})\\`);\n log('IAM bootstrap seed completed successfully.');\n}\n\nmain()\n .catch((error) => {\n console.error('[NHP][iam-seed] Failed:', error);\n process.exitCode = 1;\n })\n .finally(async () => {\n await pool.end();\n });\n`;\n}\n","/**\n * Generates a ClickHouse config override that forces IPv4-only listening.\n * Required on hosts where IPv6 is disabled — without this ClickHouse tries\n * to bind [::] first and fails, causing the healthcheck to never pass.\n */\nexport function generateClickhouseConfig(): string {\n return `<!-- ClickHouse config override: force IPv4-only listening -->\n<!-- Required on hosts with IPv6 disabled (AWS, DigitalOcean, etc.) -->\n<clickhouse>\n <listen_host>0.0.0.0</listen_host>\n</clickhouse>\n`;\n}\n\n/**\n * Generates the OpenTelemetry Collector configuration for SigNoz.\n * This YAML config is mounted into the otel-collector container.\n */\nexport function generateOtelCollectorConfig(): string {\n return `# SigNoz OpenTelemetry Collector Configuration\n# Auto-generated by @habeetat/cli\n\nreceivers:\n otlp:\n protocols:\n grpc:\n endpoint: 0.0.0.0:4317\n http:\n endpoint: 0.0.0.0:4318\n\nprocessors:\n batch:\n send_batch_size: 1000\n timeout: 5s\n resourcedetection:\n detectors:\n - env\n - system\n timeout: 2s\n\nexporters:\n clickhouselogsexporter:\n dsn: tcp://clickhouse:9000/?database=signoz_logs&username=default\n timeout: 10s\n clickhousetraces:\n dsn: tcp://clickhouse:9000/?database=signoz_traces&username=default\n timeout: 10s\n clickhousemetricswrite:\n dsn: tcp://clickhouse:9000/?database=signoz_metrics&username=default\n timeout: 10s\n\nservice:\n pipelines:\n logs:\n receivers: [otlp]\n processors: [batch]\n exporters: [clickhouselogsexporter]\n traces:\n receivers: [otlp]\n processors: [batch]\n exporters: [clickhousetraces]\n metrics:\n receivers: [otlp]\n processors: [batch]\n exporters: [clickhousemetricswrite]\n`;\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","../src/templates/bootstrap-script.ts","../src/templates/otel-collector-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 clickhouse: 'clickhouse/clickhouse-server:24.1.2-alpine',\n signozOtelCollector: 'signoz/signoz-otel-collector:0.88.22',\n signozQuery: 'signoz/query-service:0.45.0',\n signozFrontend: 'signoz/frontend:0.45.0',\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 'clickhouse',\n 'otel-collector',\n 'signoz-query-service',\n 'signoz-frontend',\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 ...(config.services.signoz && {\n OTEL_COLLECTOR_ENDPOINT: '${OTEL_COLLECTOR_ENDPOINT}',\n }),\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 // SigNoz observability stack (ClickHouse + OTel Collector + Query Service + Frontend)\n if (config.services.signoz) {\n services['clickhouse'] = {\n image: THIRD_PARTY_IMAGES.clickhouse,\n volumes: [\n 'clickhouse-data:/var/lib/clickhouse',\n 'clickhouse-logs:/var/log/clickhouse-server',\n './signoz/clickhouse-config.xml:/etc/clickhouse-server/config.d/habeetat-listen.xml:ro',\n ],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'clickhouse-client --host=127.0.0.1 --query=\"SELECT 1\" || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '60s',\n },\n };\n\n services['otel-collector'] = {\n image: THIRD_PARTY_IMAGES.signozOtelCollector,\n command: ['--config=/etc/otel-collector-config.yaml'],\n depends_on: {\n clickhouse: { condition: 'service_healthy' },\n },\n volumes: ['./signoz/otel-collector-config.yaml:/etc/otel-collector-config.yaml:ro'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n\n services['signoz-query-service'] = {\n image: THIRD_PARTY_IMAGES.signozQuery,\n depends_on: {\n clickhouse: { condition: 'service_healthy' },\n 'otel-collector': { condition: 'service_started' },\n },\n volumes: ['signoz-data:/var/lib/signoz'],\n environment: {\n ClickHouseUrl: 'tcp://clickhouse:9000',\n STORAGE: 'clickhouse',\n GODEBUG: 'netdns=go',\n SIGNOZ_LOCAL_DB_PATH: '/var/lib/signoz/signoz.db',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'wget -O- http://localhost:8080/api/v1/health 2>&1 | grep -q \"status\" || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '60s',\n },\n };\n\n services['signoz-frontend'] = {\n image: THIRD_PARTY_IMAGES.signozFrontend,\n depends_on: {\n 'signoz-query-service': { condition: 'service_healthy' },\n },\n environment: {\n FRONTEND_API_URL: 'http://signoz-query-service:8080',\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 if (config.services.signoz) nginxDependsOn.push('signoz-frontend');\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 ...(config.services.signoz && {\n 'clickhouse-data': null,\n 'clickhouse-logs': null,\n 'signoz-data': null,\n }),\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 if (config.services.signoz) upstreams.push('upstream signoz_frontend { server signoz-frontend:3301; }');\n\n const proto = config.platform.protocol;\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 ${proto};`;\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 // SigNoz Dashboard\n if (config.services.signoz) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name logs.${domain};\n location / {\n proxy_pass http://signoz_frontend;${proxyHeaders}\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection \"upgrade\";\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 if (config.services.signoz) subdomains.push('logs');\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# SSL will be added automatically by certbot --nginx\n\nserver {\n listen 80;\n server_name ${allServerNames};\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 clickhousePassword: randomHex(16),\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# SigNoz / OpenTelemetry (Observability)\n# ============================================\nSIGNOZ_URL=${protocol}://logs.${domain}\nOTEL_COLLECTOR_ENDPOINT=http://otel-collector:4317\nCLICKHOUSE_PASSWORD=${secrets.clickhousePassword}\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 composeDestroy(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down -v --remove-orphans`, {\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","// Logto IAM bootstrap seed script — embedded for scaffolding\n// This is the content of scripts/nhp-seed-logto-bootstrap.mjs\n// It runs inside a temporary Node container on the Docker network\n\nexport function getBootstrapScript(): string {\n return `#!/usr/bin/env node\nimport crypto from 'node:crypto';\n\nimport { argon2i } from 'hash-wasm';\nimport { customAlphabet } from 'nanoid';\nimport { Pool } from 'pg';\n\nconst alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst shortId = customAlphabet(alphabet, 12);\nconst longId = customAlphabet(alphabet, 21);\n\nconst connectionString =\n process.env.NHP_LOGTO_DB_URL ?? 'postgres://logto:logto@localhost:5434/logto';\n\nconst pool = new Pool({ connectionString });\n\nconst log = (message) => console.log(\\`[NHP][iam-seed] \\${message}\\`);\nconst json = (value) => JSON.stringify(value ?? {});\n\nasync function hashPassword(password) {\n return argon2i({\n password,\n salt: crypto.randomBytes(16),\n iterations: 256,\n parallelism: 1,\n memorySize: 4096,\n hashLength: 32,\n outputType: 'encoded',\n });\n}\n\nasync function ensureOrganization({ tenantId, id, name, description, customData }) {\n const orgId = id ?? longId();\n const { rows } = await pool.query(\n \\`insert into organizations (tenant_id, id, name, description, custom_data)\n values ($1, $2, $3, $4, $5::jsonb)\n on conflict (id) do update\n set tenant_id = excluded.tenant_id,\n name = excluded.name,\n description = excluded.description,\n custom_data = excluded.custom_data\n returning id\\`,\n [tenantId, orgId, name, description ?? name, json(customData)]\n );\n return rows[0].id;\n}\n\nasync function ensureOrganizationMembership({ tenantId, organizationId, userId }) {\n await pool.query(\n \\`insert into organization_user_relations (tenant_id, organization_id, user_id)\n values ($1, $2, $3)\n on conflict (tenant_id, organization_id, user_id) do nothing\\`,\n [tenantId, organizationId, userId]\n );\n}\n\nasync function ensureOrganizationRole({ tenantId, id, name, description }) {\n const roleId = id ?? longId();\n const { rows } = await pool.query(\n \\`insert into organization_roles (tenant_id, id, name, description)\n values ($1, $2, $3, $4)\n on conflict (id) do update\n set tenant_id = excluded.tenant_id,\n name = excluded.name,\n description = excluded.description\n returning id\\`,\n [tenantId, roleId, name, description ?? name]\n );\n return rows[0].id;\n}\n\nasync function ensureOrganizationRoleAssignment({ tenantId, organizationId, organizationRoleId, userId }) {\n await pool.query(\n \\`insert into organization_role_user_relations (tenant_id, organization_id, organization_role_id, user_id)\n values ($1, $2, $3, $4)\n on conflict (tenant_id, organization_id, organization_role_id, user_id) do nothing\\`,\n [tenantId, organizationId, organizationRoleId, userId]\n );\n}\n\nasync function ensureUser({ tenantId, username, email, password, displayName, customData, preferredId }) {\n let existingId;\n\n if (preferredId) {\n const byId = await pool.query('select id from users where id = $1 limit 1', [preferredId]);\n if (byId.rows.length > 0) existingId = byId.rows[0].id;\n }\n\n if (!existingId) {\n const byTenant = await pool.query(\n 'select id from users where tenant_id = $1 and (username = $2 or primary_email = $3) limit 1',\n [tenantId, username, email]\n );\n if (byTenant.rows.length > 0) existingId = byTenant.rows[0].id;\n }\n\n const passwordEncrypted = await hashPassword(password);\n const targetId = existingId ?? preferredId ?? shortId();\n\n if (existingId) {\n await pool.query(\n \\`update users\n set tenant_id = $1, username = $3, primary_email = $4,\n password_encrypted = $5, password_encryption_method = 'Argon2i',\n name = $6, custom_data = $7::jsonb\n where id = $2\\`,\n [tenantId, targetId, username, email, passwordEncrypted, displayName ?? username, json(customData)]\n );\n return targetId;\n }\n\n await pool.query(\n \\`insert into users (\n tenant_id, id, username, primary_email, password_encrypted, password_encryption_method,\n name, is_suspended, custom_data, profile, identities, logto_config, mfa_verifications\n ) values (\n $1, $2, $3, $4, $5, 'Argon2i', $6, false,\n $7::jsonb, '{}'::jsonb, '{}'::jsonb, '{}'::jsonb, '[]'::jsonb\n )\\`,\n [tenantId, targetId, username, email, passwordEncrypted, displayName ?? username, json(customData)]\n );\n return targetId;\n}\n\nasync function ensureAdminConsoleInitialized(tenantId) {\n const payload = { organizationCreated: true, signInExperienceCustomized: true };\n await pool.query(\n \\`insert into logto_configs (tenant_id, key, value)\n values ($1, 'adminConsole', $2::jsonb)\n on conflict (tenant_id, key) do update set value = excluded.value\\`,\n [tenantId, json(payload)]\n );\n}\n\nasync function ensureAdminTenantSignInMode() {\n await pool.query(\\`update sign_in_experiences set sign_in_mode = 'SignIn' where tenant_id = 'admin'\\`);\n log('Configured admin tenant sign-in mode.');\n}\n\nasync function ensureDefaultTenantSignInExperience() {\n await pool.query(\n \\`update sign_in_experiences\n set sign_in_mode = 'SignIn',\n sign_in = jsonb_build_object(\n 'methods', jsonb_build_array(\n jsonb_build_object('identifier', 'username', 'password', true, 'verificationCode', false, 'isPasswordPrimary', true),\n jsonb_build_object('identifier', 'email', 'password', true, 'verificationCode', false, 'isPasswordPrimary', true)\n )\n )\n where tenant_id = 'default'\\`\n );\n log('Configured default tenant sign-in experience.');\n}\n\nasync function ensureAdminAccountViaApi() {\n const username = process.env.NHP_PLATFORM_ADMIN_USERNAME ?? 'admin';\n const password = process.env.NHP_PLATFORM_ADMIN_PASSWORD ?? 'Habeetat_01';\n\n const { rows } = await pool.query(\n \\`select id from users where tenant_id = 'admin' and username = $1 limit 1\\`,\n [username]\n );\n\n const passwordEncrypted = await hashPassword(password);\n let adminUserId;\n\n if (rows.length === 0) {\n adminUserId = shortId();\n await pool.query(\n \\`INSERT INTO users (\n tenant_id, id, username, password_encrypted, password_encryption_method,\n name, is_suspended, custom_data, profile, identities, logto_config, mfa_verifications\n ) VALUES (\n 'admin', $1, $2, $3, 'Argon2i',\n $2, false, '{}'::jsonb, '{}'::jsonb, '{}'::jsonb, '{}'::jsonb, '[]'::jsonb\n )\\`,\n [adminUserId, username, passwordEncrypted]\n );\n log(\\`Created admin user via SQL (username: \\${username}, id: \\${adminUserId}).\\`);\n } else {\n adminUserId = rows[0].id;\n await pool.query(\n \\`UPDATE users SET password_encrypted = $1, password_encryption_method = 'Argon2i' WHERE id = $2\\`,\n [passwordEncrypted, adminUserId]\n );\n log(\\`Updated password for admin user \\${username} (id: \\${adminUserId}).\\`);\n }\n\n await pool.query(\n \\`INSERT INTO organization_user_relations (tenant_id, organization_id, user_id)\n VALUES ('admin', 't-default', $1) ON CONFLICT DO NOTHING\\`,\n [adminUserId]\n );\n\n await pool.query(\n \\`INSERT INTO organization_role_user_relations (tenant_id, organization_id, organization_role_id, user_id)\n VALUES ('admin', 't-default', 'admin', $1) ON CONFLICT DO NOTHING\\`,\n [adminUserId]\n );\n\n const { rows: allRoles } = await pool.query(\n \\`SELECT id FROM roles WHERE tenant_id = 'admin' AND type = 'User'\\`\n );\n\n for (const role of allRoles) {\n await pool.query(\n \\`INSERT INTO users_roles (tenant_id, id, user_id, role_id)\n VALUES ('admin', $1, $2, $3) ON CONFLICT (tenant_id, user_id, role_id) DO NOTHING\\`,\n [longId(), adminUserId, role.id]\n );\n }\n\n log('Admin account bootstrap via SQL completed.');\n}\n\nasync function main() {\n log('Starting IAM bootstrap seed...');\n\n const platformAdminUsername = process.env.NHP_PLATFORM_ADMIN_USERNAME ?? 'admin';\n const platformAdminEmail = process.env.NHP_PLATFORM_ADMIN_EMAIL ?? 'admin@habeetat.local';\n const platformAdminPassword = process.env.NHP_PLATFORM_ADMIN_PASSWORD ?? 'Habeetat_01';\n const platformAdminDisplayName = process.env.NHP_PLATFORM_ADMIN_DISPLAY_NAME ?? 'Platform Admin';\n const defaultTenantName = process.env.NHP_DEFAULT_TENANT_NAME ?? 'Default';\n const defaultTenantSlug = process.env.NHP_DEFAULT_TENANT_SLUG ?? 'default';\n\n const habeetatAdminOrgId = await ensureOrganization({\n tenantId: 'default',\n id: 'org_habeetat_admin',\n name: 'Habeetat Admin',\n description: 'Internal organization for Habeetat platform administrators',\n customData: { slug: 'habeetat-admin', type: 'internal' },\n });\n\n const defaultTenantOrgId = await ensureOrganization({\n tenantId: 'default',\n id: \\`org_\\${defaultTenantSlug}\\`,\n name: defaultTenantName,\n description: \\`Tenant organization: \\${defaultTenantName}\\`,\n customData: { slug: defaultTenantSlug, type: 'tenant' },\n });\n\n log(\\`Organizations ensured: Habeetat Admin (\\${habeetatAdminOrgId}), \\${defaultTenantName} (\\${defaultTenantOrgId})\\`);\n\n const orgTenantAdminRoleId = await ensureOrganizationRole({\n tenantId: 'default', id: 'org_role_tenant_admin', name: 'TENANT_ADMIN',\n description: 'Tenant administrator with full access to organization management',\n });\n\n const orgTenantUserRoleId = await ensureOrganizationRole({\n tenantId: 'default', id: 'org_role_tenant_user', name: 'TENANT_USER',\n description: 'Regular tenant user with launcher access',\n });\n\n const orgPlatformAdminRoleId = await ensureOrganizationRole({\n tenantId: 'default', id: 'org_role_plat_adm', name: 'PLATFORM_ADMIN',\n description: 'Platform administrator with access to Platform Manager',\n });\n\n log(\\`Organization roles ensured: TENANT_ADMIN=\\${orgTenantAdminRoleId}, TENANT_USER=\\${orgTenantUserRoleId}, PLATFORM_ADMIN=\\${orgPlatformAdminRoleId}\\`);\n\n await ensureAdminConsoleInitialized('default');\n await ensureAdminConsoleInitialized('admin');\n await ensureAdminTenantSignInMode();\n await ensureDefaultTenantSignInExperience();\n await ensureAdminAccountViaApi();\n\n const platformAdminUserId = await ensureUser({\n tenantId: 'default',\n preferredId: 'usr_admin01',\n username: platformAdminUsername,\n email: platformAdminEmail,\n password: platformAdminPassword,\n displayName: platformAdminDisplayName,\n customData: { tenantSlug: defaultTenantSlug },\n });\n\n await ensureOrganizationMembership({ tenantId: 'default', organizationId: habeetatAdminOrgId, userId: platformAdminUserId });\n await ensureOrganizationMembership({ tenantId: 'default', organizationId: defaultTenantOrgId, userId: platformAdminUserId });\n\n await ensureOrganizationRoleAssignment({ tenantId: 'default', organizationId: defaultTenantOrgId, organizationRoleId: orgTenantAdminRoleId, userId: platformAdminUserId });\n await ensureOrganizationRoleAssignment({ tenantId: 'default', organizationId: defaultTenantOrgId, organizationRoleId: orgTenantUserRoleId, userId: platformAdminUserId });\n await ensureOrganizationRoleAssignment({ tenantId: 'default', organizationId: habeetatAdminOrgId, organizationRoleId: orgPlatformAdminRoleId, userId: platformAdminUserId });\n\n log(\\`Ensured user \\${platformAdminUsername} (\\${platformAdminEmail}, id: \\${platformAdminUserId})\\`);\n log('IAM bootstrap seed completed successfully.');\n}\n\nmain()\n .catch((error) => {\n console.error('[NHP][iam-seed] Failed:', error);\n process.exitCode = 1;\n })\n .finally(async () => {\n await pool.end();\n });\n`;\n}\n","/**\n * Generates a ClickHouse config override that forces IPv4-only listening.\n * Required on hosts where IPv6 is disabled — without this ClickHouse tries\n * to bind [::] first and fails, causing the healthcheck to never pass.\n */\nexport function generateClickhouseConfig(): string {\n return `<!-- ClickHouse config override: force IPv4-only listening -->\n<!-- Required on hosts with IPv6 disabled (AWS, DigitalOcean, etc.) -->\n<clickhouse>\n <listen_host>0.0.0.0</listen_host>\n</clickhouse>\n`;\n}\n\n/**\n * Generates the OpenTelemetry Collector configuration for SigNoz.\n * This YAML config is mounted into the otel-collector container.\n */\nexport function generateOtelCollectorConfig(): string {\n return `# SigNoz OpenTelemetry Collector Configuration\n# Auto-generated by @habeetat/cli\n\nreceivers:\n otlp:\n protocols:\n grpc:\n endpoint: 0.0.0.0:4317\n http:\n endpoint: 0.0.0.0:4318\n\nprocessors:\n batch:\n send_batch_size: 1000\n timeout: 5s\n resourcedetection:\n detectors:\n - env\n - system\n timeout: 2s\n\nexporters:\n clickhouselogsexporter:\n dsn: tcp://clickhouse:9000/\n timeout: 10s\n docker_multi_node_cluster: false\n clickhousetraces:\n datasource: tcp://clickhouse:9000/\n docker_multi_node_cluster: false\n clickhousemetricswrite:\n endpoint: tcp://clickhouse:9000/\n resource_to_telemetry_conversion:\n enabled: true\n\nservice:\n pipelines:\n logs:\n receivers: [otlp]\n processors: [batch]\n exporters: [clickhouselogsexporter]\n traces:\n receivers: [otlp]\n processors: [batch]\n exporters: [clickhousetraces]\n metrics:\n receivers: [otlp]\n processors: [batch]\n exporters: [clickhousemetricswrite]\n`;\n}\n"]}
package/dist/index.mjs CHANGED
@@ -1019,14 +1019,16 @@ processors:
1019
1019
 
1020
1020
  exporters:
1021
1021
  clickhouselogsexporter:
1022
- dsn: tcp://clickhouse:9000/?database=signoz_logs&username=default
1022
+ dsn: tcp://clickhouse:9000/
1023
1023
  timeout: 10s
1024
+ docker_multi_node_cluster: false
1024
1025
  clickhousetraces:
1025
- dsn: tcp://clickhouse:9000/?database=signoz_traces&username=default
1026
- timeout: 10s
1026
+ datasource: tcp://clickhouse:9000/
1027
+ docker_multi_node_cluster: false
1027
1028
  clickhousemetricswrite:
1028
- dsn: tcp://clickhouse:9000/?database=signoz_metrics&username=default
1029
- timeout: 10s
1029
+ endpoint: tcp://clickhouse:9000/
1030
+ resource_to_telemetry_conversion:
1031
+ enabled: true
1030
1032
 
1031
1033
  service:
1032
1034
  pipelines:
@@ -1 +1 @@
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","../src/templates/bootstrap-script.ts","../src/templates/otel-collector-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 clickhouse: 'clickhouse/clickhouse-server:24.1.2-alpine',\n signozOtelCollector: 'signoz/signoz-otel-collector:0.88.22',\n signozQuery: 'signoz/query-service:0.45.0',\n signozFrontend: 'signoz/frontend:0.45.0',\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 'clickhouse',\n 'otel-collector',\n 'signoz-query-service',\n 'signoz-frontend',\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 ...(config.services.signoz && {\n OTEL_COLLECTOR_ENDPOINT: '${OTEL_COLLECTOR_ENDPOINT}',\n }),\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 // SigNoz observability stack (ClickHouse + OTel Collector + Query Service + Frontend)\n if (config.services.signoz) {\n services['clickhouse'] = {\n image: THIRD_PARTY_IMAGES.clickhouse,\n volumes: [\n 'clickhouse-data:/var/lib/clickhouse',\n 'clickhouse-logs:/var/log/clickhouse-server',\n './signoz/clickhouse-config.xml:/etc/clickhouse-server/config.d/habeetat-listen.xml:ro',\n ],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'clickhouse-client --host=127.0.0.1 --query=\"SELECT 1\" || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '60s',\n },\n };\n\n services['otel-collector'] = {\n image: THIRD_PARTY_IMAGES.signozOtelCollector,\n command: ['--config=/etc/otel-collector-config.yaml'],\n depends_on: {\n clickhouse: { condition: 'service_healthy' },\n },\n volumes: ['./signoz/otel-collector-config.yaml:/etc/otel-collector-config.yaml:ro'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n\n services['signoz-query-service'] = {\n image: THIRD_PARTY_IMAGES.signozQuery,\n depends_on: {\n clickhouse: { condition: 'service_healthy' },\n 'otel-collector': { condition: 'service_started' },\n },\n volumes: ['signoz-data:/var/lib/signoz'],\n environment: {\n ClickHouseUrl: 'tcp://clickhouse:9000',\n STORAGE: 'clickhouse',\n GODEBUG: 'netdns=go',\n SIGNOZ_LOCAL_DB_PATH: '/var/lib/signoz/signoz.db',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'wget -O- http://localhost:8080/api/v1/health 2>&1 | grep -q \"status\" || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '60s',\n },\n };\n\n services['signoz-frontend'] = {\n image: THIRD_PARTY_IMAGES.signozFrontend,\n depends_on: {\n 'signoz-query-service': { condition: 'service_healthy' },\n },\n environment: {\n FRONTEND_API_URL: 'http://signoz-query-service:8080',\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 if (config.services.signoz) nginxDependsOn.push('signoz-frontend');\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 ...(config.services.signoz && {\n 'clickhouse-data': null,\n 'clickhouse-logs': null,\n 'signoz-data': null,\n }),\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 if (config.services.signoz) upstreams.push('upstream signoz_frontend { server signoz-frontend:3301; }');\n\n const proto = config.platform.protocol;\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 ${proto};`;\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 // SigNoz Dashboard\n if (config.services.signoz) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name logs.${domain};\n location / {\n proxy_pass http://signoz_frontend;${proxyHeaders}\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection \"upgrade\";\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 if (config.services.signoz) subdomains.push('logs');\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# SSL will be added automatically by certbot --nginx\n\nserver {\n listen 80;\n server_name ${allServerNames};\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 clickhousePassword: randomHex(16),\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# SigNoz / OpenTelemetry (Observability)\n# ============================================\nSIGNOZ_URL=${protocol}://logs.${domain}\nOTEL_COLLECTOR_ENDPOINT=http://otel-collector:4317\nCLICKHOUSE_PASSWORD=${secrets.clickhousePassword}\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 composeDestroy(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down -v --remove-orphans`, {\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","// Logto IAM bootstrap seed script — embedded for scaffolding\n// This is the content of scripts/nhp-seed-logto-bootstrap.mjs\n// It runs inside a temporary Node container on the Docker network\n\nexport function getBootstrapScript(): string {\n return `#!/usr/bin/env node\nimport crypto from 'node:crypto';\n\nimport { argon2i } from 'hash-wasm';\nimport { customAlphabet } from 'nanoid';\nimport { Pool } from 'pg';\n\nconst alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst shortId = customAlphabet(alphabet, 12);\nconst longId = customAlphabet(alphabet, 21);\n\nconst connectionString =\n process.env.NHP_LOGTO_DB_URL ?? 'postgres://logto:logto@localhost:5434/logto';\n\nconst pool = new Pool({ connectionString });\n\nconst log = (message) => console.log(\\`[NHP][iam-seed] \\${message}\\`);\nconst json = (value) => JSON.stringify(value ?? {});\n\nasync function hashPassword(password) {\n return argon2i({\n password,\n salt: crypto.randomBytes(16),\n iterations: 256,\n parallelism: 1,\n memorySize: 4096,\n hashLength: 32,\n outputType: 'encoded',\n });\n}\n\nasync function ensureOrganization({ tenantId, id, name, description, customData }) {\n const orgId = id ?? longId();\n const { rows } = await pool.query(\n \\`insert into organizations (tenant_id, id, name, description, custom_data)\n values ($1, $2, $3, $4, $5::jsonb)\n on conflict (id) do update\n set tenant_id = excluded.tenant_id,\n name = excluded.name,\n description = excluded.description,\n custom_data = excluded.custom_data\n returning id\\`,\n [tenantId, orgId, name, description ?? name, json(customData)]\n );\n return rows[0].id;\n}\n\nasync function ensureOrganizationMembership({ tenantId, organizationId, userId }) {\n await pool.query(\n \\`insert into organization_user_relations (tenant_id, organization_id, user_id)\n values ($1, $2, $3)\n on conflict (tenant_id, organization_id, user_id) do nothing\\`,\n [tenantId, organizationId, userId]\n );\n}\n\nasync function ensureOrganizationRole({ tenantId, id, name, description }) {\n const roleId = id ?? longId();\n const { rows } = await pool.query(\n \\`insert into organization_roles (tenant_id, id, name, description)\n values ($1, $2, $3, $4)\n on conflict (id) do update\n set tenant_id = excluded.tenant_id,\n name = excluded.name,\n description = excluded.description\n returning id\\`,\n [tenantId, roleId, name, description ?? name]\n );\n return rows[0].id;\n}\n\nasync function ensureOrganizationRoleAssignment({ tenantId, organizationId, organizationRoleId, userId }) {\n await pool.query(\n \\`insert into organization_role_user_relations (tenant_id, organization_id, organization_role_id, user_id)\n values ($1, $2, $3, $4)\n on conflict (tenant_id, organization_id, organization_role_id, user_id) do nothing\\`,\n [tenantId, organizationId, organizationRoleId, userId]\n );\n}\n\nasync function ensureUser({ tenantId, username, email, password, displayName, customData, preferredId }) {\n let existingId;\n\n if (preferredId) {\n const byId = await pool.query('select id from users where id = $1 limit 1', [preferredId]);\n if (byId.rows.length > 0) existingId = byId.rows[0].id;\n }\n\n if (!existingId) {\n const byTenant = await pool.query(\n 'select id from users where tenant_id = $1 and (username = $2 or primary_email = $3) limit 1',\n [tenantId, username, email]\n );\n if (byTenant.rows.length > 0) existingId = byTenant.rows[0].id;\n }\n\n const passwordEncrypted = await hashPassword(password);\n const targetId = existingId ?? preferredId ?? shortId();\n\n if (existingId) {\n await pool.query(\n \\`update users\n set tenant_id = $1, username = $3, primary_email = $4,\n password_encrypted = $5, password_encryption_method = 'Argon2i',\n name = $6, custom_data = $7::jsonb\n where id = $2\\`,\n [tenantId, targetId, username, email, passwordEncrypted, displayName ?? username, json(customData)]\n );\n return targetId;\n }\n\n await pool.query(\n \\`insert into users (\n tenant_id, id, username, primary_email, password_encrypted, password_encryption_method,\n name, is_suspended, custom_data, profile, identities, logto_config, mfa_verifications\n ) values (\n $1, $2, $3, $4, $5, 'Argon2i', $6, false,\n $7::jsonb, '{}'::jsonb, '{}'::jsonb, '{}'::jsonb, '[]'::jsonb\n )\\`,\n [tenantId, targetId, username, email, passwordEncrypted, displayName ?? username, json(customData)]\n );\n return targetId;\n}\n\nasync function ensureAdminConsoleInitialized(tenantId) {\n const payload = { organizationCreated: true, signInExperienceCustomized: true };\n await pool.query(\n \\`insert into logto_configs (tenant_id, key, value)\n values ($1, 'adminConsole', $2::jsonb)\n on conflict (tenant_id, key) do update set value = excluded.value\\`,\n [tenantId, json(payload)]\n );\n}\n\nasync function ensureAdminTenantSignInMode() {\n await pool.query(\\`update sign_in_experiences set sign_in_mode = 'SignIn' where tenant_id = 'admin'\\`);\n log('Configured admin tenant sign-in mode.');\n}\n\nasync function ensureDefaultTenantSignInExperience() {\n await pool.query(\n \\`update sign_in_experiences\n set sign_in_mode = 'SignIn',\n sign_in = jsonb_build_object(\n 'methods', jsonb_build_array(\n jsonb_build_object('identifier', 'username', 'password', true, 'verificationCode', false, 'isPasswordPrimary', true),\n jsonb_build_object('identifier', 'email', 'password', true, 'verificationCode', false, 'isPasswordPrimary', true)\n )\n )\n where tenant_id = 'default'\\`\n );\n log('Configured default tenant sign-in experience.');\n}\n\nasync function ensureAdminAccountViaApi() {\n const username = process.env.NHP_PLATFORM_ADMIN_USERNAME ?? 'admin';\n const password = process.env.NHP_PLATFORM_ADMIN_PASSWORD ?? 'Habeetat_01';\n\n const { rows } = await pool.query(\n \\`select id from users where tenant_id = 'admin' and username = $1 limit 1\\`,\n [username]\n );\n\n const passwordEncrypted = await hashPassword(password);\n let adminUserId;\n\n if (rows.length === 0) {\n adminUserId = shortId();\n await pool.query(\n \\`INSERT INTO users (\n tenant_id, id, username, password_encrypted, password_encryption_method,\n name, is_suspended, custom_data, profile, identities, logto_config, mfa_verifications\n ) VALUES (\n 'admin', $1, $2, $3, 'Argon2i',\n $2, false, '{}'::jsonb, '{}'::jsonb, '{}'::jsonb, '{}'::jsonb, '[]'::jsonb\n )\\`,\n [adminUserId, username, passwordEncrypted]\n );\n log(\\`Created admin user via SQL (username: \\${username}, id: \\${adminUserId}).\\`);\n } else {\n adminUserId = rows[0].id;\n await pool.query(\n \\`UPDATE users SET password_encrypted = $1, password_encryption_method = 'Argon2i' WHERE id = $2\\`,\n [passwordEncrypted, adminUserId]\n );\n log(\\`Updated password for admin user \\${username} (id: \\${adminUserId}).\\`);\n }\n\n await pool.query(\n \\`INSERT INTO organization_user_relations (tenant_id, organization_id, user_id)\n VALUES ('admin', 't-default', $1) ON CONFLICT DO NOTHING\\`,\n [adminUserId]\n );\n\n await pool.query(\n \\`INSERT INTO organization_role_user_relations (tenant_id, organization_id, organization_role_id, user_id)\n VALUES ('admin', 't-default', 'admin', $1) ON CONFLICT DO NOTHING\\`,\n [adminUserId]\n );\n\n const { rows: allRoles } = await pool.query(\n \\`SELECT id FROM roles WHERE tenant_id = 'admin' AND type = 'User'\\`\n );\n\n for (const role of allRoles) {\n await pool.query(\n \\`INSERT INTO users_roles (tenant_id, id, user_id, role_id)\n VALUES ('admin', $1, $2, $3) ON CONFLICT (tenant_id, user_id, role_id) DO NOTHING\\`,\n [longId(), adminUserId, role.id]\n );\n }\n\n log('Admin account bootstrap via SQL completed.');\n}\n\nasync function main() {\n log('Starting IAM bootstrap seed...');\n\n const platformAdminUsername = process.env.NHP_PLATFORM_ADMIN_USERNAME ?? 'admin';\n const platformAdminEmail = process.env.NHP_PLATFORM_ADMIN_EMAIL ?? 'admin@habeetat.local';\n const platformAdminPassword = process.env.NHP_PLATFORM_ADMIN_PASSWORD ?? 'Habeetat_01';\n const platformAdminDisplayName = process.env.NHP_PLATFORM_ADMIN_DISPLAY_NAME ?? 'Platform Admin';\n const defaultTenantName = process.env.NHP_DEFAULT_TENANT_NAME ?? 'Default';\n const defaultTenantSlug = process.env.NHP_DEFAULT_TENANT_SLUG ?? 'default';\n\n const habeetatAdminOrgId = await ensureOrganization({\n tenantId: 'default',\n id: 'org_habeetat_admin',\n name: 'Habeetat Admin',\n description: 'Internal organization for Habeetat platform administrators',\n customData: { slug: 'habeetat-admin', type: 'internal' },\n });\n\n const defaultTenantOrgId = await ensureOrganization({\n tenantId: 'default',\n id: \\`org_\\${defaultTenantSlug}\\`,\n name: defaultTenantName,\n description: \\`Tenant organization: \\${defaultTenantName}\\`,\n customData: { slug: defaultTenantSlug, type: 'tenant' },\n });\n\n log(\\`Organizations ensured: Habeetat Admin (\\${habeetatAdminOrgId}), \\${defaultTenantName} (\\${defaultTenantOrgId})\\`);\n\n const orgTenantAdminRoleId = await ensureOrganizationRole({\n tenantId: 'default', id: 'org_role_tenant_admin', name: 'TENANT_ADMIN',\n description: 'Tenant administrator with full access to organization management',\n });\n\n const orgTenantUserRoleId = await ensureOrganizationRole({\n tenantId: 'default', id: 'org_role_tenant_user', name: 'TENANT_USER',\n description: 'Regular tenant user with launcher access',\n });\n\n const orgPlatformAdminRoleId = await ensureOrganizationRole({\n tenantId: 'default', id: 'org_role_plat_adm', name: 'PLATFORM_ADMIN',\n description: 'Platform administrator with access to Platform Manager',\n });\n\n log(\\`Organization roles ensured: TENANT_ADMIN=\\${orgTenantAdminRoleId}, TENANT_USER=\\${orgTenantUserRoleId}, PLATFORM_ADMIN=\\${orgPlatformAdminRoleId}\\`);\n\n await ensureAdminConsoleInitialized('default');\n await ensureAdminConsoleInitialized('admin');\n await ensureAdminTenantSignInMode();\n await ensureDefaultTenantSignInExperience();\n await ensureAdminAccountViaApi();\n\n const platformAdminUserId = await ensureUser({\n tenantId: 'default',\n preferredId: 'usr_admin01',\n username: platformAdminUsername,\n email: platformAdminEmail,\n password: platformAdminPassword,\n displayName: platformAdminDisplayName,\n customData: { tenantSlug: defaultTenantSlug },\n });\n\n await ensureOrganizationMembership({ tenantId: 'default', organizationId: habeetatAdminOrgId, userId: platformAdminUserId });\n await ensureOrganizationMembership({ tenantId: 'default', organizationId: defaultTenantOrgId, userId: platformAdminUserId });\n\n await ensureOrganizationRoleAssignment({ tenantId: 'default', organizationId: defaultTenantOrgId, organizationRoleId: orgTenantAdminRoleId, userId: platformAdminUserId });\n await ensureOrganizationRoleAssignment({ tenantId: 'default', organizationId: defaultTenantOrgId, organizationRoleId: orgTenantUserRoleId, userId: platformAdminUserId });\n await ensureOrganizationRoleAssignment({ tenantId: 'default', organizationId: habeetatAdminOrgId, organizationRoleId: orgPlatformAdminRoleId, userId: platformAdminUserId });\n\n log(\\`Ensured user \\${platformAdminUsername} (\\${platformAdminEmail}, id: \\${platformAdminUserId})\\`);\n log('IAM bootstrap seed completed successfully.');\n}\n\nmain()\n .catch((error) => {\n console.error('[NHP][iam-seed] Failed:', error);\n process.exitCode = 1;\n })\n .finally(async () => {\n await pool.end();\n });\n`;\n}\n","/**\n * Generates a ClickHouse config override that forces IPv4-only listening.\n * Required on hosts where IPv6 is disabled — without this ClickHouse tries\n * to bind [::] first and fails, causing the healthcheck to never pass.\n */\nexport function generateClickhouseConfig(): string {\n return `<!-- ClickHouse config override: force IPv4-only listening -->\n<!-- Required on hosts with IPv6 disabled (AWS, DigitalOcean, etc.) -->\n<clickhouse>\n <listen_host>0.0.0.0</listen_host>\n</clickhouse>\n`;\n}\n\n/**\n * Generates the OpenTelemetry Collector configuration for SigNoz.\n * This YAML config is mounted into the otel-collector container.\n */\nexport function generateOtelCollectorConfig(): string {\n return `# SigNoz OpenTelemetry Collector Configuration\n# Auto-generated by @habeetat/cli\n\nreceivers:\n otlp:\n protocols:\n grpc:\n endpoint: 0.0.0.0:4317\n http:\n endpoint: 0.0.0.0:4318\n\nprocessors:\n batch:\n send_batch_size: 1000\n timeout: 5s\n resourcedetection:\n detectors:\n - env\n - system\n timeout: 2s\n\nexporters:\n clickhouselogsexporter:\n dsn: tcp://clickhouse:9000/?database=signoz_logs&username=default\n timeout: 10s\n clickhousetraces:\n dsn: tcp://clickhouse:9000/?database=signoz_traces&username=default\n timeout: 10s\n clickhousemetricswrite:\n dsn: tcp://clickhouse:9000/?database=signoz_metrics&username=default\n timeout: 10s\n\nservice:\n pipelines:\n logs:\n receivers: [otlp]\n processors: [batch]\n exporters: [clickhouselogsexporter]\n traces:\n receivers: [otlp]\n processors: [batch]\n exporters: [clickhousetraces]\n metrics:\n receivers: [otlp]\n processors: [batch]\n exporters: [clickhousemetricswrite]\n`;\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","../src/templates/bootstrap-script.ts","../src/templates/otel-collector-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 clickhouse: 'clickhouse/clickhouse-server:24.1.2-alpine',\n signozOtelCollector: 'signoz/signoz-otel-collector:0.88.22',\n signozQuery: 'signoz/query-service:0.45.0',\n signozFrontend: 'signoz/frontend:0.45.0',\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 'clickhouse',\n 'otel-collector',\n 'signoz-query-service',\n 'signoz-frontend',\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 ...(config.services.signoz && {\n OTEL_COLLECTOR_ENDPOINT: '${OTEL_COLLECTOR_ENDPOINT}',\n }),\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 // SigNoz observability stack (ClickHouse + OTel Collector + Query Service + Frontend)\n if (config.services.signoz) {\n services['clickhouse'] = {\n image: THIRD_PARTY_IMAGES.clickhouse,\n volumes: [\n 'clickhouse-data:/var/lib/clickhouse',\n 'clickhouse-logs:/var/log/clickhouse-server',\n './signoz/clickhouse-config.xml:/etc/clickhouse-server/config.d/habeetat-listen.xml:ro',\n ],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'clickhouse-client --host=127.0.0.1 --query=\"SELECT 1\" || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '60s',\n },\n };\n\n services['otel-collector'] = {\n image: THIRD_PARTY_IMAGES.signozOtelCollector,\n command: ['--config=/etc/otel-collector-config.yaml'],\n depends_on: {\n clickhouse: { condition: 'service_healthy' },\n },\n volumes: ['./signoz/otel-collector-config.yaml:/etc/otel-collector-config.yaml:ro'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n\n services['signoz-query-service'] = {\n image: THIRD_PARTY_IMAGES.signozQuery,\n depends_on: {\n clickhouse: { condition: 'service_healthy' },\n 'otel-collector': { condition: 'service_started' },\n },\n volumes: ['signoz-data:/var/lib/signoz'],\n environment: {\n ClickHouseUrl: 'tcp://clickhouse:9000',\n STORAGE: 'clickhouse',\n GODEBUG: 'netdns=go',\n SIGNOZ_LOCAL_DB_PATH: '/var/lib/signoz/signoz.db',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'wget -O- http://localhost:8080/api/v1/health 2>&1 | grep -q \"status\" || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '60s',\n },\n };\n\n services['signoz-frontend'] = {\n image: THIRD_PARTY_IMAGES.signozFrontend,\n depends_on: {\n 'signoz-query-service': { condition: 'service_healthy' },\n },\n environment: {\n FRONTEND_API_URL: 'http://signoz-query-service:8080',\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 if (config.services.signoz) nginxDependsOn.push('signoz-frontend');\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 ...(config.services.signoz && {\n 'clickhouse-data': null,\n 'clickhouse-logs': null,\n 'signoz-data': null,\n }),\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 if (config.services.signoz) upstreams.push('upstream signoz_frontend { server signoz-frontend:3301; }');\n\n const proto = config.platform.protocol;\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 ${proto};`;\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 // SigNoz Dashboard\n if (config.services.signoz) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name logs.${domain};\n location / {\n proxy_pass http://signoz_frontend;${proxyHeaders}\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection \"upgrade\";\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 if (config.services.signoz) subdomains.push('logs');\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# SSL will be added automatically by certbot --nginx\n\nserver {\n listen 80;\n server_name ${allServerNames};\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 clickhousePassword: randomHex(16),\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# SigNoz / OpenTelemetry (Observability)\n# ============================================\nSIGNOZ_URL=${protocol}://logs.${domain}\nOTEL_COLLECTOR_ENDPOINT=http://otel-collector:4317\nCLICKHOUSE_PASSWORD=${secrets.clickhousePassword}\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 composeDestroy(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down -v --remove-orphans`, {\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","// Logto IAM bootstrap seed script — embedded for scaffolding\n// This is the content of scripts/nhp-seed-logto-bootstrap.mjs\n// It runs inside a temporary Node container on the Docker network\n\nexport function getBootstrapScript(): string {\n return `#!/usr/bin/env node\nimport crypto from 'node:crypto';\n\nimport { argon2i } from 'hash-wasm';\nimport { customAlphabet } from 'nanoid';\nimport { Pool } from 'pg';\n\nconst alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst shortId = customAlphabet(alphabet, 12);\nconst longId = customAlphabet(alphabet, 21);\n\nconst connectionString =\n process.env.NHP_LOGTO_DB_URL ?? 'postgres://logto:logto@localhost:5434/logto';\n\nconst pool = new Pool({ connectionString });\n\nconst log = (message) => console.log(\\`[NHP][iam-seed] \\${message}\\`);\nconst json = (value) => JSON.stringify(value ?? {});\n\nasync function hashPassword(password) {\n return argon2i({\n password,\n salt: crypto.randomBytes(16),\n iterations: 256,\n parallelism: 1,\n memorySize: 4096,\n hashLength: 32,\n outputType: 'encoded',\n });\n}\n\nasync function ensureOrganization({ tenantId, id, name, description, customData }) {\n const orgId = id ?? longId();\n const { rows } = await pool.query(\n \\`insert into organizations (tenant_id, id, name, description, custom_data)\n values ($1, $2, $3, $4, $5::jsonb)\n on conflict (id) do update\n set tenant_id = excluded.tenant_id,\n name = excluded.name,\n description = excluded.description,\n custom_data = excluded.custom_data\n returning id\\`,\n [tenantId, orgId, name, description ?? name, json(customData)]\n );\n return rows[0].id;\n}\n\nasync function ensureOrganizationMembership({ tenantId, organizationId, userId }) {\n await pool.query(\n \\`insert into organization_user_relations (tenant_id, organization_id, user_id)\n values ($1, $2, $3)\n on conflict (tenant_id, organization_id, user_id) do nothing\\`,\n [tenantId, organizationId, userId]\n );\n}\n\nasync function ensureOrganizationRole({ tenantId, id, name, description }) {\n const roleId = id ?? longId();\n const { rows } = await pool.query(\n \\`insert into organization_roles (tenant_id, id, name, description)\n values ($1, $2, $3, $4)\n on conflict (id) do update\n set tenant_id = excluded.tenant_id,\n name = excluded.name,\n description = excluded.description\n returning id\\`,\n [tenantId, roleId, name, description ?? name]\n );\n return rows[0].id;\n}\n\nasync function ensureOrganizationRoleAssignment({ tenantId, organizationId, organizationRoleId, userId }) {\n await pool.query(\n \\`insert into organization_role_user_relations (tenant_id, organization_id, organization_role_id, user_id)\n values ($1, $2, $3, $4)\n on conflict (tenant_id, organization_id, organization_role_id, user_id) do nothing\\`,\n [tenantId, organizationId, organizationRoleId, userId]\n );\n}\n\nasync function ensureUser({ tenantId, username, email, password, displayName, customData, preferredId }) {\n let existingId;\n\n if (preferredId) {\n const byId = await pool.query('select id from users where id = $1 limit 1', [preferredId]);\n if (byId.rows.length > 0) existingId = byId.rows[0].id;\n }\n\n if (!existingId) {\n const byTenant = await pool.query(\n 'select id from users where tenant_id = $1 and (username = $2 or primary_email = $3) limit 1',\n [tenantId, username, email]\n );\n if (byTenant.rows.length > 0) existingId = byTenant.rows[0].id;\n }\n\n const passwordEncrypted = await hashPassword(password);\n const targetId = existingId ?? preferredId ?? shortId();\n\n if (existingId) {\n await pool.query(\n \\`update users\n set tenant_id = $1, username = $3, primary_email = $4,\n password_encrypted = $5, password_encryption_method = 'Argon2i',\n name = $6, custom_data = $7::jsonb\n where id = $2\\`,\n [tenantId, targetId, username, email, passwordEncrypted, displayName ?? username, json(customData)]\n );\n return targetId;\n }\n\n await pool.query(\n \\`insert into users (\n tenant_id, id, username, primary_email, password_encrypted, password_encryption_method,\n name, is_suspended, custom_data, profile, identities, logto_config, mfa_verifications\n ) values (\n $1, $2, $3, $4, $5, 'Argon2i', $6, false,\n $7::jsonb, '{}'::jsonb, '{}'::jsonb, '{}'::jsonb, '[]'::jsonb\n )\\`,\n [tenantId, targetId, username, email, passwordEncrypted, displayName ?? username, json(customData)]\n );\n return targetId;\n}\n\nasync function ensureAdminConsoleInitialized(tenantId) {\n const payload = { organizationCreated: true, signInExperienceCustomized: true };\n await pool.query(\n \\`insert into logto_configs (tenant_id, key, value)\n values ($1, 'adminConsole', $2::jsonb)\n on conflict (tenant_id, key) do update set value = excluded.value\\`,\n [tenantId, json(payload)]\n );\n}\n\nasync function ensureAdminTenantSignInMode() {\n await pool.query(\\`update sign_in_experiences set sign_in_mode = 'SignIn' where tenant_id = 'admin'\\`);\n log('Configured admin tenant sign-in mode.');\n}\n\nasync function ensureDefaultTenantSignInExperience() {\n await pool.query(\n \\`update sign_in_experiences\n set sign_in_mode = 'SignIn',\n sign_in = jsonb_build_object(\n 'methods', jsonb_build_array(\n jsonb_build_object('identifier', 'username', 'password', true, 'verificationCode', false, 'isPasswordPrimary', true),\n jsonb_build_object('identifier', 'email', 'password', true, 'verificationCode', false, 'isPasswordPrimary', true)\n )\n )\n where tenant_id = 'default'\\`\n );\n log('Configured default tenant sign-in experience.');\n}\n\nasync function ensureAdminAccountViaApi() {\n const username = process.env.NHP_PLATFORM_ADMIN_USERNAME ?? 'admin';\n const password = process.env.NHP_PLATFORM_ADMIN_PASSWORD ?? 'Habeetat_01';\n\n const { rows } = await pool.query(\n \\`select id from users where tenant_id = 'admin' and username = $1 limit 1\\`,\n [username]\n );\n\n const passwordEncrypted = await hashPassword(password);\n let adminUserId;\n\n if (rows.length === 0) {\n adminUserId = shortId();\n await pool.query(\n \\`INSERT INTO users (\n tenant_id, id, username, password_encrypted, password_encryption_method,\n name, is_suspended, custom_data, profile, identities, logto_config, mfa_verifications\n ) VALUES (\n 'admin', $1, $2, $3, 'Argon2i',\n $2, false, '{}'::jsonb, '{}'::jsonb, '{}'::jsonb, '{}'::jsonb, '[]'::jsonb\n )\\`,\n [adminUserId, username, passwordEncrypted]\n );\n log(\\`Created admin user via SQL (username: \\${username}, id: \\${adminUserId}).\\`);\n } else {\n adminUserId = rows[0].id;\n await pool.query(\n \\`UPDATE users SET password_encrypted = $1, password_encryption_method = 'Argon2i' WHERE id = $2\\`,\n [passwordEncrypted, adminUserId]\n );\n log(\\`Updated password for admin user \\${username} (id: \\${adminUserId}).\\`);\n }\n\n await pool.query(\n \\`INSERT INTO organization_user_relations (tenant_id, organization_id, user_id)\n VALUES ('admin', 't-default', $1) ON CONFLICT DO NOTHING\\`,\n [adminUserId]\n );\n\n await pool.query(\n \\`INSERT INTO organization_role_user_relations (tenant_id, organization_id, organization_role_id, user_id)\n VALUES ('admin', 't-default', 'admin', $1) ON CONFLICT DO NOTHING\\`,\n [adminUserId]\n );\n\n const { rows: allRoles } = await pool.query(\n \\`SELECT id FROM roles WHERE tenant_id = 'admin' AND type = 'User'\\`\n );\n\n for (const role of allRoles) {\n await pool.query(\n \\`INSERT INTO users_roles (tenant_id, id, user_id, role_id)\n VALUES ('admin', $1, $2, $3) ON CONFLICT (tenant_id, user_id, role_id) DO NOTHING\\`,\n [longId(), adminUserId, role.id]\n );\n }\n\n log('Admin account bootstrap via SQL completed.');\n}\n\nasync function main() {\n log('Starting IAM bootstrap seed...');\n\n const platformAdminUsername = process.env.NHP_PLATFORM_ADMIN_USERNAME ?? 'admin';\n const platformAdminEmail = process.env.NHP_PLATFORM_ADMIN_EMAIL ?? 'admin@habeetat.local';\n const platformAdminPassword = process.env.NHP_PLATFORM_ADMIN_PASSWORD ?? 'Habeetat_01';\n const platformAdminDisplayName = process.env.NHP_PLATFORM_ADMIN_DISPLAY_NAME ?? 'Platform Admin';\n const defaultTenantName = process.env.NHP_DEFAULT_TENANT_NAME ?? 'Default';\n const defaultTenantSlug = process.env.NHP_DEFAULT_TENANT_SLUG ?? 'default';\n\n const habeetatAdminOrgId = await ensureOrganization({\n tenantId: 'default',\n id: 'org_habeetat_admin',\n name: 'Habeetat Admin',\n description: 'Internal organization for Habeetat platform administrators',\n customData: { slug: 'habeetat-admin', type: 'internal' },\n });\n\n const defaultTenantOrgId = await ensureOrganization({\n tenantId: 'default',\n id: \\`org_\\${defaultTenantSlug}\\`,\n name: defaultTenantName,\n description: \\`Tenant organization: \\${defaultTenantName}\\`,\n customData: { slug: defaultTenantSlug, type: 'tenant' },\n });\n\n log(\\`Organizations ensured: Habeetat Admin (\\${habeetatAdminOrgId}), \\${defaultTenantName} (\\${defaultTenantOrgId})\\`);\n\n const orgTenantAdminRoleId = await ensureOrganizationRole({\n tenantId: 'default', id: 'org_role_tenant_admin', name: 'TENANT_ADMIN',\n description: 'Tenant administrator with full access to organization management',\n });\n\n const orgTenantUserRoleId = await ensureOrganizationRole({\n tenantId: 'default', id: 'org_role_tenant_user', name: 'TENANT_USER',\n description: 'Regular tenant user with launcher access',\n });\n\n const orgPlatformAdminRoleId = await ensureOrganizationRole({\n tenantId: 'default', id: 'org_role_plat_adm', name: 'PLATFORM_ADMIN',\n description: 'Platform administrator with access to Platform Manager',\n });\n\n log(\\`Organization roles ensured: TENANT_ADMIN=\\${orgTenantAdminRoleId}, TENANT_USER=\\${orgTenantUserRoleId}, PLATFORM_ADMIN=\\${orgPlatformAdminRoleId}\\`);\n\n await ensureAdminConsoleInitialized('default');\n await ensureAdminConsoleInitialized('admin');\n await ensureAdminTenantSignInMode();\n await ensureDefaultTenantSignInExperience();\n await ensureAdminAccountViaApi();\n\n const platformAdminUserId = await ensureUser({\n tenantId: 'default',\n preferredId: 'usr_admin01',\n username: platformAdminUsername,\n email: platformAdminEmail,\n password: platformAdminPassword,\n displayName: platformAdminDisplayName,\n customData: { tenantSlug: defaultTenantSlug },\n });\n\n await ensureOrganizationMembership({ tenantId: 'default', organizationId: habeetatAdminOrgId, userId: platformAdminUserId });\n await ensureOrganizationMembership({ tenantId: 'default', organizationId: defaultTenantOrgId, userId: platformAdminUserId });\n\n await ensureOrganizationRoleAssignment({ tenantId: 'default', organizationId: defaultTenantOrgId, organizationRoleId: orgTenantAdminRoleId, userId: platformAdminUserId });\n await ensureOrganizationRoleAssignment({ tenantId: 'default', organizationId: defaultTenantOrgId, organizationRoleId: orgTenantUserRoleId, userId: platformAdminUserId });\n await ensureOrganizationRoleAssignment({ tenantId: 'default', organizationId: habeetatAdminOrgId, organizationRoleId: orgPlatformAdminRoleId, userId: platformAdminUserId });\n\n log(\\`Ensured user \\${platformAdminUsername} (\\${platformAdminEmail}, id: \\${platformAdminUserId})\\`);\n log('IAM bootstrap seed completed successfully.');\n}\n\nmain()\n .catch((error) => {\n console.error('[NHP][iam-seed] Failed:', error);\n process.exitCode = 1;\n })\n .finally(async () => {\n await pool.end();\n });\n`;\n}\n","/**\n * Generates a ClickHouse config override that forces IPv4-only listening.\n * Required on hosts where IPv6 is disabled — without this ClickHouse tries\n * to bind [::] first and fails, causing the healthcheck to never pass.\n */\nexport function generateClickhouseConfig(): string {\n return `<!-- ClickHouse config override: force IPv4-only listening -->\n<!-- Required on hosts with IPv6 disabled (AWS, DigitalOcean, etc.) -->\n<clickhouse>\n <listen_host>0.0.0.0</listen_host>\n</clickhouse>\n`;\n}\n\n/**\n * Generates the OpenTelemetry Collector configuration for SigNoz.\n * This YAML config is mounted into the otel-collector container.\n */\nexport function generateOtelCollectorConfig(): string {\n return `# SigNoz OpenTelemetry Collector Configuration\n# Auto-generated by @habeetat/cli\n\nreceivers:\n otlp:\n protocols:\n grpc:\n endpoint: 0.0.0.0:4317\n http:\n endpoint: 0.0.0.0:4318\n\nprocessors:\n batch:\n send_batch_size: 1000\n timeout: 5s\n resourcedetection:\n detectors:\n - env\n - system\n timeout: 2s\n\nexporters:\n clickhouselogsexporter:\n dsn: tcp://clickhouse:9000/\n timeout: 10s\n docker_multi_node_cluster: false\n clickhousetraces:\n datasource: tcp://clickhouse:9000/\n docker_multi_node_cluster: false\n clickhousemetricswrite:\n endpoint: tcp://clickhouse:9000/\n resource_to_telemetry_conversion:\n enabled: true\n\nservice:\n pipelines:\n logs:\n receivers: [otlp]\n processors: [batch]\n exporters: [clickhouselogsexporter]\n traces:\n receivers: [otlp]\n processors: [batch]\n exporters: [clickhousetraces]\n metrics:\n receivers: [otlp]\n processors: [batch]\n exporters: [clickhousemetricswrite]\n`;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@habeetat/cli",
3
- "version": "0.1.0-dev.20260325113236.a098d49",
3
+ "version": "0.1.0-dev.20260325114836.5178446",
4
4
  "description": "Habeetat Platform CLI — manage your platform instances",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",