@heroku/heroku-cli-util 10.4.0-beta.1 → 10.5.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.
package/README.md CHANGED
@@ -77,7 +77,7 @@ console.log(color.failure('Build failed')); // Red
77
77
  console.log(color.warning('Deprecated feature')); // Orange
78
78
 
79
79
  // User/Team colors
80
- console.log(color.team('my-team')); // Cyan, bold
80
+ console.log(color.team('my-team')); // Light cyan
81
81
  console.log(color.user('user@example.com')); // Cyan
82
82
 
83
83
  // General purpose
@@ -8,15 +8,25 @@ declare const COLORS: {
8
8
  readonly CODE_BG: 237;
9
9
  readonly CODE_FG: 255;
10
10
  readonly CYAN: "#50D3D5";
11
+ readonly CYAN_LIGHT: "#8FF5F7";
12
+ readonly GOLD: 220;
11
13
  readonly GRAY: 248;
12
14
  readonly GREEN: 40;
13
- readonly MAGENTA: "#FF8DD3";
15
+ readonly MAGENTA: "#FF22DD";
14
16
  readonly ORANGE: 214;
17
+ readonly PINK: 212;
15
18
  readonly PURPLE: 147;
16
19
  readonly RED: "#FF8787";
17
20
  readonly TEAL: 43;
18
21
  readonly YELLOW: 185;
19
22
  };
23
+ /** Theme name: 'heroku' (default) or 'simple' (ANSI 8 only). Set via HEROKU_THEME env. */
24
+ export type ThemeName = 'heroku' | 'simple';
25
+ /**
26
+ * Resolves active theme from HEROKU_THEME; defaults to 'heroku'.
27
+ * @returns The active theme name.
28
+ */
29
+ export declare function getTheme(): ThemeName;
20
30
  export declare const app: (text: string) => string;
21
31
  export declare const pipeline: (text: string) => string;
22
32
  export declare const space: (text: string) => string;
@@ -25,15 +35,19 @@ export declare const addon: (text: string) => string;
25
35
  export declare const attachment: (text: string) => string;
26
36
  export declare const name: (text: string) => string;
27
37
  export declare const success: (text: string) => string;
38
+ export declare const enabled: (text: string) => string;
28
39
  export declare const failure: (text: string) => string;
40
+ export declare const error: (text: string) => string;
29
41
  export declare const warning: (text: string) => string;
30
42
  export declare const team: (text: string) => string;
31
43
  export declare const user: (text: string) => string;
32
44
  export declare const label: (text: string) => string;
33
45
  export declare const info: (text: string) => string;
34
46
  export declare const inactive: (text: string) => string;
47
+ export declare const disabled: (text: string) => string;
35
48
  export declare const command: (text: string) => string;
36
49
  export declare const code: (text: string) => string;
