@vee-stack/delta-cli 2.0.4 → 2.0.5

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.
Files changed (135) hide show
  1. package/dist/analyzer/commands/analyze.js +260 -0
  2. package/dist/analyzer/commands/config.js +83 -0
  3. package/dist/analyzer/commands/report.js +38 -0
  4. package/dist/analyzer/generators/report.generator.js +123 -0
  5. package/dist/analyzer/index.js +44 -0
  6. package/dist/analyzer/scanners/project.scanner.js +92 -0
  7. package/dist/analyzer/validators/contracts.validator.js +42 -0
  8. package/dist/analyzer/validators/maintainability.validator.js +40 -0
  9. package/dist/analyzer/validators/observability.validator.js +39 -0
  10. package/dist/analyzer/validators/performance.validator.js +42 -0
  11. package/dist/analyzer/validators/security.validator.js +66 -0
  12. package/dist/analyzer/validators/soc.validator.js +75 -0
  13. package/dist/apps/cli/src/analyzer/commands/analyze.js +256 -0
  14. package/dist/apps/cli/src/analyzer/commands/config.js +83 -0
  15. package/dist/apps/cli/src/analyzer/commands/report.js +38 -0
  16. package/dist/apps/cli/src/analyzer/generators/report.generator.js +123 -0
  17. package/dist/apps/cli/src/analyzer/index.js +44 -0
  18. package/dist/apps/cli/src/analyzer/scanners/project.scanner.js +92 -0
  19. package/dist/apps/cli/src/analyzer/validators/contracts.validator.js +42 -0
  20. package/dist/apps/cli/src/analyzer/validators/maintainability.validator.js +40 -0
  21. package/dist/apps/cli/src/analyzer/validators/observability.validator.js +39 -0
  22. package/dist/apps/cli/src/analyzer/validators/performance.validator.js +42 -0
  23. package/dist/apps/cli/src/analyzer/validators/security.validator.js +66 -0
  24. package/dist/apps/cli/src/analyzer/validators/soc.validator.js +75 -0
  25. package/dist/apps/cli/src/auth/secure-auth.js +312 -0
  26. package/dist/apps/cli/src/commands/analyze.js +286 -0
  27. package/dist/apps/cli/src/commands/auth-new.js +37 -0
  28. package/dist/apps/cli/src/commands/auth.js +122 -0
  29. package/dist/apps/cli/src/commands/config.js +49 -0
  30. package/dist/apps/cli/src/commands/deploy.js +6 -0
  31. package/dist/apps/cli/src/commands/init.js +47 -0
  32. package/dist/apps/cli/src/commands/logout.js +23 -0
  33. package/dist/apps/cli/src/commands/plugins.js +21 -0
  34. package/dist/apps/cli/src/commands/status.js +80 -0
  35. package/dist/apps/cli/src/commands/sync.js +6 -0
  36. package/dist/apps/cli/src/commands/whoami.js +115 -0
  37. package/dist/apps/cli/src/components/Dashboard.js +168 -0
  38. package/dist/apps/cli/src/components/DeltaApp.js +56 -0
  39. package/dist/apps/cli/src/components/UnifiedManager.js +324 -0
  40. package/dist/apps/cli/src/core/audit.js +184 -0
  41. package/dist/apps/cli/src/core/completion.js +294 -0
  42. package/dist/apps/cli/src/core/contracts.js +6 -0
  43. package/dist/apps/cli/src/core/engine.js +124 -0
  44. package/dist/apps/cli/src/core/exit-codes.js +71 -0
  45. package/dist/apps/cli/src/core/hooks.js +181 -0
  46. package/dist/apps/cli/src/core/index.js +7 -0
  47. package/dist/apps/cli/src/core/policy.js +115 -0
  48. package/dist/apps/cli/src/core/profiles.js +161 -0
  49. package/dist/apps/cli/src/core/wizard.js +203 -0
  50. package/dist/apps/cli/src/index.js +636 -0
  51. package/dist/apps/cli/src/interactive/index.js +11 -0
  52. package/dist/apps/cli/src/plugins/GitStatusPlugin.js +99 -0
  53. package/dist/apps/cli/src/providers/ai-provider.js +74 -0
  54. package/dist/apps/cli/src/providers/local-provider.js +302 -0
  55. package/dist/apps/cli/src/providers/remote-provider.js +100 -0
  56. package/dist/apps/cli/src/types/api.js +3 -0
  57. package/dist/apps/cli/src/ui.js +219 -0
  58. package/dist/apps/cli/src/welcome.js +81 -0
  59. package/dist/auth/secure-auth.js +418 -0
  60. package/dist/bundle.js +45 -45
  61. package/dist/commands/analyze.js +363 -0
  62. package/dist/commands/auth-new.js +37 -0
  63. package/dist/commands/auth.js +133 -0
  64. package/dist/commands/config.js +50 -0
  65. package/dist/commands/deploy.js +6 -0
  66. package/dist/commands/init.js +47 -0
  67. package/dist/commands/logout.js +30 -0
  68. package/dist/commands/plugins.js +21 -0
  69. package/dist/commands/status.js +82 -0
  70. package/dist/commands/sync.js +6 -0
  71. package/dist/commands/whoami.js +71 -0
  72. package/dist/components/Dashboard.js +169 -0
  73. package/dist/components/DeltaApp.js +57 -0
  74. package/dist/components/UnifiedManager.js +344 -0
  75. package/dist/core/audit.js +184 -0
  76. package/dist/core/completion.js +294 -0
  77. package/dist/core/contracts.js +6 -0
  78. package/dist/core/engine.js +124 -0
  79. package/dist/core/exit-codes.js +71 -0
  80. package/dist/core/hooks.js +181 -0
  81. package/dist/core/index.js +7 -0
  82. package/dist/core/policy.js +115 -0
  83. package/dist/core/profiles.js +161 -0
  84. package/dist/core/wizard.js +203 -0
  85. package/dist/index.js +387 -0
  86. package/dist/interactive/index.js +11 -0
  87. package/dist/packages/domain/src/constitution/contracts/index.js +43 -0
  88. package/dist/packages/domain/src/constitution/contracts/ts.rules.js +268 -0
  89. package/dist/packages/domain/src/constitution/index.js +139 -0
  90. package/dist/packages/domain/src/constitution/maintainability/index.js +43 -0
  91. package/dist/packages/domain/src/constitution/maintainability/ts.rules.js +344 -0
  92. package/dist/packages/domain/src/constitution/observability/index.js +43 -0
  93. package/dist/packages/domain/src/constitution/observability/ts.rules.js +307 -0
  94. package/dist/packages/domain/src/constitution/performance/index.js +43 -0
  95. package/dist/packages/domain/src/constitution/performance/ts.rules.js +325 -0
  96. package/dist/packages/domain/src/constitution/security/index.js +50 -0
  97. package/dist/packages/domain/src/constitution/security/ts.rules.js +267 -0
  98. package/dist/packages/domain/src/constitution/soc/index.js +43 -0
  99. package/dist/packages/domain/src/constitution/soc/ts.rules.js +360 -0
  100. package/dist/packages/domain/src/contracts/analysis.contract.js +18 -0
  101. package/dist/packages/domain/src/contracts/index.js +7 -0
  102. package/dist/packages/domain/src/contracts/projects.contract.js +18 -0
  103. package/dist/packages/domain/src/control/registry/rules.registry.js +29 -0
  104. package/dist/packages/domain/src/control/schemas/policies.js +6 -0
  105. package/dist/packages/domain/src/core/analysis/discovery.js +163 -0
  106. package/dist/packages/domain/src/core/analysis/engine.contract.js +298 -0
  107. package/dist/packages/domain/src/core/analysis/engine.js +77 -0
  108. package/dist/packages/domain/src/core/analysis/index.js +14 -0
  109. package/dist/packages/domain/src/core/analysis/orchestrator.js +242 -0
  110. package/dist/packages/domain/src/core/comparison/engine.js +29 -0
  111. package/dist/packages/domain/src/core/comparison/index.js +5 -0
  112. package/dist/packages/domain/src/core/documentation/index.js +5 -0
  113. package/dist/packages/domain/src/core/documentation/pipeline.js +41 -0
  114. package/dist/packages/domain/src/core/fs/adapter.js +111 -0
  115. package/dist/packages/domain/src/core/fs/index.js +5 -0
  116. package/dist/packages/domain/src/core/parser/unified-parser.js +166 -0
  117. package/dist/packages/domain/src/index.js +33 -0
  118. package/dist/packages/domain/src/plugin/registry.js +195 -0
  119. package/dist/packages/domain/src/plugin/types.js +6 -0
  120. package/dist/packages/domain/src/ports/analysis.engine.js +7 -0
  121. package/dist/packages/domain/src/ports/audit.logger.js +7 -0
  122. package/dist/packages/domain/src/ports/project.repository.js +7 -0
  123. package/dist/packages/domain/src/rules/index.js +134 -0
  124. package/dist/packages/domain/src/types/analysis.js +6 -0
  125. package/dist/packages/domain/src/types/errors.js +53 -0
  126. package/dist/packages/domain/src/types/fs.js +6 -0
  127. package/dist/packages/domain/src/types/index.js +7 -0
  128. package/dist/plugins/GitStatusPlugin.js +93 -0
  129. package/dist/providers/ai-provider.js +74 -0
  130. package/dist/providers/local-provider.js +304 -0
  131. package/dist/providers/remote-provider.js +100 -0
  132. package/dist/types/api.js +3 -0
  133. package/dist/ui.js +219 -0
  134. package/dist/welcome.js +81 -0
  135. package/package.json +18 -18
