@mytechtoday/augment-extensions 0.5.0 → 0.7.0

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 (47) hide show
  1. package/cli/dist/cli.js +4 -0
  2. package/cli/dist/cli.js.map +1 -1
  3. package/cli/dist/commands/show.d.ts +4 -0
  4. package/cli/dist/commands/show.d.ts.map +1 -1
  5. package/cli/dist/commands/show.js +456 -23
  6. package/cli/dist/commands/show.js.map +1 -1
  7. package/cli/dist/utils/config-system.d.ts +111 -0
  8. package/cli/dist/utils/config-system.d.ts.map +1 -0
  9. package/cli/dist/utils/config-system.js +239 -0
  10. package/cli/dist/utils/config-system.js.map +1 -0
  11. package/cli/dist/utils/hook-system.d.ts +84 -0
  12. package/cli/dist/utils/hook-system.d.ts.map +1 -0
  13. package/cli/dist/utils/hook-system.js +151 -0
  14. package/cli/dist/utils/hook-system.js.map +1 -0
  15. package/cli/dist/utils/inspection-cache.d.ts +56 -0
  16. package/cli/dist/utils/inspection-cache.d.ts.map +1 -0
  17. package/cli/dist/utils/inspection-cache.js +166 -0
  18. package/cli/dist/utils/inspection-cache.js.map +1 -0
  19. package/cli/dist/utils/inspection-handlers.d.ts +75 -0
  20. package/cli/dist/utils/inspection-handlers.d.ts.map +1 -0
  21. package/cli/dist/utils/inspection-handlers.js +171 -0
  22. package/cli/dist/utils/inspection-handlers.js.map +1 -0
  23. package/cli/dist/utils/module-system.d.ts +1 -0
  24. package/cli/dist/utils/module-system.d.ts.map +1 -1
  25. package/cli/dist/utils/module-system.js +8 -3
  26. package/cli/dist/utils/module-system.js.map +1 -1
  27. package/cli/dist/utils/plugin-system.d.ts +133 -0
  28. package/cli/dist/utils/plugin-system.d.ts.map +1 -0
  29. package/cli/dist/utils/plugin-system.js +210 -0
  30. package/cli/dist/utils/plugin-system.js.map +1 -0
  31. package/cli/dist/utils/progress.d.ts +67 -0
  32. package/cli/dist/utils/progress.d.ts.map +1 -0
  33. package/cli/dist/utils/progress.js +146 -0
  34. package/cli/dist/utils/progress.js.map +1 -0
  35. package/cli/dist/utils/stream-reader.d.ts +34 -0
  36. package/cli/dist/utils/stream-reader.d.ts.map +1 -0
  37. package/cli/dist/utils/stream-reader.js +147 -0
  38. package/cli/dist/utils/stream-reader.js.map +1 -0
  39. package/cli/dist/utils/vscode-editor.d.ts +45 -0
  40. package/cli/dist/utils/vscode-editor.d.ts.map +1 -0
  41. package/cli/dist/utils/vscode-editor.js +171 -0
  42. package/cli/dist/utils/vscode-editor.js.map +1 -0
  43. package/cli/dist/utils/vscode-links.d.ts +49 -0
  44. package/cli/dist/utils/vscode-links.d.ts.map +1 -0
  45. package/cli/dist/utils/vscode-links.js +167 -0
  46. package/cli/dist/utils/vscode-links.js.map +1 -0
  47. package/package.json +1 -1
@@ -41,7 +41,13 @@ exports.showModuleCommand = showModuleCommand;
41
41
  const chalk_1 = __importDefault(require("chalk"));
42
42
  const fs = __importStar(require("fs"));
43
43
  const path = __importStar(require("path"));
44
+ const highlight_js_1 = __importDefault(require("highlight.js"));
44
45
  const module_system_1 = require("../utils/module-system");