50
+ export declare const snippet: (text: string) => string;
37
51
  /**
38
52
  * Color palette for reference
39
53
  * Shows ANSI256 codes for most colors, hex values for magenta, red, and cyan
@@ -41,12 +55,12 @@ export declare const code: (text: string) => string;
41
55
  export declare const colorPalette: {
42
56
  readonly addon: {
43
57
  readonly name: "yellow";
44
- readonly style: "bold";
58
+ readonly style: "normal";
45
59
  readonly value: 185;
46
60
  };
47
61
  readonly app: {
48
62
  readonly name: "purple";
49
- readonly style: "bold";
63
+ readonly style: "normal";
50
64
  readonly value: 147;
51
65
  };
52
66
  readonly attachment: {
@@ -54,6 +68,11 @@ export declare const colorPalette: {
54
68
  readonly style: "normal";
55
69
  readonly value: 185;
56
70
  };
71
+ readonly code: {
72
+ readonly name: "white on dark gray";
73
+ readonly style: "bold";
74
+ readonly value: 255;
75
+ };
57
76
  readonly command: {
58
77
  readonly name: "white on dark gray";
59
78
  readonly style: "bold";
@@ -61,7 +80,7 @@ export declare const colorPalette: {
61
80
  };
62
81
  readonly datastore: {
63
82
  readonly name: "yellow";
64
- readonly style: "bold";
83
+ readonly style: "normal";
65
84
  readonly value: 185;
66
85
  };
67
86
  readonly failure: {
@@ -69,6 +88,11 @@ export declare const colorPalette: {
69
88
  readonly style: "normal";
70
89
  readonly value: "#FF8787";
71
90
  };
91
+ readonly gold: {
92
+ readonly name: "gold";
93
+ readonly style: "normal";
94
+ readonly value: 220;
95
+ };
72
96
  readonly inactive: {
73
97
  readonly name: "gray";
74
98
  readonly style: "normal";
@@ -87,16 +111,21 @@ export declare const colorPalette: {
87
111
  readonly name: {
88
112
  readonly name: "magenta";
89
113
  readonly style: "normal";
90
- readonly value: "#FF8DD3";
114
+ readonly value: "#FF22DD";
91
115
  };
92
116
  readonly pipeline: {
93
117
  readonly name: "purple";
94
118
  readonly style: "normal";
95
119
  readonly value: 147;
96
120
  };
121
+ readonly snippet: {
122
+ readonly name: "white on dark gray";
123
+ readonly style: "normal";
124
+ readonly value: 255;
125
+ };
97
126
  readonly space: {
98
127
  readonly name: "blue";
99
- readonly style: "bold";
128
+ readonly style: "normal";
100
129
  readonly value: 117;
101
130
  };
102
131
  readonly success: {
@@ -105,9 +134,9 @@ export declare const colorPalette: {
105
134
  readonly value: 40;
106
135
  };
107
136
  readonly team: {
108
- readonly name: "cyan";
109
- readonly style: "bold";
110
- readonly value: "#50D3D5";
137
+ readonly name: "light cyan";
138
+ readonly style: "normal";
139
+ readonly value: "#8FF5F7";
111
140
  };
112
141
  readonly user: {
113
142
  readonly name: "cyan";
package/dist/ux/colors.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable import/no-named-as-default-member */
2
- import ansi from 'ansis';
2
+ import ansis from 'ansis';
3
3
  /**
4
4
  * Color constants for Heroku CLI output
5
5
  * Most colors use ANSI256 codes for better compatibility with terminals that don't support TrueColor.
@@ -14,14 +14,19 @@ const COLORS = {
14
14
  CODE_FG: 255,
15
15
  // Cyan tones (kept as hex for precise color matching)
16
16
  CYAN: '#50D3D5',
17
+ CYAN_LIGHT: '#8FF5F7',
18
+ // Gold tones (ANSI256: 220, approx. #FFD700)
19
+ GOLD: 220,
17
20
  // Gray tones (ANSI256: 248)
18
21
  GRAY: 248,
19
22
  // Green tones (ANSI256: 40)
20
23
  GREEN: 40,
21
24
  // Magenta tones (kept as hex for precise color matching)
22
- MAGENTA: '#FF8DD3',
25
+ MAGENTA: '#FF22DD',
23
26
  // Orange tones (ANSI256: 214)
24
27
  ORANGE: 214,
28
+ // Pink tones (ANSI256: 212, approx. #FF87D7 - closest match to original #FF8DD3)
29
+ PINK: 212,
25
30
  // Purple tones (ANSI256: 147 - closest match to original #ACADFF)
26
31
  PURPLE: 147,
27
32
  // Red tones (kept as hex for precise color matching)
@@ -37,53 +42,111 @@ const COLORS = {
37
42
  * Colors use ANSI256 codes where possible, with hex values for magenta, red, and cyan
38
43
  */
39
44
  // Helper function to apply color based on type (number = ANSI256, string = hex)
40
- const colorize = (color) => typeof color === 'number' ? ansi.fg(color) : ansi.hex(color);
41
- const bgColorize = (color) => typeof color === 'number' ? ansi.bg(color) : ansi.bgHex(color);
45
+ const colorize = (color) => typeof color === 'number' ? ansis.fg(color) : ansis.hex(color);
46
+ const bgColorize = (color) => typeof color === 'number' ? ansis.bg(color) : ansis.bgHex(color);
42
47
  // Check if terminal supports at least ANSI256 (level >= 2)
43
48
  // Level values: 0=no color, 1=ANSI16, 2=ANSI256, 3=TrueColor
44
- const supportsAnsi256 = ansi.level >= 2;
49
+ const supportsAnsi256 = ansis.level >= 2;
45
50
  // Helper function for purple color that falls back to ANSI16 magenta when only ANSI16 is supported