@@ -0,0 +1,56 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from 'react';
3
+ import { Box, Text, useApp } from 'ink';
4
+ import SelectInput from 'ink-select-input';
5
+ import Spinner from 'ink-spinner';
6
+ import Divider from 'ink-divider';
7
+ import { EnhancedDashboard } from './Dashboard.js';
8
+ // Delta Logo Component
9
+ export const DeltaLogo = () => {
10
+ const [frame, setFrame] = useState(0);
11
+ const frames = ['◐', '◓', '◑', '◒'];
12
+ useEffect(() => {
13
+ const timer = setInterval(() => {
14
+ setFrame((f) => (f + 1) % frames.length);
15
+ }, 100);
16
+ return () => clearInterval(timer);
17
+ }, []);
18
+ return (_jsxs(Box, { flexDirection: "column", alignItems: "center", padding: 1, children: [_jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: "\u2554\u2550\u2550\u2550" }), _jsx(Text, { color: "magenta", children: "DELTA" }), _jsx(Text, { color: "cyan", children: "\u2550\u2550\u2550\u2557" })] }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: [frames[frame], " Next-gen code analysis"] }) })] }));
19
+ };
20
+ // Main App Component
21
+ export const DeltaApp = () => {
22
+ const { exit } = useApp();
23
+ const [currentView, setCurrentView] = useState('menu');
24
+ const menuItems = [
25
+ { label: '📊 Dashboard', value: 'dashboard' },
26
+ { label: '🔍 Analyze', value: 'analyze' },
27
+ { label: '☁️ Sync', value: 'sync' },
28
+ { label: '⚙️ Settings', value: 'settings' },
29
+ { label: '❌ Exit', value: 'exit' },
30
+ ];
31
+ const handleSelect = (item) => {
32
+ if (item.value === 'exit') {
33
+ exit();
34
+ }
35
+ else if (item.value === 'dashboard') {
36
+ setCurrentView('dashboard');
37
+ }
38
+ };
39
+ if (currentView === 'dashboard') {
40
+ return _jsx(EnhancedDashboard, {});
41
+ }
42
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(DeltaLogo, {}), _jsx(Box, { marginTop: 1, marginBottom: 1, children: _jsx(Divider, { title: "Main Menu" }) }), _jsx(Box, { children: _jsx(SelectInput, { items: menuItems, onSelect: handleSelect }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press Enter to select \u2022 Q to quit" }) })] }));
43
+ };
44
+ // Loading Screen
45
+ export const LoadingScreen = ({ message = 'Loading...' }) => {
46
+ return (_jsxs(Box, { flexDirection: "column", alignItems: "center", padding: 2, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsxs(Text, { children: [" ", message] })] }));
47
+ };
48
+ // Error Display
49
+ export const ErrorDisplay = ({ error }) => {
50
+ return (_jsx(Box, { flexDirection: "column", padding: 1, children: _jsxs(Text, { bold: true, color: "red", children: ["\u274C Error: ", error.message] }) }));
51
+ };
52
+ // Success Message
53
+ export const SuccessMessage = ({ message }) => {
54
+ return (_jsx(Box, { padding: 1, children: _jsxs(Text, { color: "green", children: ["\u2713 ", message] }) }));
55
+ };
56
+ //# sourceMappingURL=DeltaApp.js.map
@@ -0,0 +1,324 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Delta Unified Manager - Professional TUI Dashboard
4
+ * World-class integrated terminal interface
5
+ * Design matching GUI screenshot with sidebar, cards, and logs
6
+ * Features: Keyboard Shortcuts, Log Filtering, Persistent State, Plugin System
7
+ */
8
+ import React, { useState, useEffect, useCallback, useRef } from 'react';
9
+ import { Box, Text, useApp, useInput } from 'ink';
10
+ import Spinner from 'ink-spinner';
11
+ import { spawn } from 'child_process';
12
+ import { platform, homedir } from 'os';
13
+ import { join } from 'path';
14
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
15
+ import { PluginRegistry } from '@delta/domain';
16
+ import { GitStatusPlugin } from '../plugins/GitStatusPlugin.js';
17
+ const CONFIG_DIR = join(homedir(), '.delta');
18
+ const STATE_FILE = join(CONFIG_DIR, 'manager-state.json');
19
+ const MENU_ITEMS = [
20
+ { id: 'build', num: '1', label: 'Build All Apps', icon: '🔨' },
21
+ { id: 'cli', num: '2', label: 'CLI Dev Server', icon: '🖥️' },
22
+ { id: 'web', num: '3', label: 'Web Dev Server', icon: '🌐' },
23
+ { id: 'docs', num: '4', label: 'Documentation', icon: '📖' },
24
+ { id: 'test', num: '5', label: 'Run Tests', icon: '🧪' },
25
+ { id: 'clean', num: '6', label: 'Clean Build', icon: '🧹' },
26
+ { id: 'install', num: '7', label: 'Install Deps', icon: '📦' },
27
+ { id: 'quit', num: '8', label: 'Quit', icon: '❌' },
28
+ ];
29
+ const SHORTCUTS = [
30
+ { key: '?', desc: 'Show help' },
31
+ { key: '/', desc: 'Search/Filter logs' },
32
+ { key: 'f', desc: 'Toggle log filters' },
33
+ { key: 'g', desc: 'Refresh Git Status (Plugin)' },
34
+ { key: '↑↓', desc: 'Navigate menu' },
35
+ { key: 'Enter', desc: 'Select/Execute' },
36
+ { key: 'Esc / Q', desc: 'Quit/Back' },
37
+ { key: '1-8', desc: 'Quick menu access' },
38
+ ];
39
+ const getSeverityFromType = (type) => {
40
+ switch (type) {
41
+ case 'error': return 'high';
42
+ case 'warning': return 'medium';
43
+ case 'success': return 'low';
44
+ default: return 'low';
45
+ }
46
+ };
47
+ const StatusBadge = ({ status, progress }) => {
48
+ const config = {
49
+ stopped: { color: 'gray', text: 'STOPPED', icon: '○' },
50
+ running: { color: 'green', text: 'RUNNING', icon: '●' },
51
+ error: { color: 'red', text: 'ERROR', icon: '✕' },
52
+ building: { color: 'yellow', text: 'BUILDING', icon: '◐' },
53
+ };
54
+ const { color, text, icon } = config[status];
55
+ return (_jsx(Text, { color: color, children: status === 'building' && progress !== undefined ? (_jsxs(_Fragment, { children: [_jsx(Spinner, { type: "dots" }), " ", text, " ", progress, "%"] })) : (_jsxs(_Fragment, { children: [icon, " ", text] })) }));
56
+ };
57
+ const ProgressBar = ({ progress, width = 15 }) => {
58
+ const filled = Math.floor((progress / 100) * width);
59
+ const empty = width - filled;
60
+ return (_jsxs(Text, { children: [_jsx(Text, { color: "green", children: '█'.repeat(filled) }), _jsx(Text, { color: "gray", children: '░'.repeat(empty) }), _jsxs(Text, { color: "cyan", children: [" ", progress, "%"] })] }));
61
+ };
62
+ const ServiceCard = ({ service }) => {
63
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: service.status === 'running' ? 'green' : service.status === 'error' ? 'red' : 'gray', paddingX: 2, paddingY: 1, width: 40, children: [_jsx(Text, { bold: true, color: "white", children: service.name }), _jsx(Box, { marginY: 1, children: _jsx(StatusBadge, { status: service.status, progress: service.progress }) }), service.port && service.status === 'running' && (_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: "Port: " }), _jsx(Text, { bold: true, color: "green", children: service.port })] })), service.status === 'building' && service.progress > 0 && (_jsx(Box, { marginY: 1, children: _jsx(ProgressBar, { progress: service.progress }) })), _jsx(Text, { dimColor: true, children: service.message })] }));
64
+ };
65
+ const LogEntry = ({ entry }) => {
66
+ const colors = { info: 'white', success: 'green', error: 'red', warning: 'yellow' };
67
+ const icons = { info: 'ℹ', success: '✓', error: '✗', warning: '⚠' };
68
+ return (_jsxs(Box, { children: [_jsxs(Text, { dimColor: true, children: ["[", entry.timestamp, "] "] }), _jsxs(Text, { color: colors[entry.type], children: [icons[entry.type], " "] }), _jsxs(Text, { children: [entry.service, ": ", entry.message] })] }));
69
+ };
70
+ const MenuItem = ({ item, isSelected }) => {
71
+ return (_jsxs(Box, { paddingX: 1, width: 28, children: [_jsxs(Text, { backgroundColor: isSelected ? 'blue' : undefined, color: isSelected ? 'white' : 'gray', children: [isSelected ? '❯ ' : ' ', isSelected ? '' : ' '] }), _jsx(Text, { backgroundColor: isSelected ? 'blue' : undefined, color: isSelected ? 'white' : 'cyan', bold: isSelected, children: item.num }), _jsx(Text, { backgroundColor: isSelected ? 'blue' : undefined, children: " " }), _jsx(Text, { backgroundColor: isSelected ? 'blue' : undefined, color: isSelected ? 'white' : 'gray', children: item.icon }), _jsx(Text, { backgroundColor: isSelected ? 'blue' : undefined, children: " " }), _jsx(Text, { backgroundColor: isSelected ? 'blue' : undefined, color: isSelected ? 'white' : 'gray', bold: isSelected, children: item.label }), _jsx(Text, { backgroundColor: isSelected ? 'blue' : undefined, children: ' '.repeat(28 - item.label.length - 4) })] }));
72
+ };
73
+ const HelpModal = ({ onClose }) => {
74
+ useInput((_, key) => {
75
+ if (key.escape || key.return)
76
+ onClose();
77
+ });
78
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1, width: 50, children: [_jsx(Text, { bold: true, color: "cyan", children: "\u2328\uFE0F Keyboard Shortcuts" }), _jsx(Box, { marginY: 1 }), SHORTCUTS.map((s, i) => (_jsxs(Box, { children: [_jsx(Text, { color: "yellow", bold: true, children: s.key.padEnd(10) }), _jsx(Text, { color: "white", children: s.desc })] }, i))), _jsx(Box, { marginY: 1 }), _jsx(Text, { dimColor: true, children: "Press Enter or Esc to close" })] }));
79
+ };
80
+ const FilterBar = ({ severity, source, isActive }) => {
81
+ const severities = ['all', 'high', 'medium', 'low'];
82
+ const sources = ['all', 'CLI', 'Web', 'Tests', 'Build', 'System'];
83
+ return (_jsx(Box, { flexDirection: "column", marginBottom: 1, children: _jsxs(Box, { children: [_jsx(Text, { color: isActive ? 'cyan' : 'gray', bold: isActive, children: "Filter: " }), _jsx(Text, { color: "gray", children: "Severity[" }), severities.map((s, i) => (_jsxs(Text, { color: severity === s ? 'green' : 'gray', bold: severity === s, children: [s, i < severities.length - 1 ? '|' : ''] }, s))), _jsx(Text, { color: "gray", children: "] Source[" }), sources.map((s, i) => (_jsxs(Text, { color: source === s ? 'green' : 'gray', bold: source === s, children: [s, i < sources.length - 1 ? '|' : ''] }, s))), _jsx(Text, { color: "gray", children: "]" })] }) }));
84
+ };
85
+ const loadUserState = () => {
86
+ try {
87
+ if (existsSync(STATE_FILE)) {
88
+ return JSON.parse(readFileSync(STATE_FILE, 'utf-8'));
89
+ }
90
+ }
91
+ catch { }
92
+ return null;
93
+ };
94
+ const saveUserState = (state) => {
95
+ try {
96
+ if (!existsSync(CONFIG_DIR))
97
+ mkdirSync(CONFIG_DIR, { recursive: true });
98
+ writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
99
+ }
100
+ catch { }
101
+ };
102
+ export const UnifiedManager = () => {
103
+ const { exit } = useApp();
104
+ const [selectedIndex, setSelectedIndex] = useState(0);
105
+ const [logs, setLogs] = useState([]);
106
+ const [showHelp, setShowHelp] = useState(false);
107
+ const [searchMode, setSearchMode] = useState(false);
108
+ const [filterMode, setFilterMode] = useState(false);
109
+ const [searchQuery, setSearchQuery] = useState('');
110
+ const [severityFilter, setSeverityFilter] = useState('all');
111
+ const [sourceFilter, setSourceFilter] = useState('all');
112
+ const [services, setServices] = useState([
113
+ { id: 'cli', name: 'CLI Dev Server', port: undefined, status: 'stopped', message: 'Ready to start', progress: 0 },
114
+ { id: 'web', name: 'Web Dev Server', port: undefined, status: 'stopped', message: 'Ready to start', progress: 0 },
115
+ ]);
116
+ const serviceProcesses = React.useRef(new Map());
117
+ const pluginRegistryRef = useRef(null);
118
+ // Create plugin context
119
+ const createPluginContext = useCallback(() => ({
120
+ addLog: (service, message, type) => {
121
+ const timestamp = new Date().toLocaleTimeString('en-US', { hour12: false });
122
+ const severity = getSeverityFromType(type);
123
+ setLogs(prev => [...prev.slice(-50), { timestamp, service, message, type, severity }]);
124
+ },
125
+ getServices: () => services.map(s => ({ id: s.id, status: s.status, port: s.port })),
126
+ getLogFilters: () => ({ severity: severityFilter, source: sourceFilter }),
127
+ registerShortcut: () => { },
128
+ getSettings: () => ({}),
129
+ saveSettings: () => { },
130
+ }), [services, severityFilter, sourceFilter]);
131
+ // Initialize plugin system
132
+ useEffect(() => {
133
+ const context = createPluginContext();
134
+ const registry = new PluginRegistry(context);
135
+ pluginRegistryRef.current = registry;
136
+ registry.register(new GitStatusPlugin(context)).catch(() => { });
137
+ }, [createPluginContext]);
138
+ useEffect(() => {
139
+ const saved = loadUserState();
140
+ if (saved) {
141
+ setSeverityFilter(saved.logFilters.severity);
142
+ setSourceFilter(saved.logFilters.source);
143
+ setSearchQuery(saved.lastSearchQuery);
144
+ }
145
+ }, []);
146
+ useEffect(() => {
147
+ saveUserState({
148
+ selectedView: 'dashboard',
149
+ logFilters: { severity: severityFilter, source: sourceFilter },
150
+ lastSearchQuery: searchQuery,
151
+ });
152
+ }, [severityFilter, sourceFilter, searchQuery]);
153
+ const addLog = useCallback((service, message, type = 'info') => {
154
+ const timestamp = new Date().toLocaleTimeString('en-US', { hour12: false });
155
+ const severity = getSeverityFromType(type);
156
+ setLogs(prev => [...prev.slice(-50), { timestamp, service, message, type, severity }]);
157
+ }, []);
158
+ const filteredLogs = logs.filter(entry => {
159
+ if (severityFilter !== 'all' && entry.severity !== severityFilter)
160
+ return false;
161
+ if (sourceFilter !== 'all' && entry.service !== sourceFilter)
162
+ return false;
163
+ if (searchQuery && !entry.message.toLowerCase().includes(searchQuery.toLowerCase()))
164
+ return false;
165
+ return true;
166
+ });
167
+ const startService = useCallback((serviceId) => {
168
+ const service = services.find(s => s.id === serviceId);
169
+ if (!service)
170
+ return;
171
+ setServices(prev => prev.map(s => s.id === serviceId ? { ...s, status: 'building', message: 'Starting...', progress: 0 } : s));
172
+ addLog(serviceId, 'Starting service...', 'info');
173
+ let progress = 0;
174
+ const progressInterval = setInterval(() => {
175
+ progress += 10;
176
+ setServices(prev => prev.map(s => s.id === serviceId ? { ...s, progress } : s));
177
+ if (progress >= 100)
178
+ clearInterval(progressInterval);
179
+ }, 150);
180
+ const proc = spawn('pnpm', ['dev'], {
181
+ cwd: join(process.cwd(), serviceId === 'cli' ? 'apps/cli' : 'apps/web'),
182
+ shell: true,
183
+ stdio: ['ignore', 'pipe', 'pipe'],
184
+ });
185
+ serviceProcesses.current.set(serviceId, proc);
186
+ proc.stdout?.on('data', (data) => {
187
+ const output = data.toString().trim();
188
+ const portMatch = output.match(/localhost:(\d+)/) || output.match(/:(\d+)/);
189
+ if (portMatch) {
190
+ const port = parseInt(portMatch[1]);
191
+ setServices(prev => prev.map(s => s.id === serviceId ? { ...s, status: 'running', port, message: 'Watching files...', progress: 100 } : s));
192
+ addLog(serviceId, `Server running on port ${port}`, 'success');
193
+ }
194
+ });
195
+ proc.stderr?.on('data', (data) => addLog(serviceId, data.toString().trim(), 'error'));
196
+ proc.on('exit', (code) => {
197
+ clearInterval(progressInterval);
198
+ setServices(prev => prev.map(s => s.id === serviceId ? { ...s, status: code === 0 ? 'stopped' : 'error', progress: 0, message: 'Stopped' } : s));
199
+ serviceProcesses.current.delete(serviceId);
200
+ addLog(serviceId, code === 0 ? 'Service stopped' : 'Service crashed', code === 0 ? 'info' : 'error');
201
+ });
202
+ }, [services, addLog]);
203
+ const stopService = useCallback((serviceId) => {
204
+ const proc = serviceProcesses.current.get(serviceId);
205
+ if (proc) {
206
+ proc.kill('SIGTERM');
207
+ serviceProcesses.current.delete(serviceId);
208
+ }
209
+ setServices(prev => prev.map(s => s.id === serviceId ? { ...s, status: 'stopped', port: undefined, message: 'Stopped', progress: 0 } : s));
210
+ addLog(serviceId, 'Service stopped', 'info');
211
+ }, [addLog]);
212
+ const buildAll = useCallback(() => {
213
+ addLog('BUILD', 'Starting build process...', 'info');
214
+ ['CLI', 'Web'].forEach((step, i) => {
215
+ setTimeout(() => {
216
+ addLog('BUILD', `${step} Build: SUCCESS`, 'success');
217
+ if (i === 1)
218
+ addLog('BUILD', 'All builds completed successfully!', 'success');
219
+ }, (i + 1) * 1500);
220
+ });
221
+ }, [addLog]);
222
+ useInput((input, key) => {
223
+ if (showHelp)
224
+ return;
225
+ if (searchMode) {
226
+ if (key.escape) {
227
+ setSearchMode(false);
228
+ setSearchQuery('');
229
+ return;
230
+ }
231
+ if (key.return) {
232
+ setSearchMode(false);
233
+ return;
234
+ }
235
+ if (key.backspace || key.delete) {
236
+ setSearchQuery(q => q.slice(0, -1));
237
+ return;
238
+ }
239
+ if (input && !key.ctrl && !key.meta) {
240
+ setSearchQuery(q => q + input);
241
+ return;
242
+ }
243
+ return;
244
+ }
245
+ if (filterMode) {
246
+ if (key.escape) {
247
+ setFilterMode(false);
248
+ return;
249
+ }
250
+ if (input === 's') {
251
+ const severities = ['all', 'high', 'medium', 'low'];
252
+ setSeverityFilter(prev => severities[(severities.indexOf(prev) + 1) % severities.length]);
253
+ return;
254
+ }
255
+ if (input === 'r') {
256
+ const sources = ['all', 'CLI', 'Web', 'Tests', 'Build', 'System'];
257
+ setSourceFilter(prev => sources[(sources.indexOf(prev) + 1) % sources.length]);
258
+ return;
259
+ }
260
+ if (key.return) {
261
+ setFilterMode(false);
262
+ return;
263
+ }
264
+ return;
265
+ }
266
+ if (input === '?') {
267
+ setShowHelp(true);
268
+ return;
269
+ }
270
+ if (input === '/') {
271
+ setSearchMode(true);
272
+ return;
273
+ }
274
+ if (input === 'g') {
275
+ // GitStatusPlugin shortcut
276
+ const registry = pluginRegistryRef.current;
277
+ if (registry) {
278
+ registry.executeCommand('git-status', 'refresh').catch(() => { });
279
+ }
280
+ return;
281
+ }
282
+ if (input === 'q' || key.escape) {
283
+ serviceProcesses.current.forEach(proc => proc.kill('SIGTERM'));
284
+ exit();
285
+ }
286
+ if (input >= '1' && input <= '8') {
287
+ const index = parseInt(input) - 1;
288
+ if (index < MENU_ITEMS.length)
289
+ setSelectedIndex(index);
290
+ return;
291
+ }
292
+ if (key.upArrow)
293
+ setSelectedIndex(i => Math.max(0, i - 1));
294
+ if (key.downArrow)
295
+ setSelectedIndex(i => Math.min(MENU_ITEMS.length - 1, i + 1));
296
+ if (key.return) {
297
+ const item = MENU_ITEMS[selectedIndex];
298
+ switch (item.id) {
299
+ case 'build':
300
+ buildAll();
301
+ break;
302
+ case 'cli':
303
+ const cliService = services.find(s => s.id === 'cli');
304
+ cliService?.status === 'running' ? stopService('cli') : startService('cli');
305
+ break;
306
+ case 'web':
307
+ const webService = services.find(s => s.id === 'web');
308
+ webService?.status === 'running' ? stopService('web') : startService('web');
309
+ break;
310
+ case 'quit':
311
+ serviceProcesses.current.forEach(proc => proc.kill('SIGTERM'));
312
+ exit();
313
+ break;
314
+ }
315
+ }
316
+ });
317
+ useEffect(() => { addLog('SYSTEM', 'Delta Unified Manager started', 'info'); }, []);
318
+ if (showHelp) {
319
+ return (_jsx(Box, { flexDirection: "column", height: 28, justifyContent: "center", alignItems: "center", children: _jsx(HelpModal, { onClose: () => setShowHelp(false) }) }));
320
+ }
321
+ return (_jsxs(Box, { flexDirection: "column", height: 28, children: [_jsxs(Box, { justifyContent: "space-between", paddingX: 1, paddingY: 0, children: [_jsx(Text, { backgroundColor: "blue", bold: true, color: "white", children: " \uD83D\uDE80 Delta Project Manager " }), _jsx(Text, { backgroundColor: "blue", color: "white", children: " v2.0 " })] }), _jsxs(Box, { flexGrow: 1, children: [_jsx(Box, { flexDirection: "column", width: 30, borderStyle: "single", borderColor: "gray", paddingY: 1, children: MENU_ITEMS.map((item, index) => (_jsx(MenuItem, { item: item, isSelected: index === selectedIndex }, item.id))) }), _jsxs(Box, { flexDirection: "column", flexGrow: 1, paddingX: 1, paddingY: 1, children: [_jsxs(Box, { flexDirection: "row", gap: 2, marginBottom: 1, children: [_jsx(ServiceCard, { service: services[0] }), _jsx(ServiceCard, { service: services[1] })] }), _jsxs(Box, { flexGrow: 1, flexDirection: "column", borderStyle: "round", borderColor: filterMode || searchMode ? 'cyan' : 'gray', paddingX: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "\uD83D\uDCCB Build & Test Logs" }), searchMode && _jsxs(Text, { color: "yellow", children: [" [Search: ", searchQuery, "_]"] }), filterMode && _jsx(Text, { color: "yellow", children: " [Filter Mode - s:severity r:source Enter:done]" })] }), _jsx(FilterBar, { severity: severityFilter, source: sourceFilter, isActive: filterMode }), _jsx(Box, { flexDirection: "column", overflow: "hidden", children: filteredLogs.length === 0 ? (_jsx(Text, { dimColor: true, children: logs.length === 0 ? 'No activity yet...' : 'No logs match current filters' })) : (filteredLogs.slice(-15).map((entry, i) => _jsx(LogEntry, { entry: entry }, i))) })] })] })] }), _jsxs(Box, { justifyContent: "space-between", paddingX: 1, paddingY: 0, children: [_jsxs(Box, { children: [_jsx(Text, { backgroundColor: "gray", color: "white", children: "[" }), _jsx(Text, { backgroundColor: "gray", color: "cyan", children: "\u2191\u2193" }), _jsx(Text, { backgroundColor: "gray", color: "white", children: "] Navigate " }), _jsx(Text, { backgroundColor: "gray", color: "white", children: "[" }), _jsx(Text, { backgroundColor: "gray", color: "cyan", children: "Enter" }), _jsx(Text, { backgroundColor: "gray", color: "white", children: "] Select " }), _jsx(Text, { backgroundColor: "gray", color: "white", children: "[" }), _jsx(Text, { backgroundColor: "gray", color: "cyan", children: "?" }), _jsx(Text, { backgroundColor: "gray", color: "white", children: "] Help " }), _jsx(Text, { backgroundColor: "gray", color: "white", children: "[" }), _jsx(Text, { backgroundColor: "gray", color: "cyan", children: "Q" }), _jsx(Text, { backgroundColor: "gray", color: "white", children: "] Quit" })] }), _jsxs(Box, { children: [_jsx(Text, { backgroundColor: "gray", color: "white", children: " CLI: " }), _jsx(Text, { backgroundColor: "gray", color: services[0].status === 'running' ? 'green' : 'gray', children: services[0].port ? `localhost:${services[0].port} ✓` : '○' }), _jsx(Text, { backgroundColor: "gray", color: "white", children: " | Web: " }), _jsx(Text, { backgroundColor: "gray", color: services[1].status === 'running' ? 'green' : 'gray', children: services[1].port ? `localhost:${services[1].port} ✓` : '○' }), _jsxs(Text, { backgroundColor: "gray", color: "white", children: [" | ", platform()] })] })] })] }));
322
+ };
323
+ export default UnifiedManager;
324
+ //# sourceMappingURL=UnifiedManager.js.map
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Audit Logger for Delta CLI
3
+ * Tracks all commands, results, and performance metrics
4
+ * Enterprise-grade logging for compliance and debugging
5
+ */
6
+ import { promises as fs } from 'fs';
7
+ import { homedir } from 'os';
8
+ import { join } from 'path';
9
+ const DEFAULT_CONFIG = {
10
+ enabled: true,
11
+ logLevel: 'standard',
12
+ retentionDays: 30,
13
+ maxEntries: 10000,
14
+ includeMetadata: true,
15
+ };
16
+ const AUDIT_DIR = join(homedir(), '.delta', 'audit');
17
+ const AUDIT_FILE = join(AUDIT_DIR, 'commands.jsonl');
18
+ const CONFIG_FILE = join(AUDIT_DIR, 'config.json');
19
+ export class AuditLogger {
20
+ config;
21
+ initialized = false;
22
+ constructor() {
23
+ this.config = DEFAULT_CONFIG;
24
+ }
25
+ async initialize() {
26
+ if (this.initialized)
27
+ return;
28
+ try {
29
+ await fs.mkdir(AUDIT_DIR, { recursive: true });
30
+ // Load config if exists
31
+ try {
32
+ const configData = await fs.readFile(CONFIG_FILE, 'utf-8');
33
+ this.config = { ...DEFAULT_CONFIG, ...JSON.parse(configData) };
34
+ }
35
+ catch {
36
+ // Use defaults
37
+ }
38
+ this.initialized = true;
39
+ }
40
+ catch (error) {
41
+ console.error('Failed to initialize audit logger:', error);
42
+ }
43
+ }
44
+ async logCommand(command, args, options, response, startTime) {
45
+ if (!this.config.enabled)
46
+ return;
47
+ await this.initialize();
48
+ const entry = {
49
+ id: this.generateId(),
50
+ timestamp: new Date().toISOString(),
51
+ command,
52
+ args,
53
+ options: this.sanitizeOptions(options),
54
+ exitCode: response.exitCode || (response.success ? 0 : 1),
55
+ success: response.success,
56
+ duration: Date.now() - startTime,
57
+ provider: response.meta?.provider || 'unknown',
58
+ error: response.error,
59
+ };
60
+ if (this.config.includeMetadata) {
61
+ entry.metadata = {
62
+ nodeVersion: process.version,
63
+ platform: process.platform,
64
+ cwd: process.cwd(),
65
+ ci: process.env.CI === 'true',
66
+ };
67
+ }
68
+ // Write to log file
69
+ await this.appendEntry(entry);
70
+ // Send to remote if configured
71
+ if (this.config.remoteEndpoint) {
72
+ await this.sendRemote(entry).catch(() => { });
73
+ }
74
+ }
75
+ async getRecentEntries(limit = 50) {
76
+ await this.initialize();
77
+ try {
78
+ const data = await fs.readFile(AUDIT_FILE, 'utf-8');
79
+ const lines = data.trim().split('\n').filter(Boolean);
80
+ return lines
81
+ .slice(-limit)
82
+ .map(line => JSON.parse(line))
83
+ .reverse();
84
+ }
85
+ catch {
86
+ return [];
87
+ }
88
+ }
89
+ async getStats() {
90
+ const entries = await this.getRecentEntries(1000);
91
+ if (entries.length === 0) {
92
+ return {
93
+ totalCommands: 0,
94
+ successRate: 0,
95
+ avgDuration: 0,
96
+ mostUsed: [],
97
+ lastUsed: 'Never',
98
+ };
99
+ }
100
+ const commands = entries.map(e => e.command);
101
+ const successCount = entries.filter(e => e.success).length;
102
+ const totalDuration = entries.reduce((sum, e) => sum + e.duration, 0);
103
+ // Count command frequency
104
+ const frequency = {};
105
+ commands.forEach(cmd => {
106
+ frequency[cmd] = (frequency[cmd] || 0) + 1;
107
+ });
108
+ const mostUsed = Object.entries(frequency)
109
+ .sort((a, b) => b[1] - a[1])
110
+ .slice(0, 5)
111
+ .map(([cmd]) => cmd);
112
+ return {
113
+ totalCommands: entries.length,
114
+ successRate: Math.round((successCount / entries.length) * 100),
115
+ avgDuration: Math.round(totalDuration / entries.length),
116
+ mostUsed,
117
+ lastUsed: entries[0]?.timestamp || 'Never',
118
+ };
119
+ }
120
+ async appendEntry(entry) {
121
+ const line = JSON.stringify(entry) + '\n';
122
+ await fs.appendFile(AUDIT_FILE, line, 'utf-8');
123
+ }
124
+ async sendRemote(entry) {
125
+ if (!this.config.remoteEndpoint)
126
+ return;
127
+ try {
128
+ await fetch(this.config.remoteEndpoint, {
129
+ method: 'POST',
130
+ headers: { 'Content-Type': 'application/json' },
131
+ body: JSON.stringify(entry),
132
+ });
133
+ }
134
+ catch {
135
+ // Silently fail - don't block CLI execution
136
+ }
137
+ }
138
+ sanitizeOptions(options) {
139
+ const sensitiveKeys = ['token', 'password', 'secret', 'key', 'auth'];
140
+ const sanitized = {};
141
+ for (const [key, value] of Object.entries(options)) {
142
+ if (sensitiveKeys.some(sk => key.toLowerCase().includes(sk))) {
143
+ sanitized[key] = '[REDACTED]';
144
+ }
145
+ else {
146
+ sanitized[key] = value;
147
+ }
148
+ }
149
+ return sanitized;
150
+ }
151
+ generateId() {
152
+ return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
153
+ }
154
+ // Cleanup old entries
155
+ async cleanup() {
156
+ if (!this.config.enabled)
157
+ return;
158
+ try {
159
+ const entries = await this.getRecentEntries(this.config.maxEntries);
160
+ const cutoff = new Date();
161
+ cutoff.setDate(cutoff.getDate() - this.config.retentionDays);
162
+ const validEntries = entries.filter(e => new Date(e.timestamp) > cutoff);
163
+ // Rewrite file with only valid entries
164
+ const data = validEntries.map(e => JSON.stringify(e)).join('\n') + '\n';
165
+ await fs.writeFile(AUDIT_FILE, data, 'utf-8');
166
+ }
167
+ catch {
168
+ // Ignore cleanup errors
169
+ }
170
+ }
171
+ }
172
+ // Singleton instance
173
+ let auditLogger = null;
174
+ export function getAuditLogger() {
175
+ if (!auditLogger) {
176
+ auditLogger = new AuditLogger();
177
+ }
178
+ return auditLogger;
179
+ }
180
+ // Export for testing
181
+ export function resetAuditLogger() {
182
+ auditLogger = null;
183
+ }
184
+ //# sourceMappingURL=audit.js.map