46
+ const inspection_cache_1 = require("../utils/inspection-cache");
47
+ const stream_reader_1 = require("../utils/stream-reader");
48
+ const progress_1 = require("../utils/progress");
49
+ const vscode_links_1 = require("../utils/vscode-links");
50
+ const vscode_editor_1 = require("../utils/vscode-editor");
45
51
  /**
46
52
  * Legacy show command - displays basic module information
47
53
  * @deprecated Use showModuleCommand for enhanced inspection
@@ -116,6 +122,10 @@ async function showModuleCommand(moduleName, filePath, options) {
116
122
  console.log(chalk_1.default.gray(' augx show module php-standards rules/psr-standards.md'));
117
123
  process.exit(1);
118
124
  }
125
+ // Disable cache if --no-cache flag is set
126
+ if (options.noCache) {
127
+ inspection_cache_1.moduleInspectionCache.setEnabled(false);
128
+ }
119
129
  // Discover and validate module using enhanced discovery
120
130
  const module = (0, module_system_1.findModuleEnhanced)(moduleName);
121
131
  if (!module) {
@@ -144,12 +154,20 @@ async function showModuleCommand(moduleName, filePath, options) {
144
154
  // Module overview (default)
145
155
  await showModuleOverview(module, options);
146
156
  }
157
+ // Re-enable cache after command completes
158
+ if (options.noCache) {
159
+ inspection_cache_1.moduleInspectionCache.setEnabled(true);
160
+ }
147
161
  }
148
162
  catch (error) {
149
163
  console.error(chalk_1.default.red('Error inspecting module:'), error);
150
164
  if (error instanceof Error) {
151
165
  console.error(chalk_1.default.gray(error.message));
152
166
  }
167
+ // Re-enable cache on error
168
+ if (options.noCache) {
169
+ inspection_cache_1.moduleInspectionCache.setEnabled(true);
170
+ }
153
171
  process.exit(1);
154
172
  }
155
173
  }
@@ -157,11 +175,18 @@ async function showModuleCommand(moduleName, filePath, options) {
157
175
  * Display module overview with metadata and file listing
158
176
  */
159
177
  async function showModuleOverview(module, options) {
160
- // Extract comprehensive metadata
161
- const extendedMetadata = (0, module_system_1.extractModuleMetadata)(module.path);
178
+ // Try to get from cache first
179
+ const cacheKey = `overview:${module.fullName}`;
180
+ let extendedMetadata = inspection_cache_1.moduleInspectionCache.get(cacheKey, module.path);
162
181
  if (!extendedMetadata) {
163
- console.error(chalk_1.default.red('Failed to extract module metadata'));
164
- return;
182
+ // Extract comprehensive metadata
183
+ extendedMetadata = (0, module_system_1.extractModuleMetadata)(module.path);
184
+ if (!extendedMetadata) {
185
+ console.error(chalk_1.default.red('Failed to extract module metadata'));
186
+ return;
187
+ }
188
+ // Cache the result
189
+ inspection_cache_1.moduleInspectionCache.set(cacheKey, extendedMetadata, module.path);
165
190
  }
166
191
  // Handle JSON output format
167
192
  if (options.json || options.format === 'json') {
@@ -189,7 +214,69 @@ async function showModuleOverview(module, options) {
189
214
  console.log(JSON.stringify(jsonOutput, null, 2));
190
215
  return;
191
216
  }
192
- // Text output format (default)
217
+ // Handle Markdown output format
218
+ if (options.format === 'markdown') {
219
+ console.log(`# ${module.fullName}\n`);
220
+ console.log(`**Version:** ${extendedMetadata.version}\n`);
221
+ console.log(`**Type:** ${extendedMetadata.type}\n`);
222
+ console.log(`**Description:** ${extendedMetadata.description}\n`);
223
+ if (extendedMetadata.tags && extendedMetadata.tags.length > 0) {
224
+ console.log(`**Tags:** ${extendedMetadata.tags.join(', ')}\n`);
225
+ }
226
+ console.log(`## Files\n`);
227
+ console.log(`- Total: ${extendedMetadata.files?.total || 0}`);
228
+ console.log(`- Rules: ${extendedMetadata.files?.rules || 0}`);
229
+ console.log(`- Examples: ${extendedMetadata.files?.examples || 0}`);
230
+ console.log(`- Other: ${extendedMetadata.files?.other || 0}\n`);
231
+ console.log(`## Size\n`);
232
+ const totalBytes = extendedMetadata.size?.totalBytes || 0;
233
+ const totalChars = extendedMetadata.size?.totalCharacters || 0;
234
+ console.log(`- Total: ${formatBytes(totalBytes)} (${totalBytes.toLocaleString()} bytes)`);
235
+ console.log(`- Characters: ${totalChars.toLocaleString()}\n`);
236
+ if (extendedMetadata.lastModified) {
237
+ console.log(`**Last Modified:** ${formatDate(extendedMetadata.lastModified)}\n`);
238
+ }
239
+ console.log(`**Location:** \`${module.path}\`\n`);
240
+ return;
241
+ }
242
+ // Handle plain text output format (ASCII-only, no colors)
243
+ if (options.format === 'text') {
244
+ console.log();
245
+ console.log(`Module: ${module.fullName}`);
246
+ console.log('='.repeat(60));
247
+ console.log();
248
+ console.log('Metadata:');
249
+ console.log(` Name: ${extendedMetadata.displayName}`);
250
+ console.log(` Version: ${extendedMetadata.version}`);
251
+ console.log(` Type: ${extendedMetadata.type}`);
252
+ console.log(` Description: ${extendedMetadata.description}`);
253
+ if (extendedMetadata.tags && extendedMetadata.tags.length > 0) {
254
+ console.log(` Tags: ${extendedMetadata.tags.join(', ')}`);
255
+ }
256
+ console.log();
257
+ console.log('Files:');
258
+ console.log(` Total: ${extendedMetadata.files?.total || 0}`);
259
+ console.log(` Rules: ${extendedMetadata.files?.rules || 0}`);
260
+ console.log(` Examples: ${extendedMetadata.files?.examples || 0}`);
261
+ console.log(` Other: ${extendedMetadata.files?.other || 0}`);
262
+ console.log();
263
+ console.log('Size:');
264
+ const totalBytes = extendedMetadata.size?.totalBytes || 0;
265
+ const totalChars = extendedMetadata.size?.totalCharacters || 0;
266
+ console.log(` Total: ${formatBytes(totalBytes)} (${totalBytes.toLocaleString()} bytes)`);
267
+ console.log(` Characters: ${totalChars.toLocaleString()}`);
268
+ console.log();
269
+ if (extendedMetadata.lastModified) {
270
+ console.log('Last Modified:');
271
+ console.log(` ${formatDate(extendedMetadata.lastModified)}`);
272
+ console.log();
273
+ }
274
+ console.log('Location:');
275
+ console.log(` ${module.path}`);
276
+ console.log();
277
+ return;
278
+ }
279
+ // Colored text output format (default)
193
280
  console.log();
194
281
  console.log(chalk_1.default.bold.blue(`📦 ${module.fullName}`));
195
282
  console.log(chalk_1.default.gray('─'.repeat(60)));
@@ -289,7 +376,8 @@ async function showModuleContent(module, options) {
289
376
  const files = listModuleFiles(module.path, {
290
377
  recursive: true,
291
378
  filter: options.filter || '*.md',
292
- groupByDirectory: true
379
+ groupByDirectory: true,
380
+ depth: options.depth
293
381
  });
294
382
  if (files.length === 0) {
295
383
  console.log(chalk_1.default.yellow('No markdown files found in module'));
@@ -320,12 +408,22 @@ async function showModuleContent(module, options) {
320
408
  modified: f.modified,
321
409
  type: f.type
322
410
  })),
323
- content: files.map(f => ({
324
- file: f.relativePath,
325
- content: fs.readFileSync(f.path, 'utf-8')
326
- }))
411
+ content: files.map(f => {
412
+ let content = fs.readFileSync(f.path, 'utf-8');
413
+ if (options.secure) {
414
+ content = redactSensitiveData(content, false);
415
+ }
416
+ return {
417
+ file: f.relativePath,
418
+ content: content
419
+ };
420
+ })
327
421
  };
328
422
  console.log(JSON.stringify(jsonOutput, null, 2));
423
+ // Log redactions summary if secure mode is enabled
424
+ if (options.secure) {
425
+ console.error(chalk_1.default.yellow('\n⚠️ Sensitive data has been redacted from output'));
426
+ }
329
427
  return;
330
428
  }
331
429
  // Handle Markdown output format