46
- const purpleColorize = () => supportsAnsi256 ? ansi.fg(COLORS.PURPLE) : ansi.magenta;
51
+ const purpleColorize = () => supportsAnsi256 ? ansis.fg(COLORS.PURPLE) : ansis.magenta;
52
+ const THEME_ENV = 'HEROKU_THEME';
53
+ /**
54
+ * Resolves active theme from HEROKU_THEME; defaults to 'heroku'.
55
+ * @returns The active theme name.
56
+ */
57
+ export function getTheme() {
58
+ const v = process.env[THEME_ENV]?.toLowerCase().trim();
59
+ if (v === 'simple')
60
+ return 'simple';
61
+ return 'heroku';
62
+ }
63
+ const herokuTheme = {
64
+ addon: (text) => colorize(COLORS.YELLOW)(text),
65
+ app: (text) => purpleColorize()(`${supportsAnsi256 ? '⬢ ' : ''}${text}`),
66
+ attachment: (text) => colorize(COLORS.GOLD)(text),
67
+ code: (text) => bgColorize(COLORS.CODE_BG).fg(COLORS.CODE_FG).bold(`${text}`),
68
+ command: (text) => bgColorize(COLORS.CODE_BG).fg(COLORS.CODE_FG).bold(` $ ${text} `),
69
+ datastore: (text) => colorize(COLORS.YELLOW)(`${supportsAnsi256 ? '⛁ ' : ''}${text}`),
70
+ failure: (text) => colorize(COLORS.RED)(text),
71
+ inactive: (text) => colorize(COLORS.GRAY)(text),
72
+ info: (text) => colorize(COLORS.TEAL)(text),
73
+ label: (text) => ansis.bold(text),
74
+ name: (text) => colorize(COLORS.PINK)(text),
75
+ pipeline: (text) => colorize(COLORS.MAGENTA)(text),
76
+ space: (text) => colorize(COLORS.BLUE)(`${supportsAnsi256 ? '⬡ ' : ''}${text}`),
77
+ success: (text) => colorize(COLORS.GREEN)(text),
78
+ team: (text) => colorize(COLORS.CYAN_LIGHT)(text),
79
+ user: (text) => colorize(COLORS.CYAN)(text),
80
+ warning: (text) => colorize(COLORS.ORANGE)(text),
81
+ };
82
+ /** Simple theme: ANSI 8 colors only, no symbols. */
83
+ const simpleTheme = {
84
+ addon: (text) => ansis.yellow(text),
85
+ app: (text) => ansis.magenta(text),
86
+ attachment: (text) => ansis.yellow(text),
87
+ code: (text) => ansis.bold(text),
88
+ command: (text) => ansis.bold(` $ ${text} `),
89
+ datastore: (text) => ansis.yellow(text),
90
+ failure: (text) => ansis.red(text),
91
+ inactive: (text) => ansis.gray(text),
92
+ info: (text) => ansis.cyan(text),
93
+ label: (text) => ansis.bold(text),
94
+ name: (text) => ansis.magenta(text),
95
+ pipeline: (text) => ansis.magenta(text),
96
+ space: (text) => ansis.cyan(text),
97
+ success: (text) => ansis.green(text),
98
+ team: (text) => ansis.cyan(text),
99
+ user: (text) => ansis.cyan(text),
100
+ warning: (text) => ansis.yellow(text),
101
+ };
102
+ const activeTheme = () => (getTheme() === 'simple' ? simpleTheme : herokuTheme);
47
103
  // Colors for entities on the Heroku platform
48
- export const app = (text) => purpleColorize().bold(`${supportsAnsi256 ? '⬢ ' : ''}${text}`);
49
- export const pipeline = (text) => purpleColorize()(text);
50
- export const space = (text) => colorize(COLORS.BLUE).bold(`${supportsAnsi256 ? '⬡ ' : ''}${text}`);
51
- export const datastore = (text) => colorize(COLORS.YELLOW).bold(`${supportsAnsi256 ? '⛁ ' : ''}${text}`);
52
- export const addon = (text) => colorize(COLORS.YELLOW).bold(text);
53
- export const attachment = (text) => colorize(COLORS.YELLOW)(text);
54
- export const name = (text) => colorize(COLORS.MAGENTA)(text);
104
+ export const app = (text) => activeTheme().app(text);
105
+ export const pipeline = (text) => activeTheme().pipeline(text);
106
+ export const space = (text) => activeTheme().space(text);
107
+ export const datastore = (text) => activeTheme().datastore(text);
108
+ export const addon = (text) => activeTheme().addon(text);
109
+ export const attachment = (text) => activeTheme().attachment(text);
110
+ export const name = (text) => activeTheme().name(text);
55
111
  // Status colors
56
- export const success = (text) => colorize(COLORS.GREEN)(text);
57
- export const failure = (text) => colorize(COLORS.RED)(text);
58
- export const warning = (text) => colorize(COLORS.ORANGE)(text);
112
+ export const success = (text) => activeTheme().success(text);
113
+ export const enabled = success;
114
+ export const failure = (text) => activeTheme().failure(text);
115
+ export const error = failure;
116
+ export const warning = (text) => activeTheme().warning(text);
59
117
  // User/Team colors
