uilint 0.2.23 → 0.2.27

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.
@@ -1,11 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  confirm,
4
+ detectCoverageSetup,
4
5
  detectNextAppRouter,
5
6
  findEslintConfigFile,
6
7
  findNextAppRouterProjects,
7
8
  getEslintConfigFilename,
8
9
  getUilintEslintConfigInfoFromSource,
10
+ injectCoverageConfig,
9
11
  installEslintPlugin,
10
12
  log,
11
13
  multiselect,
@@ -13,13 +15,17 @@ import {
13
15
  pc,
14
16
  select,
15
17
  uninstallEslintPlugin
16
- } from "./chunk-PB5DLLVC.js";
18
+ } from "./chunk-VNANPKR2.js";
17
19
  import {
18
20
  GENSTYLEGUIDE_COMMAND_MD,
21
+ loadSkill,
22
+ toInstallSpecifier
23
+ } from "./chunk-TWUDB36F.js";
24
+ import {
19
25
  detectPackageManager,
20
26
  installDependencies,
21
- loadSkill
22
- } from "./chunk-PBEKMDUH.js";
27
+ runTestsWithCoverage
28
+ } from "./chunk-P4I4RKBY.js";
23
29
 
24
30
  // src/commands/install-ui.tsx
25
31
  import { render } from "ink";
