@vee-stack/delta-cli 2.0.4 → 2.0.6
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/dist/analyzer/commands/analyze.js +260 -0
- package/dist/analyzer/commands/config.js +83 -0
- package/dist/analyzer/commands/report.js +38 -0
- package/dist/analyzer/generators/report.generator.js +123 -0
- package/dist/analyzer/index.js +44 -0
- package/dist/analyzer/scanners/project.scanner.js +92 -0
- package/dist/analyzer/validators/contracts.validator.js +42 -0
- package/dist/analyzer/validators/maintainability.validator.js +40 -0
- package/dist/analyzer/validators/observability.validator.js +39 -0
- package/dist/analyzer/validators/performance.validator.js +42 -0
- package/dist/analyzer/validators/security.validator.js +66 -0
- package/dist/analyzer/validators/soc.validator.js +75 -0
- package/dist/apps/cli/src/analyzer/commands/analyze.js +256 -0
- package/dist/apps/cli/src/analyzer/commands/config.js +83 -0
- package/dist/apps/cli/src/analyzer/commands/report.js +38 -0
- package/dist/apps/cli/src/analyzer/generators/report.generator.js +123 -0
- package/dist/apps/cli/src/analyzer/index.js +44 -0
- package/dist/apps/cli/src/analyzer/scanners/project.scanner.js +92 -0
- package/dist/apps/cli/src/analyzer/validators/contracts.validator.js +42 -0
- package/dist/apps/cli/src/analyzer/validators/maintainability.validator.js +40 -0
- package/dist/apps/cli/src/analyzer/validators/observability.validator.js +39 -0
- package/dist/apps/cli/src/analyzer/validators/performance.validator.js +42 -0
- package/dist/apps/cli/src/analyzer/validators/security.validator.js +66 -0
- package/dist/apps/cli/src/analyzer/validators/soc.validator.js +75 -0
- package/dist/apps/cli/src/auth/secure-auth.js +312 -0
- package/dist/apps/cli/src/commands/analyze.js +286 -0
- package/dist/apps/cli/src/commands/auth-new.js +37 -0
- package/dist/apps/cli/src/commands/auth.js +122 -0
- package/dist/apps/cli/src/commands/config.js +49 -0
- package/dist/apps/cli/src/commands/deploy.js +6 -0
- package/dist/apps/cli/src/commands/init.js +47 -0
- package/dist/apps/cli/src/commands/logout.js +23 -0
- package/dist/apps/cli/src/commands/plugins.js +21 -0
- package/dist/apps/cli/src/commands/status.js +80 -0
- package/dist/apps/cli/src/commands/sync.js +6 -0
- package/dist/apps/cli/src/commands/whoami.js +115 -0
- package/dist/apps/cli/src/components/Dashboard.js +168 -0
- package/dist/apps/cli/src/components/DeltaApp.js +56 -0
- package/dist/apps/cli/src/components/UnifiedManager.js +324 -0
- package/dist/apps/cli/src/core/audit.js +184 -0
- package/dist/apps/cli/src/core/completion.js +294 -0
- package/dist/apps/cli/src/core/contracts.js +6 -0
- package/dist/apps/cli/src/core/engine.js +124 -0
- package/dist/apps/cli/src/core/exit-codes.js +71 -0
- package/dist/apps/cli/src/core/hooks.js +181 -0
- package/dist/apps/cli/src/core/index.js +7 -0
- package/dist/apps/cli/src/core/policy.js +115 -0
- package/dist/apps/cli/src/core/profiles.js +161 -0
- package/dist/apps/cli/src/core/wizard.js +203 -0
- package/dist/apps/cli/src/index.js +636 -0
- package/dist/apps/cli/src/interactive/index.js +11 -0
- package/dist/apps/cli/src/plugins/GitStatusPlugin.js +99 -0
- package/dist/apps/cli/src/providers/ai-provider.js +74 -0
- package/dist/apps/cli/src/providers/local-provider.js +302 -0
- package/dist/apps/cli/src/providers/remote-provider.js +100 -0
- package/dist/apps/cli/src/types/api.js +3 -0
- package/dist/apps/cli/src/ui.js +219 -0
- package/dist/apps/cli/src/welcome.js +81 -0
- package/dist/auth/secure-auth.js +418 -0
- package/dist/bundle.js +45 -45
- package/dist/commands/analyze.js +384 -0
- package/dist/commands/auth-new.js +37 -0
- package/dist/commands/auth.js +134 -0
- package/dist/commands/config.js +51 -0
- package/dist/commands/deploy.js +6 -0
- package/dist/commands/init.js +47 -0
- package/dist/commands/logout.js +31 -0
- package/dist/commands/plugins.js +21 -0
- package/dist/commands/status.js +82 -0
- package/dist/commands/sync.js +6 -0
- package/dist/commands/whoami.js +72 -0
- package/dist/components/Dashboard.js +169 -0
- package/dist/components/DeltaApp.js +57 -0
- package/dist/components/UnifiedManager.js +344 -0
- package/dist/core/audit.js +184 -0
- package/dist/core/completion.js +294 -0
- package/dist/core/contracts.js +6 -0
- package/dist/core/engine.js +124 -0
- package/dist/core/exit-codes.js +71 -0
- package/dist/core/hooks.js +181 -0
- package/dist/core/index.js +7 -0
- package/dist/core/policy.js +115 -0
- package/dist/core/profiles.js +161 -0
- package/dist/core/wizard.js +203 -0
- package/dist/index.js +387 -0
- package/dist/interactive/index.js +11 -0
- package/dist/packages/domain/src/constitution/contracts/index.js +43 -0
- package/dist/packages/domain/src/constitution/contracts/ts.rules.js +268 -0
- package/dist/packages/domain/src/constitution/index.js +139 -0
- package/dist/packages/domain/src/constitution/maintainability/index.js +43 -0
- package/dist/packages/domain/src/constitution/maintainability/ts.rules.js +344 -0
- package/dist/packages/domain/src/constitution/observability/index.js +43 -0
- package/dist/packages/domain/src/constitution/observability/ts.rules.js +307 -0
- package/dist/packages/domain/src/constitution/performance/index.js +43 -0
- package/dist/packages/domain/src/constitution/performance/ts.rules.js +325 -0
- package/dist/packages/domain/src/constitution/security/index.js +50 -0
- package/dist/packages/domain/src/constitution/security/ts.rules.js +267 -0
- package/dist/packages/domain/src/constitution/soc/index.js +43 -0
- package/dist/packages/domain/src/constitution/soc/ts.rules.js +360 -0
- package/dist/packages/domain/src/contracts/analysis.contract.js +18 -0
- package/dist/packages/domain/src/contracts/index.js +7 -0
- package/dist/packages/domain/src/contracts/projects.contract.js +18 -0
- package/dist/packages/domain/src/control/registry/rules.registry.js +29 -0
- package/dist/packages/domain/src/control/schemas/policies.js +6 -0
- package/dist/packages/domain/src/core/analysis/discovery.js +163 -0
- package/dist/packages/domain/src/core/analysis/engine.contract.js +298 -0
- package/dist/packages/domain/src/core/analysis/engine.js +77 -0
- package/dist/packages/domain/src/core/analysis/index.js +14 -0
- package/dist/packages/domain/src/core/analysis/orchestrator.js +242 -0
- package/dist/packages/domain/src/core/comparison/engine.js +29 -0
- package/dist/packages/domain/src/core/comparison/index.js +5 -0
- package/dist/packages/domain/src/core/documentation/index.js +5 -0
- package/dist/packages/domain/src/core/documentation/pipeline.js +41 -0
- package/dist/packages/domain/src/core/fs/adapter.js +111 -0
- package/dist/packages/domain/src/core/fs/index.js +5 -0
- package/dist/packages/domain/src/core/parser/unified-parser.js +166 -0
- package/dist/packages/domain/src/index.js +33 -0
- package/dist/packages/domain/src/plugin/registry.js +195 -0
- package/dist/packages/domain/src/plugin/types.js +6 -0
- package/dist/packages/domain/src/ports/analysis.engine.js +7 -0
- package/dist/packages/domain/src/ports/audit.logger.js +7 -0
- package/dist/packages/domain/src/ports/project.repository.js +7 -0
- package/dist/packages/domain/src/rules/index.js +134 -0
- package/dist/packages/domain/src/types/analysis.js +6 -0
- package/dist/packages/domain/src/types/errors.js +53 -0
- package/dist/packages/domain/src/types/fs.js +6 -0
- package/dist/packages/domain/src/types/index.js +7 -0
- package/dist/plugins/GitStatusPlugin.js +93 -0
- package/dist/providers/ai-provider.js +74 -0
- package/dist/providers/local-provider.js +304 -0
- package/dist/providers/remote-provider.js +100 -0
- package/dist/types/api.js +3 -0
- package/dist/ui.js +219 -0
- package/dist/welcome.js +81 -0
- package/package.json +18 -18
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Auth Commands - Professional CLI with interactive prompts
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs/promises';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import * as os from 'os';
|
|
7
|
+
import { icons, startSpinner, stopSpinner, printHeader, printSection, printSuccess, printError, printInfo, printKeyValue, printCommandHint, createTable, password, printWelcome, } from '../ui.js';
|
|
8
|
+
const CONFIG_DIR = path.join(os.homedir(), '.delta');
|
|
9
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
10
|
+
async function loadConfig() {
|
|
11
|
+
try {
|
|
12
|
+
const data = await fs.readFile(CONFIG_FILE, 'utf-8');
|
|
13
|
+
return JSON.parse(data);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return {};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async function saveConfig(config) {
|
|
20
|
+
await fs.mkdir(CONFIG_DIR, { recursive: true });
|
|
21
|
+
await fs.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
22
|
+
}
|
|
23
|
+
export const authCommands = {
|
|
24
|
+
async login(options) {
|
|
25
|
+
printWelcome();
|
|
26
|
+
printHeader('Authentication');
|
|
27
|
+
let token = options.token || process.env.DELTA_PAT;
|
|
28
|
+
// Interactive prompt if no token provided
|
|
29
|
+
if (!token) {
|
|
30
|
+
printInfo('No token provided. Please enter your PAT (Personal Access Token).');
|
|
31
|
+
printCommandHint('delta login --token <your-token>', 'to skip this prompt');
|
|
32
|
+
console.log();
|
|
33
|
+
const tokenInput = await password('Enter PAT (starts with delta_pat_):');
|
|
34
|
+
if (!tokenInput) {
|
|
35
|
+
printError('Authentication cancelled');
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
token = tokenInput;
|
|
39
|
+
}
|
|
40
|
+
// Validate token format
|
|
41
|
+
if (!token.startsWith('delta_pat_')) {
|
|
42
|
+
printError('Invalid PAT token format', 'Token should start with "delta_pat_"');
|
|
43
|
+
console.log();
|
|
44
|
+
printInfo('You can get your PAT from:');
|
|
45
|
+
printCommandHint('https://app.delta.dev/settings/tokens', '');
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
// Load existing config to get custom apiUrl if set
|
|
49
|
+
const existingConfig = await loadConfig();
|
|
50
|
+
const apiUrl = process.env.DELTA_API_URL || existingConfig.apiUrl || 'https://api.delta.dev';
|
|
51
|
+
printSection('Connecting to Platform');
|
|
52
|
+
printKeyValue('API Endpoint', apiUrl);
|
|
53
|
+
console.log();
|
|
54
|
+
startSpinner('Verifying credentials...');
|
|
55
|
+
try {
|
|
56
|
+
const controller = new AbortController();
|
|
57
|
+
const timeout = setTimeout(() => controller.abort(), 10000);
|
|
58
|
+
const response = await fetch(`${apiUrl}/api/me/entitlements`, {
|
|
59
|
+
headers: {
|
|
60
|
+
'Authorization': `Bearer ${token}`,
|
|
61
|
+
'Content-Type': 'application/json',
|
|
62
|
+
},
|
|
63
|
+
signal: controller.signal,
|
|
64
|
+
});
|
|
65
|
+
clearTimeout(timeout);
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const errorText = await response.text().catch(() => response.statusText);
|
|
68
|
+
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
69
|
+
}
|
|
70
|
+
const data = await response.json();
|
|
71
|
+
if (!data.success) {
|
|
72
|
+
throw new Error(data.error?.message || 'Authentication failed');
|
|
73
|
+
}
|
|
74
|
+
// Save config
|
|
75
|
+
await saveConfig({
|
|
76
|
+
pat: token,
|
|
77
|
+
apiUrl,
|
|
78
|
+
lastUsedAt: new Date().toISOString(),
|
|
79
|
+
});
|
|
80
|
+
stopSpinner(true, 'Authentication successful!');
|
|
81
|
+
console.log();
|
|
82
|
+
const user = data.data.user;
|
|
83
|
+
const quota = data.data.quota;
|
|
84
|
+
printHeader('Account Overview');
|
|
85
|
+
// User info table
|
|
86
|
+
const userTable = createTable(['Property', 'Value']);
|
|
87
|
+
userTable.push([icons.user + ' Email', user.email], [icons.package + ' Plan', user.plan], [icons.chart + ' Quota Used', `${quota.used}/${quota.limit} reports`], [icons.lock + ' Config', CONFIG_FILE]);
|
|
88
|
+
console.log(userTable.toString());
|
|
89
|
+
console.log();
|
|
90
|
+
printSuccess(`Welcome back, ${user.email.split('@')[0]}! 🎉`);
|
|
91
|
+
console.log();
|
|
92
|
+
printCommandHint('delta whoami', 'to see full account details');
|
|
93
|
+
printCommandHint('delta analyze', 'to start analyzing code');
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
stopSpinner(false, 'Authentication failed');
|
|
97
|
+
console.log();
|
|
98
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
99
|
+
printError('Request timeout (10s)', 'Check if the server is running and accessible');
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
103
|
+
if (message.includes('401')) {
|
|
104
|
+
printError('Invalid or expired token', 'Generate a new token from the web app');
|
|
105
|
+
}
|
|
106
|
+
else if (message.includes('ENOTFOUND') || message.includes('ECONNREFUSED')) {
|
|
107
|
+
printError('Cannot connect to server', 'Check your internet connection and API URL');
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
printError(message);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
console.log();
|
|
114
|
+
printInfo('Need help? Visit: https://docs.delta.dev/cli/authentication');
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
// Export individual commands for direct import
|
|
120
|
+
export const loginCommand = authCommands.login;
|
|
121
|
+
export { loadConfig, saveConfig, CONFIG_FILE };
|
|
122
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Command - Manage CLI configuration
|
|
3
|
+
*/
|
|
4
|
+
import { loadConfig, saveConfig, CONFIG_FILE } from './auth.js';
|
|
5
|
+
export async function configCommand(options) {
|
|
6
|
+
const config = await loadConfig();
|
|
7
|
+
if (options.get) {
|
|
8
|
+
const value = config[options.get];
|
|
9
|
+
if (value !== undefined) {
|
|
10
|
+
console.log(`${options.get}: ${value}`);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
console.log(`${options.get}: (not set)`);
|
|
14
|
+
}
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (options.set) {
|
|
18
|
+
const [key, value] = options.set.split('=');
|
|
19
|
+
if (!key || value === undefined) {
|
|
20
|
+
console.error('❌ Error: Invalid format. Use: key=value');
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const newConfig = {
|
|
24
|
+
...config,
|
|
25
|
+
pat: config.pat || '',
|
|
26
|
+
apiUrl: config.apiUrl || 'https://api.delta.dev',
|
|
27
|
+
[key]: value,
|
|
28
|
+
};
|
|
29
|
+
await saveConfig(newConfig);
|
|
30
|
+
console.log(`✅ Set ${key} = ${value}`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (options.list || (!options.get && !options.set)) {
|
|
34
|
+
console.log('🔧 Delta CLI Configuration');
|
|
35
|
+
console.log(` Config file: ${CONFIG_FILE}`);
|
|
36
|
+
console.log();
|
|
37
|
+
if (config.pat) {
|
|
38
|
+
console.log(' PAT: ✅ Set (hidden)');
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
console.log(' PAT: ❌ Not set');
|
|
42
|
+
}
|
|
43
|
+
console.log(` API URL: ${config.apiUrl || 'https://api.delta.dev (default)'}`);
|
|
44
|
+
if (config.lastUsedAt) {
|
|
45
|
+
console.log(` Last used: ${new Date(config.lastUsedAt).toLocaleString()}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Init Command - Initialize a new Delta project
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs/promises';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
export async function initCommand(projectPath, options) {
|
|
7
|
+
const targetPath = path.resolve(projectPath);
|
|
8
|
+
const configPath = path.join(targetPath, 'delta.config.json');
|
|
9
|
+
try {
|
|
10
|
+
// Check if directory exists
|
|
11
|
+
await fs.access(targetPath);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
console.log(`📁 Creating directory: ${targetPath}`);
|
|
15
|
+
await fs.mkdir(targetPath, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
// Check if config already exists
|
|
18
|
+
try {
|
|
19
|
+
await fs.access(configPath);
|
|
20
|
+
if (!options.force) {
|
|
21
|
+
console.log('⚠️ Delta config already exists');
|
|
22
|
+
console.log(' Use --force to overwrite');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Config doesn't exist, continue
|
|
28
|
+
}
|
|
29
|
+
// Create default config
|
|
30
|
+
const config = {
|
|
31
|
+
name: path.basename(targetPath),
|
|
32
|
+
version: '1.0.0',
|
|
33
|
+
template: options.template || 'default',
|
|
34
|
+
createdAt: new Date().toISOString(),
|
|
35
|
+
settings: {
|
|
36
|
+
include: ['src/**/*'],
|
|
37
|
+
exclude: ['node_modules', 'dist', '.git'],
|
|
38
|
+
maxFileSize: 10485760,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
42
|
+
console.log('✅ Project initialized');
|
|
43
|
+
console.log(` Path: ${targetPath}`);
|
|
44
|
+
console.log(` Config: ${configPath}`);
|
|
45
|
+
console.log(` Template: ${config.template}`);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logout Command - Remove stored authentication
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs/promises';
|
|
5
|
+
import { CONFIG_FILE, loadConfig } from './auth.js';
|
|
6
|
+
export async function logoutCommand() {
|
|
7
|
+
try {
|
|
8
|
+
const config = await loadConfig();
|
|
9
|
+
if (!config.pat) {
|
|
10
|
+
console.log('ℹ️ Not currently authenticated');
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
// Remove the config file
|
|
14
|
+
await fs.unlink(CONFIG_FILE);
|
|
15
|
+
console.log('✅ Successfully logged out');
|
|
16
|
+
console.log(' Authentication data removed');
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
console.error('❌ Error during logout:', error instanceof Error ? error.message : String(error));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=logout.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { printSuccess, printInfo } from '../ui.js';
|
|
2
|
+
export async function pluginsCommand(options) {
|
|
3
|
+
if (options.list) {
|
|
4
|
+
printInfo('Installed plugins:');
|
|
5
|
+
}
|
|
6
|
+
else if (options.install) {
|
|
7
|
+
printInfo(`Installing plugin: ${options.install}`);
|
|
8
|
+
printSuccess('Plugin installed successfully');
|
|
9
|
+
}
|
|
10
|
+
else if (options.uninstall) {
|
|
11
|
+
printInfo(`Uninstalling plugin: ${options.uninstall}`);
|
|
12
|
+
printSuccess('Plugin uninstalled successfully');
|
|
13
|
+
}
|
|
14
|
+
else if (options.search) {
|
|
15
|
+
printInfo(`Searching for plugins: ${options.search}`);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
printInfo('Use --list, --install, --uninstall, or --search');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=plugins.js.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Status Command - Professional project and connection status
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs/promises';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { loadConfig } from './auth.js';
|
|
7
|
+
import { icons, startSpinner, stopSpinner, printWelcome, printHeader, printSection, printSuccess, printError, printWarning, printInfo, printKeyValue, printCommandHint, createTable, printDivider, confirm, } from '../ui.js';
|
|
8
|
+
export async function statusCommand(projectPath, _options) {
|
|
9
|
+
const targetPath = path.resolve(projectPath);
|
|
10
|
+
printWelcome();
|
|
11
|
+
printHeader('Project Status Check');
|
|
12
|
+
printKeyValue('Path', targetPath);
|
|
13
|
+
console.log();
|
|
14
|
+
// Check for delta config
|
|
15
|
+
printSection('Project Configuration');
|
|
16
|
+
const configPath = path.join(targetPath, 'delta.config.json');
|
|
17
|
+
try {
|
|
18
|
+
await fs.access(configPath);
|
|
19
|
+
const config = JSON.parse(await fs.readFile(configPath, 'utf-8'));
|
|
20
|
+
printSuccess('Configuration found');
|
|
21
|
+
const configTable = createTable(['Property', 'Value']);
|
|
22
|
+
configTable.push([icons.folder + ' Name', config.name || 'Unnamed'], [icons.folder + ' Type', config.type || 'default'], [icons.gear + ' Version', config.version || 'N/A'], [icons.info + ' Config File', configPath]);
|
|
23
|
+
console.log(configTable.toString());
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
printWarning('No Delta project found');
|
|
27
|
+
printInfo('Initialize a new project:');
|
|
28
|
+
printCommandHint(`delta init ${projectPath}`, 'to create a new project');
|
|
29
|
+
const shouldInit = await confirm('Would you like to initialize now?', true);
|
|
30
|
+
if (shouldInit) {
|
|
31
|
+
console.log();
|
|
32
|
+
printInfo('Run: delta init ' + projectPath);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
console.log();
|
|
36
|
+
printDivider();
|
|
37
|
+
// Check auth status
|
|
38
|
+
printSection('Authentication');
|
|
39
|
+
const auth = await loadConfig();
|
|
40
|
+
if (auth.pat) {
|
|
41
|
+
printSuccess('Authenticated');
|
|
42
|
+
printKeyValue('API URL', auth.apiUrl || 'default');
|
|
43
|
+
// Test connection
|
|
44
|
+
const apiUrl = auth.apiUrl || process.env.DELTA_API_URL || 'https://api.delta.dev';
|
|
45
|
+
startSpinner('Testing connection...');
|
|
46
|
+
try {
|
|
47
|
+
const response = await fetch(`${apiUrl}/api/me/entitlements`, {
|
|
48
|
+
headers: { 'Authorization': `Bearer ${auth.pat}` },
|
|
49
|
+
});
|
|
50
|
+
if (response.ok) {
|
|
51
|
+
stopSpinner(true, 'Connection active');
|
|
52
|
+
const data = await response.json();
|
|
53
|
+
if (data.success) {
|
|
54
|
+
printKeyValue('User', data.data.user.email);
|
|
55
|
+
printKeyValue('Plan', data.data.user.plan);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
stopSpinner(false, 'Authentication expired');
|
|
60
|
+
printError('Your session has expired');
|
|
61
|
+
printCommandHint('delta login --token <new-pat>', 'to re-authenticate');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
stopSpinner(false, 'API unreachable');
|
|
66
|
+
printError('Cannot connect to Delta API');
|
|
67
|
+
printInfo('Check your internet connection or API URL configuration');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
printError('Not authenticated');
|
|
72
|
+
printInfo('Please login to access cloud features:');
|
|
73
|
+
printCommandHint('delta login --token <pat>', 'to authenticate');
|
|
74
|
+
}
|
|
75
|
+
console.log();
|
|
76
|
+
printDivider();
|
|
77
|
+
printCommandHint('delta analyze', 'to analyze your project');
|
|
78
|
+
printCommandHint('delta whoami', 'to see account details');
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Whoami Command - Professional user info display
|
|
3
|
+
*/
|
|
4
|
+
import { loadConfig } from './auth.js';
|
|
5
|
+
import { icons, startSpinner, stopSpinner, printHeader, printSection, printSuccess, printError, printWarning, printInfo, printCommandHint, createTable, formatBytes, printDivider, } from '../ui.js';
|
|
6
|
+
export async function whoamiCommand(_options) {
|
|
7
|
+
try {
|
|
8
|
+
const config = await loadConfig();
|
|
9
|
+
if (!config.pat) {
|
|
10
|
+
printHeader('Authentication Status');
|
|
11
|
+
printError('Not authenticated');
|
|
12
|
+
console.log();
|
|
13
|
+
printInfo('Please login first:');
|
|
14
|
+
printCommandHint('delta login', 'to authenticate with your PAT');
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
printHeader('Loading Account Information');
|
|
18
|
+
startSpinner('Fetching user data...');
|
|
19
|
+
const apiUrl = config.apiUrl || process.env.DELTA_API_URL || 'https://api.delta.dev';
|
|
20
|
+
const response = await fetch(`${apiUrl}/api/me/entitlements`, {
|
|
21
|
+
headers: {
|
|
22
|
+
'Authorization': `Bearer ${config.pat}`,
|
|
23
|
+
'Content-Type': 'application/json',
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
stopSpinner(false);
|
|
28
|
+
if (response.status === 401) {
|
|
29
|
+
printError('Authentication expired or invalid');
|
|
30
|
+
console.log();
|
|
31
|
+
printInfo('Please login again:');
|
|
32
|
+
printCommandHint('delta login --token <new-pat>', 'to re-authenticate');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`API error: ${response.status} ${response.statusText}`);
|
|
36
|
+
}
|
|
37
|
+
const data = await response.json();
|
|
38
|
+
if (!data.success) {
|
|
39
|
+
throw new Error(data.error?.message || 'Failed to fetch user info');
|
|
40
|
+
}
|
|
41
|
+
stopSpinner(true);
|
|
42
|
+
console.log();
|
|
43
|
+
const user = data.data.user;
|
|
44
|
+
const quota = data.data.quota;
|
|
45
|
+
const limits = data.data.limits;
|
|
46
|
+
// User Info Section
|
|
47
|
+
printHeader('User Profile');
|
|
48
|
+
const userTable = createTable(['Property', 'Value']);
|
|
49
|
+
userTable.push([icons.user + ' Email', user.email], [icons.user + ' User ID', user.id], [icons.package + ' Plan', formatPlan(user.plan)], [icons.star + ' Role', user.role || user.plan]);
|
|
50
|
+
console.log(userTable.toString());
|
|
51
|
+
printDivider();
|
|
52
|
+
// Plan Limits Section
|
|
53
|
+
printSection('Plan Features');
|
|
54
|
+
const limitsTable = createTable(['Feature', 'Value']);
|
|
55
|
+
limitsTable.push([icons.chart + ' Max Reports/Month', limits.maxReportsPerMonth.toString()], [icons.package + ' Max Report Size', formatBytes(limits.maxReportSizeBytes)], [icons.lock + ' API Access', limits.allowApiAccess ? '✅ Yes' : '❌ No'], [icons.folder + ' Upload Allowed', limits.allowUpload ? '✅ Yes' : '❌ No']);
|
|
56
|
+
console.log(limitsTable.toString());
|
|
57
|
+
printDivider();
|
|
58
|
+
// Quota Section with visual bar
|
|
59
|
+
printSection('Usage This Month');
|
|
60
|
+
const usagePercent = (quota.used / quota.limit) * 100;
|
|
61
|
+
const bar = renderUsageBar(quota.used, quota.limit);
|
|
62
|
+
const quotaTable = createTable(['Metric', 'Value']);
|
|
63
|
+
quotaTable.push([icons.chart + ' Reports Used', `${quota.used} of ${quota.limit}`], [icons.chart + ' Remaining', quota.remaining.toString()], [icons.chart + ' Usage', bar], [icons.info + ' Resets On', new Date(quota.resetAt).toLocaleDateString('en-US', {
|
|
64
|
+
weekday: 'long',
|
|
65
|
+
year: 'numeric',
|
|
66
|
+
month: 'long',
|
|
67
|
+
day: 'numeric'
|
|
68
|
+
})]);
|
|
69
|
+
console.log(quotaTable.toString());
|
|
70
|
+
console.log();
|
|
71
|
+
if (usagePercent >= 90) {
|
|
72
|
+
printWarning(`You're using ${usagePercent.toFixed(0)}% of your monthly quota!`);
|
|
73
|
+
printCommandHint('delta upgrade', 'to increase your limits (coming soon)');
|
|
74
|
+
}
|
|
75
|
+
else if (usagePercent >= 75) {
|
|
76
|
+
printInfo(`Usage: ${usagePercent.toFixed(0)}% of monthly quota`);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
printSuccess(`Usage: ${usagePercent.toFixed(0)}% of monthly quota`);
|
|
80
|
+
}
|
|
81
|
+
console.log();
|
|
82
|
+
printCommandHint('delta analyze', 'to run a code analysis');
|
|
83
|
+
printCommandHint('delta status', 'to check project status');
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
stopSpinner(false);
|
|
87
|
+
console.log();
|
|
88
|
+
printError(error instanceof Error ? error.message : String(error));
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function formatPlan(plan) {
|
|
93
|
+
const planColors = {
|
|
94
|
+
'individual_free': '🔷 Free',
|
|
95
|
+
'individual_pro': '💎 Pro',
|
|
96
|
+
'individual_team': '👥 Team',
|
|
97
|
+
'enterprise': '🏢 Enterprise',
|
|
98
|
+
};
|
|
99
|
+
return planColors[plan] || plan;
|
|
100
|
+
}
|
|
101
|
+
function renderUsageBar(used, limit) {
|
|
102
|
+
const percentage = Math.min((used / limit) * 100, 100);
|
|
103
|
+
const filledBlocks = Math.round((percentage / 100) * 20);
|
|
104
|
+
const emptyBlocks = 20 - filledBlocks;
|
|
105
|
+
let color;
|
|
106
|
+
if (percentage >= 90)
|
|
107
|
+
color = (s) => `\x1b[31m${s}\x1b[0m`; // red
|
|
108
|
+
else if (percentage >= 75)
|
|
109
|
+
color = (s) => `\x1b[33m${s}\x1b[0m`; // yellow
|
|
110
|
+
else
|
|
111
|
+
color = (s) => `\x1b[32m${s}\x1b[0m`; // green
|
|
112
|
+
const bar = color('█'.repeat(filledBlocks)) + '░'.repeat(emptyBlocks);
|
|
113
|
+
return `${bar} ${percentage.toFixed(1)}%`;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=whoami.js.map
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Enhanced Dashboard Component
|
|
4
|
+
* Visual dashboard with project status, analysis reports, and charts
|
|
5
|
+
*/
|
|
6
|
+
import { useState, useEffect } from 'react';
|
|
7
|
+
import { Box, Text, useApp, useInput } from 'ink';
|
|
8
|
+
import Spinner from 'ink-spinner';
|
|
9
|
+
import Divider from 'ink-divider';
|
|
10
|
+
// Sparkline chart component
|
|
11
|
+
const Sparkline = ({ data, width = 20 }) => {
|
|
12
|
+
if (data.length === 0)
|
|
13
|
+
return _jsx(Text, { dimColor: true, children: "no data" });
|
|
14
|
+
const max = Math.max(...data, 1);
|
|
15
|
+
const min = Math.min(...data, 0);
|
|
16
|
+
const range = max - min || 1;
|
|
17
|
+
const bars = ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'];
|
|
18
|
+
const normalized = data.map(v => {
|
|
19
|
+
const idx = Math.floor(((v - min) / range) * (bars.length - 1));
|
|
20
|
+
return bars[Math.min(idx, bars.length - 1)];
|
|
21
|
+
});
|
|
22
|
+
// Truncate or pad to width
|
|
23
|
+
const display = normalized.slice(-width);
|
|
24
|
+
while (display.length < width) {
|
|
25
|
+
display.unshift(bars[0]);
|
|
26
|
+
}
|
|
27
|
+
return _jsx(Text, { color: "cyan", children: display.join('') });
|
|
28
|
+
};
|
|
29
|
+
// Progress bar component
|
|
30
|
+
const ProgressBar = ({ value, max, width = 20 }) => {
|
|
31
|
+
const percentage = Math.min(Math.max(value / max, 0), 1);
|
|
32
|
+
const filled = Math.floor(percentage * width);
|
|
33
|
+
const empty = width - filled;
|
|
34
|
+
const bar = '█'.repeat(filled) + '░'.repeat(empty);
|
|
35
|
+
const color = percentage > 0.7 ? 'red' : percentage > 0.4 ? 'yellow' : 'green';
|
|
36
|
+
return (_jsxs(Text, { children: [_jsx(Text, { color: color, children: bar }), _jsxs(Text, { dimColor: true, children: [" ", Math.round(percentage * 100), "%"] })] }));
|
|
37
|
+
};
|
|
38
|
+
// Status indicator
|
|
39
|
+
const StatusIndicator = ({ status }) => {
|
|
40
|
+
const icons = { ok: '✅', warning: '⚠️', error: '❌' };
|
|
41
|
+
const colors = { ok: 'green', warning: 'yellow', error: 'red' };
|
|
42
|
+
return _jsx(Text, { color: colors[status], children: icons[status] });
|
|
43
|
+
};
|
|
44
|
+
// Project row component
|
|
45
|
+
const ProjectRow = ({ project, isSelected }) => {
|
|
46
|
+
const timeAgo = project.lastAnalyze
|
|
47
|
+
? formatTimeAgo(project.lastAnalyze)
|
|
48
|
+
: 'never';
|
|
49
|
+
const totalFindings = project.findings.high + project.findings.medium + project.findings.low;
|
|
50
|
+
const findingsColor = project.findings.high > 0 ? 'red' : project.findings.medium > 0 ? 'yellow' : 'green';
|
|
51
|
+
return (_jsxs(Box, { flexDirection: "row", gap: 2, children: [_jsx(Box, { width: 3, children: isSelected ? _jsx(Text, { color: "cyan", children: "\u276F" }) : _jsx(Text, { children: " " }) }), _jsx(Box, { width: 12, children: _jsx(StatusIndicator, { status: project.status }) }), _jsx(Box, { width: 20, children: _jsx(Text, { bold: isSelected, children: project.name }) }), _jsx(Box, { width: 12, children: _jsx(Text, { dimColor: true, children: timeAgo }) }), _jsx(Box, { width: 10, children: _jsxs(Text, { color: findingsColor, children: [totalFindings, " (", project.findings.high, "H)"] }) }), _jsx(Box, { width: 10, children: _jsxs(Text, { dimColor: true, children: [project.duration, "ms"] }) })] }));
|
|
52
|
+
};
|
|
53
|
+
// Stats box component
|
|
54
|
+
const StatsBox = ({ stats }) => {
|
|
55
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 2, paddingY: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "\uD83D\uDCCA Usage Statistics" }), _jsx(Box, { children: _jsxs(Box, { flexDirection: "row", gap: 4, children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "Total Commands" }), _jsx(Text, { bold: true, children: stats.totalCommands })] }), _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "Success Rate" }), _jsxs(Text, { bold: true, color: stats.successRate > 80 ? 'green' : 'yellow', children: [stats.successRate, "%"] }), _jsx(Sparkline, { data: [stats.successRate, 100 - stats.successRate], width: 10 })] }), _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "Avg Duration" }), _jsxs(Text, { bold: true, children: [stats.avgDuration, "ms"] })] })] }) }), _jsxs(Box, { children: [_jsx(Text, { dimColor: true, children: "Most Used: " }), _jsx(Text, { children: stats.mostUsed.join(', ') || 'none' })] })] }));
|
|
56
|
+
};
|
|
57
|
+
// Findings chart
|
|
58
|
+
const FindingsChart = ({ projects }) => {
|
|
59
|
+
const totalFindings = projects.reduce((sum, p) => sum + p.findings.high + p.findings.medium + p.findings.low, 0);
|
|
60
|
+
const highCount = projects.reduce((sum, p) => sum + p.findings.high, 0);
|
|
61
|
+
const mediumCount = projects.reduce((sum, p) => sum + p.findings.medium, 0);
|
|
62
|
+
const lowCount = projects.reduce((sum, p) => sum + p.findings.low, 0);
|
|
63
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 2, paddingY: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "\uD83D\uDD0D Findings Distribution" }), _jsxs(Box, { marginY: 1, flexDirection: "column", gap: 1, children: [_jsxs(Box, { flexDirection: "row", gap: 2, children: [_jsx(Box, { width: 10, children: _jsx(Text, { color: "red", children: "High:" }) }), _jsx(ProgressBar, { value: highCount, max: Math.max(totalFindings, 1), width: 25 }), _jsxs(Text, { color: "red", children: [" ", highCount] })] }), _jsxs(Box, { flexDirection: "row", gap: 2, children: [_jsx(Box, { width: 10, children: _jsx(Text, { color: "yellow", children: "Medium:" }) }), _jsx(ProgressBar, { value: mediumCount, max: Math.max(totalFindings, 1), width: 25 }), _jsxs(Text, { color: "yellow", children: [" ", mediumCount] })] }), _jsxs(Box, { flexDirection: "row", gap: 2, children: [_jsx(Box, { width: 10, children: _jsx(Text, { color: "green", children: "Low:" }) }), _jsx(ProgressBar, { value: lowCount, max: Math.max(totalFindings, 1), width: 25 }), _jsxs(Text, { color: "green", children: [" ", lowCount] })] })] })] }));
|
|
64
|
+
};
|
|
65
|
+
// Mock data generator
|
|
66
|
+
const generateMockData = () => {
|
|
67
|
+
const projects = [
|
|
68
|
+
{
|
|
69
|
+
name: 'MyApp',
|
|
70
|
+
path: './myapp',
|
|
71
|
+
status: 'ok',
|
|
72
|
+
lastAnalyze: new Date(Date.now() - 2 * 60 * 1000),
|
|
73
|
+
findings: { high: 0, medium: 2, low: 14 },
|
|
74
|
+
duration: 1250,
|
|
75
|
+
filesAnalyzed: 42,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'WebApp',
|
|
79
|
+
path: './webapp',
|
|
80
|
+
status: 'warning',
|
|
81
|
+
lastAnalyze: new Date(Date.now() - 10 * 60 * 1000),
|
|
82
|
+
findings: { high: 2, medium: 3, low: 8 },
|
|
83
|
+
duration: 890,
|
|
84
|
+
filesAnalyzed: 28,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'API Server',
|
|
88
|
+
path: './api',
|
|
89
|
+
status: 'ok',
|
|
90
|
+
lastAnalyze: new Date(Date.now() - 30 * 60 * 1000),
|
|
91
|
+
findings: { high: 0, medium: 0, low: 5 },
|
|
92
|
+
duration: 2100,
|
|
93
|
+
filesAnalyzed: 156,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: 'Frontend',
|
|
97
|
+
path: './frontend',
|
|
98
|
+
status: 'error',
|
|
99
|
+
lastAnalyze: new Date(Date.now() - 60 * 60 * 1000),
|
|
100
|
+
findings: { high: 5, medium: 12, low: 20 },
|
|
101
|
+
duration: 3400,
|
|
102
|
+
filesAnalyzed: 203,
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
const stats = {
|
|
106
|
+
totalCommands: 127,
|
|
107
|
+
successRate: 94,
|
|
108
|
+
avgDuration: 1450,
|
|
109
|
+
mostUsed: ['analyze', 'status', 'init'],
|
|
110
|
+
};
|
|
111
|
+
return { projects, stats };
|
|
112
|
+
};
|
|
113
|
+
// Helper function
|
|
114
|
+
const formatTimeAgo = (date) => {
|
|
115
|
+
const seconds = Math.floor((Date.now() - date.getTime()) / 1000);
|
|
116
|
+
if (seconds < 60)
|
|
117
|
+
return `${seconds}s ago`;
|
|
118
|
+
const minutes = Math.floor(seconds / 60);
|
|
119
|
+
if (minutes < 60)
|
|
120
|
+
return `${minutes}m ago`;
|
|
121
|
+
const hours = Math.floor(minutes / 60);
|
|
122
|
+
if (hours < 24)
|
|
123
|
+
return `${hours}h ago`;
|
|
124
|
+
return `${Math.floor(hours / 24)}d ago`;
|
|
125
|
+
};
|
|
126
|
+
// Main Dashboard Component
|
|
127
|
+
export const EnhancedDashboard = () => {
|
|
128
|
+
const { exit } = useApp();
|
|
129
|
+
const [loading, setLoading] = useState(true);
|
|
130
|
+
const [data, setData] = useState(null);
|
|
131
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
132
|
+
const [showDetail, setShowDetail] = useState(false);
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
// Simulate loading data
|
|
135
|
+
const timer = setTimeout(() => {
|
|
136
|
+
setData(generateMockData());
|
|
137
|
+
setLoading(false);
|
|
138
|
+
}, 800);
|
|
139
|
+
return () => clearTimeout(timer);
|
|
140
|
+
}, []);
|
|
141
|
+
useInput((input, key) => {
|
|
142
|
+
if (key.escape || input === 'q') {
|
|
143
|
+
exit();
|
|
144
|
+
}
|
|
145
|
+
if (key.return && data) {
|
|
146
|
+
setShowDetail(true);
|
|
147
|
+
}
|
|
148
|
+
if (key.upArrow && data) {
|
|
149
|
+
setSelectedIndex(i => Math.max(0, i - 1));
|
|
150
|
+
}
|
|
151
|
+
if (key.downArrow && data) {
|
|
152
|
+
setSelectedIndex(i => Math.min(data.projects.length - 1, i + 1));
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
if (loading) {
|
|
156
|
+
return (_jsxs(Box, { flexDirection: "column", alignItems: "center", padding: 2, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { children: " Loading dashboard data..." })] }));
|
|
157
|
+
}
|
|
158
|
+
if (!data) {
|
|
159
|
+
return (_jsx(Box, { padding: 2, children: _jsx(Text, { color: "red", children: "Failed to load dashboard data" }) }));
|
|
160
|
+
}
|
|
161
|
+
if (showDetail) {
|
|
162
|
+
const project = data.projects[selectedIndex];
|
|
163
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Text, { bold: true, color: "cyan", children: ["\uD83D\uDCC1 Project Details: ", project.name] }), _jsx(Divider, {}), _jsxs(Box, { flexDirection: "column", gap: 1, marginY: 1, children: [_jsxs(Text, { children: ["Path: ", _jsx(Text, { color: "cyan", children: project.path })] }), _jsxs(Text, { children: ["Status: ", _jsx(StatusIndicator, { status: project.status })] }), _jsxs(Text, { children: ["Files Analyzed: ", _jsx(Text, { bold: true, children: project.filesAnalyzed })] }), _jsxs(Text, { children: ["Duration: ", _jsxs(Text, { bold: true, children: [project.duration, "ms"] })] }), _jsxs(Text, { children: ["Last Analysis: ", project.lastAnalyze?.toLocaleString() || 'never'] })] }), _jsxs(Box, { marginY: 1, children: [_jsx(Text, { bold: true, children: "Findings:" }), _jsxs(Box, { flexDirection: "row", gap: 4, children: [_jsxs(Text, { color: "red", children: ["High: ", project.findings.high] }), _jsxs(Text, { color: "yellow", children: ["Medium: ", project.findings.medium] }), _jsxs(Text, { color: "green", children: ["Low: ", project.findings.low] })] })] }), _jsx(Box, { marginTop: 2, children: _jsx(Text, { dimColor: true, children: "Press Esc or Q to go back" }) })] }));
|
|
164
|
+
}
|
|
165
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, color: "cyan", backgroundColor: "gray", children: [' ', " Delta CLI Dashboard ", ' '] }) }), _jsxs(Box, { flexDirection: "row", gap: 2, marginBottom: 1, children: [_jsx(Box, { width: "50%", children: _jsx(StatsBox, { stats: data.stats }) }), _jsx(Box, { width: "50%", children: _jsx(FindingsChart, { projects: data.projects }) })] }), _jsx(Divider, { title: "Projects" }), _jsxs(Box, { flexDirection: "row", gap: 2, marginY: 1, children: [_jsx(Box, { width: 3, children: _jsx(Text, { children: " " }) }), _jsx(Box, { width: 12, children: _jsx(Text, { dimColor: true, children: "Status" }) }), _jsx(Box, { width: 20, children: _jsx(Text, { dimColor: true, children: "Name" }) }), _jsx(Box, { width: 12, children: _jsx(Text, { dimColor: true, children: "Last" }) }), _jsx(Box, { width: 10, children: _jsx(Text, { dimColor: true, children: "Findings" }) }), _jsx(Box, { width: 10, children: _jsx(Text, { dimColor: true, children: "Duration" }) })] }), _jsx(Box, { flexDirection: "column", children: data.projects.map((project, index) => (_jsx(ProjectRow, { project: project, isSelected: index === selectedIndex }, project.name))) }), _jsx(Box, { marginTop: 2, children: _jsx(Text, { dimColor: true, children: "\u2191\u2193 Navigate \u2022 Enter Details \u2022 Q/Esc Exit" }) })] }));
|
|
166
|
+
};
|
|
167
|
+
export default EnhancedDashboard;
|
|
168
|
+
//# sourceMappingURL=Dashboard.js.map
|