60
- export const team = (text) => colorize(COLORS.CYAN).bold(text);
61
- export const user = (text) => colorize(COLORS.CYAN)(text);
118
+ export const team = (text) => activeTheme().team(text);
119
+ export const user = (text) => activeTheme().user(text);
62
120
  // General purpose colors
63
- export const label = (text) => ansi.bold(text);
64
- export const info = (text) => colorize(COLORS.TEAL)(text);
65
- export const inactive = (text) => colorize(COLORS.GRAY)(text);
66
- export const command = (text) => bgColorize(COLORS.CODE_BG).fg(COLORS.CODE_FG).bold(` $ ${text} `);
67
- export const code = (text) => bgColorize(COLORS.CODE_BG).fg(COLORS.CODE_FG).bold(`${text}`);
121
+ export const label = (text) => activeTheme().label(text);
122
+ export const info = (text) => activeTheme().info(text);
123
+ export const inactive = (text) => activeTheme().inactive(text);
124
+ export const disabled = inactive;
125
+ export const command = (text) => activeTheme().command(text);
126
+ export const code = (text) => activeTheme().code(text);
127
+ export const snippet = code;
68
128
  /**
69
129
  * Color palette for reference
70
130
  * Shows ANSI256 codes for most colors, hex values for magenta, red, and cyan
71
131
  */
72
132
  export const colorPalette = {
73
- addon: { name: 'yellow', style: 'bold', value: COLORS.YELLOW },
74
- app: { name: 'purple', style: 'bold', value: COLORS.PURPLE },
133
+ addon: { name: 'yellow', style: 'normal', value: COLORS.YELLOW },
134
+ app: { name: 'purple', style: 'normal', value: COLORS.PURPLE },
75
135
  attachment: { name: 'yellow', style: 'normal', value: COLORS.YELLOW },
136
+ code: { name: 'white on dark gray', style: 'bold', value: COLORS.CODE_FG },
76
137
  command: { name: 'white on dark gray', style: 'bold', value: COLORS.CODE_FG },
77
- datastore: { name: 'yellow', style: 'bold', value: COLORS.YELLOW },
138
+ datastore: { name: 'yellow', style: 'normal', value: COLORS.YELLOW },
78
139
  failure: { name: 'red', style: 'normal', value: COLORS.RED },
140
+ gold: { name: 'gold', style: 'normal', value: COLORS.GOLD },
79
141
  inactive: { name: 'gray', style: 'normal', value: COLORS.GRAY },
80
142
  info: { name: 'teal', style: 'normal', value: COLORS.TEAL },
81
143
  label: { name: 'bright white/black', style: 'bold', value: 'default' },
82
144
  name: { name: 'magenta', style: 'normal', value: COLORS.MAGENTA },
83
145
  pipeline: { name: 'purple', style: 'normal', value: COLORS.PURPLE },
84
- space: { name: 'blue', style: 'bold', value: COLORS.BLUE },
146
+ snippet: { name: 'white on dark gray', style: 'normal', value: COLORS.CODE_FG },
147
+ space: { name: 'blue', style: 'normal', value: COLORS.BLUE },
85
148
  success: { name: 'green', style: 'normal', value: COLORS.GREEN },
86
- team: { name: 'cyan', style: 'bold', value: COLORS.CYAN },
149
+ team: { name: 'light cyan', style: 'normal', value: COLORS.CYAN_LIGHT },
87
150
  user: { name: 'cyan', style: 'normal', value: COLORS.CYAN },
88
151
  warning: { name: 'orange', style: 'normal', value: COLORS.ORANGE },
89
152
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@heroku/heroku-cli-util",
4
- "version": "10.4.0-beta.1",
4
+ "version": "10.5.0",
5
5
  "description": "Set of helpful CLI utilities",
6
6
  "author": "Heroku",
7
7
  "license": "ISC",
@@ -49,7 +49,7 @@
49
49
  "@heroku-cli/command": "^12.0.0",
50
50
  "@heroku/http-call": "^5.5.0",
51
51
  "@oclif/core": "^4.3.0",
52
- "@oclif/table": "0.4.14",
52
+ "@oclif/table": "0.5.2",
53
53
  "ansis": "^4.1.0",
54
54
  "debug": "^4.4.0",
55
55
  "inquirer": "^12.6.1",