@tng-sh/js 0.1.8 → 0.1.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/bin/tng.js CHANGED
@@ -28,7 +28,35 @@ process.on('uncaughtException', (err) => {
28
28
  program
29
29
  .name('tng')
30
30
  .description('TNG - Advanced Code Audit, Test Generation, Visualization, Clone Detection, and Dead Code Analysis for JavaScript/TypeScript')
31
- .version('0.1.8');
31
+ .version('0.1.9');
32
+
33
+ /**
34
+ * Copy text to system clipboard
35
+ */
36
+ function copyToClipboard(text) {
37
+ const { execSync } = require('child_process');
38
+ try {
39
+ if (process.platform === 'darwin') {
40
+ execSync('pbcopy', { input: text });
41
+ return true;
42
+ } else if (process.platform === 'linux') {
43
+ try {
44
+ execSync('xclip -selection clipboard', { input: text });
45
+ return true;
46
+ } catch (e) {
47
+ try {
48
+ execSync('xsel --clipboard --input', { input: text });
49
+ return true;
50
+ } catch (e2) {
51
+ return false;
52
+ }
53
+ }
54
+ }
55
+ } catch (e) {
56
+ return false;
57
+ }
58
+ return false;
59
+ }
32
60
 
33
61
  /**
34
62
  * @command init
@@ -153,6 +181,7 @@ program
153
181
  .description('Generate X-Ray visualization')
154
182
  .option('-f, --file <path>', 'Input file path')
155
183
  .option('-m, --method <name>', 'Method name to visualize')
184
+ .option('-j, --json', 'Output results in JSON format')
156
185
  .action(async (options) => {
157
186
  if (!options.file || !options.method) {
158
187
  console.log(chalk.red('Error: Both --file and --method are required for X-Ray.'));
@@ -183,18 +212,28 @@ program
183
212
  callback
184
213
  );
185
214
 
215
+ if (options.json) {
216
+ console.log(resultJson);
217
+ return;
218
+ }
219
+
186
220
  let mermaidCode = "";
221
+ let explanation = "";
187
222
  try {
188
223
  const parsed = JSON.parse(resultJson);
189
224
  mermaidCode = parsed.mermaid_code || resultJson;
225
+ explanation = parsed.explanation || "";
190
226
  } catch (e) {
191
227
  mermaidCode = resultJson;
192
228
  }
193
229
 
194
- console.log(chalk.bold('\n--- X-Ray Result (Mermaid.js) ---\n'));
195
- console.log(chalk.blue(mermaidCode));
196
- console.log(chalk.bold('\n---------------------------------\n'));
197
- console.log(chalk.green('✓ Copy the code above and paste into https://mermaid.live'));
230
+ // Copy to clipboard
231
+ copyToClipboard(mermaidCode);
232
+
233
+ // Launch Premium UI
234
+ const GoUISession = require('../lib/goUiSession');
235
+ const session = new GoUISession();
236
+ await session.showXrayResults(options.method, '', mermaidCode, explanation);
198
237
 
199
238
  } catch (e) {
200
239
  console.log(chalk.red(`Error: ${e.message}`));
@@ -214,6 +253,7 @@ program
214
253
  .option('-c, --clones', 'Run duplicate code detection')
215
254
  .option('-l, --level <level>', 'Set clone detection level (1: token, 2: structural, 3: fuzzy, or all)', 'all')
216
255
  .option('-d, --deadcode', 'Run dead code detection (JS/TS/React)')
256
+ .option('--xray', 'Generate X-Ray visualization (Mermaid flowchart)')
217
257
  .option('--json', 'Output results as JSON events (machine-readable)')
218
258
 
219
259
  .action(async (options) => {
@@ -258,6 +298,52 @@ program
258
298
  return;
259
299
  }
260
300
 
301
+ if (options.xray) {
302
+ const config = loadConfig();
303
+ const { generateTest: nativeGenerateTest } = require('../index');
304
+
305
+ try {
306
+ const resultJson = nativeGenerateTest(
307
+ path.resolve(options.file),
308
+ options.method,
309
+ null,
310
+ 'visualize',
311
+ JSON.stringify(config),
312
+ (msg, percent) => {
313
+ if (options.json) return;
314
+ if (percent % 20 === 0) console.log(chalk.dim(`[${percent}%] ${msg}`));
315
+ }
316
+ );
317
+
318
+ if (options.json) {
319
+ console.log(resultJson);
320
+ return;
321
+ }
322
+
323
+ // For global --xray, we just launch the Premium UI directly if not JSON
324
+ const GoUISession = require('../lib/goUiSession');
325
+ const session = new GoUISession();
326
+ let mermaidCode = "";
327
+ let explanation = "";
328
+ try {
329
+ const parsed = JSON.parse(resultJson);
330
+ mermaidCode = parsed.mermaid_code || resultJson;
331
+ explanation = parsed.explanation || "";
332
+ } catch (e) {
333
+ mermaidCode = resultJson;
334
+ }
335
+
336
+ // Copy to clipboard
337
+ copyToClipboard(mermaidCode);
338
+
339
+ await session.showXrayResults(options.method, '', mermaidCode, explanation);
340
+ } catch (e) {
341
+ console.log(chalk.red(`X-Ray failed: ${e.message}`));
342
+ process.exit(1);
343
+ }
344
+ return;
345
+ }
346
+
261
347
  if (!options.type && !options.audit) {
262
348
  console.log(chalk.red('Error: --type <type> is required.'));
263
349
  process.exit(1);
@@ -558,6 +644,11 @@ program.on('--help', () => {
558
644
  console.log(' 3: Fuzzy (Fuzzy structural, catches patterns with small variations)');
559
645
  console.log(' all: Runs all detection levels (default)');
560
646
  console.log('');
647
+ console.log('X-Ray Visualization:');
648
+ console.log(' tng src/components/MyComponent.js render --xray');
649
+ console.log(' tng --file=api/handler.js --method=post --xray --json');
650
+ console.log(' tng xray -f src/utils.js -m processData');
651
+ console.log('');
561
652
  });
562
653
 
563
654
  program.parse(process.argv);
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -461,17 +461,19 @@ class GenerateTestsUI {
461
461
  // For 'visualize' type, existing backend generates a file or JSON.
462
462
  // We should parse it.
463
463
  let mermaidCode = "";
464
+ let explanation = "";
464
465
  try {
465
466
  const parsed = JSON.parse(resultJson);
466
- if (parsed.mermaid_code) mermaidCode = parsed.mermaid_code;
467
- else mermaidCode = resultJson; // Fallback
467
+ mermaidCode = parsed.mermaid_code || resultJson;
468
+ explanation = parsed.explanation || "";
468
469
  } catch (e) {
469
470
  mermaidCode = resultJson;
470
471
  }
471
472
 
472
473
  return {
473
474
  success: true,
474
- mermaidCode: mermaidCode
475
+ mermaidCode: mermaidCode,
476
+ explanation: explanation
475
477
  };
476
478
  } catch (e) {
477
479
  progress.error(`Failed to generate X-Ray: ${e.message}`);
@@ -482,21 +484,16 @@ class GenerateTestsUI {
482
484
  const result = await this.goUiSession.showProgress(`${actionName} ${displayName}`, progressHandler);
483
485
 
484
486
  if (result && result.mermaidCode) {
485
- console.log(chalk.bold('\n--- X-Ray Result (Mermaid.js) ---\n'));
486
- // Simple highlighting for terminal
487
- console.log(chalk.blue(result.mermaidCode));
488
- console.log(chalk.bold('\n---------------------------------\n'));
489
-
490
- // Prompt user action
491
- this._copyToClipboard(result.mermaidCode);
492
- console.log(chalk.green('✓ Copied to clipboard! Paste into https://mermaid.live'));
493
-
494
- // Wait for user confirmation to return
495
- const { execSync } = require('child_process');
496
- try {
497
- // Just a pause hack if we want, but showListView might be better.
498
- // For now, let's just return.
499
- } catch (e) { }
487
+ // Copy to clipboard first so it's ready for the user
488
+ this._copyToClipboard(result.mermaidCode, true);
489
+
490
+ // Show Premium X-Ray UI
491
+ await this.goUiSession.showXrayResults(
492
+ method.name,
493
+ method.class_name || '',
494
+ result.mermaidCode,
495
+ result.explanation || 'Logic flow visualization generated by TNG.'
496
+ );
500
497
  }
501
498
 
502
499
  return result;
@@ -614,12 +611,12 @@ class GenerateTestsUI {
614
611
  return { passed, failed, errors, total };
615
612
  }
616
613
 
617
- _copyToClipboard(text) {
614
+ _copyToClipboard(text, silent = false) {
618
615
  const { execSync } = require('child_process');
619
616
  try {
620
617
  if (process.platform === 'darwin') {
621
618
  execSync('pbcopy', { input: text });
622
- this.goUiSession.showClipboardSuccess(text);
619
+ if (!silent) this.goUiSession.showClipboardSuccess(text);
623
620
  } else if (process.platform === 'linux') {
624
621
  // Try xclip then xsel
625
622
  try {
@@ -627,12 +624,12 @@ class GenerateTestsUI {
627
624
  } catch (e) {
628
625
  execSync('xsel --clipboard --input', { input: text });
629
626
  }
630
- this.goUiSession.showClipboardSuccess(text);
627
+ if (!silent) this.goUiSession.showClipboardSuccess(text);
631
628
  } else {
632
- console.log(chalk.cyan(`\n📋 Please copy this command: ${text}\n`));
629
+ if (!silent) console.log(chalk.cyan(`\n📋 Please copy this command: ${text}\n`));
633
630
  }
634
631
  } catch (e) {
635
- console.error(chalk.yellow(`\n⚠️ Failed to copy to clipboard. Command: ${text}\n`));
632
+ if (!silent) console.error(chalk.yellow(`\n⚠️ Failed to copy to clipboard. Command: ${text}\n`));
636
633
  }
637
634
  }
638
635
 
@@ -369,6 +369,29 @@ class GoUISession {
369
369
  }
370
370
  }
371
371
 
372
+ async showXrayResults(methodName, className, mermaidCode, explanation) {
373
+ const data = {
374
+ method_name: methodName,
375
+ class_name: className,
376
+ mermaid_code: mermaidCode,
377
+ explanation: explanation
378
+ };
379
+ const inputFile = this._trackTempFile(this._createTempFile('xray-data', '.json'));
380
+
381
+ try {
382
+ fs.writeFileSync(inputFile, JSON.stringify(data));
383
+
384
+ spawnSync(this._binaryPath, ['xray-results', '--file', inputFile], {
385
+ stdio: 'inherit',
386
+ env: process.env
387
+ });
388
+ } catch (error) {
389
+ console.error('X-Ray results display error:', error.message);
390
+ } finally {
391
+ this._cleanupTempFile(inputFile);
392
+ }
393
+ }
394
+
372
395
  async showDeadCodeResults(filePath, resultsJson) {
373
396
  const issues = JSON.parse(resultsJson);
374
397
  const data = {
@@ -66,6 +66,10 @@ class JsonSession {
66
66
  this.emitEvent('result', auditResult || {});
67
67
  }
68
68
 
69
+ showXrayResults(xrayResult) {
70
+ this.emitEvent('result', xrayResult || {});
71
+ }
72
+
69
73
  showClones(filePath, results) {
70
74
  this.emitEvent('clones', { file_path: filePath, matches: results });
71
75
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tng-sh/js",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "TNG JavaScript CLI",
5
5
  "repository": {
6
6
  "type": "git",