@vee-stack/delta-cli 2.0.7 → 2.0.9
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/adapters/analysis.adapter.js +42 -0
- package/dist/analyzer/commands/analyze.js +74 -114
- package/dist/auth/device-auth.js +261 -0
- package/dist/auth/secure-auth.js +45 -16
- package/dist/commands/analyze.js +30 -27
- package/dist/commands/auth.js +13 -16
- package/dist/commands/status.js +2 -2
- package/dist/commands/whoami.js +6 -6
- package/dist/components/Dashboard.js +3 -5
- package/dist/components/DeltaApp.js +1 -1
- package/dist/components/UnifiedManager.js +48 -20
- package/dist/core/completion.js +14 -3
- package/dist/core/engine.js +10 -4
- package/dist/core/exit-codes.js +12 -4
- package/dist/core/wizard.js +1 -1
- package/dist/index.js +21 -5
- package/dist/providers/remote-provider.js +2 -2
- package/dist/telemetry/wrapper.js +114 -0
- package/dist/ui.js +9 -2
- package/dist/welcome.js +14 -4
- package/package.json +3 -1
- package/dist/apps/cli/src/analyzer/commands/analyze.js +0 -256
- package/dist/apps/cli/src/analyzer/commands/config.js +0 -83
- package/dist/apps/cli/src/analyzer/commands/report.js +0 -38
- package/dist/apps/cli/src/analyzer/generators/report.generator.js +0 -123
- package/dist/apps/cli/src/analyzer/index.js +0 -44
- package/dist/apps/cli/src/analyzer/scanners/project.scanner.js +0 -92
- package/dist/apps/cli/src/analyzer/validators/contracts.validator.js +0 -42
- package/dist/apps/cli/src/analyzer/validators/maintainability.validator.js +0 -40
- package/dist/apps/cli/src/analyzer/validators/observability.validator.js +0 -39
- package/dist/apps/cli/src/analyzer/validators/performance.validator.js +0 -42
- package/dist/apps/cli/src/analyzer/validators/security.validator.js +0 -66
- package/dist/apps/cli/src/analyzer/validators/soc.validator.js +0 -75
- package/dist/apps/cli/src/auth/secure-auth.js +0 -312
- package/dist/apps/cli/src/commands/analyze.js +0 -286
- package/dist/apps/cli/src/commands/auth-new.js +0 -37
- package/dist/apps/cli/src/commands/auth.js +0 -122
- package/dist/apps/cli/src/commands/config.js +0 -49
- package/dist/apps/cli/src/commands/deploy.js +0 -6
- package/dist/apps/cli/src/commands/init.js +0 -47
- package/dist/apps/cli/src/commands/logout.js +0 -23
- package/dist/apps/cli/src/commands/plugins.js +0 -21
- package/dist/apps/cli/src/commands/status.js +0 -80
- package/dist/apps/cli/src/commands/sync.js +0 -6
- package/dist/apps/cli/src/commands/whoami.js +0 -115
- package/dist/apps/cli/src/components/Dashboard.js +0 -168
- package/dist/apps/cli/src/components/DeltaApp.js +0 -56
- package/dist/apps/cli/src/components/UnifiedManager.js +0 -324
- package/dist/apps/cli/src/core/audit.js +0 -184
- package/dist/apps/cli/src/core/completion.js +0 -294
- package/dist/apps/cli/src/core/contracts.js +0 -6
- package/dist/apps/cli/src/core/engine.js +0 -124
- package/dist/apps/cli/src/core/exit-codes.js +0 -71
- package/dist/apps/cli/src/core/hooks.js +0 -181
- package/dist/apps/cli/src/core/index.js +0 -7
- package/dist/apps/cli/src/core/policy.js +0 -115
- package/dist/apps/cli/src/core/profiles.js +0 -161
- package/dist/apps/cli/src/core/wizard.js +0 -203
- package/dist/apps/cli/src/index.js +0 -636
- package/dist/apps/cli/src/interactive/index.js +0 -11
- package/dist/apps/cli/src/plugins/GitStatusPlugin.js +0 -99
- package/dist/apps/cli/src/providers/ai-provider.js +0 -74
- package/dist/apps/cli/src/providers/local-provider.js +0 -302
- package/dist/apps/cli/src/providers/remote-provider.js +0 -100
- package/dist/apps/cli/src/types/api.js +0 -3
- package/dist/apps/cli/src/ui.js +0 -219
- package/dist/apps/cli/src/welcome.js +0 -81
- package/dist/bundle.js +0 -504
- package/dist/packages/domain/src/constitution/contracts/index.js +0 -43
- package/dist/packages/domain/src/constitution/contracts/ts.rules.js +0 -268
- package/dist/packages/domain/src/constitution/index.js +0 -139
- package/dist/packages/domain/src/constitution/maintainability/index.js +0 -43
- package/dist/packages/domain/src/constitution/maintainability/ts.rules.js +0 -344
- package/dist/packages/domain/src/constitution/observability/index.js +0 -43
- package/dist/packages/domain/src/constitution/observability/ts.rules.js +0 -307
- package/dist/packages/domain/src/constitution/performance/index.js +0 -43
- package/dist/packages/domain/src/constitution/performance/ts.rules.js +0 -325
- package/dist/packages/domain/src/constitution/security/index.js +0 -50
- package/dist/packages/domain/src/constitution/security/ts.rules.js +0 -267
- package/dist/packages/domain/src/constitution/soc/index.js +0 -43
- package/dist/packages/domain/src/constitution/soc/ts.rules.js +0 -360
- package/dist/packages/domain/src/contracts/analysis.contract.js +0 -18
- package/dist/packages/domain/src/contracts/index.js +0 -7
- package/dist/packages/domain/src/contracts/projects.contract.js +0 -18
- package/dist/packages/domain/src/control/registry/rules.registry.js +0 -29
- package/dist/packages/domain/src/control/schemas/policies.js +0 -6
- package/dist/packages/domain/src/core/analysis/discovery.js +0 -163
- package/dist/packages/domain/src/core/analysis/engine.contract.js +0 -298
- package/dist/packages/domain/src/core/analysis/engine.js +0 -77
- package/dist/packages/domain/src/core/analysis/index.js +0 -14
- package/dist/packages/domain/src/core/analysis/orchestrator.js +0 -242
- package/dist/packages/domain/src/core/comparison/engine.js +0 -29
- package/dist/packages/domain/src/core/comparison/index.js +0 -5
- package/dist/packages/domain/src/core/documentation/index.js +0 -5
- package/dist/packages/domain/src/core/documentation/pipeline.js +0 -41
- package/dist/packages/domain/src/core/fs/adapter.js +0 -111
- package/dist/packages/domain/src/core/fs/index.js +0 -5
- package/dist/packages/domain/src/core/parser/unified-parser.js +0 -166
- package/dist/packages/domain/src/index.js +0 -33
- package/dist/packages/domain/src/plugin/registry.js +0 -195
- package/dist/packages/domain/src/plugin/types.js +0 -6
- package/dist/packages/domain/src/ports/analysis.engine.js +0 -7
- package/dist/packages/domain/src/ports/audit.logger.js +0 -7
- package/dist/packages/domain/src/ports/project.repository.js +0 -7
- package/dist/packages/domain/src/rules/index.js +0 -134
- package/dist/packages/domain/src/types/analysis.js +0 -6
- package/dist/packages/domain/src/types/errors.js +0 -53
- package/dist/packages/domain/src/types/fs.js +0 -6
- package/dist/packages/domain/src/types/index.js +0 -7
package/dist/auth/secure-auth.js
CHANGED
|
@@ -16,7 +16,7 @@ import { createServer } from 'http';
|
|
|
16
16
|
import { URL } from 'url';
|
|
17
17
|
import crypto from 'crypto';
|
|
18
18
|
import chalk from 'chalk';
|
|
19
|
-
import { printSuccess, printError, printInfo, printWarning, startSpinner, stopSpinner } from '../ui.js';
|
|
19
|
+
import { printSuccess, printError, printInfo, printWarning, startSpinner, stopSpinner, } from '../ui.js';
|
|
20
20
|
const CONFIG_DIR = path.join(os.homedir(), '.delta');
|
|
21
21
|
const TOKEN_FILE = path.join(CONFIG_DIR, 'tokens.enc');
|
|
22
22
|
const KEY_FILE = path.join(CONFIG_DIR, '.key');
|
|
@@ -71,10 +71,7 @@ async function decrypt(encryptedData) {
|
|
|
71
71
|
// PKCE Code Generator
|
|
72
72
|
function generatePKCE() {
|
|
73
73
|
const verifier = crypto.randomBytes(32).toString('base64url');
|
|
74
|
-
const challenge = crypto
|
|
75
|
-
.createHash('sha256')
|
|
76
|
-
.update(verifier)
|
|
77
|
-
.digest('base64url');
|
|
74
|
+
const challenge = crypto.createHash('sha256').update(verifier).digest('base64url');
|
|
78
75
|
return { verifier, challenge };
|
|
79
76
|
}
|
|
80
77
|
// Secure Token Storage using encrypted file
|
|
@@ -114,8 +111,21 @@ export class SecureTokenStore {
|
|
|
114
111
|
return tokens.access;
|
|
115
112
|
}
|
|
116
113
|
static async saveRefreshToken(token) {
|
|
114
|
+
// Encrypt token (side effect - encryption happens before storage)
|
|
115
|
+
const encrypted = await encrypt(token);
|
|
116
|
+
void encrypted; // Mark as intentionally used for encryption side effect
|
|
117
117
|
const tokens = await this.loadTokens();
|
|
118
|
-
await this.saveTokens({
|
|
118
|
+
await this.saveTokens({
|
|
119
|
+
access: tokens.access || undefined,
|
|
120
|
+
refresh: token,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
static async saveSessionInfo(sessionInfo) {
|
|
124
|
+
// For now, store session info in a separate file
|
|
125
|
+
// In production, this should be encrypted and stored securely
|
|
126
|
+
const sessionFile = path.join(CONFIG_DIR, 'session.json');
|
|
127
|
+
await fs.mkdir(CONFIG_DIR, { recursive: true });
|
|
128
|
+
await fs.writeFile(sessionFile, JSON.stringify(sessionInfo, null, 2));
|
|
119
129
|
}
|
|
120
130
|
static async getRefreshToken() {
|
|
121
131
|
const tokens = await this.loadTokens();
|
|
@@ -123,10 +133,29 @@ export class SecureTokenStore {
|
|
|
123
133
|
}
|
|
124
134
|
static async clearTokens() {
|
|
125
135
|
try {
|
|
136
|
+
// Check if file exists first
|
|
137
|
+
try {
|
|
138
|
+
await fs.access(TOKEN_FILE);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// File doesn't exist, nothing to clear
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
126
144
|
await fs.unlink(TOKEN_FILE);
|
|
145
|
+
// Also clear session file if exists
|
|
146
|
+
const sessionFile = path.join(CONFIG_DIR, 'session.json');
|
|
147
|
+
try {
|
|
148
|
+
await fs.access(sessionFile);
|
|
149
|
+
await fs.unlink(sessionFile);
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Session file may not exist
|
|
153
|
+
}
|
|
154
|
+
console.log(' Tokens cleared from:', TOKEN_FILE);
|
|
127
155
|
}
|
|
128
|
-
catch {
|
|
129
|
-
|
|
156
|
+
catch (error) {
|
|
157
|
+
console.error(' Warning: Could not clear tokens:', error.message);
|
|
158
|
+
throw error;
|
|
130
159
|
}
|
|
131
160
|
}
|
|
132
161
|
static async hasTokens() {
|
|
@@ -236,7 +265,7 @@ export async function startOAuthFlow(method = 'oauth') {
|
|
|
236
265
|
if (!tokenResponse.ok) {
|
|
237
266
|
throw new Error('Failed to exchange authorization code');
|
|
238
267
|
}
|
|
239
|
-
const tokens = await tokenResponse.json();
|
|
268
|
+
const tokens = (await tokenResponse.json());
|
|
240
269
|
// Store tokens securely
|
|
241
270
|
await SecureTokenStore.saveAccessToken(tokens.access_token);
|
|
242
271
|
await SecureTokenStore.saveRefreshToken(tokens.refresh_token);
|
|
@@ -259,13 +288,13 @@ export async function authenticateWithPAT(token) {
|
|
|
259
288
|
// Validate token
|
|
260
289
|
const response = await fetch(`${apiUrl}/api/auth/verify`, {
|
|
261
290
|
headers: {
|
|
262
|
-
|
|
291
|
+
Authorization: `Bearer ${token}`,
|
|
263
292
|
},
|
|
264
293
|
});
|
|
265
294
|
if (!response.ok) {
|
|
266
295
|
throw new Error('Invalid token');
|
|
267
296
|
}
|
|
268
|
-
const data = await response.json();
|
|
297
|
+
const data = (await response.json());
|
|
269
298
|
// Store token
|
|
270
299
|
await SecureTokenStore.saveAccessToken(token);
|
|
271
300
|
stopSpinner(true, 'Token validated');
|
|
@@ -299,7 +328,7 @@ export async function refreshAccessToken() {
|
|
|
299
328
|
if (!response.ok) {
|
|
300
329
|
throw new Error('Token refresh failed');
|
|
301
330
|
}
|
|
302
|
-
const tokens = await response.json();
|
|
331
|
+
const tokens = (await response.json());
|
|
303
332
|
await SecureTokenStore.saveAccessToken(tokens.access_token);
|
|
304
333
|
if (tokens.refresh_token) {
|
|
305
334
|
await SecureTokenStore.saveRefreshToken(tokens.refresh_token);
|
|
@@ -334,7 +363,7 @@ export async function getAuthStatus() {
|
|
|
334
363
|
const apiUrl = process.env.DELTA_API_URL || 'http://localhost:3000';
|
|
335
364
|
const response = await fetch(`${apiUrl}/api/auth/me`, {
|
|
336
365
|
headers: {
|
|
337
|
-
|
|
366
|
+
Authorization: `Bearer ${token}`,
|
|
338
367
|
},
|
|
339
368
|
});
|
|
340
369
|
if (!response.ok) {
|
|
@@ -347,19 +376,19 @@ export async function getAuthStatus() {
|
|
|
347
376
|
const newToken = await SecureTokenStore.getAccessToken();
|
|
348
377
|
const retryResponse = await fetch(`${apiUrl}/api/auth/me`, {
|
|
349
378
|
headers: {
|
|
350
|
-
|
|
379
|
+
Authorization: `Bearer ${newToken}`,
|
|
351
380
|
},
|
|
352
381
|
});
|
|
353
382
|
if (!retryResponse.ok) {
|
|
354
383
|
return { authenticated: false };
|
|
355
384
|
}
|
|
356
|
-
const userData = await retryResponse.json();
|
|
385
|
+
const userData = (await retryResponse.json());
|
|
357
386
|
return {
|
|
358
387
|
authenticated: true,
|
|
359
388
|
user: userData,
|
|
360
389
|
};
|
|
361
390
|
}
|
|
362
|
-
const userData = await response.json();
|
|
391
|
+
const userData = (await response.json());
|
|
363
392
|
return {
|
|
364
393
|
authenticated: true,
|
|
365
394
|
user: userData,
|
package/dist/commands/analyze.js
CHANGED
|
@@ -7,7 +7,7 @@ import * as crypto from 'crypto';
|
|
|
7
7
|
import { loadConfig } from './auth.js';
|
|
8
8
|
import { SecureTokenStore } from '../auth/secure-auth.js';
|
|
9
9
|
import chalk from 'chalk';
|
|
10
|
-
import { icons, startSpinner, stopSpinner, printSuccess, printInfo, printWarning, createTable, printDivider } from '../ui.js';
|
|
10
|
+
import { icons, startSpinner, stopSpinner, printSuccess, printInfo, printWarning, createTable, printDivider, } from '../ui.js';
|
|
11
11
|
function extractApiErrorPayload(payload) {
|
|
12
12
|
if (!payload || typeof payload !== 'object')
|
|
13
13
|
return {};
|
|
@@ -22,24 +22,27 @@ function extractApiErrorPayload(payload) {
|
|
|
22
22
|
}
|
|
23
23
|
export async function analyzeCommand(projectPath, options) {
|
|
24
24
|
const targetPath = path.resolve(projectPath);
|
|
25
|
-
// Check authentication FIRST
|
|
25
|
+
// Check authentication FIRST for all operations
|
|
26
|
+
printInfo('🔐 Checking authentication...');
|
|
27
|
+
await loadConfig();
|
|
28
|
+
const pat = await SecureTokenStore.getAccessToken();
|
|
29
|
+
if (!pat) {
|
|
30
|
+
console.error();
|
|
31
|
+
console.error(chalk.red('❌ Error: You must be logged in to use Delta CLI.'));
|
|
32
|
+
console.error();
|
|
33
|
+
console.error(chalk.yellow('Please authenticate first:'));
|
|
34
|
+
console.error(chalk.cyan(' delta login'));
|
|
35
|
+
console.error();
|
|
36
|
+
console.error(chalk.dim('Or use a valid PAT:'));
|
|
37
|
+
console.error(chalk.cyan(' delta login --token <your-pat>'));
|
|
38
|
+
console.error();
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
printSuccess('✓ Authenticated');
|
|
42
|
+
console.log();
|
|
43
|
+
// Additional check for upload permission
|
|
26
44
|
if (options.upload) {
|
|
27
|
-
printInfo('
|
|
28
|
-
const config = await loadConfig();
|
|
29
|
-
const pat = await SecureTokenStore.getAccessToken();
|
|
30
|
-
if (!pat) {
|
|
31
|
-
console.error();
|
|
32
|
-
console.error(chalk.red('❌ Error: You must be logged in to upload reports.'));
|
|
33
|
-
console.error();
|
|
34
|
-
console.error(chalk.yellow('Please authenticate first:'));
|
|
35
|
-
console.error(chalk.cyan(' delta login'));
|
|
36
|
-
console.error();
|
|
37
|
-
console.error(chalk.dim('Or use --upload with a valid PAT:'));
|
|
38
|
-
console.error(chalk.cyan(' delta analyze . --upload --token <your-pat>'));
|
|
39
|
-
console.error();
|
|
40
|
-
process.exit(1);
|
|
41
|
-
}
|
|
42
|
-
printSuccess('✓ Authenticated');
|
|
45
|
+
printInfo('📤 Upload mode enabled');
|
|
43
46
|
console.log();
|
|
44
47
|
}
|
|
45
48
|
printInfo('🔍 Starting Delta Analysis Engine...');
|
|
@@ -50,7 +53,9 @@ export async function analyzeCommand(projectPath, options) {
|
|
|
50
53
|
startSpinner('Scanning project files...');
|
|
51
54
|
const files = await discoverFiles(targetPath, {
|
|
52
55
|
include: options.include ? [options.include] : ['**/*.{ts,tsx,js,jsx}'],
|
|
53
|
-
exclude: options.exclude
|
|
56
|
+
exclude: options.exclude
|
|
57
|
+
? [options.exclude].concat(['node_modules', 'dist', '.git'])
|
|
58
|
+
: ['node_modules', 'dist', '.git'],
|
|
54
59
|
maxSize: parseInt(options.maxSize, 10),
|
|
55
60
|
});
|
|
56
61
|
stopSpinner(true, `Found ${files.length} files to analyze`);
|
|
@@ -133,9 +138,7 @@ export async function analyzeCommand(projectPath, options) {
|
|
|
133
138
|
root_fingerprint: '',
|
|
134
139
|
path: targetPath,
|
|
135
140
|
},
|
|
136
|
-
tools_used: [
|
|
137
|
-
{ id: 'delta-core', version: '0.5.0', adapter_version: '0.5.0' },
|
|
138
|
-
],
|
|
141
|
+
tools_used: [{ id: 'delta-core', version: '0.5.0', adapter_version: '0.5.0' }],
|
|
139
142
|
summary: {
|
|
140
143
|
total: findings.length,
|
|
141
144
|
high: findings.filter(f => f.severity === 'high').length,
|
|
@@ -209,7 +212,7 @@ async function uploadReport(report) {
|
|
|
209
212
|
const initResponse = await fetch(`${apiUrl}/api/upload/init`, {
|
|
210
213
|
method: 'POST',
|
|
211
214
|
headers: {
|
|
212
|
-
|
|
215
|
+
Authorization: `Bearer ${pat}`,
|
|
213
216
|
'Content-Type': 'application/json',
|
|
214
217
|
'Idempotency-Key': crypto.randomUUID(),
|
|
215
218
|
},
|
|
@@ -234,7 +237,7 @@ async function uploadReport(report) {
|
|
|
234
237
|
const message = apiError.message || `Init failed: ${initResponse.status}`;
|
|
235
238
|
throw new Error(message + details);
|
|
236
239
|
}
|
|
237
|
-
const initData = await initResponse.json();
|
|
240
|
+
const initData = (await initResponse.json());
|
|
238
241
|
if (!initData.success) {
|
|
239
242
|
throw new Error(initData.error?.message || 'Upload init failed');
|
|
240
243
|
}
|
|
@@ -246,7 +249,7 @@ async function uploadReport(report) {
|
|
|
246
249
|
const uploadResponse = await fetch(`${apiUrl}/api/upload/${uploadId}`, {
|
|
247
250
|
method: 'PUT',
|
|
248
251
|
headers: {
|
|
249
|
-
|
|
252
|
+
Authorization: `Bearer ${pat}`,
|
|
250
253
|
'Content-Type': 'application/json',
|
|
251
254
|
},
|
|
252
255
|
body: JSON.stringify({
|
|
@@ -277,7 +280,7 @@ async function uploadReport(report) {
|
|
|
277
280
|
const finalizeResponse = await fetch(`${apiUrl}/api/upload/${uploadId}/finalize`, {
|
|
278
281
|
method: 'POST',
|
|
279
282
|
headers: {
|
|
280
|
-
|
|
283
|
+
Authorization: `Bearer ${pat}`,
|
|
281
284
|
'Content-Type': 'application/json',
|
|
282
285
|
'Idempotency-Key': crypto.randomUUID(),
|
|
283
286
|
},
|
|
@@ -296,7 +299,7 @@ async function uploadReport(report) {
|
|
|
296
299
|
const message = apiError.message || `Finalize failed: ${finalizeResponse.status}`;
|
|
297
300
|
throw new Error(message + details);
|
|
298
301
|
}
|
|
299
|
-
const finalizeData = await finalizeResponse.json();
|
|
302
|
+
const finalizeData = (await finalizeResponse.json());
|
|
300
303
|
if (!finalizeData.success) {
|
|
301
304
|
throw new Error(finalizeData.error?.message || 'Upload finalize failed');
|
|
302
305
|
}
|
package/dist/commands/auth.js
CHANGED
|
@@ -5,7 +5,8 @@ import * as fs from 'fs/promises';
|
|
|
5
5
|
import * as path from 'path';
|
|
6
6
|
import * as os from 'os';
|
|
7
7
|
import { icons, startSpinner, stopSpinner, printHeader, printSection, printSuccess, printError, printInfo, printKeyValue, printCommandHint, createTable, printWelcome, } from '../ui.js';
|
|
8
|
-
import { SecureTokenStore
|
|
8
|
+
import { SecureTokenStore } from '../auth/secure-auth.js';
|
|
9
|
+
import { startDeviceFlow } from '../auth/device-auth.js';
|
|
9
10
|
const CONFIG_DIR = path.join(os.homedir(), '.delta');
|
|
10
11
|
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
11
12
|
async function loadConfig() {
|
|
@@ -26,24 +27,23 @@ export const authCommands = {
|
|
|
26
27
|
printWelcome();
|
|
27
28
|
printHeader('Authentication');
|
|
28
29
|
const token = options.token ?? process.env.DELTA_PAT;
|
|
29
|
-
//
|
|
30
|
+
// Load existing config to get custom apiUrl if set
|
|
31
|
+
const existingConfig = await loadConfig();
|
|
32
|
+
const apiUrl = process.env.DELTA_API_URL || existingConfig.apiUrl || 'http://localhost:3000';
|
|
33
|
+
// If no token provided, use Device Authorization Flow
|
|
30
34
|
if (!token) {
|
|
31
|
-
printInfo('No token provided. Starting
|
|
32
|
-
printInfo('
|
|
35
|
+
printInfo('No token provided. Starting Device Authorization Flow...');
|
|
36
|
+
printInfo('This will open your browser for secure authentication.');
|
|
33
37
|
console.log();
|
|
34
|
-
const success = await
|
|
38
|
+
const success = await startDeviceFlow(apiUrl);
|
|
35
39
|
if (!success) {
|
|
36
|
-
printError('
|
|
40
|
+
printError('Device authorization failed');
|
|
37
41
|
console.log();
|
|
38
42
|
printInfo('You can also authenticate using a Personal Access Token:');
|
|
39
43
|
printCommandHint('delta login --token <your-token>', '');
|
|
40
44
|
process.exit(1);
|
|
41
45
|
}
|
|
42
|
-
//
|
|
43
|
-
printSuccess('Authentication successful! 🎉');
|
|
44
|
-
console.log();
|
|
45
|
-
printCommandHint('delta whoami', 'to see account details');
|
|
46
|
-
printCommandHint('delta analyze', 'to start analyzing code');
|
|
46
|
+
// Device flow already saved the token and showed success
|
|
47
47
|
process.exit(0);
|
|
48
48
|
}
|
|
49
49
|
// PAT Token flow (when token is provided)
|
|
@@ -55,9 +55,6 @@ export const authCommands = {
|
|
|
55
55
|
printCommandHint('http://localhost:3000/dashboard/cli-tokens', '');
|
|
56
56
|
process.exit(1);
|
|
57
57
|
}
|
|
58
|
-
// Load existing config to get custom apiUrl if set
|
|
59
|
-
const existingConfig = await loadConfig();
|
|
60
|
-
const apiUrl = process.env.DELTA_API_URL || existingConfig.apiUrl || 'http://localhost:3000';
|
|
61
58
|
printSection('Connecting to Platform');
|
|
62
59
|
printKeyValue('API Endpoint', apiUrl);
|
|
63
60
|
console.log();
|
|
@@ -67,7 +64,7 @@ export const authCommands = {
|
|
|
67
64
|
const timeout = setTimeout(() => controller.abort(), 10000);
|
|
68
65
|
const response = await fetch(`${apiUrl}/api/me/entitlements`, {
|
|
69
66
|
headers: {
|
|
70
|
-
|
|
67
|
+
Authorization: `Bearer ${token}`,
|
|
71
68
|
'Content-Type': 'application/json',
|
|
72
69
|
},
|
|
73
70
|
signal: controller.signal,
|
|
@@ -77,7 +74,7 @@ export const authCommands = {
|
|
|
77
74
|
const errorText = await response.text().catch(() => response.statusText);
|
|
78
75
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
79
76
|
}
|
|
80
|
-
const data = await response.json();
|
|
77
|
+
const data = (await response.json());
|
|
81
78
|
if (!data.success) {
|
|
82
79
|
throw new Error(data.error?.message || 'Authentication failed');
|
|
83
80
|
}
|
package/dist/commands/status.js
CHANGED
|
@@ -47,11 +47,11 @@ export async function statusCommand(projectPath, _options) {
|
|
|
47
47
|
startSpinner('Testing connection...');
|
|
48
48
|
try {
|
|
49
49
|
const response = await fetch(`${apiUrl}/api/me/entitlements`, {
|
|
50
|
-
headers: {
|
|
50
|
+
headers: { Authorization: `Bearer ${pat}` },
|
|
51
51
|
});
|
|
52
52
|
if (response.ok) {
|
|
53
53
|
stopSpinner(true, 'Connection active');
|
|
54
|
-
const data = await response.json();
|
|
54
|
+
const data = (await response.json());
|
|
55
55
|
if (data.success) {
|
|
56
56
|
printKeyValue('User', data.data.user.email);
|
|
57
57
|
printKeyValue('Plan', data.data.user.plan);
|
package/dist/commands/whoami.js
CHANGED
|
@@ -21,7 +21,7 @@ export async function whoamiCommand(_options) {
|
|
|
21
21
|
const apiUrl = config.apiUrl || process.env.DELTA_API_URL || 'http://localhost:3000';
|
|
22
22
|
const response = await fetch(`${apiUrl}/api/auth/me`, {
|
|
23
23
|
headers: {
|
|
24
|
-
|
|
24
|
+
Authorization: `Bearer ${pat}`,
|
|
25
25
|
'Content-Type': 'application/json',
|
|
26
26
|
},
|
|
27
27
|
});
|
|
@@ -36,7 +36,7 @@ export async function whoamiCommand(_options) {
|
|
|
36
36
|
}
|
|
37
37
|
throw new Error(`API error: ${response.status} ${response.statusText}`);
|
|
38
38
|
}
|
|
39
|
-
const data = await response.json();
|
|
39
|
+
const data = (await response.json());
|
|
40
40
|
stopSpinner(true);
|
|
41
41
|
console.log();
|
|
42
42
|
const user = data;
|
|
@@ -62,10 +62,10 @@ export async function whoamiCommand(_options) {
|
|
|
62
62
|
}
|
|
63
63
|
function formatPlan(plan) {
|
|
64
64
|
const planColors = {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
individual_free: '🔷 Free',
|
|
66
|
+
individual_pro: '💎 Pro',
|
|
67
|
+
individual_team: '👥 Team',
|
|
68
|
+
enterprise: '🏢 Enterprise',
|
|
69
69
|
};
|
|
70
70
|
return planColors[plan] || plan;
|
|
71
71
|
}
|
|
@@ -28,7 +28,7 @@ const Sparkline = ({ data, width = 20 }) => {
|
|
|
28
28
|
return _jsx(Text, { color: "cyan", children: display.join('') });
|
|
29
29
|
};
|
|
30
30
|
// Progress bar component
|
|
31
|
-
const ProgressBar = ({ value, max, width = 20 }) => {
|
|
31
|
+
const ProgressBar = ({ value, max, width = 20, }) => {
|
|
32
32
|
const percentage = Math.min(Math.max(value / max, 0), 1);
|
|
33
33
|
const filled = Math.floor(percentage * width);
|
|
34
34
|
const empty = width - filled;
|
|
@@ -44,9 +44,7 @@ const StatusIndicator = ({ status }) => {
|
|
|
44
44
|
};
|
|
45
45
|
// Project row component
|
|
46
46
|
const ProjectRow = ({ project, isSelected }) => {
|
|
47
|
-
const timeAgo = project.lastAnalyze
|
|
48
|
-
? formatTimeAgo(project.lastAnalyze)
|
|
49
|
-
: 'never';
|
|
47
|
+
const timeAgo = project.lastAnalyze ? formatTimeAgo(project.lastAnalyze) : 'never';
|
|
50
48
|
const totalFindings = project.findings.high + project.findings.medium + project.findings.low;
|
|
51
49
|
const findingsColor = project.findings.high > 0 ? 'red' : project.findings.medium > 0 ? 'yellow' : 'green';
|
|
52
50
|
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"] }) })] }));
|
|
@@ -163,7 +161,7 @@ export const EnhancedDashboard = () => {
|
|
|
163
161
|
const project = data.projects[selectedIndex];
|
|
164
162
|
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Text, { bold: true, color: "cyan", children: ["\uD83D\uDCC1 Project Details: ", project.name] }), _jsx(CustomDivider, {}), _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" }) })] }));
|
|
165
163
|
}
|
|
166
|
-
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, color: "cyan", backgroundColor: "gray", children: [' ', "
|
|
164
|
+
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(CustomDivider, { 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" }) })] }));
|
|
167
165
|
};
|
|
168
166
|
export default EnhancedDashboard;
|
|
169
167
|
//# sourceMappingURL=Dashboard.js.map
|
|
@@ -12,7 +12,7 @@ export const DeltaLogo = () => {
|
|
|
12
12
|
const frames = ['◐', '◓', '◑', '◒'];
|
|
13
13
|
useEffect(() => {
|
|
14
14
|
const timer = setInterval(() => {
|
|
15
|
-
setFrame(
|
|
15
|
+
setFrame(f => (f + 1) % frames.length);
|
|
16
16
|
}, 100);
|
|
17
17
|
return () => clearInterval(timer);
|
|
18
18
|
}, []);
|
|
@@ -38,13 +38,17 @@ const SHORTCUTS = [
|
|
|
38
38
|
];
|
|
39
39
|
const getSeverityFromType = (type) => {
|
|
40
40
|
switch (type) {
|
|
41
|
-
case 'error':
|
|
42
|
-
|
|
43
|
-
case '
|
|
44
|
-
|
|
41
|
+
case 'error':
|
|
42
|
+
return 'high';
|
|
43
|
+
case 'warning':
|
|
44
|
+
return 'medium';
|
|
45
|
+
case 'success':
|
|
46
|
+
return 'low';
|
|
47
|
+
default:
|
|
48
|
+
return 'low';
|
|
45
49
|
}
|
|
46
50
|
};
|
|
47
|
-
const StatusBadge = ({ status, progress }) => {
|
|
51
|
+
const StatusBadge = ({ status, progress, }) => {
|
|
48
52
|
const config = {
|
|
49
53
|
stopped: { color: 'gray', text: 'STOPPED', icon: '○' },
|
|
50
54
|
running: { color: 'green', text: 'RUNNING', icon: '●' },
|
|
@@ -67,7 +71,7 @@ const LogEntry = ({ entry }) => {
|
|
|
67
71
|
const icons = { info: 'ℹ', success: '✓', error: '✗', warning: '⚠' };
|
|
68
72
|
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
73
|
};
|
|
70
|
-
const MenuItem = ({ item, isSelected }) => {
|
|
74
|
+
const MenuItem = ({ item, isSelected, }) => {
|
|
71
75
|
return (_jsxs(Box, { paddingX: 1, width: 28, children: [_jsxs(Text, { color: isSelected ? 'cyan' : 'gray', bold: isSelected, children: [isSelected ? '❯ ' : ' ', isSelected ? '' : ' '] }), _jsx(Text, { color: isSelected ? 'cyan' : 'cyan', bold: isSelected, children: item.num }), _jsx(Text, { children: " " }), _jsx(Text, { color: isSelected ? 'white' : 'gray', children: item.icon }), _jsx(Text, { children: " " }), _jsx(Text, { color: isSelected ? 'white' : 'gray', bold: isSelected, children: item.label }), _jsx(Text, { children: ' '.repeat(28 - item.label.length - 4) })] }));
|
|
72
76
|
};
|
|
73
77
|
const HelpModal = ({ onClose }) => {
|
|
@@ -75,12 +79,12 @@ const HelpModal = ({ onClose }) => {
|
|
|
75
79
|
if (key.escape || key.return)
|
|
76
80
|
onClose();
|
|
77
81
|
});
|
|
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
|
|
82
|
+
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
83
|
};
|
|
80
84
|
const FilterBar = ({ severity, source, isActive }) => {
|
|
81
85
|
const severities = ['all', 'high', 'medium', 'low'];
|
|
82
86
|
const sources = ['all', 'CLI', 'Web', 'Tests', 'Build', 'System'];
|
|
83
|
-
return (_jsx(Box, { flexDirection: "column", marginBottom: 1, children: _jsxs(Box, { children: [
|
|
87
|
+
return (_jsx(Box, { flexDirection: "column", marginBottom: 1, children: _jsxs(Box, { children: [_jsxs(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
88
|
};
|
|
85
89
|
const loadUserState = () => {
|
|
86
90
|
try {
|
|
@@ -114,8 +118,22 @@ export const UnifiedManager = () => {
|
|
|
114
118
|
const [severityFilter, setSeverityFilter] = useState('all');
|
|
115
119
|
const [sourceFilter, setSourceFilter] = useState('all');
|
|
116
120
|
const [services, setServices] = useState([
|
|
117
|
-
{
|
|
118
|
-
|
|
121
|
+
{
|
|
122
|
+
id: 'cli',
|
|
123
|
+
name: 'CLI Dev Server',
|
|
124
|
+
port: undefined,
|
|
125
|
+
status: 'stopped',
|
|
126
|
+
message: 'Ready to start',
|
|
127
|
+
progress: 0,
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
id: 'web',
|
|
131
|
+
name: 'Web Dev Server',
|
|
132
|
+
port: undefined,
|
|
133
|
+
status: 'stopped',
|
|
134
|
+
message: 'Ready to start',
|
|
135
|
+
progress: 0,
|
|
136
|
+
},
|
|
119
137
|
]);
|
|
120
138
|
const serviceProcesses = React.useRef(new Map());
|
|
121
139
|
const pluginRegistryRef = useRef(null);
|
|
@@ -172,12 +190,14 @@ export const UnifiedManager = () => {
|
|
|
172
190
|
const service = services.find(s => s.id === serviceId);
|
|
173
191
|
if (!service)
|
|
174
192
|
return;
|
|
175
|
-
setServices(prev => prev.map(s => s.id === serviceId
|
|
193
|
+
setServices(prev => prev.map(s => s.id === serviceId
|
|
194
|
+
? { ...s, status: 'building', message: 'Starting...', progress: 0 }
|
|
195
|
+
: s));
|
|
176
196
|
addLog(serviceId, 'Starting service...', 'info');
|
|
177
197
|
let progress = 0;
|
|
178
198
|
const progressInterval = setInterval(() => {
|
|
179
199
|
progress += 10;
|
|
180
|
-
setServices(prev => prev.map(s => s.id === serviceId ? { ...s, progress } : s));
|
|
200
|
+
setServices(prev => prev.map(s => (s.id === serviceId ? { ...s, progress } : s)));
|
|
181
201
|
if (progress >= 100)
|
|
182
202
|
clearInterval(progressInterval);
|
|
183
203
|
}, 150);
|
|
@@ -199,19 +219,23 @@ export const UnifiedManager = () => {
|
|
|
199
219
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
200
220
|
});
|
|
201
221
|
serviceProcesses.current.set(serviceId, proc);
|
|
202
|
-
proc.stdout?.on('data',
|
|
222
|
+
proc.stdout?.on('data', data => {
|
|
203
223
|
const output = data.toString().trim();
|
|
204
224
|
const portMatch = output.match(/localhost:(\d+)/) || output.match(/:(\d+)/);
|
|
205
225
|
if (portMatch) {
|
|
206
226
|
const port = parseInt(portMatch[1]);
|
|
207
|
-
setServices(prev => prev.map(s => s.id === serviceId
|
|
227
|
+
setServices(prev => prev.map(s => s.id === serviceId
|
|
228
|
+
? { ...s, status: 'running', port, message: 'Watching files...', progress: 100 }
|
|
229
|
+
: s));
|
|
208
230
|
addLog(serviceId, `Server running on port ${port}`, 'success');
|
|
209
231
|
}
|
|
210
232
|
});
|
|
211
|
-
proc.stderr?.on('data',
|
|
212
|
-
proc.on('exit',
|
|
233
|
+
proc.stderr?.on('data', data => addLog(serviceId, data.toString().trim(), 'error'));
|
|
234
|
+
proc.on('exit', code => {
|
|
213
235
|
clearInterval(progressInterval);
|
|
214
|
-
setServices(prev => prev.map(s => s.id === serviceId
|
|
236
|
+
setServices(prev => prev.map(s => s.id === serviceId
|
|
237
|
+
? { ...s, status: code === 0 ? 'stopped' : 'error', progress: 0, message: 'Stopped' }
|
|
238
|
+
: s));
|
|
215
239
|
serviceProcesses.current.delete(serviceId);
|
|
216
240
|
addLog(serviceId, code === 0 ? 'Service stopped' : 'Service crashed', code === 0 ? 'info' : 'error');
|
|
217
241
|
});
|
|
@@ -222,7 +246,9 @@ export const UnifiedManager = () => {
|
|
|
222
246
|
proc.kill('SIGTERM');
|
|
223
247
|
serviceProcesses.current.delete(serviceId);
|
|
224
248
|
}
|
|
225
|
-
setServices(prev => prev.map(s => s.id === serviceId
|
|
249
|
+
setServices(prev => prev.map(s => s.id === serviceId
|
|
250
|
+
? { ...s, status: 'stopped', port: undefined, message: 'Stopped', progress: 0 }
|
|
251
|
+
: s));
|
|
226
252
|
addLog(serviceId, 'Service stopped', 'info');
|
|
227
253
|
}, [addLog]);
|
|
228
254
|
const buildAll = useCallback(() => {
|
|
@@ -334,11 +360,13 @@ export const UnifiedManager = () => {
|
|
|
334
360
|
}
|
|
335
361
|
}
|
|
336
362
|
});
|
|
337
|
-
useEffect(() => {
|
|
363
|
+
useEffect(() => {
|
|
364
|
+
addLog('SYSTEM', 'Delta Unified Manager started', 'info');
|
|
365
|
+
}, []);
|
|
338
366
|
if (showHelp) {
|
|
339
367
|
return (_jsx(Box, { flexDirection: "column", height: 28, justifyContent: "center", alignItems: "center", children: _jsx(HelpModal, { onClose: () => setShowHelp(false) }) }));
|
|
340
368
|
}
|
|
341
|
-
return (_jsxs(Box, { flexDirection: "column", height: 28, children: [_jsxs(Box, { justifyContent: "space-between", paddingX: 1, paddingY: 0, children: [
|
|
369
|
+
return (_jsxs(Box, { flexDirection: "column", height: 28, children: [_jsxs(Box, { justifyContent: "space-between", paddingX: 1, paddingY: 0, children: [_jsxs(Text, { backgroundColor: "blue", bold: true, color: "white", children: [' ', "\uD83D\uDE80 Delta Project Manager", ' '] }), _jsxs(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" }), _jsxs(Text, { backgroundColor: "gray", color: "white", children: ["] Navigate", ' '] }), _jsx(Text, { backgroundColor: "gray", color: "white", children: "[" }), _jsx(Text, { backgroundColor: "gray", color: "cyan", children: "Enter" }), _jsxs(Text, { backgroundColor: "gray", color: "white", children: ["] Select", ' '] }), _jsx(Text, { backgroundColor: "gray", color: "white", children: "[" }), _jsx(Text, { backgroundColor: "gray", color: "cyan", children: "?" }), _jsxs(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: [_jsxs(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} ✓` : '○' }), _jsxs(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()] })] })] })] }));
|
|
342
370
|
};
|
|
343
371
|
export default UnifiedManager;
|
|
344
372
|
//# sourceMappingURL=UnifiedManager.js.map
|
package/dist/core/completion.js
CHANGED
|
@@ -21,7 +21,11 @@ export const completionDatabase = {
|
|
|
21
21
|
globalFlags: [
|
|
22
22
|
{ name: '--json', desc: 'Output as JSON' },
|
|
23
23
|
{ name: '--provider', values: ['local', 'remote', 'ai'], desc: 'Execution provider' },
|
|
24
|
-
{
|
|
24
|
+
{
|
|
25
|
+
name: '--theme',
|
|
26
|
+
values: ['delta', 'cyber', 'sunset', 'neon', 'ocean', 'fire'],
|
|
27
|
+
desc: 'Color theme',
|
|
28
|
+
},
|
|
25
29
|
{ name: '--verbose', desc: 'Verbose logging' },
|
|
26
30
|
{ name: '--no-color', desc: 'Disable colors' },
|
|
27
31
|
{ name: '--interactive', alias: '-i', desc: 'Interactive mode' },
|
|
@@ -43,7 +47,11 @@ export const completionDatabase = {
|
|
|
43
47
|
{ name: '--performance', desc: 'Performance analysis' },
|
|
44
48
|
],
|
|
45
49
|
init: [
|
|
46
|
-
{
|
|
50
|
+
{
|
|
51
|
+
name: '--template',
|
|
52
|
+
values: ['default', 'nextjs', 'react', 'node', 'python'],
|
|
53
|
+
desc: 'Project template',
|
|
54
|
+
},
|
|
47
55
|
{ name: '--force', alias: '-f', desc: 'Overwrite existing' },
|
|
48
56
|
{ name: '--git', desc: 'Initialize git' },
|
|
49
57
|
],
|
|
@@ -81,7 +89,10 @@ export function generateCompletionScript(shell) {
|
|
|
81
89
|
}
|
|
82
90
|
function generateBashCompletion(cliName) {
|
|
83
91
|
const commands = completionDatabase.commands.map(c => c.name).join(' ');
|
|
84
|
-
const slashCommands = completionDatabase.commands
|
|
92
|
+
const slashCommands = completionDatabase.commands
|
|
93
|
+
.flatMap(c => c.alias)
|
|
94
|
+
.filter(a => a.startsWith('/'))
|
|
95
|
+
.join(' ');
|
|
85
96
|
return `#!/bin/bash
|
|
86
97
|
# Delta CLI Bash Completion
|
|
87
98
|
# Source this file: source <(delta completion bash)
|