@staff0rd/assist 0.47.1 → 0.49.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/README.md +2 -1
- package/dist/index.js +513 -393
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { execSync as
|
|
4
|
+
import { execSync as execSync22 } from "child_process";
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
|
|
7
7
|
// package.json
|
|
8
8
|
var package_default = {
|
|
9
9
|
name: "@staff0rd/assist",
|
|
10
|
-
version: "0.
|
|
10
|
+
version: "0.49.0",
|
|
11
11
|
type: "module",
|
|
12
12
|
main: "dist/index.js",
|
|
13
13
|
bin: {
|
|
@@ -316,12 +316,12 @@ import chalk14 from "chalk";
|
|
|
316
316
|
// src/shared/promptMultiselect.ts
|
|
317
317
|
import chalk3 from "chalk";
|
|
318
318
|
import enquirer from "enquirer";
|
|
319
|
-
async function promptMultiselect(message,
|
|
319
|
+
async function promptMultiselect(message, options2) {
|
|
320
320
|
const { selected } = await enquirer.prompt({
|
|
321
321
|
type: "multiselect",
|
|
322
322
|
name: "selected",
|
|
323
323
|
message,
|
|
324
|
-
choices:
|
|
324
|
+
choices: options2.map((opt) => ({
|
|
325
325
|
name: opt.value,
|
|
326
326
|
message: `${opt.name} - ${chalk3.dim(opt.description)}`
|
|
327
327
|
})),
|
|
@@ -460,12 +460,22 @@ async function setupBuild(packageJsonPath, hasVite, hasTypescript) {
|
|
|
460
460
|
} else if (hasVite) {
|
|
461
461
|
command = "vite build --logLevel error";
|
|
462
462
|
} else {
|
|
463
|
-
command = "
|
|
463
|
+
command = "npm run build";
|
|
464
464
|
}
|
|
465
465
|
console.log(chalk6.dim(`Using: ${command}`));
|
|
466
466
|
const pkg = readPackageJson(packageJsonPath);
|
|
467
467
|
writePackageJson(packageJsonPath, addScript(pkg, "verify:build", command));
|
|
468
468
|
}
|
|
469
|
+
async function setupTypecheck(packageJsonPath) {
|
|
470
|
+
console.log(chalk6.blue("\nSetting up typecheck verification..."));
|
|
471
|
+
const command = "tsc --noEmit";
|
|
472
|
+
console.log(chalk6.dim(`Using: ${command}`));
|
|
473
|
+
const pkg = readPackageJson(packageJsonPath);
|
|
474
|
+
writePackageJson(
|
|
475
|
+
packageJsonPath,
|
|
476
|
+
addScript(pkg, "verify:typecheck", command)
|
|
477
|
+
);
|
|
478
|
+
}
|
|
469
479
|
|
|
470
480
|
// src/commands/verify/setup/setupDuplicateCode.ts
|
|
471
481
|
import * as path3 from "path";
|
|
@@ -578,8 +588,8 @@ function removeEslintConfigFiles() {
|
|
|
578
588
|
}
|
|
579
589
|
|
|
580
590
|
// src/shared/removeEslint/index.ts
|
|
581
|
-
function removeEslint(
|
|
582
|
-
const removedFromPackageJson = removeEslintFromPackageJson(
|
|
591
|
+
function removeEslint(options2 = {}) {
|
|
592
|
+
const removedFromPackageJson = removeEslintFromPackageJson(options2);
|
|
583
593
|
const removedConfigFiles = removeEslintConfigFiles();
|
|
584
594
|
if (removedFromPackageJson || removedConfigFiles) {
|
|
585
595
|
console.log("Running npm install...");
|
|
@@ -588,7 +598,7 @@ function removeEslint(options = {}) {
|
|
|
588
598
|
}
|
|
589
599
|
return false;
|
|
590
600
|
}
|
|
591
|
-
function removeEslintFromPackageJson(
|
|
601
|
+
function removeEslintFromPackageJson(options2) {
|
|
592
602
|
const packageJsonPath = "package.json";
|
|
593
603
|
if (!existsSync5(packageJsonPath)) {
|
|
594
604
|
return false;
|
|
@@ -597,7 +607,7 @@ function removeEslintFromPackageJson(options) {
|
|
|
597
607
|
let modified = false;
|
|
598
608
|
modified = removeEslintDeps(packageJson.dependencies) || modified;
|
|
599
609
|
modified = removeEslintDeps(packageJson.devDependencies) || modified;
|
|
600
|
-
modified = removeEslintScripts(packageJson.scripts,
|
|
610
|
+
modified = removeEslintScripts(packageJson.scripts, options2) || modified;
|
|
601
611
|
if (modified) {
|
|
602
612
|
writeFileSync3(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
603
613
|
`);
|
|
@@ -616,11 +626,11 @@ function removeEslintDeps(deps) {
|
|
|
616
626
|
}
|
|
617
627
|
return modified;
|
|
618
628
|
}
|
|
619
|
-
function removeEslintScripts(scripts,
|
|
629
|
+
function removeEslintScripts(scripts, options2) {
|
|
620
630
|
if (!scripts) return false;
|
|
621
631
|
let modified = false;
|
|
622
632
|
for (const key of Object.keys(scripts)) {
|
|
623
|
-
const isEslintScript = key.includes("eslint") || scripts[key].includes("eslint") ||
|
|
633
|
+
const isEslintScript = key.includes("eslint") || scripts[key].includes("eslint") || options2.removeLintScripts && key.includes("lint");
|
|
624
634
|
if (isEslintScript) {
|
|
625
635
|
delete scripts[key];
|
|
626
636
|
modified = true;
|
|
@@ -770,34 +780,21 @@ function detectExistingSetup(pkg) {
|
|
|
770
780
|
test: toolStatus(pkg, "verify:test", !!pkg.devDependencies?.vitest),
|
|
771
781
|
hasVite: !!pkg.devDependencies?.vite || !!pkg.dependencies?.vite,
|
|
772
782
|
hasTypescript: !!pkg.devDependencies?.typescript,
|
|
773
|
-
build:
|
|
774
|
-
|
|
775
|
-
hasScript: !!pkg.scripts?.["verify:build"],
|
|
776
|
-
isOutdated: false
|
|
777
|
-
},
|
|
783
|
+
build: toolStatus(pkg, "verify:build", true),
|
|
784
|
+
typecheck: toolStatus(pkg, "verify:typecheck", true),
|
|
778
785
|
hardcodedColors: toolStatus(pkg, "verify:hardcoded-colors", true),
|
|
779
786
|
hasOpenColor: !!pkg.dependencies?.["open-color"] || !!pkg.devDependencies?.["open-color"]
|
|
780
787
|
};
|
|
781
788
|
}
|
|
782
789
|
|
|
783
|
-
// src/commands/verify/init/
|
|
790
|
+
// src/commands/verify/init/options.ts
|
|
784
791
|
function getBuildDescription(setup) {
|
|
785
792
|
if (setup.hasVite && setup.hasTypescript)
|
|
786
793
|
return "TypeScript + Vite build verification";
|
|
787
794
|
if (setup.hasVite) return "Vite build verification";
|
|
788
|
-
return "
|
|
789
|
-
}
|
|
790
|
-
function shouldInclude(setup, def) {
|
|
791
|
-
return needsSetup(setup[def.toolKey]) && (def.extraCondition ?? true);
|
|
795
|
+
return "Build verification";
|
|
792
796
|
}
|
|
793
|
-
|
|
794
|
-
return {
|
|
795
|
-
name: `${def.label}${getStatusLabel(setup[def.toolKey])}`,
|
|
796
|
-
value: def.value,
|
|
797
|
-
description: def.description
|
|
798
|
-
};
|
|
799
|
-
}
|
|
800
|
-
var STATIC_OPTIONS = [
|
|
797
|
+
var options = [
|
|
801
798
|
{
|
|
802
799
|
toolKey: "knip",
|
|
803
800
|
value: "knip",
|
|
@@ -821,31 +818,45 @@ var STATIC_OPTIONS = [
|
|
|
821
818
|
value: "hardcoded-colors",
|
|
822
819
|
label: "hardcoded-colors",
|
|
823
820
|
description: "Detect hardcoded hex colors (use open-color instead)"
|
|
821
|
+
},
|
|
822
|
+
{
|
|
823
|
+
toolKey: "test",
|
|
824
|
+
value: "test",
|
|
825
|
+
label: "test",
|
|
826
|
+
description: "Run tests with vitest",
|
|
827
|
+
extraCondition: (s) => s.test.hasPackage
|
|
828
|
+
},
|
|
829
|
+
{
|
|
830
|
+
toolKey: "build",
|
|
831
|
+
value: "build",
|
|
832
|
+
label: "build",
|
|
833
|
+
description: getBuildDescription,
|
|
834
|
+
extraCondition: (s) => s.hasTypescript || s.hasVite
|
|
835
|
+
},
|
|
836
|
+
{
|
|
837
|
+
toolKey: "typecheck",
|
|
838
|
+
value: "typecheck",
|
|
839
|
+
label: "typecheck",
|
|
840
|
+
description: "TypeScript type checking",
|
|
841
|
+
extraCondition: (s) => s.hasTypescript && !s.hasVite
|
|
824
842
|
}
|
|
825
843
|
];
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
value: "test",
|
|
831
|
-
label: "test",
|
|
832
|
-
description: "Run tests with vitest",
|
|
833
|
-
extraCondition: setup.test.hasPackage
|
|
834
|
-
},
|
|
835
|
-
{
|
|
836
|
-
toolKey: "build",
|
|
837
|
-
value: "build",
|
|
838
|
-
label: "build",
|
|
839
|
-
description: getBuildDescription(setup),
|
|
840
|
-
extraCondition: setup.hasTypescript || setup.hasVite
|
|
841
|
-
}
|
|
842
|
-
];
|
|
844
|
+
|
|
845
|
+
// src/commands/verify/init/getAvailableOptions.ts
|
|
846
|
+
function resolveDescription(desc, setup) {
|
|
847
|
+
return typeof desc === "function" ? desc(setup) : desc;
|
|
843
848
|
}
|
|
844
|
-
function
|
|
845
|
-
return
|
|
849
|
+
function toVerifyOption(def, setup) {
|
|
850
|
+
return {
|
|
851
|
+
name: `${def.label}${getStatusLabel(setup[def.toolKey])}`,
|
|
852
|
+
value: def.value,
|
|
853
|
+
description: resolveDescription(def.description, setup)
|
|
854
|
+
};
|
|
846
855
|
}
|
|
847
856
|
function getAvailableOptions(setup) {
|
|
848
|
-
return
|
|
857
|
+
return options.filter(
|
|
858
|
+
(def) => needsSetup(setup[def.toolKey]) && (def.extraCondition?.(setup) ?? true)
|
|
859
|
+
).map((def) => toVerifyOption(def, setup));
|
|
849
860
|
}
|
|
850
861
|
|
|
851
862
|
// src/commands/verify/init/index.ts
|
|
@@ -856,6 +867,7 @@ function getSetupHandlers(hasVite, hasTypescript, hasOpenColor) {
|
|
|
856
867
|
"duplicate-code": (p) => setupDuplicateCode(p),
|
|
857
868
|
test: (p) => setupTest(p),
|
|
858
869
|
build: (p) => setupBuild(p, hasVite, hasTypescript),
|
|
870
|
+
typecheck: (p) => setupTypecheck(p),
|
|
859
871
|
"hardcoded-colors": (p) => setupHardcodedColors(p, hasOpenColor)
|
|
860
872
|
};
|
|
861
873
|
}
|
|
@@ -989,20 +1001,20 @@ var SETUP_HANDLERS = {
|
|
|
989
1001
|
}
|
|
990
1002
|
};
|
|
991
1003
|
function getAvailableOptions2(setup) {
|
|
992
|
-
const
|
|
1004
|
+
const options2 = [];
|
|
993
1005
|
if (!setup.hasLaunchJson && setup.hasVite)
|
|
994
|
-
|
|
1006
|
+
options2.push({
|
|
995
1007
|
name: "launch",
|
|
996
1008
|
value: "launch",
|
|
997
1009
|
description: "Debug configuration for Vite dev server"
|
|
998
1010
|
});
|
|
999
1011
|
if (!setup.hasSettingsJson)
|
|
1000
|
-
|
|
1012
|
+
options2.push({
|
|
1001
1013
|
name: "settings",
|
|
1002
1014
|
value: "settings",
|
|
1003
1015
|
description: "Biome formatter configuration"
|
|
1004
1016
|
});
|
|
1005
|
-
return
|
|
1017
|
+
return options2;
|
|
1006
1018
|
}
|
|
1007
1019
|
async function init3() {
|
|
1008
1020
|
const { pkg } = requirePackageJson();
|
|
@@ -1045,8 +1057,8 @@ import chalk17 from "chalk";
|
|
|
1045
1057
|
import fs5 from "fs";
|
|
1046
1058
|
import path10 from "path";
|
|
1047
1059
|
var EXTENSIONS = [".ts", ".tsx"];
|
|
1048
|
-
function findSourceFiles(dir,
|
|
1049
|
-
const { includeTests = true } =
|
|
1060
|
+
function findSourceFiles(dir, options2 = {}) {
|
|
1061
|
+
const { includeTests = true } = options2;
|
|
1050
1062
|
const results = [];
|
|
1051
1063
|
if (!fs5.existsSync(dir)) {
|
|
1052
1064
|
return results;
|
|
@@ -1055,7 +1067,7 @@ function findSourceFiles(dir, options = {}) {
|
|
|
1055
1067
|
for (const entry of entries) {
|
|
1056
1068
|
const fullPath = path10.join(dir, entry.name);
|
|
1057
1069
|
if (entry.isDirectory() && entry.name !== "node_modules") {
|
|
1058
|
-
results.push(...findSourceFiles(fullPath,
|
|
1070
|
+
results.push(...findSourceFiles(fullPath, options2));
|
|
1059
1071
|
} else if (entry.isFile() && EXTENSIONS.some((ext) => entry.name.endsWith(ext))) {
|
|
1060
1072
|
if (!includeTests && entry.name.includes(".test.")) {
|
|
1061
1073
|
continue;
|
|
@@ -1223,22 +1235,261 @@ function lint() {
|
|
|
1223
1235
|
}
|
|
1224
1236
|
}
|
|
1225
1237
|
|
|
1226
|
-
// src/commands/new/
|
|
1238
|
+
// src/commands/new/newCli.ts
|
|
1239
|
+
import { execSync as execSync7 } from "child_process";
|
|
1240
|
+
import { basename as basename2, resolve } from "path";
|
|
1241
|
+
|
|
1242
|
+
// src/commands/verify/hardcodedColors.ts
|
|
1243
|
+
import { execSync as execSync5 } from "child_process";
|
|
1244
|
+
var pattern = "0x[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,6}";
|
|
1245
|
+
function hardcodedColors() {
|
|
1246
|
+
try {
|
|
1247
|
+
const output = execSync5(`grep -rEnH '${pattern}' src/`, {
|
|
1248
|
+
encoding: "utf-8"
|
|
1249
|
+
});
|
|
1250
|
+
const lines = output.trim().split("\n");
|
|
1251
|
+
console.log("Hardcoded colors found:\n");
|
|
1252
|
+
for (const line of lines) {
|
|
1253
|
+
const match = line.match(/^(.+):(\d+):(.+)$/);
|
|
1254
|
+
if (match) {
|
|
1255
|
+
const [, file, lineNum, content] = match;
|
|
1256
|
+
const colorMatch = content.match(/0x[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,6}/);
|
|
1257
|
+
const color = colorMatch?.[0] ?? "unknown";
|
|
1258
|
+
console.log(`${file}:${lineNum} \u2192 ${color}`);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
console.log(`
|
|
1262
|
+
Total: ${lines.length} hardcoded color(s)`);
|
|
1263
|
+
console.log("\nUse colors from the 'open-color' (oc) library instead.");
|
|
1264
|
+
console.log("\nExample fix:");
|
|
1265
|
+
console.log(" Before: color: '#228be6'");
|
|
1266
|
+
console.log(" After: color: oc.blue[6]");
|
|
1267
|
+
console.log("\nImport open-color with: import oc from 'open-color'");
|
|
1268
|
+
process.exit(1);
|
|
1269
|
+
} catch {
|
|
1270
|
+
console.log("No hardcoded colors found.");
|
|
1271
|
+
process.exit(0);
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
// src/commands/verify/run/index.ts
|
|
1276
|
+
import { spawn } from "child_process";
|
|
1277
|
+
import * as path12 from "path";
|
|
1278
|
+
|
|
1279
|
+
// src/commands/verify/run/createTimerCallback/printTaskStatuses.ts
|
|
1280
|
+
function formatDuration(ms) {
|
|
1281
|
+
if (ms < 1e3) {
|
|
1282
|
+
return `${ms}ms`;
|
|
1283
|
+
}
|
|
1284
|
+
const seconds = (ms / 1e3).toFixed(1);
|
|
1285
|
+
return `${seconds}s`;
|
|
1286
|
+
}
|
|
1287
|
+
function printTaskStatuses(tasks) {
|
|
1288
|
+
console.log("\n--- Task Status ---");
|
|
1289
|
+
for (const task of tasks) {
|
|
1290
|
+
if (task.endTime !== void 0) {
|
|
1291
|
+
const duration = formatDuration(task.endTime - task.startTime);
|
|
1292
|
+
const status = task.code === 0 ? "\u2713" : "\u2717";
|
|
1293
|
+
console.log(` ${status} ${task.script}: ${duration}`);
|
|
1294
|
+
} else {
|
|
1295
|
+
const elapsed = formatDuration(Date.now() - task.startTime);
|
|
1296
|
+
console.log(` \u22EF ${task.script}: running (${elapsed})`);
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
console.log("-------------------\n");
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
// src/commands/verify/run/createTimerCallback/index.ts
|
|
1303
|
+
function logFailedScripts(failed) {
|
|
1304
|
+
console.error(`
|
|
1305
|
+
${failed.length} script(s) failed:`);
|
|
1306
|
+
for (const f of failed) {
|
|
1307
|
+
console.error(` - ${f.script} (exit code ${f.code})`);
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
function createTimerCallback(taskStatuses, index) {
|
|
1311
|
+
return (exitCode) => {
|
|
1312
|
+
taskStatuses[index].endTime = Date.now();
|
|
1313
|
+
taskStatuses[index].code = exitCode;
|
|
1314
|
+
printTaskStatuses(taskStatuses);
|
|
1315
|
+
};
|
|
1316
|
+
}
|
|
1317
|
+
function initTaskStatuses(scripts) {
|
|
1318
|
+
return scripts.map((script) => ({ script, startTime: Date.now() }));
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
// src/commands/verify/run/index.ts
|
|
1322
|
+
function spawnScript(script, cwd) {
|
|
1323
|
+
return spawn("npm", ["run", script], { stdio: "inherit", shell: true, cwd });
|
|
1324
|
+
}
|
|
1325
|
+
function onScriptClose(script, onComplete, resolve2) {
|
|
1326
|
+
return (code) => {
|
|
1327
|
+
const exitCode = code ?? 1;
|
|
1328
|
+
onComplete?.(exitCode);
|
|
1329
|
+
resolve2({ script, code: exitCode });
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1332
|
+
function runScript(script, cwd, onComplete) {
|
|
1333
|
+
return new Promise((resolve2) => {
|
|
1334
|
+
spawnScript(script, cwd).on(
|
|
1335
|
+
"close",
|
|
1336
|
+
onScriptClose(script, onComplete, resolve2)
|
|
1337
|
+
);
|
|
1338
|
+
});
|
|
1339
|
+
}
|
|
1340
|
+
function runAllScripts(verifyScripts, packageDir, timer) {
|
|
1341
|
+
const taskStatuses = initTaskStatuses(verifyScripts);
|
|
1342
|
+
return Promise.all(
|
|
1343
|
+
verifyScripts.map(
|
|
1344
|
+
(script, index) => runScript(
|
|
1345
|
+
script,
|
|
1346
|
+
packageDir,
|
|
1347
|
+
timer ? createTimerCallback(taskStatuses, index) : void 0
|
|
1348
|
+
)
|
|
1349
|
+
)
|
|
1350
|
+
);
|
|
1351
|
+
}
|
|
1352
|
+
function printScriptList(scripts) {
|
|
1353
|
+
console.log(`Running ${scripts.length} verify script(s) in parallel:`);
|
|
1354
|
+
for (const script of scripts) {
|
|
1355
|
+
console.log(` - ${script}`);
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
function exitIfFailed(failed) {
|
|
1359
|
+
if (failed.length === 0) return;
|
|
1360
|
+
logFailedScripts(failed);
|
|
1361
|
+
process.exit(1);
|
|
1362
|
+
}
|
|
1363
|
+
function handleResults(results, totalCount) {
|
|
1364
|
+
exitIfFailed(results.filter((r) => r.code !== 0));
|
|
1365
|
+
console.log(`
|
|
1366
|
+
All ${totalCount} verify script(s) passed`);
|
|
1367
|
+
}
|
|
1368
|
+
function resolveVerifyScripts() {
|
|
1369
|
+
const result = findPackageJsonWithVerifyScripts(process.cwd());
|
|
1370
|
+
if (!result) {
|
|
1371
|
+
console.log("No package.json with verify:* scripts found");
|
|
1372
|
+
return null;
|
|
1373
|
+
}
|
|
1374
|
+
return result;
|
|
1375
|
+
}
|
|
1376
|
+
function getPackageDir(found) {
|
|
1377
|
+
return path12.dirname(found.packageJsonPath);
|
|
1378
|
+
}
|
|
1379
|
+
async function executeVerifyScripts(found, timer) {
|
|
1380
|
+
printScriptList(found.verifyScripts);
|
|
1381
|
+
const results = await runAllScripts(
|
|
1382
|
+
found.verifyScripts,
|
|
1383
|
+
getPackageDir(found),
|
|
1384
|
+
timer
|
|
1385
|
+
);
|
|
1386
|
+
handleResults(results, found.verifyScripts.length);
|
|
1387
|
+
}
|
|
1388
|
+
async function run(options2 = {}) {
|
|
1389
|
+
const found = resolveVerifyScripts();
|
|
1390
|
+
if (!found) return;
|
|
1391
|
+
await executeVerifyScripts(found, options2.timer ?? false);
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
// src/commands/new/initPackageJson.ts
|
|
1227
1395
|
import { execSync as execSync6 } from "child_process";
|
|
1228
|
-
|
|
1396
|
+
function initPackageJson(name) {
|
|
1397
|
+
console.log("Initializing package.json...");
|
|
1398
|
+
execSync6("npm init -y", { stdio: "inherit" });
|
|
1399
|
+
console.log("Configuring package.json...");
|
|
1400
|
+
execSync6("npm pkg delete main", { stdio: "inherit" });
|
|
1401
|
+
execSync6("npm pkg set type=module", { stdio: "inherit" });
|
|
1402
|
+
execSync6(`npm pkg set bin.${name}=./dist/index.js`, { stdio: "inherit" });
|
|
1403
|
+
execSync6("npm pkg set scripts.build=tsup", { stdio: "inherit" });
|
|
1404
|
+
execSync6('npm pkg set scripts.start="node dist/index.js"', {
|
|
1405
|
+
stdio: "inherit"
|
|
1406
|
+
});
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
// src/commands/new/writeCliTemplate.ts
|
|
1410
|
+
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
1411
|
+
function writeCliTemplate(name) {
|
|
1412
|
+
console.log("Writing tsconfig.json...");
|
|
1413
|
+
writeFileSync6(
|
|
1414
|
+
"tsconfig.json",
|
|
1415
|
+
JSON.stringify(
|
|
1416
|
+
{
|
|
1417
|
+
compilerOptions: {
|
|
1418
|
+
target: "ES2022",
|
|
1419
|
+
module: "ESNext",
|
|
1420
|
+
moduleResolution: "bundler",
|
|
1421
|
+
outDir: "./dist",
|
|
1422
|
+
rootDir: "./src",
|
|
1423
|
+
strict: true,
|
|
1424
|
+
esModuleInterop: true,
|
|
1425
|
+
resolveJsonModule: true,
|
|
1426
|
+
skipLibCheck: true,
|
|
1427
|
+
forceConsistentCasingInFileNames: true
|
|
1428
|
+
},
|
|
1429
|
+
include: ["src/**/*"],
|
|
1430
|
+
exclude: ["node_modules"]
|
|
1431
|
+
},
|
|
1432
|
+
null,
|
|
1433
|
+
" "
|
|
1434
|
+
)
|
|
1435
|
+
);
|
|
1436
|
+
console.log("Writing tsup.config.ts...");
|
|
1437
|
+
writeFileSync6(
|
|
1438
|
+
"tsup.config.ts",
|
|
1439
|
+
`import { defineConfig } from "tsup";
|
|
1440
|
+
export default defineConfig({
|
|
1441
|
+
entry: ["src/index.ts"],
|
|
1442
|
+
format: ["esm"],
|
|
1443
|
+
target: "node22",
|
|
1444
|
+
outDir: "dist",
|
|
1445
|
+
clean: true,
|
|
1446
|
+
shims: true,
|
|
1447
|
+
});
|
|
1448
|
+
`
|
|
1449
|
+
);
|
|
1450
|
+
console.log("Writing src/index.ts...");
|
|
1451
|
+
mkdirSync2("src", { recursive: true });
|
|
1452
|
+
writeFileSync6(
|
|
1453
|
+
"src/index.ts",
|
|
1454
|
+
`#!/usr/bin/env node
|
|
1455
|
+
import { Command } from "commander";
|
|
1456
|
+
const program = new Command();
|
|
1457
|
+
program.name("${name}").description("").version("0.0.0");
|
|
1458
|
+
program.parse();
|
|
1459
|
+
`
|
|
1460
|
+
);
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
// src/commands/new/newCli.ts
|
|
1464
|
+
async function newCli() {
|
|
1465
|
+
const name = basename2(resolve("."));
|
|
1466
|
+
initPackageJson(name);
|
|
1467
|
+
console.log("Installing dependencies...");
|
|
1468
|
+
execSync7("npm install commander", { stdio: "inherit" });
|
|
1469
|
+
execSync7("npm install -D tsup typescript @types/node", {
|
|
1470
|
+
stdio: "inherit"
|
|
1471
|
+
});
|
|
1472
|
+
writeCliTemplate(name);
|
|
1473
|
+
await init4();
|
|
1474
|
+
await run();
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
// src/commands/new/newProject.ts
|
|
1478
|
+
import { execSync as execSync9 } from "child_process";
|
|
1479
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
1229
1480
|
|
|
1230
1481
|
// src/commands/deploy/init/index.ts
|
|
1231
|
-
import { execSync as
|
|
1482
|
+
import { execSync as execSync8 } from "child_process";
|
|
1232
1483
|
import chalk20 from "chalk";
|
|
1233
1484
|
import enquirer3 from "enquirer";
|
|
1234
1485
|
|
|
1235
1486
|
// src/commands/deploy/init/updateWorkflow.ts
|
|
1236
|
-
import { existsSync as existsSync9, mkdirSync as
|
|
1237
|
-
import { dirname as
|
|
1487
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "fs";
|
|
1488
|
+
import { dirname as dirname9, join as join7 } from "path";
|
|
1238
1489
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1239
1490
|
import chalk19 from "chalk";
|
|
1240
1491
|
var WORKFLOW_PATH = ".github/workflows/build.yml";
|
|
1241
|
-
var __dirname3 =
|
|
1492
|
+
var __dirname3 = dirname9(fileURLToPath2(import.meta.url));
|
|
1242
1493
|
function getExistingSiteId() {
|
|
1243
1494
|
if (!existsSync9(WORKFLOW_PATH)) {
|
|
1244
1495
|
return null;
|
|
@@ -1256,7 +1507,7 @@ async function updateWorkflow(siteId) {
|
|
|
1256
1507
|
const newContent = getTemplateContent(siteId);
|
|
1257
1508
|
const workflowDir = ".github/workflows";
|
|
1258
1509
|
if (!existsSync9(workflowDir)) {
|
|
1259
|
-
|
|
1510
|
+
mkdirSync3(workflowDir, { recursive: true });
|
|
1260
1511
|
}
|
|
1261
1512
|
if (existsSync9(WORKFLOW_PATH)) {
|
|
1262
1513
|
const oldContent = readFileSync7(WORKFLOW_PATH, "utf-8");
|
|
@@ -1273,7 +1524,7 @@ async function updateWorkflow(siteId) {
|
|
|
1273
1524
|
return;
|
|
1274
1525
|
}
|
|
1275
1526
|
}
|
|
1276
|
-
|
|
1527
|
+
writeFileSync7(WORKFLOW_PATH, newContent);
|
|
1277
1528
|
console.log(chalk19.green(`
|
|
1278
1529
|
Created ${WORKFLOW_PATH}`));
|
|
1279
1530
|
}
|
|
@@ -1281,7 +1532,7 @@ Created ${WORKFLOW_PATH}`));
|
|
|
1281
1532
|
// src/commands/deploy/init/index.ts
|
|
1282
1533
|
async function ensureNetlifyCli() {
|
|
1283
1534
|
try {
|
|
1284
|
-
|
|
1535
|
+
execSync8("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
1285
1536
|
} catch (error) {
|
|
1286
1537
|
if (!(error instanceof Error) || !error.message.includes("command not found"))
|
|
1287
1538
|
throw error;
|
|
@@ -1296,9 +1547,9 @@ async function ensureNetlifyCli() {
|
|
|
1296
1547
|
process.exit(1);
|
|
1297
1548
|
}
|
|
1298
1549
|
console.log(chalk20.dim("\nInstalling netlify-cli...\n"));
|
|
1299
|
-
|
|
1550
|
+
execSync8("npm install -g netlify-cli", { stdio: "inherit" });
|
|
1300
1551
|
console.log();
|
|
1301
|
-
|
|
1552
|
+
execSync8("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
1302
1553
|
}
|
|
1303
1554
|
}
|
|
1304
1555
|
function printSetupInstructions() {
|
|
@@ -1341,7 +1592,7 @@ async function init5() {
|
|
|
1341
1592
|
// src/commands/new/newProject.ts
|
|
1342
1593
|
async function newProject() {
|
|
1343
1594
|
console.log("Initializing Vite with react-ts template...");
|
|
1344
|
-
|
|
1595
|
+
execSync9("npm create vite@latest . -- --template react-ts", {
|
|
1345
1596
|
stdio: "inherit"
|
|
1346
1597
|
});
|
|
1347
1598
|
removeEslint({ removeLintScripts: true });
|
|
@@ -1365,11 +1616,18 @@ function addViteBaseConfig() {
|
|
|
1365
1616
|
'defineConfig({\n base: "./",'
|
|
1366
1617
|
);
|
|
1367
1618
|
if (updated !== content) {
|
|
1368
|
-
|
|
1619
|
+
writeFileSync8(viteConfigPath, updated);
|
|
1369
1620
|
console.log('Added base: "./" to vite.config.ts');
|
|
1370
1621
|
}
|
|
1371
1622
|
}
|
|
1372
1623
|
|
|
1624
|
+
// src/commands/new/registerNew.ts
|
|
1625
|
+
function registerNew(program2) {
|
|
1626
|
+
const newCommand = program2.command("new").description("Scaffold a new project");
|
|
1627
|
+
newCommand.command("vite").description("Initialize a new Vite React TypeScript project").action(newProject);
|
|
1628
|
+
newCommand.command("cli").description("Initialize a new tsup CLI project").action(newCli);
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1373
1631
|
// src/lib/readStdin.ts
|
|
1374
1632
|
import * as readline from "readline";
|
|
1375
1633
|
async function readStdin() {
|
|
@@ -1405,17 +1663,17 @@ function detectPlatform() {
|
|
|
1405
1663
|
}
|
|
1406
1664
|
|
|
1407
1665
|
// src/commands/notify/showNotification/showWindowsNotificationFromWsl.ts
|
|
1408
|
-
import { spawn } from "child_process";
|
|
1666
|
+
import { spawn as spawn2 } from "child_process";
|
|
1409
1667
|
import fs9 from "fs";
|
|
1410
1668
|
import { createRequire } from "module";
|
|
1411
|
-
import
|
|
1669
|
+
import path13 from "path";
|
|
1412
1670
|
var require2 = createRequire(import.meta.url);
|
|
1413
1671
|
function getSnoreToastPath() {
|
|
1414
|
-
const notifierPath =
|
|
1415
|
-
return
|
|
1672
|
+
const notifierPath = path13.dirname(require2.resolve("node-notifier"));
|
|
1673
|
+
return path13.join(notifierPath, "vendor", "snoreToast", "snoretoast-x64.exe");
|
|
1416
1674
|
}
|
|
1417
|
-
function showWindowsNotificationFromWsl(
|
|
1418
|
-
const { title, message, sound } =
|
|
1675
|
+
function showWindowsNotificationFromWsl(options2) {
|
|
1676
|
+
const { title, message, sound } = options2;
|
|
1419
1677
|
const snoreToastPath = getSnoreToastPath();
|
|
1420
1678
|
try {
|
|
1421
1679
|
fs9.chmodSync(snoreToastPath, 493);
|
|
@@ -1427,7 +1685,7 @@ function showWindowsNotificationFromWsl(options) {
|
|
|
1427
1685
|
} else if (sound === "Reminder") {
|
|
1428
1686
|
args.push("-s", "ms-winsoundevent:Notification.Reminder");
|
|
1429
1687
|
}
|
|
1430
|
-
const child =
|
|
1688
|
+
const child = spawn2(snoreToastPath, args, {
|
|
1431
1689
|
detached: true,
|
|
1432
1690
|
stdio: "ignore"
|
|
1433
1691
|
});
|
|
@@ -1436,8 +1694,8 @@ function showWindowsNotificationFromWsl(options) {
|
|
|
1436
1694
|
}
|
|
1437
1695
|
|
|
1438
1696
|
// src/commands/notify/showNotification/index.ts
|
|
1439
|
-
function showNotification(
|
|
1440
|
-
const { title, message, sound } =
|
|
1697
|
+
function showNotification(options2) {
|
|
1698
|
+
const { title, message, sound } = options2;
|
|
1441
1699
|
const platform = detectPlatform();
|
|
1442
1700
|
if (platform === "wsl") {
|
|
1443
1701
|
return showWindowsNotificationFromWsl({ title, message, sound });
|
|
@@ -1500,13 +1758,13 @@ import chalk22 from "chalk";
|
|
|
1500
1758
|
|
|
1501
1759
|
// src/commands/complexity/shared/index.ts
|
|
1502
1760
|
import fs11 from "fs";
|
|
1503
|
-
import
|
|
1761
|
+
import path15 from "path";
|
|
1504
1762
|
import chalk21 from "chalk";
|
|
1505
1763
|
import ts5 from "typescript";
|
|
1506
1764
|
|
|
1507
1765
|
// src/commands/complexity/findSourceFiles.ts
|
|
1508
1766
|
import fs10 from "fs";
|
|
1509
|
-
import
|
|
1767
|
+
import path14 from "path";
|
|
1510
1768
|
import { minimatch } from "minimatch";
|
|
1511
1769
|
function applyIgnoreGlobs(files) {
|
|
1512
1770
|
const { complexity } = loadConfig();
|
|
@@ -1521,7 +1779,7 @@ function walk(dir, results) {
|
|
|
1521
1779
|
const extensions = [".ts", ".tsx"];
|
|
1522
1780
|
const entries = fs10.readdirSync(dir, { withFileTypes: true });
|
|
1523
1781
|
for (const entry of entries) {
|
|
1524
|
-
const fullPath =
|
|
1782
|
+
const fullPath = path14.join(dir, entry.name);
|
|
1525
1783
|
if (entry.isDirectory()) {
|
|
1526
1784
|
if (entry.name !== "node_modules" && entry.name !== ".git") {
|
|
1527
1785
|
walk(fullPath, results);
|
|
@@ -1737,7 +1995,7 @@ function countSloc(content) {
|
|
|
1737
1995
|
function createSourceFromFile(filePath) {
|
|
1738
1996
|
const content = fs11.readFileSync(filePath, "utf-8");
|
|
1739
1997
|
return ts5.createSourceFile(
|
|
1740
|
-
|
|
1998
|
+
path15.basename(filePath),
|
|
1741
1999
|
content,
|
|
1742
2000
|
ts5.ScriptTarget.Latest,
|
|
1743
2001
|
true,
|
|
@@ -1766,20 +2024,20 @@ function forEachFunction(files, callback) {
|
|
|
1766
2024
|
}
|
|
1767
2025
|
|
|
1768
2026
|
// src/commands/complexity/cyclomatic.ts
|
|
1769
|
-
async function cyclomatic(pattern2 = "**/*.ts",
|
|
2027
|
+
async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
1770
2028
|
withSourceFiles(pattern2, (files) => {
|
|
1771
2029
|
const results = [];
|
|
1772
2030
|
let hasViolation = false;
|
|
1773
2031
|
forEachFunction(files, (file, name, node) => {
|
|
1774
2032
|
const complexity = calculateCyclomaticComplexity(node);
|
|
1775
2033
|
results.push({ file, name, complexity });
|
|
1776
|
-
if (
|
|
2034
|
+
if (options2.threshold !== void 0 && complexity > options2.threshold) {
|
|
1777
2035
|
hasViolation = true;
|
|
1778
2036
|
}
|
|
1779
2037
|
});
|
|
1780
2038
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
1781
2039
|
for (const { file, name, complexity } of results) {
|
|
1782
|
-
const exceedsThreshold =
|
|
2040
|
+
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
1783
2041
|
const color = exceedsThreshold ? chalk22.red : chalk22.white;
|
|
1784
2042
|
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk22.cyan(complexity)}`);
|
|
1785
2043
|
}
|
|
@@ -1797,20 +2055,20 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
1797
2055
|
|
|
1798
2056
|
// src/commands/complexity/halstead.ts
|
|
1799
2057
|
import chalk23 from "chalk";
|
|
1800
|
-
async function halstead(pattern2 = "**/*.ts",
|
|
2058
|
+
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
1801
2059
|
withSourceFiles(pattern2, (files) => {
|
|
1802
2060
|
const results = [];
|
|
1803
2061
|
let hasViolation = false;
|
|
1804
2062
|
forEachFunction(files, (file, name, node) => {
|
|
1805
2063
|
const metrics = calculateHalstead(node);
|
|
1806
2064
|
results.push({ file, name, metrics });
|
|
1807
|
-
if (
|
|
2065
|
+
if (options2.threshold !== void 0 && metrics.volume > options2.threshold) {
|
|
1808
2066
|
hasViolation = true;
|
|
1809
2067
|
}
|
|
1810
2068
|
});
|
|
1811
2069
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
1812
2070
|
for (const { file, name, metrics } of results) {
|
|
1813
|
-
const exceedsThreshold =
|
|
2071
|
+
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
1814
2072
|
const color = exceedsThreshold ? chalk23.red : chalk23.white;
|
|
1815
2073
|
console.log(
|
|
1816
2074
|
`${color(`${file}:${name}`)} \u2192 volume: ${chalk23.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk23.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk23.magenta(metrics.effort.toFixed(1))}`
|
|
@@ -1898,18 +2156,18 @@ function aggregateResults(fileMetrics) {
|
|
|
1898
2156
|
results.sort((a, b) => a.minMaintainability - b.minMaintainability);
|
|
1899
2157
|
return results;
|
|
1900
2158
|
}
|
|
1901
|
-
async function maintainability(pattern2 = "**/*.ts",
|
|
2159
|
+
async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
1902
2160
|
withSourceFiles(pattern2, (files) => {
|
|
1903
2161
|
const fileMetrics = collectFileMetrics(files);
|
|
1904
2162
|
const results = aggregateResults(fileMetrics);
|
|
1905
|
-
displayMaintainabilityResults(results,
|
|
2163
|
+
displayMaintainabilityResults(results, options2.threshold);
|
|
1906
2164
|
});
|
|
1907
2165
|
}
|
|
1908
2166
|
|
|
1909
2167
|
// src/commands/complexity/sloc.ts
|
|
1910
2168
|
import fs13 from "fs";
|
|
1911
2169
|
import chalk25 from "chalk";
|
|
1912
|
-
async function sloc(pattern2 = "**/*.ts",
|
|
2170
|
+
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
1913
2171
|
withSourceFiles(pattern2, (files) => {
|
|
1914
2172
|
const results = [];
|
|
1915
2173
|
let hasViolation = false;
|
|
@@ -1917,13 +2175,13 @@ async function sloc(pattern2 = "**/*.ts", options = {}) {
|
|
|
1917
2175
|
const content = fs13.readFileSync(file, "utf-8");
|
|
1918
2176
|
const lines = countSloc(content);
|
|
1919
2177
|
results.push({ file, lines });
|
|
1920
|
-
if (
|
|
2178
|
+
if (options2.threshold !== void 0 && lines > options2.threshold) {
|
|
1921
2179
|
hasViolation = true;
|
|
1922
2180
|
}
|
|
1923
2181
|
}
|
|
1924
2182
|
results.sort((a, b) => b.lines - a.lines);
|
|
1925
2183
|
for (const { file, lines } of results) {
|
|
1926
|
-
const exceedsThreshold =
|
|
2184
|
+
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
1927
2185
|
const color = exceedsThreshold ? chalk25.red : chalk25.white;
|
|
1928
2186
|
console.log(`${color(file)} \u2192 ${chalk25.cyan(lines)} lines`);
|
|
1929
2187
|
}
|
|
@@ -1984,7 +2242,7 @@ function registerComplexity(program2) {
|
|
|
1984
2242
|
}
|
|
1985
2243
|
|
|
1986
2244
|
// src/commands/deploy/redirect.ts
|
|
1987
|
-
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as
|
|
2245
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
1988
2246
|
import chalk27 from "chalk";
|
|
1989
2247
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
1990
2248
|
if (!window.location.pathname.endsWith('/')) {
|
|
@@ -2008,7 +2266,7 @@ function redirect() {
|
|
|
2008
2266
|
return;
|
|
2009
2267
|
}
|
|
2010
2268
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
2011
|
-
|
|
2269
|
+
writeFileSync9(indexPath, newContent);
|
|
2012
2270
|
console.log(chalk27.green("Added trailing slash redirect to index.html"));
|
|
2013
2271
|
}
|
|
2014
2272
|
|
|
@@ -2020,11 +2278,11 @@ function registerDeploy(program2) {
|
|
|
2020
2278
|
}
|
|
2021
2279
|
|
|
2022
2280
|
// src/commands/devlog/list/index.ts
|
|
2023
|
-
import { execSync as
|
|
2024
|
-
import { basename as
|
|
2281
|
+
import { execSync as execSync11 } from "child_process";
|
|
2282
|
+
import { basename as basename3 } from "path";
|
|
2025
2283
|
|
|
2026
2284
|
// src/commands/devlog/shared.ts
|
|
2027
|
-
import { execSync as
|
|
2285
|
+
import { execSync as execSync10 } from "child_process";
|
|
2028
2286
|
import chalk28 from "chalk";
|
|
2029
2287
|
|
|
2030
2288
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
@@ -2068,7 +2326,7 @@ function loadDevlogEntries(repoName) {
|
|
|
2068
2326
|
// src/commands/devlog/shared.ts
|
|
2069
2327
|
function getCommitFiles(hash) {
|
|
2070
2328
|
try {
|
|
2071
|
-
const output =
|
|
2329
|
+
const output = execSync10(`git show --name-only --format="" ${hash}`, {
|
|
2072
2330
|
encoding: "utf-8"
|
|
2073
2331
|
});
|
|
2074
2332
|
return output.trim().split("\n").filter(Boolean);
|
|
@@ -2130,16 +2388,16 @@ function printDateHeader(date, isSkipped, entries) {
|
|
|
2130
2388
|
}
|
|
2131
2389
|
|
|
2132
2390
|
// src/commands/devlog/list/index.ts
|
|
2133
|
-
function list(
|
|
2391
|
+
function list(options2) {
|
|
2134
2392
|
const config = loadConfig();
|
|
2135
|
-
const days =
|
|
2136
|
-
const ignore2 =
|
|
2393
|
+
const days = options2.days ?? 30;
|
|
2394
|
+
const ignore2 = options2.ignore ?? config.devlog?.ignore ?? [];
|
|
2137
2395
|
const skipDays = new Set(config.devlog?.skip?.days ?? []);
|
|
2138
|
-
const repoName =
|
|
2396
|
+
const repoName = basename3(process.cwd());
|
|
2139
2397
|
const devlogEntries = loadDevlogEntries(repoName);
|
|
2140
|
-
const reverseFlag =
|
|
2141
|
-
const limitFlag =
|
|
2142
|
-
const output =
|
|
2398
|
+
const reverseFlag = options2.reverse ? "--reverse " : "";
|
|
2399
|
+
const limitFlag = options2.reverse ? "" : "-n 500 ";
|
|
2400
|
+
const output = execSync11(
|
|
2143
2401
|
`git log ${reverseFlag}${limitFlag}--pretty=format:'%ad|%h|%s' --date=short`,
|
|
2144
2402
|
{ encoding: "utf-8" }
|
|
2145
2403
|
);
|
|
@@ -2147,8 +2405,8 @@ function list(options) {
|
|
|
2147
2405
|
let dateCount = 0;
|
|
2148
2406
|
let isFirst = true;
|
|
2149
2407
|
for (const [date, dateCommits] of commitsByDate) {
|
|
2150
|
-
if (
|
|
2151
|
-
if (date <
|
|
2408
|
+
if (options2.since) {
|
|
2409
|
+
if (date < options2.since) {
|
|
2152
2410
|
break;
|
|
2153
2411
|
}
|
|
2154
2412
|
} else if (dateCount >= days) {
|
|
@@ -2160,16 +2418,16 @@ function list(options) {
|
|
|
2160
2418
|
}
|
|
2161
2419
|
isFirst = false;
|
|
2162
2420
|
printDateHeader(date, skipDays.has(date), devlogEntries.get(date));
|
|
2163
|
-
printCommitsWithFiles(dateCommits, ignore2,
|
|
2421
|
+
printCommitsWithFiles(dateCommits, ignore2, options2.verbose ?? false);
|
|
2164
2422
|
}
|
|
2165
2423
|
}
|
|
2166
2424
|
|
|
2167
2425
|
// src/commands/devlog/getLastVersionInfo.ts
|
|
2168
|
-
import { execSync as
|
|
2426
|
+
import { execSync as execSync12 } from "child_process";
|
|
2169
2427
|
import semver from "semver";
|
|
2170
2428
|
function getVersionAtCommit(hash) {
|
|
2171
2429
|
try {
|
|
2172
|
-
const content =
|
|
2430
|
+
const content = execSync12(`git show ${hash}:package.json`, {
|
|
2173
2431
|
encoding: "utf-8"
|
|
2174
2432
|
});
|
|
2175
2433
|
const pkg = JSON.parse(content);
|
|
@@ -2184,7 +2442,7 @@ function stripToMinor(version2) {
|
|
|
2184
2442
|
}
|
|
2185
2443
|
function getLastVersionInfoFromGit() {
|
|
2186
2444
|
try {
|
|
2187
|
-
const output =
|
|
2445
|
+
const output = execSync12(
|
|
2188
2446
|
"git log -1 --pretty=format:'%ad|%h' --date=short",
|
|
2189
2447
|
{
|
|
2190
2448
|
encoding: "utf-8"
|
|
@@ -2227,7 +2485,7 @@ function bumpVersion(version2, type) {
|
|
|
2227
2485
|
}
|
|
2228
2486
|
|
|
2229
2487
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
2230
|
-
import { execSync as
|
|
2488
|
+
import { execSync as execSync13 } from "child_process";
|
|
2231
2489
|
import chalk31 from "chalk";
|
|
2232
2490
|
|
|
2233
2491
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
@@ -2261,7 +2519,7 @@ function findTargetDate(commitsByDate, skipDays) {
|
|
|
2261
2519
|
return Array.from(commitsByDate.keys()).filter((d) => !skipDays.has(d)).sort()[0];
|
|
2262
2520
|
}
|
|
2263
2521
|
function fetchCommitsByDate(ignore2, lastDate) {
|
|
2264
|
-
const output =
|
|
2522
|
+
const output = execSync13(
|
|
2265
2523
|
"git log --pretty=format:'%ad|%h|%s' --date=short -n 500",
|
|
2266
2524
|
{ encoding: "utf-8" }
|
|
2267
2525
|
);
|
|
@@ -2276,8 +2534,8 @@ function printVersionInfo(config, lastInfo, firstHash) {
|
|
|
2276
2534
|
versions.minor
|
|
2277
2535
|
);
|
|
2278
2536
|
}
|
|
2279
|
-
function resolveIgnoreList(
|
|
2280
|
-
return
|
|
2537
|
+
function resolveIgnoreList(options2, config) {
|
|
2538
|
+
return options2.ignore ?? config.devlog?.ignore ?? [];
|
|
2281
2539
|
}
|
|
2282
2540
|
function resolveSkipDays(config) {
|
|
2283
2541
|
return new Set(config.devlog?.skip?.days ?? []);
|
|
@@ -2305,15 +2563,15 @@ function logNoCommits(lastInfo) {
|
|
|
2305
2563
|
}
|
|
2306
2564
|
|
|
2307
2565
|
// src/commands/devlog/next/index.ts
|
|
2308
|
-
function resolveContextData(config,
|
|
2566
|
+
function resolveContextData(config, options2) {
|
|
2309
2567
|
const repoName = getRepoName();
|
|
2310
2568
|
const lastInfo = getLastVersionInfo(repoName, config);
|
|
2311
|
-
return { repoName, lastInfo, ignore: resolveIgnoreList(
|
|
2569
|
+
return { repoName, lastInfo, ignore: resolveIgnoreList(options2, config) };
|
|
2312
2570
|
}
|
|
2313
|
-
function buildContext(
|
|
2571
|
+
function buildContext(options2) {
|
|
2314
2572
|
const config = loadConfig();
|
|
2315
|
-
const data = resolveContextData(config,
|
|
2316
|
-
return { config, ...data, verbose:
|
|
2573
|
+
const data = resolveContextData(config, options2);
|
|
2574
|
+
return { config, ...data, verbose: options2.verbose ?? false };
|
|
2317
2575
|
}
|
|
2318
2576
|
function fetchNextCommits(ctx) {
|
|
2319
2577
|
const commitsByDate = fetchCommitsByDate(
|
|
@@ -2330,8 +2588,8 @@ function showResult(ctx, found) {
|
|
|
2330
2588
|
}
|
|
2331
2589
|
displayNextEntry(ctx, found.targetDate, found.commits);
|
|
2332
2590
|
}
|
|
2333
|
-
function next(
|
|
2334
|
-
const ctx = buildContext(
|
|
2591
|
+
function next(options2) {
|
|
2592
|
+
const ctx = buildContext(options2);
|
|
2335
2593
|
showResult(ctx, fetchNextCommits(ctx));
|
|
2336
2594
|
}
|
|
2337
2595
|
|
|
@@ -2387,9 +2645,12 @@ function registerDevlog(program2) {
|
|
|
2387
2645
|
devlogCommand.command("skip <date>").description("Add a date (YYYY-MM-DD) to the skip list").action(skip);
|
|
2388
2646
|
}
|
|
2389
2647
|
|
|
2648
|
+
// src/commands/prs/fixed.ts
|
|
2649
|
+
import { execSync as execSync16 } from "child_process";
|
|
2650
|
+
|
|
2390
2651
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
2391
|
-
import { execSync as
|
|
2392
|
-
import { unlinkSync as unlinkSync3, writeFileSync as
|
|
2652
|
+
import { execSync as execSync15 } from "child_process";
|
|
2653
|
+
import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync10 } from "fs";
|
|
2393
2654
|
import { tmpdir } from "os";
|
|
2394
2655
|
import { join as join10 } from "path";
|
|
2395
2656
|
|
|
@@ -2417,7 +2678,7 @@ function deleteCommentsCache(prNumber) {
|
|
|
2417
2678
|
}
|
|
2418
2679
|
|
|
2419
2680
|
// src/commands/prs/shared.ts
|
|
2420
|
-
import { execSync as
|
|
2681
|
+
import { execSync as execSync14 } from "child_process";
|
|
2421
2682
|
function isGhNotInstalled(error) {
|
|
2422
2683
|
if (error instanceof Error) {
|
|
2423
2684
|
const msg = error.message.toLowerCase();
|
|
@@ -2433,14 +2694,14 @@ function isNotFound(error) {
|
|
|
2433
2694
|
}
|
|
2434
2695
|
function getRepoInfo() {
|
|
2435
2696
|
const repoInfo = JSON.parse(
|
|
2436
|
-
|
|
2697
|
+
execSync14("gh repo view --json owner,name", { encoding: "utf-8" })
|
|
2437
2698
|
);
|
|
2438
2699
|
return { org: repoInfo.owner.login, repo: repoInfo.name };
|
|
2439
2700
|
}
|
|
2440
2701
|
function getCurrentPrNumber() {
|
|
2441
2702
|
try {
|
|
2442
2703
|
const prInfo = JSON.parse(
|
|
2443
|
-
|
|
2704
|
+
execSync14("gh pr view --json number", { encoding: "utf-8" })
|
|
2444
2705
|
);
|
|
2445
2706
|
return prInfo.number;
|
|
2446
2707
|
} catch (error) {
|
|
@@ -2454,7 +2715,7 @@ function getCurrentPrNumber() {
|
|
|
2454
2715
|
|
|
2455
2716
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
2456
2717
|
function replyToComment(org, repo, prNumber, commentId, message) {
|
|
2457
|
-
|
|
2718
|
+
execSync15(
|
|
2458
2719
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, '\\"')}" -F in_reply_to=${commentId}`,
|
|
2459
2720
|
{ stdio: "inherit" }
|
|
2460
2721
|
);
|
|
@@ -2462,9 +2723,9 @@ function replyToComment(org, repo, prNumber, commentId, message) {
|
|
|
2462
2723
|
function resolveThread(threadId) {
|
|
2463
2724
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
2464
2725
|
const queryFile = join10(tmpdir(), `gh-mutation-${Date.now()}.graphql`);
|
|
2465
|
-
|
|
2726
|
+
writeFileSync10(queryFile, mutation);
|
|
2466
2727
|
try {
|
|
2467
|
-
|
|
2728
|
+
execSync15(
|
|
2468
2729
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
2469
2730
|
{ stdio: "inherit" }
|
|
2470
2731
|
);
|
|
@@ -2514,11 +2775,22 @@ function resolveCommentWithReply(commentId, message) {
|
|
|
2514
2775
|
}
|
|
2515
2776
|
|
|
2516
2777
|
// src/commands/prs/fixed.ts
|
|
2778
|
+
function verifySha(sha) {
|
|
2779
|
+
try {
|
|
2780
|
+
return execSync16(`git rev-parse --verify ${sha}`, {
|
|
2781
|
+
encoding: "utf-8"
|
|
2782
|
+
}).trim();
|
|
2783
|
+
} catch {
|
|
2784
|
+
console.error(`Error: '${sha}' is not a valid commit in this repository.`);
|
|
2785
|
+
process.exit(1);
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2517
2788
|
function fixed(commentId, sha) {
|
|
2518
2789
|
try {
|
|
2790
|
+
const fullSha = verifySha(sha);
|
|
2519
2791
|
const { org, repo } = getRepoInfo();
|
|
2520
2792
|
const repoUrl = `https://github.com/${org}/${repo}`;
|
|
2521
|
-
const message = `Fixed in [${
|
|
2793
|
+
const message = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
|
|
2522
2794
|
resolveCommentWithReply(commentId, message);
|
|
2523
2795
|
} catch (error) {
|
|
2524
2796
|
if (isGhNotInstalled(error)) {
|
|
@@ -2531,7 +2803,7 @@ function fixed(commentId, sha) {
|
|
|
2531
2803
|
}
|
|
2532
2804
|
|
|
2533
2805
|
// src/commands/prs/listComments/index.ts
|
|
2534
|
-
import { existsSync as existsSync13, mkdirSync as
|
|
2806
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync4, writeFileSync as writeFileSync12 } from "fs";
|
|
2535
2807
|
import { join as join12 } from "path";
|
|
2536
2808
|
import { stringify } from "yaml";
|
|
2537
2809
|
|
|
@@ -2541,16 +2813,16 @@ function isClaudeCode() {
|
|
|
2541
2813
|
}
|
|
2542
2814
|
|
|
2543
2815
|
// src/commands/prs/fetchThreadIds.ts
|
|
2544
|
-
import { execSync as
|
|
2545
|
-
import { unlinkSync as unlinkSync4, writeFileSync as
|
|
2816
|
+
import { execSync as execSync17 } from "child_process";
|
|
2817
|
+
import { unlinkSync as unlinkSync4, writeFileSync as writeFileSync11 } from "fs";
|
|
2546
2818
|
import { tmpdir as tmpdir2 } from "os";
|
|
2547
2819
|
import { join as join11 } from "path";
|
|
2548
2820
|
var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
|
|
2549
2821
|
function fetchThreadIds(org, repo, prNumber) {
|
|
2550
2822
|
const queryFile = join11(tmpdir2(), `gh-query-${Date.now()}.graphql`);
|
|
2551
|
-
|
|
2823
|
+
writeFileSync11(queryFile, THREAD_QUERY);
|
|
2552
2824
|
try {
|
|
2553
|
-
const result =
|
|
2825
|
+
const result = execSync17(
|
|
2554
2826
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
2555
2827
|
{ encoding: "utf-8" }
|
|
2556
2828
|
);
|
|
@@ -2572,9 +2844,9 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
2572
2844
|
}
|
|
2573
2845
|
|
|
2574
2846
|
// src/commands/prs/listComments/fetchReviewComments.ts
|
|
2575
|
-
import { execSync as
|
|
2847
|
+
import { execSync as execSync18 } from "child_process";
|
|
2576
2848
|
function fetchJson(endpoint) {
|
|
2577
|
-
const result =
|
|
2849
|
+
const result = execSync18(`gh api ${endpoint}`, { encoding: "utf-8" });
|
|
2578
2850
|
if (!result.trim()) return [];
|
|
2579
2851
|
return JSON.parse(result);
|
|
2580
2852
|
}
|
|
@@ -2652,7 +2924,7 @@ function printComments(comments) {
|
|
|
2652
2924
|
function writeCommentsCache(prNumber, comments) {
|
|
2653
2925
|
const assistDir = join12(process.cwd(), ".assist");
|
|
2654
2926
|
if (!existsSync13(assistDir)) {
|
|
2655
|
-
|
|
2927
|
+
mkdirSync4(assistDir, { recursive: true });
|
|
2656
2928
|
}
|
|
2657
2929
|
const cacheData = {
|
|
2658
2930
|
prNumber,
|
|
@@ -2660,7 +2932,7 @@ function writeCommentsCache(prNumber, comments) {
|
|
|
2660
2932
|
comments
|
|
2661
2933
|
};
|
|
2662
2934
|
const cachePath = join12(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
2663
|
-
|
|
2935
|
+
writeFileSync12(cachePath, stringify(cacheData));
|
|
2664
2936
|
}
|
|
2665
2937
|
function handleKnownErrors(error) {
|
|
2666
2938
|
if (isGhNotInstalled(error)) {
|
|
@@ -2700,7 +2972,7 @@ async function listComments() {
|
|
|
2700
2972
|
}
|
|
2701
2973
|
|
|
2702
2974
|
// src/commands/prs/prs/index.ts
|
|
2703
|
-
import { execSync as
|
|
2975
|
+
import { execSync as execSync19 } from "child_process";
|
|
2704
2976
|
|
|
2705
2977
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
2706
2978
|
import enquirer4 from "enquirer";
|
|
@@ -2803,10 +3075,10 @@ async function displayPaginated(pullRequests) {
|
|
|
2803
3075
|
}
|
|
2804
3076
|
|
|
2805
3077
|
// src/commands/prs/prs/index.ts
|
|
2806
|
-
async function prs(
|
|
2807
|
-
const state =
|
|
3078
|
+
async function prs(options2) {
|
|
3079
|
+
const state = options2.open ? "open" : options2.closed ? "closed" : "all";
|
|
2808
3080
|
try {
|
|
2809
|
-
const result =
|
|
3081
|
+
const result = execSync19(
|
|
2810
3082
|
`gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100`,
|
|
2811
3083
|
{ encoding: "utf-8" }
|
|
2812
3084
|
);
|
|
@@ -2829,7 +3101,7 @@ async function prs(options) {
|
|
|
2829
3101
|
}
|
|
2830
3102
|
|
|
2831
3103
|
// src/commands/prs/wontfix.ts
|
|
2832
|
-
import { execSync as
|
|
3104
|
+
import { execSync as execSync20 } from "child_process";
|
|
2833
3105
|
function validateReason(reason) {
|
|
2834
3106
|
const lowerReason = reason.toLowerCase();
|
|
2835
3107
|
if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
|
|
@@ -2846,7 +3118,7 @@ function validateShaReferences(reason) {
|
|
|
2846
3118
|
const invalidShas = [];
|
|
2847
3119
|
for (const sha of shas) {
|
|
2848
3120
|
try {
|
|
2849
|
-
|
|
3121
|
+
execSync20(`git cat-file -t ${sha}`, { stdio: "pipe" });
|
|
2850
3122
|
} catch {
|
|
2851
3123
|
invalidShas.push(sha);
|
|
2852
3124
|
}
|
|
@@ -2888,8 +3160,8 @@ function registerPrs(program2) {
|
|
|
2888
3160
|
}
|
|
2889
3161
|
|
|
2890
3162
|
// src/commands/refactor/check/index.ts
|
|
2891
|
-
import { spawn as
|
|
2892
|
-
import * as
|
|
3163
|
+
import { spawn as spawn3 } from "child_process";
|
|
3164
|
+
import * as path16 from "path";
|
|
2893
3165
|
|
|
2894
3166
|
// src/commands/refactor/logViolations.ts
|
|
2895
3167
|
import chalk36 from "chalk";
|
|
@@ -2947,7 +3219,7 @@ Refactor check failed:
|
|
|
2947
3219
|
}
|
|
2948
3220
|
|
|
2949
3221
|
// src/commands/refactor/check/getViolations/index.ts
|
|
2950
|
-
import { execSync as
|
|
3222
|
+
import { execSync as execSync21 } from "child_process";
|
|
2951
3223
|
import fs15 from "fs";
|
|
2952
3224
|
import { minimatch as minimatch2 } from "minimatch";
|
|
2953
3225
|
|
|
@@ -2991,31 +3263,31 @@ function countLines(filePath) {
|
|
|
2991
3263
|
const content = fs15.readFileSync(filePath, "utf-8");
|
|
2992
3264
|
return content.split("\n").length;
|
|
2993
3265
|
}
|
|
2994
|
-
function getGitFiles(
|
|
2995
|
-
if (!
|
|
3266
|
+
function getGitFiles(options2) {
|
|
3267
|
+
if (!options2.modified && !options2.staged && !options2.unstaged) {
|
|
2996
3268
|
return null;
|
|
2997
3269
|
}
|
|
2998
3270
|
const files = /* @__PURE__ */ new Set();
|
|
2999
|
-
if (
|
|
3000
|
-
const staged =
|
|
3271
|
+
if (options2.staged || options2.modified) {
|
|
3272
|
+
const staged = execSync21("git diff --cached --name-only", {
|
|
3001
3273
|
encoding: "utf-8"
|
|
3002
3274
|
});
|
|
3003
3275
|
for (const file of staged.trim().split("\n").filter(Boolean)) {
|
|
3004
3276
|
files.add(file);
|
|
3005
3277
|
}
|
|
3006
3278
|
}
|
|
3007
|
-
if (
|
|
3008
|
-
const unstaged =
|
|
3279
|
+
if (options2.unstaged || options2.modified) {
|
|
3280
|
+
const unstaged = execSync21("git diff --name-only", { encoding: "utf-8" });
|
|
3009
3281
|
for (const file of unstaged.trim().split("\n").filter(Boolean)) {
|
|
3010
3282
|
files.add(file);
|
|
3011
3283
|
}
|
|
3012
3284
|
}
|
|
3013
3285
|
return files;
|
|
3014
3286
|
}
|
|
3015
|
-
function getViolations(pattern2,
|
|
3287
|
+
function getViolations(pattern2, options2 = {}, maxLines = DEFAULT_MAX_LINES) {
|
|
3016
3288
|
let sourceFiles = findSourceFiles("src", { includeTests: false });
|
|
3017
3289
|
const ignoredFiles = getIgnoredFiles();
|
|
3018
|
-
const gitFiles = getGitFiles(
|
|
3290
|
+
const gitFiles = getGitFiles(options2);
|
|
3019
3291
|
if (pattern2) {
|
|
3020
3292
|
sourceFiles = sourceFiles.filter((f) => minimatch2(f, pattern2));
|
|
3021
3293
|
}
|
|
@@ -3034,9 +3306,9 @@ function getViolations(pattern2, options = {}, maxLines = DEFAULT_MAX_LINES) {
|
|
|
3034
3306
|
}
|
|
3035
3307
|
|
|
3036
3308
|
// src/commands/refactor/check/index.ts
|
|
3037
|
-
function
|
|
3038
|
-
return new Promise((
|
|
3039
|
-
const child =
|
|
3309
|
+
function runScript2(script, cwd) {
|
|
3310
|
+
return new Promise((resolve2) => {
|
|
3311
|
+
const child = spawn3("npm", ["run", script], {
|
|
3040
3312
|
stdio: "pipe",
|
|
3041
3313
|
shell: true,
|
|
3042
3314
|
cwd
|
|
@@ -3049,7 +3321,7 @@ function runScript(script, cwd) {
|
|
|
3049
3321
|
output += data.toString();
|
|
3050
3322
|
});
|
|
3051
3323
|
child.on("close", (code) => {
|
|
3052
|
-
|
|
3324
|
+
resolve2({ script, code: code ?? 1, output });
|
|
3053
3325
|
});
|
|
3054
3326
|
});
|
|
3055
3327
|
}
|
|
@@ -3066,9 +3338,9 @@ ${failed.length} verify script(s) failed:`);
|
|
|
3066
3338
|
async function runVerifyQuietly() {
|
|
3067
3339
|
const result = findPackageJsonWithVerifyScripts(process.cwd());
|
|
3068
3340
|
if (!result) return true;
|
|
3069
|
-
const packageDir =
|
|
3341
|
+
const packageDir = path16.dirname(result.packageJsonPath);
|
|
3070
3342
|
const results = await Promise.all(
|
|
3071
|
-
result.verifyScripts.map((script) =>
|
|
3343
|
+
result.verifyScripts.map((script) => runScript2(script, packageDir))
|
|
3072
3344
|
);
|
|
3073
3345
|
const failed = results.filter((r) => r.code !== 0);
|
|
3074
3346
|
if (failed.length > 0) {
|
|
@@ -3077,13 +3349,13 @@ async function runVerifyQuietly() {
|
|
|
3077
3349
|
}
|
|
3078
3350
|
return true;
|
|
3079
3351
|
}
|
|
3080
|
-
async function check(pattern2,
|
|
3352
|
+
async function check(pattern2, options2) {
|
|
3081
3353
|
const verifyPassed = await runVerifyQuietly();
|
|
3082
3354
|
if (!verifyPassed) {
|
|
3083
3355
|
process.exit(1);
|
|
3084
3356
|
}
|
|
3085
|
-
const maxLines =
|
|
3086
|
-
const violations = getViolations(pattern2,
|
|
3357
|
+
const maxLines = options2.maxLines ?? DEFAULT_MAX_LINES;
|
|
3358
|
+
const violations = getViolations(pattern2, options2, maxLines);
|
|
3087
3359
|
violations.sort((a, b) => b.lines - a.lines);
|
|
3088
3360
|
logViolations(violations, maxLines);
|
|
3089
3361
|
if (violations.length > 0) {
|
|
@@ -3120,11 +3392,11 @@ function ignore(file) {
|
|
|
3120
3392
|
}
|
|
3121
3393
|
|
|
3122
3394
|
// src/commands/refactor/restructure/index.ts
|
|
3123
|
-
import
|
|
3395
|
+
import path25 from "path";
|
|
3124
3396
|
import chalk40 from "chalk";
|
|
3125
3397
|
|
|
3126
3398
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
3127
|
-
import
|
|
3399
|
+
import path17 from "path";
|
|
3128
3400
|
import ts7 from "typescript";
|
|
3129
3401
|
|
|
3130
3402
|
// src/commands/refactor/restructure/buildImportGraph/getImportSpecifiers.ts
|
|
@@ -3151,7 +3423,7 @@ function loadParsedConfig(tsConfigPath) {
|
|
|
3151
3423
|
return ts7.parseJsonConfigFileContent(
|
|
3152
3424
|
configFile.config,
|
|
3153
3425
|
ts7.sys,
|
|
3154
|
-
|
|
3426
|
+
path17.dirname(tsConfigPath)
|
|
3155
3427
|
);
|
|
3156
3428
|
}
|
|
3157
3429
|
function addToSetMap(map, key, value) {
|
|
@@ -3162,12 +3434,12 @@ function addToSetMap(map, key, value) {
|
|
|
3162
3434
|
}
|
|
3163
3435
|
set.add(value);
|
|
3164
3436
|
}
|
|
3165
|
-
function resolveImport(specifier, filePath,
|
|
3437
|
+
function resolveImport(specifier, filePath, options2) {
|
|
3166
3438
|
if (!specifier.startsWith(".")) return null;
|
|
3167
|
-
const resolved = ts7.resolveModuleName(specifier, filePath,
|
|
3439
|
+
const resolved = ts7.resolveModuleName(specifier, filePath, options2, ts7.sys);
|
|
3168
3440
|
const resolvedPath = resolved.resolvedModule?.resolvedFileName;
|
|
3169
3441
|
if (!resolvedPath || resolvedPath.includes("node_modules")) return null;
|
|
3170
|
-
return
|
|
3442
|
+
return path17.resolve(resolvedPath);
|
|
3171
3443
|
}
|
|
3172
3444
|
function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
3173
3445
|
const parsed = loadParsedConfig(tsConfigPath);
|
|
@@ -3176,7 +3448,7 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
|
3176
3448
|
const importedBy = /* @__PURE__ */ new Map();
|
|
3177
3449
|
const imports = /* @__PURE__ */ new Map();
|
|
3178
3450
|
for (const sourceFile of program2.getSourceFiles()) {
|
|
3179
|
-
const filePath =
|
|
3451
|
+
const filePath = path17.resolve(sourceFile.fileName);
|
|
3180
3452
|
if (filePath.includes("node_modules")) continue;
|
|
3181
3453
|
for (const specifier of getImportSpecifiers(sourceFile)) {
|
|
3182
3454
|
const absTarget = resolveImport(specifier, filePath, parsed.options);
|
|
@@ -3190,12 +3462,12 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
|
3190
3462
|
}
|
|
3191
3463
|
|
|
3192
3464
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
3193
|
-
import
|
|
3465
|
+
import path18 from "path";
|
|
3194
3466
|
function clusterDirectories(graph) {
|
|
3195
3467
|
const dirImportedBy = /* @__PURE__ */ new Map();
|
|
3196
3468
|
for (const edge of graph.edges) {
|
|
3197
|
-
const sourceDir =
|
|
3198
|
-
const targetDir =
|
|
3469
|
+
const sourceDir = path18.dirname(edge.source);
|
|
3470
|
+
const targetDir = path18.dirname(edge.target);
|
|
3199
3471
|
if (sourceDir === targetDir) continue;
|
|
3200
3472
|
if (!graph.files.has(edge.target)) continue;
|
|
3201
3473
|
const existing = dirImportedBy.get(targetDir) ?? /* @__PURE__ */ new Set();
|
|
@@ -3223,20 +3495,20 @@ function clusterDirectories(graph) {
|
|
|
3223
3495
|
return clusters;
|
|
3224
3496
|
}
|
|
3225
3497
|
function isAncestor(ancestor, descendant) {
|
|
3226
|
-
const rel =
|
|
3498
|
+
const rel = path18.relative(ancestor, descendant);
|
|
3227
3499
|
return !rel.startsWith("..") && rel !== "";
|
|
3228
3500
|
}
|
|
3229
3501
|
|
|
3230
3502
|
// src/commands/refactor/restructure/clusterFiles.ts
|
|
3231
|
-
import
|
|
3503
|
+
import path19 from "path";
|
|
3232
3504
|
function findRootParent(file, importedBy, visited) {
|
|
3233
3505
|
const importers = importedBy.get(file);
|
|
3234
3506
|
if (!importers || importers.size !== 1) return file;
|
|
3235
3507
|
const parent = [...importers][0];
|
|
3236
|
-
const parentDir =
|
|
3237
|
-
const fileDir =
|
|
3508
|
+
const parentDir = path19.dirname(parent);
|
|
3509
|
+
const fileDir = path19.dirname(file);
|
|
3238
3510
|
if (parentDir !== fileDir) return file;
|
|
3239
|
-
if (
|
|
3511
|
+
if (path19.basename(parent, path19.extname(parent)) === "index") return file;
|
|
3240
3512
|
if (visited.has(parent)) return file;
|
|
3241
3513
|
visited.add(parent);
|
|
3242
3514
|
return findRootParent(parent, importedBy, visited);
|
|
@@ -3244,16 +3516,16 @@ function findRootParent(file, importedBy, visited) {
|
|
|
3244
3516
|
function clusterFiles(graph) {
|
|
3245
3517
|
const clusters = /* @__PURE__ */ new Map();
|
|
3246
3518
|
for (const file of graph.files) {
|
|
3247
|
-
const
|
|
3248
|
-
if (
|
|
3519
|
+
const basename7 = path19.basename(file, path19.extname(file));
|
|
3520
|
+
if (basename7 === "index") continue;
|
|
3249
3521
|
const importers = graph.importedBy.get(file);
|
|
3250
3522
|
if (!importers || importers.size !== 1) continue;
|
|
3251
3523
|
const parent = [...importers][0];
|
|
3252
3524
|
if (!graph.files.has(parent)) continue;
|
|
3253
|
-
const parentDir =
|
|
3254
|
-
const fileDir =
|
|
3525
|
+
const parentDir = path19.dirname(parent);
|
|
3526
|
+
const fileDir = path19.dirname(file);
|
|
3255
3527
|
if (parentDir !== fileDir) continue;
|
|
3256
|
-
const parentBasename =
|
|
3528
|
+
const parentBasename = path19.basename(parent, path19.extname(parent));
|
|
3257
3529
|
if (parentBasename === "index") continue;
|
|
3258
3530
|
const root = findRootParent(parent, graph.importedBy, /* @__PURE__ */ new Set([file]));
|
|
3259
3531
|
if (!root || root === file) continue;
|
|
@@ -3265,7 +3537,7 @@ function clusterFiles(graph) {
|
|
|
3265
3537
|
}
|
|
3266
3538
|
|
|
3267
3539
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
3268
|
-
import
|
|
3540
|
+
import path20 from "path";
|
|
3269
3541
|
|
|
3270
3542
|
// src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
|
|
3271
3543
|
import fs17 from "fs";
|
|
@@ -3319,7 +3591,7 @@ function normalizeSpecifier(rel) {
|
|
|
3319
3591
|
);
|
|
3320
3592
|
}
|
|
3321
3593
|
function computeSpecifier(fromFile, toFile) {
|
|
3322
|
-
return normalizeSpecifier(
|
|
3594
|
+
return normalizeSpecifier(path20.relative(path20.dirname(fromFile), toFile));
|
|
3323
3595
|
}
|
|
3324
3596
|
function isAffected(edge, moveMap) {
|
|
3325
3597
|
return moveMap.has(edge.target) || moveMap.has(edge.source);
|
|
@@ -3363,10 +3635,10 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
3363
3635
|
}
|
|
3364
3636
|
|
|
3365
3637
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
3366
|
-
import
|
|
3638
|
+
import path21 from "path";
|
|
3367
3639
|
import chalk38 from "chalk";
|
|
3368
3640
|
function relPath(filePath) {
|
|
3369
|
-
return
|
|
3641
|
+
return path21.relative(process.cwd(), filePath);
|
|
3370
3642
|
}
|
|
3371
3643
|
function displayMoves(plan) {
|
|
3372
3644
|
if (plan.moves.length === 0) return;
|
|
@@ -3416,33 +3688,33 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
|
|
|
3416
3688
|
|
|
3417
3689
|
// src/commands/refactor/restructure/executePlan.ts
|
|
3418
3690
|
import fs18 from "fs";
|
|
3419
|
-
import
|
|
3691
|
+
import path22 from "path";
|
|
3420
3692
|
import chalk39 from "chalk";
|
|
3421
3693
|
function executePlan(plan) {
|
|
3422
3694
|
const updatedContents = applyRewrites(plan.rewrites);
|
|
3423
3695
|
for (const [file, content] of updatedContents) {
|
|
3424
3696
|
fs18.writeFileSync(file, content, "utf-8");
|
|
3425
3697
|
console.log(
|
|
3426
|
-
chalk39.cyan(` Rewrote imports in ${
|
|
3698
|
+
chalk39.cyan(` Rewrote imports in ${path22.relative(process.cwd(), file)}`)
|
|
3427
3699
|
);
|
|
3428
3700
|
}
|
|
3429
3701
|
for (const dir of plan.newDirectories) {
|
|
3430
3702
|
fs18.mkdirSync(dir, { recursive: true });
|
|
3431
|
-
console.log(chalk39.green(` Created ${
|
|
3703
|
+
console.log(chalk39.green(` Created ${path22.relative(process.cwd(), dir)}/`));
|
|
3432
3704
|
}
|
|
3433
3705
|
for (const move of plan.moves) {
|
|
3434
|
-
const targetDir =
|
|
3706
|
+
const targetDir = path22.dirname(move.to);
|
|
3435
3707
|
if (!fs18.existsSync(targetDir)) {
|
|
3436
3708
|
fs18.mkdirSync(targetDir, { recursive: true });
|
|
3437
3709
|
}
|
|
3438
3710
|
fs18.renameSync(move.from, move.to);
|
|
3439
3711
|
console.log(
|
|
3440
3712
|
chalk39.white(
|
|
3441
|
-
` Moved ${
|
|
3713
|
+
` Moved ${path22.relative(process.cwd(), move.from)} \u2192 ${path22.relative(process.cwd(), move.to)}`
|
|
3442
3714
|
)
|
|
3443
3715
|
);
|
|
3444
3716
|
}
|
|
3445
|
-
removeEmptyDirectories(plan.moves.map((m) =>
|
|
3717
|
+
removeEmptyDirectories(plan.moves.map((m) => path22.dirname(m.from)));
|
|
3446
3718
|
}
|
|
3447
3719
|
function removeEmptyDirectories(dirs) {
|
|
3448
3720
|
const unique = [...new Set(dirs)];
|
|
@@ -3453,7 +3725,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
3453
3725
|
fs18.rmdirSync(dir);
|
|
3454
3726
|
console.log(
|
|
3455
3727
|
chalk39.dim(
|
|
3456
|
-
` Removed empty directory ${
|
|
3728
|
+
` Removed empty directory ${path22.relative(process.cwd(), dir)}`
|
|
3457
3729
|
)
|
|
3458
3730
|
);
|
|
3459
3731
|
}
|
|
@@ -3462,13 +3734,13 @@ function removeEmptyDirectories(dirs) {
|
|
|
3462
3734
|
|
|
3463
3735
|
// src/commands/refactor/restructure/planFileMoves/index.ts
|
|
3464
3736
|
import fs20 from "fs";
|
|
3465
|
-
import
|
|
3737
|
+
import path24 from "path";
|
|
3466
3738
|
|
|
3467
3739
|
// src/commands/refactor/restructure/planFileMoves/planDirectoryMoves.ts
|
|
3468
3740
|
import fs19 from "fs";
|
|
3469
|
-
import
|
|
3741
|
+
import path23 from "path";
|
|
3470
3742
|
function collectEntry(results, dir, entry) {
|
|
3471
|
-
const full =
|
|
3743
|
+
const full = path23.join(dir, entry.name);
|
|
3472
3744
|
const items = entry.isDirectory() ? listFilesRecursive(full) : [full];
|
|
3473
3745
|
results.push(...items);
|
|
3474
3746
|
}
|
|
@@ -3482,15 +3754,15 @@ function listFilesRecursive(dir) {
|
|
|
3482
3754
|
}
|
|
3483
3755
|
function addDirectoryFileMoves(moves, childDir, newLocation, reason) {
|
|
3484
3756
|
for (const file of listFilesRecursive(childDir)) {
|
|
3485
|
-
const rel =
|
|
3486
|
-
moves.push({ from: file, to:
|
|
3757
|
+
const rel = path23.relative(childDir, file);
|
|
3758
|
+
moves.push({ from: file, to: path23.join(newLocation, rel), reason });
|
|
3487
3759
|
}
|
|
3488
3760
|
}
|
|
3489
3761
|
function resolveChildDest(parentDir, childDir) {
|
|
3490
|
-
return
|
|
3762
|
+
return path23.join(parentDir, path23.basename(childDir));
|
|
3491
3763
|
}
|
|
3492
3764
|
function childMoveReason(parentDir) {
|
|
3493
|
-
return `Directory only imported from ${
|
|
3765
|
+
return `Directory only imported from ${path23.basename(parentDir)}/`;
|
|
3494
3766
|
}
|
|
3495
3767
|
function registerDirectoryMove(result, childDir, dest, parentDir) {
|
|
3496
3768
|
result.directories.push(dest);
|
|
@@ -3518,7 +3790,7 @@ function emptyResult() {
|
|
|
3518
3790
|
return { moves: [], directories: [], warnings: [] };
|
|
3519
3791
|
}
|
|
3520
3792
|
function childMoveData(child, newDir, parentBase) {
|
|
3521
|
-
const to =
|
|
3793
|
+
const to = path24.join(newDir, path24.basename(child));
|
|
3522
3794
|
return { from: child, to, reason: `Only imported by ${parentBase}` };
|
|
3523
3795
|
}
|
|
3524
3796
|
function addChildMoves(moves, children, newDir, parentBase) {
|
|
@@ -3531,15 +3803,15 @@ function checkDirConflict(result, label, dir) {
|
|
|
3531
3803
|
return true;
|
|
3532
3804
|
}
|
|
3533
3805
|
function getBaseName(filePath) {
|
|
3534
|
-
return
|
|
3806
|
+
return path24.basename(filePath, path24.extname(filePath));
|
|
3535
3807
|
}
|
|
3536
3808
|
function resolveClusterDir(parent) {
|
|
3537
|
-
return
|
|
3809
|
+
return path24.join(path24.dirname(parent), getBaseName(parent));
|
|
3538
3810
|
}
|
|
3539
3811
|
function createParentMove(parent, newDir) {
|
|
3540
3812
|
return {
|
|
3541
3813
|
from: parent,
|
|
3542
|
-
to:
|
|
3814
|
+
to: path24.join(newDir, `index${path24.extname(parent)}`),
|
|
3543
3815
|
reason: `Main module of new ${getBaseName(parent)}/ directory`
|
|
3544
3816
|
};
|
|
3545
3817
|
}
|
|
@@ -3563,7 +3835,7 @@ function planFileMoves(clusters) {
|
|
|
3563
3835
|
|
|
3564
3836
|
// src/commands/refactor/restructure/index.ts
|
|
3565
3837
|
function buildPlan(candidateFiles, tsConfigPath) {
|
|
3566
|
-
const candidates = new Set(candidateFiles.map((f) =>
|
|
3838
|
+
const candidates = new Set(candidateFiles.map((f) => path25.resolve(f)));
|
|
3567
3839
|
const graph = buildImportGraph(candidates, tsConfigPath);
|
|
3568
3840
|
const allProjectFiles = /* @__PURE__ */ new Set([
|
|
3569
3841
|
...graph.importedBy.keys(),
|
|
@@ -3579,21 +3851,21 @@ function buildPlan(candidateFiles, tsConfigPath) {
|
|
|
3579
3851
|
const rewrites = computeRewrites(moves, graph.edges, allProjectFiles);
|
|
3580
3852
|
return { moves, rewrites, newDirectories: directories, warnings };
|
|
3581
3853
|
}
|
|
3582
|
-
async function restructure(pattern2,
|
|
3854
|
+
async function restructure(pattern2, options2 = {}) {
|
|
3583
3855
|
const targetPattern = pattern2 ?? "src";
|
|
3584
3856
|
const files = findSourceFiles2(targetPattern);
|
|
3585
3857
|
if (files.length === 0) {
|
|
3586
3858
|
console.log(chalk40.yellow("No files found matching pattern"));
|
|
3587
3859
|
return;
|
|
3588
3860
|
}
|
|
3589
|
-
const tsConfigPath =
|
|
3861
|
+
const tsConfigPath = path25.resolve("tsconfig.json");
|
|
3590
3862
|
const plan = buildPlan(files, tsConfigPath);
|
|
3591
3863
|
if (plan.moves.length === 0) {
|
|
3592
3864
|
console.log(chalk40.green("No restructuring needed"));
|
|
3593
3865
|
return;
|
|
3594
3866
|
}
|
|
3595
3867
|
displayPlan(plan);
|
|
3596
|
-
if (
|
|
3868
|
+
if (options2.apply) {
|
|
3597
3869
|
console.log(chalk40.bold("\nApplying changes..."));
|
|
3598
3870
|
executePlan(plan);
|
|
3599
3871
|
console.log(chalk40.green("\nRestructuring complete"));
|
|
@@ -3622,7 +3894,7 @@ function registerRefactor(program2) {
|
|
|
3622
3894
|
|
|
3623
3895
|
// src/commands/transcript/shared.ts
|
|
3624
3896
|
import { existsSync as existsSync14, readdirSync as readdirSync2, statSync } from "fs";
|
|
3625
|
-
import { basename as
|
|
3897
|
+
import { basename as basename4, join as join13, relative } from "path";
|
|
3626
3898
|
import * as readline2 from "readline";
|
|
3627
3899
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
3628
3900
|
function getDatePrefix(daysOffset = 0) {
|
|
@@ -3653,7 +3925,7 @@ function toFileInfo(baseDir, fullPath) {
|
|
|
3653
3925
|
return {
|
|
3654
3926
|
absolutePath: fullPath,
|
|
3655
3927
|
relativePath: relative(baseDir, fullPath),
|
|
3656
|
-
filename:
|
|
3928
|
+
filename: basename4(fullPath)
|
|
3657
3929
|
};
|
|
3658
3930
|
}
|
|
3659
3931
|
function findVttFilesRecursive(dir, baseDir = dir) {
|
|
@@ -3663,7 +3935,7 @@ function findMdFilesRecursive(dir, baseDir = dir) {
|
|
|
3663
3935
|
return collectFiles(dir, ".md").map((f) => toFileInfo(baseDir, f));
|
|
3664
3936
|
}
|
|
3665
3937
|
function getTranscriptBaseName(transcriptFile) {
|
|
3666
|
-
return
|
|
3938
|
+
return basename4(transcriptFile, ".md").replace(/ Transcription$/, "");
|
|
3667
3939
|
}
|
|
3668
3940
|
function createReadlineInterface() {
|
|
3669
3941
|
return readline2.createInterface({
|
|
@@ -3672,9 +3944,9 @@ function createReadlineInterface() {
|
|
|
3672
3944
|
});
|
|
3673
3945
|
}
|
|
3674
3946
|
function askQuestion(rl, question) {
|
|
3675
|
-
return new Promise((
|
|
3947
|
+
return new Promise((resolve2) => {
|
|
3676
3948
|
rl.question(question, (answer) => {
|
|
3677
|
-
|
|
3949
|
+
resolve2(answer.trim());
|
|
3678
3950
|
});
|
|
3679
3951
|
});
|
|
3680
3952
|
}
|
|
@@ -3737,7 +4009,7 @@ async function configure() {
|
|
|
3737
4009
|
import { existsSync as existsSync16 } from "fs";
|
|
3738
4010
|
|
|
3739
4011
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
3740
|
-
import { dirname as
|
|
4012
|
+
import { dirname as dirname11, join as join15 } from "path";
|
|
3741
4013
|
|
|
3742
4014
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
3743
4015
|
import { renameSync } from "fs";
|
|
@@ -3787,11 +4059,11 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
3787
4059
|
for (let i = 0; i < vttFiles.length; i++) {
|
|
3788
4060
|
const vttFile = vttFiles[i];
|
|
3789
4061
|
if (!isValidDatePrefix(vttFile.filename)) {
|
|
3790
|
-
const vttFileDir =
|
|
4062
|
+
const vttFileDir = dirname11(vttFile.absolutePath);
|
|
3791
4063
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
3792
4064
|
if (newFilename) {
|
|
3793
4065
|
const newRelativePath = join15(
|
|
3794
|
-
|
|
4066
|
+
dirname11(vttFile.relativePath),
|
|
3795
4067
|
newFilename
|
|
3796
4068
|
);
|
|
3797
4069
|
vttFiles[i] = {
|
|
@@ -3808,8 +4080,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
3808
4080
|
}
|
|
3809
4081
|
|
|
3810
4082
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
3811
|
-
import { existsSync as existsSync15, mkdirSync as
|
|
3812
|
-
import { basename as
|
|
4083
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync13 } from "fs";
|
|
4084
|
+
import { basename as basename5, dirname as dirname12, join as join16 } from "path";
|
|
3813
4085
|
|
|
3814
4086
|
// src/commands/transcript/cleanText.ts
|
|
3815
4087
|
function cleanText(text) {
|
|
@@ -3832,7 +4104,7 @@ function cleanText(text) {
|
|
|
3832
4104
|
return cleaned.join(" ").replace(/\s+/g, " ").trim();
|
|
3833
4105
|
}
|
|
3834
4106
|
|
|
3835
|
-
// src/commands/transcript/format/parseVtt/deduplicateCues/removeSubstringDuplicates.ts
|
|
4107
|
+
// src/commands/transcript/format/processVttFile/parseVtt/deduplicateCues/removeSubstringDuplicates.ts
|
|
3836
4108
|
function normalizeText(text) {
|
|
3837
4109
|
return text.toLowerCase().trim();
|
|
3838
4110
|
}
|
|
@@ -3875,7 +4147,7 @@ function removeSubstringDuplicates(cues) {
|
|
|
3875
4147
|
return cues.filter((_, i) => !toRemove.has(i));
|
|
3876
4148
|
}
|
|
3877
4149
|
|
|
3878
|
-
// src/commands/transcript/format/parseVtt/deduplicateCues/index.ts
|
|
4150
|
+
// src/commands/transcript/format/processVttFile/parseVtt/deduplicateCues/index.ts
|
|
3879
4151
|
function findWordOverlap(currentWords, nextWords) {
|
|
3880
4152
|
for (let j = Math.min(5, currentWords.length); j >= 1; j--) {
|
|
3881
4153
|
const suffix = currentWords.slice(-j).join(" ");
|
|
@@ -3923,7 +4195,7 @@ function deduplicateCues(cues) {
|
|
|
3923
4195
|
}));
|
|
3924
4196
|
}
|
|
3925
4197
|
|
|
3926
|
-
// src/commands/transcript/format/parseVtt/index.ts
|
|
4198
|
+
// src/commands/transcript/format/processVttFile/parseVtt/index.ts
|
|
3927
4199
|
function parseHMS(h, m, s) {
|
|
3928
4200
|
return Number.parseInt(h, 10) * 3600 + Number.parseInt(m, 10) * 60 + Number.parseFloat(s);
|
|
3929
4201
|
}
|
|
@@ -4016,14 +4288,14 @@ function formatChatLog(messages) {
|
|
|
4016
4288
|
|
|
4017
4289
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
4018
4290
|
function toMdFilename(vttFilename) {
|
|
4019
|
-
return `${
|
|
4291
|
+
return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
|
|
4020
4292
|
}
|
|
4021
4293
|
function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
4022
4294
|
return relativeDir === "." ? transcriptsDir : join16(transcriptsDir, relativeDir);
|
|
4023
4295
|
}
|
|
4024
4296
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
4025
4297
|
const mdFile = toMdFilename(vttFile.filename);
|
|
4026
|
-
const relativeDir =
|
|
4298
|
+
const relativeDir = dirname12(vttFile.relativePath);
|
|
4027
4299
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
4028
4300
|
const outputPath = join16(outputDir, mdFile);
|
|
4029
4301
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
@@ -4034,7 +4306,7 @@ function logSkipped(relativeDir, mdFile) {
|
|
|
4034
4306
|
}
|
|
4035
4307
|
function ensureDirectory(dir, label) {
|
|
4036
4308
|
if (!existsSync15(dir)) {
|
|
4037
|
-
|
|
4309
|
+
mkdirSync5(dir, { recursive: true });
|
|
4038
4310
|
console.log(`Created ${label}: ${dir}`);
|
|
4039
4311
|
}
|
|
4040
4312
|
}
|
|
@@ -4059,7 +4331,7 @@ function readAndParseCues(inputPath) {
|
|
|
4059
4331
|
return processCues(readFileSync12(inputPath, "utf-8"));
|
|
4060
4332
|
}
|
|
4061
4333
|
function writeFormatted(outputPath, content) {
|
|
4062
|
-
|
|
4334
|
+
writeFileSync13(outputPath, content, "utf-8");
|
|
4063
4335
|
console.log(`Written: ${outputPath}`);
|
|
4064
4336
|
}
|
|
4065
4337
|
function convertVttToMarkdown(inputPath, outputPath) {
|
|
@@ -4128,17 +4400,17 @@ async function format() {
|
|
|
4128
4400
|
|
|
4129
4401
|
// src/commands/transcript/summarise/index.ts
|
|
4130
4402
|
import { existsSync as existsSync18 } from "fs";
|
|
4131
|
-
import { basename as
|
|
4403
|
+
import { basename as basename6, dirname as dirname14, join as join18, relative as relative2 } from "path";
|
|
4132
4404
|
|
|
4133
4405
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
4134
4406
|
import {
|
|
4135
4407
|
existsSync as existsSync17,
|
|
4136
|
-
mkdirSync as
|
|
4408
|
+
mkdirSync as mkdirSync6,
|
|
4137
4409
|
readFileSync as readFileSync13,
|
|
4138
4410
|
renameSync as renameSync2,
|
|
4139
4411
|
rmSync
|
|
4140
4412
|
} from "fs";
|
|
4141
|
-
import { dirname as
|
|
4413
|
+
import { dirname as dirname13, join as join17 } from "path";
|
|
4142
4414
|
|
|
4143
4415
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
4144
4416
|
import chalk41 from "chalk";
|
|
@@ -4192,9 +4464,9 @@ function processStagedFile() {
|
|
|
4192
4464
|
process.exit(1);
|
|
4193
4465
|
}
|
|
4194
4466
|
const destPath = join17(summaryDir, matchingTranscript.relativePath);
|
|
4195
|
-
const destDir =
|
|
4467
|
+
const destDir = dirname13(destPath);
|
|
4196
4468
|
if (!existsSync17(destDir)) {
|
|
4197
|
-
|
|
4469
|
+
mkdirSync6(destDir, { recursive: true });
|
|
4198
4470
|
}
|
|
4199
4471
|
renameSync2(stagedFile.absolutePath, destPath);
|
|
4200
4472
|
const remaining = findMdFilesRecursive(STAGING_DIR);
|
|
@@ -4206,14 +4478,14 @@ function processStagedFile() {
|
|
|
4206
4478
|
|
|
4207
4479
|
// src/commands/transcript/summarise/index.ts
|
|
4208
4480
|
function buildRelativeKey(relativePath, baseName) {
|
|
4209
|
-
const relDir =
|
|
4481
|
+
const relDir = dirname14(relativePath);
|
|
4210
4482
|
return relDir === "." ? baseName : join18(relDir, baseName);
|
|
4211
4483
|
}
|
|
4212
4484
|
function buildSummaryIndex(summaryDir) {
|
|
4213
4485
|
const summaryFiles = findMdFilesRecursive(summaryDir);
|
|
4214
4486
|
return new Set(
|
|
4215
4487
|
summaryFiles.map(
|
|
4216
|
-
(f) => buildRelativeKey(f.relativePath,
|
|
4488
|
+
(f) => buildRelativeKey(f.relativePath, basename6(f.filename, ".md"))
|
|
4217
4489
|
)
|
|
4218
4490
|
);
|
|
4219
4491
|
}
|
|
@@ -4242,7 +4514,7 @@ function summarise() {
|
|
|
4242
4514
|
const next2 = missing[0];
|
|
4243
4515
|
const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
|
|
4244
4516
|
const outputPath = join18(STAGING_DIR, outputFilename);
|
|
4245
|
-
const summaryFileDir = join18(summaryDir,
|
|
4517
|
+
const summaryFileDir = join18(summaryDir, dirname14(next2.relativePath));
|
|
4246
4518
|
const relativeTranscriptPath = encodeURI(
|
|
4247
4519
|
relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
|
|
4248
4520
|
);
|
|
@@ -4266,161 +4538,9 @@ function registerTranscript(program2) {
|
|
|
4266
4538
|
transcriptCommand.command("summarise").description("List transcripts that do not have summaries").action(summarise);
|
|
4267
4539
|
}
|
|
4268
4540
|
|
|
4269
|
-
// src/commands/verify/hardcodedColors.ts
|
|
4270
|
-
import { execSync as execSync18 } from "child_process";
|
|
4271
|
-
var pattern = "0x[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,6}";
|
|
4272
|
-
function hardcodedColors() {
|
|
4273
|
-
try {
|
|
4274
|
-
const output = execSync18(`grep -rEnH '${pattern}' src/`, {
|
|
4275
|
-
encoding: "utf-8"
|
|
4276
|
-
});
|
|
4277
|
-
const lines = output.trim().split("\n");
|
|
4278
|
-
console.log("Hardcoded colors found:\n");
|
|
4279
|
-
for (const line of lines) {
|
|
4280
|
-
const match = line.match(/^(.+):(\d+):(.+)$/);
|
|
4281
|
-
if (match) {
|
|
4282
|
-
const [, file, lineNum, content] = match;
|
|
4283
|
-
const colorMatch = content.match(/0x[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,6}/);
|
|
4284
|
-
const color = colorMatch?.[0] ?? "unknown";
|
|
4285
|
-
console.log(`${file}:${lineNum} \u2192 ${color}`);
|
|
4286
|
-
}
|
|
4287
|
-
}
|
|
4288
|
-
console.log(`
|
|
4289
|
-
Total: ${lines.length} hardcoded color(s)`);
|
|
4290
|
-
console.log("\nUse colors from the 'open-color' (oc) library instead.");
|
|
4291
|
-
console.log("\nExample fix:");
|
|
4292
|
-
console.log(" Before: color: '#228be6'");
|
|
4293
|
-
console.log(" After: color: oc.blue[6]");
|
|
4294
|
-
console.log("\nImport open-color with: import oc from 'open-color'");
|
|
4295
|
-
process.exit(1);
|
|
4296
|
-
} catch {
|
|
4297
|
-
console.log("No hardcoded colors found.");
|
|
4298
|
-
process.exit(0);
|
|
4299
|
-
}
|
|
4300
|
-
}
|
|
4301
|
-
|
|
4302
|
-
// src/commands/verify/run/index.ts
|
|
4303
|
-
import { spawn as spawn3 } from "child_process";
|
|
4304
|
-
import * as path25 from "path";
|
|
4305
|
-
|
|
4306
|
-
// src/commands/verify/run/createTimerCallback/printTaskStatuses.ts
|
|
4307
|
-
function formatDuration(ms) {
|
|
4308
|
-
if (ms < 1e3) {
|
|
4309
|
-
return `${ms}ms`;
|
|
4310
|
-
}
|
|
4311
|
-
const seconds = (ms / 1e3).toFixed(1);
|
|
4312
|
-
return `${seconds}s`;
|
|
4313
|
-
}
|
|
4314
|
-
function printTaskStatuses(tasks) {
|
|
4315
|
-
console.log("\n--- Task Status ---");
|
|
4316
|
-
for (const task of tasks) {
|
|
4317
|
-
if (task.endTime !== void 0) {
|
|
4318
|
-
const duration = formatDuration(task.endTime - task.startTime);
|
|
4319
|
-
const status = task.code === 0 ? "\u2713" : "\u2717";
|
|
4320
|
-
console.log(` ${status} ${task.script}: ${duration}`);
|
|
4321
|
-
} else {
|
|
4322
|
-
const elapsed = formatDuration(Date.now() - task.startTime);
|
|
4323
|
-
console.log(` \u22EF ${task.script}: running (${elapsed})`);
|
|
4324
|
-
}
|
|
4325
|
-
}
|
|
4326
|
-
console.log("-------------------\n");
|
|
4327
|
-
}
|
|
4328
|
-
|
|
4329
|
-
// src/commands/verify/run/createTimerCallback/index.ts
|
|
4330
|
-
function logFailedScripts(failed) {
|
|
4331
|
-
console.error(`
|
|
4332
|
-
${failed.length} script(s) failed:`);
|
|
4333
|
-
for (const f of failed) {
|
|
4334
|
-
console.error(` - ${f.script} (exit code ${f.code})`);
|
|
4335
|
-
}
|
|
4336
|
-
}
|
|
4337
|
-
function createTimerCallback(taskStatuses, index) {
|
|
4338
|
-
return (exitCode) => {
|
|
4339
|
-
taskStatuses[index].endTime = Date.now();
|
|
4340
|
-
taskStatuses[index].code = exitCode;
|
|
4341
|
-
printTaskStatuses(taskStatuses);
|
|
4342
|
-
};
|
|
4343
|
-
}
|
|
4344
|
-
function initTaskStatuses(scripts) {
|
|
4345
|
-
return scripts.map((script) => ({ script, startTime: Date.now() }));
|
|
4346
|
-
}
|
|
4347
|
-
|
|
4348
|
-
// src/commands/verify/run/index.ts
|
|
4349
|
-
function spawnScript(script, cwd) {
|
|
4350
|
-
return spawn3("npm", ["run", script], { stdio: "inherit", shell: true, cwd });
|
|
4351
|
-
}
|
|
4352
|
-
function onScriptClose(script, onComplete, resolve) {
|
|
4353
|
-
return (code) => {
|
|
4354
|
-
const exitCode = code ?? 1;
|
|
4355
|
-
onComplete?.(exitCode);
|
|
4356
|
-
resolve({ script, code: exitCode });
|
|
4357
|
-
};
|
|
4358
|
-
}
|
|
4359
|
-
function runScript2(script, cwd, onComplete) {
|
|
4360
|
-
return new Promise((resolve) => {
|
|
4361
|
-
spawnScript(script, cwd).on(
|
|
4362
|
-
"close",
|
|
4363
|
-
onScriptClose(script, onComplete, resolve)
|
|
4364
|
-
);
|
|
4365
|
-
});
|
|
4366
|
-
}
|
|
4367
|
-
function runAllScripts(verifyScripts, packageDir, timer) {
|
|
4368
|
-
const taskStatuses = initTaskStatuses(verifyScripts);
|
|
4369
|
-
return Promise.all(
|
|
4370
|
-
verifyScripts.map(
|
|
4371
|
-
(script, index) => runScript2(
|
|
4372
|
-
script,
|
|
4373
|
-
packageDir,
|
|
4374
|
-
timer ? createTimerCallback(taskStatuses, index) : void 0
|
|
4375
|
-
)
|
|
4376
|
-
)
|
|
4377
|
-
);
|
|
4378
|
-
}
|
|
4379
|
-
function printScriptList(scripts) {
|
|
4380
|
-
console.log(`Running ${scripts.length} verify script(s) in parallel:`);
|
|
4381
|
-
for (const script of scripts) {
|
|
4382
|
-
console.log(` - ${script}`);
|
|
4383
|
-
}
|
|
4384
|
-
}
|
|
4385
|
-
function exitIfFailed(failed) {
|
|
4386
|
-
if (failed.length === 0) return;
|
|
4387
|
-
logFailedScripts(failed);
|
|
4388
|
-
process.exit(1);
|
|
4389
|
-
}
|
|
4390
|
-
function handleResults(results, totalCount) {
|
|
4391
|
-
exitIfFailed(results.filter((r) => r.code !== 0));
|
|
4392
|
-
console.log(`
|
|
4393
|
-
All ${totalCount} verify script(s) passed`);
|
|
4394
|
-
}
|
|
4395
|
-
function resolveVerifyScripts() {
|
|
4396
|
-
const result = findPackageJsonWithVerifyScripts(process.cwd());
|
|
4397
|
-
if (!result) {
|
|
4398
|
-
console.log("No package.json with verify:* scripts found");
|
|
4399
|
-
return null;
|
|
4400
|
-
}
|
|
4401
|
-
return result;
|
|
4402
|
-
}
|
|
4403
|
-
function getPackageDir(found) {
|
|
4404
|
-
return path25.dirname(found.packageJsonPath);
|
|
4405
|
-
}
|
|
4406
|
-
async function executeVerifyScripts(found, timer) {
|
|
4407
|
-
printScriptList(found.verifyScripts);
|
|
4408
|
-
const results = await runAllScripts(
|
|
4409
|
-
found.verifyScripts,
|
|
4410
|
-
getPackageDir(found),
|
|
4411
|
-
timer
|
|
4412
|
-
);
|
|
4413
|
-
handleResults(results, found.verifyScripts.length);
|
|
4414
|
-
}
|
|
4415
|
-
async function run(options = {}) {
|
|
4416
|
-
const found = resolveVerifyScripts();
|
|
4417
|
-
if (!found) return;
|
|
4418
|
-
await executeVerifyScripts(found, options.timer ?? false);
|
|
4419
|
-
}
|
|
4420
|
-
|
|
4421
4541
|
// src/commands/registerVerify.ts
|
|
4422
4542
|
function registerVerify(program2) {
|
|
4423
|
-
const verifyCommand = program2.command("verify").description("Run all verify:* scripts from package.json in parallel").option("--timer", "Show timing information for each task as they complete").action((
|
|
4543
|
+
const verifyCommand = program2.command("verify").description("Run all verify:* scripts from package.json in parallel").option("--timer", "Show timing information for each task as they complete").action((options2) => run(options2));
|
|
4424
4544
|
verifyCommand.command("init").description("Add verify scripts to a project").action(init2);
|
|
4425
4545
|
verifyCommand.command("hardcoded-colors").description("Check for hardcoded hex colors in src/").action(hardcodedColors);
|
|
4426
4546
|
}
|
|
@@ -4651,7 +4771,7 @@ program.command("init").description("Initialize VS Code and verify configuration
|
|
|
4651
4771
|
program.command("commit <message>").description("Create a git commit with validation").action(commit);
|
|
4652
4772
|
program.command("update").description("Update claude-code to the latest version").action(() => {
|
|
4653
4773
|
console.log("Updating claude-code...");
|
|
4654
|
-
|
|
4774
|
+
execSync22("npm install -g @anthropic-ai/claude-code", { stdio: "inherit" });
|
|
4655
4775
|
});
|
|
4656
4776
|
var configCommand = program.command("config").description("View and modify assist.yml configuration");
|
|
4657
4777
|
configCommand.command("set <key> <value>").description("Set a config value (e.g. commit.push true)").action(configSet);
|
|
@@ -4661,7 +4781,7 @@ var runCommand = program.command("run").description("Run a configured command fr
|
|
|
4661
4781
|
run2(name, args);
|
|
4662
4782
|
});
|
|
4663
4783
|
runCommand.command("add").description("Add a new run configuration to assist.yml").allowUnknownOption().allowExcessArguments().action(() => add());
|
|
4664
|
-
program
|
|
4784
|
+
registerNew(program);
|
|
4665
4785
|
var lintCommand = program.command("lint").description("Run lint checks for conventions not enforced by biomejs").action(lint);
|
|
4666
4786
|
lintCommand.command("init").description("Initialize Biome with standard linter config").action(init);
|
|
4667
4787
|
var vscodeCommand = program.command("vscode").description("VS Code configuration utilities");
|