@habeetat/cli 0.1.0-dev.20260324163104.863c721 → 0.1.0-dev.20260324163755.655b5ac
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +25 -8
- package/dist/bin.js.map +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -472,9 +472,9 @@ async function initPlatform(projectDir) {
|
|
|
472
472
|
const bootstrapScriptPath = path__default.default.join(projectDir, "scripts", "nhp-seed-logto-bootstrap.mjs");
|
|
473
473
|
const hasLocalScript = fs2__default.default.existsSync(bootstrapScriptPath);
|
|
474
474
|
if (hasLocalScript) {
|
|
475
|
-
await execa.
|
|
475
|
+
await execa.execa(
|
|
476
|
+
"docker",
|
|
476
477
|
[
|
|
477
|
-
"docker",
|
|
478
478
|
"run",
|
|
479
479
|
"--rm",
|
|
480
480
|
"--network",
|
|
@@ -488,7 +488,7 @@ async function initPlatform(projectDir) {
|
|
|
488
488
|
"-e",
|
|
489
489
|
`NHP_PLATFORM_ADMIN_PASSWORD=${adminPassword}`,
|
|
490
490
|
"-e",
|
|
491
|
-
|
|
491
|
+
`NHP_PLATFORM_ADMIN_DISPLAY_NAME=Platform Admin`,
|
|
492
492
|
"-e",
|
|
493
493
|
`NHP_DEFAULT_TENANT_NAME=${orgName}`,
|
|
494
494
|
"-e",
|
|
@@ -501,7 +501,7 @@ async function initPlatform(projectDir) {
|
|
|
501
501
|
"sh",
|
|
502
502
|
"-c",
|
|
503
503
|
"npm init -y >/dev/null 2>&1 && npm install --no-package-lock pg hash-wasm nanoid 2>/dev/null && node bootstrap.mjs"
|
|
504
|
-
]
|
|
504
|
+
],
|
|
505
505
|
{ cwd: projectDir, stdio: "pipe" }
|
|
506
506
|
);
|
|
507
507
|
bootstrapSpinner.succeed("Logto users and organizations bootstrapped");
|
|
@@ -540,10 +540,27 @@ async function initPlatform(projectDir) {
|
|
|
540
540
|
const orgName = env.ORGANIZATION_NAME || config.platform.organization || "Default";
|
|
541
541
|
const orgSlug = orgName.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
|
|
542
542
|
const adminEmail = env.PLATFORM_ADMIN_EMAIL || config.platform.adminEmail;
|
|
543
|
-
await execa.
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
543
|
+
await execa.execa("docker", [
|
|
544
|
+
"compose",
|
|
545
|
+
"-f",
|
|
546
|
+
COMPOSE_FILE,
|
|
547
|
+
"exec",
|
|
548
|
+
"-T",
|
|
549
|
+
"-e",
|
|
550
|
+
`NHP_PLATFORM_ADMIN_USER=${adminEmail.split("@")[0]}`,
|
|
551
|
+
"-e",
|
|
552
|
+
`NHP_PLATFORM_ADMIN_EMAIL=${adminEmail}`,
|
|
553
|
+
"-e",
|
|
554
|
+
`NHP_PLATFORM_ADMIN_DISPLAY_NAME=Platform Admin`,
|
|
555
|
+
"-e",
|
|
556
|
+
`NHP_DEFAULT_TENANT_NAME=${orgName}`,
|
|
557
|
+
"-e",
|
|
558
|
+
`NHP_DEFAULT_TENANT_SLUG=${orgSlug}`,
|
|
559
|
+
"backend",
|
|
560
|
+
"npx",
|
|
561
|
+
"tsx",
|
|
562
|
+
"prisma/seed.ts"
|
|
563
|
+
], { cwd: projectDir, stdio: "pipe" });
|
|
547
564
|
seedSpinner.succeed("Platform database seeded");
|
|
548
565
|
} catch {
|
|
549
566
|
seedSpinner.warn("Prisma seed skipped (may not be available in Docker image)");
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/logger.ts","../src/constants.ts","../src/utils/config.ts","../src/utils/docker.ts","../src/commands/init.ts","../src/commands/up.ts","../src/commands/down.ts","../src/commands/status.ts","../src/commands/logs.ts","../src/commands/restart.ts","../src/commands/doctor.ts","../src/commands/destroy.ts","../src/bin.ts"],"names":["chalk","path","fs","execaCommand","ora","createInterface","readFileSync","Command"],"mappings":"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","file":"bin.js","sourcesContent":["import chalk from 'chalk';\n\nconst prefix = chalk.cyan('[habeetat]');\n\nexport const logger = {\n info: (msg: string) => console.log(`${prefix} ${msg}`),\n success: (msg: string) => console.log(`${prefix} ${chalk.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(`${prefix} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${prefix} ${chalk.red('✗')} ${msg}`),\n phase: (msg: string) => {\n console.log('');\n console.log(chalk.cyan('═'.repeat(56)));\n console.log(chalk.cyan(` ${msg}`));\n console.log(chalk.cyan('═'.repeat(56)));\n console.log('');\n },\n banner: () => {\n console.log('');\n console.log(chalk.cyan('╔══════════════════════════════════════════════╗'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('║ Habeetat Platform CLI ║'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('╚══════════════════════════════════════════════╝'));\n console.log('');\n },\n};\n","export const CONFIG_FILE = 'habeetat.json';\nexport const ENV_FILE = '.env';\nexport const COMPOSE_FILE = 'docker-compose.yml';\n\nexport const DOCKER_REGISTRY = 'docker.io/capriisland';\n\nexport const IMAGES = {\n backend: 'capriisland/habeetat-backend',\n launcher: 'capriisland/habeetat-launcher',\n orgManager: 'capriisland/habeetat-org-manager',\n platformManager: 'capriisland/habeetat-platform-manager',\n sampleCrm: 'capriisland/habeetat-sample-crm',\n logtoConfig: 'capriisland/habeetat-logto-config',\n} as const;\n\nexport const THIRD_PARTY_IMAGES = {\n postgres: 'postgres:15-alpine',\n logto: 'svhd/logto:1.33',\n nginx: 'nginx:1.25-alpine',\n certbot: 'certbot/certbot',\n} as const;\n\nexport const DEFAULT_PORTS = {\n http: 80,\n https: 443,\n hostNginx: 8080,\n} as const;\n\nexport const SERVICES = [\n 'logto-db',\n 'platform-db',\n 'logto-core',\n 'backend',\n 'launcher',\n 'organization-manager',\n 'platform-manager',\n 'sample-crm',\n 'nginx',\n] as const;\n\nexport type ServiceName = (typeof SERVICES)[number];\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE } from '../constants.js';\nimport type { HabeetatConfig } from '../types.js';\n\nexport function findProjectRoot(startDir: string = process.cwd()): string | null {\n let dir = startDir;\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, CONFIG_FILE))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nexport function loadConfig(projectDir?: string): HabeetatConfig {\n const dir = projectDir || findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n const configPath = path.join(dir, CONFIG_FILE);\n const raw = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as HabeetatConfig;\n}\n\nexport function saveConfig(config: HabeetatConfig, projectDir: string): void {\n const configPath = path.join(projectDir, CONFIG_FILE);\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function getProjectDir(): string {\n const dir = findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n return dir;\n}\n","import { execaCommand } from 'execa';\nimport { logger } from './logger.js';\n\nexport async function checkDocker(): Promise<boolean> {\n try {\n const { stdout } = await execaCommand('docker --version');\n const match = stdout.match(/Docker version (\\d+)/);\n if (match && parseInt(match[1], 10) >= 20) {\n return true;\n }\n logger.error(`Docker >= 20.0 required. Found: ${stdout.trim()}`);\n return false;\n } catch {\n logger.error('Docker is not installed or not in PATH');\n logger.info('Install Docker: https://docs.docker.com/get-docker/');\n return false;\n }\n}\n\nexport async function checkDockerCompose(): Promise<boolean> {\n try {\n await execaCommand('docker compose version');\n return true;\n } catch {\n logger.error('Docker Compose V2 is not available');\n logger.info('Docker Compose V2 is included with Docker Desktop');\n return false;\n }\n}\n\nexport async function checkPrerequisites(): Promise<boolean> {\n const docker = await checkDocker();\n const compose = await checkDockerCompose();\n return docker && compose;\n}\n\nexport interface ComposeExecOptions {\n cwd: string;\n composeFile?: string;\n silent?: boolean;\n}\n\nexport async function composeUp(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} up -d`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeDown(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function 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 ora from 'ora';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { execaCommand } from 'execa';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { COMPOSE_FILE } from '../constants.js';\n\nconst INITIALIZED_FILE = '.initialized';\n\nexport function isInitialized(projectDir: string): boolean {\n return fs.existsSync(path.join(projectDir, INITIALIZED_FILE));\n}\n\nfunction markInitialized(projectDir: string): void {\n fs.writeFileSync(\n path.join(projectDir, INITIALIZED_FILE),\n JSON.stringify({ initializedAt: new Date().toISOString() }, null, 2) + '\\n',\n );\n}\n\nfunction loadEnv(projectDir: string): Record<string, string> {\n const envPath = path.join(projectDir, '.env');\n if (!fs.existsSync(envPath)) return {};\n const lines = fs.readFileSync(envPath, 'utf-8').split('\\n');\n const env: Record<string, string> = {};\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIdx = trimmed.indexOf('=');\n if (eqIdx === -1) continue;\n env[trimmed.slice(0, eqIdx)] = trimmed.slice(eqIdx + 1);\n }\n return env;\n}\n\nasync function execCompose(projectDir: string, args: string): Promise<string> {\n const { stdout } = await execaCommand(\n `docker compose -f ${COMPOSE_FILE} ${args}`,\n { cwd: projectDir },\n );\n return stdout;\n}\n\nasync function waitForService(\n projectDir: string,\n service: string,\n checkCmd: string,\n timeoutSec: number,\n): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutSec * 1000) {\n try {\n await execCompose(projectDir, `exec -T ${service} ${checkCmd}`);\n return true;\n } catch {\n await new Promise((r) => setTimeout(r, 3000));\n }\n }\n return false;\n}\n\nfunction buildSeedLogtoAppsSql(env: Record<string, string>): string {\n const protocol = env.PROTOCOL || 'https';\n const domain = env.DOMAIN || 'localhost';\n const launcherUrl = env.LAUNCHER_URL || `${protocol}://launcher.${domain}`;\n const orgManagerUrl = env.ORG_MANAGER_URL || `${protocol}://organization-manager.${domain}`;\n const platformManagerUrl = env.PLATFORM_MANAGER_URL || `${protocol}://platform-manager.${domain}`;\n const sampleCrmUrl = env.SAMPLE_CRM_URL || `${protocol}://sample-crm.${domain}`;\n const apiResource = env.IAM_AUDIENCE || `${protocol}://api.${domain}/api`;\n const m2mAppId = 'nhp-m2m-config';\n const m2mAppSecret = env.LOGTO_M2M_APP_SECRET || '';\n\n return `BEGIN;\n\n-- API Resource\nINSERT INTO resources (tenant_id, id, name, indicator, is_default, access_token_ttl)\nVALUES ('default', 'nhp-backend-resource', 'NHP Backend API', '${apiResource}', false, 3600)\nON CONFLICT (id) DO UPDATE\nSET name = EXCLUDED.name, indicator = EXCLUDED.indicator, access_token_ttl = EXCLUDED.access_token_ttl;\n\n-- Scope for API Resource\nINSERT INTO scopes (tenant_id, id, resource_id, name, description)\nVALUES ('default', 'nhp-backend-scope', 'nhp-backend-resource', 'nhp:all', 'Full access to NHP backend API')\nON CONFLICT (id) DO UPDATE\nSET resource_id = EXCLUDED.resource_id, name = EXCLUDED.name, description = EXCLUDED.description;\n\n-- Launcher SPA\nINSERT INTO applications (tenant_id, id, name, secret, description, type, oidc_client_metadata, custom_client_metadata, is_third_party)\nVALUES (\n 'default', 'nhp-launcher', 'Habeetat Launcher', 'spa-secret-nhp-launcher', 'Main launcher application', 'SPA',\n jsonb_build_object('redirectUris', ARRAY['${launcherUrl}', '${launcherUrl}/callback'], 'postLogoutRedirectUris', ARRAY['${launcherUrl}']),\n '{}'::jsonb, false\n) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description, type = EXCLUDED.type, oidc_client_metadata = EXCLUDED.oidc_client_metadata;\n\n-- Organization Manager SPA\nINSERT INTO applications (tenant_id, id, name, secret, description, type, oidc_client_metadata, custom_client_metadata, is_third_party)\nVALUES (\n 'default', 'nhp-org-manager', 'Organization Manager', 'spa-secret-nhp-org-manager', 'Organization management application', 'SPA',\n jsonb_build_object('redirectUris', ARRAY['${orgManagerUrl}', '${orgManagerUrl}/callback'], 'postLogoutRedirectUris', ARRAY['${orgManagerUrl}']),\n '{}'::jsonb, false\n) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description, type = EXCLUDED.type, oidc_client_metadata = EXCLUDED.oidc_client_metadata;\n\n-- Platform Manager SPA\nINSERT INTO applications (tenant_id, id, name, secret, description, type, oidc_client_metadata, custom_client_metadata, is_third_party)\nVALUES (\n 'default', 'nhp-plat-mgr', 'Platform Manager', 'spa-secret-nhp-plat-mgr', 'Platform administration application', 'SPA',\n jsonb_build_object('redirectUris', ARRAY['${platformManagerUrl}', '${platformManagerUrl}/callback'], 'postLogoutRedirectUris', ARRAY['${platformManagerUrl}']),\n '{}'::jsonb, false\n) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description, type = EXCLUDED.type, oidc_client_metadata = EXCLUDED.oidc_client_metadata;\n\n-- Sample CRM SPA\nINSERT INTO applications (tenant_id, id, name, secret, description, type, oidc_client_metadata, custom_client_metadata, is_third_party)\nVALUES (\n 'default', 'nhp-sample-crm', 'Sample CRM', 'spa-secret-nhp-sample-crm', 'Sample CRM application', 'SPA',\n jsonb_build_object('redirectUris', ARRAY['${sampleCrmUrl}', '${sampleCrmUrl}/callback'], 'postLogoutRedirectUris', ARRAY['${sampleCrmUrl}']),\n '{}'::jsonb, false\n) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description, type = EXCLUDED.type, oidc_client_metadata = EXCLUDED.oidc_client_metadata;\n\n-- M2M Application for backend\nINSERT INTO applications (tenant_id, id, name, secret, description, type, oidc_client_metadata, custom_client_metadata, is_third_party)\nVALUES (\n 'default', '${m2mAppId}', 'NHP M2M Config', '${m2mAppSecret}', 'Machine-to-machine application for backend services', 'MachineToMachine',\n jsonb_build_object('redirectUris', ARRAY[]::text[], 'postLogoutRedirectUris', ARRAY[]::text[]),\n '{}'::jsonb, false\n) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, secret = EXCLUDED.secret, description = EXCLUDED.description, type = EXCLUDED.type;\n\n-- Assign Management API role to M2M app\nDO $$\nDECLARE\n v_role_id TEXT;\nBEGIN\n SELECT id INTO v_role_id FROM roles\n WHERE tenant_id = 'default' AND name = 'Logto Management API access' AND type = 'MachineToMachine'\n LIMIT 1;\n\n IF v_role_id IS NULL THEN\n v_role_id := 'role_m2m_mgmt_api';\n INSERT INTO roles (tenant_id, id, name, description, type)\n VALUES ('default', v_role_id, 'Logto Management API access', 'Access to Logto Management API', 'MachineToMachine');\n\n INSERT INTO roles_scopes (tenant_id, id, role_id, scope_id)\n SELECT 'default', 'rs_' || s.id, v_role_id, s.id\n FROM scopes s WHERE s.resource_id = 'management-api' AND s.tenant_id = 'default'\n ON CONFLICT DO NOTHING;\n END IF;\n\n INSERT INTO applications_roles (tenant_id, id, application_id, role_id)\n VALUES ('default', 'ar_m2m_${m2mAppId}', '${m2mAppId}', v_role_id)\n ON CONFLICT DO NOTHING;\nEND $$;\n\n-- Update admin-console redirect URIs\nUPDATE applications\nSET oidc_client_metadata = jsonb_build_object(\n 'redirectUris', ARRAY['${protocol}://iam-console.${domain}/callback'],\n 'postLogoutRedirectUris', ARRAY['${protocol}://iam-console.${domain}']\n)\nWHERE id = 'admin-console' AND tenant_id = 'admin';\n\nCOMMIT;`;\n}\n\nfunction buildInitPlatformSql(env: Record<string, string>): string {\n const protocol = env.PROTOCOL || 'https';\n const domain = env.DOMAIN || 'localhost';\n const adminEmail = env.PLATFORM_ADMIN_EMAIL || 'admin@habeetat.local';\n const orgName = env.ORGANIZATION_NAME || 'Default Organization';\n const orgSlug = orgName.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '');\n\n return `\n-- Seed system applications\nINSERT INTO applications (id, slug, name, description, category, is_internal, is_system_app, is_hidden, auto_install, status, logto_app_id, created_at, updated_at)\nVALUES\n ('app_launcher', 'launcher', 'Habeetat Launcher', 'Main launcher and navigation hub', 'system', true, true, true, true, 'PUBLISHED', 'nhp-launcher', NOW(), NOW()),\n ('app_org_manager', 'organization-manager', 'Organization Manager', 'Manage organizations, users and roles', 'system', true, true, false, true, 'PUBLISHED', 'nhp-org-manager', NOW(), NOW()),\n ('app_plat_manager', 'platform-manager', 'Platform Manager', 'Platform administration and configuration', 'system', true, true, true, false, 'PUBLISHED', 'nhp-plat-mgr', NOW(), NOW()),\n ('app_sample_crm', 'sample-crm', 'Sample CRM', 'Sample CRM application for demonstration', 'demo', true, false, false, false, 'PUBLISHED', 'nhp-sample-crm', NOW(), NOW())\nON CONFLICT (slug) DO UPDATE SET\n name = EXCLUDED.name,\n description = EXCLUDED.description,\n logto_app_id = EXCLUDED.logto_app_id,\n is_system_app = EXCLUDED.is_system_app,\n is_hidden = EXCLUDED.is_hidden,\n auto_install = EXCLUDED.auto_install,\n status = EXCLUDED.status;\n\n-- Create initial versions for system apps\nINSERT INTO application_versions (id, app_id, version, manifest, status, created_at)\nVALUES\n ('ver_launcher_100', 'app_launcher', '1.0.0', jsonb_build_object('endpoints', jsonb_build_object('main', '${protocol}://launcher.${domain}')), 'ACTIVE', NOW()),\n ('ver_org_manager_100', 'app_org_manager', '1.0.0', jsonb_build_object('endpoints', jsonb_build_object('main', '${protocol}://organization-manager.${domain}')), 'ACTIVE', NOW()),\n ('ver_plat_manager_100', 'app_plat_manager', '1.0.0', jsonb_build_object('endpoints', jsonb_build_object('main', '${protocol}://platform-manager.${domain}')), 'ACTIVE', NOW()),\n ('ver_sample_crm_100', 'app_sample_crm', '1.0.0', jsonb_build_object('endpoints', jsonb_build_object('main', '${protocol}://sample-crm.${domain}')), 'ACTIVE', NOW())\nON CONFLICT (app_id, version) DO UPDATE SET manifest = EXCLUDED.manifest;\n\n-- Create default tenant\nINSERT INTO tenants (id, display_name, slug, status, created_at, updated_at)\nSELECT\n 'tenant_${orgSlug}',\n '${orgName}',\n '${orgSlug}',\n 'ACTIVE',\n NOW(),\n NOW()\nWHERE NOT EXISTS (\n SELECT 1 FROM tenants WHERE slug = '${orgSlug}'\n);\n\n-- Initialize tenant, admin user, roles, memberships, and app installations\nDO $$\nDECLARE\n v_tenant_id TEXT;\n v_user_id TEXT;\n v_admin_role_id TEXT;\nBEGIN\n SELECT id INTO v_tenant_id FROM tenants WHERE slug = '${orgSlug}' LIMIT 1;\n\n IF v_tenant_id IS NULL THEN\n RAISE NOTICE 'Tenant not found, skipping user setup';\n RETURN;\n END IF;\n\n SELECT id INTO v_user_id FROM users\n WHERE external_identity_id = 'usr_admin01'\n OR primary_email = '${adminEmail}'\n LIMIT 1;\n\n IF v_user_id IS NULL THEN\n v_user_id := 'usr_plat_admin01';\n INSERT INTO users (id, external_identity_id, primary_email, username, display_name, status, created_at, updated_at)\n VALUES (v_user_id, 'usr_admin01', '${adminEmail}', 'admin', 'Platform Admin', 'ACTIVE', NOW(), NOW());\n ELSE\n UPDATE users SET external_identity_id = 'usr_admin01'\n WHERE id = v_user_id AND external_identity_id IS NULL;\n END IF;\n\n SELECT id INTO v_admin_role_id FROM tenant_roles WHERE name = 'TENANT_ADMIN' LIMIT 1;\n\n IF v_admin_role_id IS NULL THEN\n v_admin_role_id := 'role_tenant_admin';\n INSERT INTO tenant_roles (id, name, description, created_at, updated_at)\n VALUES (v_admin_role_id, 'TENANT_ADMIN', 'Tenant Administrator', NOW(), NOW());\n END IF;\n\n INSERT INTO tenant_memberships (id, user_id, tenant_id, status, created_at, updated_at)\n SELECT 'tm_admin_${orgSlug}', v_user_id, v_tenant_id, 'ACTIVE', NOW(), NOW()\n WHERE NOT EXISTS (\n SELECT 1 FROM tenant_memberships WHERE user_id = v_user_id AND tenant_id = v_tenant_id\n );\n\n INSERT INTO tenant_membership_roles (id, membership_id, role_id, created_at)\n SELECT 'tmr_admin_${orgSlug}', 'tm_admin_${orgSlug}', v_admin_role_id, NOW()\n WHERE NOT EXISTS (\n SELECT 1 FROM tenant_membership_roles\n WHERE membership_id = 'tm_admin_${orgSlug}' AND role_id = v_admin_role_id\n );\nEND $$;\n\n-- Auto-install published non-hidden apps for the default tenant\nINSERT INTO tenant_application_installations (id, tenant_id, app_id, app_version_id, status, is_enabled, installed_at, updated_at)\nSELECT 'tai_${orgSlug}_' || a.slug, t.id, a.id, v.id, 'INSTALLED', true, NOW(), NOW()\nFROM tenants t\nJOIN applications a ON a.status = 'PUBLISHED' AND a.is_hidden = false\nJOIN application_versions v ON v.app_id = a.id AND v.version = '1.0.0'\nWHERE t.slug = '${orgSlug}'\nON CONFLICT (tenant_id, app_id) DO NOTHING;`;\n}\n\nexport async function initPlatform(projectDir: string): Promise<void> {\n const config = loadConfig(projectDir);\n const env = loadEnv(projectDir);\n const domain = config.platform.domain;\n\n // --- Phase 1: Wait for databases ---\n const dbSpinner = ora('Waiting for databases...').start();\n\n const logtoDbReady = await waitForService(\n projectDir, 'logto-db', 'pg_isready -U logto -d logto', 60,\n );\n if (!logtoDbReady) {\n dbSpinner.fail('logto-db did not become ready');\n throw new Error('logto-db timeout');\n }\n\n const platformDbReady = await waitForService(\n projectDir, 'platform-db',\n `pg_isready -U ${env.PLATFORM_DB_USER || 'habeetat'} -d ${env.PLATFORM_DB_NAME || 'habeetat_platform'}`,\n 60,\n );\n if (!platformDbReady) {\n dbSpinner.fail('platform-db did not become ready');\n throw new Error('platform-db timeout');\n }\n dbSpinner.succeed('Databases ready');\n\n // --- Phase 2: Wait for Logto to be healthy ---\n const logtoSpinner = ora('Waiting for Logto to be healthy (this may take up to 2 min)...').start();\n const logtoReady = await waitForService(\n projectDir, 'logto-core',\n 'wget -q --spider http://localhost:3001/oidc/.well-known/openid-configuration',\n 180,\n );\n if (!logtoReady) {\n logtoSpinner.fail('logto-core did not become healthy');\n throw new Error('logto-core timeout');\n }\n logtoSpinner.succeed('Logto is healthy');\n\n // --- Phase 3: Seed Logto applications (SQL) ---\n const logtoSeedSpinner = ora('Seeding Logto applications...').start();\n try {\n const sql = buildSeedLogtoAppsSql(env);\n await execaCommand(\n `docker compose -f ${COMPOSE_FILE} exec -T logto-db psql -U logto -d logto`,\n { cwd: projectDir, input: sql },\n );\n logtoSeedSpinner.succeed('Logto applications seeded');\n } catch (err) {\n logtoSeedSpinner.fail('Failed to seed Logto applications');\n logger.error(String(err));\n throw err;\n }\n\n // --- Phase 4: Bootstrap Logto users/orgs/roles (via Node container) ---\n const bootstrapSpinner = ora('Bootstrapping Logto users and organizations...').start();\n try {\n const orgName = env.ORGANIZATION_NAME || config.platform.organization || 'Default';\n const orgSlug = orgName.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '');\n const adminEmail = env.PLATFORM_ADMIN_EMAIL || config.platform.adminEmail;\n const adminPassword = env.PLATFORM_ADMIN_PASSWORD || 'Habeetat_01';\n const adminUsername = adminEmail.split('@')[0];\n const logtoDbUrl = `postgres://${env.LOGTO_DB_USER || 'logto'}:${env.LOGTO_DB_PASSWORD || 'logto'}@logto-db:5432/${env.LOGTO_DB_NAME || 'logto'}`;\n\n const bootstrapScriptPath = path.join(projectDir, 'scripts', 'nhp-seed-logto-bootstrap.mjs');\n const hasLocalScript = fs.existsSync(bootstrapScriptPath);\n\n if (hasLocalScript) {\n await execaCommand(\n [\n 'docker', 'run', '--rm', '--network', 'habeetat_habeetat-network',\n '-e', `NHP_LOGTO_DB_URL=${logtoDbUrl}`,\n '-e', `NHP_PLATFORM_ADMIN_USERNAME=${adminUsername}`,\n '-e', `NHP_PLATFORM_ADMIN_EMAIL=${adminEmail}`,\n '-e', `NHP_PLATFORM_ADMIN_PASSWORD=${adminPassword}`,\n '-e', 'NHP_PLATFORM_ADMIN_DISPLAY_NAME=Platform Admin',\n '-e', `NHP_DEFAULT_TENANT_NAME=${orgName}`,\n '-e', `NHP_DEFAULT_TENANT_SLUG=${orgSlug}`,\n '-v', `${bootstrapScriptPath}:/app/bootstrap.mjs:ro`,\n '-w', '/app',\n 'node:20-alpine',\n 'sh', '-c', 'npm init -y >/dev/null 2>&1 && npm install --no-package-lock pg hash-wasm nanoid 2>/dev/null && node bootstrap.mjs',\n ].join(' '),\n { cwd: projectDir, stdio: 'pipe' },\n );\n bootstrapSpinner.succeed('Logto users and organizations bootstrapped');\n } else {\n bootstrapSpinner.warn('Bootstrap script not found — skipping Logto user/org setup');\n logger.info('You may need to create the admin user manually via the Logto admin console');\n }\n } catch (err) {\n bootstrapSpinner.fail('Logto bootstrap failed');\n logger.error(String(err));\n logger.info('You may need to create the admin user manually via the Logto admin console');\n }\n\n // --- Phase 5: Wait for backend ---\n const backendSpinner = ora('Waiting for backend...').start();\n const backendReady = await waitForService(\n projectDir, 'backend', 'curl -sf http://localhost:3001/platform/status', 120,\n );\n if (!backendReady) {\n backendSpinner.fail('Backend did not become healthy');\n throw new Error('backend timeout');\n }\n backendSpinner.succeed('Backend is healthy');\n\n // --- Phase 6: Run Prisma migrations ---\n const migrateSpinner = ora('Running database migrations...').start();\n try {\n await execCompose(projectDir, 'exec -T backend npx prisma migrate deploy');\n migrateSpinner.succeed('Database migrations completed');\n } catch (err) {\n migrateSpinner.fail('Migrations failed');\n logger.error(String(err));\n logger.info('Run manually: docker compose exec backend npx prisma migrate deploy');\n }\n\n // --- Phase 7: Run Prisma seed ---\n const seedSpinner = ora('Seeding platform database...').start();\n try {\n const orgName = env.ORGANIZATION_NAME || config.platform.organization || 'Default';\n const orgSlug = orgName.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '');\n const adminEmail = env.PLATFORM_ADMIN_EMAIL || config.platform.adminEmail;\n\n await execaCommand(\n `docker compose -f ${COMPOSE_FILE} exec -T -e NHP_PLATFORM_ADMIN_USER=${adminEmail.split('@')[0]} -e NHP_PLATFORM_ADMIN_EMAIL=${adminEmail} -e \"NHP_PLATFORM_ADMIN_DISPLAY_NAME=Platform Admin\" -e \"NHP_DEFAULT_TENANT_NAME=${orgName}\" -e \"NHP_DEFAULT_TENANT_SLUG=${orgSlug}\" backend npx tsx prisma/seed.ts`,\n { cwd: projectDir, stdio: 'pipe' },\n );\n seedSpinner.succeed('Platform database seeded');\n } catch {\n seedSpinner.warn('Prisma seed skipped (may not be available in Docker image)');\n }\n\n // --- Phase 8: Initialize platform SQL (system apps, tenant, admin) ---\n const platformSpinner = ora('Initializing platform data...').start();\n try {\n const sql = buildInitPlatformSql(env);\n await execaCommand(\n `docker compose -f ${COMPOSE_FILE} exec -T platform-db psql -U ${env.PLATFORM_DB_USER || 'habeetat'} -d ${env.PLATFORM_DB_NAME || 'habeetat_platform'}`,\n { cwd: projectDir, input: sql },\n );\n platformSpinner.succeed('Platform data initialized');\n } catch (err) {\n platformSpinner.fail('Platform initialization failed');\n logger.error(String(err));\n logger.info('You may need to initialize the platform manually after first login');\n }\n\n // Mark as initialized\n markInitialized(projectDir);\n\n console.log('');\n logger.info(`✓ Platform initialized for ${domain}`);\n logger.info(` Admin: ${env.PLATFORM_ADMIN_EMAIL || config.platform.adminEmail}`);\n logger.info(` Organization: ${env.ORGANIZATION_NAME || config.platform.organization}`);\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composeUp, checkPrerequisites } from '../utils/docker.js';\nimport { isInitialized, initPlatform } from './init.js';\n\nexport async function upCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n\n logger.info(`Starting Habeetat Platform (${config.platform.domain})...`);\n\n if (!(await checkPrerequisites())) {\n process.exit(1);\n }\n\n const freshInstall = !isInitialized(projectDir);\n const spinner = ora('Starting services...').start();\n\n try {\n await composeUp({ cwd: projectDir });\n spinner.succeed('All services started');\n } catch (err) {\n spinner.fail('Failed to start services');\n logger.error(String(err));\n process.exit(1);\n }\n\n if (freshInstall) {\n console.log('');\n logger.info('First run detected — initializing platform...');\n console.log('');\n try {\n await initPlatform(projectDir);\n } catch (err) {\n logger.error('Platform initialization failed');\n logger.error(String(err));\n logger.info('You can retry with: npx habeetat init');\n process.exit(1);\n }\n }\n\n const proto = config.platform.protocol;\n const domain = config.platform.domain;\n\n console.log('');\n logger.info('Platform URLs:');\n console.log(` Launcher: ${proto}://launcher.${domain}`);\n console.log(` Organization Manager: ${proto}://organization-manager.${domain}`);\n console.log(` Platform Manager: ${proto}://platform-manager.${domain}`);\n console.log(` Backend API: ${proto}://api.${domain}`);\n console.log(` Logto IAM: ${proto}://iam.${domain}`);\n console.log(` Logto Admin Console: ${proto}://iam-console.${domain}`);\n console.log('');\n logger.info('Run `habeetat status` to check service health');\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeDown } from '../utils/docker.js';\n\nexport async function downCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const spinner = ora('Stopping services...').start();\n\n try {\n await composeDown({ cwd: projectDir });\n spinner.succeed('All services stopped');\n } catch (err) {\n spinner.fail('Failed to stop services');\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composePs } from '../utils/docker.js';\n\nexport async function statusCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n\n logger.info(`Habeetat Platform — ${config.platform.domain}`);\n logger.info(`Version: ${config.version}`);\n logger.info(`Image tag: ${config.docker.imageTag}`);\n console.log('');\n\n try {\n const output = await composePs({ cwd: projectDir });\n console.log(output);\n } catch (err) {\n logger.error('Could not get service status. Is the platform running?');\n logger.info('Run `habeetat up` to start the platform');\n process.exit(1);\n }\n}\n","import { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeLogs } from '../utils/docker.js';\nimport { SERVICES } from '../constants.js';\n\nexport async function logsCommand(\n service?: string,\n options?: { follow?: boolean; tail?: number },\n): Promise<void> {\n const projectDir = getProjectDir();\n\n if (service && !(SERVICES as readonly string[]).includes(service)) {\n logger.error(`Unknown service: ${service}`);\n logger.info(`Available services: ${SERVICES.join(', ')}`);\n process.exit(1);\n }\n\n try {\n await composeLogs({\n cwd: projectDir,\n service,\n follow: options?.follow,\n tail: options?.tail,\n });\n } catch {\n // User interrupted with Ctrl+C — that's fine\n }\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeRestart } from '../utils/docker.js';\nimport { SERVICES } from '../constants.js';\n\nexport async function restartCommand(service?: string): Promise<void> {\n const projectDir = getProjectDir();\n\n if (service && !(SERVICES as readonly string[]).includes(service)) {\n logger.error(`Unknown service: ${service}`);\n logger.info(`Available services: ${SERVICES.join(', ')}`);\n process.exit(1);\n }\n\n const label = service || 'all services';\n const spinner = ora(`Restarting ${label}...`).start();\n\n try {\n await composeRestart({ cwd: projectDir, service });\n spinner.succeed(`Restarted ${label}`);\n } catch (err) {\n spinner.fail(`Failed to restart ${label}`);\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { logger } from '../utils/logger.js';\nimport { checkDocker, checkDockerCompose } from '../utils/docker.js';\nimport { findProjectRoot, loadConfig } from '../utils/config.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE, COMPOSE_FILE, ENV_FILE } from '../constants.js';\n\nexport async function doctorCommand(): Promise<void> {\n logger.phase('Habeetat Doctor — Diagnostics');\n let issues = 0;\n\n // Check Docker\n const dockerOk = await checkDocker();\n console.log(` Docker: ${dockerOk ? chalk.green('✓ Installed') : chalk.red('✗ Not found')}`);\n if (!dockerOk) issues++;\n\n // Check Docker Compose\n const composeOk = await checkDockerCompose();\n console.log(` Docker Compose: ${composeOk ? chalk.green('✓ Available') : chalk.red('✗ Not found')}`);\n if (!composeOk) issues++;\n\n // Check project directory\n const projectDir = findProjectRoot();\n console.log(` Project dir: ${projectDir ? chalk.green(`✓ ${projectDir}`) : chalk.yellow('⚠ Not in a Habeetat project')}`);\n if (!projectDir) {\n issues++;\n console.log('');\n logger.info(`Run \\`npm create habeetat my-platform\\` to create a new project`);\n return;\n }\n\n // Check config file\n const configExists = fs.existsSync(path.join(projectDir, CONFIG_FILE));\n console.log(` ${CONFIG_FILE}: ${configExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!configExists) issues++;\n\n // Check compose file\n const composeExists = fs.existsSync(path.join(projectDir, COMPOSE_FILE));\n console.log(` ${COMPOSE_FILE}: ${composeExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!composeExists) issues++;\n\n // Check env file\n const envExists = fs.existsSync(path.join(projectDir, ENV_FILE));\n console.log(` ${ENV_FILE}: ${envExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!envExists) issues++;\n\n // Check nginx config\n const nginxExists = fs.existsSync(path.join(projectDir, 'nginx', 'platform.conf'));\n console.log(` nginx/platform.conf: ${nginxExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!nginxExists) issues++;\n\n // Load config and check images\n if (configExists) {\n try {\n const config = loadConfig(projectDir);\n console.log(` Version: ${chalk.cyan(config.version)}`);\n console.log(` Domain: ${chalk.cyan(config.platform.domain)}`);\n console.log(` Protocol: ${chalk.cyan(config.platform.protocol)}`);\n } catch (err) {\n console.log(` Config: ${chalk.red('✗ Invalid JSON')}`);\n issues++;\n }\n }\n\n console.log('');\n if (issues === 0) {\n logger.success('No issues found');\n } else {\n logger.warn(`${issues} issue(s) found`);\n }\n}\n","import ora from 'ora';\nimport { createInterface } from 'node:readline';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composeDestroy } from '../utils/docker.js';\n\nasync function confirm(message: string): Promise<boolean> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(`${message} (y/N) `, (answer) => {\n rl.close();\n resolve(answer.toLowerCase() === 'y');\n });\n });\n}\n\nexport async function destroyCommand(options: { force?: boolean }): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n const domain = config.platform.domain;\n\n logger.warn(`This will permanently destroy the Habeetat Platform (${domain}):`);\n console.log(' - Stop and remove all containers');\n console.log(' - Delete all Docker volumes (databases, data)');\n console.log(' - Remove orphan containers');\n console.log('');\n\n if (!options.force) {\n const ok = await confirm('Are you sure you want to continue?');\n if (!ok) {\n logger.info('Aborted');\n return;\n }\n }\n\n const spinner = ora('Destroying platform...').start();\n\n try {\n await composeDestroy({ cwd: projectDir });\n spinner.succeed('Platform destroyed — all containers and volumes removed');\n console.log('');\n logger.info('To reinstall, run: npx habeetat up');\n } catch (err) {\n spinner.fail('Failed to destroy platform');\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import { Command } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport path from 'node:path';\nimport { upCommand } from './commands/up.js';\nimport { downCommand } from './commands/down.js';\nimport { statusCommand } from './commands/status.js';\nimport { logsCommand } from './commands/logs.js';\nimport { restartCommand } from './commands/restart.js';\nimport { doctorCommand } from './commands/doctor.js';\nimport { destroyCommand } from './commands/destroy.js';\nimport { initPlatform } from './commands/init.js';\nimport { getProjectDir } from './utils/config.js';\n\nconst pkg = JSON.parse(\n readFileSync(path.resolve(__dirname, '..', 'package.json'), 'utf-8'),\n);\n\nconst program = new Command();\n\nprogram\n .name('habeetat')\n .description('Habeetat Platform CLI — manage your platform instances')\n .version(pkg.version);\n\nprogram\n .command('up')\n .description('Start the platform')\n .action(upCommand);\n\nprogram\n .command('down')\n .description('Stop the platform')\n .action(downCommand);\n\nprogram\n .command('status')\n .description('Show platform service status')\n .action(statusCommand);\n\nprogram\n .command('logs [service]')\n .description('View service logs')\n .option('-f, --follow', 'Follow log output')\n .option('-n, --tail <lines>', 'Number of lines to show', parseInt)\n .action((service: string | undefined, options: { follow?: boolean; tail?: number }) => {\n return logsCommand(service, options);\n });\n\nprogram\n .command('restart [service]')\n .description('Restart services')\n .action(restartCommand);\n\nprogram\n .command('doctor')\n .description('Diagnose common issues')\n .action(doctorCommand);\n\nprogram\n .command('destroy')\n .description('Destroy the platform — remove all containers and volumes')\n .option('-f, --force', 'Skip confirmation prompt')\n .action((options: { force?: boolean }) => {\n return destroyCommand(options);\n });\n\nprogram\n .command('init')\n .description('Initialize platform (seed Logto apps, create admin user, setup database)')\n .action(() => {\n return initPlatform(getProjectDir());\n });\n\nprogram.parse();\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/logger.ts","../src/constants.ts","../src/utils/config.ts","../src/utils/docker.ts","../src/commands/init.ts","../src/commands/up.ts","../src/commands/down.ts","../src/commands/status.ts","../src/commands/logs.ts","../src/commands/restart.ts","../src/commands/doctor.ts","../src/commands/destroy.ts","../src/bin.ts"],"names":["chalk","path","fs","execaCommand","ora","execa","createInterface","readFileSync","Command"],"mappings":"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","file":"bin.js","sourcesContent":["import chalk from 'chalk';\n\nconst prefix = chalk.cyan('[habeetat]');\n\nexport const logger = {\n info: (msg: string) => console.log(`${prefix} ${msg}`),\n success: (msg: string) => console.log(`${prefix} ${chalk.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(`${prefix} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${prefix} ${chalk.red('✗')} ${msg}`),\n phase: (msg: string) => {\n console.log('');\n console.log(chalk.cyan('═'.repeat(56)));\n console.log(chalk.cyan(` ${msg}`));\n console.log(chalk.cyan('═'.repeat(56)));\n console.log('');\n },\n banner: () => {\n console.log('');\n console.log(chalk.cyan('╔══════════════════════════════════════════════╗'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('║ Habeetat Platform CLI ║'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('╚══════════════════════════════════════════════╝'));\n console.log('');\n },\n};\n","export const CONFIG_FILE = 'habeetat.json';\nexport const ENV_FILE = '.env';\nexport const COMPOSE_FILE = 'docker-compose.yml';\n\nexport const DOCKER_REGISTRY = 'docker.io/capriisland';\n\nexport const IMAGES = {\n backend: 'capriisland/habeetat-backend',\n launcher: 'capriisland/habeetat-launcher',\n orgManager: 'capriisland/habeetat-org-manager',\n platformManager: 'capriisland/habeetat-platform-manager',\n sampleCrm: 'capriisland/habeetat-sample-crm',\n logtoConfig: 'capriisland/habeetat-logto-config',\n} as const;\n\nexport const THIRD_PARTY_IMAGES = {\n postgres: 'postgres:15-alpine',\n logto: 'svhd/logto:1.33',\n nginx: 'nginx:1.25-alpine',\n certbot: 'certbot/certbot',\n} as const;\n\nexport const DEFAULT_PORTS = {\n http: 80,\n https: 443,\n hostNginx: 8080,\n} as const;\n\nexport const SERVICES = [\n 'logto-db',\n 'platform-db',\n 'logto-core',\n 'backend',\n 'launcher',\n 'organization-manager',\n 'platform-manager',\n 'sample-crm',\n 'nginx',\n] as const;\n\nexport type ServiceName = (typeof SERVICES)[number];\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE } from '../constants.js';\nimport type { HabeetatConfig } from '../types.js';\n\nexport function findProjectRoot(startDir: string = process.cwd()): string | null {\n let dir = startDir;\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, CONFIG_FILE))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nexport function loadConfig(projectDir?: string): HabeetatConfig {\n const dir = projectDir || findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n const configPath = path.join(dir, CONFIG_FILE);\n const raw = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as HabeetatConfig;\n}\n\nexport function saveConfig(config: HabeetatConfig, projectDir: string): void {\n const configPath = path.join(projectDir, CONFIG_FILE);\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function getProjectDir(): string {\n const dir = findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n return dir;\n}\n","import { execaCommand } from 'execa';\nimport { logger } from './logger.js';\n\nexport async function checkDocker(): Promise<boolean> {\n try {\n const { stdout } = await execaCommand('docker --version');\n const match = stdout.match(/Docker version (\\d+)/);\n if (match && parseInt(match[1], 10) >= 20) {\n return true;\n }\n logger.error(`Docker >= 20.0 required. Found: ${stdout.trim()}`);\n return false;\n } catch {\n logger.error('Docker is not installed or not in PATH');\n logger.info('Install Docker: https://docs.docker.com/get-docker/');\n return false;\n }\n}\n\nexport async function checkDockerCompose(): Promise<boolean> {\n try {\n await execaCommand('docker compose version');\n return true;\n } catch {\n logger.error('Docker Compose V2 is not available');\n logger.info('Docker Compose V2 is included with Docker Desktop');\n return false;\n }\n}\n\nexport async function checkPrerequisites(): Promise<boolean> {\n const docker = await checkDocker();\n const compose = await checkDockerCompose();\n return docker && compose;\n}\n\nexport interface ComposeExecOptions {\n cwd: string;\n composeFile?: string;\n silent?: boolean;\n}\n\nexport async function composeUp(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} up -d`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeDown(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function 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 ora from 'ora';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { execa, execaCommand } from 'execa';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { COMPOSE_FILE } from '../constants.js';\n\nconst INITIALIZED_FILE = '.initialized';\n\nexport function isInitialized(projectDir: string): boolean {\n return fs.existsSync(path.join(projectDir, INITIALIZED_FILE));\n}\n\nfunction markInitialized(projectDir: string): void {\n fs.writeFileSync(\n path.join(projectDir, INITIALIZED_FILE),\n JSON.stringify({ initializedAt: new Date().toISOString() }, null, 2) + '\\n',\n );\n}\n\nfunction loadEnv(projectDir: string): Record<string, string> {\n const envPath = path.join(projectDir, '.env');\n if (!fs.existsSync(envPath)) return {};\n const lines = fs.readFileSync(envPath, 'utf-8').split('\\n');\n const env: Record<string, string> = {};\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIdx = trimmed.indexOf('=');\n if (eqIdx === -1) continue;\n env[trimmed.slice(0, eqIdx)] = trimmed.slice(eqIdx + 1);\n }\n return env;\n}\n\nasync function execCompose(projectDir: string, args: string): Promise<string> {\n const { stdout } = await execaCommand(\n `docker compose -f ${COMPOSE_FILE} ${args}`,\n { cwd: projectDir },\n );\n return stdout;\n}\n\nasync function waitForService(\n projectDir: string,\n service: string,\n checkCmd: string,\n timeoutSec: number,\n): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutSec * 1000) {\n try {\n await execCompose(projectDir, `exec -T ${service} ${checkCmd}`);\n return true;\n } catch {\n await new Promise((r) => setTimeout(r, 3000));\n }\n }\n return false;\n}\n\nfunction buildSeedLogtoAppsSql(env: Record<string, string>): string {\n const protocol = env.PROTOCOL || 'https';\n const domain = env.DOMAIN || 'localhost';\n const launcherUrl = env.LAUNCHER_URL || `${protocol}://launcher.${domain}`;\n const orgManagerUrl = env.ORG_MANAGER_URL || `${protocol}://organization-manager.${domain}`;\n const platformManagerUrl = env.PLATFORM_MANAGER_URL || `${protocol}://platform-manager.${domain}`;\n const sampleCrmUrl = env.SAMPLE_CRM_URL || `${protocol}://sample-crm.${domain}`;\n const apiResource = env.IAM_AUDIENCE || `${protocol}://api.${domain}/api`;\n const m2mAppId = 'nhp-m2m-config';\n const m2mAppSecret = env.LOGTO_M2M_APP_SECRET || '';\n\n return `BEGIN;\n\n-- API Resource\nINSERT INTO resources (tenant_id, id, name, indicator, is_default, access_token_ttl)\nVALUES ('default', 'nhp-backend-resource', 'NHP Backend API', '${apiResource}', false, 3600)\nON CONFLICT (id) DO UPDATE\nSET name = EXCLUDED.name, indicator = EXCLUDED.indicator, access_token_ttl = EXCLUDED.access_token_ttl;\n\n-- Scope for API Resource\nINSERT INTO scopes (tenant_id, id, resource_id, name, description)\nVALUES ('default', 'nhp-backend-scope', 'nhp-backend-resource', 'nhp:all', 'Full access to NHP backend API')\nON CONFLICT (id) DO UPDATE\nSET resource_id = EXCLUDED.resource_id, name = EXCLUDED.name, description = EXCLUDED.description;\n\n-- Launcher SPA\nINSERT INTO applications (tenant_id, id, name, secret, description, type, oidc_client_metadata, custom_client_metadata, is_third_party)\nVALUES (\n 'default', 'nhp-launcher', 'Habeetat Launcher', 'spa-secret-nhp-launcher', 'Main launcher application', 'SPA',\n jsonb_build_object('redirectUris', ARRAY['${launcherUrl}', '${launcherUrl}/callback'], 'postLogoutRedirectUris', ARRAY['${launcherUrl}']),\n '{}'::jsonb, false\n) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description, type = EXCLUDED.type, oidc_client_metadata = EXCLUDED.oidc_client_metadata;\n\n-- Organization Manager SPA\nINSERT INTO applications (tenant_id, id, name, secret, description, type, oidc_client_metadata, custom_client_metadata, is_third_party)\nVALUES (\n 'default', 'nhp-org-manager', 'Organization Manager', 'spa-secret-nhp-org-manager', 'Organization management application', 'SPA',\n jsonb_build_object('redirectUris', ARRAY['${orgManagerUrl}', '${orgManagerUrl}/callback'], 'postLogoutRedirectUris', ARRAY['${orgManagerUrl}']),\n '{}'::jsonb, false\n) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description, type = EXCLUDED.type, oidc_client_metadata = EXCLUDED.oidc_client_metadata;\n\n-- Platform Manager SPA\nINSERT INTO applications (tenant_id, id, name, secret, description, type, oidc_client_metadata, custom_client_metadata, is_third_party)\nVALUES (\n 'default', 'nhp-plat-mgr', 'Platform Manager', 'spa-secret-nhp-plat-mgr', 'Platform administration application', 'SPA',\n jsonb_build_object('redirectUris', ARRAY['${platformManagerUrl}', '${platformManagerUrl}/callback'], 'postLogoutRedirectUris', ARRAY['${platformManagerUrl}']),\n '{}'::jsonb, false\n) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description, type = EXCLUDED.type, oidc_client_metadata = EXCLUDED.oidc_client_metadata;\n\n-- Sample CRM SPA\nINSERT INTO applications (tenant_id, id, name, secret, description, type, oidc_client_metadata, custom_client_metadata, is_third_party)\nVALUES (\n 'default', 'nhp-sample-crm', 'Sample CRM', 'spa-secret-nhp-sample-crm', 'Sample CRM application', 'SPA',\n jsonb_build_object('redirectUris', ARRAY['${sampleCrmUrl}', '${sampleCrmUrl}/callback'], 'postLogoutRedirectUris', ARRAY['${sampleCrmUrl}']),\n '{}'::jsonb, false\n) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description, type = EXCLUDED.type, oidc_client_metadata = EXCLUDED.oidc_client_metadata;\n\n-- M2M Application for backend\nINSERT INTO applications (tenant_id, id, name, secret, description, type, oidc_client_metadata, custom_client_metadata, is_third_party)\nVALUES (\n 'default', '${m2mAppId}', 'NHP M2M Config', '${m2mAppSecret}', 'Machine-to-machine application for backend services', 'MachineToMachine',\n jsonb_build_object('redirectUris', ARRAY[]::text[], 'postLogoutRedirectUris', ARRAY[]::text[]),\n '{}'::jsonb, false\n) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, secret = EXCLUDED.secret, description = EXCLUDED.description, type = EXCLUDED.type;\n\n-- Assign Management API role to M2M app\nDO $$\nDECLARE\n v_role_id TEXT;\nBEGIN\n SELECT id INTO v_role_id FROM roles\n WHERE tenant_id = 'default' AND name = 'Logto Management API access' AND type = 'MachineToMachine'\n LIMIT 1;\n\n IF v_role_id IS NULL THEN\n v_role_id := 'role_m2m_mgmt_api';\n INSERT INTO roles (tenant_id, id, name, description, type)\n VALUES ('default', v_role_id, 'Logto Management API access', 'Access to Logto Management API', 'MachineToMachine');\n\n INSERT INTO roles_scopes (tenant_id, id, role_id, scope_id)\n SELECT 'default', 'rs_' || s.id, v_role_id, s.id\n FROM scopes s WHERE s.resource_id = 'management-api' AND s.tenant_id = 'default'\n ON CONFLICT DO NOTHING;\n END IF;\n\n INSERT INTO applications_roles (tenant_id, id, application_id, role_id)\n VALUES ('default', 'ar_m2m_${m2mAppId}', '${m2mAppId}', v_role_id)\n ON CONFLICT DO NOTHING;\nEND $$;\n\n-- Update admin-console redirect URIs\nUPDATE applications\nSET oidc_client_metadata = jsonb_build_object(\n 'redirectUris', ARRAY['${protocol}://iam-console.${domain}/callback'],\n 'postLogoutRedirectUris', ARRAY['${protocol}://iam-console.${domain}']\n)\nWHERE id = 'admin-console' AND tenant_id = 'admin';\n\nCOMMIT;`;\n}\n\nfunction buildInitPlatformSql(env: Record<string, string>): string {\n const protocol = env.PROTOCOL || 'https';\n const domain = env.DOMAIN || 'localhost';\n const adminEmail = env.PLATFORM_ADMIN_EMAIL || 'admin@habeetat.local';\n const orgName = env.ORGANIZATION_NAME || 'Default Organization';\n const orgSlug = orgName.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '');\n\n return `\n-- Seed system applications\nINSERT INTO applications (id, slug, name, description, category, is_internal, is_system_app, is_hidden, auto_install, status, logto_app_id, created_at, updated_at)\nVALUES\n ('app_launcher', 'launcher', 'Habeetat Launcher', 'Main launcher and navigation hub', 'system', true, true, true, true, 'PUBLISHED', 'nhp-launcher', NOW(), NOW()),\n ('app_org_manager', 'organization-manager', 'Organization Manager', 'Manage organizations, users and roles', 'system', true, true, false, true, 'PUBLISHED', 'nhp-org-manager', NOW(), NOW()),\n ('app_plat_manager', 'platform-manager', 'Platform Manager', 'Platform administration and configuration', 'system', true, true, true, false, 'PUBLISHED', 'nhp-plat-mgr', NOW(), NOW()),\n ('app_sample_crm', 'sample-crm', 'Sample CRM', 'Sample CRM application for demonstration', 'demo', true, false, false, false, 'PUBLISHED', 'nhp-sample-crm', NOW(), NOW())\nON CONFLICT (slug) DO UPDATE SET\n name = EXCLUDED.name,\n description = EXCLUDED.description,\n logto_app_id = EXCLUDED.logto_app_id,\n is_system_app = EXCLUDED.is_system_app,\n is_hidden = EXCLUDED.is_hidden,\n auto_install = EXCLUDED.auto_install,\n status = EXCLUDED.status;\n\n-- Create initial versions for system apps\nINSERT INTO application_versions (id, app_id, version, manifest, status, created_at)\nVALUES\n ('ver_launcher_100', 'app_launcher', '1.0.0', jsonb_build_object('endpoints', jsonb_build_object('main', '${protocol}://launcher.${domain}')), 'ACTIVE', NOW()),\n ('ver_org_manager_100', 'app_org_manager', '1.0.0', jsonb_build_object('endpoints', jsonb_build_object('main', '${protocol}://organization-manager.${domain}')), 'ACTIVE', NOW()),\n ('ver_plat_manager_100', 'app_plat_manager', '1.0.0', jsonb_build_object('endpoints', jsonb_build_object('main', '${protocol}://platform-manager.${domain}')), 'ACTIVE', NOW()),\n ('ver_sample_crm_100', 'app_sample_crm', '1.0.0', jsonb_build_object('endpoints', jsonb_build_object('main', '${protocol}://sample-crm.${domain}')), 'ACTIVE', NOW())\nON CONFLICT (app_id, version) DO UPDATE SET manifest = EXCLUDED.manifest;\n\n-- Create default tenant\nINSERT INTO tenants (id, display_name, slug, status, created_at, updated_at)\nSELECT\n 'tenant_${orgSlug}',\n '${orgName}',\n '${orgSlug}',\n 'ACTIVE',\n NOW(),\n NOW()\nWHERE NOT EXISTS (\n SELECT 1 FROM tenants WHERE slug = '${orgSlug}'\n);\n\n-- Initialize tenant, admin user, roles, memberships, and app installations\nDO $$\nDECLARE\n v_tenant_id TEXT;\n v_user_id TEXT;\n v_admin_role_id TEXT;\nBEGIN\n SELECT id INTO v_tenant_id FROM tenants WHERE slug = '${orgSlug}' LIMIT 1;\n\n IF v_tenant_id IS NULL THEN\n RAISE NOTICE 'Tenant not found, skipping user setup';\n RETURN;\n END IF;\n\n SELECT id INTO v_user_id FROM users\n WHERE external_identity_id = 'usr_admin01'\n OR primary_email = '${adminEmail}'\n LIMIT 1;\n\n IF v_user_id IS NULL THEN\n v_user_id := 'usr_plat_admin01';\n INSERT INTO users (id, external_identity_id, primary_email, username, display_name, status, created_at, updated_at)\n VALUES (v_user_id, 'usr_admin01', '${adminEmail}', 'admin', 'Platform Admin', 'ACTIVE', NOW(), NOW());\n ELSE\n UPDATE users SET external_identity_id = 'usr_admin01'\n WHERE id = v_user_id AND external_identity_id IS NULL;\n END IF;\n\n SELECT id INTO v_admin_role_id FROM tenant_roles WHERE name = 'TENANT_ADMIN' LIMIT 1;\n\n IF v_admin_role_id IS NULL THEN\n v_admin_role_id := 'role_tenant_admin';\n INSERT INTO tenant_roles (id, name, description, created_at, updated_at)\n VALUES (v_admin_role_id, 'TENANT_ADMIN', 'Tenant Administrator', NOW(), NOW());\n END IF;\n\n INSERT INTO tenant_memberships (id, user_id, tenant_id, status, created_at, updated_at)\n SELECT 'tm_admin_${orgSlug}', v_user_id, v_tenant_id, 'ACTIVE', NOW(), NOW()\n WHERE NOT EXISTS (\n SELECT 1 FROM tenant_memberships WHERE user_id = v_user_id AND tenant_id = v_tenant_id\n );\n\n INSERT INTO tenant_membership_roles (id, membership_id, role_id, created_at)\n SELECT 'tmr_admin_${orgSlug}', 'tm_admin_${orgSlug}', v_admin_role_id, NOW()\n WHERE NOT EXISTS (\n SELECT 1 FROM tenant_membership_roles\n WHERE membership_id = 'tm_admin_${orgSlug}' AND role_id = v_admin_role_id\n );\nEND $$;\n\n-- Auto-install published non-hidden apps for the default tenant\nINSERT INTO tenant_application_installations (id, tenant_id, app_id, app_version_id, status, is_enabled, installed_at, updated_at)\nSELECT 'tai_${orgSlug}_' || a.slug, t.id, a.id, v.id, 'INSTALLED', true, NOW(), NOW()\nFROM tenants t\nJOIN applications a ON a.status = 'PUBLISHED' AND a.is_hidden = false\nJOIN application_versions v ON v.app_id = a.id AND v.version = '1.0.0'\nWHERE t.slug = '${orgSlug}'\nON CONFLICT (tenant_id, app_id) DO NOTHING;`;\n}\n\nexport async function initPlatform(projectDir: string): Promise<void> {\n const config = loadConfig(projectDir);\n const env = loadEnv(projectDir);\n const domain = config.platform.domain;\n\n // --- Phase 1: Wait for databases ---\n const dbSpinner = ora('Waiting for databases...').start();\n\n const logtoDbReady = await waitForService(\n projectDir, 'logto-db', 'pg_isready -U logto -d logto', 60,\n );\n if (!logtoDbReady) {\n dbSpinner.fail('logto-db did not become ready');\n throw new Error('logto-db timeout');\n }\n\n const platformDbReady = await waitForService(\n projectDir, 'platform-db',\n `pg_isready -U ${env.PLATFORM_DB_USER || 'habeetat'} -d ${env.PLATFORM_DB_NAME || 'habeetat_platform'}`,\n 60,\n );\n if (!platformDbReady) {\n dbSpinner.fail('platform-db did not become ready');\n throw new Error('platform-db timeout');\n }\n dbSpinner.succeed('Databases ready');\n\n // --- Phase 2: Wait for Logto to be healthy ---\n const logtoSpinner = ora('Waiting for Logto to be healthy (this may take up to 2 min)...').start();\n const logtoReady = await waitForService(\n projectDir, 'logto-core',\n 'wget -q --spider http://localhost:3001/oidc/.well-known/openid-configuration',\n 180,\n );\n if (!logtoReady) {\n logtoSpinner.fail('logto-core did not become healthy');\n throw new Error('logto-core timeout');\n }\n logtoSpinner.succeed('Logto is healthy');\n\n // --- Phase 3: Seed Logto applications (SQL) ---\n const logtoSeedSpinner = ora('Seeding Logto applications...').start();\n try {\n const sql = buildSeedLogtoAppsSql(env);\n await execaCommand(\n `docker compose -f ${COMPOSE_FILE} exec -T logto-db psql -U logto -d logto`,\n { cwd: projectDir, input: sql },\n );\n logtoSeedSpinner.succeed('Logto applications seeded');\n } catch (err) {\n logtoSeedSpinner.fail('Failed to seed Logto applications');\n logger.error(String(err));\n throw err;\n }\n\n // --- Phase 4: Bootstrap Logto users/orgs/roles (via Node container) ---\n const bootstrapSpinner = ora('Bootstrapping Logto users and organizations...').start();\n try {\n const orgName = env.ORGANIZATION_NAME || config.platform.organization || 'Default';\n const orgSlug = orgName.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '');\n const adminEmail = env.PLATFORM_ADMIN_EMAIL || config.platform.adminEmail;\n const adminPassword = env.PLATFORM_ADMIN_PASSWORD || 'Habeetat_01';\n const adminUsername = adminEmail.split('@')[0];\n const logtoDbUrl = `postgres://${env.LOGTO_DB_USER || 'logto'}:${env.LOGTO_DB_PASSWORD || 'logto'}@logto-db:5432/${env.LOGTO_DB_NAME || 'logto'}`;\n\n const bootstrapScriptPath = path.join(projectDir, 'scripts', 'nhp-seed-logto-bootstrap.mjs');\n const hasLocalScript = fs.existsSync(bootstrapScriptPath);\n\n if (hasLocalScript) {\n await execa('docker', [\n 'run', '--rm', '--network', 'habeetat_habeetat-network',\n '-e', `NHP_LOGTO_DB_URL=${logtoDbUrl}`,\n '-e', `NHP_PLATFORM_ADMIN_USERNAME=${adminUsername}`,\n '-e', `NHP_PLATFORM_ADMIN_EMAIL=${adminEmail}`,\n '-e', `NHP_PLATFORM_ADMIN_PASSWORD=${adminPassword}`,\n '-e', `NHP_PLATFORM_ADMIN_DISPLAY_NAME=Platform Admin`,\n '-e', `NHP_DEFAULT_TENANT_NAME=${orgName}`,\n '-e', `NHP_DEFAULT_TENANT_SLUG=${orgSlug}`,\n '-v', `${bootstrapScriptPath}:/app/bootstrap.mjs:ro`,\n '-w', '/app',\n 'node:20-alpine',\n 'sh', '-c', 'npm init -y >/dev/null 2>&1 && npm install --no-package-lock pg hash-wasm nanoid 2>/dev/null && node bootstrap.mjs',\n ],\n { cwd: projectDir, stdio: 'pipe' },\n );\n bootstrapSpinner.succeed('Logto users and organizations bootstrapped');\n } else {\n bootstrapSpinner.warn('Bootstrap script not found — skipping Logto user/org setup');\n logger.info('You may need to create the admin user manually via the Logto admin console');\n }\n } catch (err) {\n bootstrapSpinner.fail('Logto bootstrap failed');\n logger.error(String(err));\n logger.info('You may need to create the admin user manually via the Logto admin console');\n }\n\n // --- Phase 5: Wait for backend ---\n const backendSpinner = ora('Waiting for backend...').start();\n const backendReady = await waitForService(\n projectDir, 'backend', 'curl -sf http://localhost:3001/platform/status', 120,\n );\n if (!backendReady) {\n backendSpinner.fail('Backend did not become healthy');\n throw new Error('backend timeout');\n }\n backendSpinner.succeed('Backend is healthy');\n\n // --- Phase 6: Run Prisma migrations ---\n const migrateSpinner = ora('Running database migrations...').start();\n try {\n await execCompose(projectDir, 'exec -T backend npx prisma migrate deploy');\n migrateSpinner.succeed('Database migrations completed');\n } catch (err) {\n migrateSpinner.fail('Migrations failed');\n logger.error(String(err));\n logger.info('Run manually: docker compose exec backend npx prisma migrate deploy');\n }\n\n // --- Phase 7: Run Prisma seed ---\n const seedSpinner = ora('Seeding platform database...').start();\n try {\n const orgName = env.ORGANIZATION_NAME || config.platform.organization || 'Default';\n const orgSlug = orgName.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '');\n const adminEmail = env.PLATFORM_ADMIN_EMAIL || config.platform.adminEmail;\n\n await execa('docker', [\n 'compose', '-f', COMPOSE_FILE, 'exec', '-T',\n '-e', `NHP_PLATFORM_ADMIN_USER=${adminEmail.split('@')[0]}`,\n '-e', `NHP_PLATFORM_ADMIN_EMAIL=${adminEmail}`,\n '-e', `NHP_PLATFORM_ADMIN_DISPLAY_NAME=Platform Admin`,\n '-e', `NHP_DEFAULT_TENANT_NAME=${orgName}`,\n '-e', `NHP_DEFAULT_TENANT_SLUG=${orgSlug}`,\n 'backend', 'npx', 'tsx', 'prisma/seed.ts',\n ], { cwd: projectDir, stdio: 'pipe' });\n seedSpinner.succeed('Platform database seeded');\n } catch {\n seedSpinner.warn('Prisma seed skipped (may not be available in Docker image)');\n }\n\n // --- Phase 8: Initialize platform SQL (system apps, tenant, admin) ---\n const platformSpinner = ora('Initializing platform data...').start();\n try {\n const sql = buildInitPlatformSql(env);\n await execaCommand(\n `docker compose -f ${COMPOSE_FILE} exec -T platform-db psql -U ${env.PLATFORM_DB_USER || 'habeetat'} -d ${env.PLATFORM_DB_NAME || 'habeetat_platform'}`,\n { cwd: projectDir, input: sql },\n );\n platformSpinner.succeed('Platform data initialized');\n } catch (err) {\n platformSpinner.fail('Platform initialization failed');\n logger.error(String(err));\n logger.info('You may need to initialize the platform manually after first login');\n }\n\n // Mark as initialized\n markInitialized(projectDir);\n\n console.log('');\n logger.info(`✓ Platform initialized for ${domain}`);\n logger.info(` Admin: ${env.PLATFORM_ADMIN_EMAIL || config.platform.adminEmail}`);\n logger.info(` Organization: ${env.ORGANIZATION_NAME || config.platform.organization}`);\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composeUp, checkPrerequisites } from '../utils/docker.js';\nimport { isInitialized, initPlatform } from './init.js';\n\nexport async function upCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n\n logger.info(`Starting Habeetat Platform (${config.platform.domain})...`);\n\n if (!(await checkPrerequisites())) {\n process.exit(1);\n }\n\n const freshInstall = !isInitialized(projectDir);\n const spinner = ora('Starting services...').start();\n\n try {\n await composeUp({ cwd: projectDir });\n spinner.succeed('All services started');\n } catch (err) {\n spinner.fail('Failed to start services');\n logger.error(String(err));\n process.exit(1);\n }\n\n if (freshInstall) {\n console.log('');\n logger.info('First run detected — initializing platform...');\n console.log('');\n try {\n await initPlatform(projectDir);\n } catch (err) {\n logger.error('Platform initialization failed');\n logger.error(String(err));\n logger.info('You can retry with: npx habeetat init');\n process.exit(1);\n }\n }\n\n const proto = config.platform.protocol;\n const domain = config.platform.domain;\n\n console.log('');\n logger.info('Platform URLs:');\n console.log(` Launcher: ${proto}://launcher.${domain}`);\n console.log(` Organization Manager: ${proto}://organization-manager.${domain}`);\n console.log(` Platform Manager: ${proto}://platform-manager.${domain}`);\n console.log(` Backend API: ${proto}://api.${domain}`);\n console.log(` Logto IAM: ${proto}://iam.${domain}`);\n console.log(` Logto Admin Console: ${proto}://iam-console.${domain}`);\n console.log('');\n logger.info('Run `habeetat status` to check service health');\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeDown } from '../utils/docker.js';\n\nexport async function downCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const spinner = ora('Stopping services...').start();\n\n try {\n await composeDown({ cwd: projectDir });\n spinner.succeed('All services stopped');\n } catch (err) {\n spinner.fail('Failed to stop services');\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composePs } from '../utils/docker.js';\n\nexport async function statusCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n\n logger.info(`Habeetat Platform — ${config.platform.domain}`);\n logger.info(`Version: ${config.version}`);\n logger.info(`Image tag: ${config.docker.imageTag}`);\n console.log('');\n\n try {\n const output = await composePs({ cwd: projectDir });\n console.log(output);\n } catch (err) {\n logger.error('Could not get service status. Is the platform running?');\n logger.info('Run `habeetat up` to start the platform');\n process.exit(1);\n }\n}\n","import { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeLogs } from '../utils/docker.js';\nimport { SERVICES } from '../constants.js';\n\nexport async function logsCommand(\n service?: string,\n options?: { follow?: boolean; tail?: number },\n): Promise<void> {\n const projectDir = getProjectDir();\n\n if (service && !(SERVICES as readonly string[]).includes(service)) {\n logger.error(`Unknown service: ${service}`);\n logger.info(`Available services: ${SERVICES.join(', ')}`);\n process.exit(1);\n }\n\n try {\n await composeLogs({\n cwd: projectDir,\n service,\n follow: options?.follow,\n tail: options?.tail,\n });\n } catch {\n // User interrupted with Ctrl+C — that's fine\n }\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeRestart } from '../utils/docker.js';\nimport { SERVICES } from '../constants.js';\n\nexport async function restartCommand(service?: string): Promise<void> {\n const projectDir = getProjectDir();\n\n if (service && !(SERVICES as readonly string[]).includes(service)) {\n logger.error(`Unknown service: ${service}`);\n logger.info(`Available services: ${SERVICES.join(', ')}`);\n process.exit(1);\n }\n\n const label = service || 'all services';\n const spinner = ora(`Restarting ${label}...`).start();\n\n try {\n await composeRestart({ cwd: projectDir, service });\n spinner.succeed(`Restarted ${label}`);\n } catch (err) {\n spinner.fail(`Failed to restart ${label}`);\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { logger } from '../utils/logger.js';\nimport { checkDocker, checkDockerCompose } from '../utils/docker.js';\nimport { findProjectRoot, loadConfig } from '../utils/config.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE, COMPOSE_FILE, ENV_FILE } from '../constants.js';\n\nexport async function doctorCommand(): Promise<void> {\n logger.phase('Habeetat Doctor — Diagnostics');\n let issues = 0;\n\n // Check Docker\n const dockerOk = await checkDocker();\n console.log(` Docker: ${dockerOk ? chalk.green('✓ Installed') : chalk.red('✗ Not found')}`);\n if (!dockerOk) issues++;\n\n // Check Docker Compose\n const composeOk = await checkDockerCompose();\n console.log(` Docker Compose: ${composeOk ? chalk.green('✓ Available') : chalk.red('✗ Not found')}`);\n if (!composeOk) issues++;\n\n // Check project directory\n const projectDir = findProjectRoot();\n console.log(` Project dir: ${projectDir ? chalk.green(`✓ ${projectDir}`) : chalk.yellow('⚠ Not in a Habeetat project')}`);\n if (!projectDir) {\n issues++;\n console.log('');\n logger.info(`Run \\`npm create habeetat my-platform\\` to create a new project`);\n return;\n }\n\n // Check config file\n const configExists = fs.existsSync(path.join(projectDir, CONFIG_FILE));\n console.log(` ${CONFIG_FILE}: ${configExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!configExists) issues++;\n\n // Check compose file\n const composeExists = fs.existsSync(path.join(projectDir, COMPOSE_FILE));\n console.log(` ${COMPOSE_FILE}: ${composeExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!composeExists) issues++;\n\n // Check env file\n const envExists = fs.existsSync(path.join(projectDir, ENV_FILE));\n console.log(` ${ENV_FILE}: ${envExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!envExists) issues++;\n\n // Check nginx config\n const nginxExists = fs.existsSync(path.join(projectDir, 'nginx', 'platform.conf'));\n console.log(` nginx/platform.conf: ${nginxExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!nginxExists) issues++;\n\n // Load config and check images\n if (configExists) {\n try {\n const config = loadConfig(projectDir);\n console.log(` Version: ${chalk.cyan(config.version)}`);\n console.log(` Domain: ${chalk.cyan(config.platform.domain)}`);\n console.log(` Protocol: ${chalk.cyan(config.platform.protocol)}`);\n } catch (err) {\n console.log(` Config: ${chalk.red('✗ Invalid JSON')}`);\n issues++;\n }\n }\n\n console.log('');\n if (issues === 0) {\n logger.success('No issues found');\n } else {\n logger.warn(`${issues} issue(s) found`);\n }\n}\n","import ora from 'ora';\nimport { createInterface } from 'node:readline';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composeDestroy } from '../utils/docker.js';\n\nasync function confirm(message: string): Promise<boolean> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(`${message} (y/N) `, (answer) => {\n rl.close();\n resolve(answer.toLowerCase() === 'y');\n });\n });\n}\n\nexport async function destroyCommand(options: { force?: boolean }): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n const domain = config.platform.domain;\n\n logger.warn(`This will permanently destroy the Habeetat Platform (${domain}):`);\n console.log(' - Stop and remove all containers');\n console.log(' - Delete all Docker volumes (databases, data)');\n console.log(' - Remove orphan containers');\n console.log('');\n\n if (!options.force) {\n const ok = await confirm('Are you sure you want to continue?');\n if (!ok) {\n logger.info('Aborted');\n return;\n }\n }\n\n const spinner = ora('Destroying platform...').start();\n\n try {\n await composeDestroy({ cwd: projectDir });\n spinner.succeed('Platform destroyed — all containers and volumes removed');\n console.log('');\n logger.info('To reinstall, run: npx habeetat up');\n } catch (err) {\n spinner.fail('Failed to destroy platform');\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import { Command } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport path from 'node:path';\nimport { upCommand } from './commands/up.js';\nimport { downCommand } from './commands/down.js';\nimport { statusCommand } from './commands/status.js';\nimport { logsCommand } from './commands/logs.js';\nimport { restartCommand } from './commands/restart.js';\nimport { doctorCommand } from './commands/doctor.js';\nimport { destroyCommand } from './commands/destroy.js';\nimport { initPlatform } from './commands/init.js';\nimport { getProjectDir } from './utils/config.js';\n\nconst pkg = JSON.parse(\n readFileSync(path.resolve(__dirname, '..', 'package.json'), 'utf-8'),\n);\n\nconst program = new Command();\n\nprogram\n .name('habeetat')\n .description('Habeetat Platform CLI — manage your platform instances')\n .version(pkg.version);\n\nprogram\n .command('up')\n .description('Start the platform')\n .action(upCommand);\n\nprogram\n .command('down')\n .description('Stop the platform')\n .action(downCommand);\n\nprogram\n .command('status')\n .description('Show platform service status')\n .action(statusCommand);\n\nprogram\n .command('logs [service]')\n .description('View service logs')\n .option('-f, --follow', 'Follow log output')\n .option('-n, --tail <lines>', 'Number of lines to show', parseInt)\n .action((service: string | undefined, options: { follow?: boolean; tail?: number }) => {\n return logsCommand(service, options);\n });\n\nprogram\n .command('restart [service]')\n .description('Restart services')\n .action(restartCommand);\n\nprogram\n .command('doctor')\n .description('Diagnose common issues')\n .action(doctorCommand);\n\nprogram\n .command('destroy')\n .description('Destroy the platform — remove all containers and volumes')\n .option('-f, --force', 'Skip confirmation prompt')\n .action((options: { force?: boolean }) => {\n return destroyCommand(options);\n });\n\nprogram\n .command('init')\n .description('Initialize platform (seed Logto apps, create admin user, setup database)')\n .action(() => {\n return initPlatform(getProjectDir());\n });\n\nprogram.parse();\n"]}
|
package/package.json
CHANGED