@@ -333,16 +431,61 @@ async function showModuleContent(module, options) {
333
431
  console.log(`# ${module.fullName}\n`);
334
432
  console.log(`**Module Type:** ${module.metadata.type}\n`);
335
433
  console.log(`**Version:** ${module.metadata.version}\n`);
434
+ if (options.secure) {
435
+ console.log(`**Security:** Sensitive data redacted\n`);
436
+ }
336
437
  console.log(`---\n`);
337
438
  for (const file of files) {
338
439
  console.log(`## ${file.relativePath}\n`);
339
- const content = fs.readFileSync(file.path, 'utf-8');
440
+ let content = fs.readFileSync(file.path, 'utf-8');
441
+ if (options.secure) {
442
+ content = redactSensitiveData(content, false);
443
+ }
340
444
  console.log(content);
341
445
  console.log('\n---\n');
342
446
  }
447
+ if (options.secure) {
448
+ console.log(`\n> ⚠️ Sensitive data has been redacted from this output\n`);
449
+ }
450
+ return;
451
+ }
452
+ // Handle plain text output format (ASCII-only, no colors)
453
+ if (options.format === 'text') {
454
+ console.log();
455
+ console.log(`Aggregated Content: ${module.fullName}`);
456
+ console.log('='.repeat(60));
457
+ console.log();
458
+ console.log(`Files: ${files.length}`);
459
+ if (options.secure) {
460
+ console.log('Security: Sensitive data redacted');
461
+ }
462
+ console.log();
463
+ for (const file of files) {
464
+ console.log(`File: ${file.relativePath}`);
465
+ console.log(`Size: ${formatBytes(file.size)} | Modified: ${formatDate(file.modified)}`);
466
+ console.log('-'.repeat(60));
467
+ console.log();
468
+ let content = fs.readFileSync(file.path, 'utf-8');
469
+ if (options.secure) {
470
+ content = redactSensitiveData(content, false);
471
+ }
472
+ console.log(content);
473
+ console.log();
474
+ console.log('='.repeat(60));
475
+ console.log();
476
+ }
477
+ const totalSize = files.reduce((sum, f) => sum + f.size, 0);
478
+ console.log('Summary:');
479
+ console.log(` Total files: ${files.length}`);
480
+ console.log(` Total size: ${formatBytes(totalSize)}`);
481
+ if (options.secure) {
482
+ console.log();
483
+ console.log('WARNING: Sensitive data has been redacted from this output');
484
+ }
485
+ console.log();
343
486
  return;
344
487
  }
345
- // Text output format (default)
488
+ // Colored text output format (default)
346
489
  console.log();
347
490
  console.log(chalk_1.default.bold.blue(`📄 Aggregated Content: ${module.fullName}`));
348
491
  console.log(chalk_1.default.gray('─'.repeat(60)));
@@ -360,6 +503,9 @@ async function showModuleContent(module, options) {
360
503
  paginationInfo = ` (Page ${currentPage} of ${totalPages})`;
361
504
  }
362
505
  console.log(chalk_1.default.bold(`Files: ${files.length}${paginationInfo}`));
506
+ if (options.secure) {
507
+ console.log(chalk_1.default.yellow('🔒 Security: Sensitive data redacted'));
508
+ }
363
509
  console.log();
364
510
  // Display each file with section headers
365
511
  for (const file of filesToDisplay) {
@@ -367,7 +513,10 @@ async function showModuleContent(module, options) {
367
513
  console.log(chalk_1.default.gray(`│ Size: ${formatBytes(file.size)} | Modified: ${formatDate(file.modified)}`));
368
514
  console.log(chalk_1.default.bold.cyan('└' + '─'.repeat(58)));
369
515
  console.log();
370
- const content = fs.readFileSync(file.path, 'utf-8');
516
+ let content = fs.readFileSync(file.path, 'utf-8');
517
+ if (options.secure) {
518
+ content = redactSensitiveData(content, false);
519
+ }
371
520
  // Preserve markdown formatting
372
521
  console.log(content);
373
522
  console.log();
@@ -391,6 +540,10 @@ async function showModuleContent(module, options) {
391
540
  console.log(chalk_1.default.cyan(` Prev page: augx show module ${module.fullName} --content --page ${currentPage - 1}`));
392
541
  }
393
542
  }
543
+ if (options.secure) {
544
+ console.log();
545
+ console.log(chalk_1.default.yellow('⚠️ Sensitive data has been redacted from this output'));
546
+ }
394
547
  console.log();
395
548
  }
