viberails 0.6.7 → 0.6.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/dist/index.cjs +259 -215
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +259 -215
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -34,14 +34,14 @@ __export(index_exports, {
|
|
|
34
34
|
VERSION: () => VERSION
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
|
-
var
|
|
37
|
+
var import_chalk18 = __toESM(require("chalk"), 1);
|
|
38
38
|
var import_commander = require("commander");
|
|
39
39
|
|
|
40
40
|
// src/commands/boundaries.ts
|
|
41
41
|
var fs3 = __toESM(require("fs"), 1);
|
|
42
42
|
var path3 = __toESM(require("path"), 1);
|
|
43
43
|
var import_config = require("@viberails/config");
|
|
44
|
-
var
|
|
44
|
+
var import_chalk3 = __toESM(require("chalk"), 1);
|
|
45
45
|
|
|
46
46
|
// src/utils/find-project-root.ts
|
|
47
47
|
var fs = __toESM(require("fs"), 1);
|
|
@@ -76,6 +76,7 @@ var clack3 = __toESM(require("@clack/prompts"), 1);
|
|
|
76
76
|
|
|
77
77
|
// src/utils/prompt-package-overrides.ts
|
|
78
78
|
var clack2 = __toESM(require("@clack/prompts"), 1);
|
|
79
|
+
var import_chalk2 = __toESM(require("chalk"), 1);
|
|
79
80
|
|
|
80
81
|
// src/utils/prompt-constants.ts
|
|
81
82
|
var SENTINEL_DONE = "__done__";
|
|
@@ -90,6 +91,7 @@ var HINT_AUTO_DETECT = "auto-detect";
|
|
|
90
91
|
|
|
91
92
|
// src/utils/prompt-submenus.ts
|
|
92
93
|
var clack = __toESM(require("@clack/prompts"), 1);
|
|
94
|
+
var import_chalk = __toESM(require("chalk"), 1);
|
|
93
95
|
var FILE_NAMING_OPTIONS = [
|
|
94
96
|
{ value: "kebab-case", label: "kebab-case" },
|
|
95
97
|
{ value: "camelCase", label: "camelCase" },
|
|
@@ -149,64 +151,56 @@ async function promptFileLimitsMenu(state) {
|
|
|
149
151
|
}
|
|
150
152
|
async function promptNamingMenu(state) {
|
|
151
153
|
while (true) {
|
|
154
|
+
const ok = import_chalk.default.green("\u2713");
|
|
155
|
+
const unset = import_chalk.default.dim("-");
|
|
156
|
+
const enforcementLabel = state.enforceNaming ? `enforced ${import_chalk.default.green("\u2713")}` : `not enforced ${import_chalk.default.dim("\u2717")}`;
|
|
152
157
|
const options = [
|
|
153
158
|
{
|
|
154
|
-
value: "enforceNaming",
|
|
155
|
-
label: "Enforce file naming",
|
|
156
|
-
hint: state.enforceNaming ? "yes" : "no"
|
|
157
|
-
}
|
|
158
|
-
];
|
|
159
|
-
if (state.enforceNaming) {
|
|
160
|
-
options.push({
|
|
161
159
|
value: "fileNaming",
|
|
162
|
-
label:
|
|
160
|
+
label: `${state.fileNamingValue ? ok : unset} File naming convention`,
|
|
163
161
|
hint: state.fileNamingValue ?? HINT_NOT_SET
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
options.push(
|
|
162
|
+
},
|
|
167
163
|
{
|
|
168
164
|
value: "componentNaming",
|
|
169
|
-
label:
|
|
165
|
+
label: `${state.componentNaming ? ok : unset} Component naming`,
|
|
170
166
|
hint: state.componentNaming ?? HINT_NOT_SET
|
|
171
167
|
},
|
|
172
168
|
{
|
|
173
169
|
value: "hookNaming",
|
|
174
|
-
label:
|
|
170
|
+
label: `${state.hookNaming ? ok : unset} Hook naming`,
|
|
175
171
|
hint: state.hookNaming ?? HINT_NOT_SET
|
|
176
172
|
},
|
|
177
173
|
{
|
|
178
174
|
value: "importAlias",
|
|
179
|
-
label:
|
|
175
|
+
label: `${state.importAlias ? ok : unset} Import alias`,
|
|
180
176
|
hint: state.importAlias ?? HINT_NOT_SET
|
|
181
177
|
},
|
|
182
|
-
{
|
|
183
|
-
|
|
184
|
-
|
|
178
|
+
{
|
|
179
|
+
value: "toggleEnforcement",
|
|
180
|
+
label: state.enforceNaming ? " Turn off enforcement" : " Turn on enforcement"
|
|
181
|
+
},
|
|
182
|
+
{ value: "back", label: " Back" }
|
|
183
|
+
];
|
|
184
|
+
const choice = await clack.select({
|
|
185
|
+
message: `Naming conventions (${enforcementLabel})`,
|
|
186
|
+
options
|
|
187
|
+
});
|
|
185
188
|
if (isCancelled(choice) || choice === "back") return;
|
|
186
|
-
if (choice === "
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
initialValue: state.enforceNaming
|
|
190
|
-
});
|
|
191
|
-
if (isCancelled(result)) continue;
|
|
192
|
-
if (result && !state.fileNamingValue) {
|
|
193
|
-
const selected = await clack.select({
|
|
194
|
-
message: "Which file naming convention should be enforced?",
|
|
195
|
-
options: [...FILE_NAMING_OPTIONS]
|
|
196
|
-
});
|
|
197
|
-
if (isCancelled(selected)) continue;
|
|
198
|
-
state.fileNamingValue = selected;
|
|
199
|
-
}
|
|
200
|
-
state.enforceNaming = result;
|
|
189
|
+
if (choice === "toggleEnforcement") {
|
|
190
|
+
state.enforceNaming = !state.enforceNaming;
|
|
191
|
+
continue;
|
|
201
192
|
}
|
|
202
193
|
if (choice === "fileNaming") {
|
|
203
194
|
const selected = await clack.select({
|
|
204
|
-
message: "
|
|
205
|
-
options: [
|
|
206
|
-
|
|
195
|
+
message: "File naming convention",
|
|
196
|
+
options: [
|
|
197
|
+
...FILE_NAMING_OPTIONS,
|
|
198
|
+
{ value: SENTINEL_CLEAR, label: "Clear (no convention)" }
|
|
199
|
+
],
|
|
200
|
+
initialValue: state.fileNamingValue ?? SENTINEL_CLEAR
|
|
207
201
|
});
|
|
208
202
|
if (isCancelled(selected)) continue;
|
|
209
|
-
state.fileNamingValue = selected;
|
|
203
|
+
state.fileNamingValue = selected === SENTINEL_CLEAR ? void 0 : selected;
|
|
210
204
|
}
|
|
211
205
|
if (choice === "componentNaming") {
|
|
212
206
|
const selected = await clack.select({
|
|
@@ -271,7 +265,7 @@ async function promptTestingMenu(state) {
|
|
|
271
265
|
{
|
|
272
266
|
value: "enforceMissingTests",
|
|
273
267
|
label: "Enforce missing tests",
|
|
274
|
-
hint: state.enforceMissingTests ? "
|
|
268
|
+
hint: state.enforceMissingTests ? import_chalk.default.green("\u2713") : import_chalk.default.dim("\u2717")
|
|
275
269
|
},
|
|
276
270
|
{
|
|
277
271
|
value: "testCoverage",
|
|
@@ -380,6 +374,19 @@ function packageOverrideHint(pkg, defaults) {
|
|
|
380
374
|
if (hasCommandOverride) tags.push("command override");
|
|
381
375
|
return tags.length > 0 ? tags.join(", ") : HINT_NO_OVERRIDES;
|
|
382
376
|
}
|
|
377
|
+
function packageOverrideIcon(pkg, defaults) {
|
|
378
|
+
const dc = defaults.coverageCommand ?? "";
|
|
379
|
+
const count = [
|
|
380
|
+
pkg.conventions?.fileNaming !== void 0 && pkg.conventions.fileNaming !== defaults.fileNamingValue,
|
|
381
|
+
pkg.rules?.maxFileLines !== void 0 && pkg.rules.maxFileLines !== defaults.maxFileLines,
|
|
382
|
+
pkg.rules?.testCoverage !== void 0 && pkg.rules.testCoverage !== defaults.testCoverage,
|
|
383
|
+
pkg.coverage?.summaryPath !== void 0 && pkg.coverage.summaryPath !== defaults.coverageSummaryPath,
|
|
384
|
+
pkg.coverage?.command !== void 0 && pkg.coverage.command !== dc
|
|
385
|
+
].filter(Boolean).length;
|
|
386
|
+
if (count === 5) return import_chalk2.default.green("\u2713");
|
|
387
|
+
if (count > 0) return import_chalk2.default.yellow("~");
|
|
388
|
+
return import_chalk2.default.dim("-");
|
|
389
|
+
}
|
|
383
390
|
async function promptPackageOverrides(packages, defaults) {
|
|
384
391
|
const editablePackages = packages.filter((pkg) => pkg.path !== ".");
|
|
385
392
|
if (editablePackages.length === 0) return packages;
|
|
@@ -387,12 +394,15 @@ async function promptPackageOverrides(packages, defaults) {
|
|
|
387
394
|
const selectedPath = await clack2.select({
|
|
388
395
|
message: "Select package to edit overrides",
|
|
389
396
|
options: [
|
|
390
|
-
...editablePackages.map((pkg) =>
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
397
|
+
...editablePackages.map((pkg) => {
|
|
398
|
+
const icon = packageOverrideIcon(pkg, defaults);
|
|
399
|
+
return {
|
|
400
|
+
value: pkg.path,
|
|
401
|
+
label: `${icon} ${pkg.path} (${pkg.name})`,
|
|
402
|
+
hint: packageOverrideHint(pkg, defaults)
|
|
403
|
+
};
|
|
404
|
+
}),
|
|
405
|
+
{ value: SENTINEL_DONE, label: " Done" }
|
|
396
406
|
]
|
|
397
407
|
});
|
|
398
408
|
if (isCancelled(selectedPath) || selectedPath === SENTINEL_DONE) break;
|
|
@@ -412,18 +422,47 @@ async function promptSinglePackageOverrides(target, defaults) {
|
|
|
412
422
|
const effectiveCommand = target.coverage?.command ?? defaults.coverageCommand ?? HINT_AUTO_DETECT;
|
|
413
423
|
const hasNamingOverride = target.conventions?.fileNaming !== void 0 && target.conventions.fileNaming !== defaults.fileNamingValue;
|
|
414
424
|
const hasMaxLinesOverride = target.rules?.maxFileLines !== void 0 && target.rules.maxFileLines !== defaults.maxFileLines;
|
|
425
|
+
const hasCoverageOverride = target.rules?.testCoverage !== void 0 && target.rules.testCoverage !== defaults.testCoverage;
|
|
426
|
+
const hasSummaryOverride = target.coverage?.summaryPath !== void 0 && target.coverage.summaryPath !== defaults.coverageSummaryPath;
|
|
427
|
+
const defaultCommand = defaults.coverageCommand ?? "";
|
|
428
|
+
const hasCommandOverride = target.coverage?.command !== void 0 && target.coverage.command !== defaultCommand;
|
|
429
|
+
const ok = import_chalk2.default.green("\u2713");
|
|
430
|
+
const unset = import_chalk2.default.dim("-");
|
|
415
431
|
const namingHint = hasNamingOverride ? String(effectiveNaming) : `inherits: ${effectiveNaming ?? "not set"}`;
|
|
416
432
|
const maxLinesHint = hasMaxLinesOverride ? String(effectiveMaxLines) : `inherits: ${effectiveMaxLines}`;
|
|
433
|
+
const coverageHint2 = hasCoverageOverride ? String(effectiveCoverage) : `inherits: ${effectiveCoverage}`;
|
|
434
|
+
const summaryHint = hasSummaryOverride ? effectiveSummary : `inherits: ${effectiveSummary}`;
|
|
435
|
+
const commandHint = hasCommandOverride ? effectiveCommand : `inherits: ${effectiveCommand}`;
|
|
417
436
|
const choice = await clack2.select({
|
|
418
437
|
message: `Edit overrides for ${target.path}`,
|
|
419
438
|
options: [
|
|
420
|
-
{
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
{
|
|
426
|
-
|
|
439
|
+
{
|
|
440
|
+
value: "fileNaming",
|
|
441
|
+
label: `${hasNamingOverride ? ok : unset} File naming`,
|
|
442
|
+
hint: namingHint
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
value: "maxFileLines",
|
|
446
|
+
label: `${hasMaxLinesOverride ? ok : unset} Max file lines`,
|
|
447
|
+
hint: maxLinesHint
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
value: "testCoverage",
|
|
451
|
+
label: `${hasCoverageOverride ? ok : unset} Test coverage`,
|
|
452
|
+
hint: coverageHint2
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
value: "summaryPath",
|
|
456
|
+
label: `${hasSummaryOverride ? ok : unset} Coverage summary path`,
|
|
457
|
+
hint: summaryHint
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
value: "command",
|
|
461
|
+
label: `${hasCommandOverride ? ok : unset} Coverage command`,
|
|
462
|
+
hint: commandHint
|
|
463
|
+
},
|
|
464
|
+
{ value: "reset", label: " Reset all overrides for this package" },
|
|
465
|
+
{ value: "back", label: " Back to package list" }
|
|
427
466
|
]
|
|
428
467
|
});
|
|
429
468
|
if (isCancelled(choice) || choice === "back") break;
|
|
@@ -503,8 +542,8 @@ async function promptSinglePackageOverrides(target, defaults) {
|
|
|
503
542
|
});
|
|
504
543
|
if (isCancelled(result)) continue;
|
|
505
544
|
const value = result.trim();
|
|
506
|
-
const
|
|
507
|
-
if (value.length === 0 || value ===
|
|
545
|
+
const defaultCommand2 = defaults.coverageCommand ?? "";
|
|
546
|
+
if (value.length === 0 || value === defaultCommand2) {
|
|
508
547
|
if (target.coverage) delete target.coverage.command;
|
|
509
548
|
} else {
|
|
510
549
|
target.coverage = { ...target.coverage ?? {}, command: value };
|
|
@@ -767,48 +806,48 @@ async function boundariesCommand(options, cwd) {
|
|
|
767
806
|
}
|
|
768
807
|
function displayRules(config) {
|
|
769
808
|
if (!config.boundaries || Object.keys(config.boundaries.deny).length === 0) {
|
|
770
|
-
console.log(
|
|
771
|
-
console.log(`Run ${
|
|
809
|
+
console.log(import_chalk3.default.yellow("No boundary rules configured."));
|
|
810
|
+
console.log(`Run ${import_chalk3.default.cyan("viberails boundaries --infer")} to generate rules.`);
|
|
772
811
|
return;
|
|
773
812
|
}
|
|
774
813
|
const { deny } = config.boundaries;
|
|
775
814
|
const sources = Object.keys(deny).filter((k) => deny[k].length > 0);
|
|
776
815
|
const totalRules = sources.reduce((sum, k) => sum + deny[k].length, 0);
|
|
777
816
|
console.log(`
|
|
778
|
-
${
|
|
817
|
+
${import_chalk3.default.bold(`Boundary rules (${totalRules} deny rules):`)}
|
|
779
818
|
`);
|
|
780
819
|
for (const source of sources) {
|
|
781
820
|
for (const target of deny[source]) {
|
|
782
|
-
console.log(` ${
|
|
821
|
+
console.log(` ${import_chalk3.default.red("\u2717")} ${source} \u2192 ${target}`);
|
|
783
822
|
}
|
|
784
823
|
}
|
|
785
824
|
console.log(
|
|
786
825
|
`
|
|
787
|
-
Enforcement: ${config.rules.enforceBoundaries ?
|
|
826
|
+
Enforcement: ${config.rules.enforceBoundaries ? import_chalk3.default.green("on") : import_chalk3.default.yellow("off")}`
|
|
788
827
|
);
|
|
789
828
|
}
|
|
790
829
|
async function inferAndDisplay(projectRoot, config, configPath) {
|
|
791
|
-
console.log(
|
|
830
|
+
console.log(import_chalk3.default.dim("Analyzing imports..."));
|
|
792
831
|
const { buildImportGraph, inferBoundaries } = await import("@viberails/graph");
|
|
793
832
|
const packages = config.packages.length > 1 ? resolveWorkspacePackages(projectRoot, config.packages) : void 0;
|
|
794
833
|
const graph = await buildImportGraph(projectRoot, {
|
|
795
834
|
packages,
|
|
796
835
|
ignore: config.ignore
|
|
797
836
|
});
|
|
798
|
-
console.log(
|
|
837
|
+
console.log(import_chalk3.default.dim(`${graph.nodes.length} files, ${graph.edges.length} edges`));
|
|
799
838
|
const inferred = inferBoundaries(graph);
|
|
800
839
|
const sources = Object.keys(inferred.deny).filter((k) => inferred.deny[k].length > 0);
|
|
801
840
|
const totalRules = sources.reduce((sum, k) => sum + inferred.deny[k].length, 0);
|
|
802
841
|
if (totalRules === 0) {
|
|
803
|
-
console.log(
|
|
842
|
+
console.log(import_chalk3.default.yellow("No boundary rules could be inferred."));
|
|
804
843
|
return;
|
|
805
844
|
}
|
|
806
845
|
console.log(`
|
|
807
|
-
${
|
|
846
|
+
${import_chalk3.default.bold("Inferred boundary rules:")}
|
|
808
847
|
`);
|
|
809
848
|
for (const source of sources) {
|
|
810
849
|
for (const target of inferred.deny[source]) {
|
|
811
|
-
console.log(` ${
|
|
850
|
+
console.log(` ${import_chalk3.default.red("\u2717")} ${source} \u2192 ${target}`);
|
|
812
851
|
}
|
|
813
852
|
}
|
|
814
853
|
console.log(`
|
|
@@ -820,11 +859,11 @@ ${import_chalk.default.bold("Inferred boundary rules:")}
|
|
|
820
859
|
config.rules.enforceBoundaries = true;
|
|
821
860
|
fs3.writeFileSync(configPath, `${JSON.stringify((0, import_config.compactConfig)(config), null, 2)}
|
|
822
861
|
`);
|
|
823
|
-
console.log(`${
|
|
862
|
+
console.log(`${import_chalk3.default.green("\u2713")} Saved ${totalRules} rules`);
|
|
824
863
|
}
|
|
825
864
|
}
|
|
826
865
|
async function showGraph(projectRoot, config) {
|
|
827
|
-
console.log(
|
|
866
|
+
console.log(import_chalk3.default.dim("Building import graph..."));
|
|
828
867
|
const { buildImportGraph } = await import("@viberails/graph");
|
|
829
868
|
const packages = config.packages.length > 1 ? resolveWorkspacePackages(projectRoot, config.packages) : void 0;
|
|
830
869
|
const graph = await buildImportGraph(projectRoot, {
|
|
@@ -832,20 +871,20 @@ async function showGraph(projectRoot, config) {
|
|
|
832
871
|
ignore: config.ignore
|
|
833
872
|
});
|
|
834
873
|
console.log(`
|
|
835
|
-
${
|
|
874
|
+
${import_chalk3.default.bold("Import dependency graph:")}
|
|
836
875
|
`);
|
|
837
876
|
console.log(` ${graph.nodes.length} files, ${graph.edges.length} imports
|
|
838
877
|
`);
|
|
839
878
|
if (graph.packages.length > 0) {
|
|
840
879
|
for (const pkg of graph.packages) {
|
|
841
880
|
const deps = pkg.internalDeps.length > 0 ? `
|
|
842
|
-
${pkg.internalDeps.map((d) => ` \u2192 ${d}`).join("\n")}` :
|
|
881
|
+
${pkg.internalDeps.map((d) => ` \u2192 ${d}`).join("\n")}` : import_chalk3.default.dim(" (no internal deps)");
|
|
843
882
|
console.log(` ${pkg.name}${deps}`);
|
|
844
883
|
}
|
|
845
884
|
}
|
|
846
885
|
if (graph.cycles.length > 0) {
|
|
847
886
|
console.log(`
|
|
848
|
-
${
|
|
887
|
+
${import_chalk3.default.yellow("Cycles detected:")}`);
|
|
849
888
|
for (const cycle of graph.cycles) {
|
|
850
889
|
const paths = cycle.map((f) => path3.relative(projectRoot, f));
|
|
851
890
|
console.log(` ${paths.join(" \u2192 ")}`);
|
|
@@ -857,7 +896,7 @@ ${import_chalk.default.yellow("Cycles detected:")}`);
|
|
|
857
896
|
var fs7 = __toESM(require("fs"), 1);
|
|
858
897
|
var path7 = __toESM(require("path"), 1);
|
|
859
898
|
var import_config5 = require("@viberails/config");
|
|
860
|
-
var
|
|
899
|
+
var import_chalk5 = __toESM(require("chalk"), 1);
|
|
861
900
|
|
|
862
901
|
// src/commands/check-config.ts
|
|
863
902
|
var import_config2 = require("@viberails/config");
|
|
@@ -1249,7 +1288,7 @@ function collectSourceFiles(dir, projectRoot) {
|
|
|
1249
1288
|
}
|
|
1250
1289
|
|
|
1251
1290
|
// src/commands/check-print.ts
|
|
1252
|
-
var
|
|
1291
|
+
var import_chalk4 = __toESM(require("chalk"), 1);
|
|
1253
1292
|
function printGroupedViolations(violations, limit) {
|
|
1254
1293
|
const groups = /* @__PURE__ */ new Map();
|
|
1255
1294
|
for (const v of violations) {
|
|
@@ -1277,12 +1316,12 @@ function printGroupedViolations(violations, limit) {
|
|
|
1277
1316
|
const toShow = group.slice(0, remaining);
|
|
1278
1317
|
const hidden = group.length - toShow.length;
|
|
1279
1318
|
for (const v of toShow) {
|
|
1280
|
-
const icon = v.severity === "error" ?
|
|
1281
|
-
console.log(`${icon} ${
|
|
1319
|
+
const icon = v.severity === "error" ? import_chalk4.default.red("\u2717") : import_chalk4.default.yellow("!");
|
|
1320
|
+
console.log(`${icon} ${import_chalk4.default.dim(v.rule)} ${v.file}: ${v.message}`);
|
|
1282
1321
|
}
|
|
1283
1322
|
totalShown += toShow.length;
|
|
1284
1323
|
if (hidden > 0) {
|
|
1285
|
-
console.log(
|
|
1324
|
+
console.log(import_chalk4.default.dim(` ... and ${hidden} more ${rule} violations`));
|
|
1286
1325
|
}
|
|
1287
1326
|
}
|
|
1288
1327
|
}
|
|
@@ -1372,13 +1411,13 @@ async function checkCommand(options, cwd) {
|
|
|
1372
1411
|
const startDir = cwd ?? process.cwd();
|
|
1373
1412
|
const projectRoot = findProjectRoot(startDir);
|
|
1374
1413
|
if (!projectRoot) {
|
|
1375
|
-
console.error(`${
|
|
1414
|
+
console.error(`${import_chalk5.default.red("Error:")} No package.json found. Are you in a JS/TS project?`);
|
|
1376
1415
|
return 1;
|
|
1377
1416
|
}
|
|
1378
1417
|
const configPath = path7.join(projectRoot, CONFIG_FILE2);
|
|
1379
1418
|
if (!fs7.existsSync(configPath)) {
|
|
1380
1419
|
console.error(
|
|
1381
|
-
`${
|
|
1420
|
+
`${import_chalk5.default.red("Error:")} No viberails.config.json found. Run \`viberails init\` first.`
|
|
1382
1421
|
);
|
|
1383
1422
|
return 1;
|
|
1384
1423
|
}
|
|
@@ -1392,7 +1431,7 @@ async function checkCommand(options, cwd) {
|
|
|
1392
1431
|
} else if (options.diffBase) {
|
|
1393
1432
|
const diff = getDiffFiles(projectRoot, options.diffBase);
|
|
1394
1433
|
if (diff.error && options.enforce) {
|
|
1395
|
-
console.error(`${
|
|
1434
|
+
console.error(`${import_chalk5.default.red("Error:")} ${diff.error}`);
|
|
1396
1435
|
return 1;
|
|
1397
1436
|
}
|
|
1398
1437
|
filesToCheck = diff.all.filter((f) => SOURCE_EXTS.has(path7.extname(f)));
|
|
@@ -1407,13 +1446,13 @@ async function checkCommand(options, cwd) {
|
|
|
1407
1446
|
if (options.format === "json") {
|
|
1408
1447
|
console.log(JSON.stringify({ violations: [], checkedFiles: 0 }));
|
|
1409
1448
|
} else {
|
|
1410
|
-
console.log(`${
|
|
1449
|
+
console.log(`${import_chalk5.default.green("\u2713")} No files to check.`);
|
|
1411
1450
|
}
|
|
1412
1451
|
return 0;
|
|
1413
1452
|
}
|
|
1414
1453
|
const violations = [];
|
|
1415
1454
|
const severity = options.enforce ? "error" : "warn";
|
|
1416
|
-
const log9 = options.format !== "json" && !options.hook && !options.quiet ? (msg) => process.stderr.write(
|
|
1455
|
+
const log9 = options.format !== "json" && !options.hook && !options.quiet ? (msg) => process.stderr.write(import_chalk5.default.dim(msg)) : () => {
|
|
1417
1456
|
};
|
|
1418
1457
|
log9(" Checking files...");
|
|
1419
1458
|
for (const file of filesToCheck) {
|
|
@@ -1508,7 +1547,7 @@ async function checkCommand(options, cwd) {
|
|
|
1508
1547
|
return options.enforce && violations.length > 0 ? 1 : 0;
|
|
1509
1548
|
}
|
|
1510
1549
|
if (violations.length === 0) {
|
|
1511
|
-
console.log(`${
|
|
1550
|
+
console.log(`${import_chalk5.default.green("\u2713")} ${filesToCheck.length} files checked \u2014 no violations`);
|
|
1512
1551
|
return 0;
|
|
1513
1552
|
}
|
|
1514
1553
|
if (!options.quiet) {
|
|
@@ -1516,7 +1555,7 @@ async function checkCommand(options, cwd) {
|
|
|
1516
1555
|
}
|
|
1517
1556
|
printSummary(violations);
|
|
1518
1557
|
if (options.enforce) {
|
|
1519
|
-
console.log(
|
|
1558
|
+
console.log(import_chalk5.default.red("Fix violations before committing."));
|
|
1520
1559
|
return 1;
|
|
1521
1560
|
}
|
|
1522
1561
|
return 0;
|
|
@@ -1574,14 +1613,14 @@ var path9 = __toESM(require("path"), 1);
|
|
|
1574
1613
|
var clack6 = __toESM(require("@clack/prompts"), 1);
|
|
1575
1614
|
var import_config6 = require("@viberails/config");
|
|
1576
1615
|
var import_scanner = require("@viberails/scanner");
|
|
1577
|
-
var
|
|
1616
|
+
var import_chalk8 = __toESM(require("chalk"), 1);
|
|
1578
1617
|
|
|
1579
1618
|
// src/display-text.ts
|
|
1580
1619
|
var import_types4 = require("@viberails/types");
|
|
1581
1620
|
|
|
1582
1621
|
// src/display.ts
|
|
1583
1622
|
var import_types3 = require("@viberails/types");
|
|
1584
|
-
var
|
|
1623
|
+
var import_chalk7 = __toESM(require("chalk"), 1);
|
|
1585
1624
|
|
|
1586
1625
|
// src/display-helpers.ts
|
|
1587
1626
|
var import_types = require("@viberails/types");
|
|
@@ -1634,7 +1673,7 @@ function formatRoleGroup(group) {
|
|
|
1634
1673
|
|
|
1635
1674
|
// src/display-monorepo.ts
|
|
1636
1675
|
var import_types2 = require("@viberails/types");
|
|
1637
|
-
var
|
|
1676
|
+
var import_chalk6 = __toESM(require("chalk"), 1);
|
|
1638
1677
|
function formatPackageSummary(pkg) {
|
|
1639
1678
|
const parts = [];
|
|
1640
1679
|
if (pkg.stack.framework) {
|
|
@@ -1651,23 +1690,23 @@ function formatPackageSummary(pkg) {
|
|
|
1651
1690
|
function displayMonorepoResults(scanResult) {
|
|
1652
1691
|
const { stack, packages } = scanResult;
|
|
1653
1692
|
console.log(`
|
|
1654
|
-
${
|
|
1655
|
-
console.log(` ${
|
|
1693
|
+
${import_chalk6.default.bold(`Detected: (monorepo, ${packages.length} packages)`)}`);
|
|
1694
|
+
console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.language)}`);
|
|
1656
1695
|
if (stack.packageManager) {
|
|
1657
|
-
console.log(` ${
|
|
1696
|
+
console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.packageManager)}`);
|
|
1658
1697
|
}
|
|
1659
1698
|
if (stack.linter && stack.formatter && stack.linter.name === stack.formatter.name) {
|
|
1660
|
-
console.log(` ${
|
|
1699
|
+
console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.linter)} (lint + format)`);
|
|
1661
1700
|
} else {
|
|
1662
1701
|
if (stack.linter) {
|
|
1663
|
-
console.log(` ${
|
|
1702
|
+
console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.linter)}`);
|
|
1664
1703
|
}
|
|
1665
1704
|
if (stack.formatter) {
|
|
1666
|
-
console.log(` ${
|
|
1705
|
+
console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.formatter)}`);
|
|
1667
1706
|
}
|
|
1668
1707
|
}
|
|
1669
1708
|
if (stack.testRunner) {
|
|
1670
|
-
console.log(` ${
|
|
1709
|
+
console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.testRunner)}`);
|
|
1671
1710
|
}
|
|
1672
1711
|
console.log("");
|
|
1673
1712
|
for (const pkg of packages) {
|
|
@@ -1678,13 +1717,13 @@ ${import_chalk4.default.bold(`Detected: (monorepo, ${packages.length} packages)`
|
|
|
1678
1717
|
);
|
|
1679
1718
|
if (packagesWithDirs.length > 0) {
|
|
1680
1719
|
console.log(`
|
|
1681
|
-
${
|
|
1720
|
+
${import_chalk6.default.bold("Structure:")}`);
|
|
1682
1721
|
for (const pkg of packagesWithDirs) {
|
|
1683
1722
|
const groups = groupByRole(pkg.structure.directories);
|
|
1684
1723
|
if (groups.length === 0) continue;
|
|
1685
1724
|
console.log(` ${pkg.relativePath}:`);
|
|
1686
1725
|
for (const group of groups) {
|
|
1687
|
-
console.log(` ${
|
|
1726
|
+
console.log(` ${import_chalk6.default.green("\u2713")} ${formatRoleGroup(group)}`);
|
|
1688
1727
|
}
|
|
1689
1728
|
}
|
|
1690
1729
|
}
|
|
@@ -1765,7 +1804,7 @@ function displayConventions(scanResult) {
|
|
|
1765
1804
|
const conventionEntries = Object.entries(scanResult.conventions);
|
|
1766
1805
|
if (conventionEntries.length === 0) return;
|
|
1767
1806
|
console.log(`
|
|
1768
|
-
${
|
|
1807
|
+
${import_chalk7.default.bold("Conventions:")}`);
|
|
1769
1808
|
for (const [key, convention] of conventionEntries) {
|
|
1770
1809
|
if (convention.confidence === "low") continue;
|
|
1771
1810
|
const label = import_types3.CONVENTION_LABELS[key] ?? key;
|
|
@@ -1773,19 +1812,19 @@ ${import_chalk5.default.bold("Conventions:")}`);
|
|
|
1773
1812
|
const pkgValues = scanResult.packages.filter((pkg) => pkg.conventions[key] && pkg.conventions[key].confidence !== "low").map((pkg) => ({ relativePath: pkg.relativePath, convention: pkg.conventions[key] }));
|
|
1774
1813
|
const allSame = pkgValues.every((pv) => pv.convention.value === convention.value);
|
|
1775
1814
|
if (allSame || pkgValues.length <= 1) {
|
|
1776
|
-
const ind = convention.confidence === "high" ?
|
|
1777
|
-
const detail =
|
|
1815
|
+
const ind = convention.confidence === "high" ? import_chalk7.default.green("\u2713") : import_chalk7.default.yellow("~");
|
|
1816
|
+
const detail = import_chalk7.default.dim(`(${confidenceLabel(convention)})`);
|
|
1778
1817
|
console.log(` ${ind} ${label}: ${convention.value} ${detail}`);
|
|
1779
1818
|
} else {
|
|
1780
|
-
console.log(` ${
|
|
1819
|
+
console.log(` ${import_chalk7.default.yellow("~")} ${label}: varies by package`);
|
|
1781
1820
|
for (const pv of pkgValues) {
|
|
1782
1821
|
const pct = Math.round(pv.convention.consistency);
|
|
1783
1822
|
console.log(` ${pv.relativePath}: ${pv.convention.value} (${pct}%)`);
|
|
1784
1823
|
}
|
|
1785
1824
|
}
|
|
1786
1825
|
} else {
|
|
1787
|
-
const ind = convention.confidence === "high" ?
|
|
1788
|
-
const detail =
|
|
1826
|
+
const ind = convention.confidence === "high" ? import_chalk7.default.green("\u2713") : import_chalk7.default.yellow("~");
|
|
1827
|
+
const detail = import_chalk7.default.dim(`(${confidenceLabel(convention)})`);
|
|
1789
1828
|
console.log(` ${ind} ${label}: ${convention.value} ${detail}`);
|
|
1790
1829
|
}
|
|
1791
1830
|
}
|
|
@@ -1793,7 +1832,7 @@ ${import_chalk5.default.bold("Conventions:")}`);
|
|
|
1793
1832
|
function displaySummarySection(scanResult) {
|
|
1794
1833
|
const pkgCount = scanResult.packages.length > 1 ? scanResult.packages.length : void 0;
|
|
1795
1834
|
console.log(`
|
|
1796
|
-
${
|
|
1835
|
+
${import_chalk7.default.bold("Summary:")}`);
|
|
1797
1836
|
console.log(` ${formatSummary(scanResult.statistics, pkgCount)}`);
|
|
1798
1837
|
const ext = formatExtensions(scanResult.statistics.filesByExtension);
|
|
1799
1838
|
if (ext) {
|
|
@@ -1807,47 +1846,47 @@ function displayScanResults(scanResult) {
|
|
|
1807
1846
|
}
|
|
1808
1847
|
const { stack } = scanResult;
|
|
1809
1848
|
console.log(`
|
|
1810
|
-
${
|
|
1849
|
+
${import_chalk7.default.bold("Detected:")}`);
|
|
1811
1850
|
if (stack.framework) {
|
|
1812
|
-
console.log(` ${
|
|
1851
|
+
console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.framework, import_types3.FRAMEWORK_NAMES)}`);
|
|
1813
1852
|
}
|
|
1814
|
-
console.log(` ${
|
|
1853
|
+
console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.language)}`);
|
|
1815
1854
|
if (stack.styling) {
|
|
1816
|
-
console.log(` ${
|
|
1855
|
+
console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.styling, import_types3.STYLING_NAMES)}`);
|
|
1817
1856
|
}
|
|
1818
1857
|
if (stack.backend) {
|
|
1819
|
-
console.log(` ${
|
|
1858
|
+
console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.backend, import_types3.FRAMEWORK_NAMES)}`);
|
|
1820
1859
|
}
|
|
1821
1860
|
if (stack.orm) {
|
|
1822
|
-
console.log(` ${
|
|
1861
|
+
console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.orm, import_types3.ORM_NAMES)}`);
|
|
1823
1862
|
}
|
|
1824
1863
|
if (stack.linter && stack.formatter && stack.linter.name === stack.formatter.name) {
|
|
1825
|
-
console.log(` ${
|
|
1864
|
+
console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.linter)} (lint + format)`);
|
|
1826
1865
|
} else {
|
|
1827
1866
|
if (stack.linter) {
|
|
1828
|
-
console.log(` ${
|
|
1867
|
+
console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.linter)}`);
|
|
1829
1868
|
}
|
|
1830
1869
|
if (stack.formatter) {
|
|
1831
|
-
console.log(` ${
|
|
1870
|
+
console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.formatter)}`);
|
|
1832
1871
|
}
|
|
1833
1872
|
}
|
|
1834
1873
|
if (stack.testRunner) {
|
|
1835
|
-
console.log(` ${
|
|
1874
|
+
console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.testRunner)}`);
|
|
1836
1875
|
}
|
|
1837
1876
|
if (stack.packageManager) {
|
|
1838
|
-
console.log(` ${
|
|
1877
|
+
console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.packageManager)}`);
|
|
1839
1878
|
}
|
|
1840
1879
|
if (stack.libraries.length > 0) {
|
|
1841
1880
|
for (const lib of stack.libraries) {
|
|
1842
|
-
console.log(` ${
|
|
1881
|
+
console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(lib, import_types3.LIBRARY_NAMES)}`);
|
|
1843
1882
|
}
|
|
1844
1883
|
}
|
|
1845
1884
|
const groups = groupByRole(scanResult.structure.directories);
|
|
1846
1885
|
if (groups.length > 0) {
|
|
1847
1886
|
console.log(`
|
|
1848
|
-
${
|
|
1887
|
+
${import_chalk7.default.bold("Structure:")}`);
|
|
1849
1888
|
for (const group of groups) {
|
|
1850
|
-
console.log(` ${
|
|
1889
|
+
console.log(` ${import_chalk7.default.green("\u2713")} ${formatRoleGroup(group)}`);
|
|
1851
1890
|
}
|
|
1852
1891
|
}
|
|
1853
1892
|
displayConventions(scanResult);
|
|
@@ -1857,25 +1896,25 @@ ${import_chalk5.default.bold("Structure:")}`);
|
|
|
1857
1896
|
function displayRulesPreview(config) {
|
|
1858
1897
|
const root = config.packages.find((p) => p.path === ".") ?? config.packages[0];
|
|
1859
1898
|
console.log(
|
|
1860
|
-
`${
|
|
1899
|
+
`${import_chalk7.default.bold("Rules:")} ${import_chalk7.default.dim("(warns on violation; use --enforce in CI to block)")}`
|
|
1861
1900
|
);
|
|
1862
|
-
console.log(` ${
|
|
1901
|
+
console.log(` ${import_chalk7.default.dim("\u2022")} Max file size: ${config.rules.maxFileLines} lines`);
|
|
1863
1902
|
if (config.rules.testCoverage > 0 && root?.structure?.testPattern) {
|
|
1864
1903
|
console.log(
|
|
1865
|
-
` ${
|
|
1904
|
+
` ${import_chalk7.default.dim("\u2022")} Test coverage target: ${config.rules.testCoverage}% (${root.structure.testPattern})`
|
|
1866
1905
|
);
|
|
1867
1906
|
} else if (config.rules.testCoverage > 0) {
|
|
1868
|
-
console.log(` ${
|
|
1907
|
+
console.log(` ${import_chalk7.default.dim("\u2022")} Test coverage target: ${config.rules.testCoverage}%`);
|
|
1869
1908
|
} else {
|
|
1870
|
-
console.log(` ${
|
|
1909
|
+
console.log(` ${import_chalk7.default.dim("\u2022")} Test coverage target: disabled`);
|
|
1871
1910
|
}
|
|
1872
1911
|
if (config.rules.enforceNaming && root?.conventions?.fileNaming) {
|
|
1873
|
-
console.log(` ${
|
|
1912
|
+
console.log(` ${import_chalk7.default.dim("\u2022")} Enforce file naming: ${root.conventions.fileNaming}`);
|
|
1874
1913
|
} else {
|
|
1875
|
-
console.log(` ${
|
|
1914
|
+
console.log(` ${import_chalk7.default.dim("\u2022")} Enforce file naming: no`);
|
|
1876
1915
|
}
|
|
1877
1916
|
console.log(
|
|
1878
|
-
` ${
|
|
1917
|
+
` ${import_chalk7.default.dim("\u2022")} Enforce boundaries: ${config.rules.enforceBoundaries ? "yes" : "no"}`
|
|
1879
1918
|
);
|
|
1880
1919
|
console.log("");
|
|
1881
1920
|
}
|
|
@@ -2200,7 +2239,7 @@ async function configCommand(options, cwd) {
|
|
|
2200
2239
|
}
|
|
2201
2240
|
const configPath = path9.join(projectRoot, CONFIG_FILE3);
|
|
2202
2241
|
if (!fs10.existsSync(configPath)) {
|
|
2203
|
-
console.log(`${
|
|
2242
|
+
console.log(`${import_chalk8.default.yellow("!")} No config found. Run ${import_chalk8.default.cyan("viberails")} first.`);
|
|
2204
2243
|
return;
|
|
2205
2244
|
}
|
|
2206
2245
|
if (!options.suppressIntro) {
|
|
@@ -2291,22 +2330,22 @@ async function rescanAndMerge(projectRoot, config) {
|
|
|
2291
2330
|
var fs13 = __toESM(require("fs"), 1);
|
|
2292
2331
|
var path13 = __toESM(require("path"), 1);
|
|
2293
2332
|
var import_config7 = require("@viberails/config");
|
|
2294
|
-
var
|
|
2333
|
+
var import_chalk10 = __toESM(require("chalk"), 1);
|
|
2295
2334
|
|
|
2296
2335
|
// src/commands/fix-helpers.ts
|
|
2297
2336
|
var import_node_child_process3 = require("child_process");
|
|
2298
|
-
var
|
|
2337
|
+
var import_chalk9 = __toESM(require("chalk"), 1);
|
|
2299
2338
|
function printPlan(renames, stubs) {
|
|
2300
2339
|
if (renames.length > 0) {
|
|
2301
|
-
console.log(
|
|
2340
|
+
console.log(import_chalk9.default.bold("\nFile renames:"));
|
|
2302
2341
|
for (const r of renames) {
|
|
2303
|
-
console.log(` ${
|
|
2342
|
+
console.log(` ${import_chalk9.default.red(r.oldPath)} \u2192 ${import_chalk9.default.green(r.newPath)}`);
|
|
2304
2343
|
}
|
|
2305
2344
|
}
|
|
2306
2345
|
if (stubs.length > 0) {
|
|
2307
|
-
console.log(
|
|
2346
|
+
console.log(import_chalk9.default.bold("\nTest stubs to create:"));
|
|
2308
2347
|
for (const s of stubs) {
|
|
2309
|
-
console.log(` ${
|
|
2348
|
+
console.log(` ${import_chalk9.default.green("+")} ${s.path}`);
|
|
2310
2349
|
}
|
|
2311
2350
|
}
|
|
2312
2351
|
}
|
|
@@ -2634,13 +2673,13 @@ async function fixCommand(options, cwd) {
|
|
|
2634
2673
|
const startDir = cwd ?? process.cwd();
|
|
2635
2674
|
const projectRoot = findProjectRoot(startDir);
|
|
2636
2675
|
if (!projectRoot) {
|
|
2637
|
-
console.error(`${
|
|
2676
|
+
console.error(`${import_chalk10.default.red("Error:")} No package.json found. Are you in a JS/TS project?`);
|
|
2638
2677
|
return 1;
|
|
2639
2678
|
}
|
|
2640
2679
|
const configPath = path13.join(projectRoot, CONFIG_FILE4);
|
|
2641
2680
|
if (!fs13.existsSync(configPath)) {
|
|
2642
2681
|
console.error(
|
|
2643
|
-
`${
|
|
2682
|
+
`${import_chalk10.default.red("Error:")} No viberails.config.json found. Run \`viberails init\` first.`
|
|
2644
2683
|
);
|
|
2645
2684
|
return 1;
|
|
2646
2685
|
}
|
|
@@ -2649,7 +2688,7 @@ async function fixCommand(options, cwd) {
|
|
|
2649
2688
|
const isDirty = checkGitDirty(projectRoot);
|
|
2650
2689
|
if (isDirty) {
|
|
2651
2690
|
console.log(
|
|
2652
|
-
|
|
2691
|
+
import_chalk10.default.yellow("Warning: You have uncommitted changes. Consider committing first.")
|
|
2653
2692
|
);
|
|
2654
2693
|
}
|
|
2655
2694
|
}
|
|
@@ -2696,41 +2735,41 @@ async function fixCommand(options, cwd) {
|
|
|
2696
2735
|
return blockedOldBareNames.has(bare);
|
|
2697
2736
|
});
|
|
2698
2737
|
if (safeRenames.length === 0 && testStubs.length === 0 && skippedRenames.length === 0) {
|
|
2699
|
-
console.log(`${
|
|
2738
|
+
console.log(`${import_chalk10.default.green("\u2713")} No fixable violations found.`);
|
|
2700
2739
|
return 0;
|
|
2701
2740
|
}
|
|
2702
2741
|
printPlan(safeRenames, testStubs);
|
|
2703
2742
|
if (skippedRenames.length > 0) {
|
|
2704
2743
|
console.log("");
|
|
2705
2744
|
console.log(
|
|
2706
|
-
|
|
2745
|
+
import_chalk10.default.yellow(
|
|
2707
2746
|
`Skipping ${skippedRenames.length} rename${skippedRenames.length > 1 ? "s" : ""} \u2014 aliased imports would break:`
|
|
2708
2747
|
)
|
|
2709
2748
|
);
|
|
2710
2749
|
for (const r of skippedRenames.slice(0, 5)) {
|
|
2711
|
-
console.log(
|
|
2750
|
+
console.log(import_chalk10.default.dim(` ${r.oldPath} \u2192 ${r.newPath}`));
|
|
2712
2751
|
}
|
|
2713
2752
|
if (skippedRenames.length > 5) {
|
|
2714
|
-
console.log(
|
|
2753
|
+
console.log(import_chalk10.default.dim(` ... and ${skippedRenames.length - 5} more`));
|
|
2715
2754
|
}
|
|
2716
2755
|
console.log("");
|
|
2717
|
-
console.log(
|
|
2756
|
+
console.log(import_chalk10.default.yellow("Affected aliased imports:"));
|
|
2718
2757
|
for (const alias of aliasImports.slice(0, 5)) {
|
|
2719
2758
|
const relFile = path13.relative(projectRoot, alias.file);
|
|
2720
|
-
console.log(
|
|
2759
|
+
console.log(import_chalk10.default.dim(` ${relFile}:${alias.line} \u2014 ${alias.specifier}`));
|
|
2721
2760
|
}
|
|
2722
2761
|
if (aliasImports.length > 5) {
|
|
2723
|
-
console.log(
|
|
2762
|
+
console.log(import_chalk10.default.dim(` ... and ${aliasImports.length - 5} more`));
|
|
2724
2763
|
}
|
|
2725
|
-
console.log(
|
|
2764
|
+
console.log(import_chalk10.default.dim(" Update these imports to relative paths first, then re-run fix."));
|
|
2726
2765
|
}
|
|
2727
2766
|
if (safeRenames.length === 0 && testStubs.length === 0) {
|
|
2728
2767
|
console.log(`
|
|
2729
|
-
${
|
|
2768
|
+
${import_chalk10.default.yellow("!")} No safe fixes to apply. Resolve aliased imports first.`);
|
|
2730
2769
|
return 0;
|
|
2731
2770
|
}
|
|
2732
2771
|
if (options.dryRun) {
|
|
2733
|
-
console.log(
|
|
2772
|
+
console.log(import_chalk10.default.dim("\nDry run \u2014 no changes applied."));
|
|
2734
2773
|
return 0;
|
|
2735
2774
|
}
|
|
2736
2775
|
if (!options.yes) {
|
|
@@ -2761,15 +2800,15 @@ ${import_chalk8.default.yellow("!")} No safe fixes to apply. Resolve aliased imp
|
|
|
2761
2800
|
}
|
|
2762
2801
|
console.log("");
|
|
2763
2802
|
if (renameCount > 0) {
|
|
2764
|
-
console.log(`${
|
|
2803
|
+
console.log(`${import_chalk10.default.green("\u2713")} Renamed ${renameCount} file${renameCount > 1 ? "s" : ""}`);
|
|
2765
2804
|
}
|
|
2766
2805
|
if (importUpdateCount > 0) {
|
|
2767
2806
|
console.log(
|
|
2768
|
-
`${
|
|
2807
|
+
`${import_chalk10.default.green("\u2713")} Updated ${importUpdateCount} import${importUpdateCount > 1 ? "s" : ""}`
|
|
2769
2808
|
);
|
|
2770
2809
|
}
|
|
2771
2810
|
if (stubCount > 0) {
|
|
2772
|
-
console.log(`${
|
|
2811
|
+
console.log(`${import_chalk10.default.green("\u2713")} Generated ${stubCount} test stub${stubCount > 1 ? "s" : ""}`);
|
|
2773
2812
|
}
|
|
2774
2813
|
return 0;
|
|
2775
2814
|
}
|
|
@@ -2780,13 +2819,13 @@ var path21 = __toESM(require("path"), 1);
|
|
|
2780
2819
|
var clack13 = __toESM(require("@clack/prompts"), 1);
|
|
2781
2820
|
var import_config9 = require("@viberails/config");
|
|
2782
2821
|
var import_scanner3 = require("@viberails/scanner");
|
|
2783
|
-
var
|
|
2822
|
+
var import_chalk16 = __toESM(require("chalk"), 1);
|
|
2784
2823
|
|
|
2785
2824
|
// src/utils/check-prerequisites.ts
|
|
2786
2825
|
var fs14 = __toESM(require("fs"), 1);
|
|
2787
2826
|
var path14 = __toESM(require("path"), 1);
|
|
2788
2827
|
var clack7 = __toESM(require("@clack/prompts"), 1);
|
|
2789
|
-
var
|
|
2828
|
+
var import_chalk11 = __toESM(require("chalk"), 1);
|
|
2790
2829
|
|
|
2791
2830
|
// src/utils/spawn-async.ts
|
|
2792
2831
|
var import_node_child_process4 = require("child_process");
|
|
@@ -2841,9 +2880,9 @@ function displayMissingPrereqs(prereqs) {
|
|
|
2841
2880
|
const missing = prereqs.filter((p) => !p.installed);
|
|
2842
2881
|
for (const m of missing) {
|
|
2843
2882
|
const suffix = m.affectedPackages ? ` \u2014 needed for coverage in: ${m.affectedPackages.join(", ")}` : ` \u2014 ${m.reason}`;
|
|
2844
|
-
console.log(` ${
|
|
2883
|
+
console.log(` ${import_chalk11.default.yellow("!")} ${m.label} not installed${suffix}`);
|
|
2845
2884
|
if (m.installCommand) {
|
|
2846
|
-
console.log(` Install: ${
|
|
2885
|
+
console.log(` Install: ${import_chalk11.default.cyan(m.installCommand)}`);
|
|
2847
2886
|
}
|
|
2848
2887
|
}
|
|
2849
2888
|
}
|
|
@@ -3168,7 +3207,7 @@ async function handleIntegrations(state, opts) {
|
|
|
3168
3207
|
}
|
|
3169
3208
|
|
|
3170
3209
|
// src/utils/prompt-main-menu-hints.ts
|
|
3171
|
-
var
|
|
3210
|
+
var import_chalk12 = __toESM(require("chalk"), 1);
|
|
3172
3211
|
function fileLimitsHint(config) {
|
|
3173
3212
|
const max = config.rules.maxFileLines;
|
|
3174
3213
|
const test = config.rules.maxTestFileLines;
|
|
@@ -3187,7 +3226,7 @@ function fileNamingHint(config, scanResult) {
|
|
|
3187
3226
|
return "mixed \u2014 will not enforce if skipped";
|
|
3188
3227
|
}
|
|
3189
3228
|
function fileNamingStatus(config) {
|
|
3190
|
-
if (!config.rules.enforceNaming) return "
|
|
3229
|
+
if (!config.rules.enforceNaming) return "unconfigured";
|
|
3191
3230
|
const rootPkg = getRootPackage(config.packages);
|
|
3192
3231
|
return rootPkg.conventions?.fileNaming ? "ok" : "needs-input";
|
|
3193
3232
|
}
|
|
@@ -3213,24 +3252,28 @@ function coverageHint(config, hasTestRunner) {
|
|
|
3213
3252
|
}
|
|
3214
3253
|
function advancedNamingHint(config) {
|
|
3215
3254
|
const rootPkg = getRootPackage(config.packages);
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3255
|
+
if (!config.rules.enforceNaming) return "not enforced";
|
|
3256
|
+
const ok = import_chalk12.default.green("\u2713");
|
|
3257
|
+
const no = import_chalk12.default.dim("\u2717");
|
|
3258
|
+
const parts = [
|
|
3259
|
+
`${rootPkg.conventions?.fileNaming ? ok : no} file naming`,
|
|
3260
|
+
`${rootPkg.conventions?.componentNaming ? ok : no} components`,
|
|
3261
|
+
`${rootPkg.conventions?.hookNaming ? ok : no} hooks`,
|
|
3262
|
+
`${rootPkg.conventions?.importAlias ? ok : no} alias`
|
|
3263
|
+
];
|
|
3264
|
+
return parts.join(import_chalk12.default.dim(", "));
|
|
3222
3265
|
}
|
|
3223
3266
|
function integrationsHint(state) {
|
|
3224
3267
|
if (!state.visited.integrations || !state.integrations)
|
|
3225
3268
|
return "not configured \u2014 select to set up";
|
|
3226
3269
|
const items = [];
|
|
3227
|
-
if (state.integrations.preCommitHook) items.push("pre-commit");
|
|
3228
|
-
if (state.integrations.typecheckHook) items.push("typecheck");
|
|
3229
|
-
if (state.integrations.lintHook) items.push("lint");
|
|
3230
|
-
if (state.integrations.claudeCodeHook) items.push("Claude");
|
|
3231
|
-
if (state.integrations.claudeMdRef) items.push("CLAUDE.md");
|
|
3232
|
-
if (state.integrations.githubAction) items.push("CI");
|
|
3233
|
-
return items.length > 0 ? items.join(" \xB7 ") : "none selected";
|
|
3270
|
+
if (state.integrations.preCommitHook) items.push(import_chalk12.default.green("pre-commit"));
|
|
3271
|
+
if (state.integrations.typecheckHook) items.push(import_chalk12.default.green("typecheck"));
|
|
3272
|
+
if (state.integrations.lintHook) items.push(import_chalk12.default.green("lint"));
|
|
3273
|
+
if (state.integrations.claudeCodeHook) items.push(import_chalk12.default.green("Claude"));
|
|
3274
|
+
if (state.integrations.claudeMdRef) items.push(import_chalk12.default.green("CLAUDE.md"));
|
|
3275
|
+
if (state.integrations.githubAction) items.push(import_chalk12.default.green("CI"));
|
|
3276
|
+
return items.length > 0 ? items.join(import_chalk12.default.dim(" \xB7 ")) : "none selected";
|
|
3234
3277
|
}
|
|
3235
3278
|
function packageOverridesHint(config) {
|
|
3236
3279
|
const rootNaming = getRootPackage(config.packages).conventions?.fileNaming;
|
|
@@ -3249,9 +3292,15 @@ function boundariesHint(config, state) {
|
|
|
3249
3292
|
return `${ruleCount} rules across ${pkgCount} packages`;
|
|
3250
3293
|
}
|
|
3251
3294
|
function advancedNamingStatus(config) {
|
|
3295
|
+
if (!config.rules.enforceNaming) return "unconfigured";
|
|
3252
3296
|
const rootPkg = getRootPackage(config.packages);
|
|
3253
|
-
const
|
|
3254
|
-
|
|
3297
|
+
const hasFile = !!rootPkg.conventions?.fileNaming;
|
|
3298
|
+
const hasComp = !!rootPkg.conventions?.componentNaming;
|
|
3299
|
+
const hasHook = !!rootPkg.conventions?.hookNaming;
|
|
3300
|
+
const hasAlias = !!rootPkg.conventions?.importAlias;
|
|
3301
|
+
if (hasFile && hasComp && hasHook && hasAlias) return "ok";
|
|
3302
|
+
if (hasFile || hasComp || hasHook || hasAlias) return "partial";
|
|
3303
|
+
return "unconfigured";
|
|
3255
3304
|
}
|
|
3256
3305
|
function packageOverridesStatus(config) {
|
|
3257
3306
|
const rootNaming = getRootPackage(config.packages).conventions?.fileNaming;
|
|
@@ -3262,15 +3311,15 @@ function packageOverridesStatus(config) {
|
|
|
3262
3311
|
return customized ? "ok" : "unconfigured";
|
|
3263
3312
|
}
|
|
3264
3313
|
function statusIcon(status) {
|
|
3265
|
-
if (status === "ok") return
|
|
3266
|
-
if (status === "needs-input") return
|
|
3267
|
-
if (status === "unconfigured") return
|
|
3268
|
-
return
|
|
3314
|
+
if (status === "ok") return import_chalk12.default.green("\u2713");
|
|
3315
|
+
if (status === "needs-input") return import_chalk12.default.yellow("?");
|
|
3316
|
+
if (status === "unconfigured") return import_chalk12.default.dim("-");
|
|
3317
|
+
return import_chalk12.default.yellow("~");
|
|
3269
3318
|
}
|
|
3270
3319
|
function buildMainMenuOptions(config, scanResult, state) {
|
|
3271
3320
|
const namingStatus = fileNamingStatus(config);
|
|
3272
|
-
const coverageStatus = config.rules.testCoverage === 0 ? "
|
|
3273
|
-
const missingTestsStatus = config.rules.enforceMissingTests ? "ok" : "
|
|
3321
|
+
const coverageStatus = config.rules.testCoverage === 0 ? "unconfigured" : !state.hasTestRunner ? "partial" : "ok";
|
|
3322
|
+
const missingTestsStatus = config.rules.enforceMissingTests ? "ok" : "unconfigured";
|
|
3274
3323
|
const options = [
|
|
3275
3324
|
{
|
|
3276
3325
|
value: "fileLimits",
|
|
@@ -3316,7 +3365,7 @@ function buildMainMenuOptions(config, scanResult, state) {
|
|
|
3316
3365
|
options.push(
|
|
3317
3366
|
{ value: "integrations", label: `${iIcon} Integrations`, hint: integrationsHint(state) },
|
|
3318
3367
|
{ value: "reset", label: " Reset all to defaults" },
|
|
3319
|
-
{ value: "review", label: " Review scan details" },
|
|
3368
|
+
{ value: "review", label: " Review scan details", hint: "detected stack & conventions" },
|
|
3320
3369
|
{ value: "done", label: " Done \u2014 write config" }
|
|
3321
3370
|
);
|
|
3322
3371
|
return options;
|
|
@@ -3396,7 +3445,7 @@ function updateGitignore(projectRoot) {
|
|
|
3396
3445
|
// src/commands/init-hooks.ts
|
|
3397
3446
|
var fs18 = __toESM(require("fs"), 1);
|
|
3398
3447
|
var path18 = __toESM(require("path"), 1);
|
|
3399
|
-
var
|
|
3448
|
+
var import_chalk13 = __toESM(require("chalk"), 1);
|
|
3400
3449
|
var import_yaml = require("yaml");
|
|
3401
3450
|
|
|
3402
3451
|
// src/commands/resolve-typecheck.ts
|
|
@@ -3441,13 +3490,13 @@ function setupPreCommitHook(projectRoot) {
|
|
|
3441
3490
|
const lefthookPath = path18.join(projectRoot, "lefthook.yml");
|
|
3442
3491
|
if (fs18.existsSync(lefthookPath)) {
|
|
3443
3492
|
addLefthookPreCommit(lefthookPath);
|
|
3444
|
-
console.log(` ${
|
|
3493
|
+
console.log(` ${import_chalk13.default.green("\u2713")} lefthook.yml \u2014 added viberails pre-commit`);
|
|
3445
3494
|
return "lefthook.yml";
|
|
3446
3495
|
}
|
|
3447
3496
|
const huskyDir = path18.join(projectRoot, ".husky");
|
|
3448
3497
|
if (fs18.existsSync(huskyDir)) {
|
|
3449
3498
|
writeHuskyPreCommit(huskyDir);
|
|
3450
|
-
console.log(` ${
|
|
3499
|
+
console.log(` ${import_chalk13.default.green("\u2713")} .husky/pre-commit \u2014 added viberails check`);
|
|
3451
3500
|
return ".husky/pre-commit";
|
|
3452
3501
|
}
|
|
3453
3502
|
const gitDir = path18.join(projectRoot, ".git");
|
|
@@ -3457,7 +3506,7 @@ function setupPreCommitHook(projectRoot) {
|
|
|
3457
3506
|
fs18.mkdirSync(hooksDir, { recursive: true });
|
|
3458
3507
|
}
|
|
3459
3508
|
writeGitHookPreCommit(hooksDir);
|
|
3460
|
-
console.log(` ${
|
|
3509
|
+
console.log(` ${import_chalk13.default.green("\u2713")} .git/hooks/pre-commit`);
|
|
3461
3510
|
return ".git/hooks/pre-commit";
|
|
3462
3511
|
}
|
|
3463
3512
|
return void 0;
|
|
@@ -3518,9 +3567,9 @@ function setupClaudeCodeHook(projectRoot) {
|
|
|
3518
3567
|
settings = JSON.parse(fs18.readFileSync(settingsPath, "utf-8"));
|
|
3519
3568
|
} catch {
|
|
3520
3569
|
console.warn(
|
|
3521
|
-
` ${
|
|
3570
|
+
` ${import_chalk13.default.yellow("!")} .claude/settings.json contains invalid JSON \u2014 skipping hook setup`
|
|
3522
3571
|
);
|
|
3523
|
-
console.warn(` Fix the JSON manually, then re-run ${
|
|
3572
|
+
console.warn(` Fix the JSON manually, then re-run ${import_chalk13.default.cyan("viberails init --force")}`);
|
|
3524
3573
|
return;
|
|
3525
3574
|
}
|
|
3526
3575
|
}
|
|
@@ -3543,7 +3592,7 @@ function setupClaudeCodeHook(projectRoot) {
|
|
|
3543
3592
|
settings.hooks = hooks;
|
|
3544
3593
|
fs18.writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}
|
|
3545
3594
|
`);
|
|
3546
|
-
console.log(` ${
|
|
3595
|
+
console.log(` ${import_chalk13.default.green("\u2713")} .claude/settings.json \u2014 added viberails PostToolUse hook`);
|
|
3547
3596
|
}
|
|
3548
3597
|
function setupClaudeMdReference(projectRoot) {
|
|
3549
3598
|
const claudeMdPath = path18.join(projectRoot, "CLAUDE.md");
|
|
@@ -3555,7 +3604,7 @@ function setupClaudeMdReference(projectRoot) {
|
|
|
3555
3604
|
const ref = "\n@.viberails/context.md\n";
|
|
3556
3605
|
const prefix = content.length === 0 ? "" : content.trimEnd();
|
|
3557
3606
|
fs18.writeFileSync(claudeMdPath, prefix + ref);
|
|
3558
|
-
console.log(` ${
|
|
3607
|
+
console.log(` ${import_chalk13.default.green("\u2713")} CLAUDE.md \u2014 added @.viberails/context.md reference`);
|
|
3559
3608
|
}
|
|
3560
3609
|
function setupGithubAction(projectRoot, packageManager, options) {
|
|
3561
3610
|
const workflowDir = path18.join(projectRoot, ".github", "workflows");
|
|
@@ -3641,7 +3690,7 @@ ${cmd}
|
|
|
3641
3690
|
// src/commands/init-hooks-extra.ts
|
|
3642
3691
|
var fs19 = __toESM(require("fs"), 1);
|
|
3643
3692
|
var path19 = __toESM(require("path"), 1);
|
|
3644
|
-
var
|
|
3693
|
+
var import_chalk14 = __toESM(require("chalk"), 1);
|
|
3645
3694
|
var import_yaml2 = require("yaml");
|
|
3646
3695
|
function addPreCommitStep(projectRoot, name, command, marker, lefthookExtra) {
|
|
3647
3696
|
const lefthookPath = path19.join(projectRoot, "lefthook.yml");
|
|
@@ -3701,12 +3750,12 @@ ${command}
|
|
|
3701
3750
|
function setupTypecheckHook(projectRoot, packageManager) {
|
|
3702
3751
|
const resolved = resolveTypecheckCommand(projectRoot, packageManager);
|
|
3703
3752
|
if (!resolved.command) {
|
|
3704
|
-
console.log(` ${
|
|
3753
|
+
console.log(` ${import_chalk14.default.yellow("!")} Skipped typecheck hook: ${resolved.reason}`);
|
|
3705
3754
|
return void 0;
|
|
3706
3755
|
}
|
|
3707
3756
|
const target = addPreCommitStep(projectRoot, "typecheck", resolved.command, "typecheck");
|
|
3708
3757
|
if (target) {
|
|
3709
|
-
console.log(` ${
|
|
3758
|
+
console.log(` ${import_chalk14.default.green("\u2713")} ${target} \u2014 added typecheck (${resolved.label})`);
|
|
3710
3759
|
}
|
|
3711
3760
|
return target;
|
|
3712
3761
|
}
|
|
@@ -3727,7 +3776,7 @@ function setupLintHook(projectRoot, linter) {
|
|
|
3727
3776
|
}
|
|
3728
3777
|
const target = addPreCommitStep(projectRoot, "lint", command, linter, lefthookExtra);
|
|
3729
3778
|
if (target) {
|
|
3730
|
-
console.log(` ${
|
|
3779
|
+
console.log(` ${import_chalk14.default.green("\u2713")} ${target} \u2014 added ${linterName} lint check`);
|
|
3731
3780
|
}
|
|
3732
3781
|
return target;
|
|
3733
3782
|
}
|
|
@@ -3736,7 +3785,7 @@ function setupSelectedIntegrations(projectRoot, integrations, opts) {
|
|
|
3736
3785
|
if (integrations.preCommitHook) {
|
|
3737
3786
|
const t = setupPreCommitHook(projectRoot);
|
|
3738
3787
|
if (t && opts.lefthookExpected && !t.includes("lefthook")) {
|
|
3739
|
-
console.log(` ${
|
|
3788
|
+
console.log(` ${import_chalk14.default.yellow("!")} Lefthook install failed \u2014 fell back to ${t}`);
|
|
3740
3789
|
}
|
|
3741
3790
|
created.push(t ? `${t} \u2014 added viberails pre-commit` : "pre-commit hook skipped");
|
|
3742
3791
|
}
|
|
@@ -3772,7 +3821,7 @@ var path20 = __toESM(require("path"), 1);
|
|
|
3772
3821
|
var clack12 = __toESM(require("@clack/prompts"), 1);
|
|
3773
3822
|
var import_config8 = require("@viberails/config");
|
|
3774
3823
|
var import_scanner2 = require("@viberails/scanner");
|
|
3775
|
-
var
|
|
3824
|
+
var import_chalk15 = __toESM(require("chalk"), 1);
|
|
3776
3825
|
|
|
3777
3826
|
// src/utils/filter-confidence.ts
|
|
3778
3827
|
function filterHighConfidence(conventions, meta) {
|
|
@@ -3808,7 +3857,7 @@ async function initNonInteractive(projectRoot, configPath) {
|
|
|
3808
3857
|
const exempted = getExemptedPackages(config);
|
|
3809
3858
|
if (exempted.length > 0) {
|
|
3810
3859
|
console.log(
|
|
3811
|
-
` ${
|
|
3860
|
+
` ${import_chalk15.default.dim("Auto-exempted from coverage:")} ${exempted.join(", ")} ${import_chalk15.default.dim("(types-only)")}`
|
|
3812
3861
|
);
|
|
3813
3862
|
}
|
|
3814
3863
|
if (config.packages.length > 1) {
|
|
@@ -3845,14 +3894,14 @@ async function initNonInteractive(projectRoot, configPath) {
|
|
|
3845
3894
|
const hookManager = detectHookManager(projectRoot);
|
|
3846
3895
|
const hasHookManager = hookManager === "Lefthook" || hookManager === "Husky";
|
|
3847
3896
|
const preCommitTarget = hasHookManager ? setupPreCommitHook(projectRoot) : void 0;
|
|
3848
|
-
const ok =
|
|
3897
|
+
const ok = import_chalk15.default.green("\u2713");
|
|
3849
3898
|
const created = [
|
|
3850
3899
|
`${ok} ${path20.basename(configPath)}`,
|
|
3851
3900
|
`${ok} .viberails/context.md`,
|
|
3852
3901
|
`${ok} .viberails/scan-result.json`,
|
|
3853
3902
|
`${ok} .claude/settings.json \u2014 added viberails hook`,
|
|
3854
3903
|
`${ok} CLAUDE.md \u2014 added @.viberails/context.md reference`,
|
|
3855
|
-
preCommitTarget ? `${ok} ${preCommitTarget}` : `${
|
|
3904
|
+
preCommitTarget ? `${ok} ${preCommitTarget}` : `${import_chalk15.default.yellow("!")} pre-commit hook skipped (install lefthook or husky)`,
|
|
3856
3905
|
actionTarget ? `${ok} ${actionTarget} \u2014 blocks PRs on violations` : ""
|
|
3857
3906
|
].filter(Boolean);
|
|
3858
3907
|
if (hasHookManager && isTypeScript) setupTypecheckHook(projectRoot, rootPkgPm);
|
|
@@ -3877,8 +3926,8 @@ async function initCommand(options, cwd) {
|
|
|
3877
3926
|
return initInteractive(projectRoot, configPath, options);
|
|
3878
3927
|
}
|
|
3879
3928
|
console.log(
|
|
3880
|
-
`${
|
|
3881
|
-
Run ${
|
|
3929
|
+
`${import_chalk16.default.yellow("!")} viberails is already initialized.
|
|
3930
|
+
Run ${import_chalk16.default.cyan("viberails")} to review or edit the existing setup, ${import_chalk16.default.cyan("viberails sync")} to update generated files, or ${import_chalk16.default.cyan("viberails init --force")} to replace it.`
|
|
3882
3931
|
);
|
|
3883
3932
|
return;
|
|
3884
3933
|
}
|
|
@@ -3919,11 +3968,6 @@ async function initInteractive(projectRoot, configPath, options) {
|
|
|
3919
3968
|
);
|
|
3920
3969
|
}
|
|
3921
3970
|
const hasTestRunner = !!scanResult.stack.testRunner;
|
|
3922
|
-
if (!hasTestRunner) {
|
|
3923
|
-
clack13.log.info(
|
|
3924
|
-
"No test runner detected. Coverage checks are inactive until a test runner is installed.\nInstall a test runner (e.g. vitest) and re-run viberails init."
|
|
3925
|
-
);
|
|
3926
|
-
}
|
|
3927
3971
|
const hookManager = detectHookManager(projectRoot);
|
|
3928
3972
|
const coveragePrereqs = checkCoveragePrereqs(projectRoot, scanResult);
|
|
3929
3973
|
const rootPkgStack = (config.packages.find((p) => p.path === ".") ?? config.packages[0])?.stack;
|
|
@@ -3955,7 +3999,7 @@ async function initInteractive(projectRoot, configPath, options) {
|
|
|
3955
3999
|
writeGeneratedFiles(projectRoot, config, scanResult);
|
|
3956
4000
|
updateGitignore(projectRoot);
|
|
3957
4001
|
ws.stop("Configuration written");
|
|
3958
|
-
const ok =
|
|
4002
|
+
const ok = import_chalk16.default.green("\u2713");
|
|
3959
4003
|
clack13.log.step(`${ok} ${path21.basename(configPath)}`);
|
|
3960
4004
|
clack13.log.step(`${ok} .viberails/context.md`);
|
|
3961
4005
|
clack13.log.step(`${ok} .viberails/scan-result.json`);
|
|
@@ -3969,7 +4013,7 @@ async function initInteractive(projectRoot, configPath, options) {
|
|
|
3969
4013
|
}
|
|
3970
4014
|
clack13.outro(
|
|
3971
4015
|
`Done! Next: review viberails.config.json, then run viberails check
|
|
3972
|
-
${
|
|
4016
|
+
${import_chalk16.default.dim("Tip: use")} ${import_chalk16.default.cyan("viberails check --enforce")} ${import_chalk16.default.dim("in CI to block PRs on violations.")}`
|
|
3973
4017
|
);
|
|
3974
4018
|
}
|
|
3975
4019
|
|
|
@@ -3979,7 +4023,7 @@ var path22 = __toESM(require("path"), 1);
|
|
|
3979
4023
|
var clack14 = __toESM(require("@clack/prompts"), 1);
|
|
3980
4024
|
var import_config11 = require("@viberails/config");
|
|
3981
4025
|
var import_scanner4 = require("@viberails/scanner");
|
|
3982
|
-
var
|
|
4026
|
+
var import_chalk17 = __toESM(require("chalk"), 1);
|
|
3983
4027
|
var CONFIG_FILE6 = "viberails.config.json";
|
|
3984
4028
|
var SCAN_RESULT_FILE2 = ".viberails/scan-result.json";
|
|
3985
4029
|
function loadPreviousStats(projectRoot) {
|
|
@@ -4020,13 +4064,13 @@ async function syncCommand(options, cwd) {
|
|
|
4020
4064
|
const statsDelta = previousStats ? formatStatsDelta(previousStats, scanResult.statistics) : void 0;
|
|
4021
4065
|
if (changes.length > 0 || statsDelta) {
|
|
4022
4066
|
console.log(`
|
|
4023
|
-
${
|
|
4067
|
+
${import_chalk17.default.bold("Changes:")}`);
|
|
4024
4068
|
for (const change of changes) {
|
|
4025
|
-
const icon = change.type === "removed" ?
|
|
4069
|
+
const icon = change.type === "removed" ? import_chalk17.default.red("-") : import_chalk17.default.green("+");
|
|
4026
4070
|
console.log(` ${icon} ${change.description}`);
|
|
4027
4071
|
}
|
|
4028
4072
|
if (statsDelta) {
|
|
4029
|
-
console.log(` ${
|
|
4073
|
+
console.log(` ${import_chalk17.default.dim(statsDelta)}`);
|
|
4030
4074
|
}
|
|
4031
4075
|
}
|
|
4032
4076
|
if (options?.interactive) {
|
|
@@ -4075,18 +4119,18 @@ ${import_chalk15.default.bold("Changes:")}`);
|
|
|
4075
4119
|
`);
|
|
4076
4120
|
writeGeneratedFiles(projectRoot, merged, scanResult);
|
|
4077
4121
|
console.log(`
|
|
4078
|
-
${
|
|
4122
|
+
${import_chalk17.default.bold("Synced:")}`);
|
|
4079
4123
|
if (configChanged) {
|
|
4080
|
-
console.log(` ${
|
|
4124
|
+
console.log(` ${import_chalk17.default.yellow("!")} ${CONFIG_FILE6} \u2014 updated (review changes)`);
|
|
4081
4125
|
} else {
|
|
4082
|
-
console.log(` ${
|
|
4126
|
+
console.log(` ${import_chalk17.default.green("\u2713")} ${CONFIG_FILE6} \u2014 unchanged`);
|
|
4083
4127
|
}
|
|
4084
|
-
console.log(` ${
|
|
4085
|
-
console.log(` ${
|
|
4128
|
+
console.log(` ${import_chalk17.default.green("\u2713")} .viberails/context.md \u2014 regenerated`);
|
|
4129
|
+
console.log(` ${import_chalk17.default.green("\u2713")} .viberails/scan-result.json \u2014 updated`);
|
|
4086
4130
|
}
|
|
4087
4131
|
|
|
4088
4132
|
// src/index.ts
|
|
4089
|
-
var VERSION = "0.6.
|
|
4133
|
+
var VERSION = "0.6.9";
|
|
4090
4134
|
var program = new import_commander.Command();
|
|
4091
4135
|
program.name("viberails").description("Guardrails for vibe coding").version(VERSION);
|
|
4092
4136
|
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) => {
|
|
@@ -4094,7 +4138,7 @@ program.command("init", { isDefault: true }).description("Scan your project and
|
|
|
4094
4138
|
await initCommand(options);
|
|
4095
4139
|
} catch (err) {
|
|
4096
4140
|
const message = err instanceof Error ? err.message : String(err);
|
|
4097
|
-
console.error(`${
|
|
4141
|
+
console.error(`${import_chalk18.default.red("Error:")} ${message}`);
|
|
4098
4142
|
process.exit(1);
|
|
4099
4143
|
}
|
|
4100
4144
|
});
|
|
@@ -4103,7 +4147,7 @@ program.command("sync").description("Re-scan and update generated files").option
|
|
|
4103
4147
|
await syncCommand(options);
|
|
4104
4148
|
} catch (err) {
|
|
4105
4149
|
const message = err instanceof Error ? err.message : String(err);
|
|
4106
|
-
console.error(`${
|
|
4150
|
+
console.error(`${import_chalk18.default.red("Error:")} ${message}`);
|
|
4107
4151
|
process.exit(1);
|
|
4108
4152
|
}
|
|
4109
4153
|
});
|
|
@@ -4112,7 +4156,7 @@ program.command("config").description("Interactively edit existing config rules"
|
|
|
4112
4156
|
await configCommand(options);
|
|
4113
4157
|
} catch (err) {
|
|
4114
4158
|
const message = err instanceof Error ? err.message : String(err);
|
|
4115
|
-
console.error(`${
|
|
4159
|
+
console.error(`${import_chalk18.default.red("Error:")} ${message}`);
|
|
4116
4160
|
process.exit(1);
|
|
4117
4161
|
}
|
|
4118
4162
|
});
|
|
@@ -4133,7 +4177,7 @@ program.command("check").description("Check files against enforced rules").optio
|
|
|
4133
4177
|
process.exit(exitCode);
|
|
4134
4178
|
} catch (err) {
|
|
4135
4179
|
const message = err instanceof Error ? err.message : String(err);
|
|
4136
|
-
console.error(`${
|
|
4180
|
+
console.error(`${import_chalk18.default.red("Error:")} ${message}`);
|
|
4137
4181
|
process.exit(1);
|
|
4138
4182
|
}
|
|
4139
4183
|
}
|
|
@@ -4144,7 +4188,7 @@ program.command("fix").description("Auto-fix file naming violations and generate
|
|
|
4144
4188
|
process.exit(exitCode);
|
|
4145
4189
|
} catch (err) {
|
|
4146
4190
|
const message = err instanceof Error ? err.message : String(err);
|
|
4147
|
-
console.error(`${
|
|
4191
|
+
console.error(`${import_chalk18.default.red("Error:")} ${message}`);
|
|
4148
4192
|
process.exit(1);
|
|
4149
4193
|
}
|
|
4150
4194
|
});
|
|
@@ -4153,7 +4197,7 @@ program.command("boundaries").description("Display, infer, or inspect import bou
|
|
|
4153
4197
|
await boundariesCommand(options);
|
|
4154
4198
|
} catch (err) {
|
|
4155
4199
|
const message = err instanceof Error ? err.message : String(err);
|
|
4156
|
-
console.error(`${
|
|
4200
|
+
console.error(`${import_chalk18.default.red("Error:")} ${message}`);
|
|
4157
4201
|
process.exit(1);
|
|
4158
4202
|
}
|
|
4159
4203
|
});
|