hermex 1.1.1 → 1.1.2

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/cli.js CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
3
  import ora from 'ora';
4
- import chalk6 from 'chalk';
4
+ import chalk5 from 'chalk';
5
+ import { minimatch } from 'minimatch';
5
6
  import { parseSync } from '@swc/core';
6
7
  import fs3 from 'fs';
7
8
  import Table from 'cli-table3';
@@ -45,7 +46,6 @@ function createState() {
45
46
  // src/swc-parser/patterns/imports.ts
46
47
  function analyzeImportDeclaration(node, state) {
47
48
  const source = node.source.value;
48
- console.log(`\u{1F4E6} Found import: ${source}`);
49
49
  for (const spec of node.specifiers) {
50
50
  switch (spec.type) {
51
51
  case "ImportDefaultSpecifier":
@@ -297,7 +297,6 @@ function analyzeJSXOpeningElement(node, state, parent) {
297
297
  if (!state.usagePatterns.jsxUsage.has(elementName)) {
298
298
  state.usagePatterns.jsxUsage.set(elementName, usage);
299
299
  }
300
- console.log(`\u{1F3A8} JSX Usage: <${elementName}>`);
301
300
  }
302
301
 
303
302
  // src/swc-parser/utils/matchers.ts
@@ -319,7 +318,6 @@ function analyzeVariableDeclaration(node, state) {
319
318
  line: node.span?.start || 0
320
319
  });
321
320
  state.componentNames.add(varName);
322
- console.log(`\u{1F4DD} Variable assignment: ${varName} = ${assignment}`);
323
321
  }
324
322
  }
325
323
  }
@@ -340,7 +338,6 @@ function analyzeDestructuringPattern(pattern, init, state) {
340
338
  line: pattern.span?.start || 0
341
339
  });
342
340
  state.componentNames.add(propName);
343
- console.log(`\u{1F527} Destructuring: ${propName} from ${init.value}`);
344
341
  }
345
342
  }
346
343
  }
@@ -368,7 +365,6 @@ function analyzeConditionalExpression(node, state) {
368
365
  alternate: alternate || "",
369
366
  line: node.span?.start || 0
370
367
  });
371
- console.log("\u{1F500} Conditional component usage found");
372
368
  }
373
369
  }
374
370
 
@@ -385,7 +381,6 @@ function analyzeArrayExpression(node, state) {
385
381
  components: node.elements?.map((elem) => elem?.value).filter(Boolean),
386
382
  line: node.span?.start || 0
387
383
  });
388
- console.log("\u{1F4CB} Array with components found");
389
384
  }
390
385
  }
391
386
  function analyzeObjectExpression(node, state) {
@@ -403,7 +398,6 @@ function analyzeObjectExpression(node, state) {
403
398
  })),
404
399
  line: node.span?.start || 0
405
400
  });
406
- console.log("\u{1F5FA}\uFE0F Object mapping with components found");
407
401
  }
408
402
  }
409
403
 
@@ -419,7 +413,6 @@ function analyzeLazyImport(node, state) {
419
413
  source,
420
414
  line: node.span?.start || 0
421
415
  });
422
- console.log(`\u{1F504} Found lazy import: ${source}`);
423
416
  }
424
417
  }
425
418
  }
@@ -431,7 +424,6 @@ function analyzeDynamicImport(node, state) {
431
424
  source,
432
425
  line: node.span?.start || 0
433
426
  });
434
- console.log(`\u26A1 Found dynamic import: ${source}`);
435
427
  }
436
428
  }
437
429
 
@@ -442,7 +434,6 @@ function analyzeHOCUsage(node, state) {
442
434
  component: node.arguments?.[0]?.value || "[unknown]",
443
435
  line: node.span?.start || 0
444
436
  });
445
- console.log(`\u{1F381} HOC usage found`);
446
437
  }
