@launchmatic/cli 0.7.2 → 0.7.3

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.
Files changed (2) hide show
  1. package/dist/index.js +123 -33
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -22430,42 +22430,124 @@ async function pollDeploymentStatus(deploymentId, spinner) {
22430
22430
  }
22431
22431
 
22432
22432
  // src/commands/logs.ts
22433
+ function resolveServiceId(opts) {
22434
+ try {
22435
+ return readContext().serviceId;
22436
+ } catch {
22437
+ }
22438
+ const manifest = readManifest();
22439
+ if (!manifest || manifest.services.length === 0) {
22440
+ console.error(
22441
+ source_default.red(
22442
+ `No .launchmatic.json here and no ${MANIFEST_FILE} at the repo root.`
22443
+ )
22444
+ );
22445
+ return null;
22446
+ }
22447
+ if (!opts.service) {
22448
+ const names = manifest.services.map((s) => s.name).join(", ");
22449
+ console.error(
22450
+ source_default.red(
22451
+ `Specify which service with --service <name>. Known: ${names}`
22452
+ )
22453
+ );
22454
+ return null;
22455
+ }
22456
+ const match = manifest.services.find((s) => s.name === opts.service);
22457
+ if (!match?.serviceId) {
22458
+ console.error(source_default.red(`No service named "${opts.service}" in ${MANIFEST_FILE}.`));
22459
+ return null;
22460
+ }
22461
+ return match.serviceId;
22462
+ }
22433
22463
  function registerLogs(program3) {
22434
- program3.command("logs").description("Stream live logs from a deployment").action(async () => {
22435
- if (!isLoggedIn()) {
22436
- console.error(source_default.red('Not logged in. Run "lm login" first.'));
22437
- process.exitCode = 1;
22438
- return;
22464
+ program3.command("logs").description(
22465
+ "Stream runtime logs (default) or print build logs for a deployment"
22466
+ ).option(
22467
+ "-b, --build",
22468
+ "Print build logs for a deployment instead of streaming runtime logs (use --deployment to target a specific one; defaults to the latest)"
22469
+ ).option(
22470
+ "-d, --deployment <id>",
22471
+ "Deployment id for --build (defaults to the latest deployment)"
22472
+ ).option(
22473
+ "-s, --service <name>",
22474
+ "Monorepo: which service to read logs for (matches launchmatic.json)"
22475
+ ).action(
22476
+ async (opts) => {
22477
+ if (!isLoggedIn()) {
22478
+ console.error(source_default.red('Not logged in. Run "lm login" first.'));
22479
+ process.exitCode = 1;
22480
+ return;
22481
+ }
22482
+ const serviceId = resolveServiceId({ service: opts.service });
22483
+ if (!serviceId) {
22484
+ process.exitCode = 1;
22485
+ return;
22486
+ }
22487
+ if (opts.build) {
22488
+ await printBuildLogs(serviceId, opts.deployment);
22489
+ return;
22490
+ }
22491
+ await streamRuntimeLogs(serviceId);
22439
22492
  }
22440
- const ctx = readContext();
22441
- const apiUrl = getApiUrl();
22442
- const wsUrl = apiUrl.replace(/^http/, "ws");
22443
- const wsToken = await getWsToken();
22444
- console.log(source_default.dim("Streaming logs (Ctrl+C to stop)...\n"));
22445
- const ws = new wrapper_default(
22446
- `${wsUrl}/ws/runtime-logs/${ctx.serviceId}?token=${wsToken}`
22493
+ );
22494
+ }
22495
+ async function printBuildLogs(serviceId, deploymentId) {
22496
+ let targetId = deploymentId;
22497
+ if (!targetId) {
22498
+ const { data: data2 } = await api(
22499
+ `/api/deployments?serviceId=${serviceId}&page=1&limit=1`
22447
22500
  );
22448
- ws.on("message", (data) => {
22449
- const msg = data.toString();
22450
- try {
22451
- const parsed = JSON.parse(msg);
22452
- const ts = parsed.timestamp ? source_default.dim(`[${new Date(parsed.timestamp).toLocaleTimeString()}]`) : "";
22453
- const line = parsed.message || parsed.line || msg;
22454
- console.log(`${ts} ${line}`);
22455
- } catch {
22456
- console.log(msg);
22457
- }
22458
- });
22459
- ws.on("error", (err) => {
22460
- console.error(source_default.red(`WebSocket error: ${err.message}`));
22461
- process.exitCode = 1;
22462
- });
22463
- ws.on("close", () => {
22464
- console.log(source_default.dim("\nLog stream ended."));
22465
- });
22466
- process.on("SIGINT", () => {
22467
- ws.close();
22468
- });
22501
+ if (!data2 || data2.length === 0) {
22502
+ console.log(source_default.dim("No deployments yet."));
22503
+ return;
22504
+ }
22505
+ targetId = data2[0].id;
22506
+ }
22507
+ const { data } = await api(
22508
+ `/api/deployments/${targetId}`
22509
+ );
22510
+ console.log(source_default.bold("Deployment: ") + data.id);
22511
+ console.log(source_default.bold("Status: ") + data.status);
22512
+ if (data.commitSha) console.log(source_default.bold("Commit: ") + data.commitSha);
22513
+ if (data.branch) console.log(source_default.bold("Branch: ") + data.branch);
22514
+ console.log(source_default.bold("Started: ") + new Date(data.createdAt).toLocaleString());
22515
+ console.log();
22516
+ if (!data.buildLogs) {
22517
+ console.log(source_default.dim("No build logs recorded for this deployment."));
22518
+ return;
22519
+ }
22520
+ console.log(source_default.bold("\u2500\u2500 Build logs \u2500\u2500"));
22521
+ console.log(data.buildLogs);
22522
+ }
22523
+ async function streamRuntimeLogs(serviceId) {
22524
+ const apiUrl = getApiUrl();
22525
+ const wsUrl = apiUrl.replace(/^http/, "ws");
22526
+ const wsToken = await getWsToken();
22527
+ console.log(source_default.dim("Streaming logs (Ctrl+C to stop)...\n"));
22528
+ const ws = new wrapper_default(
22529
+ `${wsUrl}/ws/runtime-logs/${serviceId}?token=${wsToken}`
22530
+ );
22531
+ ws.on("message", (data) => {
22532
+ const msg = data.toString();
22533
+ try {
22534
+ const parsed = JSON.parse(msg);
22535
+ const ts = parsed.timestamp ? source_default.dim(`[${new Date(parsed.timestamp).toLocaleTimeString()}]`) : "";
22536
+ const line = parsed.message || parsed.line || msg;
22537
+ console.log(`${ts} ${line}`);
22538
+ } catch {
22539
+ console.log(msg);
22540
+ }
22541
+ });
22542
+ ws.on("error", (err) => {
22543
+ console.error(source_default.red(`WebSocket error: ${err.message}`));
22544
+ process.exitCode = 1;
22545
+ });
22546
+ ws.on("close", () => {
22547
+ console.log(source_default.dim("\nLog stream ended."));
22548
+ });
22549
+ process.on("SIGINT", () => {
22550
+ ws.close();
22469
22551
  });
22470
22552
  }
22471
22553
 
@@ -25676,6 +25758,14 @@ function registerDeployments(program3) {
25676
25758
  if (data.imageTag) {
25677
25759
  console.log(source_default.bold("Image: ") + data.imageTag);
25678
25760
  }
25761
+ if (data.buildLogs) {
25762
+ console.log();
25763
+ console.log(source_default.bold("\u2500\u2500 Build logs \u2500\u2500"));
25764
+ console.log(data.buildLogs);
25765
+ } else {
25766
+ console.log();
25767
+ console.log(source_default.dim("(no build logs recorded)"));
25768
+ }
25679
25769
  } catch (err) {
25680
25770
  spinner.fail(source_default.red(`Failed: ${err instanceof Error ? err.message : "Unknown error"}`));
25681
25771
  process.exitCode = 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@launchmatic/cli",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Launchmatic CLI — deploy from your terminal",
5
5
  "private": false,
6
6
  "type": "module",