@portel/cli 1.0.0

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.
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Progress Rendering Utilities
3
+ *
4
+ * Provides ephemeral progress indicators that clear when done:
5
+ * - Spinners for indeterminate progress
6
+ * - Progress bars for determinate progress
7
+ *
8
+ * Always writes to stderr to avoid interfering with stdout data.
9
+ */
10
+ import * as readline from 'readline';
11
+ const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
12
+ /**
13
+ * Progress renderer that manages ephemeral output
14
+ * All progress is shown on stderr and clears when complete
15
+ */
16
+ export class ProgressRenderer {
17
+ spinnerInterval;
18
+ currentFrame = 0;
19
+ isActive = false;
20
+ lastMessage = '';
21
+ lastLength = 0;
22
+ /**
23
+ * Start an indeterminate spinner with auto-animation
24
+ * Updates every 80ms until stopped
25
+ */
26
+ startSpinner(message) {
27
+ this.stop();
28
+ this.isActive = true;
29
+ this.lastMessage = message;
30
+ this.renderSpinner();
31
+ this.spinnerInterval = setInterval(() => {
32
+ this.currentFrame = (this.currentFrame + 1) % SPINNER_FRAMES.length;
33
+ this.renderSpinner();
34
+ }, 80);
35
+ }
36
+ /**
37
+ * Show a single frame of spinner (no auto-animation)
38
+ */
39
+ showSpinner(message) {
40
+ this.clearLine();
41
+ this.isActive = true;
42
+ this.lastMessage = message;
43
+ this.renderSpinner();
44
+ }
45
+ /**
46
+ * Show a progress bar with percentage (0-1)
47
+ */
48
+ showProgress(value, message) {
49
+ this.stop();
50
+ this.isActive = true;
51
+ this.lastMessage = message || '';
52
+ this.renderProgressBar(value);
53
+ }
54
+ /**
55
+ * Render progress bar with spinner animation
56
+ */
57
+ render(value, message) {
58
+ this.isActive = true;
59
+ this.lastMessage = message || '';
60
+ const pct = Math.round(value * 100);
61
+ const barWidth = 20;
62
+ const filled = Math.round(value * barWidth);
63
+ const empty = barWidth - filled;
64
+ const bar = '█'.repeat(filled) + '░'.repeat(empty);
65
+ const spinner = pct < 100 ? SPINNER_FRAMES[this.currentFrame++ % SPINNER_FRAMES.length] : '✓';
66
+ const text = `${spinner} [${bar}] ${pct.toString().padStart(3)}%${this.lastMessage ? ` ${this.lastMessage}` : ''}`;
67
+ this.clearLine();
68
+ process.stderr.write(text);
69
+ this.lastLength = text.length;
70
+ }
71
+ /**
72
+ * Update message without restarting animation
73
+ */
74
+ updateMessage(message) {
75
+ if (this.isActive) {
76
+ this.lastMessage = message;
77
+ if (this.spinnerInterval) {
78
+ this.renderSpinner();
79
+ }
80
+ }
81
+ }
82
+ /**
83
+ * Stop and clear progress display
84
+ */
85
+ stop() {
86
+ this.done();
87
+ }
88
+ /**
89
+ * End progress display (clears the line)
90
+ */
91
+ done() {
92
+ if (this.spinnerInterval) {
93
+ clearInterval(this.spinnerInterval);
94
+ this.spinnerInterval = undefined;
95
+ }
96
+ if (this.isActive) {
97
+ this.clearLine();
98
+ this.isActive = false;
99
+ }
100
+ this.currentFrame = 0;
101
+ this.lastMessage = '';
102
+ this.lastLength = 0;
103
+ }
104
+ /**
105
+ * Print a persistent status message
106
+ */
107
+ status(message) {
108
+ this.done();
109
+ console.error(`ℹ ${message}`);
110
+ }
111
+ /**
112
+ * Check if progress is currently active
113
+ */
114
+ get active() {
115
+ return this.isActive;
116
+ }
117
+ clearLine() {
118
+ if ((this.lastLength > 0 || this.isActive) && process.stderr.isTTY) {
119
+ readline.clearLine(process.stderr, 0);
120
+ readline.cursorTo(process.stderr, 0);
121
+ this.lastLength = 0;
122
+ }
123
+ }
124
+ renderSpinner() {
125
+ const frame = SPINNER_FRAMES[this.currentFrame];
126
+ const text = `${frame} ${this.lastMessage}`;
127
+ this.clearLine();
128
+ process.stderr.write(text);
129
+ this.lastLength = text.length;
130
+ }
131
+ renderProgressBar(value) {
132
+ const percentage = Math.round(value * 100);
133
+ const barLength = 30;
134
+ const filled = Math.round(barLength * value);
135
+ const bar = '█'.repeat(filled) + '░'.repeat(barLength - filled);
136
+ const text = `[${bar}] ${percentage}%${this.lastMessage ? ` ${this.lastMessage}` : ''}`;
137
+ this.clearLine();
138
+ process.stderr.write(text);
139
+ this.lastLength = text.length;
140
+ }
141
+ }
142
+ // Global instance
143
+ let globalRenderer = null;
144
+ export function getProgressRenderer() {
145
+ if (!globalRenderer) {
146
+ globalRenderer = new ProgressRenderer();
147
+ }
148
+ return globalRenderer;
149
+ }
150
+ export function startSpinner(message) {
151
+ getProgressRenderer().startSpinner(message);
152
+ }
153
+ export function showProgress(value, message) {
154
+ getProgressRenderer().showProgress(value, message);
155
+ }
156
+ export function updateProgressMessage(message) {
157
+ getProgressRenderer().updateMessage(message);
158
+ }
159
+ export function stopProgress() {
160
+ getProgressRenderer().stop();
161
+ }
162
+ export function isProgressActive() {
163
+ return getProgressRenderer().active;
164
+ }
165
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../src/progress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Text Processing Utilities
3
+ *
4
+ * Shared utilities for text wrapping, formatting, and manipulation.
5
+ */
6
+ import type { TextWrapOptions } from './types.js';
7
+ export declare class TextUtils {
8
+ /**
9
+ * Wrap text to fit within specified width with optional indentation
10
+ */
11
+ static wrapText(text: string, options: TextWrapOptions): string;
12
+ /**
13
+ * Wrap text with background color applied to each line
14
+ */
15
+ static wrapTextWithBackground(text: string, maxWidth: number, indent: string, backgroundFormatter: (text: string) => string): string;
16
+ /**
17
+ * Truncate text with ellipsis if too long
18
+ */
19
+ static truncate(text: string, maxLength: number, ellipsis?: string): string;
20
+ /**
21
+ * Pad a string to a fixed width
22
+ */
23
+ static pad(text: string, width: number, align?: 'left' | 'right' | 'center'): string;
24
+ /**
25
+ * Strip ANSI escape codes from string
26
+ */
27
+ static stripAnsi(text: string): string;
28
+ /**
29
+ * Get visible length of string (excluding ANSI codes)
30
+ */
31
+ static visibleLength(text: string): number;
32
+ }
33
+ export { TextWrapOptions };
34
+ //# sourceMappingURL=text-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-utils.d.ts","sourceRoot":"","sources":["../src/text-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,qBAAa,SAAS;IACpB;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,MAAM;IA+C/D;;OAEG;IACH,MAAM,CAAC,sBAAsB,CAC3B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAC5C,MAAM;IAcT;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAc,GAAG,MAAM;IAKlF;;OAEG;IACH,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAM,GAAG,OAAO,GAAG,QAAiB,GAAG,MAAM;IAgB5F;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAKtC;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAG3C;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Text Processing Utilities
3
+ *
4
+ * Shared utilities for text wrapping, formatting, and manipulation.
5
+ */
6
+ export class TextUtils {
7
+ /**
8
+ * Wrap text to fit within specified width with optional indentation
9
+ */
10
+ static wrapText(text, options) {
11
+ const { maxWidth, indent = '', cleanupPrefixes = false, preserveWhitespace = false } = options;
12
+ if (!text)
13
+ return text;
14
+ let processedText = text;
15
+ if (cleanupPrefixes) {
16
+ processedText = text
17
+ .replace(/^[^:]+:\s*/, '')
18
+ .replace(/\s+/g, ' ')
19
+ .trim();
20
+ }
21
+ else if (!preserveWhitespace) {
22
+ processedText = text.trim();
23
+ }
24
+ if (processedText.length <= maxWidth) {
25
+ return processedText;
26
+ }
27
+ const words = processedText.split(' ');
28
+ const lines = [];
29
+ let currentLine = '';
30
+ for (const word of words) {
31
+ const testLine = currentLine ? `${currentLine} ${word}` : word;
32
+ if (testLine.length <= maxWidth) {
33
+ currentLine = testLine;
34
+ }
35
+ else {
36
+ if (currentLine) {
37
+ lines.push(currentLine);
38
+ currentLine = word;
39
+ }
40
+ else {
41
+ lines.push(word);
42
+ }
43
+ }
44
+ }
45
+ if (currentLine) {
46
+ lines.push(currentLine);
47
+ }
48
+ return lines.map((line, index) => index === 0 ? line : `\n${indent}${line}`).join('');
49
+ }
50
+ /**
51
+ * Wrap text with background color applied to each line
52
+ */
53
+ static wrapTextWithBackground(text, maxWidth, indent, backgroundFormatter) {
54
+ if (text.length <= maxWidth) {
55
+ return `${indent}${backgroundFormatter(text)}`;
56
+ }
57
+ const wrappedText = this.wrapText(text, { maxWidth, indent: '', preserveWhitespace: true });
58
+ const lines = wrappedText.split('\n');
59
+ return lines.map((line, _index) => {
60
+ const formattedLine = backgroundFormatter(line);
61
+ return `${indent}${formattedLine}`;
62
+ }).join('\n');
63
+ }
64
+ /**
65
+ * Truncate text with ellipsis if too long
66
+ */
67
+ static truncate(text, maxLength, ellipsis = '...') {
68
+ if (text.length <= maxLength)
69
+ return text;
70
+ return text.slice(0, maxLength - ellipsis.length) + ellipsis;
71
+ }
72
+ /**
73
+ * Pad a string to a fixed width
74
+ */
75
+ static pad(text, width, align = 'left') {
76
+ if (text.length >= width)
77
+ return text;
78
+ const padding = width - text.length;
79
+ switch (align) {
80
+ case 'right':
81
+ return ' '.repeat(padding) + text;
82
+ case 'center':
83
+ const left = Math.floor(padding / 2);
84
+ const right = padding - left;
85
+ return ' '.repeat(left) + text + ' '.repeat(right);
86
+ default:
87
+ return text + ' '.repeat(padding);
88
+ }
89
+ }
90
+ /**
91
+ * Strip ANSI escape codes from string
92
+ */
93
+ static stripAnsi(text) {
94
+ // eslint-disable-next-line no-control-regex
95
+ return text.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
96
+ }
97
+ /**
98
+ * Get visible length of string (excluding ANSI codes)
99
+ */
100
+ static visibleLength(text) {
101
+ return this.stripAnsi(text).length;
102
+ }
103
+ }
104
+ //# sourceMappingURL=text-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-utils.js","sourceRoot":"","sources":["../src/text-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @portel/core type definitions
3
+ */
4
+ /**
5
+ * Output format hints for CLI formatting
6
+ *
7
+ * Structural formats:
8
+ * - primitive: Single values (string, number, boolean)
9
+ * - table: Flat objects or arrays of flat objects
10
+ * - tree: Nested/hierarchical structures
11
+ * - list: Arrays of primitives
12
+ * - card: Bordered card view for objects
13
+ * - tabs: Tabbed sections for grouped data
14
+ * - accordion: Collapsible sections
15
+ * - none: No data to display
16
+ *
17
+ * Content formats:
18
+ * - json, markdown, yaml, xml, html: Syntax highlighted content
19
+ * - code / code:<lang>: Syntax highlighted code
20
+ */
21
+ export type OutputFormat = 'primitive' | 'table' | 'tree' | 'list' | 'none' | 'card' | 'grid' | 'chips' | 'kv' | 'tabs' | 'accordion' | 'json' | 'markdown' | 'yaml' | 'xml' | 'html' | 'mermaid' | `code` | `code:${string}`;
22
+ /**
23
+ * Text wrapping options for CLI output
24
+ */
25
+ export interface TextWrapOptions {
26
+ maxWidth: number;
27
+ indent?: string;
28
+ cleanupPrefixes?: boolean;
29
+ preserveWhitespace?: boolean;
30
+ }
31
+ /**
32
+ * Fuzzy match result
33
+ */
34
+ export interface FuzzyMatch {
35
+ text: string;
36
+ distance: number;
37
+ score: number;
38
+ }
39
+ /**
40
+ * Execution context for async operations
41
+ */
42
+ export interface ExecutionContext {
43
+ outputHandler?: (data: any) => void;
44
+ }
45
+ /**
46
+ * Log levels for logger
47
+ */
48
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
49
+ /**
50
+ * Logger configuration options
51
+ */
52
+ export interface LoggerOptions {
53
+ level?: LogLevel;
54
+ prefix?: string;
55
+ silent?: boolean;
56
+ debugMode?: boolean;
57
+ logFilePath?: string;
58
+ }
59
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,YAAY,GACpB,WAAW,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAChD,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,WAAW,GACvD,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,GACzD,MAAM,GAAG,QAAQ,MAAM,EAAE,CAAC;AAE9B;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @portel/core type definitions
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@portel/cli",
3
+ "version": "1.0.0",
4
+ "description": "CLI toolkit for building terminal applications - formatting, progress, fuzzy matching, logging",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "clean": "rm -rf dist",
21
+ "prepublishOnly": "npm run clean && npm run build"
22
+ },
23
+ "keywords": [
24
+ "cli",
25
+ "formatter",
26
+ "progress",
27
+ "spinner",
28
+ "fuzzy",
29
+ "logging",
30
+ "terminal",
31
+ "utilities"
32
+ ],
33
+ "author": "Portel",
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/portel-dev/portel-cli"
38
+ },
39
+ "dependencies": {
40
+ "chalk": "^5.3.0",
41
+ "cli-highlight": "^2.1.11"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^20.0.0",
45
+ "typescript": "^5.3.0"
46
+ },
47
+ "engines": {
48
+ "node": ">=18.0.0"
49
+ }
50
+ }