ktx/packages/cli/src/clack.ts

100 lines
2.3 KiB
TypeScript
Raw Permalink Normal View History

import { cancel, confirm, isCancel, log, spinner } from '@clack/prompts';
2026-05-10 23:12:26 +02:00
const ESC = String.fromCharCode(0x1b);
2026-05-10 23:51:24 +02:00
export interface KtxCliSpinner {
2026-05-10 23:12:26 +02:00
start(message: string): void;
message(message: string): void;
2026-05-10 23:12:26 +02:00
stop(message: string): void;
error(message: string): void;
}
export interface KtxCliSpinnerIo {
stderr: { write(chunk: string): void };
}
export interface KtxCliPromptAdapter {
confirm(options: { message: string; initialValue?: boolean }): Promise<boolean>;
cancel(message: string): void;
log: {
info(message: string): void;
warn(message: string): void;
error(message: string): void;
success(message: string): void;
step(message: string): void;
};
spinner(): KtxCliSpinner;
}
export class KtxCliPromptCancelledError extends Error {
constructor(message = 'Operation cancelled.') {
super(message);
this.name = 'KtxCliPromptCancelledError';
}
}
2026-05-10 23:51:24 +02:00
export function createClackSpinner(): KtxCliSpinner {
2026-05-10 23:12:26 +02:00
return spinner();
}
function magenta(text: string): string {
return `${ESC}[35m${text}${ESC}[39m`;
}
function red(text: string): string {
return `${ESC}[31m${text}${ESC}[39m`;
}
export function createStaticCliSpinner(io: KtxCliSpinnerIo): KtxCliSpinner {
return {
start(message) {
io.stderr.write(`${magenta('◐')} ${message}\n`);
},
message(message) {
io.stderr.write(`${magenta('│')} ${message}\n`);
},
stop(message) {
io.stderr.write(`${magenta('◇')} ${message}\n`);
},
error(message) {
io.stderr.write(`${red('■')} ${message}\n`);
},
};
}
export function createClackPromptAdapter(): KtxCliPromptAdapter {
return {
async confirm(options) {
const value = await confirm(options);
if (isCancel(value)) {
cancel('Operation cancelled.');
throw new KtxCliPromptCancelledError();
}
return value;
},
cancel(message) {
cancel(message);
},
log: {
info(message) {
log.info(message);
},
warn(message) {
log.warn(message);
},
error(message) {
log.error(message);
},
success(message) {
log.success(message);
},
step(message) {
log.step(message);
},
},
spinner() {
return createClackSpinner();
},
};
}