@openluxeco/cli 0.5.2 → 0.6.1
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/package.json +1 -1
- package/src/banner.js +99 -0
- package/src/cli.js +2 -0
package/package.json
CHANGED
package/src/banner.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The OpenLuxe splash — the diamond estate mark stacked above the wordmark,
|
|
3
|
+
* washed in champagne gold. Shown at the top of `openluxe` / `openluxe help`.
|
|
4
|
+
*
|
|
5
|
+
* Responsive: picks a rendition that fits the terminal width (full ANSI-shadow
|
|
6
|
+
* wordmark ≥ 72 cols, compact box-drawing wordmark ≥ 36, spaced letters below
|
|
7
|
+
* that) so a thin pane never wraps the art into noise.
|
|
8
|
+
*
|
|
9
|
+
* Zero-dep: hand-set ASCII + 256-color ANSI. Color is applied only on an
|
|
10
|
+
* interactive stdout without NO_COLOR, so piped output stays clean.
|
|
11
|
+
*/
|
|
12
|
+
import { VERSION } from './config.js';
|
|
13
|
+
|
|
14
|
+
// The mark: nested shield/gem outline (public/images/mark.svg) — apex, angled
|
|
15
|
+
// shoulders, vertical sides, chamfered flat base, hollow double-walled center.
|
|
16
|
+
const MARK = [
|
|
17
|
+
' ╱╲',
|
|
18
|
+
' ╱ ╲',
|
|
19
|
+
' ╱ ╱╲ ╲',
|
|
20
|
+
' ╱ ╱ ╲ ╲',
|
|
21
|
+
' ╱ ╱ ╲ ╲',
|
|
22
|
+
' ╱ ╱ ╲ ╲',
|
|
23
|
+
'│ │ │ │',
|
|
24
|
+
'│ │ │ │',
|
|
25
|
+
'│ ╰────────╯ │',
|
|
26
|
+
'╲ ╱',
|
|
27
|
+
' ╲──────────╱',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const MARK_SMALL = [
|
|
31
|
+
' ╱╲',
|
|
32
|
+
' ╱ ╲',
|
|
33
|
+
' ╱ ╱╲ ╲',
|
|
34
|
+
' ╱ ╱ ╲ ╲',
|
|
35
|
+
'│ │ │ │',
|
|
36
|
+
'│ ╰────╯ │',
|
|
37
|
+
'╲ ╱',
|
|
38
|
+
' ╲──────╱',
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
// 68 cols — ANSI-shadow.
|
|
42
|
+
const WORDMARK = [
|
|
43
|
+
' ██████╗ ██████╗ ███████╗███╗ ██╗██╗ ██╗ ██╗██╗ ██╗███████╗',
|
|
44
|
+
'██╔═══██╗██╔══██╗██╔════╝████╗ ██║██║ ██║ ██║╚██╗██╔╝██╔════╝',
|
|
45
|
+
'██║ ██║██████╔╝█████╗ ██╔██╗ ██║██║ ██║ ██║ ╚███╔╝ █████╗ ',
|
|
46
|
+
'██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║██║ ██║ ██║ ██╔██╗ ██╔══╝ ',
|
|
47
|
+
'╚██████╔╝██║ ███████╗██║ ╚████║███████╗╚██████╔╝██╔╝ ██╗███████╗',
|
|
48
|
+
' ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝',
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
// 32 cols — compact box-drawing caps.
|
|
52
|
+
const WORDMARK_SMALL = [
|
|
53
|
+
'╔═╗ ╔═╗ ╔═╗ ╔╗╔ ╦ ╦ ╦ ═╗ ╦ ╔═╗',
|
|
54
|
+
'║ ║ ╠═╝ ║╣ ║║║ ║ ║ ║ ╔╩╦╝ ║╣ ',
|
|
55
|
+
'╚═╝ ╩ ╚═╝ ╝╚╝ ╩═╝ ╚═╝ ╩ ╚═ ╚═╝',
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
// Champagne ramp, light → deep gold (xterm 256).
|
|
59
|
+
const RAMP = [230, 223, 222, 221, 220, 220, 178, 172];
|
|
60
|
+
|
|
61
|
+
function width(lines) {
|
|
62
|
+
return Math.max(...lines.map((l) => l.length));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function banner() {
|
|
66
|
+
const cols = process.stdout.columns || 80;
|
|
67
|
+
const on = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;
|
|
68
|
+
const dim = (s) => (on ? `\x1b[2m${s}\x1b[0m` : s);
|
|
69
|
+
|
|
70
|
+
let mark, word, footer;
|
|
71
|
+
if (cols >= 72) {
|
|
72
|
+
mark = MARK;
|
|
73
|
+
word = WORDMARK;
|
|
74
|
+
footer = `v${VERSION} · the platform, from your terminal · openluxe.co/developers`;
|
|
75
|
+
} else if (cols >= 36) {
|
|
76
|
+
mark = MARK_SMALL;
|
|
77
|
+
word = WORDMARK_SMALL;
|
|
78
|
+
footer = `v${VERSION} · openluxe.co/developers`;
|
|
79
|
+
} else {
|
|
80
|
+
mark = MARK_SMALL;
|
|
81
|
+
word = ['O P E N L U X E'];
|
|
82
|
+
footer = `v${VERSION} · openluxe.co`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Center everything against the widest element that still fits the pane.
|
|
86
|
+
// Blocks get ONE shared left margin (per-line centering would bend the
|
|
87
|
+
// mark's diagonals, since its rows are pre-aligned to each other).
|
|
88
|
+
const frame = Math.min(cols, Math.max(width(mark), width(word), footer.length));
|
|
89
|
+
const center = (line) => ' '.repeat(Math.max(0, Math.floor((frame - line.length) / 2))) + line;
|
|
90
|
+
const shade = (lines) => {
|
|
91
|
+
const pad = ' '.repeat(Math.max(0, Math.floor((frame - width(lines)) / 2)));
|
|
92
|
+
return lines.map((l, i) => {
|
|
93
|
+
const color = RAMP[Math.min(RAMP.length - 1, Math.floor((i / lines.length) * RAMP.length))];
|
|
94
|
+
return on ? `\x1b[38;5;${color}m${pad}${l}\x1b[0m` : pad + l;
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
return ['', ...shade(mark), '', ...shade(word), '', dim(center(footer))].join('\n');
|
|
99
|
+
}
|
package/src/cli.js
CHANGED
|
@@ -3,6 +3,7 @@ import { RESOURCES } from './resources.js';
|
|
|
3
3
|
import * as auth from './auth.js';
|
|
4
4
|
import { load, VERSION } from './config.js';
|
|
5
5
|
import { serve as mcpServe } from './mcp.js';
|
|
6
|
+
import { banner } from './banner.js';
|
|
6
7
|
|
|
7
8
|
const C = {
|
|
8
9
|
dim: (s) => `\x1b[2m${s}\x1b[0m`,
|
|
@@ -198,6 +199,7 @@ async function callApi(method, path, { positionals = [], flags = {}, body }) {
|
|
|
198
199
|
|
|
199
200
|
function topHelp() {
|
|
200
201
|
const { token, user, base } = load();
|
|
202
|
+
console.log(banner());
|
|
201
203
|
console.log(`
|
|
202
204
|
${C.bold('openluxe')} — OpenLuxe API command-line client
|
|
203
205
|
|