@staff0rd/assist 0.51.0 → 0.53.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 +6 -0
- package/dist/index.js +459 -243
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { execSync as
|
|
4
|
+
import { execSync as execSync23 } from "child_process";
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
|
|
7
7
|
// package.json
|
|
8
8
|
var package_default = {
|
|
9
9
|
name: "@staff0rd/assist",
|
|
10
|
-
version: "0.
|
|
10
|
+
version: "0.53.0",
|
|
11
11
|
type: "module",
|
|
12
12
|
main: "dist/index.js",
|
|
13
13
|
bin: {
|
|
@@ -1277,7 +1277,7 @@ function lint() {
|
|
|
1277
1277
|
}
|
|
1278
1278
|
|
|
1279
1279
|
// src/commands/new/registerNew/newCli/index.ts
|
|
1280
|
-
import { execSync as
|
|
1280
|
+
import { execSync as execSync8 } from "child_process";
|
|
1281
1281
|
import { basename as basename2, resolve } from "path";
|
|
1282
1282
|
|
|
1283
1283
|
// src/commands/verify/hardcodedColors.ts
|
|
@@ -1432,26 +1432,35 @@ async function run(options2 = {}) {
|
|
|
1432
1432
|
await executeVerifyScripts(found, options2.timer ?? false);
|
|
1433
1433
|
}
|
|
1434
1434
|
|
|
1435
|
-
// src/commands/new/registerNew/
|
|
1435
|
+
// src/commands/new/registerNew/initGit.ts
|
|
1436
1436
|
import { execSync as execSync6 } from "child_process";
|
|
1437
|
+
import { writeFileSync as writeFileSync6 } from "fs";
|
|
1438
|
+
function initGit() {
|
|
1439
|
+
console.log("Initializing git repository...");
|
|
1440
|
+
execSync6("git init", { stdio: "inherit" });
|
|
1441
|
+
writeFileSync6(".gitignore", "dist\nnode_modules\n");
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
// src/commands/new/registerNew/newCli/initPackageJson.ts
|
|
1445
|
+
import { execSync as execSync7 } from "child_process";
|
|
1437
1446
|
function initPackageJson(name) {
|
|
1438
1447
|
console.log("Initializing package.json...");
|
|
1439
|
-
|
|
1448
|
+
execSync7("npm init -y", { stdio: "inherit" });
|
|
1440
1449
|
console.log("Configuring package.json...");
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1450
|
+
execSync7("npm pkg delete main", { stdio: "inherit" });
|
|
1451
|
+
execSync7("npm pkg set type=module", { stdio: "inherit" });
|
|
1452
|
+
execSync7(`npm pkg set bin.${name}=./dist/index.js`, { stdio: "inherit" });
|
|
1453
|
+
execSync7("npm pkg set scripts.build=tsup", { stdio: "inherit" });
|
|
1454
|
+
execSync7('npm pkg set scripts.start="node dist/index.js"', {
|
|
1446
1455
|
stdio: "inherit"
|
|
1447
1456
|
});
|
|
1448
1457
|
}
|
|
1449
1458
|
|
|
1450
1459
|
// src/commands/new/registerNew/newCli/writeCliTemplate.ts
|
|
1451
|
-
import { mkdirSync as mkdirSync2, writeFileSync as
|
|
1460
|
+
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync7 } from "fs";
|
|
1452
1461
|
function writeCliTemplate(name) {
|
|
1453
1462
|
console.log("Writing tsconfig.json...");
|
|
1454
|
-
|
|
1463
|
+
writeFileSync7(
|
|
1455
1464
|
"tsconfig.json",
|
|
1456
1465
|
JSON.stringify(
|
|
1457
1466
|
{
|
|
@@ -1475,7 +1484,7 @@ function writeCliTemplate(name) {
|
|
|
1475
1484
|
)
|
|
1476
1485
|
);
|
|
1477
1486
|
console.log("Writing tsup.config.ts...");
|
|
1478
|
-
|
|
1487
|
+
writeFileSync7(
|
|
1479
1488
|
"tsup.config.ts",
|
|
1480
1489
|
`import { defineConfig } from "tsup";
|
|
1481
1490
|
export default defineConfig({
|
|
@@ -1490,7 +1499,7 @@ export default defineConfig({
|
|
|
1490
1499
|
);
|
|
1491
1500
|
console.log("Writing src/index.ts...");
|
|
1492
1501
|
mkdirSync2("src", { recursive: true });
|
|
1493
|
-
|
|
1502
|
+
writeFileSync7(
|
|
1494
1503
|
"src/index.ts",
|
|
1495
1504
|
`#!/usr/bin/env node
|
|
1496
1505
|
import { Command } from "commander";
|
|
@@ -1504,10 +1513,11 @@ program.parse();
|
|
|
1504
1513
|
// src/commands/new/registerNew/newCli/index.ts
|
|
1505
1514
|
async function newCli() {
|
|
1506
1515
|
const name = basename2(resolve("."));
|
|
1516
|
+
initGit();
|
|
1507
1517
|
initPackageJson(name);
|
|
1508
1518
|
console.log("Installing dependencies...");
|
|
1509
|
-
|
|
1510
|
-
|
|
1519
|
+
execSync8("npm install commander", { stdio: "inherit" });
|
|
1520
|
+
execSync8("npm install -D tsup typescript @types/node", {
|
|
1511
1521
|
stdio: "inherit"
|
|
1512
1522
|
});
|
|
1513
1523
|
writeCliTemplate(name);
|
|
@@ -1516,16 +1526,16 @@ async function newCli() {
|
|
|
1516
1526
|
}
|
|
1517
1527
|
|
|
1518
1528
|
// src/commands/new/registerNew/newProject.ts
|
|
1519
|
-
import { execSync as
|
|
1520
|
-
import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as
|
|
1529
|
+
import { execSync as execSync10 } from "child_process";
|
|
1530
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync9 } from "fs";
|
|
1521
1531
|
|
|
1522
1532
|
// src/commands/deploy/init/index.ts
|
|
1523
|
-
import { execSync as
|
|
1533
|
+
import { execSync as execSync9 } from "child_process";
|
|
1524
1534
|
import chalk21 from "chalk";
|
|
1525
1535
|
import enquirer3 from "enquirer";
|
|
1526
1536
|
|
|
1527
1537
|
// src/commands/deploy/init/updateWorkflow.ts
|
|
1528
|
-
import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync7, writeFileSync as
|
|
1538
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync8 } from "fs";
|
|
1529
1539
|
import { dirname as dirname10, join as join7 } from "path";
|
|
1530
1540
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1531
1541
|
import chalk20 from "chalk";
|
|
@@ -1565,7 +1575,7 @@ async function updateWorkflow(siteId) {
|
|
|
1565
1575
|
return;
|
|
1566
1576
|
}
|
|
1567
1577
|
}
|
|
1568
|
-
|
|
1578
|
+
writeFileSync8(WORKFLOW_PATH, newContent);
|
|
1569
1579
|
console.log(chalk20.green(`
|
|
1570
1580
|
Created ${WORKFLOW_PATH}`));
|
|
1571
1581
|
}
|
|
@@ -1573,7 +1583,7 @@ Created ${WORKFLOW_PATH}`));
|
|
|
1573
1583
|
// src/commands/deploy/init/index.ts
|
|
1574
1584
|
async function ensureNetlifyCli() {
|
|
1575
1585
|
try {
|
|
1576
|
-
|
|
1586
|
+
execSync9("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
1577
1587
|
} catch (error) {
|
|
1578
1588
|
if (!(error instanceof Error) || !error.message.includes("command not found"))
|
|
1579
1589
|
throw error;
|
|
@@ -1588,9 +1598,9 @@ async function ensureNetlifyCli() {
|
|
|
1588
1598
|
process.exit(1);
|
|
1589
1599
|
}
|
|
1590
1600
|
console.log(chalk21.dim("\nInstalling netlify-cli...\n"));
|
|
1591
|
-
|
|
1601
|
+
execSync9("npm install -g netlify-cli", { stdio: "inherit" });
|
|
1592
1602
|
console.log();
|
|
1593
|
-
|
|
1603
|
+
execSync9("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
1594
1604
|
}
|
|
1595
1605
|
}
|
|
1596
1606
|
function printSetupInstructions() {
|
|
@@ -1633,9 +1643,10 @@ async function init5() {
|
|
|
1633
1643
|
// src/commands/new/registerNew/newProject.ts
|
|
1634
1644
|
async function newProject() {
|
|
1635
1645
|
console.log("Initializing Vite with react-ts template...");
|
|
1636
|
-
|
|
1646
|
+
execSync10("npm create vite@latest . -- --template react-ts", {
|
|
1637
1647
|
stdio: "inherit"
|
|
1638
1648
|
});
|
|
1649
|
+
initGit();
|
|
1639
1650
|
removeEslint({ removeLintScripts: true });
|
|
1640
1651
|
addViteBaseConfig();
|
|
1641
1652
|
await init4();
|
|
@@ -1657,7 +1668,7 @@ function addViteBaseConfig() {
|
|
|
1657
1668
|
'defineConfig({\n base: "./",'
|
|
1658
1669
|
);
|
|
1659
1670
|
if (updated !== content) {
|
|
1660
|
-
|
|
1671
|
+
writeFileSync9(viteConfigPath, updated);
|
|
1661
1672
|
console.log('Added base: "./" to vite.config.ts');
|
|
1662
1673
|
}
|
|
1663
1674
|
}
|
|
@@ -1791,16 +1802,220 @@ async function notify() {
|
|
|
1791
1802
|
console.log(`Notification sent: ${notification_type} for ${projectName}`);
|
|
1792
1803
|
}
|
|
1793
1804
|
|
|
1794
|
-
// src/commands/
|
|
1805
|
+
// src/commands/backlog/add/index.ts
|
|
1806
|
+
import { existsSync as existsSync12 } from "fs";
|
|
1807
|
+
import chalk23 from "chalk";
|
|
1808
|
+
|
|
1809
|
+
// src/commands/backlog/shared.ts
|
|
1810
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
1811
|
+
import { join as join8 } from "path";
|
|
1812
|
+
import chalk22 from "chalk";
|
|
1813
|
+
import { parse as parseYaml2, stringify as stringifyYaml3 } from "yaml";
|
|
1814
|
+
|
|
1815
|
+
// src/commands/backlog/types.ts
|
|
1816
|
+
import { z as z2 } from "zod";
|
|
1817
|
+
var backlogStatusSchema = z2.enum(["todo", "in-progress", "done"]);
|
|
1818
|
+
var backlogItemSchema = z2.strictObject({
|
|
1819
|
+
id: z2.number(),
|
|
1820
|
+
name: z2.string(),
|
|
1821
|
+
description: z2.string().optional(),
|
|
1822
|
+
acceptanceCriteria: z2.array(z2.string()),
|
|
1823
|
+
status: backlogStatusSchema
|
|
1824
|
+
});
|
|
1825
|
+
var backlogFileSchema = z2.array(backlogItemSchema);
|
|
1826
|
+
|
|
1827
|
+
// src/commands/backlog/shared.ts
|
|
1828
|
+
function getBacklogPath() {
|
|
1829
|
+
return join8(process.cwd(), "assist.backlog.yml");
|
|
1830
|
+
}
|
|
1831
|
+
function loadBacklog() {
|
|
1832
|
+
const backlogPath = getBacklogPath();
|
|
1833
|
+
if (!existsSync11(backlogPath)) {
|
|
1834
|
+
return [];
|
|
1835
|
+
}
|
|
1836
|
+
try {
|
|
1837
|
+
const content = readFileSync9(backlogPath, "utf-8");
|
|
1838
|
+
const raw = parseYaml2(content) || [];
|
|
1839
|
+
return backlogFileSchema.parse(raw);
|
|
1840
|
+
} catch {
|
|
1841
|
+
return [];
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
function saveBacklog(items) {
|
|
1845
|
+
const backlogPath = getBacklogPath();
|
|
1846
|
+
writeFileSync10(backlogPath, stringifyYaml3(items, { lineWidth: 0 }));
|
|
1847
|
+
}
|
|
1848
|
+
function findItem(items, id) {
|
|
1849
|
+
return items.find((item) => item.id === id);
|
|
1850
|
+
}
|
|
1851
|
+
function setStatus(id, status) {
|
|
1852
|
+
const backlogPath = getBacklogPath();
|
|
1853
|
+
if (!existsSync11(backlogPath)) {
|
|
1854
|
+
console.log(
|
|
1855
|
+
chalk22.yellow(
|
|
1856
|
+
"No backlog found. Run 'assist backlog init' to create one."
|
|
1857
|
+
)
|
|
1858
|
+
);
|
|
1859
|
+
return void 0;
|
|
1860
|
+
}
|
|
1861
|
+
const items = loadBacklog();
|
|
1862
|
+
const item = findItem(items, Number.parseInt(id, 10));
|
|
1863
|
+
if (!item) {
|
|
1864
|
+
console.log(chalk22.red(`Item #${id} not found.`));
|
|
1865
|
+
return void 0;
|
|
1866
|
+
}
|
|
1867
|
+
item.status = status;
|
|
1868
|
+
saveBacklog(items);
|
|
1869
|
+
return item.name;
|
|
1870
|
+
}
|
|
1871
|
+
function getNextId(items) {
|
|
1872
|
+
if (items.length === 0) return 1;
|
|
1873
|
+
return Math.max(...items.map((item) => item.id)) + 1;
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
// src/commands/backlog/add/shared.ts
|
|
1877
|
+
import enquirer4 from "enquirer";
|
|
1878
|
+
async function promptName() {
|
|
1879
|
+
const { name } = await enquirer4.prompt({
|
|
1880
|
+
type: "input",
|
|
1881
|
+
name: "name",
|
|
1882
|
+
message: "Name:",
|
|
1883
|
+
validate: (value) => value.trim().length > 0 || "Name is required"
|
|
1884
|
+
});
|
|
1885
|
+
return name.trim();
|
|
1886
|
+
}
|
|
1887
|
+
async function promptDescription() {
|
|
1888
|
+
const { description } = await enquirer4.prompt({
|
|
1889
|
+
type: "input",
|
|
1890
|
+
name: "description",
|
|
1891
|
+
message: "Description (optional):"
|
|
1892
|
+
});
|
|
1893
|
+
return description.trim() || void 0;
|
|
1894
|
+
}
|
|
1895
|
+
async function promptAcceptanceCriteria() {
|
|
1896
|
+
const criteria = [];
|
|
1897
|
+
for (; ; ) {
|
|
1898
|
+
const { criterion } = await enquirer4.prompt({
|
|
1899
|
+
type: "input",
|
|
1900
|
+
name: "criterion",
|
|
1901
|
+
message: "Acceptance criterion (empty to finish):"
|
|
1902
|
+
});
|
|
1903
|
+
if (criterion.trim() === "") break;
|
|
1904
|
+
criteria.push(criterion.trim());
|
|
1905
|
+
}
|
|
1906
|
+
return criteria;
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
// src/commands/backlog/add/index.ts
|
|
1910
|
+
async function add() {
|
|
1911
|
+
const backlogPath = getBacklogPath();
|
|
1912
|
+
if (!existsSync12(backlogPath)) {
|
|
1913
|
+
console.log(
|
|
1914
|
+
chalk23.yellow(
|
|
1915
|
+
"No backlog found. Run 'assist backlog init' to create one."
|
|
1916
|
+
)
|
|
1917
|
+
);
|
|
1918
|
+
return;
|
|
1919
|
+
}
|
|
1920
|
+
const name = await promptName();
|
|
1921
|
+
const description = await promptDescription();
|
|
1922
|
+
const acceptanceCriteria = await promptAcceptanceCriteria();
|
|
1923
|
+
const items = loadBacklog();
|
|
1924
|
+
const id = getNextId(items);
|
|
1925
|
+
items.push({ id, name, description, acceptanceCriteria, status: "todo" });
|
|
1926
|
+
saveBacklog(items);
|
|
1927
|
+
console.log(chalk23.green(`Added item #${id}: ${name}`));
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
// src/commands/backlog/done/index.ts
|
|
1931
|
+
import chalk24 from "chalk";
|
|
1932
|
+
async function done(id) {
|
|
1933
|
+
const name = setStatus(id, "done");
|
|
1934
|
+
if (name) {
|
|
1935
|
+
console.log(chalk24.green(`Completed item #${id}: ${name}`));
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
// src/commands/backlog/init/index.ts
|
|
1940
|
+
import { existsSync as existsSync13 } from "fs";
|
|
1941
|
+
import chalk25 from "chalk";
|
|
1942
|
+
async function init6() {
|
|
1943
|
+
const backlogPath = getBacklogPath();
|
|
1944
|
+
if (existsSync13(backlogPath)) {
|
|
1945
|
+
console.log(chalk25.yellow("assist.backlog.yml already exists."));
|
|
1946
|
+
return;
|
|
1947
|
+
}
|
|
1948
|
+
saveBacklog([]);
|
|
1949
|
+
console.log(chalk25.green("Created assist.backlog.yml"));
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
// src/commands/backlog/list/index.ts
|
|
1953
|
+
import { existsSync as existsSync14 } from "fs";
|
|
1954
|
+
import chalk26 from "chalk";
|
|
1955
|
+
function statusIcon(status) {
|
|
1956
|
+
switch (status) {
|
|
1957
|
+
case "todo":
|
|
1958
|
+
return chalk26.dim("[ ]");
|
|
1959
|
+
case "in-progress":
|
|
1960
|
+
return chalk26.yellow("[~]");
|
|
1961
|
+
case "done":
|
|
1962
|
+
return chalk26.green("[x]");
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
async function list(options2) {
|
|
1966
|
+
const backlogPath = getBacklogPath();
|
|
1967
|
+
if (!existsSync14(backlogPath)) {
|
|
1968
|
+
console.log(
|
|
1969
|
+
chalk26.yellow(
|
|
1970
|
+
"No backlog found. Run 'assist backlog init' to create one."
|
|
1971
|
+
)
|
|
1972
|
+
);
|
|
1973
|
+
return;
|
|
1974
|
+
}
|
|
1975
|
+
let items = loadBacklog();
|
|
1976
|
+
if (options2.status) {
|
|
1977
|
+
items = items.filter((item) => item.status === options2.status);
|
|
1978
|
+
}
|
|
1979
|
+
if (items.length === 0) {
|
|
1980
|
+
console.log(chalk26.dim("Backlog is empty."));
|
|
1981
|
+
return;
|
|
1982
|
+
}
|
|
1983
|
+
for (const item of items) {
|
|
1984
|
+
console.log(
|
|
1985
|
+
`${statusIcon(item.status)} ${item.name} ${chalk26.dim(`#${item.id}`)}`
|
|
1986
|
+
);
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
// src/commands/backlog/start/index.ts
|
|
1795
1991
|
import chalk27 from "chalk";
|
|
1992
|
+
async function start(id) {
|
|
1993
|
+
const name = setStatus(id, "in-progress");
|
|
1994
|
+
if (name) {
|
|
1995
|
+
console.log(chalk27.green(`Started item #${id}: ${name}`));
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
// src/commands/registerBacklog.ts
|
|
2000
|
+
function registerBacklog(program2) {
|
|
2001
|
+
const backlogCommand = program2.command("backlog").description("Manage a backlog of work items").action(list);
|
|
2002
|
+
backlogCommand.command("init").description("Create an empty assist.backlog.yml").action(init6);
|
|
2003
|
+
backlogCommand.command("list").description("List all backlog items").option("--status <type>", "Filter by status (todo, in-progress, done)").action(list);
|
|
2004
|
+
backlogCommand.command("add").description("Add a new backlog item").action(add);
|
|
2005
|
+
backlogCommand.command("start <id>").description("Set a backlog item to in-progress").action(start);
|
|
2006
|
+
backlogCommand.command("done <id>").description("Set a backlog item to done").action(done);
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
// src/commands/complexity/analyze.ts
|
|
2010
|
+
import chalk33 from "chalk";
|
|
1796
2011
|
|
|
1797
2012
|
// src/commands/complexity/cyclomatic.ts
|
|
1798
|
-
import
|
|
2013
|
+
import chalk29 from "chalk";
|
|
1799
2014
|
|
|
1800
2015
|
// src/commands/complexity/shared/index.ts
|
|
1801
2016
|
import fs11 from "fs";
|
|
1802
2017
|
import path16 from "path";
|
|
1803
|
-
import
|
|
2018
|
+
import chalk28 from "chalk";
|
|
1804
2019
|
import ts5 from "typescript";
|
|
1805
2020
|
|
|
1806
2021
|
// src/commands/complexity/findSourceFiles.ts
|
|
@@ -2046,7 +2261,7 @@ function createSourceFromFile(filePath) {
|
|
|
2046
2261
|
function withSourceFiles(pattern2, callback) {
|
|
2047
2262
|
const files = findSourceFiles2(pattern2);
|
|
2048
2263
|
if (files.length === 0) {
|
|
2049
|
-
console.log(
|
|
2264
|
+
console.log(chalk28.yellow("No files found matching pattern"));
|
|
2050
2265
|
return void 0;
|
|
2051
2266
|
}
|
|
2052
2267
|
return callback(files);
|
|
@@ -2079,11 +2294,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2079
2294
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
2080
2295
|
for (const { file, name, complexity } of results) {
|
|
2081
2296
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
2082
|
-
const color = exceedsThreshold ?
|
|
2083
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
2297
|
+
const color = exceedsThreshold ? chalk29.red : chalk29.white;
|
|
2298
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk29.cyan(complexity)}`);
|
|
2084
2299
|
}
|
|
2085
2300
|
console.log(
|
|
2086
|
-
|
|
2301
|
+
chalk29.dim(
|
|
2087
2302
|
`
|
|
2088
2303
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
2089
2304
|
)
|
|
@@ -2095,7 +2310,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
2095
2310
|
}
|
|
2096
2311
|
|
|
2097
2312
|
// src/commands/complexity/halstead.ts
|
|
2098
|
-
import
|
|
2313
|
+
import chalk30 from "chalk";
|
|
2099
2314
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
2100
2315
|
withSourceFiles(pattern2, (files) => {
|
|
2101
2316
|
const results = [];
|
|
@@ -2110,13 +2325,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2110
2325
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
2111
2326
|
for (const { file, name, metrics } of results) {
|
|
2112
2327
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
2113
|
-
const color = exceedsThreshold ?
|
|
2328
|
+
const color = exceedsThreshold ? chalk30.red : chalk30.white;
|
|
2114
2329
|
console.log(
|
|
2115
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
2330
|
+
`${color(`${file}:${name}`)} \u2192 volume: ${chalk30.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk30.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk30.magenta(metrics.effort.toFixed(1))}`
|
|
2116
2331
|
);
|
|
2117
2332
|
}
|
|
2118
2333
|
console.log(
|
|
2119
|
-
|
|
2334
|
+
chalk30.dim(
|
|
2120
2335
|
`
|
|
2121
2336
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
2122
2337
|
)
|
|
@@ -2131,24 +2346,24 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
2131
2346
|
import fs12 from "fs";
|
|
2132
2347
|
|
|
2133
2348
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
2134
|
-
import
|
|
2349
|
+
import chalk31 from "chalk";
|
|
2135
2350
|
function displayMaintainabilityResults(results, threshold) {
|
|
2136
2351
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
2137
2352
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
2138
|
-
console.log(
|
|
2353
|
+
console.log(chalk31.green("All files pass maintainability threshold"));
|
|
2139
2354
|
} else {
|
|
2140
2355
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
2141
|
-
const color = threshold !== void 0 ?
|
|
2356
|
+
const color = threshold !== void 0 ? chalk31.red : chalk31.white;
|
|
2142
2357
|
console.log(
|
|
2143
|
-
`${color(file)} \u2192 avg: ${
|
|
2358
|
+
`${color(file)} \u2192 avg: ${chalk31.cyan(avgMaintainability.toFixed(1))}, min: ${chalk31.yellow(minMaintainability.toFixed(1))}`
|
|
2144
2359
|
);
|
|
2145
2360
|
}
|
|
2146
2361
|
}
|
|
2147
|
-
console.log(
|
|
2362
|
+
console.log(chalk31.dim(`
|
|
2148
2363
|
Analyzed ${results.length} files`));
|
|
2149
2364
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
2150
2365
|
console.error(
|
|
2151
|
-
|
|
2366
|
+
chalk31.red(
|
|
2152
2367
|
`
|
|
2153
2368
|
Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code. Focus on one file at a time \u2014 run 'assist complexity <file>' to see all metrics. For larger files, start by extracting responsibilities into smaller files.`
|
|
2154
2369
|
)
|
|
@@ -2207,7 +2422,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2207
2422
|
|
|
2208
2423
|
// src/commands/complexity/sloc.ts
|
|
2209
2424
|
import fs13 from "fs";
|
|
2210
|
-
import
|
|
2425
|
+
import chalk32 from "chalk";
|
|
2211
2426
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
2212
2427
|
withSourceFiles(pattern2, (files) => {
|
|
2213
2428
|
const results = [];
|
|
@@ -2223,12 +2438,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2223
2438
|
results.sort((a, b) => b.lines - a.lines);
|
|
2224
2439
|
for (const { file, lines } of results) {
|
|
2225
2440
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
2226
|
-
const color = exceedsThreshold ?
|
|
2227
|
-
console.log(`${color(file)} \u2192 ${
|
|
2441
|
+
const color = exceedsThreshold ? chalk32.red : chalk32.white;
|
|
2442
|
+
console.log(`${color(file)} \u2192 ${chalk32.cyan(lines)} lines`);
|
|
2228
2443
|
}
|
|
2229
2444
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
2230
2445
|
console.log(
|
|
2231
|
-
|
|
2446
|
+
chalk32.dim(`
|
|
2232
2447
|
Total: ${total} lines across ${files.length} files`)
|
|
2233
2448
|
);
|
|
2234
2449
|
if (hasViolation) {
|
|
@@ -2242,21 +2457,21 @@ async function analyze(pattern2) {
|
|
|
2242
2457
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
2243
2458
|
const files = findSourceFiles2(searchPattern);
|
|
2244
2459
|
if (files.length === 0) {
|
|
2245
|
-
console.log(
|
|
2460
|
+
console.log(chalk33.yellow("No files found matching pattern"));
|
|
2246
2461
|
return;
|
|
2247
2462
|
}
|
|
2248
2463
|
if (files.length === 1) {
|
|
2249
2464
|
const file = files[0];
|
|
2250
|
-
console.log(
|
|
2465
|
+
console.log(chalk33.bold.underline("SLOC"));
|
|
2251
2466
|
await sloc(file);
|
|
2252
2467
|
console.log();
|
|
2253
|
-
console.log(
|
|
2468
|
+
console.log(chalk33.bold.underline("Cyclomatic Complexity"));
|
|
2254
2469
|
await cyclomatic(file);
|
|
2255
2470
|
console.log();
|
|
2256
|
-
console.log(
|
|
2471
|
+
console.log(chalk33.bold.underline("Halstead Metrics"));
|
|
2257
2472
|
await halstead(file);
|
|
2258
2473
|
console.log();
|
|
2259
|
-
console.log(
|
|
2474
|
+
console.log(chalk33.bold.underline("Maintainability Index"));
|
|
2260
2475
|
await maintainability(file);
|
|
2261
2476
|
return;
|
|
2262
2477
|
}
|
|
@@ -2283,8 +2498,8 @@ function registerComplexity(program2) {
|
|
|
2283
2498
|
}
|
|
2284
2499
|
|
|
2285
2500
|
// src/commands/deploy/redirect.ts
|
|
2286
|
-
import { existsSync as
|
|
2287
|
-
import
|
|
2501
|
+
import { existsSync as existsSync15, readFileSync as readFileSync10, writeFileSync as writeFileSync11 } from "fs";
|
|
2502
|
+
import chalk34 from "chalk";
|
|
2288
2503
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
2289
2504
|
if (!window.location.pathname.endsWith('/')) {
|
|
2290
2505
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -2292,23 +2507,23 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
2292
2507
|
</script>`;
|
|
2293
2508
|
function redirect() {
|
|
2294
2509
|
const indexPath = "index.html";
|
|
2295
|
-
if (!
|
|
2296
|
-
console.log(
|
|
2510
|
+
if (!existsSync15(indexPath)) {
|
|
2511
|
+
console.log(chalk34.yellow("No index.html found"));
|
|
2297
2512
|
return;
|
|
2298
2513
|
}
|
|
2299
|
-
const content =
|
|
2514
|
+
const content = readFileSync10(indexPath, "utf-8");
|
|
2300
2515
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
2301
|
-
console.log(
|
|
2516
|
+
console.log(chalk34.dim("Trailing slash script already present"));
|
|
2302
2517
|
return;
|
|
2303
2518
|
}
|
|
2304
2519
|
const headCloseIndex = content.indexOf("</head>");
|
|
2305
2520
|
if (headCloseIndex === -1) {
|
|
2306
|
-
console.log(
|
|
2521
|
+
console.log(chalk34.red("Could not find </head> tag in index.html"));
|
|
2307
2522
|
return;
|
|
2308
2523
|
}
|
|
2309
2524
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
2310
|
-
|
|
2311
|
-
console.log(
|
|
2525
|
+
writeFileSync11(indexPath, newContent);
|
|
2526
|
+
console.log(chalk34.green("Added trailing slash redirect to index.html"));
|
|
2312
2527
|
}
|
|
2313
2528
|
|
|
2314
2529
|
// src/commands/registerDeploy.ts
|
|
@@ -2319,24 +2534,24 @@ function registerDeploy(program2) {
|
|
|
2319
2534
|
}
|
|
2320
2535
|
|
|
2321
2536
|
// src/commands/devlog/list/index.ts
|
|
2322
|
-
import { execSync as
|
|
2537
|
+
import { execSync as execSync12 } from "child_process";
|
|
2323
2538
|
import { basename as basename3 } from "path";
|
|
2324
2539
|
|
|
2325
2540
|
// src/commands/devlog/shared.ts
|
|
2326
|
-
import { execSync as
|
|
2327
|
-
import
|
|
2541
|
+
import { execSync as execSync11 } from "child_process";
|
|
2542
|
+
import chalk35 from "chalk";
|
|
2328
2543
|
|
|
2329
2544
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
2330
|
-
import { readdirSync, readFileSync as
|
|
2545
|
+
import { readdirSync, readFileSync as readFileSync11 } from "fs";
|
|
2331
2546
|
import { homedir } from "os";
|
|
2332
|
-
import { join as
|
|
2333
|
-
var DEVLOG_DIR =
|
|
2547
|
+
import { join as join9 } from "path";
|
|
2548
|
+
var DEVLOG_DIR = join9(homedir(), "git/blog/src/content/devlog");
|
|
2334
2549
|
function loadDevlogEntries(repoName) {
|
|
2335
2550
|
const entries = /* @__PURE__ */ new Map();
|
|
2336
2551
|
try {
|
|
2337
2552
|
const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
2338
2553
|
for (const file of files) {
|
|
2339
|
-
const content =
|
|
2554
|
+
const content = readFileSync11(join9(DEVLOG_DIR, file), "utf-8");
|
|
2340
2555
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
2341
2556
|
if (frontmatterMatch) {
|
|
2342
2557
|
const frontmatter = frontmatterMatch[1];
|
|
@@ -2367,7 +2582,7 @@ function loadDevlogEntries(repoName) {
|
|
|
2367
2582
|
// src/commands/devlog/shared.ts
|
|
2368
2583
|
function getCommitFiles(hash) {
|
|
2369
2584
|
try {
|
|
2370
|
-
const output =
|
|
2585
|
+
const output = execSync11(`git show --name-only --format="" ${hash}`, {
|
|
2371
2586
|
encoding: "utf-8"
|
|
2372
2587
|
});
|
|
2373
2588
|
return output.trim().split("\n").filter(Boolean);
|
|
@@ -2385,13 +2600,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
2385
2600
|
}
|
|
2386
2601
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
2387
2602
|
for (const commit2 of commits) {
|
|
2388
|
-
console.log(` ${
|
|
2603
|
+
console.log(` ${chalk35.yellow(commit2.hash)} ${commit2.message}`);
|
|
2389
2604
|
if (verbose) {
|
|
2390
2605
|
const visibleFiles = commit2.files.filter(
|
|
2391
2606
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
2392
2607
|
);
|
|
2393
2608
|
for (const file of visibleFiles) {
|
|
2394
|
-
console.log(` ${
|
|
2609
|
+
console.log(` ${chalk35.dim(file)}`);
|
|
2395
2610
|
}
|
|
2396
2611
|
}
|
|
2397
2612
|
}
|
|
@@ -2416,20 +2631,20 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
2416
2631
|
}
|
|
2417
2632
|
|
|
2418
2633
|
// src/commands/devlog/list/printDateHeader.ts
|
|
2419
|
-
import
|
|
2634
|
+
import chalk36 from "chalk";
|
|
2420
2635
|
function printDateHeader(date, isSkipped, entries) {
|
|
2421
2636
|
if (isSkipped) {
|
|
2422
|
-
console.log(`${
|
|
2637
|
+
console.log(`${chalk36.bold.blue(date)} ${chalk36.dim("skipped")}`);
|
|
2423
2638
|
} else if (entries && entries.length > 0) {
|
|
2424
|
-
const entryInfo = entries.map((e) => `${
|
|
2425
|
-
console.log(`${
|
|
2639
|
+
const entryInfo = entries.map((e) => `${chalk36.green(e.version)} ${e.title}`).join(" | ");
|
|
2640
|
+
console.log(`${chalk36.bold.blue(date)} ${entryInfo}`);
|
|
2426
2641
|
} else {
|
|
2427
|
-
console.log(`${
|
|
2642
|
+
console.log(`${chalk36.bold.blue(date)} ${chalk36.red("\u26A0 devlog missing")}`);
|
|
2428
2643
|
}
|
|
2429
2644
|
}
|
|
2430
2645
|
|
|
2431
2646
|
// src/commands/devlog/list/index.ts
|
|
2432
|
-
function
|
|
2647
|
+
function list2(options2) {
|
|
2433
2648
|
const config = loadConfig();
|
|
2434
2649
|
const days = options2.days ?? 30;
|
|
2435
2650
|
const ignore2 = options2.ignore ?? config.devlog?.ignore ?? [];
|
|
@@ -2438,7 +2653,7 @@ function list(options2) {
|
|
|
2438
2653
|
const devlogEntries = loadDevlogEntries(repoName);
|
|
2439
2654
|
const reverseFlag = options2.reverse ? "--reverse " : "";
|
|
2440
2655
|
const limitFlag = options2.reverse ? "" : "-n 500 ";
|
|
2441
|
-
const output =
|
|
2656
|
+
const output = execSync12(
|
|
2442
2657
|
`git log ${reverseFlag}${limitFlag}--pretty=format:'%ad|%h|%s' --date=short`,
|
|
2443
2658
|
{ encoding: "utf-8" }
|
|
2444
2659
|
);
|
|
@@ -2464,11 +2679,11 @@ function list(options2) {
|
|
|
2464
2679
|
}
|
|
2465
2680
|
|
|
2466
2681
|
// src/commands/devlog/getLastVersionInfo.ts
|
|
2467
|
-
import { execSync as
|
|
2682
|
+
import { execSync as execSync13 } from "child_process";
|
|
2468
2683
|
import semver from "semver";
|
|
2469
2684
|
function getVersionAtCommit(hash) {
|
|
2470
2685
|
try {
|
|
2471
|
-
const content =
|
|
2686
|
+
const content = execSync13(`git show ${hash}:package.json`, {
|
|
2472
2687
|
encoding: "utf-8"
|
|
2473
2688
|
});
|
|
2474
2689
|
const pkg = JSON.parse(content);
|
|
@@ -2483,7 +2698,7 @@ function stripToMinor(version2) {
|
|
|
2483
2698
|
}
|
|
2484
2699
|
function getLastVersionInfoFromGit() {
|
|
2485
2700
|
try {
|
|
2486
|
-
const output =
|
|
2701
|
+
const output = execSync13(
|
|
2487
2702
|
"git log -1 --pretty=format:'%ad|%h' --date=short",
|
|
2488
2703
|
{
|
|
2489
2704
|
encoding: "utf-8"
|
|
@@ -2526,25 +2741,25 @@ function bumpVersion(version2, type) {
|
|
|
2526
2741
|
}
|
|
2527
2742
|
|
|
2528
2743
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
2529
|
-
import { execSync as
|
|
2530
|
-
import
|
|
2744
|
+
import { execSync as execSync14 } from "child_process";
|
|
2745
|
+
import chalk38 from "chalk";
|
|
2531
2746
|
|
|
2532
2747
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
2533
|
-
import
|
|
2748
|
+
import chalk37 from "chalk";
|
|
2534
2749
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
2535
2750
|
if (conventional && firstHash) {
|
|
2536
2751
|
const version2 = getVersionAtCommit(firstHash);
|
|
2537
2752
|
if (version2) {
|
|
2538
|
-
console.log(`${
|
|
2753
|
+
console.log(`${chalk37.bold("version:")} ${stripToMinor(version2)}`);
|
|
2539
2754
|
} else {
|
|
2540
|
-
console.log(`${
|
|
2755
|
+
console.log(`${chalk37.bold("version:")} ${chalk37.red("unknown")}`);
|
|
2541
2756
|
}
|
|
2542
2757
|
} else if (patchVersion && minorVersion) {
|
|
2543
2758
|
console.log(
|
|
2544
|
-
`${
|
|
2759
|
+
`${chalk37.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
2545
2760
|
);
|
|
2546
2761
|
} else {
|
|
2547
|
-
console.log(`${
|
|
2762
|
+
console.log(`${chalk37.bold("version:")} v0.1 (initial)`);
|
|
2548
2763
|
}
|
|
2549
2764
|
}
|
|
2550
2765
|
|
|
@@ -2560,7 +2775,7 @@ function findTargetDate(commitsByDate, skipDays) {
|
|
|
2560
2775
|
return Array.from(commitsByDate.keys()).filter((d) => !skipDays.has(d)).sort()[0];
|
|
2561
2776
|
}
|
|
2562
2777
|
function fetchCommitsByDate(ignore2, lastDate) {
|
|
2563
|
-
const output =
|
|
2778
|
+
const output = execSync14(
|
|
2564
2779
|
"git log --pretty=format:'%ad|%h|%s' --date=short -n 500",
|
|
2565
2780
|
{ encoding: "utf-8" }
|
|
2566
2781
|
);
|
|
@@ -2591,16 +2806,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
2591
2806
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
2592
2807
|
}
|
|
2593
2808
|
function logName(repoName) {
|
|
2594
|
-
console.log(`${
|
|
2809
|
+
console.log(`${chalk38.bold("name:")} ${repoName}`);
|
|
2595
2810
|
}
|
|
2596
2811
|
function displayNextEntry(ctx, targetDate, commits) {
|
|
2597
2812
|
logName(ctx.repoName);
|
|
2598
2813
|
printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
|
|
2599
|
-
console.log(
|
|
2814
|
+
console.log(chalk38.bold.blue(targetDate));
|
|
2600
2815
|
printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
|
|
2601
2816
|
}
|
|
2602
2817
|
function logNoCommits(lastInfo) {
|
|
2603
|
-
console.log(
|
|
2818
|
+
console.log(chalk38.dim(noCommitsMessage(!!lastInfo)));
|
|
2604
2819
|
}
|
|
2605
2820
|
|
|
2606
2821
|
// src/commands/devlog/next/index.ts
|
|
@@ -2635,16 +2850,16 @@ function next(options2) {
|
|
|
2635
2850
|
}
|
|
2636
2851
|
|
|
2637
2852
|
// src/commands/devlog/skip.ts
|
|
2638
|
-
import
|
|
2853
|
+
import chalk39 from "chalk";
|
|
2639
2854
|
function skip(date) {
|
|
2640
2855
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
2641
|
-
console.log(
|
|
2856
|
+
console.log(chalk39.red("Invalid date format. Use YYYY-MM-DD"));
|
|
2642
2857
|
process.exit(1);
|
|
2643
2858
|
}
|
|
2644
2859
|
const config = loadConfig();
|
|
2645
2860
|
const skipDays = config.devlog?.skip?.days ?? [];
|
|
2646
2861
|
if (skipDays.includes(date)) {
|
|
2647
|
-
console.log(
|
|
2862
|
+
console.log(chalk39.yellow(`${date} is already in skip list`));
|
|
2648
2863
|
return;
|
|
2649
2864
|
}
|
|
2650
2865
|
skipDays.push(date);
|
|
@@ -2657,20 +2872,20 @@ function skip(date) {
|
|
|
2657
2872
|
}
|
|
2658
2873
|
};
|
|
2659
2874
|
saveConfig(config);
|
|
2660
|
-
console.log(
|
|
2875
|
+
console.log(chalk39.green(`Added ${date} to skip list`));
|
|
2661
2876
|
}
|
|
2662
2877
|
|
|
2663
2878
|
// src/commands/devlog/version.ts
|
|
2664
|
-
import
|
|
2879
|
+
import chalk40 from "chalk";
|
|
2665
2880
|
function version() {
|
|
2666
2881
|
const config = loadConfig();
|
|
2667
2882
|
const name = getRepoName();
|
|
2668
2883
|
const lastInfo = getLastVersionInfo(name, config);
|
|
2669
2884
|
const lastVersion = lastInfo?.version ?? null;
|
|
2670
2885
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
2671
|
-
console.log(`${
|
|
2672
|
-
console.log(`${
|
|
2673
|
-
console.log(`${
|
|
2886
|
+
console.log(`${chalk40.bold("name:")} ${name}`);
|
|
2887
|
+
console.log(`${chalk40.bold("last:")} ${lastVersion ?? chalk40.dim("none")}`);
|
|
2888
|
+
console.log(`${chalk40.bold("next:")} ${nextVersion ?? chalk40.dim("none")}`);
|
|
2674
2889
|
}
|
|
2675
2890
|
|
|
2676
2891
|
// src/commands/registerDevlog.ts
|
|
@@ -2680,46 +2895,46 @@ function registerDevlog(program2) {
|
|
|
2680
2895
|
"--days <number>",
|
|
2681
2896
|
"Number of days to show (default: 30)",
|
|
2682
2897
|
Number.parseInt
|
|
2683
|
-
).option("--since <date>", "Only show commits since this date (YYYY-MM-DD)").option("-r, --reverse", "Show earliest commits first").option("-v, --verbose", "Show file names for each commit").action(
|
|
2898
|
+
).option("--since <date>", "Only show commits since this date (YYYY-MM-DD)").option("-r, --reverse", "Show earliest commits first").option("-v, --verbose", "Show file names for each commit").action(list2);
|
|
2684
2899
|
devlogCommand.command("version").description("Show current repo name and version info").action(version);
|
|
2685
2900
|
devlogCommand.command("next").description("Show commits for the day after the last versioned entry").option("-v, --verbose", "Show file names for each commit").action(next);
|
|
2686
2901
|
devlogCommand.command("skip <date>").description("Add a date (YYYY-MM-DD) to the skip list").action(skip);
|
|
2687
2902
|
}
|
|
2688
2903
|
|
|
2689
2904
|
// src/commands/prs/fixed.ts
|
|
2690
|
-
import { execSync as
|
|
2905
|
+
import { execSync as execSync17 } from "child_process";
|
|
2691
2906
|
|
|
2692
2907
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
2693
|
-
import { execSync as
|
|
2694
|
-
import { unlinkSync as unlinkSync3, writeFileSync as
|
|
2908
|
+
import { execSync as execSync16 } from "child_process";
|
|
2909
|
+
import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync12 } from "fs";
|
|
2695
2910
|
import { tmpdir } from "os";
|
|
2696
|
-
import { join as
|
|
2911
|
+
import { join as join11 } from "path";
|
|
2697
2912
|
|
|
2698
2913
|
// src/commands/prs/loadCommentsCache.ts
|
|
2699
|
-
import { existsSync as
|
|
2700
|
-
import { join as
|
|
2914
|
+
import { existsSync as existsSync16, readFileSync as readFileSync12, unlinkSync as unlinkSync2 } from "fs";
|
|
2915
|
+
import { join as join10 } from "path";
|
|
2701
2916
|
import { parse } from "yaml";
|
|
2702
2917
|
function getCachePath(prNumber) {
|
|
2703
|
-
return
|
|
2918
|
+
return join10(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
2704
2919
|
}
|
|
2705
2920
|
function loadCommentsCache(prNumber) {
|
|
2706
2921
|
const cachePath = getCachePath(prNumber);
|
|
2707
|
-
if (!
|
|
2922
|
+
if (!existsSync16(cachePath)) {
|
|
2708
2923
|
return null;
|
|
2709
2924
|
}
|
|
2710
|
-
const content =
|
|
2925
|
+
const content = readFileSync12(cachePath, "utf-8");
|
|
2711
2926
|
return parse(content);
|
|
2712
2927
|
}
|
|
2713
2928
|
function deleteCommentsCache(prNumber) {
|
|
2714
2929
|
const cachePath = getCachePath(prNumber);
|
|
2715
|
-
if (
|
|
2930
|
+
if (existsSync16(cachePath)) {
|
|
2716
2931
|
unlinkSync2(cachePath);
|
|
2717
2932
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
2718
2933
|
}
|
|
2719
2934
|
}
|
|
2720
2935
|
|
|
2721
2936
|
// src/commands/prs/shared.ts
|
|
2722
|
-
import { execSync as
|
|
2937
|
+
import { execSync as execSync15 } from "child_process";
|
|
2723
2938
|
function isGhNotInstalled(error) {
|
|
2724
2939
|
if (error instanceof Error) {
|
|
2725
2940
|
const msg = error.message.toLowerCase();
|
|
@@ -2735,14 +2950,14 @@ function isNotFound(error) {
|
|
|
2735
2950
|
}
|
|
2736
2951
|
function getRepoInfo() {
|
|
2737
2952
|
const repoInfo = JSON.parse(
|
|
2738
|
-
|
|
2953
|
+
execSync15("gh repo view --json owner,name", { encoding: "utf-8" })
|
|
2739
2954
|
);
|
|
2740
2955
|
return { org: repoInfo.owner.login, repo: repoInfo.name };
|
|
2741
2956
|
}
|
|
2742
2957
|
function getCurrentPrNumber() {
|
|
2743
2958
|
try {
|
|
2744
2959
|
const prInfo = JSON.parse(
|
|
2745
|
-
|
|
2960
|
+
execSync15("gh pr view --json number", { encoding: "utf-8" })
|
|
2746
2961
|
);
|
|
2747
2962
|
return prInfo.number;
|
|
2748
2963
|
} catch (error) {
|
|
@@ -2756,17 +2971,17 @@ function getCurrentPrNumber() {
|
|
|
2756
2971
|
|
|
2757
2972
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
2758
2973
|
function replyToComment(org, repo, prNumber, commentId, message) {
|
|
2759
|
-
|
|
2974
|
+
execSync16(
|
|
2760
2975
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, '\\"')}" -F in_reply_to=${commentId}`,
|
|
2761
2976
|
{ stdio: "inherit" }
|
|
2762
2977
|
);
|
|
2763
2978
|
}
|
|
2764
2979
|
function resolveThread(threadId) {
|
|
2765
2980
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
2766
|
-
const queryFile =
|
|
2767
|
-
|
|
2981
|
+
const queryFile = join11(tmpdir(), `gh-mutation-${Date.now()}.graphql`);
|
|
2982
|
+
writeFileSync12(queryFile, mutation);
|
|
2768
2983
|
try {
|
|
2769
|
-
|
|
2984
|
+
execSync16(
|
|
2770
2985
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
2771
2986
|
{ stdio: "inherit" }
|
|
2772
2987
|
);
|
|
@@ -2818,7 +3033,7 @@ function resolveCommentWithReply(commentId, message) {
|
|
|
2818
3033
|
// src/commands/prs/fixed.ts
|
|
2819
3034
|
function verifySha(sha) {
|
|
2820
3035
|
try {
|
|
2821
|
-
return
|
|
3036
|
+
return execSync17(`git rev-parse --verify ${sha}`, {
|
|
2822
3037
|
encoding: "utf-8"
|
|
2823
3038
|
}).trim();
|
|
2824
3039
|
} catch {
|
|
@@ -2844,8 +3059,8 @@ function fixed(commentId, sha) {
|
|
|
2844
3059
|
}
|
|
2845
3060
|
|
|
2846
3061
|
// src/commands/prs/listComments/index.ts
|
|
2847
|
-
import { existsSync as
|
|
2848
|
-
import { join as
|
|
3062
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync4, writeFileSync as writeFileSync14 } from "fs";
|
|
3063
|
+
import { join as join13 } from "path";
|
|
2849
3064
|
import { stringify } from "yaml";
|
|
2850
3065
|
|
|
2851
3066
|
// src/lib/isClaudeCode.ts
|
|
@@ -2854,16 +3069,16 @@ function isClaudeCode() {
|
|
|
2854
3069
|
}
|
|
2855
3070
|
|
|
2856
3071
|
// src/commands/prs/fetchThreadIds.ts
|
|
2857
|
-
import { execSync as
|
|
2858
|
-
import { unlinkSync as unlinkSync4, writeFileSync as
|
|
3072
|
+
import { execSync as execSync18 } from "child_process";
|
|
3073
|
+
import { unlinkSync as unlinkSync4, writeFileSync as writeFileSync13 } from "fs";
|
|
2859
3074
|
import { tmpdir as tmpdir2 } from "os";
|
|
2860
|
-
import { join as
|
|
3075
|
+
import { join as join12 } from "path";
|
|
2861
3076
|
var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
|
|
2862
3077
|
function fetchThreadIds(org, repo, prNumber) {
|
|
2863
|
-
const queryFile =
|
|
2864
|
-
|
|
3078
|
+
const queryFile = join12(tmpdir2(), `gh-query-${Date.now()}.graphql`);
|
|
3079
|
+
writeFileSync13(queryFile, THREAD_QUERY);
|
|
2865
3080
|
try {
|
|
2866
|
-
const result =
|
|
3081
|
+
const result = execSync18(
|
|
2867
3082
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
2868
3083
|
{ encoding: "utf-8" }
|
|
2869
3084
|
);
|
|
@@ -2885,9 +3100,9 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
2885
3100
|
}
|
|
2886
3101
|
|
|
2887
3102
|
// src/commands/prs/listComments/fetchReviewComments.ts
|
|
2888
|
-
import { execSync as
|
|
3103
|
+
import { execSync as execSync19 } from "child_process";
|
|
2889
3104
|
function fetchJson(endpoint) {
|
|
2890
|
-
const result =
|
|
3105
|
+
const result = execSync19(`gh api ${endpoint}`, { encoding: "utf-8" });
|
|
2891
3106
|
if (!result.trim()) return [];
|
|
2892
3107
|
return JSON.parse(result);
|
|
2893
3108
|
}
|
|
@@ -2927,20 +3142,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
2927
3142
|
}
|
|
2928
3143
|
|
|
2929
3144
|
// src/commands/prs/listComments/formatForHuman.ts
|
|
2930
|
-
import
|
|
3145
|
+
import chalk41 from "chalk";
|
|
2931
3146
|
function formatForHuman(comment) {
|
|
2932
3147
|
if (comment.type === "review") {
|
|
2933
|
-
const stateColor = comment.state === "APPROVED" ?
|
|
3148
|
+
const stateColor = comment.state === "APPROVED" ? chalk41.green : comment.state === "CHANGES_REQUESTED" ? chalk41.red : chalk41.yellow;
|
|
2934
3149
|
return [
|
|
2935
|
-
`${
|
|
3150
|
+
`${chalk41.cyan("Review")} by ${chalk41.bold(comment.user)} ${stateColor(`[${comment.state}]`)}`,
|
|
2936
3151
|
comment.body,
|
|
2937
3152
|
""
|
|
2938
3153
|
].join("\n");
|
|
2939
3154
|
}
|
|
2940
3155
|
const location = comment.line ? `:${comment.line}` : "";
|
|
2941
3156
|
return [
|
|
2942
|
-
`${
|
|
2943
|
-
|
|
3157
|
+
`${chalk41.cyan("Line comment")} by ${chalk41.bold(comment.user)} on ${chalk41.dim(`${comment.path}${location}`)}`,
|
|
3158
|
+
chalk41.dim(comment.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
2944
3159
|
comment.body,
|
|
2945
3160
|
""
|
|
2946
3161
|
].join("\n");
|
|
@@ -2963,8 +3178,8 @@ function printComments(comments) {
|
|
|
2963
3178
|
}
|
|
2964
3179
|
}
|
|
2965
3180
|
function writeCommentsCache(prNumber, comments) {
|
|
2966
|
-
const assistDir =
|
|
2967
|
-
if (!
|
|
3181
|
+
const assistDir = join13(process.cwd(), ".assist");
|
|
3182
|
+
if (!existsSync17(assistDir)) {
|
|
2968
3183
|
mkdirSync4(assistDir, { recursive: true });
|
|
2969
3184
|
}
|
|
2970
3185
|
const cacheData = {
|
|
@@ -2972,8 +3187,8 @@ function writeCommentsCache(prNumber, comments) {
|
|
|
2972
3187
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2973
3188
|
comments
|
|
2974
3189
|
};
|
|
2975
|
-
const cachePath =
|
|
2976
|
-
|
|
3190
|
+
const cachePath = join13(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
3191
|
+
writeFileSync14(cachePath, stringify(cacheData));
|
|
2977
3192
|
}
|
|
2978
3193
|
function handleKnownErrors(error) {
|
|
2979
3194
|
if (isGhNotInstalled(error)) {
|
|
@@ -3013,19 +3228,19 @@ async function listComments() {
|
|
|
3013
3228
|
}
|
|
3014
3229
|
|
|
3015
3230
|
// src/commands/prs/prs/index.ts
|
|
3016
|
-
import { execSync as
|
|
3231
|
+
import { execSync as execSync20 } from "child_process";
|
|
3017
3232
|
|
|
3018
3233
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
3019
|
-
import
|
|
3234
|
+
import enquirer5 from "enquirer";
|
|
3020
3235
|
|
|
3021
3236
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
3022
|
-
import
|
|
3237
|
+
import chalk42 from "chalk";
|
|
3023
3238
|
var STATUS_MAP = {
|
|
3024
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
3025
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
3239
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk42.magenta("merged"), date: pr.mergedAt } : null,
|
|
3240
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk42.red("closed"), date: pr.closedAt } : null
|
|
3026
3241
|
};
|
|
3027
3242
|
function defaultStatus(pr) {
|
|
3028
|
-
return { label:
|
|
3243
|
+
return { label: chalk42.green("opened"), date: pr.createdAt };
|
|
3029
3244
|
}
|
|
3030
3245
|
function getStatus(pr) {
|
|
3031
3246
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -3034,11 +3249,11 @@ function formatDate(dateStr) {
|
|
|
3034
3249
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
3035
3250
|
}
|
|
3036
3251
|
function formatPrHeader(pr, status) {
|
|
3037
|
-
return `${
|
|
3252
|
+
return `${chalk42.cyan(`#${pr.number}`)} ${pr.title} ${chalk42.dim(`(${pr.author.login},`)} ${status.label} ${chalk42.dim(`${formatDate(status.date)})`)}`;
|
|
3038
3253
|
}
|
|
3039
3254
|
function logPrDetails(pr) {
|
|
3040
3255
|
console.log(
|
|
3041
|
-
|
|
3256
|
+
chalk42.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
3042
3257
|
);
|
|
3043
3258
|
console.log();
|
|
3044
3259
|
}
|
|
@@ -3050,8 +3265,8 @@ function printPr(pr) {
|
|
|
3050
3265
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
3051
3266
|
var PAGE_SIZE = 10;
|
|
3052
3267
|
function getPageSlice(pullRequests, page) {
|
|
3053
|
-
const
|
|
3054
|
-
return pullRequests.slice(
|
|
3268
|
+
const start2 = page * PAGE_SIZE;
|
|
3269
|
+
return pullRequests.slice(start2, start2 + PAGE_SIZE);
|
|
3055
3270
|
}
|
|
3056
3271
|
function pageHeader(page, totalPages, total) {
|
|
3057
3272
|
return `
|
|
@@ -3086,7 +3301,7 @@ function parseAction(action) {
|
|
|
3086
3301
|
}
|
|
3087
3302
|
async function promptNavigation(currentPage, totalPages) {
|
|
3088
3303
|
const choices = buildNavChoices(currentPage, totalPages);
|
|
3089
|
-
const { action } = await
|
|
3304
|
+
const { action } = await enquirer5.prompt({
|
|
3090
3305
|
type: "select",
|
|
3091
3306
|
name: "action",
|
|
3092
3307
|
message: "Navigate",
|
|
@@ -3119,7 +3334,7 @@ async function displayPaginated(pullRequests) {
|
|
|
3119
3334
|
async function prs(options2) {
|
|
3120
3335
|
const state = options2.open ? "open" : options2.closed ? "closed" : "all";
|
|
3121
3336
|
try {
|
|
3122
|
-
const result =
|
|
3337
|
+
const result = execSync20(
|
|
3123
3338
|
`gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100`,
|
|
3124
3339
|
{ encoding: "utf-8" }
|
|
3125
3340
|
);
|
|
@@ -3142,7 +3357,7 @@ async function prs(options2) {
|
|
|
3142
3357
|
}
|
|
3143
3358
|
|
|
3144
3359
|
// src/commands/prs/wontfix.ts
|
|
3145
|
-
import { execSync as
|
|
3360
|
+
import { execSync as execSync21 } from "child_process";
|
|
3146
3361
|
function validateReason(reason) {
|
|
3147
3362
|
const lowerReason = reason.toLowerCase();
|
|
3148
3363
|
if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
|
|
@@ -3159,7 +3374,7 @@ function validateShaReferences(reason) {
|
|
|
3159
3374
|
const invalidShas = [];
|
|
3160
3375
|
for (const sha of shas) {
|
|
3161
3376
|
try {
|
|
3162
|
-
|
|
3377
|
+
execSync21(`git cat-file -t ${sha}`, { stdio: "pipe" });
|
|
3163
3378
|
} catch {
|
|
3164
3379
|
invalidShas.push(sha);
|
|
3165
3380
|
}
|
|
@@ -3205,7 +3420,7 @@ import { spawn as spawn3 } from "child_process";
|
|
|
3205
3420
|
import * as path17 from "path";
|
|
3206
3421
|
|
|
3207
3422
|
// src/commands/refactor/logViolations.ts
|
|
3208
|
-
import
|
|
3423
|
+
import chalk43 from "chalk";
|
|
3209
3424
|
var DEFAULT_MAX_LINES = 100;
|
|
3210
3425
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
3211
3426
|
if (violations.length === 0) {
|
|
@@ -3214,43 +3429,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
3214
3429
|
}
|
|
3215
3430
|
return;
|
|
3216
3431
|
}
|
|
3217
|
-
console.error(
|
|
3432
|
+
console.error(chalk43.red(`
|
|
3218
3433
|
Refactor check failed:
|
|
3219
3434
|
`));
|
|
3220
|
-
console.error(
|
|
3435
|
+
console.error(chalk43.red(` The following files exceed ${maxLines} lines:
|
|
3221
3436
|
`));
|
|
3222
3437
|
for (const violation of violations) {
|
|
3223
|
-
console.error(
|
|
3438
|
+
console.error(chalk43.red(` ${violation.file} (${violation.lines} lines)`));
|
|
3224
3439
|
}
|
|
3225
3440
|
console.error(
|
|
3226
|
-
|
|
3441
|
+
chalk43.yellow(
|
|
3227
3442
|
`
|
|
3228
3443
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
3229
3444
|
way to refactor it, ignore it with:
|
|
3230
3445
|
`
|
|
3231
3446
|
)
|
|
3232
3447
|
);
|
|
3233
|
-
console.error(
|
|
3448
|
+
console.error(chalk43.gray(` assist refactor ignore <file>
|
|
3234
3449
|
`));
|
|
3235
3450
|
if (process.env.CLAUDECODE) {
|
|
3236
|
-
console.error(
|
|
3451
|
+
console.error(chalk43.cyan(`
|
|
3237
3452
|
## Extracting Code to New Files
|
|
3238
3453
|
`));
|
|
3239
3454
|
console.error(
|
|
3240
|
-
|
|
3455
|
+
chalk43.cyan(
|
|
3241
3456
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
3242
3457
|
`
|
|
3243
3458
|
)
|
|
3244
3459
|
);
|
|
3245
3460
|
console.error(
|
|
3246
|
-
|
|
3461
|
+
chalk43.cyan(
|
|
3247
3462
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
3248
3463
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
3249
3464
|
`
|
|
3250
3465
|
)
|
|
3251
3466
|
);
|
|
3252
3467
|
console.error(
|
|
3253
|
-
|
|
3468
|
+
chalk43.cyan(
|
|
3254
3469
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
3255
3470
|
domains, move it to a common/shared folder.
|
|
3256
3471
|
`
|
|
@@ -3260,7 +3475,7 @@ Refactor check failed:
|
|
|
3260
3475
|
}
|
|
3261
3476
|
|
|
3262
3477
|
// src/commands/refactor/check/getViolations/index.ts
|
|
3263
|
-
import { execSync as
|
|
3478
|
+
import { execSync as execSync22 } from "child_process";
|
|
3264
3479
|
import fs15 from "fs";
|
|
3265
3480
|
import { minimatch as minimatch2 } from "minimatch";
|
|
3266
3481
|
|
|
@@ -3310,7 +3525,7 @@ function getGitFiles(options2) {
|
|
|
3310
3525
|
}
|
|
3311
3526
|
const files = /* @__PURE__ */ new Set();
|
|
3312
3527
|
if (options2.staged || options2.modified) {
|
|
3313
|
-
const staged =
|
|
3528
|
+
const staged = execSync22("git diff --cached --name-only", {
|
|
3314
3529
|
encoding: "utf-8"
|
|
3315
3530
|
});
|
|
3316
3531
|
for (const file of staged.trim().split("\n").filter(Boolean)) {
|
|
@@ -3318,7 +3533,7 @@ function getGitFiles(options2) {
|
|
|
3318
3533
|
}
|
|
3319
3534
|
}
|
|
3320
3535
|
if (options2.unstaged || options2.modified) {
|
|
3321
|
-
const unstaged =
|
|
3536
|
+
const unstaged = execSync22("git diff --name-only", { encoding: "utf-8" });
|
|
3322
3537
|
for (const file of unstaged.trim().split("\n").filter(Boolean)) {
|
|
3323
3538
|
files.add(file);
|
|
3324
3539
|
}
|
|
@@ -3406,11 +3621,11 @@ async function check(pattern2, options2) {
|
|
|
3406
3621
|
|
|
3407
3622
|
// src/commands/refactor/ignore.ts
|
|
3408
3623
|
import fs16 from "fs";
|
|
3409
|
-
import
|
|
3624
|
+
import chalk44 from "chalk";
|
|
3410
3625
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
3411
3626
|
function ignore(file) {
|
|
3412
3627
|
if (!fs16.existsSync(file)) {
|
|
3413
|
-
console.error(
|
|
3628
|
+
console.error(chalk44.red(`Error: File does not exist: ${file}`));
|
|
3414
3629
|
process.exit(1);
|
|
3415
3630
|
}
|
|
3416
3631
|
const content = fs16.readFileSync(file, "utf-8");
|
|
@@ -3426,7 +3641,7 @@ function ignore(file) {
|
|
|
3426
3641
|
fs16.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
3427
3642
|
}
|
|
3428
3643
|
console.log(
|
|
3429
|
-
|
|
3644
|
+
chalk44.green(
|
|
3430
3645
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
3431
3646
|
)
|
|
3432
3647
|
);
|
|
@@ -3434,7 +3649,7 @@ function ignore(file) {
|
|
|
3434
3649
|
|
|
3435
3650
|
// src/commands/refactor/restructure/index.ts
|
|
3436
3651
|
import path26 from "path";
|
|
3437
|
-
import
|
|
3652
|
+
import chalk47 from "chalk";
|
|
3438
3653
|
|
|
3439
3654
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
3440
3655
|
import path18 from "path";
|
|
@@ -3583,9 +3798,9 @@ import path21 from "path";
|
|
|
3583
3798
|
// src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
|
|
3584
3799
|
import fs17 from "fs";
|
|
3585
3800
|
function getOrCreateList(map, key) {
|
|
3586
|
-
const
|
|
3587
|
-
if (!map.has(key)) map.set(key,
|
|
3588
|
-
return
|
|
3801
|
+
const list3 = map.get(key) ?? [];
|
|
3802
|
+
if (!map.has(key)) map.set(key, list3);
|
|
3803
|
+
return list3;
|
|
3589
3804
|
}
|
|
3590
3805
|
function groupByFile(rewrites) {
|
|
3591
3806
|
const grouped = /* @__PURE__ */ new Map();
|
|
@@ -3677,50 +3892,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
3677
3892
|
|
|
3678
3893
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
3679
3894
|
import path22 from "path";
|
|
3680
|
-
import
|
|
3895
|
+
import chalk45 from "chalk";
|
|
3681
3896
|
function relPath(filePath) {
|
|
3682
3897
|
return path22.relative(process.cwd(), filePath);
|
|
3683
3898
|
}
|
|
3684
3899
|
function displayMoves(plan) {
|
|
3685
3900
|
if (plan.moves.length === 0) return;
|
|
3686
|
-
console.log(
|
|
3901
|
+
console.log(chalk45.bold("\nFile moves:"));
|
|
3687
3902
|
for (const move of plan.moves) {
|
|
3688
3903
|
console.log(
|
|
3689
|
-
` ${
|
|
3904
|
+
` ${chalk45.red(relPath(move.from))} \u2192 ${chalk45.green(relPath(move.to))}`
|
|
3690
3905
|
);
|
|
3691
|
-
console.log(
|
|
3906
|
+
console.log(chalk45.dim(` ${move.reason}`));
|
|
3692
3907
|
}
|
|
3693
3908
|
}
|
|
3694
3909
|
function displayRewrites(rewrites) {
|
|
3695
3910
|
if (rewrites.length === 0) return;
|
|
3696
3911
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
3697
|
-
console.log(
|
|
3912
|
+
console.log(chalk45.bold(`
|
|
3698
3913
|
Import rewrites (${affectedFiles.size} files):`));
|
|
3699
3914
|
for (const file of affectedFiles) {
|
|
3700
|
-
console.log(` ${
|
|
3915
|
+
console.log(` ${chalk45.cyan(relPath(file))}:`);
|
|
3701
3916
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
3702
3917
|
(r) => r.file === file
|
|
3703
3918
|
)) {
|
|
3704
3919
|
console.log(
|
|
3705
|
-
` ${
|
|
3920
|
+
` ${chalk45.red(`"${oldSpecifier}"`)} \u2192 ${chalk45.green(`"${newSpecifier}"`)}`
|
|
3706
3921
|
);
|
|
3707
3922
|
}
|
|
3708
3923
|
}
|
|
3709
3924
|
}
|
|
3710
3925
|
function displayPlan(plan) {
|
|
3711
3926
|
if (plan.warnings.length > 0) {
|
|
3712
|
-
console.log(
|
|
3713
|
-
for (const w of plan.warnings) console.log(
|
|
3927
|
+
console.log(chalk45.yellow("\nWarnings:"));
|
|
3928
|
+
for (const w of plan.warnings) console.log(chalk45.yellow(` ${w}`));
|
|
3714
3929
|
}
|
|
3715
3930
|
if (plan.newDirectories.length > 0) {
|
|
3716
|
-
console.log(
|
|
3931
|
+
console.log(chalk45.bold("\nNew directories:"));
|
|
3717
3932
|
for (const dir of plan.newDirectories)
|
|
3718
|
-
console.log(
|
|
3933
|
+
console.log(chalk45.green(` ${dir}/`));
|
|
3719
3934
|
}
|
|
3720
3935
|
displayMoves(plan);
|
|
3721
3936
|
displayRewrites(plan.rewrites);
|
|
3722
3937
|
console.log(
|
|
3723
|
-
|
|
3938
|
+
chalk45.dim(
|
|
3724
3939
|
`
|
|
3725
3940
|
Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
|
|
3726
3941
|
)
|
|
@@ -3730,18 +3945,18 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
|
|
|
3730
3945
|
// src/commands/refactor/restructure/executePlan.ts
|
|
3731
3946
|
import fs18 from "fs";
|
|
3732
3947
|
import path23 from "path";
|
|
3733
|
-
import
|
|
3948
|
+
import chalk46 from "chalk";
|
|
3734
3949
|
function executePlan(plan) {
|
|
3735
3950
|
const updatedContents = applyRewrites(plan.rewrites);
|
|
3736
3951
|
for (const [file, content] of updatedContents) {
|
|
3737
3952
|
fs18.writeFileSync(file, content, "utf-8");
|
|
3738
3953
|
console.log(
|
|
3739
|
-
|
|
3954
|
+
chalk46.cyan(` Rewrote imports in ${path23.relative(process.cwd(), file)}`)
|
|
3740
3955
|
);
|
|
3741
3956
|
}
|
|
3742
3957
|
for (const dir of plan.newDirectories) {
|
|
3743
3958
|
fs18.mkdirSync(dir, { recursive: true });
|
|
3744
|
-
console.log(
|
|
3959
|
+
console.log(chalk46.green(` Created ${path23.relative(process.cwd(), dir)}/`));
|
|
3745
3960
|
}
|
|
3746
3961
|
for (const move of plan.moves) {
|
|
3747
3962
|
const targetDir = path23.dirname(move.to);
|
|
@@ -3750,7 +3965,7 @@ function executePlan(plan) {
|
|
|
3750
3965
|
}
|
|
3751
3966
|
fs18.renameSync(move.from, move.to);
|
|
3752
3967
|
console.log(
|
|
3753
|
-
|
|
3968
|
+
chalk46.white(
|
|
3754
3969
|
` Moved ${path23.relative(process.cwd(), move.from)} \u2192 ${path23.relative(process.cwd(), move.to)}`
|
|
3755
3970
|
)
|
|
3756
3971
|
);
|
|
@@ -3765,7 +3980,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
3765
3980
|
if (entries.length === 0) {
|
|
3766
3981
|
fs18.rmdirSync(dir);
|
|
3767
3982
|
console.log(
|
|
3768
|
-
|
|
3983
|
+
chalk46.dim(
|
|
3769
3984
|
` Removed empty directory ${path23.relative(process.cwd(), dir)}`
|
|
3770
3985
|
)
|
|
3771
3986
|
);
|
|
@@ -3896,22 +4111,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
3896
4111
|
const targetPattern = pattern2 ?? "src";
|
|
3897
4112
|
const files = findSourceFiles2(targetPattern);
|
|
3898
4113
|
if (files.length === 0) {
|
|
3899
|
-
console.log(
|
|
4114
|
+
console.log(chalk47.yellow("No files found matching pattern"));
|
|
3900
4115
|
return;
|
|
3901
4116
|
}
|
|
3902
4117
|
const tsConfigPath = path26.resolve("tsconfig.json");
|
|
3903
4118
|
const plan = buildPlan(files, tsConfigPath);
|
|
3904
4119
|
if (plan.moves.length === 0) {
|
|
3905
|
-
console.log(
|
|
4120
|
+
console.log(chalk47.green("No restructuring needed"));
|
|
3906
4121
|
return;
|
|
3907
4122
|
}
|
|
3908
4123
|
displayPlan(plan);
|
|
3909
4124
|
if (options2.apply) {
|
|
3910
|
-
console.log(
|
|
4125
|
+
console.log(chalk47.bold("\nApplying changes..."));
|
|
3911
4126
|
executePlan(plan);
|
|
3912
|
-
console.log(
|
|
4127
|
+
console.log(chalk47.green("\nRestructuring complete"));
|
|
3913
4128
|
} else {
|
|
3914
|
-
console.log(
|
|
4129
|
+
console.log(chalk47.dim("\nDry run. Use --apply to execute."));
|
|
3915
4130
|
}
|
|
3916
4131
|
}
|
|
3917
4132
|
|
|
@@ -3934,8 +4149,8 @@ function registerRefactor(program2) {
|
|
|
3934
4149
|
}
|
|
3935
4150
|
|
|
3936
4151
|
// src/commands/transcript/shared.ts
|
|
3937
|
-
import { existsSync as
|
|
3938
|
-
import { basename as basename4, join as
|
|
4152
|
+
import { existsSync as existsSync18, readdirSync as readdirSync2, statSync } from "fs";
|
|
4153
|
+
import { basename as basename4, join as join14, relative } from "path";
|
|
3939
4154
|
import * as readline2 from "readline";
|
|
3940
4155
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
3941
4156
|
function getDatePrefix(daysOffset = 0) {
|
|
@@ -3950,10 +4165,10 @@ function isValidDatePrefix(filename) {
|
|
|
3950
4165
|
return DATE_PREFIX_REGEX.test(filename);
|
|
3951
4166
|
}
|
|
3952
4167
|
function collectFiles(dir, extension) {
|
|
3953
|
-
if (!
|
|
4168
|
+
if (!existsSync18(dir)) return [];
|
|
3954
4169
|
const results = [];
|
|
3955
4170
|
for (const entry of readdirSync2(dir)) {
|
|
3956
|
-
const fullPath =
|
|
4171
|
+
const fullPath = join14(dir, entry);
|
|
3957
4172
|
if (statSync(fullPath).isDirectory()) {
|
|
3958
4173
|
results.push(...collectFiles(fullPath, extension));
|
|
3959
4174
|
} else if (entry.endsWith(extension)) {
|
|
@@ -4047,14 +4262,14 @@ async function configure() {
|
|
|
4047
4262
|
}
|
|
4048
4263
|
|
|
4049
4264
|
// src/commands/transcript/format/index.ts
|
|
4050
|
-
import { existsSync as
|
|
4265
|
+
import { existsSync as existsSync20 } from "fs";
|
|
4051
4266
|
|
|
4052
4267
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
4053
|
-
import { dirname as dirname12, join as
|
|
4268
|
+
import { dirname as dirname12, join as join16 } from "path";
|
|
4054
4269
|
|
|
4055
4270
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
4056
4271
|
import { renameSync } from "fs";
|
|
4057
|
-
import { join as
|
|
4272
|
+
import { join as join15 } from "path";
|
|
4058
4273
|
async function resolveDate(rl, choice) {
|
|
4059
4274
|
if (choice === "1") return getDatePrefix(0);
|
|
4060
4275
|
if (choice === "2") return getDatePrefix(-1);
|
|
@@ -4069,7 +4284,7 @@ async function resolveDate(rl, choice) {
|
|
|
4069
4284
|
}
|
|
4070
4285
|
function renameWithPrefix(vttDir, vttFile, prefix) {
|
|
4071
4286
|
const newFilename = `${prefix}.${vttFile}`;
|
|
4072
|
-
renameSync(
|
|
4287
|
+
renameSync(join15(vttDir, vttFile), join15(vttDir, newFilename));
|
|
4073
4288
|
console.log(`Renamed to: ${newFilename}`);
|
|
4074
4289
|
return newFilename;
|
|
4075
4290
|
}
|
|
@@ -4103,12 +4318,12 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
4103
4318
|
const vttFileDir = dirname12(vttFile.absolutePath);
|
|
4104
4319
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
4105
4320
|
if (newFilename) {
|
|
4106
|
-
const newRelativePath =
|
|
4321
|
+
const newRelativePath = join16(
|
|
4107
4322
|
dirname12(vttFile.relativePath),
|
|
4108
4323
|
newFilename
|
|
4109
4324
|
);
|
|
4110
4325
|
vttFiles[i] = {
|
|
4111
|
-
absolutePath:
|
|
4326
|
+
absolutePath: join16(vttFileDir, newFilename),
|
|
4112
4327
|
relativePath: newRelativePath,
|
|
4113
4328
|
filename: newFilename
|
|
4114
4329
|
};
|
|
@@ -4121,8 +4336,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
4121
4336
|
}
|
|
4122
4337
|
|
|
4123
4338
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
4124
|
-
import { existsSync as
|
|
4125
|
-
import { basename as basename5, dirname as dirname13, join as
|
|
4339
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync15 } from "fs";
|
|
4340
|
+
import { basename as basename5, dirname as dirname13, join as join17 } from "path";
|
|
4126
4341
|
|
|
4127
4342
|
// src/commands/transcript/cleanText.ts
|
|
4128
4343
|
function cleanText(text) {
|
|
@@ -4262,10 +4477,10 @@ function extractSpeaker(fullText) {
|
|
|
4262
4477
|
function isTextLine(line) {
|
|
4263
4478
|
return !!line.trim() && !line.includes("-->");
|
|
4264
4479
|
}
|
|
4265
|
-
function scanTextLines(lines,
|
|
4266
|
-
let i =
|
|
4480
|
+
function scanTextLines(lines, start2) {
|
|
4481
|
+
let i = start2;
|
|
4267
4482
|
while (i < lines.length && isTextLine(lines[i])) i++;
|
|
4268
|
-
return { texts: lines.slice(
|
|
4483
|
+
return { texts: lines.slice(start2, i).map((l) => l.trim()), end: i };
|
|
4269
4484
|
}
|
|
4270
4485
|
function collectTextLines(lines, startIndex) {
|
|
4271
4486
|
const { texts, end } = scanTextLines(lines, startIndex);
|
|
@@ -4332,21 +4547,21 @@ function toMdFilename(vttFilename) {
|
|
|
4332
4547
|
return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
|
|
4333
4548
|
}
|
|
4334
4549
|
function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
4335
|
-
return relativeDir === "." ? transcriptsDir :
|
|
4550
|
+
return relativeDir === "." ? transcriptsDir : join17(transcriptsDir, relativeDir);
|
|
4336
4551
|
}
|
|
4337
4552
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
4338
4553
|
const mdFile = toMdFilename(vttFile.filename);
|
|
4339
4554
|
const relativeDir = dirname13(vttFile.relativePath);
|
|
4340
4555
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
4341
|
-
const outputPath =
|
|
4556
|
+
const outputPath = join17(outputDir, mdFile);
|
|
4342
4557
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
4343
4558
|
}
|
|
4344
4559
|
function logSkipped(relativeDir, mdFile) {
|
|
4345
|
-
console.log(`Skipping (already exists): ${
|
|
4560
|
+
console.log(`Skipping (already exists): ${join17(relativeDir, mdFile)}`);
|
|
4346
4561
|
return "skipped";
|
|
4347
4562
|
}
|
|
4348
4563
|
function ensureDirectory(dir, label) {
|
|
4349
|
-
if (!
|
|
4564
|
+
if (!existsSync19(dir)) {
|
|
4350
4565
|
mkdirSync5(dir, { recursive: true });
|
|
4351
4566
|
console.log(`Created ${label}: ${dir}`);
|
|
4352
4567
|
}
|
|
@@ -4369,10 +4584,10 @@ function logReduction(cueCount, messageCount) {
|
|
|
4369
4584
|
}
|
|
4370
4585
|
function readAndParseCues(inputPath) {
|
|
4371
4586
|
console.log(`Reading: ${inputPath}`);
|
|
4372
|
-
return processCues(
|
|
4587
|
+
return processCues(readFileSync13(inputPath, "utf-8"));
|
|
4373
4588
|
}
|
|
4374
4589
|
function writeFormatted(outputPath, content) {
|
|
4375
|
-
|
|
4590
|
+
writeFileSync15(outputPath, content, "utf-8");
|
|
4376
4591
|
console.log(`Written: ${outputPath}`);
|
|
4377
4592
|
}
|
|
4378
4593
|
function convertVttToMarkdown(inputPath, outputPath) {
|
|
@@ -4382,7 +4597,7 @@ function convertVttToMarkdown(inputPath, outputPath) {
|
|
|
4382
4597
|
logReduction(cues.length, chatMessages.length);
|
|
4383
4598
|
}
|
|
4384
4599
|
function tryProcessVtt(vttFile, paths) {
|
|
4385
|
-
if (
|
|
4600
|
+
if (existsSync19(paths.outputPath))
|
|
4386
4601
|
return logSkipped(paths.relativeDir, paths.mdFile);
|
|
4387
4602
|
convertVttToMarkdown(vttFile.absolutePath, paths.outputPath);
|
|
4388
4603
|
return "processed";
|
|
@@ -4408,7 +4623,7 @@ function processAllFiles(vttFiles, transcriptsDir) {
|
|
|
4408
4623
|
logSummary(counts);
|
|
4409
4624
|
}
|
|
4410
4625
|
function requireVttDir(vttDir) {
|
|
4411
|
-
if (!
|
|
4626
|
+
if (!existsSync20(vttDir)) {
|
|
4412
4627
|
console.error(`VTT directory not found: ${vttDir}`);
|
|
4413
4628
|
process.exit(1);
|
|
4414
4629
|
}
|
|
@@ -4440,28 +4655,28 @@ async function format() {
|
|
|
4440
4655
|
}
|
|
4441
4656
|
|
|
4442
4657
|
// src/commands/transcript/summarise/index.ts
|
|
4443
|
-
import { existsSync as
|
|
4444
|
-
import { basename as basename6, dirname as dirname15, join as
|
|
4658
|
+
import { existsSync as existsSync22 } from "fs";
|
|
4659
|
+
import { basename as basename6, dirname as dirname15, join as join19, relative as relative2 } from "path";
|
|
4445
4660
|
|
|
4446
4661
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
4447
4662
|
import {
|
|
4448
|
-
existsSync as
|
|
4663
|
+
existsSync as existsSync21,
|
|
4449
4664
|
mkdirSync as mkdirSync6,
|
|
4450
|
-
readFileSync as
|
|
4665
|
+
readFileSync as readFileSync14,
|
|
4451
4666
|
renameSync as renameSync2,
|
|
4452
4667
|
rmSync
|
|
4453
4668
|
} from "fs";
|
|
4454
|
-
import { dirname as dirname14, join as
|
|
4669
|
+
import { dirname as dirname14, join as join18 } from "path";
|
|
4455
4670
|
|
|
4456
4671
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
4457
|
-
import
|
|
4672
|
+
import chalk48 from "chalk";
|
|
4458
4673
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
4459
4674
|
function validateStagedContent(filename, content) {
|
|
4460
4675
|
const firstLine = content.split("\n")[0];
|
|
4461
4676
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
4462
4677
|
if (!match) {
|
|
4463
4678
|
console.error(
|
|
4464
|
-
|
|
4679
|
+
chalk48.red(
|
|
4465
4680
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
4466
4681
|
)
|
|
4467
4682
|
);
|
|
@@ -4470,7 +4685,7 @@ function validateStagedContent(filename, content) {
|
|
|
4470
4685
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
4471
4686
|
if (!contentAfterLink) {
|
|
4472
4687
|
console.error(
|
|
4473
|
-
|
|
4688
|
+
chalk48.red(
|
|
4474
4689
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
4475
4690
|
)
|
|
4476
4691
|
);
|
|
@@ -4480,9 +4695,9 @@ function validateStagedContent(filename, content) {
|
|
|
4480
4695
|
}
|
|
4481
4696
|
|
|
4482
4697
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
4483
|
-
var STAGING_DIR =
|
|
4698
|
+
var STAGING_DIR = join18(process.cwd(), ".assist", "transcript");
|
|
4484
4699
|
function processStagedFile() {
|
|
4485
|
-
if (!
|
|
4700
|
+
if (!existsSync21(STAGING_DIR)) {
|
|
4486
4701
|
return false;
|
|
4487
4702
|
}
|
|
4488
4703
|
const stagedFiles = findMdFilesRecursive(STAGING_DIR);
|
|
@@ -4491,7 +4706,7 @@ function processStagedFile() {
|
|
|
4491
4706
|
}
|
|
4492
4707
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
4493
4708
|
const stagedFile = stagedFiles[0];
|
|
4494
|
-
const content =
|
|
4709
|
+
const content = readFileSync14(stagedFile.absolutePath, "utf-8");
|
|
4495
4710
|
validateStagedContent(stagedFile.filename, content);
|
|
4496
4711
|
const stagedBaseName = getTranscriptBaseName(stagedFile.filename);
|
|
4497
4712
|
const transcriptFiles = findMdFilesRecursive(transcriptsDir);
|
|
@@ -4504,9 +4719,9 @@ function processStagedFile() {
|
|
|
4504
4719
|
);
|
|
4505
4720
|
process.exit(1);
|
|
4506
4721
|
}
|
|
4507
|
-
const destPath =
|
|
4722
|
+
const destPath = join18(summaryDir, matchingTranscript.relativePath);
|
|
4508
4723
|
const destDir = dirname14(destPath);
|
|
4509
|
-
if (!
|
|
4724
|
+
if (!existsSync21(destDir)) {
|
|
4510
4725
|
mkdirSync6(destDir, { recursive: true });
|
|
4511
4726
|
}
|
|
4512
4727
|
renameSync2(stagedFile.absolutePath, destPath);
|
|
@@ -4520,7 +4735,7 @@ function processStagedFile() {
|
|
|
4520
4735
|
// src/commands/transcript/summarise/index.ts
|
|
4521
4736
|
function buildRelativeKey(relativePath, baseName) {
|
|
4522
4737
|
const relDir = dirname15(relativePath);
|
|
4523
|
-
return relDir === "." ? baseName :
|
|
4738
|
+
return relDir === "." ? baseName : join19(relDir, baseName);
|
|
4524
4739
|
}
|
|
4525
4740
|
function buildSummaryIndex(summaryDir) {
|
|
4526
4741
|
const summaryFiles = findMdFilesRecursive(summaryDir);
|
|
@@ -4533,7 +4748,7 @@ function buildSummaryIndex(summaryDir) {
|
|
|
4533
4748
|
function summarise() {
|
|
4534
4749
|
processStagedFile();
|
|
4535
4750
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
4536
|
-
if (!
|
|
4751
|
+
if (!existsSync22(transcriptsDir)) {
|
|
4537
4752
|
console.log("No transcripts directory found.");
|
|
4538
4753
|
return;
|
|
4539
4754
|
}
|
|
@@ -4554,8 +4769,8 @@ function summarise() {
|
|
|
4554
4769
|
}
|
|
4555
4770
|
const next2 = missing[0];
|
|
4556
4771
|
const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
|
|
4557
|
-
const outputPath =
|
|
4558
|
-
const summaryFileDir =
|
|
4772
|
+
const outputPath = join19(STAGING_DIR, outputFilename);
|
|
4773
|
+
const summaryFileDir = join19(summaryDir, dirname15(next2.relativePath));
|
|
4559
4774
|
const relativeTranscriptPath = encodeURI(
|
|
4560
4775
|
relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
|
|
4561
4776
|
);
|
|
@@ -4642,7 +4857,7 @@ function saveNewRunConfig(name, command, args) {
|
|
|
4642
4857
|
runList.push(buildRunEntry(name, command, args));
|
|
4643
4858
|
saveConfig(config);
|
|
4644
4859
|
}
|
|
4645
|
-
function
|
|
4860
|
+
function add2() {
|
|
4646
4861
|
const { name, command, args } = requireParsedArgs();
|
|
4647
4862
|
saveNewRunConfig(name, command, args);
|
|
4648
4863
|
console.log(
|
|
@@ -4723,7 +4938,7 @@ import { fileURLToPath as fileURLToPath3 } from "url";
|
|
|
4723
4938
|
// src/commands/sync/syncClaudeMd.ts
|
|
4724
4939
|
import * as fs21 from "fs";
|
|
4725
4940
|
import * as path27 from "path";
|
|
4726
|
-
import
|
|
4941
|
+
import chalk49 from "chalk";
|
|
4727
4942
|
async function syncClaudeMd(claudeDir, targetBase) {
|
|
4728
4943
|
const source = path27.join(claudeDir, "CLAUDE.md");
|
|
4729
4944
|
const target = path27.join(targetBase, "CLAUDE.md");
|
|
@@ -4732,12 +4947,12 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
4732
4947
|
const targetContent = fs21.readFileSync(target, "utf-8");
|
|
4733
4948
|
if (sourceContent !== targetContent) {
|
|
4734
4949
|
console.log(
|
|
4735
|
-
|
|
4950
|
+
chalk49.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
4736
4951
|
);
|
|
4737
4952
|
console.log();
|
|
4738
4953
|
printDiff(targetContent, sourceContent);
|
|
4739
4954
|
const confirm = await promptConfirm(
|
|
4740
|
-
|
|
4955
|
+
chalk49.red("Overwrite existing CLAUDE.md?"),
|
|
4741
4956
|
false
|
|
4742
4957
|
);
|
|
4743
4958
|
if (!confirm) {
|
|
@@ -4753,7 +4968,7 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
4753
4968
|
// src/commands/sync/syncSettings.ts
|
|
4754
4969
|
import * as fs22 from "fs";
|
|
4755
4970
|
import * as path28 from "path";
|
|
4756
|
-
import
|
|
4971
|
+
import chalk50 from "chalk";
|
|
4757
4972
|
async function syncSettings(claudeDir, targetBase) {
|
|
4758
4973
|
const source = path28.join(claudeDir, "settings.json");
|
|
4759
4974
|
const target = path28.join(targetBase, "settings.json");
|
|
@@ -4764,12 +4979,12 @@ async function syncSettings(claudeDir, targetBase) {
|
|
|
4764
4979
|
const normalizedTarget = JSON.stringify(JSON.parse(targetContent), null, 2);
|
|
4765
4980
|
if (normalizedSource !== normalizedTarget) {
|
|
4766
4981
|
console.log(
|
|
4767
|
-
|
|
4982
|
+
chalk50.yellow("\n\u26A0\uFE0F Warning: settings.json differs from existing file")
|
|
4768
4983
|
);
|
|
4769
4984
|
console.log();
|
|
4770
4985
|
printDiff(targetContent, sourceContent);
|
|
4771
4986
|
const confirm = await promptConfirm(
|
|
4772
|
-
|
|
4987
|
+
chalk50.red("Overwrite existing settings.json?"),
|
|
4773
4988
|
false
|
|
4774
4989
|
);
|
|
4775
4990
|
if (!confirm) {
|
|
@@ -4812,7 +5027,7 @@ program.command("init").description("Initialize VS Code and verify configuration
|
|
|
4812
5027
|
program.command("commit <message>").description("Create a git commit with validation").action(commit);
|
|
4813
5028
|
program.command("update").description("Update claude-code to the latest version").action(() => {
|
|
4814
5029
|
console.log("Updating claude-code...");
|
|
4815
|
-
|
|
5030
|
+
execSync23("npm install -g @anthropic-ai/claude-code", { stdio: "inherit" });
|
|
4816
5031
|
});
|
|
4817
5032
|
var configCommand = program.command("config").description("View and modify assist.yml configuration");
|
|
4818
5033
|
configCommand.command("set <key> <value>").description("Set a config value (e.g. commit.push true)").action(configSet);
|
|
@@ -4821,7 +5036,7 @@ configCommand.command("list").description("List all config values").action(confi
|
|
|
4821
5036
|
var runCommand = program.command("run").description("Run a configured command from assist.yml").argument("<name>", "Name of the configured command").argument("[args...]", "Arguments to pass to the command").allowUnknownOption().action((name, args) => {
|
|
4822
5037
|
run2(name, args);
|
|
4823
5038
|
});
|
|
4824
|
-
runCommand.command("add").description("Add a new run configuration to assist.yml").allowUnknownOption().allowExcessArguments().action(() =>
|
|
5039
|
+
runCommand.command("add").description("Add a new run configuration to assist.yml").allowUnknownOption().allowExcessArguments().action(() => add2());
|
|
4825
5040
|
registerNew(program);
|
|
4826
5041
|
var lintCommand = program.command("lint").description("Run lint checks for conventions not enforced by biomejs").action(lint);
|
|
4827
5042
|
lintCommand.command("init").description("Initialize Biome with standard linter config").action(init);
|
|
@@ -4832,6 +5047,7 @@ program.command("notify").description(
|
|
|
4832
5047
|
"Show notification from Claude Code hook (reads JSON from stdin)"
|
|
4833
5048
|
).action(notify);
|
|
4834
5049
|
registerPrs(program);
|
|
5050
|
+
registerBacklog(program);
|
|
4835
5051
|
registerVerify(program);
|
|
4836
5052
|
registerRefactor(program);
|
|
4837
5053
|
registerDevlog(program);
|