UNPKG

trigger.dev

Version:

A Command-Line Interface for Trigger.dev projects

126 lines 4.69 kB
import { log } from "@clack/prompts"; import { stripVTControlCharacters } from "node:util"; import { DeploymentEventFromString, } from "@trigger.dev/core/v3/schemas"; import chalk from "chalk"; import { z } from "zod"; import { chalkError, chalkGrey, chalkWarning } from "../utilities/cliOutput.js"; import { logger } from "../utilities/logger.js"; import { spinner } from "../utilities/windows.js"; export const BuildLogsMode = z.enum(["compact", "full"]); export function resolveBuildLogsMode(requested, env) { // No redrawable spinner in CI, piped output, or the Windows fallback spinner. if (env.plain || env.ci || !env.tty || env.windows) { return "full"; } return requested; } function formatBuildLogLine(entry) { const timestamp = chalkGrey(entry.timestamp.toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit", fractionalSecondDigits: 3, })); const message = entry.level === "error" ? chalk.bold(chalkError(entry.message)) : entry.level === "warn" ? chalkWarning(entry.message) : entry.level === "debug" ? chalkGrey(entry.message) : entry.message; return `│ ${timestamp} ${message}`; } export function createBuildLogRenderer(options) { const $spinner = options.spinner ?? spinner(); const print = options.print ?? ((line) => console.log(line)); const success = options.success ?? ((message) => log.success(message)); const tailSize = options.tailSize ?? 20; const tail = []; let started = false; $spinner.start("Build queued"); const compactMessage = (message) => { const columns = options.columns ?? process.stdout.columns ?? 120; const available = Math.max(columns - options.title.length - 8, 20); const singleLine = stripVTControlCharacters(message).replace(/\s+/g, " ").trim(); return singleLine.length > available ? `${singleLine.slice(0, available - 1)}…` : singleLine; }; return { get started() { return started; }, log(entry) { const line = formatBuildLogLine(entry); if (options.mode === "full") { if (!started) { $spinner.stop("Build started"); print("│"); } started = true; print(line); return; } started = true; tail.push(line); if (tail.length > tailSize) { tail.shift(); } const message = compactMessage(entry.message); if (message.length > 0 && !/^[-=#*_.\s]+$/.test(message)) { $spinner.message(`${options.title}: ${message}`); } }, finish(message, outcome) { if (options.mode === "full" && started) { if (outcome === "success") { success(message); } return; } $spinner.stop(message, outcome === "failure" ? 2 : undefined); if (options.mode === "compact" && outcome === "failure" && tail.length > 0) { print("│"); print(`│ ${chalkGrey(`Last ${tail.length} ${tail.length === 1 ? "line" : "lines"} of the build log:`)}`); for (const line of tail) { print(line); } print("│"); } }, }; } export async function streamDeploymentEvents(records, renderer, onFinalized) { let finalEvent; for await (const record of records) { const result = DeploymentEventFromString.safeParse(record.body); if (!result.success) { logger.debug("Failed to parse deployment event, skipping", { error: result.error, record: record.body, }); continue; } const event = result.data; switch (event.type) { case "log": { renderer.log({ timestamp: new Date(record.timestamp), level: event.data.level, message: event.data.message, }); break; } case "finalized": { finalEvent = event.data; onFinalized(); break; } default: { event; logger.debug("Unknown deployment event, skipping", { event }); } } } return finalEvent; } //# sourceMappingURL=buildLogs.js.map