@ably/cli
Version:
Ably CLI for Pub/Sub, Chat and Spaces
119 lines (118 loc) • 4.54 kB
JavaScript
import { Flags } from "@oclif/core";
import chalk from "chalk";
import { AblyBaseCommand } from "../../base-command.js";
export default class LogsChannelLifecycle extends AblyBaseCommand {
static description = "Stream logs from [meta]channel.lifecycle meta channel";
static examples = [
"$ ably logs channel-lifecycle subscribe",
"$ ably logs channel-lifecycle subscribe --rewind 10",
];
static flags = {
...AblyBaseCommand.globalFlags,
json: Flags.boolean({
default: false,
description: "Output results as JSON",
}),
rewind: Flags.integer({
default: 0,
description: "Number of messages to rewind when subscribing",
}),
};
async run() {
const { flags } = await this.parse(LogsChannelLifecycle);
let client = null;
try {
// Create the Ably client
client = await this.createAblyRealtimeClient(flags);
if (!client)
return;
const channelName = "[meta]channel.lifecycle";
const channelOptions = {};
// Configure rewind if specified
if (flags.rewind > 0) {
channelOptions.params = {
...channelOptions.params,
rewind: flags.rewind.toString(),
};
}
const channel = client.channels.get(channelName, channelOptions);
this.log(`Subscribing to ${chalk.cyan(channelName)}...`);
this.log("Press Ctrl+C to exit");
this.log("");
// Subscribe to the channel
channel.subscribe((message) => {
const timestamp = message.timestamp
? new Date(message.timestamp).toISOString()
: new Date().toISOString();
const event = message.name || "unknown";
if (this.shouldOutputJson(flags)) {
const jsonOutput = {
channel: channelName,
data: message.data,
event: message.name || "unknown",
timestamp,
};
this.log(this.formatJsonOutput(jsonOutput, flags));
return;
}
// Color-code different event types
let eventColor = chalk.blue;
// For channel lifecycle events
if (event.includes("attached")) {
eventColor = chalk.green;
}
else if (event.includes("detached")) {
eventColor = chalk.yellow;
}
else if (event.includes("failed")) {
eventColor = chalk.red;
}
else if (event.includes("suspended")) {
eventColor = chalk.magenta;
}
// Format the log output
this.log(`${chalk.dim(`[${timestamp}]`)} Channel: ${chalk.cyan(channelName)} | Event: ${eventColor(event)}`);
if (this.shouldOutputJson(flags)) {
this.log(this.formatJsonOutput(message.data, flags));
}
else {
this.log(`Data: ${this.formatJsonOutput(message.data, flags)}`);
}
this.log("");
});
// Set up cleanup for when the process is terminated
const cleanup = () => {
if (client) {
client.close();
}
};
// Handle process termination
if (process.env.ABLY_INTERACTIVE_MODE === 'true') {
// In interactive mode, just ensure cleanup happens on exit
// Don't interfere with signal handling
process.on("exit", () => {
cleanup();
});
}
else {
// Normal mode - handle SIGINT ourselves
process.on("SIGINT", () => {
this.log("\nSubscription ended");
cleanup();
process.exit(0);
});
}
// Wait indefinitely
await new Promise(() => { });
}
catch (error) {
const err = error;
this.error(err.message);
}
finally {
if (client) {
client.close();
}
}
}
}