447
438
  function analyzeMemoUsage(node, state) {
448
439
  const component = node.arguments?.[0];
@@ -451,28 +442,23 @@ function analyzeMemoUsage(node, state) {
451
442
  component: component.value,
452
443
  line: node.span?.start || 0
453
444
  });
454
- console.log(`\u{1F9E0} Memoized component: ${component.value}`);
455
445
  }
456
446
  }
457
447
  function analyzeForwardRefUsage(node, state) {
458
448
  state.usagePatterns.forwardedRefs.add({
459
449
  line: node.span?.start || 0
460
450
  });
461
- console.log("\u2197\uFE0F ForwardRef usage found");
462
451
  }
463
452
  function analyzePortalUsage(node, state) {
464
453
  state.usagePatterns.portalUsage.add({
465
454
  line: node.span?.start || 0
466
455
  });
467
- console.log("\u{1F300} Portal usage found");
468
456
  }
469
457
  function analyzeMemberExpression(node, state) {
470
458
  if (node.object?.type === "Identifier" && state.allIdentifiers.has(node.object.value)) {
471
- const namespaceName = node.object.value;
472
459
  const propertyName = node.property?.value;
473
460
  if (propertyName) {
474
461
  state.componentNames.add(propertyName);
475
- console.log(`\u{1F517} Namespace access: ${namespaceName}.${propertyName}`);
476
462
  }
477
463
  }
478
464
  }
@@ -664,15 +650,8 @@ function parseCode(code, options = {}) {
664
650
  return report;
665
651
  }
666
652
  function parseFile(filePath, options = {}) {
667
- console.log(`
668
- \u{1F4C1} Analyzing: ${filePath}`);
669
- try {
670
- const code = fs3.readFileSync(filePath, "utf8");
671
- return parseCode(code, options);
672
- } catch (error) {
673
- console.error(`\u274C Error parsing ${filePath}:`, error.message);
674
- return null;
675
- }
653
+ const code = fs3.readFileSync(filePath, "utf8");
654
+ return parseCode(code, options);
676
655
  }