@@ -870,7 +876,19 @@ var nextOverlayInstaller = {
870
876
  dependencies.push({
871
877
  packagePath: projectPath,
872
878
  packageManager: project.packageManager,
873
- packages: ["uilint-react", "uilint-core", "jsx-loc-plugin"]
879
+ packages: [
880
+ toInstallSpecifier("uilint-react", {
881
+ preferWorkspaceProtocol: project.packageManager === "pnpm",
882
+ workspaceRoot: project.workspaceRoot,
883
+ targetProjectPath: projectPath
884
+ }),
885
+ toInstallSpecifier("uilint-core", {
886
+ preferWorkspaceProtocol: project.packageManager === "pnpm",
887
+ workspaceRoot: project.workspaceRoot,
888
+ targetProjectPath: projectPath
889
+ }),
890
+ "jsx-loc-plugin"
891
+ ]
874
892
  });
875
893
  actions.push({
876
894
  type: "inject_react",
@@ -1674,7 +1692,7 @@ import {
1674
1692
  chmodSync,
1675
1693
  rmSync
1676
1694
  } from "fs";
1677
- import { dirname as dirname4 } from "path";
1695
+ import { dirname as dirname4, join as join10 } from "path";
1678
1696
 
1679
1697
  // src/utils/react-inject.ts
1680
1698
  import { existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync } from "fs";
@@ -3240,6 +3258,7 @@ function touchFiles(filePaths) {
3240
3258
  }
3241
3259
 
3242
3260
  // src/commands/install/execute.ts
3261
+ import { findWorkspaceRoot as findWorkspaceRoot2 } from "uilint-core/node";
3243
3262
  async function executeAction(action, options) {
3244
3263
  const { dryRun = false } = options;
3245
3264
  try {
@@ -3340,6 +3359,9 @@ async function executeAction(action, options) {
3340
3359
  case "inject_vite_config": {
3341
3360
  return await executeInjectViteConfig(action, options);
3342
3361
  }
3362
+ case "inject_vitest_coverage": {
3363
+ return await executeInjectVitestCoverage(action, options);
3364
+ }
3343
3365
  case "install_next_routes": {
3344
3366
  return await executeInstallNextRoutes(action, options);
3345
3367
  }
@@ -3451,6 +3473,31 @@ async function executeInjectViteConfig(action, options) {
3451
3473
  modifiedFiles: result.modifiedFiles
3452
3474
  };
3453
3475
  }
3476
+ async function executeInjectVitestCoverage(action, options) {
3477
+ const { dryRun = false } = options;
3478
+ const setup = detectCoverageSetup(action.projectPath);
3479
+ const vitestConfigPath = action.vitestConfigPath || setup.vitestConfigPath;
3480
+ if (!vitestConfigPath) {
3481
+ return {
3482
+ action,
3483
+ success: true
3484
+ // Don't fail the install, coverage config is optional
3485
+ };
3486
+ }
3487
+ if (dryRun) {
3488
+ return {
3489
+ action,
3490
+ success: true,
3491
+ wouldDo: `Inject coverage config into vitest.config: ${vitestConfigPath}`
3492
+ };
3493
+ }
3494
+ const modified = injectCoverageConfig(vitestConfigPath);
3495
+ return {
3496
+ action,
3497
+ success: true,
3498
+ modifiedFiles: modified ? [vitestConfigPath] : void 0
3499
+ };
3500
+ }
3454
3501
  async function executeInjectNextConfig(action, options) {
3455
3502
  const { dryRun = false } = options;
3456
3503
  if (dryRun) {
@@ -3740,6 +3787,36 @@ function getProjectPathFromActions(actionsPerformed) {
3740
3787
  }
3741
3788
  return void 0;
3742
3789
  }
3790
+ function normalizePnpmWorkspaceUilintSpecs(packagePath, packages) {
3791
+ const workspaceRoot = findWorkspaceRoot2(packagePath);
3792
+ if (!existsSync10(join10(workspaceRoot, "pnpm-workspace.yaml"))) return packages;
3793
+ const touchesUilint = packages.some((p) => p === "uilint-eslint" || p.startsWith("uilint-"));
3794
+ if (!touchesUilint) return packages;
3795
+ const pkgJsonPath = join10(packagePath, "package.json");
3796
+ if (!existsSync10(pkgJsonPath)) return packages;
3797
+ let pkg = null;
3798
+ try {
3799
+ pkg = JSON.parse(readFileSync8(pkgJsonPath, "utf-8"));
3800
+ } catch {
3801
+ return packages;
3802
+ }
3803
+ const wanted = ["uilint-core", "uilint-eslint", "uilint-react"];
3804
+ const present = /* @__PURE__ */ new Set();
3805
+ for (const name of wanted) {
3806
+ const range = pkg?.dependencies?.[name] ?? pkg?.devDependencies?.[name];
3807
+ if (typeof range === "string") {
3808
+ present.add(name);
3809
+ }
3810
+ }
3811
+ if (present.size === 0) return packages;
3812
+ const filtered = packages.filter(
3813
+ (p) => !/^uilint-(core|eslint|react)(@.+)?$/.test(p)
3814
+ );
3815
+ for (const name of present) {
3816
+ filtered.push(`${name}@workspace:*`);
3817
+ }
3818
+ return filtered;
3819
+ }
3743
3820
  async function execute(plan, options = {}) {
3744
3821
  const {
3745
3822
  dryRun = false,
@@ -3763,13 +3840,14 @@ async function execute(plan, options = {}) {
3763
3840
  continue;
3764
3841
  }
3765
3842
  try {
3843
+ const pkgs = dep.packageManager === "pnpm" ? normalizePnpmWorkspaceUilintSpecs(dep.packagePath, dep.packages) : dep.packages;
3766
3844
  await installDependencies2(
3767
3845
  dep.packageManager,
3768
3846
  dep.packagePath,
3769
- dep.packages
3847
+ pkgs
3770
3848
  );
3771
3849
  dependencyResults.push({
3772
- install: dep,
3850
+ install: { ...dep, packages: pkgs },
3773
3851
  success: true
3774
3852
  });
3775
3853
  } catch (error) {
@@ -3830,7 +3908,7 @@ async function execute(plan, options = {}) {
3830
3908
  import { ruleRegistry as ruleRegistry3 } from "uilint-eslint";
3831
3909
 
3832
3910
  // src/commands/install/installers/genstyleguide.ts
3833
- import { join as join10 } from "path";
3911
+ import { join as join11 } from "path";
3834
3912
  var genstyleguideInstaller = {
3835
3913
  id: "genstyleguide",
3836
3914
  name: "/genstyleguide command",
@@ -3840,7 +3918,7 @@ var genstyleguideInstaller = {
3840
3918
  return true;
3841
3919
  },
3842
3920
  getTargets(project) {
3843
- const commandPath = join10(project.cursorDir.path, "commands", "genstyleguide.md");
3921
+ const commandPath = join11(project.cursorDir.path, "commands", "genstyleguide.md");
3844
3922
  const isInstalled = project.commands.genstyleguide;
3845
3923
  return [
3846
3924
  {
@@ -3853,7 +3931,7 @@ var genstyleguideInstaller = {
3853
3931
  },
3854
3932
  plan(targets, config, project) {
3855
3933
  const actions = [];
3856
- const commandsDir = join10(project.cursorDir.path, "commands");
3934
+ const commandsDir = join11(project.cursorDir.path, "commands");
3857
3935
  if (!project.cursorDir.exists) {
3858
3936
  actions.push({
3859
3937
  type: "create_directory",
@@ -3866,7 +3944,7 @@ var genstyleguideInstaller = {
3866
3944
  });
3867
3945
  actions.push({
3868
3946
  type: "create_file",
3869
- path: join10(commandsDir, "genstyleguide.md"),
3947
+ path: join11(commandsDir, "genstyleguide.md"),
3870
3948
  content: GENSTYLEGUIDE_COMMAND_MD
3871
3949
  });
3872
3950
  return {
@@ -3895,7 +3973,7 @@ var genstyleguideInstaller = {
3895
3973
  },
3896
3974
  planUninstall(targets, project) {
3897
3975
  const actions = [];
3898
- const commandPath = join10(project.cursorDir.path, "commands", "genstyleguide.md");
3976
+ const commandPath = join11(project.cursorDir.path, "commands", "genstyleguide.md");
3899
3977
  actions.push({
3900
3978
  type: "delete_file",
3901
3979
  path: commandPath
@@ -3906,7 +3984,7 @@ var genstyleguideInstaller = {
3906
3984
 
3907
3985
  // src/commands/install/installers/skill.ts
3908
3986
  import { existsSync as existsSync11 } from "fs";
3909
- import { join as join11 } from "path";
3987
+ import { join as join12 } from "path";
3910
3988
  var skillInstaller = {
3911
3989
  id: "skill",
3912
3990
  name: "UI Consistency Agent skill",
@@ -3916,8 +3994,8 @@ var skillInstaller = {
3916
3994
  return true;
3917
3995
  },
3918
3996
  getTargets(project) {
3919
- const skillsDir = join11(project.cursorDir.path, "skills", "ui-consistency-enforcer");
3920
- const skillMdPath = join11(skillsDir, "SKILL.md");
3997
+ const skillsDir = join12(project.cursorDir.path, "skills", "ui-consistency-enforcer");
3998
+ const skillMdPath = join12(skillsDir, "SKILL.md");
3921
3999
  const isInstalled = existsSync11(skillMdPath);
3922
4000
  return [
3923
4001
  {
@@ -3937,21 +4015,21 @@ var skillInstaller = {
3937
4015
  path: project.cursorDir.path
3938
4016
  });
3939
4017
  }
3940
- const skillsDir = join11(project.cursorDir.path, "skills");
4018
+ const skillsDir = join12(project.cursorDir.path, "skills");
3941
4019
  actions.push({
3942
4020
  type: "create_directory",
3943
4021
  path: skillsDir
3944
4022
  });
3945
4023
  try {
3946
4024
  const skill = loadSkill("ui-consistency-enforcer");
3947
- const skillDir = join11(skillsDir, skill.name);
4025
+ const skillDir = join12(skillsDir, skill.name);
3948
4026
  actions.push({
3949
4027
  type: "create_directory",
3950
4028
  path: skillDir
3951
4029
  });
3952
4030
  for (const file of skill.files) {
3953
- const filePath = join11(skillDir, file.relativePath);
3954
- const fileDir = join11(
4031
+ const filePath = join12(skillDir, file.relativePath);
4032
+ const fileDir = join12(
3955
4033
  skillDir,
3956
4034
  file.relativePath.split("/").slice(0, -1).join("/")
3957
4035
  );
@@ -4007,7 +4085,7 @@ var skillInstaller = {
4007
4085
  },
4008
4086
  planUninstall(targets, project) {
4009
4087
  const actions = [];
4010
- const skillDir = join11(project.cursorDir.path, "skills", "ui-consistency-enforcer");
4088
+ const skillDir = join12(project.cursorDir.path, "skills", "ui-consistency-enforcer");
4011
4089
  actions.push({
4012
4090
  type: "remove_directory",
4013
4091
  path: skillDir
@@ -4017,7 +4095,7 @@ var skillInstaller = {
4017
4095
  };
4018
4096
 
4019
4097
  // src/commands/install/installers/eslint.ts
4020
- import { join as join12 } from "path";
4098
+ import { join as join13 } from "path";
4021
4099
  import { ruleRegistry as ruleRegistry2, getRulesByCategory as getRulesByCategory2 } from "uilint-eslint";
4022
4100
  function getUpgradeInfo(configuredRuleIds) {
4023
4101
  const configuredSet = new Set(configuredRuleIds);
@@ -4032,9 +4110,6 @@ function getUpgradeInfo(configuredRuleIds) {
4032
4110
  summary
4033
4111
  };
4034
4112
  }
4035
- function toInstallSpecifier(pkgName) {
4036
- return pkgName;
4037
- }
4038
4113
  function formatRuleOption(rule) {
4039
4114
  const severityBadge = rule.defaultSeverity === "error" ? pc.red("error") : pc.yellow("warn");
4040
4115
  return {
@@ -4171,6 +4246,9 @@ var eslintInstaller = {
4171
4246
  const warnCount = configuredRules.filter(
4172
4247
  (r) => r.severity === "warn"
4173
4248
  ).length;
4249
+ const hasSemanticDuplicates = configuredRules.some(
4250
+ (cr) => cr.rule.id === "no-semantic-duplicates"
4251
+ );
4174
4252
  log("");
4175
4253
  note(
4176
4254
  configuredRules.map(
@@ -4178,6 +4256,19 @@ var eslintInstaller = {
4178
4256
  ).join("\n"),
4179
4257
  `Selected ${configuredRules.length} rules (${errorCount} errors, ${warnCount} warnings)`
4180
4258
  );
4259
+ if (hasSemanticDuplicates) {
4260
+ log("");
4261
+ log(
4262
+ pc.yellow(
4263
+ "\u26A0\uFE0F The no-semantic-duplicates rule requires a semantic index."
4264
+ )
4265
+ );
4266
+ log(
4267
+ pc.dim(
4268
+ " Run 'uilint duplicates index' in each target app to build it."
4269
+ )
4270
+ );
4271
+ }
4181
4272
  return { configuredRules };
4182
4273
  },
4183
4274
  plan(targets, config, project) {
@@ -4193,7 +4284,7 @@ var eslintInstaller = {
4193
4284
  for (const target of targets) {
4194
4285
  const pkgInfo = project.packages.find((p) => p.path === target.path);
4195
4286
  if (!pkgInfo || !pkgInfo.eslintConfigPath) continue;
4196
- const rulesDir = join12(target.path, ".uilint", "rules");
4287
+ const rulesDir = join13(target.path, ".uilint", "rules");
4197
4288
  actions.push({
4198
4289
  type: "create_directory",
4199
4290
  path: rulesDir
@@ -4201,7 +4292,14 @@ var eslintInstaller = {
4201
4292
  dependencies.push({
4202
4293
  packagePath: target.path,
4203
4294
  packageManager: detectPackageManager(target.path),
4204
- packages: [toInstallSpecifier("uilint-eslint"), "typescript-eslint"]
4295
+ packages: [
4296
+ toInstallSpecifier("uilint-eslint", {
4297
+ preferWorkspaceProtocol: project.packageManager === "pnpm",
4298
+ workspaceRoot: project.workspaceRoot,
4299
+ targetProjectPath: target.path
4300
+ }),
4301
+ "typescript-eslint"
4302
+ ]
4205
4303
  });
4206
4304
  actions.push({
4207
4305
  type: "inject_eslint",
@@ -4211,7 +4309,7 @@ var eslintInstaller = {
4211
4309
  hasExistingRules: pkgInfo.hasUilintRules
4212
4310
  });
4213
4311
  }
4214
- const gitignorePath = join12(project.workspaceRoot, ".gitignore");
4312
+ const gitignorePath = join13(project.workspaceRoot, ".gitignore");
4215
4313
  actions.push({
4216
4314
  type: "append_to_file",
4217
4315
  path: gitignorePath,
@@ -4253,7 +4351,7 @@ var eslintInstaller = {
4253
4351
  packagePath: target.path,
4254
4352
  configPath: pkgInfo.eslintConfigPath
4255
4353
  });
4256
- const rulesDir = join12(target.path, ".uilint", "rules");
4354
+ const rulesDir = join13(target.path, ".uilint", "rules");
4257
4355
  actions.push({
4258
4356
  type: "remove_directory",
4259
4357
  path: rulesDir
@@ -4286,13 +4384,27 @@ var viteOverlayInstaller = {
4286
4384
  const dependencies = [];
4287
4385
  if (targets.length === 0) return { actions, dependencies };
4288
4386
  const target = targets[0];
4289
- const appInfo = project.viteApps.find((app) => app.projectPath === target.path);
4387
+ const appInfo = project.viteApps.find(
4388
+ (app) => app.projectPath === target.path
4389
+ );
4290
4390
  if (!appInfo) return { actions, dependencies };
4291
4391
  const { projectPath, detection } = appInfo;
4292
4392
  dependencies.push({
4293
4393
  packagePath: projectPath,
4294
4394
  packageManager: project.packageManager,
4295
- packages: ["uilint-react", "uilint-core", "jsx-loc-plugin"]
4395
+ packages: [
4396
+ toInstallSpecifier("uilint-react", {
4397
+ preferWorkspaceProtocol: project.packageManager === "pnpm",
4398
+ workspaceRoot: project.workspaceRoot,
4399
+ targetProjectPath: projectPath
4400
+ }),
4401
+ toInstallSpecifier("uilint-core", {
4402
+ preferWorkspaceProtocol: project.packageManager === "pnpm",
4403
+ workspaceRoot: project.workspaceRoot,
4404
+ targetProjectPath: projectPath
4405
+ }),
4406
+ "jsx-loc-plugin"
4407
+ ]
4296
4408
  });
4297
4409
  actions.push({
4298
4410
  type: "inject_react",
@@ -4370,6 +4482,105 @@ registerInstaller(viteOverlayInstaller);
4370
4482
 
4371
4483
  // src/commands/install-ui.tsx
4372
4484
  import { jsx as jsx7 } from "react/jsx-runtime";
4485
+ function limitList(items, max) {
4486
+ if (items.length <= max) return items;
4487
+ return [...items.slice(0, max), pc.dim(`\u2026and ${items.length - max} more`)];
4488
+ }
4489
+ function printInstallReport(result, testCoverageResult) {
4490
+ const failedDeps = result.dependencyResults.filter((r) => !r.success);
4491
+ const okDeps = result.dependencyResults.filter((r) => r.success);
4492
+ const failedActions = result.actionsPerformed.filter((r) => !r.success);
4493
+ const okActions = result.actionsPerformed.filter((r) => r.success);
4494
+ if (result.success) {
4495
+ console.log(`
4496
+ ${pc.green("\u2713")} Operation completed successfully`);
4497
+ } else {
4498
+ console.log(`
4499
+ ${pc.yellow("\u26A0")} Operation completed with errors`);
4500
+ }
4501
+ const { summary } = result;
4502
+ const installed = summary.installedItems.map((x) => String(x));
4503
+ const created = summary.filesCreated;
4504
+ const modified = summary.filesModified;
4505
+ const deleted = summary.filesDeleted;
4506
+ if (installed.length > 0) {
4507
+ console.log(`
4508
+ ${pc.bold("Installed:")}`);
4509
+ for (const item of installed) console.log(`- ${pc.green("\u2713")} ${item}`);
4510
+ }
4511
+ if (summary.eslintTargets.length > 0) {
4512
+ console.log(`
4513
+ ${pc.bold("ESLint configured:")}`);
4514
+ for (const t of summary.eslintTargets) {
4515
+ console.log(
4516
+ `- ${pc.green("\u2713")} ${t.displayName} ${pc.dim(`(${t.configFile})`)}`
4517
+ );
4518
+ }
4519
+ }
4520
+ if (created.length + modified.length + deleted.length > 0) {
4521
+ console.log(`
4522
+ ${pc.bold("Files:")}`);
4523
+ for (const p of limitList(created, 20))
4524
+ console.log(`- ${pc.green("+")} ${p}`);
4525
+ for (const p of limitList(modified, 20))
4526
+ console.log(`- ${pc.yellow("~")} ${p}`);
4527
+ for (const p of limitList(deleted, 20))
4528
+ console.log(`- ${pc.red("-")} ${p}`);
4529
+ }
4530
+ if (summary.dependenciesInstalled.length > 0) {
4531
+ console.log(`
4532
+ ${pc.bold("Dependencies installed:")}`);
4533
+ for (const d of summary.dependenciesInstalled) {
4534
+ console.log(
4535
+ `- ${pc.green("\u2713")} ${d.packagePath} ${pc.dim(`\u2190 ${d.packages.join(", ")}`)}`
4536
+ );
4537
+ }
4538
+ }
4539
+ if (testCoverageResult?.ran) {
4540
+ console.log(`
4541
+ ${pc.bold("Test coverage:")}`);
4542
+ if (testCoverageResult.success) {
4543
+ console.log(`- ${pc.green("\u2713")} Coverage data generated successfully`);
4544
+ } else {
4545
+ console.log(`- ${pc.yellow("\u26A0")} Tests ran with errors`);
4546
+ if (testCoverageResult.error) {
4547
+ console.log(pc.dim(` ${testCoverageResult.error.split("\n")[0]}`));
4548
+ }
4549
+ }
4550
+ }
4551
+ if (failedDeps.length > 0 || failedActions.length > 0) {
4552
+ console.log(`
4553
+ ${pc.bold(pc.red("Failures:"))}`);
4554
+ }
4555
+ if (failedDeps.length > 0) {
4556
+ console.log(`
4557
+ ${pc.bold("Dependency installs failed:")}`);
4558
+ for (const dep of failedDeps) {
4559
+ const pkgs = dep.install.packages.join(", ");
4560
+ console.log(
4561
+ `- ${pc.red("\u2717")} ${dep.install.packageManager} in ${dep.install.packagePath} ${pc.dim(`\u2190 ${pkgs}`)}`
4562
+ );
4563
+ if (dep.error) console.log(pc.dim(dep.error.split("\n").slice(0, 30).join("\n")));
4564
+ }
4565
+ }
4566
+ if (failedActions.length > 0) {
4567
+ console.log(`
4568
+ ${pc.bold("Actions failed:")}`);
4569
+ for (const a of failedActions) {
4570
+ const action = a.action;
4571
+ const type = String(action.type || "unknown");
4572
+ const pathish = typeof action.path === "string" && action.path || typeof action.projectPath === "string" && action.projectPath || typeof action.packagePath === "string" && action.packagePath || "";
4573
+ console.error(`- ${type}${pathish ? ` (${pathish})` : ""}`);
4574
+ if (a.error) console.error(` ${a.error}`);
4575
+ }
4576
+ }
4577
+ console.log(
4578
+ pc.dim(
4579
+ `
4580
+ Summary: ${okActions.length} action(s) ok, ${failedActions.length} failed \xB7 ${okDeps.length} dep install(s) ok, ${failedDeps.length} failed`
4581
+ )
4582
+ );
4583
+ }
4373
4584
  function selectionsToUserChoices(selections, project, eslintRules, injectionPointConfig) {
4374
4585
  const items = [];
4375
4586
  const choices = { items };
@@ -4448,7 +4659,7 @@ async function installUI(options = {}, executeOptions = {}) {
4448
4659
  console.log("\nNo changes selected");
4449
4660
  process.exit(0);
4450
4661
  }
4451
- const { createPlan } = await import("./plan-SIXVCXCK.js");
4662
+ const { createPlan } = await import("./plan-5WHKVACB.js");
4452
4663
  const plan = createPlan(project, choices, { force: options.force });
4453
4664
  if (hasUninstalls && uninstallSelections) {
4454
4665
  for (const selection of uninstallSelections) {
@@ -4464,17 +4675,28 @@ async function installUI(options = {}, executeOptions = {}) {
4464
4675
  ...executeOptions,
4465
4676
  projectPath: project.projectPath
4466
4677
  });
4467
- if (result.success) {
4468
- if (hasInstalls && hasUninstalls) {
4469
- console.log("\n\u2713 Changes applied successfully!");
4470
- } else if (hasUninstalls) {
4471
- console.log("\n\u2713 Uninstallation completed successfully!");
4472
- } else {
4473
- console.log("\n\u2713 Installation completed successfully!");
4678
+ let testCoverageResult;
4679
+ if (result.success && eslintRules?.some((r) => r.rule.id === "require-test-coverage")) {
4680
+ const eslintTargetPaths = choices.eslint?.packagePaths ?? [];
4681
+ for (const targetPath of eslintTargetPaths) {
4682
+ const coverageSetup = detectCoverageSetup(targetPath);
4683
+ if (coverageSetup.hasVitest && coverageSetup.hasCoverageConfig) {
4684
+ console.log(`
4685
+ ${pc.blue("Running tests with coverage...")}`);
4686
+ const pm = detectPackageManager(targetPath);
4687
+ try {
4688
+ await runTestsWithCoverage(pm, targetPath);
4689
+ testCoverageResult = { ran: true, success: true };
4690
+ console.log(`${pc.green("\u2713")} Coverage data generated`);
4691
+ } catch (error) {
4692
+ const errorMsg = error instanceof Error ? error.message : String(error);
4693
+ testCoverageResult = { ran: true, success: false, error: errorMsg };
4694
+ console.log(`${pc.yellow("\u26A0")} Tests completed with errors`);
4695
+ }
4696
+ }
4474
4697
  }
4475
- } else {
4476
- console.log("\n\u26A0 Operation completed with errors");
4477
4698
  }
4699
+ printInstallReport(result, testCoverageResult);
4478
4700
  process.exit(result.success ? 0 : 1);
4479
4701
  },
4480
4702
  onError: (error) => {
@@ -4489,4 +4711,4 @@ async function installUI(options = {}, executeOptions = {}) {
4489
4711
  export {
4490
4712
  installUI
4491
4713
  };
4492
- //# sourceMappingURL=install-ui-TXV7A34M.js.map
4714
+ //# sourceMappingURL=install-ui-CCZ3XJDE.js.map