@staff0rd/assist 0.232.0 → 0.233.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 -0
- package/dist/index.js +785 -764
- 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.233.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -102,7 +102,7 @@ var package_default = {
|
|
|
102
102
|
};
|
|
103
103
|
|
|
104
104
|
// src/commands/backlog/next.ts
|
|
105
|
-
import
|
|
105
|
+
import chalk14 from "chalk";
|
|
106
106
|
import enquirer2 from "enquirer";
|
|
107
107
|
|
|
108
108
|
// src/shared/exitOnCancel.ts
|
|
@@ -117,51 +117,22 @@ async function exitOnCancel(promise) {
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
// src/
|
|
121
|
-
import {
|
|
122
|
-
import
|
|
123
|
-
|
|
124
|
-
// src/commands/handover/getHandoverPath.ts
|
|
125
|
-
import { join } from "path";
|
|
126
|
-
function getHandoverPath(cwd = process.cwd()) {
|
|
127
|
-
return join(cwd, ".assist", "HANDOVER.md");
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// src/commands/backlog/blockedByHandover.ts
|
|
131
|
-
function blockedByHandover(cwd = process.cwd()) {
|
|
132
|
-
if (!existsSync(getHandoverPath(cwd))) return false;
|
|
133
|
-
console.log(
|
|
134
|
-
chalk.yellow(
|
|
135
|
-
"HANDOVER.md present \u2014 resolve the pending handover before running backlog items."
|
|
136
|
-
)
|
|
137
|
-
);
|
|
138
|
-
console.log(
|
|
139
|
-
chalk.dim(
|
|
140
|
-
"Start a fresh session to load it, or run `assist handover archive` to set it aside."
|
|
141
|
-
)
|
|
142
|
-
);
|
|
143
|
-
return true;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// src/commands/backlog/acquireLock.ts
|
|
147
|
-
import { existsSync as existsSync7, readFileSync as readFileSync3, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
148
|
-
import { join as join6 } from "path";
|
|
149
|
-
|
|
150
|
-
// src/commands/backlog/shared.ts
|
|
151
|
-
import chalk6 from "chalk";
|
|
120
|
+
// src/shared/pullIfConfigured.ts
|
|
121
|
+
import { execSync } from "child_process";
|
|
122
|
+
import chalk2 from "chalk";
|
|
152
123
|
|
|
153
124
|
// src/shared/loadConfig.ts
|
|
154
|
-
import { existsSync as
|
|
125
|
+
import { existsSync as existsSync2, writeFileSync } from "fs";
|
|
155
126
|
import { homedir } from "os";
|
|
156
|
-
import { dirname, join
|
|
157
|
-
import
|
|
127
|
+
import { dirname, join } from "path";
|
|
128
|
+
import chalk from "chalk";
|
|
158
129
|
import { stringify as stringifyYaml } from "yaml";
|
|
159
130
|
|
|
160
131
|
// src/shared/loadRawYaml.ts
|
|
161
|
-
import { existsSync
|
|
132
|
+
import { existsSync, readFileSync } from "fs";
|
|
162
133
|
import { parse as parseYaml } from "yaml";
|
|
163
134
|
function loadRawYaml(path52) {
|
|
164
|
-
if (!
|
|
135
|
+
if (!existsSync(path52)) return {};
|
|
165
136
|
try {
|
|
166
137
|
const content = readFileSync(path52, "utf-8");
|
|
167
138
|
return parseYaml(content) || {};
|
|
@@ -347,11 +318,11 @@ function isRunLink(entry) {
|
|
|
347
318
|
function findConfigUp(startDir) {
|
|
348
319
|
let current = startDir;
|
|
349
320
|
while (current !== dirname(current)) {
|
|
350
|
-
const claudePath =
|
|
351
|
-
if (
|
|
321
|
+
const claudePath = join(current, ".claude", "assist.yml");
|
|
322
|
+
if (existsSync2(claudePath))
|
|
352
323
|
return { configPath: claudePath, rootDir: current };
|
|
353
|
-
const rootPath =
|
|
354
|
-
if (
|
|
324
|
+
const rootPath = join(current, "assist.yml");
|
|
325
|
+
if (existsSync2(rootPath)) return { configPath: rootPath, rootDir: current };
|
|
355
326
|
current = dirname(current);
|
|
356
327
|
}
|
|
357
328
|
return null;
|
|
@@ -359,10 +330,10 @@ function findConfigUp(startDir) {
|
|
|
359
330
|
function getConfigPath() {
|
|
360
331
|
const found = findConfigUp(process.cwd());
|
|
361
332
|
if (found) return found.configPath;
|
|
362
|
-
return
|
|
333
|
+
return join(process.cwd(), "assist.yml");
|
|
363
334
|
}
|
|
364
335
|
function getGlobalConfigPath() {
|
|
365
|
-
return
|
|
336
|
+
return join(homedir(), ".assist.yml");
|
|
366
337
|
}
|
|
367
338
|
function getConfigDir() {
|
|
368
339
|
return dirname(getConfigPath());
|
|
@@ -379,7 +350,7 @@ function loadConfig() {
|
|
|
379
350
|
}
|
|
380
351
|
function loadConfigFrom(startDir) {
|
|
381
352
|
const found = findConfigUp(startDir);
|
|
382
|
-
const configPath = found?.configPath ??
|
|
353
|
+
const configPath = found?.configPath ?? join(startDir, "assist.yml");
|
|
383
354
|
const globalRaw = loadRawYaml(getGlobalConfigPath());
|
|
384
355
|
const projectRaw = loadRawYaml(configPath);
|
|
385
356
|
const merged = mergeRawConfigs(globalRaw, projectRaw);
|
|
@@ -405,7 +376,7 @@ function getTranscriptConfig() {
|
|
|
405
376
|
const config = loadConfig();
|
|
406
377
|
if (!config.transcript) {
|
|
407
378
|
console.error(
|
|
408
|
-
|
|
379
|
+
chalk.red(
|
|
409
380
|
"Transcript directories not configured. Run 'assist transcript configure' first."
|
|
410
381
|
)
|
|
411
382
|
);
|
|
@@ -414,6 +385,51 @@ function getTranscriptConfig() {
|
|
|
414
385
|
return config.transcript;
|
|
415
386
|
}
|
|
416
387
|
|
|
388
|
+
// src/shared/pullIfConfigured.ts
|
|
389
|
+
function pullIfConfigured() {
|
|
390
|
+
const config = loadConfig();
|
|
391
|
+
if (!config.commit?.pull) return;
|
|
392
|
+
try {
|
|
393
|
+
execSync("git pull --ff-only", { stdio: "inherit" });
|
|
394
|
+
} catch {
|
|
395
|
+
console.error(chalk2.red("git pull --ff-only failed; aborting."));
|
|
396
|
+
process.exit(1);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// src/commands/backlog/blockedByHandover.ts
|
|
401
|
+
import { existsSync as existsSync3 } from "fs";
|
|
402
|
+
import chalk3 from "chalk";
|
|
403
|
+
|
|
404
|
+
// src/commands/handover/getHandoverPath.ts
|
|
405
|
+
import { join as join2 } from "path";
|
|
406
|
+
function getHandoverPath(cwd = process.cwd()) {
|
|
407
|
+
return join2(cwd, ".assist", "HANDOVER.md");
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// src/commands/backlog/blockedByHandover.ts
|
|
411
|
+
function blockedByHandover(cwd = process.cwd()) {
|
|
412
|
+
if (!existsSync3(getHandoverPath(cwd))) return false;
|
|
413
|
+
console.log(
|
|
414
|
+
chalk3.yellow(
|
|
415
|
+
"HANDOVER.md present \u2014 resolve the pending handover before running backlog items."
|
|
416
|
+
)
|
|
417
|
+
);
|
|
418
|
+
console.log(
|
|
419
|
+
chalk3.dim(
|
|
420
|
+
"Start a fresh session to load it, or run `assist handover archive` to set it aside."
|
|
421
|
+
)
|
|
422
|
+
);
|
|
423
|
+
return true;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// src/commands/backlog/acquireLock.ts
|
|
427
|
+
import { existsSync as existsSync7, readFileSync as readFileSync3, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
428
|
+
import { join as join6 } from "path";
|
|
429
|
+
|
|
430
|
+
// src/commands/backlog/shared.ts
|
|
431
|
+
import chalk7 from "chalk";
|
|
432
|
+
|
|
417
433
|
// src/commands/backlog/deleteItem.ts
|
|
418
434
|
import { eq } from "drizzle-orm";
|
|
419
435
|
|
|
@@ -506,7 +522,7 @@ async function deleteItem(orm, id) {
|
|
|
506
522
|
// src/commands/backlog/migrateLocalBacklog.ts
|
|
507
523
|
import { existsSync as existsSync5 } from "fs";
|
|
508
524
|
import { join as join4 } from "path";
|
|
509
|
-
import
|
|
525
|
+
import chalk5 from "chalk";
|
|
510
526
|
|
|
511
527
|
// src/commands/backlog/backupLocalBacklogFiles.ts
|
|
512
528
|
import { existsSync as existsSync4, renameSync } from "fs";
|
|
@@ -525,17 +541,17 @@ function backupLocalBacklogFiles(dir) {
|
|
|
525
541
|
}
|
|
526
542
|
|
|
527
543
|
// src/commands/backlog/gitPullBacklog.ts
|
|
528
|
-
import { execSync } from "child_process";
|
|
529
|
-
import
|
|
544
|
+
import { execSync as execSync2 } from "child_process";
|
|
545
|
+
import chalk4 from "chalk";
|
|
530
546
|
function gitPullBacklog(dir) {
|
|
531
547
|
try {
|
|
532
|
-
|
|
548
|
+
execSync2("git pull --ff-only", {
|
|
533
549
|
cwd: dir,
|
|
534
550
|
stdio: ["pipe", "pipe", "pipe"]
|
|
535
551
|
});
|
|
536
552
|
} catch {
|
|
537
553
|
console.error(
|
|
538
|
-
|
|
554
|
+
chalk4.yellow(
|
|
539
555
|
"backlog migrate: git pull skipped (no upstream or pull failed); using the local file."
|
|
540
556
|
)
|
|
541
557
|
);
|
|
@@ -835,7 +851,7 @@ async function migrateLocalBacklog(orm, dir, origin) {
|
|
|
835
851
|
if (existing > 0) {
|
|
836
852
|
const moved2 = backupLocalBacklogFiles(dir);
|
|
837
853
|
console.error(
|
|
838
|
-
|
|
854
|
+
chalk5.yellow(
|
|
839
855
|
`backlog migrate: Postgres already has ${existing} item(s) for ${origin}; skipped import to avoid duplicates and archived the local file (${moved2.join(", ")}).`
|
|
840
856
|
)
|
|
841
857
|
);
|
|
@@ -847,7 +863,7 @@ async function migrateLocalBacklog(orm, dir, origin) {
|
|
|
847
863
|
await verifyImport(orm, origin, items2, imported);
|
|
848
864
|
const moved = backupLocalBacklogFiles(dir);
|
|
849
865
|
console.error(
|
|
850
|
-
|
|
866
|
+
chalk5.green(
|
|
851
867
|
`backlog migrate: imported ${imported} item(s) into Postgres (${moved.join(", ")}).`
|
|
852
868
|
)
|
|
853
869
|
);
|
|
@@ -881,7 +897,7 @@ function findBacklogUp(startDir) {
|
|
|
881
897
|
}
|
|
882
898
|
|
|
883
899
|
// src/commands/backlog/getBacklogOrm.ts
|
|
884
|
-
import
|
|
900
|
+
import chalk6 from "chalk";
|
|
885
901
|
import { Pool } from "pg";
|
|
886
902
|
|
|
887
903
|
// src/commands/backlog/BacklogOrm.ts
|
|
@@ -967,7 +983,7 @@ Managed Postgres providers such as Supabase or Neon work out of the box.`;
|
|
|
967
983
|
function getDatabaseUrl() {
|
|
968
984
|
const url = process.env[DATABASE_URL_ENV] ?? loadConfig().backlog.databaseUrl;
|
|
969
985
|
if (!url) {
|
|
970
|
-
console.error(
|
|
986
|
+
console.error(chalk6.red(MISSING_URL_MESSAGE));
|
|
971
987
|
process.exit(1);
|
|
972
988
|
}
|
|
973
989
|
return url;
|
|
@@ -1010,7 +1026,7 @@ async function closeBacklogDb() {
|
|
|
1010
1026
|
}
|
|
1011
1027
|
|
|
1012
1028
|
// src/commands/backlog/getCurrentOrigin.ts
|
|
1013
|
-
import { execSync as
|
|
1029
|
+
import { execSync as execSync3 } from "child_process";
|
|
1014
1030
|
function stripLeadingSlashes(path52) {
|
|
1015
1031
|
return path52.replace(/^\/+/, "");
|
|
1016
1032
|
}
|
|
@@ -1032,7 +1048,7 @@ function normalizeOrigin(raw) {
|
|
|
1032
1048
|
}
|
|
1033
1049
|
function tryGit(cwd, args) {
|
|
1034
1050
|
try {
|
|
1035
|
-
const out =
|
|
1051
|
+
const out = execSync3(`git ${args}`, {
|
|
1036
1052
|
cwd,
|
|
1037
1053
|
encoding: "utf-8",
|
|
1038
1054
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -1138,7 +1154,7 @@ async function findOneItem(id) {
|
|
|
1138
1154
|
const { orm } = await getReady();
|
|
1139
1155
|
const item = Number.isNaN(numId) ? void 0 : await loadItem(orm, numId);
|
|
1140
1156
|
if (!item) {
|
|
1141
|
-
console.log(
|
|
1157
|
+
console.log(chalk7.red(`Item #${id} not found.`));
|
|
1142
1158
|
return void 0;
|
|
1143
1159
|
}
|
|
1144
1160
|
return { orm, item };
|
|
@@ -1146,7 +1162,7 @@ async function findOneItem(id) {
|
|
|
1146
1162
|
async function setStatus(id, status2) {
|
|
1147
1163
|
const { orm } = await getReady();
|
|
1148
1164
|
const name = await updateStatus(orm, Number.parseInt(id, 10), status2);
|
|
1149
|
-
if (name === void 0) console.log(
|
|
1165
|
+
if (name === void 0) console.log(chalk7.red(`Item #${id} not found.`));
|
|
1150
1166
|
return name;
|
|
1151
1167
|
}
|
|
1152
1168
|
async function setCurrentPhase(id, phase) {
|
|
@@ -1156,7 +1172,7 @@ async function setCurrentPhase(id, phase) {
|
|
|
1156
1172
|
async function removeItem(id) {
|
|
1157
1173
|
const { orm } = await getReady();
|
|
1158
1174
|
const name = await deleteItem(orm, Number.parseInt(id, 10));
|
|
1159
|
-
if (name === void 0) console.log(
|
|
1175
|
+
if (name === void 0) console.log(chalk7.red(`Item #${id} not found.`));
|
|
1160
1176
|
return name;
|
|
1161
1177
|
}
|
|
1162
1178
|
|
|
@@ -1198,30 +1214,30 @@ function releaseLock(itemId) {
|
|
|
1198
1214
|
}
|
|
1199
1215
|
|
|
1200
1216
|
// src/commands/backlog/list/shared.ts
|
|
1201
|
-
import
|
|
1217
|
+
import chalk8 from "chalk";
|
|
1202
1218
|
function statusIcon(status2) {
|
|
1203
1219
|
switch (status2) {
|
|
1204
1220
|
case "todo":
|
|
1205
|
-
return
|
|
1221
|
+
return chalk8.dim("[ ]");
|
|
1206
1222
|
case "in-progress":
|
|
1207
|
-
return
|
|
1223
|
+
return chalk8.yellow("[~]");
|
|
1208
1224
|
case "done":
|
|
1209
|
-
return
|
|
1225
|
+
return chalk8.green("[x]");
|
|
1210
1226
|
case "wontdo":
|
|
1211
|
-
return
|
|
1227
|
+
return chalk8.dim("[-]");
|
|
1212
1228
|
}
|
|
1213
1229
|
}
|
|
1214
1230
|
function typeLabel(type) {
|
|
1215
1231
|
switch (type) {
|
|
1216
1232
|
case "bug":
|
|
1217
|
-
return
|
|
1233
|
+
return chalk8.magenta("Bug");
|
|
1218
1234
|
case "story":
|
|
1219
|
-
return
|
|
1235
|
+
return chalk8.cyan("Story");
|
|
1220
1236
|
}
|
|
1221
1237
|
}
|
|
1222
1238
|
function phaseLabel(item) {
|
|
1223
1239
|
if (!item.plan) return "";
|
|
1224
|
-
return
|
|
1240
|
+
return chalk8.dim(` (phase ${item.currentPhase ?? 1}/${item.plan.length})`);
|
|
1225
1241
|
}
|
|
1226
1242
|
function isBlocked(item, items2) {
|
|
1227
1243
|
const deps2 = (item.links ?? []).filter((l) => l.type === "depends-on");
|
|
@@ -1233,15 +1249,15 @@ function isBlocked(item, items2) {
|
|
|
1233
1249
|
function dependencyLabel(item, items2) {
|
|
1234
1250
|
const deps2 = (item.links ?? []).filter((l) => l.type === "depends-on");
|
|
1235
1251
|
if (deps2.length === 0) return "";
|
|
1236
|
-
if (isBlocked(item, items2)) return
|
|
1237
|
-
return
|
|
1252
|
+
if (isBlocked(item, items2)) return chalk8.red(" [blocked]");
|
|
1253
|
+
return chalk8.dim(` [${deps2.length} dep${deps2.length > 1 ? "s" : ""}]`);
|
|
1238
1254
|
}
|
|
1239
1255
|
function printVerboseDetails(item) {
|
|
1240
1256
|
if (item.description) {
|
|
1241
|
-
console.log(` ${
|
|
1257
|
+
console.log(` ${chalk8.dim("Description:")} ${item.description}`);
|
|
1242
1258
|
}
|
|
1243
1259
|
if (item.acceptanceCriteria.length > 0) {
|
|
1244
|
-
console.log(` ${
|
|
1260
|
+
console.log(` ${chalk8.dim("Acceptance criteria:")}`);
|
|
1245
1261
|
for (const [i, criterion] of item.acceptanceCriteria.entries()) {
|
|
1246
1262
|
console.log(` ${i + 1}. ${criterion}`);
|
|
1247
1263
|
}
|
|
@@ -1257,17 +1273,17 @@ function findResumable(items2) {
|
|
|
1257
1273
|
}
|
|
1258
1274
|
|
|
1259
1275
|
// src/commands/backlog/findUnblockedTodos.ts
|
|
1260
|
-
import
|
|
1276
|
+
import chalk9 from "chalk";
|
|
1261
1277
|
function findUnblockedTodos(items2) {
|
|
1262
1278
|
const todo = items2.filter((i) => i.status === "todo");
|
|
1263
1279
|
if (todo.length === 0) {
|
|
1264
|
-
console.log(
|
|
1280
|
+
console.log(chalk9.green("All backlog items complete."));
|
|
1265
1281
|
return void 0;
|
|
1266
1282
|
}
|
|
1267
1283
|
const unblocked = todo.filter((i) => !isBlocked(i, items2));
|
|
1268
1284
|
if (unblocked.length === 0) {
|
|
1269
1285
|
console.log(
|
|
1270
|
-
|
|
1286
|
+
chalk9.yellow("All remaining todo items are blocked by dependencies.")
|
|
1271
1287
|
);
|
|
1272
1288
|
return void 0;
|
|
1273
1289
|
}
|
|
@@ -1275,10 +1291,10 @@ function findUnblockedTodos(items2) {
|
|
|
1275
1291
|
}
|
|
1276
1292
|
|
|
1277
1293
|
// src/commands/backlog/run.ts
|
|
1278
|
-
import
|
|
1294
|
+
import chalk13 from "chalk";
|
|
1279
1295
|
|
|
1280
1296
|
// src/commands/backlog/prepareRun.ts
|
|
1281
|
-
import
|
|
1297
|
+
import chalk10 from "chalk";
|
|
1282
1298
|
|
|
1283
1299
|
// src/commands/backlog/resolvePlan.ts
|
|
1284
1300
|
function resolvePlan(item) {
|
|
@@ -1301,13 +1317,13 @@ async function prepareRun(id) {
|
|
|
1301
1317
|
const plan2 = resolvePlan(item);
|
|
1302
1318
|
const startPhase = (item.currentPhase ?? 1) - 1;
|
|
1303
1319
|
if (item.status === "done") {
|
|
1304
|
-
console.log(
|
|
1320
|
+
console.log(chalk10.green(`Already done: #${id}: ${item.name}`));
|
|
1305
1321
|
return void 0;
|
|
1306
1322
|
}
|
|
1307
1323
|
if (startPhase > plan2.length) {
|
|
1308
1324
|
await setStatus(id, "done");
|
|
1309
1325
|
console.log(
|
|
1310
|
-
|
|
1326
|
+
chalk10.green(`All phases already complete for #${id}: ${item.name}`)
|
|
1311
1327
|
);
|
|
1312
1328
|
return void 0;
|
|
1313
1329
|
}
|
|
@@ -1315,7 +1331,7 @@ async function prepareRun(id) {
|
|
|
1315
1331
|
}
|
|
1316
1332
|
|
|
1317
1333
|
// src/commands/backlog/executePhase.ts
|
|
1318
|
-
import
|
|
1334
|
+
import chalk12 from "chalk";
|
|
1319
1335
|
|
|
1320
1336
|
// src/shared/spawnClaude.ts
|
|
1321
1337
|
import { spawn } from "child_process";
|
|
@@ -1440,7 +1456,7 @@ function buildPhasePrompt(item, phaseNumber, phase) {
|
|
|
1440
1456
|
|
|
1441
1457
|
// src/commands/backlog/resolvePhaseResult.ts
|
|
1442
1458
|
import { existsSync as existsSync9, unlinkSync as unlinkSync2 } from "fs";
|
|
1443
|
-
import
|
|
1459
|
+
import chalk11 from "chalk";
|
|
1444
1460
|
|
|
1445
1461
|
// src/commands/backlog/handleIncompletePhase.ts
|
|
1446
1462
|
import enquirer from "enquirer";
|
|
@@ -1510,12 +1526,12 @@ async function resolvePhaseResult(phaseIndex, itemId) {
|
|
|
1510
1526
|
if (signal?.event === "rewind") {
|
|
1511
1527
|
const targetPhase = signal.targetPhase;
|
|
1512
1528
|
const targetPhaseNumber = targetPhase + 1;
|
|
1513
|
-
console.log(
|
|
1529
|
+
console.log(chalk11.yellow(`
|
|
1514
1530
|
Rewinding to phase ${targetPhaseNumber}.`));
|
|
1515
1531
|
return targetPhase;
|
|
1516
1532
|
}
|
|
1517
1533
|
const phaseNumber = phaseIndex + 1;
|
|
1518
|
-
console.log(
|
|
1534
|
+
console.log(chalk11.green(`
|
|
1519
1535
|
Phase ${phaseNumber} completed.`));
|
|
1520
1536
|
return phaseIndex + 1;
|
|
1521
1537
|
}
|
|
@@ -1542,7 +1558,7 @@ async function executePhase(item, phaseIndex, phases, spawnOptions) {
|
|
|
1542
1558
|
const phase = phases[phaseIndex];
|
|
1543
1559
|
const phaseNumber = phaseIndex + 1;
|
|
1544
1560
|
console.log(
|
|
1545
|
-
|
|
1561
|
+
chalk12.bold(
|
|
1546
1562
|
`
|
|
1547
1563
|
--- Phase ${phaseNumber}/${phases.length}: ${phase.name} ---
|
|
1548
1564
|
`
|
|
@@ -1631,15 +1647,15 @@ async function runPrepared(id, prepared, spawnOptions) {
|
|
|
1631
1647
|
}
|
|
1632
1648
|
}
|
|
1633
1649
|
function logProgress(id, { plan: plan2, startPhase, item }) {
|
|
1634
|
-
console.log(
|
|
1650
|
+
console.log(chalk13.bold(`Running plan for #${id}: ${item.name}`));
|
|
1635
1651
|
if (startPhase > 0) {
|
|
1636
1652
|
const phaseNumber = startPhase + 1;
|
|
1637
1653
|
console.log(
|
|
1638
|
-
|
|
1654
|
+
chalk13.dim(`Resuming from phase ${phaseNumber}/${plan2.length}
|
|
1639
1655
|
`)
|
|
1640
1656
|
);
|
|
1641
1657
|
} else {
|
|
1642
|
-
console.log(
|
|
1658
|
+
console.log(chalk13.dim(`${plan2.length} phase(s)
|
|
1643
1659
|
`));
|
|
1644
1660
|
}
|
|
1645
1661
|
}
|
|
@@ -1653,7 +1669,7 @@ async function ensureDone(id) {
|
|
|
1653
1669
|
// src/commands/backlog/next.ts
|
|
1654
1670
|
function toChoice(item, items2) {
|
|
1655
1671
|
const name = `${typeLabel(item.type)} #${item.id}: ${item.name}`;
|
|
1656
|
-
return isBlocked(item, items2) ? { name, disabled:
|
|
1672
|
+
return isBlocked(item, items2) ? { name, disabled: chalk14.red("[blocked]") } : { name };
|
|
1657
1673
|
}
|
|
1658
1674
|
async function selectItem(todo, items2) {
|
|
1659
1675
|
const { selected } = await exitOnCancel(
|
|
@@ -1666,28 +1682,31 @@ async function selectItem(todo, items2) {
|
|
|
1666
1682
|
);
|
|
1667
1683
|
return selected.match(/#(\d+)/)?.[1] ?? "";
|
|
1668
1684
|
}
|
|
1669
|
-
|
|
1685
|
+
function pickResumable(items2) {
|
|
1670
1686
|
const resumable = findResumable(items2);
|
|
1671
|
-
if (resumable)
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1687
|
+
if (!resumable) return void 0;
|
|
1688
|
+
console.log(
|
|
1689
|
+
chalk14.bold(`Resuming in-progress item #${resumable.id}: ${resumable.name}`)
|
|
1690
|
+
);
|
|
1691
|
+
return String(resumable.id);
|
|
1692
|
+
}
|
|
1693
|
+
function autoSelect(unblocked) {
|
|
1694
|
+
const item = unblocked[0];
|
|
1695
|
+
console.log(chalk14.bold(`Auto-selecting item #${item.id}: ${item.name}`));
|
|
1696
|
+
return String(item.id);
|
|
1697
|
+
}
|
|
1698
|
+
async function pickItem(items2, firstPick = false) {
|
|
1699
|
+
const resumable = pickResumable(items2);
|
|
1700
|
+
if (resumable) return resumable;
|
|
1679
1701
|
const unblocked = findUnblockedTodos(items2);
|
|
1680
1702
|
if (!unblocked) return void 0;
|
|
1681
|
-
if (firstPick && unblocked.length === 1)
|
|
1682
|
-
const item = unblocked[0];
|
|
1683
|
-
console.log(chalk13.bold(`Auto-selecting item #${item.id}: ${item.name}`));
|
|
1684
|
-
return String(item.id);
|
|
1685
|
-
}
|
|
1703
|
+
if (firstPick && unblocked.length === 1) return autoSelect(unblocked);
|
|
1686
1704
|
const todo = items2.filter((i) => i.status === "todo");
|
|
1687
1705
|
return selectItem(todo, items2);
|
|
1688
1706
|
}
|
|
1689
1707
|
async function next(options2) {
|
|
1690
1708
|
if (blockedByHandover()) return;
|
|
1709
|
+
pullIfConfigured();
|
|
1691
1710
|
let firstPick = true;
|
|
1692
1711
|
while (true) {
|
|
1693
1712
|
const id = await pickItem(await loadBacklog(), firstPick);
|
|
@@ -1699,7 +1718,7 @@ async function next(options2) {
|
|
|
1699
1718
|
}
|
|
1700
1719
|
|
|
1701
1720
|
// src/commands/backlog/phaseDone.ts
|
|
1702
|
-
import
|
|
1721
|
+
import chalk15 from "chalk";
|
|
1703
1722
|
|
|
1704
1723
|
// src/commands/backlog/appendComment.ts
|
|
1705
1724
|
import { sql as sql2 } from "drizzle-orm";
|
|
@@ -1734,11 +1753,11 @@ async function phaseDone(id, phase, summary) {
|
|
|
1734
1753
|
const { orm } = await getReady();
|
|
1735
1754
|
const status2 = await getItemStatus(orm, itemId);
|
|
1736
1755
|
if (status2 === void 0) {
|
|
1737
|
-
console.log(
|
|
1756
|
+
console.log(chalk15.red(`Item #${id} not found.`));
|
|
1738
1757
|
return;
|
|
1739
1758
|
}
|
|
1740
1759
|
if (status2 === "done") {
|
|
1741
|
-
console.log(
|
|
1760
|
+
console.log(chalk15.dim(`Item #${id} already done, skipping phase advance.`));
|
|
1742
1761
|
return;
|
|
1743
1762
|
}
|
|
1744
1763
|
await appendComment(orm, itemId, summary, {
|
|
@@ -1747,24 +1766,24 @@ async function phaseDone(id, phase, summary) {
|
|
|
1747
1766
|
});
|
|
1748
1767
|
await setCurrentPhase(id, phaseNumber + 1);
|
|
1749
1768
|
console.log(
|
|
1750
|
-
|
|
1769
|
+
chalk15.green(`Phase ${phaseNumber} of item #${id} marked as complete.`)
|
|
1751
1770
|
);
|
|
1752
1771
|
}
|
|
1753
1772
|
|
|
1754
1773
|
// src/commands/backlog/plan.ts
|
|
1755
|
-
import
|
|
1774
|
+
import chalk16 from "chalk";
|
|
1756
1775
|
async function plan(id) {
|
|
1757
1776
|
const found = await findOneItem(id);
|
|
1758
1777
|
if (!found) return;
|
|
1759
1778
|
const { item } = found;
|
|
1760
1779
|
if (!item.plan || item.plan.length === 0) {
|
|
1761
|
-
console.log(
|
|
1780
|
+
console.log(chalk16.dim("No plan defined for this item."));
|
|
1762
1781
|
return;
|
|
1763
1782
|
}
|
|
1764
|
-
console.log(
|
|
1783
|
+
console.log(chalk16.bold(item.name));
|
|
1765
1784
|
console.log();
|
|
1766
1785
|
for (const [i, phase] of item.plan.entries()) {
|
|
1767
|
-
console.log(`${
|
|
1786
|
+
console.log(`${chalk16.bold(`Phase ${i + 1}:`)} ${phase.name}`);
|
|
1768
1787
|
for (const task of phase.tasks) {
|
|
1769
1788
|
console.log(` - ${task.task}`);
|
|
1770
1789
|
}
|
|
@@ -1773,21 +1792,21 @@ async function plan(id) {
|
|
|
1773
1792
|
}
|
|
1774
1793
|
|
|
1775
1794
|
// src/commands/backlog/show/index.ts
|
|
1776
|
-
import
|
|
1795
|
+
import chalk20 from "chalk";
|
|
1777
1796
|
|
|
1778
1797
|
// src/commands/backlog/formatComment.ts
|
|
1779
|
-
import
|
|
1798
|
+
import chalk17 from "chalk";
|
|
1780
1799
|
function formatComment(entry) {
|
|
1781
|
-
const id = entry.id !== void 0 ?
|
|
1782
|
-
const tag = entry.type === "summary" ?
|
|
1783
|
-
const phase = entry.phase !== void 0 ?
|
|
1784
|
-
const time =
|
|
1800
|
+
const id = entry.id !== void 0 ? chalk17.dim(`#${entry.id} `) : "";
|
|
1801
|
+
const tag = entry.type === "summary" ? chalk17.magenta("[summary]") : chalk17.cyan("[comment]");
|
|
1802
|
+
const phase = entry.phase !== void 0 ? chalk17.dim(` (phase ${entry.phase})`) : "";
|
|
1803
|
+
const time = chalk17.dim(entry.timestamp);
|
|
1785
1804
|
return `${id}${tag}${phase} ${time}
|
|
1786
1805
|
${entry.text}`;
|
|
1787
1806
|
}
|
|
1788
1807
|
|
|
1789
1808
|
// src/commands/backlog/show/printLinks.ts
|
|
1790
|
-
import
|
|
1809
|
+
import chalk18 from "chalk";
|
|
1791
1810
|
|
|
1792
1811
|
// src/commands/backlog/show/loadLinkTargets.ts
|
|
1793
1812
|
import { inArray as inArray2 } from "drizzle-orm";
|
|
@@ -1809,17 +1828,17 @@ async function printLinks(orm, item) {
|
|
|
1809
1828
|
orm,
|
|
1810
1829
|
links2.map((l) => l.targetId)
|
|
1811
1830
|
);
|
|
1812
|
-
console.log(
|
|
1831
|
+
console.log(chalk18.bold("Links"));
|
|
1813
1832
|
for (const link3 of links2) {
|
|
1814
1833
|
const target = targets.find((i) => i.id === link3.targetId);
|
|
1815
|
-
const typeLabel2 = link3.type === "depends-on" ?
|
|
1834
|
+
const typeLabel2 = link3.type === "depends-on" ? chalk18.red("depends-on") : chalk18.blue("relates-to");
|
|
1816
1835
|
if (target) {
|
|
1817
1836
|
console.log(
|
|
1818
|
-
` ${typeLabel2} #${target.id} ${target.name} ${
|
|
1837
|
+
` ${typeLabel2} #${target.id} ${target.name} ${chalk18.dim(`(${target.status})`)}`
|
|
1819
1838
|
);
|
|
1820
1839
|
} else {
|
|
1821
1840
|
console.log(
|
|
1822
|
-
` ${typeLabel2} #${link3.targetId} ${
|
|
1841
|
+
` ${typeLabel2} #${link3.targetId} ${chalk18.dim("(not found)")}`
|
|
1823
1842
|
);
|
|
1824
1843
|
}
|
|
1825
1844
|
}
|
|
@@ -1827,15 +1846,15 @@ async function printLinks(orm, item) {
|
|
|
1827
1846
|
}
|
|
1828
1847
|
|
|
1829
1848
|
// src/commands/backlog/show/printPhaseTasks.ts
|
|
1830
|
-
import
|
|
1849
|
+
import chalk19 from "chalk";
|
|
1831
1850
|
function printPhaseTasks(phase) {
|
|
1832
1851
|
for (const task of phase.tasks) {
|
|
1833
1852
|
console.log(` - ${task.task}`);
|
|
1834
1853
|
}
|
|
1835
1854
|
if (phase.manualChecks && phase.manualChecks.length > 0) {
|
|
1836
|
-
console.log(` ${
|
|
1855
|
+
console.log(` ${chalk19.dim("Manual checks:")}`);
|
|
1837
1856
|
for (const check2 of phase.manualChecks) {
|
|
1838
|
-
console.log(` ${
|
|
1857
|
+
console.log(` ${chalk19.dim(`- ${check2}`)}`);
|
|
1839
1858
|
}
|
|
1840
1859
|
}
|
|
1841
1860
|
}
|
|
@@ -1843,7 +1862,7 @@ function printPhaseTasks(phase) {
|
|
|
1843
1862
|
// src/commands/backlog/show/index.ts
|
|
1844
1863
|
function printPlan(item) {
|
|
1845
1864
|
if (!item.plan || item.plan.length === 0) return;
|
|
1846
|
-
console.log(
|
|
1865
|
+
console.log(chalk20.bold("Plan"));
|
|
1847
1866
|
for (const [i, phase] of item.plan.entries()) {
|
|
1848
1867
|
const isCurrent = item.currentPhase === i + 1;
|
|
1849
1868
|
printPhase(phase, i, isCurrent);
|
|
@@ -1852,8 +1871,8 @@ function printPlan(item) {
|
|
|
1852
1871
|
}
|
|
1853
1872
|
function phaseHeader(index2, name, isCurrent) {
|
|
1854
1873
|
const phaseNumber = index2 + 1;
|
|
1855
|
-
const marker = isCurrent ?
|
|
1856
|
-
const label2 = isCurrent ?
|
|
1874
|
+
const marker = isCurrent ? chalk20.green("\u25B6 ") : " ";
|
|
1875
|
+
const label2 = isCurrent ? chalk20.green.bold(`Phase ${phaseNumber}: ${name}`) : `${chalk20.bold(`Phase ${phaseNumber}:`)} ${name}`;
|
|
1857
1876
|
return `${marker}${label2}`;
|
|
1858
1877
|
}
|
|
1859
1878
|
function printPhase(phase, index2, isCurrent) {
|
|
@@ -1861,15 +1880,15 @@ function printPhase(phase, index2, isCurrent) {
|
|
|
1861
1880
|
printPhaseTasks(phase);
|
|
1862
1881
|
}
|
|
1863
1882
|
function printHeader(item) {
|
|
1864
|
-
console.log(
|
|
1883
|
+
console.log(chalk20.bold(`#${item.id} ${item.name}`));
|
|
1865
1884
|
console.log(
|
|
1866
|
-
`${
|
|
1885
|
+
`${chalk20.dim("Type:")} ${item.type} ${chalk20.dim("Status:")} ${item.status}`
|
|
1867
1886
|
);
|
|
1868
1887
|
console.log();
|
|
1869
1888
|
}
|
|
1870
1889
|
function printAcceptanceCriteria(criteria) {
|
|
1871
1890
|
if (criteria.length === 0) return;
|
|
1872
|
-
console.log(
|
|
1891
|
+
console.log(chalk20.bold("Acceptance Criteria"));
|
|
1873
1892
|
for (const [i, ac] of criteria.entries()) {
|
|
1874
1893
|
console.log(` ${i + 1}. ${ac}`);
|
|
1875
1894
|
}
|
|
@@ -1881,7 +1900,7 @@ async function show(id) {
|
|
|
1881
1900
|
const { orm, item } = found;
|
|
1882
1901
|
printHeader(item);
|
|
1883
1902
|
if (item.description) {
|
|
1884
|
-
console.log(
|
|
1903
|
+
console.log(chalk20.bold("Description"));
|
|
1885
1904
|
console.log(item.description);
|
|
1886
1905
|
console.log();
|
|
1887
1906
|
}
|
|
@@ -1893,7 +1912,7 @@ async function show(id) {
|
|
|
1893
1912
|
function printComments(item) {
|
|
1894
1913
|
const entries = item.comments ?? [];
|
|
1895
1914
|
if (entries.length === 0) return;
|
|
1896
|
-
console.log(
|
|
1915
|
+
console.log(chalk20.bold("Comments"));
|
|
1897
1916
|
for (const entry of entries) {
|
|
1898
1917
|
console.log(` ${formatComment(entry)}`);
|
|
1899
1918
|
}
|
|
@@ -1907,7 +1926,7 @@ import { WebSocketServer } from "ws";
|
|
|
1907
1926
|
import {
|
|
1908
1927
|
createServer
|
|
1909
1928
|
} from "http";
|
|
1910
|
-
import
|
|
1929
|
+
import chalk21 from "chalk";
|
|
1911
1930
|
|
|
1912
1931
|
// src/shared/openBrowser.ts
|
|
1913
1932
|
import { exec } from "child_process";
|
|
@@ -1953,8 +1972,8 @@ function startWebServer(label2, port, handler, initialPath) {
|
|
|
1953
1972
|
handler(req, res, port);
|
|
1954
1973
|
});
|
|
1955
1974
|
server.listen(port, () => {
|
|
1956
|
-
console.log(
|
|
1957
|
-
console.log(
|
|
1975
|
+
console.log(chalk21.green(`${label2}: ${url}`));
|
|
1976
|
+
console.log(chalk21.dim("Press Ctrl+C to stop"));
|
|
1958
1977
|
openBrowser(url);
|
|
1959
1978
|
});
|
|
1960
1979
|
return server;
|
|
@@ -2395,7 +2414,7 @@ function handleSocket(ws, manager) {
|
|
|
2395
2414
|
}
|
|
2396
2415
|
|
|
2397
2416
|
// src/shared/getInstallDir.ts
|
|
2398
|
-
import { execSync as
|
|
2417
|
+
import { execSync as execSync4 } from "child_process";
|
|
2399
2418
|
import { dirname as dirname5, resolve as resolve4 } from "path";
|
|
2400
2419
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2401
2420
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
@@ -2405,7 +2424,7 @@ function getInstallDir() {
|
|
|
2405
2424
|
}
|
|
2406
2425
|
function isGitRepo(dir) {
|
|
2407
2426
|
try {
|
|
2408
|
-
const result =
|
|
2427
|
+
const result = execSync4("git rev-parse --show-toplevel", {
|
|
2409
2428
|
cwd: dir,
|
|
2410
2429
|
stdio: "pipe"
|
|
2411
2430
|
}).toString().trim();
|
|
@@ -2847,33 +2866,33 @@ async function web2(options2) {
|
|
|
2847
2866
|
}
|
|
2848
2867
|
|
|
2849
2868
|
// src/commands/backlog/launchMode.ts
|
|
2850
|
-
import
|
|
2869
|
+
import chalk23 from "chalk";
|
|
2851
2870
|
|
|
2852
2871
|
// src/commands/backlog/tryRunById.ts
|
|
2853
|
-
import
|
|
2872
|
+
import chalk22 from "chalk";
|
|
2854
2873
|
async function tryRunById(id, options2) {
|
|
2855
2874
|
const items2 = await loadBacklog();
|
|
2856
2875
|
const numericId = Number.parseInt(id, 10);
|
|
2857
2876
|
const item = Number.isNaN(numericId) ? void 0 : items2.find((i) => i.id === numericId);
|
|
2858
2877
|
if (!item) {
|
|
2859
|
-
console.log(
|
|
2878
|
+
console.log(chalk22.red(`Item #${id} not found.`));
|
|
2860
2879
|
return false;
|
|
2861
2880
|
}
|
|
2862
2881
|
if (item.status === "done") {
|
|
2863
|
-
console.log(
|
|
2882
|
+
console.log(chalk22.red(`Item #${id} is already done.`));
|
|
2864
2883
|
return false;
|
|
2865
2884
|
}
|
|
2866
2885
|
if (item.status === "wontdo") {
|
|
2867
|
-
console.log(
|
|
2886
|
+
console.log(chalk22.red(`Item #${id} is marked won't do.`));
|
|
2868
2887
|
return false;
|
|
2869
2888
|
}
|
|
2870
2889
|
if (isBlocked(item, items2)) {
|
|
2871
2890
|
console.log(
|
|
2872
|
-
|
|
2891
|
+
chalk22.red(`Item #${id} is blocked by unresolved dependencies.`)
|
|
2873
2892
|
);
|
|
2874
2893
|
return false;
|
|
2875
2894
|
}
|
|
2876
|
-
console.log(
|
|
2895
|
+
console.log(chalk22.bold(`
|
|
2877
2896
|
Running backlog item #${id}...
|
|
2878
2897
|
`));
|
|
2879
2898
|
await run(id, options2);
|
|
@@ -2882,6 +2901,7 @@ Running backlog item #${id}...
|
|
|
2882
2901
|
|
|
2883
2902
|
// src/commands/backlog/launchMode.ts
|
|
2884
2903
|
async function launchMode(slashCommand) {
|
|
2904
|
+
pullIfConfigured();
|
|
2885
2905
|
process.env.ASSIST_SESSION_ID = String(process.pid);
|
|
2886
2906
|
const { child, done: done2 } = spawnClaude(`/${slashCommand}`, { allowEdits: true });
|
|
2887
2907
|
watchForMarker(child);
|
|
@@ -2893,13 +2913,13 @@ async function launchMode(slashCommand) {
|
|
|
2893
2913
|
if (typeof signal.id === "string" && signal.id) {
|
|
2894
2914
|
if (await tryRunById(signal.id, { allowEdits: true })) return;
|
|
2895
2915
|
}
|
|
2896
|
-
console.log(
|
|
2916
|
+
console.log(chalk23.bold("\nChaining into assist next...\n"));
|
|
2897
2917
|
await next({ allowEdits: true });
|
|
2898
2918
|
}
|
|
2899
2919
|
}
|
|
2900
2920
|
|
|
2901
2921
|
// src/commands/backlog/refine.ts
|
|
2902
|
-
import
|
|
2922
|
+
import chalk24 from "chalk";
|
|
2903
2923
|
import enquirer3 from "enquirer";
|
|
2904
2924
|
async function pickItemForRefine() {
|
|
2905
2925
|
const items2 = await loadBacklog();
|
|
@@ -2907,12 +2927,12 @@ async function pickItemForRefine() {
|
|
|
2907
2927
|
(i) => i.status === "todo" || i.status === "in-progress"
|
|
2908
2928
|
);
|
|
2909
2929
|
if (active.length === 0) {
|
|
2910
|
-
console.log(
|
|
2930
|
+
console.log(chalk24.yellow("No active backlog items to refine."));
|
|
2911
2931
|
return void 0;
|
|
2912
2932
|
}
|
|
2913
2933
|
if (active.length === 1) {
|
|
2914
2934
|
const item = active[0];
|
|
2915
|
-
console.log(
|
|
2935
|
+
console.log(chalk24.bold(`Auto-selecting item #${item.id}: ${item.name}`));
|
|
2916
2936
|
return String(item.id);
|
|
2917
2937
|
}
|
|
2918
2938
|
const { selected } = await exitOnCancel(
|
|
@@ -2934,7 +2954,7 @@ async function refine(id) {
|
|
|
2934
2954
|
}
|
|
2935
2955
|
|
|
2936
2956
|
// src/commands/commit.ts
|
|
2937
|
-
import { execSync as
|
|
2957
|
+
import { execSync as execSync5 } from "child_process";
|
|
2938
2958
|
|
|
2939
2959
|
// src/shared/shellQuote.ts
|
|
2940
2960
|
function shellQuote(arg) {
|
|
@@ -2971,25 +2991,25 @@ function validateMessage(message, config) {
|
|
|
2971
2991
|
|
|
2972
2992
|
// src/commands/commit.ts
|
|
2973
2993
|
function commitStaged(message) {
|
|
2974
|
-
|
|
2975
|
-
return
|
|
2994
|
+
execSync5(`git commit -m ${shellQuote(message)}`, { stdio: "inherit" });
|
|
2995
|
+
return execSync5("git rev-parse --short=7 HEAD", {
|
|
2976
2996
|
encoding: "utf-8"
|
|
2977
2997
|
}).trim();
|
|
2978
2998
|
}
|
|
2979
2999
|
function stageAndCommit(files, message) {
|
|
2980
3000
|
const escaped = files.map(shellQuote).join(" ");
|
|
2981
|
-
|
|
3001
|
+
execSync5(`git add ${escaped}`, { stdio: "inherit" });
|
|
2982
3002
|
return commitStaged(message);
|
|
2983
3003
|
}
|
|
2984
3004
|
function execCommit(files, message, config) {
|
|
2985
3005
|
try {
|
|
2986
3006
|
if (config.commit?.pull) {
|
|
2987
|
-
|
|
3007
|
+
execSync5("git pull", { stdio: "inherit" });
|
|
2988
3008
|
}
|
|
2989
3009
|
const sha = files.length > 0 ? stageAndCommit(files, message) : commitStaged(message);
|
|
2990
3010
|
console.log(`Committed: ${sha}`);
|
|
2991
3011
|
if (config.commit?.push) {
|
|
2992
|
-
|
|
3012
|
+
execSync5("git push", { stdio: "inherit" });
|
|
2993
3013
|
console.log("Pushed to remote");
|
|
2994
3014
|
}
|
|
2995
3015
|
process.exit(0);
|
|
@@ -2999,7 +3019,7 @@ function execCommit(files, message, config) {
|
|
|
2999
3019
|
}
|
|
3000
3020
|
function commit(args) {
|
|
3001
3021
|
if (args[0] === "status") {
|
|
3002
|
-
|
|
3022
|
+
execSync5("git status && echo '---DIFF---' && git diff", {
|
|
3003
3023
|
stdio: "inherit"
|
|
3004
3024
|
});
|
|
3005
3025
|
return;
|
|
@@ -3016,9 +3036,9 @@ function commit(args) {
|
|
|
3016
3036
|
}
|
|
3017
3037
|
|
|
3018
3038
|
// src/commands/coverage.ts
|
|
3019
|
-
import { execSync as
|
|
3039
|
+
import { execSync as execSync6 } from "child_process";
|
|
3020
3040
|
function coverage() {
|
|
3021
|
-
const output =
|
|
3041
|
+
const output = execSync6(
|
|
3022
3042
|
"npx vitest run --coverage --coverage.include='src/**/*.ts' --coverage.all --coverage.reporter=text 2>&1",
|
|
3023
3043
|
{ encoding: "utf-8", timeout: 12e4 }
|
|
3024
3044
|
);
|
|
@@ -3031,10 +3051,10 @@ function coverage() {
|
|
|
3031
3051
|
}
|
|
3032
3052
|
|
|
3033
3053
|
// src/commands/verify/init/index.ts
|
|
3034
|
-
import
|
|
3054
|
+
import chalk39 from "chalk";
|
|
3035
3055
|
|
|
3036
3056
|
// src/shared/promptMultiselect.ts
|
|
3037
|
-
import
|
|
3057
|
+
import chalk25 from "chalk";
|
|
3038
3058
|
import enquirer4 from "enquirer";
|
|
3039
3059
|
async function promptMultiselect(message, options2) {
|
|
3040
3060
|
const { selected } = await exitOnCancel(
|
|
@@ -3044,7 +3064,7 @@ async function promptMultiselect(message, options2) {
|
|
|
3044
3064
|
message,
|
|
3045
3065
|
choices: options2.map((opt) => ({
|
|
3046
3066
|
name: opt.value,
|
|
3047
|
-
message: `${opt.name} - ${
|
|
3067
|
+
message: `${opt.name} - ${chalk25.dim(opt.description)}`
|
|
3048
3068
|
})),
|
|
3049
3069
|
// @ts-expect-error - enquirer types don't include symbols but it's supported
|
|
3050
3070
|
symbols: {
|
|
@@ -3061,7 +3081,7 @@ async function promptMultiselect(message, options2) {
|
|
|
3061
3081
|
// src/shared/readPackageJson.ts
|
|
3062
3082
|
import * as fs3 from "fs";
|
|
3063
3083
|
import * as path4 from "path";
|
|
3064
|
-
import
|
|
3084
|
+
import chalk26 from "chalk";
|
|
3065
3085
|
function findPackageJson() {
|
|
3066
3086
|
const packageJsonPath = path4.join(process.cwd(), "package.json");
|
|
3067
3087
|
if (fs3.existsSync(packageJsonPath)) {
|
|
@@ -3075,7 +3095,7 @@ function readPackageJson(filePath) {
|
|
|
3075
3095
|
function requirePackageJson() {
|
|
3076
3096
|
const packageJsonPath = findPackageJson();
|
|
3077
3097
|
if (!packageJsonPath) {
|
|
3078
|
-
console.error(
|
|
3098
|
+
console.error(chalk26.red("No package.json found in current directory"));
|
|
3079
3099
|
process.exit(1);
|
|
3080
3100
|
}
|
|
3081
3101
|
const pkg = readPackageJson(packageJsonPath);
|
|
@@ -3104,9 +3124,9 @@ function findPackageJsonWithVerifyScripts(startDir) {
|
|
|
3104
3124
|
}
|
|
3105
3125
|
|
|
3106
3126
|
// src/commands/verify/installPackage.ts
|
|
3107
|
-
import { execSync as
|
|
3127
|
+
import { execSync as execSync7 } from "child_process";
|
|
3108
3128
|
import { writeFileSync as writeFileSync4 } from "fs";
|
|
3109
|
-
import
|
|
3129
|
+
import chalk27 from "chalk";
|
|
3110
3130
|
function writePackageJson(filePath, pkg) {
|
|
3111
3131
|
writeFileSync4(filePath, `${JSON.stringify(pkg, null, 2)}
|
|
3112
3132
|
`);
|
|
@@ -3121,12 +3141,12 @@ function addScript(pkg, name, command) {
|
|
|
3121
3141
|
};
|
|
3122
3142
|
}
|
|
3123
3143
|
function installPackage(name, cwd) {
|
|
3124
|
-
console.log(
|
|
3144
|
+
console.log(chalk27.dim(`Installing ${name}...`));
|
|
3125
3145
|
try {
|
|
3126
|
-
|
|
3146
|
+
execSync7(`npm install -D ${name}`, { stdio: "inherit", cwd });
|
|
3127
3147
|
return true;
|
|
3128
3148
|
} catch {
|
|
3129
|
-
console.error(
|
|
3149
|
+
console.error(chalk27.red(`Failed to install ${name}`));
|
|
3130
3150
|
return false;
|
|
3131
3151
|
}
|
|
3132
3152
|
}
|
|
@@ -3180,9 +3200,9 @@ var expectedScripts = {
|
|
|
3180
3200
|
};
|
|
3181
3201
|
|
|
3182
3202
|
// src/commands/verify/setup/setupBuild.ts
|
|
3183
|
-
import
|
|
3203
|
+
import chalk28 from "chalk";
|
|
3184
3204
|
async function setupBuild(_packageJsonPath, writer, hasVite, hasTypescript) {
|
|
3185
|
-
console.log(
|
|
3205
|
+
console.log(chalk28.blue("\nSetting up build verification..."));
|
|
3186
3206
|
let command;
|
|
3187
3207
|
if (hasVite && hasTypescript) {
|
|
3188
3208
|
command = "tsc -b && vite build --logLevel error";
|
|
@@ -3191,21 +3211,21 @@ async function setupBuild(_packageJsonPath, writer, hasVite, hasTypescript) {
|
|
|
3191
3211
|
} else {
|
|
3192
3212
|
command = "npm run build";
|
|
3193
3213
|
}
|
|
3194
|
-
console.log(
|
|
3214
|
+
console.log(chalk28.dim(`Using: ${command}`));
|
|
3195
3215
|
writer("verify:build", command);
|
|
3196
3216
|
}
|
|
3197
3217
|
async function setupTypecheck(_packageJsonPath, writer) {
|
|
3198
|
-
console.log(
|
|
3218
|
+
console.log(chalk28.blue("\nSetting up typecheck verification..."));
|
|
3199
3219
|
const command = "tsc --noEmit";
|
|
3200
|
-
console.log(
|
|
3220
|
+
console.log(chalk28.dim(`Using: ${command}`));
|
|
3201
3221
|
writer("verify:typecheck", command);
|
|
3202
3222
|
}
|
|
3203
3223
|
|
|
3204
3224
|
// src/commands/verify/setup/setupDuplicateCode.ts
|
|
3205
3225
|
import * as path5 from "path";
|
|
3206
|
-
import
|
|
3226
|
+
import chalk29 from "chalk";
|
|
3207
3227
|
async function setupDuplicateCode(packageJsonPath, writer) {
|
|
3208
|
-
console.log(
|
|
3228
|
+
console.log(chalk29.blue("\nSetting up jscpd..."));
|
|
3209
3229
|
const cwd = path5.dirname(packageJsonPath);
|
|
3210
3230
|
const pkg = readPackageJson(packageJsonPath);
|
|
3211
3231
|
const hasJscpd = !!pkg.dependencies?.jscpd || !!pkg.devDependencies?.jscpd;
|
|
@@ -3217,12 +3237,12 @@ async function setupDuplicateCode(packageJsonPath, writer) {
|
|
|
3217
3237
|
|
|
3218
3238
|
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
3219
3239
|
import * as path6 from "path";
|
|
3220
|
-
import
|
|
3240
|
+
import chalk31 from "chalk";
|
|
3221
3241
|
|
|
3222
3242
|
// src/commands/verify/addToKnipIgnoreBinaries.ts
|
|
3223
3243
|
import { existsSync as existsSync13, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
|
|
3224
3244
|
import { join as join12 } from "path";
|
|
3225
|
-
import
|
|
3245
|
+
import chalk30 from "chalk";
|
|
3226
3246
|
function loadKnipConfig(knipJsonPath) {
|
|
3227
3247
|
if (existsSync13(knipJsonPath)) {
|
|
3228
3248
|
return JSON.parse(readFileSync8(knipJsonPath, "utf-8"));
|
|
@@ -3241,16 +3261,16 @@ function addToKnipIgnoreBinaries(cwd, binary) {
|
|
|
3241
3261
|
`${JSON.stringify(knipConfig, null, " ")}
|
|
3242
3262
|
`
|
|
3243
3263
|
);
|
|
3244
|
-
console.log(
|
|
3264
|
+
console.log(chalk30.dim(`Added '${binary}' to knip.json ignoreBinaries`));
|
|
3245
3265
|
}
|
|
3246
3266
|
} catch {
|
|
3247
|
-
console.log(
|
|
3267
|
+
console.log(chalk30.yellow("Warning: Could not update knip.json"));
|
|
3248
3268
|
}
|
|
3249
3269
|
}
|
|
3250
3270
|
|
|
3251
3271
|
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
3252
3272
|
async function setupHardcodedColors(packageJsonPath, writer, hasOpenColor) {
|
|
3253
|
-
console.log(
|
|
3273
|
+
console.log(chalk31.blue("\nSetting up hardcoded colors check..."));
|
|
3254
3274
|
const cwd = path6.dirname(packageJsonPath);
|
|
3255
3275
|
if (!hasOpenColor) {
|
|
3256
3276
|
installPackage("open-color", cwd);
|
|
@@ -3261,9 +3281,9 @@ async function setupHardcodedColors(packageJsonPath, writer, hasOpenColor) {
|
|
|
3261
3281
|
|
|
3262
3282
|
// src/commands/verify/setup/setupKnip.ts
|
|
3263
3283
|
import * as path7 from "path";
|
|
3264
|
-
import
|
|
3284
|
+
import chalk32 from "chalk";
|
|
3265
3285
|
async function setupKnip(packageJsonPath, writer) {
|
|
3266
|
-
console.log(
|
|
3286
|
+
console.log(chalk32.blue("\nSetting up knip..."));
|
|
3267
3287
|
const cwd = path7.dirname(packageJsonPath);
|
|
3268
3288
|
const pkg = readPackageJson(packageJsonPath);
|
|
3269
3289
|
if (!pkg.devDependencies?.knip && !installPackage("knip", cwd)) {
|
|
@@ -3274,14 +3294,14 @@ async function setupKnip(packageJsonPath, writer) {
|
|
|
3274
3294
|
|
|
3275
3295
|
// src/commands/verify/setup/setupLint.ts
|
|
3276
3296
|
import * as path8 from "path";
|
|
3277
|
-
import
|
|
3297
|
+
import chalk35 from "chalk";
|
|
3278
3298
|
|
|
3279
3299
|
// src/commands/lint/init.ts
|
|
3280
|
-
import { execSync as
|
|
3300
|
+
import { execSync as execSync9 } from "child_process";
|
|
3281
3301
|
import { existsSync as existsSync16, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "fs";
|
|
3282
3302
|
import { dirname as dirname11, join as join13 } from "path";
|
|
3283
3303
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3284
|
-
import
|
|
3304
|
+
import chalk34 from "chalk";
|
|
3285
3305
|
|
|
3286
3306
|
// src/shared/promptConfirm.ts
|
|
3287
3307
|
import enquirer5 from "enquirer";
|
|
@@ -3303,7 +3323,7 @@ async function promptConfirm(message, initial = true) {
|
|
|
3303
3323
|
}
|
|
3304
3324
|
|
|
3305
3325
|
// src/shared/removeEslint/index.ts
|
|
3306
|
-
import { execSync as
|
|
3326
|
+
import { execSync as execSync8 } from "child_process";
|
|
3307
3327
|
import { existsSync as existsSync15, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
|
|
3308
3328
|
|
|
3309
3329
|
// src/shared/removeEslint/removeEslintConfigFiles.ts
|
|
@@ -3338,7 +3358,7 @@ function removeEslint(options2 = {}) {
|
|
|
3338
3358
|
const removedConfigFiles = removeEslintConfigFiles();
|
|
3339
3359
|
if (removedFromPackageJson || removedConfigFiles) {
|
|
3340
3360
|
console.log("Running npm install...");
|
|
3341
|
-
|
|
3361
|
+
execSync8("npm install", { stdio: "inherit" });
|
|
3342
3362
|
return true;
|
|
3343
3363
|
}
|
|
3344
3364
|
return false;
|
|
@@ -3385,7 +3405,7 @@ function removeEslintScripts(scripts, options2) {
|
|
|
3385
3405
|
}
|
|
3386
3406
|
|
|
3387
3407
|
// src/utils/printDiff.ts
|
|
3388
|
-
import
|
|
3408
|
+
import chalk33 from "chalk";
|
|
3389
3409
|
import * as diff from "diff";
|
|
3390
3410
|
function normalizeJson(content) {
|
|
3391
3411
|
try {
|
|
@@ -3403,11 +3423,11 @@ function printDiff(oldContent, newContent) {
|
|
|
3403
3423
|
const lines = change.value.replace(/\n$/, "").split("\n");
|
|
3404
3424
|
for (const line of lines) {
|
|
3405
3425
|
if (change.added) {
|
|
3406
|
-
console.log(
|
|
3426
|
+
console.log(chalk33.green(`+ ${line}`));
|
|
3407
3427
|
} else if (change.removed) {
|
|
3408
|
-
console.log(
|
|
3428
|
+
console.log(chalk33.red(`- ${line}`));
|
|
3409
3429
|
} else {
|
|
3410
|
-
console.log(
|
|
3430
|
+
console.log(chalk33.dim(` ${line}`));
|
|
3411
3431
|
}
|
|
3412
3432
|
}
|
|
3413
3433
|
}
|
|
@@ -3420,7 +3440,7 @@ async function init() {
|
|
|
3420
3440
|
const biomeConfigPath = "biome.json";
|
|
3421
3441
|
if (!existsSync16(biomeConfigPath)) {
|
|
3422
3442
|
console.log("Initializing Biome...");
|
|
3423
|
-
|
|
3443
|
+
execSync9("npx @biomejs/biome init", { stdio: "inherit" });
|
|
3424
3444
|
}
|
|
3425
3445
|
if (!existsSync16(biomeConfigPath)) {
|
|
3426
3446
|
console.log("No biome.json found, skipping linter config");
|
|
@@ -3441,10 +3461,10 @@ async function init() {
|
|
|
3441
3461
|
console.log("biome.json already has the correct linter config");
|
|
3442
3462
|
return;
|
|
3443
3463
|
}
|
|
3444
|
-
console.log(
|
|
3464
|
+
console.log(chalk34.yellow("\n\u26A0\uFE0F biome.json will be updated:"));
|
|
3445
3465
|
console.log();
|
|
3446
3466
|
printDiff(oldContent, newContent);
|
|
3447
|
-
const confirm = await promptConfirm(
|
|
3467
|
+
const confirm = await promptConfirm(chalk34.red("Update biome.json?"));
|
|
3448
3468
|
if (!confirm) {
|
|
3449
3469
|
console.log("Skipped biome.json update");
|
|
3450
3470
|
return;
|
|
@@ -3455,7 +3475,7 @@ async function init() {
|
|
|
3455
3475
|
|
|
3456
3476
|
// src/commands/verify/setup/setupLint.ts
|
|
3457
3477
|
async function setupLint(packageJsonPath, writer) {
|
|
3458
|
-
console.log(
|
|
3478
|
+
console.log(chalk35.blue("\nSetting up biome..."));
|
|
3459
3479
|
const cwd = path8.dirname(packageJsonPath);
|
|
3460
3480
|
const pkg = readPackageJson(packageJsonPath);
|
|
3461
3481
|
if (!pkg.devDependencies?.["@biomejs/biome"]) {
|
|
@@ -3469,17 +3489,17 @@ async function setupLint(packageJsonPath, writer) {
|
|
|
3469
3489
|
|
|
3470
3490
|
// src/commands/verify/setup/setupMaintainability.ts
|
|
3471
3491
|
import * as path9 from "path";
|
|
3472
|
-
import
|
|
3492
|
+
import chalk36 from "chalk";
|
|
3473
3493
|
async function setupMaintainability(packageJsonPath, writer) {
|
|
3474
|
-
console.log(
|
|
3494
|
+
console.log(chalk36.blue("\nSetting up maintainability check..."));
|
|
3475
3495
|
addToKnipIgnoreBinaries(path9.dirname(packageJsonPath), "assist");
|
|
3476
3496
|
writer("verify:maintainability", expectedScripts["verify:maintainability"]);
|
|
3477
3497
|
}
|
|
3478
3498
|
|
|
3479
3499
|
// src/commands/verify/setup/setupSkott.ts
|
|
3480
|
-
import
|
|
3500
|
+
import chalk37 from "chalk";
|
|
3481
3501
|
async function setupSkott(_packageJsonPath, writer) {
|
|
3482
|
-
console.log(
|
|
3502
|
+
console.log(chalk37.blue("\nSetting up circular dependency check..."));
|
|
3483
3503
|
writer("verify:circular-deps", expectedScripts["verify:circular-deps"], {
|
|
3484
3504
|
quiet: true
|
|
3485
3505
|
});
|
|
@@ -3487,9 +3507,9 @@ async function setupSkott(_packageJsonPath, writer) {
|
|
|
3487
3507
|
|
|
3488
3508
|
// src/commands/verify/setup/setupTest.ts
|
|
3489
3509
|
import * as path10 from "path";
|
|
3490
|
-
import
|
|
3510
|
+
import chalk38 from "chalk";
|
|
3491
3511
|
async function setupTest(packageJsonPath, writer) {
|
|
3492
|
-
console.log(
|
|
3512
|
+
console.log(chalk38.blue("\nSetting up vitest..."));
|
|
3493
3513
|
const cwd = path10.dirname(packageJsonPath);
|
|
3494
3514
|
const pkg = readPackageJson(packageJsonPath);
|
|
3495
3515
|
if (!pkg.devDependencies?.vitest && !installPackage("vitest", cwd)) {
|
|
@@ -3655,25 +3675,25 @@ async function runSelectedSetups(selected, packageJsonPath, writer, handlers2) {
|
|
|
3655
3675
|
for (const choice of selected) {
|
|
3656
3676
|
await handlers2[choice]?.(packageJsonPath, writer);
|
|
3657
3677
|
}
|
|
3658
|
-
console.log(
|
|
3678
|
+
console.log(chalk39.green(`
|
|
3659
3679
|
Added ${selected.length} verify script(s):`));
|
|
3660
3680
|
for (const choice of selected) {
|
|
3661
|
-
console.log(
|
|
3681
|
+
console.log(chalk39.green(` - verify:${choice}`));
|
|
3662
3682
|
}
|
|
3663
|
-
console.log(
|
|
3683
|
+
console.log(chalk39.dim("\nRun 'assist verify' to run all verify scripts"));
|
|
3664
3684
|
}
|
|
3665
3685
|
async function promptForScripts(availableOptions) {
|
|
3666
3686
|
if (availableOptions.length === 0) {
|
|
3667
|
-
console.log(
|
|
3687
|
+
console.log(chalk39.green("All verify scripts are already configured!"));
|
|
3668
3688
|
return null;
|
|
3669
3689
|
}
|
|
3670
|
-
console.log(
|
|
3690
|
+
console.log(chalk39.bold("Available verify scripts to add:\n"));
|
|
3671
3691
|
const selected = await promptMultiselect(
|
|
3672
3692
|
"Select verify scripts to add:",
|
|
3673
3693
|
availableOptions
|
|
3674
3694
|
);
|
|
3675
3695
|
if (selected.length === 0) {
|
|
3676
|
-
console.log(
|
|
3696
|
+
console.log(chalk39.yellow("No scripts selected"));
|
|
3677
3697
|
return null;
|
|
3678
3698
|
}
|
|
3679
3699
|
return selected;
|
|
@@ -3693,17 +3713,17 @@ async function init2(options2 = {}) {
|
|
|
3693
3713
|
}
|
|
3694
3714
|
|
|
3695
3715
|
// src/commands/vscode/init/index.ts
|
|
3696
|
-
import
|
|
3716
|
+
import chalk41 from "chalk";
|
|
3697
3717
|
|
|
3698
3718
|
// src/commands/vscode/init/createLaunchJson.ts
|
|
3699
3719
|
import * as fs4 from "fs";
|
|
3700
3720
|
import * as path11 from "path";
|
|
3701
|
-
import
|
|
3721
|
+
import chalk40 from "chalk";
|
|
3702
3722
|
function ensureVscodeFolder() {
|
|
3703
3723
|
const vscodeDir = path11.join(process.cwd(), ".vscode");
|
|
3704
3724
|
if (!fs4.existsSync(vscodeDir)) {
|
|
3705
3725
|
fs4.mkdirSync(vscodeDir);
|
|
3706
|
-
console.log(
|
|
3726
|
+
console.log(chalk40.dim("Created .vscode folder"));
|
|
3707
3727
|
}
|
|
3708
3728
|
}
|
|
3709
3729
|
function removeVscodeFromGitignore() {
|
|
@@ -3718,7 +3738,7 @@ function removeVscodeFromGitignore() {
|
|
|
3718
3738
|
);
|
|
3719
3739
|
if (filteredLines.length !== lines.length) {
|
|
3720
3740
|
fs4.writeFileSync(gitignorePath, filteredLines.join("\n"));
|
|
3721
|
-
console.log(
|
|
3741
|
+
console.log(chalk40.dim("Removed .vscode references from .gitignore"));
|
|
3722
3742
|
}
|
|
3723
3743
|
}
|
|
3724
3744
|
function createLaunchJson(type) {
|
|
@@ -3737,7 +3757,7 @@ function createLaunchJson(type) {
|
|
|
3737
3757
|
const launchPath = path11.join(process.cwd(), ".vscode", "launch.json");
|
|
3738
3758
|
fs4.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
|
|
3739
3759
|
`);
|
|
3740
|
-
console.log(
|
|
3760
|
+
console.log(chalk40.green("Created .vscode/launch.json"));
|
|
3741
3761
|
}
|
|
3742
3762
|
function createSettingsJson() {
|
|
3743
3763
|
const settings = {
|
|
@@ -3750,7 +3770,7 @@ function createSettingsJson() {
|
|
|
3750
3770
|
const settingsPath = path11.join(process.cwd(), ".vscode", "settings.json");
|
|
3751
3771
|
fs4.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
|
|
3752
3772
|
`);
|
|
3753
|
-
console.log(
|
|
3773
|
+
console.log(chalk40.green("Created .vscode/settings.json"));
|
|
3754
3774
|
}
|
|
3755
3775
|
function createExtensionsJson() {
|
|
3756
3776
|
const extensions = {
|
|
@@ -3762,7 +3782,7 @@ function createExtensionsJson() {
|
|
|
3762
3782
|
`${JSON.stringify(extensions, null, " ")}
|
|
3763
3783
|
`
|
|
3764
3784
|
);
|
|
3765
|
-
console.log(
|
|
3785
|
+
console.log(chalk40.green("Created .vscode/extensions.json"));
|
|
3766
3786
|
}
|
|
3767
3787
|
|
|
3768
3788
|
// src/commands/vscode/init/detectVscodeSetup.ts
|
|
@@ -3819,7 +3839,7 @@ function applySelections(selected, setup2) {
|
|
|
3819
3839
|
for (const choice of selected) handlers2[choice]?.();
|
|
3820
3840
|
}
|
|
3821
3841
|
async function promptForOptions(options2) {
|
|
3822
|
-
console.log(
|
|
3842
|
+
console.log(chalk41.bold("Available VS Code configurations to add:\n"));
|
|
3823
3843
|
return promptMultiselect("Select configurations to add:", options2);
|
|
3824
3844
|
}
|
|
3825
3845
|
async function init3({ all = false } = {}) {
|
|
@@ -3827,17 +3847,17 @@ async function init3({ all = false } = {}) {
|
|
|
3827
3847
|
const setup2 = detectVscodeSetup(pkg);
|
|
3828
3848
|
const options2 = getAvailableOptions2(setup2);
|
|
3829
3849
|
if (options2.length === 0) {
|
|
3830
|
-
console.log(
|
|
3850
|
+
console.log(chalk41.green("VS Code configuration already exists!"));
|
|
3831
3851
|
return;
|
|
3832
3852
|
}
|
|
3833
3853
|
const selected = all ? options2.map((o) => o.value) : await promptForOptions(options2);
|
|
3834
3854
|
if (selected.length === 0) {
|
|
3835
|
-
console.log(
|
|
3855
|
+
console.log(chalk41.yellow("No configurations selected"));
|
|
3836
3856
|
return;
|
|
3837
3857
|
}
|
|
3838
3858
|
applySelections(selected, setup2);
|
|
3839
3859
|
console.log(
|
|
3840
|
-
|
|
3860
|
+
chalk41.green(`
|
|
3841
3861
|
Added ${selected.length} VS Code configuration(s)`)
|
|
3842
3862
|
);
|
|
3843
3863
|
}
|
|
@@ -3850,7 +3870,7 @@ async function init4() {
|
|
|
3850
3870
|
|
|
3851
3871
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
3852
3872
|
import path18 from "path";
|
|
3853
|
-
import
|
|
3873
|
+
import chalk43 from "chalk";
|
|
3854
3874
|
|
|
3855
3875
|
// src/commands/lint/lint/checkFileNames.ts
|
|
3856
3876
|
import fs7 from "fs";
|
|
@@ -3930,7 +3950,7 @@ function checkFileNames() {
|
|
|
3930
3950
|
}
|
|
3931
3951
|
|
|
3932
3952
|
// src/commands/lint/lint/fixFileNameViolations.ts
|
|
3933
|
-
import
|
|
3953
|
+
import chalk42 from "chalk";
|
|
3934
3954
|
|
|
3935
3955
|
// src/commands/lint/lint/applyMoves.ts
|
|
3936
3956
|
import fs8 from "fs";
|
|
@@ -4015,25 +4035,25 @@ function fixFileNameViolations(moves) {
|
|
|
4015
4035
|
const start3 = performance.now();
|
|
4016
4036
|
const project = createLintProject();
|
|
4017
4037
|
const cwd = process.cwd();
|
|
4018
|
-
applyMoves(project, moves, cwd, (line) => console.log(
|
|
4038
|
+
applyMoves(project, moves, cwd, (line) => console.log(chalk42.green(line)));
|
|
4019
4039
|
const ms = (performance.now() - start3).toFixed(0);
|
|
4020
|
-
console.log(
|
|
4040
|
+
console.log(chalk42.dim(` Done in ${ms}ms`));
|
|
4021
4041
|
}
|
|
4022
4042
|
|
|
4023
4043
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
4024
4044
|
function reportViolations(violations) {
|
|
4025
|
-
console.error(
|
|
4045
|
+
console.error(chalk43.red("\nFile name check failed:\n"));
|
|
4026
4046
|
console.error(
|
|
4027
|
-
|
|
4047
|
+
chalk43.red(
|
|
4028
4048
|
" Files without classes or React components should not start with a capital letter.\n"
|
|
4029
4049
|
)
|
|
4030
4050
|
);
|
|
4031
4051
|
for (const violation of violations) {
|
|
4032
|
-
console.error(
|
|
4033
|
-
console.error(
|
|
4052
|
+
console.error(chalk43.red(` ${violation.filePath}`));
|
|
4053
|
+
console.error(chalk43.gray(` Rename to: ${violation.suggestedName}
|
|
4034
4054
|
`));
|
|
4035
4055
|
}
|
|
4036
|
-
console.error(
|
|
4056
|
+
console.error(chalk43.dim(" Run with -f to auto-fix.\n"));
|
|
4037
4057
|
}
|
|
4038
4058
|
function runFileNameCheck(fix = false) {
|
|
4039
4059
|
const violations = checkFileNames();
|
|
@@ -4062,17 +4082,17 @@ function runFileNameCheck(fix = false) {
|
|
|
4062
4082
|
import fs10 from "fs";
|
|
4063
4083
|
|
|
4064
4084
|
// src/commands/lint/shared.ts
|
|
4065
|
-
import
|
|
4085
|
+
import chalk44 from "chalk";
|
|
4066
4086
|
function reportViolations2(violations, checkName, errorMessage, successMessage) {
|
|
4067
4087
|
if (violations.length > 0) {
|
|
4068
|
-
console.error(
|
|
4088
|
+
console.error(chalk44.red(`
|
|
4069
4089
|
${checkName} failed:
|
|
4070
4090
|
`));
|
|
4071
|
-
console.error(
|
|
4091
|
+
console.error(chalk44.red(` ${errorMessage}
|
|
4072
4092
|
`));
|
|
4073
4093
|
for (const violation of violations) {
|
|
4074
|
-
console.error(
|
|
4075
|
-
console.error(
|
|
4094
|
+
console.error(chalk44.red(` ${violation.filePath}:${violation.line}`));
|
|
4095
|
+
console.error(chalk44.gray(` ${violation.content}
|
|
4076
4096
|
`));
|
|
4077
4097
|
}
|
|
4078
4098
|
return false;
|
|
@@ -4166,17 +4186,17 @@ function lint(options2 = {}) {
|
|
|
4166
4186
|
}
|
|
4167
4187
|
|
|
4168
4188
|
// src/commands/new/registerNew/newCli/index.ts
|
|
4169
|
-
import { execSync as
|
|
4189
|
+
import { execSync as execSync15 } from "child_process";
|
|
4170
4190
|
import { basename as basename3, resolve as resolve6 } from "path";
|
|
4171
4191
|
|
|
4172
4192
|
// src/commands/verify/hardcodedColors.ts
|
|
4173
|
-
import { execSync as
|
|
4193
|
+
import { execSync as execSync10 } from "child_process";
|
|
4174
4194
|
import { minimatch } from "minimatch";
|
|
4175
4195
|
var pattern = "0x[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,6}";
|
|
4176
4196
|
function hardcodedColors() {
|
|
4177
4197
|
const ignoreGlobs = loadConfig().hardcodedColors?.ignore ?? [];
|
|
4178
4198
|
try {
|
|
4179
|
-
const output =
|
|
4199
|
+
const output = execSync10(`grep -rEnH '${pattern}' src/`, {
|
|
4180
4200
|
encoding: "utf-8"
|
|
4181
4201
|
});
|
|
4182
4202
|
const lines = output.trim().split("\n").filter((line) => {
|
|
@@ -4257,10 +4277,10 @@ function list() {
|
|
|
4257
4277
|
}
|
|
4258
4278
|
|
|
4259
4279
|
// src/commands/verify/noVenv.ts
|
|
4260
|
-
import { execSync as
|
|
4280
|
+
import { execSync as execSync11 } from "child_process";
|
|
4261
4281
|
function noVenv() {
|
|
4262
4282
|
try {
|
|
4263
|
-
const output =
|
|
4283
|
+
const output = execSync11(
|
|
4264
4284
|
"find . -type d -name venv -not -path '*/node_modules/*'",
|
|
4265
4285
|
{
|
|
4266
4286
|
encoding: "utf-8"
|
|
@@ -4292,9 +4312,9 @@ Total: ${folders.length} venv folder(s)`);
|
|
|
4292
4312
|
import { minimatch as minimatch2 } from "minimatch";
|
|
4293
4313
|
|
|
4294
4314
|
// src/commands/verify/run/getChangedFiles.ts
|
|
4295
|
-
import { execSync as
|
|
4315
|
+
import { execSync as execSync12 } from "child_process";
|
|
4296
4316
|
function getChangedFiles() {
|
|
4297
|
-
const output =
|
|
4317
|
+
const output = execSync12("git diff --name-only HEAD", {
|
|
4298
4318
|
encoding: "utf-8"
|
|
4299
4319
|
}).trim();
|
|
4300
4320
|
if (output === "") return [];
|
|
@@ -4465,25 +4485,25 @@ async function run2(options2 = {}) {
|
|
|
4465
4485
|
}
|
|
4466
4486
|
|
|
4467
4487
|
// src/commands/new/registerNew/initGit.ts
|
|
4468
|
-
import { execSync as
|
|
4488
|
+
import { execSync as execSync13 } from "child_process";
|
|
4469
4489
|
import { writeFileSync as writeFileSync9 } from "fs";
|
|
4470
4490
|
function initGit() {
|
|
4471
4491
|
console.log("Initializing git repository...");
|
|
4472
|
-
|
|
4492
|
+
execSync13("git init", { stdio: "inherit" });
|
|
4473
4493
|
writeFileSync9(".gitignore", "dist\nnode_modules\n");
|
|
4474
4494
|
}
|
|
4475
4495
|
|
|
4476
4496
|
// src/commands/new/registerNew/newCli/initPackageJson.ts
|
|
4477
|
-
import { execSync as
|
|
4497
|
+
import { execSync as execSync14 } from "child_process";
|
|
4478
4498
|
function initPackageJson(name) {
|
|
4479
4499
|
console.log("Initializing package.json...");
|
|
4480
|
-
|
|
4500
|
+
execSync14("npm init -y", { stdio: "inherit" });
|
|
4481
4501
|
console.log("Configuring package.json...");
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4502
|
+
execSync14("npm pkg delete main", { stdio: "inherit" });
|
|
4503
|
+
execSync14("npm pkg set type=module", { stdio: "inherit" });
|
|
4504
|
+
execSync14(`npm pkg set bin.${name}=./dist/index.js`, { stdio: "inherit" });
|
|
4505
|
+
execSync14("npm pkg set scripts.build=tsup", { stdio: "inherit" });
|
|
4506
|
+
execSync14('npm pkg set scripts.start="node dist/index.js"', {
|
|
4487
4507
|
stdio: "inherit"
|
|
4488
4508
|
});
|
|
4489
4509
|
}
|
|
@@ -4548,8 +4568,8 @@ async function newCli() {
|
|
|
4548
4568
|
initGit();
|
|
4549
4569
|
initPackageJson(name);
|
|
4550
4570
|
console.log("Installing dependencies...");
|
|
4551
|
-
|
|
4552
|
-
|
|
4571
|
+
execSync15("npm install commander", { stdio: "inherit" });
|
|
4572
|
+
execSync15("npm install -D tsup typescript @types/node", {
|
|
4553
4573
|
stdio: "inherit"
|
|
4554
4574
|
});
|
|
4555
4575
|
writeCliTemplate(name);
|
|
@@ -4558,19 +4578,19 @@ async function newCli() {
|
|
|
4558
4578
|
}
|
|
4559
4579
|
|
|
4560
4580
|
// src/commands/new/registerNew/newProject.ts
|
|
4561
|
-
import { execSync as
|
|
4581
|
+
import { execSync as execSync17 } from "child_process";
|
|
4562
4582
|
import { existsSync as existsSync20, readFileSync as readFileSync13, writeFileSync as writeFileSync12 } from "fs";
|
|
4563
4583
|
|
|
4564
4584
|
// src/commands/deploy/init/index.ts
|
|
4565
|
-
import { execSync as
|
|
4566
|
-
import
|
|
4585
|
+
import { execSync as execSync16 } from "child_process";
|
|
4586
|
+
import chalk46 from "chalk";
|
|
4567
4587
|
import enquirer6 from "enquirer";
|
|
4568
4588
|
|
|
4569
4589
|
// src/commands/deploy/init/updateWorkflow.ts
|
|
4570
4590
|
import { existsSync as existsSync19, mkdirSync as mkdirSync3, readFileSync as readFileSync12, writeFileSync as writeFileSync11 } from "fs";
|
|
4571
4591
|
import { dirname as dirname16, join as join16 } from "path";
|
|
4572
4592
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
4573
|
-
import
|
|
4593
|
+
import chalk45 from "chalk";
|
|
4574
4594
|
var WORKFLOW_PATH = ".github/workflows/build.yml";
|
|
4575
4595
|
var __dirname4 = dirname16(fileURLToPath4(import.meta.url));
|
|
4576
4596
|
function getExistingSiteId() {
|
|
@@ -4595,67 +4615,67 @@ async function updateWorkflow(siteId) {
|
|
|
4595
4615
|
if (existsSync19(WORKFLOW_PATH)) {
|
|
4596
4616
|
const oldContent = readFileSync12(WORKFLOW_PATH, "utf-8");
|
|
4597
4617
|
if (oldContent === newContent) {
|
|
4598
|
-
console.log(
|
|
4618
|
+
console.log(chalk45.green("build.yml is already up to date"));
|
|
4599
4619
|
return;
|
|
4600
4620
|
}
|
|
4601
|
-
console.log(
|
|
4621
|
+
console.log(chalk45.yellow("\nbuild.yml will be updated:"));
|
|
4602
4622
|
console.log();
|
|
4603
4623
|
printDiff(oldContent, newContent);
|
|
4604
|
-
const confirm = await promptConfirm(
|
|
4624
|
+
const confirm = await promptConfirm(chalk45.red("Update build.yml?"));
|
|
4605
4625
|
if (!confirm) {
|
|
4606
4626
|
console.log("Skipped build.yml update");
|
|
4607
4627
|
return;
|
|
4608
4628
|
}
|
|
4609
4629
|
}
|
|
4610
4630
|
writeFileSync11(WORKFLOW_PATH, newContent);
|
|
4611
|
-
console.log(
|
|
4631
|
+
console.log(chalk45.green(`
|
|
4612
4632
|
Created ${WORKFLOW_PATH}`));
|
|
4613
4633
|
}
|
|
4614
4634
|
|
|
4615
4635
|
// src/commands/deploy/init/index.ts
|
|
4616
4636
|
async function ensureNetlifyCli() {
|
|
4617
4637
|
try {
|
|
4618
|
-
|
|
4638
|
+
execSync16("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
4619
4639
|
} catch (error) {
|
|
4620
4640
|
if (!(error instanceof Error) || !error.message.includes("command not found"))
|
|
4621
4641
|
throw error;
|
|
4622
|
-
console.error(
|
|
4642
|
+
console.error(chalk46.red("\nNetlify CLI is not installed.\n"));
|
|
4623
4643
|
const install = await promptConfirm("Would you like to install it now?");
|
|
4624
4644
|
if (!install) {
|
|
4625
4645
|
console.log(
|
|
4626
|
-
|
|
4646
|
+
chalk46.yellow(
|
|
4627
4647
|
"\nInstall it manually with: npm install -g netlify-cli\n"
|
|
4628
4648
|
)
|
|
4629
4649
|
);
|
|
4630
4650
|
process.exit(1);
|
|
4631
4651
|
}
|
|
4632
|
-
console.log(
|
|
4633
|
-
|
|
4652
|
+
console.log(chalk46.dim("\nInstalling netlify-cli...\n"));
|
|
4653
|
+
execSync16("npm install -g netlify-cli", { stdio: "inherit" });
|
|
4634
4654
|
console.log();
|
|
4635
|
-
|
|
4655
|
+
execSync16("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
4636
4656
|
}
|
|
4637
4657
|
}
|
|
4638
4658
|
function printSetupInstructions() {
|
|
4639
|
-
console.log(
|
|
4659
|
+
console.log(chalk46.bold("\nDeployment initialized successfully!"));
|
|
4640
4660
|
console.log(
|
|
4641
|
-
|
|
4661
|
+
chalk46.yellow("\nTo complete setup, create a personal access token at:")
|
|
4642
4662
|
);
|
|
4643
4663
|
console.log(
|
|
4644
|
-
|
|
4664
|
+
chalk46.cyan(
|
|
4645
4665
|
"https://app.netlify.com/user/applications#personal-access-tokens"
|
|
4646
4666
|
)
|
|
4647
4667
|
);
|
|
4648
4668
|
console.log(
|
|
4649
|
-
|
|
4669
|
+
chalk46.yellow(
|
|
4650
4670
|
"\nThen add it as NETLIFY_AUTH_TOKEN in your GitHub repository secrets."
|
|
4651
4671
|
)
|
|
4652
4672
|
);
|
|
4653
4673
|
}
|
|
4654
4674
|
async function init5() {
|
|
4655
|
-
console.log(
|
|
4675
|
+
console.log(chalk46.bold("Initializing Netlify deployment...\n"));
|
|
4656
4676
|
const existingSiteId = getExistingSiteId();
|
|
4657
4677
|
if (existingSiteId) {
|
|
4658
|
-
console.log(
|
|
4678
|
+
console.log(chalk46.dim(`Using existing site ID: ${existingSiteId}
|
|
4659
4679
|
`));
|
|
4660
4680
|
await updateWorkflow(existingSiteId);
|
|
4661
4681
|
return;
|
|
@@ -4675,7 +4695,7 @@ async function init5() {
|
|
|
4675
4695
|
// src/commands/new/registerNew/newProject.ts
|
|
4676
4696
|
async function newProject() {
|
|
4677
4697
|
console.log("Initializing Vite with react-ts template...");
|
|
4678
|
-
|
|
4698
|
+
execSync17("npm create vite@latest . -- --template react-ts", {
|
|
4679
4699
|
stdio: "inherit"
|
|
4680
4700
|
});
|
|
4681
4701
|
initGit();
|
|
@@ -4867,11 +4887,11 @@ function activityChart(data, range) {
|
|
|
4867
4887
|
}
|
|
4868
4888
|
|
|
4869
4889
|
// src/commands/activity/fetchCommitsPerDay.ts
|
|
4870
|
-
import { execSync as
|
|
4890
|
+
import { execSync as execSync18 } from "child_process";
|
|
4871
4891
|
function fetchContributions(from, to) {
|
|
4872
4892
|
const query = `{ viewer { contributionsCollection(from: "${from}T00:00:00Z", to: "${to}T23:59:59Z") { contributionCalendar { weeks { contributionDays { date contributionCount } } } } } }`;
|
|
4873
4893
|
const jq = ".data.viewer.contributionsCollection.contributionCalendar.weeks[].contributionDays[]";
|
|
4874
|
-
const raw =
|
|
4894
|
+
const raw = execSync18(`gh api graphql -f query='${query}' --jq '${jq}'`, {
|
|
4875
4895
|
encoding: "utf-8"
|
|
4876
4896
|
}).trim();
|
|
4877
4897
|
if (!raw) return [];
|
|
@@ -4933,26 +4953,26 @@ function registerActivity(program2) {
|
|
|
4933
4953
|
}
|
|
4934
4954
|
|
|
4935
4955
|
// src/commands/backlog/comment/index.ts
|
|
4936
|
-
import
|
|
4956
|
+
import chalk47 from "chalk";
|
|
4937
4957
|
async function comment(id, text2) {
|
|
4938
4958
|
const found = await findOneItem(id);
|
|
4939
4959
|
if (!found) process.exit(1);
|
|
4940
4960
|
await appendComment(found.orm, found.item.id, text2);
|
|
4941
|
-
console.log(
|
|
4961
|
+
console.log(chalk47.green(`Comment added to item #${id}.`));
|
|
4942
4962
|
}
|
|
4943
4963
|
|
|
4944
4964
|
// src/commands/backlog/comments/index.ts
|
|
4945
|
-
import
|
|
4965
|
+
import chalk48 from "chalk";
|
|
4946
4966
|
async function comments2(id) {
|
|
4947
4967
|
const found = await findOneItem(id);
|
|
4948
4968
|
if (!found) process.exit(1);
|
|
4949
4969
|
const { item } = found;
|
|
4950
4970
|
const entries = item.comments ?? [];
|
|
4951
4971
|
if (entries.length === 0) {
|
|
4952
|
-
console.log(
|
|
4972
|
+
console.log(chalk48.dim(`No comments on item #${id}.`));
|
|
4953
4973
|
return;
|
|
4954
4974
|
}
|
|
4955
|
-
console.log(
|
|
4975
|
+
console.log(chalk48.bold(`Comments for #${id}: ${item.name}
|
|
4956
4976
|
`));
|
|
4957
4977
|
for (const entry of entries) {
|
|
4958
4978
|
console.log(`${formatComment(entry)}
|
|
@@ -4961,7 +4981,7 @@ async function comments2(id) {
|
|
|
4961
4981
|
}
|
|
4962
4982
|
|
|
4963
4983
|
// src/commands/backlog/delete-comment/index.ts
|
|
4964
|
-
import
|
|
4984
|
+
import chalk49 from "chalk";
|
|
4965
4985
|
|
|
4966
4986
|
// src/commands/backlog/deleteComment.ts
|
|
4967
4987
|
import { and as and2, eq as eq12 } from "drizzle-orm";
|
|
@@ -4985,16 +5005,16 @@ async function deleteCommentCmd(id, commentId) {
|
|
|
4985
5005
|
switch (outcome) {
|
|
4986
5006
|
case "deleted":
|
|
4987
5007
|
console.log(
|
|
4988
|
-
|
|
5008
|
+
chalk49.green(`Comment #${commentId} deleted from item #${id}.`)
|
|
4989
5009
|
);
|
|
4990
5010
|
break;
|
|
4991
5011
|
case "not-found":
|
|
4992
|
-
console.log(
|
|
5012
|
+
console.log(chalk49.red(`Comment #${commentId} not found on item #${id}.`));
|
|
4993
5013
|
process.exit(1);
|
|
4994
5014
|
break;
|
|
4995
5015
|
case "is-summary":
|
|
4996
5016
|
console.log(
|
|
4997
|
-
|
|
5017
|
+
chalk49.red(
|
|
4998
5018
|
`Comment #${commentId} is a phase summary and cannot be deleted.`
|
|
4999
5019
|
)
|
|
5000
5020
|
);
|
|
@@ -5012,7 +5032,7 @@ function registerCommentCommands(cmd) {
|
|
|
5012
5032
|
|
|
5013
5033
|
// src/commands/backlog/export/index.ts
|
|
5014
5034
|
import { writeFile } from "fs/promises";
|
|
5015
|
-
import
|
|
5035
|
+
import chalk50 from "chalk";
|
|
5016
5036
|
|
|
5017
5037
|
// src/commands/backlog/dump/DumpTable.ts
|
|
5018
5038
|
var DUMP_FORMAT = "assist-backlog-dump";
|
|
@@ -5079,7 +5099,7 @@ async function exportBacklog(file) {
|
|
|
5079
5099
|
if (file) {
|
|
5080
5100
|
await writeFile(file, dump);
|
|
5081
5101
|
console.error(
|
|
5082
|
-
|
|
5102
|
+
chalk50.green(`Exported backlog to ${file} (${dump.length} bytes).`)
|
|
5083
5103
|
);
|
|
5084
5104
|
return;
|
|
5085
5105
|
}
|
|
@@ -5095,7 +5115,7 @@ function registerExportCommand(cmd) {
|
|
|
5095
5115
|
|
|
5096
5116
|
// src/commands/backlog/import/index.ts
|
|
5097
5117
|
import { readFile } from "fs/promises";
|
|
5098
|
-
import
|
|
5118
|
+
import chalk52 from "chalk";
|
|
5099
5119
|
|
|
5100
5120
|
// src/commands/backlog/dump/countCopyRows.ts
|
|
5101
5121
|
function countCopyRows(data) {
|
|
@@ -5172,7 +5192,7 @@ function validateDump({ header, sections }) {
|
|
|
5172
5192
|
}
|
|
5173
5193
|
|
|
5174
5194
|
// src/commands/backlog/import/confirmReplace.ts
|
|
5175
|
-
import
|
|
5195
|
+
import chalk51 from "chalk";
|
|
5176
5196
|
async function countRows(client, table) {
|
|
5177
5197
|
const { rows } = await client.query(
|
|
5178
5198
|
`SELECT count(*)::int AS n FROM ${table}`
|
|
@@ -5183,7 +5203,7 @@ function printSummary(current, incoming) {
|
|
|
5183
5203
|
const lines = DUMP_TABLES.map(
|
|
5184
5204
|
(t, i) => ` ${t.name}: ${current[i]} \u2192 ${incoming[i]} rows`
|
|
5185
5205
|
);
|
|
5186
|
-
console.error(
|
|
5206
|
+
console.error(chalk51.bold("\nThis will REPLACE all backlog data:"));
|
|
5187
5207
|
console.error(`${lines.join("\n")}
|
|
5188
5208
|
`);
|
|
5189
5209
|
}
|
|
@@ -5259,13 +5279,13 @@ async function importBacklog(file, options2 = {}) {
|
|
|
5259
5279
|
);
|
|
5260
5280
|
await withBacklogClient(async (client) => {
|
|
5261
5281
|
if (!options2.yes && !await confirmReplace(client, incoming, !file)) {
|
|
5262
|
-
console.error(
|
|
5282
|
+
console.error(chalk52.yellow("Import cancelled; no changes made."));
|
|
5263
5283
|
return;
|
|
5264
5284
|
}
|
|
5265
5285
|
await restore(client, parsed);
|
|
5266
5286
|
const total = incoming.reduce((sum, n) => sum + n, 0);
|
|
5267
5287
|
console.error(
|
|
5268
|
-
|
|
5288
|
+
chalk52.green(
|
|
5269
5289
|
`Imported backlog: ${total} rows restored across ${DUMP_TABLES.length} tables.`
|
|
5270
5290
|
)
|
|
5271
5291
|
);
|
|
@@ -5282,7 +5302,7 @@ function registerImportCommand(cmd) {
|
|
|
5282
5302
|
}
|
|
5283
5303
|
|
|
5284
5304
|
// src/commands/backlog/add/index.ts
|
|
5285
|
-
import
|
|
5305
|
+
import chalk53 from "chalk";
|
|
5286
5306
|
|
|
5287
5307
|
// src/commands/backlog/add/shared.ts
|
|
5288
5308
|
import { spawnSync } from "child_process";
|
|
@@ -5372,11 +5392,11 @@ async function add(options2) {
|
|
|
5372
5392
|
},
|
|
5373
5393
|
getOrigin()
|
|
5374
5394
|
);
|
|
5375
|
-
console.log(
|
|
5395
|
+
console.log(chalk53.green(`Added item #${id}: ${name}`));
|
|
5376
5396
|
}
|
|
5377
5397
|
|
|
5378
5398
|
// src/commands/backlog/addPhase.ts
|
|
5379
|
-
import
|
|
5399
|
+
import chalk55 from "chalk";
|
|
5380
5400
|
|
|
5381
5401
|
// src/commands/backlog/insertPhaseAt.ts
|
|
5382
5402
|
import { eq as eq14 } from "drizzle-orm";
|
|
@@ -5406,7 +5426,7 @@ async function insertPhaseAt(orm, itemId, phaseIdx, name, tasks, manualChecks, c
|
|
|
5406
5426
|
}
|
|
5407
5427
|
|
|
5408
5428
|
// src/commands/backlog/resolveInsertPosition.ts
|
|
5409
|
-
import
|
|
5429
|
+
import chalk54 from "chalk";
|
|
5410
5430
|
import { count, eq as eq15 } from "drizzle-orm";
|
|
5411
5431
|
async function resolveInsertPosition(orm, itemId, position) {
|
|
5412
5432
|
const [row] = await orm.select({ cnt: count() }).from(planPhases).where(eq15(planPhases.itemId, itemId));
|
|
@@ -5415,7 +5435,7 @@ async function resolveInsertPosition(orm, itemId, position) {
|
|
|
5415
5435
|
const pos = Number.parseInt(position, 10);
|
|
5416
5436
|
if (pos < 1 || pos > phaseCount + 1) {
|
|
5417
5437
|
console.log(
|
|
5418
|
-
|
|
5438
|
+
chalk54.red(
|
|
5419
5439
|
`Position ${pos} is out of range. Must be between 1 and ${phaseCount + 1}.`
|
|
5420
5440
|
)
|
|
5421
5441
|
);
|
|
@@ -5436,7 +5456,7 @@ async function addPhase(id, name, options2) {
|
|
|
5436
5456
|
if (!found) return;
|
|
5437
5457
|
const tasks = options2.task ?? [];
|
|
5438
5458
|
if (tasks.length === 0) {
|
|
5439
|
-
console.log(
|
|
5459
|
+
console.log(chalk55.red("At least one --task is required."));
|
|
5440
5460
|
process.exitCode = 1;
|
|
5441
5461
|
return;
|
|
5442
5462
|
}
|
|
@@ -5455,25 +5475,25 @@ async function addPhase(id, name, options2) {
|
|
|
5455
5475
|
);
|
|
5456
5476
|
const verb = options2.position !== void 0 ? "Inserted" : "Added";
|
|
5457
5477
|
console.log(
|
|
5458
|
-
|
|
5478
|
+
chalk55.green(
|
|
5459
5479
|
`${verb} phase ${phaseIdx + 1} "${name}" to item #${itemId} with ${tasks.length} task(s).`
|
|
5460
5480
|
)
|
|
5461
5481
|
);
|
|
5462
5482
|
}
|
|
5463
5483
|
|
|
5464
5484
|
// src/commands/backlog/init/index.ts
|
|
5465
|
-
import
|
|
5485
|
+
import chalk56 from "chalk";
|
|
5466
5486
|
async function init6() {
|
|
5467
5487
|
await getBacklogOrm();
|
|
5468
5488
|
console.log(
|
|
5469
|
-
|
|
5489
|
+
chalk56.green(
|
|
5470
5490
|
`Backlog database ready. This repository maps to origin: ${getOrigin()}`
|
|
5471
5491
|
)
|
|
5472
5492
|
);
|
|
5473
5493
|
}
|
|
5474
5494
|
|
|
5475
5495
|
// src/commands/backlog/list/index.ts
|
|
5476
|
-
import
|
|
5496
|
+
import chalk57 from "chalk";
|
|
5477
5497
|
|
|
5478
5498
|
// src/commands/backlog/originDisplayName.ts
|
|
5479
5499
|
function originDisplayName(origin) {
|
|
@@ -5525,7 +5545,7 @@ async function list2(options2) {
|
|
|
5525
5545
|
const allItems = await loadBacklog(options2.allRepos);
|
|
5526
5546
|
const items2 = filterItems(allItems, options2);
|
|
5527
5547
|
if (items2.length === 0) {
|
|
5528
|
-
console.log(
|
|
5548
|
+
console.log(chalk57.dim("Backlog is empty."));
|
|
5529
5549
|
return;
|
|
5530
5550
|
}
|
|
5531
5551
|
const labels = originDisplayLabels(
|
|
@@ -5534,9 +5554,9 @@ async function list2(options2) {
|
|
|
5534
5554
|
const repoNameOf = (item) => item.origin ? labels.get(item.origin) ?? "" : "";
|
|
5535
5555
|
const prefixWidth = options2.allRepos ? Math.max(0, ...items2.map((i) => repoNameOf(i).length)) : 0;
|
|
5536
5556
|
for (const item of items2) {
|
|
5537
|
-
const repoPrefix2 = options2.allRepos ? `${
|
|
5557
|
+
const repoPrefix2 = options2.allRepos ? `${chalk57.dim(repoNameOf(item).padEnd(prefixWidth))} ` : "";
|
|
5538
5558
|
console.log(
|
|
5539
|
-
`${repoPrefix2}${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
5559
|
+
`${repoPrefix2}${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk57.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
|
|
5540
5560
|
);
|
|
5541
5561
|
if (options2.verbose) {
|
|
5542
5562
|
printVerboseDetails(item);
|
|
@@ -5562,7 +5582,7 @@ function registerItemCommands(cmd) {
|
|
|
5562
5582
|
}
|
|
5563
5583
|
|
|
5564
5584
|
// src/commands/backlog/link.ts
|
|
5565
|
-
import
|
|
5585
|
+
import chalk59 from "chalk";
|
|
5566
5586
|
|
|
5567
5587
|
// src/commands/backlog/hasCycle.ts
|
|
5568
5588
|
function hasCycle(adjacency, fromId, toId) {
|
|
@@ -5594,14 +5614,14 @@ async function loadDependencyGraph(orm) {
|
|
|
5594
5614
|
}
|
|
5595
5615
|
|
|
5596
5616
|
// src/commands/backlog/validateLinkTarget.ts
|
|
5597
|
-
import
|
|
5617
|
+
import chalk58 from "chalk";
|
|
5598
5618
|
function validateLinkTarget(fromItem, fromNum, toNum, linkType) {
|
|
5599
5619
|
const duplicate = (fromItem.links ?? []).some(
|
|
5600
5620
|
(l) => l.targetId === toNum && l.type === linkType
|
|
5601
5621
|
);
|
|
5602
5622
|
if (duplicate) {
|
|
5603
5623
|
console.log(
|
|
5604
|
-
|
|
5624
|
+
chalk58.yellow(`Link already exists: #${fromNum} ${linkType} #${toNum}`)
|
|
5605
5625
|
);
|
|
5606
5626
|
return false;
|
|
5607
5627
|
}
|
|
@@ -5610,7 +5630,7 @@ function validateLinkTarget(fromItem, fromNum, toNum, linkType) {
|
|
|
5610
5630
|
|
|
5611
5631
|
// src/commands/backlog/link.ts
|
|
5612
5632
|
function fail(message) {
|
|
5613
|
-
console.log(
|
|
5633
|
+
console.log(chalk59.red(message));
|
|
5614
5634
|
return void 0;
|
|
5615
5635
|
}
|
|
5616
5636
|
function parseLinkType(type) {
|
|
@@ -5640,12 +5660,12 @@ async function link(fromId, toId, opts) {
|
|
|
5640
5660
|
if (await createsCycle(orm, linkType, fromNum, toNum)) return;
|
|
5641
5661
|
await orm.insert(links).values({ itemId: fromNum, type: linkType, targetId: toNum });
|
|
5642
5662
|
console.log(
|
|
5643
|
-
|
|
5663
|
+
chalk59.green(`Linked #${fromNum} ${linkType} #${toNum} (${toItem.name})`)
|
|
5644
5664
|
);
|
|
5645
5665
|
}
|
|
5646
5666
|
|
|
5647
5667
|
// src/commands/backlog/unlink.ts
|
|
5648
|
-
import
|
|
5668
|
+
import chalk60 from "chalk";
|
|
5649
5669
|
import { and as and4, eq as eq17 } from "drizzle-orm";
|
|
5650
5670
|
async function unlink(fromId, toId) {
|
|
5651
5671
|
const fromNum = Number.parseInt(fromId, 10);
|
|
@@ -5653,19 +5673,19 @@ async function unlink(fromId, toId) {
|
|
|
5653
5673
|
const { orm } = await getReady();
|
|
5654
5674
|
const fromItem = await loadItem(orm, fromNum);
|
|
5655
5675
|
if (!fromItem) {
|
|
5656
|
-
console.log(
|
|
5676
|
+
console.log(chalk60.red(`Item #${fromId} not found.`));
|
|
5657
5677
|
return;
|
|
5658
5678
|
}
|
|
5659
5679
|
if (!fromItem.links || fromItem.links.length === 0) {
|
|
5660
|
-
console.log(
|
|
5680
|
+
console.log(chalk60.yellow(`No links found on item #${fromId}.`));
|
|
5661
5681
|
return;
|
|
5662
5682
|
}
|
|
5663
5683
|
if (!fromItem.links.some((l) => l.targetId === toNum)) {
|
|
5664
|
-
console.log(
|
|
5684
|
+
console.log(chalk60.yellow(`No link from #${fromId} to #${toId} found.`));
|
|
5665
5685
|
return;
|
|
5666
5686
|
}
|
|
5667
5687
|
await orm.delete(links).where(and4(eq17(links.itemId, fromNum), eq17(links.targetId, toNum)));
|
|
5668
|
-
console.log(
|
|
5688
|
+
console.log(chalk60.green(`Removed link from #${fromId} to #${toId}.`));
|
|
5669
5689
|
}
|
|
5670
5690
|
|
|
5671
5691
|
// src/commands/backlog/registerLinkCommands.ts
|
|
@@ -5685,7 +5705,7 @@ function registerPlanCommands(cmd) {
|
|
|
5685
5705
|
}
|
|
5686
5706
|
|
|
5687
5707
|
// src/commands/backlog/rewindPhase.ts
|
|
5688
|
-
import
|
|
5708
|
+
import chalk61 from "chalk";
|
|
5689
5709
|
function validateRewind2(item, phaseNumber) {
|
|
5690
5710
|
if (!item.plan || item.plan.length === 0) {
|
|
5691
5711
|
return `Item #${item.id} has no plan phases.`;
|
|
@@ -5705,12 +5725,12 @@ async function rewindPhase(id, phase, opts) {
|
|
|
5705
5725
|
const { orm } = await getReady();
|
|
5706
5726
|
const item = await loadItem(orm, Number.parseInt(id, 10));
|
|
5707
5727
|
if (!item) {
|
|
5708
|
-
console.log(
|
|
5728
|
+
console.log(chalk61.red(`Item #${id} not found.`));
|
|
5709
5729
|
return;
|
|
5710
5730
|
}
|
|
5711
5731
|
const error = validateRewind2(item, phaseNumber);
|
|
5712
5732
|
if (error) {
|
|
5713
|
-
console.log(
|
|
5733
|
+
console.log(chalk61.red(error));
|
|
5714
5734
|
process.exitCode = 1;
|
|
5715
5735
|
return;
|
|
5716
5736
|
}
|
|
@@ -5728,7 +5748,7 @@ async function rewindPhase(id, phase, opts) {
|
|
|
5728
5748
|
targetPhase: phaseIndex
|
|
5729
5749
|
});
|
|
5730
5750
|
console.log(
|
|
5731
|
-
|
|
5751
|
+
chalk61.green(`Rewound item #${id} to phase ${phaseNumber} (${phaseName}).`)
|
|
5732
5752
|
);
|
|
5733
5753
|
}
|
|
5734
5754
|
|
|
@@ -5740,27 +5760,28 @@ function registerRewindCommand(cmd) {
|
|
|
5740
5760
|
// src/commands/backlog/registerRunCommand.ts
|
|
5741
5761
|
function registerRunCommand(cmd) {
|
|
5742
5762
|
cmd.command("run <id>").description("Run a backlog item's plan phase-by-phase with Claude").option("-w, --write", "Run Claude with auto permission mode (default)").option("--no-write", "Run Claude without auto permission mode").action(async (id, opts) => {
|
|
5763
|
+
pullIfConfigured();
|
|
5743
5764
|
await run(id, { allowEdits: opts.write !== false });
|
|
5744
5765
|
});
|
|
5745
5766
|
}
|
|
5746
5767
|
|
|
5747
5768
|
// src/commands/backlog/search/index.ts
|
|
5748
|
-
import
|
|
5769
|
+
import chalk62 from "chalk";
|
|
5749
5770
|
async function search(query) {
|
|
5750
5771
|
const items2 = await searchBacklog(query);
|
|
5751
5772
|
if (items2.length === 0) {
|
|
5752
|
-
console.log(
|
|
5773
|
+
console.log(chalk62.dim(`No items matching "${query}".`));
|
|
5753
5774
|
return;
|
|
5754
5775
|
}
|
|
5755
5776
|
console.log(
|
|
5756
|
-
|
|
5777
|
+
chalk62.dim(
|
|
5757
5778
|
`${items2.length} item${items2.length === 1 ? "" : "s"} matching "${query}":
|
|
5758
5779
|
`
|
|
5759
5780
|
)
|
|
5760
5781
|
);
|
|
5761
5782
|
for (const item of items2) {
|
|
5762
5783
|
console.log(
|
|
5763
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
5784
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk62.dim(`#${item.id}`)} ${item.name}`
|
|
5764
5785
|
);
|
|
5765
5786
|
}
|
|
5766
5787
|
}
|
|
@@ -5771,16 +5792,16 @@ function registerSearchCommand(cmd) {
|
|
|
5771
5792
|
}
|
|
5772
5793
|
|
|
5773
5794
|
// src/commands/backlog/delete/index.ts
|
|
5774
|
-
import
|
|
5795
|
+
import chalk63 from "chalk";
|
|
5775
5796
|
async function del(id) {
|
|
5776
5797
|
const name = await removeItem(id);
|
|
5777
5798
|
if (name) {
|
|
5778
|
-
console.log(
|
|
5799
|
+
console.log(chalk63.green(`Deleted item #${id}: ${name}`));
|
|
5779
5800
|
}
|
|
5780
5801
|
}
|
|
5781
5802
|
|
|
5782
5803
|
// src/commands/backlog/done/index.ts
|
|
5783
|
-
import
|
|
5804
|
+
import chalk64 from "chalk";
|
|
5784
5805
|
async function done(id, summary) {
|
|
5785
5806
|
const found = await findOneItem(id);
|
|
5786
5807
|
if (!found) return;
|
|
@@ -5790,12 +5811,12 @@ async function done(id, summary) {
|
|
|
5790
5811
|
const pending = item.plan.slice(completedCount);
|
|
5791
5812
|
if (pending.length > 0) {
|
|
5792
5813
|
console.log(
|
|
5793
|
-
|
|
5814
|
+
chalk64.red(
|
|
5794
5815
|
`Cannot complete item #${id}: ${pending.length} pending phase(s):`
|
|
5795
5816
|
)
|
|
5796
5817
|
);
|
|
5797
5818
|
for (const phase of pending) {
|
|
5798
|
-
console.log(
|
|
5819
|
+
console.log(chalk64.yellow(` - ${phase.name}`));
|
|
5799
5820
|
}
|
|
5800
5821
|
process.exitCode = 1;
|
|
5801
5822
|
return;
|
|
@@ -5806,35 +5827,35 @@ async function done(id, summary) {
|
|
|
5806
5827
|
const phase = item.currentPhase ?? 1;
|
|
5807
5828
|
await appendComment(orm, item.id, summary, { phase, type: "summary" });
|
|
5808
5829
|
}
|
|
5809
|
-
console.log(
|
|
5830
|
+
console.log(chalk64.green(`Completed item #${id}: ${item.name}`));
|
|
5810
5831
|
}
|
|
5811
5832
|
|
|
5812
5833
|
// src/commands/backlog/start/index.ts
|
|
5813
|
-
import
|
|
5834
|
+
import chalk65 from "chalk";
|
|
5814
5835
|
async function start(id) {
|
|
5815
5836
|
const name = await setStatus(id, "in-progress");
|
|
5816
5837
|
if (name) {
|
|
5817
|
-
console.log(
|
|
5838
|
+
console.log(chalk65.green(`Started item #${id}: ${name}`));
|
|
5818
5839
|
}
|
|
5819
5840
|
}
|
|
5820
5841
|
|
|
5821
5842
|
// src/commands/backlog/stop/index.ts
|
|
5822
|
-
import
|
|
5843
|
+
import chalk66 from "chalk";
|
|
5823
5844
|
import { and as and5, eq as eq18 } from "drizzle-orm";
|
|
5824
5845
|
async function stop() {
|
|
5825
5846
|
const { orm } = await getReady();
|
|
5826
5847
|
const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and5(eq18(items.status, "in-progress"), eq18(items.origin, getOrigin()))).returning({ id: items.id, name: items.name });
|
|
5827
5848
|
if (stopped.length === 0) {
|
|
5828
|
-
console.log(
|
|
5849
|
+
console.log(chalk66.yellow("No in-progress items to stop."));
|
|
5829
5850
|
return;
|
|
5830
5851
|
}
|
|
5831
5852
|
for (const item of stopped) {
|
|
5832
|
-
console.log(
|
|
5853
|
+
console.log(chalk66.yellow(`Stopped item #${item.id}: ${item.name}`));
|
|
5833
5854
|
}
|
|
5834
5855
|
}
|
|
5835
5856
|
|
|
5836
5857
|
// src/commands/backlog/wontdo/index.ts
|
|
5837
|
-
import
|
|
5858
|
+
import chalk67 from "chalk";
|
|
5838
5859
|
async function wontdo(id, reason) {
|
|
5839
5860
|
const found = await findOneItem(id);
|
|
5840
5861
|
if (!found) return;
|
|
@@ -5844,7 +5865,7 @@ async function wontdo(id, reason) {
|
|
|
5844
5865
|
const phase = item.currentPhase ?? 1;
|
|
5845
5866
|
await appendComment(orm, item.id, reason, { phase, type: "summary" });
|
|
5846
5867
|
}
|
|
5847
|
-
console.log(
|
|
5868
|
+
console.log(chalk67.red(`Won't do item #${id}: ${item.name}`));
|
|
5848
5869
|
}
|
|
5849
5870
|
|
|
5850
5871
|
// src/commands/backlog/registerStatusCommands.ts
|
|
@@ -5857,11 +5878,11 @@ function registerStatusCommands(cmd) {
|
|
|
5857
5878
|
}
|
|
5858
5879
|
|
|
5859
5880
|
// src/commands/backlog/removePhase.ts
|
|
5860
|
-
import
|
|
5881
|
+
import chalk69 from "chalk";
|
|
5861
5882
|
import { and as and8, eq as eq21 } from "drizzle-orm";
|
|
5862
5883
|
|
|
5863
5884
|
// src/commands/backlog/findPhase.ts
|
|
5864
|
-
import
|
|
5885
|
+
import chalk68 from "chalk";
|
|
5865
5886
|
import { and as and6, count as count2, eq as eq19 } from "drizzle-orm";
|
|
5866
5887
|
async function findPhase(id, phase) {
|
|
5867
5888
|
const found = await findOneItem(id);
|
|
@@ -5872,7 +5893,7 @@ async function findPhase(id, phase) {
|
|
|
5872
5893
|
const [row] = await orm.select({ cnt: count2() }).from(planPhases).where(and6(eq19(planPhases.itemId, itemId), eq19(planPhases.idx, phaseIdx)));
|
|
5873
5894
|
if (!row || row.cnt === 0) {
|
|
5874
5895
|
console.log(
|
|
5875
|
-
|
|
5896
|
+
chalk68.red(`Phase ${phaseIdx + 1} not found on item #${itemId}.`)
|
|
5876
5897
|
);
|
|
5877
5898
|
process.exitCode = 1;
|
|
5878
5899
|
return void 0;
|
|
@@ -5919,12 +5940,12 @@ async function removePhase(id, phase) {
|
|
|
5919
5940
|
await adjustCurrentPhase(tx, item, phaseIdx);
|
|
5920
5941
|
});
|
|
5921
5942
|
console.log(
|
|
5922
|
-
|
|
5943
|
+
chalk69.green(`Removed phase ${phaseIdx + 1} from item #${itemId}.`)
|
|
5923
5944
|
);
|
|
5924
5945
|
}
|
|
5925
5946
|
|
|
5926
5947
|
// src/commands/backlog/update/index.ts
|
|
5927
|
-
import
|
|
5948
|
+
import chalk71 from "chalk";
|
|
5928
5949
|
import { eq as eq22 } from "drizzle-orm";
|
|
5929
5950
|
|
|
5930
5951
|
// src/commands/backlog/update/parseListIndex.ts
|
|
@@ -6000,16 +6021,16 @@ function applyAcMutations(current, options2) {
|
|
|
6000
6021
|
}
|
|
6001
6022
|
|
|
6002
6023
|
// src/commands/backlog/update/buildUpdateValues.ts
|
|
6003
|
-
import
|
|
6024
|
+
import chalk70 from "chalk";
|
|
6004
6025
|
function buildUpdateValues(options2) {
|
|
6005
6026
|
const { name, desc: desc2, type, ac } = options2;
|
|
6006
6027
|
if (!name && !desc2 && !type && !ac) {
|
|
6007
|
-
console.log(
|
|
6028
|
+
console.log(chalk70.red("Nothing to update. Provide at least one flag."));
|
|
6008
6029
|
process.exitCode = 1;
|
|
6009
6030
|
return void 0;
|
|
6010
6031
|
}
|
|
6011
6032
|
if (type && type !== "story" && type !== "bug") {
|
|
6012
|
-
console.log(
|
|
6033
|
+
console.log(chalk70.red('Invalid type. Must be "story" or "bug".'));
|
|
6013
6034
|
process.exitCode = 1;
|
|
6014
6035
|
return void 0;
|
|
6015
6036
|
}
|
|
@@ -6042,14 +6063,14 @@ async function update(id, options2) {
|
|
|
6042
6063
|
if (hasAcMutations(options2)) {
|
|
6043
6064
|
if (options2.ac) {
|
|
6044
6065
|
console.log(
|
|
6045
|
-
|
|
6066
|
+
chalk71.red("Cannot combine --ac with --add-ac/--edit-ac/--remove-ac.")
|
|
6046
6067
|
);
|
|
6047
6068
|
process.exitCode = 1;
|
|
6048
6069
|
return;
|
|
6049
6070
|
}
|
|
6050
6071
|
const mutation = applyAcMutations(found.item.acceptanceCriteria, options2);
|
|
6051
6072
|
if (!mutation.ok) {
|
|
6052
|
-
console.log(
|
|
6073
|
+
console.log(chalk71.red(mutation.error));
|
|
6053
6074
|
process.exitCode = 1;
|
|
6054
6075
|
return;
|
|
6055
6076
|
}
|
|
@@ -6060,11 +6081,11 @@ async function update(id, options2) {
|
|
|
6060
6081
|
const { orm } = found;
|
|
6061
6082
|
const itemId = found.item.id;
|
|
6062
6083
|
await orm.update(items).set(built.set).where(eq22(items.id, itemId));
|
|
6063
|
-
console.log(
|
|
6084
|
+
console.log(chalk71.green(`Updated ${built.fields} on item #${itemId}.`));
|
|
6064
6085
|
}
|
|
6065
6086
|
|
|
6066
6087
|
// src/commands/backlog/updatePhase.ts
|
|
6067
|
-
import
|
|
6088
|
+
import chalk72 from "chalk";
|
|
6068
6089
|
|
|
6069
6090
|
// src/commands/backlog/applyPhaseUpdate.ts
|
|
6070
6091
|
import { and as and9, eq as eq23 } from "drizzle-orm";
|
|
@@ -6168,7 +6189,7 @@ async function updatePhase(id, phase, options2) {
|
|
|
6168
6189
|
const { item, orm, itemId, phaseIdx } = found;
|
|
6169
6190
|
const resolved = resolvePhaseFields(options2, item.plan?.[phaseIdx]);
|
|
6170
6191
|
if (!resolved.ok) {
|
|
6171
|
-
console.log(
|
|
6192
|
+
console.log(chalk72.red(resolved.error));
|
|
6172
6193
|
process.exitCode = 1;
|
|
6173
6194
|
return;
|
|
6174
6195
|
}
|
|
@@ -6180,7 +6201,7 @@ async function updatePhase(id, phase, options2) {
|
|
|
6180
6201
|
manualCheck && "manual checks"
|
|
6181
6202
|
].filter(Boolean).join(", ");
|
|
6182
6203
|
console.log(
|
|
6183
|
-
|
|
6204
|
+
chalk72.green(
|
|
6184
6205
|
`Updated ${fields} on phase ${phaseIdx + 1} of item #${itemId}.`
|
|
6185
6206
|
)
|
|
6186
6207
|
);
|
|
@@ -6832,7 +6853,7 @@ import { homedir as homedir6 } from "os";
|
|
|
6832
6853
|
import { join as join20 } from "path";
|
|
6833
6854
|
|
|
6834
6855
|
// src/shared/checkCliAvailable.ts
|
|
6835
|
-
import { execSync as
|
|
6856
|
+
import { execSync as execSync19 } from "child_process";
|
|
6836
6857
|
function checkCliAvailable(cli) {
|
|
6837
6858
|
const binary = cli.split(/\s+/)[0];
|
|
6838
6859
|
const opts = {
|
|
@@ -6840,11 +6861,11 @@ function checkCliAvailable(cli) {
|
|
|
6840
6861
|
stdio: ["ignore", "pipe", "pipe"]
|
|
6841
6862
|
};
|
|
6842
6863
|
try {
|
|
6843
|
-
|
|
6864
|
+
execSync19(`command -v ${binary}`, opts);
|
|
6844
6865
|
return true;
|
|
6845
6866
|
} catch {
|
|
6846
6867
|
try {
|
|
6847
|
-
|
|
6868
|
+
execSync19(`where ${binary}`, opts);
|
|
6848
6869
|
return true;
|
|
6849
6870
|
} catch {
|
|
6850
6871
|
return false;
|
|
@@ -6860,11 +6881,11 @@ function assertCliExists(cli) {
|
|
|
6860
6881
|
}
|
|
6861
6882
|
|
|
6862
6883
|
// src/commands/permitCliReads/colorize.ts
|
|
6863
|
-
import
|
|
6884
|
+
import chalk73 from "chalk";
|
|
6864
6885
|
function colorize(plainOutput) {
|
|
6865
6886
|
return plainOutput.split("\n").map((line) => {
|
|
6866
|
-
if (line.startsWith(" R ")) return
|
|
6867
|
-
if (line.startsWith(" W ")) return
|
|
6887
|
+
if (line.startsWith(" R ")) return chalk73.green(line);
|
|
6888
|
+
if (line.startsWith(" W ")) return chalk73.red(line);
|
|
6868
6889
|
return line;
|
|
6869
6890
|
}).join("\n");
|
|
6870
6891
|
}
|
|
@@ -7162,7 +7183,7 @@ async function permitCliReads(cli, options2 = { noCache: false }) {
|
|
|
7162
7183
|
}
|
|
7163
7184
|
|
|
7164
7185
|
// src/commands/deny/denyAdd.ts
|
|
7165
|
-
import
|
|
7186
|
+
import chalk74 from "chalk";
|
|
7166
7187
|
|
|
7167
7188
|
// src/commands/deny/loadDenyConfig.ts
|
|
7168
7189
|
function loadDenyConfig(global) {
|
|
@@ -7182,16 +7203,16 @@ function loadDenyConfig(global) {
|
|
|
7182
7203
|
function denyAdd(pattern2, message, options2) {
|
|
7183
7204
|
const { deny, saveDeny } = loadDenyConfig(options2.global);
|
|
7184
7205
|
if (deny.some((r) => r.pattern === pattern2)) {
|
|
7185
|
-
console.log(
|
|
7206
|
+
console.log(chalk74.yellow(`Deny rule already exists for: ${pattern2}`));
|
|
7186
7207
|
return;
|
|
7187
7208
|
}
|
|
7188
7209
|
deny.push({ pattern: pattern2, message });
|
|
7189
7210
|
saveDeny(deny);
|
|
7190
|
-
console.log(
|
|
7211
|
+
console.log(chalk74.green(`Added deny rule: ${pattern2} \u2192 ${message}`));
|
|
7191
7212
|
}
|
|
7192
7213
|
|
|
7193
7214
|
// src/commands/deny/denyList.ts
|
|
7194
|
-
import
|
|
7215
|
+
import chalk75 from "chalk";
|
|
7195
7216
|
function denyList() {
|
|
7196
7217
|
const globalRaw = loadGlobalConfigRaw();
|
|
7197
7218
|
const projectRaw = loadProjectConfig();
|
|
@@ -7202,7 +7223,7 @@ function denyList() {
|
|
|
7202
7223
|
projectDeny.length > 0 ? projectDeny : void 0
|
|
7203
7224
|
);
|
|
7204
7225
|
if (!merged || merged.length === 0) {
|
|
7205
|
-
console.log(
|
|
7226
|
+
console.log(chalk75.dim("No deny rules configured."));
|
|
7206
7227
|
return;
|
|
7207
7228
|
}
|
|
7208
7229
|
const projectPatterns = new Set(projectDeny.map((r) => r.pattern));
|
|
@@ -7210,23 +7231,23 @@ function denyList() {
|
|
|
7210
7231
|
for (const rule of merged) {
|
|
7211
7232
|
const inProject = projectPatterns.has(rule.pattern);
|
|
7212
7233
|
const inGlobal = globalPatterns.has(rule.pattern);
|
|
7213
|
-
const label2 = inProject && inGlobal ?
|
|
7214
|
-
console.log(`${
|
|
7234
|
+
const label2 = inProject && inGlobal ? chalk75.dim(" (project, overrides global)") : inGlobal ? chalk75.dim(" (global)") : "";
|
|
7235
|
+
console.log(`${chalk75.red(rule.pattern)} \u2192 ${rule.message}${label2}`);
|
|
7215
7236
|
}
|
|
7216
7237
|
}
|
|
7217
7238
|
|
|
7218
7239
|
// src/commands/deny/denyRemove.ts
|
|
7219
|
-
import
|
|
7240
|
+
import chalk76 from "chalk";
|
|
7220
7241
|
function denyRemove(pattern2, options2) {
|
|
7221
7242
|
const { deny, saveDeny } = loadDenyConfig(options2.global);
|
|
7222
7243
|
const index2 = deny.findIndex((r) => r.pattern === pattern2);
|
|
7223
7244
|
if (index2 === -1) {
|
|
7224
|
-
console.log(
|
|
7245
|
+
console.log(chalk76.yellow(`No deny rule found for: ${pattern2}`));
|
|
7225
7246
|
return;
|
|
7226
7247
|
}
|
|
7227
7248
|
deny.splice(index2, 1);
|
|
7228
7249
|
saveDeny(deny.length > 0 ? deny : void 0);
|
|
7229
|
-
console.log(
|
|
7250
|
+
console.log(chalk76.green(`Removed deny rule: ${pattern2}`));
|
|
7230
7251
|
}
|
|
7231
7252
|
|
|
7232
7253
|
// src/commands/registerDeny.ts
|
|
@@ -7255,15 +7276,15 @@ function registerCliHook(program2) {
|
|
|
7255
7276
|
}
|
|
7256
7277
|
|
|
7257
7278
|
// src/commands/complexity/analyze.ts
|
|
7258
|
-
import
|
|
7279
|
+
import chalk82 from "chalk";
|
|
7259
7280
|
|
|
7260
7281
|
// src/commands/complexity/cyclomatic.ts
|
|
7261
|
-
import
|
|
7282
|
+
import chalk78 from "chalk";
|
|
7262
7283
|
|
|
7263
7284
|
// src/commands/complexity/shared/index.ts
|
|
7264
7285
|
import fs14 from "fs";
|
|
7265
7286
|
import path22 from "path";
|
|
7266
|
-
import
|
|
7287
|
+
import chalk77 from "chalk";
|
|
7267
7288
|
import ts5 from "typescript";
|
|
7268
7289
|
|
|
7269
7290
|
// src/commands/complexity/findSourceFiles.ts
|
|
@@ -7509,7 +7530,7 @@ function createSourceFromFile(filePath) {
|
|
|
7509
7530
|
function withSourceFiles(pattern2, callback) {
|
|
7510
7531
|
const files = findSourceFiles2(pattern2);
|
|
7511
7532
|
if (files.length === 0) {
|
|
7512
|
-
console.log(
|
|
7533
|
+
console.log(chalk77.yellow("No files found matching pattern"));
|
|
7513
7534
|
return void 0;
|
|
7514
7535
|
}
|
|
7515
7536
|
return callback(files);
|
|
@@ -7542,11 +7563,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
7542
7563
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
7543
7564
|
for (const { file, name, complexity } of results) {
|
|
7544
7565
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
7545
|
-
const color = exceedsThreshold ?
|
|
7546
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
7566
|
+
const color = exceedsThreshold ? chalk78.red : chalk78.white;
|
|
7567
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk78.cyan(complexity)}`);
|
|
7547
7568
|
}
|
|
7548
7569
|
console.log(
|
|
7549
|
-
|
|
7570
|
+
chalk78.dim(
|
|
7550
7571
|
`
|
|
7551
7572
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
7552
7573
|
)
|
|
@@ -7558,7 +7579,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
7558
7579
|
}
|
|
7559
7580
|
|
|
7560
7581
|
// src/commands/complexity/halstead.ts
|
|
7561
|
-
import
|
|
7582
|
+
import chalk79 from "chalk";
|
|
7562
7583
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
7563
7584
|
withSourceFiles(pattern2, (files) => {
|
|
7564
7585
|
const results = [];
|
|
@@ -7573,13 +7594,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
7573
7594
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
7574
7595
|
for (const { file, name, metrics } of results) {
|
|
7575
7596
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
7576
|
-
const color = exceedsThreshold ?
|
|
7597
|
+
const color = exceedsThreshold ? chalk79.red : chalk79.white;
|
|
7577
7598
|
console.log(
|
|
7578
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
7599
|
+
`${color(`${file}:${name}`)} \u2192 volume: ${chalk79.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk79.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk79.magenta(metrics.effort.toFixed(1))}`
|
|
7579
7600
|
);
|
|
7580
7601
|
}
|
|
7581
7602
|
console.log(
|
|
7582
|
-
|
|
7603
|
+
chalk79.dim(
|
|
7583
7604
|
`
|
|
7584
7605
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
7585
7606
|
)
|
|
@@ -7594,28 +7615,28 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
7594
7615
|
import fs15 from "fs";
|
|
7595
7616
|
|
|
7596
7617
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
7597
|
-
import
|
|
7618
|
+
import chalk80 from "chalk";
|
|
7598
7619
|
function displayMaintainabilityResults(results, threshold) {
|
|
7599
7620
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
7600
7621
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
7601
|
-
console.log(
|
|
7622
|
+
console.log(chalk80.green("All files pass maintainability threshold"));
|
|
7602
7623
|
} else {
|
|
7603
7624
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
7604
|
-
const color = threshold !== void 0 ?
|
|
7625
|
+
const color = threshold !== void 0 ? chalk80.red : chalk80.white;
|
|
7605
7626
|
console.log(
|
|
7606
|
-
`${color(file)} \u2192 avg: ${
|
|
7627
|
+
`${color(file)} \u2192 avg: ${chalk80.cyan(avgMaintainability.toFixed(1))}, min: ${chalk80.yellow(minMaintainability.toFixed(1))}`
|
|
7607
7628
|
);
|
|
7608
7629
|
}
|
|
7609
7630
|
}
|
|
7610
|
-
console.log(
|
|
7631
|
+
console.log(chalk80.dim(`
|
|
7611
7632
|
Analyzed ${results.length} files`));
|
|
7612
7633
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
7613
7634
|
console.error(
|
|
7614
|
-
|
|
7635
|
+
chalk80.red(
|
|
7615
7636
|
`
|
|
7616
7637
|
Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
|
|
7617
7638
|
|
|
7618
|
-
\u26A0\uFE0F ${
|
|
7639
|
+
\u26A0\uFE0F ${chalk80.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.`
|
|
7619
7640
|
)
|
|
7620
7641
|
);
|
|
7621
7642
|
process.exit(1);
|
|
@@ -7672,7 +7693,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
7672
7693
|
|
|
7673
7694
|
// src/commands/complexity/sloc.ts
|
|
7674
7695
|
import fs16 from "fs";
|
|
7675
|
-
import
|
|
7696
|
+
import chalk81 from "chalk";
|
|
7676
7697
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
7677
7698
|
withSourceFiles(pattern2, (files) => {
|
|
7678
7699
|
const results = [];
|
|
@@ -7688,12 +7709,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
7688
7709
|
results.sort((a, b) => b.lines - a.lines);
|
|
7689
7710
|
for (const { file, lines } of results) {
|
|
7690
7711
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
7691
|
-
const color = exceedsThreshold ?
|
|
7692
|
-
console.log(`${color(file)} \u2192 ${
|
|
7712
|
+
const color = exceedsThreshold ? chalk81.red : chalk81.white;
|
|
7713
|
+
console.log(`${color(file)} \u2192 ${chalk81.cyan(lines)} lines`);
|
|
7693
7714
|
}
|
|
7694
7715
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
7695
7716
|
console.log(
|
|
7696
|
-
|
|
7717
|
+
chalk81.dim(`
|
|
7697
7718
|
Total: ${total} lines across ${files.length} files`)
|
|
7698
7719
|
);
|
|
7699
7720
|
if (hasViolation) {
|
|
@@ -7707,21 +7728,21 @@ async function analyze(pattern2) {
|
|
|
7707
7728
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
7708
7729
|
const files = findSourceFiles2(searchPattern);
|
|
7709
7730
|
if (files.length === 0) {
|
|
7710
|
-
console.log(
|
|
7731
|
+
console.log(chalk82.yellow("No files found matching pattern"));
|
|
7711
7732
|
return;
|
|
7712
7733
|
}
|
|
7713
7734
|
if (files.length === 1) {
|
|
7714
7735
|
const file = files[0];
|
|
7715
|
-
console.log(
|
|
7736
|
+
console.log(chalk82.bold.underline("SLOC"));
|
|
7716
7737
|
await sloc(file);
|
|
7717
7738
|
console.log();
|
|
7718
|
-
console.log(
|
|
7739
|
+
console.log(chalk82.bold.underline("Cyclomatic Complexity"));
|
|
7719
7740
|
await cyclomatic(file);
|
|
7720
7741
|
console.log();
|
|
7721
|
-
console.log(
|
|
7742
|
+
console.log(chalk82.bold.underline("Halstead Metrics"));
|
|
7722
7743
|
await halstead(file);
|
|
7723
7744
|
console.log();
|
|
7724
|
-
console.log(
|
|
7745
|
+
console.log(chalk82.bold.underline("Maintainability Index"));
|
|
7725
7746
|
await maintainability(file);
|
|
7726
7747
|
return;
|
|
7727
7748
|
}
|
|
@@ -7748,7 +7769,7 @@ function registerComplexity(program2) {
|
|
|
7748
7769
|
}
|
|
7749
7770
|
|
|
7750
7771
|
// src/commands/config/index.ts
|
|
7751
|
-
import
|
|
7772
|
+
import chalk83 from "chalk";
|
|
7752
7773
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
7753
7774
|
|
|
7754
7775
|
// src/commands/config/setNestedValue.ts
|
|
@@ -7811,7 +7832,7 @@ function formatIssuePath(issue, key) {
|
|
|
7811
7832
|
function printValidationErrors(issues, key) {
|
|
7812
7833
|
for (const issue of issues) {
|
|
7813
7834
|
console.error(
|
|
7814
|
-
|
|
7835
|
+
chalk83.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
|
|
7815
7836
|
);
|
|
7816
7837
|
}
|
|
7817
7838
|
}
|
|
@@ -7828,7 +7849,7 @@ var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
|
7828
7849
|
function assertNotGlobalOnly(key, global) {
|
|
7829
7850
|
if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
|
|
7830
7851
|
console.error(
|
|
7831
|
-
|
|
7852
|
+
chalk83.red(
|
|
7832
7853
|
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
7833
7854
|
)
|
|
7834
7855
|
);
|
|
@@ -7851,7 +7872,7 @@ function configSet(key, value, options2 = {}) {
|
|
|
7851
7872
|
applyConfigSet(key, coerced, options2.global ?? false);
|
|
7852
7873
|
const target = options2.global ? "global" : "project";
|
|
7853
7874
|
console.log(
|
|
7854
|
-
|
|
7875
|
+
chalk83.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
|
|
7855
7876
|
);
|
|
7856
7877
|
}
|
|
7857
7878
|
function configList() {
|
|
@@ -7860,7 +7881,7 @@ function configList() {
|
|
|
7860
7881
|
}
|
|
7861
7882
|
|
|
7862
7883
|
// src/commands/config/configGet.ts
|
|
7863
|
-
import
|
|
7884
|
+
import chalk84 from "chalk";
|
|
7864
7885
|
|
|
7865
7886
|
// src/commands/config/getNestedValue.ts
|
|
7866
7887
|
function isTraversable(value) {
|
|
@@ -7892,7 +7913,7 @@ function requireNestedValue(config, key) {
|
|
|
7892
7913
|
return value;
|
|
7893
7914
|
}
|
|
7894
7915
|
function exitKeyNotSet(key) {
|
|
7895
|
-
console.error(
|
|
7916
|
+
console.error(chalk84.red(`Key "${key}" is not set`));
|
|
7896
7917
|
process.exit(1);
|
|
7897
7918
|
}
|
|
7898
7919
|
|
|
@@ -7906,7 +7927,7 @@ function registerConfig(program2) {
|
|
|
7906
7927
|
|
|
7907
7928
|
// src/commands/deploy/redirect.ts
|
|
7908
7929
|
import { existsSync as existsSync24, readFileSync as readFileSync18, writeFileSync as writeFileSync16 } from "fs";
|
|
7909
|
-
import
|
|
7930
|
+
import chalk85 from "chalk";
|
|
7910
7931
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
7911
7932
|
if (!window.location.pathname.endsWith('/')) {
|
|
7912
7933
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -7915,22 +7936,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
7915
7936
|
function redirect() {
|
|
7916
7937
|
const indexPath = "index.html";
|
|
7917
7938
|
if (!existsSync24(indexPath)) {
|
|
7918
|
-
console.log(
|
|
7939
|
+
console.log(chalk85.yellow("No index.html found"));
|
|
7919
7940
|
return;
|
|
7920
7941
|
}
|
|
7921
7942
|
const content = readFileSync18(indexPath, "utf-8");
|
|
7922
7943
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
7923
|
-
console.log(
|
|
7944
|
+
console.log(chalk85.dim("Trailing slash script already present"));
|
|
7924
7945
|
return;
|
|
7925
7946
|
}
|
|
7926
7947
|
const headCloseIndex = content.indexOf("</head>");
|
|
7927
7948
|
if (headCloseIndex === -1) {
|
|
7928
|
-
console.log(
|
|
7949
|
+
console.log(chalk85.red("Could not find </head> tag in index.html"));
|
|
7929
7950
|
return;
|
|
7930
7951
|
}
|
|
7931
7952
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
7932
7953
|
writeFileSync16(indexPath, newContent);
|
|
7933
|
-
console.log(
|
|
7954
|
+
console.log(chalk85.green("Added trailing slash redirect to index.html"));
|
|
7934
7955
|
}
|
|
7935
7956
|
|
|
7936
7957
|
// src/commands/registerDeploy.ts
|
|
@@ -7956,8 +7977,8 @@ function loadBlogSkipDays(repoName) {
|
|
|
7956
7977
|
}
|
|
7957
7978
|
|
|
7958
7979
|
// src/commands/devlog/shared.ts
|
|
7959
|
-
import { execSync as
|
|
7960
|
-
import
|
|
7980
|
+
import { execSync as execSync20 } from "child_process";
|
|
7981
|
+
import chalk86 from "chalk";
|
|
7961
7982
|
|
|
7962
7983
|
// src/shared/getRepoName.ts
|
|
7963
7984
|
import { existsSync as existsSync25, readFileSync as readFileSync19 } from "fs";
|
|
@@ -8048,7 +8069,7 @@ function loadAllDevlogLatestDates() {
|
|
|
8048
8069
|
// src/commands/devlog/shared.ts
|
|
8049
8070
|
function getCommitFiles(hash) {
|
|
8050
8071
|
try {
|
|
8051
|
-
const output =
|
|
8072
|
+
const output = execSync20(`git show --name-only --format="" ${hash}`, {
|
|
8052
8073
|
encoding: "utf-8"
|
|
8053
8074
|
});
|
|
8054
8075
|
return output.trim().split("\n").filter(Boolean);
|
|
@@ -8066,13 +8087,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
8066
8087
|
}
|
|
8067
8088
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
8068
8089
|
for (const commit2 of commits) {
|
|
8069
|
-
console.log(` ${
|
|
8090
|
+
console.log(` ${chalk86.yellow(commit2.hash)} ${commit2.message}`);
|
|
8070
8091
|
if (verbose) {
|
|
8071
8092
|
const visibleFiles = commit2.files.filter(
|
|
8072
8093
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
8073
8094
|
);
|
|
8074
8095
|
for (const file of visibleFiles) {
|
|
8075
|
-
console.log(` ${
|
|
8096
|
+
console.log(` ${chalk86.dim(file)}`);
|
|
8076
8097
|
}
|
|
8077
8098
|
}
|
|
8078
8099
|
}
|
|
@@ -8097,15 +8118,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
8097
8118
|
}
|
|
8098
8119
|
|
|
8099
8120
|
// src/commands/devlog/list/printDateHeader.ts
|
|
8100
|
-
import
|
|
8121
|
+
import chalk87 from "chalk";
|
|
8101
8122
|
function printDateHeader(date, isSkipped, entries) {
|
|
8102
8123
|
if (isSkipped) {
|
|
8103
|
-
console.log(`${
|
|
8124
|
+
console.log(`${chalk87.bold.blue(date)} ${chalk87.dim("skipped")}`);
|
|
8104
8125
|
} else if (entries && entries.length > 0) {
|
|
8105
|
-
const entryInfo = entries.map((e) => `${
|
|
8106
|
-
console.log(`${
|
|
8126
|
+
const entryInfo = entries.map((e) => `${chalk87.green(e.version)} ${e.title}`).join(" | ");
|
|
8127
|
+
console.log(`${chalk87.bold.blue(date)} ${entryInfo}`);
|
|
8107
8128
|
} else {
|
|
8108
|
-
console.log(`${
|
|
8129
|
+
console.log(`${chalk87.bold.blue(date)} ${chalk87.red("\u26A0 devlog missing")}`);
|
|
8109
8130
|
}
|
|
8110
8131
|
}
|
|
8111
8132
|
|
|
@@ -8144,11 +8165,11 @@ function list3(options2) {
|
|
|
8144
8165
|
}
|
|
8145
8166
|
|
|
8146
8167
|
// src/commands/devlog/getLastVersionInfo.ts
|
|
8147
|
-
import { execFileSync as execFileSync2, execSync as
|
|
8168
|
+
import { execFileSync as execFileSync2, execSync as execSync21 } from "child_process";
|
|
8148
8169
|
import semver from "semver";
|
|
8149
8170
|
function getVersionAtCommit(hash) {
|
|
8150
8171
|
try {
|
|
8151
|
-
const content =
|
|
8172
|
+
const content = execSync21(`git show ${hash}:package.json`, {
|
|
8152
8173
|
encoding: "utf-8"
|
|
8153
8174
|
});
|
|
8154
8175
|
const pkg = JSON.parse(content);
|
|
@@ -8209,24 +8230,24 @@ function bumpVersion(version2, type) {
|
|
|
8209
8230
|
|
|
8210
8231
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
8211
8232
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
8212
|
-
import
|
|
8233
|
+
import chalk89 from "chalk";
|
|
8213
8234
|
|
|
8214
8235
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
8215
|
-
import
|
|
8236
|
+
import chalk88 from "chalk";
|
|
8216
8237
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
8217
8238
|
if (conventional && firstHash) {
|
|
8218
8239
|
const version2 = getVersionAtCommit(firstHash);
|
|
8219
8240
|
if (version2) {
|
|
8220
|
-
console.log(`${
|
|
8241
|
+
console.log(`${chalk88.bold("version:")} ${stripToMinor(version2)}`);
|
|
8221
8242
|
} else {
|
|
8222
|
-
console.log(`${
|
|
8243
|
+
console.log(`${chalk88.bold("version:")} ${chalk88.red("unknown")}`);
|
|
8223
8244
|
}
|
|
8224
8245
|
} else if (patchVersion && minorVersion) {
|
|
8225
8246
|
console.log(
|
|
8226
|
-
`${
|
|
8247
|
+
`${chalk88.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
8227
8248
|
);
|
|
8228
8249
|
} else {
|
|
8229
|
-
console.log(`${
|
|
8250
|
+
console.log(`${chalk88.bold("version:")} v0.1 (initial)`);
|
|
8230
8251
|
}
|
|
8231
8252
|
}
|
|
8232
8253
|
|
|
@@ -8274,16 +8295,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
8274
8295
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
8275
8296
|
}
|
|
8276
8297
|
function logName(repoName) {
|
|
8277
|
-
console.log(`${
|
|
8298
|
+
console.log(`${chalk89.bold("name:")} ${repoName}`);
|
|
8278
8299
|
}
|
|
8279
8300
|
function displayNextEntry(ctx, targetDate, commits) {
|
|
8280
8301
|
logName(ctx.repoName);
|
|
8281
8302
|
printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
|
|
8282
|
-
console.log(
|
|
8303
|
+
console.log(chalk89.bold.blue(targetDate));
|
|
8283
8304
|
printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
|
|
8284
8305
|
}
|
|
8285
8306
|
function logNoCommits(lastInfo) {
|
|
8286
|
-
console.log(
|
|
8307
|
+
console.log(chalk89.dim(noCommitsMessage(!!lastInfo)));
|
|
8287
8308
|
}
|
|
8288
8309
|
|
|
8289
8310
|
// src/commands/devlog/next/index.ts
|
|
@@ -8321,14 +8342,14 @@ function next2(options2) {
|
|
|
8321
8342
|
}
|
|
8322
8343
|
|
|
8323
8344
|
// src/commands/devlog/repos/index.ts
|
|
8324
|
-
import { execSync as
|
|
8345
|
+
import { execSync as execSync22 } from "child_process";
|
|
8325
8346
|
|
|
8326
8347
|
// src/commands/devlog/repos/printReposTable.ts
|
|
8327
|
-
import
|
|
8348
|
+
import chalk90 from "chalk";
|
|
8328
8349
|
function colorStatus(status2) {
|
|
8329
|
-
if (status2 === "missing") return
|
|
8330
|
-
if (status2 === "outdated") return
|
|
8331
|
-
return
|
|
8350
|
+
if (status2 === "missing") return chalk90.red(status2);
|
|
8351
|
+
if (status2 === "outdated") return chalk90.yellow(status2);
|
|
8352
|
+
return chalk90.green(status2);
|
|
8332
8353
|
}
|
|
8333
8354
|
function formatRow(row, nameWidth) {
|
|
8334
8355
|
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
@@ -8342,8 +8363,8 @@ function printReposTable(rows) {
|
|
|
8342
8363
|
"Last Devlog".padEnd(11),
|
|
8343
8364
|
"Status"
|
|
8344
8365
|
].join(" ");
|
|
8345
|
-
console.log(
|
|
8346
|
-
console.log(
|
|
8366
|
+
console.log(chalk90.dim(header));
|
|
8367
|
+
console.log(chalk90.dim("-".repeat(header.length)));
|
|
8347
8368
|
for (const row of rows) {
|
|
8348
8369
|
console.log(formatRow(row, nameWidth));
|
|
8349
8370
|
}
|
|
@@ -8356,7 +8377,7 @@ function getStatus(lastPush, lastDevlog) {
|
|
|
8356
8377
|
return lastDevlog < lastPush ? "outdated" : "ok";
|
|
8357
8378
|
}
|
|
8358
8379
|
function fetchRepos(days, all) {
|
|
8359
|
-
const json =
|
|
8380
|
+
const json = execSync22(
|
|
8360
8381
|
"gh repo list staff0rd --json name,pushedAt,isArchived --limit 200",
|
|
8361
8382
|
{ encoding: "utf-8" }
|
|
8362
8383
|
);
|
|
@@ -8401,14 +8422,14 @@ function repos(options2) {
|
|
|
8401
8422
|
// src/commands/devlog/skip.ts
|
|
8402
8423
|
import { writeFileSync as writeFileSync17 } from "fs";
|
|
8403
8424
|
import { join as join24 } from "path";
|
|
8404
|
-
import
|
|
8425
|
+
import chalk91 from "chalk";
|
|
8405
8426
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
8406
8427
|
function getBlogConfigPath() {
|
|
8407
8428
|
return join24(BLOG_REPO_ROOT, "assist.yml");
|
|
8408
8429
|
}
|
|
8409
8430
|
function skip(date) {
|
|
8410
8431
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
8411
|
-
console.log(
|
|
8432
|
+
console.log(chalk91.red("Invalid date format. Use YYYY-MM-DD"));
|
|
8412
8433
|
process.exit(1);
|
|
8413
8434
|
}
|
|
8414
8435
|
const repoName = getRepoName();
|
|
@@ -8419,7 +8440,7 @@ function skip(date) {
|
|
|
8419
8440
|
const skipDays = skip2[repoName] ?? [];
|
|
8420
8441
|
if (skipDays.includes(date)) {
|
|
8421
8442
|
console.log(
|
|
8422
|
-
|
|
8443
|
+
chalk91.yellow(`${date} is already in skip list for ${repoName}`)
|
|
8423
8444
|
);
|
|
8424
8445
|
return;
|
|
8425
8446
|
}
|
|
@@ -8429,20 +8450,20 @@ function skip(date) {
|
|
|
8429
8450
|
devlog.skip = skip2;
|
|
8430
8451
|
config.devlog = devlog;
|
|
8431
8452
|
writeFileSync17(configPath, stringifyYaml3(config, { lineWidth: 0 }));
|
|
8432
|
-
console.log(
|
|
8453
|
+
console.log(chalk91.green(`Added ${date} to skip list for ${repoName}`));
|
|
8433
8454
|
}
|
|
8434
8455
|
|
|
8435
8456
|
// src/commands/devlog/version.ts
|
|
8436
|
-
import
|
|
8457
|
+
import chalk92 from "chalk";
|
|
8437
8458
|
function version() {
|
|
8438
8459
|
const config = loadConfig();
|
|
8439
8460
|
const name = getRepoName();
|
|
8440
8461
|
const lastInfo = getLastVersionInfo(name, config);
|
|
8441
8462
|
const lastVersion = lastInfo?.version ?? null;
|
|
8442
8463
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
8443
|
-
console.log(`${
|
|
8444
|
-
console.log(`${
|
|
8445
|
-
console.log(`${
|
|
8464
|
+
console.log(`${chalk92.bold("name:")} ${name}`);
|
|
8465
|
+
console.log(`${chalk92.bold("last:")} ${lastVersion ?? chalk92.dim("none")}`);
|
|
8466
|
+
console.log(`${chalk92.bold("next:")} ${nextVersion ?? chalk92.dim("none")}`);
|
|
8446
8467
|
}
|
|
8447
8468
|
|
|
8448
8469
|
// src/commands/registerDevlog.ts
|
|
@@ -8466,7 +8487,7 @@ function registerDevlog(program2) {
|
|
|
8466
8487
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
8467
8488
|
import { closeSync, openSync, readdirSync as readdirSync2 } from "fs";
|
|
8468
8489
|
import { join as join25 } from "path";
|
|
8469
|
-
import
|
|
8490
|
+
import chalk93 from "chalk";
|
|
8470
8491
|
|
|
8471
8492
|
// src/shared/findRepoRoot.ts
|
|
8472
8493
|
import { existsSync as existsSync26 } from "fs";
|
|
@@ -8529,14 +8550,14 @@ function checkBuildLocks(startDir) {
|
|
|
8529
8550
|
const locked = findFirstLockedDll(startDir ?? getSearchRoot());
|
|
8530
8551
|
if (locked) {
|
|
8531
8552
|
console.error(
|
|
8532
|
-
|
|
8553
|
+
chalk93.red("Build output locked (is VS debugging?): ") + locked
|
|
8533
8554
|
);
|
|
8534
8555
|
process.exit(1);
|
|
8535
8556
|
}
|
|
8536
8557
|
}
|
|
8537
8558
|
async function checkBuildLocksCommand() {
|
|
8538
8559
|
checkBuildLocks();
|
|
8539
|
-
console.log(
|
|
8560
|
+
console.log(chalk93.green("No build locks detected"));
|
|
8540
8561
|
}
|
|
8541
8562
|
|
|
8542
8563
|
// src/commands/dotnet/buildTree.ts
|
|
@@ -8635,30 +8656,30 @@ function escapeRegex(s) {
|
|
|
8635
8656
|
}
|
|
8636
8657
|
|
|
8637
8658
|
// src/commands/dotnet/printTree.ts
|
|
8638
|
-
import
|
|
8659
|
+
import chalk94 from "chalk";
|
|
8639
8660
|
function printNodes(nodes, prefix2) {
|
|
8640
8661
|
for (let i = 0; i < nodes.length; i++) {
|
|
8641
8662
|
const isLast = i === nodes.length - 1;
|
|
8642
8663
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
8643
8664
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
8644
8665
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
8645
|
-
const label2 = isMissing ?
|
|
8666
|
+
const label2 = isMissing ? chalk94.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
8646
8667
|
console.log(`${prefix2}${connector}${label2}`);
|
|
8647
8668
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
8648
8669
|
}
|
|
8649
8670
|
}
|
|
8650
8671
|
function printTree(tree, totalCount, solutions) {
|
|
8651
|
-
console.log(
|
|
8652
|
-
console.log(
|
|
8672
|
+
console.log(chalk94.bold("\nProject Dependency Tree"));
|
|
8673
|
+
console.log(chalk94.cyan(tree.relativePath));
|
|
8653
8674
|
printNodes(tree.children, "");
|
|
8654
|
-
console.log(
|
|
8675
|
+
console.log(chalk94.dim(`
|
|
8655
8676
|
${totalCount} projects total (including root)`));
|
|
8656
|
-
console.log(
|
|
8677
|
+
console.log(chalk94.bold("\nSolution Membership"));
|
|
8657
8678
|
if (solutions.length === 0) {
|
|
8658
|
-
console.log(
|
|
8679
|
+
console.log(chalk94.yellow(" Not found in any .sln"));
|
|
8659
8680
|
} else {
|
|
8660
8681
|
for (const sln of solutions) {
|
|
8661
|
-
console.log(` ${
|
|
8682
|
+
console.log(` ${chalk94.green(sln)}`);
|
|
8662
8683
|
}
|
|
8663
8684
|
}
|
|
8664
8685
|
console.log();
|
|
@@ -8687,16 +8708,16 @@ function printJson(tree, totalCount, solutions) {
|
|
|
8687
8708
|
// src/commands/dotnet/resolveCsproj.ts
|
|
8688
8709
|
import { existsSync as existsSync27 } from "fs";
|
|
8689
8710
|
import path26 from "path";
|
|
8690
|
-
import
|
|
8711
|
+
import chalk95 from "chalk";
|
|
8691
8712
|
function resolveCsproj(csprojPath) {
|
|
8692
8713
|
const resolved = path26.resolve(csprojPath);
|
|
8693
8714
|
if (!existsSync27(resolved)) {
|
|
8694
|
-
console.error(
|
|
8715
|
+
console.error(chalk95.red(`File not found: ${resolved}`));
|
|
8695
8716
|
process.exit(1);
|
|
8696
8717
|
}
|
|
8697
8718
|
const repoRoot = findRepoRoot(path26.dirname(resolved));
|
|
8698
8719
|
if (!repoRoot) {
|
|
8699
|
-
console.error(
|
|
8720
|
+
console.error(chalk95.red("Could not find git repository root"));
|
|
8700
8721
|
process.exit(1);
|
|
8701
8722
|
}
|
|
8702
8723
|
return { resolved, repoRoot };
|
|
@@ -8716,7 +8737,7 @@ async function deps(csprojPath, options2) {
|
|
|
8716
8737
|
}
|
|
8717
8738
|
|
|
8718
8739
|
// src/commands/dotnet/getChangedCsFiles.ts
|
|
8719
|
-
import { execSync as
|
|
8740
|
+
import { execSync as execSync23 } from "child_process";
|
|
8720
8741
|
var SCOPE_ALL = "all";
|
|
8721
8742
|
var SCOPE_BASE = "base:";
|
|
8722
8743
|
var SCOPE_COMMIT = "commit:";
|
|
@@ -8740,18 +8761,18 @@ function getChangedCsFiles(scope) {
|
|
|
8740
8761
|
} else {
|
|
8741
8762
|
cmd = "git diff --name-only HEAD";
|
|
8742
8763
|
}
|
|
8743
|
-
const output =
|
|
8764
|
+
const output = execSync23(cmd, { encoding: "utf-8" }).trim();
|
|
8744
8765
|
if (output === "") return [];
|
|
8745
8766
|
return output.split("\n").filter((f) => f.toLowerCase().endsWith(".cs"));
|
|
8746
8767
|
}
|
|
8747
8768
|
|
|
8748
8769
|
// src/commands/dotnet/inSln.ts
|
|
8749
|
-
import
|
|
8770
|
+
import chalk96 from "chalk";
|
|
8750
8771
|
async function inSln(csprojPath) {
|
|
8751
8772
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
8752
8773
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
8753
8774
|
if (solutions.length === 0) {
|
|
8754
|
-
console.log(
|
|
8775
|
+
console.log(chalk96.yellow("Not found in any .sln file"));
|
|
8755
8776
|
process.exit(1);
|
|
8756
8777
|
}
|
|
8757
8778
|
for (const sln of solutions) {
|
|
@@ -8760,7 +8781,7 @@ async function inSln(csprojPath) {
|
|
|
8760
8781
|
}
|
|
8761
8782
|
|
|
8762
8783
|
// src/commands/dotnet/inspect.ts
|
|
8763
|
-
import
|
|
8784
|
+
import chalk102 from "chalk";
|
|
8764
8785
|
|
|
8765
8786
|
// src/shared/formatElapsed.ts
|
|
8766
8787
|
function formatElapsed(ms) {
|
|
@@ -8772,12 +8793,12 @@ function formatElapsed(ms) {
|
|
|
8772
8793
|
}
|
|
8773
8794
|
|
|
8774
8795
|
// src/commands/dotnet/displayIssues.ts
|
|
8775
|
-
import
|
|
8796
|
+
import chalk97 from "chalk";
|
|
8776
8797
|
var SEVERITY_COLOR = {
|
|
8777
|
-
ERROR:
|
|
8778
|
-
WARNING:
|
|
8779
|
-
SUGGESTION:
|
|
8780
|
-
HINT:
|
|
8798
|
+
ERROR: chalk97.red,
|
|
8799
|
+
WARNING: chalk97.yellow,
|
|
8800
|
+
SUGGESTION: chalk97.cyan,
|
|
8801
|
+
HINT: chalk97.dim
|
|
8781
8802
|
};
|
|
8782
8803
|
function groupByFile(issues) {
|
|
8783
8804
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -8793,15 +8814,15 @@ function groupByFile(issues) {
|
|
|
8793
8814
|
}
|
|
8794
8815
|
function displayIssues(issues) {
|
|
8795
8816
|
for (const [file, fileIssues] of groupByFile(issues)) {
|
|
8796
|
-
console.log(
|
|
8817
|
+
console.log(chalk97.bold(file));
|
|
8797
8818
|
for (const issue of fileIssues.sort((a, b) => a.line - b.line)) {
|
|
8798
|
-
const color = SEVERITY_COLOR[issue.severity] ??
|
|
8819
|
+
const color = SEVERITY_COLOR[issue.severity] ?? chalk97.white;
|
|
8799
8820
|
console.log(
|
|
8800
|
-
` ${
|
|
8821
|
+
` ${chalk97.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
|
|
8801
8822
|
);
|
|
8802
8823
|
}
|
|
8803
8824
|
}
|
|
8804
|
-
console.log(
|
|
8825
|
+
console.log(chalk97.dim(`
|
|
8805
8826
|
${issues.length} issue(s) found`));
|
|
8806
8827
|
}
|
|
8807
8828
|
|
|
@@ -8860,12 +8881,12 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
|
|
|
8860
8881
|
// src/commands/dotnet/resolveSolution.ts
|
|
8861
8882
|
import { existsSync as existsSync28 } from "fs";
|
|
8862
8883
|
import path27 from "path";
|
|
8863
|
-
import
|
|
8884
|
+
import chalk99 from "chalk";
|
|
8864
8885
|
|
|
8865
8886
|
// src/commands/dotnet/findSolution.ts
|
|
8866
8887
|
import { readdirSync as readdirSync4 } from "fs";
|
|
8867
8888
|
import { dirname as dirname18, join as join26 } from "path";
|
|
8868
|
-
import
|
|
8889
|
+
import chalk98 from "chalk";
|
|
8869
8890
|
function findSlnInDir(dir) {
|
|
8870
8891
|
try {
|
|
8871
8892
|
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join26(dir, f));
|
|
@@ -8881,17 +8902,17 @@ function findSolution() {
|
|
|
8881
8902
|
const slnFiles = findSlnInDir(current);
|
|
8882
8903
|
if (slnFiles.length === 1) return slnFiles[0];
|
|
8883
8904
|
if (slnFiles.length > 1) {
|
|
8884
|
-
console.error(
|
|
8905
|
+
console.error(chalk98.red(`Multiple .sln files found in ${current}:`));
|
|
8885
8906
|
for (const f of slnFiles) console.error(` ${f}`);
|
|
8886
8907
|
console.error(
|
|
8887
|
-
|
|
8908
|
+
chalk98.yellow("Specify which one: assist dotnet inspect <sln>")
|
|
8888
8909
|
);
|
|
8889
8910
|
process.exit(1);
|
|
8890
8911
|
}
|
|
8891
8912
|
if (current === ceiling) break;
|
|
8892
8913
|
current = dirname18(current);
|
|
8893
8914
|
}
|
|
8894
|
-
console.error(
|
|
8915
|
+
console.error(chalk98.red("No .sln file found between cwd and repo root"));
|
|
8895
8916
|
process.exit(1);
|
|
8896
8917
|
}
|
|
8897
8918
|
|
|
@@ -8900,7 +8921,7 @@ function resolveSolution(sln) {
|
|
|
8900
8921
|
if (sln) {
|
|
8901
8922
|
const resolved = path27.resolve(sln);
|
|
8902
8923
|
if (!existsSync28(resolved)) {
|
|
8903
|
-
console.error(
|
|
8924
|
+
console.error(chalk99.red(`Solution file not found: ${resolved}`));
|
|
8904
8925
|
process.exit(1);
|
|
8905
8926
|
}
|
|
8906
8927
|
return resolved;
|
|
@@ -8938,18 +8959,18 @@ function parseInspectReport(json) {
|
|
|
8938
8959
|
}
|
|
8939
8960
|
|
|
8940
8961
|
// src/commands/dotnet/runInspectCode.ts
|
|
8941
|
-
import { execSync as
|
|
8962
|
+
import { execSync as execSync24 } from "child_process";
|
|
8942
8963
|
import { existsSync as existsSync29, readFileSync as readFileSync23, unlinkSync as unlinkSync5 } from "fs";
|
|
8943
8964
|
import { tmpdir as tmpdir3 } from "os";
|
|
8944
8965
|
import path28 from "path";
|
|
8945
|
-
import
|
|
8966
|
+
import chalk100 from "chalk";
|
|
8946
8967
|
function assertJbInstalled() {
|
|
8947
8968
|
try {
|
|
8948
|
-
|
|
8969
|
+
execSync24("jb inspectcode --version", { stdio: "pipe" });
|
|
8949
8970
|
} catch {
|
|
8950
|
-
console.error(
|
|
8971
|
+
console.error(chalk100.red("jb is not installed. Install with:"));
|
|
8951
8972
|
console.error(
|
|
8952
|
-
|
|
8973
|
+
chalk100.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
|
|
8953
8974
|
);
|
|
8954
8975
|
process.exit(1);
|
|
8955
8976
|
}
|
|
@@ -8959,7 +8980,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
8959
8980
|
const includeFlag = include ? ` --include="${include}"` : "";
|
|
8960
8981
|
const sweaFlag = swea ? " --swea" : "";
|
|
8961
8982
|
try {
|
|
8962
|
-
|
|
8983
|
+
execSync24(
|
|
8963
8984
|
`jb inspectcode "${slnPath}" -o="${reportPath}"${includeFlag}${sweaFlag} --verbosity=OFF`,
|
|
8964
8985
|
{ stdio: "pipe" }
|
|
8965
8986
|
);
|
|
@@ -8967,11 +8988,11 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
8967
8988
|
if (err && typeof err === "object" && "stderr" in err) {
|
|
8968
8989
|
process.stderr.write(err.stderr);
|
|
8969
8990
|
}
|
|
8970
|
-
console.error(
|
|
8991
|
+
console.error(chalk100.red("jb inspectcode failed"));
|
|
8971
8992
|
process.exit(1);
|
|
8972
8993
|
}
|
|
8973
8994
|
if (!existsSync29(reportPath)) {
|
|
8974
|
-
console.error(
|
|
8995
|
+
console.error(chalk100.red("Report file not generated"));
|
|
8975
8996
|
process.exit(1);
|
|
8976
8997
|
}
|
|
8977
8998
|
const xml = readFileSync23(reportPath, "utf-8");
|
|
@@ -8980,8 +9001,8 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
8980
9001
|
}
|
|
8981
9002
|
|
|
8982
9003
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
8983
|
-
import { execSync as
|
|
8984
|
-
import
|
|
9004
|
+
import { execSync as execSync25 } from "child_process";
|
|
9005
|
+
import chalk101 from "chalk";
|
|
8985
9006
|
function resolveMsbuildPath() {
|
|
8986
9007
|
const { run: run4 } = loadConfig();
|
|
8987
9008
|
const configs = resolveRunConfigs(run4, getConfigDir());
|
|
@@ -8991,11 +9012,11 @@ function resolveMsbuildPath() {
|
|
|
8991
9012
|
function assertMsbuildInstalled() {
|
|
8992
9013
|
const msbuild = resolveMsbuildPath();
|
|
8993
9014
|
try {
|
|
8994
|
-
|
|
9015
|
+
execSync25(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
8995
9016
|
} catch {
|
|
8996
|
-
console.error(
|
|
9017
|
+
console.error(chalk101.red(`msbuild not found at: ${msbuild}`));
|
|
8997
9018
|
console.error(
|
|
8998
|
-
|
|
9019
|
+
chalk101.yellow(
|
|
8999
9020
|
"Configure it via a 'build' run entry in .claude/assist.yml or add msbuild to PATH."
|
|
9000
9021
|
)
|
|
9001
9022
|
);
|
|
@@ -9017,7 +9038,7 @@ function runRoslynInspect(slnPath) {
|
|
|
9017
9038
|
const msbuild = resolveMsbuildPath();
|
|
9018
9039
|
let output;
|
|
9019
9040
|
try {
|
|
9020
|
-
output =
|
|
9041
|
+
output = execSync25(
|
|
9021
9042
|
`"${msbuild}" "${slnPath}" -t:Build -v:minimal -maxcpucount -p:EnforceCodeStyleInBuild=true -p:RunAnalyzersDuringBuild=true 2>&1`,
|
|
9022
9043
|
{ encoding: "utf-8", stdio: "pipe", maxBuffer: 50 * 1024 * 1024 }
|
|
9023
9044
|
);
|
|
@@ -9042,17 +9063,17 @@ function runEngine(resolved, changedFiles, options2) {
|
|
|
9042
9063
|
// src/commands/dotnet/inspect.ts
|
|
9043
9064
|
function logScope(changedFiles) {
|
|
9044
9065
|
if (changedFiles === null) {
|
|
9045
|
-
console.log(
|
|
9066
|
+
console.log(chalk102.dim("Inspecting full solution..."));
|
|
9046
9067
|
} else {
|
|
9047
9068
|
console.log(
|
|
9048
|
-
|
|
9069
|
+
chalk102.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
|
|
9049
9070
|
);
|
|
9050
9071
|
}
|
|
9051
9072
|
}
|
|
9052
9073
|
function reportResults(issues, elapsed) {
|
|
9053
9074
|
if (issues.length > 0) displayIssues(issues);
|
|
9054
|
-
else console.log(
|
|
9055
|
-
console.log(
|
|
9075
|
+
else console.log(chalk102.green("No issues found"));
|
|
9076
|
+
console.log(chalk102.dim(`Completed in ${formatElapsed(elapsed)}`));
|
|
9056
9077
|
if (issues.length > 0) process.exit(1);
|
|
9057
9078
|
}
|
|
9058
9079
|
async function inspect(sln, options2) {
|
|
@@ -9063,7 +9084,7 @@ async function inspect(sln, options2) {
|
|
|
9063
9084
|
const scope = parseScope(options2.scope);
|
|
9064
9085
|
const changedFiles = getChangedCsFiles(scope);
|
|
9065
9086
|
if (changedFiles !== null && changedFiles.length === 0) {
|
|
9066
|
-
console.log(
|
|
9087
|
+
console.log(chalk102.green("No changed .cs files found"));
|
|
9067
9088
|
return;
|
|
9068
9089
|
}
|
|
9069
9090
|
logScope(changedFiles);
|
|
@@ -9317,7 +9338,7 @@ function registerHandover(program2) {
|
|
|
9317
9338
|
}
|
|
9318
9339
|
|
|
9319
9340
|
// src/commands/jira/acceptanceCriteria.ts
|
|
9320
|
-
import
|
|
9341
|
+
import chalk104 from "chalk";
|
|
9321
9342
|
|
|
9322
9343
|
// src/commands/jira/adfToText.ts
|
|
9323
9344
|
function renderInline(node) {
|
|
@@ -9377,12 +9398,12 @@ function adfToText(doc) {
|
|
|
9377
9398
|
}
|
|
9378
9399
|
|
|
9379
9400
|
// src/commands/jira/fetchIssue.ts
|
|
9380
|
-
import { execSync as
|
|
9381
|
-
import
|
|
9401
|
+
import { execSync as execSync26 } from "child_process";
|
|
9402
|
+
import chalk103 from "chalk";
|
|
9382
9403
|
function fetchIssue(issueKey, fields) {
|
|
9383
9404
|
let result;
|
|
9384
9405
|
try {
|
|
9385
|
-
result =
|
|
9406
|
+
result = execSync26(
|
|
9386
9407
|
`acli jira workitem view ${issueKey} -f ${fields} --json`,
|
|
9387
9408
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
9388
9409
|
);
|
|
@@ -9391,15 +9412,15 @@ function fetchIssue(issueKey, fields) {
|
|
|
9391
9412
|
const stderr = error.stderr;
|
|
9392
9413
|
if (stderr.includes("unauthorized")) {
|
|
9393
9414
|
console.error(
|
|
9394
|
-
|
|
9415
|
+
chalk103.red("Jira authentication expired."),
|
|
9395
9416
|
"Run",
|
|
9396
|
-
|
|
9417
|
+
chalk103.cyan("assist jira auth"),
|
|
9397
9418
|
"to re-authenticate."
|
|
9398
9419
|
);
|
|
9399
9420
|
process.exit(1);
|
|
9400
9421
|
}
|
|
9401
9422
|
}
|
|
9402
|
-
console.error(
|
|
9423
|
+
console.error(chalk103.red(`Failed to fetch ${issueKey}.`));
|
|
9403
9424
|
process.exit(1);
|
|
9404
9425
|
}
|
|
9405
9426
|
return JSON.parse(result);
|
|
@@ -9413,7 +9434,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
9413
9434
|
const parsed = fetchIssue(issueKey, field);
|
|
9414
9435
|
const acValue = parsed?.fields?.[field];
|
|
9415
9436
|
if (!acValue) {
|
|
9416
|
-
console.log(
|
|
9437
|
+
console.log(chalk104.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
9417
9438
|
return;
|
|
9418
9439
|
}
|
|
9419
9440
|
if (typeof acValue === "string") {
|
|
@@ -9428,7 +9449,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
9428
9449
|
}
|
|
9429
9450
|
|
|
9430
9451
|
// src/commands/jira/jiraAuth.ts
|
|
9431
|
-
import { execSync as
|
|
9452
|
+
import { execSync as execSync27 } from "child_process";
|
|
9432
9453
|
|
|
9433
9454
|
// src/shared/loadJson.ts
|
|
9434
9455
|
import { existsSync as existsSync32, mkdirSync as mkdirSync7, readFileSync as readFileSync26, writeFileSync as writeFileSync18 } from "fs";
|
|
@@ -9492,7 +9513,7 @@ async function jiraAuth() {
|
|
|
9492
9513
|
console.error("All fields are required.");
|
|
9493
9514
|
process.exit(1);
|
|
9494
9515
|
}
|
|
9495
|
-
|
|
9516
|
+
execSync27(`acli jira auth login --site ${site} --email "${email}" --token`, {
|
|
9496
9517
|
encoding: "utf-8",
|
|
9497
9518
|
input: token,
|
|
9498
9519
|
stdio: ["pipe", "inherit", "inherit"]
|
|
@@ -9508,14 +9529,14 @@ async function jiraAuth() {
|
|
|
9508
9529
|
}
|
|
9509
9530
|
|
|
9510
9531
|
// src/commands/jira/viewIssue.ts
|
|
9511
|
-
import
|
|
9532
|
+
import chalk105 from "chalk";
|
|
9512
9533
|
function viewIssue(issueKey) {
|
|
9513
9534
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
9514
9535
|
const fields = parsed?.fields;
|
|
9515
9536
|
const summary = fields?.summary;
|
|
9516
9537
|
const description = fields?.description;
|
|
9517
9538
|
if (summary) {
|
|
9518
|
-
console.log(
|
|
9539
|
+
console.log(chalk105.bold(summary));
|
|
9519
9540
|
}
|
|
9520
9541
|
if (description) {
|
|
9521
9542
|
if (summary) console.log();
|
|
@@ -9529,7 +9550,7 @@ function viewIssue(issueKey) {
|
|
|
9529
9550
|
}
|
|
9530
9551
|
if (!summary && !description) {
|
|
9531
9552
|
console.log(
|
|
9532
|
-
|
|
9553
|
+
chalk105.yellow(`No summary or description found on ${issueKey}.`)
|
|
9533
9554
|
);
|
|
9534
9555
|
}
|
|
9535
9556
|
}
|
|
@@ -9545,15 +9566,15 @@ function registerJira(program2) {
|
|
|
9545
9566
|
// src/commands/mermaid/index.ts
|
|
9546
9567
|
import { mkdirSync as mkdirSync8, readdirSync as readdirSync5 } from "fs";
|
|
9547
9568
|
import { resolve as resolve10 } from "path";
|
|
9548
|
-
import
|
|
9569
|
+
import chalk108 from "chalk";
|
|
9549
9570
|
|
|
9550
9571
|
// src/commands/mermaid/exportFile.ts
|
|
9551
9572
|
import { readFileSync as readFileSync27, writeFileSync as writeFileSync19 } from "fs";
|
|
9552
9573
|
import { basename as basename7, extname, resolve as resolve9 } from "path";
|
|
9553
|
-
import
|
|
9574
|
+
import chalk107 from "chalk";
|
|
9554
9575
|
|
|
9555
9576
|
// src/commands/mermaid/renderBlock.ts
|
|
9556
|
-
import
|
|
9577
|
+
import chalk106 from "chalk";
|
|
9557
9578
|
async function renderBlock(krokiUrl, source) {
|
|
9558
9579
|
const response = await fetch(`${krokiUrl}/mermaid/svg`, {
|
|
9559
9580
|
method: "POST",
|
|
@@ -9562,7 +9583,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
9562
9583
|
});
|
|
9563
9584
|
if (!response.ok) {
|
|
9564
9585
|
console.error(
|
|
9565
|
-
|
|
9586
|
+
chalk106.red(
|
|
9566
9587
|
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
9567
9588
|
)
|
|
9568
9589
|
);
|
|
@@ -9580,19 +9601,19 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
9580
9601
|
if (onlyIndex !== void 0) {
|
|
9581
9602
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
9582
9603
|
console.error(
|
|
9583
|
-
|
|
9604
|
+
chalk107.red(
|
|
9584
9605
|
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
9585
9606
|
)
|
|
9586
9607
|
);
|
|
9587
9608
|
process.exit(1);
|
|
9588
9609
|
}
|
|
9589
9610
|
console.log(
|
|
9590
|
-
|
|
9611
|
+
chalk107.gray(
|
|
9591
9612
|
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
9592
9613
|
)
|
|
9593
9614
|
);
|
|
9594
9615
|
} else {
|
|
9595
|
-
console.log(
|
|
9616
|
+
console.log(chalk107.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
9596
9617
|
}
|
|
9597
9618
|
for (const [i, source] of blocks.entries()) {
|
|
9598
9619
|
const idx = i + 1;
|
|
@@ -9600,7 +9621,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
9600
9621
|
const outPath = resolve9(outDir, `${stem}-${idx}.svg`);
|
|
9601
9622
|
const svg = await renderBlock(krokiUrl, source);
|
|
9602
9623
|
writeFileSync19(outPath, svg, "utf8");
|
|
9603
|
-
console.log(
|
|
9624
|
+
console.log(chalk107.green(` \u2192 ${outPath}`));
|
|
9604
9625
|
}
|
|
9605
9626
|
}
|
|
9606
9627
|
function extractMermaidBlocks(markdown) {
|
|
@@ -9616,18 +9637,18 @@ async function mermaidExport(file, options2 = {}) {
|
|
|
9616
9637
|
if (options2.index !== void 0) {
|
|
9617
9638
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
9618
9639
|
console.error(
|
|
9619
|
-
|
|
9640
|
+
chalk108.red(`--index must be a positive integer (got ${options2.index})`)
|
|
9620
9641
|
);
|
|
9621
9642
|
process.exit(1);
|
|
9622
9643
|
}
|
|
9623
9644
|
if (!file) {
|
|
9624
|
-
console.error(
|
|
9645
|
+
console.error(chalk108.red("--index requires a file argument"));
|
|
9625
9646
|
process.exit(1);
|
|
9626
9647
|
}
|
|
9627
9648
|
}
|
|
9628
9649
|
const files = file ? [file] : readdirSync5(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
|
|
9629
9650
|
if (files.length === 0) {
|
|
9630
|
-
console.log(
|
|
9651
|
+
console.log(chalk108.gray("No markdown files found in current directory."));
|
|
9631
9652
|
return;
|
|
9632
9653
|
}
|
|
9633
9654
|
for (const f of files) {
|
|
@@ -9650,7 +9671,7 @@ function registerMermaid(program2) {
|
|
|
9650
9671
|
}
|
|
9651
9672
|
|
|
9652
9673
|
// src/commands/news/add/index.ts
|
|
9653
|
-
import
|
|
9674
|
+
import chalk109 from "chalk";
|
|
9654
9675
|
import enquirer8 from "enquirer";
|
|
9655
9676
|
async function add2(url) {
|
|
9656
9677
|
if (!url) {
|
|
@@ -9673,17 +9694,17 @@ async function add2(url) {
|
|
|
9673
9694
|
const news = config.news ?? {};
|
|
9674
9695
|
const feeds = news.feeds ?? [];
|
|
9675
9696
|
if (feeds.includes(url)) {
|
|
9676
|
-
console.log(
|
|
9697
|
+
console.log(chalk109.yellow("Feed already exists in config"));
|
|
9677
9698
|
return;
|
|
9678
9699
|
}
|
|
9679
9700
|
feeds.push(url);
|
|
9680
9701
|
config.news = { ...news, feeds };
|
|
9681
9702
|
saveGlobalConfig(config);
|
|
9682
|
-
console.log(
|
|
9703
|
+
console.log(chalk109.green(`Added feed: ${url}`));
|
|
9683
9704
|
}
|
|
9684
9705
|
|
|
9685
9706
|
// src/commands/news/web/handleRequest.ts
|
|
9686
|
-
import
|
|
9707
|
+
import chalk110 from "chalk";
|
|
9687
9708
|
|
|
9688
9709
|
// src/commands/news/web/shared.ts
|
|
9689
9710
|
import { decodeHTML } from "entities";
|
|
@@ -9819,17 +9840,17 @@ function prefetch() {
|
|
|
9819
9840
|
const config = loadConfig();
|
|
9820
9841
|
const total = config.news.feeds.length;
|
|
9821
9842
|
if (total === 0) return;
|
|
9822
|
-
process.stdout.write(
|
|
9843
|
+
process.stdout.write(chalk110.dim(`Fetching ${total} feed(s)\u2026 `));
|
|
9823
9844
|
prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
|
|
9824
9845
|
const width = 20;
|
|
9825
9846
|
const filled = Math.round(done2 / t * width);
|
|
9826
9847
|
const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
|
|
9827
9848
|
process.stdout.write(
|
|
9828
|
-
`\r${
|
|
9849
|
+
`\r${chalk110.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
|
|
9829
9850
|
);
|
|
9830
9851
|
}).then((items2) => {
|
|
9831
9852
|
process.stdout.write(
|
|
9832
|
-
`\r${
|
|
9853
|
+
`\r${chalk110.green(`Fetched ${items2.length} items from ${total} feed(s)`)}
|
|
9833
9854
|
`
|
|
9834
9855
|
);
|
|
9835
9856
|
cachedItems = items2;
|
|
@@ -9874,7 +9895,7 @@ function registerNews(program2) {
|
|
|
9874
9895
|
}
|
|
9875
9896
|
|
|
9876
9897
|
// src/commands/prompts/printPromptsTable.ts
|
|
9877
|
-
import
|
|
9898
|
+
import chalk111 from "chalk";
|
|
9878
9899
|
function truncate(str, max) {
|
|
9879
9900
|
if (str.length <= max) return str;
|
|
9880
9901
|
return `${str.slice(0, max - 1)}\u2026`;
|
|
@@ -9892,14 +9913,14 @@ function printPromptsTable(rows) {
|
|
|
9892
9913
|
"Command".padEnd(commandWidth),
|
|
9893
9914
|
"Repos"
|
|
9894
9915
|
].join(" ");
|
|
9895
|
-
console.log(
|
|
9896
|
-
console.log(
|
|
9916
|
+
console.log(chalk111.dim(header));
|
|
9917
|
+
console.log(chalk111.dim("-".repeat(header.length)));
|
|
9897
9918
|
for (const row of rows) {
|
|
9898
9919
|
const count4 = String(row.count).padStart(countWidth);
|
|
9899
9920
|
const tool = row.tool.padEnd(toolWidth);
|
|
9900
9921
|
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
9901
9922
|
console.log(
|
|
9902
|
-
`${
|
|
9923
|
+
`${chalk111.yellow(count4)} ${tool} ${command} ${chalk111.dim(row.repos)}`
|
|
9903
9924
|
);
|
|
9904
9925
|
}
|
|
9905
9926
|
}
|
|
@@ -9955,10 +9976,10 @@ function runGhGraphql(mutation, vars) {
|
|
|
9955
9976
|
}
|
|
9956
9977
|
|
|
9957
9978
|
// src/commands/prs/shared.ts
|
|
9958
|
-
import { execSync as
|
|
9979
|
+
import { execSync as execSync29 } from "child_process";
|
|
9959
9980
|
|
|
9960
9981
|
// src/commands/prs/getPreferredRemoteRepo.ts
|
|
9961
|
-
import { execSync as
|
|
9982
|
+
import { execSync as execSync28 } from "child_process";
|
|
9962
9983
|
var GITHUB_URL_PATTERN = /(?:git@github\.com:|https:\/\/github\.com\/)([^/]+)\/([^/]+?)(?:\.git)?\/?$/;
|
|
9963
9984
|
function parseGitHubUrl(url) {
|
|
9964
9985
|
const match = url.match(GITHUB_URL_PATTERN);
|
|
@@ -9967,7 +9988,7 @@ function parseGitHubUrl(url) {
|
|
|
9967
9988
|
}
|
|
9968
9989
|
function tryGetRemoteUrl(remote) {
|
|
9969
9990
|
try {
|
|
9970
|
-
return
|
|
9991
|
+
return execSync28(`git remote get-url ${remote}`, {
|
|
9971
9992
|
encoding: "utf-8",
|
|
9972
9993
|
stdio: ["pipe", "pipe", "pipe"]
|
|
9973
9994
|
}).trim();
|
|
@@ -9977,7 +9998,7 @@ function tryGetRemoteUrl(remote) {
|
|
|
9977
9998
|
}
|
|
9978
9999
|
function getCurrentBranchRemote() {
|
|
9979
10000
|
try {
|
|
9980
|
-
const ref =
|
|
10001
|
+
const ref = execSync28(
|
|
9981
10002
|
"git rev-parse --abbrev-ref --symbolic-full-name @{u}",
|
|
9982
10003
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
9983
10004
|
).trim();
|
|
@@ -9989,7 +10010,7 @@ function getCurrentBranchRemote() {
|
|
|
9989
10010
|
}
|
|
9990
10011
|
function listRemotes() {
|
|
9991
10012
|
try {
|
|
9992
|
-
return
|
|
10013
|
+
return execSync28("git remote", {
|
|
9993
10014
|
encoding: "utf-8",
|
|
9994
10015
|
stdio: ["pipe", "pipe", "pipe"]
|
|
9995
10016
|
}).trim().split("\n").filter(Boolean);
|
|
@@ -10034,12 +10055,12 @@ function getRepoInfo() {
|
|
|
10034
10055
|
const preferred = getPreferredRemoteRepo();
|
|
10035
10056
|
if (preferred) return preferred;
|
|
10036
10057
|
const repoInfo = JSON.parse(
|
|
10037
|
-
|
|
10058
|
+
execSync29("gh repo view --json owner,name", { encoding: "utf-8" })
|
|
10038
10059
|
);
|
|
10039
10060
|
return { org: repoInfo.owner.login, repo: repoInfo.name };
|
|
10040
10061
|
}
|
|
10041
10062
|
function getCurrentBranch() {
|
|
10042
|
-
return
|
|
10063
|
+
return execSync29("git rev-parse --abbrev-ref HEAD", {
|
|
10043
10064
|
encoding: "utf-8"
|
|
10044
10065
|
}).trim();
|
|
10045
10066
|
}
|
|
@@ -10047,7 +10068,7 @@ function viewCurrentPr(fields) {
|
|
|
10047
10068
|
const { org, repo } = getRepoInfo();
|
|
10048
10069
|
const branch = getCurrentBranch();
|
|
10049
10070
|
return JSON.parse(
|
|
10050
|
-
|
|
10071
|
+
execSync29(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
|
|
10051
10072
|
encoding: "utf-8"
|
|
10052
10073
|
})
|
|
10053
10074
|
);
|
|
@@ -10129,10 +10150,10 @@ function comment2(path52, line, body, startLine) {
|
|
|
10129
10150
|
}
|
|
10130
10151
|
|
|
10131
10152
|
// src/commands/prs/fixed.ts
|
|
10132
|
-
import { execSync as
|
|
10153
|
+
import { execSync as execSync31 } from "child_process";
|
|
10133
10154
|
|
|
10134
10155
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
10135
|
-
import { execSync as
|
|
10156
|
+
import { execSync as execSync30 } from "child_process";
|
|
10136
10157
|
import { unlinkSync as unlinkSync8, writeFileSync as writeFileSync21 } from "fs";
|
|
10137
10158
|
import { tmpdir as tmpdir5 } from "os";
|
|
10138
10159
|
import { join as join32 } from "path";
|
|
@@ -10162,7 +10183,7 @@ function deleteCommentsCache(prNumber) {
|
|
|
10162
10183
|
|
|
10163
10184
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
10164
10185
|
function replyToComment(org, repo, prNumber, commentId, message) {
|
|
10165
|
-
|
|
10186
|
+
execSync30(
|
|
10166
10187
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, '\\"')}" -F in_reply_to=${commentId}`,
|
|
10167
10188
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
10168
10189
|
);
|
|
@@ -10172,7 +10193,7 @@ function resolveThread(threadId) {
|
|
|
10172
10193
|
const queryFile = join32(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
|
|
10173
10194
|
writeFileSync21(queryFile, mutation);
|
|
10174
10195
|
try {
|
|
10175
|
-
|
|
10196
|
+
execSync30(
|
|
10176
10197
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
10177
10198
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
10178
10199
|
);
|
|
@@ -10224,7 +10245,7 @@ function resolveCommentWithReply(commentId, message) {
|
|
|
10224
10245
|
// src/commands/prs/fixed.ts
|
|
10225
10246
|
function verifySha(sha) {
|
|
10226
10247
|
try {
|
|
10227
|
-
return
|
|
10248
|
+
return execSync31(`git rev-parse --verify ${sha}`, {
|
|
10228
10249
|
encoding: "utf-8"
|
|
10229
10250
|
}).trim();
|
|
10230
10251
|
} catch {
|
|
@@ -10238,7 +10259,7 @@ function fixed(commentId, sha) {
|
|
|
10238
10259
|
const { org, repo } = getRepoInfo();
|
|
10239
10260
|
const repoUrl = `https://github.com/${org}/${repo}`;
|
|
10240
10261
|
const message = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
|
|
10241
|
-
|
|
10262
|
+
execSync31("git push", { stdio: "inherit" });
|
|
10242
10263
|
resolveCommentWithReply(commentId, message);
|
|
10243
10264
|
} catch (error) {
|
|
10244
10265
|
if (isGhNotInstalled(error)) {
|
|
@@ -10256,7 +10277,7 @@ import { join as join34 } from "path";
|
|
|
10256
10277
|
import { stringify } from "yaml";
|
|
10257
10278
|
|
|
10258
10279
|
// src/commands/prs/fetchThreadIds.ts
|
|
10259
|
-
import { execSync as
|
|
10280
|
+
import { execSync as execSync32 } from "child_process";
|
|
10260
10281
|
import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync22 } from "fs";
|
|
10261
10282
|
import { tmpdir as tmpdir6 } from "os";
|
|
10262
10283
|
import { join as join33 } from "path";
|
|
@@ -10265,7 +10286,7 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
10265
10286
|
const queryFile = join33(tmpdir6(), `gh-query-${Date.now()}.graphql`);
|
|
10266
10287
|
writeFileSync22(queryFile, THREAD_QUERY);
|
|
10267
10288
|
try {
|
|
10268
|
-
const result =
|
|
10289
|
+
const result = execSync32(
|
|
10269
10290
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
10270
10291
|
{ encoding: "utf-8" }
|
|
10271
10292
|
);
|
|
@@ -10287,9 +10308,9 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
10287
10308
|
}
|
|
10288
10309
|
|
|
10289
10310
|
// src/commands/prs/listComments/fetchReviewComments.ts
|
|
10290
|
-
import { execSync as
|
|
10311
|
+
import { execSync as execSync33 } from "child_process";
|
|
10291
10312
|
function fetchJson(endpoint) {
|
|
10292
|
-
const result =
|
|
10313
|
+
const result = execSync33(`gh api --paginate ${endpoint}`, {
|
|
10293
10314
|
encoding: "utf-8"
|
|
10294
10315
|
});
|
|
10295
10316
|
if (!result.trim()) return [];
|
|
@@ -10331,20 +10352,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
10331
10352
|
}
|
|
10332
10353
|
|
|
10333
10354
|
// src/commands/prs/listComments/printComments.ts
|
|
10334
|
-
import
|
|
10355
|
+
import chalk112 from "chalk";
|
|
10335
10356
|
function formatForHuman(comment3) {
|
|
10336
10357
|
if (comment3.type === "review") {
|
|
10337
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
10358
|
+
const stateColor = comment3.state === "APPROVED" ? chalk112.green : comment3.state === "CHANGES_REQUESTED" ? chalk112.red : chalk112.yellow;
|
|
10338
10359
|
return [
|
|
10339
|
-
`${
|
|
10360
|
+
`${chalk112.cyan("Review")} by ${chalk112.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
10340
10361
|
comment3.body,
|
|
10341
10362
|
""
|
|
10342
10363
|
].join("\n");
|
|
10343
10364
|
}
|
|
10344
10365
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
10345
10366
|
return [
|
|
10346
|
-
`${
|
|
10347
|
-
|
|
10367
|
+
`${chalk112.cyan("Line comment")} by ${chalk112.bold(comment3.user)} on ${chalk112.dim(`${comment3.path}${location}`)}`,
|
|
10368
|
+
chalk112.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
10348
10369
|
comment3.body,
|
|
10349
10370
|
""
|
|
10350
10371
|
].join("\n");
|
|
@@ -10428,19 +10449,19 @@ async function listComments() {
|
|
|
10428
10449
|
}
|
|
10429
10450
|
|
|
10430
10451
|
// src/commands/prs/prs/index.ts
|
|
10431
|
-
import { execSync as
|
|
10452
|
+
import { execSync as execSync34 } from "child_process";
|
|
10432
10453
|
|
|
10433
10454
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
10434
10455
|
import enquirer9 from "enquirer";
|
|
10435
10456
|
|
|
10436
10457
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
10437
|
-
import
|
|
10458
|
+
import chalk113 from "chalk";
|
|
10438
10459
|
var STATUS_MAP = {
|
|
10439
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
10440
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
10460
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk113.magenta("merged"), date: pr.mergedAt } : null,
|
|
10461
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk113.red("closed"), date: pr.closedAt } : null
|
|
10441
10462
|
};
|
|
10442
10463
|
function defaultStatus(pr) {
|
|
10443
|
-
return { label:
|
|
10464
|
+
return { label: chalk113.green("opened"), date: pr.createdAt };
|
|
10444
10465
|
}
|
|
10445
10466
|
function getStatus2(pr) {
|
|
10446
10467
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -10449,11 +10470,11 @@ function formatDate(dateStr) {
|
|
|
10449
10470
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
10450
10471
|
}
|
|
10451
10472
|
function formatPrHeader(pr, status2) {
|
|
10452
|
-
return `${
|
|
10473
|
+
return `${chalk113.cyan(`#${pr.number}`)} ${pr.title} ${chalk113.dim(`(${pr.author.login},`)} ${status2.label} ${chalk113.dim(`${formatDate(status2.date)})`)}`;
|
|
10453
10474
|
}
|
|
10454
10475
|
function logPrDetails(pr) {
|
|
10455
10476
|
console.log(
|
|
10456
|
-
|
|
10477
|
+
chalk113.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
10457
10478
|
);
|
|
10458
10479
|
console.log();
|
|
10459
10480
|
}
|
|
@@ -10535,7 +10556,7 @@ async function prs(options2) {
|
|
|
10535
10556
|
const state = options2.open ? "open" : options2.closed ? "closed" : "all";
|
|
10536
10557
|
try {
|
|
10537
10558
|
const { org, repo } = getRepoInfo();
|
|
10538
|
-
const result =
|
|
10559
|
+
const result = execSync34(
|
|
10539
10560
|
`gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100 -R ${org}/${repo}`,
|
|
10540
10561
|
{ encoding: "utf-8" }
|
|
10541
10562
|
);
|
|
@@ -10558,7 +10579,7 @@ async function prs(options2) {
|
|
|
10558
10579
|
}
|
|
10559
10580
|
|
|
10560
10581
|
// src/commands/prs/wontfix.ts
|
|
10561
|
-
import { execSync as
|
|
10582
|
+
import { execSync as execSync35 } from "child_process";
|
|
10562
10583
|
function validateReason(reason) {
|
|
10563
10584
|
const lowerReason = reason.toLowerCase();
|
|
10564
10585
|
if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
|
|
@@ -10575,7 +10596,7 @@ function validateShaReferences(reason) {
|
|
|
10575
10596
|
const invalidShas = [];
|
|
10576
10597
|
for (const sha of shas) {
|
|
10577
10598
|
try {
|
|
10578
|
-
|
|
10599
|
+
execSync35(`git cat-file -t ${sha}`, { stdio: "pipe" });
|
|
10579
10600
|
} catch {
|
|
10580
10601
|
invalidShas.push(sha);
|
|
10581
10602
|
}
|
|
@@ -10620,10 +10641,10 @@ function registerPrs(program2) {
|
|
|
10620
10641
|
}
|
|
10621
10642
|
|
|
10622
10643
|
// src/commands/ravendb/ravendbAuth.ts
|
|
10623
|
-
import
|
|
10644
|
+
import chalk119 from "chalk";
|
|
10624
10645
|
|
|
10625
10646
|
// src/shared/createConnectionAuth.ts
|
|
10626
|
-
import
|
|
10647
|
+
import chalk114 from "chalk";
|
|
10627
10648
|
function listConnections(connections, format2) {
|
|
10628
10649
|
if (connections.length === 0) {
|
|
10629
10650
|
console.log("No connections configured.");
|
|
@@ -10636,7 +10657,7 @@ function listConnections(connections, format2) {
|
|
|
10636
10657
|
function removeConnection(connections, name, save) {
|
|
10637
10658
|
const filtered = connections.filter((c) => c.name !== name);
|
|
10638
10659
|
if (filtered.length === connections.length) {
|
|
10639
|
-
console.error(
|
|
10660
|
+
console.error(chalk114.red(`Connection "${name}" not found.`));
|
|
10640
10661
|
process.exit(1);
|
|
10641
10662
|
}
|
|
10642
10663
|
save(filtered);
|
|
@@ -10682,17 +10703,17 @@ function saveConnections(connections) {
|
|
|
10682
10703
|
}
|
|
10683
10704
|
|
|
10684
10705
|
// src/commands/ravendb/promptConnection.ts
|
|
10685
|
-
import
|
|
10706
|
+
import chalk117 from "chalk";
|
|
10686
10707
|
|
|
10687
10708
|
// src/commands/ravendb/selectOpSecret.ts
|
|
10688
|
-
import
|
|
10709
|
+
import chalk116 from "chalk";
|
|
10689
10710
|
import Enquirer2 from "enquirer";
|
|
10690
10711
|
|
|
10691
10712
|
// src/commands/ravendb/searchItems.ts
|
|
10692
|
-
import { execSync as
|
|
10693
|
-
import
|
|
10713
|
+
import { execSync as execSync36 } from "child_process";
|
|
10714
|
+
import chalk115 from "chalk";
|
|
10694
10715
|
function opExec(args) {
|
|
10695
|
-
return
|
|
10716
|
+
return execSync36(`op ${args}`, {
|
|
10696
10717
|
encoding: "utf-8",
|
|
10697
10718
|
stdio: ["pipe", "pipe", "pipe"]
|
|
10698
10719
|
}).trim();
|
|
@@ -10703,7 +10724,7 @@ function searchItems(search2) {
|
|
|
10703
10724
|
items2 = JSON.parse(opExec("item list --format=json"));
|
|
10704
10725
|
} catch {
|
|
10705
10726
|
console.error(
|
|
10706
|
-
|
|
10727
|
+
chalk115.red(
|
|
10707
10728
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
10708
10729
|
)
|
|
10709
10730
|
);
|
|
@@ -10717,7 +10738,7 @@ function getItemFields(itemId) {
|
|
|
10717
10738
|
const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
|
|
10718
10739
|
return item.fields.filter((f) => f.reference && f.label);
|
|
10719
10740
|
} catch {
|
|
10720
|
-
console.error(
|
|
10741
|
+
console.error(chalk115.red("Failed to get item details from 1Password."));
|
|
10721
10742
|
process.exit(1);
|
|
10722
10743
|
}
|
|
10723
10744
|
}
|
|
@@ -10736,7 +10757,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
10736
10757
|
}).run();
|
|
10737
10758
|
const items2 = searchItems(search2);
|
|
10738
10759
|
if (items2.length === 0) {
|
|
10739
|
-
console.error(
|
|
10760
|
+
console.error(chalk116.red(`No items found matching "${search2}".`));
|
|
10740
10761
|
process.exit(1);
|
|
10741
10762
|
}
|
|
10742
10763
|
const itemId = await selectOne(
|
|
@@ -10745,7 +10766,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
10745
10766
|
);
|
|
10746
10767
|
const fields = getItemFields(itemId);
|
|
10747
10768
|
if (fields.length === 0) {
|
|
10748
|
-
console.error(
|
|
10769
|
+
console.error(chalk116.red("No fields with references found on this item."));
|
|
10749
10770
|
process.exit(1);
|
|
10750
10771
|
}
|
|
10751
10772
|
const ref = await selectOne(
|
|
@@ -10759,7 +10780,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
10759
10780
|
async function promptConnection(existingNames) {
|
|
10760
10781
|
const name = await promptInput("name", "Connection name:");
|
|
10761
10782
|
if (existingNames.includes(name)) {
|
|
10762
|
-
console.error(
|
|
10783
|
+
console.error(chalk117.red(`Connection "${name}" already exists.`));
|
|
10763
10784
|
process.exit(1);
|
|
10764
10785
|
}
|
|
10765
10786
|
const url = await promptInput(
|
|
@@ -10768,22 +10789,22 @@ async function promptConnection(existingNames) {
|
|
|
10768
10789
|
);
|
|
10769
10790
|
const database = await promptInput("database", "Database name:");
|
|
10770
10791
|
if (!name || !url || !database) {
|
|
10771
|
-
console.error(
|
|
10792
|
+
console.error(chalk117.red("All fields are required."));
|
|
10772
10793
|
process.exit(1);
|
|
10773
10794
|
}
|
|
10774
10795
|
const apiKeyRef = await selectOpSecret();
|
|
10775
|
-
console.log(
|
|
10796
|
+
console.log(chalk117.dim(`Using: ${apiKeyRef}`));
|
|
10776
10797
|
return { name, url, database, apiKeyRef };
|
|
10777
10798
|
}
|
|
10778
10799
|
|
|
10779
10800
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
10780
|
-
import
|
|
10801
|
+
import chalk118 from "chalk";
|
|
10781
10802
|
function ravendbSetConnection(name) {
|
|
10782
10803
|
const raw = loadGlobalConfigRaw();
|
|
10783
10804
|
const ravendb = raw.ravendb ?? {};
|
|
10784
10805
|
const connections = ravendb.connections ?? [];
|
|
10785
10806
|
if (!connections.some((c) => c.name === name)) {
|
|
10786
|
-
console.error(
|
|
10807
|
+
console.error(chalk118.red(`Connection "${name}" not found.`));
|
|
10787
10808
|
console.error(
|
|
10788
10809
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
10789
10810
|
);
|
|
@@ -10799,16 +10820,16 @@ function ravendbSetConnection(name) {
|
|
|
10799
10820
|
var ravendbAuth = createConnectionAuth({
|
|
10800
10821
|
load: loadConnections,
|
|
10801
10822
|
save: saveConnections,
|
|
10802
|
-
format: (c) => `${
|
|
10823
|
+
format: (c) => `${chalk119.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
10803
10824
|
promptNew: promptConnection,
|
|
10804
10825
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
10805
10826
|
});
|
|
10806
10827
|
|
|
10807
10828
|
// src/commands/ravendb/ravendbCollections.ts
|
|
10808
|
-
import
|
|
10829
|
+
import chalk123 from "chalk";
|
|
10809
10830
|
|
|
10810
10831
|
// src/commands/ravendb/ravenFetch.ts
|
|
10811
|
-
import
|
|
10832
|
+
import chalk121 from "chalk";
|
|
10812
10833
|
|
|
10813
10834
|
// src/commands/ravendb/getAccessToken.ts
|
|
10814
10835
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -10844,21 +10865,21 @@ ${errorText}`
|
|
|
10844
10865
|
}
|
|
10845
10866
|
|
|
10846
10867
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
10847
|
-
import { execSync as
|
|
10848
|
-
import
|
|
10868
|
+
import { execSync as execSync37 } from "child_process";
|
|
10869
|
+
import chalk120 from "chalk";
|
|
10849
10870
|
function resolveOpSecret(reference) {
|
|
10850
10871
|
if (!reference.startsWith("op://")) {
|
|
10851
|
-
console.error(
|
|
10872
|
+
console.error(chalk120.red(`Invalid secret reference: must start with op://`));
|
|
10852
10873
|
process.exit(1);
|
|
10853
10874
|
}
|
|
10854
10875
|
try {
|
|
10855
|
-
return
|
|
10876
|
+
return execSync37(`op read "${reference}"`, {
|
|
10856
10877
|
encoding: "utf-8",
|
|
10857
10878
|
stdio: ["pipe", "pipe", "pipe"]
|
|
10858
10879
|
}).trim();
|
|
10859
10880
|
} catch {
|
|
10860
10881
|
console.error(
|
|
10861
|
-
|
|
10882
|
+
chalk120.red(
|
|
10862
10883
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
10863
10884
|
)
|
|
10864
10885
|
);
|
|
@@ -10885,7 +10906,7 @@ async function ravenFetch(connection, path52) {
|
|
|
10885
10906
|
if (!response.ok) {
|
|
10886
10907
|
const body = await response.text();
|
|
10887
10908
|
console.error(
|
|
10888
|
-
|
|
10909
|
+
chalk121.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
10889
10910
|
);
|
|
10890
10911
|
console.error(body.substring(0, 500));
|
|
10891
10912
|
process.exit(1);
|
|
@@ -10894,7 +10915,7 @@ async function ravenFetch(connection, path52) {
|
|
|
10894
10915
|
}
|
|
10895
10916
|
|
|
10896
10917
|
// src/commands/ravendb/resolveConnection.ts
|
|
10897
|
-
import
|
|
10918
|
+
import chalk122 from "chalk";
|
|
10898
10919
|
function loadRavendb() {
|
|
10899
10920
|
const raw = loadGlobalConfigRaw();
|
|
10900
10921
|
const ravendb = raw.ravendb;
|
|
@@ -10908,7 +10929,7 @@ function resolveConnection(name) {
|
|
|
10908
10929
|
const connectionName = name ?? defaultConnection;
|
|
10909
10930
|
if (!connectionName) {
|
|
10910
10931
|
console.error(
|
|
10911
|
-
|
|
10932
|
+
chalk122.red(
|
|
10912
10933
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
10913
10934
|
)
|
|
10914
10935
|
);
|
|
@@ -10916,7 +10937,7 @@ function resolveConnection(name) {
|
|
|
10916
10937
|
}
|
|
10917
10938
|
const connection = connections.find((c) => c.name === connectionName);
|
|
10918
10939
|
if (!connection) {
|
|
10919
|
-
console.error(
|
|
10940
|
+
console.error(chalk122.red(`Connection "${connectionName}" not found.`));
|
|
10920
10941
|
console.error(
|
|
10921
10942
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
10922
10943
|
);
|
|
@@ -10947,15 +10968,15 @@ async function ravendbCollections(connectionName) {
|
|
|
10947
10968
|
return;
|
|
10948
10969
|
}
|
|
10949
10970
|
for (const c of collections) {
|
|
10950
|
-
console.log(`${
|
|
10971
|
+
console.log(`${chalk123.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
10951
10972
|
}
|
|
10952
10973
|
}
|
|
10953
10974
|
|
|
10954
10975
|
// src/commands/ravendb/ravendbQuery.ts
|
|
10955
|
-
import
|
|
10976
|
+
import chalk125 from "chalk";
|
|
10956
10977
|
|
|
10957
10978
|
// src/commands/ravendb/fetchAllPages.ts
|
|
10958
|
-
import
|
|
10979
|
+
import chalk124 from "chalk";
|
|
10959
10980
|
|
|
10960
10981
|
// src/commands/ravendb/buildQueryPath.ts
|
|
10961
10982
|
function buildQueryPath(opts) {
|
|
@@ -10993,7 +11014,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
10993
11014
|
allResults.push(...results);
|
|
10994
11015
|
start3 += results.length;
|
|
10995
11016
|
process.stderr.write(
|
|
10996
|
-
`\r${
|
|
11017
|
+
`\r${chalk124.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
10997
11018
|
);
|
|
10998
11019
|
if (start3 >= totalResults) break;
|
|
10999
11020
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -11008,7 +11029,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
11008
11029
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
11009
11030
|
const resolved = resolveArgs(connectionName, collection);
|
|
11010
11031
|
if (!resolved.collection && !options2.query) {
|
|
11011
|
-
console.error(
|
|
11032
|
+
console.error(chalk125.red("Provide a collection name or --query filter."));
|
|
11012
11033
|
process.exit(1);
|
|
11013
11034
|
}
|
|
11014
11035
|
const { collection: col } = resolved;
|
|
@@ -11046,7 +11067,7 @@ import { spawn as spawn5 } from "child_process";
|
|
|
11046
11067
|
import * as path29 from "path";
|
|
11047
11068
|
|
|
11048
11069
|
// src/commands/refactor/logViolations.ts
|
|
11049
|
-
import
|
|
11070
|
+
import chalk126 from "chalk";
|
|
11050
11071
|
var DEFAULT_MAX_LINES = 100;
|
|
11051
11072
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
11052
11073
|
if (violations.length === 0) {
|
|
@@ -11055,43 +11076,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
11055
11076
|
}
|
|
11056
11077
|
return;
|
|
11057
11078
|
}
|
|
11058
|
-
console.error(
|
|
11079
|
+
console.error(chalk126.red(`
|
|
11059
11080
|
Refactor check failed:
|
|
11060
11081
|
`));
|
|
11061
|
-
console.error(
|
|
11082
|
+
console.error(chalk126.red(` The following files exceed ${maxLines} lines:
|
|
11062
11083
|
`));
|
|
11063
11084
|
for (const violation of violations) {
|
|
11064
|
-
console.error(
|
|
11085
|
+
console.error(chalk126.red(` ${violation.file} (${violation.lines} lines)`));
|
|
11065
11086
|
}
|
|
11066
11087
|
console.error(
|
|
11067
|
-
|
|
11088
|
+
chalk126.yellow(
|
|
11068
11089
|
`
|
|
11069
11090
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
11070
11091
|
way to refactor it, ignore it with:
|
|
11071
11092
|
`
|
|
11072
11093
|
)
|
|
11073
11094
|
);
|
|
11074
|
-
console.error(
|
|
11095
|
+
console.error(chalk126.gray(` assist refactor ignore <file>
|
|
11075
11096
|
`));
|
|
11076
11097
|
if (process.env.CLAUDECODE) {
|
|
11077
|
-
console.error(
|
|
11098
|
+
console.error(chalk126.cyan(`
|
|
11078
11099
|
## Extracting Code to New Files
|
|
11079
11100
|
`));
|
|
11080
11101
|
console.error(
|
|
11081
|
-
|
|
11102
|
+
chalk126.cyan(
|
|
11082
11103
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
11083
11104
|
`
|
|
11084
11105
|
)
|
|
11085
11106
|
);
|
|
11086
11107
|
console.error(
|
|
11087
|
-
|
|
11108
|
+
chalk126.cyan(
|
|
11088
11109
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
11089
11110
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
11090
11111
|
`
|
|
11091
11112
|
)
|
|
11092
11113
|
);
|
|
11093
11114
|
console.error(
|
|
11094
|
-
|
|
11115
|
+
chalk126.cyan(
|
|
11095
11116
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
11096
11117
|
domains, move it to a common/shared folder.
|
|
11097
11118
|
`
|
|
@@ -11101,7 +11122,7 @@ Refactor check failed:
|
|
|
11101
11122
|
}
|
|
11102
11123
|
|
|
11103
11124
|
// src/commands/refactor/check/getViolations/index.ts
|
|
11104
|
-
import { execSync as
|
|
11125
|
+
import { execSync as execSync38 } from "child_process";
|
|
11105
11126
|
import fs19 from "fs";
|
|
11106
11127
|
import { minimatch as minimatch4 } from "minimatch";
|
|
11107
11128
|
|
|
@@ -11151,7 +11172,7 @@ function getGitFiles(options2) {
|
|
|
11151
11172
|
}
|
|
11152
11173
|
const files = /* @__PURE__ */ new Set();
|
|
11153
11174
|
if (options2.staged || options2.modified) {
|
|
11154
|
-
const staged =
|
|
11175
|
+
const staged = execSync38("git diff --cached --name-only", {
|
|
11155
11176
|
encoding: "utf-8"
|
|
11156
11177
|
});
|
|
11157
11178
|
for (const file of staged.trim().split("\n").filter(Boolean)) {
|
|
@@ -11159,7 +11180,7 @@ function getGitFiles(options2) {
|
|
|
11159
11180
|
}
|
|
11160
11181
|
}
|
|
11161
11182
|
if (options2.unstaged || options2.modified) {
|
|
11162
|
-
const unstaged =
|
|
11183
|
+
const unstaged = execSync38("git diff --name-only", { encoding: "utf-8" });
|
|
11163
11184
|
for (const file of unstaged.trim().split("\n").filter(Boolean)) {
|
|
11164
11185
|
files.add(file);
|
|
11165
11186
|
}
|
|
@@ -11247,7 +11268,7 @@ async function check(pattern2, options2) {
|
|
|
11247
11268
|
|
|
11248
11269
|
// src/commands/refactor/extract/index.ts
|
|
11249
11270
|
import path36 from "path";
|
|
11250
|
-
import
|
|
11271
|
+
import chalk129 from "chalk";
|
|
11251
11272
|
|
|
11252
11273
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
11253
11274
|
import { SyntaxKind as SyntaxKind3 } from "ts-morph";
|
|
@@ -11794,23 +11815,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
11794
11815
|
|
|
11795
11816
|
// src/commands/refactor/extract/displayPlan.ts
|
|
11796
11817
|
import path33 from "path";
|
|
11797
|
-
import
|
|
11818
|
+
import chalk127 from "chalk";
|
|
11798
11819
|
function section(title) {
|
|
11799
11820
|
return `
|
|
11800
|
-
${
|
|
11821
|
+
${chalk127.cyan(title)}`;
|
|
11801
11822
|
}
|
|
11802
11823
|
function displayImporters(plan2, cwd) {
|
|
11803
11824
|
if (plan2.importersToUpdate.length === 0) return;
|
|
11804
11825
|
console.log(section("Update importers:"));
|
|
11805
11826
|
for (const imp of plan2.importersToUpdate) {
|
|
11806
11827
|
const rel = path33.relative(cwd, imp.file.getFilePath());
|
|
11807
|
-
console.log(` ${
|
|
11828
|
+
console.log(` ${chalk127.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
11808
11829
|
}
|
|
11809
11830
|
}
|
|
11810
11831
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
11811
|
-
console.log(
|
|
11832
|
+
console.log(chalk127.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
11812
11833
|
`));
|
|
11813
|
-
console.log(` ${
|
|
11834
|
+
console.log(` ${chalk127.cyan("Functions to move:")}`);
|
|
11814
11835
|
for (const name of plan2.extractedNames) {
|
|
11815
11836
|
console.log(` ${name}`);
|
|
11816
11837
|
}
|
|
@@ -11844,7 +11865,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
11844
11865
|
|
|
11845
11866
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
11846
11867
|
import path35 from "path";
|
|
11847
|
-
import
|
|
11868
|
+
import chalk128 from "chalk";
|
|
11848
11869
|
import { Project as Project3 } from "ts-morph";
|
|
11849
11870
|
|
|
11850
11871
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -11904,7 +11925,7 @@ function loadProjectFile(file) {
|
|
|
11904
11925
|
});
|
|
11905
11926
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
11906
11927
|
if (!sourceFile) {
|
|
11907
|
-
console.log(
|
|
11928
|
+
console.log(chalk128.red(`File not found in project: ${file}`));
|
|
11908
11929
|
process.exit(1);
|
|
11909
11930
|
}
|
|
11910
11931
|
return { project, sourceFile };
|
|
@@ -11927,19 +11948,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
11927
11948
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
11928
11949
|
if (options2.apply) {
|
|
11929
11950
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
11930
|
-
console.log(
|
|
11951
|
+
console.log(chalk129.green("\nExtraction complete"));
|
|
11931
11952
|
} else {
|
|
11932
|
-
console.log(
|
|
11953
|
+
console.log(chalk129.dim("\nDry run. Use --apply to execute."));
|
|
11933
11954
|
}
|
|
11934
11955
|
}
|
|
11935
11956
|
|
|
11936
11957
|
// src/commands/refactor/ignore.ts
|
|
11937
11958
|
import fs21 from "fs";
|
|
11938
|
-
import
|
|
11959
|
+
import chalk130 from "chalk";
|
|
11939
11960
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
11940
11961
|
function ignore(file) {
|
|
11941
11962
|
if (!fs21.existsSync(file)) {
|
|
11942
|
-
console.error(
|
|
11963
|
+
console.error(chalk130.red(`Error: File does not exist: ${file}`));
|
|
11943
11964
|
process.exit(1);
|
|
11944
11965
|
}
|
|
11945
11966
|
const content = fs21.readFileSync(file, "utf-8");
|
|
@@ -11955,7 +11976,7 @@ function ignore(file) {
|
|
|
11955
11976
|
fs21.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
11956
11977
|
}
|
|
11957
11978
|
console.log(
|
|
11958
|
-
|
|
11979
|
+
chalk130.green(
|
|
11959
11980
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
11960
11981
|
)
|
|
11961
11982
|
);
|
|
@@ -11963,25 +11984,25 @@ function ignore(file) {
|
|
|
11963
11984
|
|
|
11964
11985
|
// src/commands/refactor/rename/index.ts
|
|
11965
11986
|
import path37 from "path";
|
|
11966
|
-
import
|
|
11987
|
+
import chalk131 from "chalk";
|
|
11967
11988
|
async function rename(source, destination, options2 = {}) {
|
|
11968
11989
|
const destPath = path37.resolve(destination);
|
|
11969
11990
|
const cwd = process.cwd();
|
|
11970
11991
|
const relSource = path37.relative(cwd, path37.resolve(source));
|
|
11971
11992
|
const relDest = path37.relative(cwd, destPath);
|
|
11972
11993
|
const { project, sourceFile } = loadProjectFile(source);
|
|
11973
|
-
console.log(
|
|
11994
|
+
console.log(chalk131.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
11974
11995
|
if (options2.apply) {
|
|
11975
11996
|
sourceFile.move(destPath);
|
|
11976
11997
|
await project.save();
|
|
11977
|
-
console.log(
|
|
11998
|
+
console.log(chalk131.green("Done"));
|
|
11978
11999
|
} else {
|
|
11979
|
-
console.log(
|
|
12000
|
+
console.log(chalk131.dim("Dry run. Use --apply to execute."));
|
|
11980
12001
|
}
|
|
11981
12002
|
}
|
|
11982
12003
|
|
|
11983
12004
|
// src/commands/refactor/renameSymbol/index.ts
|
|
11984
|
-
import
|
|
12005
|
+
import chalk132 from "chalk";
|
|
11985
12006
|
|
|
11986
12007
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
11987
12008
|
import { SyntaxKind as SyntaxKind13 } from "ts-morph";
|
|
@@ -12027,33 +12048,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
12027
12048
|
const { project, sourceFile } = loadProjectFile(file);
|
|
12028
12049
|
const symbol = findSymbol(sourceFile, oldName);
|
|
12029
12050
|
if (!symbol) {
|
|
12030
|
-
console.log(
|
|
12051
|
+
console.log(chalk132.red(`Symbol "${oldName}" not found in ${file}`));
|
|
12031
12052
|
process.exit(1);
|
|
12032
12053
|
}
|
|
12033
12054
|
const grouped = groupReferences(symbol, cwd);
|
|
12034
12055
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
12035
12056
|
console.log(
|
|
12036
|
-
|
|
12057
|
+
chalk132.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
12037
12058
|
`)
|
|
12038
12059
|
);
|
|
12039
12060
|
for (const [refFile, lines] of grouped) {
|
|
12040
12061
|
console.log(
|
|
12041
|
-
` ${
|
|
12062
|
+
` ${chalk132.dim(refFile)}: lines ${chalk132.cyan(lines.join(", "))}`
|
|
12042
12063
|
);
|
|
12043
12064
|
}
|
|
12044
12065
|
if (options2.apply) {
|
|
12045
12066
|
symbol.rename(newName);
|
|
12046
12067
|
await project.save();
|
|
12047
|
-
console.log(
|
|
12068
|
+
console.log(chalk132.green(`
|
|
12048
12069
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
12049
12070
|
} else {
|
|
12050
|
-
console.log(
|
|
12071
|
+
console.log(chalk132.dim("\nDry run. Use --apply to execute."));
|
|
12051
12072
|
}
|
|
12052
12073
|
}
|
|
12053
12074
|
|
|
12054
12075
|
// src/commands/refactor/restructure/index.ts
|
|
12055
12076
|
import path47 from "path";
|
|
12056
|
-
import
|
|
12077
|
+
import chalk135 from "chalk";
|
|
12057
12078
|
|
|
12058
12079
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
12059
12080
|
import path39 from "path";
|
|
@@ -12296,50 +12317,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
12296
12317
|
|
|
12297
12318
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
12298
12319
|
import path43 from "path";
|
|
12299
|
-
import
|
|
12320
|
+
import chalk133 from "chalk";
|
|
12300
12321
|
function relPath(filePath) {
|
|
12301
12322
|
return path43.relative(process.cwd(), filePath);
|
|
12302
12323
|
}
|
|
12303
12324
|
function displayMoves(plan2) {
|
|
12304
12325
|
if (plan2.moves.length === 0) return;
|
|
12305
|
-
console.log(
|
|
12326
|
+
console.log(chalk133.bold("\nFile moves:"));
|
|
12306
12327
|
for (const move of plan2.moves) {
|
|
12307
12328
|
console.log(
|
|
12308
|
-
` ${
|
|
12329
|
+
` ${chalk133.red(relPath(move.from))} \u2192 ${chalk133.green(relPath(move.to))}`
|
|
12309
12330
|
);
|
|
12310
|
-
console.log(
|
|
12331
|
+
console.log(chalk133.dim(` ${move.reason}`));
|
|
12311
12332
|
}
|
|
12312
12333
|
}
|
|
12313
12334
|
function displayRewrites(rewrites) {
|
|
12314
12335
|
if (rewrites.length === 0) return;
|
|
12315
12336
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
12316
|
-
console.log(
|
|
12337
|
+
console.log(chalk133.bold(`
|
|
12317
12338
|
Import rewrites (${affectedFiles.size} files):`));
|
|
12318
12339
|
for (const file of affectedFiles) {
|
|
12319
|
-
console.log(` ${
|
|
12340
|
+
console.log(` ${chalk133.cyan(relPath(file))}:`);
|
|
12320
12341
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
12321
12342
|
(r) => r.file === file
|
|
12322
12343
|
)) {
|
|
12323
12344
|
console.log(
|
|
12324
|
-
` ${
|
|
12345
|
+
` ${chalk133.red(`"${oldSpecifier}"`)} \u2192 ${chalk133.green(`"${newSpecifier}"`)}`
|
|
12325
12346
|
);
|
|
12326
12347
|
}
|
|
12327
12348
|
}
|
|
12328
12349
|
}
|
|
12329
12350
|
function displayPlan2(plan2) {
|
|
12330
12351
|
if (plan2.warnings.length > 0) {
|
|
12331
|
-
console.log(
|
|
12332
|
-
for (const w of plan2.warnings) console.log(
|
|
12352
|
+
console.log(chalk133.yellow("\nWarnings:"));
|
|
12353
|
+
for (const w of plan2.warnings) console.log(chalk133.yellow(` ${w}`));
|
|
12333
12354
|
}
|
|
12334
12355
|
if (plan2.newDirectories.length > 0) {
|
|
12335
|
-
console.log(
|
|
12356
|
+
console.log(chalk133.bold("\nNew directories:"));
|
|
12336
12357
|
for (const dir of plan2.newDirectories)
|
|
12337
|
-
console.log(
|
|
12358
|
+
console.log(chalk133.green(` ${dir}/`));
|
|
12338
12359
|
}
|
|
12339
12360
|
displayMoves(plan2);
|
|
12340
12361
|
displayRewrites(plan2.rewrites);
|
|
12341
12362
|
console.log(
|
|
12342
|
-
|
|
12363
|
+
chalk133.dim(
|
|
12343
12364
|
`
|
|
12344
12365
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
12345
12366
|
)
|
|
@@ -12349,18 +12370,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
12349
12370
|
// src/commands/refactor/restructure/executePlan.ts
|
|
12350
12371
|
import fs23 from "fs";
|
|
12351
12372
|
import path44 from "path";
|
|
12352
|
-
import
|
|
12373
|
+
import chalk134 from "chalk";
|
|
12353
12374
|
function executePlan(plan2) {
|
|
12354
12375
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
12355
12376
|
for (const [file, content] of updatedContents) {
|
|
12356
12377
|
fs23.writeFileSync(file, content, "utf-8");
|
|
12357
12378
|
console.log(
|
|
12358
|
-
|
|
12379
|
+
chalk134.cyan(` Rewrote imports in ${path44.relative(process.cwd(), file)}`)
|
|
12359
12380
|
);
|
|
12360
12381
|
}
|
|
12361
12382
|
for (const dir of plan2.newDirectories) {
|
|
12362
12383
|
fs23.mkdirSync(dir, { recursive: true });
|
|
12363
|
-
console.log(
|
|
12384
|
+
console.log(chalk134.green(` Created ${path44.relative(process.cwd(), dir)}/`));
|
|
12364
12385
|
}
|
|
12365
12386
|
for (const move of plan2.moves) {
|
|
12366
12387
|
const targetDir = path44.dirname(move.to);
|
|
@@ -12369,7 +12390,7 @@ function executePlan(plan2) {
|
|
|
12369
12390
|
}
|
|
12370
12391
|
fs23.renameSync(move.from, move.to);
|
|
12371
12392
|
console.log(
|
|
12372
|
-
|
|
12393
|
+
chalk134.white(
|
|
12373
12394
|
` Moved ${path44.relative(process.cwd(), move.from)} \u2192 ${path44.relative(process.cwd(), move.to)}`
|
|
12374
12395
|
)
|
|
12375
12396
|
);
|
|
@@ -12384,7 +12405,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
12384
12405
|
if (entries.length === 0) {
|
|
12385
12406
|
fs23.rmdirSync(dir);
|
|
12386
12407
|
console.log(
|
|
12387
|
-
|
|
12408
|
+
chalk134.dim(
|
|
12388
12409
|
` Removed empty directory ${path44.relative(process.cwd(), dir)}`
|
|
12389
12410
|
)
|
|
12390
12411
|
);
|
|
@@ -12517,22 +12538,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
12517
12538
|
const targetPattern = pattern2 ?? "src";
|
|
12518
12539
|
const files = findSourceFiles2(targetPattern);
|
|
12519
12540
|
if (files.length === 0) {
|
|
12520
|
-
console.log(
|
|
12541
|
+
console.log(chalk135.yellow("No files found matching pattern"));
|
|
12521
12542
|
return;
|
|
12522
12543
|
}
|
|
12523
12544
|
const tsConfigPath = path47.resolve("tsconfig.json");
|
|
12524
12545
|
const plan2 = buildPlan3(files, tsConfigPath);
|
|
12525
12546
|
if (plan2.moves.length === 0) {
|
|
12526
|
-
console.log(
|
|
12547
|
+
console.log(chalk135.green("No restructuring needed"));
|
|
12527
12548
|
return;
|
|
12528
12549
|
}
|
|
12529
12550
|
displayPlan2(plan2);
|
|
12530
12551
|
if (options2.apply) {
|
|
12531
|
-
console.log(
|
|
12552
|
+
console.log(chalk135.bold("\nApplying changes..."));
|
|
12532
12553
|
executePlan(plan2);
|
|
12533
|
-
console.log(
|
|
12554
|
+
console.log(chalk135.green("\nRestructuring complete"));
|
|
12534
12555
|
} else {
|
|
12535
|
-
console.log(
|
|
12556
|
+
console.log(chalk135.dim("\nDry run. Use --apply to execute."));
|
|
12536
12557
|
}
|
|
12537
12558
|
}
|
|
12538
12559
|
|
|
@@ -12681,9 +12702,9 @@ function buildReviewPaths(repoRoot, key) {
|
|
|
12681
12702
|
}
|
|
12682
12703
|
|
|
12683
12704
|
// src/commands/review/fetchExistingComments.ts
|
|
12684
|
-
import { execSync as
|
|
12705
|
+
import { execSync as execSync39 } from "child_process";
|
|
12685
12706
|
function fetchRawComments(org, repo, prNumber) {
|
|
12686
|
-
const out =
|
|
12707
|
+
const out = execSync39(
|
|
12687
12708
|
`gh api --paginate repos/${org}/${repo}/pulls/${prNumber}/comments`,
|
|
12688
12709
|
{ encoding: "utf-8", maxBuffer: 64 * 1024 * 1024 }
|
|
12689
12710
|
);
|
|
@@ -12714,12 +12735,12 @@ function fetchExistingComments() {
|
|
|
12714
12735
|
}
|
|
12715
12736
|
|
|
12716
12737
|
// src/commands/review/gatherContext.ts
|
|
12717
|
-
import { execSync as
|
|
12738
|
+
import { execSync as execSync41 } from "child_process";
|
|
12718
12739
|
|
|
12719
12740
|
// src/commands/review/fetchPrDiffInfo.ts
|
|
12720
|
-
import { execSync as
|
|
12741
|
+
import { execSync as execSync40 } from "child_process";
|
|
12721
12742
|
function getCurrentBranch2() {
|
|
12722
|
-
return
|
|
12743
|
+
return execSync40("git rev-parse --abbrev-ref HEAD", {
|
|
12723
12744
|
encoding: "utf-8"
|
|
12724
12745
|
}).trim();
|
|
12725
12746
|
}
|
|
@@ -12729,7 +12750,7 @@ function fetchPrDiffInfo() {
|
|
|
12729
12750
|
const fields = "number,baseRefName,baseRefOid,headRefName,headRefOid";
|
|
12730
12751
|
let raw;
|
|
12731
12752
|
try {
|
|
12732
|
-
raw =
|
|
12753
|
+
raw = execSync40(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
|
|
12733
12754
|
encoding: "utf-8",
|
|
12734
12755
|
stdio: ["ignore", "pipe", "pipe"]
|
|
12735
12756
|
});
|
|
@@ -12753,7 +12774,7 @@ function fetchPrDiffInfo() {
|
|
|
12753
12774
|
}
|
|
12754
12775
|
function fetchPrChangedFiles(prNumber) {
|
|
12755
12776
|
const { org, repo } = getRepoInfo();
|
|
12756
|
-
const out =
|
|
12777
|
+
const out = execSync40(`gh pr diff ${prNumber} --name-only -R ${org}/${repo}`, {
|
|
12757
12778
|
encoding: "utf-8",
|
|
12758
12779
|
maxBuffer: 64 * 1024 * 1024
|
|
12759
12780
|
});
|
|
@@ -12761,7 +12782,7 @@ function fetchPrChangedFiles(prNumber) {
|
|
|
12761
12782
|
}
|
|
12762
12783
|
function fetchPrDiff(prNumber) {
|
|
12763
12784
|
const { org, repo } = getRepoInfo();
|
|
12764
|
-
return
|
|
12785
|
+
return execSync40(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
|
|
12765
12786
|
encoding: "utf-8",
|
|
12766
12787
|
maxBuffer: 256 * 1024 * 1024
|
|
12767
12788
|
});
|
|
@@ -12769,11 +12790,11 @@ function fetchPrDiff(prNumber) {
|
|
|
12769
12790
|
|
|
12770
12791
|
// src/commands/review/gatherContext.ts
|
|
12771
12792
|
function gatherContext() {
|
|
12772
|
-
const branch =
|
|
12793
|
+
const branch = execSync41("git rev-parse --abbrev-ref HEAD", {
|
|
12773
12794
|
encoding: "utf-8"
|
|
12774
12795
|
}).trim();
|
|
12775
|
-
const sha =
|
|
12776
|
-
const shortSha =
|
|
12796
|
+
const sha = execSync41("git rev-parse HEAD", { encoding: "utf-8" }).trim();
|
|
12797
|
+
const shortSha = execSync41("git rev-parse --short=7 HEAD", {
|
|
12777
12798
|
encoding: "utf-8"
|
|
12778
12799
|
}).trim();
|
|
12779
12800
|
const prInfo = fetchPrDiffInfo();
|
|
@@ -12997,18 +13018,18 @@ async function postAndMaybeSubmit(lineBound, markdown, options2) {
|
|
|
12997
13018
|
}
|
|
12998
13019
|
|
|
12999
13020
|
// src/commands/review/warnUnlocated.ts
|
|
13000
|
-
import
|
|
13021
|
+
import chalk136 from "chalk";
|
|
13001
13022
|
function warnUnlocated(unlocated) {
|
|
13002
13023
|
if (unlocated.length === 0) return;
|
|
13003
13024
|
console.warn(
|
|
13004
|
-
|
|
13025
|
+
chalk136.yellow(
|
|
13005
13026
|
`Skipped ${unlocated.length} finding(s) without a parseable file:line:`
|
|
13006
13027
|
)
|
|
13007
13028
|
);
|
|
13008
13029
|
for (const finding of unlocated) {
|
|
13009
|
-
const where = finding.location ||
|
|
13030
|
+
const where = finding.location || chalk136.dim("missing");
|
|
13010
13031
|
console.warn(
|
|
13011
|
-
` ${
|
|
13032
|
+
` ${chalk136.yellow("\xB7")} ${finding.title} ${chalk136.dim(`(${where})`)}`
|
|
13012
13033
|
);
|
|
13013
13034
|
}
|
|
13014
13035
|
}
|
|
@@ -14085,11 +14106,11 @@ async function reviewPr(repoRoot, options2) {
|
|
|
14085
14106
|
}
|
|
14086
14107
|
|
|
14087
14108
|
// src/commands/review/gatherShaContext.ts
|
|
14088
|
-
import { execSync as
|
|
14109
|
+
import { execSync as execSync42 } from "child_process";
|
|
14089
14110
|
function resolveSha(ref, format2) {
|
|
14090
14111
|
const flag = format2 === "short" ? "--short=7 " : "";
|
|
14091
14112
|
try {
|
|
14092
|
-
return
|
|
14113
|
+
return execSync42(`git rev-parse --verify ${flag}${ref}^{commit}`, {
|
|
14093
14114
|
encoding: "utf-8",
|
|
14094
14115
|
stdio: ["ignore", "pipe", "pipe"]
|
|
14095
14116
|
}).trim();
|
|
@@ -14103,11 +14124,11 @@ function gatherShaContext(ref) {
|
|
|
14103
14124
|
const shortSha = resolveSha(sha, "short");
|
|
14104
14125
|
const parentSha = resolveSha(`${sha}^`, "long");
|
|
14105
14126
|
const range = `${parentSha}..${sha}`;
|
|
14106
|
-
const changedFiles =
|
|
14127
|
+
const changedFiles = execSync42(`git diff --name-only ${range}`, {
|
|
14107
14128
|
encoding: "utf-8",
|
|
14108
14129
|
maxBuffer: 64 * 1024 * 1024
|
|
14109
14130
|
}).trim().split("\n").filter(Boolean);
|
|
14110
|
-
const diff2 =
|
|
14131
|
+
const diff2 = execSync42(`git diff ${range}`, {
|
|
14111
14132
|
encoding: "utf-8",
|
|
14112
14133
|
maxBuffer: 256 * 1024 * 1024
|
|
14113
14134
|
});
|
|
@@ -14202,7 +14223,7 @@ function registerReview(program2) {
|
|
|
14202
14223
|
}
|
|
14203
14224
|
|
|
14204
14225
|
// src/commands/seq/seqAuth.ts
|
|
14205
|
-
import
|
|
14226
|
+
import chalk138 from "chalk";
|
|
14206
14227
|
|
|
14207
14228
|
// src/commands/seq/loadConnections.ts
|
|
14208
14229
|
function loadConnections2() {
|
|
@@ -14231,10 +14252,10 @@ function setDefaultConnection(name) {
|
|
|
14231
14252
|
}
|
|
14232
14253
|
|
|
14233
14254
|
// src/shared/assertUniqueName.ts
|
|
14234
|
-
import
|
|
14255
|
+
import chalk137 from "chalk";
|
|
14235
14256
|
function assertUniqueName(existingNames, name) {
|
|
14236
14257
|
if (existingNames.includes(name)) {
|
|
14237
|
-
console.error(
|
|
14258
|
+
console.error(chalk137.red(`Connection "${name}" already exists.`));
|
|
14238
14259
|
process.exit(1);
|
|
14239
14260
|
}
|
|
14240
14261
|
}
|
|
@@ -14252,16 +14273,16 @@ async function promptConnection2(existingNames) {
|
|
|
14252
14273
|
var seqAuth = createConnectionAuth({
|
|
14253
14274
|
load: loadConnections2,
|
|
14254
14275
|
save: saveConnections2,
|
|
14255
|
-
format: (c) => `${
|
|
14276
|
+
format: (c) => `${chalk138.bold(c.name)} ${c.url}`,
|
|
14256
14277
|
promptNew: promptConnection2,
|
|
14257
14278
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
14258
14279
|
});
|
|
14259
14280
|
|
|
14260
14281
|
// src/commands/seq/seqQuery.ts
|
|
14261
|
-
import
|
|
14282
|
+
import chalk142 from "chalk";
|
|
14262
14283
|
|
|
14263
14284
|
// src/commands/seq/fetchSeq.ts
|
|
14264
|
-
import
|
|
14285
|
+
import chalk139 from "chalk";
|
|
14265
14286
|
async function fetchSeq(conn, path52, params) {
|
|
14266
14287
|
const url = `${conn.url}${path52}?${params}`;
|
|
14267
14288
|
const response = await fetch(url, {
|
|
@@ -14272,7 +14293,7 @@ async function fetchSeq(conn, path52, params) {
|
|
|
14272
14293
|
});
|
|
14273
14294
|
if (!response.ok) {
|
|
14274
14295
|
const body = await response.text();
|
|
14275
|
-
console.error(
|
|
14296
|
+
console.error(chalk139.red(`Seq returned ${response.status}: ${body}`));
|
|
14276
14297
|
process.exit(1);
|
|
14277
14298
|
}
|
|
14278
14299
|
return response;
|
|
@@ -14327,23 +14348,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
14327
14348
|
}
|
|
14328
14349
|
|
|
14329
14350
|
// src/commands/seq/formatEvent.ts
|
|
14330
|
-
import
|
|
14351
|
+
import chalk140 from "chalk";
|
|
14331
14352
|
function levelColor(level) {
|
|
14332
14353
|
switch (level) {
|
|
14333
14354
|
case "Fatal":
|
|
14334
|
-
return
|
|
14355
|
+
return chalk140.bgRed.white;
|
|
14335
14356
|
case "Error":
|
|
14336
|
-
return
|
|
14357
|
+
return chalk140.red;
|
|
14337
14358
|
case "Warning":
|
|
14338
|
-
return
|
|
14359
|
+
return chalk140.yellow;
|
|
14339
14360
|
case "Information":
|
|
14340
|
-
return
|
|
14361
|
+
return chalk140.cyan;
|
|
14341
14362
|
case "Debug":
|
|
14342
|
-
return
|
|
14363
|
+
return chalk140.gray;
|
|
14343
14364
|
case "Verbose":
|
|
14344
|
-
return
|
|
14365
|
+
return chalk140.dim;
|
|
14345
14366
|
default:
|
|
14346
|
-
return
|
|
14367
|
+
return chalk140.white;
|
|
14347
14368
|
}
|
|
14348
14369
|
}
|
|
14349
14370
|
function levelAbbrev(level) {
|
|
@@ -14384,12 +14405,12 @@ function formatTimestamp(iso) {
|
|
|
14384
14405
|
function formatEvent(event) {
|
|
14385
14406
|
const color = levelColor(event.Level);
|
|
14386
14407
|
const abbrev = levelAbbrev(event.Level);
|
|
14387
|
-
const ts8 =
|
|
14408
|
+
const ts8 = chalk140.dim(formatTimestamp(event.Timestamp));
|
|
14388
14409
|
const msg = renderMessage(event);
|
|
14389
14410
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
14390
14411
|
if (event.Exception) {
|
|
14391
14412
|
for (const line of event.Exception.split("\n")) {
|
|
14392
|
-
lines.push(
|
|
14413
|
+
lines.push(chalk140.red(` ${line}`));
|
|
14393
14414
|
}
|
|
14394
14415
|
}
|
|
14395
14416
|
return lines.join("\n");
|
|
@@ -14422,11 +14443,11 @@ function rejectTimestampFilter(filter) {
|
|
|
14422
14443
|
}
|
|
14423
14444
|
|
|
14424
14445
|
// src/shared/resolveNamedConnection.ts
|
|
14425
|
-
import
|
|
14446
|
+
import chalk141 from "chalk";
|
|
14426
14447
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
14427
14448
|
if (connections.length === 0) {
|
|
14428
14449
|
console.error(
|
|
14429
|
-
|
|
14450
|
+
chalk141.red(
|
|
14430
14451
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
14431
14452
|
)
|
|
14432
14453
|
);
|
|
@@ -14435,7 +14456,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
14435
14456
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
14436
14457
|
const connection = connections.find((c) => c.name === target);
|
|
14437
14458
|
if (!connection) {
|
|
14438
|
-
console.error(
|
|
14459
|
+
console.error(chalk141.red(`${kind} connection "${target}" not found.`));
|
|
14439
14460
|
process.exit(1);
|
|
14440
14461
|
}
|
|
14441
14462
|
return connection;
|
|
@@ -14464,7 +14485,7 @@ async function seqQuery(filter, options2) {
|
|
|
14464
14485
|
new URLSearchParams({ filter, count: String(count4) })
|
|
14465
14486
|
);
|
|
14466
14487
|
if (events.length === 0) {
|
|
14467
|
-
console.log(
|
|
14488
|
+
console.log(chalk142.yellow("No events found."));
|
|
14468
14489
|
return;
|
|
14469
14490
|
}
|
|
14470
14491
|
if (options2.json) {
|
|
@@ -14475,11 +14496,11 @@ async function seqQuery(filter, options2) {
|
|
|
14475
14496
|
for (const event of chronological) {
|
|
14476
14497
|
console.log(formatEvent(event));
|
|
14477
14498
|
}
|
|
14478
|
-
console.log(
|
|
14499
|
+
console.log(chalk142.dim(`
|
|
14479
14500
|
${events.length} events`));
|
|
14480
14501
|
if (events.length >= count4) {
|
|
14481
14502
|
console.log(
|
|
14482
|
-
|
|
14503
|
+
chalk142.yellow(
|
|
14483
14504
|
`Results limited to ${count4}. Use --count to retrieve more.`
|
|
14484
14505
|
)
|
|
14485
14506
|
);
|
|
@@ -14487,10 +14508,10 @@ ${events.length} events`));
|
|
|
14487
14508
|
}
|
|
14488
14509
|
|
|
14489
14510
|
// src/shared/setNamedDefaultConnection.ts
|
|
14490
|
-
import
|
|
14511
|
+
import chalk143 from "chalk";
|
|
14491
14512
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
14492
14513
|
if (!connections.find((c) => c.name === name)) {
|
|
14493
|
-
console.error(
|
|
14514
|
+
console.error(chalk143.red(`Connection "${name}" not found.`));
|
|
14494
14515
|
process.exit(1);
|
|
14495
14516
|
}
|
|
14496
14517
|
setDefault(name);
|
|
@@ -14534,7 +14555,7 @@ function registerSignal(program2) {
|
|
|
14534
14555
|
}
|
|
14535
14556
|
|
|
14536
14557
|
// src/commands/sql/sqlAuth.ts
|
|
14537
|
-
import
|
|
14558
|
+
import chalk145 from "chalk";
|
|
14538
14559
|
|
|
14539
14560
|
// src/commands/sql/loadConnections.ts
|
|
14540
14561
|
function loadConnections3() {
|
|
@@ -14563,7 +14584,7 @@ function setDefaultConnection2(name) {
|
|
|
14563
14584
|
}
|
|
14564
14585
|
|
|
14565
14586
|
// src/commands/sql/promptConnection.ts
|
|
14566
|
-
import
|
|
14587
|
+
import chalk144 from "chalk";
|
|
14567
14588
|
async function promptConnection3(existingNames) {
|
|
14568
14589
|
const name = await promptInput("name", "Connection name:", "default");
|
|
14569
14590
|
assertUniqueName(existingNames, name);
|
|
@@ -14571,7 +14592,7 @@ async function promptConnection3(existingNames) {
|
|
|
14571
14592
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
14572
14593
|
const port = Number.parseInt(portStr, 10);
|
|
14573
14594
|
if (!Number.isFinite(port)) {
|
|
14574
|
-
console.error(
|
|
14595
|
+
console.error(chalk144.red(`Invalid port "${portStr}".`));
|
|
14575
14596
|
process.exit(1);
|
|
14576
14597
|
}
|
|
14577
14598
|
const user = await promptInput("user", "User:");
|
|
@@ -14584,13 +14605,13 @@ async function promptConnection3(existingNames) {
|
|
|
14584
14605
|
var sqlAuth = createConnectionAuth({
|
|
14585
14606
|
load: loadConnections3,
|
|
14586
14607
|
save: saveConnections3,
|
|
14587
|
-
format: (c) => `${
|
|
14608
|
+
format: (c) => `${chalk145.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
14588
14609
|
promptNew: promptConnection3,
|
|
14589
14610
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
14590
14611
|
});
|
|
14591
14612
|
|
|
14592
14613
|
// src/commands/sql/printTable.ts
|
|
14593
|
-
import
|
|
14614
|
+
import chalk146 from "chalk";
|
|
14594
14615
|
function formatCell(value) {
|
|
14595
14616
|
if (value === null || value === void 0) return "";
|
|
14596
14617
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -14599,7 +14620,7 @@ function formatCell(value) {
|
|
|
14599
14620
|
}
|
|
14600
14621
|
function printTable(rows) {
|
|
14601
14622
|
if (rows.length === 0) {
|
|
14602
|
-
console.log(
|
|
14623
|
+
console.log(chalk146.yellow("(no rows)"));
|
|
14603
14624
|
return;
|
|
14604
14625
|
}
|
|
14605
14626
|
const columns = Object.keys(rows[0]);
|
|
@@ -14607,13 +14628,13 @@ function printTable(rows) {
|
|
|
14607
14628
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
14608
14629
|
);
|
|
14609
14630
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
14610
|
-
console.log(
|
|
14611
|
-
console.log(
|
|
14631
|
+
console.log(chalk146.dim(header));
|
|
14632
|
+
console.log(chalk146.dim("-".repeat(header.length)));
|
|
14612
14633
|
for (const row of rows) {
|
|
14613
14634
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
14614
14635
|
console.log(line);
|
|
14615
14636
|
}
|
|
14616
|
-
console.log(
|
|
14637
|
+
console.log(chalk146.dim(`
|
|
14617
14638
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
14618
14639
|
}
|
|
14619
14640
|
|
|
@@ -14673,7 +14694,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
14673
14694
|
}
|
|
14674
14695
|
|
|
14675
14696
|
// src/commands/sql/sqlMutate.ts
|
|
14676
|
-
import
|
|
14697
|
+
import chalk147 from "chalk";
|
|
14677
14698
|
|
|
14678
14699
|
// src/commands/sql/isMutation.ts
|
|
14679
14700
|
var MUTATION_KEYWORDS = [
|
|
@@ -14707,7 +14728,7 @@ function isMutation(sql4) {
|
|
|
14707
14728
|
async function sqlMutate(query, connectionName) {
|
|
14708
14729
|
if (!isMutation(query)) {
|
|
14709
14730
|
console.error(
|
|
14710
|
-
|
|
14731
|
+
chalk147.red(
|
|
14711
14732
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
14712
14733
|
)
|
|
14713
14734
|
);
|
|
@@ -14717,18 +14738,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
14717
14738
|
const pool = await sqlConnect(conn);
|
|
14718
14739
|
try {
|
|
14719
14740
|
const result = await pool.request().query(query);
|
|
14720
|
-
console.log(
|
|
14741
|
+
console.log(chalk147.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
14721
14742
|
} finally {
|
|
14722
14743
|
await pool.close();
|
|
14723
14744
|
}
|
|
14724
14745
|
}
|
|
14725
14746
|
|
|
14726
14747
|
// src/commands/sql/sqlQuery.ts
|
|
14727
|
-
import
|
|
14748
|
+
import chalk148 from "chalk";
|
|
14728
14749
|
async function sqlQuery(query, connectionName) {
|
|
14729
14750
|
if (isMutation(query)) {
|
|
14730
14751
|
console.error(
|
|
14731
|
-
|
|
14752
|
+
chalk148.red(
|
|
14732
14753
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
14733
14754
|
)
|
|
14734
14755
|
);
|
|
@@ -14743,7 +14764,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
14743
14764
|
printTable(rows);
|
|
14744
14765
|
} else {
|
|
14745
14766
|
console.log(
|
|
14746
|
-
|
|
14767
|
+
chalk148.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
14747
14768
|
);
|
|
14748
14769
|
}
|
|
14749
14770
|
} finally {
|
|
@@ -15323,14 +15344,14 @@ import {
|
|
|
15323
15344
|
import { dirname as dirname22, join as join40 } from "path";
|
|
15324
15345
|
|
|
15325
15346
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
15326
|
-
import
|
|
15347
|
+
import chalk149 from "chalk";
|
|
15327
15348
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
15328
15349
|
function validateStagedContent(filename, content) {
|
|
15329
15350
|
const firstLine = content.split("\n")[0];
|
|
15330
15351
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
15331
15352
|
if (!match) {
|
|
15332
15353
|
console.error(
|
|
15333
|
-
|
|
15354
|
+
chalk149.red(
|
|
15334
15355
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
15335
15356
|
)
|
|
15336
15357
|
);
|
|
@@ -15339,7 +15360,7 @@ function validateStagedContent(filename, content) {
|
|
|
15339
15360
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
15340
15361
|
if (!contentAfterLink) {
|
|
15341
15362
|
console.error(
|
|
15342
|
-
|
|
15363
|
+
chalk149.red(
|
|
15343
15364
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
15344
15365
|
)
|
|
15345
15366
|
);
|
|
@@ -15542,7 +15563,7 @@ import { mkdirSync as mkdirSync14 } from "fs";
|
|
|
15542
15563
|
import { join as join45 } from "path";
|
|
15543
15564
|
|
|
15544
15565
|
// src/commands/voice/checkLockFile.ts
|
|
15545
|
-
import { execSync as
|
|
15566
|
+
import { execSync as execSync43 } from "child_process";
|
|
15546
15567
|
import { existsSync as existsSync44, mkdirSync as mkdirSync13, readFileSync as readFileSync34, writeFileSync as writeFileSync27 } from "fs";
|
|
15547
15568
|
import { join as join44 } from "path";
|
|
15548
15569
|
function isProcessAlive2(pid) {
|
|
@@ -15571,7 +15592,7 @@ function bootstrapVenv() {
|
|
|
15571
15592
|
if (existsSync44(getVenvPython())) return;
|
|
15572
15593
|
console.log("Setting up Python environment...");
|
|
15573
15594
|
const pythonDir = getPythonDir();
|
|
15574
|
-
|
|
15595
|
+
execSync43(
|
|
15575
15596
|
`uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
|
|
15576
15597
|
{
|
|
15577
15598
|
stdio: "inherit",
|
|
@@ -15735,14 +15756,14 @@ function registerVoice(program2) {
|
|
|
15735
15756
|
|
|
15736
15757
|
// src/commands/roam/auth.ts
|
|
15737
15758
|
import { randomBytes } from "crypto";
|
|
15738
|
-
import
|
|
15759
|
+
import chalk150 from "chalk";
|
|
15739
15760
|
|
|
15740
15761
|
// src/lib/openBrowser.ts
|
|
15741
|
-
import { execSync as
|
|
15762
|
+
import { execSync as execSync44 } from "child_process";
|
|
15742
15763
|
function tryExec(commands) {
|
|
15743
15764
|
for (const cmd of commands) {
|
|
15744
15765
|
try {
|
|
15745
|
-
|
|
15766
|
+
execSync44(cmd);
|
|
15746
15767
|
return true;
|
|
15747
15768
|
} catch {
|
|
15748
15769
|
}
|
|
@@ -15910,13 +15931,13 @@ async function auth() {
|
|
|
15910
15931
|
saveGlobalConfig(config);
|
|
15911
15932
|
const state = randomBytes(16).toString("hex");
|
|
15912
15933
|
console.log(
|
|
15913
|
-
|
|
15934
|
+
chalk150.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
15914
15935
|
);
|
|
15915
|
-
console.log(
|
|
15916
|
-
console.log(
|
|
15917
|
-
console.log(
|
|
15936
|
+
console.log(chalk150.white("http://localhost:14523/callback\n"));
|
|
15937
|
+
console.log(chalk150.blue("Opening browser for authorization..."));
|
|
15938
|
+
console.log(chalk150.dim("Waiting for authorization callback..."));
|
|
15918
15939
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
15919
|
-
console.log(
|
|
15940
|
+
console.log(chalk150.dim("Exchanging code for tokens..."));
|
|
15920
15941
|
const tokens = await exchangeToken({
|
|
15921
15942
|
code,
|
|
15922
15943
|
clientId,
|
|
@@ -15932,7 +15953,7 @@ async function auth() {
|
|
|
15932
15953
|
};
|
|
15933
15954
|
saveGlobalConfig(config);
|
|
15934
15955
|
console.log(
|
|
15935
|
-
|
|
15956
|
+
chalk150.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
15936
15957
|
);
|
|
15937
15958
|
}
|
|
15938
15959
|
|
|
@@ -16084,11 +16105,11 @@ function resolveParams(params, cliArgs) {
|
|
|
16084
16105
|
}
|
|
16085
16106
|
|
|
16086
16107
|
// src/commands/run/runPreCommands.ts
|
|
16087
|
-
import { execSync as
|
|
16108
|
+
import { execSync as execSync45 } from "child_process";
|
|
16088
16109
|
function runPreCommands(pre, cwd) {
|
|
16089
16110
|
for (const cmd of pre) {
|
|
16090
16111
|
try {
|
|
16091
|
-
|
|
16112
|
+
execSync45(cmd, { stdio: "inherit", cwd });
|
|
16092
16113
|
} catch (err) {
|
|
16093
16114
|
const code = err && typeof err === "object" && "status" in err ? err.status : 1;
|
|
16094
16115
|
process.exit(code);
|
|
@@ -16351,11 +16372,11 @@ function registerRun(program2) {
|
|
|
16351
16372
|
}
|
|
16352
16373
|
|
|
16353
16374
|
// src/commands/screenshot/index.ts
|
|
16354
|
-
import { execSync as
|
|
16375
|
+
import { execSync as execSync46 } from "child_process";
|
|
16355
16376
|
import { existsSync as existsSync49, mkdirSync as mkdirSync17, unlinkSync as unlinkSync15, writeFileSync as writeFileSync30 } from "fs";
|
|
16356
16377
|
import { tmpdir as tmpdir7 } from "os";
|
|
16357
16378
|
import { join as join51, resolve as resolve13 } from "path";
|
|
16358
|
-
import
|
|
16379
|
+
import chalk151 from "chalk";
|
|
16359
16380
|
|
|
16360
16381
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
16361
16382
|
var captureWindowPs1 = `
|
|
@@ -16494,7 +16515,7 @@ function runPowerShellScript(processName, outputPath) {
|
|
|
16494
16515
|
const scriptPath = join51(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
|
|
16495
16516
|
writeFileSync30(scriptPath, captureWindowPs1, "utf-8");
|
|
16496
16517
|
try {
|
|
16497
|
-
|
|
16518
|
+
execSync46(
|
|
16498
16519
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
16499
16520
|
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }
|
|
16500
16521
|
);
|
|
@@ -16506,20 +16527,20 @@ function screenshot(processName) {
|
|
|
16506
16527
|
const config = loadConfig();
|
|
16507
16528
|
const outputDir = resolve13(config.screenshot.outputDir);
|
|
16508
16529
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
16509
|
-
console.log(
|
|
16530
|
+
console.log(chalk151.gray(`Capturing window for process "${processName}" ...`));
|
|
16510
16531
|
try {
|
|
16511
16532
|
runPowerShellScript(processName, outputPath);
|
|
16512
|
-
console.log(
|
|
16533
|
+
console.log(chalk151.green(`Screenshot saved: ${outputPath}`));
|
|
16513
16534
|
} catch (error) {
|
|
16514
16535
|
const msg = error instanceof Error ? error.message : String(error);
|
|
16515
|
-
console.error(
|
|
16536
|
+
console.error(chalk151.red(`Failed to capture screenshot: ${msg}`));
|
|
16516
16537
|
process.exit(1);
|
|
16517
16538
|
}
|
|
16518
16539
|
}
|
|
16519
16540
|
|
|
16520
16541
|
// src/commands/sessions/summarise/index.ts
|
|
16521
16542
|
import * as fs28 from "fs";
|
|
16522
|
-
import
|
|
16543
|
+
import chalk152 from "chalk";
|
|
16523
16544
|
|
|
16524
16545
|
// src/commands/sessions/summarise/shared.ts
|
|
16525
16546
|
import * as fs26 from "fs";
|
|
@@ -16646,22 +16667,22 @@ ${firstMessage}`);
|
|
|
16646
16667
|
async function summarise4(options2) {
|
|
16647
16668
|
const files = await discoverSessionJsonlPaths();
|
|
16648
16669
|
if (files.length === 0) {
|
|
16649
|
-
console.log(
|
|
16670
|
+
console.log(chalk152.yellow("No sessions found."));
|
|
16650
16671
|
return;
|
|
16651
16672
|
}
|
|
16652
16673
|
const toProcess = selectCandidates(files, options2);
|
|
16653
16674
|
if (toProcess.length === 0) {
|
|
16654
|
-
console.log(
|
|
16675
|
+
console.log(chalk152.green("All sessions already summarised."));
|
|
16655
16676
|
return;
|
|
16656
16677
|
}
|
|
16657
16678
|
console.log(
|
|
16658
|
-
|
|
16679
|
+
chalk152.cyan(
|
|
16659
16680
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
16660
16681
|
)
|
|
16661
16682
|
);
|
|
16662
16683
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
16663
16684
|
console.log(
|
|
16664
|
-
|
|
16685
|
+
chalk152.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk152.yellow(`, ${failed2} skipped`) : "")
|
|
16665
16686
|
);
|
|
16666
16687
|
}
|
|
16667
16688
|
function selectCandidates(files, options2) {
|
|
@@ -16681,16 +16702,16 @@ function processSessions(files) {
|
|
|
16681
16702
|
let failed2 = 0;
|
|
16682
16703
|
for (let i = 0; i < files.length; i++) {
|
|
16683
16704
|
const file = files[i];
|
|
16684
|
-
process.stdout.write(
|
|
16705
|
+
process.stdout.write(chalk152.dim(` [${i + 1}/${files.length}] `));
|
|
16685
16706
|
const summary = summariseSession(file);
|
|
16686
16707
|
if (summary) {
|
|
16687
16708
|
writeSummary(file, summary);
|
|
16688
16709
|
succeeded++;
|
|
16689
|
-
process.stdout.write(`${
|
|
16710
|
+
process.stdout.write(`${chalk152.green("\u2713")} ${summary}
|
|
16690
16711
|
`);
|
|
16691
16712
|
} else {
|
|
16692
16713
|
failed2++;
|
|
16693
|
-
process.stdout.write(` ${
|
|
16714
|
+
process.stdout.write(` ${chalk152.yellow("skip")}
|
|
16694
16715
|
`);
|
|
16695
16716
|
}
|
|
16696
16717
|
}
|
|
@@ -16705,10 +16726,10 @@ function registerSessions(program2) {
|
|
|
16705
16726
|
}
|
|
16706
16727
|
|
|
16707
16728
|
// src/commands/statusLine.ts
|
|
16708
|
-
import
|
|
16729
|
+
import chalk154 from "chalk";
|
|
16709
16730
|
|
|
16710
16731
|
// src/commands/buildLimitsSegment.ts
|
|
16711
|
-
import
|
|
16732
|
+
import chalk153 from "chalk";
|
|
16712
16733
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
16713
16734
|
var SEVEN_DAY_SECONDS = 7 * 86400;
|
|
16714
16735
|
function formatTimeLeft(resetsAt) {
|
|
@@ -16731,10 +16752,10 @@ function projectUsage(pct, resetsAt, windowSeconds) {
|
|
|
16731
16752
|
function colorizeRateLimit(pct, resetsAt, windowSeconds) {
|
|
16732
16753
|
const label2 = `${Math.round(pct)}%`;
|
|
16733
16754
|
const projected = projectUsage(pct, resetsAt, windowSeconds);
|
|
16734
|
-
if (projected == null) return
|
|
16735
|
-
if (projected > 100) return
|
|
16736
|
-
if (projected > 75) return
|
|
16737
|
-
return
|
|
16755
|
+
if (projected == null) return chalk153.green(label2);
|
|
16756
|
+
if (projected > 100) return chalk153.red(label2);
|
|
16757
|
+
if (projected > 75) return chalk153.yellow(label2);
|
|
16758
|
+
return chalk153.green(label2);
|
|
16738
16759
|
}
|
|
16739
16760
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel) {
|
|
16740
16761
|
const timeLabel = resetsAt ? formatTimeLeft(resetsAt) : fallbackLabel;
|
|
@@ -16760,14 +16781,14 @@ function buildLimitsSegment(rateLimits) {
|
|
|
16760
16781
|
}
|
|
16761
16782
|
|
|
16762
16783
|
// src/commands/statusLine.ts
|
|
16763
|
-
|
|
16784
|
+
chalk154.level = 3;
|
|
16764
16785
|
function formatNumber(num) {
|
|
16765
16786
|
return num.toLocaleString("en-US");
|
|
16766
16787
|
}
|
|
16767
16788
|
function colorizePercent(pct) {
|
|
16768
16789
|
const label2 = `${Math.round(pct)}%`;
|
|
16769
|
-
if (pct > 80) return
|
|
16770
|
-
if (pct > 40) return
|
|
16790
|
+
if (pct > 80) return chalk154.red(label2);
|
|
16791
|
+
if (pct > 40) return chalk154.yellow(label2);
|
|
16771
16792
|
return label2;
|
|
16772
16793
|
}
|
|
16773
16794
|
async function statusLine() {
|
|
@@ -16790,7 +16811,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
16790
16811
|
// src/commands/sync/syncClaudeMd.ts
|
|
16791
16812
|
import * as fs29 from "fs";
|
|
16792
16813
|
import * as path48 from "path";
|
|
16793
|
-
import
|
|
16814
|
+
import chalk155 from "chalk";
|
|
16794
16815
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
16795
16816
|
const source = path48.join(claudeDir, "CLAUDE.md");
|
|
16796
16817
|
const target = path48.join(targetBase, "CLAUDE.md");
|
|
@@ -16799,12 +16820,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
16799
16820
|
const targetContent = fs29.readFileSync(target, "utf-8");
|
|
16800
16821
|
if (sourceContent !== targetContent) {
|
|
16801
16822
|
console.log(
|
|
16802
|
-
|
|
16823
|
+
chalk155.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
16803
16824
|
);
|
|
16804
16825
|
console.log();
|
|
16805
16826
|
printDiff(targetContent, sourceContent);
|
|
16806
16827
|
const confirm = options2?.yes || await promptConfirm(
|
|
16807
|
-
|
|
16828
|
+
chalk155.red("Overwrite existing CLAUDE.md?"),
|
|
16808
16829
|
false
|
|
16809
16830
|
);
|
|
16810
16831
|
if (!confirm) {
|
|
@@ -16820,7 +16841,7 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
16820
16841
|
// src/commands/sync/syncSettings.ts
|
|
16821
16842
|
import * as fs30 from "fs";
|
|
16822
16843
|
import * as path49 from "path";
|
|
16823
|
-
import
|
|
16844
|
+
import chalk156 from "chalk";
|
|
16824
16845
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
16825
16846
|
const source = path49.join(claudeDir, "settings.json");
|
|
16826
16847
|
const target = path49.join(targetBase, "settings.json");
|
|
@@ -16836,14 +16857,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
16836
16857
|
if (mergedContent !== normalizedTarget) {
|
|
16837
16858
|
if (!options2?.yes) {
|
|
16838
16859
|
console.log(
|
|
16839
|
-
|
|
16860
|
+
chalk156.yellow(
|
|
16840
16861
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
16841
16862
|
)
|
|
16842
16863
|
);
|
|
16843
16864
|
console.log();
|
|
16844
16865
|
printDiff(targetContent, mergedContent);
|
|
16845
16866
|
const confirm = await promptConfirm(
|
|
16846
|
-
|
|
16867
|
+
chalk156.red("Overwrite existing settings.json?"),
|
|
16847
16868
|
false
|
|
16848
16869
|
);
|
|
16849
16870
|
if (!confirm) {
|
|
@@ -16882,7 +16903,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
16882
16903
|
}
|
|
16883
16904
|
|
|
16884
16905
|
// src/commands/update.ts
|
|
16885
|
-
import { execSync as
|
|
16906
|
+
import { execSync as execSync47 } from "child_process";
|
|
16886
16907
|
import * as path51 from "path";
|
|
16887
16908
|
function isGlobalNpmInstall(dir) {
|
|
16888
16909
|
try {
|
|
@@ -16890,7 +16911,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
16890
16911
|
if (resolved.split(path51.sep).includes("node_modules")) {
|
|
16891
16912
|
return true;
|
|
16892
16913
|
}
|
|
16893
|
-
const globalPrefix =
|
|
16914
|
+
const globalPrefix = execSync47("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
16894
16915
|
return resolved.toLowerCase().startsWith(path51.resolve(globalPrefix).toLowerCase());
|
|
16895
16916
|
} catch {
|
|
16896
16917
|
return false;
|
|
@@ -16901,18 +16922,18 @@ async function update2() {
|
|
|
16901
16922
|
console.log(`Assist is installed at: ${installDir}`);
|
|
16902
16923
|
if (isGitRepo(installDir)) {
|
|
16903
16924
|
console.log("Detected git repo installation, pulling latest...");
|
|
16904
|
-
|
|
16925
|
+
execSync47("git pull", { cwd: installDir, stdio: "inherit" });
|
|
16905
16926
|
console.log("Installing dependencies...");
|
|
16906
|
-
|
|
16927
|
+
execSync47("npm i", { cwd: installDir, stdio: "inherit" });
|
|
16907
16928
|
console.log("Building...");
|
|
16908
|
-
|
|
16929
|
+
execSync47("npm run build", { cwd: installDir, stdio: "inherit" });
|
|
16909
16930
|
console.log("Syncing commands...");
|
|
16910
|
-
|
|
16931
|
+
execSync47("assist sync", { stdio: "inherit" });
|
|
16911
16932
|
} else if (isGlobalNpmInstall(installDir)) {
|
|
16912
16933
|
console.log("Detected global npm installation, updating...");
|
|
16913
|
-
|
|
16934
|
+
execSync47("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
|
|
16914
16935
|
console.log("Syncing commands...");
|
|
16915
|
-
|
|
16936
|
+
execSync47("assist sync", { stdio: "inherit" });
|
|
16916
16937
|
} else {
|
|
16917
16938
|
console.error(
|
|
16918
16939
|
"Could not determine installation method. Expected a git repo or global npm install."
|