codeant-cli 0.1.1 → 0.1.2
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/components/Welcome.js +143 -0
- package/src/index.js +35 -29
package/package.json
CHANGED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { Text, Box, useApp } from 'ink';
|
|
3
|
+
|
|
4
|
+
const logo = `
|
|
5
|
+
___ _ _ _
|
|
6
|
+
/ __\\___ __| | ___ / \\ _ __ | |_
|
|
7
|
+
/ / / _ \\ / _\` |/ _ \\/ /\\ | '_ \\| __|
|
|
8
|
+
/ /__| (_) | (_| | __/\\_/ \\ | | | | |_
|
|
9
|
+
\\____/\\___/ \\__,_|\\___\\___/\\_/_| |_|\\__|
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
const tagline = "Your AI-powered code review companion";
|
|
13
|
+
|
|
14
|
+
const commands = [
|
|
15
|
+
{ cmd: 'codeant secrets', desc: 'Scan for secrets in your code' },
|
|
16
|
+
{ cmd: 'codeant login', desc: 'Login to CodeAnt' },
|
|
17
|
+
{ cmd: 'codeant --help', desc: 'Show all commands' },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
export default function Welcome() {
|
|
21
|
+
const { exit } = useApp();
|
|
22
|
+
const [displayedLogo, setDisplayedLogo] = useState('');
|
|
23
|
+
const [displayedTagline, setDisplayedTagline] = useState('');
|
|
24
|
+
const [showCursor, setShowCursor] = useState(true);
|
|
25
|
+
const [phase, setPhase] = useState('logo');
|
|
26
|
+
const [showCommands, setShowCommands] = useState(false);
|
|
27
|
+
|
|
28
|
+
// Typing effect for logo (fast)
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (phase !== 'logo') return;
|
|
31
|
+
|
|
32
|
+
let i = 0;
|
|
33
|
+
const chars = logo.split('');
|
|
34
|
+
const interval = setInterval(() => {
|
|
35
|
+
if (i < chars.length) {
|
|
36
|
+
setDisplayedLogo(prev => prev + chars[i]);
|
|
37
|
+
i++;
|
|
38
|
+
} else {
|
|
39
|
+
clearInterval(interval);
|
|
40
|
+
setPhase('tagline');
|
|
41
|
+
}
|
|
42
|
+
}, 2);
|
|
43
|
+
|
|
44
|
+
return () => clearInterval(interval);
|
|
45
|
+
}, [phase]);
|
|
46
|
+
|
|
47
|
+
// Typing effect for tagline (slower, more dramatic)
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (phase !== 'tagline') return;
|
|
50
|
+
|
|
51
|
+
let i = 0;
|
|
52
|
+
const chars = tagline.split('');
|
|
53
|
+
const interval = setInterval(() => {
|
|
54
|
+
if (i < chars.length) {
|
|
55
|
+
setDisplayedTagline(prev => prev + chars[i]);
|
|
56
|
+
i++;
|
|
57
|
+
} else {
|
|
58
|
+
clearInterval(interval);
|
|
59
|
+
setPhase('commands');
|
|
60
|
+
setShowCommands(true);
|
|
61
|
+
}
|
|
62
|
+
}, 25);
|
|
63
|
+
|
|
64
|
+
return () => clearInterval(interval);
|
|
65
|
+
}, [phase]);
|
|
66
|
+
|
|
67
|
+
// Blinking cursor
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
if (phase === 'commands') {
|
|
70
|
+
setShowCursor(false);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const interval = setInterval(() => {
|
|
74
|
+
setShowCursor(prev => !prev);
|
|
75
|
+
}, 400);
|
|
76
|
+
return () => clearInterval(interval);
|
|
77
|
+
}, [phase]);
|
|
78
|
+
|
|
79
|
+
// Exit after animation
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
if (showCommands) {
|
|
82
|
+
const timeout = setTimeout(() => exit(), 100);
|
|
83
|
+
return () => clearTimeout(timeout);
|
|
84
|
+
}
|
|
85
|
+
}, [showCommands, exit]);
|
|
86
|
+
|
|
87
|
+
const cursor = showCursor ? '|' : ' ';
|
|
88
|
+
|
|
89
|
+
const elements = [
|
|
90
|
+
React.createElement(Text, { key: 'logo', color: 'cyan', bold: true }, displayedLogo)
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
if (phase !== 'logo') {
|
|
94
|
+
elements.push(
|
|
95
|
+
React.createElement(
|
|
96
|
+
Box,
|
|
97
|
+
{ key: 'tagline-box', marginTop: 0 },
|
|
98
|
+
React.createElement(
|
|
99
|
+
Text,
|
|
100
|
+
{ color: 'magenta', italic: true },
|
|
101
|
+
displayedTagline,
|
|
102
|
+
React.createElement(Text, { color: 'gray' }, cursor)
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (showCommands) {
|
|
109
|
+
elements.push(
|
|
110
|
+
React.createElement(Text, { key: 'divider', color: 'gray' }, '─────────────────────────────────────────')
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
elements.push(
|
|
114
|
+
React.createElement(
|
|
115
|
+
Box,
|
|
116
|
+
{ key: 'commands-box', marginTop: 1, flexDirection: 'column' },
|
|
117
|
+
React.createElement(Text, { color: 'yellow', bold: true }, 'Quick Start:'),
|
|
118
|
+
...commands.map((item, idx) =>
|
|
119
|
+
React.createElement(
|
|
120
|
+
Box,
|
|
121
|
+
{ key: `cmd-${idx}`, marginLeft: 2 },
|
|
122
|
+
React.createElement(Text, { color: 'green' }, `$ ${item.cmd}`),
|
|
123
|
+
React.createElement(Text, { color: 'gray' }, ` ${item.desc}`)
|
|
124
|
+
)
|
|
125
|
+
)
|
|
126
|
+
)
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
elements.push(
|
|
130
|
+
React.createElement(
|
|
131
|
+
Box,
|
|
132
|
+
{ key: 'version-box', marginTop: 1 },
|
|
133
|
+
React.createElement(Text, { color: 'gray' }, 'v0.1.0')
|
|
134
|
+
)
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return React.createElement(
|
|
139
|
+
Box,
|
|
140
|
+
{ flexDirection: 'column', padding: 1 },
|
|
141
|
+
...elements
|
|
142
|
+
);
|
|
143
|
+
}
|
package/src/index.js
CHANGED
|
@@ -8,11 +8,16 @@ import SetBaseUrl from './commands/setBaseUrl.js';
|
|
|
8
8
|
import GetBaseUrl from './commands/getBaseUrl.js';
|
|
9
9
|
import Login from './commands/login.js';
|
|
10
10
|
import Logout from './commands/logout.js';
|
|
11
|
+
import Welcome from './components/Welcome.js';
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
.
|
|
15
|
-
|
|
13
|
+
// Show welcome animation if no arguments provided
|
|
14
|
+
if (process.argv.length === 2) {
|
|
15
|
+
render(React.createElement(Welcome));
|
|
16
|
+
} else {
|
|
17
|
+
program
|
|
18
|
+
.name('codeant')
|
|
19
|
+
.description('Code review CLI tool')
|
|
20
|
+
.version('0.1.0');
|
|
16
21
|
|
|
17
22
|
program
|
|
18
23
|
.command('secrets')
|
|
@@ -43,32 +48,33 @@ program
|
|
|
43
48
|
render(React.createElement(Secrets, { scanType, failOn, include, exclude }));
|
|
44
49
|
});
|
|
45
50
|
|
|
46
|
-
program
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
program
|
|
52
|
+
.command('set-base-url <url>')
|
|
53
|
+
.description('Set the API base URL')
|
|
54
|
+
.action((url) => {
|
|
55
|
+
render(React.createElement(SetBaseUrl, { url }));
|
|
56
|
+
});
|
|
52
57
|
|
|
53
|
-
program
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
program
|
|
59
|
+
.command('get-base-url')
|
|
60
|
+
.description('Show the current API base URL')
|
|
61
|
+
.action(() => {
|
|
62
|
+
render(React.createElement(GetBaseUrl));
|
|
63
|
+
});
|
|
59
64
|
|
|
60
|
-
program
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
program
|
|
66
|
+
.command('login')
|
|
67
|
+
.description('Login to CodeAnt')
|
|
68
|
+
.action(() => {
|
|
69
|
+
render(React.createElement(Login));
|
|
70
|
+
});
|
|
66
71
|
|
|
67
|
-
program
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
program
|
|
73
|
+
.command('logout')
|
|
74
|
+
.description('Logout from CodeAnt')
|
|
75
|
+
.action(() => {
|
|
76
|
+
render(React.createElement(Logout));
|
|
77
|
+
});
|
|
73
78
|
|
|
74
|
-
program.parse();
|
|
79
|
+
program.parse();
|
|
80
|
+
}
|