@staff0rd/assist 0.111.0 → 0.112.0
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.js +683 -669
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.112.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -67,6 +67,7 @@ var package_default = {
|
|
|
67
67
|
jotai: "^2.18.0",
|
|
68
68
|
jscpd: "^4.0.5",
|
|
69
69
|
knip: "^5.71.0",
|
|
70
|
+
madge: "^8.0.0",
|
|
70
71
|
marked: "^15.0.12",
|
|
71
72
|
react: "^19.2.4",
|
|
72
73
|
"react-dom": "^19.2.4",
|
|
@@ -89,10 +90,10 @@ import { stringify as stringifyYaml } from "yaml";
|
|
|
89
90
|
// src/shared/loadRawYaml.ts
|
|
90
91
|
import { existsSync, readFileSync } from "fs";
|
|
91
92
|
import { parse as parseYaml } from "yaml";
|
|
92
|
-
function loadRawYaml(
|
|
93
|
-
if (!existsSync(
|
|
93
|
+
function loadRawYaml(path42) {
|
|
94
|
+
if (!existsSync(path42)) return {};
|
|
94
95
|
try {
|
|
95
|
-
const content = readFileSync(
|
|
96
|
+
const content = readFileSync(path42, "utf-8");
|
|
96
97
|
return parseYaml(content) || {};
|
|
97
98
|
} catch {
|
|
98
99
|
return {};
|
|
@@ -330,9 +331,9 @@ function isTraversable(value) {
|
|
|
330
331
|
function stepInto(current, key) {
|
|
331
332
|
return isTraversable(current) ? current[key] : void 0;
|
|
332
333
|
}
|
|
333
|
-
function getNestedValue(obj,
|
|
334
|
+
function getNestedValue(obj, path42) {
|
|
334
335
|
let current = obj;
|
|
335
|
-
for (const key of
|
|
336
|
+
for (const key of path42.split(".")) current = stepInto(current, key);
|
|
336
337
|
return current;
|
|
337
338
|
}
|
|
338
339
|
|
|
@@ -373,8 +374,8 @@ function stepIntoNested(container, key, nextKey) {
|
|
|
373
374
|
}
|
|
374
375
|
return ensureObject(container, resolved);
|
|
375
376
|
}
|
|
376
|
-
function setNestedValue(obj,
|
|
377
|
-
const keys =
|
|
377
|
+
function setNestedValue(obj, path42, value) {
|
|
378
|
+
const keys = path42.split(".");
|
|
378
379
|
const result = { ...obj };
|
|
379
380
|
let current = result;
|
|
380
381
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -443,7 +444,7 @@ function configList() {
|
|
|
443
444
|
}
|
|
444
445
|
|
|
445
446
|
// src/commands/verify/init/index.ts
|
|
446
|
-
import
|
|
447
|
+
import chalk17 from "chalk";
|
|
447
448
|
|
|
448
449
|
// src/shared/promptMultiselect.ts
|
|
449
450
|
import chalk3 from "chalk";
|
|
@@ -513,28 +514,12 @@ function findPackageJsonWithVerifyScripts(startDir) {
|
|
|
513
514
|
}
|
|
514
515
|
}
|
|
515
516
|
|
|
516
|
-
// src/commands/verify/setup/expectedScripts.ts
|
|
517
|
-
var expectedScripts = {
|
|
518
|
-
"verify:knip": "knip --no-progress --treat-config-hints-as-errors",
|
|
519
|
-
"verify:lint": "biome check --write --error-on-warnings .",
|
|
520
|
-
"verify:duplicate-code": "jscpd --format 'typescript,tsx' --exitCode 1 --ignore '**/*.test.*' -r consoleFull src",
|
|
521
|
-
"verify:test": "vitest run --reporter=dot --silent",
|
|
522
|
-
"verify:hardcoded-colors": "assist verify hardcoded-colors",
|
|
523
|
-
"verify:no-venv": "assist verify no-venv",
|
|
524
|
-
"verify:maintainability": "assist complexity maintainability ./src --threshold 60",
|
|
525
|
-
"verify:madge": "madge --circular --ts-config ./tsconfig.json --extensions ts,tsx src/"
|
|
526
|
-
};
|
|
527
|
-
|
|
528
|
-
// src/commands/verify/setup/setupBuild.ts
|
|
529
|
-
import chalk6 from "chalk";
|
|
530
|
-
|
|
531
517
|
// src/commands/verify/installPackage.ts
|
|
532
518
|
import { execSync as execSync2 } from "child_process";
|
|
533
|
-
import
|
|
534
|
-
import * as path2 from "path";
|
|
519
|
+
import { writeFileSync as writeFileSync2 } from "fs";
|
|
535
520
|
import chalk5 from "chalk";
|
|
536
521
|
function writePackageJson(filePath, pkg) {
|
|
537
|
-
|
|
522
|
+
writeFileSync2(filePath, `${JSON.stringify(pkg, null, 2)}
|
|
538
523
|
`);
|
|
539
524
|
}
|
|
540
525
|
function addScript(pkg, name, command) {
|
|
@@ -556,29 +541,6 @@ function installPackage(name, cwd) {
|
|
|
556
541
|
return false;
|
|
557
542
|
}
|
|
558
543
|
}
|
|
559
|
-
function addToKnipIgnoreBinaries(cwd, binary) {
|
|
560
|
-
const knipJsonPath = path2.join(cwd, "knip.json");
|
|
561
|
-
try {
|
|
562
|
-
let knipConfig;
|
|
563
|
-
if (fs2.existsSync(knipJsonPath)) {
|
|
564
|
-
knipConfig = JSON.parse(fs2.readFileSync(knipJsonPath, "utf-8"));
|
|
565
|
-
} else {
|
|
566
|
-
knipConfig = { $schema: "https://unpkg.com/knip@5/schema.json" };
|
|
567
|
-
}
|
|
568
|
-
const ignoreBinaries = knipConfig.ignoreBinaries ?? [];
|
|
569
|
-
if (!ignoreBinaries.includes(binary)) {
|
|
570
|
-
knipConfig.ignoreBinaries = [...ignoreBinaries, binary];
|
|
571
|
-
fs2.writeFileSync(
|
|
572
|
-
knipJsonPath,
|
|
573
|
-
`${JSON.stringify(knipConfig, null, " ")}
|
|
574
|
-
`
|
|
575
|
-
);
|
|
576
|
-
console.log(chalk5.dim(`Added '${binary}' to knip.json ignoreBinaries`));
|
|
577
|
-
}
|
|
578
|
-
} catch {
|
|
579
|
-
console.log(chalk5.yellow("Warning: Could not update knip.json"));
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
544
|
function setupVerifyScript(packageJsonPath, scriptName, command) {
|
|
583
545
|
writePackageJson(
|
|
584
546
|
packageJsonPath,
|
|
@@ -586,8 +548,43 @@ function setupVerifyScript(packageJsonPath, scriptName, command) {
|
|
|
586
548
|
);
|
|
587
549
|
}
|
|
588
550
|
|
|
551
|
+
// src/commands/verify/setupVerifyRunEntry.ts
|
|
552
|
+
var GLOBAL_COMMANDS = /* @__PURE__ */ new Set(["assist", "npm", "npx", "node"]);
|
|
553
|
+
function buildRunEntry(scriptName, command) {
|
|
554
|
+
const parts = command.split(/\s+/);
|
|
555
|
+
const needsNpx = !GLOBAL_COMMANDS.has(parts[0]);
|
|
556
|
+
const entry = {
|
|
557
|
+
name: scriptName,
|
|
558
|
+
command: needsNpx ? "npx" : parts[0]
|
|
559
|
+
};
|
|
560
|
+
const args = needsNpx ? parts : parts.slice(1);
|
|
561
|
+
if (args.length > 0) entry.args = args;
|
|
562
|
+
return entry;
|
|
563
|
+
}
|
|
564
|
+
function setupVerifyRunEntry(scriptName, command) {
|
|
565
|
+
const config = loadProjectConfig();
|
|
566
|
+
if (!config.run) config.run = [];
|
|
567
|
+
const runList = config.run;
|
|
568
|
+
if (runList.find((r) => r.name === scriptName)) return;
|
|
569
|
+
runList.push(buildRunEntry(scriptName, command));
|
|
570
|
+
saveConfig(config);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// src/commands/verify/setup/expectedScripts.ts
|
|
574
|
+
var expectedScripts = {
|
|
575
|
+
"verify:knip": "knip --no-progress --treat-config-hints-as-errors",
|
|
576
|
+
"verify:lint": "biome check --write --error-on-warnings .",
|
|
577
|
+
"verify:duplicate-code": "jscpd --format 'typescript,tsx' --exitCode 1 --ignore '**/*.test.*' -r consoleFull src",
|
|
578
|
+
"verify:test": "vitest run --reporter=dot --silent",
|
|
579
|
+
"verify:hardcoded-colors": "assist verify hardcoded-colors",
|
|
580
|
+
"verify:no-venv": "assist verify no-venv",
|
|
581
|
+
"verify:maintainability": "assist complexity maintainability ./src --threshold 60",
|
|
582
|
+
"verify:madge": "madge --circular --ts-config ./tsconfig.json --extensions ts,tsx src/"
|
|
583
|
+
};
|
|
584
|
+
|
|
589
585
|
// src/commands/verify/setup/setupBuild.ts
|
|
590
|
-
|
|
586
|
+
import chalk6 from "chalk";
|
|
587
|
+
async function setupBuild(_packageJsonPath, writer, hasVite, hasTypescript) {
|
|
591
588
|
console.log(chalk6.blue("\nSetting up build verification..."));
|
|
592
589
|
let command;
|
|
593
590
|
if (hasVite && hasTypescript) {
|
|
@@ -598,82 +595,96 @@ async function setupBuild(packageJsonPath, hasVite, hasTypescript) {
|
|
|
598
595
|
command = "npm run build";
|
|
599
596
|
}
|
|
600
597
|
console.log(chalk6.dim(`Using: ${command}`));
|
|
601
|
-
|
|
602
|
-
writePackageJson(packageJsonPath, addScript(pkg, "verify:build", command));
|
|
598
|
+
writer("verify:build", command);
|
|
603
599
|
}
|
|
604
|
-
async function setupTypecheck(
|
|
600
|
+
async function setupTypecheck(_packageJsonPath, writer) {
|
|
605
601
|
console.log(chalk6.blue("\nSetting up typecheck verification..."));
|
|
606
602
|
const command = "tsc --noEmit";
|
|
607
603
|
console.log(chalk6.dim(`Using: ${command}`));
|
|
608
|
-
|
|
609
|
-
writePackageJson(
|
|
610
|
-
packageJsonPath,
|
|
611
|
-
addScript(pkg, "verify:typecheck", command)
|
|
612
|
-
);
|
|
604
|
+
writer("verify:typecheck", command);
|
|
613
605
|
}
|
|
614
606
|
|
|
615
607
|
// src/commands/verify/setup/setupDuplicateCode.ts
|
|
616
|
-
import * as
|
|
608
|
+
import * as path2 from "path";
|
|
617
609
|
import chalk7 from "chalk";
|
|
618
|
-
async function setupDuplicateCode(packageJsonPath) {
|
|
610
|
+
async function setupDuplicateCode(packageJsonPath, writer) {
|
|
619
611
|
console.log(chalk7.blue("\nSetting up jscpd..."));
|
|
620
|
-
const cwd =
|
|
612
|
+
const cwd = path2.dirname(packageJsonPath);
|
|
621
613
|
const pkg = readPackageJson(packageJsonPath);
|
|
622
614
|
const hasJscpd = !!pkg.dependencies?.jscpd || !!pkg.devDependencies?.jscpd;
|
|
623
615
|
if (!hasJscpd && !installPackage("jscpd", cwd)) {
|
|
624
616
|
return;
|
|
625
617
|
}
|
|
626
|
-
|
|
627
|
-
packageJsonPath,
|
|
628
|
-
"verify:duplicate-code",
|
|
629
|
-
expectedScripts["verify:duplicate-code"]
|
|
630
|
-
);
|
|
618
|
+
writer("verify:duplicate-code", expectedScripts["verify:duplicate-code"]);
|
|
631
619
|
}
|
|
632
620
|
|
|
633
621
|
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
634
|
-
import * as
|
|
622
|
+
import * as path3 from "path";
|
|
623
|
+
import chalk9 from "chalk";
|
|
624
|
+
|
|
625
|
+
// src/commands/verify/addToKnipIgnoreBinaries.ts
|
|
626
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
627
|
+
import { join as join3 } from "path";
|
|
635
628
|
import chalk8 from "chalk";
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
629
|
+
function loadKnipConfig(knipJsonPath) {
|
|
630
|
+
if (existsSync4(knipJsonPath)) {
|
|
631
|
+
return JSON.parse(readFileSync4(knipJsonPath, "utf-8"));
|
|
632
|
+
}
|
|
633
|
+
return { $schema: "https://unpkg.com/knip@5/schema.json" };
|
|
634
|
+
}
|
|
635
|
+
function addToKnipIgnoreBinaries(cwd, binary) {
|
|
636
|
+
const knipJsonPath = join3(cwd, "knip.json");
|
|
637
|
+
try {
|
|
638
|
+
const knipConfig = loadKnipConfig(knipJsonPath);
|
|
639
|
+
const ignoreBinaries = knipConfig.ignoreBinaries ?? [];
|
|
640
|
+
if (!ignoreBinaries.includes(binary)) {
|
|
641
|
+
knipConfig.ignoreBinaries = [...ignoreBinaries, binary];
|
|
642
|
+
writeFileSync3(
|
|
643
|
+
knipJsonPath,
|
|
644
|
+
`${JSON.stringify(knipConfig, null, " ")}
|
|
645
|
+
`
|
|
646
|
+
);
|
|
647
|
+
console.log(chalk8.dim(`Added '${binary}' to knip.json ignoreBinaries`));
|
|
648
|
+
}
|
|
649
|
+
} catch {
|
|
650
|
+
console.log(chalk8.yellow("Warning: Could not update knip.json"));
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
655
|
+
async function setupHardcodedColors(packageJsonPath, writer, hasOpenColor) {
|
|
656
|
+
console.log(chalk9.blue("\nSetting up hardcoded colors check..."));
|
|
657
|
+
const cwd = path3.dirname(packageJsonPath);
|
|
639
658
|
if (!hasOpenColor) {
|
|
640
659
|
installPackage("open-color", cwd);
|
|
641
660
|
}
|
|
642
661
|
addToKnipIgnoreBinaries(cwd, "assist");
|
|
643
|
-
|
|
644
|
-
packageJsonPath,
|
|
645
|
-
"verify:hardcoded-colors",
|
|
646
|
-
expectedScripts["verify:hardcoded-colors"]
|
|
647
|
-
);
|
|
662
|
+
writer("verify:hardcoded-colors", expectedScripts["verify:hardcoded-colors"]);
|
|
648
663
|
}
|
|
649
664
|
|
|
650
665
|
// src/commands/verify/setup/setupKnip.ts
|
|
651
|
-
import * as
|
|
652
|
-
import
|
|
653
|
-
async function setupKnip(packageJsonPath) {
|
|
654
|
-
console.log(
|
|
655
|
-
const cwd =
|
|
666
|
+
import * as path4 from "path";
|
|
667
|
+
import chalk10 from "chalk";
|
|
668
|
+
async function setupKnip(packageJsonPath, writer) {
|
|
669
|
+
console.log(chalk10.blue("\nSetting up knip..."));
|
|
670
|
+
const cwd = path4.dirname(packageJsonPath);
|
|
656
671
|
const pkg = readPackageJson(packageJsonPath);
|
|
657
672
|
if (!pkg.devDependencies?.knip && !installPackage("knip", cwd)) {
|
|
658
673
|
return;
|
|
659
674
|
}
|
|
660
|
-
|
|
661
|
-
packageJsonPath,
|
|
662
|
-
"verify:knip",
|
|
663
|
-
expectedScripts["verify:knip"]
|
|
664
|
-
);
|
|
675
|
+
writer("verify:knip", expectedScripts["verify:knip"]);
|
|
665
676
|
}
|
|
666
677
|
|
|
667
678
|
// src/commands/verify/setup/setupLint.ts
|
|
668
|
-
import * as
|
|
669
|
-
import
|
|
679
|
+
import * as path5 from "path";
|
|
680
|
+
import chalk13 from "chalk";
|
|
670
681
|
|
|
671
682
|
// src/commands/lint/init.ts
|
|
672
683
|
import { execSync as execSync4 } from "child_process";
|
|
673
|
-
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as
|
|
684
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
674
685
|
import { dirname as dirname5, join as join4 } from "path";
|
|
675
686
|
import { fileURLToPath } from "url";
|
|
676
|
-
import
|
|
687
|
+
import chalk12 from "chalk";
|
|
677
688
|
|
|
678
689
|
// src/shared/promptConfirm.ts
|
|
679
690
|
import enquirer2 from "enquirer";
|
|
@@ -694,7 +705,7 @@ async function promptConfirm(message, initial = true) {
|
|
|
694
705
|
|
|
695
706
|
// src/shared/removeEslint/index.ts
|
|
696
707
|
import { execSync as execSync3 } from "child_process";
|
|
697
|
-
import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as
|
|
708
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
698
709
|
|
|
699
710
|
// src/shared/removeEslint/removeEslintConfigFiles.ts
|
|
700
711
|
import { existsSync as existsSync5, unlinkSync } from "fs";
|
|
@@ -744,7 +755,7 @@ function removeEslintFromPackageJson(options2) {
|
|
|
744
755
|
modified = removeEslintDeps(packageJson.devDependencies) || modified;
|
|
745
756
|
modified = removeEslintScripts(packageJson.scripts, options2) || modified;
|
|
746
757
|
if (modified) {
|
|
747
|
-
|
|
758
|
+
writeFileSync4(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
748
759
|
`);
|
|
749
760
|
console.log("Removed eslint references from package.json");
|
|
750
761
|
}
|
|
@@ -775,7 +786,7 @@ function removeEslintScripts(scripts, options2) {
|
|
|
775
786
|
}
|
|
776
787
|
|
|
777
788
|
// src/utils/printDiff.ts
|
|
778
|
-
import
|
|
789
|
+
import chalk11 from "chalk";
|
|
779
790
|
import * as diff from "diff";
|
|
780
791
|
function normalizeJson(content) {
|
|
781
792
|
try {
|
|
@@ -793,11 +804,11 @@ function printDiff(oldContent, newContent) {
|
|
|
793
804
|
const lines = change.value.replace(/\n$/, "").split("\n");
|
|
794
805
|
for (const line of lines) {
|
|
795
806
|
if (change.added) {
|
|
796
|
-
console.log(
|
|
807
|
+
console.log(chalk11.green(`+ ${line}`));
|
|
797
808
|
} else if (change.removed) {
|
|
798
|
-
console.log(
|
|
809
|
+
console.log(chalk11.red(`- ${line}`));
|
|
799
810
|
} else {
|
|
800
|
-
console.log(
|
|
811
|
+
console.log(chalk11.dim(` ${line}`));
|
|
801
812
|
}
|
|
802
813
|
}
|
|
803
814
|
}
|
|
@@ -831,22 +842,22 @@ async function init() {
|
|
|
831
842
|
console.log("biome.json already has the correct linter config");
|
|
832
843
|
return;
|
|
833
844
|
}
|
|
834
|
-
console.log(
|
|
845
|
+
console.log(chalk12.yellow("\n\u26A0\uFE0F biome.json will be updated:"));
|
|
835
846
|
console.log();
|
|
836
847
|
printDiff(oldContent, newContent);
|
|
837
|
-
const confirm = await promptConfirm(
|
|
848
|
+
const confirm = await promptConfirm(chalk12.red("Update biome.json?"));
|
|
838
849
|
if (!confirm) {
|
|
839
850
|
console.log("Skipped biome.json update");
|
|
840
851
|
return;
|
|
841
852
|
}
|
|
842
|
-
|
|
853
|
+
writeFileSync5(biomeConfigPath, newContent);
|
|
843
854
|
console.log("Updated biome.json with linter config");
|
|
844
855
|
}
|
|
845
856
|
|
|
846
857
|
// src/commands/verify/setup/setupLint.ts
|
|
847
|
-
async function setupLint(packageJsonPath) {
|
|
848
|
-
console.log(
|
|
849
|
-
const cwd =
|
|
858
|
+
async function setupLint(packageJsonPath, writer) {
|
|
859
|
+
console.log(chalk13.blue("\nSetting up biome..."));
|
|
860
|
+
const cwd = path5.dirname(packageJsonPath);
|
|
850
861
|
const pkg = readPackageJson(packageJsonPath);
|
|
851
862
|
if (!pkg.devDependencies?.["@biomejs/biome"]) {
|
|
852
863
|
if (!installPackage("@biomejs/biome", cwd)) {
|
|
@@ -854,59 +865,43 @@ async function setupLint(packageJsonPath) {
|
|
|
854
865
|
}
|
|
855
866
|
}
|
|
856
867
|
await init();
|
|
857
|
-
|
|
858
|
-
packageJsonPath,
|
|
859
|
-
"verify:lint",
|
|
860
|
-
expectedScripts["verify:lint"]
|
|
861
|
-
);
|
|
868
|
+
writer("verify:lint", expectedScripts["verify:lint"]);
|
|
862
869
|
}
|
|
863
870
|
|
|
864
871
|
// src/commands/verify/setup/setupMadge.ts
|
|
865
|
-
import * as
|
|
866
|
-
import
|
|
867
|
-
async function setupMadge(packageJsonPath) {
|
|
868
|
-
console.log(
|
|
869
|
-
const cwd =
|
|
872
|
+
import * as path6 from "path";
|
|
873
|
+
import chalk14 from "chalk";
|
|
874
|
+
async function setupMadge(packageJsonPath, writer) {
|
|
875
|
+
console.log(chalk14.blue("\nSetting up madge..."));
|
|
876
|
+
const cwd = path6.dirname(packageJsonPath);
|
|
870
877
|
const pkg = readPackageJson(packageJsonPath);
|
|
871
878
|
const hasMadge = !!pkg.dependencies?.madge || !!pkg.devDependencies?.madge;
|
|
872
879
|
if (!hasMadge && !installPackage("madge", cwd)) {
|
|
873
880
|
return;
|
|
874
881
|
}
|
|
875
|
-
|
|
876
|
-
packageJsonPath,
|
|
877
|
-
"verify:madge",
|
|
878
|
-
expectedScripts["verify:madge"]
|
|
879
|
-
);
|
|
882
|
+
writer("verify:madge", expectedScripts["verify:madge"]);
|
|
880
883
|
}
|
|
881
884
|
|
|
882
885
|
// src/commands/verify/setup/setupMaintainability.ts
|
|
883
|
-
import * as
|
|
884
|
-
import
|
|
885
|
-
async function setupMaintainability(packageJsonPath) {
|
|
886
|
-
console.log(
|
|
887
|
-
addToKnipIgnoreBinaries(
|
|
888
|
-
|
|
889
|
-
packageJsonPath,
|
|
890
|
-
"verify:maintainability",
|
|
891
|
-
expectedScripts["verify:maintainability"]
|
|
892
|
-
);
|
|
886
|
+
import * as path7 from "path";
|
|
887
|
+
import chalk15 from "chalk";
|
|
888
|
+
async function setupMaintainability(packageJsonPath, writer) {
|
|
889
|
+
console.log(chalk15.blue("\nSetting up maintainability check..."));
|
|
890
|
+
addToKnipIgnoreBinaries(path7.dirname(packageJsonPath), "assist");
|
|
891
|
+
writer("verify:maintainability", expectedScripts["verify:maintainability"]);
|
|
893
892
|
}
|
|
894
893
|
|
|
895
894
|
// src/commands/verify/setup/setupTest.ts
|
|
896
|
-
import * as
|
|
897
|
-
import
|
|
898
|
-
async function setupTest(packageJsonPath) {
|
|
899
|
-
console.log(
|
|
900
|
-
const cwd =
|
|
895
|
+
import * as path8 from "path";
|
|
896
|
+
import chalk16 from "chalk";
|
|
897
|
+
async function setupTest(packageJsonPath, writer) {
|
|
898
|
+
console.log(chalk16.blue("\nSetting up vitest..."));
|
|
899
|
+
const cwd = path8.dirname(packageJsonPath);
|
|
901
900
|
const pkg = readPackageJson(packageJsonPath);
|
|
902
901
|
if (!pkg.devDependencies?.vitest && !installPackage("vitest", cwd)) {
|
|
903
902
|
return;
|
|
904
903
|
}
|
|
905
|
-
|
|
906
|
-
packageJsonPath,
|
|
907
|
-
"verify:test",
|
|
908
|
-
expectedScripts["verify:test"]
|
|
909
|
-
);
|
|
904
|
+
writer("verify:test", expectedScripts["verify:test"]);
|
|
910
905
|
}
|
|
911
906
|
|
|
912
907
|
// src/commands/verify/init/detectExistingSetup/needsSetup.ts
|
|
@@ -924,30 +919,44 @@ function getStatusLabel(status2) {
|
|
|
924
919
|
function hasDep(pkg, name) {
|
|
925
920
|
return !!pkg.dependencies?.[name] || !!pkg.devDependencies?.[name];
|
|
926
921
|
}
|
|
927
|
-
function toolStatus(pkg, scriptName, hasPackage) {
|
|
922
|
+
function toolStatus(pkg, scriptName, hasPackage, configScriptNames) {
|
|
928
923
|
const currentScript = pkg.scripts?.[scriptName];
|
|
924
|
+
const hasConfigEntry = configScriptNames.has(scriptName) || [...configScriptNames].some((n) => n.startsWith(`${scriptName}-`));
|
|
929
925
|
const expectedCommand = expectedScripts[scriptName];
|
|
930
926
|
return {
|
|
931
927
|
hasPackage,
|
|
932
|
-
hasScript: !!currentScript,
|
|
928
|
+
hasScript: !!currentScript || hasConfigEntry,
|
|
933
929
|
isOutdated: !!currentScript && !!expectedCommand && currentScript !== expectedCommand
|
|
934
930
|
};
|
|
935
931
|
}
|
|
936
|
-
function
|
|
937
|
-
const
|
|
932
|
+
function loadConfigScriptNames() {
|
|
933
|
+
const config = loadConfig();
|
|
934
|
+
return new Set((config.run ?? []).map((r) => r.name));
|
|
935
|
+
}
|
|
936
|
+
function buildToolStatuses(pkg, configScriptNames) {
|
|
937
|
+
const status2 = (script, has) => toolStatus(pkg, script, has, configScriptNames);
|
|
938
938
|
return {
|
|
939
939
|
knip: status2("verify:knip", hasDep(pkg, "knip")),
|
|
940
940
|
biome: status2("verify:lint", hasDep(pkg, "@biomejs/biome")),
|
|
941
941
|
jscpd: status2("verify:duplicate-code", hasDep(pkg, "jscpd")),
|
|
942
942
|
test: status2("verify:test", hasDep(pkg, "vitest")),
|
|
943
|
-
hasVite: hasDep(pkg, "vite"),
|
|
944
|
-
hasTypescript: !!pkg.devDependencies?.typescript,
|
|
945
943
|
build: status2("verify:build", true),
|
|
946
944
|
typecheck: status2("verify:typecheck", true),
|
|
947
945
|
hardcodedColors: status2("verify:hardcoded-colors", true),
|
|
948
946
|
madge: status2("verify:madge", hasDep(pkg, "madge")),
|
|
949
|
-
maintainability: status2("verify:maintainability", true)
|
|
950
|
-
|
|
947
|
+
maintainability: status2("verify:maintainability", true)
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
function detectExistingSetup(pkg) {
|
|
951
|
+
const configScriptNames = loadConfigScriptNames();
|
|
952
|
+
return {
|
|
953
|
+
...buildToolStatuses(pkg, configScriptNames),
|
|
954
|
+
hasVite: hasDep(pkg, "vite"),
|
|
955
|
+
hasTypescript: !!pkg.devDependencies?.typescript,
|
|
956
|
+
hasOpenColor: hasDep(pkg, "open-color"),
|
|
957
|
+
hasConfigScripts: [...configScriptNames].some(
|
|
958
|
+
(n) => n.startsWith("verify:")
|
|
959
|
+
)
|
|
951
960
|
};
|
|
952
961
|
}
|
|
953
962
|
|
|
@@ -1035,43 +1044,45 @@ function getAvailableOptions(setup2) {
|
|
|
1035
1044
|
).map((def) => toVerifyOption(def, setup2));
|
|
1036
1045
|
}
|
|
1037
1046
|
|
|
1038
|
-
// src/commands/verify/init/
|
|
1047
|
+
// src/commands/verify/init/getSetupHandlers.ts
|
|
1039
1048
|
function getSetupHandlers(hasVite, hasTypescript, hasOpenColor) {
|
|
1040
1049
|
return {
|
|
1041
|
-
knip: (p) => setupKnip(p),
|
|
1042
|
-
lint: (p) => setupLint(p),
|
|
1043
|
-
"duplicate-code": (p) => setupDuplicateCode(p),
|
|
1044
|
-
test: (p) => setupTest(p),
|
|
1045
|
-
build: (p) => setupBuild(p, hasVite, hasTypescript),
|
|
1046
|
-
typecheck: (p) => setupTypecheck(p),
|
|
1047
|
-
"hardcoded-colors": (p) => setupHardcodedColors(p, hasOpenColor),
|
|
1048
|
-
madge: (p) => setupMadge(p),
|
|
1049
|
-
maintainability: (p) => setupMaintainability(p)
|
|
1050
|
+
knip: (p, w) => setupKnip(p, w),
|
|
1051
|
+
lint: (p, w) => setupLint(p, w),
|
|
1052
|
+
"duplicate-code": (p, w) => setupDuplicateCode(p, w),
|
|
1053
|
+
test: (p, w) => setupTest(p, w),
|
|
1054
|
+
build: (p, w) => setupBuild(p, w, hasVite, hasTypescript),
|
|
1055
|
+
typecheck: (p, w) => setupTypecheck(p, w),
|
|
1056
|
+
"hardcoded-colors": (p, w) => setupHardcodedColors(p, w, hasOpenColor),
|
|
1057
|
+
madge: (p, w) => setupMadge(p, w),
|
|
1058
|
+
maintainability: (p, w) => setupMaintainability(p, w)
|
|
1050
1059
|
};
|
|
1051
1060
|
}
|
|
1052
|
-
|
|
1061
|
+
|
|
1062
|
+
// src/commands/verify/init/index.ts
|
|
1063
|
+
async function runSelectedSetups(selected, packageJsonPath, writer, handlers) {
|
|
1053
1064
|
for (const choice of selected) {
|
|
1054
|
-
await handlers[choice]?.(packageJsonPath);
|
|
1065
|
+
await handlers[choice]?.(packageJsonPath, writer);
|
|
1055
1066
|
}
|
|
1056
|
-
console.log(
|
|
1067
|
+
console.log(chalk17.green(`
|
|
1057
1068
|
Added ${selected.length} verify script(s):`));
|
|
1058
1069
|
for (const choice of selected) {
|
|
1059
|
-
console.log(
|
|
1070
|
+
console.log(chalk17.green(` - verify:${choice}`));
|
|
1060
1071
|
}
|
|
1061
|
-
console.log(
|
|
1072
|
+
console.log(chalk17.dim("\nRun 'assist verify' to run all verify scripts"));
|
|
1062
1073
|
}
|
|
1063
1074
|
async function promptForScripts(availableOptions) {
|
|
1064
1075
|
if (availableOptions.length === 0) {
|
|
1065
|
-
console.log(
|
|
1076
|
+
console.log(chalk17.green("All verify scripts are already configured!"));
|
|
1066
1077
|
return null;
|
|
1067
1078
|
}
|
|
1068
|
-
console.log(
|
|
1079
|
+
console.log(chalk17.bold("Available verify scripts to add:\n"));
|
|
1069
1080
|
const selected = await promptMultiselect(
|
|
1070
1081
|
"Select verify scripts to add:",
|
|
1071
1082
|
availableOptions
|
|
1072
1083
|
);
|
|
1073
1084
|
if (selected.length === 0) {
|
|
1074
|
-
console.log(
|
|
1085
|
+
console.log(chalk17.yellow("No scripts selected"));
|
|
1075
1086
|
return null;
|
|
1076
1087
|
}
|
|
1077
1088
|
return selected;
|
|
@@ -1081,41 +1092,42 @@ async function init2() {
|
|
|
1081
1092
|
const setup2 = detectExistingSetup(pkg);
|
|
1082
1093
|
const selected = await promptForScripts(getAvailableOptions(setup2));
|
|
1083
1094
|
if (!selected) return;
|
|
1095
|
+
const writer = setup2.hasConfigScripts ? setupVerifyRunEntry : (name, cmd) => setupVerifyScript(packageJsonPath, name, cmd);
|
|
1084
1096
|
const handlers = getSetupHandlers(
|
|
1085
1097
|
setup2.hasVite,
|
|
1086
1098
|
setup2.hasTypescript,
|
|
1087
1099
|
setup2.hasOpenColor
|
|
1088
1100
|
);
|
|
1089
|
-
await runSelectedSetups(selected, packageJsonPath, handlers);
|
|
1101
|
+
await runSelectedSetups(selected, packageJsonPath, writer, handlers);
|
|
1090
1102
|
}
|
|
1091
1103
|
|
|
1092
1104
|
// src/commands/vscode/init/index.ts
|
|
1093
|
-
import
|
|
1105
|
+
import chalk19 from "chalk";
|
|
1094
1106
|
|
|
1095
1107
|
// src/commands/vscode/init/createLaunchJson.ts
|
|
1096
|
-
import * as
|
|
1097
|
-
import * as
|
|
1098
|
-
import
|
|
1108
|
+
import * as fs2 from "fs";
|
|
1109
|
+
import * as path9 from "path";
|
|
1110
|
+
import chalk18 from "chalk";
|
|
1099
1111
|
function ensureVscodeFolder() {
|
|
1100
|
-
const vscodeDir =
|
|
1101
|
-
if (!
|
|
1102
|
-
|
|
1103
|
-
console.log(
|
|
1112
|
+
const vscodeDir = path9.join(process.cwd(), ".vscode");
|
|
1113
|
+
if (!fs2.existsSync(vscodeDir)) {
|
|
1114
|
+
fs2.mkdirSync(vscodeDir);
|
|
1115
|
+
console.log(chalk18.dim("Created .vscode folder"));
|
|
1104
1116
|
}
|
|
1105
1117
|
}
|
|
1106
1118
|
function removeVscodeFromGitignore() {
|
|
1107
|
-
const gitignorePath =
|
|
1108
|
-
if (!
|
|
1119
|
+
const gitignorePath = path9.join(process.cwd(), ".gitignore");
|
|
1120
|
+
if (!fs2.existsSync(gitignorePath)) {
|
|
1109
1121
|
return;
|
|
1110
1122
|
}
|
|
1111
|
-
const content =
|
|
1123
|
+
const content = fs2.readFileSync(gitignorePath, "utf-8");
|
|
1112
1124
|
const lines = content.split("\n");
|
|
1113
1125
|
const filteredLines = lines.filter(
|
|
1114
1126
|
(line) => !line.trim().toLowerCase().includes(".vscode")
|
|
1115
1127
|
);
|
|
1116
1128
|
if (filteredLines.length !== lines.length) {
|
|
1117
|
-
|
|
1118
|
-
console.log(
|
|
1129
|
+
fs2.writeFileSync(gitignorePath, filteredLines.join("\n"));
|
|
1130
|
+
console.log(chalk18.dim("Removed .vscode references from .gitignore"));
|
|
1119
1131
|
}
|
|
1120
1132
|
}
|
|
1121
1133
|
function createLaunchJson(type) {
|
|
@@ -1131,10 +1143,10 @@ function createLaunchJson(type) {
|
|
|
1131
1143
|
}
|
|
1132
1144
|
]
|
|
1133
1145
|
};
|
|
1134
|
-
const launchPath =
|
|
1135
|
-
|
|
1146
|
+
const launchPath = path9.join(process.cwd(), ".vscode", "launch.json");
|
|
1147
|
+
fs2.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
|
|
1136
1148
|
`);
|
|
1137
|
-
console.log(
|
|
1149
|
+
console.log(chalk18.green("Created .vscode/launch.json"));
|
|
1138
1150
|
}
|
|
1139
1151
|
function createSettingsJson() {
|
|
1140
1152
|
const settings = {
|
|
@@ -1144,33 +1156,33 @@ function createSettingsJson() {
|
|
|
1144
1156
|
"source.organizeImports.biome": "explicit"
|
|
1145
1157
|
}
|
|
1146
1158
|
};
|
|
1147
|
-
const settingsPath =
|
|
1148
|
-
|
|
1159
|
+
const settingsPath = path9.join(process.cwd(), ".vscode", "settings.json");
|
|
1160
|
+
fs2.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
|
|
1149
1161
|
`);
|
|
1150
|
-
console.log(
|
|
1162
|
+
console.log(chalk18.green("Created .vscode/settings.json"));
|
|
1151
1163
|
}
|
|
1152
1164
|
function createExtensionsJson() {
|
|
1153
1165
|
const extensions = {
|
|
1154
1166
|
recommendations: ["biomejs.biome"]
|
|
1155
1167
|
};
|
|
1156
|
-
const extensionsPath =
|
|
1157
|
-
|
|
1168
|
+
const extensionsPath = path9.join(process.cwd(), ".vscode", "extensions.json");
|
|
1169
|
+
fs2.writeFileSync(
|
|
1158
1170
|
extensionsPath,
|
|
1159
1171
|
`${JSON.stringify(extensions, null, " ")}
|
|
1160
1172
|
`
|
|
1161
1173
|
);
|
|
1162
|
-
console.log(
|
|
1174
|
+
console.log(chalk18.green("Created .vscode/extensions.json"));
|
|
1163
1175
|
}
|
|
1164
1176
|
|
|
1165
1177
|
// src/commands/vscode/init/detectVscodeSetup.ts
|
|
1166
|
-
import * as
|
|
1167
|
-
import * as
|
|
1178
|
+
import * as fs3 from "fs";
|
|
1179
|
+
import * as path10 from "path";
|
|
1168
1180
|
function detectVscodeSetup(pkg) {
|
|
1169
|
-
const vscodeDir =
|
|
1181
|
+
const vscodeDir = path10.join(process.cwd(), ".vscode");
|
|
1170
1182
|
return {
|
|
1171
|
-
hasVscodeFolder:
|
|
1172
|
-
hasLaunchJson:
|
|
1173
|
-
hasSettingsJson:
|
|
1183
|
+
hasVscodeFolder: fs3.existsSync(vscodeDir),
|
|
1184
|
+
hasLaunchJson: fs3.existsSync(path10.join(vscodeDir, "launch.json")),
|
|
1185
|
+
hasSettingsJson: fs3.existsSync(path10.join(vscodeDir, "settings.json")),
|
|
1174
1186
|
hasVite: !!pkg.devDependencies?.vite || !!pkg.dependencies?.vite,
|
|
1175
1187
|
hasTsup: !!pkg.devDependencies?.tsup || !!pkg.dependencies?.tsup
|
|
1176
1188
|
};
|
|
@@ -1216,7 +1228,7 @@ function applySelections(selected, setup2) {
|
|
|
1216
1228
|
for (const choice of selected) handlers[choice]?.();
|
|
1217
1229
|
}
|
|
1218
1230
|
async function promptForOptions(options2) {
|
|
1219
|
-
console.log(
|
|
1231
|
+
console.log(chalk19.bold("Available VS Code configurations to add:\n"));
|
|
1220
1232
|
return promptMultiselect("Select configurations to add:", options2);
|
|
1221
1233
|
}
|
|
1222
1234
|
async function init3({ all = false } = {}) {
|
|
@@ -1224,17 +1236,17 @@ async function init3({ all = false } = {}) {
|
|
|
1224
1236
|
const setup2 = detectVscodeSetup(pkg);
|
|
1225
1237
|
const options2 = getAvailableOptions2(setup2);
|
|
1226
1238
|
if (options2.length === 0) {
|
|
1227
|
-
console.log(
|
|
1239
|
+
console.log(chalk19.green("VS Code configuration already exists!"));
|
|
1228
1240
|
return;
|
|
1229
1241
|
}
|
|
1230
1242
|
const selected = all ? options2.map((o) => o.value) : await promptForOptions(options2);
|
|
1231
1243
|
if (selected.length === 0) {
|
|
1232
|
-
console.log(
|
|
1244
|
+
console.log(chalk19.yellow("No configurations selected"));
|
|
1233
1245
|
return;
|
|
1234
1246
|
}
|
|
1235
1247
|
applySelections(selected, setup2);
|
|
1236
1248
|
console.log(
|
|
1237
|
-
|
|
1249
|
+
chalk19.green(`
|
|
1238
1250
|
Added ${selected.length} VS Code configuration(s)`)
|
|
1239
1251
|
);
|
|
1240
1252
|
}
|
|
@@ -1246,26 +1258,26 @@ async function init4() {
|
|
|
1246
1258
|
}
|
|
1247
1259
|
|
|
1248
1260
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
1249
|
-
import
|
|
1250
|
-
import
|
|
1261
|
+
import path16 from "path";
|
|
1262
|
+
import chalk21 from "chalk";
|
|
1251
1263
|
|
|
1252
1264
|
// src/commands/lint/lint/checkFileNames.ts
|
|
1253
|
-
import fs6 from "fs";
|
|
1254
|
-
import path13 from "path";
|
|
1255
|
-
|
|
1256
|
-
// src/shared/findSourceFiles.ts
|
|
1257
1265
|
import fs5 from "fs";
|
|
1258
1266
|
import path12 from "path";
|
|
1267
|
+
|
|
1268
|
+
// src/shared/findSourceFiles.ts
|
|
1269
|
+
import fs4 from "fs";
|
|
1270
|
+
import path11 from "path";
|
|
1259
1271
|
var EXTENSIONS = [".ts", ".tsx"];
|
|
1260
1272
|
function findSourceFiles(dir, options2 = {}) {
|
|
1261
1273
|
const { includeTests = true } = options2;
|
|
1262
1274
|
const results = [];
|
|
1263
|
-
if (!
|
|
1275
|
+
if (!fs4.existsSync(dir)) {
|
|
1264
1276
|
return results;
|
|
1265
1277
|
}
|
|
1266
|
-
const entries =
|
|
1278
|
+
const entries = fs4.readdirSync(dir, { withFileTypes: true });
|
|
1267
1279
|
for (const entry of entries) {
|
|
1268
|
-
const fullPath =
|
|
1280
|
+
const fullPath = path11.join(dir, entry.name);
|
|
1269
1281
|
if (entry.isDirectory() && entry.name !== "node_modules") {
|
|
1270
1282
|
results.push(...findSourceFiles(fullPath, options2));
|
|
1271
1283
|
} else if (entry.isFile() && EXTENSIONS.some((ext) => entry.name.endsWith(ext))) {
|
|
@@ -1309,11 +1321,11 @@ function checkFileNames() {
|
|
|
1309
1321
|
const sourceFiles = findSourceFiles("src");
|
|
1310
1322
|
const violations = [];
|
|
1311
1323
|
for (const filePath of sourceFiles) {
|
|
1312
|
-
const fileName =
|
|
1324
|
+
const fileName = path12.basename(filePath);
|
|
1313
1325
|
const nameWithoutExt = fileName.replace(/\.(ts|tsx)$/, "");
|
|
1314
1326
|
if (/\.(stories|test)\.(ts|tsx)$/.test(fileName)) continue;
|
|
1315
1327
|
if (/^[A-Z]/.test(nameWithoutExt)) {
|
|
1316
|
-
const content =
|
|
1328
|
+
const content = fs5.readFileSync(filePath, "utf-8");
|
|
1317
1329
|
if (!hasClassOrComponent(content) && !hasMatchingTypeExport(content, nameWithoutExt)) {
|
|
1318
1330
|
violations.push({
|
|
1319
1331
|
filePath,
|
|
@@ -1327,17 +1339,17 @@ function checkFileNames() {
|
|
|
1327
1339
|
}
|
|
1328
1340
|
|
|
1329
1341
|
// src/commands/lint/lint/fixFileNameViolations.ts
|
|
1330
|
-
import
|
|
1342
|
+
import chalk20 from "chalk";
|
|
1331
1343
|
|
|
1332
1344
|
// src/commands/lint/lint/applyMoves.ts
|
|
1333
|
-
import
|
|
1334
|
-
import
|
|
1345
|
+
import fs6 from "fs";
|
|
1346
|
+
import path14 from "path";
|
|
1335
1347
|
|
|
1336
1348
|
// src/commands/lint/lint/renameExports.ts
|
|
1337
|
-
import
|
|
1349
|
+
import path13 from "path";
|
|
1338
1350
|
import { SyntaxKind } from "ts-morph";
|
|
1339
1351
|
function nameWithoutExtension(filePath) {
|
|
1340
|
-
return
|
|
1352
|
+
return path13.basename(filePath).replace(/\.(ts|tsx)$/, "");
|
|
1341
1353
|
}
|
|
1342
1354
|
function renameExports(project, absSource, absDest) {
|
|
1343
1355
|
const oldName = nameWithoutExtension(absSource);
|
|
@@ -1366,40 +1378,40 @@ function isCaseOnly(a, b) {
|
|
|
1366
1378
|
}
|
|
1367
1379
|
function moveCaseInsensitive(absSource, absDest) {
|
|
1368
1380
|
const tmp = `${absSource}.tmp`;
|
|
1369
|
-
|
|
1370
|
-
|
|
1381
|
+
fs6.renameSync(absSource, tmp);
|
|
1382
|
+
fs6.renameSync(tmp, absDest);
|
|
1371
1383
|
}
|
|
1372
1384
|
function applyMoves(project, moves, cwd, emit) {
|
|
1373
1385
|
for (const { sourcePath, destPath } of moves) {
|
|
1374
1386
|
const start3 = performance.now();
|
|
1375
|
-
const absSource =
|
|
1376
|
-
const absDest =
|
|
1387
|
+
const absSource = path14.resolve(sourcePath);
|
|
1388
|
+
const absDest = path14.resolve(destPath);
|
|
1377
1389
|
for (const r of renameExports(project, absSource, absDest)) {
|
|
1378
1390
|
emit(` Renamed export ${r} in ${sourcePath}`);
|
|
1379
1391
|
}
|
|
1380
1392
|
const sourceFile = project.getSourceFile(absSource);
|
|
1381
1393
|
if (sourceFile) sourceFile.move(absDest);
|
|
1382
1394
|
const ms = (performance.now() - start3).toFixed(0);
|
|
1383
|
-
const rel = `${
|
|
1395
|
+
const rel = `${path14.relative(cwd, absSource)} \u2192 ${path14.relative(cwd, absDest)}`;
|
|
1384
1396
|
emit(` Renamed ${rel} (${ms}ms)`);
|
|
1385
1397
|
}
|
|
1386
1398
|
project.saveSync();
|
|
1387
1399
|
for (const { sourcePath, destPath } of moves) {
|
|
1388
|
-
const absSource =
|
|
1389
|
-
const absDest =
|
|
1390
|
-
if (isCaseOnly(absSource, absDest) &&
|
|
1400
|
+
const absSource = path14.resolve(sourcePath);
|
|
1401
|
+
const absDest = path14.resolve(destPath);
|
|
1402
|
+
if (isCaseOnly(absSource, absDest) && fs6.existsSync(absSource)) {
|
|
1391
1403
|
moveCaseInsensitive(absSource, absDest);
|
|
1392
1404
|
}
|
|
1393
1405
|
}
|
|
1394
1406
|
}
|
|
1395
1407
|
|
|
1396
1408
|
// src/commands/lint/lint/createLintProject.ts
|
|
1397
|
-
import
|
|
1398
|
-
import
|
|
1409
|
+
import fs7 from "fs";
|
|
1410
|
+
import path15 from "path";
|
|
1399
1411
|
import { Project } from "ts-morph";
|
|
1400
1412
|
function createLintProject() {
|
|
1401
|
-
const tsConfigPath =
|
|
1402
|
-
const project =
|
|
1413
|
+
const tsConfigPath = path15.resolve("tsconfig.json");
|
|
1414
|
+
const project = fs7.existsSync(tsConfigPath) ? new Project({
|
|
1403
1415
|
tsConfigFilePath: tsConfigPath,
|
|
1404
1416
|
skipAddingFilesFromTsConfig: true
|
|
1405
1417
|
}) : new Project();
|
|
@@ -1412,25 +1424,25 @@ function fixFileNameViolations(moves) {
|
|
|
1412
1424
|
const start3 = performance.now();
|
|
1413
1425
|
const project = createLintProject();
|
|
1414
1426
|
const cwd = process.cwd();
|
|
1415
|
-
applyMoves(project, moves, cwd, (line) => console.log(
|
|
1427
|
+
applyMoves(project, moves, cwd, (line) => console.log(chalk20.green(line)));
|
|
1416
1428
|
const ms = (performance.now() - start3).toFixed(0);
|
|
1417
|
-
console.log(
|
|
1429
|
+
console.log(chalk20.dim(` Done in ${ms}ms`));
|
|
1418
1430
|
}
|
|
1419
1431
|
|
|
1420
1432
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
1421
1433
|
function reportViolations(violations) {
|
|
1422
|
-
console.error(
|
|
1434
|
+
console.error(chalk21.red("\nFile name check failed:\n"));
|
|
1423
1435
|
console.error(
|
|
1424
|
-
|
|
1436
|
+
chalk21.red(
|
|
1425
1437
|
" Files without classes or React components should not start with a capital letter.\n"
|
|
1426
1438
|
)
|
|
1427
1439
|
);
|
|
1428
1440
|
for (const violation of violations) {
|
|
1429
|
-
console.error(
|
|
1430
|
-
console.error(
|
|
1441
|
+
console.error(chalk21.red(` ${violation.filePath}`));
|
|
1442
|
+
console.error(chalk21.gray(` Rename to: ${violation.suggestedName}
|
|
1431
1443
|
`));
|
|
1432
1444
|
}
|
|
1433
|
-
console.error(
|
|
1445
|
+
console.error(chalk21.dim(" Run with -f to auto-fix.\n"));
|
|
1434
1446
|
}
|
|
1435
1447
|
function runFileNameCheck(fix = false) {
|
|
1436
1448
|
const violations = checkFileNames();
|
|
@@ -1449,27 +1461,27 @@ function runFileNameCheck(fix = false) {
|
|
|
1449
1461
|
fixFileNameViolations(
|
|
1450
1462
|
violations.map((v) => ({
|
|
1451
1463
|
sourcePath: v.filePath,
|
|
1452
|
-
destPath:
|
|
1464
|
+
destPath: path16.join(path16.dirname(v.filePath), v.suggestedName)
|
|
1453
1465
|
}))
|
|
1454
1466
|
);
|
|
1455
1467
|
return true;
|
|
1456
1468
|
}
|
|
1457
1469
|
|
|
1458
1470
|
// src/commands/lint/lint/runImportExtensionCheck.ts
|
|
1459
|
-
import
|
|
1471
|
+
import fs8 from "fs";
|
|
1460
1472
|
|
|
1461
1473
|
// src/commands/lint/shared.ts
|
|
1462
|
-
import
|
|
1474
|
+
import chalk22 from "chalk";
|
|
1463
1475
|
function reportViolations2(violations, checkName, errorMessage, successMessage) {
|
|
1464
1476
|
if (violations.length > 0) {
|
|
1465
|
-
console.error(
|
|
1477
|
+
console.error(chalk22.red(`
|
|
1466
1478
|
${checkName} failed:
|
|
1467
1479
|
`));
|
|
1468
|
-
console.error(
|
|
1480
|
+
console.error(chalk22.red(` ${errorMessage}
|
|
1469
1481
|
`));
|
|
1470
1482
|
for (const violation of violations) {
|
|
1471
|
-
console.error(
|
|
1472
|
-
console.error(
|
|
1483
|
+
console.error(chalk22.red(` ${violation.filePath}:${violation.line}`));
|
|
1484
|
+
console.error(chalk22.gray(` ${violation.content}
|
|
1473
1485
|
`));
|
|
1474
1486
|
}
|
|
1475
1487
|
return false;
|
|
@@ -1482,7 +1494,7 @@ ${checkName} failed:
|
|
|
1482
1494
|
|
|
1483
1495
|
// src/commands/lint/lint/runImportExtensionCheck.ts
|
|
1484
1496
|
function checkForImportExtensions(filePath) {
|
|
1485
|
-
const content =
|
|
1497
|
+
const content = fs8.readFileSync(filePath, "utf-8");
|
|
1486
1498
|
const lines = content.split("\n");
|
|
1487
1499
|
const violations = [];
|
|
1488
1500
|
const importExtensionPattern = /from\s+["']\..*\.(js|ts)["']/;
|
|
@@ -1516,9 +1528,9 @@ function runImportExtensionCheck() {
|
|
|
1516
1528
|
}
|
|
1517
1529
|
|
|
1518
1530
|
// src/commands/lint/lint/runStaticImportCheck.ts
|
|
1519
|
-
import
|
|
1531
|
+
import fs9 from "fs";
|
|
1520
1532
|
function checkForDynamicImports(filePath) {
|
|
1521
|
-
const content =
|
|
1533
|
+
const content = fs9.readFileSync(filePath, "utf-8");
|
|
1522
1534
|
const lines = content.split("\n");
|
|
1523
1535
|
const violations = [];
|
|
1524
1536
|
const requirePattern = /\brequire\s*\(/;
|
|
@@ -1611,7 +1623,7 @@ Total: ${lines.length} hardcoded color(s)`);
|
|
|
1611
1623
|
}
|
|
1612
1624
|
|
|
1613
1625
|
// src/commands/verify/run/resolveEntries.ts
|
|
1614
|
-
import * as
|
|
1626
|
+
import * as path17 from "path";
|
|
1615
1627
|
function buildFullCommand(command, args) {
|
|
1616
1628
|
return [shellQuote(command), ...(args ?? []).map(shellQuote)].join(" ");
|
|
1617
1629
|
}
|
|
@@ -1628,7 +1640,7 @@ function getRunEntries() {
|
|
|
1628
1640
|
function getPackageJsonEntries() {
|
|
1629
1641
|
const result = findPackageJsonWithVerifyScripts(process.cwd());
|
|
1630
1642
|
if (!result) return [];
|
|
1631
|
-
const cwd =
|
|
1643
|
+
const cwd = path17.dirname(result.packageJsonPath);
|
|
1632
1644
|
return result.verifyScripts.map((script) => ({
|
|
1633
1645
|
name: script,
|
|
1634
1646
|
fullCommand: `npm run ${script}`,
|
|
@@ -1852,11 +1864,11 @@ async function run(options2 = {}) {
|
|
|
1852
1864
|
|
|
1853
1865
|
// src/commands/new/registerNew/initGit.ts
|
|
1854
1866
|
import { execSync as execSync8 } from "child_process";
|
|
1855
|
-
import { writeFileSync as
|
|
1867
|
+
import { writeFileSync as writeFileSync7 } from "fs";
|
|
1856
1868
|
function initGit() {
|
|
1857
1869
|
console.log("Initializing git repository...");
|
|
1858
1870
|
execSync8("git init", { stdio: "inherit" });
|
|
1859
|
-
|
|
1871
|
+
writeFileSync7(".gitignore", "dist\nnode_modules\n");
|
|
1860
1872
|
}
|
|
1861
1873
|
|
|
1862
1874
|
// src/commands/new/registerNew/newCli/initPackageJson.ts
|
|
@@ -1875,10 +1887,10 @@ function initPackageJson(name) {
|
|
|
1875
1887
|
}
|
|
1876
1888
|
|
|
1877
1889
|
// src/commands/new/registerNew/newCli/writeCliTemplate.ts
|
|
1878
|
-
import { mkdirSync as mkdirSync2, writeFileSync as
|
|
1890
|
+
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync8 } from "fs";
|
|
1879
1891
|
function writeCliTemplate(name) {
|
|
1880
1892
|
console.log("Writing tsconfig.json...");
|
|
1881
|
-
|
|
1893
|
+
writeFileSync8(
|
|
1882
1894
|
"tsconfig.json",
|
|
1883
1895
|
JSON.stringify(
|
|
1884
1896
|
{
|
|
@@ -1902,7 +1914,7 @@ function writeCliTemplate(name) {
|
|
|
1902
1914
|
)
|
|
1903
1915
|
);
|
|
1904
1916
|
console.log("Writing tsup.config.ts...");
|
|
1905
|
-
|
|
1917
|
+
writeFileSync8(
|
|
1906
1918
|
"tsup.config.ts",
|
|
1907
1919
|
`import { defineConfig } from "tsup";
|
|
1908
1920
|
export default defineConfig({
|
|
@@ -1917,7 +1929,7 @@ export default defineConfig({
|
|
|
1917
1929
|
);
|
|
1918
1930
|
console.log("Writing src/index.ts...");
|
|
1919
1931
|
mkdirSync2("src", { recursive: true });
|
|
1920
|
-
|
|
1932
|
+
writeFileSync8(
|
|
1921
1933
|
"src/index.ts",
|
|
1922
1934
|
`#!/usr/bin/env node
|
|
1923
1935
|
import { Command } from "commander";
|
|
@@ -1945,18 +1957,18 @@ async function newCli() {
|
|
|
1945
1957
|
|
|
1946
1958
|
// src/commands/new/registerNew/newProject.ts
|
|
1947
1959
|
import { execSync as execSync12 } from "child_process";
|
|
1948
|
-
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as
|
|
1960
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
1949
1961
|
|
|
1950
1962
|
// src/commands/deploy/init/index.ts
|
|
1951
1963
|
import { execSync as execSync11 } from "child_process";
|
|
1952
|
-
import
|
|
1964
|
+
import chalk24 from "chalk";
|
|
1953
1965
|
import enquirer3 from "enquirer";
|
|
1954
1966
|
|
|
1955
1967
|
// src/commands/deploy/init/updateWorkflow.ts
|
|
1956
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as
|
|
1968
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync9 } from "fs";
|
|
1957
1969
|
import { dirname as dirname11, join as join7 } from "path";
|
|
1958
1970
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1959
|
-
import
|
|
1971
|
+
import chalk23 from "chalk";
|
|
1960
1972
|
var WORKFLOW_PATH = ".github/workflows/build.yml";
|
|
1961
1973
|
var __dirname3 = dirname11(fileURLToPath2(import.meta.url));
|
|
1962
1974
|
function getExistingSiteId() {
|
|
@@ -1981,20 +1993,20 @@ async function updateWorkflow(siteId) {
|
|
|
1981
1993
|
if (existsSync10(WORKFLOW_PATH)) {
|
|
1982
1994
|
const oldContent = readFileSync8(WORKFLOW_PATH, "utf-8");
|
|
1983
1995
|
if (oldContent === newContent) {
|
|
1984
|
-
console.log(
|
|
1996
|
+
console.log(chalk23.green("build.yml is already up to date"));
|
|
1985
1997
|
return;
|
|
1986
1998
|
}
|
|
1987
|
-
console.log(
|
|
1999
|
+
console.log(chalk23.yellow("\nbuild.yml will be updated:"));
|
|
1988
2000
|
console.log();
|
|
1989
2001
|
printDiff(oldContent, newContent);
|
|
1990
|
-
const confirm = await promptConfirm(
|
|
2002
|
+
const confirm = await promptConfirm(chalk23.red("Update build.yml?"));
|
|
1991
2003
|
if (!confirm) {
|
|
1992
2004
|
console.log("Skipped build.yml update");
|
|
1993
2005
|
return;
|
|
1994
2006
|
}
|
|
1995
2007
|
}
|
|
1996
|
-
|
|
1997
|
-
console.log(
|
|
2008
|
+
writeFileSync9(WORKFLOW_PATH, newContent);
|
|
2009
|
+
console.log(chalk23.green(`
|
|
1998
2010
|
Created ${WORKFLOW_PATH}`));
|
|
1999
2011
|
}
|
|
2000
2012
|
|
|
@@ -2005,43 +2017,43 @@ async function ensureNetlifyCli() {
|
|
|
2005
2017
|
} catch (error) {
|
|
2006
2018
|
if (!(error instanceof Error) || !error.message.includes("command not found"))
|
|
2007
2019
|
throw error;
|
|
2008
|
-
console.error(
|
|
2020
|
+
console.error(chalk24.red("\nNetlify CLI is not installed.\n"));
|
|
2009
2021
|
const install = await promptConfirm("Would you like to install it now?");
|
|
2010
2022
|
if (!install) {
|
|
2011
2023
|
console.log(
|
|
2012
|
-
|
|
2024
|
+
chalk24.yellow(
|
|
2013
2025
|
"\nInstall it manually with: npm install -g netlify-cli\n"
|
|
2014
2026
|
)
|
|
2015
2027
|
);
|
|
2016
2028
|
process.exit(1);
|
|
2017
2029
|
}
|
|
2018
|
-
console.log(
|
|
2030
|
+
console.log(chalk24.dim("\nInstalling netlify-cli...\n"));
|
|
2019
2031
|
execSync11("npm install -g netlify-cli", { stdio: "inherit" });
|
|
2020
2032
|
console.log();
|
|
2021
2033
|
execSync11("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
2022
2034
|
}
|
|
2023
2035
|
}
|
|
2024
2036
|
function printSetupInstructions() {
|
|
2025
|
-
console.log(
|
|
2037
|
+
console.log(chalk24.bold("\nDeployment initialized successfully!"));
|
|
2026
2038
|
console.log(
|
|
2027
|
-
|
|
2039
|
+
chalk24.yellow("\nTo complete setup, create a personal access token at:")
|
|
2028
2040
|
);
|
|
2029
2041
|
console.log(
|
|
2030
|
-
|
|
2042
|
+
chalk24.cyan(
|
|
2031
2043
|
"https://app.netlify.com/user/applications#personal-access-tokens"
|
|
2032
2044
|
)
|
|
2033
2045
|
);
|
|
2034
2046
|
console.log(
|
|
2035
|
-
|
|
2047
|
+
chalk24.yellow(
|
|
2036
2048
|
"\nThen add it as NETLIFY_AUTH_TOKEN in your GitHub repository secrets."
|
|
2037
2049
|
)
|
|
2038
2050
|
);
|
|
2039
2051
|
}
|
|
2040
2052
|
async function init5() {
|
|
2041
|
-
console.log(
|
|
2053
|
+
console.log(chalk24.bold("Initializing Netlify deployment...\n"));
|
|
2042
2054
|
const existingSiteId = getExistingSiteId();
|
|
2043
2055
|
if (existingSiteId) {
|
|
2044
|
-
console.log(
|
|
2056
|
+
console.log(chalk24.dim(`Using existing site ID: ${existingSiteId}
|
|
2045
2057
|
`));
|
|
2046
2058
|
await updateWorkflow(existingSiteId);
|
|
2047
2059
|
return;
|
|
@@ -2087,7 +2099,7 @@ function addViteBaseConfig() {
|
|
|
2087
2099
|
'defineConfig({\n base: "./",'
|
|
2088
2100
|
);
|
|
2089
2101
|
if (updated !== content) {
|
|
2090
|
-
|
|
2102
|
+
writeFileSync10(viteConfigPath, updated);
|
|
2091
2103
|
console.log('Added base: "./" to vite.config.ts');
|
|
2092
2104
|
}
|
|
2093
2105
|
}
|
|
@@ -2135,19 +2147,19 @@ function detectPlatform() {
|
|
|
2135
2147
|
|
|
2136
2148
|
// src/commands/notify/showNotification/showWindowsNotificationFromWsl.ts
|
|
2137
2149
|
import { spawn as spawn2 } from "child_process";
|
|
2138
|
-
import
|
|
2150
|
+
import fs10 from "fs";
|
|
2139
2151
|
import { createRequire } from "module";
|
|
2140
|
-
import
|
|
2152
|
+
import path18 from "path";
|
|
2141
2153
|
var require2 = createRequire(import.meta.url);
|
|
2142
2154
|
function getSnoreToastPath() {
|
|
2143
|
-
const notifierPath =
|
|
2144
|
-
return
|
|
2155
|
+
const notifierPath = path18.dirname(require2.resolve("node-notifier"));
|
|
2156
|
+
return path18.join(notifierPath, "vendor", "snoreToast", "snoretoast-x64.exe");
|
|
2145
2157
|
}
|
|
2146
2158
|
function showWindowsNotificationFromWsl(options2) {
|
|
2147
2159
|
const { title, message, sound } = options2;
|
|
2148
2160
|
const snoreToastPath = getSnoreToastPath();
|
|
2149
2161
|
try {
|
|
2150
|
-
|
|
2162
|
+
fs10.chmodSync(snoreToastPath, 493);
|
|
2151
2163
|
} catch {
|
|
2152
2164
|
}
|
|
2153
2165
|
const args = ["-t", title, "-m", message];
|
|
@@ -2221,12 +2233,12 @@ async function notify() {
|
|
|
2221
2233
|
|
|
2222
2234
|
// src/commands/backlog/add/index.ts
|
|
2223
2235
|
import { existsSync as existsSync13 } from "fs";
|
|
2224
|
-
import
|
|
2236
|
+
import chalk26 from "chalk";
|
|
2225
2237
|
|
|
2226
2238
|
// src/commands/backlog/shared.ts
|
|
2227
|
-
import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as
|
|
2239
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync11 } from "fs";
|
|
2228
2240
|
import { join as join8 } from "path";
|
|
2229
|
-
import
|
|
2241
|
+
import chalk25 from "chalk";
|
|
2230
2242
|
import { parse as parseYaml2, stringify as stringifyYaml3 } from "yaml";
|
|
2231
2243
|
|
|
2232
2244
|
// src/commands/backlog/types.ts
|
|
@@ -2262,7 +2274,7 @@ function loadBacklog() {
|
|
|
2262
2274
|
}
|
|
2263
2275
|
function saveBacklog(items) {
|
|
2264
2276
|
const backlogPath = getBacklogPath();
|
|
2265
|
-
|
|
2277
|
+
writeFileSync11(backlogPath, stringifyYaml3(items, { lineWidth: 0 }));
|
|
2266
2278
|
}
|
|
2267
2279
|
function findItem(items, id) {
|
|
2268
2280
|
return items.find((item) => item.id === id);
|
|
@@ -2270,7 +2282,7 @@ function findItem(items, id) {
|
|
|
2270
2282
|
function loadAndFindItem(id) {
|
|
2271
2283
|
if (!existsSync12(getBacklogPath())) {
|
|
2272
2284
|
console.log(
|
|
2273
|
-
|
|
2285
|
+
chalk25.yellow(
|
|
2274
2286
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
2275
2287
|
)
|
|
2276
2288
|
);
|
|
@@ -2279,7 +2291,7 @@ function loadAndFindItem(id) {
|
|
|
2279
2291
|
const items = loadBacklog();
|
|
2280
2292
|
const item = findItem(items, Number.parseInt(id, 10));
|
|
2281
2293
|
if (!item) {
|
|
2282
|
-
console.log(
|
|
2294
|
+
console.log(chalk25.red(`Item #${id} not found.`));
|
|
2283
2295
|
return void 0;
|
|
2284
2296
|
}
|
|
2285
2297
|
return { items, item };
|
|
@@ -2304,7 +2316,7 @@ function getNextId(items) {
|
|
|
2304
2316
|
|
|
2305
2317
|
// src/commands/backlog/add/shared.ts
|
|
2306
2318
|
import { spawnSync } from "child_process";
|
|
2307
|
-
import { mkdtempSync, readFileSync as readFileSync11, unlinkSync as unlinkSync2, writeFileSync as
|
|
2319
|
+
import { mkdtempSync, readFileSync as readFileSync11, unlinkSync as unlinkSync2, writeFileSync as writeFileSync12 } from "fs";
|
|
2308
2320
|
import { tmpdir } from "os";
|
|
2309
2321
|
import { join as join9 } from "path";
|
|
2310
2322
|
import enquirer4 from "enquirer";
|
|
@@ -2348,7 +2360,7 @@ function openEditor() {
|
|
|
2348
2360
|
const editor = process.env.EDITOR || process.env.VISUAL || "vi";
|
|
2349
2361
|
const dir = mkdtempSync(join9(tmpdir(), "assist-"));
|
|
2350
2362
|
const filePath = join9(dir, "description.md");
|
|
2351
|
-
|
|
2363
|
+
writeFileSync12(filePath, "");
|
|
2352
2364
|
const result = spawnSync(editor, [filePath], { stdio: "inherit" });
|
|
2353
2365
|
if (result.status !== 0) {
|
|
2354
2366
|
unlinkSync2(filePath);
|
|
@@ -2377,7 +2389,7 @@ async function add() {
|
|
|
2377
2389
|
const backlogPath = getBacklogPath();
|
|
2378
2390
|
if (!existsSync13(backlogPath)) {
|
|
2379
2391
|
console.log(
|
|
2380
|
-
|
|
2392
|
+
chalk26.yellow(
|
|
2381
2393
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
2382
2394
|
)
|
|
2383
2395
|
);
|
|
@@ -2398,67 +2410,67 @@ async function add() {
|
|
|
2398
2410
|
status: "todo"
|
|
2399
2411
|
});
|
|
2400
2412
|
saveBacklog(items);
|
|
2401
|
-
console.log(
|
|
2413
|
+
console.log(chalk26.green(`Added item #${id}: ${name}`));
|
|
2402
2414
|
}
|
|
2403
2415
|
|
|
2404
2416
|
// src/commands/backlog/delete/index.ts
|
|
2405
|
-
import
|
|
2417
|
+
import chalk27 from "chalk";
|
|
2406
2418
|
async function del(id) {
|
|
2407
2419
|
const name = removeItem(id);
|
|
2408
2420
|
if (name) {
|
|
2409
|
-
console.log(
|
|
2421
|
+
console.log(chalk27.green(`Deleted item #${id}: ${name}`));
|
|
2410
2422
|
}
|
|
2411
2423
|
}
|
|
2412
2424
|
|
|
2413
2425
|
// src/commands/backlog/done/index.ts
|
|
2414
|
-
import
|
|
2426
|
+
import chalk28 from "chalk";
|
|
2415
2427
|
async function done(id) {
|
|
2416
2428
|
const name = setStatus(id, "done");
|
|
2417
2429
|
if (name) {
|
|
2418
|
-
console.log(
|
|
2430
|
+
console.log(chalk28.green(`Completed item #${id}: ${name}`));
|
|
2419
2431
|
}
|
|
2420
2432
|
}
|
|
2421
2433
|
|
|
2422
2434
|
// src/commands/backlog/init/index.ts
|
|
2423
2435
|
import { existsSync as existsSync14 } from "fs";
|
|
2424
|
-
import
|
|
2436
|
+
import chalk29 from "chalk";
|
|
2425
2437
|
async function init6() {
|
|
2426
2438
|
const backlogPath = getBacklogPath();
|
|
2427
2439
|
if (existsSync14(backlogPath)) {
|
|
2428
|
-
console.log(
|
|
2440
|
+
console.log(chalk29.yellow("assist.backlog.yml already exists."));
|
|
2429
2441
|
return;
|
|
2430
2442
|
}
|
|
2431
2443
|
saveBacklog([]);
|
|
2432
|
-
console.log(
|
|
2444
|
+
console.log(chalk29.green("Created assist.backlog.yml"));
|
|
2433
2445
|
}
|
|
2434
2446
|
|
|
2435
2447
|
// src/commands/backlog/list/index.ts
|
|
2436
2448
|
import { existsSync as existsSync15 } from "fs";
|
|
2437
|
-
import
|
|
2449
|
+
import chalk30 from "chalk";
|
|
2438
2450
|
function statusIcon(status2) {
|
|
2439
2451
|
switch (status2) {
|
|
2440
2452
|
case "todo":
|
|
2441
|
-
return
|
|
2453
|
+
return chalk30.dim("[ ]");
|
|
2442
2454
|
case "in-progress":
|
|
2443
|
-
return
|
|
2455
|
+
return chalk30.yellow("[~]");
|
|
2444
2456
|
case "done":
|
|
2445
|
-
return
|
|
2457
|
+
return chalk30.green("[x]");
|
|
2446
2458
|
}
|
|
2447
2459
|
}
|
|
2448
2460
|
function typeLabel(type) {
|
|
2449
2461
|
switch (type) {
|
|
2450
2462
|
case "bug":
|
|
2451
|
-
return
|
|
2463
|
+
return chalk30.magenta("Bug");
|
|
2452
2464
|
case "story":
|
|
2453
|
-
return
|
|
2465
|
+
return chalk30.cyan("Story");
|
|
2454
2466
|
}
|
|
2455
2467
|
}
|
|
2456
2468
|
function printVerboseDetails(item) {
|
|
2457
2469
|
if (item.description) {
|
|
2458
|
-
console.log(` ${
|
|
2470
|
+
console.log(` ${chalk30.dim("Description:")} ${item.description}`);
|
|
2459
2471
|
}
|
|
2460
2472
|
if (item.acceptanceCriteria.length > 0) {
|
|
2461
|
-
console.log(` ${
|
|
2473
|
+
console.log(` ${chalk30.dim("Acceptance criteria:")}`);
|
|
2462
2474
|
for (const criterion of item.acceptanceCriteria) {
|
|
2463
2475
|
console.log(` - ${criterion}`);
|
|
2464
2476
|
}
|
|
@@ -2474,7 +2486,7 @@ async function list2(options2) {
|
|
|
2474
2486
|
const backlogPath = getBacklogPath();
|
|
2475
2487
|
if (!existsSync15(backlogPath)) {
|
|
2476
2488
|
console.log(
|
|
2477
|
-
|
|
2489
|
+
chalk30.yellow(
|
|
2478
2490
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
2479
2491
|
)
|
|
2480
2492
|
);
|
|
@@ -2482,12 +2494,12 @@ async function list2(options2) {
|
|
|
2482
2494
|
}
|
|
2483
2495
|
const items = filterItems(loadBacklog(), options2);
|
|
2484
2496
|
if (items.length === 0) {
|
|
2485
|
-
console.log(
|
|
2497
|
+
console.log(chalk30.dim("Backlog is empty."));
|
|
2486
2498
|
return;
|
|
2487
2499
|
}
|
|
2488
2500
|
for (const item of items) {
|
|
2489
2501
|
console.log(
|
|
2490
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
2502
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk30.dim(`#${item.id}`)} ${item.name}`
|
|
2491
2503
|
);
|
|
2492
2504
|
if (options2.verbose) {
|
|
2493
2505
|
printVerboseDetails(item);
|
|
@@ -2496,11 +2508,11 @@ async function list2(options2) {
|
|
|
2496
2508
|
}
|
|
2497
2509
|
|
|
2498
2510
|
// src/commands/backlog/start/index.ts
|
|
2499
|
-
import
|
|
2511
|
+
import chalk31 from "chalk";
|
|
2500
2512
|
async function start(id) {
|
|
2501
2513
|
const name = setStatus(id, "in-progress");
|
|
2502
2514
|
if (name) {
|
|
2503
|
-
console.log(
|
|
2515
|
+
console.log(chalk31.green(`Started item #${id}: ${name}`));
|
|
2504
2516
|
}
|
|
2505
2517
|
}
|
|
2506
2518
|
|
|
@@ -2512,7 +2524,7 @@ import {
|
|
|
2512
2524
|
} from "http";
|
|
2513
2525
|
import { dirname as dirname12, join as join10 } from "path";
|
|
2514
2526
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
2515
|
-
import
|
|
2527
|
+
import chalk32 from "chalk";
|
|
2516
2528
|
function respondJson(res, status2, data) {
|
|
2517
2529
|
res.writeHead(status2, { "Content-Type": "application/json" });
|
|
2518
2530
|
res.end(JSON.stringify(data));
|
|
@@ -2556,8 +2568,8 @@ function startWebServer(label2, port, handler) {
|
|
|
2556
2568
|
handler(req, res, port);
|
|
2557
2569
|
});
|
|
2558
2570
|
server.listen(port, () => {
|
|
2559
|
-
console.log(
|
|
2560
|
-
console.log(
|
|
2571
|
+
console.log(chalk32.green(`${label2}: ${url}`));
|
|
2572
|
+
console.log(chalk32.dim("Press Ctrl+C to stop"));
|
|
2561
2573
|
exec(`open ${url}`);
|
|
2562
2574
|
});
|
|
2563
2575
|
}
|
|
@@ -2786,7 +2798,7 @@ function extractGraphqlQuery(args) {
|
|
|
2786
2798
|
}
|
|
2787
2799
|
|
|
2788
2800
|
// src/shared/loadCliReads.ts
|
|
2789
|
-
import { existsSync as existsSync16, readFileSync as readFileSync13, writeFileSync as
|
|
2801
|
+
import { existsSync as existsSync16, readFileSync as readFileSync13, writeFileSync as writeFileSync13 } from "fs";
|
|
2790
2802
|
import { dirname as dirname13, resolve as resolve2 } from "path";
|
|
2791
2803
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
2792
2804
|
var __filename2 = fileURLToPath4(import.meta.url);
|
|
@@ -2797,19 +2809,19 @@ function getCliReadsPath() {
|
|
|
2797
2809
|
var cachedLines;
|
|
2798
2810
|
function getCliReadsLines() {
|
|
2799
2811
|
if (cachedLines) return cachedLines;
|
|
2800
|
-
const
|
|
2801
|
-
if (!existsSync16(
|
|
2812
|
+
const path42 = getCliReadsPath();
|
|
2813
|
+
if (!existsSync16(path42)) {
|
|
2802
2814
|
cachedLines = [];
|
|
2803
2815
|
return cachedLines;
|
|
2804
2816
|
}
|
|
2805
|
-
cachedLines = readFileSync13(
|
|
2817
|
+
cachedLines = readFileSync13(path42, "utf-8").split("\n").filter((line) => line.trim() !== "");
|
|
2806
2818
|
return cachedLines;
|
|
2807
2819
|
}
|
|
2808
2820
|
function loadCliReads() {
|
|
2809
2821
|
return getCliReadsLines();
|
|
2810
2822
|
}
|
|
2811
2823
|
function saveCliReads(commands) {
|
|
2812
|
-
|
|
2824
|
+
writeFileSync13(getCliReadsPath(), `${commands.join("\n")}
|
|
2813
2825
|
`);
|
|
2814
2826
|
cachedLines = void 0;
|
|
2815
2827
|
}
|
|
@@ -3002,7 +3014,7 @@ ${reasons.join("\n")}`);
|
|
|
3002
3014
|
}
|
|
3003
3015
|
|
|
3004
3016
|
// src/commands/permitCliReads/index.ts
|
|
3005
|
-
import { existsSync as existsSync18, mkdirSync as mkdirSync4, readFileSync as readFileSync15, writeFileSync as
|
|
3017
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync4, readFileSync as readFileSync15, writeFileSync as writeFileSync14 } from "fs";
|
|
3006
3018
|
import { homedir as homedir4 } from "os";
|
|
3007
3019
|
import { join as join12 } from "path";
|
|
3008
3020
|
|
|
@@ -3048,11 +3060,11 @@ function assertCliExists(cli) {
|
|
|
3048
3060
|
}
|
|
3049
3061
|
|
|
3050
3062
|
// src/commands/permitCliReads/colorize.ts
|
|
3051
|
-
import
|
|
3063
|
+
import chalk33 from "chalk";
|
|
3052
3064
|
function colorize(plainOutput) {
|
|
3053
3065
|
return plainOutput.split("\n").map((line) => {
|
|
3054
|
-
if (line.startsWith(" R ")) return
|
|
3055
|
-
if (line.startsWith(" W ")) return
|
|
3066
|
+
if (line.startsWith(" R ")) return chalk33.green(line);
|
|
3067
|
+
if (line.startsWith(" W ")) return chalk33.red(line);
|
|
3056
3068
|
return line;
|
|
3057
3069
|
}).join("\n");
|
|
3058
3070
|
}
|
|
@@ -3154,14 +3166,14 @@ function showProgress(p, label2) {
|
|
|
3154
3166
|
const pct = Math.round(p.done / p.total * 100);
|
|
3155
3167
|
process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
|
|
3156
3168
|
}
|
|
3157
|
-
async function resolveCommand(cli,
|
|
3158
|
-
showProgress(p,
|
|
3159
|
-
const subHelp = await runHelp([cli, ...
|
|
3169
|
+
async function resolveCommand(cli, path42, description, depth, p) {
|
|
3170
|
+
showProgress(p, path42.join(" "));
|
|
3171
|
+
const subHelp = await runHelp([cli, ...path42]);
|
|
3160
3172
|
if (!subHelp || !hasSubcommands(subHelp)) {
|
|
3161
|
-
return [{ path:
|
|
3173
|
+
return [{ path: path42, description }];
|
|
3162
3174
|
}
|
|
3163
|
-
const children = await discoverAt(cli,
|
|
3164
|
-
return children.length > 0 ? children : [{ path:
|
|
3175
|
+
const children = await discoverAt(cli, path42, depth + 1, p);
|
|
3176
|
+
return children.length > 0 ? children : [{ path: path42, description }];
|
|
3165
3177
|
}
|
|
3166
3178
|
async function discoverAt(cli, parentPath, depth, p) {
|
|
3167
3179
|
if (depth > SAFETY_DEPTH) return [];
|
|
@@ -3309,14 +3321,14 @@ function logPath(cli) {
|
|
|
3309
3321
|
return join12(homedir4(), ".assist", `cli-discover-${safeName}.log`);
|
|
3310
3322
|
}
|
|
3311
3323
|
function readCache(cli) {
|
|
3312
|
-
const
|
|
3313
|
-
if (!existsSync18(
|
|
3314
|
-
return readFileSync15(
|
|
3324
|
+
const path42 = logPath(cli);
|
|
3325
|
+
if (!existsSync18(path42)) return void 0;
|
|
3326
|
+
return readFileSync15(path42, "utf-8");
|
|
3315
3327
|
}
|
|
3316
3328
|
function writeCache(cli, output) {
|
|
3317
3329
|
const dir = join12(homedir4(), ".assist");
|
|
3318
3330
|
mkdirSync4(dir, { recursive: true });
|
|
3319
|
-
|
|
3331
|
+
writeFileSync14(logPath(cli), output);
|
|
3320
3332
|
}
|
|
3321
3333
|
async function permitCliReads(cli, options2 = { noCache: false }) {
|
|
3322
3334
|
if (!cli) {
|
|
@@ -3363,20 +3375,20 @@ function registerCliHook(program2) {
|
|
|
3363
3375
|
}
|
|
3364
3376
|
|
|
3365
3377
|
// src/commands/complexity/analyze.ts
|
|
3366
|
-
import
|
|
3378
|
+
import chalk39 from "chalk";
|
|
3367
3379
|
|
|
3368
3380
|
// src/commands/complexity/cyclomatic.ts
|
|
3369
|
-
import
|
|
3381
|
+
import chalk35 from "chalk";
|
|
3370
3382
|
|
|
3371
3383
|
// src/commands/complexity/shared/index.ts
|
|
3372
|
-
import
|
|
3373
|
-
import
|
|
3374
|
-
import
|
|
3384
|
+
import fs12 from "fs";
|
|
3385
|
+
import path20 from "path";
|
|
3386
|
+
import chalk34 from "chalk";
|
|
3375
3387
|
import ts5 from "typescript";
|
|
3376
3388
|
|
|
3377
3389
|
// src/commands/complexity/findSourceFiles.ts
|
|
3378
|
-
import
|
|
3379
|
-
import
|
|
3390
|
+
import fs11 from "fs";
|
|
3391
|
+
import path19 from "path";
|
|
3380
3392
|
import { minimatch as minimatch3 } from "minimatch";
|
|
3381
3393
|
function applyIgnoreGlobs(files) {
|
|
3382
3394
|
const { complexity } = loadConfig();
|
|
@@ -3385,13 +3397,13 @@ function applyIgnoreGlobs(files) {
|
|
|
3385
3397
|
);
|
|
3386
3398
|
}
|
|
3387
3399
|
function walk(dir, results) {
|
|
3388
|
-
if (!
|
|
3400
|
+
if (!fs11.existsSync(dir)) {
|
|
3389
3401
|
return;
|
|
3390
3402
|
}
|
|
3391
3403
|
const extensions = [".ts", ".tsx"];
|
|
3392
|
-
const entries =
|
|
3404
|
+
const entries = fs11.readdirSync(dir, { withFileTypes: true });
|
|
3393
3405
|
for (const entry of entries) {
|
|
3394
|
-
const fullPath =
|
|
3406
|
+
const fullPath = path19.join(dir, entry.name);
|
|
3395
3407
|
if (entry.isDirectory()) {
|
|
3396
3408
|
if (entry.name !== "node_modules" && entry.name !== ".git") {
|
|
3397
3409
|
walk(fullPath, results);
|
|
@@ -3407,10 +3419,10 @@ function findSourceFiles2(pattern2, baseDir = ".") {
|
|
|
3407
3419
|
walk(baseDir, results);
|
|
3408
3420
|
return applyIgnoreGlobs(results.filter((f) => minimatch3(f, pattern2)));
|
|
3409
3421
|
}
|
|
3410
|
-
if (
|
|
3422
|
+
if (fs11.existsSync(pattern2) && fs11.statSync(pattern2).isFile()) {
|
|
3411
3423
|
return [pattern2];
|
|
3412
3424
|
}
|
|
3413
|
-
if (
|
|
3425
|
+
if (fs11.existsSync(pattern2) && fs11.statSync(pattern2).isDirectory()) {
|
|
3414
3426
|
walk(pattern2, results);
|
|
3415
3427
|
return applyIgnoreGlobs(results);
|
|
3416
3428
|
}
|
|
@@ -3605,9 +3617,9 @@ function countSloc(content) {
|
|
|
3605
3617
|
|
|
3606
3618
|
// src/commands/complexity/shared/index.ts
|
|
3607
3619
|
function createSourceFromFile(filePath) {
|
|
3608
|
-
const content =
|
|
3620
|
+
const content = fs12.readFileSync(filePath, "utf-8");
|
|
3609
3621
|
return ts5.createSourceFile(
|
|
3610
|
-
|
|
3622
|
+
path20.basename(filePath),
|
|
3611
3623
|
content,
|
|
3612
3624
|
ts5.ScriptTarget.Latest,
|
|
3613
3625
|
true,
|
|
@@ -3617,7 +3629,7 @@ function createSourceFromFile(filePath) {
|
|
|
3617
3629
|
function withSourceFiles(pattern2, callback) {
|
|
3618
3630
|
const files = findSourceFiles2(pattern2);
|
|
3619
3631
|
if (files.length === 0) {
|
|
3620
|
-
console.log(
|
|
3632
|
+
console.log(chalk34.yellow("No files found matching pattern"));
|
|
3621
3633
|
return void 0;
|
|
3622
3634
|
}
|
|
3623
3635
|
return callback(files);
|
|
@@ -3650,11 +3662,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
3650
3662
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
3651
3663
|
for (const { file, name, complexity } of results) {
|
|
3652
3664
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
3653
|
-
const color = exceedsThreshold ?
|
|
3654
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
3665
|
+
const color = exceedsThreshold ? chalk35.red : chalk35.white;
|
|
3666
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk35.cyan(complexity)}`);
|
|
3655
3667
|
}
|
|
3656
3668
|
console.log(
|
|
3657
|
-
|
|
3669
|
+
chalk35.dim(
|
|
3658
3670
|
`
|
|
3659
3671
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
3660
3672
|
)
|
|
@@ -3666,7 +3678,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
3666
3678
|
}
|
|
3667
3679
|
|
|
3668
3680
|
// src/commands/complexity/halstead.ts
|
|
3669
|
-
import
|
|
3681
|
+
import chalk36 from "chalk";
|
|
3670
3682
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
3671
3683
|
withSourceFiles(pattern2, (files) => {
|
|
3672
3684
|
const results = [];
|
|
@@ -3681,13 +3693,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
3681
3693
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
3682
3694
|
for (const { file, name, metrics } of results) {
|
|
3683
3695
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
3684
|
-
const color = exceedsThreshold ?
|
|
3696
|
+
const color = exceedsThreshold ? chalk36.red : chalk36.white;
|
|
3685
3697
|
console.log(
|
|
3686
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
3698
|
+
`${color(`${file}:${name}`)} \u2192 volume: ${chalk36.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk36.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk36.magenta(metrics.effort.toFixed(1))}`
|
|
3687
3699
|
);
|
|
3688
3700
|
}
|
|
3689
3701
|
console.log(
|
|
3690
|
-
|
|
3702
|
+
chalk36.dim(
|
|
3691
3703
|
`
|
|
3692
3704
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
3693
3705
|
)
|
|
@@ -3699,31 +3711,31 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
3699
3711
|
}
|
|
3700
3712
|
|
|
3701
3713
|
// src/commands/complexity/maintainability/index.ts
|
|
3702
|
-
import
|
|
3714
|
+
import fs13 from "fs";
|
|
3703
3715
|
|
|
3704
3716
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
3705
|
-
import
|
|
3717
|
+
import chalk37 from "chalk";
|
|
3706
3718
|
function displayMaintainabilityResults(results, threshold) {
|
|
3707
3719
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
3708
3720
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
3709
|
-
console.log(
|
|
3721
|
+
console.log(chalk37.green("All files pass maintainability threshold"));
|
|
3710
3722
|
} else {
|
|
3711
3723
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
3712
|
-
const color = threshold !== void 0 ?
|
|
3724
|
+
const color = threshold !== void 0 ? chalk37.red : chalk37.white;
|
|
3713
3725
|
console.log(
|
|
3714
|
-
`${color(file)} \u2192 avg: ${
|
|
3726
|
+
`${color(file)} \u2192 avg: ${chalk37.cyan(avgMaintainability.toFixed(1))}, min: ${chalk37.yellow(minMaintainability.toFixed(1))}`
|
|
3715
3727
|
);
|
|
3716
3728
|
}
|
|
3717
3729
|
}
|
|
3718
|
-
console.log(
|
|
3730
|
+
console.log(chalk37.dim(`
|
|
3719
3731
|
Analyzed ${results.length} files`));
|
|
3720
3732
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
3721
3733
|
console.error(
|
|
3722
|
-
|
|
3734
|
+
chalk37.red(
|
|
3723
3735
|
`
|
|
3724
3736
|
Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
|
|
3725
3737
|
|
|
3726
|
-
\u26A0\uFE0F ${
|
|
3738
|
+
\u26A0\uFE0F ${chalk37.bold("Diagnose and fix one file at a time")} \u2014 do not investigate or fix multiple files in parallel. Run 'assist complexity <file>' to see all metrics. For larger files, start by extracting responsibilities into smaller files.`
|
|
3727
3739
|
)
|
|
3728
3740
|
);
|
|
3729
3741
|
process.exit(1);
|
|
@@ -3741,7 +3753,7 @@ function calculateMaintainabilityIndex(halsteadVolume, cyclomaticComplexity, slo
|
|
|
3741
3753
|
function collectFileMetrics(files) {
|
|
3742
3754
|
const fileMetrics = /* @__PURE__ */ new Map();
|
|
3743
3755
|
for (const file of files) {
|
|
3744
|
-
const content =
|
|
3756
|
+
const content = fs13.readFileSync(file, "utf-8");
|
|
3745
3757
|
fileMetrics.set(file, { sloc: countSloc(content), functions: [] });
|
|
3746
3758
|
}
|
|
3747
3759
|
forEachFunction(files, (file, _name, node) => {
|
|
@@ -3779,14 +3791,14 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
3779
3791
|
}
|
|
3780
3792
|
|
|
3781
3793
|
// src/commands/complexity/sloc.ts
|
|
3782
|
-
import
|
|
3783
|
-
import
|
|
3794
|
+
import fs14 from "fs";
|
|
3795
|
+
import chalk38 from "chalk";
|
|
3784
3796
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
3785
3797
|
withSourceFiles(pattern2, (files) => {
|
|
3786
3798
|
const results = [];
|
|
3787
3799
|
let hasViolation = false;
|
|
3788
3800
|
for (const file of files) {
|
|
3789
|
-
const content =
|
|
3801
|
+
const content = fs14.readFileSync(file, "utf-8");
|
|
3790
3802
|
const lines = countSloc(content);
|
|
3791
3803
|
results.push({ file, lines });
|
|
3792
3804
|
if (options2.threshold !== void 0 && lines > options2.threshold) {
|
|
@@ -3796,12 +3808,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
3796
3808
|
results.sort((a, b) => b.lines - a.lines);
|
|
3797
3809
|
for (const { file, lines } of results) {
|
|
3798
3810
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
3799
|
-
const color = exceedsThreshold ?
|
|
3800
|
-
console.log(`${color(file)} \u2192 ${
|
|
3811
|
+
const color = exceedsThreshold ? chalk38.red : chalk38.white;
|
|
3812
|
+
console.log(`${color(file)} \u2192 ${chalk38.cyan(lines)} lines`);
|
|
3801
3813
|
}
|
|
3802
3814
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
3803
3815
|
console.log(
|
|
3804
|
-
|
|
3816
|
+
chalk38.dim(`
|
|
3805
3817
|
Total: ${total} lines across ${files.length} files`)
|
|
3806
3818
|
);
|
|
3807
3819
|
if (hasViolation) {
|
|
@@ -3815,21 +3827,21 @@ async function analyze(pattern2) {
|
|
|
3815
3827
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
3816
3828
|
const files = findSourceFiles2(searchPattern);
|
|
3817
3829
|
if (files.length === 0) {
|
|
3818
|
-
console.log(
|
|
3830
|
+
console.log(chalk39.yellow("No files found matching pattern"));
|
|
3819
3831
|
return;
|
|
3820
3832
|
}
|
|
3821
3833
|
if (files.length === 1) {
|
|
3822
3834
|
const file = files[0];
|
|
3823
|
-
console.log(
|
|
3835
|
+
console.log(chalk39.bold.underline("SLOC"));
|
|
3824
3836
|
await sloc(file);
|
|
3825
3837
|
console.log();
|
|
3826
|
-
console.log(
|
|
3838
|
+
console.log(chalk39.bold.underline("Cyclomatic Complexity"));
|
|
3827
3839
|
await cyclomatic(file);
|
|
3828
3840
|
console.log();
|
|
3829
|
-
console.log(
|
|
3841
|
+
console.log(chalk39.bold.underline("Halstead Metrics"));
|
|
3830
3842
|
await halstead(file);
|
|
3831
3843
|
console.log();
|
|
3832
|
-
console.log(
|
|
3844
|
+
console.log(chalk39.bold.underline("Maintainability Index"));
|
|
3833
3845
|
await maintainability(file);
|
|
3834
3846
|
return;
|
|
3835
3847
|
}
|
|
@@ -3856,8 +3868,8 @@ function registerComplexity(program2) {
|
|
|
3856
3868
|
}
|
|
3857
3869
|
|
|
3858
3870
|
// src/commands/deploy/redirect.ts
|
|
3859
|
-
import { existsSync as existsSync19, readFileSync as readFileSync16, writeFileSync as
|
|
3860
|
-
import
|
|
3871
|
+
import { existsSync as existsSync19, readFileSync as readFileSync16, writeFileSync as writeFileSync15 } from "fs";
|
|
3872
|
+
import chalk40 from "chalk";
|
|
3861
3873
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
3862
3874
|
if (!window.location.pathname.endsWith('/')) {
|
|
3863
3875
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -3866,22 +3878,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
3866
3878
|
function redirect() {
|
|
3867
3879
|
const indexPath = "index.html";
|
|
3868
3880
|
if (!existsSync19(indexPath)) {
|
|
3869
|
-
console.log(
|
|
3881
|
+
console.log(chalk40.yellow("No index.html found"));
|
|
3870
3882
|
return;
|
|
3871
3883
|
}
|
|
3872
3884
|
const content = readFileSync16(indexPath, "utf-8");
|
|
3873
3885
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
3874
|
-
console.log(
|
|
3886
|
+
console.log(chalk40.dim("Trailing slash script already present"));
|
|
3875
3887
|
return;
|
|
3876
3888
|
}
|
|
3877
3889
|
const headCloseIndex = content.indexOf("</head>");
|
|
3878
3890
|
if (headCloseIndex === -1) {
|
|
3879
|
-
console.log(
|
|
3891
|
+
console.log(chalk40.red("Could not find </head> tag in index.html"));
|
|
3880
3892
|
return;
|
|
3881
3893
|
}
|
|
3882
3894
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
3883
|
-
|
|
3884
|
-
console.log(
|
|
3895
|
+
writeFileSync15(indexPath, newContent);
|
|
3896
|
+
console.log(chalk40.green("Added trailing slash redirect to index.html"));
|
|
3885
3897
|
}
|
|
3886
3898
|
|
|
3887
3899
|
// src/commands/registerDeploy.ts
|
|
@@ -3908,7 +3920,7 @@ function loadBlogSkipDays(repoName) {
|
|
|
3908
3920
|
|
|
3909
3921
|
// src/commands/devlog/shared.ts
|
|
3910
3922
|
import { execSync as execSync15 } from "child_process";
|
|
3911
|
-
import
|
|
3923
|
+
import chalk41 from "chalk";
|
|
3912
3924
|
|
|
3913
3925
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
3914
3926
|
import { readdirSync, readFileSync as readFileSync17 } from "fs";
|
|
@@ -3995,13 +4007,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
3995
4007
|
}
|
|
3996
4008
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
3997
4009
|
for (const commit2 of commits) {
|
|
3998
|
-
console.log(` ${
|
|
4010
|
+
console.log(` ${chalk41.yellow(commit2.hash)} ${commit2.message}`);
|
|
3999
4011
|
if (verbose) {
|
|
4000
4012
|
const visibleFiles = commit2.files.filter(
|
|
4001
4013
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
4002
4014
|
);
|
|
4003
4015
|
for (const file of visibleFiles) {
|
|
4004
|
-
console.log(` ${
|
|
4016
|
+
console.log(` ${chalk41.dim(file)}`);
|
|
4005
4017
|
}
|
|
4006
4018
|
}
|
|
4007
4019
|
}
|
|
@@ -4026,15 +4038,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
4026
4038
|
}
|
|
4027
4039
|
|
|
4028
4040
|
// src/commands/devlog/list/printDateHeader.ts
|
|
4029
|
-
import
|
|
4041
|
+
import chalk42 from "chalk";
|
|
4030
4042
|
function printDateHeader(date, isSkipped, entries) {
|
|
4031
4043
|
if (isSkipped) {
|
|
4032
|
-
console.log(`${
|
|
4044
|
+
console.log(`${chalk42.bold.blue(date)} ${chalk42.dim("skipped")}`);
|
|
4033
4045
|
} else if (entries && entries.length > 0) {
|
|
4034
|
-
const entryInfo = entries.map((e) => `${
|
|
4035
|
-
console.log(`${
|
|
4046
|
+
const entryInfo = entries.map((e) => `${chalk42.green(e.version)} ${e.title}`).join(" | ");
|
|
4047
|
+
console.log(`${chalk42.bold.blue(date)} ${entryInfo}`);
|
|
4036
4048
|
} else {
|
|
4037
|
-
console.log(`${
|
|
4049
|
+
console.log(`${chalk42.bold.blue(date)} ${chalk42.red("\u26A0 devlog missing")}`);
|
|
4038
4050
|
}
|
|
4039
4051
|
}
|
|
4040
4052
|
|
|
@@ -4137,24 +4149,24 @@ function bumpVersion(version2, type) {
|
|
|
4137
4149
|
|
|
4138
4150
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
4139
4151
|
import { execSync as execSync18 } from "child_process";
|
|
4140
|
-
import
|
|
4152
|
+
import chalk44 from "chalk";
|
|
4141
4153
|
|
|
4142
4154
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
4143
|
-
import
|
|
4155
|
+
import chalk43 from "chalk";
|
|
4144
4156
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
4145
4157
|
if (conventional && firstHash) {
|
|
4146
4158
|
const version2 = getVersionAtCommit(firstHash);
|
|
4147
4159
|
if (version2) {
|
|
4148
|
-
console.log(`${
|
|
4160
|
+
console.log(`${chalk43.bold("version:")} ${stripToMinor(version2)}`);
|
|
4149
4161
|
} else {
|
|
4150
|
-
console.log(`${
|
|
4162
|
+
console.log(`${chalk43.bold("version:")} ${chalk43.red("unknown")}`);
|
|
4151
4163
|
}
|
|
4152
4164
|
} else if (patchVersion && minorVersion) {
|
|
4153
4165
|
console.log(
|
|
4154
|
-
`${
|
|
4166
|
+
`${chalk43.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
4155
4167
|
);
|
|
4156
4168
|
} else {
|
|
4157
|
-
console.log(`${
|
|
4169
|
+
console.log(`${chalk43.bold("version:")} v0.1 (initial)`);
|
|
4158
4170
|
}
|
|
4159
4171
|
}
|
|
4160
4172
|
|
|
@@ -4201,16 +4213,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
4201
4213
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
4202
4214
|
}
|
|
4203
4215
|
function logName(repoName) {
|
|
4204
|
-
console.log(`${
|
|
4216
|
+
console.log(`${chalk44.bold("name:")} ${repoName}`);
|
|
4205
4217
|
}
|
|
4206
4218
|
function displayNextEntry(ctx, targetDate, commits) {
|
|
4207
4219
|
logName(ctx.repoName);
|
|
4208
4220
|
printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
|
|
4209
|
-
console.log(
|
|
4221
|
+
console.log(chalk44.bold.blue(targetDate));
|
|
4210
4222
|
printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
|
|
4211
4223
|
}
|
|
4212
4224
|
function logNoCommits(lastInfo) {
|
|
4213
|
-
console.log(
|
|
4225
|
+
console.log(chalk44.dim(noCommitsMessage(!!lastInfo)));
|
|
4214
4226
|
}
|
|
4215
4227
|
|
|
4216
4228
|
// src/commands/devlog/next/index.ts
|
|
@@ -4251,11 +4263,11 @@ function next(options2) {
|
|
|
4251
4263
|
import { execSync as execSync19 } from "child_process";
|
|
4252
4264
|
|
|
4253
4265
|
// src/commands/devlog/repos/printReposTable.ts
|
|
4254
|
-
import
|
|
4266
|
+
import chalk45 from "chalk";
|
|
4255
4267
|
function colorStatus(status2) {
|
|
4256
|
-
if (status2 === "missing") return
|
|
4257
|
-
if (status2 === "outdated") return
|
|
4258
|
-
return
|
|
4268
|
+
if (status2 === "missing") return chalk45.red(status2);
|
|
4269
|
+
if (status2 === "outdated") return chalk45.yellow(status2);
|
|
4270
|
+
return chalk45.green(status2);
|
|
4259
4271
|
}
|
|
4260
4272
|
function formatRow(row, nameWidth) {
|
|
4261
4273
|
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
@@ -4269,8 +4281,8 @@ function printReposTable(rows) {
|
|
|
4269
4281
|
"Last Devlog".padEnd(11),
|
|
4270
4282
|
"Status"
|
|
4271
4283
|
].join(" ");
|
|
4272
|
-
console.log(
|
|
4273
|
-
console.log(
|
|
4284
|
+
console.log(chalk45.dim(header));
|
|
4285
|
+
console.log(chalk45.dim("-".repeat(header.length)));
|
|
4274
4286
|
for (const row of rows) {
|
|
4275
4287
|
console.log(formatRow(row, nameWidth));
|
|
4276
4288
|
}
|
|
@@ -4326,16 +4338,16 @@ function repos(options2) {
|
|
|
4326
4338
|
}
|
|
4327
4339
|
|
|
4328
4340
|
// src/commands/devlog/skip.ts
|
|
4329
|
-
import { writeFileSync as
|
|
4341
|
+
import { writeFileSync as writeFileSync16 } from "fs";
|
|
4330
4342
|
import { join as join15 } from "path";
|
|
4331
|
-
import
|
|
4343
|
+
import chalk46 from "chalk";
|
|
4332
4344
|
import { stringify as stringifyYaml4 } from "yaml";
|
|
4333
4345
|
function getBlogConfigPath() {
|
|
4334
4346
|
return join15(BLOG_REPO_ROOT, "assist.yml");
|
|
4335
4347
|
}
|
|
4336
4348
|
function skip(date) {
|
|
4337
4349
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
4338
|
-
console.log(
|
|
4350
|
+
console.log(chalk46.red("Invalid date format. Use YYYY-MM-DD"));
|
|
4339
4351
|
process.exit(1);
|
|
4340
4352
|
}
|
|
4341
4353
|
const repoName = getRepoName();
|
|
@@ -4346,7 +4358,7 @@ function skip(date) {
|
|
|
4346
4358
|
const skipDays = skip2[repoName] ?? [];
|
|
4347
4359
|
if (skipDays.includes(date)) {
|
|
4348
4360
|
console.log(
|
|
4349
|
-
|
|
4361
|
+
chalk46.yellow(`${date} is already in skip list for ${repoName}`)
|
|
4350
4362
|
);
|
|
4351
4363
|
return;
|
|
4352
4364
|
}
|
|
@@ -4355,21 +4367,21 @@ function skip(date) {
|
|
|
4355
4367
|
skip2[repoName] = skipDays;
|
|
4356
4368
|
devlog.skip = skip2;
|
|
4357
4369
|
config.devlog = devlog;
|
|
4358
|
-
|
|
4359
|
-
console.log(
|
|
4370
|
+
writeFileSync16(configPath, stringifyYaml4(config, { lineWidth: 0 }));
|
|
4371
|
+
console.log(chalk46.green(`Added ${date} to skip list for ${repoName}`));
|
|
4360
4372
|
}
|
|
4361
4373
|
|
|
4362
4374
|
// src/commands/devlog/version.ts
|
|
4363
|
-
import
|
|
4375
|
+
import chalk47 from "chalk";
|
|
4364
4376
|
function version() {
|
|
4365
4377
|
const config = loadConfig();
|
|
4366
4378
|
const name = getRepoName();
|
|
4367
4379
|
const lastInfo = getLastVersionInfo(name, config);
|
|
4368
4380
|
const lastVersion = lastInfo?.version ?? null;
|
|
4369
4381
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
4370
|
-
console.log(`${
|
|
4371
|
-
console.log(`${
|
|
4372
|
-
console.log(`${
|
|
4382
|
+
console.log(`${chalk47.bold("name:")} ${name}`);
|
|
4383
|
+
console.log(`${chalk47.bold("last:")} ${lastVersion ?? chalk47.dim("none")}`);
|
|
4384
|
+
console.log(`${chalk47.bold("next:")} ${nextVersion ?? chalk47.dim("none")}`);
|
|
4373
4385
|
}
|
|
4374
4386
|
|
|
4375
4387
|
// src/commands/registerDevlog.ts
|
|
@@ -4392,7 +4404,7 @@ function registerDevlog(program2) {
|
|
|
4392
4404
|
|
|
4393
4405
|
// src/commands/jira/acceptanceCriteria.ts
|
|
4394
4406
|
import { execSync as execSync20 } from "child_process";
|
|
4395
|
-
import
|
|
4407
|
+
import chalk48 from "chalk";
|
|
4396
4408
|
|
|
4397
4409
|
// src/commands/jira/adfToText.ts
|
|
4398
4410
|
function renderInline(node) {
|
|
@@ -4467,21 +4479,21 @@ function acceptanceCriteria(issueKey) {
|
|
|
4467
4479
|
const stderr = error.stderr;
|
|
4468
4480
|
if (stderr.includes("unauthorized")) {
|
|
4469
4481
|
console.error(
|
|
4470
|
-
|
|
4482
|
+
chalk48.red("Jira authentication expired."),
|
|
4471
4483
|
"Run",
|
|
4472
|
-
|
|
4484
|
+
chalk48.cyan("assist jira auth"),
|
|
4473
4485
|
"to re-authenticate."
|
|
4474
4486
|
);
|
|
4475
4487
|
process.exit(1);
|
|
4476
4488
|
}
|
|
4477
4489
|
}
|
|
4478
|
-
console.error(
|
|
4490
|
+
console.error(chalk48.red(`Failed to fetch ${issueKey}.`));
|
|
4479
4491
|
process.exit(1);
|
|
4480
4492
|
}
|
|
4481
4493
|
const parsed = JSON.parse(result);
|
|
4482
4494
|
const acValue = parsed?.fields?.[field];
|
|
4483
4495
|
if (!acValue) {
|
|
4484
|
-
console.log(
|
|
4496
|
+
console.log(chalk48.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
4485
4497
|
return;
|
|
4486
4498
|
}
|
|
4487
4499
|
if (typeof acValue === "string") {
|
|
@@ -4500,7 +4512,7 @@ import { execSync as execSync21 } from "child_process";
|
|
|
4500
4512
|
import Enquirer from "enquirer";
|
|
4501
4513
|
|
|
4502
4514
|
// src/shared/loadJson.ts
|
|
4503
|
-
import { existsSync as existsSync20, mkdirSync as mkdirSync5, readFileSync as readFileSync18, writeFileSync as
|
|
4515
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync5, readFileSync as readFileSync18, writeFileSync as writeFileSync17 } from "fs";
|
|
4504
4516
|
import { homedir as homedir6 } from "os";
|
|
4505
4517
|
import { join as join16 } from "path";
|
|
4506
4518
|
function getStoreDir() {
|
|
@@ -4510,10 +4522,10 @@ function getStorePath(filename) {
|
|
|
4510
4522
|
return join16(getStoreDir(), filename);
|
|
4511
4523
|
}
|
|
4512
4524
|
function loadJson(filename) {
|
|
4513
|
-
const
|
|
4514
|
-
if (existsSync20(
|
|
4525
|
+
const path42 = getStorePath(filename);
|
|
4526
|
+
if (existsSync20(path42)) {
|
|
4515
4527
|
try {
|
|
4516
|
-
return JSON.parse(readFileSync18(
|
|
4528
|
+
return JSON.parse(readFileSync18(path42, "utf-8"));
|
|
4517
4529
|
} catch {
|
|
4518
4530
|
return {};
|
|
4519
4531
|
}
|
|
@@ -4525,7 +4537,7 @@ function saveJson(filename, data) {
|
|
|
4525
4537
|
if (!existsSync20(dir)) {
|
|
4526
4538
|
mkdirSync5(dir, { recursive: true });
|
|
4527
4539
|
}
|
|
4528
|
-
|
|
4540
|
+
writeFileSync17(getStorePath(filename), JSON.stringify(data, null, 2));
|
|
4529
4541
|
}
|
|
4530
4542
|
|
|
4531
4543
|
// src/commands/jira/jiraAuth.ts
|
|
@@ -4580,7 +4592,7 @@ function registerJira(program2) {
|
|
|
4580
4592
|
|
|
4581
4593
|
// src/commands/netframework/buildTree.ts
|
|
4582
4594
|
import { readFileSync as readFileSync19 } from "fs";
|
|
4583
|
-
import
|
|
4595
|
+
import path21 from "path";
|
|
4584
4596
|
var PROJECT_REF_RE = /<ProjectReference\s+Include="([^"]+)"/g;
|
|
4585
4597
|
function getProjectRefs(csprojPath) {
|
|
4586
4598
|
const content = readFileSync19(csprojPath, "utf-8");
|
|
@@ -4591,14 +4603,14 @@ function getProjectRefs(csprojPath) {
|
|
|
4591
4603
|
return refs;
|
|
4592
4604
|
}
|
|
4593
4605
|
function buildTree(csprojPath, repoRoot, visited = /* @__PURE__ */ new Set()) {
|
|
4594
|
-
const abs =
|
|
4595
|
-
const rel =
|
|
4606
|
+
const abs = path21.resolve(csprojPath);
|
|
4607
|
+
const rel = path21.relative(repoRoot, abs);
|
|
4596
4608
|
const node = { path: abs, relativePath: rel, children: [] };
|
|
4597
4609
|
if (visited.has(abs)) return node;
|
|
4598
4610
|
visited.add(abs);
|
|
4599
|
-
const dir =
|
|
4611
|
+
const dir = path21.dirname(abs);
|
|
4600
4612
|
for (const ref of getProjectRefs(abs)) {
|
|
4601
|
-
const childAbs =
|
|
4613
|
+
const childAbs = path21.resolve(dir, ref);
|
|
4602
4614
|
try {
|
|
4603
4615
|
readFileSync19(childAbs);
|
|
4604
4616
|
node.children.push(buildTree(childAbs, repoRoot, visited));
|
|
@@ -4626,7 +4638,7 @@ function collectAllDeps(node) {
|
|
|
4626
4638
|
|
|
4627
4639
|
// src/commands/netframework/findContainingSolutions.ts
|
|
4628
4640
|
import { readdirSync as readdirSync2, readFileSync as readFileSync20, statSync } from "fs";
|
|
4629
|
-
import
|
|
4641
|
+
import path22 from "path";
|
|
4630
4642
|
function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
4631
4643
|
if (depth > maxDepth) return [];
|
|
4632
4644
|
const results = [];
|
|
@@ -4639,7 +4651,7 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
|
4639
4651
|
for (const entry of entries) {
|
|
4640
4652
|
if (entry.startsWith(".") || entry === "node_modules" || entry === "packages")
|
|
4641
4653
|
continue;
|
|
4642
|
-
const full =
|
|
4654
|
+
const full = path22.join(dir, entry);
|
|
4643
4655
|
try {
|
|
4644
4656
|
const stat = statSync(full);
|
|
4645
4657
|
if (stat.isFile() && entry.endsWith(".sln")) {
|
|
@@ -4653,8 +4665,8 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
|
4653
4665
|
return results;
|
|
4654
4666
|
}
|
|
4655
4667
|
function findContainingSolutions(csprojPath, repoRoot) {
|
|
4656
|
-
const csprojAbs =
|
|
4657
|
-
const csprojBasename =
|
|
4668
|
+
const csprojAbs = path22.resolve(csprojPath);
|
|
4669
|
+
const csprojBasename = path22.basename(csprojAbs);
|
|
4658
4670
|
const slnFiles = findSlnFiles(repoRoot, 3);
|
|
4659
4671
|
const matches = [];
|
|
4660
4672
|
const pattern2 = new RegExp(`[\\\\"/]${escapeRegex(csprojBasename)}"`);
|
|
@@ -4662,7 +4674,7 @@ function findContainingSolutions(csprojPath, repoRoot) {
|
|
|
4662
4674
|
try {
|
|
4663
4675
|
const content = readFileSync20(sln, "utf-8");
|
|
4664
4676
|
if (pattern2.test(content)) {
|
|
4665
|
-
matches.push(
|
|
4677
|
+
matches.push(path22.relative(repoRoot, sln));
|
|
4666
4678
|
}
|
|
4667
4679
|
} catch {
|
|
4668
4680
|
}
|
|
@@ -4674,30 +4686,30 @@ function escapeRegex(s) {
|
|
|
4674
4686
|
}
|
|
4675
4687
|
|
|
4676
4688
|
// src/commands/netframework/printTree.ts
|
|
4677
|
-
import
|
|
4689
|
+
import chalk49 from "chalk";
|
|
4678
4690
|
function printNodes(nodes, prefix2) {
|
|
4679
4691
|
for (let i = 0; i < nodes.length; i++) {
|
|
4680
4692
|
const isLast = i === nodes.length - 1;
|
|
4681
4693
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
4682
4694
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
4683
4695
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
4684
|
-
const label2 = isMissing ?
|
|
4696
|
+
const label2 = isMissing ? chalk49.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
4685
4697
|
console.log(`${prefix2}${connector}${label2}`);
|
|
4686
4698
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
4687
4699
|
}
|
|
4688
4700
|
}
|
|
4689
4701
|
function printTree(tree, totalCount, solutions) {
|
|
4690
|
-
console.log(
|
|
4691
|
-
console.log(
|
|
4702
|
+
console.log(chalk49.bold("\nProject Dependency Tree"));
|
|
4703
|
+
console.log(chalk49.cyan(tree.relativePath));
|
|
4692
4704
|
printNodes(tree.children, "");
|
|
4693
|
-
console.log(
|
|
4705
|
+
console.log(chalk49.dim(`
|
|
4694
4706
|
${totalCount} projects total (including root)`));
|
|
4695
|
-
console.log(
|
|
4707
|
+
console.log(chalk49.bold("\nSolution Membership"));
|
|
4696
4708
|
if (solutions.length === 0) {
|
|
4697
|
-
console.log(
|
|
4709
|
+
console.log(chalk49.yellow(" Not found in any .sln"));
|
|
4698
4710
|
} else {
|
|
4699
4711
|
for (const sln of solutions) {
|
|
4700
|
-
console.log(` ${
|
|
4712
|
+
console.log(` ${chalk49.green(sln)}`);
|
|
4701
4713
|
}
|
|
4702
4714
|
}
|
|
4703
4715
|
console.log();
|
|
@@ -4725,33 +4737,33 @@ function printJson(tree, totalCount, solutions) {
|
|
|
4725
4737
|
|
|
4726
4738
|
// src/commands/netframework/resolveCsproj.ts
|
|
4727
4739
|
import { existsSync as existsSync22 } from "fs";
|
|
4728
|
-
import
|
|
4729
|
-
import
|
|
4740
|
+
import path24 from "path";
|
|
4741
|
+
import chalk50 from "chalk";
|
|
4730
4742
|
|
|
4731
4743
|
// src/commands/netframework/findRepoRoot.ts
|
|
4732
4744
|
import { existsSync as existsSync21 } from "fs";
|
|
4733
|
-
import
|
|
4745
|
+
import path23 from "path";
|
|
4734
4746
|
function findRepoRoot(dir) {
|
|
4735
4747
|
let current = dir;
|
|
4736
|
-
while (current !==
|
|
4737
|
-
if (existsSync21(
|
|
4748
|
+
while (current !== path23.dirname(current)) {
|
|
4749
|
+
if (existsSync21(path23.join(current, ".git"))) {
|
|
4738
4750
|
return current;
|
|
4739
4751
|
}
|
|
4740
|
-
current =
|
|
4752
|
+
current = path23.dirname(current);
|
|
4741
4753
|
}
|
|
4742
4754
|
return null;
|
|
4743
4755
|
}
|
|
4744
4756
|
|
|
4745
4757
|
// src/commands/netframework/resolveCsproj.ts
|
|
4746
4758
|
function resolveCsproj(csprojPath) {
|
|
4747
|
-
const resolved =
|
|
4759
|
+
const resolved = path24.resolve(csprojPath);
|
|
4748
4760
|
if (!existsSync22(resolved)) {
|
|
4749
|
-
console.error(
|
|
4761
|
+
console.error(chalk50.red(`File not found: ${resolved}`));
|
|
4750
4762
|
process.exit(1);
|
|
4751
4763
|
}
|
|
4752
|
-
const repoRoot = findRepoRoot(
|
|
4764
|
+
const repoRoot = findRepoRoot(path24.dirname(resolved));
|
|
4753
4765
|
if (!repoRoot) {
|
|
4754
|
-
console.error(
|
|
4766
|
+
console.error(chalk50.red("Could not find git repository root"));
|
|
4755
4767
|
process.exit(1);
|
|
4756
4768
|
}
|
|
4757
4769
|
return { resolved, repoRoot };
|
|
@@ -4771,12 +4783,12 @@ async function deps(csprojPath, options2) {
|
|
|
4771
4783
|
}
|
|
4772
4784
|
|
|
4773
4785
|
// src/commands/netframework/inSln.ts
|
|
4774
|
-
import
|
|
4786
|
+
import chalk51 from "chalk";
|
|
4775
4787
|
async function inSln(csprojPath) {
|
|
4776
4788
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
4777
4789
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
4778
4790
|
if (solutions.length === 0) {
|
|
4779
|
-
console.log(
|
|
4791
|
+
console.log(chalk51.yellow("Not found in any .sln file"));
|
|
4780
4792
|
process.exit(1);
|
|
4781
4793
|
}
|
|
4782
4794
|
for (const sln of solutions) {
|
|
@@ -4792,7 +4804,7 @@ function registerNetframework(program2) {
|
|
|
4792
4804
|
}
|
|
4793
4805
|
|
|
4794
4806
|
// src/commands/news/add/index.ts
|
|
4795
|
-
import
|
|
4807
|
+
import chalk52 from "chalk";
|
|
4796
4808
|
import enquirer5 from "enquirer";
|
|
4797
4809
|
async function add2(url) {
|
|
4798
4810
|
if (!url) {
|
|
@@ -4815,17 +4827,17 @@ async function add2(url) {
|
|
|
4815
4827
|
const news = config.news ?? {};
|
|
4816
4828
|
const feeds = news.feeds ?? [];
|
|
4817
4829
|
if (feeds.includes(url)) {
|
|
4818
|
-
console.log(
|
|
4830
|
+
console.log(chalk52.yellow("Feed already exists in config"));
|
|
4819
4831
|
return;
|
|
4820
4832
|
}
|
|
4821
4833
|
feeds.push(url);
|
|
4822
4834
|
config.news = { ...news, feeds };
|
|
4823
4835
|
saveGlobalConfig(config);
|
|
4824
|
-
console.log(
|
|
4836
|
+
console.log(chalk52.green(`Added feed: ${url}`));
|
|
4825
4837
|
}
|
|
4826
4838
|
|
|
4827
4839
|
// src/commands/news/web/handleRequest.ts
|
|
4828
|
-
import
|
|
4840
|
+
import chalk53 from "chalk";
|
|
4829
4841
|
|
|
4830
4842
|
// src/commands/news/web/shared.ts
|
|
4831
4843
|
import { decodeHTML } from "entities";
|
|
@@ -4961,17 +4973,17 @@ function prefetch() {
|
|
|
4961
4973
|
const config = loadConfig();
|
|
4962
4974
|
const total = config.news.feeds.length;
|
|
4963
4975
|
if (total === 0) return;
|
|
4964
|
-
process.stdout.write(
|
|
4976
|
+
process.stdout.write(chalk53.dim(`Fetching ${total} feed(s)\u2026 `));
|
|
4965
4977
|
prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
|
|
4966
4978
|
const width = 20;
|
|
4967
4979
|
const filled = Math.round(done2 / t * width);
|
|
4968
4980
|
const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
|
|
4969
4981
|
process.stdout.write(
|
|
4970
|
-
`\r${
|
|
4982
|
+
`\r${chalk53.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
|
|
4971
4983
|
);
|
|
4972
4984
|
}).then((items) => {
|
|
4973
4985
|
process.stdout.write(
|
|
4974
|
-
`\r${
|
|
4986
|
+
`\r${chalk53.green(`Fetched ${items.length} items from ${total} feed(s)`)}
|
|
4975
4987
|
`
|
|
4976
4988
|
);
|
|
4977
4989
|
cachedItems = items;
|
|
@@ -5017,7 +5029,7 @@ function registerNews(program2) {
|
|
|
5017
5029
|
|
|
5018
5030
|
// src/commands/prs/comment.ts
|
|
5019
5031
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
5020
|
-
import { unlinkSync as unlinkSync3, writeFileSync as
|
|
5032
|
+
import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync18 } from "fs";
|
|
5021
5033
|
import { tmpdir as tmpdir2 } from "os";
|
|
5022
5034
|
import { join as join17 } from "path";
|
|
5023
5035
|
|
|
@@ -5086,13 +5098,13 @@ function validateLine(line) {
|
|
|
5086
5098
|
process.exit(1);
|
|
5087
5099
|
}
|
|
5088
5100
|
}
|
|
5089
|
-
function comment(
|
|
5101
|
+
function comment(path42, line, body) {
|
|
5090
5102
|
validateBody(body);
|
|
5091
5103
|
validateLine(line);
|
|
5092
5104
|
try {
|
|
5093
5105
|
const prId = getCurrentPrNodeId();
|
|
5094
5106
|
const queryFile = join17(tmpdir2(), `gh-query-${Date.now()}.graphql`);
|
|
5095
|
-
|
|
5107
|
+
writeFileSync18(queryFile, MUTATION);
|
|
5096
5108
|
try {
|
|
5097
5109
|
const result = spawnSync2(
|
|
5098
5110
|
"gh",
|
|
@@ -5106,7 +5118,7 @@ function comment(path43, line, body) {
|
|
|
5106
5118
|
"-f",
|
|
5107
5119
|
`body=${body}`,
|
|
5108
5120
|
"-f",
|
|
5109
|
-
`path=${
|
|
5121
|
+
`path=${path42}`,
|
|
5110
5122
|
"-F",
|
|
5111
5123
|
`line=${line}`
|
|
5112
5124
|
],
|
|
@@ -5115,7 +5127,7 @@ function comment(path43, line, body) {
|
|
|
5115
5127
|
if (result.status !== 0) {
|
|
5116
5128
|
throw new Error(result.stderr || result.stdout);
|
|
5117
5129
|
}
|
|
5118
|
-
console.log(`Added review comment on ${
|
|
5130
|
+
console.log(`Added review comment on ${path42}:${line}`);
|
|
5119
5131
|
} finally {
|
|
5120
5132
|
unlinkSync3(queryFile);
|
|
5121
5133
|
}
|
|
@@ -5134,7 +5146,7 @@ import { execSync as execSync24 } from "child_process";
|
|
|
5134
5146
|
|
|
5135
5147
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
5136
5148
|
import { execSync as execSync23 } from "child_process";
|
|
5137
|
-
import { unlinkSync as unlinkSync5, writeFileSync as
|
|
5149
|
+
import { unlinkSync as unlinkSync5, writeFileSync as writeFileSync19 } from "fs";
|
|
5138
5150
|
import { tmpdir as tmpdir3 } from "os";
|
|
5139
5151
|
import { join as join19 } from "path";
|
|
5140
5152
|
|
|
@@ -5171,7 +5183,7 @@ function replyToComment(org, repo, prNumber, commentId, message) {
|
|
|
5171
5183
|
function resolveThread(threadId) {
|
|
5172
5184
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
5173
5185
|
const queryFile = join19(tmpdir3(), `gh-mutation-${Date.now()}.graphql`);
|
|
5174
|
-
|
|
5186
|
+
writeFileSync19(queryFile, mutation);
|
|
5175
5187
|
try {
|
|
5176
5188
|
execSync23(
|
|
5177
5189
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
@@ -5252,19 +5264,19 @@ function fixed(commentId, sha) {
|
|
|
5252
5264
|
}
|
|
5253
5265
|
|
|
5254
5266
|
// src/commands/prs/listComments/index.ts
|
|
5255
|
-
import { existsSync as existsSync24, mkdirSync as mkdirSync6, writeFileSync as
|
|
5267
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync6, writeFileSync as writeFileSync21 } from "fs";
|
|
5256
5268
|
import { join as join21 } from "path";
|
|
5257
5269
|
import { stringify } from "yaml";
|
|
5258
5270
|
|
|
5259
5271
|
// src/commands/prs/fetchThreadIds.ts
|
|
5260
5272
|
import { execSync as execSync25 } from "child_process";
|
|
5261
|
-
import { unlinkSync as unlinkSync6, writeFileSync as
|
|
5273
|
+
import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync20 } from "fs";
|
|
5262
5274
|
import { tmpdir as tmpdir4 } from "os";
|
|
5263
5275
|
import { join as join20 } from "path";
|
|
5264
5276
|
var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
|
|
5265
5277
|
function fetchThreadIds(org, repo, prNumber) {
|
|
5266
5278
|
const queryFile = join20(tmpdir4(), `gh-query-${Date.now()}.graphql`);
|
|
5267
|
-
|
|
5279
|
+
writeFileSync20(queryFile, THREAD_QUERY);
|
|
5268
5280
|
try {
|
|
5269
5281
|
const result = execSync25(
|
|
5270
5282
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
@@ -5332,20 +5344,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
5332
5344
|
}
|
|
5333
5345
|
|
|
5334
5346
|
// src/commands/prs/listComments/printComments.ts
|
|
5335
|
-
import
|
|
5347
|
+
import chalk54 from "chalk";
|
|
5336
5348
|
function formatForHuman(comment2) {
|
|
5337
5349
|
if (comment2.type === "review") {
|
|
5338
|
-
const stateColor = comment2.state === "APPROVED" ?
|
|
5350
|
+
const stateColor = comment2.state === "APPROVED" ? chalk54.green : comment2.state === "CHANGES_REQUESTED" ? chalk54.red : chalk54.yellow;
|
|
5339
5351
|
return [
|
|
5340
|
-
`${
|
|
5352
|
+
`${chalk54.cyan("Review")} by ${chalk54.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
|
|
5341
5353
|
comment2.body,
|
|
5342
5354
|
""
|
|
5343
5355
|
].join("\n");
|
|
5344
5356
|
}
|
|
5345
5357
|
const location = comment2.line ? `:${comment2.line}` : "";
|
|
5346
5358
|
return [
|
|
5347
|
-
`${
|
|
5348
|
-
|
|
5359
|
+
`${chalk54.cyan("Line comment")} by ${chalk54.bold(comment2.user)} on ${chalk54.dim(`${comment2.path}${location}`)}`,
|
|
5360
|
+
chalk54.dim(comment2.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
5349
5361
|
comment2.body,
|
|
5350
5362
|
""
|
|
5351
5363
|
].join("\n");
|
|
@@ -5387,7 +5399,7 @@ function writeCommentsCache(prNumber, comments) {
|
|
|
5387
5399
|
comments
|
|
5388
5400
|
};
|
|
5389
5401
|
const cachePath = join21(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
5390
|
-
|
|
5402
|
+
writeFileSync21(cachePath, stringify(cacheData));
|
|
5391
5403
|
}
|
|
5392
5404
|
function handleKnownErrors(error) {
|
|
5393
5405
|
if (isGhNotInstalled(error)) {
|
|
@@ -5435,13 +5447,13 @@ import { execSync as execSync27 } from "child_process";
|
|
|
5435
5447
|
import enquirer6 from "enquirer";
|
|
5436
5448
|
|
|
5437
5449
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
5438
|
-
import
|
|
5450
|
+
import chalk55 from "chalk";
|
|
5439
5451
|
var STATUS_MAP = {
|
|
5440
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
5441
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
5452
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk55.magenta("merged"), date: pr.mergedAt } : null,
|
|
5453
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk55.red("closed"), date: pr.closedAt } : null
|
|
5442
5454
|
};
|
|
5443
5455
|
function defaultStatus(pr) {
|
|
5444
|
-
return { label:
|
|
5456
|
+
return { label: chalk55.green("opened"), date: pr.createdAt };
|
|
5445
5457
|
}
|
|
5446
5458
|
function getStatus2(pr) {
|
|
5447
5459
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -5450,11 +5462,11 @@ function formatDate(dateStr) {
|
|
|
5450
5462
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
5451
5463
|
}
|
|
5452
5464
|
function formatPrHeader(pr, status2) {
|
|
5453
|
-
return `${
|
|
5465
|
+
return `${chalk55.cyan(`#${pr.number}`)} ${pr.title} ${chalk55.dim(`(${pr.author.login},`)} ${status2.label} ${chalk55.dim(`${formatDate(status2.date)})`)}`;
|
|
5454
5466
|
}
|
|
5455
5467
|
function logPrDetails(pr) {
|
|
5456
5468
|
console.log(
|
|
5457
|
-
|
|
5469
|
+
chalk55.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
5458
5470
|
);
|
|
5459
5471
|
console.log();
|
|
5460
5472
|
}
|
|
@@ -5614,17 +5626,17 @@ function registerPrs(program2) {
|
|
|
5614
5626
|
prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
|
|
5615
5627
|
wontfix(Number.parseInt(commentId, 10), reason);
|
|
5616
5628
|
});
|
|
5617
|
-
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((
|
|
5618
|
-
comment(
|
|
5629
|
+
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path42, line, body) => {
|
|
5630
|
+
comment(path42, Number.parseInt(line, 10), body);
|
|
5619
5631
|
});
|
|
5620
5632
|
}
|
|
5621
5633
|
|
|
5622
5634
|
// src/commands/refactor/check/index.ts
|
|
5623
5635
|
import { spawn as spawn3 } from "child_process";
|
|
5624
|
-
import * as
|
|
5636
|
+
import * as path25 from "path";
|
|
5625
5637
|
|
|
5626
5638
|
// src/commands/refactor/logViolations.ts
|
|
5627
|
-
import
|
|
5639
|
+
import chalk56 from "chalk";
|
|
5628
5640
|
var DEFAULT_MAX_LINES = 100;
|
|
5629
5641
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
5630
5642
|
if (violations.length === 0) {
|
|
@@ -5633,43 +5645,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
5633
5645
|
}
|
|
5634
5646
|
return;
|
|
5635
5647
|
}
|
|
5636
|
-
console.error(
|
|
5648
|
+
console.error(chalk56.red(`
|
|
5637
5649
|
Refactor check failed:
|
|
5638
5650
|
`));
|
|
5639
|
-
console.error(
|
|
5651
|
+
console.error(chalk56.red(` The following files exceed ${maxLines} lines:
|
|
5640
5652
|
`));
|
|
5641
5653
|
for (const violation of violations) {
|
|
5642
|
-
console.error(
|
|
5654
|
+
console.error(chalk56.red(` ${violation.file} (${violation.lines} lines)`));
|
|
5643
5655
|
}
|
|
5644
5656
|
console.error(
|
|
5645
|
-
|
|
5657
|
+
chalk56.yellow(
|
|
5646
5658
|
`
|
|
5647
5659
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
5648
5660
|
way to refactor it, ignore it with:
|
|
5649
5661
|
`
|
|
5650
5662
|
)
|
|
5651
5663
|
);
|
|
5652
|
-
console.error(
|
|
5664
|
+
console.error(chalk56.gray(` assist refactor ignore <file>
|
|
5653
5665
|
`));
|
|
5654
5666
|
if (process.env.CLAUDECODE) {
|
|
5655
|
-
console.error(
|
|
5667
|
+
console.error(chalk56.cyan(`
|
|
5656
5668
|
## Extracting Code to New Files
|
|
5657
5669
|
`));
|
|
5658
5670
|
console.error(
|
|
5659
|
-
|
|
5671
|
+
chalk56.cyan(
|
|
5660
5672
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
5661
5673
|
`
|
|
5662
5674
|
)
|
|
5663
5675
|
);
|
|
5664
5676
|
console.error(
|
|
5665
|
-
|
|
5677
|
+
chalk56.cyan(
|
|
5666
5678
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
5667
5679
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
5668
5680
|
`
|
|
5669
5681
|
)
|
|
5670
5682
|
);
|
|
5671
5683
|
console.error(
|
|
5672
|
-
|
|
5684
|
+
chalk56.cyan(
|
|
5673
5685
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
5674
5686
|
domains, move it to a common/shared folder.
|
|
5675
5687
|
`
|
|
@@ -5680,17 +5692,17 @@ Refactor check failed:
|
|
|
5680
5692
|
|
|
5681
5693
|
// src/commands/refactor/check/getViolations/index.ts
|
|
5682
5694
|
import { execSync as execSync29 } from "child_process";
|
|
5683
|
-
import
|
|
5695
|
+
import fs16 from "fs";
|
|
5684
5696
|
import { minimatch as minimatch4 } from "minimatch";
|
|
5685
5697
|
|
|
5686
5698
|
// src/commands/refactor/check/getViolations/getIgnoredFiles.ts
|
|
5687
|
-
import
|
|
5699
|
+
import fs15 from "fs";
|
|
5688
5700
|
var REFACTOR_YML_PATH = "refactor.yml";
|
|
5689
5701
|
function parseRefactorYml() {
|
|
5690
|
-
if (!
|
|
5702
|
+
if (!fs15.existsSync(REFACTOR_YML_PATH)) {
|
|
5691
5703
|
return [];
|
|
5692
5704
|
}
|
|
5693
|
-
const content =
|
|
5705
|
+
const content = fs15.readFileSync(REFACTOR_YML_PATH, "utf-8");
|
|
5694
5706
|
const entries = [];
|
|
5695
5707
|
const lines = content.split("\n");
|
|
5696
5708
|
let currentEntry = {};
|
|
@@ -5720,7 +5732,7 @@ function getIgnoredFiles() {
|
|
|
5720
5732
|
|
|
5721
5733
|
// src/commands/refactor/check/getViolations/index.ts
|
|
5722
5734
|
function countLines(filePath) {
|
|
5723
|
-
const content =
|
|
5735
|
+
const content = fs16.readFileSync(filePath, "utf-8");
|
|
5724
5736
|
return content.split("\n").length;
|
|
5725
5737
|
}
|
|
5726
5738
|
function getGitFiles(options2) {
|
|
@@ -5798,7 +5810,7 @@ ${failed.length} verify script(s) failed:`);
|
|
|
5798
5810
|
async function runVerifyQuietly() {
|
|
5799
5811
|
const result = findPackageJsonWithVerifyScripts(process.cwd());
|
|
5800
5812
|
if (!result) return true;
|
|
5801
|
-
const packageDir =
|
|
5813
|
+
const packageDir = path25.dirname(result.packageJsonPath);
|
|
5802
5814
|
const results = await Promise.all(
|
|
5803
5815
|
result.verifyScripts.map((script) => runScript(script, packageDir))
|
|
5804
5816
|
);
|
|
@@ -5824,64 +5836,64 @@ async function check(pattern2, options2) {
|
|
|
5824
5836
|
}
|
|
5825
5837
|
|
|
5826
5838
|
// src/commands/refactor/ignore.ts
|
|
5827
|
-
import
|
|
5828
|
-
import
|
|
5839
|
+
import fs17 from "fs";
|
|
5840
|
+
import chalk57 from "chalk";
|
|
5829
5841
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
5830
5842
|
function ignore(file) {
|
|
5831
|
-
if (!
|
|
5832
|
-
console.error(
|
|
5843
|
+
if (!fs17.existsSync(file)) {
|
|
5844
|
+
console.error(chalk57.red(`Error: File does not exist: ${file}`));
|
|
5833
5845
|
process.exit(1);
|
|
5834
5846
|
}
|
|
5835
|
-
const content =
|
|
5847
|
+
const content = fs17.readFileSync(file, "utf-8");
|
|
5836
5848
|
const lineCount = content.split("\n").length;
|
|
5837
5849
|
const maxLines = lineCount + 10;
|
|
5838
5850
|
const entry = `- file: ${file}
|
|
5839
5851
|
maxLines: ${maxLines}
|
|
5840
5852
|
`;
|
|
5841
|
-
if (
|
|
5842
|
-
const existing =
|
|
5843
|
-
|
|
5853
|
+
if (fs17.existsSync(REFACTOR_YML_PATH2)) {
|
|
5854
|
+
const existing = fs17.readFileSync(REFACTOR_YML_PATH2, "utf-8");
|
|
5855
|
+
fs17.writeFileSync(REFACTOR_YML_PATH2, existing + entry);
|
|
5844
5856
|
} else {
|
|
5845
|
-
|
|
5857
|
+
fs17.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
5846
5858
|
}
|
|
5847
5859
|
console.log(
|
|
5848
|
-
|
|
5860
|
+
chalk57.green(
|
|
5849
5861
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
5850
5862
|
)
|
|
5851
5863
|
);
|
|
5852
5864
|
}
|
|
5853
5865
|
|
|
5854
5866
|
// src/commands/refactor/rename/index.ts
|
|
5855
|
-
import
|
|
5856
|
-
import
|
|
5867
|
+
import path26 from "path";
|
|
5868
|
+
import chalk58 from "chalk";
|
|
5857
5869
|
import { Project as Project2 } from "ts-morph";
|
|
5858
5870
|
async function rename(source, destination, options2 = {}) {
|
|
5859
|
-
const sourcePath =
|
|
5860
|
-
const destPath =
|
|
5871
|
+
const sourcePath = path26.resolve(source);
|
|
5872
|
+
const destPath = path26.resolve(destination);
|
|
5861
5873
|
const cwd = process.cwd();
|
|
5862
|
-
const relSource =
|
|
5863
|
-
const relDest =
|
|
5874
|
+
const relSource = path26.relative(cwd, sourcePath);
|
|
5875
|
+
const relDest = path26.relative(cwd, destPath);
|
|
5864
5876
|
const project = new Project2({
|
|
5865
|
-
tsConfigFilePath:
|
|
5877
|
+
tsConfigFilePath: path26.resolve("tsconfig.json")
|
|
5866
5878
|
});
|
|
5867
5879
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
5868
5880
|
if (!sourceFile) {
|
|
5869
|
-
console.log(
|
|
5881
|
+
console.log(chalk58.red(`File not found in project: ${source}`));
|
|
5870
5882
|
process.exit(1);
|
|
5871
5883
|
}
|
|
5872
|
-
console.log(
|
|
5884
|
+
console.log(chalk58.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
5873
5885
|
if (options2.apply) {
|
|
5874
5886
|
sourceFile.move(destPath);
|
|
5875
5887
|
await project.save();
|
|
5876
|
-
console.log(
|
|
5888
|
+
console.log(chalk58.green("Done"));
|
|
5877
5889
|
} else {
|
|
5878
|
-
console.log(
|
|
5890
|
+
console.log(chalk58.dim("Dry run. Use --apply to execute."));
|
|
5879
5891
|
}
|
|
5880
5892
|
}
|
|
5881
5893
|
|
|
5882
5894
|
// src/commands/refactor/renameSymbol/index.ts
|
|
5883
|
-
import
|
|
5884
|
-
import
|
|
5895
|
+
import path28 from "path";
|
|
5896
|
+
import chalk59 from "chalk";
|
|
5885
5897
|
import { Project as Project3 } from "ts-morph";
|
|
5886
5898
|
|
|
5887
5899
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
@@ -5909,12 +5921,12 @@ function findSymbol(sourceFile, symbolName) {
|
|
|
5909
5921
|
}
|
|
5910
5922
|
|
|
5911
5923
|
// src/commands/refactor/renameSymbol/groupReferences.ts
|
|
5912
|
-
import
|
|
5924
|
+
import path27 from "path";
|
|
5913
5925
|
function groupReferences(symbol, cwd) {
|
|
5914
5926
|
const refs = symbol.findReferencesAsNodes();
|
|
5915
5927
|
const grouped = /* @__PURE__ */ new Map();
|
|
5916
5928
|
for (const ref of refs) {
|
|
5917
|
-
const refFile =
|
|
5929
|
+
const refFile = path27.relative(cwd, ref.getSourceFile().getFilePath());
|
|
5918
5930
|
const lines = grouped.get(refFile) ?? [];
|
|
5919
5931
|
if (!grouped.has(refFile)) grouped.set(refFile, lines);
|
|
5920
5932
|
lines.push(ref.getStartLineNumber());
|
|
@@ -5924,47 +5936,47 @@ function groupReferences(symbol, cwd) {
|
|
|
5924
5936
|
|
|
5925
5937
|
// src/commands/refactor/renameSymbol/index.ts
|
|
5926
5938
|
async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
5927
|
-
const filePath =
|
|
5928
|
-
const tsConfigPath =
|
|
5939
|
+
const filePath = path28.resolve(file);
|
|
5940
|
+
const tsConfigPath = path28.resolve("tsconfig.json");
|
|
5929
5941
|
const cwd = process.cwd();
|
|
5930
5942
|
const project = new Project3({ tsConfigFilePath: tsConfigPath });
|
|
5931
5943
|
const sourceFile = project.getSourceFile(filePath);
|
|
5932
5944
|
if (!sourceFile) {
|
|
5933
|
-
console.log(
|
|
5945
|
+
console.log(chalk59.red(`File not found in project: ${file}`));
|
|
5934
5946
|
process.exit(1);
|
|
5935
5947
|
}
|
|
5936
5948
|
const symbol = findSymbol(sourceFile, oldName);
|
|
5937
5949
|
if (!symbol) {
|
|
5938
|
-
console.log(
|
|
5950
|
+
console.log(chalk59.red(`Symbol "${oldName}" not found in ${file}`));
|
|
5939
5951
|
process.exit(1);
|
|
5940
5952
|
}
|
|
5941
5953
|
const grouped = groupReferences(symbol, cwd);
|
|
5942
5954
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
5943
5955
|
console.log(
|
|
5944
|
-
|
|
5956
|
+
chalk59.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
5945
5957
|
`)
|
|
5946
5958
|
);
|
|
5947
5959
|
for (const [refFile, lines] of grouped) {
|
|
5948
5960
|
console.log(
|
|
5949
|
-
` ${
|
|
5961
|
+
` ${chalk59.dim(refFile)}: lines ${chalk59.cyan(lines.join(", "))}`
|
|
5950
5962
|
);
|
|
5951
5963
|
}
|
|
5952
5964
|
if (options2.apply) {
|
|
5953
5965
|
symbol.rename(newName);
|
|
5954
5966
|
await project.save();
|
|
5955
|
-
console.log(
|
|
5967
|
+
console.log(chalk59.green(`
|
|
5956
5968
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
5957
5969
|
} else {
|
|
5958
|
-
console.log(
|
|
5970
|
+
console.log(chalk59.dim("\nDry run. Use --apply to execute."));
|
|
5959
5971
|
}
|
|
5960
5972
|
}
|
|
5961
5973
|
|
|
5962
5974
|
// src/commands/refactor/restructure/index.ts
|
|
5963
|
-
import
|
|
5964
|
-
import
|
|
5975
|
+
import path37 from "path";
|
|
5976
|
+
import chalk62 from "chalk";
|
|
5965
5977
|
|
|
5966
5978
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
5967
|
-
import
|
|
5979
|
+
import path29 from "path";
|
|
5968
5980
|
import ts7 from "typescript";
|
|
5969
5981
|
|
|
5970
5982
|
// src/commands/refactor/restructure/buildImportGraph/getImportSpecifiers.ts
|
|
@@ -5991,7 +6003,7 @@ function loadParsedConfig(tsConfigPath) {
|
|
|
5991
6003
|
return ts7.parseJsonConfigFileContent(
|
|
5992
6004
|
configFile.config,
|
|
5993
6005
|
ts7.sys,
|
|
5994
|
-
|
|
6006
|
+
path29.dirname(tsConfigPath)
|
|
5995
6007
|
);
|
|
5996
6008
|
}
|
|
5997
6009
|
function addToSetMap(map, key, value) {
|
|
@@ -6007,7 +6019,7 @@ function resolveImport(specifier, filePath, options2) {
|
|
|
6007
6019
|
const resolved = ts7.resolveModuleName(specifier, filePath, options2, ts7.sys);
|
|
6008
6020
|
const resolvedPath = resolved.resolvedModule?.resolvedFileName;
|
|
6009
6021
|
if (!resolvedPath || resolvedPath.includes("node_modules")) return null;
|
|
6010
|
-
return
|
|
6022
|
+
return path29.resolve(resolvedPath);
|
|
6011
6023
|
}
|
|
6012
6024
|
function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
6013
6025
|
const parsed = loadParsedConfig(tsConfigPath);
|
|
@@ -6016,7 +6028,7 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
|
6016
6028
|
const importedBy = /* @__PURE__ */ new Map();
|
|
6017
6029
|
const imports = /* @__PURE__ */ new Map();
|
|
6018
6030
|
for (const sourceFile of program2.getSourceFiles()) {
|
|
6019
|
-
const filePath =
|
|
6031
|
+
const filePath = path29.resolve(sourceFile.fileName);
|
|
6020
6032
|
if (filePath.includes("node_modules")) continue;
|
|
6021
6033
|
for (const specifier of getImportSpecifiers(sourceFile)) {
|
|
6022
6034
|
const absTarget = resolveImport(specifier, filePath, parsed.options);
|
|
@@ -6030,12 +6042,12 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
|
6030
6042
|
}
|
|
6031
6043
|
|
|
6032
6044
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
6033
|
-
import
|
|
6045
|
+
import path30 from "path";
|
|
6034
6046
|
function clusterDirectories(graph) {
|
|
6035
6047
|
const dirImportedBy = /* @__PURE__ */ new Map();
|
|
6036
6048
|
for (const edge of graph.edges) {
|
|
6037
|
-
const sourceDir =
|
|
6038
|
-
const targetDir =
|
|
6049
|
+
const sourceDir = path30.dirname(edge.source);
|
|
6050
|
+
const targetDir = path30.dirname(edge.target);
|
|
6039
6051
|
if (sourceDir === targetDir) continue;
|
|
6040
6052
|
if (!graph.files.has(edge.target)) continue;
|
|
6041
6053
|
const existing = dirImportedBy.get(targetDir) ?? /* @__PURE__ */ new Set();
|
|
@@ -6063,20 +6075,20 @@ function clusterDirectories(graph) {
|
|
|
6063
6075
|
return clusters;
|
|
6064
6076
|
}
|
|
6065
6077
|
function isAncestor(ancestor, descendant) {
|
|
6066
|
-
const rel =
|
|
6078
|
+
const rel = path30.relative(ancestor, descendant);
|
|
6067
6079
|
return !rel.startsWith("..") && rel !== "";
|
|
6068
6080
|
}
|
|
6069
6081
|
|
|
6070
6082
|
// src/commands/refactor/restructure/clusterFiles.ts
|
|
6071
|
-
import
|
|
6083
|
+
import path31 from "path";
|
|
6072
6084
|
function findRootParent(file, importedBy, visited) {
|
|
6073
6085
|
const importers = importedBy.get(file);
|
|
6074
6086
|
if (!importers || importers.size !== 1) return file;
|
|
6075
6087
|
const parent = [...importers][0];
|
|
6076
|
-
const parentDir =
|
|
6077
|
-
const fileDir =
|
|
6088
|
+
const parentDir = path31.dirname(parent);
|
|
6089
|
+
const fileDir = path31.dirname(file);
|
|
6078
6090
|
if (parentDir !== fileDir) return file;
|
|
6079
|
-
if (
|
|
6091
|
+
if (path31.basename(parent, path31.extname(parent)) === "index") return file;
|
|
6080
6092
|
if (visited.has(parent)) return file;
|
|
6081
6093
|
visited.add(parent);
|
|
6082
6094
|
return findRootParent(parent, importedBy, visited);
|
|
@@ -6084,16 +6096,16 @@ function findRootParent(file, importedBy, visited) {
|
|
|
6084
6096
|
function clusterFiles(graph) {
|
|
6085
6097
|
const clusters = /* @__PURE__ */ new Map();
|
|
6086
6098
|
for (const file of graph.files) {
|
|
6087
|
-
const basename7 =
|
|
6099
|
+
const basename7 = path31.basename(file, path31.extname(file));
|
|
6088
6100
|
if (basename7 === "index") continue;
|
|
6089
6101
|
const importers = graph.importedBy.get(file);
|
|
6090
6102
|
if (!importers || importers.size !== 1) continue;
|
|
6091
6103
|
const parent = [...importers][0];
|
|
6092
6104
|
if (!graph.files.has(parent)) continue;
|
|
6093
|
-
const parentDir =
|
|
6094
|
-
const fileDir =
|
|
6105
|
+
const parentDir = path31.dirname(parent);
|
|
6106
|
+
const fileDir = path31.dirname(file);
|
|
6095
6107
|
if (parentDir !== fileDir) continue;
|
|
6096
|
-
const parentBasename =
|
|
6108
|
+
const parentBasename = path31.basename(parent, path31.extname(parent));
|
|
6097
6109
|
if (parentBasename === "index") continue;
|
|
6098
6110
|
const root = findRootParent(parent, graph.importedBy, /* @__PURE__ */ new Set([file]));
|
|
6099
6111
|
if (!root || root === file) continue;
|
|
@@ -6105,10 +6117,10 @@ function clusterFiles(graph) {
|
|
|
6105
6117
|
}
|
|
6106
6118
|
|
|
6107
6119
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
6108
|
-
import
|
|
6120
|
+
import path32 from "path";
|
|
6109
6121
|
|
|
6110
6122
|
// src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
|
|
6111
|
-
import
|
|
6123
|
+
import fs18 from "fs";
|
|
6112
6124
|
function getOrCreateList(map, key) {
|
|
6113
6125
|
const list4 = map.get(key) ?? [];
|
|
6114
6126
|
if (!map.has(key)) map.set(key, list4);
|
|
@@ -6127,7 +6139,7 @@ function rewriteSpecifier(content, oldSpecifier, newSpecifier) {
|
|
|
6127
6139
|
return content.replace(pattern2, `$1${newSpecifier}$2`);
|
|
6128
6140
|
}
|
|
6129
6141
|
function applyFileRewrites(file, fileRewrites) {
|
|
6130
|
-
let content =
|
|
6142
|
+
let content = fs18.readFileSync(file, "utf-8");
|
|
6131
6143
|
for (const { oldSpecifier, newSpecifier } of fileRewrites) {
|
|
6132
6144
|
content = rewriteSpecifier(content, oldSpecifier, newSpecifier);
|
|
6133
6145
|
}
|
|
@@ -6159,7 +6171,7 @@ function normalizeSpecifier(rel) {
|
|
|
6159
6171
|
);
|
|
6160
6172
|
}
|
|
6161
6173
|
function computeSpecifier(fromFile, toFile) {
|
|
6162
|
-
return normalizeSpecifier(
|
|
6174
|
+
return normalizeSpecifier(path32.relative(path32.dirname(fromFile), toFile));
|
|
6163
6175
|
}
|
|
6164
6176
|
function isAffected(edge, moveMap) {
|
|
6165
6177
|
return moveMap.has(edge.target) || moveMap.has(edge.source);
|
|
@@ -6203,51 +6215,51 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
6203
6215
|
}
|
|
6204
6216
|
|
|
6205
6217
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
6206
|
-
import
|
|
6207
|
-
import
|
|
6218
|
+
import path33 from "path";
|
|
6219
|
+
import chalk60 from "chalk";
|
|
6208
6220
|
function relPath(filePath) {
|
|
6209
|
-
return
|
|
6221
|
+
return path33.relative(process.cwd(), filePath);
|
|
6210
6222
|
}
|
|
6211
6223
|
function displayMoves(plan) {
|
|
6212
6224
|
if (plan.moves.length === 0) return;
|
|
6213
|
-
console.log(
|
|
6225
|
+
console.log(chalk60.bold("\nFile moves:"));
|
|
6214
6226
|
for (const move of plan.moves) {
|
|
6215
6227
|
console.log(
|
|
6216
|
-
` ${
|
|
6228
|
+
` ${chalk60.red(relPath(move.from))} \u2192 ${chalk60.green(relPath(move.to))}`
|
|
6217
6229
|
);
|
|
6218
|
-
console.log(
|
|
6230
|
+
console.log(chalk60.dim(` ${move.reason}`));
|
|
6219
6231
|
}
|
|
6220
6232
|
}
|
|
6221
6233
|
function displayRewrites(rewrites) {
|
|
6222
6234
|
if (rewrites.length === 0) return;
|
|
6223
6235
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
6224
|
-
console.log(
|
|
6236
|
+
console.log(chalk60.bold(`
|
|
6225
6237
|
Import rewrites (${affectedFiles.size} files):`));
|
|
6226
6238
|
for (const file of affectedFiles) {
|
|
6227
|
-
console.log(` ${
|
|
6239
|
+
console.log(` ${chalk60.cyan(relPath(file))}:`);
|
|
6228
6240
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
6229
6241
|
(r) => r.file === file
|
|
6230
6242
|
)) {
|
|
6231
6243
|
console.log(
|
|
6232
|
-
` ${
|
|
6244
|
+
` ${chalk60.red(`"${oldSpecifier}"`)} \u2192 ${chalk60.green(`"${newSpecifier}"`)}`
|
|
6233
6245
|
);
|
|
6234
6246
|
}
|
|
6235
6247
|
}
|
|
6236
6248
|
}
|
|
6237
6249
|
function displayPlan(plan) {
|
|
6238
6250
|
if (plan.warnings.length > 0) {
|
|
6239
|
-
console.log(
|
|
6240
|
-
for (const w of plan.warnings) console.log(
|
|
6251
|
+
console.log(chalk60.yellow("\nWarnings:"));
|
|
6252
|
+
for (const w of plan.warnings) console.log(chalk60.yellow(` ${w}`));
|
|
6241
6253
|
}
|
|
6242
6254
|
if (plan.newDirectories.length > 0) {
|
|
6243
|
-
console.log(
|
|
6255
|
+
console.log(chalk60.bold("\nNew directories:"));
|
|
6244
6256
|
for (const dir of plan.newDirectories)
|
|
6245
|
-
console.log(
|
|
6257
|
+
console.log(chalk60.green(` ${dir}/`));
|
|
6246
6258
|
}
|
|
6247
6259
|
displayMoves(plan);
|
|
6248
6260
|
displayRewrites(plan.rewrites);
|
|
6249
6261
|
console.log(
|
|
6250
|
-
|
|
6262
|
+
chalk60.dim(
|
|
6251
6263
|
`
|
|
6252
6264
|
Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
|
|
6253
6265
|
)
|
|
@@ -6255,45 +6267,45 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
|
|
|
6255
6267
|
}
|
|
6256
6268
|
|
|
6257
6269
|
// src/commands/refactor/restructure/executePlan.ts
|
|
6258
|
-
import
|
|
6259
|
-
import
|
|
6260
|
-
import
|
|
6270
|
+
import fs19 from "fs";
|
|
6271
|
+
import path34 from "path";
|
|
6272
|
+
import chalk61 from "chalk";
|
|
6261
6273
|
function executePlan(plan) {
|
|
6262
6274
|
const updatedContents = applyRewrites(plan.rewrites);
|
|
6263
6275
|
for (const [file, content] of updatedContents) {
|
|
6264
|
-
|
|
6276
|
+
fs19.writeFileSync(file, content, "utf-8");
|
|
6265
6277
|
console.log(
|
|
6266
|
-
|
|
6278
|
+
chalk61.cyan(` Rewrote imports in ${path34.relative(process.cwd(), file)}`)
|
|
6267
6279
|
);
|
|
6268
6280
|
}
|
|
6269
6281
|
for (const dir of plan.newDirectories) {
|
|
6270
|
-
|
|
6271
|
-
console.log(
|
|
6282
|
+
fs19.mkdirSync(dir, { recursive: true });
|
|
6283
|
+
console.log(chalk61.green(` Created ${path34.relative(process.cwd(), dir)}/`));
|
|
6272
6284
|
}
|
|
6273
6285
|
for (const move of plan.moves) {
|
|
6274
|
-
const targetDir =
|
|
6275
|
-
if (!
|
|
6276
|
-
|
|
6286
|
+
const targetDir = path34.dirname(move.to);
|
|
6287
|
+
if (!fs19.existsSync(targetDir)) {
|
|
6288
|
+
fs19.mkdirSync(targetDir, { recursive: true });
|
|
6277
6289
|
}
|
|
6278
|
-
|
|
6290
|
+
fs19.renameSync(move.from, move.to);
|
|
6279
6291
|
console.log(
|
|
6280
|
-
|
|
6281
|
-
` Moved ${
|
|
6292
|
+
chalk61.white(
|
|
6293
|
+
` Moved ${path34.relative(process.cwd(), move.from)} \u2192 ${path34.relative(process.cwd(), move.to)}`
|
|
6282
6294
|
)
|
|
6283
6295
|
);
|
|
6284
6296
|
}
|
|
6285
|
-
removeEmptyDirectories(plan.moves.map((m) =>
|
|
6297
|
+
removeEmptyDirectories(plan.moves.map((m) => path34.dirname(m.from)));
|
|
6286
6298
|
}
|
|
6287
6299
|
function removeEmptyDirectories(dirs) {
|
|
6288
6300
|
const unique = [...new Set(dirs)];
|
|
6289
6301
|
for (const dir of unique) {
|
|
6290
|
-
if (!
|
|
6291
|
-
const entries =
|
|
6302
|
+
if (!fs19.existsSync(dir)) continue;
|
|
6303
|
+
const entries = fs19.readdirSync(dir);
|
|
6292
6304
|
if (entries.length === 0) {
|
|
6293
|
-
|
|
6305
|
+
fs19.rmdirSync(dir);
|
|
6294
6306
|
console.log(
|
|
6295
|
-
|
|
6296
|
-
` Removed empty directory ${
|
|
6307
|
+
chalk61.dim(
|
|
6308
|
+
` Removed empty directory ${path34.relative(process.cwd(), dir)}`
|
|
6297
6309
|
)
|
|
6298
6310
|
);
|
|
6299
6311
|
}
|
|
@@ -6301,14 +6313,24 @@ function removeEmptyDirectories(dirs) {
|
|
|
6301
6313
|
}
|
|
6302
6314
|
|
|
6303
6315
|
// src/commands/refactor/restructure/planFileMoves/index.ts
|
|
6304
|
-
import
|
|
6305
|
-
|
|
6316
|
+
import path36 from "path";
|
|
6317
|
+
|
|
6318
|
+
// src/commands/refactor/restructure/planFileMoves/shared.ts
|
|
6319
|
+
import fs20 from "fs";
|
|
6320
|
+
function emptyResult() {
|
|
6321
|
+
return { moves: [], directories: [], warnings: [] };
|
|
6322
|
+
}
|
|
6323
|
+
function checkDirConflict(result, label2, dir) {
|
|
6324
|
+
if (!fs20.existsSync(dir)) return false;
|
|
6325
|
+
result.warnings.push(`Skipping ${label2}: directory ${dir} already exists`);
|
|
6326
|
+
return true;
|
|
6327
|
+
}
|
|
6306
6328
|
|
|
6307
6329
|
// src/commands/refactor/restructure/planFileMoves/planDirectoryMoves.ts
|
|
6308
6330
|
import fs21 from "fs";
|
|
6309
|
-
import
|
|
6331
|
+
import path35 from "path";
|
|
6310
6332
|
function collectEntry(results, dir, entry) {
|
|
6311
|
-
const full =
|
|
6333
|
+
const full = path35.join(dir, entry.name);
|
|
6312
6334
|
const items = entry.isDirectory() ? listFilesRecursive(full) : [full];
|
|
6313
6335
|
results.push(...items);
|
|
6314
6336
|
}
|
|
@@ -6322,15 +6344,15 @@ function listFilesRecursive(dir) {
|
|
|
6322
6344
|
}
|
|
6323
6345
|
function addDirectoryFileMoves(moves, childDir, newLocation, reason) {
|
|
6324
6346
|
for (const file of listFilesRecursive(childDir)) {
|
|
6325
|
-
const rel =
|
|
6326
|
-
moves.push({ from: file, to:
|
|
6347
|
+
const rel = path35.relative(childDir, file);
|
|
6348
|
+
moves.push({ from: file, to: path35.join(newLocation, rel), reason });
|
|
6327
6349
|
}
|
|
6328
6350
|
}
|
|
6329
6351
|
function resolveChildDest(parentDir, childDir) {
|
|
6330
|
-
return
|
|
6352
|
+
return path35.join(parentDir, path35.basename(childDir));
|
|
6331
6353
|
}
|
|
6332
6354
|
function childMoveReason(parentDir) {
|
|
6333
|
-
return `Directory only imported from ${
|
|
6355
|
+
return `Directory only imported from ${path35.basename(parentDir)}/`;
|
|
6334
6356
|
}
|
|
6335
6357
|
function registerDirectoryMove(result, childDir, dest, parentDir) {
|
|
6336
6358
|
result.directories.push(dest);
|
|
@@ -6354,32 +6376,24 @@ function planDirectoryMoves(clusters) {
|
|
|
6354
6376
|
}
|
|
6355
6377
|
|
|
6356
6378
|
// src/commands/refactor/restructure/planFileMoves/index.ts
|
|
6357
|
-
function emptyResult() {
|
|
6358
|
-
return { moves: [], directories: [], warnings: [] };
|
|
6359
|
-
}
|
|
6360
6379
|
function childMoveData(child, newDir, parentBase) {
|
|
6361
|
-
const to =
|
|
6380
|
+
const to = path36.join(newDir, path36.basename(child));
|
|
6362
6381
|
return { from: child, to, reason: `Only imported by ${parentBase}` };
|
|
6363
6382
|
}
|
|
6364
6383
|
function addChildMoves(moves, children, newDir, parentBase) {
|
|
6365
6384
|
for (const child of children)
|
|
6366
6385
|
moves.push(childMoveData(child, newDir, parentBase));
|
|
6367
6386
|
}
|
|
6368
|
-
function checkDirConflict(result, label2, dir) {
|
|
6369
|
-
if (!fs22.existsSync(dir)) return false;
|
|
6370
|
-
result.warnings.push(`Skipping ${label2}: directory ${dir} already exists`);
|
|
6371
|
-
return true;
|
|
6372
|
-
}
|
|
6373
6387
|
function getBaseName(filePath) {
|
|
6374
|
-
return
|
|
6388
|
+
return path36.basename(filePath, path36.extname(filePath));
|
|
6375
6389
|
}
|
|
6376
6390
|
function resolveClusterDir(parent) {
|
|
6377
|
-
return
|
|
6391
|
+
return path36.join(path36.dirname(parent), getBaseName(parent));
|
|
6378
6392
|
}
|
|
6379
6393
|
function createParentMove(parent, newDir) {
|
|
6380
6394
|
return {
|
|
6381
6395
|
from: parent,
|
|
6382
|
-
to:
|
|
6396
|
+
to: path36.join(newDir, `index${path36.extname(parent)}`),
|
|
6383
6397
|
reason: `Main module of new ${getBaseName(parent)}/ directory`
|
|
6384
6398
|
};
|
|
6385
6399
|
}
|
|
@@ -6403,7 +6417,7 @@ function planFileMoves(clusters) {
|
|
|
6403
6417
|
|
|
6404
6418
|
// src/commands/refactor/restructure/index.ts
|
|
6405
6419
|
function buildPlan(candidateFiles, tsConfigPath) {
|
|
6406
|
-
const candidates = new Set(candidateFiles.map((f) =>
|
|
6420
|
+
const candidates = new Set(candidateFiles.map((f) => path37.resolve(f)));
|
|
6407
6421
|
const graph = buildImportGraph(candidates, tsConfigPath);
|
|
6408
6422
|
const allProjectFiles = /* @__PURE__ */ new Set([
|
|
6409
6423
|
...graph.importedBy.keys(),
|
|
@@ -6423,22 +6437,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
6423
6437
|
const targetPattern = pattern2 ?? "src";
|
|
6424
6438
|
const files = findSourceFiles2(targetPattern);
|
|
6425
6439
|
if (files.length === 0) {
|
|
6426
|
-
console.log(
|
|
6440
|
+
console.log(chalk62.yellow("No files found matching pattern"));
|
|
6427
6441
|
return;
|
|
6428
6442
|
}
|
|
6429
|
-
const tsConfigPath =
|
|
6443
|
+
const tsConfigPath = path37.resolve("tsconfig.json");
|
|
6430
6444
|
const plan = buildPlan(files, tsConfigPath);
|
|
6431
6445
|
if (plan.moves.length === 0) {
|
|
6432
|
-
console.log(
|
|
6446
|
+
console.log(chalk62.green("No restructuring needed"));
|
|
6433
6447
|
return;
|
|
6434
6448
|
}
|
|
6435
6449
|
displayPlan(plan);
|
|
6436
6450
|
if (options2.apply) {
|
|
6437
|
-
console.log(
|
|
6451
|
+
console.log(chalk62.bold("\nApplying changes..."));
|
|
6438
6452
|
executePlan(plan);
|
|
6439
|
-
console.log(
|
|
6453
|
+
console.log(chalk62.green("\nRestructuring complete"));
|
|
6440
6454
|
} else {
|
|
6441
|
-
console.log(
|
|
6455
|
+
console.log(chalk62.dim("\nDry run. Use --apply to execute."));
|
|
6442
6456
|
}
|
|
6443
6457
|
}
|
|
6444
6458
|
|
|
@@ -6653,7 +6667,7 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
6653
6667
|
}
|
|
6654
6668
|
|
|
6655
6669
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
6656
|
-
import { existsSync as existsSync26, mkdirSync as mkdirSync7, readFileSync as readFileSync22, writeFileSync as
|
|
6670
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync7, readFileSync as readFileSync22, writeFileSync as writeFileSync22 } from "fs";
|
|
6657
6671
|
import { basename as basename5, dirname as dirname17, join as join25 } from "path";
|
|
6658
6672
|
|
|
6659
6673
|
// src/commands/transcript/cleanText.ts
|
|
@@ -6904,7 +6918,7 @@ function readAndParseCues(inputPath) {
|
|
|
6904
6918
|
return processCues(readFileSync22(inputPath, "utf-8"));
|
|
6905
6919
|
}
|
|
6906
6920
|
function writeFormatted(outputPath, content) {
|
|
6907
|
-
|
|
6921
|
+
writeFileSync22(outputPath, content, "utf-8");
|
|
6908
6922
|
console.log(`Written: ${outputPath}`);
|
|
6909
6923
|
}
|
|
6910
6924
|
function convertVttToMarkdown(inputPath, outputPath) {
|
|
@@ -6986,14 +7000,14 @@ import {
|
|
|
6986
7000
|
import { dirname as dirname18, join as join26 } from "path";
|
|
6987
7001
|
|
|
6988
7002
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
6989
|
-
import
|
|
7003
|
+
import chalk63 from "chalk";
|
|
6990
7004
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
6991
7005
|
function validateStagedContent(filename, content) {
|
|
6992
7006
|
const firstLine = content.split("\n")[0];
|
|
6993
7007
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
6994
7008
|
if (!match) {
|
|
6995
7009
|
console.error(
|
|
6996
|
-
|
|
7010
|
+
chalk63.red(
|
|
6997
7011
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
6998
7012
|
)
|
|
6999
7013
|
);
|
|
@@ -7002,7 +7016,7 @@ function validateStagedContent(filename, content) {
|
|
|
7002
7016
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
7003
7017
|
if (!contentAfterLink) {
|
|
7004
7018
|
console.error(
|
|
7005
|
-
|
|
7019
|
+
chalk63.red(
|
|
7006
7020
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
7007
7021
|
)
|
|
7008
7022
|
);
|
|
@@ -7203,7 +7217,7 @@ import { join as join31 } from "path";
|
|
|
7203
7217
|
|
|
7204
7218
|
// src/commands/voice/checkLockFile.ts
|
|
7205
7219
|
import { execSync as execSync30 } from "child_process";
|
|
7206
|
-
import { existsSync as existsSync31, mkdirSync as mkdirSync9, readFileSync as readFileSync25, writeFileSync as
|
|
7220
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync9, readFileSync as readFileSync25, writeFileSync as writeFileSync23 } from "fs";
|
|
7207
7221
|
import { join as join30 } from "path";
|
|
7208
7222
|
function isProcessAlive(pid) {
|
|
7209
7223
|
try {
|
|
@@ -7242,7 +7256,7 @@ function bootstrapVenv() {
|
|
|
7242
7256
|
function writeLockFile(pid) {
|
|
7243
7257
|
const lockFile = getLockFile();
|
|
7244
7258
|
mkdirSync9(join30(lockFile, ".."), { recursive: true });
|
|
7245
|
-
|
|
7259
|
+
writeFileSync23(
|
|
7246
7260
|
lockFile,
|
|
7247
7261
|
JSON.stringify({
|
|
7248
7262
|
pid,
|
|
@@ -7270,7 +7284,7 @@ function setup() {
|
|
|
7270
7284
|
|
|
7271
7285
|
// src/commands/voice/start.ts
|
|
7272
7286
|
import { spawn as spawn4 } from "child_process";
|
|
7273
|
-
import { mkdirSync as mkdirSync11, writeFileSync as
|
|
7287
|
+
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync24 } from "fs";
|
|
7274
7288
|
import { join as join32 } from "path";
|
|
7275
7289
|
|
|
7276
7290
|
// src/commands/voice/buildDaemonEnv.ts
|
|
@@ -7299,7 +7313,7 @@ function spawnBackground(python, script, env) {
|
|
|
7299
7313
|
console.error("Failed to start voice daemon");
|
|
7300
7314
|
process.exit(1);
|
|
7301
7315
|
}
|
|
7302
|
-
|
|
7316
|
+
writeFileSync24(voicePaths.pid, String(pid));
|
|
7303
7317
|
writeLockFile(pid);
|
|
7304
7318
|
console.log(`Voice daemon started (PID ${pid})`);
|
|
7305
7319
|
}
|
|
@@ -7395,7 +7409,7 @@ function registerVoice(program2) {
|
|
|
7395
7409
|
|
|
7396
7410
|
// src/commands/roam/auth.ts
|
|
7397
7411
|
import { randomBytes } from "crypto";
|
|
7398
|
-
import
|
|
7412
|
+
import chalk64 from "chalk";
|
|
7399
7413
|
|
|
7400
7414
|
// src/lib/openBrowser.ts
|
|
7401
7415
|
import { execSync as execSync31 } from "child_process";
|
|
@@ -7570,13 +7584,13 @@ async function auth() {
|
|
|
7570
7584
|
saveGlobalConfig(config);
|
|
7571
7585
|
const state = randomBytes(16).toString("hex");
|
|
7572
7586
|
console.log(
|
|
7573
|
-
|
|
7587
|
+
chalk64.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
7574
7588
|
);
|
|
7575
|
-
console.log(
|
|
7576
|
-
console.log(
|
|
7577
|
-
console.log(
|
|
7589
|
+
console.log(chalk64.white("http://localhost:14523/callback\n"));
|
|
7590
|
+
console.log(chalk64.blue("Opening browser for authorization..."));
|
|
7591
|
+
console.log(chalk64.dim("Waiting for authorization callback..."));
|
|
7578
7592
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
7579
|
-
console.log(
|
|
7593
|
+
console.log(chalk64.dim("Exchanging code for tokens..."));
|
|
7580
7594
|
const tokens = await exchangeToken({
|
|
7581
7595
|
code,
|
|
7582
7596
|
clientId,
|
|
@@ -7592,7 +7606,7 @@ async function auth() {
|
|
|
7592
7606
|
};
|
|
7593
7607
|
saveGlobalConfig(config);
|
|
7594
7608
|
console.log(
|
|
7595
|
-
|
|
7609
|
+
chalk64.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
7596
7610
|
);
|
|
7597
7611
|
}
|
|
7598
7612
|
|
|
@@ -7639,7 +7653,7 @@ function resolveParams(params, cliArgs) {
|
|
|
7639
7653
|
}
|
|
7640
7654
|
|
|
7641
7655
|
// src/commands/run/add.ts
|
|
7642
|
-
import { mkdirSync as mkdirSync12, writeFileSync as
|
|
7656
|
+
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync25 } from "fs";
|
|
7643
7657
|
import { join as join33 } from "path";
|
|
7644
7658
|
function findAddIndex() {
|
|
7645
7659
|
const addIndex = process.argv.indexOf("add");
|
|
@@ -7657,7 +7671,7 @@ function parseAddArguments() {
|
|
|
7657
7671
|
const addIndex = findAddIndex();
|
|
7658
7672
|
return addIndex === -1 ? null : extractAddArgs(addIndex);
|
|
7659
7673
|
}
|
|
7660
|
-
function
|
|
7674
|
+
function buildRunEntry2(name, command, args) {
|
|
7661
7675
|
const entry = {
|
|
7662
7676
|
name,
|
|
7663
7677
|
command
|
|
@@ -7690,7 +7704,7 @@ function getOrInitRunList() {
|
|
|
7690
7704
|
function saveNewRunConfig(name, command, args) {
|
|
7691
7705
|
const { config, runList } = getOrInitRunList();
|
|
7692
7706
|
ensureNoDuplicate(runList, name);
|
|
7693
|
-
runList.push(
|
|
7707
|
+
runList.push(buildRunEntry2(name, command, args));
|
|
7694
7708
|
saveConfig(config);
|
|
7695
7709
|
}
|
|
7696
7710
|
function createCommandFile(name) {
|
|
@@ -7703,7 +7717,7 @@ description: Run ${name}
|
|
|
7703
7717
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
7704
7718
|
`;
|
|
7705
7719
|
const filePath = join33(dir, `${name}.md`);
|
|
7706
|
-
|
|
7720
|
+
writeFileSync25(filePath, content);
|
|
7707
7721
|
console.log(`Created command file: ${filePath}`);
|
|
7708
7722
|
}
|
|
7709
7723
|
function add3() {
|
|
@@ -7780,14 +7794,14 @@ function run2(name, args) {
|
|
|
7780
7794
|
}
|
|
7781
7795
|
|
|
7782
7796
|
// src/commands/statusLine.ts
|
|
7783
|
-
import
|
|
7797
|
+
import chalk65 from "chalk";
|
|
7784
7798
|
function formatNumber(num) {
|
|
7785
7799
|
return num.toLocaleString("en-US");
|
|
7786
7800
|
}
|
|
7787
7801
|
function colorizePercent(pct) {
|
|
7788
7802
|
const label2 = `${pct}%`;
|
|
7789
|
-
if (pct > 80) return
|
|
7790
|
-
if (pct > 40) return
|
|
7803
|
+
if (pct > 80) return chalk65.red(label2);
|
|
7804
|
+
if (pct > 40) return chalk65.yellow(label2);
|
|
7791
7805
|
return label2;
|
|
7792
7806
|
}
|
|
7793
7807
|
async function statusLine() {
|
|
@@ -7805,29 +7819,29 @@ async function statusLine() {
|
|
|
7805
7819
|
}
|
|
7806
7820
|
|
|
7807
7821
|
// src/commands/sync.ts
|
|
7808
|
-
import * as
|
|
7822
|
+
import * as fs24 from "fs";
|
|
7809
7823
|
import * as os from "os";
|
|
7810
|
-
import * as
|
|
7824
|
+
import * as path40 from "path";
|
|
7811
7825
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
7812
7826
|
|
|
7813
7827
|
// src/commands/sync/syncClaudeMd.ts
|
|
7814
|
-
import * as
|
|
7815
|
-
import * as
|
|
7816
|
-
import
|
|
7828
|
+
import * as fs22 from "fs";
|
|
7829
|
+
import * as path38 from "path";
|
|
7830
|
+
import chalk66 from "chalk";
|
|
7817
7831
|
async function syncClaudeMd(claudeDir, targetBase) {
|
|
7818
|
-
const source =
|
|
7819
|
-
const target =
|
|
7820
|
-
const sourceContent =
|
|
7821
|
-
if (
|
|
7822
|
-
const targetContent =
|
|
7832
|
+
const source = path38.join(claudeDir, "CLAUDE.md");
|
|
7833
|
+
const target = path38.join(targetBase, "CLAUDE.md");
|
|
7834
|
+
const sourceContent = fs22.readFileSync(source, "utf-8");
|
|
7835
|
+
if (fs22.existsSync(target)) {
|
|
7836
|
+
const targetContent = fs22.readFileSync(target, "utf-8");
|
|
7823
7837
|
if (sourceContent !== targetContent) {
|
|
7824
7838
|
console.log(
|
|
7825
|
-
|
|
7839
|
+
chalk66.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
7826
7840
|
);
|
|
7827
7841
|
console.log();
|
|
7828
7842
|
printDiff(targetContent, sourceContent);
|
|
7829
7843
|
const confirm = await promptConfirm(
|
|
7830
|
-
|
|
7844
|
+
chalk66.red("Overwrite existing CLAUDE.md?"),
|
|
7831
7845
|
false
|
|
7832
7846
|
);
|
|
7833
7847
|
if (!confirm) {
|
|
@@ -7836,21 +7850,21 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
7836
7850
|
}
|
|
7837
7851
|
}
|
|
7838
7852
|
}
|
|
7839
|
-
|
|
7853
|
+
fs22.copyFileSync(source, target);
|
|
7840
7854
|
console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
|
|
7841
7855
|
}
|
|
7842
7856
|
|
|
7843
7857
|
// src/commands/sync/syncSettings.ts
|
|
7844
|
-
import * as
|
|
7845
|
-
import * as
|
|
7846
|
-
import
|
|
7858
|
+
import * as fs23 from "fs";
|
|
7859
|
+
import * as path39 from "path";
|
|
7860
|
+
import chalk67 from "chalk";
|
|
7847
7861
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
7848
|
-
const source =
|
|
7849
|
-
const target =
|
|
7850
|
-
const sourceContent =
|
|
7862
|
+
const source = path39.join(claudeDir, "settings.json");
|
|
7863
|
+
const target = path39.join(targetBase, "settings.json");
|
|
7864
|
+
const sourceContent = fs23.readFileSync(source, "utf-8");
|
|
7851
7865
|
const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
|
|
7852
|
-
if (
|
|
7853
|
-
const targetContent =
|
|
7866
|
+
if (fs23.existsSync(target)) {
|
|
7867
|
+
const targetContent = fs23.readFileSync(target, "utf-8");
|
|
7854
7868
|
const normalizedTarget = JSON.stringify(
|
|
7855
7869
|
JSON.parse(targetContent),
|
|
7856
7870
|
null,
|
|
@@ -7859,14 +7873,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
7859
7873
|
if (mergedContent !== normalizedTarget) {
|
|
7860
7874
|
if (!options2?.yes) {
|
|
7861
7875
|
console.log(
|
|
7862
|
-
|
|
7876
|
+
chalk67.yellow(
|
|
7863
7877
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
7864
7878
|
)
|
|
7865
7879
|
);
|
|
7866
7880
|
console.log();
|
|
7867
7881
|
printDiff(targetContent, mergedContent);
|
|
7868
7882
|
const confirm = await promptConfirm(
|
|
7869
|
-
|
|
7883
|
+
chalk67.red("Overwrite existing settings.json?"),
|
|
7870
7884
|
false
|
|
7871
7885
|
);
|
|
7872
7886
|
if (!confirm) {
|
|
@@ -7876,27 +7890,27 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
7876
7890
|
}
|
|
7877
7891
|
}
|
|
7878
7892
|
}
|
|
7879
|
-
|
|
7893
|
+
fs23.writeFileSync(target, mergedContent);
|
|
7880
7894
|
console.log("Copied settings.json to ~/.claude/settings.json");
|
|
7881
7895
|
}
|
|
7882
7896
|
|
|
7883
7897
|
// src/commands/sync.ts
|
|
7884
7898
|
var __filename4 = fileURLToPath7(import.meta.url);
|
|
7885
|
-
var __dirname7 =
|
|
7899
|
+
var __dirname7 = path40.dirname(__filename4);
|
|
7886
7900
|
async function sync(options2) {
|
|
7887
|
-
const claudeDir =
|
|
7888
|
-
const targetBase =
|
|
7901
|
+
const claudeDir = path40.join(__dirname7, "..", "claude");
|
|
7902
|
+
const targetBase = path40.join(os.homedir(), ".claude");
|
|
7889
7903
|
syncCommands(claudeDir, targetBase);
|
|
7890
7904
|
await syncSettings(claudeDir, targetBase, { yes: options2?.yes });
|
|
7891
7905
|
await syncClaudeMd(claudeDir, targetBase);
|
|
7892
7906
|
}
|
|
7893
7907
|
function syncCommands(claudeDir, targetBase) {
|
|
7894
|
-
const sourceDir =
|
|
7895
|
-
const targetDir =
|
|
7896
|
-
|
|
7897
|
-
const files =
|
|
7908
|
+
const sourceDir = path40.join(claudeDir, "commands");
|
|
7909
|
+
const targetDir = path40.join(targetBase, "commands");
|
|
7910
|
+
fs24.mkdirSync(targetDir, { recursive: true });
|
|
7911
|
+
const files = fs24.readdirSync(sourceDir);
|
|
7898
7912
|
for (const file of files) {
|
|
7899
|
-
|
|
7913
|
+
fs24.copyFileSync(path40.join(sourceDir, file), path40.join(targetDir, file));
|
|
7900
7914
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
7901
7915
|
}
|
|
7902
7916
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|
|
@@ -7904,15 +7918,15 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
7904
7918
|
|
|
7905
7919
|
// src/commands/update.ts
|
|
7906
7920
|
import { execSync as execSync32 } from "child_process";
|
|
7907
|
-
import * as
|
|
7921
|
+
import * as path41 from "path";
|
|
7908
7922
|
function isGlobalNpmInstall(dir) {
|
|
7909
7923
|
try {
|
|
7910
|
-
const resolved =
|
|
7911
|
-
if (resolved.split(
|
|
7924
|
+
const resolved = path41.resolve(dir);
|
|
7925
|
+
if (resolved.split(path41.sep).includes("node_modules")) {
|
|
7912
7926
|
return true;
|
|
7913
7927
|
}
|
|
7914
7928
|
const globalPrefix = execSync32("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
7915
|
-
return resolved.toLowerCase().startsWith(
|
|
7929
|
+
return resolved.toLowerCase().startsWith(path41.resolve(globalPrefix).toLowerCase());
|
|
7916
7930
|
} catch {
|
|
7917
7931
|
return false;
|
|
7918
7932
|
}
|