dbn-cli 0.2.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,137 @@
1
+ /**
2
+ * Formatting utilities for displaying data
3
+ */
4
+
5
+ /**
6
+ * Format a number with thousand separators
7
+ * @param num - Number to format
8
+ * @returns Formatted number string
9
+ */
10
+ export function formatNumber(num: number): string {
11
+ return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
12
+ }
13
+
14
+ /**
15
+ * Truncate a string to a specific visible width with ellipsis
16
+ * @param str - String to truncate
17
+ * @param maxWidth - Maximum visible width (accounting for double-width chars)
18
+ * @returns Truncated string
19
+ */
20
+ import stringWidth from 'string-width';
21
+
22
+ export function truncate(str: string, maxWidth: number): string {
23
+ if (!str) return '';
24
+ const s = String(str);
25
+
26
+ const currentWidth = getVisibleWidth(s);
27
+ if (currentWidth <= maxWidth) return s;
28
+
29
+ // Need to truncate - build string character by character
30
+ let result = '';
31
+ let width = 0;
32
+ const ellipsis = '...';
33
+ const ellipsisWidth = 3; // '...' is 3 single-width chars
34
+
35
+ // Use grapheme-aware widths using string-width
36
+ for (const ch of Array.from(s)) {
37
+ const charWidth = stringWidth(ch);
38
+
39
+ if (width + charWidth + ellipsisWidth > maxWidth) break;
40
+
41
+ result += ch;
42
+ width += charWidth;
43
+ }
44
+
45
+ return result + ellipsis;
46
+ }
47
+
48
+ /**
49
+ * Pad a string to a specific visible width
50
+ * @param str - String to pad
51
+ * @param targetWidth - Target visible width (accounting for double-width chars)
52
+ * @param align - Alignment: 'left', 'right', or 'center'
53
+ * @returns Padded string
54
+ */
55
+ export function pad(str: string, targetWidth: number, align: 'left' | 'right' | 'center' = 'left'): string {
56
+ const s = String(str || '');
57
+ const currentWidth = getVisibleWidth(s);
58
+
59
+ if (currentWidth >= targetWidth) {
60
+ // Need to truncate
61
+ let result = '';
62
+ let width = 0;
63
+
64
+ // Build using string-width for grapheme-aware sizing
65
+ for (const char of Array.from(s)) {
66
+ const charWidth = stringWidth(char);
67
+
68
+ if (width + charWidth > targetWidth) break;
69
+
70
+ result += char;
71
+ width += charWidth;
72
+ }
73
+
74
+ // If we stopped before a double-width char and have 1 space left, add a space
75
+ if (width < targetWidth) {
76
+ result += ' '.repeat(targetWidth - width);
77
+ }
78
+
79
+ return result;
80
+ }
81
+
82
+ const padding = targetWidth - currentWidth;
83
+
84
+ if (align === 'right') {
85
+ return ' '.repeat(padding) + s;
86
+ } else if (align === 'center') {
87
+ const leftPad = Math.floor(padding / 2);
88
+ const rightPad = padding - leftPad;
89
+ return ' '.repeat(leftPad) + s + ' '.repeat(rightPad);
90
+ } else {
91
+ return s + ' '.repeat(padding);
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Format a value for display (handle null, undefined, etc.)
97
+ * @param value - Value to format
98
+ * @returns Formatted string
99
+ */
100
+ export function formatValue(value: any): string {
101
+ if (value === null) return 'NULL';
102
+ if (value === undefined) return '';
103
+ if (typeof value === 'boolean') return value ? 'true' : 'false';
104
+ if (typeof value === 'object') return JSON.stringify(value);
105
+
106
+ // Convert to string and remove control characters (newlines, tabs, etc.)
107
+ const str = String(value);
108
+ return str.replace(/[\n\r\t\v\f]/g, ' ').replace(/\s+/g, ' ');
109
+ }
110
+
111
+ /**
112
+ * Check if a character is double-width (CJK, emoji, etc.)
113
+ * @param char - Single character or code point
114
+ * @returns True if character is double-width
115
+ */
116
+ // Deprecated: custom double-width detection replaced by `string-width`.
117
+ // Keep function stub for backward compatibility if other modules import it.
118
+ function isDoubleWidth(_char: string): boolean {
119
+ return false; // use string-width instead
120
+ }
121
+
122
+ /**
123
+ * Get the visible width of a string (accounting for ANSI codes, CJK characters, and emoji)
124
+ * @param str - String to measure
125
+ * @returns Visible width
126
+ */
127
+ export function getVisibleWidth(str: string): number {
128
+ // Remove ANSI escape codes
129
+ const cleanStr = str.replace(/\x1b\[[0-9;]*m/g, '');
130
+
131
+ let width = 0;
132
+ for (const ch of Array.from(cleanStr)) {
133
+ width += stringWidth(ch);
134
+ }
135
+
136
+ return width;
137
+ }