@settlemint/sdk-utils 2.6.3-pre3cdc339 → 2.6.4-main400d9402
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/README.md +181 -166
- package/dist/environment.cjs +75 -35
- package/dist/environment.cjs.map +1 -1
- package/dist/environment.js +75 -35
- package/dist/environment.js.map +1 -1
- package/dist/package-manager.cjs +75 -35
- package/dist/package-manager.cjs.map +1 -1
- package/dist/package-manager.js +75 -35
- package/dist/package-manager.js.map +1 -1
- package/dist/terminal.cjs +75 -35
- package/dist/terminal.cjs.map +1 -1
- package/dist/terminal.d.cts +6 -3
- package/dist/terminal.d.ts +6 -3
- package/dist/terminal.js +75 -35
- package/dist/terminal.js.map +1 -1
- package/package.json +1 -1
package/dist/terminal.cjs
CHANGED
|
@@ -34,10 +34,18 @@ console_table_printer = __toESM(console_table_printer);
|
|
|
34
34
|
|
|
35
35
|
//#region src/terminal/should-print.ts
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
37
|
+
* Determines whether terminal output should be printed based on environment variables.
|
|
38
|
+
*
|
|
39
|
+
* **Environment Variable Precedence:**
|
|
40
|
+
* 1. `SETTLEMINT_DISABLE_TERMINAL="true"` - Completely disables all terminal output (highest priority)
|
|
41
|
+
* 2. `CLAUDECODE`, `REPL_ID`, or `AGENT` (any truthy value) - Enables quiet mode, suppressing info/debug/status messages
|
|
42
|
+
*
|
|
43
|
+
* **Quiet Mode Behavior:**
|
|
44
|
+
* When quiet mode is active (Claude Code environments), this function returns `false` to suppress
|
|
45
|
+
* informational output. However, warnings and errors are always displayed regardless of quiet mode,
|
|
46
|
+
* as they are handled separately in the `note()` function with level-based filtering.
|
|
47
|
+
*
|
|
48
|
+
* @returns `true` if terminal output should be printed, `false` if suppressed
|
|
41
49
|
*/
|
|
42
50
|
function shouldPrint() {
|
|
43
51
|
if (process.env.SETTLEMINT_DISABLE_TERMINAL === "true") {
|
|
@@ -249,13 +257,62 @@ const intro = (msg) => {
|
|
|
249
257
|
//#endregion
|
|
250
258
|
//#region src/terminal/note.ts
|
|
251
259
|
/**
|
|
260
|
+
* Applies color to a message if not already colored.
|
|
261
|
+
* @param msg - The message to colorize
|
|
262
|
+
* @param level - The severity level determining the color
|
|
263
|
+
* @returns Colorized message (yellow for warnings, red for errors, unchanged for info)
|
|
264
|
+
*/
|
|
265
|
+
function colorize(msg, level) {
|
|
266
|
+
if (msg.includes("\x1B[")) {
|
|
267
|
+
return msg;
|
|
268
|
+
}
|
|
269
|
+
if (level === "warn") {
|
|
270
|
+
return (0, yoctocolors.yellowBright)(msg);
|
|
271
|
+
}
|
|
272
|
+
if (level === "error") {
|
|
273
|
+
return (0, yoctocolors.redBright)(msg);
|
|
274
|
+
}
|
|
275
|
+
return msg;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Determines whether a message should be printed based on its level and quiet mode.
|
|
279
|
+
* @param level - The severity level of the message
|
|
280
|
+
* @returns true if the message should be printed, false otherwise
|
|
281
|
+
*/
|
|
282
|
+
function canPrint(level) {
|
|
283
|
+
if (level !== "info") {
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
return shouldPrint();
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Prepares a message for display by converting Error objects and masking tokens.
|
|
290
|
+
* @param value - The message string or Error object
|
|
291
|
+
* @param level - The severity level (stack traces are included for errors)
|
|
292
|
+
* @returns Masked message text, optionally with stack trace
|
|
293
|
+
*/
|
|
294
|
+
function prepareMessage(value, level) {
|
|
295
|
+
let text;
|
|
296
|
+
if (value instanceof Error) {
|
|
297
|
+
text = value.message;
|
|
298
|
+
if (level === "error" && value.stack) {
|
|
299
|
+
text = `${text}\n\n${value.stack}`;
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
text = value;
|
|
303
|
+
}
|
|
304
|
+
return maskTokens(text);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
252
307
|
* Displays a note message with optional warning or error level formatting.
|
|
253
308
|
* Regular notes are displayed in normal text, warnings are shown in yellow, and errors in red.
|
|
254
309
|
* Any sensitive tokens in the message are masked before display.
|
|
255
310
|
* Warnings and errors are always displayed, even in quiet mode (when CLAUDECODE, REPL_ID, or AGENT env vars are set).
|
|
256
311
|
* When an Error object is provided with level "error", the stack trace is automatically included.
|
|
257
312
|
*
|
|
258
|
-
* @param message - The message to display as a note
|
|
313
|
+
* @param message - The message to display as a note. Can be either:
|
|
314
|
+
* - A string: Displayed directly with appropriate styling
|
|
315
|
+
* - An Error object: The error message is displayed, and for level "error", the stack trace is automatically included
|
|
259
316
|
* @param level - The note level: "info" (default), "warn" for warning styling, or "error" for error styling
|
|
260
317
|
* @example
|
|
261
318
|
* import { note } from "@settlemint/sdk-utils/terminal";
|
|
@@ -266,46 +323,30 @@ const intro = (msg) => {
|
|
|
266
323
|
* // Display warning note
|
|
267
324
|
* note("Low disk space remaining", "warn");
|
|
268
325
|
*
|
|
269
|
-
* // Display error note
|
|
326
|
+
* // Display error note (string)
|
|
270
327
|
* note("Operation failed", "error");
|
|
271
328
|
*
|
|
272
|
-
* // Display error with stack trace automatically
|
|
329
|
+
* // Display error with stack trace automatically (Error object)
|
|
273
330
|
* try {
|
|
274
331
|
* // some operation
|
|
275
332
|
* } catch (error) {
|
|
333
|
+
* // If error is an Error object and level is "error", stack trace is included automatically
|
|
276
334
|
* note(error, "error");
|
|
277
335
|
* }
|
|
278
336
|
*/
|
|
279
337
|
const note = (message, level = "info") => {
|
|
280
|
-
|
|
281
|
-
let _error;
|
|
282
|
-
if (message instanceof Error) {
|
|
283
|
-
_error = message;
|
|
284
|
-
messageText = message.message;
|
|
285
|
-
if (level === "error" && message.stack) {
|
|
286
|
-
messageText = `${messageText}\n\n${message.stack}`;
|
|
287
|
-
}
|
|
288
|
-
} else {
|
|
289
|
-
messageText = message;
|
|
290
|
-
}
|
|
291
|
-
const maskedMessage = maskTokens(messageText);
|
|
292
|
-
const _isQuietMode = process.env.CLAUDECODE || process.env.REPL_ID || process.env.AGENT;
|
|
293
|
-
if (level === "warn" || level === "error") {
|
|
294
|
-
console.log("");
|
|
295
|
-
if (level === "warn") {
|
|
296
|
-
const coloredMessage = maskedMessage.includes("\x1B[") ? maskedMessage : (0, yoctocolors.yellowBright)(maskedMessage);
|
|
297
|
-
console.warn(coloredMessage);
|
|
298
|
-
} else {
|
|
299
|
-
const coloredMessage = maskedMessage.includes("\x1B[") ? maskedMessage : (0, yoctocolors.redBright)(maskedMessage);
|
|
300
|
-
console.error(coloredMessage);
|
|
301
|
-
}
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
if (!shouldPrint()) {
|
|
338
|
+
if (!canPrint(level)) {
|
|
305
339
|
return;
|
|
306
340
|
}
|
|
341
|
+
const msg = prepareMessage(message, level);
|
|
307
342
|
console.log("");
|
|
308
|
-
|
|
343
|
+
if (level === "warn") {
|
|
344
|
+
console.warn(colorize(msg, level));
|
|
345
|
+
} else if (level === "error") {
|
|
346
|
+
console.error(colorize(msg, level));
|
|
347
|
+
} else {
|
|
348
|
+
console.log(msg);
|
|
349
|
+
}
|
|
309
350
|
};
|
|
310
351
|
|
|
311
352
|
//#endregion
|
|
@@ -401,8 +442,7 @@ var SpinnerError = class extends Error {
|
|
|
401
442
|
const spinner = async (options) => {
|
|
402
443
|
const handleError = (error) => {
|
|
403
444
|
note(error, "error");
|
|
404
|
-
|
|
405
|
-
throw new SpinnerError(errorMessage, error);
|
|
445
|
+
throw new SpinnerError(error.message, error);
|
|
406
446
|
};
|
|
407
447
|
if (is_in_ci.default || !shouldPrint()) {
|
|
408
448
|
try {
|
package/dist/terminal.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.cjs","names":["code: number","output: string[]","stdoutOutput: string[]","stderrOutput: string[]","messageText: string","_error: Error | undefined","items","originalError: Error","isInCi","spinner","table","Table"],"sources":["../src/terminal/should-print.ts","../src/terminal/ascii.ts","../src/logging/mask-tokens.ts","../src/terminal/cancel.ts","../src/terminal/execute-command.ts","../src/terminal/intro.ts","../src/terminal/note.ts","../src/terminal/list.ts","../src/terminal/outro.ts","../src/terminal/spinner.ts","../src/string.ts","../src/terminal/table.ts"],"sourcesContent":["/**\n * Returns true if the terminal should print, false otherwise.\n * When CLAUDECODE, REPL_ID, or AGENT env vars are set, suppresses info/debug output\n * but warnings and errors will still be displayed.\n * @returns true if the terminal should print, false otherwise.\n */\nexport function shouldPrint() {\n if (process.env.SETTLEMINT_DISABLE_TERMINAL === \"true\") {\n return false;\n }\n // In quiet mode (Claude Code), suppress info/debug/status messages\n // Warnings and errors will still be displayed via note() with appropriate levels\n if (process.env.CLAUDECODE || process.env.REPL_ID || process.env.AGENT) {\n return false;\n }\n return true;\n}\n","import { magentaBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Prints the SettleMint ASCII art logo to the console in magenta color.\n * Used for CLI branding and visual identification.\n *\n * @example\n * import { ascii } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Prints the SettleMint logo\n * ascii();\n */\nexport const ascii = (): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\n magentaBright(`\n _________ __ __ .__ _____ .__ __\n / _____/ _____/ |__/ |_| | ____ / \\\\ |__| _____/ |_\n \\\\_____ \\\\_/ __ \\\\ __\\\\ __\\\\ | _/ __ \\\\ / \\\\ / \\\\| |/ \\\\ __\\\\\n / \\\\ ___/| | | | | |_\\\\ ___// Y \\\\ | | \\\\ |\n/_________/\\\\_____>__| |__| |____/\\\\_____>____|____/__|___|__/__|\n`),\n );\n};\n","/**\n * Masks sensitive SettleMint tokens in output text by replacing them with asterisks.\n * Handles personal access tokens (PAT), application access tokens (AAT), and service account tokens (SAT).\n *\n * @param output - The text string that may contain sensitive tokens\n * @returns The text with any sensitive tokens masked with asterisks\n * @example\n * import { maskTokens } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Masks a token in text\n * const masked = maskTokens(\"Token: sm_pat_****\"); // \"Token: ***\"\n */\nexport const maskTokens = (output: string): string => {\n return output.replace(/sm_(pat|aat|sat)_[0-9a-zA-Z]+/g, \"***\");\n};\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { inverse, redBright } from \"yoctocolors\";\n\n/**\n * Error class used to indicate that the operation was cancelled.\n * This error is used to signal that the operation should be aborted.\n */\nexport class CancelError extends Error {}\n\n/**\n * Displays an error message in red inverse text and throws a CancelError.\n * Used to terminate execution with a visible error message.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The error message to display\n * @returns never - Function does not return as it throws an error\n * @example\n * import { cancel } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Exits process with error message\n * cancel(\"An error occurred\");\n */\nexport const cancel = (msg: string): never => {\n console.log(\"\");\n console.log(inverse(redBright(maskTokens(msg))));\n console.log(\"\");\n throw new CancelError(msg);\n};\n","import { type SpawnOptionsWithoutStdio, spawn } from \"node:child_process\";\nimport { maskTokens } from \"../logging/mask-tokens.js\";\n\n/**\n * Options for executing a command, extending SpawnOptionsWithoutStdio\n */\nexport interface ExecuteCommandOptions extends SpawnOptionsWithoutStdio {\n /** Whether to suppress output to stdout/stderr */\n silent?: boolean;\n}\n\n/**\n * Error class for command execution errors\n * @extends Error\n */\nexport class CommandError extends Error {\n /**\n * Constructs a new CommandError\n * @param message - The error message\n * @param code - The exit code of the command\n * @param output - The output of the command\n */\n constructor(\n message: string,\n public readonly code: number,\n public readonly output: string[],\n ) {\n super(message);\n }\n}\n\n/**\n * Checks if we're in quiet mode (Claude Code environment)\n */\nfunction isQuietMode(): boolean {\n return !!(process.env.CLAUDECODE || process.env.REPL_ID || process.env.AGENT);\n}\n\n/**\n * Executes a command with the given arguments in a child process.\n * Pipes stdin to the child process and captures stdout/stderr output.\n * Masks any sensitive tokens in the output before displaying or returning.\n * In quiet mode (when CLAUDECODE, REPL_ID, or AGENT env vars are set),\n * output is suppressed unless the command errors out.\n *\n * @param command - The command to execute\n * @param args - Array of arguments to pass to the command\n * @param options - Options for customizing command execution\n * @returns Array of output strings from stdout and stderr\n * @throws {CommandError} If the process fails to start or exits with non-zero code\n * @example\n * import { executeCommand } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Execute git clone\n * await executeCommand(\"git\", [\"clone\", \"repo-url\"]);\n *\n * // Execute silently\n * await executeCommand(\"npm\", [\"install\"], { silent: true });\n */\nexport async function executeCommand(\n command: string,\n args: string[],\n options?: ExecuteCommandOptions,\n): Promise<string[]> {\n const { silent, ...spawnOptions } = options ?? {};\n const quietMode = isQuietMode();\n // In quiet mode, suppress output unless explicitly overridden with silent: false\n const shouldSuppressOutput = quietMode ? silent !== false : !!silent;\n\n const child = spawn(command, args, { ...spawnOptions, env: { ...process.env, ...options?.env } });\n process.stdin.pipe(child.stdin);\n const output: string[] = [];\n const stdoutOutput: string[] = [];\n const stderrOutput: string[] = [];\n\n return new Promise((resolve, reject) => {\n child.stdout.on(\"data\", (data: Buffer | string) => {\n const maskedData = maskTokens(data.toString());\n if (!shouldSuppressOutput) {\n process.stdout.write(maskedData);\n }\n output.push(maskedData);\n stdoutOutput.push(maskedData);\n });\n child.stderr.on(\"data\", (data: Buffer | string) => {\n const maskedData = maskTokens(data.toString());\n if (!shouldSuppressOutput) {\n process.stderr.write(maskedData);\n }\n output.push(maskedData);\n stderrOutput.push(maskedData);\n });\n\n const showErrorOutput = () => {\n // In quiet mode, show output on error\n if (quietMode && shouldSuppressOutput && output.length > 0) {\n // Write stdout to stdout and stderr to stderr\n if (stdoutOutput.length > 0) {\n process.stdout.write(stdoutOutput.join(\"\"));\n }\n if (stderrOutput.length > 0) {\n process.stderr.write(stderrOutput.join(\"\"));\n }\n }\n };\n\n child.on(\"error\", (err) => {\n process.stdin.unpipe(child.stdin);\n showErrorOutput();\n reject(new CommandError(err.message, \"code\" in err && typeof err.code === \"number\" ? err.code : 1, output));\n });\n child.on(\"close\", (code) => {\n process.stdin.unpipe(child.stdin);\n if (code === 0 || code === null || code === 143) {\n resolve(output);\n return;\n }\n // In quiet mode, show output on error\n showErrorOutput();\n reject(new CommandError(`Command \"${command}\" exited with code ${code}`, code, output));\n });\n });\n}\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { magentaBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Displays an introductory message in magenta text with padding.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The message to display as introduction\n * @example\n * import { intro } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display intro message\n * intro(\"Starting deployment...\");\n */\nexport const intro = (msg: string): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\"\");\n console.log(magentaBright(maskTokens(msg)));\n console.log(\"\");\n};\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { redBright, yellowBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Displays a note message with optional warning or error level formatting.\n * Regular notes are displayed in normal text, warnings are shown in yellow, and errors in red.\n * Any sensitive tokens in the message are masked before display.\n * Warnings and errors are always displayed, even in quiet mode (when CLAUDECODE, REPL_ID, or AGENT env vars are set).\n * When an Error object is provided with level \"error\", the stack trace is automatically included.\n *\n * @param message - The message to display as a note, or an Error object\n * @param level - The note level: \"info\" (default), \"warn\" for warning styling, or \"error\" for error styling\n * @example\n * import { note } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display info note\n * note(\"Operation completed successfully\");\n *\n * // Display warning note\n * note(\"Low disk space remaining\", \"warn\");\n *\n * // Display error note\n * note(\"Operation failed\", \"error\");\n *\n * // Display error with stack trace automatically\n * try {\n * // some operation\n * } catch (error) {\n * note(error, \"error\");\n * }\n */\nexport const note = (message: string | Error, level: \"info\" | \"warn\" | \"error\" = \"info\"): void => {\n let messageText: string;\n let _error: Error | undefined;\n\n if (message instanceof Error) {\n _error = message;\n messageText = message.message;\n // For errors, automatically include stack trace\n if (level === \"error\" && message.stack) {\n messageText = `${messageText}\\n\\n${message.stack}`;\n }\n } else {\n messageText = message;\n }\n\n const maskedMessage = maskTokens(messageText);\n const _isQuietMode = process.env.CLAUDECODE || process.env.REPL_ID || process.env.AGENT;\n\n // Always print warnings and errors, even in quiet mode\n if (level === \"warn\" || level === \"error\") {\n console.log(\"\");\n if (level === \"warn\") {\n // Apply yellow color if not already colored (check if message contains ANSI codes)\n const coloredMessage = maskedMessage.includes(\"\\u001b[\") ? maskedMessage : yellowBright(maskedMessage);\n console.warn(coloredMessage);\n } else {\n // Apply red color if not already colored (check if message contains ANSI codes)\n const coloredMessage = maskedMessage.includes(\"\\u001b[\") ? maskedMessage : redBright(maskedMessage);\n console.error(coloredMessage);\n }\n return;\n }\n\n // For info messages, check if we should print\n if (!shouldPrint()) {\n return;\n }\n\n console.log(\"\");\n console.log(maskedMessage);\n};\n","import { note } from \"./note.js\";\n\n/**\n * Displays a list of items in a formatted manner, supporting nested items.\n *\n * @param title - The title of the list\n * @param items - The items to display, can be strings or arrays for nested items\n * @returns The formatted list\n * @example\n * import { list } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Simple list\n * list(\"Use cases\", [\"use case 1\", \"use case 2\", \"use case 3\"]);\n *\n * // Nested list\n * list(\"Providers\", [\n * \"AWS\",\n * [\"us-east-1\", \"eu-west-1\"],\n * \"Azure\",\n * [\"eastus\", \"westeurope\"]\n * ]);\n */\nexport function list(title: string, items: Array<string | string[]>) {\n const formatItems = (items: Array<string | string[]>): string => {\n return items\n .map((item) => {\n if (Array.isArray(item)) {\n return item.map((subItem) => ` • ${subItem}`).join(\"\\n\");\n }\n return ` • ${item}`;\n })\n .join(\"\\n\");\n };\n\n return note(`${title}:\\n\\n${formatItems(items)}`);\n}\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { shouldPrint } from \"@/terminal/should-print.js\";\nimport { greenBright, inverse } from \"yoctocolors\";\n\n/**\n * Displays a closing message in green inverted text with padding.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The message to display as conclusion\n * @example\n * import { outro } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display outro message\n * outro(\"Deployment completed successfully!\");\n */\nexport const outro = (msg: string): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\"\");\n console.log(inverse(greenBright(maskTokens(msg))));\n console.log(\"\");\n};\n","import isInCi from \"is-in-ci\";\nimport yoctoSpinner, { type Spinner } from \"yocto-spinner\";\nimport { redBright } from \"yoctocolors\";\nimport { maskTokens } from \"../logging/mask-tokens.js\";\nimport { note } from \"./note.js\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Error class used to indicate that the spinner operation failed.\n * This error is used to signal that the operation should be aborted.\n */\nexport class SpinnerError extends Error {\n constructor(\n message: string,\n public readonly originalError: Error,\n ) {\n super(message);\n this.name = \"SpinnerError\";\n }\n}\n\n/**\n * Options for configuring the spinner behavior\n */\nexport interface SpinnerOptions<R> {\n /** Message to display when spinner starts */\n startMessage: string;\n /** Async task to execute while spinner is active */\n task: (spinner?: Spinner) => Promise<R>;\n /** Message to display when spinner completes successfully */\n stopMessage: string;\n}\n\n/**\n * Displays a loading spinner while executing an async task.\n * Shows progress with start/stop messages and handles errors.\n * Spinner is disabled in CI environments.\n *\n * @param options - Configuration options for the spinner\n * @returns The result from the executed task\n * @throws Will exit process with code 1 if task fails\n * @example\n * import { spinner } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Show spinner during async task\n * const result = await spinner({\n * startMessage: \"Deploying...\",\n * task: async () => {\n * // Async work here\n * return \"success\";\n * },\n * stopMessage: \"Deployed successfully!\"\n * });\n */\nexport const spinner = async <R>(options: SpinnerOptions<R>): Promise<R> => {\n const handleError = (error: Error) => {\n note(error, \"error\");\n const errorMessage = maskTokens(error.message);\n throw new SpinnerError(errorMessage, error);\n };\n if (isInCi || !shouldPrint()) {\n try {\n return await options.task();\n } catch (err) {\n return handleError(err as Error);\n }\n }\n const spinner = yoctoSpinner({ stream: process.stdout }).start(options.startMessage);\n try {\n const result = await options.task(spinner);\n spinner.success(options.stopMessage);\n // Ensure spinner success message renders before proceeding to avoid\n // terminal output overlap issues with subsequent messages\n await new Promise((resolve) => process.nextTick(resolve));\n return result;\n } catch (err) {\n spinner.error(redBright(`${options.startMessage} --> Error!`));\n return handleError(err as Error);\n }\n};\n","/**\n * Capitalizes the first letter of a string.\n *\n * @param val - The string to capitalize\n * @returns The input string with its first letter capitalized\n *\n * @example\n * import { capitalizeFirstLetter } from \"@settlemint/sdk-utils\";\n *\n * const capitalized = capitalizeFirstLetter(\"hello\");\n * // Returns: \"Hello\"\n */\nexport function capitalizeFirstLetter(val: string) {\n return String(val).charAt(0).toUpperCase() + String(val).slice(1);\n}\n\n/**\n * Converts a camelCase string to a human-readable string.\n *\n * @param s - The camelCase string to convert\n * @returns The human-readable string\n *\n * @example\n * import { camelCaseToWords } from \"@settlemint/sdk-utils\";\n *\n * const words = camelCaseToWords(\"camelCaseString\");\n * // Returns: \"Camel Case String\"\n */\nexport function camelCaseToWords(s: string) {\n const result = s.replace(/([a-z])([A-Z])/g, \"$1 $2\");\n const withSpaces = result.replace(/([A-Z])([a-z])/g, \" $1$2\");\n const capitalized = capitalizeFirstLetter(withSpaces);\n return capitalized.replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Replaces underscores and hyphens with spaces.\n *\n * @param s - The string to replace underscores and hyphens with spaces\n * @returns The input string with underscores and hyphens replaced with spaces\n *\n * @example\n * import { replaceUnderscoresAndHyphensWithSpaces } from \"@settlemint/sdk-utils\";\n *\n * const result = replaceUnderscoresAndHyphensWithSpaces(\"Already_Spaced-Second\");\n * // Returns: \"Already Spaced Second\"\n */\nexport function replaceUnderscoresAndHyphensWithSpaces(s: string) {\n return s.replace(/[-_]/g, \" \");\n}\n\n/**\n * Truncates a string to a maximum length and appends \"...\" if it is longer.\n *\n * @param value - The string to truncate\n * @param maxLength - The maximum length of the string\n * @returns The truncated string or the original string if it is shorter than the maximum length\n *\n * @example\n * import { truncate } from \"@settlemint/sdk-utils\";\n *\n * const truncated = truncate(\"Hello, world!\", 10);\n * // Returns: \"Hello, wor...\"\n */\nexport function truncate(value: string, maxLength: number) {\n if (value.length <= maxLength) {\n return value;\n }\n return `${value.slice(0, maxLength)}...`;\n}\n","import { Table } from \"console-table-printer\";\nimport { whiteBright } from \"yoctocolors\";\nimport { camelCaseToWords } from \"@/string.js\";\nimport { note } from \"./note.js\";\nimport { shouldPrint } from \"./should-print.js\";\n/**\n * Displays data in a formatted table in the terminal.\n *\n * @param title - Title to display above the table\n * @param data - Array of objects to display in table format\n * @example\n * import { table } from \"@settlemint/sdk-utils/terminal\";\n *\n * const data = [\n * { name: \"Item 1\", value: 100 },\n * { name: \"Item 2\", value: 200 }\n * ];\n *\n * table(\"My Table\", data);\n */\nexport function table(title: string, data: unknown[]): void {\n if (!shouldPrint()) {\n return;\n }\n\n note(title);\n\n if (!data || data.length === 0) {\n note(\"No data to display\");\n return;\n }\n\n const columnKeys = Object.keys(data[0] as Record<string, unknown>);\n const table = new Table({\n columns: columnKeys.map((key) => ({\n name: key,\n title: whiteBright(camelCaseToWords(key)),\n alignment: \"left\",\n })),\n });\n // biome-ignore lint/suspicious/noExplicitAny: Data structure varies based on table content\n table.addRows(data as Array<Record<string, any>>);\n table.printTable();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"terminal.cjs","names":["code: number","output: string[]","stdoutOutput: string[]","stderrOutput: string[]","text: string","items","originalError: Error","isInCi","spinner","table","Table"],"sources":["../src/terminal/should-print.ts","../src/terminal/ascii.ts","../src/logging/mask-tokens.ts","../src/terminal/cancel.ts","../src/terminal/execute-command.ts","../src/terminal/intro.ts","../src/terminal/note.ts","../src/terminal/list.ts","../src/terminal/outro.ts","../src/terminal/spinner.ts","../src/string.ts","../src/terminal/table.ts"],"sourcesContent":["/**\n * Determines whether terminal output should be printed based on environment variables.\n *\n * **Environment Variable Precedence:**\n * 1. `SETTLEMINT_DISABLE_TERMINAL=\"true\"` - Completely disables all terminal output (highest priority)\n * 2. `CLAUDECODE`, `REPL_ID`, or `AGENT` (any truthy value) - Enables quiet mode, suppressing info/debug/status messages\n *\n * **Quiet Mode Behavior:**\n * When quiet mode is active (Claude Code environments), this function returns `false` to suppress\n * informational output. However, warnings and errors are always displayed regardless of quiet mode,\n * as they are handled separately in the `note()` function with level-based filtering.\n *\n * @returns `true` if terminal output should be printed, `false` if suppressed\n */\nexport function shouldPrint(): boolean {\n if (process.env.SETTLEMINT_DISABLE_TERMINAL === \"true\") {\n return false;\n }\n // In quiet mode (Claude Code), suppress info/debug/status messages\n // Warnings and errors will still be displayed via note() with appropriate levels\n if (process.env.CLAUDECODE || process.env.REPL_ID || process.env.AGENT) {\n return false;\n }\n return true;\n}\n","import { magentaBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Prints the SettleMint ASCII art logo to the console in magenta color.\n * Used for CLI branding and visual identification.\n *\n * @example\n * import { ascii } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Prints the SettleMint logo\n * ascii();\n */\nexport const ascii = (): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\n magentaBright(`\n _________ __ __ .__ _____ .__ __\n / _____/ _____/ |__/ |_| | ____ / \\\\ |__| _____/ |_\n \\\\_____ \\\\_/ __ \\\\ __\\\\ __\\\\ | _/ __ \\\\ / \\\\ / \\\\| |/ \\\\ __\\\\\n / \\\\ ___/| | | | | |_\\\\ ___// Y \\\\ | | \\\\ |\n/_________/\\\\_____>__| |__| |____/\\\\_____>____|____/__|___|__/__|\n`),\n );\n};\n","/**\n * Masks sensitive SettleMint tokens in output text by replacing them with asterisks.\n * Handles personal access tokens (PAT), application access tokens (AAT), and service account tokens (SAT).\n *\n * @param output - The text string that may contain sensitive tokens\n * @returns The text with any sensitive tokens masked with asterisks\n * @example\n * import { maskTokens } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Masks a token in text\n * const masked = maskTokens(\"Token: sm_pat_****\"); // \"Token: ***\"\n */\nexport const maskTokens = (output: string): string => {\n return output.replace(/sm_(pat|aat|sat)_[0-9a-zA-Z]+/g, \"***\");\n};\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { inverse, redBright } from \"yoctocolors\";\n\n/**\n * Error class used to indicate that the operation was cancelled.\n * This error is used to signal that the operation should be aborted.\n */\nexport class CancelError extends Error {}\n\n/**\n * Displays an error message in red inverse text and throws a CancelError.\n * Used to terminate execution with a visible error message.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The error message to display\n * @returns never - Function does not return as it throws an error\n * @example\n * import { cancel } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Exits process with error message\n * cancel(\"An error occurred\");\n */\nexport const cancel = (msg: string): never => {\n console.log(\"\");\n console.log(inverse(redBright(maskTokens(msg))));\n console.log(\"\");\n throw new CancelError(msg);\n};\n","import { type SpawnOptionsWithoutStdio, spawn } from \"node:child_process\";\nimport { maskTokens } from \"../logging/mask-tokens.js\";\n\n/**\n * Options for executing a command, extending SpawnOptionsWithoutStdio\n */\nexport interface ExecuteCommandOptions extends SpawnOptionsWithoutStdio {\n /** Whether to suppress output to stdout/stderr */\n silent?: boolean;\n}\n\n/**\n * Error class for command execution errors\n * @extends Error\n */\nexport class CommandError extends Error {\n /**\n * Constructs a new CommandError\n * @param message - The error message\n * @param code - The exit code of the command\n * @param output - The output of the command\n */\n constructor(\n message: string,\n public readonly code: number,\n public readonly output: string[],\n ) {\n super(message);\n }\n}\n\n/**\n * Checks if we're in quiet mode (Claude Code environment)\n */\nfunction isQuietMode(): boolean {\n return !!(process.env.CLAUDECODE || process.env.REPL_ID || process.env.AGENT);\n}\n\n/**\n * Executes a command with the given arguments in a child process.\n * Pipes stdin to the child process and captures stdout/stderr output.\n * Masks any sensitive tokens in the output before displaying or returning.\n * In quiet mode (when CLAUDECODE, REPL_ID, or AGENT env vars are set),\n * output is suppressed unless the command errors out.\n *\n * @param command - The command to execute\n * @param args - Array of arguments to pass to the command\n * @param options - Options for customizing command execution\n * @returns Array of output strings from stdout and stderr\n * @throws {CommandError} If the process fails to start or exits with non-zero code\n * @example\n * import { executeCommand } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Execute git clone\n * await executeCommand(\"git\", [\"clone\", \"repo-url\"]);\n *\n * // Execute silently\n * await executeCommand(\"npm\", [\"install\"], { silent: true });\n */\nexport async function executeCommand(\n command: string,\n args: string[],\n options?: ExecuteCommandOptions,\n): Promise<string[]> {\n const { silent, ...spawnOptions } = options ?? {};\n const quietMode = isQuietMode();\n // In quiet mode, suppress output unless explicitly overridden with silent: false\n const shouldSuppressOutput = quietMode ? silent !== false : !!silent;\n\n const child = spawn(command, args, { ...spawnOptions, env: { ...process.env, ...options?.env } });\n process.stdin.pipe(child.stdin);\n const output: string[] = [];\n const stdoutOutput: string[] = [];\n const stderrOutput: string[] = [];\n\n return new Promise((resolve, reject) => {\n child.stdout.on(\"data\", (data: Buffer | string) => {\n const maskedData = maskTokens(data.toString());\n if (!shouldSuppressOutput) {\n process.stdout.write(maskedData);\n }\n output.push(maskedData);\n stdoutOutput.push(maskedData);\n });\n child.stderr.on(\"data\", (data: Buffer | string) => {\n const maskedData = maskTokens(data.toString());\n if (!shouldSuppressOutput) {\n process.stderr.write(maskedData);\n }\n output.push(maskedData);\n stderrOutput.push(maskedData);\n });\n\n const showErrorOutput = () => {\n // In quiet mode, show output on error\n if (quietMode && shouldSuppressOutput && output.length > 0) {\n // Write stdout to stdout and stderr to stderr\n if (stdoutOutput.length > 0) {\n process.stdout.write(stdoutOutput.join(\"\"));\n }\n if (stderrOutput.length > 0) {\n process.stderr.write(stderrOutput.join(\"\"));\n }\n }\n };\n\n child.on(\"error\", (err) => {\n process.stdin.unpipe(child.stdin);\n showErrorOutput();\n reject(new CommandError(err.message, \"code\" in err && typeof err.code === \"number\" ? err.code : 1, output));\n });\n child.on(\"close\", (code) => {\n process.stdin.unpipe(child.stdin);\n if (code === 0 || code === null || code === 143) {\n resolve(output);\n return;\n }\n // In quiet mode, show output on error\n showErrorOutput();\n reject(new CommandError(`Command \"${command}\" exited with code ${code}`, code, output));\n });\n });\n}\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { magentaBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Displays an introductory message in magenta text with padding.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The message to display as introduction\n * @example\n * import { intro } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display intro message\n * intro(\"Starting deployment...\");\n */\nexport const intro = (msg: string): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\"\");\n console.log(magentaBright(maskTokens(msg)));\n console.log(\"\");\n};\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { redBright, yellowBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Applies color to a message if not already colored.\n * @param msg - The message to colorize\n * @param level - The severity level determining the color\n * @returns Colorized message (yellow for warnings, red for errors, unchanged for info)\n */\nfunction colorize(msg: string, level: \"info\" | \"warn\" | \"error\"): string {\n // Don't re-colorize messages that already contain ANSI escape codes\n if (msg.includes(\"\\u001b[\")) {\n return msg;\n }\n if (level === \"warn\") {\n return yellowBright(msg);\n }\n if (level === \"error\") {\n return redBright(msg);\n }\n return msg;\n}\n\n/**\n * Determines whether a message should be printed based on its level and quiet mode.\n * @param level - The severity level of the message\n * @returns true if the message should be printed, false otherwise\n */\nfunction canPrint(level: \"info\" | \"warn\" | \"error\"): boolean {\n // Warnings and errors always print, even in quiet mode\n if (level !== \"info\") {\n return true;\n }\n // Info messages respect shouldPrint() which checks for quiet mode\n return shouldPrint();\n}\n\n/**\n * Prepares a message for display by converting Error objects and masking tokens.\n * @param value - The message string or Error object\n * @param level - The severity level (stack traces are included for errors)\n * @returns Masked message text, optionally with stack trace\n */\nfunction prepareMessage(value: string | Error, level: \"info\" | \"warn\" | \"error\"): string {\n let text: string;\n if (value instanceof Error) {\n text = value.message;\n // For errors, automatically include stack trace\n if (level === \"error\" && value.stack) {\n text = `${text}\\n\\n${value.stack}`;\n }\n } else {\n text = value;\n }\n return maskTokens(text);\n}\n\n/**\n * Displays a note message with optional warning or error level formatting.\n * Regular notes are displayed in normal text, warnings are shown in yellow, and errors in red.\n * Any sensitive tokens in the message are masked before display.\n * Warnings and errors are always displayed, even in quiet mode (when CLAUDECODE, REPL_ID, or AGENT env vars are set).\n * When an Error object is provided with level \"error\", the stack trace is automatically included.\n *\n * @param message - The message to display as a note. Can be either:\n * - A string: Displayed directly with appropriate styling\n * - An Error object: The error message is displayed, and for level \"error\", the stack trace is automatically included\n * @param level - The note level: \"info\" (default), \"warn\" for warning styling, or \"error\" for error styling\n * @example\n * import { note } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display info note\n * note(\"Operation completed successfully\");\n *\n * // Display warning note\n * note(\"Low disk space remaining\", \"warn\");\n *\n * // Display error note (string)\n * note(\"Operation failed\", \"error\");\n *\n * // Display error with stack trace automatically (Error object)\n * try {\n * // some operation\n * } catch (error) {\n * // If error is an Error object and level is \"error\", stack trace is included automatically\n * note(error, \"error\");\n * }\n */\nexport const note = (message: string | Error, level: \"info\" | \"warn\" | \"error\" = \"info\"): void => {\n if (!canPrint(level)) {\n return;\n }\n\n const msg = prepareMessage(message, level);\n console.log(\"\");\n\n if (level === \"warn\") {\n console.warn(colorize(msg, level));\n } else if (level === \"error\") {\n console.error(colorize(msg, level));\n } else {\n console.log(msg);\n }\n};\n","import { note } from \"./note.js\";\n\n/**\n * Displays a list of items in a formatted manner, supporting nested items.\n *\n * @param title - The title of the list\n * @param items - The items to display, can be strings or arrays for nested items\n * @returns The formatted list\n * @example\n * import { list } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Simple list\n * list(\"Use cases\", [\"use case 1\", \"use case 2\", \"use case 3\"]);\n *\n * // Nested list\n * list(\"Providers\", [\n * \"AWS\",\n * [\"us-east-1\", \"eu-west-1\"],\n * \"Azure\",\n * [\"eastus\", \"westeurope\"]\n * ]);\n */\nexport function list(title: string, items: Array<string | string[]>) {\n const formatItems = (items: Array<string | string[]>): string => {\n return items\n .map((item) => {\n if (Array.isArray(item)) {\n return item.map((subItem) => ` • ${subItem}`).join(\"\\n\");\n }\n return ` • ${item}`;\n })\n .join(\"\\n\");\n };\n\n return note(`${title}:\\n\\n${formatItems(items)}`);\n}\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { shouldPrint } from \"@/terminal/should-print.js\";\nimport { greenBright, inverse } from \"yoctocolors\";\n\n/**\n * Displays a closing message in green inverted text with padding.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The message to display as conclusion\n * @example\n * import { outro } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display outro message\n * outro(\"Deployment completed successfully!\");\n */\nexport const outro = (msg: string): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\"\");\n console.log(inverse(greenBright(maskTokens(msg))));\n console.log(\"\");\n};\n","import isInCi from \"is-in-ci\";\nimport yoctoSpinner, { type Spinner } from \"yocto-spinner\";\nimport { redBright } from \"yoctocolors\";\nimport { note } from \"./note.js\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Error class used to indicate that the spinner operation failed.\n * This error is used to signal that the operation should be aborted.\n */\nexport class SpinnerError extends Error {\n constructor(\n message: string,\n public readonly originalError: Error,\n ) {\n super(message);\n this.name = \"SpinnerError\";\n }\n}\n\n/**\n * Options for configuring the spinner behavior\n */\nexport interface SpinnerOptions<R> {\n /** Message to display when spinner starts */\n startMessage: string;\n /** Async task to execute while spinner is active */\n task: (spinner?: Spinner) => Promise<R>;\n /** Message to display when spinner completes successfully */\n stopMessage: string;\n}\n\n/**\n * Displays a loading spinner while executing an async task.\n * Shows progress with start/stop messages and handles errors.\n * Spinner is disabled in CI environments.\n *\n * @param options - Configuration options for the spinner\n * @returns The result from the executed task\n * @throws Will exit process with code 1 if task fails\n * @example\n * import { spinner } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Show spinner during async task\n * const result = await spinner({\n * startMessage: \"Deploying...\",\n * task: async () => {\n * // Async work here\n * return \"success\";\n * },\n * stopMessage: \"Deployed successfully!\"\n * });\n */\nexport const spinner = async <R>(options: SpinnerOptions<R>): Promise<R> => {\n const handleError = (error: Error) => {\n note(error, \"error\");\n throw new SpinnerError(error.message, error);\n };\n if (isInCi || !shouldPrint()) {\n try {\n return await options.task();\n } catch (err) {\n return handleError(err as Error);\n }\n }\n const spinner = yoctoSpinner({ stream: process.stdout }).start(options.startMessage);\n try {\n const result = await options.task(spinner);\n spinner.success(options.stopMessage);\n // Ensure spinner success message renders before proceeding to avoid\n // terminal output overlap issues with subsequent messages\n await new Promise((resolve) => process.nextTick(resolve));\n return result;\n } catch (err) {\n spinner.error(redBright(`${options.startMessage} --> Error!`));\n return handleError(err as Error);\n }\n};\n","/**\n * Capitalizes the first letter of a string.\n *\n * @param val - The string to capitalize\n * @returns The input string with its first letter capitalized\n *\n * @example\n * import { capitalizeFirstLetter } from \"@settlemint/sdk-utils\";\n *\n * const capitalized = capitalizeFirstLetter(\"hello\");\n * // Returns: \"Hello\"\n */\nexport function capitalizeFirstLetter(val: string) {\n return String(val).charAt(0).toUpperCase() + String(val).slice(1);\n}\n\n/**\n * Converts a camelCase string to a human-readable string.\n *\n * @param s - The camelCase string to convert\n * @returns The human-readable string\n *\n * @example\n * import { camelCaseToWords } from \"@settlemint/sdk-utils\";\n *\n * const words = camelCaseToWords(\"camelCaseString\");\n * // Returns: \"Camel Case String\"\n */\nexport function camelCaseToWords(s: string) {\n const result = s.replace(/([a-z])([A-Z])/g, \"$1 $2\");\n const withSpaces = result.replace(/([A-Z])([a-z])/g, \" $1$2\");\n const capitalized = capitalizeFirstLetter(withSpaces);\n return capitalized.replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Replaces underscores and hyphens with spaces.\n *\n * @param s - The string to replace underscores and hyphens with spaces\n * @returns The input string with underscores and hyphens replaced with spaces\n *\n * @example\n * import { replaceUnderscoresAndHyphensWithSpaces } from \"@settlemint/sdk-utils\";\n *\n * const result = replaceUnderscoresAndHyphensWithSpaces(\"Already_Spaced-Second\");\n * // Returns: \"Already Spaced Second\"\n */\nexport function replaceUnderscoresAndHyphensWithSpaces(s: string) {\n return s.replace(/[-_]/g, \" \");\n}\n\n/**\n * Truncates a string to a maximum length and appends \"...\" if it is longer.\n *\n * @param value - The string to truncate\n * @param maxLength - The maximum length of the string\n * @returns The truncated string or the original string if it is shorter than the maximum length\n *\n * @example\n * import { truncate } from \"@settlemint/sdk-utils\";\n *\n * const truncated = truncate(\"Hello, world!\", 10);\n * // Returns: \"Hello, wor...\"\n */\nexport function truncate(value: string, maxLength: number) {\n if (value.length <= maxLength) {\n return value;\n }\n return `${value.slice(0, maxLength)}...`;\n}\n","import { Table } from \"console-table-printer\";\nimport { whiteBright } from \"yoctocolors\";\nimport { camelCaseToWords } from \"@/string.js\";\nimport { note } from \"./note.js\";\nimport { shouldPrint } from \"./should-print.js\";\n/**\n * Displays data in a formatted table in the terminal.\n *\n * @param title - Title to display above the table\n * @param data - Array of objects to display in table format\n * @example\n * import { table } from \"@settlemint/sdk-utils/terminal\";\n *\n * const data = [\n * { name: \"Item 1\", value: 100 },\n * { name: \"Item 2\", value: 200 }\n * ];\n *\n * table(\"My Table\", data);\n */\nexport function table(title: string, data: unknown[]): void {\n if (!shouldPrint()) {\n return;\n }\n\n note(title);\n\n if (!data || data.length === 0) {\n note(\"No data to display\");\n return;\n }\n\n const columnKeys = Object.keys(data[0] as Record<string, unknown>);\n const table = new Table({\n columns: columnKeys.map((key) => ({\n name: key,\n title: whiteBright(camelCaseToWords(key)),\n alignment: \"left\",\n })),\n });\n // biome-ignore lint/suspicious/noExplicitAny: Data structure varies based on table content\n table.addRows(data as Array<Record<string, any>>);\n table.printTable();\n}\n"],"mappings":"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"}
|
package/dist/terminal.d.cts
CHANGED
|
@@ -127,7 +127,9 @@ declare function list(title: string, items: Array<string | string[]>): void;
|
|
|
127
127
|
* Warnings and errors are always displayed, even in quiet mode (when CLAUDECODE, REPL_ID, or AGENT env vars are set).
|
|
128
128
|
* When an Error object is provided with level "error", the stack trace is automatically included.
|
|
129
129
|
*
|
|
130
|
-
* @param message - The message to display as a note
|
|
130
|
+
* @param message - The message to display as a note. Can be either:
|
|
131
|
+
* - A string: Displayed directly with appropriate styling
|
|
132
|
+
* - An Error object: The error message is displayed, and for level "error", the stack trace is automatically included
|
|
131
133
|
* @param level - The note level: "info" (default), "warn" for warning styling, or "error" for error styling
|
|
132
134
|
* @example
|
|
133
135
|
* import { note } from "@settlemint/sdk-utils/terminal";
|
|
@@ -138,13 +140,14 @@ declare function list(title: string, items: Array<string | string[]>): void;
|
|
|
138
140
|
* // Display warning note
|
|
139
141
|
* note("Low disk space remaining", "warn");
|
|
140
142
|
*
|
|
141
|
-
* // Display error note
|
|
143
|
+
* // Display error note (string)
|
|
142
144
|
* note("Operation failed", "error");
|
|
143
145
|
*
|
|
144
|
-
* // Display error with stack trace automatically
|
|
146
|
+
* // Display error with stack trace automatically (Error object)
|
|
145
147
|
* try {
|
|
146
148
|
* // some operation
|
|
147
149
|
* } catch (error) {
|
|
150
|
+
* // If error is an Error object and level is "error", stack trace is included automatically
|
|
148
151
|
* note(error, "error");
|
|
149
152
|
* }
|
|
150
153
|
*/
|
package/dist/terminal.d.ts
CHANGED
|
@@ -127,7 +127,9 @@ declare function list(title: string, items: Array<string | string[]>): void;
|
|
|
127
127
|
* Warnings and errors are always displayed, even in quiet mode (when CLAUDECODE, REPL_ID, or AGENT env vars are set).
|
|
128
128
|
* When an Error object is provided with level "error", the stack trace is automatically included.
|
|
129
129
|
*
|
|
130
|
-
* @param message - The message to display as a note
|
|
130
|
+
* @param message - The message to display as a note. Can be either:
|
|
131
|
+
* - A string: Displayed directly with appropriate styling
|
|
132
|
+
* - An Error object: The error message is displayed, and for level "error", the stack trace is automatically included
|
|
131
133
|
* @param level - The note level: "info" (default), "warn" for warning styling, or "error" for error styling
|
|
132
134
|
* @example
|
|
133
135
|
* import { note } from "@settlemint/sdk-utils/terminal";
|
|
@@ -138,13 +140,14 @@ declare function list(title: string, items: Array<string | string[]>): void;
|
|
|
138
140
|
* // Display warning note
|
|
139
141
|
* note("Low disk space remaining", "warn");
|
|
140
142
|
*
|
|
141
|
-
* // Display error note
|
|
143
|
+
* // Display error note (string)
|
|
142
144
|
* note("Operation failed", "error");
|
|
143
145
|
*
|
|
144
|
-
* // Display error with stack trace automatically
|
|
146
|
+
* // Display error with stack trace automatically (Error object)
|
|
145
147
|
* try {
|
|
146
148
|
* // some operation
|
|
147
149
|
* } catch (error) {
|
|
150
|
+
* // If error is an Error object and level is "error", stack trace is included automatically
|
|
148
151
|
* note(error, "error");
|
|
149
152
|
* }
|
|
150
153
|
*/
|
package/dist/terminal.js
CHANGED
|
@@ -6,10 +6,18 @@ import { Table } from "console-table-printer";
|
|
|
6
6
|
|
|
7
7
|
//#region src/terminal/should-print.ts
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* Determines whether terminal output should be printed based on environment variables.
|
|
10
|
+
*
|
|
11
|
+
* **Environment Variable Precedence:**
|
|
12
|
+
* 1. `SETTLEMINT_DISABLE_TERMINAL="true"` - Completely disables all terminal output (highest priority)
|
|
13
|
+
* 2. `CLAUDECODE`, `REPL_ID`, or `AGENT` (any truthy value) - Enables quiet mode, suppressing info/debug/status messages
|
|
14
|
+
*
|
|
15
|
+
* **Quiet Mode Behavior:**
|
|
16
|
+
* When quiet mode is active (Claude Code environments), this function returns `false` to suppress
|
|
17
|
+
* informational output. However, warnings and errors are always displayed regardless of quiet mode,
|
|
18
|
+
* as they are handled separately in the `note()` function with level-based filtering.
|
|
19
|
+
*
|
|
20
|
+
* @returns `true` if terminal output should be printed, `false` if suppressed
|
|
13
21
|
*/
|
|
14
22
|
function shouldPrint() {
|
|
15
23
|
if (process.env.SETTLEMINT_DISABLE_TERMINAL === "true") {
|
|
@@ -221,13 +229,62 @@ const intro = (msg) => {
|
|
|
221
229
|
//#endregion
|
|
222
230
|
//#region src/terminal/note.ts
|
|
223
231
|
/**
|
|
232
|
+
* Applies color to a message if not already colored.
|
|
233
|
+
* @param msg - The message to colorize
|
|
234
|
+
* @param level - The severity level determining the color
|
|
235
|
+
* @returns Colorized message (yellow for warnings, red for errors, unchanged for info)
|
|
236
|
+
*/
|
|
237
|
+
function colorize(msg, level) {
|
|
238
|
+
if (msg.includes("\x1B[")) {
|
|
239
|
+
return msg;
|
|
240
|
+
}
|
|
241
|
+
if (level === "warn") {
|
|
242
|
+
return yellowBright(msg);
|
|
243
|
+
}
|
|
244
|
+
if (level === "error") {
|
|
245
|
+
return redBright(msg);
|
|
246
|
+
}
|
|
247
|
+
return msg;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Determines whether a message should be printed based on its level and quiet mode.
|
|
251
|
+
* @param level - The severity level of the message
|
|
252
|
+
* @returns true if the message should be printed, false otherwise
|
|
253
|
+
*/
|
|
254
|
+
function canPrint(level) {
|
|
255
|
+
if (level !== "info") {
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
return shouldPrint();
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Prepares a message for display by converting Error objects and masking tokens.
|
|
262
|
+
* @param value - The message string or Error object
|
|
263
|
+
* @param level - The severity level (stack traces are included for errors)
|
|
264
|
+
* @returns Masked message text, optionally with stack trace
|
|
265
|
+
*/
|
|
266
|
+
function prepareMessage(value, level) {
|
|
267
|
+
let text;
|
|
268
|
+
if (value instanceof Error) {
|
|
269
|
+
text = value.message;
|
|
270
|
+
if (level === "error" && value.stack) {
|
|
271
|
+
text = `${text}\n\n${value.stack}`;
|
|
272
|
+
}
|
|
273
|
+
} else {
|
|
274
|
+
text = value;
|
|
275
|
+
}
|
|
276
|
+
return maskTokens(text);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
224
279
|
* Displays a note message with optional warning or error level formatting.
|
|
225
280
|
* Regular notes are displayed in normal text, warnings are shown in yellow, and errors in red.
|
|
226
281
|
* Any sensitive tokens in the message are masked before display.
|
|
227
282
|
* Warnings and errors are always displayed, even in quiet mode (when CLAUDECODE, REPL_ID, or AGENT env vars are set).
|
|
228
283
|
* When an Error object is provided with level "error", the stack trace is automatically included.
|
|
229
284
|
*
|
|
230
|
-
* @param message - The message to display as a note
|
|
285
|
+
* @param message - The message to display as a note. Can be either:
|
|
286
|
+
* - A string: Displayed directly with appropriate styling
|
|
287
|
+
* - An Error object: The error message is displayed, and for level "error", the stack trace is automatically included
|
|
231
288
|
* @param level - The note level: "info" (default), "warn" for warning styling, or "error" for error styling
|
|
232
289
|
* @example
|
|
233
290
|
* import { note } from "@settlemint/sdk-utils/terminal";
|
|
@@ -238,46 +295,30 @@ const intro = (msg) => {
|
|
|
238
295
|
* // Display warning note
|
|
239
296
|
* note("Low disk space remaining", "warn");
|
|
240
297
|
*
|
|
241
|
-
* // Display error note
|
|
298
|
+
* // Display error note (string)
|
|
242
299
|
* note("Operation failed", "error");
|
|
243
300
|
*
|
|
244
|
-
* // Display error with stack trace automatically
|
|
301
|
+
* // Display error with stack trace automatically (Error object)
|
|
245
302
|
* try {
|
|
246
303
|
* // some operation
|
|
247
304
|
* } catch (error) {
|
|
305
|
+
* // If error is an Error object and level is "error", stack trace is included automatically
|
|
248
306
|
* note(error, "error");
|
|
249
307
|
* }
|
|
250
308
|
*/
|
|
251
309
|
const note = (message, level = "info") => {
|
|
252
|
-
|
|
253
|
-
let _error;
|
|
254
|
-
if (message instanceof Error) {
|
|
255
|
-
_error = message;
|
|
256
|
-
messageText = message.message;
|
|
257
|
-
if (level === "error" && message.stack) {
|
|
258
|
-
messageText = `${messageText}\n\n${message.stack}`;
|
|
259
|
-
}
|
|
260
|
-
} else {
|
|
261
|
-
messageText = message;
|
|
262
|
-
}
|
|
263
|
-
const maskedMessage = maskTokens(messageText);
|
|
264
|
-
const _isQuietMode = process.env.CLAUDECODE || process.env.REPL_ID || process.env.AGENT;
|
|
265
|
-
if (level === "warn" || level === "error") {
|
|
266
|
-
console.log("");
|
|
267
|
-
if (level === "warn") {
|
|
268
|
-
const coloredMessage = maskedMessage.includes("\x1B[") ? maskedMessage : yellowBright(maskedMessage);
|
|
269
|
-
console.warn(coloredMessage);
|
|
270
|
-
} else {
|
|
271
|
-
const coloredMessage = maskedMessage.includes("\x1B[") ? maskedMessage : redBright(maskedMessage);
|
|
272
|
-
console.error(coloredMessage);
|
|
273
|
-
}
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
if (!shouldPrint()) {
|
|
310
|
+
if (!canPrint(level)) {
|
|
277
311
|
return;
|
|
278
312
|
}
|
|
313
|
+
const msg = prepareMessage(message, level);
|
|
279
314
|
console.log("");
|
|
280
|
-
|
|
315
|
+
if (level === "warn") {
|
|
316
|
+
console.warn(colorize(msg, level));
|
|
317
|
+
} else if (level === "error") {
|
|
318
|
+
console.error(colorize(msg, level));
|
|
319
|
+
} else {
|
|
320
|
+
console.log(msg);
|
|
321
|
+
}
|
|
281
322
|
};
|
|
282
323
|
|
|
283
324
|
//#endregion
|
|
@@ -373,8 +414,7 @@ var SpinnerError = class extends Error {
|
|
|
373
414
|
const spinner = async (options) => {
|
|
374
415
|
const handleError = (error) => {
|
|
375
416
|
note(error, "error");
|
|
376
|
-
|
|
377
|
-
throw new SpinnerError(errorMessage, error);
|
|
417
|
+
throw new SpinnerError(error.message, error);
|
|
378
418
|
};
|
|
379
419
|
if (isInCi || !shouldPrint()) {
|
|
380
420
|
try {
|
package/dist/terminal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.js","names":["code: number","output: string[]","stdoutOutput: string[]","stderrOutput: string[]","messageText: string","_error: Error | undefined","items","originalError: Error","spinner","table"],"sources":["../src/terminal/should-print.ts","../src/terminal/ascii.ts","../src/logging/mask-tokens.ts","../src/terminal/cancel.ts","../src/terminal/execute-command.ts","../src/terminal/intro.ts","../src/terminal/note.ts","../src/terminal/list.ts","../src/terminal/outro.ts","../src/terminal/spinner.ts","../src/string.ts","../src/terminal/table.ts"],"sourcesContent":["/**\n * Returns true if the terminal should print, false otherwise.\n * When CLAUDECODE, REPL_ID, or AGENT env vars are set, suppresses info/debug output\n * but warnings and errors will still be displayed.\n * @returns true if the terminal should print, false otherwise.\n */\nexport function shouldPrint() {\n if (process.env.SETTLEMINT_DISABLE_TERMINAL === \"true\") {\n return false;\n }\n // In quiet mode (Claude Code), suppress info/debug/status messages\n // Warnings and errors will still be displayed via note() with appropriate levels\n if (process.env.CLAUDECODE || process.env.REPL_ID || process.env.AGENT) {\n return false;\n }\n return true;\n}\n","import { magentaBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Prints the SettleMint ASCII art logo to the console in magenta color.\n * Used for CLI branding and visual identification.\n *\n * @example\n * import { ascii } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Prints the SettleMint logo\n * ascii();\n */\nexport const ascii = (): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\n magentaBright(`\n _________ __ __ .__ _____ .__ __\n / _____/ _____/ |__/ |_| | ____ / \\\\ |__| _____/ |_\n \\\\_____ \\\\_/ __ \\\\ __\\\\ __\\\\ | _/ __ \\\\ / \\\\ / \\\\| |/ \\\\ __\\\\\n / \\\\ ___/| | | | | |_\\\\ ___// Y \\\\ | | \\\\ |\n/_________/\\\\_____>__| |__| |____/\\\\_____>____|____/__|___|__/__|\n`),\n );\n};\n","/**\n * Masks sensitive SettleMint tokens in output text by replacing them with asterisks.\n * Handles personal access tokens (PAT), application access tokens (AAT), and service account tokens (SAT).\n *\n * @param output - The text string that may contain sensitive tokens\n * @returns The text with any sensitive tokens masked with asterisks\n * @example\n * import { maskTokens } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Masks a token in text\n * const masked = maskTokens(\"Token: sm_pat_****\"); // \"Token: ***\"\n */\nexport const maskTokens = (output: string): string => {\n return output.replace(/sm_(pat|aat|sat)_[0-9a-zA-Z]+/g, \"***\");\n};\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { inverse, redBright } from \"yoctocolors\";\n\n/**\n * Error class used to indicate that the operation was cancelled.\n * This error is used to signal that the operation should be aborted.\n */\nexport class CancelError extends Error {}\n\n/**\n * Displays an error message in red inverse text and throws a CancelError.\n * Used to terminate execution with a visible error message.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The error message to display\n * @returns never - Function does not return as it throws an error\n * @example\n * import { cancel } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Exits process with error message\n * cancel(\"An error occurred\");\n */\nexport const cancel = (msg: string): never => {\n console.log(\"\");\n console.log(inverse(redBright(maskTokens(msg))));\n console.log(\"\");\n throw new CancelError(msg);\n};\n","import { type SpawnOptionsWithoutStdio, spawn } from \"node:child_process\";\nimport { maskTokens } from \"../logging/mask-tokens.js\";\n\n/**\n * Options for executing a command, extending SpawnOptionsWithoutStdio\n */\nexport interface ExecuteCommandOptions extends SpawnOptionsWithoutStdio {\n /** Whether to suppress output to stdout/stderr */\n silent?: boolean;\n}\n\n/**\n * Error class for command execution errors\n * @extends Error\n */\nexport class CommandError extends Error {\n /**\n * Constructs a new CommandError\n * @param message - The error message\n * @param code - The exit code of the command\n * @param output - The output of the command\n */\n constructor(\n message: string,\n public readonly code: number,\n public readonly output: string[],\n ) {\n super(message);\n }\n}\n\n/**\n * Checks if we're in quiet mode (Claude Code environment)\n */\nfunction isQuietMode(): boolean {\n return !!(process.env.CLAUDECODE || process.env.REPL_ID || process.env.AGENT);\n}\n\n/**\n * Executes a command with the given arguments in a child process.\n * Pipes stdin to the child process and captures stdout/stderr output.\n * Masks any sensitive tokens in the output before displaying or returning.\n * In quiet mode (when CLAUDECODE, REPL_ID, or AGENT env vars are set),\n * output is suppressed unless the command errors out.\n *\n * @param command - The command to execute\n * @param args - Array of arguments to pass to the command\n * @param options - Options for customizing command execution\n * @returns Array of output strings from stdout and stderr\n * @throws {CommandError} If the process fails to start or exits with non-zero code\n * @example\n * import { executeCommand } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Execute git clone\n * await executeCommand(\"git\", [\"clone\", \"repo-url\"]);\n *\n * // Execute silently\n * await executeCommand(\"npm\", [\"install\"], { silent: true });\n */\nexport async function executeCommand(\n command: string,\n args: string[],\n options?: ExecuteCommandOptions,\n): Promise<string[]> {\n const { silent, ...spawnOptions } = options ?? {};\n const quietMode = isQuietMode();\n // In quiet mode, suppress output unless explicitly overridden with silent: false\n const shouldSuppressOutput = quietMode ? silent !== false : !!silent;\n\n const child = spawn(command, args, { ...spawnOptions, env: { ...process.env, ...options?.env } });\n process.stdin.pipe(child.stdin);\n const output: string[] = [];\n const stdoutOutput: string[] = [];\n const stderrOutput: string[] = [];\n\n return new Promise((resolve, reject) => {\n child.stdout.on(\"data\", (data: Buffer | string) => {\n const maskedData = maskTokens(data.toString());\n if (!shouldSuppressOutput) {\n process.stdout.write(maskedData);\n }\n output.push(maskedData);\n stdoutOutput.push(maskedData);\n });\n child.stderr.on(\"data\", (data: Buffer | string) => {\n const maskedData = maskTokens(data.toString());\n if (!shouldSuppressOutput) {\n process.stderr.write(maskedData);\n }\n output.push(maskedData);\n stderrOutput.push(maskedData);\n });\n\n const showErrorOutput = () => {\n // In quiet mode, show output on error\n if (quietMode && shouldSuppressOutput && output.length > 0) {\n // Write stdout to stdout and stderr to stderr\n if (stdoutOutput.length > 0) {\n process.stdout.write(stdoutOutput.join(\"\"));\n }\n if (stderrOutput.length > 0) {\n process.stderr.write(stderrOutput.join(\"\"));\n }\n }\n };\n\n child.on(\"error\", (err) => {\n process.stdin.unpipe(child.stdin);\n showErrorOutput();\n reject(new CommandError(err.message, \"code\" in err && typeof err.code === \"number\" ? err.code : 1, output));\n });\n child.on(\"close\", (code) => {\n process.stdin.unpipe(child.stdin);\n if (code === 0 || code === null || code === 143) {\n resolve(output);\n return;\n }\n // In quiet mode, show output on error\n showErrorOutput();\n reject(new CommandError(`Command \"${command}\" exited with code ${code}`, code, output));\n });\n });\n}\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { magentaBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Displays an introductory message in magenta text with padding.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The message to display as introduction\n * @example\n * import { intro } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display intro message\n * intro(\"Starting deployment...\");\n */\nexport const intro = (msg: string): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\"\");\n console.log(magentaBright(maskTokens(msg)));\n console.log(\"\");\n};\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { redBright, yellowBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Displays a note message with optional warning or error level formatting.\n * Regular notes are displayed in normal text, warnings are shown in yellow, and errors in red.\n * Any sensitive tokens in the message are masked before display.\n * Warnings and errors are always displayed, even in quiet mode (when CLAUDECODE, REPL_ID, or AGENT env vars are set).\n * When an Error object is provided with level \"error\", the stack trace is automatically included.\n *\n * @param message - The message to display as a note, or an Error object\n * @param level - The note level: \"info\" (default), \"warn\" for warning styling, or \"error\" for error styling\n * @example\n * import { note } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display info note\n * note(\"Operation completed successfully\");\n *\n * // Display warning note\n * note(\"Low disk space remaining\", \"warn\");\n *\n * // Display error note\n * note(\"Operation failed\", \"error\");\n *\n * // Display error with stack trace automatically\n * try {\n * // some operation\n * } catch (error) {\n * note(error, \"error\");\n * }\n */\nexport const note = (message: string | Error, level: \"info\" | \"warn\" | \"error\" = \"info\"): void => {\n let messageText: string;\n let _error: Error | undefined;\n\n if (message instanceof Error) {\n _error = message;\n messageText = message.message;\n // For errors, automatically include stack trace\n if (level === \"error\" && message.stack) {\n messageText = `${messageText}\\n\\n${message.stack}`;\n }\n } else {\n messageText = message;\n }\n\n const maskedMessage = maskTokens(messageText);\n const _isQuietMode = process.env.CLAUDECODE || process.env.REPL_ID || process.env.AGENT;\n\n // Always print warnings and errors, even in quiet mode\n if (level === \"warn\" || level === \"error\") {\n console.log(\"\");\n if (level === \"warn\") {\n // Apply yellow color if not already colored (check if message contains ANSI codes)\n const coloredMessage = maskedMessage.includes(\"\\u001b[\") ? maskedMessage : yellowBright(maskedMessage);\n console.warn(coloredMessage);\n } else {\n // Apply red color if not already colored (check if message contains ANSI codes)\n const coloredMessage = maskedMessage.includes(\"\\u001b[\") ? maskedMessage : redBright(maskedMessage);\n console.error(coloredMessage);\n }\n return;\n }\n\n // For info messages, check if we should print\n if (!shouldPrint()) {\n return;\n }\n\n console.log(\"\");\n console.log(maskedMessage);\n};\n","import { note } from \"./note.js\";\n\n/**\n * Displays a list of items in a formatted manner, supporting nested items.\n *\n * @param title - The title of the list\n * @param items - The items to display, can be strings or arrays for nested items\n * @returns The formatted list\n * @example\n * import { list } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Simple list\n * list(\"Use cases\", [\"use case 1\", \"use case 2\", \"use case 3\"]);\n *\n * // Nested list\n * list(\"Providers\", [\n * \"AWS\",\n * [\"us-east-1\", \"eu-west-1\"],\n * \"Azure\",\n * [\"eastus\", \"westeurope\"]\n * ]);\n */\nexport function list(title: string, items: Array<string | string[]>) {\n const formatItems = (items: Array<string | string[]>): string => {\n return items\n .map((item) => {\n if (Array.isArray(item)) {\n return item.map((subItem) => ` • ${subItem}`).join(\"\\n\");\n }\n return ` • ${item}`;\n })\n .join(\"\\n\");\n };\n\n return note(`${title}:\\n\\n${formatItems(items)}`);\n}\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { shouldPrint } from \"@/terminal/should-print.js\";\nimport { greenBright, inverse } from \"yoctocolors\";\n\n/**\n * Displays a closing message in green inverted text with padding.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The message to display as conclusion\n * @example\n * import { outro } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display outro message\n * outro(\"Deployment completed successfully!\");\n */\nexport const outro = (msg: string): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\"\");\n console.log(inverse(greenBright(maskTokens(msg))));\n console.log(\"\");\n};\n","import isInCi from \"is-in-ci\";\nimport yoctoSpinner, { type Spinner } from \"yocto-spinner\";\nimport { redBright } from \"yoctocolors\";\nimport { maskTokens } from \"../logging/mask-tokens.js\";\nimport { note } from \"./note.js\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Error class used to indicate that the spinner operation failed.\n * This error is used to signal that the operation should be aborted.\n */\nexport class SpinnerError extends Error {\n constructor(\n message: string,\n public readonly originalError: Error,\n ) {\n super(message);\n this.name = \"SpinnerError\";\n }\n}\n\n/**\n * Options for configuring the spinner behavior\n */\nexport interface SpinnerOptions<R> {\n /** Message to display when spinner starts */\n startMessage: string;\n /** Async task to execute while spinner is active */\n task: (spinner?: Spinner) => Promise<R>;\n /** Message to display when spinner completes successfully */\n stopMessage: string;\n}\n\n/**\n * Displays a loading spinner while executing an async task.\n * Shows progress with start/stop messages and handles errors.\n * Spinner is disabled in CI environments.\n *\n * @param options - Configuration options for the spinner\n * @returns The result from the executed task\n * @throws Will exit process with code 1 if task fails\n * @example\n * import { spinner } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Show spinner during async task\n * const result = await spinner({\n * startMessage: \"Deploying...\",\n * task: async () => {\n * // Async work here\n * return \"success\";\n * },\n * stopMessage: \"Deployed successfully!\"\n * });\n */\nexport const spinner = async <R>(options: SpinnerOptions<R>): Promise<R> => {\n const handleError = (error: Error) => {\n note(error, \"error\");\n const errorMessage = maskTokens(error.message);\n throw new SpinnerError(errorMessage, error);\n };\n if (isInCi || !shouldPrint()) {\n try {\n return await options.task();\n } catch (err) {\n return handleError(err as Error);\n }\n }\n const spinner = yoctoSpinner({ stream: process.stdout }).start(options.startMessage);\n try {\n const result = await options.task(spinner);\n spinner.success(options.stopMessage);\n // Ensure spinner success message renders before proceeding to avoid\n // terminal output overlap issues with subsequent messages\n await new Promise((resolve) => process.nextTick(resolve));\n return result;\n } catch (err) {\n spinner.error(redBright(`${options.startMessage} --> Error!`));\n return handleError(err as Error);\n }\n};\n","/**\n * Capitalizes the first letter of a string.\n *\n * @param val - The string to capitalize\n * @returns The input string with its first letter capitalized\n *\n * @example\n * import { capitalizeFirstLetter } from \"@settlemint/sdk-utils\";\n *\n * const capitalized = capitalizeFirstLetter(\"hello\");\n * // Returns: \"Hello\"\n */\nexport function capitalizeFirstLetter(val: string) {\n return String(val).charAt(0).toUpperCase() + String(val).slice(1);\n}\n\n/**\n * Converts a camelCase string to a human-readable string.\n *\n * @param s - The camelCase string to convert\n * @returns The human-readable string\n *\n * @example\n * import { camelCaseToWords } from \"@settlemint/sdk-utils\";\n *\n * const words = camelCaseToWords(\"camelCaseString\");\n * // Returns: \"Camel Case String\"\n */\nexport function camelCaseToWords(s: string) {\n const result = s.replace(/([a-z])([A-Z])/g, \"$1 $2\");\n const withSpaces = result.replace(/([A-Z])([a-z])/g, \" $1$2\");\n const capitalized = capitalizeFirstLetter(withSpaces);\n return capitalized.replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Replaces underscores and hyphens with spaces.\n *\n * @param s - The string to replace underscores and hyphens with spaces\n * @returns The input string with underscores and hyphens replaced with spaces\n *\n * @example\n * import { replaceUnderscoresAndHyphensWithSpaces } from \"@settlemint/sdk-utils\";\n *\n * const result = replaceUnderscoresAndHyphensWithSpaces(\"Already_Spaced-Second\");\n * // Returns: \"Already Spaced Second\"\n */\nexport function replaceUnderscoresAndHyphensWithSpaces(s: string) {\n return s.replace(/[-_]/g, \" \");\n}\n\n/**\n * Truncates a string to a maximum length and appends \"...\" if it is longer.\n *\n * @param value - The string to truncate\n * @param maxLength - The maximum length of the string\n * @returns The truncated string or the original string if it is shorter than the maximum length\n *\n * @example\n * import { truncate } from \"@settlemint/sdk-utils\";\n *\n * const truncated = truncate(\"Hello, world!\", 10);\n * // Returns: \"Hello, wor...\"\n */\nexport function truncate(value: string, maxLength: number) {\n if (value.length <= maxLength) {\n return value;\n }\n return `${value.slice(0, maxLength)}...`;\n}\n","import { Table } from \"console-table-printer\";\nimport { whiteBright } from \"yoctocolors\";\nimport { camelCaseToWords } from \"@/string.js\";\nimport { note } from \"./note.js\";\nimport { shouldPrint } from \"./should-print.js\";\n/**\n * Displays data in a formatted table in the terminal.\n *\n * @param title - Title to display above the table\n * @param data - Array of objects to display in table format\n * @example\n * import { table } from \"@settlemint/sdk-utils/terminal\";\n *\n * const data = [\n * { name: \"Item 1\", value: 100 },\n * { name: \"Item 2\", value: 200 }\n * ];\n *\n * table(\"My Table\", data);\n */\nexport function table(title: string, data: unknown[]): void {\n if (!shouldPrint()) {\n return;\n }\n\n note(title);\n\n if (!data || data.length === 0) {\n note(\"No data to display\");\n return;\n }\n\n const columnKeys = Object.keys(data[0] as Record<string, unknown>);\n const table = new Table({\n columns: columnKeys.map((key) => ({\n name: key,\n title: whiteBright(camelCaseToWords(key)),\n alignment: \"left\",\n })),\n });\n // biome-ignore lint/suspicious/noExplicitAny: Data structure varies based on table content\n table.addRows(data as Array<Record<string, any>>);\n table.printTable();\n}\n"],"mappings":";;;;;;;;;;;;;AAMA,SAAgB,cAAc;AAC5B,KAAI,QAAQ,IAAI,gCAAgC,QAAQ;AACtD,SAAO;;AAIT,KAAI,QAAQ,IAAI,cAAc,QAAQ,IAAI,WAAW,QAAQ,IAAI,OAAO;AACtE,SAAO;;AAET,QAAO;;;;;;;;;;;;;;;ACFT,MAAa,cAAoB;AAC/B,KAAI,CAAC,aAAa,EAAE;AAClB;;AAEF,SAAQ,IACN,cAAc;;;;;;EAMhB,CACC;;;;;;;;;;;;;;;;;ACbH,MAAa,cAAc,WAA2B;AACpD,QAAO,OAAO,QAAQ,kCAAkC,MAAM;;;;;;;;;ACNhE,IAAa,cAAb,cAAiC,MAAM;;;;;;;;;;;;;;AAevC,MAAa,UAAU,QAAuB;AAC5C,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,QAAQ,UAAU,WAAW,IAAI,CAAC,CAAC,CAAC;AAChD,SAAQ,IAAI,GAAG;AACf,OAAM,IAAI,YAAY,IAAI;;;;;;;;;ACX5B,IAAa,eAAb,cAAkC,MAAM;;;;;;;CAOtC,YACE,SACA,AAAgBA,MAChB,AAAgBC,QAChB;AACA,QAAM,QAAQ;EAHE;EACA;;;;;;AASpB,SAAS,cAAuB;AAC9B,QAAO,CAAC,EAAE,QAAQ,IAAI,cAAc,QAAQ,IAAI,WAAW,QAAQ,IAAI;;;;;;;;;;;;;;;;;;;;;;;AAwBzE,eAAsB,eACpB,SACA,MACA,SACmB;CACnB,MAAM,EAAE,OAAQ,GAAG,iBAAiB,WAAW,EAAE;CACjD,MAAM,YAAY,aAAa;CAE/B,MAAM,uBAAuB,YAAY,WAAW,QAAQ,CAAC,CAAC;CAE9D,MAAM,QAAQ,MAAM,SAAS,MAAM;EAAE,GAAG;EAAc,KAAK;GAAE,GAAG,QAAQ;GAAK,GAAG,SAAS;GAAK;EAAE,CAAC;AACjG,SAAQ,MAAM,KAAK,MAAM,MAAM;CAC/B,MAAMA,SAAmB,EAAE;CAC3B,MAAMC,eAAyB,EAAE;CACjC,MAAMC,eAAyB,EAAE;AAEjC,QAAO,IAAI,SAAS,SAAS,WAAW;AACtC,QAAM,OAAO,GAAG,SAAS,SAA0B;GACjD,MAAM,aAAa,WAAW,KAAK,UAAU,CAAC;AAC9C,OAAI,CAAC,sBAAsB;AACzB,YAAQ,OAAO,MAAM,WAAW;;AAElC,UAAO,KAAK,WAAW;AACvB,gBAAa,KAAK,WAAW;IAC7B;AACF,QAAM,OAAO,GAAG,SAAS,SAA0B;GACjD,MAAM,aAAa,WAAW,KAAK,UAAU,CAAC;AAC9C,OAAI,CAAC,sBAAsB;AACzB,YAAQ,OAAO,MAAM,WAAW;;AAElC,UAAO,KAAK,WAAW;AACvB,gBAAa,KAAK,WAAW;IAC7B;EAEF,MAAM,wBAAwB;AAE5B,OAAI,aAAa,wBAAwB,OAAO,SAAS,GAAG;AAE1D,QAAI,aAAa,SAAS,GAAG;AAC3B,aAAQ,OAAO,MAAM,aAAa,KAAK,GAAG,CAAC;;AAE7C,QAAI,aAAa,SAAS,GAAG;AAC3B,aAAQ,OAAO,MAAM,aAAa,KAAK,GAAG,CAAC;;;;AAKjD,QAAM,GAAG,UAAU,QAAQ;AACzB,WAAQ,MAAM,OAAO,MAAM,MAAM;AACjC,oBAAiB;AACjB,UAAO,IAAI,aAAa,IAAI,SAAS,UAAU,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,GAAG,OAAO,CAAC;IAC3G;AACF,QAAM,GAAG,UAAU,SAAS;AAC1B,WAAQ,MAAM,OAAO,MAAM,MAAM;AACjC,OAAI,SAAS,KAAK,SAAS,QAAQ,SAAS,KAAK;AAC/C,YAAQ,OAAO;AACf;;AAGF,oBAAiB;AACjB,UAAO,IAAI,aAAa,YAAY,QAAQ,qBAAqB,QAAQ,MAAM,OAAO,CAAC;IACvF;GACF;;;;;;;;;;;;;;;;AC1GJ,MAAa,SAAS,QAAsB;AAC1C,KAAI,CAAC,aAAa,EAAE;AAClB;;AAEF,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,cAAc,WAAW,IAAI,CAAC,CAAC;AAC3C,SAAQ,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACWjB,MAAa,QAAQ,SAAyB,QAAmC,WAAiB;CAChG,IAAIC;CACJ,IAAIC;AAEJ,KAAI,mBAAmB,OAAO;AAC5B,WAAS;AACT,gBAAc,QAAQ;AAEtB,MAAI,UAAU,WAAW,QAAQ,OAAO;AACtC,iBAAc,GAAG,YAAY,MAAM,QAAQ;;QAExC;AACL,gBAAc;;CAGhB,MAAM,gBAAgB,WAAW,YAAY;CAC7C,MAAM,eAAe,QAAQ,IAAI,cAAc,QAAQ,IAAI,WAAW,QAAQ,IAAI;AAGlF,KAAI,UAAU,UAAU,UAAU,SAAS;AACzC,UAAQ,IAAI,GAAG;AACf,MAAI,UAAU,QAAQ;GAEpB,MAAM,iBAAiB,cAAc,SAAS,QAAU,GAAG,gBAAgB,aAAa,cAAc;AACtG,WAAQ,KAAK,eAAe;SACvB;GAEL,MAAM,iBAAiB,cAAc,SAAS,QAAU,GAAG,gBAAgB,UAAU,cAAc;AACnG,WAAQ,MAAM,eAAe;;AAE/B;;AAIF,KAAI,CAAC,aAAa,EAAE;AAClB;;AAGF,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;ACjD5B,SAAgB,KAAK,OAAe,OAAiC;CACnE,MAAM,eAAe,YAA4C;AAC/D,SAAOC,QACJ,KAAK,SAAS;AACb,OAAI,MAAM,QAAQ,KAAK,EAAE;AACvB,WAAO,KAAK,KAAK,YAAY,SAAS,UAAU,CAAC,KAAK,KAAK;;AAE7D,UAAO,OAAO;IACd,CACD,KAAK,KAAK;;AAGf,QAAO,KAAK,GAAG,MAAM,OAAO,YAAY,MAAM,GAAG;;;;;;;;;;;;;;;;ACnBnD,MAAa,SAAS,QAAsB;AAC1C,KAAI,CAAC,aAAa,EAAE;AAClB;;AAEF,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,QAAQ,YAAY,WAAW,IAAI,CAAC,CAAC,CAAC;AAClD,SAAQ,IAAI,GAAG;;;;;;;;;ACVjB,IAAa,eAAb,cAAkC,MAAM;CACtC,YACE,SACA,AAAgBC,eAChB;AACA,QAAM,QAAQ;EAFE;AAGhB,OAAK,OAAO;;;;;;;;;;;;;;;;;;;;;;;;AAqChB,MAAa,UAAU,OAAU,YAA2C;CAC1E,MAAM,eAAe,UAAiB;AACpC,OAAK,OAAO,QAAQ;EACpB,MAAM,eAAe,WAAW,MAAM,QAAQ;AAC9C,QAAM,IAAI,aAAa,cAAc,MAAM;;AAE7C,KAAI,UAAU,CAAC,aAAa,EAAE;AAC5B,MAAI;AACF,UAAO,MAAM,QAAQ,MAAM;WACpB,KAAK;AACZ,UAAO,YAAY,IAAa;;;CAGpC,MAAMC,YAAU,aAAa,EAAE,QAAQ,QAAQ,QAAQ,CAAC,CAAC,MAAM,QAAQ,aAAa;AACpF,KAAI;EACF,MAAM,SAAS,MAAM,QAAQ,KAAKA,UAAQ;AAC1C,YAAQ,QAAQ,QAAQ,YAAY;AAGpC,QAAM,IAAI,SAAS,YAAY,QAAQ,SAAS,QAAQ,CAAC;AACzD,SAAO;UACA,KAAK;AACZ,YAAQ,MAAM,UAAU,GAAG,QAAQ,aAAa,aAAa,CAAC;AAC9D,SAAO,YAAY,IAAa;;;;;;;;;;;;;;;;;;ACjEpC,SAAgB,sBAAsB,KAAa;AACjD,QAAO,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,aAAa,GAAG,OAAO,IAAI,CAAC,MAAM,EAAE;;;;;;;;;;;;;;AAenE,SAAgB,iBAAiB,GAAW;CAC1C,MAAM,SAAS,EAAE,QAAQ,mBAAmB,QAAQ;CACpD,MAAM,aAAa,OAAO,QAAQ,mBAAmB,QAAQ;CAC7D,MAAM,cAAc,sBAAsB,WAAW;AACrD,QAAO,YAAY,QAAQ,QAAQ,IAAI,CAAC,MAAM;;;;;;;;;;;;;;AAehD,SAAgB,uCAAuC,GAAW;AAChE,QAAO,EAAE,QAAQ,SAAS,IAAI;;;;;;;;;;;;;;;AAgBhC,SAAgB,SAAS,OAAe,WAAmB;AACzD,KAAI,MAAM,UAAU,WAAW;AAC7B,SAAO;;AAET,QAAO,GAAG,MAAM,MAAM,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;AChDtC,SAAgB,MAAM,OAAe,MAAuB;AAC1D,KAAI,CAAC,aAAa,EAAE;AAClB;;AAGF,MAAK,MAAM;AAEX,KAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,OAAK,qBAAqB;AAC1B;;CAGF,MAAM,aAAa,OAAO,KAAK,KAAK,GAA8B;CAClE,MAAMC,UAAQ,IAAI,MAAM,EACtB,SAAS,WAAW,KAAK,SAAS;EAChC,MAAM;EACN,OAAO,YAAY,iBAAiB,IAAI,CAAC;EACzC,WAAW;EACZ,EAAE,EACJ,CAAC;AAEF,SAAM,QAAQ,KAAmC;AACjD,SAAM,YAAY"}
|
|
1
|
+
{"version":3,"file":"terminal.js","names":["code: number","output: string[]","stdoutOutput: string[]","stderrOutput: string[]","text: string","items","originalError: Error","spinner","table"],"sources":["../src/terminal/should-print.ts","../src/terminal/ascii.ts","../src/logging/mask-tokens.ts","../src/terminal/cancel.ts","../src/terminal/execute-command.ts","../src/terminal/intro.ts","../src/terminal/note.ts","../src/terminal/list.ts","../src/terminal/outro.ts","../src/terminal/spinner.ts","../src/string.ts","../src/terminal/table.ts"],"sourcesContent":["/**\n * Determines whether terminal output should be printed based on environment variables.\n *\n * **Environment Variable Precedence:**\n * 1. `SETTLEMINT_DISABLE_TERMINAL=\"true\"` - Completely disables all terminal output (highest priority)\n * 2. `CLAUDECODE`, `REPL_ID`, or `AGENT` (any truthy value) - Enables quiet mode, suppressing info/debug/status messages\n *\n * **Quiet Mode Behavior:**\n * When quiet mode is active (Claude Code environments), this function returns `false` to suppress\n * informational output. However, warnings and errors are always displayed regardless of quiet mode,\n * as they are handled separately in the `note()` function with level-based filtering.\n *\n * @returns `true` if terminal output should be printed, `false` if suppressed\n */\nexport function shouldPrint(): boolean {\n if (process.env.SETTLEMINT_DISABLE_TERMINAL === \"true\") {\n return false;\n }\n // In quiet mode (Claude Code), suppress info/debug/status messages\n // Warnings and errors will still be displayed via note() with appropriate levels\n if (process.env.CLAUDECODE || process.env.REPL_ID || process.env.AGENT) {\n return false;\n }\n return true;\n}\n","import { magentaBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Prints the SettleMint ASCII art logo to the console in magenta color.\n * Used for CLI branding and visual identification.\n *\n * @example\n * import { ascii } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Prints the SettleMint logo\n * ascii();\n */\nexport const ascii = (): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\n magentaBright(`\n _________ __ __ .__ _____ .__ __\n / _____/ _____/ |__/ |_| | ____ / \\\\ |__| _____/ |_\n \\\\_____ \\\\_/ __ \\\\ __\\\\ __\\\\ | _/ __ \\\\ / \\\\ / \\\\| |/ \\\\ __\\\\\n / \\\\ ___/| | | | | |_\\\\ ___// Y \\\\ | | \\\\ |\n/_________/\\\\_____>__| |__| |____/\\\\_____>____|____/__|___|__/__|\n`),\n );\n};\n","/**\n * Masks sensitive SettleMint tokens in output text by replacing them with asterisks.\n * Handles personal access tokens (PAT), application access tokens (AAT), and service account tokens (SAT).\n *\n * @param output - The text string that may contain sensitive tokens\n * @returns The text with any sensitive tokens masked with asterisks\n * @example\n * import { maskTokens } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Masks a token in text\n * const masked = maskTokens(\"Token: sm_pat_****\"); // \"Token: ***\"\n */\nexport const maskTokens = (output: string): string => {\n return output.replace(/sm_(pat|aat|sat)_[0-9a-zA-Z]+/g, \"***\");\n};\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { inverse, redBright } from \"yoctocolors\";\n\n/**\n * Error class used to indicate that the operation was cancelled.\n * This error is used to signal that the operation should be aborted.\n */\nexport class CancelError extends Error {}\n\n/**\n * Displays an error message in red inverse text and throws a CancelError.\n * Used to terminate execution with a visible error message.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The error message to display\n * @returns never - Function does not return as it throws an error\n * @example\n * import { cancel } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Exits process with error message\n * cancel(\"An error occurred\");\n */\nexport const cancel = (msg: string): never => {\n console.log(\"\");\n console.log(inverse(redBright(maskTokens(msg))));\n console.log(\"\");\n throw new CancelError(msg);\n};\n","import { type SpawnOptionsWithoutStdio, spawn } from \"node:child_process\";\nimport { maskTokens } from \"../logging/mask-tokens.js\";\n\n/**\n * Options for executing a command, extending SpawnOptionsWithoutStdio\n */\nexport interface ExecuteCommandOptions extends SpawnOptionsWithoutStdio {\n /** Whether to suppress output to stdout/stderr */\n silent?: boolean;\n}\n\n/**\n * Error class for command execution errors\n * @extends Error\n */\nexport class CommandError extends Error {\n /**\n * Constructs a new CommandError\n * @param message - The error message\n * @param code - The exit code of the command\n * @param output - The output of the command\n */\n constructor(\n message: string,\n public readonly code: number,\n public readonly output: string[],\n ) {\n super(message);\n }\n}\n\n/**\n * Checks if we're in quiet mode (Claude Code environment)\n */\nfunction isQuietMode(): boolean {\n return !!(process.env.CLAUDECODE || process.env.REPL_ID || process.env.AGENT);\n}\n\n/**\n * Executes a command with the given arguments in a child process.\n * Pipes stdin to the child process and captures stdout/stderr output.\n * Masks any sensitive tokens in the output before displaying or returning.\n * In quiet mode (when CLAUDECODE, REPL_ID, or AGENT env vars are set),\n * output is suppressed unless the command errors out.\n *\n * @param command - The command to execute\n * @param args - Array of arguments to pass to the command\n * @param options - Options for customizing command execution\n * @returns Array of output strings from stdout and stderr\n * @throws {CommandError} If the process fails to start or exits with non-zero code\n * @example\n * import { executeCommand } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Execute git clone\n * await executeCommand(\"git\", [\"clone\", \"repo-url\"]);\n *\n * // Execute silently\n * await executeCommand(\"npm\", [\"install\"], { silent: true });\n */\nexport async function executeCommand(\n command: string,\n args: string[],\n options?: ExecuteCommandOptions,\n): Promise<string[]> {\n const { silent, ...spawnOptions } = options ?? {};\n const quietMode = isQuietMode();\n // In quiet mode, suppress output unless explicitly overridden with silent: false\n const shouldSuppressOutput = quietMode ? silent !== false : !!silent;\n\n const child = spawn(command, args, { ...spawnOptions, env: { ...process.env, ...options?.env } });\n process.stdin.pipe(child.stdin);\n const output: string[] = [];\n const stdoutOutput: string[] = [];\n const stderrOutput: string[] = [];\n\n return new Promise((resolve, reject) => {\n child.stdout.on(\"data\", (data: Buffer | string) => {\n const maskedData = maskTokens(data.toString());\n if (!shouldSuppressOutput) {\n process.stdout.write(maskedData);\n }\n output.push(maskedData);\n stdoutOutput.push(maskedData);\n });\n child.stderr.on(\"data\", (data: Buffer | string) => {\n const maskedData = maskTokens(data.toString());\n if (!shouldSuppressOutput) {\n process.stderr.write(maskedData);\n }\n output.push(maskedData);\n stderrOutput.push(maskedData);\n });\n\n const showErrorOutput = () => {\n // In quiet mode, show output on error\n if (quietMode && shouldSuppressOutput && output.length > 0) {\n // Write stdout to stdout and stderr to stderr\n if (stdoutOutput.length > 0) {\n process.stdout.write(stdoutOutput.join(\"\"));\n }\n if (stderrOutput.length > 0) {\n process.stderr.write(stderrOutput.join(\"\"));\n }\n }\n };\n\n child.on(\"error\", (err) => {\n process.stdin.unpipe(child.stdin);\n showErrorOutput();\n reject(new CommandError(err.message, \"code\" in err && typeof err.code === \"number\" ? err.code : 1, output));\n });\n child.on(\"close\", (code) => {\n process.stdin.unpipe(child.stdin);\n if (code === 0 || code === null || code === 143) {\n resolve(output);\n return;\n }\n // In quiet mode, show output on error\n showErrorOutput();\n reject(new CommandError(`Command \"${command}\" exited with code ${code}`, code, output));\n });\n });\n}\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { magentaBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Displays an introductory message in magenta text with padding.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The message to display as introduction\n * @example\n * import { intro } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display intro message\n * intro(\"Starting deployment...\");\n */\nexport const intro = (msg: string): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\"\");\n console.log(magentaBright(maskTokens(msg)));\n console.log(\"\");\n};\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { redBright, yellowBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Applies color to a message if not already colored.\n * @param msg - The message to colorize\n * @param level - The severity level determining the color\n * @returns Colorized message (yellow for warnings, red for errors, unchanged for info)\n */\nfunction colorize(msg: string, level: \"info\" | \"warn\" | \"error\"): string {\n // Don't re-colorize messages that already contain ANSI escape codes\n if (msg.includes(\"\\u001b[\")) {\n return msg;\n }\n if (level === \"warn\") {\n return yellowBright(msg);\n }\n if (level === \"error\") {\n return redBright(msg);\n }\n return msg;\n}\n\n/**\n * Determines whether a message should be printed based on its level and quiet mode.\n * @param level - The severity level of the message\n * @returns true if the message should be printed, false otherwise\n */\nfunction canPrint(level: \"info\" | \"warn\" | \"error\"): boolean {\n // Warnings and errors always print, even in quiet mode\n if (level !== \"info\") {\n return true;\n }\n // Info messages respect shouldPrint() which checks for quiet mode\n return shouldPrint();\n}\n\n/**\n * Prepares a message for display by converting Error objects and masking tokens.\n * @param value - The message string or Error object\n * @param level - The severity level (stack traces are included for errors)\n * @returns Masked message text, optionally with stack trace\n */\nfunction prepareMessage(value: string | Error, level: \"info\" | \"warn\" | \"error\"): string {\n let text: string;\n if (value instanceof Error) {\n text = value.message;\n // For errors, automatically include stack trace\n if (level === \"error\" && value.stack) {\n text = `${text}\\n\\n${value.stack}`;\n }\n } else {\n text = value;\n }\n return maskTokens(text);\n}\n\n/**\n * Displays a note message with optional warning or error level formatting.\n * Regular notes are displayed in normal text, warnings are shown in yellow, and errors in red.\n * Any sensitive tokens in the message are masked before display.\n * Warnings and errors are always displayed, even in quiet mode (when CLAUDECODE, REPL_ID, or AGENT env vars are set).\n * When an Error object is provided with level \"error\", the stack trace is automatically included.\n *\n * @param message - The message to display as a note. Can be either:\n * - A string: Displayed directly with appropriate styling\n * - An Error object: The error message is displayed, and for level \"error\", the stack trace is automatically included\n * @param level - The note level: \"info\" (default), \"warn\" for warning styling, or \"error\" for error styling\n * @example\n * import { note } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display info note\n * note(\"Operation completed successfully\");\n *\n * // Display warning note\n * note(\"Low disk space remaining\", \"warn\");\n *\n * // Display error note (string)\n * note(\"Operation failed\", \"error\");\n *\n * // Display error with stack trace automatically (Error object)\n * try {\n * // some operation\n * } catch (error) {\n * // If error is an Error object and level is \"error\", stack trace is included automatically\n * note(error, \"error\");\n * }\n */\nexport const note = (message: string | Error, level: \"info\" | \"warn\" | \"error\" = \"info\"): void => {\n if (!canPrint(level)) {\n return;\n }\n\n const msg = prepareMessage(message, level);\n console.log(\"\");\n\n if (level === \"warn\") {\n console.warn(colorize(msg, level));\n } else if (level === \"error\") {\n console.error(colorize(msg, level));\n } else {\n console.log(msg);\n }\n};\n","import { note } from \"./note.js\";\n\n/**\n * Displays a list of items in a formatted manner, supporting nested items.\n *\n * @param title - The title of the list\n * @param items - The items to display, can be strings or arrays for nested items\n * @returns The formatted list\n * @example\n * import { list } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Simple list\n * list(\"Use cases\", [\"use case 1\", \"use case 2\", \"use case 3\"]);\n *\n * // Nested list\n * list(\"Providers\", [\n * \"AWS\",\n * [\"us-east-1\", \"eu-west-1\"],\n * \"Azure\",\n * [\"eastus\", \"westeurope\"]\n * ]);\n */\nexport function list(title: string, items: Array<string | string[]>) {\n const formatItems = (items: Array<string | string[]>): string => {\n return items\n .map((item) => {\n if (Array.isArray(item)) {\n return item.map((subItem) => ` • ${subItem}`).join(\"\\n\");\n }\n return ` • ${item}`;\n })\n .join(\"\\n\");\n };\n\n return note(`${title}:\\n\\n${formatItems(items)}`);\n}\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { shouldPrint } from \"@/terminal/should-print.js\";\nimport { greenBright, inverse } from \"yoctocolors\";\n\n/**\n * Displays a closing message in green inverted text with padding.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The message to display as conclusion\n * @example\n * import { outro } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display outro message\n * outro(\"Deployment completed successfully!\");\n */\nexport const outro = (msg: string): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\"\");\n console.log(inverse(greenBright(maskTokens(msg))));\n console.log(\"\");\n};\n","import isInCi from \"is-in-ci\";\nimport yoctoSpinner, { type Spinner } from \"yocto-spinner\";\nimport { redBright } from \"yoctocolors\";\nimport { note } from \"./note.js\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Error class used to indicate that the spinner operation failed.\n * This error is used to signal that the operation should be aborted.\n */\nexport class SpinnerError extends Error {\n constructor(\n message: string,\n public readonly originalError: Error,\n ) {\n super(message);\n this.name = \"SpinnerError\";\n }\n}\n\n/**\n * Options for configuring the spinner behavior\n */\nexport interface SpinnerOptions<R> {\n /** Message to display when spinner starts */\n startMessage: string;\n /** Async task to execute while spinner is active */\n task: (spinner?: Spinner) => Promise<R>;\n /** Message to display when spinner completes successfully */\n stopMessage: string;\n}\n\n/**\n * Displays a loading spinner while executing an async task.\n * Shows progress with start/stop messages and handles errors.\n * Spinner is disabled in CI environments.\n *\n * @param options - Configuration options for the spinner\n * @returns The result from the executed task\n * @throws Will exit process with code 1 if task fails\n * @example\n * import { spinner } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Show spinner during async task\n * const result = await spinner({\n * startMessage: \"Deploying...\",\n * task: async () => {\n * // Async work here\n * return \"success\";\n * },\n * stopMessage: \"Deployed successfully!\"\n * });\n */\nexport const spinner = async <R>(options: SpinnerOptions<R>): Promise<R> => {\n const handleError = (error: Error) => {\n note(error, \"error\");\n throw new SpinnerError(error.message, error);\n };\n if (isInCi || !shouldPrint()) {\n try {\n return await options.task();\n } catch (err) {\n return handleError(err as Error);\n }\n }\n const spinner = yoctoSpinner({ stream: process.stdout }).start(options.startMessage);\n try {\n const result = await options.task(spinner);\n spinner.success(options.stopMessage);\n // Ensure spinner success message renders before proceeding to avoid\n // terminal output overlap issues with subsequent messages\n await new Promise((resolve) => process.nextTick(resolve));\n return result;\n } catch (err) {\n spinner.error(redBright(`${options.startMessage} --> Error!`));\n return handleError(err as Error);\n }\n};\n","/**\n * Capitalizes the first letter of a string.\n *\n * @param val - The string to capitalize\n * @returns The input string with its first letter capitalized\n *\n * @example\n * import { capitalizeFirstLetter } from \"@settlemint/sdk-utils\";\n *\n * const capitalized = capitalizeFirstLetter(\"hello\");\n * // Returns: \"Hello\"\n */\nexport function capitalizeFirstLetter(val: string) {\n return String(val).charAt(0).toUpperCase() + String(val).slice(1);\n}\n\n/**\n * Converts a camelCase string to a human-readable string.\n *\n * @param s - The camelCase string to convert\n * @returns The human-readable string\n *\n * @example\n * import { camelCaseToWords } from \"@settlemint/sdk-utils\";\n *\n * const words = camelCaseToWords(\"camelCaseString\");\n * // Returns: \"Camel Case String\"\n */\nexport function camelCaseToWords(s: string) {\n const result = s.replace(/([a-z])([A-Z])/g, \"$1 $2\");\n const withSpaces = result.replace(/([A-Z])([a-z])/g, \" $1$2\");\n const capitalized = capitalizeFirstLetter(withSpaces);\n return capitalized.replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Replaces underscores and hyphens with spaces.\n *\n * @param s - The string to replace underscores and hyphens with spaces\n * @returns The input string with underscores and hyphens replaced with spaces\n *\n * @example\n * import { replaceUnderscoresAndHyphensWithSpaces } from \"@settlemint/sdk-utils\";\n *\n * const result = replaceUnderscoresAndHyphensWithSpaces(\"Already_Spaced-Second\");\n * // Returns: \"Already Spaced Second\"\n */\nexport function replaceUnderscoresAndHyphensWithSpaces(s: string) {\n return s.replace(/[-_]/g, \" \");\n}\n\n/**\n * Truncates a string to a maximum length and appends \"...\" if it is longer.\n *\n * @param value - The string to truncate\n * @param maxLength - The maximum length of the string\n * @returns The truncated string or the original string if it is shorter than the maximum length\n *\n * @example\n * import { truncate } from \"@settlemint/sdk-utils\";\n *\n * const truncated = truncate(\"Hello, world!\", 10);\n * // Returns: \"Hello, wor...\"\n */\nexport function truncate(value: string, maxLength: number) {\n if (value.length <= maxLength) {\n return value;\n }\n return `${value.slice(0, maxLength)}...`;\n}\n","import { Table } from \"console-table-printer\";\nimport { whiteBright } from \"yoctocolors\";\nimport { camelCaseToWords } from \"@/string.js\";\nimport { note } from \"./note.js\";\nimport { shouldPrint } from \"./should-print.js\";\n/**\n * Displays data in a formatted table in the terminal.\n *\n * @param title - Title to display above the table\n * @param data - Array of objects to display in table format\n * @example\n * import { table } from \"@settlemint/sdk-utils/terminal\";\n *\n * const data = [\n * { name: \"Item 1\", value: 100 },\n * { name: \"Item 2\", value: 200 }\n * ];\n *\n * table(\"My Table\", data);\n */\nexport function table(title: string, data: unknown[]): void {\n if (!shouldPrint()) {\n return;\n }\n\n note(title);\n\n if (!data || data.length === 0) {\n note(\"No data to display\");\n return;\n }\n\n const columnKeys = Object.keys(data[0] as Record<string, unknown>);\n const table = new Table({\n columns: columnKeys.map((key) => ({\n name: key,\n title: whiteBright(camelCaseToWords(key)),\n alignment: \"left\",\n })),\n });\n // biome-ignore lint/suspicious/noExplicitAny: Data structure varies based on table content\n table.addRows(data as Array<Record<string, any>>);\n table.printTable();\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED