viberails 0.6.0 → 0.6.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/index.cjs CHANGED
@@ -3047,8 +3047,15 @@ function setupGithubAction(projectRoot, packageManager, options) {
3047
3047
  }
3048
3048
  }
3049
3049
  if (options?.linter) {
3050
- const lintCmd = options.linter === "biome" ? "biome check ." : "eslint .";
3051
- lines.push(` - run: ${runPrefix} ${lintCmd}`);
3050
+ const lintCmd = options.linter === "biome" ? "biome check" : "eslint";
3051
+ lines.push(
3052
+ ` - name: Lint changed files`,
3053
+ ` run: |`,
3054
+ ` FILES=$(git diff --name-only --diff-filter=ACMR origin/\${{ github.event.pull_request.base.ref }}...HEAD -- '*.js' '*.ts' '*.jsx' '*.tsx')`,
3055
+ ` if [ -n "$FILES" ]; then`,
3056
+ ` echo "$FILES" | xargs ${runPrefix} ${lintCmd}`,
3057
+ ` fi`
3058
+ );
3052
3059
  }
3053
3060
  lines.push(
3054
3061
  ` - run: npx viberails check --enforce --diff-base origin/\${{ github.event.pull_request.base.ref }}`,
@@ -3080,7 +3087,7 @@ var fs18 = __toESM(require("fs"), 1);
3080
3087
  var path18 = __toESM(require("path"), 1);
3081
3088
  var import_chalk11 = __toESM(require("chalk"), 1);
3082
3089
  var import_yaml2 = require("yaml");
3083
- function addPreCommitStep(projectRoot, name, command, marker) {
3090
+ function addPreCommitStep(projectRoot, name, command, marker, lefthookExtra) {
3084
3091
  const lefthookPath = path18.join(projectRoot, "lefthook.yml");
3085
3092
  if (fs18.existsSync(lefthookPath)) {
3086
3093
  const content = fs18.readFileSync(lefthookPath, "utf-8");
@@ -3088,7 +3095,7 @@ function addPreCommitStep(projectRoot, name, command, marker) {
3088
3095
  const doc = (0, import_yaml2.parse)(content) ?? {};
3089
3096
  if (!doc["pre-commit"]) doc["pre-commit"] = { commands: {} };
3090
3097
  if (!doc["pre-commit"].commands) doc["pre-commit"].commands = {};
3091
- doc["pre-commit"].commands[name] = { run: command };
3098
+ doc["pre-commit"].commands[name] = { run: command, ...lefthookExtra };
3092
3099
  fs18.writeFileSync(lefthookPath, (0, import_yaml2.stringify)(doc));
3093
3100
  return "lefthook.yml";
3094
3101
  }
@@ -3148,9 +3155,21 @@ function setupTypecheckHook(projectRoot, packageManager) {
3148
3155
  return target;
3149
3156
  }
3150
3157
  function setupLintHook(projectRoot, linter) {
3151
- const command = linter === "biome" ? "npx biome check ." : "npx eslint .";
3158
+ const isLefthook = fs18.existsSync(path18.join(projectRoot, "lefthook.yml"));
3152
3159
  const linterName = linter === "biome" ? "Biome" : "ESLint";
3153
- const target = addPreCommitStep(projectRoot, "lint", command, linter);
3160
+ let command;
3161
+ let lefthookExtra;
3162
+ if (isLefthook) {
3163
+ command = linter === "biome" ? "npx biome check {staged_files}" : "npx eslint {staged_files}";
3164
+ lefthookExtra = {
3165
+ glob: linter === "biome" ? "*.{js,ts,jsx,tsx,json,css}" : "*.{js,ts,jsx,tsx}"
3166
+ };
3167
+ } else {
3168
+ const exts = linter === "biome" ? "'*.js' '*.ts' '*.jsx' '*.tsx' '*.json' '*.css'" : "'*.js' '*.ts' '*.jsx' '*.tsx'";
3169
+ const lintCmd = linter === "biome" ? "biome check" : "eslint";
3170
+ command = `git diff --cached --name-only --diff-filter=ACMR -- ${exts} | xargs npx ${lintCmd}`;
3171
+ }
3172
+ const target = addPreCommitStep(projectRoot, "lint", command, linter, lefthookExtra);
3154
3173
  if (target) {
3155
3174
  console.log(` ${import_chalk11.default.green("\u2713")} ${target} \u2014 added ${linterName} lint check`);
3156
3175
  }
@@ -3212,9 +3231,11 @@ async function initCommand(options, cwd) {
3212
3231
  await initInteractive(projectRoot, configPath, options);
3213
3232
  }
3214
3233
  async function initNonInteractive(projectRoot, configPath) {
3215
- console.log(import_chalk12.default.dim("Scanning project..."));
3234
+ const s = clack8.spinner();
3235
+ s.start("Scanning project...");
3216
3236
  const scanResult = await (0, import_scanner2.scan)(projectRoot);
3217
3237
  const config = (0, import_config8.generateConfig)(scanResult);
3238
+ s.stop("Scan complete");
3218
3239
  for (const pkg of config.packages) {
3219
3240
  const pkgMeta = config._meta?.packages?.[pkg.path]?.conventions;
3220
3241
  pkg.conventions = filterHighConfidence(pkg.conventions ?? {}, pkgMeta);
@@ -3229,7 +3250,8 @@ async function initNonInteractive(projectRoot, configPath) {
3229
3250
  );
3230
3251
  }
3231
3252
  if (config.packages.length > 1) {
3232
- console.log(import_chalk12.default.dim("Building import graph..."));
3253
+ const bs = clack8.spinner();
3254
+ bs.start("Building import graph...");
3233
3255
  const { buildImportGraph, inferBoundaries } = await import("@viberails/graph");
3234
3256
  const packages = resolveWorkspacePackages(projectRoot, config.packages);
3235
3257
  const graph = await buildImportGraph(projectRoot, { packages, ignore: config.ignore });
@@ -3238,7 +3260,9 @@ async function initNonInteractive(projectRoot, configPath) {
3238
3260
  if (denyCount > 0) {
3239
3261
  config.boundaries = inferred;
3240
3262
  config.rules.enforceBoundaries = true;
3241
- console.log(` Inferred ${denyCount} boundary rules`);
3263
+ bs.stop(`Inferred ${denyCount} boundary rules`);
3264
+ } else {
3265
+ bs.stop("No boundary rules inferred");
3242
3266
  }
3243
3267
  }
3244
3268
  const compacted = (0, import_config8.compactConfig)(config);
@@ -3360,19 +3384,22 @@ async function initInteractive(projectRoot, configPath, options) {
3360
3384
  clack8.outro("Aborted. No files were written.");
3361
3385
  return;
3362
3386
  }
3387
+ const ws = clack8.spinner();
3388
+ ws.start("Writing configuration and setting up integrations...");
3363
3389
  const compacted = (0, import_config8.compactConfig)(config);
3364
3390
  fs19.writeFileSync(configPath, `${JSON.stringify(compacted, null, 2)}
3365
3391
  `);
3366
3392
  writeGeneratedFiles(projectRoot, config, scanResult);
3367
3393
  updateGitignore(projectRoot);
3368
- const ok = import_chalk12.default.green("\u2713");
3369
- clack8.log.step(`${ok} ${path19.basename(configPath)}`);
3370
- clack8.log.step(`${ok} .viberails/context.md`);
3371
- clack8.log.step(`${ok} .viberails/scan-result.json`);
3372
3394
  setupSelectedIntegrations(projectRoot, integrations, {
3373
3395
  linter: rootPkgStack?.linter?.split("@")[0],
3374
3396
  packageManager: rootPkgStack?.packageManager?.split("@")[0]
3375
3397
  });
3398
+ ws.stop("Configuration written");
3399
+ const ok = import_chalk12.default.green("\u2713");
3400
+ clack8.log.step(`${ok} ${path19.basename(configPath)}`);
3401
+ clack8.log.step(`${ok} .viberails/context.md`);
3402
+ clack8.log.step(`${ok} .viberails/scan-result.json`);
3376
3403
  clack8.outro(
3377
3404
  `Done! Next: review viberails.config.json, then run viberails check
3378
3405
  ${import_chalk12.default.dim("Tip: use")} ${import_chalk12.default.cyan("viberails check --enforce")} ${import_chalk12.default.dim("in CI to block PRs on violations.")}`
@@ -3411,8 +3438,10 @@ async function syncCommand(options, cwd) {
3411
3438
  const configPath = path20.join(projectRoot, CONFIG_FILE6);
3412
3439
  const existing = await (0, import_config9.loadConfig)(configPath);
3413
3440
  const previousStats = loadPreviousStats(projectRoot);
3414
- console.log(import_chalk13.default.dim("Scanning project..."));
3441
+ const s = clack9.spinner();
3442
+ s.start("Scanning project...");
3415
3443
  const scanResult = await (0, import_scanner3.scan)(projectRoot);
3444
+ s.stop("Scan complete");
3416
3445
  const merged = (0, import_config9.mergeConfig)(existing, scanResult);
3417
3446
  const compacted = (0, import_config9.compactConfig)(merged);
3418
3447
  const compactedJson = JSON.stringify(compacted, null, 2);
@@ -3486,7 +3515,7 @@ ${import_chalk13.default.bold("Synced:")}`);
3486
3515
  }
3487
3516
 
3488
3517
  // src/index.ts
3489
- var VERSION = "0.6.0";
3518
+ var VERSION = "0.6.2";
3490
3519
  var program = new import_commander.Command();
3491
3520
  program.name("viberails").description("Guardrails for vibe coding").version(VERSION);
3492
3521
  program.command("init", { isDefault: true }).description("Scan your project and set up enforcement guardrails").option("-y, --yes", "Non-interactive mode (use defaults, high-confidence only)").option("-f, --force", "Re-initialize, replacing existing config").action(async (options) => {