@staff0rd/assist 0.108.2 → 0.109.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 +424 -401
- package/package.json +1 -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.109.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -88,10 +88,10 @@ import { stringify as stringifyYaml } from "yaml";
|
|
|
88
88
|
// src/shared/loadRawYaml.ts
|
|
89
89
|
import { existsSync, readFileSync } from "fs";
|
|
90
90
|
import { parse as parseYaml } from "yaml";
|
|
91
|
-
function loadRawYaml(
|
|
92
|
-
if (!existsSync(
|
|
91
|
+
function loadRawYaml(path36) {
|
|
92
|
+
if (!existsSync(path36)) return {};
|
|
93
93
|
try {
|
|
94
|
-
const content = readFileSync(
|
|
94
|
+
const content = readFileSync(path36, "utf-8");
|
|
95
95
|
return parseYaml(content) || {};
|
|
96
96
|
} catch {
|
|
97
97
|
return {};
|
|
@@ -329,9 +329,9 @@ function isTraversable(value) {
|
|
|
329
329
|
function stepInto(current, key) {
|
|
330
330
|
return isTraversable(current) ? current[key] : void 0;
|
|
331
331
|
}
|
|
332
|
-
function getNestedValue(obj,
|
|
332
|
+
function getNestedValue(obj, path36) {
|
|
333
333
|
let current = obj;
|
|
334
|
-
for (const key of
|
|
334
|
+
for (const key of path36.split(".")) current = stepInto(current, key);
|
|
335
335
|
return current;
|
|
336
336
|
}
|
|
337
337
|
|
|
@@ -372,8 +372,8 @@ function stepIntoNested(container, key, nextKey) {
|
|
|
372
372
|
}
|
|
373
373
|
return ensureObject(container, resolved);
|
|
374
374
|
}
|
|
375
|
-
function setNestedValue(obj,
|
|
376
|
-
const keys =
|
|
375
|
+
function setNestedValue(obj, path36, value) {
|
|
376
|
+
const keys = path36.split(".");
|
|
377
377
|
const result = { ...obj };
|
|
378
378
|
let current = result;
|
|
379
379
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -442,7 +442,7 @@ function configList() {
|
|
|
442
442
|
}
|
|
443
443
|
|
|
444
444
|
// src/commands/verify/init/index.ts
|
|
445
|
-
import
|
|
445
|
+
import chalk16 from "chalk";
|
|
446
446
|
|
|
447
447
|
// src/shared/promptMultiselect.ts
|
|
448
448
|
import chalk3 from "chalk";
|
|
@@ -520,7 +520,8 @@ var expectedScripts = {
|
|
|
520
520
|
"verify:test": "vitest run --reporter=dot --silent",
|
|
521
521
|
"verify:hardcoded-colors": "assist verify hardcoded-colors",
|
|
522
522
|
"verify:no-venv": "assist verify no-venv",
|
|
523
|
-
"verify:maintainability": "assist complexity maintainability ./src --threshold 60"
|
|
523
|
+
"verify:maintainability": "assist complexity maintainability ./src --threshold 60",
|
|
524
|
+
"verify:madge": "madge --circular --ts-config ./tsconfig.json --extensions ts,tsx src/"
|
|
524
525
|
};
|
|
525
526
|
|
|
526
527
|
// src/commands/verify/setup/setupBuild.ts
|
|
@@ -859,12 +860,30 @@ async function setupLint(packageJsonPath) {
|
|
|
859
860
|
);
|
|
860
861
|
}
|
|
861
862
|
|
|
862
|
-
// src/commands/verify/setup/
|
|
863
|
+
// src/commands/verify/setup/setupMadge.ts
|
|
863
864
|
import * as path7 from "path";
|
|
864
865
|
import chalk13 from "chalk";
|
|
866
|
+
async function setupMadge(packageJsonPath) {
|
|
867
|
+
console.log(chalk13.blue("\nSetting up madge..."));
|
|
868
|
+
const cwd = path7.dirname(packageJsonPath);
|
|
869
|
+
const pkg = readPackageJson(packageJsonPath);
|
|
870
|
+
const hasMadge = !!pkg.dependencies?.madge || !!pkg.devDependencies?.madge;
|
|
871
|
+
if (!hasMadge && !installPackage("madge", cwd)) {
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
setupVerifyScript(
|
|
875
|
+
packageJsonPath,
|
|
876
|
+
"verify:madge",
|
|
877
|
+
expectedScripts["verify:madge"]
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
// src/commands/verify/setup/setupMaintainability.ts
|
|
882
|
+
import * as path8 from "path";
|
|
883
|
+
import chalk14 from "chalk";
|
|
865
884
|
async function setupMaintainability(packageJsonPath) {
|
|
866
|
-
console.log(
|
|
867
|
-
addToKnipIgnoreBinaries(
|
|
885
|
+
console.log(chalk14.blue("\nSetting up maintainability check..."));
|
|
886
|
+
addToKnipIgnoreBinaries(path8.dirname(packageJsonPath), "assist");
|
|
868
887
|
setupVerifyScript(
|
|
869
888
|
packageJsonPath,
|
|
870
889
|
"verify:maintainability",
|
|
@@ -873,11 +892,11 @@ async function setupMaintainability(packageJsonPath) {
|
|
|
873
892
|
}
|
|
874
893
|
|
|
875
894
|
// src/commands/verify/setup/setupTest.ts
|
|
876
|
-
import * as
|
|
877
|
-
import
|
|
895
|
+
import * as path9 from "path";
|
|
896
|
+
import chalk15 from "chalk";
|
|
878
897
|
async function setupTest(packageJsonPath) {
|
|
879
|
-
console.log(
|
|
880
|
-
const cwd =
|
|
898
|
+
console.log(chalk15.blue("\nSetting up vitest..."));
|
|
899
|
+
const cwd = path9.dirname(packageJsonPath);
|
|
881
900
|
const pkg = readPackageJson(packageJsonPath);
|
|
882
901
|
if (!pkg.devDependencies?.vitest && !installPackage("vitest", cwd)) {
|
|
883
902
|
return;
|
|
@@ -901,6 +920,9 @@ function getStatusLabel(status2) {
|
|
|
901
920
|
}
|
|
902
921
|
|
|
903
922
|
// src/commands/verify/init/detectExistingSetup/index.ts
|
|
923
|
+
function hasDep(pkg, name) {
|
|
924
|
+
return !!pkg.dependencies?.[name] || !!pkg.devDependencies?.[name];
|
|
925
|
+
}
|
|
904
926
|
function toolStatus(pkg, scriptName, hasPackage) {
|
|
905
927
|
const currentScript = pkg.scripts?.[scriptName];
|
|
906
928
|
const expectedCommand = expectedScripts[scriptName];
|
|
@@ -911,26 +933,20 @@ function toolStatus(pkg, scriptName, hasPackage) {
|
|
|
911
933
|
};
|
|
912
934
|
}
|
|
913
935
|
function detectExistingSetup(pkg) {
|
|
936
|
+
const status2 = (script, has) => toolStatus(pkg, script, has);
|
|
914
937
|
return {
|
|
915
|
-
knip:
|
|
916
|
-
biome:
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
),
|
|
921
|
-
jscpd: toolStatus(
|
|
922
|
-
pkg,
|
|
923
|
-
"verify:duplicate-code",
|
|
924
|
-
!!pkg.dependencies?.jscpd || !!pkg.devDependencies?.jscpd
|
|
925
|
-
),
|
|
926
|
-
test: toolStatus(pkg, "verify:test", !!pkg.devDependencies?.vitest),
|
|
927
|
-
hasVite: !!pkg.devDependencies?.vite || !!pkg.dependencies?.vite,
|
|
938
|
+
knip: status2("verify:knip", hasDep(pkg, "knip")),
|
|
939
|
+
biome: status2("verify:lint", hasDep(pkg, "@biomejs/biome")),
|
|
940
|
+
jscpd: status2("verify:duplicate-code", hasDep(pkg, "jscpd")),
|
|
941
|
+
test: status2("verify:test", hasDep(pkg, "vitest")),
|
|
942
|
+
hasVite: hasDep(pkg, "vite"),
|
|
928
943
|
hasTypescript: !!pkg.devDependencies?.typescript,
|
|
929
|
-
build:
|
|
930
|
-
typecheck:
|
|
931
|
-
hardcodedColors:
|
|
932
|
-
|
|
933
|
-
|
|
944
|
+
build: status2("verify:build", true),
|
|
945
|
+
typecheck: status2("verify:typecheck", true),
|
|
946
|
+
hardcodedColors: status2("verify:hardcoded-colors", true),
|
|
947
|
+
madge: status2("verify:madge", hasDep(pkg, "madge")),
|
|
948
|
+
maintainability: status2("verify:maintainability", true),
|
|
949
|
+
hasOpenColor: hasDep(pkg, "open-color")
|
|
934
950
|
};
|
|
935
951
|
}
|
|
936
952
|
|
|
@@ -987,6 +1003,12 @@ var options = [
|
|
|
987
1003
|
description: "TypeScript type checking",
|
|
988
1004
|
extraCondition: (s) => s.hasTypescript && !s.hasVite
|
|
989
1005
|
},
|
|
1006
|
+
{
|
|
1007
|
+
toolKey: "madge",
|
|
1008
|
+
value: "madge",
|
|
1009
|
+
label: "madge",
|
|
1010
|
+
description: "Circular dependency detection with madge"
|
|
1011
|
+
},
|
|
990
1012
|
{
|
|
991
1013
|
toolKey: "maintainability",
|
|
992
1014
|
value: "maintainability",
|
|
@@ -1022,6 +1044,7 @@ function getSetupHandlers(hasVite, hasTypescript, hasOpenColor) {
|
|
|
1022
1044
|
build: (p) => setupBuild(p, hasVite, hasTypescript),
|
|
1023
1045
|
typecheck: (p) => setupTypecheck(p),
|
|
1024
1046
|
"hardcoded-colors": (p) => setupHardcodedColors(p, hasOpenColor),
|
|
1047
|
+
madge: (p) => setupMadge(p),
|
|
1025
1048
|
maintainability: (p) => setupMaintainability(p)
|
|
1026
1049
|
};
|
|
1027
1050
|
}
|
|
@@ -1029,25 +1052,25 @@ async function runSelectedSetups(selected, packageJsonPath, handlers) {
|
|
|
1029
1052
|
for (const choice of selected) {
|
|
1030
1053
|
await handlers[choice]?.(packageJsonPath);
|
|
1031
1054
|
}
|
|
1032
|
-
console.log(
|
|
1055
|
+
console.log(chalk16.green(`
|
|
1033
1056
|
Added ${selected.length} verify script(s):`));
|
|
1034
1057
|
for (const choice of selected) {
|
|
1035
|
-
console.log(
|
|
1058
|
+
console.log(chalk16.green(` - verify:${choice}`));
|
|
1036
1059
|
}
|
|
1037
|
-
console.log(
|
|
1060
|
+
console.log(chalk16.dim("\nRun 'assist verify' to run all verify scripts"));
|
|
1038
1061
|
}
|
|
1039
1062
|
async function promptForScripts(availableOptions) {
|
|
1040
1063
|
if (availableOptions.length === 0) {
|
|
1041
|
-
console.log(
|
|
1064
|
+
console.log(chalk16.green("All verify scripts are already configured!"));
|
|
1042
1065
|
return null;
|
|
1043
1066
|
}
|
|
1044
|
-
console.log(
|
|
1067
|
+
console.log(chalk16.bold("Available verify scripts to add:\n"));
|
|
1045
1068
|
const selected = await promptMultiselect(
|
|
1046
1069
|
"Select verify scripts to add:",
|
|
1047
1070
|
availableOptions
|
|
1048
1071
|
);
|
|
1049
1072
|
if (selected.length === 0) {
|
|
1050
|
-
console.log(
|
|
1073
|
+
console.log(chalk16.yellow("No scripts selected"));
|
|
1051
1074
|
return null;
|
|
1052
1075
|
}
|
|
1053
1076
|
return selected;
|
|
@@ -1066,21 +1089,21 @@ async function init2() {
|
|
|
1066
1089
|
}
|
|
1067
1090
|
|
|
1068
1091
|
// src/commands/vscode/init/index.ts
|
|
1069
|
-
import
|
|
1092
|
+
import chalk18 from "chalk";
|
|
1070
1093
|
|
|
1071
1094
|
// src/commands/vscode/init/createLaunchJson.ts
|
|
1072
1095
|
import * as fs3 from "fs";
|
|
1073
|
-
import * as
|
|
1074
|
-
import
|
|
1096
|
+
import * as path10 from "path";
|
|
1097
|
+
import chalk17 from "chalk";
|
|
1075
1098
|
function ensureVscodeFolder() {
|
|
1076
|
-
const vscodeDir =
|
|
1099
|
+
const vscodeDir = path10.join(process.cwd(), ".vscode");
|
|
1077
1100
|
if (!fs3.existsSync(vscodeDir)) {
|
|
1078
1101
|
fs3.mkdirSync(vscodeDir);
|
|
1079
|
-
console.log(
|
|
1102
|
+
console.log(chalk17.dim("Created .vscode folder"));
|
|
1080
1103
|
}
|
|
1081
1104
|
}
|
|
1082
1105
|
function removeVscodeFromGitignore() {
|
|
1083
|
-
const gitignorePath =
|
|
1106
|
+
const gitignorePath = path10.join(process.cwd(), ".gitignore");
|
|
1084
1107
|
if (!fs3.existsSync(gitignorePath)) {
|
|
1085
1108
|
return;
|
|
1086
1109
|
}
|
|
@@ -1091,7 +1114,7 @@ function removeVscodeFromGitignore() {
|
|
|
1091
1114
|
);
|
|
1092
1115
|
if (filteredLines.length !== lines.length) {
|
|
1093
1116
|
fs3.writeFileSync(gitignorePath, filteredLines.join("\n"));
|
|
1094
|
-
console.log(
|
|
1117
|
+
console.log(chalk17.dim("Removed .vscode references from .gitignore"));
|
|
1095
1118
|
}
|
|
1096
1119
|
}
|
|
1097
1120
|
function createLaunchJson(type) {
|
|
@@ -1107,10 +1130,10 @@ function createLaunchJson(type) {
|
|
|
1107
1130
|
}
|
|
1108
1131
|
]
|
|
1109
1132
|
};
|
|
1110
|
-
const launchPath =
|
|
1133
|
+
const launchPath = path10.join(process.cwd(), ".vscode", "launch.json");
|
|
1111
1134
|
fs3.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
|
|
1112
1135
|
`);
|
|
1113
|
-
console.log(
|
|
1136
|
+
console.log(chalk17.green("Created .vscode/launch.json"));
|
|
1114
1137
|
}
|
|
1115
1138
|
function createSettingsJson() {
|
|
1116
1139
|
const settings = {
|
|
@@ -1120,33 +1143,33 @@ function createSettingsJson() {
|
|
|
1120
1143
|
"source.organizeImports.biome": "explicit"
|
|
1121
1144
|
}
|
|
1122
1145
|
};
|
|
1123
|
-
const settingsPath =
|
|
1146
|
+
const settingsPath = path10.join(process.cwd(), ".vscode", "settings.json");
|
|
1124
1147
|
fs3.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
|
|
1125
1148
|
`);
|
|
1126
|
-
console.log(
|
|
1149
|
+
console.log(chalk17.green("Created .vscode/settings.json"));
|
|
1127
1150
|
}
|
|
1128
1151
|
function createExtensionsJson() {
|
|
1129
1152
|
const extensions = {
|
|
1130
1153
|
recommendations: ["biomejs.biome"]
|
|
1131
1154
|
};
|
|
1132
|
-
const extensionsPath =
|
|
1155
|
+
const extensionsPath = path10.join(process.cwd(), ".vscode", "extensions.json");
|
|
1133
1156
|
fs3.writeFileSync(
|
|
1134
1157
|
extensionsPath,
|
|
1135
1158
|
`${JSON.stringify(extensions, null, " ")}
|
|
1136
1159
|
`
|
|
1137
1160
|
);
|
|
1138
|
-
console.log(
|
|
1161
|
+
console.log(chalk17.green("Created .vscode/extensions.json"));
|
|
1139
1162
|
}
|
|
1140
1163
|
|
|
1141
1164
|
// src/commands/vscode/init/detectVscodeSetup.ts
|
|
1142
1165
|
import * as fs4 from "fs";
|
|
1143
|
-
import * as
|
|
1166
|
+
import * as path11 from "path";
|
|
1144
1167
|
function detectVscodeSetup(pkg) {
|
|
1145
|
-
const vscodeDir =
|
|
1168
|
+
const vscodeDir = path11.join(process.cwd(), ".vscode");
|
|
1146
1169
|
return {
|
|
1147
1170
|
hasVscodeFolder: fs4.existsSync(vscodeDir),
|
|
1148
|
-
hasLaunchJson: fs4.existsSync(
|
|
1149
|
-
hasSettingsJson: fs4.existsSync(
|
|
1171
|
+
hasLaunchJson: fs4.existsSync(path11.join(vscodeDir, "launch.json")),
|
|
1172
|
+
hasSettingsJson: fs4.existsSync(path11.join(vscodeDir, "settings.json")),
|
|
1150
1173
|
hasVite: !!pkg.devDependencies?.vite || !!pkg.dependencies?.vite,
|
|
1151
1174
|
hasTsup: !!pkg.devDependencies?.tsup || !!pkg.dependencies?.tsup
|
|
1152
1175
|
};
|
|
@@ -1192,7 +1215,7 @@ function applySelections(selected, setup2) {
|
|
|
1192
1215
|
for (const choice of selected) handlers[choice]?.();
|
|
1193
1216
|
}
|
|
1194
1217
|
async function promptForOptions(options2) {
|
|
1195
|
-
console.log(
|
|
1218
|
+
console.log(chalk18.bold("Available VS Code configurations to add:\n"));
|
|
1196
1219
|
return promptMultiselect("Select configurations to add:", options2);
|
|
1197
1220
|
}
|
|
1198
1221
|
async function init3({ all = false } = {}) {
|
|
@@ -1200,17 +1223,17 @@ async function init3({ all = false } = {}) {
|
|
|
1200
1223
|
const setup2 = detectVscodeSetup(pkg);
|
|
1201
1224
|
const options2 = getAvailableOptions2(setup2);
|
|
1202
1225
|
if (options2.length === 0) {
|
|
1203
|
-
console.log(
|
|
1226
|
+
console.log(chalk18.green("VS Code configuration already exists!"));
|
|
1204
1227
|
return;
|
|
1205
1228
|
}
|
|
1206
1229
|
const selected = all ? options2.map((o) => o.value) : await promptForOptions(options2);
|
|
1207
1230
|
if (selected.length === 0) {
|
|
1208
|
-
console.log(
|
|
1231
|
+
console.log(chalk18.yellow("No configurations selected"));
|
|
1209
1232
|
return;
|
|
1210
1233
|
}
|
|
1211
1234
|
applySelections(selected, setup2);
|
|
1212
1235
|
console.log(
|
|
1213
|
-
|
|
1236
|
+
chalk18.green(`
|
|
1214
1237
|
Added ${selected.length} VS Code configuration(s)`)
|
|
1215
1238
|
);
|
|
1216
1239
|
}
|
|
@@ -1223,12 +1246,12 @@ async function init4() {
|
|
|
1223
1246
|
|
|
1224
1247
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
1225
1248
|
import fs6 from "fs";
|
|
1226
|
-
import
|
|
1227
|
-
import
|
|
1249
|
+
import path13 from "path";
|
|
1250
|
+
import chalk19 from "chalk";
|
|
1228
1251
|
|
|
1229
1252
|
// src/shared/findSourceFiles.ts
|
|
1230
1253
|
import fs5 from "fs";
|
|
1231
|
-
import
|
|
1254
|
+
import path12 from "path";
|
|
1232
1255
|
var EXTENSIONS = [".ts", ".tsx"];
|
|
1233
1256
|
function findSourceFiles(dir, options2 = {}) {
|
|
1234
1257
|
const { includeTests = true } = options2;
|
|
@@ -1238,7 +1261,7 @@ function findSourceFiles(dir, options2 = {}) {
|
|
|
1238
1261
|
}
|
|
1239
1262
|
const entries = fs5.readdirSync(dir, { withFileTypes: true });
|
|
1240
1263
|
for (const entry of entries) {
|
|
1241
|
-
const fullPath =
|
|
1264
|
+
const fullPath = path12.join(dir, entry.name);
|
|
1242
1265
|
if (entry.isDirectory() && entry.name !== "node_modules") {
|
|
1243
1266
|
results.push(...findSourceFiles(fullPath, options2));
|
|
1244
1267
|
} else if (entry.isFile() && EXTENSIONS.some((ext) => entry.name.endsWith(ext))) {
|
|
@@ -1262,7 +1285,7 @@ function checkFileNames() {
|
|
|
1262
1285
|
const sourceFiles = findSourceFiles("src");
|
|
1263
1286
|
const violations = [];
|
|
1264
1287
|
for (const filePath of sourceFiles) {
|
|
1265
|
-
const fileName =
|
|
1288
|
+
const fileName = path13.basename(filePath);
|
|
1266
1289
|
const nameWithoutExt = fileName.replace(/\.(ts|tsx)$/, "");
|
|
1267
1290
|
if (/^[A-Z]/.test(nameWithoutExt)) {
|
|
1268
1291
|
const content = fs6.readFileSync(filePath, "utf-8");
|
|
@@ -1276,16 +1299,16 @@ function checkFileNames() {
|
|
|
1276
1299
|
function runFileNameCheck() {
|
|
1277
1300
|
const violations = checkFileNames();
|
|
1278
1301
|
if (violations.length > 0) {
|
|
1279
|
-
console.error(
|
|
1302
|
+
console.error(chalk19.red("\nFile name check failed:\n"));
|
|
1280
1303
|
console.error(
|
|
1281
|
-
|
|
1304
|
+
chalk19.red(
|
|
1282
1305
|
" Files without classes or React components should not start with a capital letter.\n"
|
|
1283
1306
|
)
|
|
1284
1307
|
);
|
|
1285
1308
|
for (const violation of violations) {
|
|
1286
|
-
console.error(
|
|
1309
|
+
console.error(chalk19.red(` ${violation.filePath}`));
|
|
1287
1310
|
console.error(
|
|
1288
|
-
|
|
1311
|
+
chalk19.gray(
|
|
1289
1312
|
` Rename to: ${violation.fileName.charAt(0).toLowerCase()}${violation.fileName.slice(1)}
|
|
1290
1313
|
`
|
|
1291
1314
|
)
|
|
@@ -1305,17 +1328,17 @@ function runFileNameCheck() {
|
|
|
1305
1328
|
import fs7 from "fs";
|
|
1306
1329
|
|
|
1307
1330
|
// src/commands/lint/shared.ts
|
|
1308
|
-
import
|
|
1331
|
+
import chalk20 from "chalk";
|
|
1309
1332
|
function reportViolations(violations, checkName, errorMessage, successMessage) {
|
|
1310
1333
|
if (violations.length > 0) {
|
|
1311
|
-
console.error(
|
|
1334
|
+
console.error(chalk20.red(`
|
|
1312
1335
|
${checkName} failed:
|
|
1313
1336
|
`));
|
|
1314
|
-
console.error(
|
|
1337
|
+
console.error(chalk20.red(` ${errorMessage}
|
|
1315
1338
|
`));
|
|
1316
1339
|
for (const violation of violations) {
|
|
1317
|
-
console.error(
|
|
1318
|
-
console.error(
|
|
1340
|
+
console.error(chalk20.red(` ${violation.filePath}:${violation.line}`));
|
|
1341
|
+
console.error(chalk20.gray(` ${violation.content}
|
|
1319
1342
|
`));
|
|
1320
1343
|
}
|
|
1321
1344
|
return false;
|
|
@@ -1457,7 +1480,7 @@ Total: ${lines.length} hardcoded color(s)`);
|
|
|
1457
1480
|
}
|
|
1458
1481
|
|
|
1459
1482
|
// src/commands/verify/run/resolveEntries.ts
|
|
1460
|
-
import * as
|
|
1483
|
+
import * as path14 from "path";
|
|
1461
1484
|
function buildFullCommand(command, args) {
|
|
1462
1485
|
return [shellQuote(command), ...(args ?? []).map(shellQuote)].join(" ");
|
|
1463
1486
|
}
|
|
@@ -1474,7 +1497,7 @@ function getRunEntries() {
|
|
|
1474
1497
|
function getPackageJsonEntries() {
|
|
1475
1498
|
const result = findPackageJsonWithVerifyScripts(process.cwd());
|
|
1476
1499
|
if (!result) return [];
|
|
1477
|
-
const cwd =
|
|
1500
|
+
const cwd = path14.dirname(result.packageJsonPath);
|
|
1478
1501
|
return result.verifyScripts.map((script) => ({
|
|
1479
1502
|
name: script,
|
|
1480
1503
|
fullCommand: `npm run ${script}`,
|
|
@@ -1795,16 +1818,16 @@ import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSyn
|
|
|
1795
1818
|
|
|
1796
1819
|
// src/commands/deploy/init/index.ts
|
|
1797
1820
|
import { execSync as execSync11 } from "child_process";
|
|
1798
|
-
import
|
|
1821
|
+
import chalk22 from "chalk";
|
|
1799
1822
|
import enquirer3 from "enquirer";
|
|
1800
1823
|
|
|
1801
1824
|
// src/commands/deploy/init/updateWorkflow.ts
|
|
1802
1825
|
import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
1803
|
-
import { dirname as
|
|
1826
|
+
import { dirname as dirname11, join as join7 } from "path";
|
|
1804
1827
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1805
|
-
import
|
|
1828
|
+
import chalk21 from "chalk";
|
|
1806
1829
|
var WORKFLOW_PATH = ".github/workflows/build.yml";
|
|
1807
|
-
var __dirname3 =
|
|
1830
|
+
var __dirname3 = dirname11(fileURLToPath2(import.meta.url));
|
|
1808
1831
|
function getExistingSiteId() {
|
|
1809
1832
|
if (!existsSync10(WORKFLOW_PATH)) {
|
|
1810
1833
|
return null;
|
|
@@ -1827,20 +1850,20 @@ async function updateWorkflow(siteId) {
|
|
|
1827
1850
|
if (existsSync10(WORKFLOW_PATH)) {
|
|
1828
1851
|
const oldContent = readFileSync8(WORKFLOW_PATH, "utf-8");
|
|
1829
1852
|
if (oldContent === newContent) {
|
|
1830
|
-
console.log(
|
|
1853
|
+
console.log(chalk21.green("build.yml is already up to date"));
|
|
1831
1854
|
return;
|
|
1832
1855
|
}
|
|
1833
|
-
console.log(
|
|
1856
|
+
console.log(chalk21.yellow("\nbuild.yml will be updated:"));
|
|
1834
1857
|
console.log();
|
|
1835
1858
|
printDiff(oldContent, newContent);
|
|
1836
|
-
const confirm = await promptConfirm(
|
|
1859
|
+
const confirm = await promptConfirm(chalk21.red("Update build.yml?"));
|
|
1837
1860
|
if (!confirm) {
|
|
1838
1861
|
console.log("Skipped build.yml update");
|
|
1839
1862
|
return;
|
|
1840
1863
|
}
|
|
1841
1864
|
}
|
|
1842
1865
|
writeFileSync8(WORKFLOW_PATH, newContent);
|
|
1843
|
-
console.log(
|
|
1866
|
+
console.log(chalk21.green(`
|
|
1844
1867
|
Created ${WORKFLOW_PATH}`));
|
|
1845
1868
|
}
|
|
1846
1869
|
|
|
@@ -1851,43 +1874,43 @@ async function ensureNetlifyCli() {
|
|
|
1851
1874
|
} catch (error) {
|
|
1852
1875
|
if (!(error instanceof Error) || !error.message.includes("command not found"))
|
|
1853
1876
|
throw error;
|
|
1854
|
-
console.error(
|
|
1877
|
+
console.error(chalk22.red("\nNetlify CLI is not installed.\n"));
|
|
1855
1878
|
const install = await promptConfirm("Would you like to install it now?");
|
|
1856
1879
|
if (!install) {
|
|
1857
1880
|
console.log(
|
|
1858
|
-
|
|
1881
|
+
chalk22.yellow(
|
|
1859
1882
|
"\nInstall it manually with: npm install -g netlify-cli\n"
|
|
1860
1883
|
)
|
|
1861
1884
|
);
|
|
1862
1885
|
process.exit(1);
|
|
1863
1886
|
}
|
|
1864
|
-
console.log(
|
|
1887
|
+
console.log(chalk22.dim("\nInstalling netlify-cli...\n"));
|
|
1865
1888
|
execSync11("npm install -g netlify-cli", { stdio: "inherit" });
|
|
1866
1889
|
console.log();
|
|
1867
1890
|
execSync11("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
1868
1891
|
}
|
|
1869
1892
|
}
|
|
1870
1893
|
function printSetupInstructions() {
|
|
1871
|
-
console.log(
|
|
1894
|
+
console.log(chalk22.bold("\nDeployment initialized successfully!"));
|
|
1872
1895
|
console.log(
|
|
1873
|
-
|
|
1896
|
+
chalk22.yellow("\nTo complete setup, create a personal access token at:")
|
|
1874
1897
|
);
|
|
1875
1898
|
console.log(
|
|
1876
|
-
|
|
1899
|
+
chalk22.cyan(
|
|
1877
1900
|
"https://app.netlify.com/user/applications#personal-access-tokens"
|
|
1878
1901
|
)
|
|
1879
1902
|
);
|
|
1880
1903
|
console.log(
|
|
1881
|
-
|
|
1904
|
+
chalk22.yellow(
|
|
1882
1905
|
"\nThen add it as NETLIFY_AUTH_TOKEN in your GitHub repository secrets."
|
|
1883
1906
|
)
|
|
1884
1907
|
);
|
|
1885
1908
|
}
|
|
1886
1909
|
async function init5() {
|
|
1887
|
-
console.log(
|
|
1910
|
+
console.log(chalk22.bold("Initializing Netlify deployment...\n"));
|
|
1888
1911
|
const existingSiteId = getExistingSiteId();
|
|
1889
1912
|
if (existingSiteId) {
|
|
1890
|
-
console.log(
|
|
1913
|
+
console.log(chalk22.dim(`Using existing site ID: ${existingSiteId}
|
|
1891
1914
|
`));
|
|
1892
1915
|
await updateWorkflow(existingSiteId);
|
|
1893
1916
|
return;
|
|
@@ -1983,11 +2006,11 @@ function detectPlatform() {
|
|
|
1983
2006
|
import { spawn as spawn2 } from "child_process";
|
|
1984
2007
|
import fs9 from "fs";
|
|
1985
2008
|
import { createRequire } from "module";
|
|
1986
|
-
import
|
|
2009
|
+
import path15 from "path";
|
|
1987
2010
|
var require2 = createRequire(import.meta.url);
|
|
1988
2011
|
function getSnoreToastPath() {
|
|
1989
|
-
const notifierPath =
|
|
1990
|
-
return
|
|
2012
|
+
const notifierPath = path15.dirname(require2.resolve("node-notifier"));
|
|
2013
|
+
return path15.join(notifierPath, "vendor", "snoreToast", "snoretoast-x64.exe");
|
|
1991
2014
|
}
|
|
1992
2015
|
function showWindowsNotificationFromWsl(options2) {
|
|
1993
2016
|
const { title, message, sound } = options2;
|
|
@@ -2067,12 +2090,12 @@ async function notify() {
|
|
|
2067
2090
|
|
|
2068
2091
|
// src/commands/backlog/add/index.ts
|
|
2069
2092
|
import { existsSync as existsSync13 } from "fs";
|
|
2070
|
-
import
|
|
2093
|
+
import chalk24 from "chalk";
|
|
2071
2094
|
|
|
2072
2095
|
// src/commands/backlog/shared.ts
|
|
2073
2096
|
import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync10 } from "fs";
|
|
2074
2097
|
import { join as join8 } from "path";
|
|
2075
|
-
import
|
|
2098
|
+
import chalk23 from "chalk";
|
|
2076
2099
|
import { parse as parseYaml2, stringify as stringifyYaml3 } from "yaml";
|
|
2077
2100
|
|
|
2078
2101
|
// src/commands/backlog/types.ts
|
|
@@ -2116,7 +2139,7 @@ function findItem(items, id) {
|
|
|
2116
2139
|
function loadAndFindItem(id) {
|
|
2117
2140
|
if (!existsSync12(getBacklogPath())) {
|
|
2118
2141
|
console.log(
|
|
2119
|
-
|
|
2142
|
+
chalk23.yellow(
|
|
2120
2143
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
2121
2144
|
)
|
|
2122
2145
|
);
|
|
@@ -2125,7 +2148,7 @@ function loadAndFindItem(id) {
|
|
|
2125
2148
|
const items = loadBacklog();
|
|
2126
2149
|
const item = findItem(items, Number.parseInt(id, 10));
|
|
2127
2150
|
if (!item) {
|
|
2128
|
-
console.log(
|
|
2151
|
+
console.log(chalk23.red(`Item #${id} not found.`));
|
|
2129
2152
|
return void 0;
|
|
2130
2153
|
}
|
|
2131
2154
|
return { items, item };
|
|
@@ -2223,7 +2246,7 @@ async function add() {
|
|
|
2223
2246
|
const backlogPath = getBacklogPath();
|
|
2224
2247
|
if (!existsSync13(backlogPath)) {
|
|
2225
2248
|
console.log(
|
|
2226
|
-
|
|
2249
|
+
chalk24.yellow(
|
|
2227
2250
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
2228
2251
|
)
|
|
2229
2252
|
);
|
|
@@ -2244,67 +2267,67 @@ async function add() {
|
|
|
2244
2267
|
status: "todo"
|
|
2245
2268
|
});
|
|
2246
2269
|
saveBacklog(items);
|
|
2247
|
-
console.log(
|
|
2270
|
+
console.log(chalk24.green(`Added item #${id}: ${name}`));
|
|
2248
2271
|
}
|
|
2249
2272
|
|
|
2250
2273
|
// src/commands/backlog/delete/index.ts
|
|
2251
|
-
import
|
|
2274
|
+
import chalk25 from "chalk";
|
|
2252
2275
|
async function del(id) {
|
|
2253
2276
|
const name = removeItem(id);
|
|
2254
2277
|
if (name) {
|
|
2255
|
-
console.log(
|
|
2278
|
+
console.log(chalk25.green(`Deleted item #${id}: ${name}`));
|
|
2256
2279
|
}
|
|
2257
2280
|
}
|
|
2258
2281
|
|
|
2259
2282
|
// src/commands/backlog/done/index.ts
|
|
2260
|
-
import
|
|
2283
|
+
import chalk26 from "chalk";
|
|
2261
2284
|
async function done(id) {
|
|
2262
2285
|
const name = setStatus(id, "done");
|
|
2263
2286
|
if (name) {
|
|
2264
|
-
console.log(
|
|
2287
|
+
console.log(chalk26.green(`Completed item #${id}: ${name}`));
|
|
2265
2288
|
}
|
|
2266
2289
|
}
|
|
2267
2290
|
|
|
2268
2291
|
// src/commands/backlog/init/index.ts
|
|
2269
2292
|
import { existsSync as existsSync14 } from "fs";
|
|
2270
|
-
import
|
|
2293
|
+
import chalk27 from "chalk";
|
|
2271
2294
|
async function init6() {
|
|
2272
2295
|
const backlogPath = getBacklogPath();
|
|
2273
2296
|
if (existsSync14(backlogPath)) {
|
|
2274
|
-
console.log(
|
|
2297
|
+
console.log(chalk27.yellow("assist.backlog.yml already exists."));
|
|
2275
2298
|
return;
|
|
2276
2299
|
}
|
|
2277
2300
|
saveBacklog([]);
|
|
2278
|
-
console.log(
|
|
2301
|
+
console.log(chalk27.green("Created assist.backlog.yml"));
|
|
2279
2302
|
}
|
|
2280
2303
|
|
|
2281
2304
|
// src/commands/backlog/list/index.ts
|
|
2282
2305
|
import { existsSync as existsSync15 } from "fs";
|
|
2283
|
-
import
|
|
2306
|
+
import chalk28 from "chalk";
|
|
2284
2307
|
function statusIcon(status2) {
|
|
2285
2308
|
switch (status2) {
|
|
2286
2309
|
case "todo":
|
|
2287
|
-
return
|
|
2310
|
+
return chalk28.dim("[ ]");
|
|
2288
2311
|
case "in-progress":
|
|
2289
|
-
return
|
|
2312
|
+
return chalk28.yellow("[~]");
|
|
2290
2313
|
case "done":
|
|
2291
|
-
return
|
|
2314
|
+
return chalk28.green("[x]");
|
|
2292
2315
|
}
|
|
2293
2316
|
}
|
|
2294
2317
|
function typeLabel(type) {
|
|
2295
2318
|
switch (type) {
|
|
2296
2319
|
case "bug":
|
|
2297
|
-
return
|
|
2320
|
+
return chalk28.magenta("Bug");
|
|
2298
2321
|
case "story":
|
|
2299
|
-
return
|
|
2322
|
+
return chalk28.cyan("Story");
|
|
2300
2323
|
}
|
|
2301
2324
|
}
|
|
2302
2325
|
function printVerboseDetails(item) {
|
|
2303
2326
|
if (item.description) {
|
|
2304
|
-
console.log(` ${
|
|
2327
|
+
console.log(` ${chalk28.dim("Description:")} ${item.description}`);
|
|
2305
2328
|
}
|
|
2306
2329
|
if (item.acceptanceCriteria.length > 0) {
|
|
2307
|
-
console.log(` ${
|
|
2330
|
+
console.log(` ${chalk28.dim("Acceptance criteria:")}`);
|
|
2308
2331
|
for (const criterion of item.acceptanceCriteria) {
|
|
2309
2332
|
console.log(` - ${criterion}`);
|
|
2310
2333
|
}
|
|
@@ -2320,7 +2343,7 @@ async function list2(options2) {
|
|
|
2320
2343
|
const backlogPath = getBacklogPath();
|
|
2321
2344
|
if (!existsSync15(backlogPath)) {
|
|
2322
2345
|
console.log(
|
|
2323
|
-
|
|
2346
|
+
chalk28.yellow(
|
|
2324
2347
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
2325
2348
|
)
|
|
2326
2349
|
);
|
|
@@ -2328,12 +2351,12 @@ async function list2(options2) {
|
|
|
2328
2351
|
}
|
|
2329
2352
|
const items = filterItems(loadBacklog(), options2);
|
|
2330
2353
|
if (items.length === 0) {
|
|
2331
|
-
console.log(
|
|
2354
|
+
console.log(chalk28.dim("Backlog is empty."));
|
|
2332
2355
|
return;
|
|
2333
2356
|
}
|
|
2334
2357
|
for (const item of items) {
|
|
2335
2358
|
console.log(
|
|
2336
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
2359
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk28.dim(`#${item.id}`)} ${item.name}`
|
|
2337
2360
|
);
|
|
2338
2361
|
if (options2.verbose) {
|
|
2339
2362
|
printVerboseDetails(item);
|
|
@@ -2342,11 +2365,11 @@ async function list2(options2) {
|
|
|
2342
2365
|
}
|
|
2343
2366
|
|
|
2344
2367
|
// src/commands/backlog/start/index.ts
|
|
2345
|
-
import
|
|
2368
|
+
import chalk29 from "chalk";
|
|
2346
2369
|
async function start(id) {
|
|
2347
2370
|
const name = setStatus(id, "in-progress");
|
|
2348
2371
|
if (name) {
|
|
2349
|
-
console.log(
|
|
2372
|
+
console.log(chalk29.green(`Started item #${id}: ${name}`));
|
|
2350
2373
|
}
|
|
2351
2374
|
}
|
|
2352
2375
|
|
|
@@ -2356,15 +2379,15 @@ import { readFileSync as readFileSync12 } from "fs";
|
|
|
2356
2379
|
import {
|
|
2357
2380
|
createServer
|
|
2358
2381
|
} from "http";
|
|
2359
|
-
import { dirname as
|
|
2382
|
+
import { dirname as dirname12, join as join10 } from "path";
|
|
2360
2383
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
2361
|
-
import
|
|
2384
|
+
import chalk30 from "chalk";
|
|
2362
2385
|
function respondJson(res, status2, data) {
|
|
2363
2386
|
res.writeHead(status2, { "Content-Type": "application/json" });
|
|
2364
2387
|
res.end(JSON.stringify(data));
|
|
2365
2388
|
}
|
|
2366
2389
|
function createBundleHandler(importMetaUrl, bundlePath) {
|
|
2367
|
-
const dir =
|
|
2390
|
+
const dir = dirname12(fileURLToPath3(importMetaUrl));
|
|
2368
2391
|
let cache;
|
|
2369
2392
|
return (_req, res) => {
|
|
2370
2393
|
if (!cache) {
|
|
@@ -2402,8 +2425,8 @@ function startWebServer(label2, port, handler) {
|
|
|
2402
2425
|
handler(req, res, port);
|
|
2403
2426
|
});
|
|
2404
2427
|
server.listen(port, () => {
|
|
2405
|
-
console.log(
|
|
2406
|
-
console.log(
|
|
2428
|
+
console.log(chalk30.green(`${label2}: ${url}`));
|
|
2429
|
+
console.log(chalk30.dim("Press Ctrl+C to stop"));
|
|
2407
2430
|
exec(`open ${url}`);
|
|
2408
2431
|
});
|
|
2409
2432
|
}
|
|
@@ -2633,22 +2656,22 @@ function extractGraphqlQuery(args) {
|
|
|
2633
2656
|
|
|
2634
2657
|
// src/shared/loadCliReads.ts
|
|
2635
2658
|
import { existsSync as existsSync16, readFileSync as readFileSync13, writeFileSync as writeFileSync12 } from "fs";
|
|
2636
|
-
import { dirname as
|
|
2659
|
+
import { dirname as dirname13, resolve as resolve2 } from "path";
|
|
2637
2660
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
2638
2661
|
var __filename2 = fileURLToPath4(import.meta.url);
|
|
2639
|
-
var __dirname4 =
|
|
2662
|
+
var __dirname4 = dirname13(__filename2);
|
|
2640
2663
|
function getCliReadsPath() {
|
|
2641
2664
|
return resolve2(__dirname4, "..", "assist.cli-reads");
|
|
2642
2665
|
}
|
|
2643
2666
|
var cachedLines;
|
|
2644
2667
|
function getCliReadsLines() {
|
|
2645
2668
|
if (cachedLines) return cachedLines;
|
|
2646
|
-
const
|
|
2647
|
-
if (!existsSync16(
|
|
2669
|
+
const path36 = getCliReadsPath();
|
|
2670
|
+
if (!existsSync16(path36)) {
|
|
2648
2671
|
cachedLines = [];
|
|
2649
2672
|
return cachedLines;
|
|
2650
2673
|
}
|
|
2651
|
-
cachedLines = readFileSync13(
|
|
2674
|
+
cachedLines = readFileSync13(path36, "utf-8").split("\n").filter((line) => line.trim() !== "");
|
|
2652
2675
|
return cachedLines;
|
|
2653
2676
|
}
|
|
2654
2677
|
function loadCliReads() {
|
|
@@ -2854,10 +2877,10 @@ import { join as join12 } from "path";
|
|
|
2854
2877
|
|
|
2855
2878
|
// src/shared/getInstallDir.ts
|
|
2856
2879
|
import { execSync as execSync13 } from "child_process";
|
|
2857
|
-
import { dirname as
|
|
2880
|
+
import { dirname as dirname14, resolve as resolve4 } from "path";
|
|
2858
2881
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
2859
2882
|
var __filename3 = fileURLToPath5(import.meta.url);
|
|
2860
|
-
var __dirname5 =
|
|
2883
|
+
var __dirname5 = dirname14(__filename3);
|
|
2861
2884
|
function getInstallDir() {
|
|
2862
2885
|
return resolve4(__dirname5, "..");
|
|
2863
2886
|
}
|
|
@@ -2894,11 +2917,11 @@ function assertCliExists(cli) {
|
|
|
2894
2917
|
}
|
|
2895
2918
|
|
|
2896
2919
|
// src/commands/permitCliReads/colorize.ts
|
|
2897
|
-
import
|
|
2920
|
+
import chalk31 from "chalk";
|
|
2898
2921
|
function colorize(plainOutput) {
|
|
2899
2922
|
return plainOutput.split("\n").map((line) => {
|
|
2900
|
-
if (line.startsWith(" R ")) return
|
|
2901
|
-
if (line.startsWith(" W ")) return
|
|
2923
|
+
if (line.startsWith(" R ")) return chalk31.green(line);
|
|
2924
|
+
if (line.startsWith(" W ")) return chalk31.red(line);
|
|
2902
2925
|
return line;
|
|
2903
2926
|
}).join("\n");
|
|
2904
2927
|
}
|
|
@@ -3000,14 +3023,14 @@ function showProgress(p, label2) {
|
|
|
3000
3023
|
const pct = Math.round(p.done / p.total * 100);
|
|
3001
3024
|
process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
|
|
3002
3025
|
}
|
|
3003
|
-
async function resolveCommand(cli,
|
|
3004
|
-
showProgress(p,
|
|
3005
|
-
const subHelp = await runHelp([cli, ...
|
|
3026
|
+
async function resolveCommand(cli, path36, description, depth, p) {
|
|
3027
|
+
showProgress(p, path36.join(" "));
|
|
3028
|
+
const subHelp = await runHelp([cli, ...path36]);
|
|
3006
3029
|
if (!subHelp || !hasSubcommands(subHelp)) {
|
|
3007
|
-
return [{ path:
|
|
3030
|
+
return [{ path: path36, description }];
|
|
3008
3031
|
}
|
|
3009
|
-
const children = await discoverAt(cli,
|
|
3010
|
-
return children.length > 0 ? children : [{ path:
|
|
3032
|
+
const children = await discoverAt(cli, path36, depth + 1, p);
|
|
3033
|
+
return children.length > 0 ? children : [{ path: path36, description }];
|
|
3011
3034
|
}
|
|
3012
3035
|
async function discoverAt(cli, parentPath, depth, p) {
|
|
3013
3036
|
if (depth > SAFETY_DEPTH) return [];
|
|
@@ -3155,9 +3178,9 @@ function logPath(cli) {
|
|
|
3155
3178
|
return join12(homedir4(), ".assist", `cli-discover-${safeName}.log`);
|
|
3156
3179
|
}
|
|
3157
3180
|
function readCache(cli) {
|
|
3158
|
-
const
|
|
3159
|
-
if (!existsSync18(
|
|
3160
|
-
return readFileSync15(
|
|
3181
|
+
const path36 = logPath(cli);
|
|
3182
|
+
if (!existsSync18(path36)) return void 0;
|
|
3183
|
+
return readFileSync15(path36, "utf-8");
|
|
3161
3184
|
}
|
|
3162
3185
|
function writeCache(cli, output) {
|
|
3163
3186
|
const dir = join12(homedir4(), ".assist");
|
|
@@ -3209,20 +3232,20 @@ function registerCliHook(program2) {
|
|
|
3209
3232
|
}
|
|
3210
3233
|
|
|
3211
3234
|
// src/commands/complexity/analyze.ts
|
|
3212
|
-
import
|
|
3235
|
+
import chalk37 from "chalk";
|
|
3213
3236
|
|
|
3214
3237
|
// src/commands/complexity/cyclomatic.ts
|
|
3215
|
-
import
|
|
3238
|
+
import chalk33 from "chalk";
|
|
3216
3239
|
|
|
3217
3240
|
// src/commands/complexity/shared/index.ts
|
|
3218
3241
|
import fs11 from "fs";
|
|
3219
|
-
import
|
|
3220
|
-
import
|
|
3242
|
+
import path17 from "path";
|
|
3243
|
+
import chalk32 from "chalk";
|
|
3221
3244
|
import ts5 from "typescript";
|
|
3222
3245
|
|
|
3223
3246
|
// src/commands/complexity/findSourceFiles.ts
|
|
3224
3247
|
import fs10 from "fs";
|
|
3225
|
-
import
|
|
3248
|
+
import path16 from "path";
|
|
3226
3249
|
import { minimatch as minimatch3 } from "minimatch";
|
|
3227
3250
|
function applyIgnoreGlobs(files) {
|
|
3228
3251
|
const { complexity } = loadConfig();
|
|
@@ -3237,7 +3260,7 @@ function walk(dir, results) {
|
|
|
3237
3260
|
const extensions = [".ts", ".tsx"];
|
|
3238
3261
|
const entries = fs10.readdirSync(dir, { withFileTypes: true });
|
|
3239
3262
|
for (const entry of entries) {
|
|
3240
|
-
const fullPath =
|
|
3263
|
+
const fullPath = path16.join(dir, entry.name);
|
|
3241
3264
|
if (entry.isDirectory()) {
|
|
3242
3265
|
if (entry.name !== "node_modules" && entry.name !== ".git") {
|
|
3243
3266
|
walk(fullPath, results);
|
|
@@ -3453,7 +3476,7 @@ function countSloc(content) {
|
|
|
3453
3476
|
function createSourceFromFile(filePath) {
|
|
3454
3477
|
const content = fs11.readFileSync(filePath, "utf-8");
|
|
3455
3478
|
return ts5.createSourceFile(
|
|
3456
|
-
|
|
3479
|
+
path17.basename(filePath),
|
|
3457
3480
|
content,
|
|
3458
3481
|
ts5.ScriptTarget.Latest,
|
|
3459
3482
|
true,
|
|
@@ -3463,7 +3486,7 @@ function createSourceFromFile(filePath) {
|
|
|
3463
3486
|
function withSourceFiles(pattern2, callback) {
|
|
3464
3487
|
const files = findSourceFiles2(pattern2);
|
|
3465
3488
|
if (files.length === 0) {
|
|
3466
|
-
console.log(
|
|
3489
|
+
console.log(chalk32.yellow("No files found matching pattern"));
|
|
3467
3490
|
return void 0;
|
|
3468
3491
|
}
|
|
3469
3492
|
return callback(files);
|
|
@@ -3496,11 +3519,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
3496
3519
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
3497
3520
|
for (const { file, name, complexity } of results) {
|
|
3498
3521
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
3499
|
-
const color = exceedsThreshold ?
|
|
3500
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
3522
|
+
const color = exceedsThreshold ? chalk33.red : chalk33.white;
|
|
3523
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk33.cyan(complexity)}`);
|
|
3501
3524
|
}
|
|
3502
3525
|
console.log(
|
|
3503
|
-
|
|
3526
|
+
chalk33.dim(
|
|
3504
3527
|
`
|
|
3505
3528
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
3506
3529
|
)
|
|
@@ -3512,7 +3535,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
3512
3535
|
}
|
|
3513
3536
|
|
|
3514
3537
|
// src/commands/complexity/halstead.ts
|
|
3515
|
-
import
|
|
3538
|
+
import chalk34 from "chalk";
|
|
3516
3539
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
3517
3540
|
withSourceFiles(pattern2, (files) => {
|
|
3518
3541
|
const results = [];
|
|
@@ -3527,13 +3550,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
3527
3550
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
3528
3551
|
for (const { file, name, metrics } of results) {
|
|
3529
3552
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
3530
|
-
const color = exceedsThreshold ?
|
|
3553
|
+
const color = exceedsThreshold ? chalk34.red : chalk34.white;
|
|
3531
3554
|
console.log(
|
|
3532
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
3555
|
+
`${color(`${file}:${name}`)} \u2192 volume: ${chalk34.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk34.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk34.magenta(metrics.effort.toFixed(1))}`
|
|
3533
3556
|
);
|
|
3534
3557
|
}
|
|
3535
3558
|
console.log(
|
|
3536
|
-
|
|
3559
|
+
chalk34.dim(
|
|
3537
3560
|
`
|
|
3538
3561
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
3539
3562
|
)
|
|
@@ -3548,28 +3571,28 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
3548
3571
|
import fs12 from "fs";
|
|
3549
3572
|
|
|
3550
3573
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
3551
|
-
import
|
|
3574
|
+
import chalk35 from "chalk";
|
|
3552
3575
|
function displayMaintainabilityResults(results, threshold) {
|
|
3553
3576
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
3554
3577
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
3555
|
-
console.log(
|
|
3578
|
+
console.log(chalk35.green("All files pass maintainability threshold"));
|
|
3556
3579
|
} else {
|
|
3557
3580
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
3558
|
-
const color = threshold !== void 0 ?
|
|
3581
|
+
const color = threshold !== void 0 ? chalk35.red : chalk35.white;
|
|
3559
3582
|
console.log(
|
|
3560
|
-
`${color(file)} \u2192 avg: ${
|
|
3583
|
+
`${color(file)} \u2192 avg: ${chalk35.cyan(avgMaintainability.toFixed(1))}, min: ${chalk35.yellow(minMaintainability.toFixed(1))}`
|
|
3561
3584
|
);
|
|
3562
3585
|
}
|
|
3563
3586
|
}
|
|
3564
|
-
console.log(
|
|
3587
|
+
console.log(chalk35.dim(`
|
|
3565
3588
|
Analyzed ${results.length} files`));
|
|
3566
3589
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
3567
3590
|
console.error(
|
|
3568
|
-
|
|
3591
|
+
chalk35.red(
|
|
3569
3592
|
`
|
|
3570
3593
|
Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
|
|
3571
3594
|
|
|
3572
|
-
\u26A0\uFE0F ${
|
|
3595
|
+
\u26A0\uFE0F ${chalk35.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.`
|
|
3573
3596
|
)
|
|
3574
3597
|
);
|
|
3575
3598
|
process.exit(1);
|
|
@@ -3626,7 +3649,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
3626
3649
|
|
|
3627
3650
|
// src/commands/complexity/sloc.ts
|
|
3628
3651
|
import fs13 from "fs";
|
|
3629
|
-
import
|
|
3652
|
+
import chalk36 from "chalk";
|
|
3630
3653
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
3631
3654
|
withSourceFiles(pattern2, (files) => {
|
|
3632
3655
|
const results = [];
|
|
@@ -3642,12 +3665,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
3642
3665
|
results.sort((a, b) => b.lines - a.lines);
|
|
3643
3666
|
for (const { file, lines } of results) {
|
|
3644
3667
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
3645
|
-
const color = exceedsThreshold ?
|
|
3646
|
-
console.log(`${color(file)} \u2192 ${
|
|
3668
|
+
const color = exceedsThreshold ? chalk36.red : chalk36.white;
|
|
3669
|
+
console.log(`${color(file)} \u2192 ${chalk36.cyan(lines)} lines`);
|
|
3647
3670
|
}
|
|
3648
3671
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
3649
3672
|
console.log(
|
|
3650
|
-
|
|
3673
|
+
chalk36.dim(`
|
|
3651
3674
|
Total: ${total} lines across ${files.length} files`)
|
|
3652
3675
|
);
|
|
3653
3676
|
if (hasViolation) {
|
|
@@ -3661,21 +3684,21 @@ async function analyze(pattern2) {
|
|
|
3661
3684
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
3662
3685
|
const files = findSourceFiles2(searchPattern);
|
|
3663
3686
|
if (files.length === 0) {
|
|
3664
|
-
console.log(
|
|
3687
|
+
console.log(chalk37.yellow("No files found matching pattern"));
|
|
3665
3688
|
return;
|
|
3666
3689
|
}
|
|
3667
3690
|
if (files.length === 1) {
|
|
3668
3691
|
const file = files[0];
|
|
3669
|
-
console.log(
|
|
3692
|
+
console.log(chalk37.bold.underline("SLOC"));
|
|
3670
3693
|
await sloc(file);
|
|
3671
3694
|
console.log();
|
|
3672
|
-
console.log(
|
|
3695
|
+
console.log(chalk37.bold.underline("Cyclomatic Complexity"));
|
|
3673
3696
|
await cyclomatic(file);
|
|
3674
3697
|
console.log();
|
|
3675
|
-
console.log(
|
|
3698
|
+
console.log(chalk37.bold.underline("Halstead Metrics"));
|
|
3676
3699
|
await halstead(file);
|
|
3677
3700
|
console.log();
|
|
3678
|
-
console.log(
|
|
3701
|
+
console.log(chalk37.bold.underline("Maintainability Index"));
|
|
3679
3702
|
await maintainability(file);
|
|
3680
3703
|
return;
|
|
3681
3704
|
}
|
|
@@ -3703,7 +3726,7 @@ function registerComplexity(program2) {
|
|
|
3703
3726
|
|
|
3704
3727
|
// src/commands/deploy/redirect.ts
|
|
3705
3728
|
import { existsSync as existsSync19, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "fs";
|
|
3706
|
-
import
|
|
3729
|
+
import chalk38 from "chalk";
|
|
3707
3730
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
3708
3731
|
if (!window.location.pathname.endsWith('/')) {
|
|
3709
3732
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -3712,22 +3735,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
3712
3735
|
function redirect() {
|
|
3713
3736
|
const indexPath = "index.html";
|
|
3714
3737
|
if (!existsSync19(indexPath)) {
|
|
3715
|
-
console.log(
|
|
3738
|
+
console.log(chalk38.yellow("No index.html found"));
|
|
3716
3739
|
return;
|
|
3717
3740
|
}
|
|
3718
3741
|
const content = readFileSync16(indexPath, "utf-8");
|
|
3719
3742
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
3720
|
-
console.log(
|
|
3743
|
+
console.log(chalk38.dim("Trailing slash script already present"));
|
|
3721
3744
|
return;
|
|
3722
3745
|
}
|
|
3723
3746
|
const headCloseIndex = content.indexOf("</head>");
|
|
3724
3747
|
if (headCloseIndex === -1) {
|
|
3725
|
-
console.log(
|
|
3748
|
+
console.log(chalk38.red("Could not find </head> tag in index.html"));
|
|
3726
3749
|
return;
|
|
3727
3750
|
}
|
|
3728
3751
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
3729
3752
|
writeFileSync14(indexPath, newContent);
|
|
3730
|
-
console.log(
|
|
3753
|
+
console.log(chalk38.green("Added trailing slash redirect to index.html"));
|
|
3731
3754
|
}
|
|
3732
3755
|
|
|
3733
3756
|
// src/commands/registerDeploy.ts
|
|
@@ -3754,7 +3777,7 @@ function loadBlogSkipDays(repoName) {
|
|
|
3754
3777
|
|
|
3755
3778
|
// src/commands/devlog/shared.ts
|
|
3756
3779
|
import { execSync as execSync15 } from "child_process";
|
|
3757
|
-
import
|
|
3780
|
+
import chalk39 from "chalk";
|
|
3758
3781
|
|
|
3759
3782
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
3760
3783
|
import { readdirSync, readFileSync as readFileSync17 } from "fs";
|
|
@@ -3841,13 +3864,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
3841
3864
|
}
|
|
3842
3865
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
3843
3866
|
for (const commit2 of commits) {
|
|
3844
|
-
console.log(` ${
|
|
3867
|
+
console.log(` ${chalk39.yellow(commit2.hash)} ${commit2.message}`);
|
|
3845
3868
|
if (verbose) {
|
|
3846
3869
|
const visibleFiles = commit2.files.filter(
|
|
3847
3870
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
3848
3871
|
);
|
|
3849
3872
|
for (const file of visibleFiles) {
|
|
3850
|
-
console.log(` ${
|
|
3873
|
+
console.log(` ${chalk39.dim(file)}`);
|
|
3851
3874
|
}
|
|
3852
3875
|
}
|
|
3853
3876
|
}
|
|
@@ -3872,15 +3895,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
3872
3895
|
}
|
|
3873
3896
|
|
|
3874
3897
|
// src/commands/devlog/list/printDateHeader.ts
|
|
3875
|
-
import
|
|
3898
|
+
import chalk40 from "chalk";
|
|
3876
3899
|
function printDateHeader(date, isSkipped, entries) {
|
|
3877
3900
|
if (isSkipped) {
|
|
3878
|
-
console.log(`${
|
|
3901
|
+
console.log(`${chalk40.bold.blue(date)} ${chalk40.dim("skipped")}`);
|
|
3879
3902
|
} else if (entries && entries.length > 0) {
|
|
3880
|
-
const entryInfo = entries.map((e) => `${
|
|
3881
|
-
console.log(`${
|
|
3903
|
+
const entryInfo = entries.map((e) => `${chalk40.green(e.version)} ${e.title}`).join(" | ");
|
|
3904
|
+
console.log(`${chalk40.bold.blue(date)} ${entryInfo}`);
|
|
3882
3905
|
} else {
|
|
3883
|
-
console.log(`${
|
|
3906
|
+
console.log(`${chalk40.bold.blue(date)} ${chalk40.red("\u26A0 devlog missing")}`);
|
|
3884
3907
|
}
|
|
3885
3908
|
}
|
|
3886
3909
|
|
|
@@ -3983,24 +4006,24 @@ function bumpVersion(version2, type) {
|
|
|
3983
4006
|
|
|
3984
4007
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
3985
4008
|
import { execSync as execSync18 } from "child_process";
|
|
3986
|
-
import
|
|
4009
|
+
import chalk42 from "chalk";
|
|
3987
4010
|
|
|
3988
4011
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
3989
|
-
import
|
|
4012
|
+
import chalk41 from "chalk";
|
|
3990
4013
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
3991
4014
|
if (conventional && firstHash) {
|
|
3992
4015
|
const version2 = getVersionAtCommit(firstHash);
|
|
3993
4016
|
if (version2) {
|
|
3994
|
-
console.log(`${
|
|
4017
|
+
console.log(`${chalk41.bold("version:")} ${stripToMinor(version2)}`);
|
|
3995
4018
|
} else {
|
|
3996
|
-
console.log(`${
|
|
4019
|
+
console.log(`${chalk41.bold("version:")} ${chalk41.red("unknown")}`);
|
|
3997
4020
|
}
|
|
3998
4021
|
} else if (patchVersion && minorVersion) {
|
|
3999
4022
|
console.log(
|
|
4000
|
-
`${
|
|
4023
|
+
`${chalk41.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
4001
4024
|
);
|
|
4002
4025
|
} else {
|
|
4003
|
-
console.log(`${
|
|
4026
|
+
console.log(`${chalk41.bold("version:")} v0.1 (initial)`);
|
|
4004
4027
|
}
|
|
4005
4028
|
}
|
|
4006
4029
|
|
|
@@ -4047,16 +4070,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
4047
4070
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
4048
4071
|
}
|
|
4049
4072
|
function logName(repoName) {
|
|
4050
|
-
console.log(`${
|
|
4073
|
+
console.log(`${chalk42.bold("name:")} ${repoName}`);
|
|
4051
4074
|
}
|
|
4052
4075
|
function displayNextEntry(ctx, targetDate, commits) {
|
|
4053
4076
|
logName(ctx.repoName);
|
|
4054
4077
|
printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
|
|
4055
|
-
console.log(
|
|
4078
|
+
console.log(chalk42.bold.blue(targetDate));
|
|
4056
4079
|
printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
|
|
4057
4080
|
}
|
|
4058
4081
|
function logNoCommits(lastInfo) {
|
|
4059
|
-
console.log(
|
|
4082
|
+
console.log(chalk42.dim(noCommitsMessage(!!lastInfo)));
|
|
4060
4083
|
}
|
|
4061
4084
|
|
|
4062
4085
|
// src/commands/devlog/next/index.ts
|
|
@@ -4097,11 +4120,11 @@ function next(options2) {
|
|
|
4097
4120
|
import { execSync as execSync19 } from "child_process";
|
|
4098
4121
|
|
|
4099
4122
|
// src/commands/devlog/repos/printReposTable.ts
|
|
4100
|
-
import
|
|
4123
|
+
import chalk43 from "chalk";
|
|
4101
4124
|
function colorStatus(status2) {
|
|
4102
|
-
if (status2 === "missing") return
|
|
4103
|
-
if (status2 === "outdated") return
|
|
4104
|
-
return
|
|
4125
|
+
if (status2 === "missing") return chalk43.red(status2);
|
|
4126
|
+
if (status2 === "outdated") return chalk43.yellow(status2);
|
|
4127
|
+
return chalk43.green(status2);
|
|
4105
4128
|
}
|
|
4106
4129
|
function formatRow(row, nameWidth) {
|
|
4107
4130
|
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
@@ -4115,8 +4138,8 @@ function printReposTable(rows) {
|
|
|
4115
4138
|
"Last Devlog".padEnd(11),
|
|
4116
4139
|
"Status"
|
|
4117
4140
|
].join(" ");
|
|
4118
|
-
console.log(
|
|
4119
|
-
console.log(
|
|
4141
|
+
console.log(chalk43.dim(header));
|
|
4142
|
+
console.log(chalk43.dim("-".repeat(header.length)));
|
|
4120
4143
|
for (const row of rows) {
|
|
4121
4144
|
console.log(formatRow(row, nameWidth));
|
|
4122
4145
|
}
|
|
@@ -4174,14 +4197,14 @@ function repos(options2) {
|
|
|
4174
4197
|
// src/commands/devlog/skip.ts
|
|
4175
4198
|
import { writeFileSync as writeFileSync15 } from "fs";
|
|
4176
4199
|
import { join as join15 } from "path";
|
|
4177
|
-
import
|
|
4200
|
+
import chalk44 from "chalk";
|
|
4178
4201
|
import { stringify as stringifyYaml4 } from "yaml";
|
|
4179
4202
|
function getBlogConfigPath() {
|
|
4180
4203
|
return join15(BLOG_REPO_ROOT, "assist.yml");
|
|
4181
4204
|
}
|
|
4182
4205
|
function skip(date) {
|
|
4183
4206
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
4184
|
-
console.log(
|
|
4207
|
+
console.log(chalk44.red("Invalid date format. Use YYYY-MM-DD"));
|
|
4185
4208
|
process.exit(1);
|
|
4186
4209
|
}
|
|
4187
4210
|
const repoName = getRepoName();
|
|
@@ -4192,7 +4215,7 @@ function skip(date) {
|
|
|
4192
4215
|
const skipDays = skip2[repoName] ?? [];
|
|
4193
4216
|
if (skipDays.includes(date)) {
|
|
4194
4217
|
console.log(
|
|
4195
|
-
|
|
4218
|
+
chalk44.yellow(`${date} is already in skip list for ${repoName}`)
|
|
4196
4219
|
);
|
|
4197
4220
|
return;
|
|
4198
4221
|
}
|
|
@@ -4202,20 +4225,20 @@ function skip(date) {
|
|
|
4202
4225
|
devlog.skip = skip2;
|
|
4203
4226
|
config.devlog = devlog;
|
|
4204
4227
|
writeFileSync15(configPath, stringifyYaml4(config, { lineWidth: 0 }));
|
|
4205
|
-
console.log(
|
|
4228
|
+
console.log(chalk44.green(`Added ${date} to skip list for ${repoName}`));
|
|
4206
4229
|
}
|
|
4207
4230
|
|
|
4208
4231
|
// src/commands/devlog/version.ts
|
|
4209
|
-
import
|
|
4232
|
+
import chalk45 from "chalk";
|
|
4210
4233
|
function version() {
|
|
4211
4234
|
const config = loadConfig();
|
|
4212
4235
|
const name = getRepoName();
|
|
4213
4236
|
const lastInfo = getLastVersionInfo(name, config);
|
|
4214
4237
|
const lastVersion = lastInfo?.version ?? null;
|
|
4215
4238
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
4216
|
-
console.log(`${
|
|
4217
|
-
console.log(`${
|
|
4218
|
-
console.log(`${
|
|
4239
|
+
console.log(`${chalk45.bold("name:")} ${name}`);
|
|
4240
|
+
console.log(`${chalk45.bold("last:")} ${lastVersion ?? chalk45.dim("none")}`);
|
|
4241
|
+
console.log(`${chalk45.bold("next:")} ${nextVersion ?? chalk45.dim("none")}`);
|
|
4219
4242
|
}
|
|
4220
4243
|
|
|
4221
4244
|
// src/commands/registerDevlog.ts
|
|
@@ -4238,7 +4261,7 @@ function registerDevlog(program2) {
|
|
|
4238
4261
|
|
|
4239
4262
|
// src/commands/jira/acceptanceCriteria.ts
|
|
4240
4263
|
import { execSync as execSync20 } from "child_process";
|
|
4241
|
-
import
|
|
4264
|
+
import chalk46 from "chalk";
|
|
4242
4265
|
|
|
4243
4266
|
// src/commands/jira/adfToText.ts
|
|
4244
4267
|
function renderInline(node) {
|
|
@@ -4313,21 +4336,21 @@ function acceptanceCriteria(issueKey) {
|
|
|
4313
4336
|
const stderr = error.stderr;
|
|
4314
4337
|
if (stderr.includes("unauthorized")) {
|
|
4315
4338
|
console.error(
|
|
4316
|
-
|
|
4339
|
+
chalk46.red("Jira authentication expired."),
|
|
4317
4340
|
"Run",
|
|
4318
|
-
|
|
4341
|
+
chalk46.cyan("assist jira auth"),
|
|
4319
4342
|
"to re-authenticate."
|
|
4320
4343
|
);
|
|
4321
4344
|
process.exit(1);
|
|
4322
4345
|
}
|
|
4323
4346
|
}
|
|
4324
|
-
console.error(
|
|
4347
|
+
console.error(chalk46.red(`Failed to fetch ${issueKey}.`));
|
|
4325
4348
|
process.exit(1);
|
|
4326
4349
|
}
|
|
4327
4350
|
const parsed = JSON.parse(result);
|
|
4328
4351
|
const acValue = parsed?.fields?.[field];
|
|
4329
4352
|
if (!acValue) {
|
|
4330
|
-
console.log(
|
|
4353
|
+
console.log(chalk46.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
4331
4354
|
return;
|
|
4332
4355
|
}
|
|
4333
4356
|
if (typeof acValue === "string") {
|
|
@@ -4356,10 +4379,10 @@ function getStorePath(filename) {
|
|
|
4356
4379
|
return join16(getStoreDir(), filename);
|
|
4357
4380
|
}
|
|
4358
4381
|
function loadJson(filename) {
|
|
4359
|
-
const
|
|
4360
|
-
if (existsSync20(
|
|
4382
|
+
const path36 = getStorePath(filename);
|
|
4383
|
+
if (existsSync20(path36)) {
|
|
4361
4384
|
try {
|
|
4362
|
-
return JSON.parse(readFileSync18(
|
|
4385
|
+
return JSON.parse(readFileSync18(path36, "utf-8"));
|
|
4363
4386
|
} catch {
|
|
4364
4387
|
return {};
|
|
4365
4388
|
}
|
|
@@ -4426,7 +4449,7 @@ function registerJira(program2) {
|
|
|
4426
4449
|
|
|
4427
4450
|
// src/commands/netframework/buildTree.ts
|
|
4428
4451
|
import { readFileSync as readFileSync19 } from "fs";
|
|
4429
|
-
import
|
|
4452
|
+
import path18 from "path";
|
|
4430
4453
|
var PROJECT_REF_RE = /<ProjectReference\s+Include="([^"]+)"/g;
|
|
4431
4454
|
function getProjectRefs(csprojPath) {
|
|
4432
4455
|
const content = readFileSync19(csprojPath, "utf-8");
|
|
@@ -4437,14 +4460,14 @@ function getProjectRefs(csprojPath) {
|
|
|
4437
4460
|
return refs;
|
|
4438
4461
|
}
|
|
4439
4462
|
function buildTree(csprojPath, repoRoot, visited = /* @__PURE__ */ new Set()) {
|
|
4440
|
-
const abs =
|
|
4441
|
-
const rel =
|
|
4463
|
+
const abs = path18.resolve(csprojPath);
|
|
4464
|
+
const rel = path18.relative(repoRoot, abs);
|
|
4442
4465
|
const node = { path: abs, relativePath: rel, children: [] };
|
|
4443
4466
|
if (visited.has(abs)) return node;
|
|
4444
4467
|
visited.add(abs);
|
|
4445
|
-
const dir =
|
|
4468
|
+
const dir = path18.dirname(abs);
|
|
4446
4469
|
for (const ref of getProjectRefs(abs)) {
|
|
4447
|
-
const childAbs =
|
|
4470
|
+
const childAbs = path18.resolve(dir, ref);
|
|
4448
4471
|
try {
|
|
4449
4472
|
readFileSync19(childAbs);
|
|
4450
4473
|
node.children.push(buildTree(childAbs, repoRoot, visited));
|
|
@@ -4472,7 +4495,7 @@ function collectAllDeps(node) {
|
|
|
4472
4495
|
|
|
4473
4496
|
// src/commands/netframework/findContainingSolutions.ts
|
|
4474
4497
|
import { readdirSync as readdirSync2, readFileSync as readFileSync20, statSync } from "fs";
|
|
4475
|
-
import
|
|
4498
|
+
import path19 from "path";
|
|
4476
4499
|
function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
4477
4500
|
if (depth > maxDepth) return [];
|
|
4478
4501
|
const results = [];
|
|
@@ -4485,7 +4508,7 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
|
4485
4508
|
for (const entry of entries) {
|
|
4486
4509
|
if (entry.startsWith(".") || entry === "node_modules" || entry === "packages")
|
|
4487
4510
|
continue;
|
|
4488
|
-
const full =
|
|
4511
|
+
const full = path19.join(dir, entry);
|
|
4489
4512
|
try {
|
|
4490
4513
|
const stat = statSync(full);
|
|
4491
4514
|
if (stat.isFile() && entry.endsWith(".sln")) {
|
|
@@ -4499,8 +4522,8 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
|
4499
4522
|
return results;
|
|
4500
4523
|
}
|
|
4501
4524
|
function findContainingSolutions(csprojPath, repoRoot) {
|
|
4502
|
-
const csprojAbs =
|
|
4503
|
-
const csprojBasename =
|
|
4525
|
+
const csprojAbs = path19.resolve(csprojPath);
|
|
4526
|
+
const csprojBasename = path19.basename(csprojAbs);
|
|
4504
4527
|
const slnFiles = findSlnFiles(repoRoot, 3);
|
|
4505
4528
|
const matches = [];
|
|
4506
4529
|
const pattern2 = new RegExp(`[\\\\"/]${escapeRegex(csprojBasename)}"`);
|
|
@@ -4508,7 +4531,7 @@ function findContainingSolutions(csprojPath, repoRoot) {
|
|
|
4508
4531
|
try {
|
|
4509
4532
|
const content = readFileSync20(sln, "utf-8");
|
|
4510
4533
|
if (pattern2.test(content)) {
|
|
4511
|
-
matches.push(
|
|
4534
|
+
matches.push(path19.relative(repoRoot, sln));
|
|
4512
4535
|
}
|
|
4513
4536
|
} catch {
|
|
4514
4537
|
}
|
|
@@ -4520,30 +4543,30 @@ function escapeRegex(s) {
|
|
|
4520
4543
|
}
|
|
4521
4544
|
|
|
4522
4545
|
// src/commands/netframework/printTree.ts
|
|
4523
|
-
import
|
|
4546
|
+
import chalk47 from "chalk";
|
|
4524
4547
|
function printNodes(nodes, prefix2) {
|
|
4525
4548
|
for (let i = 0; i < nodes.length; i++) {
|
|
4526
4549
|
const isLast = i === nodes.length - 1;
|
|
4527
4550
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
4528
4551
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
4529
4552
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
4530
|
-
const label2 = isMissing ?
|
|
4553
|
+
const label2 = isMissing ? chalk47.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
4531
4554
|
console.log(`${prefix2}${connector}${label2}`);
|
|
4532
4555
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
4533
4556
|
}
|
|
4534
4557
|
}
|
|
4535
4558
|
function printTree(tree, totalCount, solutions) {
|
|
4536
|
-
console.log(
|
|
4537
|
-
console.log(
|
|
4559
|
+
console.log(chalk47.bold("\nProject Dependency Tree"));
|
|
4560
|
+
console.log(chalk47.cyan(tree.relativePath));
|
|
4538
4561
|
printNodes(tree.children, "");
|
|
4539
|
-
console.log(
|
|
4562
|
+
console.log(chalk47.dim(`
|
|
4540
4563
|
${totalCount} projects total (including root)`));
|
|
4541
|
-
console.log(
|
|
4564
|
+
console.log(chalk47.bold("\nSolution Membership"));
|
|
4542
4565
|
if (solutions.length === 0) {
|
|
4543
|
-
console.log(
|
|
4566
|
+
console.log(chalk47.yellow(" Not found in any .sln"));
|
|
4544
4567
|
} else {
|
|
4545
4568
|
for (const sln of solutions) {
|
|
4546
|
-
console.log(` ${
|
|
4569
|
+
console.log(` ${chalk47.green(sln)}`);
|
|
4547
4570
|
}
|
|
4548
4571
|
}
|
|
4549
4572
|
console.log();
|
|
@@ -4571,33 +4594,33 @@ function printJson(tree, totalCount, solutions) {
|
|
|
4571
4594
|
|
|
4572
4595
|
// src/commands/netframework/resolveCsproj.ts
|
|
4573
4596
|
import { existsSync as existsSync22 } from "fs";
|
|
4574
|
-
import
|
|
4575
|
-
import
|
|
4597
|
+
import path21 from "path";
|
|
4598
|
+
import chalk48 from "chalk";
|
|
4576
4599
|
|
|
4577
4600
|
// src/commands/netframework/findRepoRoot.ts
|
|
4578
4601
|
import { existsSync as existsSync21 } from "fs";
|
|
4579
|
-
import
|
|
4602
|
+
import path20 from "path";
|
|
4580
4603
|
function findRepoRoot(dir) {
|
|
4581
4604
|
let current = dir;
|
|
4582
|
-
while (current !==
|
|
4583
|
-
if (existsSync21(
|
|
4605
|
+
while (current !== path20.dirname(current)) {
|
|
4606
|
+
if (existsSync21(path20.join(current, ".git"))) {
|
|
4584
4607
|
return current;
|
|
4585
4608
|
}
|
|
4586
|
-
current =
|
|
4609
|
+
current = path20.dirname(current);
|
|
4587
4610
|
}
|
|
4588
4611
|
return null;
|
|
4589
4612
|
}
|
|
4590
4613
|
|
|
4591
4614
|
// src/commands/netframework/resolveCsproj.ts
|
|
4592
4615
|
function resolveCsproj(csprojPath) {
|
|
4593
|
-
const resolved =
|
|
4616
|
+
const resolved = path21.resolve(csprojPath);
|
|
4594
4617
|
if (!existsSync22(resolved)) {
|
|
4595
|
-
console.error(
|
|
4618
|
+
console.error(chalk48.red(`File not found: ${resolved}`));
|
|
4596
4619
|
process.exit(1);
|
|
4597
4620
|
}
|
|
4598
|
-
const repoRoot = findRepoRoot(
|
|
4621
|
+
const repoRoot = findRepoRoot(path21.dirname(resolved));
|
|
4599
4622
|
if (!repoRoot) {
|
|
4600
|
-
console.error(
|
|
4623
|
+
console.error(chalk48.red("Could not find git repository root"));
|
|
4601
4624
|
process.exit(1);
|
|
4602
4625
|
}
|
|
4603
4626
|
return { resolved, repoRoot };
|
|
@@ -4617,12 +4640,12 @@ async function deps(csprojPath, options2) {
|
|
|
4617
4640
|
}
|
|
4618
4641
|
|
|
4619
4642
|
// src/commands/netframework/inSln.ts
|
|
4620
|
-
import
|
|
4643
|
+
import chalk49 from "chalk";
|
|
4621
4644
|
async function inSln(csprojPath) {
|
|
4622
4645
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
4623
4646
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
4624
4647
|
if (solutions.length === 0) {
|
|
4625
|
-
console.log(
|
|
4648
|
+
console.log(chalk49.yellow("Not found in any .sln file"));
|
|
4626
4649
|
process.exit(1);
|
|
4627
4650
|
}
|
|
4628
4651
|
for (const sln of solutions) {
|
|
@@ -4638,7 +4661,7 @@ function registerNetframework(program2) {
|
|
|
4638
4661
|
}
|
|
4639
4662
|
|
|
4640
4663
|
// src/commands/news/add/index.ts
|
|
4641
|
-
import
|
|
4664
|
+
import chalk50 from "chalk";
|
|
4642
4665
|
import enquirer5 from "enquirer";
|
|
4643
4666
|
async function add2(url) {
|
|
4644
4667
|
if (!url) {
|
|
@@ -4661,17 +4684,17 @@ async function add2(url) {
|
|
|
4661
4684
|
const news = config.news ?? {};
|
|
4662
4685
|
const feeds = news.feeds ?? [];
|
|
4663
4686
|
if (feeds.includes(url)) {
|
|
4664
|
-
console.log(
|
|
4687
|
+
console.log(chalk50.yellow("Feed already exists in config"));
|
|
4665
4688
|
return;
|
|
4666
4689
|
}
|
|
4667
4690
|
feeds.push(url);
|
|
4668
4691
|
config.news = { ...news, feeds };
|
|
4669
4692
|
saveGlobalConfig(config);
|
|
4670
|
-
console.log(
|
|
4693
|
+
console.log(chalk50.green(`Added feed: ${url}`));
|
|
4671
4694
|
}
|
|
4672
4695
|
|
|
4673
4696
|
// src/commands/news/web/handleRequest.ts
|
|
4674
|
-
import
|
|
4697
|
+
import chalk51 from "chalk";
|
|
4675
4698
|
|
|
4676
4699
|
// src/commands/news/web/shared.ts
|
|
4677
4700
|
import { decodeHTML } from "entities";
|
|
@@ -4807,17 +4830,17 @@ function prefetch() {
|
|
|
4807
4830
|
const config = loadConfig();
|
|
4808
4831
|
const total = config.news.feeds.length;
|
|
4809
4832
|
if (total === 0) return;
|
|
4810
|
-
process.stdout.write(
|
|
4833
|
+
process.stdout.write(chalk51.dim(`Fetching ${total} feed(s)\u2026 `));
|
|
4811
4834
|
prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
|
|
4812
4835
|
const width = 20;
|
|
4813
4836
|
const filled = Math.round(done2 / t * width);
|
|
4814
4837
|
const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
|
|
4815
4838
|
process.stdout.write(
|
|
4816
|
-
`\r${
|
|
4839
|
+
`\r${chalk51.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
|
|
4817
4840
|
);
|
|
4818
4841
|
}).then((items) => {
|
|
4819
4842
|
process.stdout.write(
|
|
4820
|
-
`\r${
|
|
4843
|
+
`\r${chalk51.green(`Fetched ${items.length} items from ${total} feed(s)`)}
|
|
4821
4844
|
`
|
|
4822
4845
|
);
|
|
4823
4846
|
cachedItems = items;
|
|
@@ -4932,7 +4955,7 @@ function validateLine(line) {
|
|
|
4932
4955
|
process.exit(1);
|
|
4933
4956
|
}
|
|
4934
4957
|
}
|
|
4935
|
-
function comment(
|
|
4958
|
+
function comment(path36, line, body) {
|
|
4936
4959
|
validateBody(body);
|
|
4937
4960
|
validateLine(line);
|
|
4938
4961
|
try {
|
|
@@ -4952,7 +4975,7 @@ function comment(path35, line, body) {
|
|
|
4952
4975
|
"-f",
|
|
4953
4976
|
`body=${body}`,
|
|
4954
4977
|
"-f",
|
|
4955
|
-
`path=${
|
|
4978
|
+
`path=${path36}`,
|
|
4956
4979
|
"-F",
|
|
4957
4980
|
`line=${line}`
|
|
4958
4981
|
],
|
|
@@ -4961,7 +4984,7 @@ function comment(path35, line, body) {
|
|
|
4961
4984
|
if (result.status !== 0) {
|
|
4962
4985
|
throw new Error(result.stderr || result.stdout);
|
|
4963
4986
|
}
|
|
4964
|
-
console.log(`Added review comment on ${
|
|
4987
|
+
console.log(`Added review comment on ${path36}:${line}`);
|
|
4965
4988
|
} finally {
|
|
4966
4989
|
unlinkSync3(queryFile);
|
|
4967
4990
|
}
|
|
@@ -5178,20 +5201,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
5178
5201
|
}
|
|
5179
5202
|
|
|
5180
5203
|
// src/commands/prs/listComments/printComments.ts
|
|
5181
|
-
import
|
|
5204
|
+
import chalk52 from "chalk";
|
|
5182
5205
|
function formatForHuman(comment2) {
|
|
5183
5206
|
if (comment2.type === "review") {
|
|
5184
|
-
const stateColor = comment2.state === "APPROVED" ?
|
|
5207
|
+
const stateColor = comment2.state === "APPROVED" ? chalk52.green : comment2.state === "CHANGES_REQUESTED" ? chalk52.red : chalk52.yellow;
|
|
5185
5208
|
return [
|
|
5186
|
-
`${
|
|
5209
|
+
`${chalk52.cyan("Review")} by ${chalk52.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
|
|
5187
5210
|
comment2.body,
|
|
5188
5211
|
""
|
|
5189
5212
|
].join("\n");
|
|
5190
5213
|
}
|
|
5191
5214
|
const location = comment2.line ? `:${comment2.line}` : "";
|
|
5192
5215
|
return [
|
|
5193
|
-
`${
|
|
5194
|
-
|
|
5216
|
+
`${chalk52.cyan("Line comment")} by ${chalk52.bold(comment2.user)} on ${chalk52.dim(`${comment2.path}${location}`)}`,
|
|
5217
|
+
chalk52.dim(comment2.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
5195
5218
|
comment2.body,
|
|
5196
5219
|
""
|
|
5197
5220
|
].join("\n");
|
|
@@ -5281,13 +5304,13 @@ import { execSync as execSync27 } from "child_process";
|
|
|
5281
5304
|
import enquirer6 from "enquirer";
|
|
5282
5305
|
|
|
5283
5306
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
5284
|
-
import
|
|
5307
|
+
import chalk53 from "chalk";
|
|
5285
5308
|
var STATUS_MAP = {
|
|
5286
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
5287
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
5309
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk53.magenta("merged"), date: pr.mergedAt } : null,
|
|
5310
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk53.red("closed"), date: pr.closedAt } : null
|
|
5288
5311
|
};
|
|
5289
5312
|
function defaultStatus(pr) {
|
|
5290
|
-
return { label:
|
|
5313
|
+
return { label: chalk53.green("opened"), date: pr.createdAt };
|
|
5291
5314
|
}
|
|
5292
5315
|
function getStatus2(pr) {
|
|
5293
5316
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -5296,11 +5319,11 @@ function formatDate(dateStr) {
|
|
|
5296
5319
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
5297
5320
|
}
|
|
5298
5321
|
function formatPrHeader(pr, status2) {
|
|
5299
|
-
return `${
|
|
5322
|
+
return `${chalk53.cyan(`#${pr.number}`)} ${pr.title} ${chalk53.dim(`(${pr.author.login},`)} ${status2.label} ${chalk53.dim(`${formatDate(status2.date)})`)}`;
|
|
5300
5323
|
}
|
|
5301
5324
|
function logPrDetails(pr) {
|
|
5302
5325
|
console.log(
|
|
5303
|
-
|
|
5326
|
+
chalk53.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
5304
5327
|
);
|
|
5305
5328
|
console.log();
|
|
5306
5329
|
}
|
|
@@ -5460,17 +5483,17 @@ function registerPrs(program2) {
|
|
|
5460
5483
|
prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
|
|
5461
5484
|
wontfix(Number.parseInt(commentId, 10), reason);
|
|
5462
5485
|
});
|
|
5463
|
-
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((
|
|
5464
|
-
comment(
|
|
5486
|
+
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path36, line, body) => {
|
|
5487
|
+
comment(path36, Number.parseInt(line, 10), body);
|
|
5465
5488
|
});
|
|
5466
5489
|
}
|
|
5467
5490
|
|
|
5468
5491
|
// src/commands/refactor/check/index.ts
|
|
5469
5492
|
import { spawn as spawn3 } from "child_process";
|
|
5470
|
-
import * as
|
|
5493
|
+
import * as path22 from "path";
|
|
5471
5494
|
|
|
5472
5495
|
// src/commands/refactor/logViolations.ts
|
|
5473
|
-
import
|
|
5496
|
+
import chalk54 from "chalk";
|
|
5474
5497
|
var DEFAULT_MAX_LINES = 100;
|
|
5475
5498
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
5476
5499
|
if (violations.length === 0) {
|
|
@@ -5479,43 +5502,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
5479
5502
|
}
|
|
5480
5503
|
return;
|
|
5481
5504
|
}
|
|
5482
|
-
console.error(
|
|
5505
|
+
console.error(chalk54.red(`
|
|
5483
5506
|
Refactor check failed:
|
|
5484
5507
|
`));
|
|
5485
|
-
console.error(
|
|
5508
|
+
console.error(chalk54.red(` The following files exceed ${maxLines} lines:
|
|
5486
5509
|
`));
|
|
5487
5510
|
for (const violation of violations) {
|
|
5488
|
-
console.error(
|
|
5511
|
+
console.error(chalk54.red(` ${violation.file} (${violation.lines} lines)`));
|
|
5489
5512
|
}
|
|
5490
5513
|
console.error(
|
|
5491
|
-
|
|
5514
|
+
chalk54.yellow(
|
|
5492
5515
|
`
|
|
5493
5516
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
5494
5517
|
way to refactor it, ignore it with:
|
|
5495
5518
|
`
|
|
5496
5519
|
)
|
|
5497
5520
|
);
|
|
5498
|
-
console.error(
|
|
5521
|
+
console.error(chalk54.gray(` assist refactor ignore <file>
|
|
5499
5522
|
`));
|
|
5500
5523
|
if (process.env.CLAUDECODE) {
|
|
5501
|
-
console.error(
|
|
5524
|
+
console.error(chalk54.cyan(`
|
|
5502
5525
|
## Extracting Code to New Files
|
|
5503
5526
|
`));
|
|
5504
5527
|
console.error(
|
|
5505
|
-
|
|
5528
|
+
chalk54.cyan(
|
|
5506
5529
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
5507
5530
|
`
|
|
5508
5531
|
)
|
|
5509
5532
|
);
|
|
5510
5533
|
console.error(
|
|
5511
|
-
|
|
5534
|
+
chalk54.cyan(
|
|
5512
5535
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
5513
5536
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
5514
5537
|
`
|
|
5515
5538
|
)
|
|
5516
5539
|
);
|
|
5517
5540
|
console.error(
|
|
5518
|
-
|
|
5541
|
+
chalk54.cyan(
|
|
5519
5542
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
5520
5543
|
domains, move it to a common/shared folder.
|
|
5521
5544
|
`
|
|
@@ -5644,7 +5667,7 @@ ${failed.length} verify script(s) failed:`);
|
|
|
5644
5667
|
async function runVerifyQuietly() {
|
|
5645
5668
|
const result = findPackageJsonWithVerifyScripts(process.cwd());
|
|
5646
5669
|
if (!result) return true;
|
|
5647
|
-
const packageDir =
|
|
5670
|
+
const packageDir = path22.dirname(result.packageJsonPath);
|
|
5648
5671
|
const results = await Promise.all(
|
|
5649
5672
|
result.verifyScripts.map((script) => runScript(script, packageDir))
|
|
5650
5673
|
);
|
|
@@ -5671,11 +5694,11 @@ async function check(pattern2, options2) {
|
|
|
5671
5694
|
|
|
5672
5695
|
// src/commands/refactor/ignore.ts
|
|
5673
5696
|
import fs16 from "fs";
|
|
5674
|
-
import
|
|
5697
|
+
import chalk55 from "chalk";
|
|
5675
5698
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
5676
5699
|
function ignore(file) {
|
|
5677
5700
|
if (!fs16.existsSync(file)) {
|
|
5678
|
-
console.error(
|
|
5701
|
+
console.error(chalk55.red(`Error: File does not exist: ${file}`));
|
|
5679
5702
|
process.exit(1);
|
|
5680
5703
|
}
|
|
5681
5704
|
const content = fs16.readFileSync(file, "utf-8");
|
|
@@ -5691,18 +5714,18 @@ function ignore(file) {
|
|
|
5691
5714
|
fs16.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
5692
5715
|
}
|
|
5693
5716
|
console.log(
|
|
5694
|
-
|
|
5717
|
+
chalk55.green(
|
|
5695
5718
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
5696
5719
|
)
|
|
5697
5720
|
);
|
|
5698
5721
|
}
|
|
5699
5722
|
|
|
5700
5723
|
// src/commands/refactor/restructure/index.ts
|
|
5701
|
-
import
|
|
5702
|
-
import
|
|
5724
|
+
import path31 from "path";
|
|
5725
|
+
import chalk58 from "chalk";
|
|
5703
5726
|
|
|
5704
5727
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
5705
|
-
import
|
|
5728
|
+
import path23 from "path";
|
|
5706
5729
|
import ts7 from "typescript";
|
|
5707
5730
|
|
|
5708
5731
|
// src/commands/refactor/restructure/buildImportGraph/getImportSpecifiers.ts
|
|
@@ -5729,7 +5752,7 @@ function loadParsedConfig(tsConfigPath) {
|
|
|
5729
5752
|
return ts7.parseJsonConfigFileContent(
|
|
5730
5753
|
configFile.config,
|
|
5731
5754
|
ts7.sys,
|
|
5732
|
-
|
|
5755
|
+
path23.dirname(tsConfigPath)
|
|
5733
5756
|
);
|
|
5734
5757
|
}
|
|
5735
5758
|
function addToSetMap(map, key, value) {
|
|
@@ -5745,7 +5768,7 @@ function resolveImport(specifier, filePath, options2) {
|
|
|
5745
5768
|
const resolved = ts7.resolveModuleName(specifier, filePath, options2, ts7.sys);
|
|
5746
5769
|
const resolvedPath = resolved.resolvedModule?.resolvedFileName;
|
|
5747
5770
|
if (!resolvedPath || resolvedPath.includes("node_modules")) return null;
|
|
5748
|
-
return
|
|
5771
|
+
return path23.resolve(resolvedPath);
|
|
5749
5772
|
}
|
|
5750
5773
|
function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
5751
5774
|
const parsed = loadParsedConfig(tsConfigPath);
|
|
@@ -5754,7 +5777,7 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
|
5754
5777
|
const importedBy = /* @__PURE__ */ new Map();
|
|
5755
5778
|
const imports = /* @__PURE__ */ new Map();
|
|
5756
5779
|
for (const sourceFile of program2.getSourceFiles()) {
|
|
5757
|
-
const filePath =
|
|
5780
|
+
const filePath = path23.resolve(sourceFile.fileName);
|
|
5758
5781
|
if (filePath.includes("node_modules")) continue;
|
|
5759
5782
|
for (const specifier of getImportSpecifiers(sourceFile)) {
|
|
5760
5783
|
const absTarget = resolveImport(specifier, filePath, parsed.options);
|
|
@@ -5768,12 +5791,12 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
|
5768
5791
|
}
|
|
5769
5792
|
|
|
5770
5793
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
5771
|
-
import
|
|
5794
|
+
import path24 from "path";
|
|
5772
5795
|
function clusterDirectories(graph) {
|
|
5773
5796
|
const dirImportedBy = /* @__PURE__ */ new Map();
|
|
5774
5797
|
for (const edge of graph.edges) {
|
|
5775
|
-
const sourceDir =
|
|
5776
|
-
const targetDir =
|
|
5798
|
+
const sourceDir = path24.dirname(edge.source);
|
|
5799
|
+
const targetDir = path24.dirname(edge.target);
|
|
5777
5800
|
if (sourceDir === targetDir) continue;
|
|
5778
5801
|
if (!graph.files.has(edge.target)) continue;
|
|
5779
5802
|
const existing = dirImportedBy.get(targetDir) ?? /* @__PURE__ */ new Set();
|
|
@@ -5801,20 +5824,20 @@ function clusterDirectories(graph) {
|
|
|
5801
5824
|
return clusters;
|
|
5802
5825
|
}
|
|
5803
5826
|
function isAncestor(ancestor, descendant) {
|
|
5804
|
-
const rel =
|
|
5827
|
+
const rel = path24.relative(ancestor, descendant);
|
|
5805
5828
|
return !rel.startsWith("..") && rel !== "";
|
|
5806
5829
|
}
|
|
5807
5830
|
|
|
5808
5831
|
// src/commands/refactor/restructure/clusterFiles.ts
|
|
5809
|
-
import
|
|
5832
|
+
import path25 from "path";
|
|
5810
5833
|
function findRootParent(file, importedBy, visited) {
|
|
5811
5834
|
const importers = importedBy.get(file);
|
|
5812
5835
|
if (!importers || importers.size !== 1) return file;
|
|
5813
5836
|
const parent = [...importers][0];
|
|
5814
|
-
const parentDir =
|
|
5815
|
-
const fileDir =
|
|
5837
|
+
const parentDir = path25.dirname(parent);
|
|
5838
|
+
const fileDir = path25.dirname(file);
|
|
5816
5839
|
if (parentDir !== fileDir) return file;
|
|
5817
|
-
if (
|
|
5840
|
+
if (path25.basename(parent, path25.extname(parent)) === "index") return file;
|
|
5818
5841
|
if (visited.has(parent)) return file;
|
|
5819
5842
|
visited.add(parent);
|
|
5820
5843
|
return findRootParent(parent, importedBy, visited);
|
|
@@ -5822,16 +5845,16 @@ function findRootParent(file, importedBy, visited) {
|
|
|
5822
5845
|
function clusterFiles(graph) {
|
|
5823
5846
|
const clusters = /* @__PURE__ */ new Map();
|
|
5824
5847
|
for (const file of graph.files) {
|
|
5825
|
-
const basename7 =
|
|
5848
|
+
const basename7 = path25.basename(file, path25.extname(file));
|
|
5826
5849
|
if (basename7 === "index") continue;
|
|
5827
5850
|
const importers = graph.importedBy.get(file);
|
|
5828
5851
|
if (!importers || importers.size !== 1) continue;
|
|
5829
5852
|
const parent = [...importers][0];
|
|
5830
5853
|
if (!graph.files.has(parent)) continue;
|
|
5831
|
-
const parentDir =
|
|
5832
|
-
const fileDir =
|
|
5854
|
+
const parentDir = path25.dirname(parent);
|
|
5855
|
+
const fileDir = path25.dirname(file);
|
|
5833
5856
|
if (parentDir !== fileDir) continue;
|
|
5834
|
-
const parentBasename =
|
|
5857
|
+
const parentBasename = path25.basename(parent, path25.extname(parent));
|
|
5835
5858
|
if (parentBasename === "index") continue;
|
|
5836
5859
|
const root = findRootParent(parent, graph.importedBy, /* @__PURE__ */ new Set([file]));
|
|
5837
5860
|
if (!root || root === file) continue;
|
|
@@ -5843,7 +5866,7 @@ function clusterFiles(graph) {
|
|
|
5843
5866
|
}
|
|
5844
5867
|
|
|
5845
5868
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
5846
|
-
import
|
|
5869
|
+
import path26 from "path";
|
|
5847
5870
|
|
|
5848
5871
|
// src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
|
|
5849
5872
|
import fs17 from "fs";
|
|
@@ -5897,7 +5920,7 @@ function normalizeSpecifier(rel) {
|
|
|
5897
5920
|
);
|
|
5898
5921
|
}
|
|
5899
5922
|
function computeSpecifier(fromFile, toFile) {
|
|
5900
|
-
return normalizeSpecifier(
|
|
5923
|
+
return normalizeSpecifier(path26.relative(path26.dirname(fromFile), toFile));
|
|
5901
5924
|
}
|
|
5902
5925
|
function isAffected(edge, moveMap) {
|
|
5903
5926
|
return moveMap.has(edge.target) || moveMap.has(edge.source);
|
|
@@ -5941,51 +5964,51 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
5941
5964
|
}
|
|
5942
5965
|
|
|
5943
5966
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
5944
|
-
import
|
|
5945
|
-
import
|
|
5967
|
+
import path27 from "path";
|
|
5968
|
+
import chalk56 from "chalk";
|
|
5946
5969
|
function relPath(filePath) {
|
|
5947
|
-
return
|
|
5970
|
+
return path27.relative(process.cwd(), filePath);
|
|
5948
5971
|
}
|
|
5949
5972
|
function displayMoves(plan) {
|
|
5950
5973
|
if (plan.moves.length === 0) return;
|
|
5951
|
-
console.log(
|
|
5974
|
+
console.log(chalk56.bold("\nFile moves:"));
|
|
5952
5975
|
for (const move of plan.moves) {
|
|
5953
5976
|
console.log(
|
|
5954
|
-
` ${
|
|
5977
|
+
` ${chalk56.red(relPath(move.from))} \u2192 ${chalk56.green(relPath(move.to))}`
|
|
5955
5978
|
);
|
|
5956
|
-
console.log(
|
|
5979
|
+
console.log(chalk56.dim(` ${move.reason}`));
|
|
5957
5980
|
}
|
|
5958
5981
|
}
|
|
5959
5982
|
function displayRewrites(rewrites) {
|
|
5960
5983
|
if (rewrites.length === 0) return;
|
|
5961
5984
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
5962
|
-
console.log(
|
|
5985
|
+
console.log(chalk56.bold(`
|
|
5963
5986
|
Import rewrites (${affectedFiles.size} files):`));
|
|
5964
5987
|
for (const file of affectedFiles) {
|
|
5965
|
-
console.log(` ${
|
|
5988
|
+
console.log(` ${chalk56.cyan(relPath(file))}:`);
|
|
5966
5989
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
5967
5990
|
(r) => r.file === file
|
|
5968
5991
|
)) {
|
|
5969
5992
|
console.log(
|
|
5970
|
-
` ${
|
|
5993
|
+
` ${chalk56.red(`"${oldSpecifier}"`)} \u2192 ${chalk56.green(`"${newSpecifier}"`)}`
|
|
5971
5994
|
);
|
|
5972
5995
|
}
|
|
5973
5996
|
}
|
|
5974
5997
|
}
|
|
5975
5998
|
function displayPlan(plan) {
|
|
5976
5999
|
if (plan.warnings.length > 0) {
|
|
5977
|
-
console.log(
|
|
5978
|
-
for (const w of plan.warnings) console.log(
|
|
6000
|
+
console.log(chalk56.yellow("\nWarnings:"));
|
|
6001
|
+
for (const w of plan.warnings) console.log(chalk56.yellow(` ${w}`));
|
|
5979
6002
|
}
|
|
5980
6003
|
if (plan.newDirectories.length > 0) {
|
|
5981
|
-
console.log(
|
|
6004
|
+
console.log(chalk56.bold("\nNew directories:"));
|
|
5982
6005
|
for (const dir of plan.newDirectories)
|
|
5983
|
-
console.log(
|
|
6006
|
+
console.log(chalk56.green(` ${dir}/`));
|
|
5984
6007
|
}
|
|
5985
6008
|
displayMoves(plan);
|
|
5986
6009
|
displayRewrites(plan.rewrites);
|
|
5987
6010
|
console.log(
|
|
5988
|
-
|
|
6011
|
+
chalk56.dim(
|
|
5989
6012
|
`
|
|
5990
6013
|
Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
|
|
5991
6014
|
)
|
|
@@ -5994,33 +6017,33 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
|
|
|
5994
6017
|
|
|
5995
6018
|
// src/commands/refactor/restructure/executePlan.ts
|
|
5996
6019
|
import fs18 from "fs";
|
|
5997
|
-
import
|
|
5998
|
-
import
|
|
6020
|
+
import path28 from "path";
|
|
6021
|
+
import chalk57 from "chalk";
|
|
5999
6022
|
function executePlan(plan) {
|
|
6000
6023
|
const updatedContents = applyRewrites(plan.rewrites);
|
|
6001
6024
|
for (const [file, content] of updatedContents) {
|
|
6002
6025
|
fs18.writeFileSync(file, content, "utf-8");
|
|
6003
6026
|
console.log(
|
|
6004
|
-
|
|
6027
|
+
chalk57.cyan(` Rewrote imports in ${path28.relative(process.cwd(), file)}`)
|
|
6005
6028
|
);
|
|
6006
6029
|
}
|
|
6007
6030
|
for (const dir of plan.newDirectories) {
|
|
6008
6031
|
fs18.mkdirSync(dir, { recursive: true });
|
|
6009
|
-
console.log(
|
|
6032
|
+
console.log(chalk57.green(` Created ${path28.relative(process.cwd(), dir)}/`));
|
|
6010
6033
|
}
|
|
6011
6034
|
for (const move of plan.moves) {
|
|
6012
|
-
const targetDir =
|
|
6035
|
+
const targetDir = path28.dirname(move.to);
|
|
6013
6036
|
if (!fs18.existsSync(targetDir)) {
|
|
6014
6037
|
fs18.mkdirSync(targetDir, { recursive: true });
|
|
6015
6038
|
}
|
|
6016
6039
|
fs18.renameSync(move.from, move.to);
|
|
6017
6040
|
console.log(
|
|
6018
|
-
|
|
6019
|
-
` Moved ${
|
|
6041
|
+
chalk57.white(
|
|
6042
|
+
` Moved ${path28.relative(process.cwd(), move.from)} \u2192 ${path28.relative(process.cwd(), move.to)}`
|
|
6020
6043
|
)
|
|
6021
6044
|
);
|
|
6022
6045
|
}
|
|
6023
|
-
removeEmptyDirectories(plan.moves.map((m) =>
|
|
6046
|
+
removeEmptyDirectories(plan.moves.map((m) => path28.dirname(m.from)));
|
|
6024
6047
|
}
|
|
6025
6048
|
function removeEmptyDirectories(dirs) {
|
|
6026
6049
|
const unique = [...new Set(dirs)];
|
|
@@ -6030,8 +6053,8 @@ function removeEmptyDirectories(dirs) {
|
|
|
6030
6053
|
if (entries.length === 0) {
|
|
6031
6054
|
fs18.rmdirSync(dir);
|
|
6032
6055
|
console.log(
|
|
6033
|
-
|
|
6034
|
-
` Removed empty directory ${
|
|
6056
|
+
chalk57.dim(
|
|
6057
|
+
` Removed empty directory ${path28.relative(process.cwd(), dir)}`
|
|
6035
6058
|
)
|
|
6036
6059
|
);
|
|
6037
6060
|
}
|
|
@@ -6040,13 +6063,13 @@ function removeEmptyDirectories(dirs) {
|
|
|
6040
6063
|
|
|
6041
6064
|
// src/commands/refactor/restructure/planFileMoves/index.ts
|
|
6042
6065
|
import fs20 from "fs";
|
|
6043
|
-
import
|
|
6066
|
+
import path30 from "path";
|
|
6044
6067
|
|
|
6045
6068
|
// src/commands/refactor/restructure/planFileMoves/planDirectoryMoves.ts
|
|
6046
6069
|
import fs19 from "fs";
|
|
6047
|
-
import
|
|
6070
|
+
import path29 from "path";
|
|
6048
6071
|
function collectEntry(results, dir, entry) {
|
|
6049
|
-
const full =
|
|
6072
|
+
const full = path29.join(dir, entry.name);
|
|
6050
6073
|
const items = entry.isDirectory() ? listFilesRecursive(full) : [full];
|
|
6051
6074
|
results.push(...items);
|
|
6052
6075
|
}
|
|
@@ -6060,15 +6083,15 @@ function listFilesRecursive(dir) {
|
|
|
6060
6083
|
}
|
|
6061
6084
|
function addDirectoryFileMoves(moves, childDir, newLocation, reason) {
|
|
6062
6085
|
for (const file of listFilesRecursive(childDir)) {
|
|
6063
|
-
const rel =
|
|
6064
|
-
moves.push({ from: file, to:
|
|
6086
|
+
const rel = path29.relative(childDir, file);
|
|
6087
|
+
moves.push({ from: file, to: path29.join(newLocation, rel), reason });
|
|
6065
6088
|
}
|
|
6066
6089
|
}
|
|
6067
6090
|
function resolveChildDest(parentDir, childDir) {
|
|
6068
|
-
return
|
|
6091
|
+
return path29.join(parentDir, path29.basename(childDir));
|
|
6069
6092
|
}
|
|
6070
6093
|
function childMoveReason(parentDir) {
|
|
6071
|
-
return `Directory only imported from ${
|
|
6094
|
+
return `Directory only imported from ${path29.basename(parentDir)}/`;
|
|
6072
6095
|
}
|
|
6073
6096
|
function registerDirectoryMove(result, childDir, dest, parentDir) {
|
|
6074
6097
|
result.directories.push(dest);
|
|
@@ -6096,7 +6119,7 @@ function emptyResult() {
|
|
|
6096
6119
|
return { moves: [], directories: [], warnings: [] };
|
|
6097
6120
|
}
|
|
6098
6121
|
function childMoveData(child, newDir, parentBase) {
|
|
6099
|
-
const to =
|
|
6122
|
+
const to = path30.join(newDir, path30.basename(child));
|
|
6100
6123
|
return { from: child, to, reason: `Only imported by ${parentBase}` };
|
|
6101
6124
|
}
|
|
6102
6125
|
function addChildMoves(moves, children, newDir, parentBase) {
|
|
@@ -6109,15 +6132,15 @@ function checkDirConflict(result, label2, dir) {
|
|
|
6109
6132
|
return true;
|
|
6110
6133
|
}
|
|
6111
6134
|
function getBaseName(filePath) {
|
|
6112
|
-
return
|
|
6135
|
+
return path30.basename(filePath, path30.extname(filePath));
|
|
6113
6136
|
}
|
|
6114
6137
|
function resolveClusterDir(parent) {
|
|
6115
|
-
return
|
|
6138
|
+
return path30.join(path30.dirname(parent), getBaseName(parent));
|
|
6116
6139
|
}
|
|
6117
6140
|
function createParentMove(parent, newDir) {
|
|
6118
6141
|
return {
|
|
6119
6142
|
from: parent,
|
|
6120
|
-
to:
|
|
6143
|
+
to: path30.join(newDir, `index${path30.extname(parent)}`),
|
|
6121
6144
|
reason: `Main module of new ${getBaseName(parent)}/ directory`
|
|
6122
6145
|
};
|
|
6123
6146
|
}
|
|
@@ -6141,7 +6164,7 @@ function planFileMoves(clusters) {
|
|
|
6141
6164
|
|
|
6142
6165
|
// src/commands/refactor/restructure/index.ts
|
|
6143
6166
|
function buildPlan(candidateFiles, tsConfigPath) {
|
|
6144
|
-
const candidates = new Set(candidateFiles.map((f) =>
|
|
6167
|
+
const candidates = new Set(candidateFiles.map((f) => path31.resolve(f)));
|
|
6145
6168
|
const graph = buildImportGraph(candidates, tsConfigPath);
|
|
6146
6169
|
const allProjectFiles = /* @__PURE__ */ new Set([
|
|
6147
6170
|
...graph.importedBy.keys(),
|
|
@@ -6161,22 +6184,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
6161
6184
|
const targetPattern = pattern2 ?? "src";
|
|
6162
6185
|
const files = findSourceFiles2(targetPattern);
|
|
6163
6186
|
if (files.length === 0) {
|
|
6164
|
-
console.log(
|
|
6187
|
+
console.log(chalk58.yellow("No files found matching pattern"));
|
|
6165
6188
|
return;
|
|
6166
6189
|
}
|
|
6167
|
-
const tsConfigPath =
|
|
6190
|
+
const tsConfigPath = path31.resolve("tsconfig.json");
|
|
6168
6191
|
const plan = buildPlan(files, tsConfigPath);
|
|
6169
6192
|
if (plan.moves.length === 0) {
|
|
6170
|
-
console.log(
|
|
6193
|
+
console.log(chalk58.green("No restructuring needed"));
|
|
6171
6194
|
return;
|
|
6172
6195
|
}
|
|
6173
6196
|
displayPlan(plan);
|
|
6174
6197
|
if (options2.apply) {
|
|
6175
|
-
console.log(
|
|
6198
|
+
console.log(chalk58.bold("\nApplying changes..."));
|
|
6176
6199
|
executePlan(plan);
|
|
6177
|
-
console.log(
|
|
6200
|
+
console.log(chalk58.green("\nRestructuring complete"));
|
|
6178
6201
|
} else {
|
|
6179
|
-
console.log(
|
|
6202
|
+
console.log(chalk58.dim("\nDry run. Use --apply to execute."));
|
|
6180
6203
|
}
|
|
6181
6204
|
}
|
|
6182
6205
|
|
|
@@ -6315,7 +6338,7 @@ async function configure() {
|
|
|
6315
6338
|
import { existsSync as existsSync27 } from "fs";
|
|
6316
6339
|
|
|
6317
6340
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
6318
|
-
import { dirname as
|
|
6341
|
+
import { dirname as dirname16, join as join24 } from "path";
|
|
6319
6342
|
|
|
6320
6343
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
6321
6344
|
import { renameSync } from "fs";
|
|
@@ -6365,11 +6388,11 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
6365
6388
|
for (let i = 0; i < vttFiles.length; i++) {
|
|
6366
6389
|
const vttFile = vttFiles[i];
|
|
6367
6390
|
if (!isValidDatePrefix(vttFile.filename)) {
|
|
6368
|
-
const vttFileDir =
|
|
6391
|
+
const vttFileDir = dirname16(vttFile.absolutePath);
|
|
6369
6392
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
6370
6393
|
if (newFilename) {
|
|
6371
6394
|
const newRelativePath = join24(
|
|
6372
|
-
|
|
6395
|
+
dirname16(vttFile.relativePath),
|
|
6373
6396
|
newFilename
|
|
6374
6397
|
);
|
|
6375
6398
|
vttFiles[i] = {
|
|
@@ -6387,7 +6410,7 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
6387
6410
|
|
|
6388
6411
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
6389
6412
|
import { existsSync as existsSync26, mkdirSync as mkdirSync7, readFileSync as readFileSync22, writeFileSync as writeFileSync21 } from "fs";
|
|
6390
|
-
import { basename as basename5, dirname as
|
|
6413
|
+
import { basename as basename5, dirname as dirname17, join as join25 } from "path";
|
|
6391
6414
|
|
|
6392
6415
|
// src/commands/transcript/cleanText.ts
|
|
6393
6416
|
function cleanText(text) {
|
|
@@ -6601,7 +6624,7 @@ function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
|
6601
6624
|
}
|
|
6602
6625
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
6603
6626
|
const mdFile = toMdFilename(vttFile.filename);
|
|
6604
|
-
const relativeDir =
|
|
6627
|
+
const relativeDir = dirname17(vttFile.relativePath);
|
|
6605
6628
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
6606
6629
|
const outputPath = join25(outputDir, mdFile);
|
|
6607
6630
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
@@ -6706,7 +6729,7 @@ async function format() {
|
|
|
6706
6729
|
|
|
6707
6730
|
// src/commands/transcript/summarise/index.ts
|
|
6708
6731
|
import { existsSync as existsSync29 } from "fs";
|
|
6709
|
-
import { basename as basename6, dirname as
|
|
6732
|
+
import { basename as basename6, dirname as dirname19, join as join27, relative as relative2 } from "path";
|
|
6710
6733
|
|
|
6711
6734
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
6712
6735
|
import {
|
|
@@ -6716,17 +6739,17 @@ import {
|
|
|
6716
6739
|
renameSync as renameSync2,
|
|
6717
6740
|
rmSync
|
|
6718
6741
|
} from "fs";
|
|
6719
|
-
import { dirname as
|
|
6742
|
+
import { dirname as dirname18, join as join26 } from "path";
|
|
6720
6743
|
|
|
6721
6744
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
6722
|
-
import
|
|
6745
|
+
import chalk59 from "chalk";
|
|
6723
6746
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
6724
6747
|
function validateStagedContent(filename, content) {
|
|
6725
6748
|
const firstLine = content.split("\n")[0];
|
|
6726
6749
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
6727
6750
|
if (!match) {
|
|
6728
6751
|
console.error(
|
|
6729
|
-
|
|
6752
|
+
chalk59.red(
|
|
6730
6753
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
6731
6754
|
)
|
|
6732
6755
|
);
|
|
@@ -6735,7 +6758,7 @@ function validateStagedContent(filename, content) {
|
|
|
6735
6758
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
6736
6759
|
if (!contentAfterLink) {
|
|
6737
6760
|
console.error(
|
|
6738
|
-
|
|
6761
|
+
chalk59.red(
|
|
6739
6762
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
6740
6763
|
)
|
|
6741
6764
|
);
|
|
@@ -6770,7 +6793,7 @@ function processStagedFile() {
|
|
|
6770
6793
|
process.exit(1);
|
|
6771
6794
|
}
|
|
6772
6795
|
const destPath = join26(summaryDir, matchingTranscript.relativePath);
|
|
6773
|
-
const destDir =
|
|
6796
|
+
const destDir = dirname18(destPath);
|
|
6774
6797
|
if (!existsSync28(destDir)) {
|
|
6775
6798
|
mkdirSync8(destDir, { recursive: true });
|
|
6776
6799
|
}
|
|
@@ -6784,7 +6807,7 @@ function processStagedFile() {
|
|
|
6784
6807
|
|
|
6785
6808
|
// src/commands/transcript/summarise/index.ts
|
|
6786
6809
|
function buildRelativeKey(relativePath, baseName) {
|
|
6787
|
-
const relDir =
|
|
6810
|
+
const relDir = dirname19(relativePath);
|
|
6788
6811
|
return relDir === "." ? baseName : join27(relDir, baseName);
|
|
6789
6812
|
}
|
|
6790
6813
|
function buildSummaryIndex(summaryDir) {
|
|
@@ -6820,7 +6843,7 @@ function summarise2() {
|
|
|
6820
6843
|
const next2 = missing[0];
|
|
6821
6844
|
const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
|
|
6822
6845
|
const outputPath = join27(STAGING_DIR, outputFilename);
|
|
6823
|
-
const summaryFileDir = join27(summaryDir,
|
|
6846
|
+
const summaryFileDir = join27(summaryDir, dirname19(next2.relativePath));
|
|
6824
6847
|
const relativeTranscriptPath = encodeURI(
|
|
6825
6848
|
relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
|
|
6826
6849
|
);
|
|
@@ -6870,9 +6893,9 @@ import { join as join29 } from "path";
|
|
|
6870
6893
|
|
|
6871
6894
|
// src/commands/voice/shared.ts
|
|
6872
6895
|
import { homedir as homedir7 } from "os";
|
|
6873
|
-
import { dirname as
|
|
6896
|
+
import { dirname as dirname20, join as join28 } from "path";
|
|
6874
6897
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
6875
|
-
var __dirname6 =
|
|
6898
|
+
var __dirname6 = dirname20(fileURLToPath6(import.meta.url));
|
|
6876
6899
|
var VOICE_DIR = join28(homedir7(), ".assist", "voice");
|
|
6877
6900
|
var voicePaths = {
|
|
6878
6901
|
dir: VOICE_DIR,
|
|
@@ -7128,7 +7151,7 @@ function registerVoice(program2) {
|
|
|
7128
7151
|
|
|
7129
7152
|
// src/commands/roam/auth.ts
|
|
7130
7153
|
import { randomBytes } from "crypto";
|
|
7131
|
-
import
|
|
7154
|
+
import chalk60 from "chalk";
|
|
7132
7155
|
|
|
7133
7156
|
// src/lib/openBrowser.ts
|
|
7134
7157
|
import { execSync as execSync31 } from "child_process";
|
|
@@ -7303,13 +7326,13 @@ async function auth() {
|
|
|
7303
7326
|
saveGlobalConfig(config);
|
|
7304
7327
|
const state = randomBytes(16).toString("hex");
|
|
7305
7328
|
console.log(
|
|
7306
|
-
|
|
7329
|
+
chalk60.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
7307
7330
|
);
|
|
7308
|
-
console.log(
|
|
7309
|
-
console.log(
|
|
7310
|
-
console.log(
|
|
7331
|
+
console.log(chalk60.white("http://localhost:14523/callback\n"));
|
|
7332
|
+
console.log(chalk60.blue("Opening browser for authorization..."));
|
|
7333
|
+
console.log(chalk60.dim("Waiting for authorization callback..."));
|
|
7311
7334
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
7312
|
-
console.log(
|
|
7335
|
+
console.log(chalk60.dim("Exchanging code for tokens..."));
|
|
7313
7336
|
const tokens = await exchangeToken({
|
|
7314
7337
|
code,
|
|
7315
7338
|
clientId,
|
|
@@ -7325,7 +7348,7 @@ async function auth() {
|
|
|
7325
7348
|
};
|
|
7326
7349
|
saveGlobalConfig(config);
|
|
7327
7350
|
console.log(
|
|
7328
|
-
|
|
7351
|
+
chalk60.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
7329
7352
|
);
|
|
7330
7353
|
}
|
|
7331
7354
|
|
|
@@ -7513,14 +7536,14 @@ function run2(name, args) {
|
|
|
7513
7536
|
}
|
|
7514
7537
|
|
|
7515
7538
|
// src/commands/statusLine.ts
|
|
7516
|
-
import
|
|
7539
|
+
import chalk61 from "chalk";
|
|
7517
7540
|
function formatNumber(num) {
|
|
7518
7541
|
return num.toLocaleString("en-US");
|
|
7519
7542
|
}
|
|
7520
7543
|
function colorizePercent(pct) {
|
|
7521
7544
|
const label2 = `${pct}%`;
|
|
7522
|
-
if (pct > 80) return
|
|
7523
|
-
if (pct > 40) return
|
|
7545
|
+
if (pct > 80) return chalk61.red(label2);
|
|
7546
|
+
if (pct > 40) return chalk61.yellow(label2);
|
|
7524
7547
|
return label2;
|
|
7525
7548
|
}
|
|
7526
7549
|
async function statusLine() {
|
|
@@ -7540,27 +7563,27 @@ async function statusLine() {
|
|
|
7540
7563
|
// src/commands/sync.ts
|
|
7541
7564
|
import * as fs23 from "fs";
|
|
7542
7565
|
import * as os from "os";
|
|
7543
|
-
import * as
|
|
7566
|
+
import * as path34 from "path";
|
|
7544
7567
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
7545
7568
|
|
|
7546
7569
|
// src/commands/sync/syncClaudeMd.ts
|
|
7547
7570
|
import * as fs21 from "fs";
|
|
7548
|
-
import * as
|
|
7549
|
-
import
|
|
7571
|
+
import * as path32 from "path";
|
|
7572
|
+
import chalk62 from "chalk";
|
|
7550
7573
|
async function syncClaudeMd(claudeDir, targetBase) {
|
|
7551
|
-
const source =
|
|
7552
|
-
const target =
|
|
7574
|
+
const source = path32.join(claudeDir, "CLAUDE.md");
|
|
7575
|
+
const target = path32.join(targetBase, "CLAUDE.md");
|
|
7553
7576
|
const sourceContent = fs21.readFileSync(source, "utf-8");
|
|
7554
7577
|
if (fs21.existsSync(target)) {
|
|
7555
7578
|
const targetContent = fs21.readFileSync(target, "utf-8");
|
|
7556
7579
|
if (sourceContent !== targetContent) {
|
|
7557
7580
|
console.log(
|
|
7558
|
-
|
|
7581
|
+
chalk62.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
7559
7582
|
);
|
|
7560
7583
|
console.log();
|
|
7561
7584
|
printDiff(targetContent, sourceContent);
|
|
7562
7585
|
const confirm = await promptConfirm(
|
|
7563
|
-
|
|
7586
|
+
chalk62.red("Overwrite existing CLAUDE.md?"),
|
|
7564
7587
|
false
|
|
7565
7588
|
);
|
|
7566
7589
|
if (!confirm) {
|
|
@@ -7575,11 +7598,11 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
7575
7598
|
|
|
7576
7599
|
// src/commands/sync/syncSettings.ts
|
|
7577
7600
|
import * as fs22 from "fs";
|
|
7578
|
-
import * as
|
|
7579
|
-
import
|
|
7601
|
+
import * as path33 from "path";
|
|
7602
|
+
import chalk63 from "chalk";
|
|
7580
7603
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
7581
|
-
const source =
|
|
7582
|
-
const target =
|
|
7604
|
+
const source = path33.join(claudeDir, "settings.json");
|
|
7605
|
+
const target = path33.join(targetBase, "settings.json");
|
|
7583
7606
|
const sourceContent = fs22.readFileSync(source, "utf-8");
|
|
7584
7607
|
const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
|
|
7585
7608
|
if (fs22.existsSync(target)) {
|
|
@@ -7592,14 +7615,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
7592
7615
|
if (mergedContent !== normalizedTarget) {
|
|
7593
7616
|
if (!options2?.yes) {
|
|
7594
7617
|
console.log(
|
|
7595
|
-
|
|
7618
|
+
chalk63.yellow(
|
|
7596
7619
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
7597
7620
|
)
|
|
7598
7621
|
);
|
|
7599
7622
|
console.log();
|
|
7600
7623
|
printDiff(targetContent, mergedContent);
|
|
7601
7624
|
const confirm = await promptConfirm(
|
|
7602
|
-
|
|
7625
|
+
chalk63.red("Overwrite existing settings.json?"),
|
|
7603
7626
|
false
|
|
7604
7627
|
);
|
|
7605
7628
|
if (!confirm) {
|
|
@@ -7615,21 +7638,21 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
7615
7638
|
|
|
7616
7639
|
// src/commands/sync.ts
|
|
7617
7640
|
var __filename4 = fileURLToPath7(import.meta.url);
|
|
7618
|
-
var __dirname7 =
|
|
7641
|
+
var __dirname7 = path34.dirname(__filename4);
|
|
7619
7642
|
async function sync(options2) {
|
|
7620
|
-
const claudeDir =
|
|
7621
|
-
const targetBase =
|
|
7643
|
+
const claudeDir = path34.join(__dirname7, "..", "claude");
|
|
7644
|
+
const targetBase = path34.join(os.homedir(), ".claude");
|
|
7622
7645
|
syncCommands(claudeDir, targetBase);
|
|
7623
7646
|
await syncSettings(claudeDir, targetBase, { yes: options2?.yes });
|
|
7624
7647
|
await syncClaudeMd(claudeDir, targetBase);
|
|
7625
7648
|
}
|
|
7626
7649
|
function syncCommands(claudeDir, targetBase) {
|
|
7627
|
-
const sourceDir =
|
|
7628
|
-
const targetDir =
|
|
7650
|
+
const sourceDir = path34.join(claudeDir, "commands");
|
|
7651
|
+
const targetDir = path34.join(targetBase, "commands");
|
|
7629
7652
|
fs23.mkdirSync(targetDir, { recursive: true });
|
|
7630
7653
|
const files = fs23.readdirSync(sourceDir);
|
|
7631
7654
|
for (const file of files) {
|
|
7632
|
-
fs23.copyFileSync(
|
|
7655
|
+
fs23.copyFileSync(path34.join(sourceDir, file), path34.join(targetDir, file));
|
|
7633
7656
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
7634
7657
|
}
|
|
7635
7658
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|
|
@@ -7637,15 +7660,15 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
7637
7660
|
|
|
7638
7661
|
// src/commands/update.ts
|
|
7639
7662
|
import { execSync as execSync32 } from "child_process";
|
|
7640
|
-
import * as
|
|
7663
|
+
import * as path35 from "path";
|
|
7641
7664
|
function isGlobalNpmInstall(dir) {
|
|
7642
7665
|
try {
|
|
7643
|
-
const resolved =
|
|
7644
|
-
if (resolved.split(
|
|
7666
|
+
const resolved = path35.resolve(dir);
|
|
7667
|
+
if (resolved.split(path35.sep).includes("node_modules")) {
|
|
7645
7668
|
return true;
|
|
7646
7669
|
}
|
|
7647
7670
|
const globalPrefix = execSync32("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
7648
|
-
return resolved.toLowerCase().startsWith(
|
|
7671
|
+
return resolved.toLowerCase().startsWith(path35.resolve(globalPrefix).toLowerCase());
|
|
7649
7672
|
} catch {
|
|
7650
7673
|
return false;
|
|
7651
7674
|
}
|