396
549
  /**
@@ -413,10 +566,71 @@ async function showModuleFile(module, filePath, options) {
413
566
  console.log(chalk_1.default.gray(`Module path: ${module.path}`));
414
567
  process.exit(1);
415
568
  }
416
- // Read file content
417
- const content = fs.readFileSync(fullPath, 'utf-8');
418
- const lines = content.split('\n');
569
+ // Handle --open flag: Open file in VS Code editor
570
+ if (options.open) {
571
+ try {
572
+ if (!(0, vscode_editor_1.isVSCodeAvailable)()) {
573
+ console.error(chalk_1.default.red('VS Code CLI is not available. Please install VS Code and ensure "code" is in your PATH.'));
574
+ process.exit(1);
575
+ }
576
+ await (0, vscode_editor_1.openInEditor)(fullPath);
577
+ console.log(chalk_1.default.green(`✓ Opened ${path.basename(fullPath)} in VS Code editor`));
578
+ return;
579
+ }
580
+ catch (error) {
581
+ console.error(chalk_1.default.red(`Failed to open file: ${error instanceof Error ? error.message : String(error)}`));
582
+ process.exit(1);
583
+ }
584
+ }
585
+ // Handle --preview flag: Open file in VS Code preview pane
586
+ if (options.preview) {
587
+ try {
588
+ if (!(0, vscode_editor_1.isVSCodeAvailable)()) {
589
+ console.error(chalk_1.default.red('VS Code CLI is not available. Please install VS Code and ensure "code" is in your PATH.'));
590
+ process.exit(1);
591
+ }
592
+ await (0, vscode_editor_1.openInPreview)(fullPath);
593
+ console.log(chalk_1.default.green(`✓ Opened ${path.basename(fullPath)} in VS Code preview pane`));
594
+ return;
595
+ }
596
+ catch (error) {
597
+ console.error(chalk_1.default.red(`Failed to open file: ${error instanceof Error ? error.message : String(error)}`));
598
+ process.exit(1);
599
+ }
600
+ }
419
601
  const stats = fs.statSync(fullPath);
602
+ const fileSizeThreshold = 1024 * 1024; // 1MB threshold for streaming
603
+ // Use streaming for large files
604
+ let content;
605
+ if (stats.size > fileSizeThreshold) {
606
+ // Show progress for large files
607
+ const spinner = new progress_1.Spinner(`Reading large file (${formatBytes(stats.size)})...`);
608
+ spinner.start();
609
+ try {
610
+ // Stream large files
611
+ const chunks = [];
612
+ await (0, stream_reader_1.readFileStreaming)(fullPath, async (chunk, streamStats) => {
613
+ chunks.push(chunk);
614
+ const progress = (streamStats.bytesRead / stats.size) * 100;
615
+ spinner.setText(`Reading large file: ${progress.toFixed(1)}% (${formatBytes(streamStats.bytesRead)}/${formatBytes(stats.size)})`);
616
+ }, { highWaterMark: 64 * 1024 });
617
+ content = chunks.join('');
618
+ spinner.stop(chalk_1.default.green('✓ File loaded successfully'));
619
+ }
620
+ catch (error) {
621
+ spinner.stop(chalk_1.default.red('✗ Failed to read file'));
622
+ throw error;
623
+ }
624
+ }
625
+ else {
626
+ // Read small files normally
627
+ content = fs.readFileSync(fullPath, 'utf-8');
628
+ }
629
+ // Apply redaction if secure flag is set
630
+ if (options.secure) {
631
+ content = redactSensitiveData(content, true);
632
+ }
633
+ const lines = content.split('\n');
420
634
  // Get relative path for display
421
635
  const relativePath = path.relative(module.path, fullPath);
422
636
  // Handle JSON output format
@@ -443,27 +657,87 @@ async function showModuleFile(module, filePath, options) {
443
657
  console.log('```');
444
658
  return;
445
659
  }
446
- // Text output format (default) with line numbers
660
+ // Handle plain text output format (ASCII-only, no colors, no line numbers)
661
+ if (options.format === 'text') {
662
+ console.log();
663
+ console.log(`File: ${relativePath}`);
664
+ console.log('='.repeat(60));
665
+ console.log();
666
+ console.log('File Information:');
667
+ console.log(` Module: ${module.fullName}`);
668
+ console.log(` Path: ${relativePath}`);
669
+ console.log(` Size: ${formatBytes(stats.size)}`);
670
+ console.log(` Lines: ${lines.length}`);
671
+ console.log(` Modified: ${formatDate(stats.mtime)}`);
672
+ const detectedLang = detectLanguage(fullPath);
673
+ if (detectedLang) {
674
+ console.log(` Language: ${detectedLang}`);
675
+ }
676
+ console.log();
677
+ console.log('Content:');
678
+ console.log('-'.repeat(60));
679
+ console.log();
680
+ console.log(content);
681
+ console.log();
682
+ console.log('='.repeat(60));
683
+ console.log();
684
+ return;
685
+ }
686
+ // Colored text output format (default) with line numbers
687
+ const workspaceRoot = (0, vscode_links_1.getWorkspaceRoot)();
688
+ const clickablePath = (0, vscode_links_1.formatClickablePath)(fullPath, { workspaceRoot });
447
689
  console.log();
448
690
  console.log(chalk_1.default.bold.blue(`📄 ${relativePath}`));
691
+ console.log(chalk_1.default.gray(` ${clickablePath}`));
449
692
  console.log(chalk_1.default.gray('─'.repeat(60)));
450
693
  console.log();
451
694
  console.log(chalk_1.default.bold('File Information:'));
452
695
  console.log(chalk_1.default.gray(` Module: ${module.fullName}`));
453
696
  console.log(chalk_1.default.gray(` Path: ${relativePath}`));
697
+ console.log(chalk_1.default.gray(` Full: ${clickablePath}`));
454
698
  console.log(chalk_1.default.gray(` Size: ${formatBytes(stats.size)}`));
455
699
  console.log(chalk_1.default.gray(` Lines: ${lines.length}`));
456
700
  console.log(chalk_1.default.gray(` Modified: ${formatDate(stats.mtime)}`));
701
+ // Display detected language
702
+ const detectedLang = detectLanguage(fullPath);
703
+ if (detectedLang) {
704
+ console.log(chalk_1.default.gray(` Language: ${detectedLang}`));
705
+ }
457
706
  console.log();
458
707
  console.log(chalk_1.default.bold('Content:'));
459
708
  console.log(chalk_1.default.gray('─'.repeat(60)));
460
709
  console.log();
461
- // Display content with line numbers
462
- const lineNumberWidth = lines.length.toString().length;
463
- lines.forEach((line, index) => {
464
- const lineNumber = (index + 1).toString().padStart(lineNumberWidth, ' ');
465
- console.log(chalk_1.default.gray(`${lineNumber} │ `) + line);
466
- });
710
+ // Apply syntax highlighting if enabled (default: enabled)
711
+ const enableHighlighting = options.format !== 'text' && process.stdout.isTTY;
712
+ if (enableHighlighting && detectedLang) {
713
+ // Try to apply syntax highlighting
714
+ try {
715
+ const highlighted = applySyntaxHighlighting(content, fullPath, true);
716
+ const highlightedLines = highlighted.split('\n');
717
+ // Display with line numbers
718
+ const lineNumberWidth = highlightedLines.length.toString().length;
719
+ highlightedLines.forEach((line, index) => {
720
+ const lineNumber = (index + 1).toString().padStart(lineNumberWidth, ' ');
721
+ console.log(chalk_1.default.gray(`${lineNumber} │ `) + line);
722
+ });
723
+ }
724
+ catch (error) {
725
+ // Fallback to plain display if highlighting fails
726
+ const lineNumberWidth = lines.length.toString().length;
727
+ lines.forEach((line, index) => {
728
+ const lineNumber = (index + 1).toString().padStart(lineNumberWidth, ' ');
729
+ console.log(chalk_1.default.gray(`${lineNumber} │ `) + line);
730
+ });
731
+ }
732
+ }
733
+ else {
734
+ // Display content with line numbers (no highlighting)
735
+ const lineNumberWidth = lines.length.toString().length;
736
+ lines.forEach((line, index) => {
737
+ const lineNumber = (index + 1).toString().padStart(lineNumberWidth, ' ');
738
+ console.log(chalk_1.default.gray(`${lineNumber} │ `) + line);
739
+ });
740
+ }
467
741
  console.log();
468
742
  console.log(chalk_1.default.gray('─'.repeat(60)));
469
743
  console.log();
@@ -551,6 +825,100 @@ function highlightSearchTerm(text, searchTerm) {
551
825
  const regex = new RegExp(`(${searchTerm})`, 'gi');
552
826
  return text.replace(regex, chalk_1.default.yellow.bold('$1'));
553
827
  }
828
+ /**
829
+ * Apply syntax highlighting to code content
830
+ * Detects language from file extension and applies appropriate highlighting
831
+ */
832
+ function applySyntaxHighlighting(content, filePath, enableColors = true) {
833
+ if (!enableColors) {
834
+ return content;
835
+ }
836
+ try {
837
+ // Detect language from file extension
838
+ const ext = path.extname(filePath).toLowerCase();
839
+ const languageMap = {
840
+ '.ts': 'typescript',
841
+ '.js': 'javascript',
842
+ '.jsx': 'javascript',
843
+ '.tsx': 'typescript',
844
+ '.py': 'python',
845
+ '.php': 'php',
846
+ '.rb': 'ruby',
847
+ '.go': 'go',
848
+ '.rs': 'rust',
849
+ '.java': 'java',
850
+ '.c': 'c',
851
+ '.cpp': 'cpp',
852
+ '.cs': 'csharp',
853
+ '.sh': 'bash',
854
+ '.ps1': 'powershell',
855
+ '.md': 'markdown',
856
+ '.json': 'json',
857
+ '.yaml': 'yaml',
858
+ '.yml': 'yaml',
859
+ '.xml': 'xml',
860
+ '.html': 'html',
861
+ '.css': 'css',
862
+ '.scss': 'scss',
863
+ '.sql': 'sql'
864
+ };
865
+ const language = languageMap[ext];
866
+ if (language) {
867
+ const highlighted = highlight_js_1.default.highlight(content, { language, ignoreIllegals: true });
868
+ return highlighted.value;
869
+ }
870
+ // Auto-detect if no extension match
871
+ const autoDetected = highlight_js_1.default.highlightAuto(content);
872
+ return autoDetected.value;
873
+ }
874
+ catch (error) {
875
+ // If highlighting fails, return original content
876
+ return content;
877
+ }
878
+ }
879
+ /**
880
+ * Convert ANSI color codes from highlight.js to chalk colors
881
+ * This is a simplified version - highlight.js uses HTML-like tags
882
+ */
883
+ function convertHighlightToChalk(highlightedCode) {
884
+ // highlight.js returns HTML-like output, we need to convert to terminal colors
885
+ // For now, return as-is since we're using it in terminal context
886
+ // A more sophisticated implementation would parse the HTML and apply chalk colors
887
+ return highlightedCode;
888
+ }
889
+ /**
890
+ * Detect language from file extension
891
+ */
892
+ function detectLanguage(filePath) {
893
+ const ext = path.extname(filePath).toLowerCase();
894
+ const languageMap = {
895
+ '.ts': 'TypeScript',
896
+ '.js': 'JavaScript',
897
+ '.jsx': 'JavaScript (JSX)',
898
+ '.tsx': 'TypeScript (TSX)',
899
+ '.py': 'Python',
900
+ '.php': 'PHP',
901
+ '.rb': 'Ruby',
902
+ '.go': 'Go',
903
+ '.rs': 'Rust',
904
+ '.java': 'Java',
905
+ '.c': 'C',
906
+ '.cpp': 'C++',
907
+ '.cs': 'C#',
908
+ '.sh': 'Bash',
909
+ '.ps1': 'PowerShell',
910
+ '.md': 'Markdown',
911
+ '.json': 'JSON',
912
+ '.yaml': 'YAML',
913
+ '.yml': 'YAML',
914
+ '.xml': 'XML',
915
+ '.html': 'HTML',
916
+ '.css': 'CSS',
917
+ '.scss': 'SCSS',
918
+ '.sql': 'SQL'
919
+ };
920
+ return languageMap[ext] || null;
921
+ }
554
922
  /**
555
923
  * Get similar modules for legacy showCommand
556
924
  * @deprecated Use getModuleSuggestions from module-system instead
@@ -559,4 +927,69 @@ async function getSimilarModules(searchTerm) {
559
927
  const suggestions = (0, module_system_1.getModuleSuggestions)(searchTerm, 5);
560
928
  return suggestions.map(m => m.fullName);
561
929
  }
930
+ /**
931
+ * Redaction patterns for sensitive data
932
+ */
933
+ const REDACTION_PATTERNS = [
934
+ // API Keys
935
+ { pattern: /\b([A-Za-z0-9_-]*API[_-]?KEY[_-]?[A-Za-z0-9_-]*)\s*[:=]\s*['"]?([A-Za-z0-9_\-\/+=]{16,})['"]?/gi, name: 'API_KEY' },
936
+ { pattern: /\b(api[_-]?key)\s*[:=]\s*['"]?([A-Za-z0-9_\-\/+=]{16,})['"]?/gi, name: 'API_KEY' },
937
+ // Secrets
938
+ { pattern: /\b([A-Za-z0-9_-]*SECRET[_-]?[A-Za-z0-9_-]*)\s*[:=]\s*['"]?([A-Za-z0-9_\-\/+=]{16,})['"]?/gi, name: 'SECRET' },
939
+ { pattern: /\b(secret)\s*[:=]\s*['"]?([A-Za-z0-9_\-\/+=]{16,})['"]?/gi, name: 'SECRET' },
940
+ // Tokens
941
+ { pattern: /\b([A-Za-z0-9_-]*TOKEN[_-]?[A-Za-z0-9_-]*)\s*[:=]\s*['"]?([A-Za-z0-9_\-\/+=]{16,})['"]?/gi, name: 'TOKEN' },
942
+ { pattern: /\b(token)\s*[:=]\s*['"]?([A-Za-z0-9_\-\/+=]{16,})['"]?/gi, name: 'TOKEN' },
943
+ { pattern: /\b(bearer)\s+([A-Za-z0-9_\-\/+=]{16,})/gi, name: 'BEARER_TOKEN' },
944
+ // Passwords
945
+ { pattern: /\b([A-Za-z0-9_-]*PASSWORD[_-]?[A-Za-z0-9_-]*)\s*[:=]\s*['"]?([^\s'"]{8,})['"]?/gi, name: 'PASSWORD' },
946
+ { pattern: /\b(password|passwd|pwd)\s*[:=]\s*['"]?([^\s'"]{8,})['"]?/gi, name: 'PASSWORD' },
947
+ // Private Keys
948
+ { pattern: /(-----BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY-----[\s\S]*?-----END\s+(?:RSA\s+)?PRIVATE\s+KEY-----)/gi, name: 'PRIVATE_KEY' },
949
+ // AWS Keys
950
+ { pattern: /\b(AKIA[0-9A-Z]{16})\b/g, name: 'AWS_ACCESS_KEY' },
951
+ { pattern: /\b([A-Za-z0-9/+=]{40})\b/g, name: 'AWS_SECRET_KEY' },
952
+ // GitHub Tokens
953
+ { pattern: /\b(ghp_[A-Za-z0-9]{36})\b/g, name: 'GITHUB_TOKEN' },
954
+ { pattern: /\b(gho_[A-Za-z0-9]{36})\b/g, name: 'GITHUB_OAUTH' },
955
+ { pattern: /\b(ghu_[A-Za-z0-9]{36})\b/g, name: 'GITHUB_USER_TOKEN' },
956
+ { pattern: /\b(ghs_[A-Za-z0-9]{36})\b/g, name: 'GITHUB_SERVER_TOKEN' },
957
+ { pattern: /\b(ghr_[A-Za-z0-9]{36})\b/g, name: 'GITHUB_REFRESH_TOKEN' },
958
+ // Generic credentials
959
+ { pattern: /\b(credentials?)\s*[:=]\s*['"]?([^\s'"]{16,})['"]?/gi, name: 'CREDENTIALS' },
960
+ { pattern: /\b(auth)\s*[:=]\s*['"]?([A-Za-z0-9_\-\/+=]{16,})['"]?/gi, name: 'AUTH' }
961
+ ];
962
+ /**
963
+ * Redact sensitive data from content
964
+ */
965
+ function redactSensitiveData(content, logRedactions = false) {
966
+ let redactedContent = content;
967
+ const redactions = [];
968
+ for (const { pattern, name } of REDACTION_PATTERNS) {
969
+ const matches = content.match(pattern);
970
+ if (matches && matches.length > 0) {
971
+ redactedContent = redactedContent.replace(pattern, (match, ...args) => {
972
+ // For patterns with capture groups, preserve the key name but redact the value
973
+ if (args.length >= 2) {
974
+ const keyName = args[0];
975
+ return `${keyName}=[REDACTED_${name}]`;
976
+ }
977
+ // For patterns without capture groups, redact the entire match
978
+ return `[REDACTED_${name}]`;
979
+ });
980
+ if (logRedactions) {
981
+ redactions.push({ pattern: name, count: matches.length });
982
+ }
983
+ }
984
+ }
985
+ // Log redactions if requested
986
+ if (logRedactions && redactions.length > 0) {
987
+ console.log(chalk_1.default.yellow('\n⚠️ Sensitive data redacted:'));
988
+ for (const { pattern, count } of redactions) {
989
+ console.log(chalk_1.default.gray(` ${pattern}: ${count} occurrence(s)`));
990
+ }
991
+ console.log();
992
+ }
993
+ return redactedContent;
994
+ }
562
995
  //# sourceMappingURL=show.js.map