@staff0rd/assist 0.49.0 → 0.51.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 +333 -292
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { Command } from "commander";
|
|
|
7
7
|
// package.json
|
|
8
8
|
var package_default = {
|
|
9
9
|
name: "@staff0rd/assist",
|
|
10
|
-
version: "0.
|
|
10
|
+
version: "0.51.0",
|
|
11
11
|
type: "module",
|
|
12
12
|
main: "dist/index.js",
|
|
13
13
|
bin: {
|
|
@@ -222,9 +222,9 @@ function isTraversable(value) {
|
|
|
222
222
|
function stepInto(current, key) {
|
|
223
223
|
return isTraversable(current) ? current[key] : void 0;
|
|
224
224
|
}
|
|
225
|
-
function getNestedValue(obj,
|
|
225
|
+
function getNestedValue(obj, path30) {
|
|
226
226
|
let current = obj;
|
|
227
|
-
for (const key of
|
|
227
|
+
for (const key of path30.split(".")) current = stepInto(current, key);
|
|
228
228
|
return current;
|
|
229
229
|
}
|
|
230
230
|
function isPlainObject(val) {
|
|
@@ -241,8 +241,8 @@ function buildNestedPath(root, keys) {
|
|
|
241
241
|
}
|
|
242
242
|
return current;
|
|
243
243
|
}
|
|
244
|
-
function setNestedValue(obj,
|
|
245
|
-
const keys =
|
|
244
|
+
function setNestedValue(obj, path30, value) {
|
|
245
|
+
const keys = path30.split(".");
|
|
246
246
|
const result = { ...obj };
|
|
247
247
|
buildNestedPath(result, keys)[keys[keys.length - 1]] = value;
|
|
248
248
|
return result;
|
|
@@ -311,7 +311,7 @@ function configList() {
|
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
// src/commands/verify/init/index.ts
|
|
314
|
-
import
|
|
314
|
+
import chalk15 from "chalk";
|
|
315
315
|
|
|
316
316
|
// src/shared/promptMultiselect.ts
|
|
317
317
|
import chalk3 from "chalk";
|
|
@@ -387,7 +387,8 @@ var expectedScripts = {
|
|
|
387
387
|
"verify:lint": "biome check --write .",
|
|
388
388
|
"verify:duplicate-code": "jscpd --format 'typescript,tsx' --exitCode 1 --ignore '**/*.test.*' -r consoleFull src",
|
|
389
389
|
"verify:test": "vitest run --reporter=dot --silent",
|
|
390
|
-
"verify:hardcoded-colors": "assist verify hardcoded-colors"
|
|
390
|
+
"verify:hardcoded-colors": "assist verify hardcoded-colors",
|
|
391
|
+
"verify:maintainability": "assist complexity maintainability ./src --threshold 60"
|
|
391
392
|
};
|
|
392
393
|
|
|
393
394
|
// src/commands/verify/setup/setupBuild.ts
|
|
@@ -726,12 +727,25 @@ async function setupLint(packageJsonPath) {
|
|
|
726
727
|
);
|
|
727
728
|
}
|
|
728
729
|
|
|
729
|
-
// src/commands/verify/setup/
|
|
730
|
+
// src/commands/verify/setup/setupMaintainability.ts
|
|
730
731
|
import * as path7 from "path";
|
|
731
732
|
import chalk13 from "chalk";
|
|
733
|
+
async function setupMaintainability(packageJsonPath) {
|
|
734
|
+
console.log(chalk13.blue("\nSetting up maintainability check..."));
|
|
735
|
+
addToKnipIgnoreBinaries(path7.dirname(packageJsonPath), "assist");
|
|
736
|
+
setupVerifyScript(
|
|
737
|
+
packageJsonPath,
|
|
738
|
+
"verify:maintainability",
|
|
739
|
+
expectedScripts["verify:maintainability"]
|
|
740
|
+
);
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// src/commands/verify/setup/setupTest.ts
|
|
744
|
+
import * as path8 from "path";
|
|
745
|
+
import chalk14 from "chalk";
|
|
732
746
|
async function setupTest(packageJsonPath) {
|
|
733
|
-
console.log(
|
|
734
|
-
const cwd =
|
|
747
|
+
console.log(chalk14.blue("\nSetting up vitest..."));
|
|
748
|
+
const cwd = path8.dirname(packageJsonPath);
|
|
735
749
|
const pkg = readPackageJson(packageJsonPath);
|
|
736
750
|
if (!pkg.devDependencies?.vitest && !installPackage("vitest", cwd)) {
|
|
737
751
|
return;
|
|
@@ -783,11 +797,12 @@ function detectExistingSetup(pkg) {
|
|
|
783
797
|
build: toolStatus(pkg, "verify:build", true),
|
|
784
798
|
typecheck: toolStatus(pkg, "verify:typecheck", true),
|
|
785
799
|
hardcodedColors: toolStatus(pkg, "verify:hardcoded-colors", true),
|
|
800
|
+
maintainability: toolStatus(pkg, "verify:maintainability", true),
|
|
786
801
|
hasOpenColor: !!pkg.dependencies?.["open-color"] || !!pkg.devDependencies?.["open-color"]
|
|
787
802
|
};
|
|
788
803
|
}
|
|
789
804
|
|
|
790
|
-
// src/commands/verify/init/options.ts
|
|
805
|
+
// src/commands/verify/init/getAvailableOptions/options.ts
|
|
791
806
|
function getBuildDescription(setup) {
|
|
792
807
|
if (setup.hasVite && setup.hasTypescript)
|
|
793
808
|
return "TypeScript + Vite build verification";
|
|
@@ -839,10 +854,16 @@ var options = [
|
|
|
839
854
|
label: "typecheck",
|
|
840
855
|
description: "TypeScript type checking",
|
|
841
856
|
extraCondition: (s) => s.hasTypescript && !s.hasVite
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
toolKey: "maintainability",
|
|
860
|
+
value: "maintainability",
|
|
861
|
+
label: "maintainability",
|
|
862
|
+
description: "Maintainability index threshold check"
|
|
842
863
|
}
|
|
843
864
|
];
|
|
844
865
|
|
|
845
|
-
// src/commands/verify/init/getAvailableOptions.ts
|
|
866
|
+
// src/commands/verify/init/getAvailableOptions/index.ts
|
|
846
867
|
function resolveDescription(desc, setup) {
|
|
847
868
|
return typeof desc === "function" ? desc(setup) : desc;
|
|
848
869
|
}
|
|
@@ -868,37 +889,42 @@ function getSetupHandlers(hasVite, hasTypescript, hasOpenColor) {
|
|
|
868
889
|
test: (p) => setupTest(p),
|
|
869
890
|
build: (p) => setupBuild(p, hasVite, hasTypescript),
|
|
870
891
|
typecheck: (p) => setupTypecheck(p),
|
|
871
|
-
"hardcoded-colors": (p) => setupHardcodedColors(p, hasOpenColor)
|
|
892
|
+
"hardcoded-colors": (p) => setupHardcodedColors(p, hasOpenColor),
|
|
893
|
+
maintainability: (p) => setupMaintainability(p)
|
|
872
894
|
};
|
|
873
895
|
}
|
|
874
896
|
async function runSelectedSetups(selected, packageJsonPath, handlers) {
|
|
875
897
|
for (const choice of selected) {
|
|
876
898
|
await handlers[choice]?.(packageJsonPath);
|
|
877
899
|
}
|
|
878
|
-
console.log(
|
|
900
|
+
console.log(chalk15.green(`
|
|
879
901
|
Added ${selected.length} verify script(s):`));
|
|
880
902
|
for (const choice of selected) {
|
|
881
|
-
console.log(
|
|
903
|
+
console.log(chalk15.green(` - verify:${choice}`));
|
|
882
904
|
}
|
|
883
|
-
console.log(
|
|
905
|
+
console.log(chalk15.dim("\nRun 'assist verify' to run all verify scripts"));
|
|
884
906
|
}
|
|
885
|
-
async function
|
|
886
|
-
const { packageJsonPath, pkg } = requirePackageJson();
|
|
887
|
-
const setup = detectExistingSetup(pkg);
|
|
888
|
-
const availableOptions = getAvailableOptions(setup);
|
|
907
|
+
async function promptForScripts(availableOptions) {
|
|
889
908
|
if (availableOptions.length === 0) {
|
|
890
|
-
console.log(
|
|
891
|
-
return;
|
|
909
|
+
console.log(chalk15.green("All verify scripts are already configured!"));
|
|
910
|
+
return null;
|
|
892
911
|
}
|
|
893
|
-
console.log(
|
|
912
|
+
console.log(chalk15.bold("Available verify scripts to add:\n"));
|
|
894
913
|
const selected = await promptMultiselect(
|
|
895
914
|
"Select verify scripts to add:",
|
|
896
915
|
availableOptions
|
|
897
916
|
);
|
|
898
917
|
if (selected.length === 0) {
|
|
899
|
-
console.log(
|
|
900
|
-
return;
|
|
918
|
+
console.log(chalk15.yellow("No scripts selected"));
|
|
919
|
+
return null;
|
|
901
920
|
}
|
|
921
|
+
return selected;
|
|
922
|
+
}
|
|
923
|
+
async function init2() {
|
|
924
|
+
const { packageJsonPath, pkg } = requirePackageJson();
|
|
925
|
+
const setup = detectExistingSetup(pkg);
|
|
926
|
+
const selected = await promptForScripts(getAvailableOptions(setup));
|
|
927
|
+
if (!selected) return;
|
|
902
928
|
const handlers = getSetupHandlers(
|
|
903
929
|
setup.hasVite,
|
|
904
930
|
setup.hasTypescript,
|
|
@@ -908,21 +934,21 @@ async function init2() {
|
|
|
908
934
|
}
|
|
909
935
|
|
|
910
936
|
// src/commands/vscode/init/index.ts
|
|
911
|
-
import
|
|
937
|
+
import chalk17 from "chalk";
|
|
912
938
|
|
|
913
939
|
// src/commands/vscode/init/createLaunchJson.ts
|
|
914
940
|
import * as fs3 from "fs";
|
|
915
|
-
import * as
|
|
916
|
-
import
|
|
941
|
+
import * as path9 from "path";
|
|
942
|
+
import chalk16 from "chalk";
|
|
917
943
|
function ensureVscodeFolder() {
|
|
918
|
-
const vscodeDir =
|
|
944
|
+
const vscodeDir = path9.join(process.cwd(), ".vscode");
|
|
919
945
|
if (!fs3.existsSync(vscodeDir)) {
|
|
920
946
|
fs3.mkdirSync(vscodeDir);
|
|
921
|
-
console.log(
|
|
947
|
+
console.log(chalk16.dim("Created .vscode folder"));
|
|
922
948
|
}
|
|
923
949
|
}
|
|
924
950
|
function removeVscodeFromGitignore() {
|
|
925
|
-
const gitignorePath =
|
|
951
|
+
const gitignorePath = path9.join(process.cwd(), ".gitignore");
|
|
926
952
|
if (!fs3.existsSync(gitignorePath)) {
|
|
927
953
|
return;
|
|
928
954
|
}
|
|
@@ -933,25 +959,26 @@ function removeVscodeFromGitignore() {
|
|
|
933
959
|
);
|
|
934
960
|
if (filteredLines.length !== lines.length) {
|
|
935
961
|
fs3.writeFileSync(gitignorePath, filteredLines.join("\n"));
|
|
936
|
-
console.log(
|
|
962
|
+
console.log(chalk16.dim("Removed .vscode references from .gitignore"));
|
|
937
963
|
}
|
|
938
964
|
}
|
|
939
|
-
function createLaunchJson() {
|
|
965
|
+
function createLaunchJson(type) {
|
|
966
|
+
const command = type === "vite" ? "npm run dev -- --open" : "npm run start";
|
|
940
967
|
const launchConfig = {
|
|
941
968
|
version: "0.2.0",
|
|
942
969
|
configurations: [
|
|
943
970
|
{
|
|
944
|
-
name:
|
|
971
|
+
name: command,
|
|
945
972
|
type: "node-terminal",
|
|
946
973
|
request: "launch",
|
|
947
|
-
command
|
|
974
|
+
command
|
|
948
975
|
}
|
|
949
976
|
]
|
|
950
977
|
};
|
|
951
|
-
const launchPath =
|
|
978
|
+
const launchPath = path9.join(process.cwd(), ".vscode", "launch.json");
|
|
952
979
|
fs3.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
|
|
953
980
|
`);
|
|
954
|
-
console.log(
|
|
981
|
+
console.log(chalk16.green("Created .vscode/launch.json"));
|
|
955
982
|
}
|
|
956
983
|
function createSettingsJson() {
|
|
957
984
|
const settings = {
|
|
@@ -961,52 +988,53 @@ function createSettingsJson() {
|
|
|
961
988
|
"source.organizeImports.biome": "explicit"
|
|
962
989
|
}
|
|
963
990
|
};
|
|
964
|
-
const settingsPath =
|
|
991
|
+
const settingsPath = path9.join(process.cwd(), ".vscode", "settings.json");
|
|
965
992
|
fs3.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
|
|
966
993
|
`);
|
|
967
|
-
console.log(
|
|
994
|
+
console.log(chalk16.green("Created .vscode/settings.json"));
|
|
968
995
|
}
|
|
969
996
|
function createExtensionsJson() {
|
|
970
997
|
const extensions = {
|
|
971
998
|
recommendations: ["biomejs.biome"]
|
|
972
999
|
};
|
|
973
|
-
const extensionsPath =
|
|
1000
|
+
const extensionsPath = path9.join(process.cwd(), ".vscode", "extensions.json");
|
|
974
1001
|
fs3.writeFileSync(
|
|
975
1002
|
extensionsPath,
|
|
976
1003
|
`${JSON.stringify(extensions, null, " ")}
|
|
977
1004
|
`
|
|
978
1005
|
);
|
|
979
|
-
console.log(
|
|
1006
|
+
console.log(chalk16.green("Created .vscode/extensions.json"));
|
|
980
1007
|
}
|
|
981
1008
|
|
|
982
1009
|
// src/commands/vscode/init/detectVscodeSetup.ts
|
|
983
1010
|
import * as fs4 from "fs";
|
|
984
|
-
import * as
|
|
1011
|
+
import * as path10 from "path";
|
|
985
1012
|
function detectVscodeSetup(pkg) {
|
|
986
|
-
const vscodeDir =
|
|
1013
|
+
const vscodeDir = path10.join(process.cwd(), ".vscode");
|
|
987
1014
|
return {
|
|
988
1015
|
hasVscodeFolder: fs4.existsSync(vscodeDir),
|
|
989
|
-
hasLaunchJson: fs4.existsSync(
|
|
990
|
-
hasSettingsJson: fs4.existsSync(
|
|
991
|
-
hasVite: !!pkg.devDependencies?.vite || !!pkg.dependencies?.vite
|
|
1016
|
+
hasLaunchJson: fs4.existsSync(path10.join(vscodeDir, "launch.json")),
|
|
1017
|
+
hasSettingsJson: fs4.existsSync(path10.join(vscodeDir, "settings.json")),
|
|
1018
|
+
hasVite: !!pkg.devDependencies?.vite || !!pkg.dependencies?.vite,
|
|
1019
|
+
hasTsup: !!pkg.devDependencies?.tsup || !!pkg.dependencies?.tsup
|
|
992
1020
|
};
|
|
993
1021
|
}
|
|
994
1022
|
|
|
995
|
-
// src/commands/vscode/init/
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
};
|
|
1023
|
+
// src/commands/vscode/init/getAvailableOptions.ts
|
|
1024
|
+
function getLaunchDescription(setup) {
|
|
1025
|
+
if (setup.hasLaunchJson) return void 0;
|
|
1026
|
+
if (setup.hasVite) return "Debug configuration for Vite dev server";
|
|
1027
|
+
if (setup.hasTsup) return "Debug configuration for Node.js CLI";
|
|
1028
|
+
return void 0;
|
|
1029
|
+
}
|
|
1003
1030
|
function getAvailableOptions2(setup) {
|
|
1004
1031
|
const options2 = [];
|
|
1005
|
-
|
|
1032
|
+
const launchDescription = getLaunchDescription(setup);
|
|
1033
|
+
if (launchDescription)
|
|
1006
1034
|
options2.push({
|
|
1007
1035
|
name: "launch",
|
|
1008
1036
|
value: "launch",
|
|
1009
|
-
description:
|
|
1037
|
+
description: launchDescription
|
|
1010
1038
|
});
|
|
1011
1039
|
if (!setup.hasSettingsJson)
|
|
1012
1040
|
options2.push({
|
|
@@ -1016,28 +1044,41 @@ function getAvailableOptions2(setup) {
|
|
|
1016
1044
|
});
|
|
1017
1045
|
return options2;
|
|
1018
1046
|
}
|
|
1047
|
+
|
|
1048
|
+
// src/commands/vscode/init/index.ts
|
|
1049
|
+
function applySelections(selected, setup) {
|
|
1050
|
+
removeVscodeFromGitignore();
|
|
1051
|
+
ensureVscodeFolder();
|
|
1052
|
+
const launchType = setup.hasVite ? "vite" : "tsup";
|
|
1053
|
+
const handlers = {
|
|
1054
|
+
launch: () => createLaunchJson(launchType),
|
|
1055
|
+
settings: () => {
|
|
1056
|
+
createSettingsJson();
|
|
1057
|
+
createExtensionsJson();
|
|
1058
|
+
}
|
|
1059
|
+
};
|
|
1060
|
+
for (const choice of selected) handlers[choice]?.();
|
|
1061
|
+
}
|
|
1062
|
+
async function promptForOptions(options2) {
|
|
1063
|
+
console.log(chalk17.bold("Available VS Code configurations to add:\n"));
|
|
1064
|
+
return promptMultiselect("Select configurations to add:", options2);
|
|
1065
|
+
}
|
|
1019
1066
|
async function init3() {
|
|
1020
1067
|
const { pkg } = requirePackageJson();
|
|
1021
1068
|
const setup = detectVscodeSetup(pkg);
|
|
1022
|
-
const
|
|
1023
|
-
if (
|
|
1024
|
-
console.log(
|
|
1069
|
+
const options2 = getAvailableOptions2(setup);
|
|
1070
|
+
if (options2.length === 0) {
|
|
1071
|
+
console.log(chalk17.green("VS Code configuration already exists!"));
|
|
1025
1072
|
return;
|
|
1026
1073
|
}
|
|
1027
|
-
|
|
1028
|
-
const selected = await promptMultiselect(
|
|
1029
|
-
"Select configurations to add:",
|
|
1030
|
-
availableOptions
|
|
1031
|
-
);
|
|
1074
|
+
const selected = await promptForOptions(options2);
|
|
1032
1075
|
if (selected.length === 0) {
|
|
1033
|
-
console.log(
|
|
1076
|
+
console.log(chalk17.yellow("No configurations selected"));
|
|
1034
1077
|
return;
|
|
1035
1078
|
}
|
|
1036
|
-
|
|
1037
|
-
ensureVscodeFolder();
|
|
1038
|
-
for (const choice of selected) SETUP_HANDLERS[choice]?.();
|
|
1079
|
+
applySelections(selected, setup);
|
|
1039
1080
|
console.log(
|
|
1040
|
-
|
|
1081
|
+
chalk17.green(`
|
|
1041
1082
|
Added ${selected.length} VS Code configuration(s)`)
|
|
1042
1083
|
);
|
|
1043
1084
|
}
|
|
@@ -1050,12 +1091,12 @@ async function init4() {
|
|
|
1050
1091
|
|
|
1051
1092
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
1052
1093
|
import fs6 from "fs";
|
|
1053
|
-
import
|
|
1054
|
-
import
|
|
1094
|
+
import path12 from "path";
|
|
1095
|
+
import chalk18 from "chalk";
|
|
1055
1096
|
|
|
1056
1097
|
// src/shared/findSourceFiles.ts
|
|
1057
1098
|
import fs5 from "fs";
|
|
1058
|
-
import
|
|
1099
|
+
import path11 from "path";
|
|
1059
1100
|
var EXTENSIONS = [".ts", ".tsx"];
|
|
1060
1101
|
function findSourceFiles(dir, options2 = {}) {
|
|
1061
1102
|
const { includeTests = true } = options2;
|
|
@@ -1065,7 +1106,7 @@ function findSourceFiles(dir, options2 = {}) {
|
|
|
1065
1106
|
}
|
|
1066
1107
|
const entries = fs5.readdirSync(dir, { withFileTypes: true });
|
|
1067
1108
|
for (const entry of entries) {
|
|
1068
|
-
const fullPath =
|
|
1109
|
+
const fullPath = path11.join(dir, entry.name);
|
|
1069
1110
|
if (entry.isDirectory() && entry.name !== "node_modules") {
|
|
1070
1111
|
results.push(...findSourceFiles(fullPath, options2));
|
|
1071
1112
|
} else if (entry.isFile() && EXTENSIONS.some((ext) => entry.name.endsWith(ext))) {
|
|
@@ -1089,7 +1130,7 @@ function checkFileNames() {
|
|
|
1089
1130
|
const sourceFiles = findSourceFiles("src");
|
|
1090
1131
|
const violations = [];
|
|
1091
1132
|
for (const filePath of sourceFiles) {
|
|
1092
|
-
const fileName =
|
|
1133
|
+
const fileName = path12.basename(filePath);
|
|
1093
1134
|
const nameWithoutExt = fileName.replace(/\.(ts|tsx)$/, "");
|
|
1094
1135
|
if (/^[A-Z]/.test(nameWithoutExt)) {
|
|
1095
1136
|
const content = fs6.readFileSync(filePath, "utf-8");
|
|
@@ -1103,16 +1144,16 @@ function checkFileNames() {
|
|
|
1103
1144
|
function runFileNameCheck() {
|
|
1104
1145
|
const violations = checkFileNames();
|
|
1105
1146
|
if (violations.length > 0) {
|
|
1106
|
-
console.error(
|
|
1147
|
+
console.error(chalk18.red("\nFile name check failed:\n"));
|
|
1107
1148
|
console.error(
|
|
1108
|
-
|
|
1149
|
+
chalk18.red(
|
|
1109
1150
|
" Files without classes or React components should not start with a capital letter.\n"
|
|
1110
1151
|
)
|
|
1111
1152
|
);
|
|
1112
1153
|
for (const violation of violations) {
|
|
1113
|
-
console.error(
|
|
1154
|
+
console.error(chalk18.red(` ${violation.filePath}`));
|
|
1114
1155
|
console.error(
|
|
1115
|
-
|
|
1156
|
+
chalk18.gray(
|
|
1116
1157
|
` Rename to: ${violation.fileName.charAt(0).toLowerCase()}${violation.fileName.slice(1)}
|
|
1117
1158
|
`
|
|
1118
1159
|
)
|
|
@@ -1132,17 +1173,17 @@ function runFileNameCheck() {
|
|
|
1132
1173
|
import fs7 from "fs";
|
|
1133
1174
|
|
|
1134
1175
|
// src/commands/lint/shared.ts
|
|
1135
|
-
import
|
|
1176
|
+
import chalk19 from "chalk";
|
|
1136
1177
|
function reportViolations(violations, checkName, errorMessage, successMessage) {
|
|
1137
1178
|
if (violations.length > 0) {
|
|
1138
|
-
console.error(
|
|
1179
|
+
console.error(chalk19.red(`
|
|
1139
1180
|
${checkName} failed:
|
|
1140
1181
|
`));
|
|
1141
|
-
console.error(
|
|
1182
|
+
console.error(chalk19.red(` ${errorMessage}
|
|
1142
1183
|
`));
|
|
1143
1184
|
for (const violation of violations) {
|
|
1144
|
-
console.error(
|
|
1145
|
-
console.error(
|
|
1185
|
+
console.error(chalk19.red(` ${violation.filePath}:${violation.line}`));
|
|
1186
|
+
console.error(chalk19.gray(` ${violation.content}
|
|
1146
1187
|
`));
|
|
1147
1188
|
}
|
|
1148
1189
|
return false;
|
|
@@ -1235,7 +1276,7 @@ function lint() {
|
|
|
1235
1276
|
}
|
|
1236
1277
|
}
|
|
1237
1278
|
|
|
1238
|
-
// src/commands/new/newCli.ts
|
|
1279
|
+
// src/commands/new/registerNew/newCli/index.ts
|
|
1239
1280
|
import { execSync as execSync7 } from "child_process";
|
|
1240
1281
|
import { basename as basename2, resolve } from "path";
|
|
1241
1282
|
|
|
@@ -1274,7 +1315,7 @@ Total: ${lines.length} hardcoded color(s)`);
|
|
|
1274
1315
|
|
|
1275
1316
|
// src/commands/verify/run/index.ts
|
|
1276
1317
|
import { spawn } from "child_process";
|
|
1277
|
-
import * as
|
|
1318
|
+
import * as path13 from "path";
|
|
1278
1319
|
|
|
1279
1320
|
// src/commands/verify/run/createTimerCallback/printTaskStatuses.ts
|
|
1280
1321
|
function formatDuration(ms) {
|
|
@@ -1374,7 +1415,7 @@ function resolveVerifyScripts() {
|
|
|
1374
1415
|
return result;
|
|
1375
1416
|
}
|
|
1376
1417
|
function getPackageDir(found) {
|
|
1377
|
-
return
|
|
1418
|
+
return path13.dirname(found.packageJsonPath);
|
|
1378
1419
|
}
|
|
1379
1420
|
async function executeVerifyScripts(found, timer) {
|
|
1380
1421
|
printScriptList(found.verifyScripts);
|
|
@@ -1391,7 +1432,7 @@ async function run(options2 = {}) {
|
|
|
1391
1432
|
await executeVerifyScripts(found, options2.timer ?? false);
|
|
1392
1433
|
}
|
|
1393
1434
|
|
|
1394
|
-
// src/commands/new/initPackageJson.ts
|
|
1435
|
+
// src/commands/new/registerNew/newCli/initPackageJson.ts
|
|
1395
1436
|
import { execSync as execSync6 } from "child_process";
|
|
1396
1437
|
function initPackageJson(name) {
|
|
1397
1438
|
console.log("Initializing package.json...");
|
|
@@ -1406,7 +1447,7 @@ function initPackageJson(name) {
|
|
|
1406
1447
|
});
|
|
1407
1448
|
}
|
|
1408
1449
|
|
|
1409
|
-
// src/commands/new/writeCliTemplate.ts
|
|
1450
|
+
// src/commands/new/registerNew/newCli/writeCliTemplate.ts
|
|
1410
1451
|
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
1411
1452
|
function writeCliTemplate(name) {
|
|
1412
1453
|
console.log("Writing tsconfig.json...");
|
|
@@ -1460,7 +1501,7 @@ program.parse();
|
|
|
1460
1501
|
);
|
|
1461
1502
|
}
|
|
1462
1503
|
|
|
1463
|
-
// src/commands/new/newCli.ts
|
|
1504
|
+
// src/commands/new/registerNew/newCli/index.ts
|
|
1464
1505
|
async function newCli() {
|
|
1465
1506
|
const name = basename2(resolve("."));
|
|
1466
1507
|
initPackageJson(name);
|
|
@@ -1474,22 +1515,22 @@ async function newCli() {
|
|
|
1474
1515
|
await run();
|
|
1475
1516
|
}
|
|
1476
1517
|
|
|
1477
|
-
// src/commands/new/newProject.ts
|
|
1518
|
+
// src/commands/new/registerNew/newProject.ts
|
|
1478
1519
|
import { execSync as execSync9 } from "child_process";
|
|
1479
1520
|
import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
1480
1521
|
|
|
1481
1522
|
// src/commands/deploy/init/index.ts
|
|
1482
1523
|
import { execSync as execSync8 } from "child_process";
|
|
1483
|
-
import
|
|
1524
|
+
import chalk21 from "chalk";
|
|
1484
1525
|
import enquirer3 from "enquirer";
|
|
1485
1526
|
|
|
1486
1527
|
// src/commands/deploy/init/updateWorkflow.ts
|
|
1487
1528
|
import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "fs";
|
|
1488
|
-
import { dirname as
|
|
1529
|
+
import { dirname as dirname10, join as join7 } from "path";
|
|
1489
1530
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1490
|
-
import
|
|
1531
|
+
import chalk20 from "chalk";
|
|
1491
1532
|
var WORKFLOW_PATH = ".github/workflows/build.yml";
|
|
1492
|
-
var __dirname3 =
|
|
1533
|
+
var __dirname3 = dirname10(fileURLToPath2(import.meta.url));
|
|
1493
1534
|
function getExistingSiteId() {
|
|
1494
1535
|
if (!existsSync9(WORKFLOW_PATH)) {
|
|
1495
1536
|
return null;
|
|
@@ -1512,20 +1553,20 @@ async function updateWorkflow(siteId) {
|
|
|
1512
1553
|
if (existsSync9(WORKFLOW_PATH)) {
|
|
1513
1554
|
const oldContent = readFileSync7(WORKFLOW_PATH, "utf-8");
|
|
1514
1555
|
if (oldContent === newContent) {
|
|
1515
|
-
console.log(
|
|
1556
|
+
console.log(chalk20.green("build.yml is already up to date"));
|
|
1516
1557
|
return;
|
|
1517
1558
|
}
|
|
1518
|
-
console.log(
|
|
1559
|
+
console.log(chalk20.yellow("\nbuild.yml will be updated:"));
|
|
1519
1560
|
console.log();
|
|
1520
1561
|
printDiff(oldContent, newContent);
|
|
1521
|
-
const confirm = await promptConfirm(
|
|
1562
|
+
const confirm = await promptConfirm(chalk20.red("Update build.yml?"));
|
|
1522
1563
|
if (!confirm) {
|
|
1523
1564
|
console.log("Skipped build.yml update");
|
|
1524
1565
|
return;
|
|
1525
1566
|
}
|
|
1526
1567
|
}
|
|
1527
1568
|
writeFileSync7(WORKFLOW_PATH, newContent);
|
|
1528
|
-
console.log(
|
|
1569
|
+
console.log(chalk20.green(`
|
|
1529
1570
|
Created ${WORKFLOW_PATH}`));
|
|
1530
1571
|
}
|
|
1531
1572
|
|
|
@@ -1536,43 +1577,43 @@ async function ensureNetlifyCli() {
|
|
|
1536
1577
|
} catch (error) {
|
|
1537
1578
|
if (!(error instanceof Error) || !error.message.includes("command not found"))
|
|
1538
1579
|
throw error;
|
|
1539
|
-
console.error(
|
|
1580
|
+
console.error(chalk21.red("\nNetlify CLI is not installed.\n"));
|
|
1540
1581
|
const install = await promptConfirm("Would you like to install it now?");
|
|
1541
1582
|
if (!install) {
|
|
1542
1583
|
console.log(
|
|
1543
|
-
|
|
1584
|
+
chalk21.yellow(
|
|
1544
1585
|
"\nInstall it manually with: npm install -g netlify-cli\n"
|
|
1545
1586
|
)
|
|
1546
1587
|
);
|
|
1547
1588
|
process.exit(1);
|
|
1548
1589
|
}
|
|
1549
|
-
console.log(
|
|
1590
|
+
console.log(chalk21.dim("\nInstalling netlify-cli...\n"));
|
|
1550
1591
|
execSync8("npm install -g netlify-cli", { stdio: "inherit" });
|
|
1551
1592
|
console.log();
|
|
1552
1593
|
execSync8("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
1553
1594
|
}
|
|
1554
1595
|
}
|
|
1555
1596
|
function printSetupInstructions() {
|
|
1556
|
-
console.log(
|
|
1597
|
+
console.log(chalk21.bold("\nDeployment initialized successfully!"));
|
|
1557
1598
|
console.log(
|
|
1558
|
-
|
|
1599
|
+
chalk21.yellow("\nTo complete setup, create a personal access token at:")
|
|
1559
1600
|
);
|
|
1560
1601
|
console.log(
|
|
1561
|
-
|
|
1602
|
+
chalk21.cyan(
|
|
1562
1603
|
"https://app.netlify.com/user/applications#personal-access-tokens"
|
|
1563
1604
|
)
|
|
1564
1605
|
);
|
|
1565
1606
|
console.log(
|
|
1566
|
-
|
|
1607
|
+
chalk21.yellow(
|
|
1567
1608
|
"\nThen add it as NETLIFY_AUTH_TOKEN in your GitHub repository secrets."
|
|
1568
1609
|
)
|
|
1569
1610
|
);
|
|
1570
1611
|
}
|
|
1571
1612
|
async function init5() {
|
|
1572
|
-
console.log(
|
|
1613
|
+
console.log(chalk21.bold("Initializing Netlify deployment...\n"));
|
|
1573
1614
|
const existingSiteId = getExistingSiteId();
|
|
1574
1615
|
if (existingSiteId) {
|
|
1575
|
-
console.log(
|
|
1616
|
+
console.log(chalk21.dim(`Using existing site ID: ${existingSiteId}
|
|
1576
1617
|
`));
|
|
1577
1618
|
await updateWorkflow(existingSiteId);
|
|
1578
1619
|
return;
|
|
@@ -1589,7 +1630,7 @@ async function init5() {
|
|
|
1589
1630
|
printSetupInstructions();
|
|
1590
1631
|
}
|
|
1591
1632
|
|
|
1592
|
-
// src/commands/new/newProject.ts
|
|
1633
|
+
// src/commands/new/registerNew/newProject.ts
|
|
1593
1634
|
async function newProject() {
|
|
1594
1635
|
console.log("Initializing Vite with react-ts template...");
|
|
1595
1636
|
execSync9("npm create vite@latest . -- --template react-ts", {
|
|
@@ -1621,7 +1662,7 @@ function addViteBaseConfig() {
|
|
|
1621
1662
|
}
|
|
1622
1663
|
}
|
|
1623
1664
|
|
|
1624
|
-
// src/commands/new/registerNew.ts
|
|
1665
|
+
// src/commands/new/registerNew/index.ts
|
|
1625
1666
|
function registerNew(program2) {
|
|
1626
1667
|
const newCommand = program2.command("new").description("Scaffold a new project");
|
|
1627
1668
|
newCommand.command("vite").description("Initialize a new Vite React TypeScript project").action(newProject);
|
|
@@ -1666,11 +1707,11 @@ function detectPlatform() {
|
|
|
1666
1707
|
import { spawn as spawn2 } from "child_process";
|
|
1667
1708
|
import fs9 from "fs";
|
|
1668
1709
|
import { createRequire } from "module";
|
|
1669
|
-
import
|
|
1710
|
+
import path14 from "path";
|
|
1670
1711
|
var require2 = createRequire(import.meta.url);
|
|
1671
1712
|
function getSnoreToastPath() {
|
|
1672
|
-
const notifierPath =
|
|
1673
|
-
return
|
|
1713
|
+
const notifierPath = path14.dirname(require2.resolve("node-notifier"));
|
|
1714
|
+
return path14.join(notifierPath, "vendor", "snoreToast", "snoretoast-x64.exe");
|
|
1674
1715
|
}
|
|
1675
1716
|
function showWindowsNotificationFromWsl(options2) {
|
|
1676
1717
|
const { title, message, sound } = options2;
|
|
@@ -1751,20 +1792,20 @@ async function notify() {
|
|
|
1751
1792
|
}
|
|
1752
1793
|
|
|
1753
1794
|
// src/commands/complexity/analyze.ts
|
|
1754
|
-
import
|
|
1795
|
+
import chalk27 from "chalk";
|
|
1755
1796
|
|
|
1756
1797
|
// src/commands/complexity/cyclomatic.ts
|
|
1757
|
-
import
|
|
1798
|
+
import chalk23 from "chalk";
|
|
1758
1799
|
|
|
1759
1800
|
// src/commands/complexity/shared/index.ts
|
|
1760
1801
|
import fs11 from "fs";
|
|
1761
|
-
import
|
|
1762
|
-
import
|
|
1802
|
+
import path16 from "path";
|
|
1803
|
+
import chalk22 from "chalk";
|
|
1763
1804
|
import ts5 from "typescript";
|
|
1764
1805
|
|
|
1765
1806
|
// src/commands/complexity/findSourceFiles.ts
|
|
1766
1807
|
import fs10 from "fs";
|
|
1767
|
-
import
|
|
1808
|
+
import path15 from "path";
|
|
1768
1809
|
import { minimatch } from "minimatch";
|
|
1769
1810
|
function applyIgnoreGlobs(files) {
|
|
1770
1811
|
const { complexity } = loadConfig();
|
|
@@ -1779,7 +1820,7 @@ function walk(dir, results) {
|
|
|
1779
1820
|
const extensions = [".ts", ".tsx"];
|
|
1780
1821
|
const entries = fs10.readdirSync(dir, { withFileTypes: true });
|
|
1781
1822
|
for (const entry of entries) {
|
|
1782
|
-
const fullPath =
|
|
1823
|
+
const fullPath = path15.join(dir, entry.name);
|
|
1783
1824
|
if (entry.isDirectory()) {
|
|
1784
1825
|
if (entry.name !== "node_modules" && entry.name !== ".git") {
|
|
1785
1826
|
walk(fullPath, results);
|
|
@@ -1995,7 +2036,7 @@ function countSloc(content) {
|
|
|
1995
2036
|
function createSourceFromFile(filePath) {
|
|
1996
2037
|
const content = fs11.readFileSync(filePath, "utf-8");
|
|
1997
2038
|
return ts5.createSourceFile(
|
|
1998
|
-
|
|
2039
|
+
path16.basename(filePath),
|
|
1999
2040
|
content,
|
|
2000
2041
|
ts5.ScriptTarget.Latest,
|
|
2001
2042
|
true,
|
|
@@ -2005,7 +2046,7 @@ function createSourceFromFile(filePath) {
|
|
|
2005
2046
|
function withSourceFiles(pattern2, callback) {
|
|
2006
2047
|
const files = findSourceFiles2(pattern2);
|
|
2007
2048
|
if (files.length === 0) {
|
|
2008
|
-
console.log(
|
|
2049
|
+
console.log(chalk22.yellow("No files found matching pattern"));
|
|
2009
2050
|
return void 0;
|
|
2010
2051
|
}
|
|
2011
2052
|
return callback(files);
|
|
@@ -2038,11 +2079,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2038
2079
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
2039
2080
|
for (const { file, name, complexity } of results) {
|
|
2040
2081
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
2041
|
-
const color = exceedsThreshold ?
|
|
2042
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
2082
|
+
const color = exceedsThreshold ? chalk23.red : chalk23.white;
|
|
2083
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk23.cyan(complexity)}`);
|
|
2043
2084
|
}
|
|
2044
2085
|
console.log(
|
|
2045
|
-
|
|
2086
|
+
chalk23.dim(
|
|
2046
2087
|
`
|
|
2047
2088
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
2048
2089
|
)
|
|
@@ -2054,7 +2095,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
2054
2095
|
}
|
|
2055
2096
|
|
|
2056
2097
|
// src/commands/complexity/halstead.ts
|
|
2057
|
-
import
|
|
2098
|
+
import chalk24 from "chalk";
|
|
2058
2099
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
2059
2100
|
withSourceFiles(pattern2, (files) => {
|
|
2060
2101
|
const results = [];
|
|
@@ -2069,13 +2110,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2069
2110
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
2070
2111
|
for (const { file, name, metrics } of results) {
|
|
2071
2112
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
2072
|
-
const color = exceedsThreshold ?
|
|
2113
|
+
const color = exceedsThreshold ? chalk24.red : chalk24.white;
|
|
2073
2114
|
console.log(
|
|
2074
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
2115
|
+
`${color(`${file}:${name}`)} \u2192 volume: ${chalk24.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk24.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk24.magenta(metrics.effort.toFixed(1))}`
|
|
2075
2116
|
);
|
|
2076
2117
|
}
|
|
2077
2118
|
console.log(
|
|
2078
|
-
|
|
2119
|
+
chalk24.dim(
|
|
2079
2120
|
`
|
|
2080
2121
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
2081
2122
|
)
|
|
@@ -2090,24 +2131,24 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
2090
2131
|
import fs12 from "fs";
|
|
2091
2132
|
|
|
2092
2133
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
2093
|
-
import
|
|
2134
|
+
import chalk25 from "chalk";
|
|
2094
2135
|
function displayMaintainabilityResults(results, threshold) {
|
|
2095
2136
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
2096
2137
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
2097
|
-
console.log(
|
|
2138
|
+
console.log(chalk25.green("All files pass maintainability threshold"));
|
|
2098
2139
|
} else {
|
|
2099
2140
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
2100
|
-
const color = threshold !== void 0 ?
|
|
2141
|
+
const color = threshold !== void 0 ? chalk25.red : chalk25.white;
|
|
2101
2142
|
console.log(
|
|
2102
|
-
`${color(file)} \u2192 avg: ${
|
|
2143
|
+
`${color(file)} \u2192 avg: ${chalk25.cyan(avgMaintainability.toFixed(1))}, min: ${chalk25.yellow(minMaintainability.toFixed(1))}`
|
|
2103
2144
|
);
|
|
2104
2145
|
}
|
|
2105
2146
|
}
|
|
2106
|
-
console.log(
|
|
2147
|
+
console.log(chalk25.dim(`
|
|
2107
2148
|
Analyzed ${results.length} files`));
|
|
2108
2149
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
2109
2150
|
console.error(
|
|
2110
|
-
|
|
2151
|
+
chalk25.red(
|
|
2111
2152
|
`
|
|
2112
2153
|
Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code. Focus on one file at a time \u2014 run 'assist complexity <file>' to see all metrics. For larger files, start by extracting responsibilities into smaller files.`
|
|
2113
2154
|
)
|
|
@@ -2166,7 +2207,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2166
2207
|
|
|
2167
2208
|
// src/commands/complexity/sloc.ts
|
|
2168
2209
|
import fs13 from "fs";
|
|
2169
|
-
import
|
|
2210
|
+
import chalk26 from "chalk";
|
|
2170
2211
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
2171
2212
|
withSourceFiles(pattern2, (files) => {
|
|
2172
2213
|
const results = [];
|
|
@@ -2182,12 +2223,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2182
2223
|
results.sort((a, b) => b.lines - a.lines);
|
|
2183
2224
|
for (const { file, lines } of results) {
|
|
2184
2225
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
2185
|
-
const color = exceedsThreshold ?
|
|
2186
|
-
console.log(`${color(file)} \u2192 ${
|
|
2226
|
+
const color = exceedsThreshold ? chalk26.red : chalk26.white;
|
|
2227
|
+
console.log(`${color(file)} \u2192 ${chalk26.cyan(lines)} lines`);
|
|
2187
2228
|
}
|
|
2188
2229
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
2189
2230
|
console.log(
|
|
2190
|
-
|
|
2231
|
+
chalk26.dim(`
|
|
2191
2232
|
Total: ${total} lines across ${files.length} files`)
|
|
2192
2233
|
);
|
|
2193
2234
|
if (hasViolation) {
|
|
@@ -2201,21 +2242,21 @@ async function analyze(pattern2) {
|
|
|
2201
2242
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
2202
2243
|
const files = findSourceFiles2(searchPattern);
|
|
2203
2244
|
if (files.length === 0) {
|
|
2204
|
-
console.log(
|
|
2245
|
+
console.log(chalk27.yellow("No files found matching pattern"));
|
|
2205
2246
|
return;
|
|
2206
2247
|
}
|
|
2207
2248
|
if (files.length === 1) {
|
|
2208
2249
|
const file = files[0];
|
|
2209
|
-
console.log(
|
|
2250
|
+
console.log(chalk27.bold.underline("SLOC"));
|
|
2210
2251
|
await sloc(file);
|
|
2211
2252
|
console.log();
|
|
2212
|
-
console.log(
|
|
2253
|
+
console.log(chalk27.bold.underline("Cyclomatic Complexity"));
|
|
2213
2254
|
await cyclomatic(file);
|
|
2214
2255
|
console.log();
|
|
2215
|
-
console.log(
|
|
2256
|
+
console.log(chalk27.bold.underline("Halstead Metrics"));
|
|
2216
2257
|
await halstead(file);
|
|
2217
2258
|
console.log();
|
|
2218
|
-
console.log(
|
|
2259
|
+
console.log(chalk27.bold.underline("Maintainability Index"));
|
|
2219
2260
|
await maintainability(file);
|
|
2220
2261
|
return;
|
|
2221
2262
|
}
|
|
@@ -2243,7 +2284,7 @@ function registerComplexity(program2) {
|
|
|
2243
2284
|
|
|
2244
2285
|
// src/commands/deploy/redirect.ts
|
|
2245
2286
|
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
2246
|
-
import
|
|
2287
|
+
import chalk28 from "chalk";
|
|
2247
2288
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
2248
2289
|
if (!window.location.pathname.endsWith('/')) {
|
|
2249
2290
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -2252,22 +2293,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
2252
2293
|
function redirect() {
|
|
2253
2294
|
const indexPath = "index.html";
|
|
2254
2295
|
if (!existsSync11(indexPath)) {
|
|
2255
|
-
console.log(
|
|
2296
|
+
console.log(chalk28.yellow("No index.html found"));
|
|
2256
2297
|
return;
|
|
2257
2298
|
}
|
|
2258
2299
|
const content = readFileSync9(indexPath, "utf-8");
|
|
2259
2300
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
2260
|
-
console.log(
|
|
2301
|
+
console.log(chalk28.dim("Trailing slash script already present"));
|
|
2261
2302
|
return;
|
|
2262
2303
|
}
|
|
2263
2304
|
const headCloseIndex = content.indexOf("</head>");
|
|
2264
2305
|
if (headCloseIndex === -1) {
|
|
2265
|
-
console.log(
|
|
2306
|
+
console.log(chalk28.red("Could not find </head> tag in index.html"));
|
|
2266
2307
|
return;
|
|
2267
2308
|
}
|
|
2268
2309
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
2269
2310
|
writeFileSync9(indexPath, newContent);
|
|
2270
|
-
console.log(
|
|
2311
|
+
console.log(chalk28.green("Added trailing slash redirect to index.html"));
|
|
2271
2312
|
}
|
|
2272
2313
|
|
|
2273
2314
|
// src/commands/registerDeploy.ts
|
|
@@ -2283,7 +2324,7 @@ import { basename as basename3 } from "path";
|
|
|
2283
2324
|
|
|
2284
2325
|
// src/commands/devlog/shared.ts
|
|
2285
2326
|
import { execSync as execSync10 } from "child_process";
|
|
2286
|
-
import
|
|
2327
|
+
import chalk29 from "chalk";
|
|
2287
2328
|
|
|
2288
2329
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
2289
2330
|
import { readdirSync, readFileSync as readFileSync10 } from "fs";
|
|
@@ -2344,13 +2385,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
2344
2385
|
}
|
|
2345
2386
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
2346
2387
|
for (const commit2 of commits) {
|
|
2347
|
-
console.log(` ${
|
|
2388
|
+
console.log(` ${chalk29.yellow(commit2.hash)} ${commit2.message}`);
|
|
2348
2389
|
if (verbose) {
|
|
2349
2390
|
const visibleFiles = commit2.files.filter(
|
|
2350
2391
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
2351
2392
|
);
|
|
2352
2393
|
for (const file of visibleFiles) {
|
|
2353
|
-
console.log(` ${
|
|
2394
|
+
console.log(` ${chalk29.dim(file)}`);
|
|
2354
2395
|
}
|
|
2355
2396
|
}
|
|
2356
2397
|
}
|
|
@@ -2375,15 +2416,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
2375
2416
|
}
|
|
2376
2417
|
|
|
2377
2418
|
// src/commands/devlog/list/printDateHeader.ts
|
|
2378
|
-
import
|
|
2419
|
+
import chalk30 from "chalk";
|
|
2379
2420
|
function printDateHeader(date, isSkipped, entries) {
|
|
2380
2421
|
if (isSkipped) {
|
|
2381
|
-
console.log(`${
|
|
2422
|
+
console.log(`${chalk30.bold.blue(date)} ${chalk30.dim("skipped")}`);
|
|
2382
2423
|
} else if (entries && entries.length > 0) {
|
|
2383
|
-
const entryInfo = entries.map((e) => `${
|
|
2384
|
-
console.log(`${
|
|
2424
|
+
const entryInfo = entries.map((e) => `${chalk30.green(e.version)} ${e.title}`).join(" | ");
|
|
2425
|
+
console.log(`${chalk30.bold.blue(date)} ${entryInfo}`);
|
|
2385
2426
|
} else {
|
|
2386
|
-
console.log(`${
|
|
2427
|
+
console.log(`${chalk30.bold.blue(date)} ${chalk30.red("\u26A0 devlog missing")}`);
|
|
2387
2428
|
}
|
|
2388
2429
|
}
|
|
2389
2430
|
|
|
@@ -2486,24 +2527,24 @@ function bumpVersion(version2, type) {
|
|
|
2486
2527
|
|
|
2487
2528
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
2488
2529
|
import { execSync as execSync13 } from "child_process";
|
|
2489
|
-
import
|
|
2530
|
+
import chalk32 from "chalk";
|
|
2490
2531
|
|
|
2491
2532
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
2492
|
-
import
|
|
2533
|
+
import chalk31 from "chalk";
|
|
2493
2534
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
2494
2535
|
if (conventional && firstHash) {
|
|
2495
2536
|
const version2 = getVersionAtCommit(firstHash);
|
|
2496
2537
|
if (version2) {
|
|
2497
|
-
console.log(`${
|
|
2538
|
+
console.log(`${chalk31.bold("version:")} ${stripToMinor(version2)}`);
|
|
2498
2539
|
} else {
|
|
2499
|
-
console.log(`${
|
|
2540
|
+
console.log(`${chalk31.bold("version:")} ${chalk31.red("unknown")}`);
|
|
2500
2541
|
}
|
|
2501
2542
|
} else if (patchVersion && minorVersion) {
|
|
2502
2543
|
console.log(
|
|
2503
|
-
`${
|
|
2544
|
+
`${chalk31.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
2504
2545
|
);
|
|
2505
2546
|
} else {
|
|
2506
|
-
console.log(`${
|
|
2547
|
+
console.log(`${chalk31.bold("version:")} v0.1 (initial)`);
|
|
2507
2548
|
}
|
|
2508
2549
|
}
|
|
2509
2550
|
|
|
@@ -2550,16 +2591,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
2550
2591
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
2551
2592
|
}
|
|
2552
2593
|
function logName(repoName) {
|
|
2553
|
-
console.log(`${
|
|
2594
|
+
console.log(`${chalk32.bold("name:")} ${repoName}`);
|
|
2554
2595
|
}
|
|
2555
2596
|
function displayNextEntry(ctx, targetDate, commits) {
|
|
2556
2597
|
logName(ctx.repoName);
|
|
2557
2598
|
printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
|
|
2558
|
-
console.log(
|
|
2599
|
+
console.log(chalk32.bold.blue(targetDate));
|
|
2559
2600
|
printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
|
|
2560
2601
|
}
|
|
2561
2602
|
function logNoCommits(lastInfo) {
|
|
2562
|
-
console.log(
|
|
2603
|
+
console.log(chalk32.dim(noCommitsMessage(!!lastInfo)));
|
|
2563
2604
|
}
|
|
2564
2605
|
|
|
2565
2606
|
// src/commands/devlog/next/index.ts
|
|
@@ -2594,16 +2635,16 @@ function next(options2) {
|
|
|
2594
2635
|
}
|
|
2595
2636
|
|
|
2596
2637
|
// src/commands/devlog/skip.ts
|
|
2597
|
-
import
|
|
2638
|
+
import chalk33 from "chalk";
|
|
2598
2639
|
function skip(date) {
|
|
2599
2640
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
2600
|
-
console.log(
|
|
2641
|
+
console.log(chalk33.red("Invalid date format. Use YYYY-MM-DD"));
|
|
2601
2642
|
process.exit(1);
|
|
2602
2643
|
}
|
|
2603
2644
|
const config = loadConfig();
|
|
2604
2645
|
const skipDays = config.devlog?.skip?.days ?? [];
|
|
2605
2646
|
if (skipDays.includes(date)) {
|
|
2606
|
-
console.log(
|
|
2647
|
+
console.log(chalk33.yellow(`${date} is already in skip list`));
|
|
2607
2648
|
return;
|
|
2608
2649
|
}
|
|
2609
2650
|
skipDays.push(date);
|
|
@@ -2616,20 +2657,20 @@ function skip(date) {
|
|
|
2616
2657
|
}
|
|
2617
2658
|
};
|
|
2618
2659
|
saveConfig(config);
|
|
2619
|
-
console.log(
|
|
2660
|
+
console.log(chalk33.green(`Added ${date} to skip list`));
|
|
2620
2661
|
}
|
|
2621
2662
|
|
|
2622
2663
|
// src/commands/devlog/version.ts
|
|
2623
|
-
import
|
|
2664
|
+
import chalk34 from "chalk";
|
|
2624
2665
|
function version() {
|
|
2625
2666
|
const config = loadConfig();
|
|
2626
2667
|
const name = getRepoName();
|
|
2627
2668
|
const lastInfo = getLastVersionInfo(name, config);
|
|
2628
2669
|
const lastVersion = lastInfo?.version ?? null;
|
|
2629
2670
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
2630
|
-
console.log(`${
|
|
2631
|
-
console.log(`${
|
|
2632
|
-
console.log(`${
|
|
2671
|
+
console.log(`${chalk34.bold("name:")} ${name}`);
|
|
2672
|
+
console.log(`${chalk34.bold("last:")} ${lastVersion ?? chalk34.dim("none")}`);
|
|
2673
|
+
console.log(`${chalk34.bold("next:")} ${nextVersion ?? chalk34.dim("none")}`);
|
|
2633
2674
|
}
|
|
2634
2675
|
|
|
2635
2676
|
// src/commands/registerDevlog.ts
|
|
@@ -2886,20 +2927,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
2886
2927
|
}
|
|
2887
2928
|
|
|
2888
2929
|
// src/commands/prs/listComments/formatForHuman.ts
|
|
2889
|
-
import
|
|
2930
|
+
import chalk35 from "chalk";
|
|
2890
2931
|
function formatForHuman(comment) {
|
|
2891
2932
|
if (comment.type === "review") {
|
|
2892
|
-
const stateColor = comment.state === "APPROVED" ?
|
|
2933
|
+
const stateColor = comment.state === "APPROVED" ? chalk35.green : comment.state === "CHANGES_REQUESTED" ? chalk35.red : chalk35.yellow;
|
|
2893
2934
|
return [
|
|
2894
|
-
`${
|
|
2935
|
+
`${chalk35.cyan("Review")} by ${chalk35.bold(comment.user)} ${stateColor(`[${comment.state}]`)}`,
|
|
2895
2936
|
comment.body,
|
|
2896
2937
|
""
|
|
2897
2938
|
].join("\n");
|
|
2898
2939
|
}
|
|
2899
2940
|
const location = comment.line ? `:${comment.line}` : "";
|
|
2900
2941
|
return [
|
|
2901
|
-
`${
|
|
2902
|
-
|
|
2942
|
+
`${chalk35.cyan("Line comment")} by ${chalk35.bold(comment.user)} on ${chalk35.dim(`${comment.path}${location}`)}`,
|
|
2943
|
+
chalk35.dim(comment.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
2903
2944
|
comment.body,
|
|
2904
2945
|
""
|
|
2905
2946
|
].join("\n");
|
|
@@ -2978,13 +3019,13 @@ import { execSync as execSync19 } from "child_process";
|
|
|
2978
3019
|
import enquirer4 from "enquirer";
|
|
2979
3020
|
|
|
2980
3021
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
2981
|
-
import
|
|
3022
|
+
import chalk36 from "chalk";
|
|
2982
3023
|
var STATUS_MAP = {
|
|
2983
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
2984
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
3024
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk36.magenta("merged"), date: pr.mergedAt } : null,
|
|
3025
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk36.red("closed"), date: pr.closedAt } : null
|
|
2985
3026
|
};
|
|
2986
3027
|
function defaultStatus(pr) {
|
|
2987
|
-
return { label:
|
|
3028
|
+
return { label: chalk36.green("opened"), date: pr.createdAt };
|
|
2988
3029
|
}
|
|
2989
3030
|
function getStatus(pr) {
|
|
2990
3031
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -2993,11 +3034,11 @@ function formatDate(dateStr) {
|
|
|
2993
3034
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
2994
3035
|
}
|
|
2995
3036
|
function formatPrHeader(pr, status) {
|
|
2996
|
-
return `${
|
|
3037
|
+
return `${chalk36.cyan(`#${pr.number}`)} ${pr.title} ${chalk36.dim(`(${pr.author.login},`)} ${status.label} ${chalk36.dim(`${formatDate(status.date)})`)}`;
|
|
2997
3038
|
}
|
|
2998
3039
|
function logPrDetails(pr) {
|
|
2999
3040
|
console.log(
|
|
3000
|
-
|
|
3041
|
+
chalk36.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
3001
3042
|
);
|
|
3002
3043
|
console.log();
|
|
3003
3044
|
}
|
|
@@ -3161,10 +3202,10 @@ function registerPrs(program2) {
|
|
|
3161
3202
|
|
|
3162
3203
|
// src/commands/refactor/check/index.ts
|
|
3163
3204
|
import { spawn as spawn3 } from "child_process";
|
|
3164
|
-
import * as
|
|
3205
|
+
import * as path17 from "path";
|
|
3165
3206
|
|
|
3166
3207
|
// src/commands/refactor/logViolations.ts
|
|
3167
|
-
import
|
|
3208
|
+
import chalk37 from "chalk";
|
|
3168
3209
|
var DEFAULT_MAX_LINES = 100;
|
|
3169
3210
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
3170
3211
|
if (violations.length === 0) {
|
|
@@ -3173,43 +3214,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
3173
3214
|
}
|
|
3174
3215
|
return;
|
|
3175
3216
|
}
|
|
3176
|
-
console.error(
|
|
3217
|
+
console.error(chalk37.red(`
|
|
3177
3218
|
Refactor check failed:
|
|
3178
3219
|
`));
|
|
3179
|
-
console.error(
|
|
3220
|
+
console.error(chalk37.red(` The following files exceed ${maxLines} lines:
|
|
3180
3221
|
`));
|
|
3181
3222
|
for (const violation of violations) {
|
|
3182
|
-
console.error(
|
|
3223
|
+
console.error(chalk37.red(` ${violation.file} (${violation.lines} lines)`));
|
|
3183
3224
|
}
|
|
3184
3225
|
console.error(
|
|
3185
|
-
|
|
3226
|
+
chalk37.yellow(
|
|
3186
3227
|
`
|
|
3187
3228
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
3188
3229
|
way to refactor it, ignore it with:
|
|
3189
3230
|
`
|
|
3190
3231
|
)
|
|
3191
3232
|
);
|
|
3192
|
-
console.error(
|
|
3233
|
+
console.error(chalk37.gray(` assist refactor ignore <file>
|
|
3193
3234
|
`));
|
|
3194
3235
|
if (process.env.CLAUDECODE) {
|
|
3195
|
-
console.error(
|
|
3236
|
+
console.error(chalk37.cyan(`
|
|
3196
3237
|
## Extracting Code to New Files
|
|
3197
3238
|
`));
|
|
3198
3239
|
console.error(
|
|
3199
|
-
|
|
3240
|
+
chalk37.cyan(
|
|
3200
3241
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
3201
3242
|
`
|
|
3202
3243
|
)
|
|
3203
3244
|
);
|
|
3204
3245
|
console.error(
|
|
3205
|
-
|
|
3246
|
+
chalk37.cyan(
|
|
3206
3247
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
3207
3248
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
3208
3249
|
`
|
|
3209
3250
|
)
|
|
3210
3251
|
);
|
|
3211
3252
|
console.error(
|
|
3212
|
-
|
|
3253
|
+
chalk37.cyan(
|
|
3213
3254
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
3214
3255
|
domains, move it to a common/shared folder.
|
|
3215
3256
|
`
|
|
@@ -3338,7 +3379,7 @@ ${failed.length} verify script(s) failed:`);
|
|
|
3338
3379
|
async function runVerifyQuietly() {
|
|
3339
3380
|
const result = findPackageJsonWithVerifyScripts(process.cwd());
|
|
3340
3381
|
if (!result) return true;
|
|
3341
|
-
const packageDir =
|
|
3382
|
+
const packageDir = path17.dirname(result.packageJsonPath);
|
|
3342
3383
|
const results = await Promise.all(
|
|
3343
3384
|
result.verifyScripts.map((script) => runScript2(script, packageDir))
|
|
3344
3385
|
);
|
|
@@ -3365,11 +3406,11 @@ async function check(pattern2, options2) {
|
|
|
3365
3406
|
|
|
3366
3407
|
// src/commands/refactor/ignore.ts
|
|
3367
3408
|
import fs16 from "fs";
|
|
3368
|
-
import
|
|
3409
|
+
import chalk38 from "chalk";
|
|
3369
3410
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
3370
3411
|
function ignore(file) {
|
|
3371
3412
|
if (!fs16.existsSync(file)) {
|
|
3372
|
-
console.error(
|
|
3413
|
+
console.error(chalk38.red(`Error: File does not exist: ${file}`));
|
|
3373
3414
|
process.exit(1);
|
|
3374
3415
|
}
|
|
3375
3416
|
const content = fs16.readFileSync(file, "utf-8");
|
|
@@ -3385,18 +3426,18 @@ function ignore(file) {
|
|
|
3385
3426
|
fs16.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
3386
3427
|
}
|
|
3387
3428
|
console.log(
|
|
3388
|
-
|
|
3429
|
+
chalk38.green(
|
|
3389
3430
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
3390
3431
|
)
|
|
3391
3432
|
);
|
|
3392
3433
|
}
|
|
3393
3434
|
|
|
3394
3435
|
// src/commands/refactor/restructure/index.ts
|
|
3395
|
-
import
|
|
3396
|
-
import
|
|
3436
|
+
import path26 from "path";
|
|
3437
|
+
import chalk41 from "chalk";
|
|
3397
3438
|
|
|
3398
3439
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
3399
|
-
import
|
|
3440
|
+
import path18 from "path";
|
|
3400
3441
|
import ts7 from "typescript";
|
|
3401
3442
|
|
|
3402
3443
|
// src/commands/refactor/restructure/buildImportGraph/getImportSpecifiers.ts
|
|
@@ -3423,7 +3464,7 @@ function loadParsedConfig(tsConfigPath) {
|
|
|
3423
3464
|
return ts7.parseJsonConfigFileContent(
|
|
3424
3465
|
configFile.config,
|
|
3425
3466
|
ts7.sys,
|
|
3426
|
-
|
|
3467
|
+
path18.dirname(tsConfigPath)
|
|
3427
3468
|
);
|
|
3428
3469
|
}
|
|
3429
3470
|
function addToSetMap(map, key, value) {
|
|
@@ -3439,7 +3480,7 @@ function resolveImport(specifier, filePath, options2) {
|
|
|
3439
3480
|
const resolved = ts7.resolveModuleName(specifier, filePath, options2, ts7.sys);
|
|
3440
3481
|
const resolvedPath = resolved.resolvedModule?.resolvedFileName;
|
|
3441
3482
|
if (!resolvedPath || resolvedPath.includes("node_modules")) return null;
|
|
3442
|
-
return
|
|
3483
|
+
return path18.resolve(resolvedPath);
|
|
3443
3484
|
}
|
|
3444
3485
|
function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
3445
3486
|
const parsed = loadParsedConfig(tsConfigPath);
|
|
@@ -3448,7 +3489,7 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
|
3448
3489
|
const importedBy = /* @__PURE__ */ new Map();
|
|
3449
3490
|
const imports = /* @__PURE__ */ new Map();
|
|
3450
3491
|
for (const sourceFile of program2.getSourceFiles()) {
|
|
3451
|
-
const filePath =
|
|
3492
|
+
const filePath = path18.resolve(sourceFile.fileName);
|
|
3452
3493
|
if (filePath.includes("node_modules")) continue;
|
|
3453
3494
|
for (const specifier of getImportSpecifiers(sourceFile)) {
|
|
3454
3495
|
const absTarget = resolveImport(specifier, filePath, parsed.options);
|
|
@@ -3462,12 +3503,12 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
|
3462
3503
|
}
|
|
3463
3504
|
|
|
3464
3505
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
3465
|
-
import
|
|
3506
|
+
import path19 from "path";
|
|
3466
3507
|
function clusterDirectories(graph) {
|
|
3467
3508
|
const dirImportedBy = /* @__PURE__ */ new Map();
|
|
3468
3509
|
for (const edge of graph.edges) {
|
|
3469
|
-
const sourceDir =
|
|
3470
|
-
const targetDir =
|
|
3510
|
+
const sourceDir = path19.dirname(edge.source);
|
|
3511
|
+
const targetDir = path19.dirname(edge.target);
|
|
3471
3512
|
if (sourceDir === targetDir) continue;
|
|
3472
3513
|
if (!graph.files.has(edge.target)) continue;
|
|
3473
3514
|
const existing = dirImportedBy.get(targetDir) ?? /* @__PURE__ */ new Set();
|
|
@@ -3495,20 +3536,20 @@ function clusterDirectories(graph) {
|
|
|
3495
3536
|
return clusters;
|
|
3496
3537
|
}
|
|
3497
3538
|
function isAncestor(ancestor, descendant) {
|
|
3498
|
-
const rel =
|
|
3539
|
+
const rel = path19.relative(ancestor, descendant);
|
|
3499
3540
|
return !rel.startsWith("..") && rel !== "";
|
|
3500
3541
|
}
|
|
3501
3542
|
|
|
3502
3543
|
// src/commands/refactor/restructure/clusterFiles.ts
|
|
3503
|
-
import
|
|
3544
|
+
import path20 from "path";
|
|
3504
3545
|
function findRootParent(file, importedBy, visited) {
|
|
3505
3546
|
const importers = importedBy.get(file);
|
|
3506
3547
|
if (!importers || importers.size !== 1) return file;
|
|
3507
3548
|
const parent = [...importers][0];
|
|
3508
|
-
const parentDir =
|
|
3509
|
-
const fileDir =
|
|
3549
|
+
const parentDir = path20.dirname(parent);
|
|
3550
|
+
const fileDir = path20.dirname(file);
|
|
3510
3551
|
if (parentDir !== fileDir) return file;
|
|
3511
|
-
if (
|
|
3552
|
+
if (path20.basename(parent, path20.extname(parent)) === "index") return file;
|
|
3512
3553
|
if (visited.has(parent)) return file;
|
|
3513
3554
|
visited.add(parent);
|
|
3514
3555
|
return findRootParent(parent, importedBy, visited);
|
|
@@ -3516,16 +3557,16 @@ function findRootParent(file, importedBy, visited) {
|
|
|
3516
3557
|
function clusterFiles(graph) {
|
|
3517
3558
|
const clusters = /* @__PURE__ */ new Map();
|
|
3518
3559
|
for (const file of graph.files) {
|
|
3519
|
-
const basename7 =
|
|
3560
|
+
const basename7 = path20.basename(file, path20.extname(file));
|
|
3520
3561
|
if (basename7 === "index") continue;
|
|
3521
3562
|
const importers = graph.importedBy.get(file);
|
|
3522
3563
|
if (!importers || importers.size !== 1) continue;
|
|
3523
3564
|
const parent = [...importers][0];
|
|
3524
3565
|
if (!graph.files.has(parent)) continue;
|
|
3525
|
-
const parentDir =
|
|
3526
|
-
const fileDir =
|
|
3566
|
+
const parentDir = path20.dirname(parent);
|
|
3567
|
+
const fileDir = path20.dirname(file);
|
|
3527
3568
|
if (parentDir !== fileDir) continue;
|
|
3528
|
-
const parentBasename =
|
|
3569
|
+
const parentBasename = path20.basename(parent, path20.extname(parent));
|
|
3529
3570
|
if (parentBasename === "index") continue;
|
|
3530
3571
|
const root = findRootParent(parent, graph.importedBy, /* @__PURE__ */ new Set([file]));
|
|
3531
3572
|
if (!root || root === file) continue;
|
|
@@ -3537,7 +3578,7 @@ function clusterFiles(graph) {
|
|
|
3537
3578
|
}
|
|
3538
3579
|
|
|
3539
3580
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
3540
|
-
import
|
|
3581
|
+
import path21 from "path";
|
|
3541
3582
|
|
|
3542
3583
|
// src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
|
|
3543
3584
|
import fs17 from "fs";
|
|
@@ -3591,7 +3632,7 @@ function normalizeSpecifier(rel) {
|
|
|
3591
3632
|
);
|
|
3592
3633
|
}
|
|
3593
3634
|
function computeSpecifier(fromFile, toFile) {
|
|
3594
|
-
return normalizeSpecifier(
|
|
3635
|
+
return normalizeSpecifier(path21.relative(path21.dirname(fromFile), toFile));
|
|
3595
3636
|
}
|
|
3596
3637
|
function isAffected(edge, moveMap) {
|
|
3597
3638
|
return moveMap.has(edge.target) || moveMap.has(edge.source);
|
|
@@ -3635,51 +3676,51 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
3635
3676
|
}
|
|
3636
3677
|
|
|
3637
3678
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
3638
|
-
import
|
|
3639
|
-
import
|
|
3679
|
+
import path22 from "path";
|
|
3680
|
+
import chalk39 from "chalk";
|
|
3640
3681
|
function relPath(filePath) {
|
|
3641
|
-
return
|
|
3682
|
+
return path22.relative(process.cwd(), filePath);
|
|
3642
3683
|
}
|
|
3643
3684
|
function displayMoves(plan) {
|
|
3644
3685
|
if (plan.moves.length === 0) return;
|
|
3645
|
-
console.log(
|
|
3686
|
+
console.log(chalk39.bold("\nFile moves:"));
|
|
3646
3687
|
for (const move of plan.moves) {
|
|
3647
3688
|
console.log(
|
|
3648
|
-
` ${
|
|
3689
|
+
` ${chalk39.red(relPath(move.from))} \u2192 ${chalk39.green(relPath(move.to))}`
|
|
3649
3690
|
);
|
|
3650
|
-
console.log(
|
|
3691
|
+
console.log(chalk39.dim(` ${move.reason}`));
|
|
3651
3692
|
}
|
|
3652
3693
|
}
|
|
3653
3694
|
function displayRewrites(rewrites) {
|
|
3654
3695
|
if (rewrites.length === 0) return;
|
|
3655
3696
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
3656
|
-
console.log(
|
|
3697
|
+
console.log(chalk39.bold(`
|
|
3657
3698
|
Import rewrites (${affectedFiles.size} files):`));
|
|
3658
3699
|
for (const file of affectedFiles) {
|
|
3659
|
-
console.log(` ${
|
|
3700
|
+
console.log(` ${chalk39.cyan(relPath(file))}:`);
|
|
3660
3701
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
3661
3702
|
(r) => r.file === file
|
|
3662
3703
|
)) {
|
|
3663
3704
|
console.log(
|
|
3664
|
-
` ${
|
|
3705
|
+
` ${chalk39.red(`"${oldSpecifier}"`)} \u2192 ${chalk39.green(`"${newSpecifier}"`)}`
|
|
3665
3706
|
);
|
|
3666
3707
|
}
|
|
3667
3708
|
}
|
|
3668
3709
|
}
|
|
3669
3710
|
function displayPlan(plan) {
|
|
3670
3711
|
if (plan.warnings.length > 0) {
|
|
3671
|
-
console.log(
|
|
3672
|
-
for (const w of plan.warnings) console.log(
|
|
3712
|
+
console.log(chalk39.yellow("\nWarnings:"));
|
|
3713
|
+
for (const w of plan.warnings) console.log(chalk39.yellow(` ${w}`));
|
|
3673
3714
|
}
|
|
3674
3715
|
if (plan.newDirectories.length > 0) {
|
|
3675
|
-
console.log(
|
|
3716
|
+
console.log(chalk39.bold("\nNew directories:"));
|
|
3676
3717
|
for (const dir of plan.newDirectories)
|
|
3677
|
-
console.log(
|
|
3718
|
+
console.log(chalk39.green(` ${dir}/`));
|
|
3678
3719
|
}
|
|
3679
3720
|
displayMoves(plan);
|
|
3680
3721
|
displayRewrites(plan.rewrites);
|
|
3681
3722
|
console.log(
|
|
3682
|
-
|
|
3723
|
+
chalk39.dim(
|
|
3683
3724
|
`
|
|
3684
3725
|
Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
|
|
3685
3726
|
)
|
|
@@ -3688,33 +3729,33 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
|
|
|
3688
3729
|
|
|
3689
3730
|
// src/commands/refactor/restructure/executePlan.ts
|
|
3690
3731
|
import fs18 from "fs";
|
|
3691
|
-
import
|
|
3692
|
-
import
|
|
3732
|
+
import path23 from "path";
|
|
3733
|
+
import chalk40 from "chalk";
|
|
3693
3734
|
function executePlan(plan) {
|
|
3694
3735
|
const updatedContents = applyRewrites(plan.rewrites);
|
|
3695
3736
|
for (const [file, content] of updatedContents) {
|
|
3696
3737
|
fs18.writeFileSync(file, content, "utf-8");
|
|
3697
3738
|
console.log(
|
|
3698
|
-
|
|
3739
|
+
chalk40.cyan(` Rewrote imports in ${path23.relative(process.cwd(), file)}`)
|
|
3699
3740
|
);
|
|
3700
3741
|
}
|
|
3701
3742
|
for (const dir of plan.newDirectories) {
|
|
3702
3743
|
fs18.mkdirSync(dir, { recursive: true });
|
|
3703
|
-
console.log(
|
|
3744
|
+
console.log(chalk40.green(` Created ${path23.relative(process.cwd(), dir)}/`));
|
|
3704
3745
|
}
|
|
3705
3746
|
for (const move of plan.moves) {
|
|
3706
|
-
const targetDir =
|
|
3747
|
+
const targetDir = path23.dirname(move.to);
|
|
3707
3748
|
if (!fs18.existsSync(targetDir)) {
|
|
3708
3749
|
fs18.mkdirSync(targetDir, { recursive: true });
|
|
3709
3750
|
}
|
|
3710
3751
|
fs18.renameSync(move.from, move.to);
|
|
3711
3752
|
console.log(
|
|
3712
|
-
|
|
3713
|
-
` Moved ${
|
|
3753
|
+
chalk40.white(
|
|
3754
|
+
` Moved ${path23.relative(process.cwd(), move.from)} \u2192 ${path23.relative(process.cwd(), move.to)}`
|
|
3714
3755
|
)
|
|
3715
3756
|
);
|
|
3716
3757
|
}
|
|
3717
|
-
removeEmptyDirectories(plan.moves.map((m) =>
|
|
3758
|
+
removeEmptyDirectories(plan.moves.map((m) => path23.dirname(m.from)));
|
|
3718
3759
|
}
|
|
3719
3760
|
function removeEmptyDirectories(dirs) {
|
|
3720
3761
|
const unique = [...new Set(dirs)];
|
|
@@ -3724,8 +3765,8 @@ function removeEmptyDirectories(dirs) {
|
|
|
3724
3765
|
if (entries.length === 0) {
|
|
3725
3766
|
fs18.rmdirSync(dir);
|
|
3726
3767
|
console.log(
|
|
3727
|
-
|
|
3728
|
-
` Removed empty directory ${
|
|
3768
|
+
chalk40.dim(
|
|
3769
|
+
` Removed empty directory ${path23.relative(process.cwd(), dir)}`
|
|
3729
3770
|
)
|
|
3730
3771
|
);
|
|
3731
3772
|
}
|
|
@@ -3734,13 +3775,13 @@ function removeEmptyDirectories(dirs) {
|
|
|
3734
3775
|
|
|
3735
3776
|
// src/commands/refactor/restructure/planFileMoves/index.ts
|
|
3736
3777
|
import fs20 from "fs";
|
|
3737
|
-
import
|
|
3778
|
+
import path25 from "path";
|
|
3738
3779
|
|
|
3739
3780
|
// src/commands/refactor/restructure/planFileMoves/planDirectoryMoves.ts
|
|
3740
3781
|
import fs19 from "fs";
|
|
3741
|
-
import
|
|
3782
|
+
import path24 from "path";
|
|
3742
3783
|
function collectEntry(results, dir, entry) {
|
|
3743
|
-
const full =
|
|
3784
|
+
const full = path24.join(dir, entry.name);
|
|
3744
3785
|
const items = entry.isDirectory() ? listFilesRecursive(full) : [full];
|
|
3745
3786
|
results.push(...items);
|
|
3746
3787
|
}
|
|
@@ -3754,15 +3795,15 @@ function listFilesRecursive(dir) {
|
|
|
3754
3795
|
}
|
|
3755
3796
|
function addDirectoryFileMoves(moves, childDir, newLocation, reason) {
|
|
3756
3797
|
for (const file of listFilesRecursive(childDir)) {
|
|
3757
|
-
const rel =
|
|
3758
|
-
moves.push({ from: file, to:
|
|
3798
|
+
const rel = path24.relative(childDir, file);
|
|
3799
|
+
moves.push({ from: file, to: path24.join(newLocation, rel), reason });
|
|
3759
3800
|
}
|
|
3760
3801
|
}
|
|
3761
3802
|
function resolveChildDest(parentDir, childDir) {
|
|
3762
|
-
return
|
|
3803
|
+
return path24.join(parentDir, path24.basename(childDir));
|
|
3763
3804
|
}
|
|
3764
3805
|
function childMoveReason(parentDir) {
|
|
3765
|
-
return `Directory only imported from ${
|
|
3806
|
+
return `Directory only imported from ${path24.basename(parentDir)}/`;
|
|
3766
3807
|
}
|
|
3767
3808
|
function registerDirectoryMove(result, childDir, dest, parentDir) {
|
|
3768
3809
|
result.directories.push(dest);
|
|
@@ -3790,7 +3831,7 @@ function emptyResult() {
|
|
|
3790
3831
|
return { moves: [], directories: [], warnings: [] };
|
|
3791
3832
|
}
|
|
3792
3833
|
function childMoveData(child, newDir, parentBase) {
|
|
3793
|
-
const to =
|
|
3834
|
+
const to = path25.join(newDir, path25.basename(child));
|
|
3794
3835
|
return { from: child, to, reason: `Only imported by ${parentBase}` };
|
|
3795
3836
|
}
|
|
3796
3837
|
function addChildMoves(moves, children, newDir, parentBase) {
|
|
@@ -3803,15 +3844,15 @@ function checkDirConflict(result, label, dir) {
|
|
|
3803
3844
|
return true;
|
|
3804
3845
|
}
|
|
3805
3846
|
function getBaseName(filePath) {
|
|
3806
|
-
return
|
|
3847
|
+
return path25.basename(filePath, path25.extname(filePath));
|
|
3807
3848
|
}
|
|
3808
3849
|
function resolveClusterDir(parent) {
|
|
3809
|
-
return
|
|
3850
|
+
return path25.join(path25.dirname(parent), getBaseName(parent));
|
|
3810
3851
|
}
|
|
3811
3852
|
function createParentMove(parent, newDir) {
|
|
3812
3853
|
return {
|
|
3813
3854
|
from: parent,
|
|
3814
|
-
to:
|
|
3855
|
+
to: path25.join(newDir, `index${path25.extname(parent)}`),
|
|
3815
3856
|
reason: `Main module of new ${getBaseName(parent)}/ directory`
|
|
3816
3857
|
};
|
|
3817
3858
|
}
|
|
@@ -3835,7 +3876,7 @@ function planFileMoves(clusters) {
|
|
|
3835
3876
|
|
|
3836
3877
|
// src/commands/refactor/restructure/index.ts
|
|
3837
3878
|
function buildPlan(candidateFiles, tsConfigPath) {
|
|
3838
|
-
const candidates = new Set(candidateFiles.map((f) =>
|
|
3879
|
+
const candidates = new Set(candidateFiles.map((f) => path26.resolve(f)));
|
|
3839
3880
|
const graph = buildImportGraph(candidates, tsConfigPath);
|
|
3840
3881
|
const allProjectFiles = /* @__PURE__ */ new Set([
|
|
3841
3882
|
...graph.importedBy.keys(),
|
|
@@ -3855,22 +3896,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
3855
3896
|
const targetPattern = pattern2 ?? "src";
|
|
3856
3897
|
const files = findSourceFiles2(targetPattern);
|
|
3857
3898
|
if (files.length === 0) {
|
|
3858
|
-
console.log(
|
|
3899
|
+
console.log(chalk41.yellow("No files found matching pattern"));
|
|
3859
3900
|
return;
|
|
3860
3901
|
}
|
|
3861
|
-
const tsConfigPath =
|
|
3902
|
+
const tsConfigPath = path26.resolve("tsconfig.json");
|
|
3862
3903
|
const plan = buildPlan(files, tsConfigPath);
|
|
3863
3904
|
if (plan.moves.length === 0) {
|
|
3864
|
-
console.log(
|
|
3905
|
+
console.log(chalk41.green("No restructuring needed"));
|
|
3865
3906
|
return;
|
|
3866
3907
|
}
|
|
3867
3908
|
displayPlan(plan);
|
|
3868
3909
|
if (options2.apply) {
|
|
3869
|
-
console.log(
|
|
3910
|
+
console.log(chalk41.bold("\nApplying changes..."));
|
|
3870
3911
|
executePlan(plan);
|
|
3871
|
-
console.log(
|
|
3912
|
+
console.log(chalk41.green("\nRestructuring complete"));
|
|
3872
3913
|
} else {
|
|
3873
|
-
console.log(
|
|
3914
|
+
console.log(chalk41.dim("\nDry run. Use --apply to execute."));
|
|
3874
3915
|
}
|
|
3875
3916
|
}
|
|
3876
3917
|
|
|
@@ -4009,7 +4050,7 @@ async function configure() {
|
|
|
4009
4050
|
import { existsSync as existsSync16 } from "fs";
|
|
4010
4051
|
|
|
4011
4052
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
4012
|
-
import { dirname as
|
|
4053
|
+
import { dirname as dirname12, join as join15 } from "path";
|
|
4013
4054
|
|
|
4014
4055
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
4015
4056
|
import { renameSync } from "fs";
|
|
@@ -4059,11 +4100,11 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
4059
4100
|
for (let i = 0; i < vttFiles.length; i++) {
|
|
4060
4101
|
const vttFile = vttFiles[i];
|
|
4061
4102
|
if (!isValidDatePrefix(vttFile.filename)) {
|
|
4062
|
-
const vttFileDir =
|
|
4103
|
+
const vttFileDir = dirname12(vttFile.absolutePath);
|
|
4063
4104
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
4064
4105
|
if (newFilename) {
|
|
4065
4106
|
const newRelativePath = join15(
|
|
4066
|
-
|
|
4107
|
+
dirname12(vttFile.relativePath),
|
|
4067
4108
|
newFilename
|
|
4068
4109
|
);
|
|
4069
4110
|
vttFiles[i] = {
|
|
@@ -4081,7 +4122,7 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
4081
4122
|
|
|
4082
4123
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
4083
4124
|
import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync13 } from "fs";
|
|
4084
|
-
import { basename as basename5, dirname as
|
|
4125
|
+
import { basename as basename5, dirname as dirname13, join as join16 } from "path";
|
|
4085
4126
|
|
|
4086
4127
|
// src/commands/transcript/cleanText.ts
|
|
4087
4128
|
function cleanText(text) {
|
|
@@ -4295,7 +4336,7 @@ function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
|
4295
4336
|
}
|
|
4296
4337
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
4297
4338
|
const mdFile = toMdFilename(vttFile.filename);
|
|
4298
|
-
const relativeDir =
|
|
4339
|
+
const relativeDir = dirname13(vttFile.relativePath);
|
|
4299
4340
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
4300
4341
|
const outputPath = join16(outputDir, mdFile);
|
|
4301
4342
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
@@ -4400,7 +4441,7 @@ async function format() {
|
|
|
4400
4441
|
|
|
4401
4442
|
// src/commands/transcript/summarise/index.ts
|
|
4402
4443
|
import { existsSync as existsSync18 } from "fs";
|
|
4403
|
-
import { basename as basename6, dirname as
|
|
4444
|
+
import { basename as basename6, dirname as dirname15, join as join18, relative as relative2 } from "path";
|
|
4404
4445
|
|
|
4405
4446
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
4406
4447
|
import {
|
|
@@ -4410,17 +4451,17 @@ import {
|
|
|
4410
4451
|
renameSync as renameSync2,
|
|
4411
4452
|
rmSync
|
|
4412
4453
|
} from "fs";
|
|
4413
|
-
import { dirname as
|
|
4454
|
+
import { dirname as dirname14, join as join17 } from "path";
|
|
4414
4455
|
|
|
4415
4456
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
4416
|
-
import
|
|
4457
|
+
import chalk42 from "chalk";
|
|
4417
4458
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
4418
4459
|
function validateStagedContent(filename, content) {
|
|
4419
4460
|
const firstLine = content.split("\n")[0];
|
|
4420
4461
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
4421
4462
|
if (!match) {
|
|
4422
4463
|
console.error(
|
|
4423
|
-
|
|
4464
|
+
chalk42.red(
|
|
4424
4465
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
4425
4466
|
)
|
|
4426
4467
|
);
|
|
@@ -4429,7 +4470,7 @@ function validateStagedContent(filename, content) {
|
|
|
4429
4470
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
4430
4471
|
if (!contentAfterLink) {
|
|
4431
4472
|
console.error(
|
|
4432
|
-
|
|
4473
|
+
chalk42.red(
|
|
4433
4474
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
4434
4475
|
)
|
|
4435
4476
|
);
|
|
@@ -4464,7 +4505,7 @@ function processStagedFile() {
|
|
|
4464
4505
|
process.exit(1);
|
|
4465
4506
|
}
|
|
4466
4507
|
const destPath = join17(summaryDir, matchingTranscript.relativePath);
|
|
4467
|
-
const destDir =
|
|
4508
|
+
const destDir = dirname14(destPath);
|
|
4468
4509
|
if (!existsSync17(destDir)) {
|
|
4469
4510
|
mkdirSync6(destDir, { recursive: true });
|
|
4470
4511
|
}
|
|
@@ -4478,7 +4519,7 @@ function processStagedFile() {
|
|
|
4478
4519
|
|
|
4479
4520
|
// src/commands/transcript/summarise/index.ts
|
|
4480
4521
|
function buildRelativeKey(relativePath, baseName) {
|
|
4481
|
-
const relDir =
|
|
4522
|
+
const relDir = dirname15(relativePath);
|
|
4482
4523
|
return relDir === "." ? baseName : join18(relDir, baseName);
|
|
4483
4524
|
}
|
|
4484
4525
|
function buildSummaryIndex(summaryDir) {
|
|
@@ -4514,7 +4555,7 @@ function summarise() {
|
|
|
4514
4555
|
const next2 = missing[0];
|
|
4515
4556
|
const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
|
|
4516
4557
|
const outputPath = join18(STAGING_DIR, outputFilename);
|
|
4517
|
-
const summaryFileDir = join18(summaryDir,
|
|
4558
|
+
const summaryFileDir = join18(summaryDir, dirname15(next2.relativePath));
|
|
4518
4559
|
const relativeTranscriptPath = encodeURI(
|
|
4519
4560
|
relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
|
|
4520
4561
|
);
|
|
@@ -4676,27 +4717,27 @@ async function statusLine() {
|
|
|
4676
4717
|
// src/commands/sync.ts
|
|
4677
4718
|
import * as fs23 from "fs";
|
|
4678
4719
|
import * as os from "os";
|
|
4679
|
-
import * as
|
|
4720
|
+
import * as path29 from "path";
|
|
4680
4721
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4681
4722
|
|
|
4682
4723
|
// src/commands/sync/syncClaudeMd.ts
|
|
4683
4724
|
import * as fs21 from "fs";
|
|
4684
|
-
import * as
|
|
4685
|
-
import
|
|
4725
|
+
import * as path27 from "path";
|
|
4726
|
+
import chalk43 from "chalk";
|
|
4686
4727
|
async function syncClaudeMd(claudeDir, targetBase) {
|
|
4687
|
-
const source =
|
|
4688
|
-
const target =
|
|
4728
|
+
const source = path27.join(claudeDir, "CLAUDE.md");
|
|
4729
|
+
const target = path27.join(targetBase, "CLAUDE.md");
|
|
4689
4730
|
const sourceContent = fs21.readFileSync(source, "utf-8");
|
|
4690
4731
|
if (fs21.existsSync(target)) {
|
|
4691
4732
|
const targetContent = fs21.readFileSync(target, "utf-8");
|
|
4692
4733
|
if (sourceContent !== targetContent) {
|
|
4693
4734
|
console.log(
|
|
4694
|
-
|
|
4735
|
+
chalk43.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
4695
4736
|
);
|
|
4696
4737
|
console.log();
|
|
4697
4738
|
printDiff(targetContent, sourceContent);
|
|
4698
4739
|
const confirm = await promptConfirm(
|
|
4699
|
-
|
|
4740
|
+
chalk43.red("Overwrite existing CLAUDE.md?"),
|
|
4700
4741
|
false
|
|
4701
4742
|
);
|
|
4702
4743
|
if (!confirm) {
|
|
@@ -4711,11 +4752,11 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
4711
4752
|
|
|
4712
4753
|
// src/commands/sync/syncSettings.ts
|
|
4713
4754
|
import * as fs22 from "fs";
|
|
4714
|
-
import * as
|
|
4715
|
-
import
|
|
4755
|
+
import * as path28 from "path";
|
|
4756
|
+
import chalk44 from "chalk";
|
|
4716
4757
|
async function syncSettings(claudeDir, targetBase) {
|
|
4717
|
-
const source =
|
|
4718
|
-
const target =
|
|
4758
|
+
const source = path28.join(claudeDir, "settings.json");
|
|
4759
|
+
const target = path28.join(targetBase, "settings.json");
|
|
4719
4760
|
const sourceContent = fs22.readFileSync(source, "utf-8");
|
|
4720
4761
|
const normalizedSource = JSON.stringify(JSON.parse(sourceContent), null, 2);
|
|
4721
4762
|
if (fs22.existsSync(target)) {
|
|
@@ -4723,12 +4764,12 @@ async function syncSettings(claudeDir, targetBase) {
|
|
|
4723
4764
|
const normalizedTarget = JSON.stringify(JSON.parse(targetContent), null, 2);
|
|
4724
4765
|
if (normalizedSource !== normalizedTarget) {
|
|
4725
4766
|
console.log(
|
|
4726
|
-
|
|
4767
|
+
chalk44.yellow("\n\u26A0\uFE0F Warning: settings.json differs from existing file")
|
|
4727
4768
|
);
|
|
4728
4769
|
console.log();
|
|
4729
4770
|
printDiff(targetContent, sourceContent);
|
|
4730
4771
|
const confirm = await promptConfirm(
|
|
4731
|
-
|
|
4772
|
+
chalk44.red("Overwrite existing settings.json?"),
|
|
4732
4773
|
false
|
|
4733
4774
|
);
|
|
4734
4775
|
if (!confirm) {
|
|
@@ -4743,21 +4784,21 @@ async function syncSettings(claudeDir, targetBase) {
|
|
|
4743
4784
|
|
|
4744
4785
|
// src/commands/sync.ts
|
|
4745
4786
|
var __filename2 = fileURLToPath3(import.meta.url);
|
|
4746
|
-
var __dirname4 =
|
|
4787
|
+
var __dirname4 = path29.dirname(__filename2);
|
|
4747
4788
|
async function sync() {
|
|
4748
|
-
const claudeDir =
|
|
4749
|
-
const targetBase =
|
|
4789
|
+
const claudeDir = path29.join(__dirname4, "..", "claude");
|
|
4790
|
+
const targetBase = path29.join(os.homedir(), ".claude");
|
|
4750
4791
|
syncCommands(claudeDir, targetBase);
|
|
4751
4792
|
await syncSettings(claudeDir, targetBase);
|
|
4752
4793
|
await syncClaudeMd(claudeDir, targetBase);
|
|
4753
4794
|
}
|
|
4754
4795
|
function syncCommands(claudeDir, targetBase) {
|
|
4755
|
-
const sourceDir =
|
|
4756
|
-
const targetDir =
|
|
4796
|
+
const sourceDir = path29.join(claudeDir, "commands");
|
|
4797
|
+
const targetDir = path29.join(targetBase, "commands");
|
|
4757
4798
|
fs23.mkdirSync(targetDir, { recursive: true });
|
|
4758
4799
|
const files = fs23.readdirSync(sourceDir);
|
|
4759
4800
|
for (const file of files) {
|
|
4760
|
-
fs23.copyFileSync(
|
|
4801
|
+
fs23.copyFileSync(path29.join(sourceDir, file), path29.join(targetDir, file));
|
|
4761
4802
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
4762
4803
|
}
|
|
4763
4804
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|