@habeetat/cli 0.1.0-dev.20260324154244.f7ef1fb → 0.1.0-dev.20260324160126.e789960
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 +48 -0
- package/dist/bin.js.map +1 -1
- package/dist/index.js +2 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -7,6 +7,7 @@ var path = require('path');
|
|
|
7
7
|
var ora = require('ora');
|
|
8
8
|
var chalk2 = require('chalk');
|
|
9
9
|
var execa = require('execa');
|
|
10
|
+
var readline = require('readline');
|
|
10
11
|
|
|
11
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
13
|
|
|
@@ -130,6 +131,13 @@ async function composeDown(opts) {
|
|
|
130
131
|
stdio: opts.silent ? "pipe" : "inherit"
|
|
131
132
|
});
|
|
132
133
|
}
|
|
134
|
+
async function composeDestroy(opts) {
|
|
135
|
+
const file = opts.composeFile || "docker-compose.yml";
|
|
136
|
+
await execa.execaCommand(`docker compose -f ${file} down -v --remove-orphans`, {
|
|
137
|
+
cwd: opts.cwd,
|
|
138
|
+
stdio: opts.silent ? "pipe" : "inherit"
|
|
139
|
+
});
|
|
140
|
+
}
|
|
133
141
|
async function composePs(opts) {
|
|
134
142
|
const file = opts.composeFile || "docker-compose.yml";
|
|
135
143
|
const { stdout } = await execa.execaCommand(`docker compose -f ${file} ps`, {
|
|
@@ -301,6 +309,43 @@ async function doctorCommand() {
|
|
|
301
309
|
logger.warn(`${issues} issue(s) found`);
|
|
302
310
|
}
|
|
303
311
|
}
|
|
312
|
+
async function confirm(message) {
|
|
313
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
314
|
+
return new Promise((resolve) => {
|
|
315
|
+
rl.question(`${message} (y/N) `, (answer) => {
|
|
316
|
+
rl.close();
|
|
317
|
+
resolve(answer.toLowerCase() === "y");
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
async function destroyCommand(options) {
|
|
322
|
+
const projectDir = getProjectDir();
|
|
323
|
+
const config = loadConfig(projectDir);
|
|
324
|
+
const domain = config.platform.domain;
|
|
325
|
+
logger.warn(`This will permanently destroy the Habeetat Platform (${domain}):`);
|
|
326
|
+
console.log(" - Stop and remove all containers");
|
|
327
|
+
console.log(" - Delete all Docker volumes (databases, data)");
|
|
328
|
+
console.log(" - Remove orphan containers");
|
|
329
|
+
console.log("");
|
|
330
|
+
if (!options.force) {
|
|
331
|
+
const ok = await confirm("Are you sure you want to continue?");
|
|
332
|
+
if (!ok) {
|
|
333
|
+
logger.info("Aborted");
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const spinner = ora__default.default("Destroying platform...").start();
|
|
338
|
+
try {
|
|
339
|
+
await composeDestroy({ cwd: projectDir });
|
|
340
|
+
spinner.succeed("Platform destroyed \u2014 all containers and volumes removed");
|
|
341
|
+
console.log("");
|
|
342
|
+
logger.info("To reinstall, run: npx habeetat up");
|
|
343
|
+
} catch (err) {
|
|
344
|
+
spinner.fail("Failed to destroy platform");
|
|
345
|
+
logger.error(String(err));
|
|
346
|
+
process.exit(1);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
304
349
|
|
|
305
350
|
// src/bin.ts
|
|
306
351
|
var pkg = JSON.parse(
|
|
@@ -316,6 +361,9 @@ program.command("logs [service]").description("View service logs").option("-f, -
|
|
|
316
361
|
});
|
|
317
362
|
program.command("restart [service]").description("Restart services").action(restartCommand);
|
|
318
363
|
program.command("doctor").description("Diagnose common issues").action(doctorCommand);
|
|
364
|
+
program.command("destroy").description("Destroy the platform \u2014 remove all containers and volumes").option("-f, --force", "Skip confirmation prompt").action((options) => {
|
|
365
|
+
return destroyCommand(options);
|
|
366
|
+
});
|
|
319
367
|
program.parse();
|
|
320
368
|
//# sourceMappingURL=bin.js.map
|
|
321
369
|
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/logger.ts","../src/constants.ts","../src/utils/config.ts","../src/utils/docker.ts","../src/commands/up.ts","../src/commands/down.ts","../src/commands/status.ts","../src/commands/logs.ts","../src/commands/restart.ts","../src/commands/doctor.ts","../src/bin.ts"],"names":["chalk","path","fs","execaCommand","ora","readFileSync","Command"],"mappings":";;;;;;;;;;;;;;;;;AAEA,IAAM,MAAA,GAASA,uBAAA,CAAM,IAAA,CAAK,YAAY,CAAA;AAE/B,IAAM,MAAA,GAAS;AAAA,EACpB,IAAA,EAAM,CAAC,GAAA,KAAgB,OAAA,CAAQ,IAAI,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,CAAA;AAAA,EACrD,OAAA,EAAS,CAAC,GAAA,KAAgB,OAAA,CAAQ,IAAI,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIA,uBAAA,CAAM,KAAA,CAAM,QAAG,CAAC,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,CAAA;AAAA,EAC5E,IAAA,EAAM,CAAC,GAAA,KAAgB,OAAA,CAAQ,IAAI,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIA,uBAAA,CAAM,MAAA,CAAO,QAAG,CAAC,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,CAAA;AAAA,EAC1E,KAAA,EAAO,CAAC,GAAA,KAAgB,OAAA,CAAQ,MAAM,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIA,uBAAA,CAAM,GAAA,CAAI,QAAG,CAAC,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,CAAA;AAAA,EAC1E,KAAA,EAAO,CAAC,GAAA,KAAgB;AACtB,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,IAAA,OAAA,CAAQ,IAAIA,uBAAA,CAAM,IAAA,CAAK,SAAI,MAAA,CAAO,EAAE,CAAC,CAAC,CAAA;AACtC,IAAA,OAAA,CAAQ,IAAIA,uBAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,GAAG,EAAE,CAAC,CAAA;AAClC,IAAA,OAAA,CAAQ,IAAIA,uBAAA,CAAM,IAAA,CAAK,SAAI,MAAA,CAAO,EAAE,CAAC,CAAC,CAAA;AACtC,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAAA,EAChB,CAAA;AAAA,EACA,QAAQ,MAAM;AACZ,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,IAAA,OAAA,CAAQ,GAAA,CAAIA,uBAAA,CAAM,IAAA,CAAK,kSAAkD,CAAC,CAAA;AAC1E,IAAA,OAAA,CAAQ,GAAA,CAAIA,uBAAA,CAAM,IAAA,CAAK,4DAAkD,CAAC,CAAA;AAC1E,IAAA,OAAA,CAAQ,GAAA,CAAIA,uBAAA,CAAM,IAAA,CAAK,4DAAkD,CAAC,CAAA;AAC1E,IAAA,OAAA,CAAQ,GAAA,CAAIA,uBAAA,CAAM,IAAA,CAAK,4DAAkD,CAAC,CAAA;AAC1E,IAAA,OAAA,CAAQ,GAAA,CAAIA,uBAAA,CAAM,IAAA,CAAK,kSAAkD,CAAC,CAAA;AAC1E,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAAA,EAChB;AACF,CAAA;;;ACzBO,IAAM,WAAA,GAAc,eAAA;AACpB,IAAM,QAAA,GAAW,MAAA;AACjB,IAAM,YAAA,GAAe,oBAAA;AA0BrB,IAAM,QAAA,GAAW;AAAA,EACtB,UAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,sBAAA;AAAA,EACA,kBAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAA;;;ACjCO,SAAS,eAAA,CAAgB,QAAA,GAAmB,OAAA,CAAQ,GAAA,EAAI,EAAkB;AAC/E,EAAA,IAAI,GAAA,GAAM,QAAA;AACV,EAAA,OAAO,GAAA,KAAQC,qBAAA,CAAK,OAAA,CAAQ,GAAG,CAAA,EAAG;AAChC,IAAA,IAAIC,qBAAG,UAAA,CAAWD,qBAAA,CAAK,KAAK,GAAA,EAAK,WAAW,CAAC,CAAA,EAAG;AAC9C,MAAA,OAAO,GAAA;AAAA,IACT;AACA,IAAA,GAAA,GAAMA,qBAAA,CAAK,QAAQ,GAAG,CAAA;AAAA,EACxB;AACA,EAAA,OAAO,IAAA;AACT;AAEO,SAAS,WAAW,UAAA,EAAqC;AAC9D,EAAA,MAAM,GAAA,GAAM,cAAc,eAAA,EAAgB;AAC1C,EAAA,IAAI,CAAC,GAAA,EAAK;AACR,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kBAAkB,WAAW,CAAA,8CAAA;AAAA,KAC/B;AAAA,EACF;AACA,EAAA,MAAM,UAAA,GAAaA,qBAAA,CAAK,IAAA,CAAK,GAAA,EAAK,WAAW,CAAA;AAC7C,EAAA,MAAM,GAAA,GAAMC,oBAAA,CAAG,YAAA,CAAa,UAAA,EAAY,OAAO,CAAA;AAC/C,EAAA,OAAO,IAAA,CAAK,MAAM,GAAG,CAAA;AACvB;AAOO,SAAS,aAAA,GAAwB;AACtC,EAAA,MAAM,MAAM,eAAA,EAAgB;AAC5B,EAAA,IAAI,CAAC,GAAA,EAAK;AACR,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kBAAkB,WAAW,CAAA,8CAAA;AAAA,KAC/B;AAAA,EACF;AACA,EAAA,OAAO,GAAA;AACT;ACtCA,eAAsB,WAAA,GAAgC;AACpD,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAMC,mBAAa,kBAAkB,CAAA;AACxD,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,sBAAsB,CAAA;AACjD,IAAA,IAAI,SAAS,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA,EAAG,EAAE,KAAK,EAAA,EAAI;AACzC,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAA,CAAO,KAAA,CAAM,CAAA,gCAAA,EAAmC,MAAA,CAAO,IAAA,EAAM,CAAA,CAAE,CAAA;AAC/D,IAAA,OAAO,KAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,MAAA,CAAO,MAAM,wCAAwC,CAAA;AACrD,IAAA,MAAA,CAAO,KAAK,qDAAqD,CAAA;AACjE,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,eAAsB,kBAAA,GAAuC;AAC3D,EAAA,IAAI;AACF,IAAA,MAAMA,mBAAa,wBAAwB,CAAA;AAC3C,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,MAAA,CAAO,MAAM,oCAAoC,CAAA;AACjD,IAAA,MAAA,CAAO,KAAK,mDAAmD,CAAA;AAC/D,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,eAAsB,kBAAA,GAAuC;AAC3D,EAAA,MAAM,MAAA,GAAS,MAAM,WAAA,EAAY;AACjC,EAAA,MAAM,OAAA,GAAU,MAAM,kBAAA,EAAmB;AACzC,EAAA,OAAO,MAAA,IAAU,OAAA;AACnB;AAQA,eAAsB,UAAU,IAAA,EAAyC;AACvE,EAAA,MAAM,IAAA,GAAO,KAAK,WAAA,IAAe,oBAAA;AACjC,EAAA,MAAMA,kBAAA,CAAa,CAAA,kBAAA,EAAqB,IAAI,CAAA,MAAA,CAAA,EAAU;AAAA,IACpD,KAAK,IAAA,CAAK,GAAA;AAAA,IACV,KAAA,EAAO,IAAA,CAAK,MAAA,GAAS,MAAA,GAAS;AAAA,GAC/B,CAAA;AACH;AAEA,eAAsB,YAAY,IAAA,EAAyC;AACzE,EAAA,MAAM,IAAA,GAAO,KAAK,WAAA,IAAe,oBAAA;AACjC,EAAA,MAAMA,kBAAA,CAAa,CAAA,kBAAA,EAAqB,IAAI,CAAA,KAAA,CAAA,EAAS;AAAA,IACnD,KAAK,IAAA,CAAK,GAAA;AAAA,IACV,KAAA,EAAO,IAAA,CAAK,MAAA,GAAS,MAAA,GAAS;AAAA,GAC/B,CAAA;AACH;AAEA,eAAsB,UAAU,IAAA,EAA2C;AACzE,EAAA,MAAM,IAAA,GAAO,KAAK,WAAA,IAAe,oBAAA;AACjC,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAMA,kBAAA,CAAa,CAAA,kBAAA,EAAqB,IAAI,CAAA,GAAA,CAAA,EAAO;AAAA,IACpE,KAAK,IAAA,CAAK;AAAA,GACX,CAAA;AACD,EAAA,OAAO,MAAA;AACT;AAEA,eAAsB,YACpB,IAAA,EACe;AACf,EAAA,MAAM,IAAA,GAAO,KAAK,WAAA,IAAe,oBAAA;AACjC,EAAA,MAAM,QAAQ,CAAC,QAAA,EAAU,SAAA,EAAW,IAAA,EAAM,MAAM,MAAM,CAAA;AACtD,EAAA,IAAI,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AAChC,EAAA,IAAI,IAAA,CAAK,MAAM,KAAA,CAAM,IAAA,CAAK,UAAU,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA;AACrD,EAAA,IAAI,IAAA,CAAK,OAAA,EAAS,KAAA,CAAM,IAAA,CAAK,KAAK,OAAO,CAAA;AAEzC,EAAA,MAAMA,kBAAA,CAAa,KAAA,CAAM,IAAA,CAAK,GAAG,CAAA,EAAG;AAAA,IAClC,KAAK,IAAA,CAAK,GAAA;AAAA,IACV,KAAA,EAAO;AAAA,GACR,CAAA;AACH;AAEA,eAAsB,eACpB,IAAA,EACe;AACf,EAAA,MAAM,IAAA,GAAO,KAAK,WAAA,IAAe,oBAAA;AACjC,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,GACb,CAAA,kBAAA,EAAqB,IAAI,YAAY,IAAA,CAAK,OAAO,CAAA,CAAA,GACjD,CAAA,kBAAA,EAAqB,IAAI,CAAA,QAAA,CAAA;AAE7B,EAAA,MAAMA,mBAAa,GAAA,EAAK;AAAA,IACtB,KAAK,IAAA,CAAK,GAAA;AAAA,IACV,KAAA,EAAO,IAAA,CAAK,MAAA,GAAS,MAAA,GAAS;AAAA,GAC/B,CAAA;AACH;;;ACxFA,eAAsB,SAAA,GAA2B;AAC/C,EAAA,MAAM,aAAa,aAAA,EAAc;AACjC,EAAA,MAAM,MAAA,GAAS,WAAW,UAAU,CAAA;AAEpC,EAAA,MAAA,CAAO,IAAA,CAAK,CAAA,4BAAA,EAA+B,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,IAAA,CAAM,CAAA;AAEvE,EAAA,IAAI,CAAE,MAAM,kBAAA,EAAmB,EAAI;AACjC,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,MAAM,OAAA,GAAUC,oBAAA,CAAI,sBAAsB,CAAA,CAAE,KAAA,EAAM;AAElD,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,CAAU,EAAE,GAAA,EAAK,UAAA,EAAY,CAAA;AACnC,IAAA,OAAA,CAAQ,QAAQ,sBAAsB,CAAA;AAEtC,IAAA,MAAM,KAAA,GAAQ,OAAO,QAAA,CAAS,QAAA;AAC9B,IAAA,MAAM,MAAA,GAAS,OAAO,QAAA,CAAS,MAAA;AAE/B,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,IAAA,MAAA,CAAO,KAAK,gBAAgB,CAAA;AAC5B,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,wBAAA,EAA2B,KAAK,CAAA,YAAA,EAAe,MAAM,CAAA,CAAE,CAAA;AACnE,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,wBAAA,EAA2B,KAAK,CAAA,wBAAA,EAA2B,MAAM,CAAA,CAAE,CAAA;AAC/E,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,wBAAA,EAA2B,KAAK,CAAA,oBAAA,EAAuB,MAAM,CAAA,CAAE,CAAA;AAC3E,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,wBAAA,EAA2B,KAAK,CAAA,OAAA,EAAU,MAAM,CAAA,CAAE,CAAA;AAC9D,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,wBAAA,EAA2B,KAAK,CAAA,OAAA,EAAU,MAAM,CAAA,CAAE,CAAA;AAC9D,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,wBAAA,EAA2B,KAAK,CAAA,eAAA,EAAkB,MAAM,CAAA,CAAE,CAAA;AACtE,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,IAAA,MAAA,CAAO,KAAK,+CAA+C,CAAA;AAAA,EAC7D,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAK,0BAA0B,CAAA;AACvC,IAAA,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AACxB,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF;AClCA,eAAsB,WAAA,GAA6B;AACjD,EAAA,MAAM,aAAa,aAAA,EAAc;AACjC,EAAA,MAAM,OAAA,GAAUA,oBAAAA,CAAI,sBAAsB,CAAA,CAAE,KAAA,EAAM;AAElD,EAAA,IAAI;AACF,IAAA,MAAM,WAAA,CAAY,EAAE,GAAA,EAAK,UAAA,EAAY,CAAA;AACrC,IAAA,OAAA,CAAQ,QAAQ,sBAAsB,CAAA;AAAA,EACxC,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAK,yBAAyB,CAAA;AACtC,IAAA,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AACxB,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF;;;ACbA,eAAsB,aAAA,GAA+B;AACnD,EAAA,MAAM,aAAa,aAAA,EAAc;AACjC,EAAA,MAAM,MAAA,GAAS,WAAW,UAAU,CAAA;AAEpC,EAAA,MAAA,CAAO,IAAA,CAAK,CAAA,yBAAA,EAAuB,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAC3D,EAAA,MAAA,CAAO,IAAA,CAAK,CAAA,SAAA,EAAY,MAAA,CAAO,OAAO,CAAA,CAAE,CAAA;AACxC,EAAA,MAAA,CAAO,IAAA,CAAK,CAAA,WAAA,EAAc,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAA,CAAE,CAAA;AAClD,EAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAEd,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,MAAM,SAAA,CAAU,EAAE,GAAA,EAAK,YAAY,CAAA;AAClD,IAAA,OAAA,CAAQ,IAAI,MAAM,CAAA;AAAA,EACpB,SAAS,GAAA,EAAK;AACZ,IAAA,MAAA,CAAO,MAAM,wDAAwD,CAAA;AACrE,IAAA,MAAA,CAAO,KAAK,yCAAyC,CAAA;AACrD,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF;;;AChBA,eAAsB,WAAA,CACpB,SACA,OAAA,EACe;AACf,EAAA,MAAM,aAAa,aAAA,EAAc;AAEjC,EAAA,IAAI,OAAA,IAAW,CAAE,QAAA,CAA+B,QAAA,CAAS,OAAO,CAAA,EAAG;AACjE,IAAA,MAAA,CAAO,KAAA,CAAM,CAAA,iBAAA,EAAoB,OAAO,CAAA,CAAE,CAAA;AAC1C,IAAA,MAAA,CAAO,KAAK,CAAA,oBAAA,EAAuB,QAAA,CAAS,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AACxD,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,WAAA,CAAY;AAAA,MAChB,GAAA,EAAK,UAAA;AAAA,MACL,OAAA;AAAA,MACA,QAAQ,OAAA,EAAS,MAAA;AAAA,MACjB,MAAM,OAAA,EAAS;AAAA,KAChB,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;ACrBA,eAAsB,eAAe,OAAA,EAAiC;AACpE,EAAA,MAAM,aAAa,aAAA,EAAc;AAEjC,EAAA,IAAI,OAAA,IAAW,CAAE,QAAA,CAA+B,QAAA,CAAS,OAAO,CAAA,EAAG;AACjE,IAAA,MAAA,CAAO,KAAA,CAAM,CAAA,iBAAA,EAAoB,OAAO,CAAA,CAAE,CAAA;AAC1C,IAAA,MAAA,CAAO,KAAK,CAAA,oBAAA,EAAuB,QAAA,CAAS,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AACxD,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,MAAM,QAAQ,OAAA,IAAW,cAAA;AACzB,EAAA,MAAM,UAAUA,oBAAAA,CAAI,CAAA,WAAA,EAAc,KAAK,CAAA,GAAA,CAAK,EAAE,KAAA,EAAM;AAEpD,EAAA,IAAI;AACF,IAAA,MAAM,cAAA,CAAe,EAAE,GAAA,EAAK,UAAA,EAAY,SAAS,CAAA;AACjD,IAAA,OAAA,CAAQ,OAAA,CAAQ,CAAA,UAAA,EAAa,KAAK,CAAA,CAAE,CAAA;AAAA,EACtC,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,kBAAA,EAAqB,KAAK,CAAA,CAAE,CAAA;AACzC,IAAA,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AACxB,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF;AClBA,eAAsB,aAAA,GAA+B;AACnD,EAAA,MAAA,CAAO,MAAM,oCAA+B,CAAA;AAC5C,EAAA,IAAI,MAAA,GAAS,CAAA;AAGb,EAAA,MAAM,QAAA,GAAW,MAAM,WAAA,EAAY;AACnC,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,mBAAA,EAAsB,QAAA,GAAWJ,uBAAAA,CAAM,KAAA,CAAM,kBAAa,CAAA,GAAIA,uBAAAA,CAAM,GAAA,CAAI,kBAAa,CAAC,CAAA,CAAE,CAAA;AACpG,EAAA,IAAI,CAAC,QAAA,EAAU,MAAA,EAAA;AAGf,EAAA,MAAM,SAAA,GAAY,MAAM,kBAAA,EAAmB;AAC3C,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,mBAAA,EAAsB,SAAA,GAAYA,uBAAAA,CAAM,KAAA,CAAM,kBAAa,CAAA,GAAIA,uBAAAA,CAAM,GAAA,CAAI,kBAAa,CAAC,CAAA,CAAE,CAAA;AACrG,EAAA,IAAI,CAAC,SAAA,EAAW,MAAA,EAAA;AAGhB,EAAA,MAAM,aAAa,eAAA,EAAgB;AACnC,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,mBAAA,EAAsB,UAAA,GAAaA,uBAAAA,CAAM,KAAA,CAAM,CAAA,OAAA,EAAK,UAAU,CAAA,CAAE,CAAA,GAAIA,uBAAAA,CAAM,MAAA,CAAO,kCAA6B,CAAC,CAAA,CAAE,CAAA;AAC7H,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,MAAA,EAAA;AACA,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,IAAA,MAAA,CAAO,KAAK,CAAA,+DAAA,CAAiE,CAAA;AAC7E,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,eAAeE,oBAAAA,CAAG,UAAA,CAAWD,sBAAK,IAAA,CAAK,UAAA,EAAY,WAAW,CAAC,CAAA;AACrE,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAA,EAAK,WAAW,CAAA,IAAA,EAAO,YAAA,GAAeD,uBAAAA,CAAM,KAAA,CAAM,cAAS,CAAA,GAAIA,uBAAAA,CAAM,GAAA,CAAI,gBAAW,CAAC,CAAA,CAAE,CAAA;AACnG,EAAA,IAAI,CAAC,YAAA,EAAc,MAAA,EAAA;AAGnB,EAAA,MAAM,gBAAgBE,oBAAAA,CAAG,UAAA,CAAWD,sBAAK,IAAA,CAAK,UAAA,EAAY,YAAY,CAAC,CAAA;AACvE,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAA,EAAK,YAAY,CAAA,EAAA,EAAK,aAAA,GAAgBD,uBAAAA,CAAM,KAAA,CAAM,cAAS,CAAA,GAAIA,uBAAAA,CAAM,GAAA,CAAI,gBAAW,CAAC,CAAA,CAAE,CAAA;AACnG,EAAA,IAAI,CAAC,aAAA,EAAe,MAAA,EAAA;AAGpB,EAAA,MAAM,YAAYE,oBAAAA,CAAG,UAAA,CAAWD,sBAAK,IAAA,CAAK,UAAA,EAAY,QAAQ,CAAC,CAAA;AAC/D,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAA,EAAK,QAAQ,CAAA,cAAA,EAAiB,SAAA,GAAYD,uBAAAA,CAAM,KAAA,CAAM,cAAS,CAAA,GAAIA,uBAAAA,CAAM,GAAA,CAAI,gBAAW,CAAC,CAAA,CAAE,CAAA;AACvG,EAAA,IAAI,CAAC,SAAA,EAAW,MAAA,EAAA;AAGhB,EAAA,MAAM,WAAA,GAAcE,qBAAG,UAAA,CAAWD,qBAAAA,CAAK,KAAK,UAAA,EAAY,OAAA,EAAS,eAAe,CAAC,CAAA;AACjF,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,uBAAA,EAA0B,WAAA,GAAcD,uBAAAA,CAAM,KAAA,CAAM,cAAS,CAAA,GAAIA,uBAAAA,CAAM,GAAA,CAAI,gBAAW,CAAC,CAAA,CAAE,CAAA;AACrG,EAAA,IAAI,CAAC,WAAA,EAAa,MAAA,EAAA;AAGlB,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,WAAW,UAAU,CAAA;AACpC,MAAA,OAAA,CAAQ,IAAI,CAAA,mBAAA,EAAsBA,uBAAAA,CAAM,KAAK,MAAA,CAAO,OAAO,CAAC,CAAA,CAAE,CAAA;AAC9D,MAAA,OAAA,CAAQ,GAAA,CAAI,sBAAsBA,uBAAAA,CAAM,IAAA,CAAK,OAAO,QAAA,CAAS,MAAM,CAAC,CAAA,CAAE,CAAA;AACtE,MAAA,OAAA,CAAQ,GAAA,CAAI,sBAAsBA,uBAAAA,CAAM,IAAA,CAAK,OAAO,QAAA,CAAS,QAAQ,CAAC,CAAA,CAAE,CAAA;AAAA,IAC1E,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,IAAI,CAAA,mBAAA,EAAsBA,uBAAAA,CAAM,GAAA,CAAI,qBAAgB,CAAC,CAAA,CAAE,CAAA;AAC/D,MAAA,MAAA,EAAA;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,EAAA,IAAI,WAAW,CAAA,EAAG;AAChB,IAAA,MAAA,CAAO,QAAQ,iBAAiB,CAAA;AAAA,EAClC,CAAA,MAAO;AACL,IAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,MAAM,CAAA,eAAA,CAAiB,CAAA;AAAA,EACxC;AACF;;;AC5DA,IAAM,MAAM,IAAA,CAAK,KAAA;AAAA,EACfK,iBAAaJ,qBAAAA,CAAK,OAAA,CAAQ,WAAW,IAAA,EAAM,cAAc,GAAG,OAAO;AACrE,CAAA;AAEA,IAAM,OAAA,GAAU,IAAIK,iBAAA,EAAQ;AAE5B,OAAA,CACG,IAAA,CAAK,UAAU,CAAA,CACf,WAAA,CAAY,6DAAwD,CAAA,CACpE,OAAA,CAAQ,IAAI,OAAO,CAAA;AAEtB,OAAA,CACG,QAAQ,IAAI,CAAA,CACZ,YAAY,oBAAoB,CAAA,CAChC,OAAO,SAAS,CAAA;AAEnB,OAAA,CACG,QAAQ,MAAM,CAAA,CACd,YAAY,mBAAmB,CAAA,CAC/B,OAAO,WAAW,CAAA;AAErB,OAAA,CACG,QAAQ,QAAQ,CAAA,CAChB,YAAY,8BAA8B,CAAA,CAC1C,OAAO,aAAa,CAAA;AAEvB,OAAA,CACG,QAAQ,gBAAgB,CAAA,CACxB,YAAY,mBAAmB,CAAA,CAC/B,OAAO,cAAA,EAAgB,mBAAmB,CAAA,CAC1C,MAAA,CAAO,sBAAsB,yBAAA,EAA2B,QAAQ,EAChE,MAAA,CAAO,CAAC,SAA6B,OAAA,KAAiD;AACrF,EAAA,OAAO,WAAA,CAAY,SAAS,OAAO,CAAA;AACrC,CAAC,CAAA;AAEH,OAAA,CACG,QAAQ,mBAAmB,CAAA,CAC3B,YAAY,kBAAkB,CAAA,CAC9B,OAAO,cAAc,CAAA;AAExB,OAAA,CACG,QAAQ,QAAQ,CAAA,CAChB,YAAY,wBAAwB,CAAA,CACpC,OAAO,aAAa,CAAA;AAEvB,OAAA,CAAQ,KAAA,EAAM","file":"bin.js","sourcesContent":["import chalk from 'chalk';\n\nconst prefix = chalk.cyan('[habeetat]');\n\nexport const logger = {\n info: (msg: string) => console.log(`${prefix} ${msg}`),\n success: (msg: string) => console.log(`${prefix} ${chalk.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(`${prefix} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${prefix} ${chalk.red('✗')} ${msg}`),\n phase: (msg: string) => {\n console.log('');\n console.log(chalk.cyan('═'.repeat(56)));\n console.log(chalk.cyan(` ${msg}`));\n console.log(chalk.cyan('═'.repeat(56)));\n console.log('');\n },\n banner: () => {\n console.log('');\n console.log(chalk.cyan('╔══════════════════════════════════════════════╗'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('║ Habeetat Platform CLI ║'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('╚══════════════════════════════════════════════╝'));\n console.log('');\n },\n};\n","export const CONFIG_FILE = 'habeetat.json';\nexport const ENV_FILE = '.env';\nexport const COMPOSE_FILE = 'docker-compose.yml';\n\nexport const DOCKER_REGISTRY = 'docker.io/capriisland';\n\nexport const IMAGES = {\n backend: 'capriisland/habeetat-backend',\n launcher: 'capriisland/habeetat-launcher',\n orgManager: 'capriisland/habeetat-org-manager',\n platformManager: 'capriisland/habeetat-platform-manager',\n sampleCrm: 'capriisland/habeetat-sample-crm',\n logtoConfig: 'capriisland/habeetat-logto-config',\n} as const;\n\nexport const THIRD_PARTY_IMAGES = {\n postgres: 'postgres:15-alpine',\n logto: 'svhd/logto:1.33',\n nginx: 'nginx:1.25-alpine',\n certbot: 'certbot/certbot',\n} as const;\n\nexport const DEFAULT_PORTS = {\n http: 80,\n https: 443,\n hostNginx: 8080,\n} as const;\n\nexport const SERVICES = [\n 'logto-db',\n 'platform-db',\n 'logto-core',\n 'backend',\n 'launcher',\n 'organization-manager',\n 'platform-manager',\n 'sample-crm',\n 'nginx',\n] as const;\n\nexport type ServiceName = (typeof SERVICES)[number];\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE } from '../constants.js';\nimport type { HabeetatConfig } from '../types.js';\n\nexport function findProjectRoot(startDir: string = process.cwd()): string | null {\n let dir = startDir;\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, CONFIG_FILE))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nexport function loadConfig(projectDir?: string): HabeetatConfig {\n const dir = projectDir || findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n const configPath = path.join(dir, CONFIG_FILE);\n const raw = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as HabeetatConfig;\n}\n\nexport function saveConfig(config: HabeetatConfig, projectDir: string): void {\n const configPath = path.join(projectDir, CONFIG_FILE);\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function getProjectDir(): string {\n const dir = findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n return dir;\n}\n","import { execaCommand } from 'execa';\nimport { logger } from './logger.js';\n\nexport async function checkDocker(): Promise<boolean> {\n try {\n const { stdout } = await execaCommand('docker --version');\n const match = stdout.match(/Docker version (\\d+)/);\n if (match && parseInt(match[1], 10) >= 20) {\n return true;\n }\n logger.error(`Docker >= 20.0 required. Found: ${stdout.trim()}`);\n return false;\n } catch {\n logger.error('Docker is not installed or not in PATH');\n logger.info('Install Docker: https://docs.docker.com/get-docker/');\n return false;\n }\n}\n\nexport async function checkDockerCompose(): Promise<boolean> {\n try {\n await execaCommand('docker compose version');\n return true;\n } catch {\n logger.error('Docker Compose V2 is not available');\n logger.info('Docker Compose V2 is included with Docker Desktop');\n return false;\n }\n}\n\nexport async function checkPrerequisites(): Promise<boolean> {\n const docker = await checkDocker();\n const compose = await checkDockerCompose();\n return docker && compose;\n}\n\nexport interface ComposeExecOptions {\n cwd: string;\n composeFile?: string;\n silent?: boolean;\n}\n\nexport async function composeUp(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} up -d`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeDown(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composePs(opts: ComposeExecOptions): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(`docker compose -f ${file} ps`, {\n cwd: opts.cwd,\n });\n return stdout;\n}\n\nexport async function composeLogs(\n opts: ComposeExecOptions & { service?: string; follow?: boolean; tail?: number },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const parts = ['docker', 'compose', '-f', file, 'logs'];\n if (opts.follow) parts.push('-f');\n if (opts.tail) parts.push('--tail', String(opts.tail));\n if (opts.service) parts.push(opts.service);\n\n await execaCommand(parts.join(' '), {\n cwd: opts.cwd,\n stdio: 'inherit',\n });\n}\n\nexport async function composeRestart(\n opts: ComposeExecOptions & { service?: string },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const cmd = opts.service\n ? `docker compose -f ${file} restart ${opts.service}`\n : `docker compose -f ${file} restart`;\n\n await execaCommand(cmd, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeExec(\n opts: ComposeExecOptions & { service: string; command: string },\n): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(\n `docker compose -f ${file} exec -T ${opts.service} ${opts.command}`,\n { cwd: opts.cwd },\n );\n return stdout;\n}\n\nexport async function dockerPull(image: string): Promise<void> {\n await execaCommand(`docker pull ${image}`, { stdio: 'inherit' });\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composeUp, checkPrerequisites } from '../utils/docker.js';\n\nexport async function upCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n\n logger.info(`Starting Habeetat Platform (${config.platform.domain})...`);\n\n if (!(await checkPrerequisites())) {\n process.exit(1);\n }\n\n const spinner = ora('Starting services...').start();\n\n try {\n await composeUp({ cwd: projectDir });\n spinner.succeed('All services started');\n\n const proto = config.platform.protocol;\n const domain = config.platform.domain;\n\n console.log('');\n logger.info('Platform URLs:');\n console.log(` Launcher: ${proto}://launcher.${domain}`);\n console.log(` Organization Manager: ${proto}://organization-manager.${domain}`);\n console.log(` Platform Manager: ${proto}://platform-manager.${domain}`);\n console.log(` Backend API: ${proto}://api.${domain}`);\n console.log(` Logto IAM: ${proto}://iam.${domain}`);\n console.log(` Logto Admin Console: ${proto}://iam-console.${domain}`);\n console.log('');\n logger.info('Run `habeetat status` to check service health');\n } catch (err) {\n spinner.fail('Failed to start services');\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeDown } from '../utils/docker.js';\n\nexport async function downCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const spinner = ora('Stopping services...').start();\n\n try {\n await composeDown({ cwd: projectDir });\n spinner.succeed('All services stopped');\n } catch (err) {\n spinner.fail('Failed to stop services');\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composePs } from '../utils/docker.js';\n\nexport async function statusCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n\n logger.info(`Habeetat Platform — ${config.platform.domain}`);\n logger.info(`Version: ${config.version}`);\n logger.info(`Image tag: ${config.docker.imageTag}`);\n console.log('');\n\n try {\n const output = await composePs({ cwd: projectDir });\n console.log(output);\n } catch (err) {\n logger.error('Could not get service status. Is the platform running?');\n logger.info('Run `habeetat up` to start the platform');\n process.exit(1);\n }\n}\n","import { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeLogs } from '../utils/docker.js';\nimport { SERVICES } from '../constants.js';\n\nexport async function logsCommand(\n service?: string,\n options?: { follow?: boolean; tail?: number },\n): Promise<void> {\n const projectDir = getProjectDir();\n\n if (service && !(SERVICES as readonly string[]).includes(service)) {\n logger.error(`Unknown service: ${service}`);\n logger.info(`Available services: ${SERVICES.join(', ')}`);\n process.exit(1);\n }\n\n try {\n await composeLogs({\n cwd: projectDir,\n service,\n follow: options?.follow,\n tail: options?.tail,\n });\n } catch {\n // User interrupted with Ctrl+C — that's fine\n }\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeRestart } from '../utils/docker.js';\nimport { SERVICES } from '../constants.js';\n\nexport async function restartCommand(service?: string): Promise<void> {\n const projectDir = getProjectDir();\n\n if (service && !(SERVICES as readonly string[]).includes(service)) {\n logger.error(`Unknown service: ${service}`);\n logger.info(`Available services: ${SERVICES.join(', ')}`);\n process.exit(1);\n }\n\n const label = service || 'all services';\n const spinner = ora(`Restarting ${label}...`).start();\n\n try {\n await composeRestart({ cwd: projectDir, service });\n spinner.succeed(`Restarted ${label}`);\n } catch (err) {\n spinner.fail(`Failed to restart ${label}`);\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { logger } from '../utils/logger.js';\nimport { checkDocker, checkDockerCompose } from '../utils/docker.js';\nimport { findProjectRoot, loadConfig } from '../utils/config.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE, COMPOSE_FILE, ENV_FILE } from '../constants.js';\n\nexport async function doctorCommand(): Promise<void> {\n logger.phase('Habeetat Doctor — Diagnostics');\n let issues = 0;\n\n // Check Docker\n const dockerOk = await checkDocker();\n console.log(` Docker: ${dockerOk ? chalk.green('✓ Installed') : chalk.red('✗ Not found')}`);\n if (!dockerOk) issues++;\n\n // Check Docker Compose\n const composeOk = await checkDockerCompose();\n console.log(` Docker Compose: ${composeOk ? chalk.green('✓ Available') : chalk.red('✗ Not found')}`);\n if (!composeOk) issues++;\n\n // Check project directory\n const projectDir = findProjectRoot();\n console.log(` Project dir: ${projectDir ? chalk.green(`✓ ${projectDir}`) : chalk.yellow('⚠ Not in a Habeetat project')}`);\n if (!projectDir) {\n issues++;\n console.log('');\n logger.info(`Run \\`npm create habeetat my-platform\\` to create a new project`);\n return;\n }\n\n // Check config file\n const configExists = fs.existsSync(path.join(projectDir, CONFIG_FILE));\n console.log(` ${CONFIG_FILE}: ${configExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!configExists) issues++;\n\n // Check compose file\n const composeExists = fs.existsSync(path.join(projectDir, COMPOSE_FILE));\n console.log(` ${COMPOSE_FILE}: ${composeExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!composeExists) issues++;\n\n // Check env file\n const envExists = fs.existsSync(path.join(projectDir, ENV_FILE));\n console.log(` ${ENV_FILE}: ${envExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!envExists) issues++;\n\n // Check nginx config\n const nginxExists = fs.existsSync(path.join(projectDir, 'nginx', 'platform.conf'));\n console.log(` nginx/platform.conf: ${nginxExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!nginxExists) issues++;\n\n // Load config and check images\n if (configExists) {\n try {\n const config = loadConfig(projectDir);\n console.log(` Version: ${chalk.cyan(config.version)}`);\n console.log(` Domain: ${chalk.cyan(config.platform.domain)}`);\n console.log(` Protocol: ${chalk.cyan(config.platform.protocol)}`);\n } catch (err) {\n console.log(` Config: ${chalk.red('✗ Invalid JSON')}`);\n issues++;\n }\n }\n\n console.log('');\n if (issues === 0) {\n logger.success('No issues found');\n } else {\n logger.warn(`${issues} issue(s) found`);\n }\n}\n","import { Command } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport path from 'node:path';\nimport { upCommand } from './commands/up.js';\nimport { downCommand } from './commands/down.js';\nimport { statusCommand } from './commands/status.js';\nimport { logsCommand } from './commands/logs.js';\nimport { restartCommand } from './commands/restart.js';\nimport { doctorCommand } from './commands/doctor.js';\n\nconst pkg = JSON.parse(\n readFileSync(path.resolve(__dirname, '..', 'package.json'), 'utf-8'),\n);\n\nconst program = new Command();\n\nprogram\n .name('habeetat')\n .description('Habeetat Platform CLI — manage your platform instances')\n .version(pkg.version);\n\nprogram\n .command('up')\n .description('Start the platform')\n .action(upCommand);\n\nprogram\n .command('down')\n .description('Stop the platform')\n .action(downCommand);\n\nprogram\n .command('status')\n .description('Show platform service status')\n .action(statusCommand);\n\nprogram\n .command('logs [service]')\n .description('View service logs')\n .option('-f, --follow', 'Follow log output')\n .option('-n, --tail <lines>', 'Number of lines to show', parseInt)\n .action((service: string | undefined, options: { follow?: boolean; tail?: number }) => {\n return logsCommand(service, options);\n });\n\nprogram\n .command('restart [service]')\n .description('Restart services')\n .action(restartCommand);\n\nprogram\n .command('doctor')\n .description('Diagnose common issues')\n .action(doctorCommand);\n\nprogram.parse();\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/logger.ts","../src/constants.ts","../src/utils/config.ts","../src/utils/docker.ts","../src/commands/up.ts","../src/commands/down.ts","../src/commands/status.ts","../src/commands/logs.ts","../src/commands/restart.ts","../src/commands/doctor.ts","../src/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 { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composeUp, checkPrerequisites } from '../utils/docker.js';\n\nexport async function upCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n\n logger.info(`Starting Habeetat Platform (${config.platform.domain})...`);\n\n if (!(await checkPrerequisites())) {\n process.exit(1);\n }\n\n const spinner = ora('Starting services...').start();\n\n try {\n await composeUp({ cwd: projectDir });\n spinner.succeed('All services started');\n\n const proto = config.platform.protocol;\n const domain = config.platform.domain;\n\n console.log('');\n logger.info('Platform URLs:');\n console.log(` Launcher: ${proto}://launcher.${domain}`);\n console.log(` Organization Manager: ${proto}://organization-manager.${domain}`);\n console.log(` Platform Manager: ${proto}://platform-manager.${domain}`);\n console.log(` Backend API: ${proto}://api.${domain}`);\n console.log(` Logto IAM: ${proto}://iam.${domain}`);\n console.log(` Logto Admin Console: ${proto}://iam-console.${domain}`);\n console.log('');\n logger.info('Run `habeetat status` to check service health');\n } catch (err) {\n spinner.fail('Failed to start services');\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeDown } from '../utils/docker.js';\n\nexport async function downCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const spinner = ora('Stopping services...').start();\n\n try {\n await composeDown({ cwd: projectDir });\n spinner.succeed('All services stopped');\n } catch (err) {\n spinner.fail('Failed to stop services');\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import { logger } from '../utils/logger.js';\nimport { getProjectDir, loadConfig } from '../utils/config.js';\nimport { composePs } from '../utils/docker.js';\n\nexport async function statusCommand(): Promise<void> {\n const projectDir = getProjectDir();\n const config = loadConfig(projectDir);\n\n logger.info(`Habeetat Platform — ${config.platform.domain}`);\n logger.info(`Version: ${config.version}`);\n logger.info(`Image tag: ${config.docker.imageTag}`);\n console.log('');\n\n try {\n const output = await composePs({ cwd: projectDir });\n console.log(output);\n } catch (err) {\n logger.error('Could not get service status. Is the platform running?');\n logger.info('Run `habeetat up` to start the platform');\n process.exit(1);\n }\n}\n","import { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeLogs } from '../utils/docker.js';\nimport { SERVICES } from '../constants.js';\n\nexport async function logsCommand(\n service?: string,\n options?: { follow?: boolean; tail?: number },\n): Promise<void> {\n const projectDir = getProjectDir();\n\n if (service && !(SERVICES as readonly string[]).includes(service)) {\n logger.error(`Unknown service: ${service}`);\n logger.info(`Available services: ${SERVICES.join(', ')}`);\n process.exit(1);\n }\n\n try {\n await composeLogs({\n cwd: projectDir,\n service,\n follow: options?.follow,\n tail: options?.tail,\n });\n } catch {\n // User interrupted with Ctrl+C — that's fine\n }\n}\n","import ora from 'ora';\nimport { logger } from '../utils/logger.js';\nimport { getProjectDir } from '../utils/config.js';\nimport { composeRestart } from '../utils/docker.js';\nimport { SERVICES } from '../constants.js';\n\nexport async function restartCommand(service?: string): Promise<void> {\n const projectDir = getProjectDir();\n\n if (service && !(SERVICES as readonly string[]).includes(service)) {\n logger.error(`Unknown service: ${service}`);\n logger.info(`Available services: ${SERVICES.join(', ')}`);\n process.exit(1);\n }\n\n const label = service || 'all services';\n const spinner = ora(`Restarting ${label}...`).start();\n\n try {\n await composeRestart({ cwd: projectDir, service });\n spinner.succeed(`Restarted ${label}`);\n } catch (err) {\n spinner.fail(`Failed to restart ${label}`);\n logger.error(String(err));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { logger } from '../utils/logger.js';\nimport { checkDocker, checkDockerCompose } from '../utils/docker.js';\nimport { findProjectRoot, loadConfig } from '../utils/config.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE, COMPOSE_FILE, ENV_FILE } from '../constants.js';\n\nexport async function doctorCommand(): Promise<void> {\n logger.phase('Habeetat Doctor — Diagnostics');\n let issues = 0;\n\n // Check Docker\n const dockerOk = await checkDocker();\n console.log(` Docker: ${dockerOk ? chalk.green('✓ Installed') : chalk.red('✗ Not found')}`);\n if (!dockerOk) issues++;\n\n // Check Docker Compose\n const composeOk = await checkDockerCompose();\n console.log(` Docker Compose: ${composeOk ? chalk.green('✓ Available') : chalk.red('✗ Not found')}`);\n if (!composeOk) issues++;\n\n // Check project directory\n const projectDir = findProjectRoot();\n console.log(` Project dir: ${projectDir ? chalk.green(`✓ ${projectDir}`) : chalk.yellow('⚠ Not in a Habeetat project')}`);\n if (!projectDir) {\n issues++;\n console.log('');\n logger.info(`Run \\`npm create habeetat my-platform\\` to create a new project`);\n return;\n }\n\n // Check config file\n const configExists = fs.existsSync(path.join(projectDir, CONFIG_FILE));\n console.log(` ${CONFIG_FILE}: ${configExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!configExists) issues++;\n\n // Check compose file\n const composeExists = fs.existsSync(path.join(projectDir, COMPOSE_FILE));\n console.log(` ${COMPOSE_FILE}: ${composeExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!composeExists) issues++;\n\n // Check env file\n const envExists = fs.existsSync(path.join(projectDir, ENV_FILE));\n console.log(` ${ENV_FILE}: ${envExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!envExists) issues++;\n\n // Check nginx config\n const nginxExists = fs.existsSync(path.join(projectDir, 'nginx', 'platform.conf'));\n console.log(` nginx/platform.conf: ${nginxExists ? chalk.green('✓ Found') : chalk.red('✗ Missing')}`);\n if (!nginxExists) issues++;\n\n // Load config and check images\n if (configExists) {\n try {\n const config = loadConfig(projectDir);\n console.log(` Version: ${chalk.cyan(config.version)}`);\n console.log(` Domain: ${chalk.cyan(config.platform.domain)}`);\n console.log(` Protocol: ${chalk.cyan(config.platform.protocol)}`);\n } catch (err) {\n console.log(` Config: ${chalk.red('✗ Invalid JSON')}`);\n issues++;\n }\n }\n\n console.log('');\n if (issues === 0) {\n logger.success('No issues found');\n } else {\n logger.warn(`${issues} issue(s) found`);\n }\n}\n","import 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';\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.parse();\n"]}
|
package/dist/index.js
CHANGED
|
@@ -414,31 +414,13 @@ function generateHostNginxConf(config) {
|
|
|
414
414
|
# Auto-generated by @habeetat/cli for domain: ${domain}
|
|
415
415
|
# This file should be placed in /etc/nginx/sites-available/habeetat-${sanitize(domain)}
|
|
416
416
|
# and symlinked to /etc/nginx/sites-enabled/
|
|
417
|
+
#
|
|
418
|
+
# SSL will be added automatically by certbot --nginx
|
|
417
419
|
|
|
418
|
-
# HTTP \u2192 HTTPS redirect
|
|
419
420
|
server {
|
|
420
421
|
listen 80;
|
|
421
422
|
server_name ${allServerNames};
|
|
422
423
|
|
|
423
|
-
location /.well-known/acme-challenge/ {
|
|
424
|
-
root /var/www/certbot;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
location / {
|
|
428
|
-
return 301 https://$host$request_uri;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
# HTTPS \u2014 proxy all Habeetat subdomains to the container nginx
|
|
433
|
-
server {
|
|
434
|
-
listen 443 ssl;
|
|
435
|
-
server_name ${allServerNames};
|
|
436
|
-
|
|
437
|
-
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
|
438
|
-
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
|
439
|
-
include /etc/letsencrypt/options-ssl-nginx.conf;
|
|
440
|
-
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
|
441
|
-
|
|
442
424
|
client_max_body_size 50M;
|
|
443
425
|
|
|
444
426
|
location / {
|
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"],"names":["crypto","chalk","execaCommand","path","fs"],"mappings":"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","file":"index.js","sourcesContent":["export const CONFIG_FILE = 'habeetat.json';\nexport const ENV_FILE = '.env';\nexport const COMPOSE_FILE = 'docker-compose.yml';\n\nexport const DOCKER_REGISTRY = 'docker.io/capriisland';\n\nexport const IMAGES = {\n backend: 'capriisland/habeetat-backend',\n launcher: 'capriisland/habeetat-launcher',\n orgManager: 'capriisland/habeetat-org-manager',\n platformManager: 'capriisland/habeetat-platform-manager',\n sampleCrm: 'capriisland/habeetat-sample-crm',\n logtoConfig: 'capriisland/habeetat-logto-config',\n} as const;\n\nexport const THIRD_PARTY_IMAGES = {\n postgres: 'postgres:15-alpine',\n logto: 'svhd/logto:1.33',\n nginx: 'nginx:1.25-alpine',\n certbot: 'certbot/certbot',\n} as const;\n\nexport const DEFAULT_PORTS = {\n http: 80,\n https: 443,\n hostNginx: 8080,\n} as const;\n\nexport const SERVICES = [\n 'logto-db',\n 'platform-db',\n 'logto-core',\n 'backend',\n 'launcher',\n 'organization-manager',\n 'platform-manager',\n 'sample-crm',\n 'nginx',\n] as const;\n\nexport type ServiceName = (typeof SERVICES)[number];\n","import type { HabeetatConfig } from '../types.js';\nimport { THIRD_PARTY_IMAGES } from '../constants.js';\n\nexport function generateDockerCompose(config: HabeetatConfig): string {\n const tag = config.docker.imageTag;\n const registry = config.docker.registry;\n\n const services: Record<string, unknown> = {\n 'logto-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${LOGTO_DB_USER}',\n POSTGRES_PASSWORD: '${LOGTO_DB_PASSWORD}',\n POSTGRES_DB: '${LOGTO_DB_NAME}',\n },\n volumes: ['logto-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${LOGTO_DB_USER} -d ${LOGTO_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'platform-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${PLATFORM_DB_USER}',\n POSTGRES_PASSWORD: '${PLATFORM_DB_PASSWORD}',\n POSTGRES_DB: '${PLATFORM_DB_NAME}',\n },\n volumes: ['platform-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${PLATFORM_DB_USER} -d ${PLATFORM_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'logto-core': {\n image: THIRD_PARTY_IMAGES.logto,\n entrypoint: ['sh', '-c'],\n command: ['npm run cli -- db seed -- --swe && npm run start || npm run start'],\n depends_on: {\n 'logto-db': { condition: 'service_healthy' },\n },\n environment: {\n DB_URL: 'postgres://${LOGTO_DB_USER}:${LOGTO_DB_PASSWORD}@logto-db:5432/${LOGTO_DB_NAME}',\n ENDPOINT: '${LOGTO_ENDPOINT}',\n ADMIN_ENDPOINT: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_CONSOLE_URL: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_PORT: '3002',\n TRUST_PROXY_HEADER: '1',\n COOKIE_KEYS: '${ENCRYPTION_KEY}',\n ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n CORS_ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n ADMIN_CONSOLE_ALLOWED_ORIGINS: '${LOGTO_ADMIN_ENDPOINT}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'wget -q --spider http://localhost:3001/oidc/.well-known/openid-configuration || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '90s',\n },\n },\n\n backend: {\n image: `${registry}/habeetat-backend:${tag}`,\n depends_on: {\n 'logto-core': { condition: 'service_healthy' },\n 'platform-db': { condition: 'service_healthy' },\n },\n environment: {\n NODE_ENV: 'production',\n DATABASE_URL: 'postgres://${PLATFORM_DB_USER}:${PLATFORM_DB_PASSWORD}@platform-db:5432/${PLATFORM_DB_NAME}',\n IAM_ISSUER_URL: '${LOGTO_ENDPOINT}/oidc',\n IAM_JWKS_URL: 'http://logto-core:3001',\n IAM_AUDIENCE: '${IAM_AUDIENCE}',\n LOGTO_ENDPOINT: 'http://logto-core:3001',\n LOGTO_EXTERNAL_ENDPOINT: '${LOGTO_ENDPOINT}',\n SDK_API_RESOURCE: '${IAM_AUDIENCE}',\n LOGTO_M2M_APP_ID: 'nhp-m2m-config',\n LOGTO_M2M_APP_SECRET: '${LOGTO_M2M_APP_SECRET}',\n ENCRYPTION_KEY: '${ENCRYPTION_KEY}',\n LAUNCHER_URL: '${LAUNCHER_URL}',\n CORS_ORIGINS: '${CORS_ORIGINS}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD', 'curl', '-f', 'http://localhost:3001/platform/status'],\n interval: '30s',\n timeout: '10s',\n retries: 3,\n start_period: '60s',\n },\n },\n };\n\n if (config.services.launcher) {\n services['launcher'] = {\n image: `${registry}/habeetat-launcher:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_IAM_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_IAM_AUDIENCE: '${IAM_AUDIENCE}',\n VITE_IAM_APP_ID: 'nhp-launcher',\n VITE_APP_BASE_URL: '${LAUNCHER_URL}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.organizationManager) {\n services['organization-manager'] = {\n image: `${registry}/habeetat-org-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-org-manager',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${ORG_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.platformManager) {\n services['platform-manager'] = {\n image: `${registry}/habeetat-platform-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-plat-mgr',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${PLATFORM_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.sampleCrm) {\n services['sample-crm'] = {\n image: `${registry}/habeetat-sample-crm:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n VITE_APP_BASE_URL: '${SAMPLE_CRM_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n // Nginx reverse proxy (internal routing only — SSL handled by host nginx)\n const nginxDependsOn = ['logto-core', 'backend'];\n if (config.services.launcher) nginxDependsOn.push('launcher');\n if (config.services.organizationManager) nginxDependsOn.push('organization-manager');\n if (config.services.platformManager) nginxDependsOn.push('platform-manager');\n if (config.services.sampleCrm) nginxDependsOn.push('sample-crm');\n\n const hostPort = config.nginx.hostPort;\n\n services['nginx'] = {\n image: THIRD_PARTY_IMAGES.nginx,\n depends_on: nginxDependsOn,\n volumes: ['./nginx/platform.conf:/etc/nginx/conf.d/default.conf:ro'],\n ports: [`127.0.0.1:${hostPort}:80`],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n command: `/bin/sh -c 'while :; do sleep 6h & wait $\\${!}; nginx -s reload; done & nginx -g \"daemon off;\"'`,\n };\n\n const compose = {\n name: 'habeetat',\n services,\n volumes: {\n 'logto-db-data': null,\n 'platform-db-data': null,\n },\n networks: {\n 'habeetat-network': {\n driver: 'bridge',\n },\n },\n };\n\n return toYaml(compose);\n}\n\n// Minimal YAML serializer — avoids adding a dependency for simple structure\nfunction toYaml(obj: unknown, indent = 0): string {\n const pad = ' '.repeat(indent);\n\n if (obj === null || obj === undefined) return '';\n if (typeof obj === 'string') {\n if (obj.includes('\\n') || obj.includes(\"'\") || obj.includes('\"') || obj.includes(':') || obj.includes('#') || obj.includes('{') || obj.includes('}') || obj.includes('$')) {\n return `'${obj.replace(/'/g, \"''\")}'`;\n }\n return obj;\n }\n if (typeof obj === 'number' || typeof obj === 'boolean') return String(obj);\n\n if (Array.isArray(obj)) {\n if (obj.length === 0) return '[]';\n // Check if all items are scalars\n const allScalar = obj.every(\n (item) => typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean',\n );\n if (allScalar) {\n return obj\n .map((item) => `\\n${pad}- ${toYaml(item, indent + 2)}`)\n .join('');\n }\n return obj\n .map((item) => {\n const val = toYaml(item, indent + 2);\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n // Object inside array — inline the first key after the dash\n const lines = val.split('\\n').filter((l) => l.trim());\n if (lines.length > 0) {\n const first = lines[0].trimStart();\n const rest = lines.slice(1).map((l) => `${pad} ${l.trimStart()}`).join('\\n');\n return `\\n${pad}- ${first}${rest ? '\\n' + rest : ''}`;\n }\n }\n return `\\n${pad}- ${val}`;\n })\n .join('');\n }\n\n if (typeof obj === 'object') {\n const entries = Object.entries(obj as Record<string, unknown>);\n if (entries.length === 0) return '{}';\n return entries\n .map(([key, value]) => {\n if (value === null || value === undefined) return `${pad}${key}:`;\n if (typeof value === 'object' && !Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:\\n${nested}`;\n }\n if (Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:${nested}`;\n }\n return `${pad}${key}: ${toYaml(value, indent)}`;\n })\n .join('\\n');\n }\n\n return String(obj);\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n\n const upstreams = [\n 'upstream logto { server logto-core:3001; }',\n 'upstream logto_admin { server logto-core:3002; }',\n 'upstream api { server backend:3001; }',\n ];\n\n if (config.services.launcher) upstreams.push('upstream launcher { server launcher:80; }');\n if (config.services.organizationManager) upstreams.push('upstream organization-manager { server organization-manager:80; }');\n if (config.services.platformManager) upstreams.push('upstream platform-manager { server platform-manager:80; }');\n if (config.services.sampleCrm) upstreams.push('upstream sample-crm { server sample-crm:80; }');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;`;\n\n const serverBlocks: string[] = [];\n\n // Logto IAM\n serverBlocks.push(`\nserver {\n listen 80;\n server_name iam.${domain};\n location / {\n proxy_pass http://logto;${proxyHeaders}\n }\n}`);\n\n // Logto Admin Console\n serverBlocks.push(`\nserver {\n listen 80;\n server_name iam-console.${domain};\n location / {\n proxy_pass http://logto_admin;${proxyHeaders}\n }\n}`);\n\n // Backend API\n serverBlocks.push(`\nserver {\n listen 80;\n server_name api.${domain};\n location / {\n limit_req zone=api_limit burst=20 nodelay;\n proxy_pass http://api;${proxyHeaders}\n }\n}`);\n\n // Launcher\n if (config.services.launcher) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name launcher.${domain};\n location / {\n proxy_pass http://launcher;${proxyHeaders}\n }\n}`);\n }\n\n // Organization Manager\n if (config.services.organizationManager) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name organization-manager.${domain};\n location / {\n proxy_pass http://organization-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Platform Manager\n if (config.services.platformManager) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name platform-manager.${domain};\n location / {\n proxy_pass http://platform-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Sample CRM\n if (config.services.sampleCrm) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name sample-crm.${domain};\n location / {\n proxy_pass http://sample-crm;${proxyHeaders}\n }\n}`);\n }\n\n return `# Habeetat Platform - Container Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n# This handles internal routing between Docker services.\n# SSL is handled by the host nginx (see /etc/nginx/sites-enabled/).\n\n${upstreams.join('\\n')}\n\nlimit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;\n${serverBlocks.join('\\n')}\n`;\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateHostNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n const port = config.nginx.hostPort;\n\n const subdomains = [\n 'iam',\n 'iam-console',\n 'api',\n ];\n\n if (config.services.launcher) subdomains.push('launcher');\n if (config.services.organizationManager) subdomains.push('organization-manager');\n if (config.services.platformManager) subdomains.push('platform-manager');\n if (config.services.sampleCrm) subdomains.push('sample-crm');\n\n const allServerNames = subdomains.map((s) => `${s}.${domain}`).join(' ');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_set_header X-Forwarded-Host $host;\n proxy_http_version 1.1;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection \"upgrade\";`;\n\n return `# Habeetat Platform - Host Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n# This file should be placed in /etc/nginx/sites-available/habeetat-${sanitize(domain)}\n# and symlinked to /etc/nginx/sites-enabled/\n\n# HTTP → HTTPS redirect\nserver {\n listen 80;\n server_name ${allServerNames};\n\n location /.well-known/acme-challenge/ {\n root /var/www/certbot;\n }\n\n location / {\n return 301 https://$host$request_uri;\n }\n}\n\n# HTTPS — proxy all Habeetat subdomains to the container nginx\nserver {\n listen 443 ssl;\n server_name ${allServerNames};\n\n ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;\n ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;\n include /etc/letsencrypt/options-ssl-nginx.conf;\n ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;\n\n client_max_body_size 50M;\n\n location / {\n proxy_pass http://127.0.0.1:${port};${proxyHeaders}\n }\n}\n`;\n}\n\nfunction sanitize(domain: string): string {\n return domain.replace(/[^a-zA-Z0-9.-]/g, '-');\n}\n","import crypto from 'node:crypto';\n\nexport function randomHex(bytes: number): string {\n return crypto.randomBytes(bytes).toString('hex');\n}\n\nexport function generateSecrets() {\n return {\n logtoDbPassword: randomHex(16),\n platformDbPassword: randomHex(16),\n encryptionKey: randomHex(32),\n logtoM2mAppSecret: randomHex(32),\n };\n}\n","import type { CreateOptions } from '../types.js';\nimport { generateSecrets } from '../utils/crypto.js';\n\nexport function generateEnvFile(opts: CreateOptions): string {\n const protocol = opts.ssl ? 'https' : 'http';\n const domain = opts.domain;\n const secrets = generateSecrets();\n\n return `# Habeetat Platform - Environment Configuration\n# Generated by @habeetat/cli on ${new Date().toISOString()}\n\n# ============================================\n# Domain Configuration\n# ============================================\nDOMAIN=${domain}\nPROTOCOL=${protocol}\n\n# ============================================\n# Service URLs (External - Browser-facing)\n# ============================================\nLOGTO_ENDPOINT=${protocol}://iam.${domain}\nLOGTO_ADMIN_ENDPOINT=${protocol}://iam-console.${domain}\nLAUNCHER_URL=${protocol}://launcher.${domain}\nORG_MANAGER_URL=${protocol}://organization-manager.${domain}\nPLATFORM_MANAGER_URL=${protocol}://platform-manager.${domain}\nSAMPLE_CRM_URL=${protocol}://sample-crm.${domain}\nBACKEND_API_URL=${protocol}://api.${domain}\nCORS_ORIGINS=${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain},${protocol}://sample-crm.${domain}\n\n# ============================================\n# Database Configuration\n# ============================================\nLOGTO_DB_USER=logto\nLOGTO_DB_PASSWORD=${secrets.logtoDbPassword}\nLOGTO_DB_NAME=logto\n\nPLATFORM_DB_USER=habeetat\nPLATFORM_DB_PASSWORD=${secrets.platformDbPassword}\nPLATFORM_DB_NAME=habeetat_platform\n\n# ============================================\n# Logto IAM Configuration\n# ============================================\nLOGTO_ADMIN_USERNAME=${opts.adminEmail}\nLOGTO_ADMIN_PASSWORD=${opts.adminPassword}\n\nIAM_ISSUER_URL=${protocol}://iam.${domain}/oidc\nIAM_AUDIENCE=${protocol}://api.${domain}/api\nSDK_API_RESOURCE=${protocol}://api.${domain}/api\n\nLOGTO_M2M_APP_ID=nhp-m2m-config\nLOGTO_M2M_APP_SECRET=${secrets.logtoM2mAppSecret}\n\n# ============================================\n# Platform Configuration\n# ============================================\nPLATFORM_ADMIN_EMAIL=${opts.adminEmail}\nPLATFORM_ADMIN_PASSWORD=${opts.adminPassword}\nORGANIZATION_NAME=${opts.organizationName}\n\n# ============================================\n# Security\n# ============================================\nENCRYPTION_KEY=${secrets.encryptionKey}\n\n# ============================================\n# CORS Configuration\n# ============================================\nALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\nCORS_ALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\n`;\n}\n","import chalk from 'chalk';\n\nconst prefix = chalk.cyan('[habeetat]');\n\nexport const logger = {\n info: (msg: string) => console.log(`${prefix} ${msg}`),\n success: (msg: string) => console.log(`${prefix} ${chalk.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(`${prefix} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${prefix} ${chalk.red('✗')} ${msg}`),\n phase: (msg: string) => {\n console.log('');\n console.log(chalk.cyan('═'.repeat(56)));\n console.log(chalk.cyan(` ${msg}`));\n console.log(chalk.cyan('═'.repeat(56)));\n console.log('');\n },\n banner: () => {\n console.log('');\n console.log(chalk.cyan('╔══════════════════════════════════════════════╗'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('║ Habeetat Platform CLI ║'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('╚══════════════════════════════════════════════╝'));\n console.log('');\n },\n};\n","import { execaCommand } from 'execa';\nimport { logger } from './logger.js';\n\nexport async function checkDocker(): Promise<boolean> {\n try {\n const { stdout } = await execaCommand('docker --version');\n const match = stdout.match(/Docker version (\\d+)/);\n if (match && parseInt(match[1], 10) >= 20) {\n return true;\n }\n logger.error(`Docker >= 20.0 required. Found: ${stdout.trim()}`);\n return false;\n } catch {\n logger.error('Docker is not installed or not in PATH');\n logger.info('Install Docker: https://docs.docker.com/get-docker/');\n return false;\n }\n}\n\nexport async function checkDockerCompose(): Promise<boolean> {\n try {\n await execaCommand('docker compose version');\n return true;\n } catch {\n logger.error('Docker Compose V2 is not available');\n logger.info('Docker Compose V2 is included with Docker Desktop');\n return false;\n }\n}\n\nexport async function checkPrerequisites(): Promise<boolean> {\n const docker = await checkDocker();\n const compose = await checkDockerCompose();\n return docker && compose;\n}\n\nexport interface ComposeExecOptions {\n cwd: string;\n composeFile?: string;\n silent?: boolean;\n}\n\nexport async function composeUp(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} up -d`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeDown(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composePs(opts: ComposeExecOptions): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(`docker compose -f ${file} ps`, {\n cwd: opts.cwd,\n });\n return stdout;\n}\n\nexport async function composeLogs(\n opts: ComposeExecOptions & { service?: string; follow?: boolean; tail?: number },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const parts = ['docker', 'compose', '-f', file, 'logs'];\n if (opts.follow) parts.push('-f');\n if (opts.tail) parts.push('--tail', String(opts.tail));\n if (opts.service) parts.push(opts.service);\n\n await execaCommand(parts.join(' '), {\n cwd: opts.cwd,\n stdio: 'inherit',\n });\n}\n\nexport async function composeRestart(\n opts: ComposeExecOptions & { service?: string },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const cmd = opts.service\n ? `docker compose -f ${file} restart ${opts.service}`\n : `docker compose -f ${file} restart`;\n\n await execaCommand(cmd, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeExec(\n opts: ComposeExecOptions & { service: string; command: string },\n): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(\n `docker compose -f ${file} exec -T ${opts.service} ${opts.command}`,\n { cwd: opts.cwd },\n );\n return stdout;\n}\n\nexport async function dockerPull(image: string): Promise<void> {\n await execaCommand(`docker pull ${image}`, { stdio: 'inherit' });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE } from '../constants.js';\nimport type { HabeetatConfig } from '../types.js';\n\nexport function findProjectRoot(startDir: string = process.cwd()): string | null {\n let dir = startDir;\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, CONFIG_FILE))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nexport function loadConfig(projectDir?: string): HabeetatConfig {\n const dir = projectDir || findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n const configPath = path.join(dir, CONFIG_FILE);\n const raw = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as HabeetatConfig;\n}\n\nexport function saveConfig(config: HabeetatConfig, projectDir: string): void {\n const configPath = path.join(projectDir, CONFIG_FILE);\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function getProjectDir(): string {\n const dir = findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n return dir;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/templates/docker-compose.ts","../src/templates/nginx.ts","../src/templates/host-nginx.ts","../src/utils/crypto.ts","../src/templates/env.ts","../src/utils/logger.ts","../src/utils/docker.ts","../src/utils/config.ts"],"names":["crypto","chalk","execaCommand","path","fs"],"mappings":"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","file":"index.js","sourcesContent":["export const CONFIG_FILE = 'habeetat.json';\nexport const ENV_FILE = '.env';\nexport const COMPOSE_FILE = 'docker-compose.yml';\n\nexport const DOCKER_REGISTRY = 'docker.io/capriisland';\n\nexport const IMAGES = {\n backend: 'capriisland/habeetat-backend',\n launcher: 'capriisland/habeetat-launcher',\n orgManager: 'capriisland/habeetat-org-manager',\n platformManager: 'capriisland/habeetat-platform-manager',\n sampleCrm: 'capriisland/habeetat-sample-crm',\n logtoConfig: 'capriisland/habeetat-logto-config',\n} as const;\n\nexport const THIRD_PARTY_IMAGES = {\n postgres: 'postgres:15-alpine',\n logto: 'svhd/logto:1.33',\n nginx: 'nginx:1.25-alpine',\n certbot: 'certbot/certbot',\n} as const;\n\nexport const DEFAULT_PORTS = {\n http: 80,\n https: 443,\n hostNginx: 8080,\n} as const;\n\nexport const SERVICES = [\n 'logto-db',\n 'platform-db',\n 'logto-core',\n 'backend',\n 'launcher',\n 'organization-manager',\n 'platform-manager',\n 'sample-crm',\n 'nginx',\n] as const;\n\nexport type ServiceName = (typeof SERVICES)[number];\n","import type { HabeetatConfig } from '../types.js';\nimport { THIRD_PARTY_IMAGES } from '../constants.js';\n\nexport function generateDockerCompose(config: HabeetatConfig): string {\n const tag = config.docker.imageTag;\n const registry = config.docker.registry;\n\n const services: Record<string, unknown> = {\n 'logto-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${LOGTO_DB_USER}',\n POSTGRES_PASSWORD: '${LOGTO_DB_PASSWORD}',\n POSTGRES_DB: '${LOGTO_DB_NAME}',\n },\n volumes: ['logto-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${LOGTO_DB_USER} -d ${LOGTO_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'platform-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${PLATFORM_DB_USER}',\n POSTGRES_PASSWORD: '${PLATFORM_DB_PASSWORD}',\n POSTGRES_DB: '${PLATFORM_DB_NAME}',\n },\n volumes: ['platform-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${PLATFORM_DB_USER} -d ${PLATFORM_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'logto-core': {\n image: THIRD_PARTY_IMAGES.logto,\n entrypoint: ['sh', '-c'],\n command: ['npm run cli -- db seed -- --swe && npm run start || npm run start'],\n depends_on: {\n 'logto-db': { condition: 'service_healthy' },\n },\n environment: {\n DB_URL: 'postgres://${LOGTO_DB_USER}:${LOGTO_DB_PASSWORD}@logto-db:5432/${LOGTO_DB_NAME}',\n ENDPOINT: '${LOGTO_ENDPOINT}',\n ADMIN_ENDPOINT: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_CONSOLE_URL: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_PORT: '3002',\n TRUST_PROXY_HEADER: '1',\n COOKIE_KEYS: '${ENCRYPTION_KEY}',\n ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n CORS_ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n ADMIN_CONSOLE_ALLOWED_ORIGINS: '${LOGTO_ADMIN_ENDPOINT}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'wget -q --spider http://localhost:3001/oidc/.well-known/openid-configuration || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '90s',\n },\n },\n\n backend: {\n image: `${registry}/habeetat-backend:${tag}`,\n depends_on: {\n 'logto-core': { condition: 'service_healthy' },\n 'platform-db': { condition: 'service_healthy' },\n },\n environment: {\n NODE_ENV: 'production',\n DATABASE_URL: 'postgres://${PLATFORM_DB_USER}:${PLATFORM_DB_PASSWORD}@platform-db:5432/${PLATFORM_DB_NAME}',\n IAM_ISSUER_URL: '${LOGTO_ENDPOINT}/oidc',\n IAM_JWKS_URL: 'http://logto-core:3001',\n IAM_AUDIENCE: '${IAM_AUDIENCE}',\n LOGTO_ENDPOINT: 'http://logto-core:3001',\n LOGTO_EXTERNAL_ENDPOINT: '${LOGTO_ENDPOINT}',\n SDK_API_RESOURCE: '${IAM_AUDIENCE}',\n LOGTO_M2M_APP_ID: 'nhp-m2m-config',\n LOGTO_M2M_APP_SECRET: '${LOGTO_M2M_APP_SECRET}',\n ENCRYPTION_KEY: '${ENCRYPTION_KEY}',\n LAUNCHER_URL: '${LAUNCHER_URL}',\n CORS_ORIGINS: '${CORS_ORIGINS}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD', 'curl', '-f', 'http://localhost:3001/platform/status'],\n interval: '30s',\n timeout: '10s',\n retries: 3,\n start_period: '60s',\n },\n },\n };\n\n if (config.services.launcher) {\n services['launcher'] = {\n image: `${registry}/habeetat-launcher:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_IAM_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_IAM_AUDIENCE: '${IAM_AUDIENCE}',\n VITE_IAM_APP_ID: 'nhp-launcher',\n VITE_APP_BASE_URL: '${LAUNCHER_URL}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.organizationManager) {\n services['organization-manager'] = {\n image: `${registry}/habeetat-org-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-org-manager',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${ORG_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.platformManager) {\n services['platform-manager'] = {\n image: `${registry}/habeetat-platform-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-plat-mgr',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${PLATFORM_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.sampleCrm) {\n services['sample-crm'] = {\n image: `${registry}/habeetat-sample-crm:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n VITE_APP_BASE_URL: '${SAMPLE_CRM_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n // Nginx reverse proxy (internal routing only — SSL handled by host nginx)\n const nginxDependsOn = ['logto-core', 'backend'];\n if (config.services.launcher) nginxDependsOn.push('launcher');\n if (config.services.organizationManager) nginxDependsOn.push('organization-manager');\n if (config.services.platformManager) nginxDependsOn.push('platform-manager');\n if (config.services.sampleCrm) nginxDependsOn.push('sample-crm');\n\n const hostPort = config.nginx.hostPort;\n\n services['nginx'] = {\n image: THIRD_PARTY_IMAGES.nginx,\n depends_on: nginxDependsOn,\n volumes: ['./nginx/platform.conf:/etc/nginx/conf.d/default.conf:ro'],\n ports: [`127.0.0.1:${hostPort}:80`],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n command: `/bin/sh -c 'while :; do sleep 6h & wait $\\${!}; nginx -s reload; done & nginx -g \"daemon off;\"'`,\n };\n\n const compose = {\n name: 'habeetat',\n services,\n volumes: {\n 'logto-db-data': null,\n 'platform-db-data': null,\n },\n networks: {\n 'habeetat-network': {\n driver: 'bridge',\n },\n },\n };\n\n return toYaml(compose);\n}\n\n// Minimal YAML serializer — avoids adding a dependency for simple structure\nfunction toYaml(obj: unknown, indent = 0): string {\n const pad = ' '.repeat(indent);\n\n if (obj === null || obj === undefined) return '';\n if (typeof obj === 'string') {\n if (obj.includes('\\n') || obj.includes(\"'\") || obj.includes('\"') || obj.includes(':') || obj.includes('#') || obj.includes('{') || obj.includes('}') || obj.includes('$')) {\n return `'${obj.replace(/'/g, \"''\")}'`;\n }\n return obj;\n }\n if (typeof obj === 'number' || typeof obj === 'boolean') return String(obj);\n\n if (Array.isArray(obj)) {\n if (obj.length === 0) return '[]';\n // Check if all items are scalars\n const allScalar = obj.every(\n (item) => typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean',\n );\n if (allScalar) {\n return obj\n .map((item) => `\\n${pad}- ${toYaml(item, indent + 2)}`)\n .join('');\n }\n return obj\n .map((item) => {\n const val = toYaml(item, indent + 2);\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n // Object inside array — inline the first key after the dash\n const lines = val.split('\\n').filter((l) => l.trim());\n if (lines.length > 0) {\n const first = lines[0].trimStart();\n const rest = lines.slice(1).map((l) => `${pad} ${l.trimStart()}`).join('\\n');\n return `\\n${pad}- ${first}${rest ? '\\n' + rest : ''}`;\n }\n }\n return `\\n${pad}- ${val}`;\n })\n .join('');\n }\n\n if (typeof obj === 'object') {\n const entries = Object.entries(obj as Record<string, unknown>);\n if (entries.length === 0) return '{}';\n return entries\n .map(([key, value]) => {\n if (value === null || value === undefined) return `${pad}${key}:`;\n if (typeof value === 'object' && !Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:\\n${nested}`;\n }\n if (Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:${nested}`;\n }\n return `${pad}${key}: ${toYaml(value, indent)}`;\n })\n .join('\\n');\n }\n\n return String(obj);\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n\n const upstreams = [\n 'upstream logto { server logto-core:3001; }',\n 'upstream logto_admin { server logto-core:3002; }',\n 'upstream api { server backend:3001; }',\n ];\n\n if (config.services.launcher) upstreams.push('upstream launcher { server launcher:80; }');\n if (config.services.organizationManager) upstreams.push('upstream organization-manager { server organization-manager:80; }');\n if (config.services.platformManager) upstreams.push('upstream platform-manager { server platform-manager:80; }');\n if (config.services.sampleCrm) upstreams.push('upstream sample-crm { server sample-crm:80; }');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;`;\n\n const serverBlocks: string[] = [];\n\n // Logto IAM\n serverBlocks.push(`\nserver {\n listen 80;\n server_name iam.${domain};\n location / {\n proxy_pass http://logto;${proxyHeaders}\n }\n}`);\n\n // Logto Admin Console\n serverBlocks.push(`\nserver {\n listen 80;\n server_name iam-console.${domain};\n location / {\n proxy_pass http://logto_admin;${proxyHeaders}\n }\n}`);\n\n // Backend API\n serverBlocks.push(`\nserver {\n listen 80;\n server_name api.${domain};\n location / {\n limit_req zone=api_limit burst=20 nodelay;\n proxy_pass http://api;${proxyHeaders}\n }\n}`);\n\n // Launcher\n if (config.services.launcher) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name launcher.${domain};\n location / {\n proxy_pass http://launcher;${proxyHeaders}\n }\n}`);\n }\n\n // Organization Manager\n if (config.services.organizationManager) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name organization-manager.${domain};\n location / {\n proxy_pass http://organization-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Platform Manager\n if (config.services.platformManager) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name platform-manager.${domain};\n location / {\n proxy_pass http://platform-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Sample CRM\n if (config.services.sampleCrm) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name sample-crm.${domain};\n location / {\n proxy_pass http://sample-crm;${proxyHeaders}\n }\n}`);\n }\n\n return `# Habeetat Platform - Container Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n# This handles internal routing between Docker services.\n# SSL is handled by the host nginx (see /etc/nginx/sites-enabled/).\n\n${upstreams.join('\\n')}\n\nlimit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;\n${serverBlocks.join('\\n')}\n`;\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateHostNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n const port = config.nginx.hostPort;\n\n const subdomains = [\n 'iam',\n 'iam-console',\n 'api',\n ];\n\n if (config.services.launcher) subdomains.push('launcher');\n if (config.services.organizationManager) subdomains.push('organization-manager');\n if (config.services.platformManager) subdomains.push('platform-manager');\n if (config.services.sampleCrm) subdomains.push('sample-crm');\n\n const allServerNames = subdomains.map((s) => `${s}.${domain}`).join(' ');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_set_header X-Forwarded-Host $host;\n proxy_http_version 1.1;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection \"upgrade\";`;\n\n return `# Habeetat Platform - Host Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n# This file should be placed in /etc/nginx/sites-available/habeetat-${sanitize(domain)}\n# and symlinked to /etc/nginx/sites-enabled/\n#\n# 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 };\n}\n","import type { CreateOptions } from '../types.js';\nimport { generateSecrets } from '../utils/crypto.js';\n\nexport function generateEnvFile(opts: CreateOptions): string {\n const protocol = opts.ssl ? 'https' : 'http';\n const domain = opts.domain;\n const secrets = generateSecrets();\n\n return `# Habeetat Platform - Environment Configuration\n# Generated by @habeetat/cli on ${new Date().toISOString()}\n\n# ============================================\n# Domain Configuration\n# ============================================\nDOMAIN=${domain}\nPROTOCOL=${protocol}\n\n# ============================================\n# Service URLs (External - Browser-facing)\n# ============================================\nLOGTO_ENDPOINT=${protocol}://iam.${domain}\nLOGTO_ADMIN_ENDPOINT=${protocol}://iam-console.${domain}\nLAUNCHER_URL=${protocol}://launcher.${domain}\nORG_MANAGER_URL=${protocol}://organization-manager.${domain}\nPLATFORM_MANAGER_URL=${protocol}://platform-manager.${domain}\nSAMPLE_CRM_URL=${protocol}://sample-crm.${domain}\nBACKEND_API_URL=${protocol}://api.${domain}\nCORS_ORIGINS=${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain},${protocol}://sample-crm.${domain}\n\n# ============================================\n# Database Configuration\n# ============================================\nLOGTO_DB_USER=logto\nLOGTO_DB_PASSWORD=${secrets.logtoDbPassword}\nLOGTO_DB_NAME=logto\n\nPLATFORM_DB_USER=habeetat\nPLATFORM_DB_PASSWORD=${secrets.platformDbPassword}\nPLATFORM_DB_NAME=habeetat_platform\n\n# ============================================\n# Logto IAM Configuration\n# ============================================\nLOGTO_ADMIN_USERNAME=${opts.adminEmail}\nLOGTO_ADMIN_PASSWORD=${opts.adminPassword}\n\nIAM_ISSUER_URL=${protocol}://iam.${domain}/oidc\nIAM_AUDIENCE=${protocol}://api.${domain}/api\nSDK_API_RESOURCE=${protocol}://api.${domain}/api\n\nLOGTO_M2M_APP_ID=nhp-m2m-config\nLOGTO_M2M_APP_SECRET=${secrets.logtoM2mAppSecret}\n\n# ============================================\n# Platform Configuration\n# ============================================\nPLATFORM_ADMIN_EMAIL=${opts.adminEmail}\nPLATFORM_ADMIN_PASSWORD=${opts.adminPassword}\nORGANIZATION_NAME=${opts.organizationName}\n\n# ============================================\n# Security\n# ============================================\nENCRYPTION_KEY=${secrets.encryptionKey}\n\n# ============================================\n# CORS Configuration\n# ============================================\nALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\nCORS_ALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\n`;\n}\n","import chalk from 'chalk';\n\nconst prefix = chalk.cyan('[habeetat]');\n\nexport const logger = {\n info: (msg: string) => console.log(`${prefix} ${msg}`),\n success: (msg: string) => console.log(`${prefix} ${chalk.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(`${prefix} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${prefix} ${chalk.red('✗')} ${msg}`),\n phase: (msg: string) => {\n console.log('');\n console.log(chalk.cyan('═'.repeat(56)));\n console.log(chalk.cyan(` ${msg}`));\n console.log(chalk.cyan('═'.repeat(56)));\n console.log('');\n },\n banner: () => {\n console.log('');\n console.log(chalk.cyan('╔══════════════════════════════════════════════╗'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('║ Habeetat Platform CLI ║'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('╚══════════════════════════════════════════════╝'));\n console.log('');\n },\n};\n","import { execaCommand } from 'execa';\nimport { logger } from './logger.js';\n\nexport async function checkDocker(): Promise<boolean> {\n try {\n const { stdout } = await execaCommand('docker --version');\n const match = stdout.match(/Docker version (\\d+)/);\n if (match && parseInt(match[1], 10) >= 20) {\n return true;\n }\n logger.error(`Docker >= 20.0 required. Found: ${stdout.trim()}`);\n return false;\n } catch {\n logger.error('Docker is not installed or not in PATH');\n logger.info('Install Docker: https://docs.docker.com/get-docker/');\n return false;\n }\n}\n\nexport async function checkDockerCompose(): Promise<boolean> {\n try {\n await execaCommand('docker compose version');\n return true;\n } catch {\n logger.error('Docker Compose V2 is not available');\n logger.info('Docker Compose V2 is included with Docker Desktop');\n return false;\n }\n}\n\nexport async function checkPrerequisites(): Promise<boolean> {\n const docker = await checkDocker();\n const compose = await checkDockerCompose();\n return docker && compose;\n}\n\nexport interface ComposeExecOptions {\n cwd: string;\n composeFile?: string;\n silent?: boolean;\n}\n\nexport async function composeUp(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} up -d`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeDown(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function 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"]}
|
package/dist/index.mjs
CHANGED
|
@@ -405,31 +405,13 @@ function generateHostNginxConf(config) {
|
|
|
405
405
|
# Auto-generated by @habeetat/cli for domain: ${domain}
|
|
406
406
|
# This file should be placed in /etc/nginx/sites-available/habeetat-${sanitize(domain)}
|
|
407
407
|
# and symlinked to /etc/nginx/sites-enabled/
|
|
408
|
+
#
|
|
409
|
+
# SSL will be added automatically by certbot --nginx
|
|
408
410
|
|
|
409
|
-
# HTTP \u2192 HTTPS redirect
|
|
410
411
|
server {
|
|
411
412
|
listen 80;
|
|
412
413
|
server_name ${allServerNames};
|
|
413
414
|
|
|
414
|
-
location /.well-known/acme-challenge/ {
|
|
415
|
-
root /var/www/certbot;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
location / {
|
|
419
|
-
return 301 https://$host$request_uri;
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
# HTTPS \u2014 proxy all Habeetat subdomains to the container nginx
|
|
424
|
-
server {
|
|
425
|
-
listen 443 ssl;
|
|
426
|
-
server_name ${allServerNames};
|
|
427
|
-
|
|
428
|
-
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
|
429
|
-
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
|
430
|
-
include /etc/letsencrypt/options-ssl-nginx.conf;
|
|
431
|
-
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
|
432
|
-
|
|
433
415
|
client_max_body_size 50M;
|
|
434
416
|
|
|
435
417
|
location / {
|
package/dist/index.mjs.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"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export const CONFIG_FILE = 'habeetat.json';\nexport const ENV_FILE = '.env';\nexport const COMPOSE_FILE = 'docker-compose.yml';\n\nexport const DOCKER_REGISTRY = 'docker.io/capriisland';\n\nexport const IMAGES = {\n backend: 'capriisland/habeetat-backend',\n launcher: 'capriisland/habeetat-launcher',\n orgManager: 'capriisland/habeetat-org-manager',\n platformManager: 'capriisland/habeetat-platform-manager',\n sampleCrm: 'capriisland/habeetat-sample-crm',\n logtoConfig: 'capriisland/habeetat-logto-config',\n} as const;\n\nexport const THIRD_PARTY_IMAGES = {\n postgres: 'postgres:15-alpine',\n logto: 'svhd/logto:1.33',\n nginx: 'nginx:1.25-alpine',\n certbot: 'certbot/certbot',\n} as const;\n\nexport const DEFAULT_PORTS = {\n http: 80,\n https: 443,\n hostNginx: 8080,\n} as const;\n\nexport const SERVICES = [\n 'logto-db',\n 'platform-db',\n 'logto-core',\n 'backend',\n 'launcher',\n 'organization-manager',\n 'platform-manager',\n 'sample-crm',\n 'nginx',\n] as const;\n\nexport type ServiceName = (typeof SERVICES)[number];\n","import type { HabeetatConfig } from '../types.js';\nimport { THIRD_PARTY_IMAGES } from '../constants.js';\n\nexport function generateDockerCompose(config: HabeetatConfig): string {\n const tag = config.docker.imageTag;\n const registry = config.docker.registry;\n\n const services: Record<string, unknown> = {\n 'logto-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${LOGTO_DB_USER}',\n POSTGRES_PASSWORD: '${LOGTO_DB_PASSWORD}',\n POSTGRES_DB: '${LOGTO_DB_NAME}',\n },\n volumes: ['logto-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${LOGTO_DB_USER} -d ${LOGTO_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'platform-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${PLATFORM_DB_USER}',\n POSTGRES_PASSWORD: '${PLATFORM_DB_PASSWORD}',\n POSTGRES_DB: '${PLATFORM_DB_NAME}',\n },\n volumes: ['platform-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${PLATFORM_DB_USER} -d ${PLATFORM_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'logto-core': {\n image: THIRD_PARTY_IMAGES.logto,\n entrypoint: ['sh', '-c'],\n command: ['npm run cli -- db seed -- --swe && npm run start || npm run start'],\n depends_on: {\n 'logto-db': { condition: 'service_healthy' },\n },\n environment: {\n DB_URL: 'postgres://${LOGTO_DB_USER}:${LOGTO_DB_PASSWORD}@logto-db:5432/${LOGTO_DB_NAME}',\n ENDPOINT: '${LOGTO_ENDPOINT}',\n ADMIN_ENDPOINT: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_CONSOLE_URL: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_PORT: '3002',\n TRUST_PROXY_HEADER: '1',\n COOKIE_KEYS: '${ENCRYPTION_KEY}',\n ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n CORS_ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n ADMIN_CONSOLE_ALLOWED_ORIGINS: '${LOGTO_ADMIN_ENDPOINT}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'wget -q --spider http://localhost:3001/oidc/.well-known/openid-configuration || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '90s',\n },\n },\n\n backend: {\n image: `${registry}/habeetat-backend:${tag}`,\n depends_on: {\n 'logto-core': { condition: 'service_healthy' },\n 'platform-db': { condition: 'service_healthy' },\n },\n environment: {\n NODE_ENV: 'production',\n DATABASE_URL: 'postgres://${PLATFORM_DB_USER}:${PLATFORM_DB_PASSWORD}@platform-db:5432/${PLATFORM_DB_NAME}',\n IAM_ISSUER_URL: '${LOGTO_ENDPOINT}/oidc',\n IAM_JWKS_URL: 'http://logto-core:3001',\n IAM_AUDIENCE: '${IAM_AUDIENCE}',\n LOGTO_ENDPOINT: 'http://logto-core:3001',\n LOGTO_EXTERNAL_ENDPOINT: '${LOGTO_ENDPOINT}',\n SDK_API_RESOURCE: '${IAM_AUDIENCE}',\n LOGTO_M2M_APP_ID: 'nhp-m2m-config',\n LOGTO_M2M_APP_SECRET: '${LOGTO_M2M_APP_SECRET}',\n ENCRYPTION_KEY: '${ENCRYPTION_KEY}',\n LAUNCHER_URL: '${LAUNCHER_URL}',\n CORS_ORIGINS: '${CORS_ORIGINS}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD', 'curl', '-f', 'http://localhost:3001/platform/status'],\n interval: '30s',\n timeout: '10s',\n retries: 3,\n start_period: '60s',\n },\n },\n };\n\n if (config.services.launcher) {\n services['launcher'] = {\n image: `${registry}/habeetat-launcher:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_IAM_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_IAM_AUDIENCE: '${IAM_AUDIENCE}',\n VITE_IAM_APP_ID: 'nhp-launcher',\n VITE_APP_BASE_URL: '${LAUNCHER_URL}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.organizationManager) {\n services['organization-manager'] = {\n image: `${registry}/habeetat-org-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-org-manager',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${ORG_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.platformManager) {\n services['platform-manager'] = {\n image: `${registry}/habeetat-platform-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-plat-mgr',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${PLATFORM_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.sampleCrm) {\n services['sample-crm'] = {\n image: `${registry}/habeetat-sample-crm:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n VITE_APP_BASE_URL: '${SAMPLE_CRM_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n // Nginx reverse proxy (internal routing only — SSL handled by host nginx)\n const nginxDependsOn = ['logto-core', 'backend'];\n if (config.services.launcher) nginxDependsOn.push('launcher');\n if (config.services.organizationManager) nginxDependsOn.push('organization-manager');\n if (config.services.platformManager) nginxDependsOn.push('platform-manager');\n if (config.services.sampleCrm) nginxDependsOn.push('sample-crm');\n\n const hostPort = config.nginx.hostPort;\n\n services['nginx'] = {\n image: THIRD_PARTY_IMAGES.nginx,\n depends_on: nginxDependsOn,\n volumes: ['./nginx/platform.conf:/etc/nginx/conf.d/default.conf:ro'],\n ports: [`127.0.0.1:${hostPort}:80`],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n command: `/bin/sh -c 'while :; do sleep 6h & wait $\\${!}; nginx -s reload; done & nginx -g \"daemon off;\"'`,\n };\n\n const compose = {\n name: 'habeetat',\n services,\n volumes: {\n 'logto-db-data': null,\n 'platform-db-data': null,\n },\n networks: {\n 'habeetat-network': {\n driver: 'bridge',\n },\n },\n };\n\n return toYaml(compose);\n}\n\n// Minimal YAML serializer — avoids adding a dependency for simple structure\nfunction toYaml(obj: unknown, indent = 0): string {\n const pad = ' '.repeat(indent);\n\n if (obj === null || obj === undefined) return '';\n if (typeof obj === 'string') {\n if (obj.includes('\\n') || obj.includes(\"'\") || obj.includes('\"') || obj.includes(':') || obj.includes('#') || obj.includes('{') || obj.includes('}') || obj.includes('$')) {\n return `'${obj.replace(/'/g, \"''\")}'`;\n }\n return obj;\n }\n if (typeof obj === 'number' || typeof obj === 'boolean') return String(obj);\n\n if (Array.isArray(obj)) {\n if (obj.length === 0) return '[]';\n // Check if all items are scalars\n const allScalar = obj.every(\n (item) => typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean',\n );\n if (allScalar) {\n return obj\n .map((item) => `\\n${pad}- ${toYaml(item, indent + 2)}`)\n .join('');\n }\n return obj\n .map((item) => {\n const val = toYaml(item, indent + 2);\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n // Object inside array — inline the first key after the dash\n const lines = val.split('\\n').filter((l) => l.trim());\n if (lines.length > 0) {\n const first = lines[0].trimStart();\n const rest = lines.slice(1).map((l) => `${pad} ${l.trimStart()}`).join('\\n');\n return `\\n${pad}- ${first}${rest ? '\\n' + rest : ''}`;\n }\n }\n return `\\n${pad}- ${val}`;\n })\n .join('');\n }\n\n if (typeof obj === 'object') {\n const entries = Object.entries(obj as Record<string, unknown>);\n if (entries.length === 0) return '{}';\n return entries\n .map(([key, value]) => {\n if (value === null || value === undefined) return `${pad}${key}:`;\n if (typeof value === 'object' && !Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:\\n${nested}`;\n }\n if (Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:${nested}`;\n }\n return `${pad}${key}: ${toYaml(value, indent)}`;\n })\n .join('\\n');\n }\n\n return String(obj);\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n\n const upstreams = [\n 'upstream logto { server logto-core:3001; }',\n 'upstream logto_admin { server logto-core:3002; }',\n 'upstream api { server backend:3001; }',\n ];\n\n if (config.services.launcher) upstreams.push('upstream launcher { server launcher:80; }');\n if (config.services.organizationManager) upstreams.push('upstream organization-manager { server organization-manager:80; }');\n if (config.services.platformManager) upstreams.push('upstream platform-manager { server platform-manager:80; }');\n if (config.services.sampleCrm) upstreams.push('upstream sample-crm { server sample-crm:80; }');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;`;\n\n const serverBlocks: string[] = [];\n\n // Logto IAM\n serverBlocks.push(`\nserver {\n listen 80;\n server_name iam.${domain};\n location / {\n proxy_pass http://logto;${proxyHeaders}\n }\n}`);\n\n // Logto Admin Console\n serverBlocks.push(`\nserver {\n listen 80;\n server_name iam-console.${domain};\n location / {\n proxy_pass http://logto_admin;${proxyHeaders}\n }\n}`);\n\n // Backend API\n serverBlocks.push(`\nserver {\n listen 80;\n server_name api.${domain};\n location / {\n limit_req zone=api_limit burst=20 nodelay;\n proxy_pass http://api;${proxyHeaders}\n }\n}`);\n\n // Launcher\n if (config.services.launcher) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name launcher.${domain};\n location / {\n proxy_pass http://launcher;${proxyHeaders}\n }\n}`);\n }\n\n // Organization Manager\n if (config.services.organizationManager) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name organization-manager.${domain};\n location / {\n proxy_pass http://organization-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Platform Manager\n if (config.services.platformManager) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name platform-manager.${domain};\n location / {\n proxy_pass http://platform-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Sample CRM\n if (config.services.sampleCrm) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name sample-crm.${domain};\n location / {\n proxy_pass http://sample-crm;${proxyHeaders}\n }\n}`);\n }\n\n return `# Habeetat Platform - Container Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n# This handles internal routing between Docker services.\n# SSL is handled by the host nginx (see /etc/nginx/sites-enabled/).\n\n${upstreams.join('\\n')}\n\nlimit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;\n${serverBlocks.join('\\n')}\n`;\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateHostNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n const port = config.nginx.hostPort;\n\n const subdomains = [\n 'iam',\n 'iam-console',\n 'api',\n ];\n\n if (config.services.launcher) subdomains.push('launcher');\n if (config.services.organizationManager) subdomains.push('organization-manager');\n if (config.services.platformManager) subdomains.push('platform-manager');\n if (config.services.sampleCrm) subdomains.push('sample-crm');\n\n const allServerNames = subdomains.map((s) => `${s}.${domain}`).join(' ');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_set_header X-Forwarded-Host $host;\n proxy_http_version 1.1;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection \"upgrade\";`;\n\n return `# Habeetat Platform - Host Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n# This file should be placed in /etc/nginx/sites-available/habeetat-${sanitize(domain)}\n# and symlinked to /etc/nginx/sites-enabled/\n\n# HTTP → HTTPS redirect\nserver {\n listen 80;\n server_name ${allServerNames};\n\n location /.well-known/acme-challenge/ {\n root /var/www/certbot;\n }\n\n location / {\n return 301 https://$host$request_uri;\n }\n}\n\n# HTTPS — proxy all Habeetat subdomains to the container nginx\nserver {\n listen 443 ssl;\n server_name ${allServerNames};\n\n ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;\n ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;\n include /etc/letsencrypt/options-ssl-nginx.conf;\n ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;\n\n client_max_body_size 50M;\n\n location / {\n proxy_pass http://127.0.0.1:${port};${proxyHeaders}\n }\n}\n`;\n}\n\nfunction sanitize(domain: string): string {\n return domain.replace(/[^a-zA-Z0-9.-]/g, '-');\n}\n","import crypto from 'node:crypto';\n\nexport function randomHex(bytes: number): string {\n return crypto.randomBytes(bytes).toString('hex');\n}\n\nexport function generateSecrets() {\n return {\n logtoDbPassword: randomHex(16),\n platformDbPassword: randomHex(16),\n encryptionKey: randomHex(32),\n logtoM2mAppSecret: randomHex(32),\n };\n}\n","import type { CreateOptions } from '../types.js';\nimport { generateSecrets } from '../utils/crypto.js';\n\nexport function generateEnvFile(opts: CreateOptions): string {\n const protocol = opts.ssl ? 'https' : 'http';\n const domain = opts.domain;\n const secrets = generateSecrets();\n\n return `# Habeetat Platform - Environment Configuration\n# Generated by @habeetat/cli on ${new Date().toISOString()}\n\n# ============================================\n# Domain Configuration\n# ============================================\nDOMAIN=${domain}\nPROTOCOL=${protocol}\n\n# ============================================\n# Service URLs (External - Browser-facing)\n# ============================================\nLOGTO_ENDPOINT=${protocol}://iam.${domain}\nLOGTO_ADMIN_ENDPOINT=${protocol}://iam-console.${domain}\nLAUNCHER_URL=${protocol}://launcher.${domain}\nORG_MANAGER_URL=${protocol}://organization-manager.${domain}\nPLATFORM_MANAGER_URL=${protocol}://platform-manager.${domain}\nSAMPLE_CRM_URL=${protocol}://sample-crm.${domain}\nBACKEND_API_URL=${protocol}://api.${domain}\nCORS_ORIGINS=${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain},${protocol}://sample-crm.${domain}\n\n# ============================================\n# Database Configuration\n# ============================================\nLOGTO_DB_USER=logto\nLOGTO_DB_PASSWORD=${secrets.logtoDbPassword}\nLOGTO_DB_NAME=logto\n\nPLATFORM_DB_USER=habeetat\nPLATFORM_DB_PASSWORD=${secrets.platformDbPassword}\nPLATFORM_DB_NAME=habeetat_platform\n\n# ============================================\n# Logto IAM Configuration\n# ============================================\nLOGTO_ADMIN_USERNAME=${opts.adminEmail}\nLOGTO_ADMIN_PASSWORD=${opts.adminPassword}\n\nIAM_ISSUER_URL=${protocol}://iam.${domain}/oidc\nIAM_AUDIENCE=${protocol}://api.${domain}/api\nSDK_API_RESOURCE=${protocol}://api.${domain}/api\n\nLOGTO_M2M_APP_ID=nhp-m2m-config\nLOGTO_M2M_APP_SECRET=${secrets.logtoM2mAppSecret}\n\n# ============================================\n# Platform Configuration\n# ============================================\nPLATFORM_ADMIN_EMAIL=${opts.adminEmail}\nPLATFORM_ADMIN_PASSWORD=${opts.adminPassword}\nORGANIZATION_NAME=${opts.organizationName}\n\n# ============================================\n# Security\n# ============================================\nENCRYPTION_KEY=${secrets.encryptionKey}\n\n# ============================================\n# CORS Configuration\n# ============================================\nALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\nCORS_ALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\n`;\n}\n","import chalk from 'chalk';\n\nconst prefix = chalk.cyan('[habeetat]');\n\nexport const logger = {\n info: (msg: string) => console.log(`${prefix} ${msg}`),\n success: (msg: string) => console.log(`${prefix} ${chalk.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(`${prefix} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${prefix} ${chalk.red('✗')} ${msg}`),\n phase: (msg: string) => {\n console.log('');\n console.log(chalk.cyan('═'.repeat(56)));\n console.log(chalk.cyan(` ${msg}`));\n console.log(chalk.cyan('═'.repeat(56)));\n console.log('');\n },\n banner: () => {\n console.log('');\n console.log(chalk.cyan('╔══════════════════════════════════════════════╗'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('║ Habeetat Platform CLI ║'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('╚══════════════════════════════════════════════╝'));\n console.log('');\n },\n};\n","import { execaCommand } from 'execa';\nimport { logger } from './logger.js';\n\nexport async function checkDocker(): Promise<boolean> {\n try {\n const { stdout } = await execaCommand('docker --version');\n const match = stdout.match(/Docker version (\\d+)/);\n if (match && parseInt(match[1], 10) >= 20) {\n return true;\n }\n logger.error(`Docker >= 20.0 required. Found: ${stdout.trim()}`);\n return false;\n } catch {\n logger.error('Docker is not installed or not in PATH');\n logger.info('Install Docker: https://docs.docker.com/get-docker/');\n return false;\n }\n}\n\nexport async function checkDockerCompose(): Promise<boolean> {\n try {\n await execaCommand('docker compose version');\n return true;\n } catch {\n logger.error('Docker Compose V2 is not available');\n logger.info('Docker Compose V2 is included with Docker Desktop');\n return false;\n }\n}\n\nexport async function checkPrerequisites(): Promise<boolean> {\n const docker = await checkDocker();\n const compose = await checkDockerCompose();\n return docker && compose;\n}\n\nexport interface ComposeExecOptions {\n cwd: string;\n composeFile?: string;\n silent?: boolean;\n}\n\nexport async function composeUp(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} up -d`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeDown(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composePs(opts: ComposeExecOptions): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(`docker compose -f ${file} ps`, {\n cwd: opts.cwd,\n });\n return stdout;\n}\n\nexport async function composeLogs(\n opts: ComposeExecOptions & { service?: string; follow?: boolean; tail?: number },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const parts = ['docker', 'compose', '-f', file, 'logs'];\n if (opts.follow) parts.push('-f');\n if (opts.tail) parts.push('--tail', String(opts.tail));\n if (opts.service) parts.push(opts.service);\n\n await execaCommand(parts.join(' '), {\n cwd: opts.cwd,\n stdio: 'inherit',\n });\n}\n\nexport async function composeRestart(\n opts: ComposeExecOptions & { service?: string },\n): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n const cmd = opts.service\n ? `docker compose -f ${file} restart ${opts.service}`\n : `docker compose -f ${file} restart`;\n\n await execaCommand(cmd, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeExec(\n opts: ComposeExecOptions & { service: string; command: string },\n): Promise<string> {\n const file = opts.composeFile || 'docker-compose.yml';\n const { stdout } = await execaCommand(\n `docker compose -f ${file} exec -T ${opts.service} ${opts.command}`,\n { cwd: opts.cwd },\n );\n return stdout;\n}\n\nexport async function dockerPull(image: string): Promise<void> {\n await execaCommand(`docker pull ${image}`, { stdio: 'inherit' });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { CONFIG_FILE } from '../constants.js';\nimport type { HabeetatConfig } from '../types.js';\n\nexport function findProjectRoot(startDir: string = process.cwd()): string | null {\n let dir = startDir;\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, CONFIG_FILE))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nexport function loadConfig(projectDir?: string): HabeetatConfig {\n const dir = projectDir || findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n const configPath = path.join(dir, CONFIG_FILE);\n const raw = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as HabeetatConfig;\n}\n\nexport function saveConfig(config: HabeetatConfig, projectDir: string): void {\n const configPath = path.join(projectDir, CONFIG_FILE);\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function getProjectDir(): string {\n const dir = findProjectRoot();\n if (!dir) {\n throw new Error(\n `Could not find ${CONFIG_FILE}. Are you inside a Habeetat project directory?`,\n );\n }\n return dir;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/templates/docker-compose.ts","../src/templates/nginx.ts","../src/templates/host-nginx.ts","../src/utils/crypto.ts","../src/templates/env.ts","../src/utils/logger.ts","../src/utils/docker.ts","../src/utils/config.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export const CONFIG_FILE = 'habeetat.json';\nexport const ENV_FILE = '.env';\nexport const COMPOSE_FILE = 'docker-compose.yml';\n\nexport const DOCKER_REGISTRY = 'docker.io/capriisland';\n\nexport const IMAGES = {\n backend: 'capriisland/habeetat-backend',\n launcher: 'capriisland/habeetat-launcher',\n orgManager: 'capriisland/habeetat-org-manager',\n platformManager: 'capriisland/habeetat-platform-manager',\n sampleCrm: 'capriisland/habeetat-sample-crm',\n logtoConfig: 'capriisland/habeetat-logto-config',\n} as const;\n\nexport const THIRD_PARTY_IMAGES = {\n postgres: 'postgres:15-alpine',\n logto: 'svhd/logto:1.33',\n nginx: 'nginx:1.25-alpine',\n certbot: 'certbot/certbot',\n} as const;\n\nexport const DEFAULT_PORTS = {\n http: 80,\n https: 443,\n hostNginx: 8080,\n} as const;\n\nexport const SERVICES = [\n 'logto-db',\n 'platform-db',\n 'logto-core',\n 'backend',\n 'launcher',\n 'organization-manager',\n 'platform-manager',\n 'sample-crm',\n 'nginx',\n] as const;\n\nexport type ServiceName = (typeof SERVICES)[number];\n","import type { HabeetatConfig } from '../types.js';\nimport { THIRD_PARTY_IMAGES } from '../constants.js';\n\nexport function generateDockerCompose(config: HabeetatConfig): string {\n const tag = config.docker.imageTag;\n const registry = config.docker.registry;\n\n const services: Record<string, unknown> = {\n 'logto-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${LOGTO_DB_USER}',\n POSTGRES_PASSWORD: '${LOGTO_DB_PASSWORD}',\n POSTGRES_DB: '${LOGTO_DB_NAME}',\n },\n volumes: ['logto-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${LOGTO_DB_USER} -d ${LOGTO_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'platform-db': {\n image: THIRD_PARTY_IMAGES.postgres,\n environment: {\n POSTGRES_USER: '${PLATFORM_DB_USER}',\n POSTGRES_PASSWORD: '${PLATFORM_DB_PASSWORD}',\n POSTGRES_DB: '${PLATFORM_DB_NAME}',\n },\n volumes: ['platform-db-data:/var/lib/postgresql/data'],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'pg_isready -U ${PLATFORM_DB_USER} -d ${PLATFORM_DB_NAME}'],\n interval: '5s',\n timeout: '3s',\n retries: 10,\n },\n },\n\n 'logto-core': {\n image: THIRD_PARTY_IMAGES.logto,\n entrypoint: ['sh', '-c'],\n command: ['npm run cli -- db seed -- --swe && npm run start || npm run start'],\n depends_on: {\n 'logto-db': { condition: 'service_healthy' },\n },\n environment: {\n DB_URL: 'postgres://${LOGTO_DB_USER}:${LOGTO_DB_PASSWORD}@logto-db:5432/${LOGTO_DB_NAME}',\n ENDPOINT: '${LOGTO_ENDPOINT}',\n ADMIN_ENDPOINT: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_CONSOLE_URL: '${LOGTO_ADMIN_ENDPOINT}',\n ADMIN_PORT: '3002',\n TRUST_PROXY_HEADER: '1',\n COOKIE_KEYS: '${ENCRYPTION_KEY}',\n ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n CORS_ALLOWED_ORIGINS: '${LOGTO_ENDPOINT},${LOGTO_ADMIN_ENDPOINT},${LAUNCHER_URL},${ORG_MANAGER_URL},${PLATFORM_MANAGER_URL},${SAMPLE_CRM_URL},${BACKEND_API_URL}',\n ADMIN_CONSOLE_ALLOWED_ORIGINS: '${LOGTO_ADMIN_ENDPOINT}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD-SHELL', 'wget -q --spider http://localhost:3001/oidc/.well-known/openid-configuration || exit 1'],\n interval: '10s',\n timeout: '5s',\n retries: 15,\n start_period: '90s',\n },\n },\n\n backend: {\n image: `${registry}/habeetat-backend:${tag}`,\n depends_on: {\n 'logto-core': { condition: 'service_healthy' },\n 'platform-db': { condition: 'service_healthy' },\n },\n environment: {\n NODE_ENV: 'production',\n DATABASE_URL: 'postgres://${PLATFORM_DB_USER}:${PLATFORM_DB_PASSWORD}@platform-db:5432/${PLATFORM_DB_NAME}',\n IAM_ISSUER_URL: '${LOGTO_ENDPOINT}/oidc',\n IAM_JWKS_URL: 'http://logto-core:3001',\n IAM_AUDIENCE: '${IAM_AUDIENCE}',\n LOGTO_ENDPOINT: 'http://logto-core:3001',\n LOGTO_EXTERNAL_ENDPOINT: '${LOGTO_ENDPOINT}',\n SDK_API_RESOURCE: '${IAM_AUDIENCE}',\n LOGTO_M2M_APP_ID: 'nhp-m2m-config',\n LOGTO_M2M_APP_SECRET: '${LOGTO_M2M_APP_SECRET}',\n ENCRYPTION_KEY: '${ENCRYPTION_KEY}',\n LAUNCHER_URL: '${LAUNCHER_URL}',\n CORS_ORIGINS: '${CORS_ORIGINS}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n healthcheck: {\n test: ['CMD', 'curl', '-f', 'http://localhost:3001/platform/status'],\n interval: '30s',\n timeout: '10s',\n retries: 3,\n start_period: '60s',\n },\n },\n };\n\n if (config.services.launcher) {\n services['launcher'] = {\n image: `${registry}/habeetat-launcher:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_IAM_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_IAM_AUDIENCE: '${IAM_AUDIENCE}',\n VITE_IAM_APP_ID: 'nhp-launcher',\n VITE_APP_BASE_URL: '${LAUNCHER_URL}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.organizationManager) {\n services['organization-manager'] = {\n image: `${registry}/habeetat-org-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-org-manager',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${ORG_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.platformManager) {\n services['platform-manager'] = {\n image: `${registry}/habeetat-platform-manager:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_APP_ID: 'nhp-plat-mgr',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_APP_BASE_URL: '${PLATFORM_MANAGER_URL}',\n VITE_BACKEND_API_URL: '${BACKEND_API_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n if (config.services.sampleCrm) {\n services['sample-crm'] = {\n image: `${registry}/habeetat-sample-crm:${tag}`,\n depends_on: ['backend'],\n environment: {\n VITE_LOGTO_ENDPOINT: '${LOGTO_ENDPOINT}',\n VITE_LOGTO_API_RESOURCE: '${IAM_AUDIENCE}',\n VITE_PLATFORM_API_URL: '${BACKEND_API_URL}',\n VITE_APP_BASE_URL: '${SAMPLE_CRM_URL}',\n },\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n };\n }\n\n // Nginx reverse proxy (internal routing only — SSL handled by host nginx)\n const nginxDependsOn = ['logto-core', 'backend'];\n if (config.services.launcher) nginxDependsOn.push('launcher');\n if (config.services.organizationManager) nginxDependsOn.push('organization-manager');\n if (config.services.platformManager) nginxDependsOn.push('platform-manager');\n if (config.services.sampleCrm) nginxDependsOn.push('sample-crm');\n\n const hostPort = config.nginx.hostPort;\n\n services['nginx'] = {\n image: THIRD_PARTY_IMAGES.nginx,\n depends_on: nginxDependsOn,\n volumes: ['./nginx/platform.conf:/etc/nginx/conf.d/default.conf:ro'],\n ports: [`127.0.0.1:${hostPort}:80`],\n networks: ['habeetat-network'],\n restart: 'unless-stopped',\n command: `/bin/sh -c 'while :; do sleep 6h & wait $\\${!}; nginx -s reload; done & nginx -g \"daemon off;\"'`,\n };\n\n const compose = {\n name: 'habeetat',\n services,\n volumes: {\n 'logto-db-data': null,\n 'platform-db-data': null,\n },\n networks: {\n 'habeetat-network': {\n driver: 'bridge',\n },\n },\n };\n\n return toYaml(compose);\n}\n\n// Minimal YAML serializer — avoids adding a dependency for simple structure\nfunction toYaml(obj: unknown, indent = 0): string {\n const pad = ' '.repeat(indent);\n\n if (obj === null || obj === undefined) return '';\n if (typeof obj === 'string') {\n if (obj.includes('\\n') || obj.includes(\"'\") || obj.includes('\"') || obj.includes(':') || obj.includes('#') || obj.includes('{') || obj.includes('}') || obj.includes('$')) {\n return `'${obj.replace(/'/g, \"''\")}'`;\n }\n return obj;\n }\n if (typeof obj === 'number' || typeof obj === 'boolean') return String(obj);\n\n if (Array.isArray(obj)) {\n if (obj.length === 0) return '[]';\n // Check if all items are scalars\n const allScalar = obj.every(\n (item) => typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean',\n );\n if (allScalar) {\n return obj\n .map((item) => `\\n${pad}- ${toYaml(item, indent + 2)}`)\n .join('');\n }\n return obj\n .map((item) => {\n const val = toYaml(item, indent + 2);\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n // Object inside array — inline the first key after the dash\n const lines = val.split('\\n').filter((l) => l.trim());\n if (lines.length > 0) {\n const first = lines[0].trimStart();\n const rest = lines.slice(1).map((l) => `${pad} ${l.trimStart()}`).join('\\n');\n return `\\n${pad}- ${first}${rest ? '\\n' + rest : ''}`;\n }\n }\n return `\\n${pad}- ${val}`;\n })\n .join('');\n }\n\n if (typeof obj === 'object') {\n const entries = Object.entries(obj as Record<string, unknown>);\n if (entries.length === 0) return '{}';\n return entries\n .map(([key, value]) => {\n if (value === null || value === undefined) return `${pad}${key}:`;\n if (typeof value === 'object' && !Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:\\n${nested}`;\n }\n if (Array.isArray(value)) {\n const nested = toYaml(value, indent + 2);\n return `${pad}${key}:${nested}`;\n }\n return `${pad}${key}: ${toYaml(value, indent)}`;\n })\n .join('\\n');\n }\n\n return String(obj);\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n\n const upstreams = [\n 'upstream logto { server logto-core:3001; }',\n 'upstream logto_admin { server logto-core:3002; }',\n 'upstream api { server backend:3001; }',\n ];\n\n if (config.services.launcher) upstreams.push('upstream launcher { server launcher:80; }');\n if (config.services.organizationManager) upstreams.push('upstream organization-manager { server organization-manager:80; }');\n if (config.services.platformManager) upstreams.push('upstream platform-manager { server platform-manager:80; }');\n if (config.services.sampleCrm) upstreams.push('upstream sample-crm { server sample-crm:80; }');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;`;\n\n const serverBlocks: string[] = [];\n\n // Logto IAM\n serverBlocks.push(`\nserver {\n listen 80;\n server_name iam.${domain};\n location / {\n proxy_pass http://logto;${proxyHeaders}\n }\n}`);\n\n // Logto Admin Console\n serverBlocks.push(`\nserver {\n listen 80;\n server_name iam-console.${domain};\n location / {\n proxy_pass http://logto_admin;${proxyHeaders}\n }\n}`);\n\n // Backend API\n serverBlocks.push(`\nserver {\n listen 80;\n server_name api.${domain};\n location / {\n limit_req zone=api_limit burst=20 nodelay;\n proxy_pass http://api;${proxyHeaders}\n }\n}`);\n\n // Launcher\n if (config.services.launcher) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name launcher.${domain};\n location / {\n proxy_pass http://launcher;${proxyHeaders}\n }\n}`);\n }\n\n // Organization Manager\n if (config.services.organizationManager) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name organization-manager.${domain};\n location / {\n proxy_pass http://organization-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Platform Manager\n if (config.services.platformManager) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name platform-manager.${domain};\n location / {\n proxy_pass http://platform-manager;${proxyHeaders}\n }\n}`);\n }\n\n // Sample CRM\n if (config.services.sampleCrm) {\n serverBlocks.push(`\nserver {\n listen 80;\n server_name sample-crm.${domain};\n location / {\n proxy_pass http://sample-crm;${proxyHeaders}\n }\n}`);\n }\n\n return `# Habeetat Platform - Container Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n# This handles internal routing between Docker services.\n# SSL is handled by the host nginx (see /etc/nginx/sites-enabled/).\n\n${upstreams.join('\\n')}\n\nlimit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;\n${serverBlocks.join('\\n')}\n`;\n}\n","import type { HabeetatConfig } from '../types.js';\n\nexport function generateHostNginxConf(config: HabeetatConfig): string {\n const domain = config.platform.domain;\n const port = config.nginx.hostPort;\n\n const subdomains = [\n 'iam',\n 'iam-console',\n 'api',\n ];\n\n if (config.services.launcher) subdomains.push('launcher');\n if (config.services.organizationManager) subdomains.push('organization-manager');\n if (config.services.platformManager) subdomains.push('platform-manager');\n if (config.services.sampleCrm) subdomains.push('sample-crm');\n\n const allServerNames = subdomains.map((s) => `${s}.${domain}`).join(' ');\n\n const proxyHeaders = `\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_set_header X-Forwarded-Host $host;\n proxy_http_version 1.1;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection \"upgrade\";`;\n\n return `# Habeetat Platform - Host Nginx Configuration\n# Auto-generated by @habeetat/cli for domain: ${domain}\n# This file should be placed in /etc/nginx/sites-available/habeetat-${sanitize(domain)}\n# and symlinked to /etc/nginx/sites-enabled/\n#\n# 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 };\n}\n","import type { CreateOptions } from '../types.js';\nimport { generateSecrets } from '../utils/crypto.js';\n\nexport function generateEnvFile(opts: CreateOptions): string {\n const protocol = opts.ssl ? 'https' : 'http';\n const domain = opts.domain;\n const secrets = generateSecrets();\n\n return `# Habeetat Platform - Environment Configuration\n# Generated by @habeetat/cli on ${new Date().toISOString()}\n\n# ============================================\n# Domain Configuration\n# ============================================\nDOMAIN=${domain}\nPROTOCOL=${protocol}\n\n# ============================================\n# Service URLs (External - Browser-facing)\n# ============================================\nLOGTO_ENDPOINT=${protocol}://iam.${domain}\nLOGTO_ADMIN_ENDPOINT=${protocol}://iam-console.${domain}\nLAUNCHER_URL=${protocol}://launcher.${domain}\nORG_MANAGER_URL=${protocol}://organization-manager.${domain}\nPLATFORM_MANAGER_URL=${protocol}://platform-manager.${domain}\nSAMPLE_CRM_URL=${protocol}://sample-crm.${domain}\nBACKEND_API_URL=${protocol}://api.${domain}\nCORS_ORIGINS=${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain},${protocol}://sample-crm.${domain}\n\n# ============================================\n# Database Configuration\n# ============================================\nLOGTO_DB_USER=logto\nLOGTO_DB_PASSWORD=${secrets.logtoDbPassword}\nLOGTO_DB_NAME=logto\n\nPLATFORM_DB_USER=habeetat\nPLATFORM_DB_PASSWORD=${secrets.platformDbPassword}\nPLATFORM_DB_NAME=habeetat_platform\n\n# ============================================\n# Logto IAM Configuration\n# ============================================\nLOGTO_ADMIN_USERNAME=${opts.adminEmail}\nLOGTO_ADMIN_PASSWORD=${opts.adminPassword}\n\nIAM_ISSUER_URL=${protocol}://iam.${domain}/oidc\nIAM_AUDIENCE=${protocol}://api.${domain}/api\nSDK_API_RESOURCE=${protocol}://api.${domain}/api\n\nLOGTO_M2M_APP_ID=nhp-m2m-config\nLOGTO_M2M_APP_SECRET=${secrets.logtoM2mAppSecret}\n\n# ============================================\n# Platform Configuration\n# ============================================\nPLATFORM_ADMIN_EMAIL=${opts.adminEmail}\nPLATFORM_ADMIN_PASSWORD=${opts.adminPassword}\nORGANIZATION_NAME=${opts.organizationName}\n\n# ============================================\n# Security\n# ============================================\nENCRYPTION_KEY=${secrets.encryptionKey}\n\n# ============================================\n# CORS Configuration\n# ============================================\nALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\nCORS_ALLOWED_ORIGINS=${protocol}://iam-console.${domain},${protocol}://launcher.${domain},${protocol}://organization-manager.${domain},${protocol}://platform-manager.${domain}\n`;\n}\n","import chalk from 'chalk';\n\nconst prefix = chalk.cyan('[habeetat]');\n\nexport const logger = {\n info: (msg: string) => console.log(`${prefix} ${msg}`),\n success: (msg: string) => console.log(`${prefix} ${chalk.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(`${prefix} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${prefix} ${chalk.red('✗')} ${msg}`),\n phase: (msg: string) => {\n console.log('');\n console.log(chalk.cyan('═'.repeat(56)));\n console.log(chalk.cyan(` ${msg}`));\n console.log(chalk.cyan('═'.repeat(56)));\n console.log('');\n },\n banner: () => {\n console.log('');\n console.log(chalk.cyan('╔══════════════════════════════════════════════╗'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('║ Habeetat Platform CLI ║'));\n console.log(chalk.cyan('║ ║'));\n console.log(chalk.cyan('╚══════════════════════════════════════════════╝'));\n console.log('');\n },\n};\n","import { execaCommand } from 'execa';\nimport { logger } from './logger.js';\n\nexport async function checkDocker(): Promise<boolean> {\n try {\n const { stdout } = await execaCommand('docker --version');\n const match = stdout.match(/Docker version (\\d+)/);\n if (match && parseInt(match[1], 10) >= 20) {\n return true;\n }\n logger.error(`Docker >= 20.0 required. Found: ${stdout.trim()}`);\n return false;\n } catch {\n logger.error('Docker is not installed or not in PATH');\n logger.info('Install Docker: https://docs.docker.com/get-docker/');\n return false;\n }\n}\n\nexport async function checkDockerCompose(): Promise<boolean> {\n try {\n await execaCommand('docker compose version');\n return true;\n } catch {\n logger.error('Docker Compose V2 is not available');\n logger.info('Docker Compose V2 is included with Docker Desktop');\n return false;\n }\n}\n\nexport async function checkPrerequisites(): Promise<boolean> {\n const docker = await checkDocker();\n const compose = await checkDockerCompose();\n return docker && compose;\n}\n\nexport interface ComposeExecOptions {\n cwd: string;\n composeFile?: string;\n silent?: boolean;\n}\n\nexport async function composeUp(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} up -d`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function composeDown(opts: ComposeExecOptions): Promise<void> {\n const file = opts.composeFile || 'docker-compose.yml';\n await execaCommand(`docker compose -f ${file} down`, {\n cwd: opts.cwd,\n stdio: opts.silent ? 'pipe' : 'inherit',\n });\n}\n\nexport async function 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"]}
|
package/package.json
CHANGED