677
656
  function filterReportByLibrary(report, libraryName) {
678
657
  const isFromLibrary = (source) => source.startsWith(libraryName) || source.includes(libraryName);
@@ -945,14 +924,14 @@ function formatCount(num) {
945
924
  return num.toLocaleString();
946
925
  }
947
926
  function formatDuration(seconds) {
948
- return `${seconds.toFixed(1)}s`;
927
+ return `${seconds.toFixed(2)}s`;
949
928
  }
950
929
 
951
930
  // src/utils/print-summary.ts
952
931
  function printHeader() {
953
- console.log(chalk6.green.bold("\n\u{1F4CA} Summary\n"));
932
+ console.log(chalk5.green.bold("\n\u{1F4CA} Summary\n"));
954
933
  }
955
- function printSummary(aggregated, elapsedTimeSeconds) {
934
+ function printSummary(aggregated) {
956
935
  printHeader();
957
936
  const table = new Table({
958
937
  head: ["Metric", "Count"],
@@ -975,30 +954,6 @@ function printSummary(aggregated, elapsedTimeSeconds) {
975
954
  ["Total Usages", formatCount(totalExternalUsage)]
976
955
  );
977
956
  console.log(table.toString());
978
- console.log(
979
- chalk6.green(
980
- `Analysis completed successfully in ${formatDuration(elapsedTimeSeconds)}
981
- `
982
- )
983
- );
984
- }
985
- function printHeader2() {
986
- console.log(chalk6.cyan.bold("\n\u{1F4CB} Details\n"));
987
- }
988
- function printDetails(aggregated) {
989
- printHeader2();
990
- console.log(
991
- chalk6.cyan(
992
- ` Total usage patterns: ${formatCount(aggregated.totalUsagePatterns)}`
993
- )
994
- );
995
- for (const pattern of aggregated.patternCounts) {
996
- if (pattern.count > 0) {
997
- console.log(
998
- chalk6.cyan(` ${pattern.displayName}: ${formatCount(pattern.count)}`)
999
- );
1000
- }
1001
- }
1002
957
  }
1003
958
  function renderBarChart(data, options = {}) {
1004
959
  const {
@@ -1008,12 +963,12 @@ function renderBarChart(data, options = {}) {
1008
963
  emptyChar = "\u2591"
1009
964
  } = options;
1010
965
  if (data.length === 0) {
1011
- console.log(chalk6.gray(" No data to display"));
966
+ console.log(chalk5.gray(" No data to display"));
1012
967
  return;
1013
968
  }
1014
969
  const maxValue = Math.max(...data.map((d) => d.value));
1015
970
  if (maxValue === 0) {
1016
- console.log(chalk6.gray(" All values are zero"));
971
+ console.log(chalk5.gray(" All values are zero"));
1017
972
  return;
1018
973
  }
1019
974
  const maxLabelLength = Math.max(...data.map((d) => d.label.length));
@@ -1022,7 +977,7 @@ function renderBarChart(data, options = {}) {
1022
977
  const barLength = Math.round(percentage * maxWidth);
1023
978
  const emptyLength = maxWidth - barLength;
1024
979
  const paddedLabel = item.label.padEnd(maxLabelLength, " ");
1025
- const bar = chalk6.green(barChar.repeat(barLength)) + chalk6.gray(emptyChar.repeat(emptyLength));
980
+ const bar = chalk5.green(barChar.repeat(barLength)) + chalk5.gray(emptyChar.repeat(emptyLength));
1026
981
  const valueStr = showValues ? ` ${formatCount(item.value)}` : "";
1027
982
  console.log(`${paddedLabel} ${bar}${valueStr}
1028
983
  `);
@@ -1030,8 +985,8 @@ function renderBarChart(data, options = {}) {
1030
985
  }
1031
986
 
1032
987
  // src/utils/print-components.ts
1033
- function printHeader3() {
1034
- console.log(chalk6.magenta.bold("\n\u269B\uFE0F Components\n"));
988
+ function printHeader2() {
989
+ console.log(chalk5.magenta.bold("\n\u269B\uFE0F Components\n"));
1035
990
  }
1036
991
  function printComponents(aggregated, mode) {
1037
992
  const components = aggregated.topComponents;
@@ -1042,12 +997,12 @@ function printComponents(aggregated, mode) {
1042
997
  }
1043
998
  }
1044
999
  function printComponentsTable(components) {
1045
- printHeader3();
1000
+ printHeader2();
1046
1001
  const externalComponents = components.filter(
1047
1002
  (comp) => comp.source !== "unknown" && comp.source !== "local"
1048
1003
  );
1049
1004
  if (externalComponents.length === 0) {
1050
- console.log(chalk6.gray(" No external components found"));
1005
+ console.log(chalk5.gray(" No external components found"));
1051
1006
  return;
1052
1007
  }
1053
1008
  const table = new Table({
@@ -1063,12 +1018,12 @@ function printComponentsTable(components) {
1063
1018
  console.log(table.toString());
1064
1019
  }
1065
1020
  function printComponentsChart(components) {
1066
- printHeader3();
1021
+ printHeader2();
1067
1022
  const externalComponents = components.filter(
1068
1023
  (comp) => comp.source !== "unknown" && comp.source !== "local"
1069
1024
  );
1070
1025
  if (externalComponents.length === 0) {
1071
- console.log(chalk6.gray(" No external components found"));
1026
+ console.log(chalk5.gray(" No external components found"));
1072
1027
  return;
1073
1028
  }
1074
1029
  const data = externalComponents.map((comp) => ({
@@ -1077,8 +1032,8 @@ function printComponentsChart(components) {
1077
1032
  }));
1078
1033
  renderBarChart(data, { maxWidth: 50 });
1079
1034
  }
1080
- function printHeader4() {
1081
- console.log(chalk6.blue.bold("\n\u{1F50D} Code Patterns\n"));
1035
+ function printHeader3() {
1036
+ console.log(chalk5.blue.bold("\n\u{1F50D} Code Patterns\n"));
1082
1037
  }
1083
1038
  function printPatterns(aggregated, mode) {
1084
1039
  const patterns = aggregated.patternCounts.filter((p) => p.count > 0);
@@ -1089,9 +1044,9 @@ function printPatterns(aggregated, mode) {
1089
1044
  }
1090
1045
  }
1091
1046
  function printPatternsTable(patterns) {
1092
- printHeader4();
1047
+ printHeader3();
1093
1048
  if (patterns.length === 0) {
1094
- console.log(chalk6.gray(" No patterns found"));
1049
+ console.log(chalk5.gray(" No patterns found"));
1095
1050
  return;
1096
1051
  }
1097
1052
  const table = new Table({
@@ -1106,13 +1061,13 @@ function printPatternsTable(patterns) {
1106
1061
  });
1107
1062
  console.log(table.toString());
1108
1063
  const totalPatterns = patterns.reduce((sum, p) => sum + p.count, 0);
1109
- console.log(chalk6.gray(`
1064
+ console.log(chalk5.gray(`
1110
1065
  Total: ${totalPatterns} patterns detected`));
1111
1066
  }
1112
1067
  function printPatternsChart(patterns) {
1113
- printHeader4();
1068
+ printHeader3();
1114
1069
  if (patterns.length === 0) {
1115
- console.log(chalk6.gray(" No patterns found"));
1070
+ console.log(chalk5.gray(" No patterns found"));
1116
1071
  return;
1117
1072
  }
1118
1073
  const data = patterns.map((pattern) => ({
@@ -1121,8 +1076,8 @@ function printPatternsChart(patterns) {
1121
1076
  }));
1122
1077
  renderBarChart(data, { maxWidth: 50 });
1123
1078
  }
1124
- function printHeader5() {
1125
- console.log(chalk6.blueBright.bold("\n\u{1F4E6} Packages\n"));
1079
+ function printHeader4() {
1080
+ console.log(chalk5.blueBright.bold("\n\u{1F4E6} Packages\n"));
1126
1081
  }
1127
1082
  function printPackages(aggregated, mode) {
1128
1083
  const packages = aggregated.packageDistribution;
@@ -1133,9 +1088,9 @@ function printPackages(aggregated, mode) {
1133
1088
  }
1134
1089
  }
1135
1090
  function printPackagesTable(packages) {
1136
- printHeader5();
1091
+ printHeader4();
1137
1092
  if (packages.length === 0) {
1138
- console.log(chalk6.gray(" No packages found"));
1093
+ console.log(chalk5.gray(" No packages found"));
1139
1094
  return;
1140
1095
  }
1141
1096
  const table = new Table({
@@ -1161,16 +1116,16 @@ function printPackagesTable(packages) {
1161
1116
  );
1162
1117
  const totalExternalUsage = packages.reduce((sum, p) => sum + p.usageCount, 0);
1163
1118
  console.log(
1164
- chalk6.gray(
1119
+ chalk5.gray(
1165
1120
  `
1166
1121
  Total: ${formatCount(packages.length)} packages | ${formatCount(totalComponents)} unique components | ${formatCount(totalExternalUsage)} total usages`
1167
1122
  )
1168
1123
  );
1169
1124
  }
1170
1125
  function printPackagesChart(packages) {
1171
- printHeader5();
1126
+ printHeader4();
1172
1127
  if (packages.length === 0) {
1173
- console.log(chalk6.gray(" No packages found"));
1128
+ console.log(chalk5.gray(" No packages found"));
1174
1129
  return;
1175
1130
  }
1176
1131
  const maxBarWidth = 40;
@@ -1182,9 +1137,9 @@ function printPackagesChart(packages) {
1182
1137
  );
1183
1138
  const emptyLength = maxBarWidth - barLength;
1184
1139
  const paddedLabel = pkg.packageName.padEnd(maxLabelLength, " ");
1185
- const bar = chalk6.green("\u2588".repeat(barLength)) + chalk6.gray("\u2591".repeat(emptyLength));
1140
+ const bar = chalk5.green("\u2588".repeat(barLength)) + chalk5.gray("\u2591".repeat(emptyLength));
1186
1141
  console.log(
1187
- `${paddedLabel} ${bar} ${chalk6.bold(pkg.percentage.toFixed(1) + "%")} (${pkg.usageCount})`
1142
+ `${paddedLabel} ${bar} ${chalk5.bold(pkg.percentage.toFixed(1) + "%")} (${pkg.usageCount})`
1188
1143
  );
1189
1144
  });
1190
1145
  }
@@ -1385,16 +1340,13 @@ function registerScanCommand(program2) {
1385
1340
  "**/node_modules/**",
1386
1341
  "**/dist/**",
1387
1342
  "**/build/**"
1343
+ ]).option("--allow-packages <pattern>", "Pattern for what packages to scan", [
1344
+ "**"
1388
1345
  ]).option(
1389
- "--allow-packages <pattern>",
1390
- "Glob pattern for what packages to scan",
1391
- "ALL"
1392
- // TO FIX
1393
- ).option(
1394
1346
  "--ignore-packages <pattern>",
1395
- "Glob pattern for what packages to ignore",
1347
+ "Pattern for what packages to ignore",
1396
1348
  []
1397
- ).option("--summary [mode]", "Show summary stats (log, false)", "log").option("--no-summary", "Do not show summary stats").option("--details", "Show detailed pattern counts").option(
1349
+ ).option("--no-summary", "Hide summary", "table").option(
1398
1350
  "--components [mode]",
1399
1351
  "Show components table/chart (table, chart)",
1400
1352
  "table"
@@ -1411,21 +1363,23 @@ function registerScanCommand(program2) {
1411
1363
  await executeScan(pattern, normalizedOptions);
1412
1364
  });
1413
1365
  }
1414
- function normalizeIgnorePatterns(ignore) {
1415
- if (!ignore) {
1366
+ function normalizeArray(value) {
1367
+ if (!value) {
1416
1368
  return [];
1417
1369
  }
1418
- return Array.isArray(ignore) ? ignore : [ignore];
1370
+ return Array.isArray(value) ? value : [value];
1419
1371
  }
1420
1372
  function normalizeOptions(options) {
1421
1373
  return {
1422
1374
  verbose: options.verbose || false,
1423
1375
  summary: options.summary === false || options.summary === "false" ? false : "log",
1424
- details: options.details || false,
1376
+ noSummary: options.noSummary || false,
1425
1377
  components: options.components || "table",
1426
1378
  packages: options.packages || "table",
1427
1379
  patterns: options.patterns || "table",
1428
- ignore: normalizeIgnorePatterns(options.ignore)
1380
+ ignore: normalizeArray(options.ignore),
1381
+ allowPackages: normalizeArray(options.allowPackages),
1382
+ ignorePackages: normalizeArray(options.ignorePackages)
1429
1383
  };
1430
1384
  }
1431
1385
  async function executeScan(pattern, options) {
@@ -1433,19 +1387,26 @@ async function executeScan(pattern, options) {
1433
1387
  const spinner = ora("Parsing lockfile...").start();
1434
1388
  try {
1435
1389
  const lockfileResult = findAndParseLockfile(process.cwd());
1390
+ const allPackages = Object.keys(lockfileResult.versions);
1391
+ const filteredPackages = allPackages.filter((pkg) => {
1392
+ const allowed = options.allowPackages.some((p) => minimatch(pkg, p));
1393
+ const ignored = options.ignorePackages.some((p) => minimatch(pkg, p));
1394
+ return allowed && !ignored;
1395
+ });
1396
+ const filteredVersions = {};
1397
+ for (const pkg of filteredPackages) {
1398
+ filteredVersions[pkg] = lockfileResult.versions[pkg];
1399
+ }
1436
1400
  spinner.succeed(
1437
- chalk6.blue(
1438
- `\u{1F4E6} Found ${lockfileResult.lockfileType} lockfile (supports: ${lockfileResult.supportedVersions.join(", ")}) - ${Object.keys(lockfileResult.versions).length} packages`
1439
- )
1401
+ `Found ${lockfileResult.lockfileType} lockfile (supports: ${lockfileResult.supportedVersions.join(", ")}) - ${filteredPackages.length}/${allPackages.length} packages`
1440
1402
  );
1441
- console.log("availablePackages", lockfileResult);
1442
1403
  spinner.start("Finding files...");
1443
1404
  const files = await findFiles(pattern, options.ignore);
1444
1405
  if (files.length === 0) {
1445
- spinner.fail("TEST");
1406
+ spinner.fail(`No files found matching pattern: ${pattern}`);
1446
1407
  return;
1447
1408
  }
1448
- spinner.succeed(chalk6.green(` Found ${files.length} files`));
1409
+ spinner.succeed(chalk5.green(` Found ${files.length} files`));
1449
1410
  spinner.start("Analyzing files...");
1450
1411
  const reports = [];
1451
1412
  for (let i = 0; i < files.length; i++) {
@@ -1453,39 +1414,34 @@ async function executeScan(pattern, options) {
1453
1414
  if (!options.verbose) {
1454
1415
  spinner.text = `Analyzing files... (${i + 1}/${files.length})`;
1455
1416
  }
1456
- try {
1457
- const report = parseFile(file);
1458
- if (report) {
1459
- reports.push(report);
1460
- }
1461
- } catch (error) {
1462
- spinner.stop();
1463
- console.error(chalk6.red(`Error analyzing ${file}: ${error.message}`));
1464
- spinner.start();
1417
+ const report = parseFile(file);
1418
+ if (report) {
1419
+ reports.push(report);
1465
1420
  }
1466
1421
  }
1467
- spinner.succeed(
1468
- chalk6.green(`Analysis complete! Analyzed ${reports.length} files`)
1469
- );
1470
1422
  const elapsedTime = (Date.now() - startTime) / 1e3;
1471
- const aggregated = aggregateReports(reports, lockfileResult.versions);
1472
- if (options.packages) {
1423
+ const aggregated = aggregateReports(reports, filteredVersions);
1424
+ if (options.packages && !options.noPackages) {
1473
1425
  printPackages(aggregated, options.packages);
1474
1426
  }
1475
- if (options.details) {
1476
- printDetails(aggregated);
1477
- }
1478
- if (options.components) {
1427
+ if (options.components && !options.noComponents) {
1479
1428
  printComponents(aggregated, options.components);
1480
1429
  }
1481
- if (options.patterns) {
1430
+ if (options.patterns && !options.noPatterns) {
1482
1431
  printPatterns(aggregated, options.patterns);
1483
1432
  }
1484
- if (options.summary) {
1485
- printSummary(aggregated, elapsedTime);
1433
+ if (options.summary && !options.noSummary) {
1434
+ printSummary(aggregated);
1486
1435
  }
1436
+ console.log("");
1437
+ spinner.succeed(
1438
+ chalk5.green.bold(
1439
+ ` Analysis complete! Analyzed ${reports.length} files in ${formatDuration(elapsedTime)}
1440
+ `
1441
+ )
1442
+ );
1487
1443
  } catch (error) {
1488
- spinner.fail(chalk6.red("Analysis failed: " + error.message));
1444
+ spinner.fail(chalk5.red("Analysis failed: " + error.message));
1489
1445
  console.error(error);
1490
1446
  process.exit(1);
1491
1447
  }
@@ -1493,7 +1449,7 @@ async function executeScan(pattern, options) {
1493
1449
 
1494
1450
  // package.json
1495
1451
  var package_default = {
1496
- version: "1.1.1-beta.1"};
1452
+ version: "1.1.1"};
1497
1453
 
1498
1454
  // src/cli.ts
1499
1455
  var program = new Command();