@staff0rd/assist 0.179.0 → 0.180.1
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 +1 -0
- package/allowed.cli-reads +1 -0
- package/dist/allowed.cli-reads +1 -0
- package/dist/index.js +515 -408
- package/package.json +4 -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.180.1",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -39,6 +39,8 @@ var package_default = {
|
|
|
39
39
|
},
|
|
40
40
|
dependencies: {
|
|
41
41
|
"better-sqlite3": "^12.8.0",
|
|
42
|
+
blessed: "^0.1.81",
|
|
43
|
+
"blessed-contrib": "^4.11.0",
|
|
42
44
|
chalk: "^5.6.2",
|
|
43
45
|
commander: "^14.0.2",
|
|
44
46
|
diff: "^8.0.2",
|
|
@@ -61,6 +63,7 @@ var package_default = {
|
|
|
61
63
|
"@semantic-release/exec": "^7.1.0",
|
|
62
64
|
"@semantic-release/git": "^10.0.1",
|
|
63
65
|
"@types/better-sqlite3": "^7.6.13",
|
|
66
|
+
"@types/blessed": "^0.1.27",
|
|
64
67
|
"@types/node": "^24.10.1",
|
|
65
68
|
"@types/node-notifier": "^8.0.5",
|
|
66
69
|
"@types/react": "^19.2.14",
|
|
@@ -1829,155 +1832,6 @@ function commit(args) {
|
|
|
1829
1832
|
execCommit(files, message, config);
|
|
1830
1833
|
}
|
|
1831
1834
|
|
|
1832
|
-
// src/commands/config/index.ts
|
|
1833
|
-
import chalk19 from "chalk";
|
|
1834
|
-
import { stringify as stringifyYaml2 } from "yaml";
|
|
1835
|
-
|
|
1836
|
-
// src/commands/config/setNestedValue.ts
|
|
1837
|
-
function isPlainObject(val) {
|
|
1838
|
-
return val !== null && typeof val === "object" && !Array.isArray(val);
|
|
1839
|
-
}
|
|
1840
|
-
function isNumericKey(key) {
|
|
1841
|
-
return /^\d+$/.test(key);
|
|
1842
|
-
}
|
|
1843
|
-
function resolveKey(key) {
|
|
1844
|
-
return isNumericKey(key) ? Number.parseInt(key, 10) : key;
|
|
1845
|
-
}
|
|
1846
|
-
function getItem(container, key) {
|
|
1847
|
-
if (Array.isArray(container)) return container[key];
|
|
1848
|
-
return container[key];
|
|
1849
|
-
}
|
|
1850
|
-
function setItem(container, key, value) {
|
|
1851
|
-
if (Array.isArray(container)) container[key] = value;
|
|
1852
|
-
else container[key] = value;
|
|
1853
|
-
}
|
|
1854
|
-
function ensureArray(container, key) {
|
|
1855
|
-
const existing = getItem(container, key);
|
|
1856
|
-
const arr = Array.isArray(existing) ? [...existing] : [];
|
|
1857
|
-
setItem(container, key, arr);
|
|
1858
|
-
return arr;
|
|
1859
|
-
}
|
|
1860
|
-
function ensureObject(container, key) {
|
|
1861
|
-
const existing = getItem(container, key);
|
|
1862
|
-
const obj = isPlainObject(existing) ? { ...existing } : {};
|
|
1863
|
-
setItem(container, key, obj);
|
|
1864
|
-
return obj;
|
|
1865
|
-
}
|
|
1866
|
-
function stepIntoNested(container, key, nextKey) {
|
|
1867
|
-
const resolved = resolveKey(key);
|
|
1868
|
-
if (nextKey !== void 0 && isNumericKey(nextKey)) {
|
|
1869
|
-
return ensureArray(container, resolved);
|
|
1870
|
-
}
|
|
1871
|
-
return ensureObject(container, resolved);
|
|
1872
|
-
}
|
|
1873
|
-
function setNestedValue(obj, path50, value) {
|
|
1874
|
-
const keys = path50.split(".");
|
|
1875
|
-
const result = { ...obj };
|
|
1876
|
-
let current = result;
|
|
1877
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
1878
|
-
current = stepIntoNested(current, keys[i], keys[i + 1]);
|
|
1879
|
-
}
|
|
1880
|
-
setItem(current, resolveKey(keys[keys.length - 1]), value);
|
|
1881
|
-
return result;
|
|
1882
|
-
}
|
|
1883
|
-
|
|
1884
|
-
// src/commands/config/index.ts
|
|
1885
|
-
function coerceValue(value) {
|
|
1886
|
-
if (value === "true") return true;
|
|
1887
|
-
if (value === "false") return false;
|
|
1888
|
-
return value;
|
|
1889
|
-
}
|
|
1890
|
-
function formatIssuePath(issue, key) {
|
|
1891
|
-
return issue.path.length > 0 ? issue.path.join(".") : key;
|
|
1892
|
-
}
|
|
1893
|
-
function printValidationErrors(issues, key) {
|
|
1894
|
-
for (const issue of issues) {
|
|
1895
|
-
console.error(
|
|
1896
|
-
chalk19.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
|
|
1897
|
-
);
|
|
1898
|
-
}
|
|
1899
|
-
}
|
|
1900
|
-
function exitValidationFailed(issues, key) {
|
|
1901
|
-
printValidationErrors(issues, key);
|
|
1902
|
-
process.exit(1);
|
|
1903
|
-
}
|
|
1904
|
-
function validateConfig(updated, key) {
|
|
1905
|
-
const result = assistConfigSchema.safeParse(updated);
|
|
1906
|
-
if (!result.success) return exitValidationFailed(result.error.issues, key);
|
|
1907
|
-
return updated;
|
|
1908
|
-
}
|
|
1909
|
-
var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
1910
|
-
function assertNotGlobalOnly(key, global) {
|
|
1911
|
-
if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
|
|
1912
|
-
console.error(
|
|
1913
|
-
chalk19.red(
|
|
1914
|
-
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
1915
|
-
)
|
|
1916
|
-
);
|
|
1917
|
-
process.exit(1);
|
|
1918
|
-
}
|
|
1919
|
-
}
|
|
1920
|
-
function applyConfigSet(key, coerced, global) {
|
|
1921
|
-
assertNotGlobalOnly(key, global);
|
|
1922
|
-
const raw = global ? loadGlobalConfigRaw() : loadProjectConfig();
|
|
1923
|
-
const updated = setNestedValue(raw, key, coerced);
|
|
1924
|
-
validateConfig(updated, key);
|
|
1925
|
-
if (global) {
|
|
1926
|
-
saveGlobalConfig(updated);
|
|
1927
|
-
} else {
|
|
1928
|
-
saveConfig(updated);
|
|
1929
|
-
}
|
|
1930
|
-
}
|
|
1931
|
-
function configSet(key, value, options2 = {}) {
|
|
1932
|
-
const coerced = coerceValue(value);
|
|
1933
|
-
applyConfigSet(key, coerced, options2.global ?? false);
|
|
1934
|
-
const target = options2.global ? "global" : "project";
|
|
1935
|
-
console.log(
|
|
1936
|
-
chalk19.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
|
|
1937
|
-
);
|
|
1938
|
-
}
|
|
1939
|
-
function configList() {
|
|
1940
|
-
const config = loadConfig();
|
|
1941
|
-
console.log(stringifyYaml2(config, { lineWidth: 0 }).trimEnd());
|
|
1942
|
-
}
|
|
1943
|
-
|
|
1944
|
-
// src/commands/config/configGet.ts
|
|
1945
|
-
import chalk20 from "chalk";
|
|
1946
|
-
|
|
1947
|
-
// src/commands/config/getNestedValue.ts
|
|
1948
|
-
function isTraversable(value) {
|
|
1949
|
-
return value !== null && value !== void 0 && typeof value === "object";
|
|
1950
|
-
}
|
|
1951
|
-
function stepInto(current, key) {
|
|
1952
|
-
return isTraversable(current) ? current[key] : void 0;
|
|
1953
|
-
}
|
|
1954
|
-
function getNestedValue(obj, path50) {
|
|
1955
|
-
let current = obj;
|
|
1956
|
-
for (const key of path50.split(".")) current = stepInto(current, key);
|
|
1957
|
-
return current;
|
|
1958
|
-
}
|
|
1959
|
-
|
|
1960
|
-
// src/commands/config/configGet.ts
|
|
1961
|
-
function configGet(key) {
|
|
1962
|
-
console.log(
|
|
1963
|
-
formatOutput(
|
|
1964
|
-
requireNestedValue(loadConfig(), key)
|
|
1965
|
-
)
|
|
1966
|
-
);
|
|
1967
|
-
}
|
|
1968
|
-
function formatOutput(value) {
|
|
1969
|
-
return typeof value === "object" && value !== null ? JSON.stringify(value, null, 2) : String(value);
|
|
1970
|
-
}
|
|
1971
|
-
function requireNestedValue(config, key) {
|
|
1972
|
-
const value = getNestedValue(config, key);
|
|
1973
|
-
if (value === void 0) return exitKeyNotSet(key);
|
|
1974
|
-
return value;
|
|
1975
|
-
}
|
|
1976
|
-
function exitKeyNotSet(key) {
|
|
1977
|
-
console.error(chalk20.red(`Key "${key}" is not set`));
|
|
1978
|
-
process.exit(1);
|
|
1979
|
-
}
|
|
1980
|
-
|
|
1981
1835
|
// src/commands/coverage.ts
|
|
1982
1836
|
import { execSync as execSync2 } from "child_process";
|
|
1983
1837
|
function coverage() {
|
|
@@ -1994,10 +1848,10 @@ function coverage() {
|
|
|
1994
1848
|
}
|
|
1995
1849
|
|
|
1996
1850
|
// src/commands/verify/init/index.ts
|
|
1997
|
-
import
|
|
1851
|
+
import chalk33 from "chalk";
|
|
1998
1852
|
|
|
1999
1853
|
// src/shared/promptMultiselect.ts
|
|
2000
|
-
import
|
|
1854
|
+
import chalk19 from "chalk";
|
|
2001
1855
|
import enquirer4 from "enquirer";
|
|
2002
1856
|
async function promptMultiselect(message, options2) {
|
|
2003
1857
|
const { selected } = await exitOnCancel(
|
|
@@ -2007,7 +1861,7 @@ async function promptMultiselect(message, options2) {
|
|
|
2007
1861
|
message,
|
|
2008
1862
|
choices: options2.map((opt) => ({
|
|
2009
1863
|
name: opt.value,
|
|
2010
|
-
message: `${opt.name} - ${
|
|
1864
|
+
message: `${opt.name} - ${chalk19.dim(opt.description)}`
|
|
2011
1865
|
})),
|
|
2012
1866
|
// @ts-expect-error - enquirer types don't include symbols but it's supported
|
|
2013
1867
|
symbols: {
|
|
@@ -2024,7 +1878,7 @@ async function promptMultiselect(message, options2) {
|
|
|
2024
1878
|
// src/shared/readPackageJson.ts
|
|
2025
1879
|
import * as fs from "fs";
|
|
2026
1880
|
import * as path from "path";
|
|
2027
|
-
import
|
|
1881
|
+
import chalk20 from "chalk";
|
|
2028
1882
|
function findPackageJson() {
|
|
2029
1883
|
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
2030
1884
|
if (fs.existsSync(packageJsonPath)) {
|
|
@@ -2038,7 +1892,7 @@ function readPackageJson(filePath) {
|
|
|
2038
1892
|
function requirePackageJson() {
|
|
2039
1893
|
const packageJsonPath = findPackageJson();
|
|
2040
1894
|
if (!packageJsonPath) {
|
|
2041
|
-
console.error(
|
|
1895
|
+
console.error(chalk20.red("No package.json found in current directory"));
|
|
2042
1896
|
process.exit(1);
|
|
2043
1897
|
}
|
|
2044
1898
|
const pkg = readPackageJson(packageJsonPath);
|
|
@@ -2069,7 +1923,7 @@ function findPackageJsonWithVerifyScripts(startDir) {
|
|
|
2069
1923
|
// src/commands/verify/installPackage.ts
|
|
2070
1924
|
import { execSync as execSync3 } from "child_process";
|
|
2071
1925
|
import { writeFileSync as writeFileSync6 } from "fs";
|
|
2072
|
-
import
|
|
1926
|
+
import chalk21 from "chalk";
|
|
2073
1927
|
function writePackageJson(filePath, pkg) {
|
|
2074
1928
|
writeFileSync6(filePath, `${JSON.stringify(pkg, null, 2)}
|
|
2075
1929
|
`);
|
|
@@ -2084,12 +1938,12 @@ function addScript(pkg, name, command) {
|
|
|
2084
1938
|
};
|
|
2085
1939
|
}
|
|
2086
1940
|
function installPackage(name, cwd) {
|
|
2087
|
-
console.log(
|
|
1941
|
+
console.log(chalk21.dim(`Installing ${name}...`));
|
|
2088
1942
|
try {
|
|
2089
1943
|
execSync3(`npm install -D ${name}`, { stdio: "inherit", cwd });
|
|
2090
1944
|
return true;
|
|
2091
1945
|
} catch {
|
|
2092
|
-
console.error(
|
|
1946
|
+
console.error(chalk21.red(`Failed to install ${name}`));
|
|
2093
1947
|
return false;
|
|
2094
1948
|
}
|
|
2095
1949
|
}
|
|
@@ -2136,9 +1990,9 @@ var expectedScripts = {
|
|
|
2136
1990
|
};
|
|
2137
1991
|
|
|
2138
1992
|
// src/commands/verify/setup/setupBuild.ts
|
|
2139
|
-
import
|
|
1993
|
+
import chalk22 from "chalk";
|
|
2140
1994
|
async function setupBuild(_packageJsonPath, writer, hasVite, hasTypescript) {
|
|
2141
|
-
console.log(
|
|
1995
|
+
console.log(chalk22.blue("\nSetting up build verification..."));
|
|
2142
1996
|
let command;
|
|
2143
1997
|
if (hasVite && hasTypescript) {
|
|
2144
1998
|
command = "tsc -b && vite build --logLevel error";
|
|
@@ -2147,21 +2001,21 @@ async function setupBuild(_packageJsonPath, writer, hasVite, hasTypescript) {
|
|
|
2147
2001
|
} else {
|
|
2148
2002
|
command = "npm run build";
|
|
2149
2003
|
}
|
|
2150
|
-
console.log(
|
|
2004
|
+
console.log(chalk22.dim(`Using: ${command}`));
|
|
2151
2005
|
writer("verify:build", command);
|
|
2152
2006
|
}
|
|
2153
2007
|
async function setupTypecheck(_packageJsonPath, writer) {
|
|
2154
|
-
console.log(
|
|
2008
|
+
console.log(chalk22.blue("\nSetting up typecheck verification..."));
|
|
2155
2009
|
const command = "tsc --noEmit";
|
|
2156
|
-
console.log(
|
|
2010
|
+
console.log(chalk22.dim(`Using: ${command}`));
|
|
2157
2011
|
writer("verify:typecheck", command);
|
|
2158
2012
|
}
|
|
2159
2013
|
|
|
2160
2014
|
// src/commands/verify/setup/setupDuplicateCode.ts
|
|
2161
2015
|
import * as path2 from "path";
|
|
2162
|
-
import
|
|
2016
|
+
import chalk23 from "chalk";
|
|
2163
2017
|
async function setupDuplicateCode(packageJsonPath, writer) {
|
|
2164
|
-
console.log(
|
|
2018
|
+
console.log(chalk23.blue("\nSetting up jscpd..."));
|
|
2165
2019
|
const cwd = path2.dirname(packageJsonPath);
|
|
2166
2020
|
const pkg = readPackageJson(packageJsonPath);
|
|
2167
2021
|
const hasJscpd = !!pkg.dependencies?.jscpd || !!pkg.devDependencies?.jscpd;
|
|
@@ -2173,12 +2027,12 @@ async function setupDuplicateCode(packageJsonPath, writer) {
|
|
|
2173
2027
|
|
|
2174
2028
|
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
2175
2029
|
import * as path3 from "path";
|
|
2176
|
-
import
|
|
2030
|
+
import chalk25 from "chalk";
|
|
2177
2031
|
|
|
2178
2032
|
// src/commands/verify/addToKnipIgnoreBinaries.ts
|
|
2179
2033
|
import { existsSync as existsSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "fs";
|
|
2180
2034
|
import { join as join10 } from "path";
|
|
2181
|
-
import
|
|
2035
|
+
import chalk24 from "chalk";
|
|
2182
2036
|
function loadKnipConfig(knipJsonPath) {
|
|
2183
2037
|
if (existsSync11(knipJsonPath)) {
|
|
2184
2038
|
return JSON.parse(readFileSync10(knipJsonPath, "utf-8"));
|
|
@@ -2197,16 +2051,16 @@ function addToKnipIgnoreBinaries(cwd, binary) {
|
|
|
2197
2051
|
`${JSON.stringify(knipConfig, null, " ")}
|
|
2198
2052
|
`
|
|
2199
2053
|
);
|
|
2200
|
-
console.log(
|
|
2054
|
+
console.log(chalk24.dim(`Added '${binary}' to knip.json ignoreBinaries`));
|
|
2201
2055
|
}
|
|
2202
2056
|
} catch {
|
|
2203
|
-
console.log(
|
|
2057
|
+
console.log(chalk24.yellow("Warning: Could not update knip.json"));
|
|
2204
2058
|
}
|
|
2205
2059
|
}
|
|
2206
2060
|
|
|
2207
2061
|
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
2208
2062
|
async function setupHardcodedColors(packageJsonPath, writer, hasOpenColor) {
|
|
2209
|
-
console.log(
|
|
2063
|
+
console.log(chalk25.blue("\nSetting up hardcoded colors check..."));
|
|
2210
2064
|
const cwd = path3.dirname(packageJsonPath);
|
|
2211
2065
|
if (!hasOpenColor) {
|
|
2212
2066
|
installPackage("open-color", cwd);
|
|
@@ -2217,9 +2071,9 @@ async function setupHardcodedColors(packageJsonPath, writer, hasOpenColor) {
|
|
|
2217
2071
|
|
|
2218
2072
|
// src/commands/verify/setup/setupKnip.ts
|
|
2219
2073
|
import * as path4 from "path";
|
|
2220
|
-
import
|
|
2074
|
+
import chalk26 from "chalk";
|
|
2221
2075
|
async function setupKnip(packageJsonPath, writer) {
|
|
2222
|
-
console.log(
|
|
2076
|
+
console.log(chalk26.blue("\nSetting up knip..."));
|
|
2223
2077
|
const cwd = path4.dirname(packageJsonPath);
|
|
2224
2078
|
const pkg = readPackageJson(packageJsonPath);
|
|
2225
2079
|
if (!pkg.devDependencies?.knip && !installPackage("knip", cwd)) {
|
|
@@ -2230,14 +2084,14 @@ async function setupKnip(packageJsonPath, writer) {
|
|
|
2230
2084
|
|
|
2231
2085
|
// src/commands/verify/setup/setupLint.ts
|
|
2232
2086
|
import * as path5 from "path";
|
|
2233
|
-
import
|
|
2087
|
+
import chalk29 from "chalk";
|
|
2234
2088
|
|
|
2235
2089
|
// src/commands/lint/init.ts
|
|
2236
2090
|
import { execSync as execSync5 } from "child_process";
|
|
2237
2091
|
import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "fs";
|
|
2238
2092
|
import { dirname as dirname7, join as join11 } from "path";
|
|
2239
2093
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2240
|
-
import
|
|
2094
|
+
import chalk28 from "chalk";
|
|
2241
2095
|
|
|
2242
2096
|
// src/shared/promptConfirm.ts
|
|
2243
2097
|
import enquirer5 from "enquirer";
|
|
@@ -2341,7 +2195,7 @@ function removeEslintScripts(scripts, options2) {
|
|
|
2341
2195
|
}
|
|
2342
2196
|
|
|
2343
2197
|
// src/utils/printDiff.ts
|
|
2344
|
-
import
|
|
2198
|
+
import chalk27 from "chalk";
|
|
2345
2199
|
import * as diff from "diff";
|
|
2346
2200
|
function normalizeJson(content) {
|
|
2347
2201
|
try {
|
|
@@ -2359,11 +2213,11 @@ function printDiff(oldContent, newContent) {
|
|
|
2359
2213
|
const lines = change.value.replace(/\n$/, "").split("\n");
|
|
2360
2214
|
for (const line of lines) {
|
|
2361
2215
|
if (change.added) {
|
|
2362
|
-
console.log(
|
|
2216
|
+
console.log(chalk27.green(`+ ${line}`));
|
|
2363
2217
|
} else if (change.removed) {
|
|
2364
|
-
console.log(
|
|
2218
|
+
console.log(chalk27.red(`- ${line}`));
|
|
2365
2219
|
} else {
|
|
2366
|
-
console.log(
|
|
2220
|
+
console.log(chalk27.dim(` ${line}`));
|
|
2367
2221
|
}
|
|
2368
2222
|
}
|
|
2369
2223
|
}
|
|
@@ -2397,10 +2251,10 @@ async function init() {
|
|
|
2397
2251
|
console.log("biome.json already has the correct linter config");
|
|
2398
2252
|
return;
|
|
2399
2253
|
}
|
|
2400
|
-
console.log(
|
|
2254
|
+
console.log(chalk28.yellow("\n\u26A0\uFE0F biome.json will be updated:"));
|
|
2401
2255
|
console.log();
|
|
2402
2256
|
printDiff(oldContent, newContent);
|
|
2403
|
-
const confirm = await promptConfirm(
|
|
2257
|
+
const confirm = await promptConfirm(chalk28.red("Update biome.json?"));
|
|
2404
2258
|
if (!confirm) {
|
|
2405
2259
|
console.log("Skipped biome.json update");
|
|
2406
2260
|
return;
|
|
@@ -2411,7 +2265,7 @@ async function init() {
|
|
|
2411
2265
|
|
|
2412
2266
|
// src/commands/verify/setup/setupLint.ts
|
|
2413
2267
|
async function setupLint(packageJsonPath, writer) {
|
|
2414
|
-
console.log(
|
|
2268
|
+
console.log(chalk29.blue("\nSetting up biome..."));
|
|
2415
2269
|
const cwd = path5.dirname(packageJsonPath);
|
|
2416
2270
|
const pkg = readPackageJson(packageJsonPath);
|
|
2417
2271
|
if (!pkg.devDependencies?.["@biomejs/biome"]) {
|
|
@@ -2425,9 +2279,9 @@ async function setupLint(packageJsonPath, writer) {
|
|
|
2425
2279
|
|
|
2426
2280
|
// src/commands/verify/setup/setupMadge.ts
|
|
2427
2281
|
import * as path6 from "path";
|
|
2428
|
-
import
|
|
2282
|
+
import chalk30 from "chalk";
|
|
2429
2283
|
async function setupMadge(packageJsonPath, writer) {
|
|
2430
|
-
console.log(
|
|
2284
|
+
console.log(chalk30.blue("\nSetting up madge..."));
|
|
2431
2285
|
const cwd = path6.dirname(packageJsonPath);
|
|
2432
2286
|
const pkg = readPackageJson(packageJsonPath);
|
|
2433
2287
|
const hasMadge = !!pkg.dependencies?.madge || !!pkg.devDependencies?.madge;
|
|
@@ -2439,18 +2293,18 @@ async function setupMadge(packageJsonPath, writer) {
|
|
|
2439
2293
|
|
|
2440
2294
|
// src/commands/verify/setup/setupMaintainability.ts
|
|
2441
2295
|
import * as path7 from "path";
|
|
2442
|
-
import
|
|
2296
|
+
import chalk31 from "chalk";
|
|
2443
2297
|
async function setupMaintainability(packageJsonPath, writer) {
|
|
2444
|
-
console.log(
|
|
2298
|
+
console.log(chalk31.blue("\nSetting up maintainability check..."));
|
|
2445
2299
|
addToKnipIgnoreBinaries(path7.dirname(packageJsonPath), "assist");
|
|
2446
2300
|
writer("verify:maintainability", expectedScripts["verify:maintainability"]);
|
|
2447
2301
|
}
|
|
2448
2302
|
|
|
2449
2303
|
// src/commands/verify/setup/setupTest.ts
|
|
2450
2304
|
import * as path8 from "path";
|
|
2451
|
-
import
|
|
2305
|
+
import chalk32 from "chalk";
|
|
2452
2306
|
async function setupTest(packageJsonPath, writer) {
|
|
2453
|
-
console.log(
|
|
2307
|
+
console.log(chalk32.blue("\nSetting up vitest..."));
|
|
2454
2308
|
const cwd = path8.dirname(packageJsonPath);
|
|
2455
2309
|
const pkg = readPackageJson(packageJsonPath);
|
|
2456
2310
|
if (!pkg.devDependencies?.vitest && !installPackage("vitest", cwd)) {
|
|
@@ -2619,25 +2473,25 @@ async function runSelectedSetups(selected, packageJsonPath, writer, handlers) {
|
|
|
2619
2473
|
for (const choice of selected) {
|
|
2620
2474
|
await handlers[choice]?.(packageJsonPath, writer);
|
|
2621
2475
|
}
|
|
2622
|
-
console.log(
|
|
2476
|
+
console.log(chalk33.green(`
|
|
2623
2477
|
Added ${selected.length} verify script(s):`));
|
|
2624
2478
|
for (const choice of selected) {
|
|
2625
|
-
console.log(
|
|
2479
|
+
console.log(chalk33.green(` - verify:${choice}`));
|
|
2626
2480
|
}
|
|
2627
|
-
console.log(
|
|
2481
|
+
console.log(chalk33.dim("\nRun 'assist verify' to run all verify scripts"));
|
|
2628
2482
|
}
|
|
2629
2483
|
async function promptForScripts(availableOptions) {
|
|
2630
2484
|
if (availableOptions.length === 0) {
|
|
2631
|
-
console.log(
|
|
2485
|
+
console.log(chalk33.green("All verify scripts are already configured!"));
|
|
2632
2486
|
return null;
|
|
2633
2487
|
}
|
|
2634
|
-
console.log(
|
|
2488
|
+
console.log(chalk33.bold("Available verify scripts to add:\n"));
|
|
2635
2489
|
const selected = await promptMultiselect(
|
|
2636
2490
|
"Select verify scripts to add:",
|
|
2637
2491
|
availableOptions
|
|
2638
2492
|
);
|
|
2639
2493
|
if (selected.length === 0) {
|
|
2640
|
-
console.log(
|
|
2494
|
+
console.log(chalk33.yellow("No scripts selected"));
|
|
2641
2495
|
return null;
|
|
2642
2496
|
}
|
|
2643
2497
|
return selected;
|
|
@@ -2657,17 +2511,17 @@ async function init2() {
|
|
|
2657
2511
|
}
|
|
2658
2512
|
|
|
2659
2513
|
// src/commands/vscode/init/index.ts
|
|
2660
|
-
import
|
|
2514
|
+
import chalk35 from "chalk";
|
|
2661
2515
|
|
|
2662
2516
|
// src/commands/vscode/init/createLaunchJson.ts
|
|
2663
2517
|
import * as fs2 from "fs";
|
|
2664
2518
|
import * as path9 from "path";
|
|
2665
|
-
import
|
|
2519
|
+
import chalk34 from "chalk";
|
|
2666
2520
|
function ensureVscodeFolder() {
|
|
2667
2521
|
const vscodeDir = path9.join(process.cwd(), ".vscode");
|
|
2668
2522
|
if (!fs2.existsSync(vscodeDir)) {
|
|
2669
2523
|
fs2.mkdirSync(vscodeDir);
|
|
2670
|
-
console.log(
|
|
2524
|
+
console.log(chalk34.dim("Created .vscode folder"));
|
|
2671
2525
|
}
|
|
2672
2526
|
}
|
|
2673
2527
|
function removeVscodeFromGitignore() {
|
|
@@ -2682,7 +2536,7 @@ function removeVscodeFromGitignore() {
|
|
|
2682
2536
|
);
|
|
2683
2537
|
if (filteredLines.length !== lines.length) {
|
|
2684
2538
|
fs2.writeFileSync(gitignorePath, filteredLines.join("\n"));
|
|
2685
|
-
console.log(
|
|
2539
|
+
console.log(chalk34.dim("Removed .vscode references from .gitignore"));
|
|
2686
2540
|
}
|
|
2687
2541
|
}
|
|
2688
2542
|
function createLaunchJson(type) {
|
|
@@ -2701,7 +2555,7 @@ function createLaunchJson(type) {
|
|
|
2701
2555
|
const launchPath = path9.join(process.cwd(), ".vscode", "launch.json");
|
|
2702
2556
|
fs2.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
|
|
2703
2557
|
`);
|
|
2704
|
-
console.log(
|
|
2558
|
+
console.log(chalk34.green("Created .vscode/launch.json"));
|
|
2705
2559
|
}
|
|
2706
2560
|
function createSettingsJson() {
|
|
2707
2561
|
const settings = {
|
|
@@ -2714,7 +2568,7 @@ function createSettingsJson() {
|
|
|
2714
2568
|
const settingsPath = path9.join(process.cwd(), ".vscode", "settings.json");
|
|
2715
2569
|
fs2.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
|
|
2716
2570
|
`);
|
|
2717
|
-
console.log(
|
|
2571
|
+
console.log(chalk34.green("Created .vscode/settings.json"));
|
|
2718
2572
|
}
|
|
2719
2573
|
function createExtensionsJson() {
|
|
2720
2574
|
const extensions = {
|
|
@@ -2726,7 +2580,7 @@ function createExtensionsJson() {
|
|
|
2726
2580
|
`${JSON.stringify(extensions, null, " ")}
|
|
2727
2581
|
`
|
|
2728
2582
|
);
|
|
2729
|
-
console.log(
|
|
2583
|
+
console.log(chalk34.green("Created .vscode/extensions.json"));
|
|
2730
2584
|
}
|
|
2731
2585
|
|
|
2732
2586
|
// src/commands/vscode/init/detectVscodeSetup.ts
|
|
@@ -2783,7 +2637,7 @@ function applySelections(selected, setup2) {
|
|
|
2783
2637
|
for (const choice of selected) handlers[choice]?.();
|
|
2784
2638
|
}
|
|
2785
2639
|
async function promptForOptions(options2) {
|
|
2786
|
-
console.log(
|
|
2640
|
+
console.log(chalk35.bold("Available VS Code configurations to add:\n"));
|
|
2787
2641
|
return promptMultiselect("Select configurations to add:", options2);
|
|
2788
2642
|
}
|
|
2789
2643
|
async function init3({ all = false } = {}) {
|
|
@@ -2791,17 +2645,17 @@ async function init3({ all = false } = {}) {
|
|
|
2791
2645
|
const setup2 = detectVscodeSetup(pkg);
|
|
2792
2646
|
const options2 = getAvailableOptions2(setup2);
|
|
2793
2647
|
if (options2.length === 0) {
|
|
2794
|
-
console.log(
|
|
2648
|
+
console.log(chalk35.green("VS Code configuration already exists!"));
|
|
2795
2649
|
return;
|
|
2796
2650
|
}
|
|
2797
2651
|
const selected = all ? options2.map((o) => o.value) : await promptForOptions(options2);
|
|
2798
2652
|
if (selected.length === 0) {
|
|
2799
|
-
console.log(
|
|
2653
|
+
console.log(chalk35.yellow("No configurations selected"));
|
|
2800
2654
|
return;
|
|
2801
2655
|
}
|
|
2802
2656
|
applySelections(selected, setup2);
|
|
2803
2657
|
console.log(
|
|
2804
|
-
|
|
2658
|
+
chalk35.green(`
|
|
2805
2659
|
Added ${selected.length} VS Code configuration(s)`)
|
|
2806
2660
|
);
|
|
2807
2661
|
}
|
|
@@ -2814,7 +2668,7 @@ async function init4() {
|
|
|
2814
2668
|
|
|
2815
2669
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
2816
2670
|
import path16 from "path";
|
|
2817
|
-
import
|
|
2671
|
+
import chalk37 from "chalk";
|
|
2818
2672
|
|
|
2819
2673
|
// src/commands/lint/lint/checkFileNames.ts
|
|
2820
2674
|
import fs5 from "fs";
|
|
@@ -2894,7 +2748,7 @@ function checkFileNames() {
|
|
|
2894
2748
|
}
|
|
2895
2749
|
|
|
2896
2750
|
// src/commands/lint/lint/fixFileNameViolations.ts
|
|
2897
|
-
import
|
|
2751
|
+
import chalk36 from "chalk";
|
|
2898
2752
|
|
|
2899
2753
|
// src/commands/lint/lint/applyMoves.ts
|
|
2900
2754
|
import fs6 from "fs";
|
|
@@ -2979,25 +2833,25 @@ function fixFileNameViolations(moves) {
|
|
|
2979
2833
|
const start3 = performance.now();
|
|
2980
2834
|
const project = createLintProject();
|
|
2981
2835
|
const cwd = process.cwd();
|
|
2982
|
-
applyMoves(project, moves, cwd, (line) => console.log(
|
|
2836
|
+
applyMoves(project, moves, cwd, (line) => console.log(chalk36.green(line)));
|
|
2983
2837
|
const ms = (performance.now() - start3).toFixed(0);
|
|
2984
|
-
console.log(
|
|
2838
|
+
console.log(chalk36.dim(` Done in ${ms}ms`));
|
|
2985
2839
|
}
|
|
2986
2840
|
|
|
2987
2841
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
2988
2842
|
function reportViolations(violations) {
|
|
2989
|
-
console.error(
|
|
2843
|
+
console.error(chalk37.red("\nFile name check failed:\n"));
|
|
2990
2844
|
console.error(
|
|
2991
|
-
|
|
2845
|
+
chalk37.red(
|
|
2992
2846
|
" Files without classes or React components should not start with a capital letter.\n"
|
|
2993
2847
|
)
|
|
2994
2848
|
);
|
|
2995
2849
|
for (const violation of violations) {
|
|
2996
|
-
console.error(
|
|
2997
|
-
console.error(
|
|
2850
|
+
console.error(chalk37.red(` ${violation.filePath}`));
|
|
2851
|
+
console.error(chalk37.gray(` Rename to: ${violation.suggestedName}
|
|
2998
2852
|
`));
|
|
2999
2853
|
}
|
|
3000
|
-
console.error(
|
|
2854
|
+
console.error(chalk37.dim(" Run with -f to auto-fix.\n"));
|
|
3001
2855
|
}
|
|
3002
2856
|
function runFileNameCheck(fix = false) {
|
|
3003
2857
|
const violations = checkFileNames();
|
|
@@ -3026,17 +2880,17 @@ function runFileNameCheck(fix = false) {
|
|
|
3026
2880
|
import fs8 from "fs";
|
|
3027
2881
|
|
|
3028
2882
|
// src/commands/lint/shared.ts
|
|
3029
|
-
import
|
|
2883
|
+
import chalk38 from "chalk";
|
|
3030
2884
|
function reportViolations2(violations, checkName, errorMessage, successMessage) {
|
|
3031
2885
|
if (violations.length > 0) {
|
|
3032
|
-
console.error(
|
|
2886
|
+
console.error(chalk38.red(`
|
|
3033
2887
|
${checkName} failed:
|
|
3034
2888
|
`));
|
|
3035
|
-
console.error(
|
|
2889
|
+
console.error(chalk38.red(` ${errorMessage}
|
|
3036
2890
|
`));
|
|
3037
2891
|
for (const violation of violations) {
|
|
3038
|
-
console.error(
|
|
3039
|
-
console.error(
|
|
2892
|
+
console.error(chalk38.red(` ${violation.filePath}:${violation.line}`));
|
|
2893
|
+
console.error(chalk38.gray(` ${violation.content}
|
|
3040
2894
|
`));
|
|
3041
2895
|
}
|
|
3042
2896
|
return false;
|
|
@@ -3516,14 +3370,14 @@ import { existsSync as existsSync18, readFileSync as readFileSync15, writeFileSy
|
|
|
3516
3370
|
|
|
3517
3371
|
// src/commands/deploy/init/index.ts
|
|
3518
3372
|
import { execSync as execSync12 } from "child_process";
|
|
3519
|
-
import
|
|
3373
|
+
import chalk40 from "chalk";
|
|
3520
3374
|
import enquirer6 from "enquirer";
|
|
3521
3375
|
|
|
3522
3376
|
// src/commands/deploy/init/updateWorkflow.ts
|
|
3523
3377
|
import { existsSync as existsSync17, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync13 } from "fs";
|
|
3524
3378
|
import { dirname as dirname13, join as join14 } from "path";
|
|
3525
3379
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3526
|
-
import
|
|
3380
|
+
import chalk39 from "chalk";
|
|
3527
3381
|
var WORKFLOW_PATH = ".github/workflows/build.yml";
|
|
3528
3382
|
var __dirname3 = dirname13(fileURLToPath3(import.meta.url));
|
|
3529
3383
|
function getExistingSiteId() {
|
|
@@ -3548,20 +3402,20 @@ async function updateWorkflow(siteId) {
|
|
|
3548
3402
|
if (existsSync17(WORKFLOW_PATH)) {
|
|
3549
3403
|
const oldContent = readFileSync14(WORKFLOW_PATH, "utf-8");
|
|
3550
3404
|
if (oldContent === newContent) {
|
|
3551
|
-
console.log(
|
|
3405
|
+
console.log(chalk39.green("build.yml is already up to date"));
|
|
3552
3406
|
return;
|
|
3553
3407
|
}
|
|
3554
|
-
console.log(
|
|
3408
|
+
console.log(chalk39.yellow("\nbuild.yml will be updated:"));
|
|
3555
3409
|
console.log();
|
|
3556
3410
|
printDiff(oldContent, newContent);
|
|
3557
|
-
const confirm = await promptConfirm(
|
|
3411
|
+
const confirm = await promptConfirm(chalk39.red("Update build.yml?"));
|
|
3558
3412
|
if (!confirm) {
|
|
3559
3413
|
console.log("Skipped build.yml update");
|
|
3560
3414
|
return;
|
|
3561
3415
|
}
|
|
3562
3416
|
}
|
|
3563
3417
|
writeFileSync13(WORKFLOW_PATH, newContent);
|
|
3564
|
-
console.log(
|
|
3418
|
+
console.log(chalk39.green(`
|
|
3565
3419
|
Created ${WORKFLOW_PATH}`));
|
|
3566
3420
|
}
|
|
3567
3421
|
|
|
@@ -3572,43 +3426,43 @@ async function ensureNetlifyCli() {
|
|
|
3572
3426
|
} catch (error) {
|
|
3573
3427
|
if (!(error instanceof Error) || !error.message.includes("command not found"))
|
|
3574
3428
|
throw error;
|
|
3575
|
-
console.error(
|
|
3429
|
+
console.error(chalk40.red("\nNetlify CLI is not installed.\n"));
|
|
3576
3430
|
const install = await promptConfirm("Would you like to install it now?");
|
|
3577
3431
|
if (!install) {
|
|
3578
3432
|
console.log(
|
|
3579
|
-
|
|
3433
|
+
chalk40.yellow(
|
|
3580
3434
|
"\nInstall it manually with: npm install -g netlify-cli\n"
|
|
3581
3435
|
)
|
|
3582
3436
|
);
|
|
3583
3437
|
process.exit(1);
|
|
3584
3438
|
}
|
|
3585
|
-
console.log(
|
|
3439
|
+
console.log(chalk40.dim("\nInstalling netlify-cli...\n"));
|
|
3586
3440
|
execSync12("npm install -g netlify-cli", { stdio: "inherit" });
|
|
3587
3441
|
console.log();
|
|
3588
3442
|
execSync12("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
3589
3443
|
}
|
|
3590
3444
|
}
|
|
3591
3445
|
function printSetupInstructions() {
|
|
3592
|
-
console.log(
|
|
3446
|
+
console.log(chalk40.bold("\nDeployment initialized successfully!"));
|
|
3593
3447
|
console.log(
|
|
3594
|
-
|
|
3448
|
+
chalk40.yellow("\nTo complete setup, create a personal access token at:")
|
|
3595
3449
|
);
|
|
3596
3450
|
console.log(
|
|
3597
|
-
|
|
3451
|
+
chalk40.cyan(
|
|
3598
3452
|
"https://app.netlify.com/user/applications#personal-access-tokens"
|
|
3599
3453
|
)
|
|
3600
3454
|
);
|
|
3601
3455
|
console.log(
|
|
3602
|
-
|
|
3456
|
+
chalk40.yellow(
|
|
3603
3457
|
"\nThen add it as NETLIFY_AUTH_TOKEN in your GitHub repository secrets."
|
|
3604
3458
|
)
|
|
3605
3459
|
);
|
|
3606
3460
|
}
|
|
3607
3461
|
async function init5() {
|
|
3608
|
-
console.log(
|
|
3462
|
+
console.log(chalk40.bold("Initializing Netlify deployment...\n"));
|
|
3609
3463
|
const existingSiteId = getExistingSiteId();
|
|
3610
3464
|
if (existingSiteId) {
|
|
3611
|
-
console.log(
|
|
3465
|
+
console.log(chalk40.dim(`Using existing site ID: ${existingSiteId}
|
|
3612
3466
|
`));
|
|
3613
3467
|
await updateWorkflow(existingSiteId);
|
|
3614
3468
|
return;
|
|
@@ -3786,28 +3640,126 @@ async function notify() {
|
|
|
3786
3640
|
console.log(`Notification sent: ${notification_type} for ${projectName}`);
|
|
3787
3641
|
}
|
|
3788
3642
|
|
|
3643
|
+
// src/commands/activity/activityChart.ts
|
|
3644
|
+
import blessed from "blessed";
|
|
3645
|
+
import contrib from "blessed-contrib";
|
|
3646
|
+
function activityChart(data) {
|
|
3647
|
+
const screen = blessed.screen({
|
|
3648
|
+
smartCSR: true,
|
|
3649
|
+
title: "Commit Activity"
|
|
3650
|
+
});
|
|
3651
|
+
const grid = new contrib.grid({ rows: 1, cols: 1, screen });
|
|
3652
|
+
const labels = data.map((d) => d.date.slice(5));
|
|
3653
|
+
const values = data.map((d) => d.count);
|
|
3654
|
+
const line = grid.set(0, 0, 1, 1, contrib.line, {
|
|
3655
|
+
label: " Commits per week (press q to close) ",
|
|
3656
|
+
showLegend: true,
|
|
3657
|
+
legend: { width: 12 },
|
|
3658
|
+
xLabelPadding: 3,
|
|
3659
|
+
xPadding: 5,
|
|
3660
|
+
wholeNumbersOnly: true
|
|
3661
|
+
});
|
|
3662
|
+
line.setData([
|
|
3663
|
+
{
|
|
3664
|
+
title: "Commits",
|
|
3665
|
+
x: labels,
|
|
3666
|
+
y: values,
|
|
3667
|
+
style: { line: "green" }
|
|
3668
|
+
}
|
|
3669
|
+
]);
|
|
3670
|
+
screen.key(["q", "C-c", "escape"], () => {
|
|
3671
|
+
screen.destroy();
|
|
3672
|
+
});
|
|
3673
|
+
screen.render();
|
|
3674
|
+
}
|
|
3675
|
+
|
|
3676
|
+
// src/commands/activity/fetchCommitsPerDay.ts
|
|
3677
|
+
import { execSync as execSync14 } from "child_process";
|
|
3678
|
+
function fetchContributions(from, to) {
|
|
3679
|
+
const query = `{ viewer { contributionsCollection(from: "${from}T00:00:00Z", to: "${to}T23:59:59Z") { contributionCalendar { weeks { contributionDays { date contributionCount } } } } } }`;
|
|
3680
|
+
const jq = ".data.viewer.contributionsCollection.contributionCalendar.weeks[].contributionDays[]";
|
|
3681
|
+
const raw = execSync14(`gh api graphql -f query='${query}' --jq '${jq}'`, {
|
|
3682
|
+
encoding: "utf-8"
|
|
3683
|
+
}).trim();
|
|
3684
|
+
if (!raw) return [];
|
|
3685
|
+
return raw.split("\n").map((line) => {
|
|
3686
|
+
const obj = JSON.parse(line);
|
|
3687
|
+
return { date: obj.date, count: obj.contributionCount };
|
|
3688
|
+
});
|
|
3689
|
+
}
|
|
3690
|
+
function fetchCommitsPerDay(since) {
|
|
3691
|
+
const start3 = new Date(since);
|
|
3692
|
+
const end = /* @__PURE__ */ new Date();
|
|
3693
|
+
const results = [];
|
|
3694
|
+
let cursor = new Date(start3);
|
|
3695
|
+
while (cursor <= end) {
|
|
3696
|
+
const yearEnd = new Date(cursor);
|
|
3697
|
+
yearEnd.setFullYear(yearEnd.getFullYear(), yearEnd.getMonth() + 12);
|
|
3698
|
+
yearEnd.setDate(yearEnd.getDate() - 1);
|
|
3699
|
+
const windowEnd = yearEnd > end ? end : yearEnd;
|
|
3700
|
+
const from = cursor.toISOString().slice(0, 10);
|
|
3701
|
+
const to = windowEnd.toISOString().slice(0, 10);
|
|
3702
|
+
results.push(...fetchContributions(from, to));
|
|
3703
|
+
cursor = new Date(windowEnd);
|
|
3704
|
+
cursor.setDate(cursor.getDate() + 1);
|
|
3705
|
+
}
|
|
3706
|
+
return results.filter(
|
|
3707
|
+
(d) => d.date >= since && d.date <= end.toISOString().slice(0, 10)
|
|
3708
|
+
);
|
|
3709
|
+
}
|
|
3710
|
+
|
|
3711
|
+
// src/commands/activity.ts
|
|
3712
|
+
async function activity(options2) {
|
|
3713
|
+
const since = options2.since ?? new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString().slice(0, 10);
|
|
3714
|
+
const data = fetchCommitsPerDay(since);
|
|
3715
|
+
if (data.length < 2) {
|
|
3716
|
+
console.log("Not enough data points to chart.");
|
|
3717
|
+
return;
|
|
3718
|
+
}
|
|
3719
|
+
const total = data.reduce((sum, d) => sum + d.count, 0);
|
|
3720
|
+
const activeDays = data.filter((d) => d.count > 0).length;
|
|
3721
|
+
console.log(`${total} commits across ${activeDays} active days.`);
|
|
3722
|
+
const weekly = /* @__PURE__ */ new Map();
|
|
3723
|
+
for (const { date, count } of data) {
|
|
3724
|
+
const d = new Date(date);
|
|
3725
|
+
d.setDate(d.getDate() - d.getDay());
|
|
3726
|
+
const weekStart = d.toISOString().slice(0, 10);
|
|
3727
|
+
weekly.set(weekStart, (weekly.get(weekStart) ?? 0) + count);
|
|
3728
|
+
}
|
|
3729
|
+
const weeklyData = [...weekly.entries()].map(([date, count]) => ({ date, count })).sort((a, b) => a.date.localeCompare(b.date));
|
|
3730
|
+
activityChart(weeklyData);
|
|
3731
|
+
}
|
|
3732
|
+
|
|
3733
|
+
// src/commands/registerActivity.ts
|
|
3734
|
+
function registerActivity(program2) {
|
|
3735
|
+
program2.command("activity").description("Chart GitHub commit activity per day").option(
|
|
3736
|
+
"--since <date>",
|
|
3737
|
+
"Start date (YYYY-MM-DD), defaults to 30 days ago"
|
|
3738
|
+
).action(activity);
|
|
3739
|
+
}
|
|
3740
|
+
|
|
3789
3741
|
// src/commands/backlog/comment/index.ts
|
|
3790
|
-
import
|
|
3742
|
+
import chalk41 from "chalk";
|
|
3791
3743
|
function comment(id, text) {
|
|
3792
3744
|
const result = loadAndFindItem(id);
|
|
3793
3745
|
if (!result) process.exit(1);
|
|
3794
3746
|
addComment(result.item, text);
|
|
3795
3747
|
saveBacklog(result.items);
|
|
3796
|
-
console.log(
|
|
3748
|
+
console.log(chalk41.green(`Comment added to item #${id}.`));
|
|
3797
3749
|
}
|
|
3798
3750
|
|
|
3799
3751
|
// src/commands/backlog/comments/index.ts
|
|
3800
|
-
import
|
|
3752
|
+
import chalk42 from "chalk";
|
|
3801
3753
|
function comments(id) {
|
|
3802
3754
|
const result = loadAndFindItem(id);
|
|
3803
3755
|
if (!result) process.exit(1);
|
|
3804
3756
|
const { item } = result;
|
|
3805
3757
|
const entries = item.comments ?? [];
|
|
3806
3758
|
if (entries.length === 0) {
|
|
3807
|
-
console.log(
|
|
3759
|
+
console.log(chalk42.dim(`No comments on item #${id}.`));
|
|
3808
3760
|
return;
|
|
3809
3761
|
}
|
|
3810
|
-
console.log(
|
|
3762
|
+
console.log(chalk42.bold(`Comments for #${id}: ${item.name}
|
|
3811
3763
|
`));
|
|
3812
3764
|
for (const entry of entries) {
|
|
3813
3765
|
console.log(`${formatComment(entry)}
|
|
@@ -3822,17 +3774,17 @@ function registerCommentCommands(cmd) {
|
|
|
3822
3774
|
}
|
|
3823
3775
|
|
|
3824
3776
|
// src/commands/backlog/add/index.ts
|
|
3825
|
-
import
|
|
3777
|
+
import chalk44 from "chalk";
|
|
3826
3778
|
|
|
3827
3779
|
// src/commands/backlog/commitBacklog.ts
|
|
3828
|
-
import { execSync as
|
|
3780
|
+
import { execSync as execSync15 } from "child_process";
|
|
3829
3781
|
import { join as join15 } from "path";
|
|
3830
|
-
import
|
|
3782
|
+
import chalk43 from "chalk";
|
|
3831
3783
|
function commitBacklog(id, name) {
|
|
3832
3784
|
const config = loadConfig();
|
|
3833
3785
|
if (!config.backlog.autoCommit) {
|
|
3834
3786
|
console.log(
|
|
3835
|
-
|
|
3787
|
+
chalk43.yellow(
|
|
3836
3788
|
"Warning: auto-commit is disabled. Stage and commit the backlog file manually."
|
|
3837
3789
|
)
|
|
3838
3790
|
);
|
|
@@ -3841,10 +3793,10 @@ function commitBacklog(id, name) {
|
|
|
3841
3793
|
try {
|
|
3842
3794
|
const jsonlPath = join15(getBacklogDir(), ".assist", "backlog.jsonl");
|
|
3843
3795
|
const message = `chore: add backlog item #${id} \u2014 ${name}`;
|
|
3844
|
-
|
|
3845
|
-
|
|
3796
|
+
execSync15(`git add ${shellQuote(jsonlPath)}`, { stdio: "ignore" });
|
|
3797
|
+
execSync15(`git commit -m ${shellQuote(message)}`, { stdio: "ignore" });
|
|
3846
3798
|
} catch {
|
|
3847
|
-
console.log(
|
|
3799
|
+
console.log(chalk43.yellow("Warning: could not auto-commit backlog file."));
|
|
3848
3800
|
}
|
|
3849
3801
|
}
|
|
3850
3802
|
|
|
@@ -3936,12 +3888,12 @@ async function addFromOptions(options2) {
|
|
|
3936
3888
|
});
|
|
3937
3889
|
saveBacklog(items);
|
|
3938
3890
|
commitBacklog(id, name);
|
|
3939
|
-
console.log(
|
|
3891
|
+
console.log(chalk44.green(`Added item #${id}: ${name}`));
|
|
3940
3892
|
}
|
|
3941
3893
|
async function add(options2) {
|
|
3942
3894
|
if (!backlogExists()) {
|
|
3943
3895
|
console.log(
|
|
3944
|
-
|
|
3896
|
+
chalk44.yellow(
|
|
3945
3897
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
3946
3898
|
)
|
|
3947
3899
|
);
|
|
@@ -3951,13 +3903,13 @@ async function add(options2) {
|
|
|
3951
3903
|
}
|
|
3952
3904
|
|
|
3953
3905
|
// src/commands/backlog/addPhase.ts
|
|
3954
|
-
import
|
|
3906
|
+
import chalk45 from "chalk";
|
|
3955
3907
|
function addPhase(id, name, options2) {
|
|
3956
3908
|
const result = loadAndFindItem(id);
|
|
3957
3909
|
if (!result) return;
|
|
3958
3910
|
const tasks = options2.task ?? [];
|
|
3959
3911
|
if (tasks.length === 0) {
|
|
3960
|
-
console.log(
|
|
3912
|
+
console.log(chalk45.red("At least one --task is required."));
|
|
3961
3913
|
process.exitCode = 1;
|
|
3962
3914
|
return;
|
|
3963
3915
|
}
|
|
@@ -3979,25 +3931,25 @@ function addPhase(id, name, options2) {
|
|
|
3979
3931
|
exportToJsonl(db, dir);
|
|
3980
3932
|
commitBacklog(itemId, result.item.name);
|
|
3981
3933
|
console.log(
|
|
3982
|
-
|
|
3934
|
+
chalk45.green(
|
|
3983
3935
|
`Added phase ${phaseIdx + 1} "${name}" to item #${itemId} with ${tasks.length} task(s).`
|
|
3984
3936
|
)
|
|
3985
3937
|
);
|
|
3986
3938
|
}
|
|
3987
3939
|
|
|
3988
3940
|
// src/commands/backlog/init/index.ts
|
|
3989
|
-
import
|
|
3941
|
+
import chalk46 from "chalk";
|
|
3990
3942
|
async function init6() {
|
|
3991
3943
|
if (backlogExists()) {
|
|
3992
|
-
console.log(
|
|
3944
|
+
console.log(chalk46.yellow("Backlog already exists."));
|
|
3993
3945
|
return;
|
|
3994
3946
|
}
|
|
3995
3947
|
saveBacklog([]);
|
|
3996
|
-
console.log(
|
|
3948
|
+
console.log(chalk46.green("Created backlog."));
|
|
3997
3949
|
}
|
|
3998
3950
|
|
|
3999
3951
|
// src/commands/backlog/list/index.ts
|
|
4000
|
-
import
|
|
3952
|
+
import chalk47 from "chalk";
|
|
4001
3953
|
function filterItems(items, options2) {
|
|
4002
3954
|
if (options2.status) return items.filter((i) => i.status === options2.status);
|
|
4003
3955
|
if (!options2.all)
|
|
@@ -4007,7 +3959,7 @@ function filterItems(items, options2) {
|
|
|
4007
3959
|
async function list2(options2) {
|
|
4008
3960
|
if (!backlogExists()) {
|
|
4009
3961
|
console.log(
|
|
4010
|
-
|
|
3962
|
+
chalk47.yellow(
|
|
4011
3963
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
4012
3964
|
)
|
|
4013
3965
|
);
|
|
@@ -4016,12 +3968,12 @@ async function list2(options2) {
|
|
|
4016
3968
|
const allItems = loadBacklog();
|
|
4017
3969
|
const items = filterItems(allItems, options2);
|
|
4018
3970
|
if (items.length === 0) {
|
|
4019
|
-
console.log(
|
|
3971
|
+
console.log(chalk47.dim("Backlog is empty."));
|
|
4020
3972
|
return;
|
|
4021
3973
|
}
|
|
4022
3974
|
for (const item of items) {
|
|
4023
3975
|
console.log(
|
|
4024
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
3976
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk47.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
|
|
4025
3977
|
);
|
|
4026
3978
|
if (options2.verbose) {
|
|
4027
3979
|
printVerboseDetails(item);
|
|
@@ -4044,7 +3996,7 @@ function registerItemCommands(cmd) {
|
|
|
4044
3996
|
}
|
|
4045
3997
|
|
|
4046
3998
|
// src/commands/backlog/link.ts
|
|
4047
|
-
import
|
|
3999
|
+
import chalk49 from "chalk";
|
|
4048
4000
|
|
|
4049
4001
|
// src/commands/backlog/hasCycle.ts
|
|
4050
4002
|
function hasCycle(items, fromId, toId) {
|
|
@@ -4067,11 +4019,11 @@ function hasCycle(items, fromId, toId) {
|
|
|
4067
4019
|
}
|
|
4068
4020
|
|
|
4069
4021
|
// src/commands/backlog/validateLinkTarget.ts
|
|
4070
|
-
import
|
|
4022
|
+
import chalk48 from "chalk";
|
|
4071
4023
|
function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
4072
4024
|
const toItem = items.find((i) => i.id === toNum);
|
|
4073
4025
|
if (!toItem) {
|
|
4074
|
-
console.log(
|
|
4026
|
+
console.log(chalk48.red(`Item #${toId} not found.`));
|
|
4075
4027
|
return void 0;
|
|
4076
4028
|
}
|
|
4077
4029
|
if (!fromItem.links) fromItem.links = [];
|
|
@@ -4080,7 +4032,7 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
|
4080
4032
|
);
|
|
4081
4033
|
if (duplicate) {
|
|
4082
4034
|
console.log(
|
|
4083
|
-
|
|
4035
|
+
chalk48.yellow(`Link already exists: #${fromId} ${linkType} #${toId}`)
|
|
4084
4036
|
);
|
|
4085
4037
|
return void 0;
|
|
4086
4038
|
}
|
|
@@ -4091,13 +4043,13 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
|
4091
4043
|
function link(fromId, toId, opts) {
|
|
4092
4044
|
const linkType = opts.type ?? "relates-to";
|
|
4093
4045
|
if (linkType !== "relates-to" && linkType !== "depends-on") {
|
|
4094
|
-
console.log(
|
|
4046
|
+
console.log(chalk49.red(`Invalid link type: ${linkType}`));
|
|
4095
4047
|
return;
|
|
4096
4048
|
}
|
|
4097
4049
|
const fromNum = Number.parseInt(fromId, 10);
|
|
4098
4050
|
const toNum = Number.parseInt(toId, 10);
|
|
4099
4051
|
if (fromNum === toNum) {
|
|
4100
|
-
console.log(
|
|
4052
|
+
console.log(chalk49.red("Cannot link an item to itself."));
|
|
4101
4053
|
return;
|
|
4102
4054
|
}
|
|
4103
4055
|
const result = loadAndFindItem(fromId);
|
|
@@ -4114,7 +4066,7 @@ function link(fromId, toId, opts) {
|
|
|
4114
4066
|
if (!toItem) return;
|
|
4115
4067
|
if (linkType === "depends-on" && hasCycle(items, fromNum, toNum)) {
|
|
4116
4068
|
console.log(
|
|
4117
|
-
|
|
4069
|
+
chalk49.red(
|
|
4118
4070
|
`Cannot add dependency: #${fromId} \u2192 #${toId} would create a circular dependency.`
|
|
4119
4071
|
)
|
|
4120
4072
|
);
|
|
@@ -4124,32 +4076,32 @@ function link(fromId, toId, opts) {
|
|
|
4124
4076
|
fromItem.links.push({ type: linkType, targetId: toNum });
|
|
4125
4077
|
saveBacklog(items);
|
|
4126
4078
|
console.log(
|
|
4127
|
-
|
|
4079
|
+
chalk49.green(`Linked #${fromId} ${linkType} #${toId} (${toItem.name})`)
|
|
4128
4080
|
);
|
|
4129
4081
|
}
|
|
4130
4082
|
|
|
4131
4083
|
// src/commands/backlog/unlink.ts
|
|
4132
|
-
import
|
|
4084
|
+
import chalk50 from "chalk";
|
|
4133
4085
|
function unlink(fromId, toId) {
|
|
4134
4086
|
const toNum = Number.parseInt(toId, 10);
|
|
4135
4087
|
const result = loadAndFindItem(fromId);
|
|
4136
4088
|
if (!result) return;
|
|
4137
4089
|
const { items, item: fromItem } = result;
|
|
4138
4090
|
if (!fromItem.links || fromItem.links.length === 0) {
|
|
4139
|
-
console.log(
|
|
4091
|
+
console.log(chalk50.yellow(`No links found on item #${fromId}.`));
|
|
4140
4092
|
return;
|
|
4141
4093
|
}
|
|
4142
4094
|
const before = fromItem.links.length;
|
|
4143
4095
|
fromItem.links = fromItem.links.filter((l) => l.targetId !== toNum);
|
|
4144
4096
|
if (fromItem.links.length === before) {
|
|
4145
|
-
console.log(
|
|
4097
|
+
console.log(chalk50.yellow(`No link from #${fromId} to #${toId} found.`));
|
|
4146
4098
|
return;
|
|
4147
4099
|
}
|
|
4148
4100
|
if (fromItem.links.length === 0) {
|
|
4149
4101
|
fromItem.links = void 0;
|
|
4150
4102
|
}
|
|
4151
4103
|
saveBacklog(items);
|
|
4152
|
-
console.log(
|
|
4104
|
+
console.log(chalk50.green(`Removed link from #${fromId} to #${toId}.`));
|
|
4153
4105
|
}
|
|
4154
4106
|
|
|
4155
4107
|
// src/commands/backlog/registerLinkCommands.ts
|
|
@@ -4170,11 +4122,11 @@ function registerRunCommand(cmd) {
|
|
|
4170
4122
|
}
|
|
4171
4123
|
|
|
4172
4124
|
// src/commands/backlog/search/index.ts
|
|
4173
|
-
import
|
|
4125
|
+
import chalk51 from "chalk";
|
|
4174
4126
|
async function search(query) {
|
|
4175
4127
|
if (!backlogExists()) {
|
|
4176
4128
|
console.log(
|
|
4177
|
-
|
|
4129
|
+
chalk51.yellow(
|
|
4178
4130
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
4179
4131
|
)
|
|
4180
4132
|
);
|
|
@@ -4182,18 +4134,18 @@ async function search(query) {
|
|
|
4182
4134
|
}
|
|
4183
4135
|
const items = searchBacklog(query);
|
|
4184
4136
|
if (items.length === 0) {
|
|
4185
|
-
console.log(
|
|
4137
|
+
console.log(chalk51.dim(`No items matching "${query}".`));
|
|
4186
4138
|
return;
|
|
4187
4139
|
}
|
|
4188
4140
|
console.log(
|
|
4189
|
-
|
|
4141
|
+
chalk51.dim(
|
|
4190
4142
|
`${items.length} item${items.length === 1 ? "" : "s"} matching "${query}":
|
|
4191
4143
|
`
|
|
4192
4144
|
)
|
|
4193
4145
|
);
|
|
4194
4146
|
for (const item of items) {
|
|
4195
4147
|
console.log(
|
|
4196
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
4148
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk51.dim(`#${item.id}`)} ${item.name}`
|
|
4197
4149
|
);
|
|
4198
4150
|
}
|
|
4199
4151
|
}
|
|
@@ -4204,16 +4156,16 @@ function registerSearchCommand(cmd) {
|
|
|
4204
4156
|
}
|
|
4205
4157
|
|
|
4206
4158
|
// src/commands/backlog/delete/index.ts
|
|
4207
|
-
import
|
|
4159
|
+
import chalk52 from "chalk";
|
|
4208
4160
|
async function del(id) {
|
|
4209
4161
|
const name = removeItem(id);
|
|
4210
4162
|
if (name) {
|
|
4211
|
-
console.log(
|
|
4163
|
+
console.log(chalk52.green(`Deleted item #${id}: ${name}`));
|
|
4212
4164
|
}
|
|
4213
4165
|
}
|
|
4214
4166
|
|
|
4215
4167
|
// src/commands/backlog/done/index.ts
|
|
4216
|
-
import
|
|
4168
|
+
import chalk53 from "chalk";
|
|
4217
4169
|
async function done(id, summary) {
|
|
4218
4170
|
const result = loadAndFindItem(id);
|
|
4219
4171
|
if (!result) return;
|
|
@@ -4223,12 +4175,12 @@ async function done(id, summary) {
|
|
|
4223
4175
|
const pending = item.plan.slice(completed);
|
|
4224
4176
|
if (pending.length > 0) {
|
|
4225
4177
|
console.log(
|
|
4226
|
-
|
|
4178
|
+
chalk53.red(
|
|
4227
4179
|
`Cannot complete item #${id}: ${pending.length} pending phase(s):`
|
|
4228
4180
|
)
|
|
4229
4181
|
);
|
|
4230
4182
|
for (const phase of pending) {
|
|
4231
|
-
console.log(
|
|
4183
|
+
console.log(chalk53.yellow(` - ${phase.name}`));
|
|
4232
4184
|
}
|
|
4233
4185
|
process.exitCode = 1;
|
|
4234
4186
|
return;
|
|
@@ -4240,20 +4192,20 @@ async function done(id, summary) {
|
|
|
4240
4192
|
addPhaseSummary(item, summary, phase);
|
|
4241
4193
|
}
|
|
4242
4194
|
saveBacklog(result.items);
|
|
4243
|
-
console.log(
|
|
4195
|
+
console.log(chalk53.green(`Completed item #${id}: ${item.name}`));
|
|
4244
4196
|
}
|
|
4245
4197
|
|
|
4246
4198
|
// src/commands/backlog/start/index.ts
|
|
4247
|
-
import
|
|
4199
|
+
import chalk54 from "chalk";
|
|
4248
4200
|
async function start(id) {
|
|
4249
4201
|
const name = setStatus(id, "in-progress");
|
|
4250
4202
|
if (name) {
|
|
4251
|
-
console.log(
|
|
4203
|
+
console.log(chalk54.green(`Started item #${id}: ${name}`));
|
|
4252
4204
|
}
|
|
4253
4205
|
}
|
|
4254
4206
|
|
|
4255
4207
|
// src/commands/backlog/wontdo/index.ts
|
|
4256
|
-
import
|
|
4208
|
+
import chalk55 from "chalk";
|
|
4257
4209
|
async function wontdo(id, reason) {
|
|
4258
4210
|
const result = loadAndFindItem(id);
|
|
4259
4211
|
if (!result) return;
|
|
@@ -4263,7 +4215,7 @@ async function wontdo(id, reason) {
|
|
|
4263
4215
|
addPhaseSummary(result.item, reason, phase);
|
|
4264
4216
|
}
|
|
4265
4217
|
saveBacklog(result.items);
|
|
4266
|
-
console.log(
|
|
4218
|
+
console.log(chalk55.red(`Won't do item #${id}: ${result.item.name}`));
|
|
4267
4219
|
}
|
|
4268
4220
|
|
|
4269
4221
|
// src/commands/backlog/registerStatusCommands.ts
|
|
@@ -4275,10 +4227,10 @@ function registerStatusCommands(cmd) {
|
|
|
4275
4227
|
}
|
|
4276
4228
|
|
|
4277
4229
|
// src/commands/backlog/removePhase.ts
|
|
4278
|
-
import
|
|
4230
|
+
import chalk57 from "chalk";
|
|
4279
4231
|
|
|
4280
4232
|
// src/commands/backlog/findPhase.ts
|
|
4281
|
-
import
|
|
4233
|
+
import chalk56 from "chalk";
|
|
4282
4234
|
function findPhase(id, phase) {
|
|
4283
4235
|
const result = loadAndFindItem(id);
|
|
4284
4236
|
if (!result) return void 0;
|
|
@@ -4290,7 +4242,7 @@ function findPhase(id, phase) {
|
|
|
4290
4242
|
"SELECT COUNT(*) as cnt FROM plan_phases WHERE item_id = ? AND idx = ?"
|
|
4291
4243
|
).get(itemId, phaseIdx);
|
|
4292
4244
|
if (existing.cnt === 0) {
|
|
4293
|
-
console.log(
|
|
4245
|
+
console.log(chalk56.red(`Phase ${phaseIdx} not found on item #${itemId}.`));
|
|
4294
4246
|
process.exitCode = 1;
|
|
4295
4247
|
return void 0;
|
|
4296
4248
|
}
|
|
@@ -4346,23 +4298,23 @@ function removePhase(id, phase) {
|
|
|
4346
4298
|
run4();
|
|
4347
4299
|
exportToJsonl(db, dir);
|
|
4348
4300
|
commitBacklog(itemId, result.item.name);
|
|
4349
|
-
console.log(
|
|
4301
|
+
console.log(chalk57.green(`Removed phase ${phaseIdx} from item #${itemId}.`));
|
|
4350
4302
|
}
|
|
4351
4303
|
|
|
4352
4304
|
// src/commands/backlog/update/index.ts
|
|
4353
|
-
import
|
|
4305
|
+
import chalk59 from "chalk";
|
|
4354
4306
|
|
|
4355
4307
|
// src/commands/backlog/update/buildUpdateSql.ts
|
|
4356
|
-
import
|
|
4308
|
+
import chalk58 from "chalk";
|
|
4357
4309
|
function buildUpdateSql(options2) {
|
|
4358
4310
|
const { name, desc, type, ac } = options2;
|
|
4359
4311
|
if (!name && !desc && !type && !ac) {
|
|
4360
|
-
console.log(
|
|
4312
|
+
console.log(chalk58.red("Nothing to update. Provide at least one flag."));
|
|
4361
4313
|
process.exitCode = 1;
|
|
4362
4314
|
return void 0;
|
|
4363
4315
|
}
|
|
4364
4316
|
if (type && type !== "story" && type !== "bug") {
|
|
4365
|
-
console.log(
|
|
4317
|
+
console.log(chalk58.red('Invalid type. Must be "story" or "bug".'));
|
|
4366
4318
|
process.exitCode = 1;
|
|
4367
4319
|
return void 0;
|
|
4368
4320
|
}
|
|
@@ -4407,11 +4359,11 @@ function update(id, options2) {
|
|
|
4407
4359
|
);
|
|
4408
4360
|
exportToJsonl(db, dir);
|
|
4409
4361
|
commitBacklog(itemId, options2.name ?? result.item.name);
|
|
4410
|
-
console.log(
|
|
4362
|
+
console.log(chalk59.green(`Updated ${built.fields} on item #${itemId}.`));
|
|
4411
4363
|
}
|
|
4412
4364
|
|
|
4413
4365
|
// src/commands/backlog/updatePhase.ts
|
|
4414
|
-
import
|
|
4366
|
+
import chalk60 from "chalk";
|
|
4415
4367
|
|
|
4416
4368
|
// src/commands/backlog/applyPhaseUpdate.ts
|
|
4417
4369
|
function applyPhaseUpdate(db, itemId, phaseIdx, fields) {
|
|
@@ -4445,7 +4397,7 @@ function applyPhaseUpdate(db, itemId, phaseIdx, fields) {
|
|
|
4445
4397
|
function updatePhase(id, phase, options2) {
|
|
4446
4398
|
const { name, task, manualCheck } = options2;
|
|
4447
4399
|
if (!name && !task && !manualCheck) {
|
|
4448
|
-
console.log(
|
|
4400
|
+
console.log(chalk60.red("Nothing to update. Provide at least one flag."));
|
|
4449
4401
|
process.exitCode = 1;
|
|
4450
4402
|
return;
|
|
4451
4403
|
}
|
|
@@ -4461,7 +4413,7 @@ function updatePhase(id, phase, options2) {
|
|
|
4461
4413
|
manualCheck && "manual checks"
|
|
4462
4414
|
].filter(Boolean).join(", ");
|
|
4463
4415
|
console.log(
|
|
4464
|
-
|
|
4416
|
+
chalk60.green(`Updated ${fields} on phase ${phaseIdx} of item #${itemId}.`)
|
|
4465
4417
|
);
|
|
4466
4418
|
}
|
|
4467
4419
|
|
|
@@ -4912,48 +4864,48 @@ ${reasons.join("\n")}`);
|
|
|
4912
4864
|
}
|
|
4913
4865
|
|
|
4914
4866
|
// src/commands/deny/denyAdd.ts
|
|
4915
|
-
import
|
|
4867
|
+
import chalk61 from "chalk";
|
|
4916
4868
|
function denyAdd(pattern2, message) {
|
|
4917
4869
|
const config = loadProjectConfig();
|
|
4918
4870
|
const deny = config.deny ?? [];
|
|
4919
4871
|
if (deny.some((r) => r.pattern === pattern2)) {
|
|
4920
|
-
console.log(
|
|
4872
|
+
console.log(chalk61.yellow(`Deny rule already exists for: ${pattern2}`));
|
|
4921
4873
|
return;
|
|
4922
4874
|
}
|
|
4923
4875
|
deny.push({ pattern: pattern2, message });
|
|
4924
4876
|
config.deny = deny;
|
|
4925
4877
|
saveConfig(config);
|
|
4926
|
-
console.log(
|
|
4878
|
+
console.log(chalk61.green(`Added deny rule: ${pattern2} \u2192 ${message}`));
|
|
4927
4879
|
}
|
|
4928
4880
|
|
|
4929
4881
|
// src/commands/deny/denyList.ts
|
|
4930
|
-
import
|
|
4882
|
+
import chalk62 from "chalk";
|
|
4931
4883
|
function denyList() {
|
|
4932
4884
|
const config = loadConfig();
|
|
4933
4885
|
const deny = config.deny;
|
|
4934
4886
|
if (!deny || deny.length === 0) {
|
|
4935
|
-
console.log(
|
|
4887
|
+
console.log(chalk62.dim("No deny rules configured."));
|
|
4936
4888
|
return;
|
|
4937
4889
|
}
|
|
4938
4890
|
for (const rule of deny) {
|
|
4939
|
-
console.log(`${
|
|
4891
|
+
console.log(`${chalk62.red(rule.pattern)} \u2192 ${rule.message}`);
|
|
4940
4892
|
}
|
|
4941
4893
|
}
|
|
4942
4894
|
|
|
4943
4895
|
// src/commands/deny/denyRemove.ts
|
|
4944
|
-
import
|
|
4896
|
+
import chalk63 from "chalk";
|
|
4945
4897
|
function denyRemove(pattern2) {
|
|
4946
4898
|
const config = loadProjectConfig();
|
|
4947
4899
|
const deny = config.deny ?? [];
|
|
4948
4900
|
const index = deny.findIndex((r) => r.pattern === pattern2);
|
|
4949
4901
|
if (index === -1) {
|
|
4950
|
-
console.log(
|
|
4902
|
+
console.log(chalk63.yellow(`No deny rule found for: ${pattern2}`));
|
|
4951
4903
|
return;
|
|
4952
4904
|
}
|
|
4953
4905
|
deny.splice(index, 1);
|
|
4954
4906
|
config.deny = deny.length > 0 ? deny : void 0;
|
|
4955
4907
|
saveConfig(config);
|
|
4956
|
-
console.log(
|
|
4908
|
+
console.log(chalk63.green(`Removed deny rule: ${pattern2}`));
|
|
4957
4909
|
}
|
|
4958
4910
|
|
|
4959
4911
|
// src/commands/permitCliReads/index.ts
|
|
@@ -4962,7 +4914,7 @@ import { homedir as homedir4 } from "os";
|
|
|
4962
4914
|
import { join as join18 } from "path";
|
|
4963
4915
|
|
|
4964
4916
|
// src/shared/getInstallDir.ts
|
|
4965
|
-
import { execSync as
|
|
4917
|
+
import { execSync as execSync16 } from "child_process";
|
|
4966
4918
|
import { dirname as dirname15, resolve as resolve4 } from "path";
|
|
4967
4919
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
4968
4920
|
var __filename3 = fileURLToPath5(import.meta.url);
|
|
@@ -4972,7 +4924,7 @@ function getInstallDir() {
|
|
|
4972
4924
|
}
|
|
4973
4925
|
function isGitRepo(dir) {
|
|
4974
4926
|
try {
|
|
4975
|
-
const result =
|
|
4927
|
+
const result = execSync16("git rev-parse --show-toplevel", {
|
|
4976
4928
|
cwd: dir,
|
|
4977
4929
|
stdio: "pipe"
|
|
4978
4930
|
}).toString().trim();
|
|
@@ -4983,7 +4935,7 @@ function isGitRepo(dir) {
|
|
|
4983
4935
|
}
|
|
4984
4936
|
|
|
4985
4937
|
// src/commands/permitCliReads/assertCliExists.ts
|
|
4986
|
-
import { execSync as
|
|
4938
|
+
import { execSync as execSync17 } from "child_process";
|
|
4987
4939
|
function assertCliExists(cli) {
|
|
4988
4940
|
const binary = cli.split(/\s+/)[0];
|
|
4989
4941
|
const opts = {
|
|
@@ -4991,10 +4943,10 @@ function assertCliExists(cli) {
|
|
|
4991
4943
|
stdio: ["ignore", "pipe", "pipe"]
|
|
4992
4944
|
};
|
|
4993
4945
|
try {
|
|
4994
|
-
|
|
4946
|
+
execSync17(`command -v ${binary}`, opts);
|
|
4995
4947
|
} catch {
|
|
4996
4948
|
try {
|
|
4997
|
-
|
|
4949
|
+
execSync17(`where ${binary}`, opts);
|
|
4998
4950
|
} catch {
|
|
4999
4951
|
console.error(`CLI "${cli}" not found in PATH`);
|
|
5000
4952
|
process.exit(1);
|
|
@@ -5003,11 +4955,11 @@ function assertCliExists(cli) {
|
|
|
5003
4955
|
}
|
|
5004
4956
|
|
|
5005
4957
|
// src/commands/permitCliReads/colorize.ts
|
|
5006
|
-
import
|
|
4958
|
+
import chalk64 from "chalk";
|
|
5007
4959
|
function colorize(plainOutput) {
|
|
5008
4960
|
return plainOutput.split("\n").map((line) => {
|
|
5009
|
-
if (line.startsWith(" R ")) return
|
|
5010
|
-
if (line.startsWith(" W ")) return
|
|
4961
|
+
if (line.startsWith(" R ")) return chalk64.green(line);
|
|
4962
|
+
if (line.startsWith(" W ")) return chalk64.red(line);
|
|
5011
4963
|
return line;
|
|
5012
4964
|
}).join("\n");
|
|
5013
4965
|
}
|
|
@@ -5325,15 +5277,15 @@ function registerCliHook(program2) {
|
|
|
5325
5277
|
}
|
|
5326
5278
|
|
|
5327
5279
|
// src/commands/complexity/analyze.ts
|
|
5328
|
-
import
|
|
5280
|
+
import chalk70 from "chalk";
|
|
5329
5281
|
|
|
5330
5282
|
// src/commands/complexity/cyclomatic.ts
|
|
5331
|
-
import
|
|
5283
|
+
import chalk66 from "chalk";
|
|
5332
5284
|
|
|
5333
5285
|
// src/commands/complexity/shared/index.ts
|
|
5334
5286
|
import fs12 from "fs";
|
|
5335
5287
|
import path20 from "path";
|
|
5336
|
-
import
|
|
5288
|
+
import chalk65 from "chalk";
|
|
5337
5289
|
import ts5 from "typescript";
|
|
5338
5290
|
|
|
5339
5291
|
// src/commands/complexity/findSourceFiles.ts
|
|
@@ -5579,7 +5531,7 @@ function createSourceFromFile(filePath) {
|
|
|
5579
5531
|
function withSourceFiles(pattern2, callback) {
|
|
5580
5532
|
const files = findSourceFiles2(pattern2);
|
|
5581
5533
|
if (files.length === 0) {
|
|
5582
|
-
console.log(
|
|
5534
|
+
console.log(chalk65.yellow("No files found matching pattern"));
|
|
5583
5535
|
return void 0;
|
|
5584
5536
|
}
|
|
5585
5537
|
return callback(files);
|
|
@@ -5612,11 +5564,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5612
5564
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
5613
5565
|
for (const { file, name, complexity } of results) {
|
|
5614
5566
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
5615
|
-
const color = exceedsThreshold ?
|
|
5616
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
5567
|
+
const color = exceedsThreshold ? chalk66.red : chalk66.white;
|
|
5568
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk66.cyan(complexity)}`);
|
|
5617
5569
|
}
|
|
5618
5570
|
console.log(
|
|
5619
|
-
|
|
5571
|
+
chalk66.dim(
|
|
5620
5572
|
`
|
|
5621
5573
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
5622
5574
|
)
|
|
@@ -5628,7 +5580,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
5628
5580
|
}
|
|
5629
5581
|
|
|
5630
5582
|
// src/commands/complexity/halstead.ts
|
|
5631
|
-
import
|
|
5583
|
+
import chalk67 from "chalk";
|
|
5632
5584
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
5633
5585
|
withSourceFiles(pattern2, (files) => {
|
|
5634
5586
|
const results = [];
|
|
@@ -5643,13 +5595,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5643
5595
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
5644
5596
|
for (const { file, name, metrics } of results) {
|
|
5645
5597
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
5646
|
-
const color = exceedsThreshold ?
|
|
5598
|
+
const color = exceedsThreshold ? chalk67.red : chalk67.white;
|
|
5647
5599
|
console.log(
|
|
5648
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
5600
|
+
`${color(`${file}:${name}`)} \u2192 volume: ${chalk67.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk67.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk67.magenta(metrics.effort.toFixed(1))}`
|
|
5649
5601
|
);
|
|
5650
5602
|
}
|
|
5651
5603
|
console.log(
|
|
5652
|
-
|
|
5604
|
+
chalk67.dim(
|
|
5653
5605
|
`
|
|
5654
5606
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
5655
5607
|
)
|
|
@@ -5664,28 +5616,28 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
5664
5616
|
import fs13 from "fs";
|
|
5665
5617
|
|
|
5666
5618
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
5667
|
-
import
|
|
5619
|
+
import chalk68 from "chalk";
|
|
5668
5620
|
function displayMaintainabilityResults(results, threshold) {
|
|
5669
5621
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
5670
5622
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
5671
|
-
console.log(
|
|
5623
|
+
console.log(chalk68.green("All files pass maintainability threshold"));
|
|
5672
5624
|
} else {
|
|
5673
5625
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
5674
|
-
const color = threshold !== void 0 ?
|
|
5626
|
+
const color = threshold !== void 0 ? chalk68.red : chalk68.white;
|
|
5675
5627
|
console.log(
|
|
5676
|
-
`${color(file)} \u2192 avg: ${
|
|
5628
|
+
`${color(file)} \u2192 avg: ${chalk68.cyan(avgMaintainability.toFixed(1))}, min: ${chalk68.yellow(minMaintainability.toFixed(1))}`
|
|
5677
5629
|
);
|
|
5678
5630
|
}
|
|
5679
5631
|
}
|
|
5680
|
-
console.log(
|
|
5632
|
+
console.log(chalk68.dim(`
|
|
5681
5633
|
Analyzed ${results.length} files`));
|
|
5682
5634
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
5683
5635
|
console.error(
|
|
5684
|
-
|
|
5636
|
+
chalk68.red(
|
|
5685
5637
|
`
|
|
5686
5638
|
Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
|
|
5687
5639
|
|
|
5688
|
-
\u26A0\uFE0F ${
|
|
5640
|
+
\u26A0\uFE0F ${chalk68.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.`
|
|
5689
5641
|
)
|
|
5690
5642
|
);
|
|
5691
5643
|
process.exit(1);
|
|
@@ -5742,7 +5694,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5742
5694
|
|
|
5743
5695
|
// src/commands/complexity/sloc.ts
|
|
5744
5696
|
import fs14 from "fs";
|
|
5745
|
-
import
|
|
5697
|
+
import chalk69 from "chalk";
|
|
5746
5698
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
5747
5699
|
withSourceFiles(pattern2, (files) => {
|
|
5748
5700
|
const results = [];
|
|
@@ -5758,12 +5710,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5758
5710
|
results.sort((a, b) => b.lines - a.lines);
|
|
5759
5711
|
for (const { file, lines } of results) {
|
|
5760
5712
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
5761
|
-
const color = exceedsThreshold ?
|
|
5762
|
-
console.log(`${color(file)} \u2192 ${
|
|
5713
|
+
const color = exceedsThreshold ? chalk69.red : chalk69.white;
|
|
5714
|
+
console.log(`${color(file)} \u2192 ${chalk69.cyan(lines)} lines`);
|
|
5763
5715
|
}
|
|
5764
5716
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
5765
5717
|
console.log(
|
|
5766
|
-
|
|
5718
|
+
chalk69.dim(`
|
|
5767
5719
|
Total: ${total} lines across ${files.length} files`)
|
|
5768
5720
|
);
|
|
5769
5721
|
if (hasViolation) {
|
|
@@ -5777,21 +5729,21 @@ async function analyze(pattern2) {
|
|
|
5777
5729
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
5778
5730
|
const files = findSourceFiles2(searchPattern);
|
|
5779
5731
|
if (files.length === 0) {
|
|
5780
|
-
console.log(
|
|
5732
|
+
console.log(chalk70.yellow("No files found matching pattern"));
|
|
5781
5733
|
return;
|
|
5782
5734
|
}
|
|
5783
5735
|
if (files.length === 1) {
|
|
5784
5736
|
const file = files[0];
|
|
5785
|
-
console.log(
|
|
5737
|
+
console.log(chalk70.bold.underline("SLOC"));
|
|
5786
5738
|
await sloc(file);
|
|
5787
5739
|
console.log();
|
|
5788
|
-
console.log(
|
|
5740
|
+
console.log(chalk70.bold.underline("Cyclomatic Complexity"));
|
|
5789
5741
|
await cyclomatic(file);
|
|
5790
5742
|
console.log();
|
|
5791
|
-
console.log(
|
|
5743
|
+
console.log(chalk70.bold.underline("Halstead Metrics"));
|
|
5792
5744
|
await halstead(file);
|
|
5793
5745
|
console.log();
|
|
5794
|
-
console.log(
|
|
5746
|
+
console.log(chalk70.bold.underline("Maintainability Index"));
|
|
5795
5747
|
await maintainability(file);
|
|
5796
5748
|
return;
|
|
5797
5749
|
}
|
|
@@ -5817,6 +5769,163 @@ function registerComplexity(program2) {
|
|
|
5817
5769
|
complexityCommand.command("sloc [pattern]").description("Count source lines of code per file").option("--threshold <number>", "Max lines threshold", Number.parseInt).action(sloc);
|
|
5818
5770
|
}
|
|
5819
5771
|
|
|
5772
|
+
// src/commands/config/index.ts
|
|
5773
|
+
import chalk71 from "chalk";
|
|
5774
|
+
import { stringify as stringifyYaml2 } from "yaml";
|
|
5775
|
+
|
|
5776
|
+
// src/commands/config/setNestedValue.ts
|
|
5777
|
+
function isPlainObject(val) {
|
|
5778
|
+
return val !== null && typeof val === "object" && !Array.isArray(val);
|
|
5779
|
+
}
|
|
5780
|
+
function isNumericKey(key) {
|
|
5781
|
+
return /^\d+$/.test(key);
|
|
5782
|
+
}
|
|
5783
|
+
function resolveKey(key) {
|
|
5784
|
+
return isNumericKey(key) ? Number.parseInt(key, 10) : key;
|
|
5785
|
+
}
|
|
5786
|
+
function getItem(container, key) {
|
|
5787
|
+
if (Array.isArray(container)) return container[key];
|
|
5788
|
+
return container[key];
|
|
5789
|
+
}
|
|
5790
|
+
function setItem(container, key, value) {
|
|
5791
|
+
if (Array.isArray(container)) container[key] = value;
|
|
5792
|
+
else container[key] = value;
|
|
5793
|
+
}
|
|
5794
|
+
function ensureArray(container, key) {
|
|
5795
|
+
const existing = getItem(container, key);
|
|
5796
|
+
const arr = Array.isArray(existing) ? [...existing] : [];
|
|
5797
|
+
setItem(container, key, arr);
|
|
5798
|
+
return arr;
|
|
5799
|
+
}
|
|
5800
|
+
function ensureObject(container, key) {
|
|
5801
|
+
const existing = getItem(container, key);
|
|
5802
|
+
const obj = isPlainObject(existing) ? { ...existing } : {};
|
|
5803
|
+
setItem(container, key, obj);
|
|
5804
|
+
return obj;
|
|
5805
|
+
}
|
|
5806
|
+
function stepIntoNested(container, key, nextKey) {
|
|
5807
|
+
const resolved = resolveKey(key);
|
|
5808
|
+
if (nextKey !== void 0 && isNumericKey(nextKey)) {
|
|
5809
|
+
return ensureArray(container, resolved);
|
|
5810
|
+
}
|
|
5811
|
+
return ensureObject(container, resolved);
|
|
5812
|
+
}
|
|
5813
|
+
function setNestedValue(obj, path50, value) {
|
|
5814
|
+
const keys = path50.split(".");
|
|
5815
|
+
const result = { ...obj };
|
|
5816
|
+
let current = result;
|
|
5817
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
5818
|
+
current = stepIntoNested(current, keys[i], keys[i + 1]);
|
|
5819
|
+
}
|
|
5820
|
+
setItem(current, resolveKey(keys[keys.length - 1]), value);
|
|
5821
|
+
return result;
|
|
5822
|
+
}
|
|
5823
|
+
|
|
5824
|
+
// src/commands/config/index.ts
|
|
5825
|
+
function coerceValue(value) {
|
|
5826
|
+
if (value === "true") return true;
|
|
5827
|
+
if (value === "false") return false;
|
|
5828
|
+
return value;
|
|
5829
|
+
}
|
|
5830
|
+
function formatIssuePath(issue, key) {
|
|
5831
|
+
return issue.path.length > 0 ? issue.path.join(".") : key;
|
|
5832
|
+
}
|
|
5833
|
+
function printValidationErrors(issues, key) {
|
|
5834
|
+
for (const issue of issues) {
|
|
5835
|
+
console.error(
|
|
5836
|
+
chalk71.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
|
|
5837
|
+
);
|
|
5838
|
+
}
|
|
5839
|
+
}
|
|
5840
|
+
function exitValidationFailed(issues, key) {
|
|
5841
|
+
printValidationErrors(issues, key);
|
|
5842
|
+
process.exit(1);
|
|
5843
|
+
}
|
|
5844
|
+
function validateConfig(updated, key) {
|
|
5845
|
+
const result = assistConfigSchema.safeParse(updated);
|
|
5846
|
+
if (!result.success) return exitValidationFailed(result.error.issues, key);
|
|
5847
|
+
return updated;
|
|
5848
|
+
}
|
|
5849
|
+
var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
5850
|
+
function assertNotGlobalOnly(key, global) {
|
|
5851
|
+
if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
|
|
5852
|
+
console.error(
|
|
5853
|
+
chalk71.red(
|
|
5854
|
+
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
5855
|
+
)
|
|
5856
|
+
);
|
|
5857
|
+
process.exit(1);
|
|
5858
|
+
}
|
|
5859
|
+
}
|
|
5860
|
+
function applyConfigSet(key, coerced, global) {
|
|
5861
|
+
assertNotGlobalOnly(key, global);
|
|
5862
|
+
const raw = global ? loadGlobalConfigRaw() : loadProjectConfig();
|
|
5863
|
+
const updated = setNestedValue(raw, key, coerced);
|
|
5864
|
+
validateConfig(updated, key);
|
|
5865
|
+
if (global) {
|
|
5866
|
+
saveGlobalConfig(updated);
|
|
5867
|
+
} else {
|
|
5868
|
+
saveConfig(updated);
|
|
5869
|
+
}
|
|
5870
|
+
}
|
|
5871
|
+
function configSet(key, value, options2 = {}) {
|
|
5872
|
+
const coerced = coerceValue(value);
|
|
5873
|
+
applyConfigSet(key, coerced, options2.global ?? false);
|
|
5874
|
+
const target = options2.global ? "global" : "project";
|
|
5875
|
+
console.log(
|
|
5876
|
+
chalk71.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
|
|
5877
|
+
);
|
|
5878
|
+
}
|
|
5879
|
+
function configList() {
|
|
5880
|
+
const config = loadConfig();
|
|
5881
|
+
console.log(stringifyYaml2(config, { lineWidth: 0 }).trimEnd());
|
|
5882
|
+
}
|
|
5883
|
+
|
|
5884
|
+
// src/commands/config/configGet.ts
|
|
5885
|
+
import chalk72 from "chalk";
|
|
5886
|
+
|
|
5887
|
+
// src/commands/config/getNestedValue.ts
|
|
5888
|
+
function isTraversable(value) {
|
|
5889
|
+
return value !== null && value !== void 0 && typeof value === "object";
|
|
5890
|
+
}
|
|
5891
|
+
function stepInto(current, key) {
|
|
5892
|
+
return isTraversable(current) ? current[key] : void 0;
|
|
5893
|
+
}
|
|
5894
|
+
function getNestedValue(obj, path50) {
|
|
5895
|
+
let current = obj;
|
|
5896
|
+
for (const key of path50.split(".")) current = stepInto(current, key);
|
|
5897
|
+
return current;
|
|
5898
|
+
}
|
|
5899
|
+
|
|
5900
|
+
// src/commands/config/configGet.ts
|
|
5901
|
+
function configGet(key) {
|
|
5902
|
+
console.log(
|
|
5903
|
+
formatOutput(
|
|
5904
|
+
requireNestedValue(loadConfig(), key)
|
|
5905
|
+
)
|
|
5906
|
+
);
|
|
5907
|
+
}
|
|
5908
|
+
function formatOutput(value) {
|
|
5909
|
+
return typeof value === "object" && value !== null ? JSON.stringify(value, null, 2) : String(value);
|
|
5910
|
+
}
|
|
5911
|
+
function requireNestedValue(config, key) {
|
|
5912
|
+
const value = getNestedValue(config, key);
|
|
5913
|
+
if (value === void 0) return exitKeyNotSet(key);
|
|
5914
|
+
return value;
|
|
5915
|
+
}
|
|
5916
|
+
function exitKeyNotSet(key) {
|
|
5917
|
+
console.error(chalk72.red(`Key "${key}" is not set`));
|
|
5918
|
+
process.exit(1);
|
|
5919
|
+
}
|
|
5920
|
+
|
|
5921
|
+
// src/commands/registerConfig.ts
|
|
5922
|
+
function registerConfig(program2) {
|
|
5923
|
+
const configCommand = program2.command("config").description("View and modify assist.yml configuration");
|
|
5924
|
+
configCommand.command("set <key> <value>").description("Set a config value (e.g. commit.push true)").option("-g, --global", "Write to global ~/.assist.yml").action((key, value, options2) => configSet(key, value, options2));
|
|
5925
|
+
configCommand.command("get <key>").description("Get a config value").action(configGet);
|
|
5926
|
+
configCommand.command("list").description("List all config values").action(configList);
|
|
5927
|
+
}
|
|
5928
|
+
|
|
5820
5929
|
// src/commands/deploy/redirect.ts
|
|
5821
5930
|
import { existsSync as existsSync22, readFileSync as readFileSync20, writeFileSync as writeFileSync18 } from "fs";
|
|
5822
5931
|
import chalk73 from "chalk";
|
|
@@ -5854,7 +5963,7 @@ function registerDeploy(program2) {
|
|
|
5854
5963
|
}
|
|
5855
5964
|
|
|
5856
5965
|
// src/commands/devlog/list/index.ts
|
|
5857
|
-
import { execSync as
|
|
5966
|
+
import { execSync as execSync19 } from "child_process";
|
|
5858
5967
|
import { basename as basename3 } from "path";
|
|
5859
5968
|
|
|
5860
5969
|
// src/commands/devlog/loadBlogSkipDays.ts
|
|
@@ -5869,7 +5978,7 @@ function loadBlogSkipDays(repoName) {
|
|
|
5869
5978
|
}
|
|
5870
5979
|
|
|
5871
5980
|
// src/commands/devlog/shared.ts
|
|
5872
|
-
import { execSync as
|
|
5981
|
+
import { execSync as execSync18 } from "child_process";
|
|
5873
5982
|
import chalk74 from "chalk";
|
|
5874
5983
|
|
|
5875
5984
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
@@ -5939,7 +6048,7 @@ function loadAllDevlogLatestDates() {
|
|
|
5939
6048
|
// src/commands/devlog/shared.ts
|
|
5940
6049
|
function getCommitFiles(hash) {
|
|
5941
6050
|
try {
|
|
5942
|
-
const output =
|
|
6051
|
+
const output = execSync18(`git show --name-only --format="" ${hash}`, {
|
|
5943
6052
|
encoding: "utf-8"
|
|
5944
6053
|
});
|
|
5945
6054
|
return output.trim().split("\n").filter(Boolean);
|
|
@@ -6010,7 +6119,7 @@ function list3(options2) {
|
|
|
6010
6119
|
const devlogEntries = loadDevlogEntries(repoName);
|
|
6011
6120
|
const reverseFlag = options2.reverse ? "--reverse " : "";
|
|
6012
6121
|
const limitFlag = options2.reverse ? "" : "-n 500 ";
|
|
6013
|
-
const output =
|
|
6122
|
+
const output = execSync19(
|
|
6014
6123
|
`git log ${reverseFlag}${limitFlag}--pretty=format:'%ad|%h|%s' --date=short`,
|
|
6015
6124
|
{ encoding: "utf-8" }
|
|
6016
6125
|
);
|
|
@@ -6036,11 +6145,11 @@ function list3(options2) {
|
|
|
6036
6145
|
}
|
|
6037
6146
|
|
|
6038
6147
|
// src/commands/devlog/getLastVersionInfo.ts
|
|
6039
|
-
import { execSync as
|
|
6148
|
+
import { execSync as execSync20 } from "child_process";
|
|
6040
6149
|
import semver from "semver";
|
|
6041
6150
|
function getVersionAtCommit(hash) {
|
|
6042
6151
|
try {
|
|
6043
|
-
const content =
|
|
6152
|
+
const content = execSync20(`git show ${hash}:package.json`, {
|
|
6044
6153
|
encoding: "utf-8"
|
|
6045
6154
|
});
|
|
6046
6155
|
const pkg = JSON.parse(content);
|
|
@@ -6055,7 +6164,7 @@ function stripToMinor(version2) {
|
|
|
6055
6164
|
}
|
|
6056
6165
|
function getLastVersionInfoFromGit() {
|
|
6057
6166
|
try {
|
|
6058
|
-
const output =
|
|
6167
|
+
const output = execSync20(
|
|
6059
6168
|
"git log -1 --pretty=format:'%ad|%h' --date=short",
|
|
6060
6169
|
{
|
|
6061
6170
|
encoding: "utf-8"
|
|
@@ -6099,7 +6208,7 @@ function bumpVersion(version2, type) {
|
|
|
6099
6208
|
}
|
|
6100
6209
|
|
|
6101
6210
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
6102
|
-
import { execSync as
|
|
6211
|
+
import { execSync as execSync21 } from "child_process";
|
|
6103
6212
|
import chalk77 from "chalk";
|
|
6104
6213
|
|
|
6105
6214
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
@@ -6133,7 +6242,7 @@ function findTargetDate(commitsByDate, skipDays) {
|
|
|
6133
6242
|
return Array.from(commitsByDate.keys()).filter((d) => !skipDays.has(d)).sort()[0];
|
|
6134
6243
|
}
|
|
6135
6244
|
function fetchCommitsByDate(ignore2, lastDate) {
|
|
6136
|
-
const output =
|
|
6245
|
+
const output = execSync21(
|
|
6137
6246
|
"git log --pretty=format:'%ad|%h|%s' --date=short -n 500",
|
|
6138
6247
|
{ encoding: "utf-8" }
|
|
6139
6248
|
);
|
|
@@ -6211,7 +6320,7 @@ function next2(options2) {
|
|
|
6211
6320
|
}
|
|
6212
6321
|
|
|
6213
6322
|
// src/commands/devlog/repos/index.ts
|
|
6214
|
-
import { execSync as
|
|
6323
|
+
import { execSync as execSync22 } from "child_process";
|
|
6215
6324
|
|
|
6216
6325
|
// src/commands/devlog/repos/printReposTable.ts
|
|
6217
6326
|
import chalk78 from "chalk";
|
|
@@ -6246,7 +6355,7 @@ function getStatus(lastPush, lastDevlog) {
|
|
|
6246
6355
|
return lastDevlog < lastPush ? "outdated" : "ok";
|
|
6247
6356
|
}
|
|
6248
6357
|
function fetchRepos(days, all) {
|
|
6249
|
-
const json =
|
|
6358
|
+
const json = execSync22(
|
|
6250
6359
|
"gh repo list staff0rd --json name,pushedAt,isArchived --limit 200",
|
|
6251
6360
|
{ encoding: "utf-8" }
|
|
6252
6361
|
);
|
|
@@ -6606,7 +6715,7 @@ async function deps(csprojPath, options2) {
|
|
|
6606
6715
|
}
|
|
6607
6716
|
|
|
6608
6717
|
// src/commands/dotnet/getChangedCsFiles.ts
|
|
6609
|
-
import { execSync as
|
|
6718
|
+
import { execSync as execSync23 } from "child_process";
|
|
6610
6719
|
var SCOPE_ALL = "all";
|
|
6611
6720
|
var SCOPE_BASE = "base:";
|
|
6612
6721
|
var SCOPE_COMMIT = "commit:";
|
|
@@ -6630,7 +6739,7 @@ function getChangedCsFiles(scope) {
|
|
|
6630
6739
|
} else {
|
|
6631
6740
|
cmd = "git diff --name-only HEAD";
|
|
6632
6741
|
}
|
|
6633
|
-
const output =
|
|
6742
|
+
const output = execSync23(cmd, { encoding: "utf-8" }).trim();
|
|
6634
6743
|
if (output === "") return [];
|
|
6635
6744
|
return output.split("\n").filter((f) => f.toLowerCase().endsWith(".cs"));
|
|
6636
6745
|
}
|
|
@@ -6828,14 +6937,14 @@ function parseInspectReport(json) {
|
|
|
6828
6937
|
}
|
|
6829
6938
|
|
|
6830
6939
|
// src/commands/dotnet/runInspectCode.ts
|
|
6831
|
-
import { execSync as
|
|
6940
|
+
import { execSync as execSync24 } from "child_process";
|
|
6832
6941
|
import { existsSync as existsSync26, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "fs";
|
|
6833
6942
|
import { tmpdir as tmpdir2 } from "os";
|
|
6834
6943
|
import path26 from "path";
|
|
6835
6944
|
import chalk88 from "chalk";
|
|
6836
6945
|
function assertJbInstalled() {
|
|
6837
6946
|
try {
|
|
6838
|
-
|
|
6947
|
+
execSync24("jb inspectcode --version", { stdio: "pipe" });
|
|
6839
6948
|
} catch {
|
|
6840
6949
|
console.error(chalk88.red("jb is not installed. Install with:"));
|
|
6841
6950
|
console.error(
|
|
@@ -6849,7 +6958,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
6849
6958
|
const includeFlag = include ? ` --include="${include}"` : "";
|
|
6850
6959
|
const sweaFlag = swea ? " --swea" : "";
|
|
6851
6960
|
try {
|
|
6852
|
-
|
|
6961
|
+
execSync24(
|
|
6853
6962
|
`jb inspectcode "${slnPath}" -o="${reportPath}"${includeFlag}${sweaFlag} --verbosity=OFF`,
|
|
6854
6963
|
{ stdio: "pipe" }
|
|
6855
6964
|
);
|
|
@@ -6870,7 +6979,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
6870
6979
|
}
|
|
6871
6980
|
|
|
6872
6981
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
6873
|
-
import { execSync as
|
|
6982
|
+
import { execSync as execSync25 } from "child_process";
|
|
6874
6983
|
import chalk89 from "chalk";
|
|
6875
6984
|
function resolveMsbuildPath() {
|
|
6876
6985
|
const config = loadConfig();
|
|
@@ -6880,7 +6989,7 @@ function resolveMsbuildPath() {
|
|
|
6880
6989
|
function assertMsbuildInstalled() {
|
|
6881
6990
|
const msbuild = resolveMsbuildPath();
|
|
6882
6991
|
try {
|
|
6883
|
-
|
|
6992
|
+
execSync25(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
6884
6993
|
} catch {
|
|
6885
6994
|
console.error(chalk89.red(`msbuild not found at: ${msbuild}`));
|
|
6886
6995
|
console.error(
|
|
@@ -6906,7 +7015,7 @@ function runRoslynInspect(slnPath) {
|
|
|
6906
7015
|
const msbuild = resolveMsbuildPath();
|
|
6907
7016
|
let output;
|
|
6908
7017
|
try {
|
|
6909
|
-
output =
|
|
7018
|
+
output = execSync25(
|
|
6910
7019
|
`"${msbuild}" "${slnPath}" -t:Build -v:minimal -maxcpucount -p:EnforceCodeStyleInBuild=true -p:RunAnalyzersDuringBuild=true 2>&1`,
|
|
6911
7020
|
{ encoding: "utf-8", stdio: "pipe", maxBuffer: 50 * 1024 * 1024 }
|
|
6912
7021
|
);
|
|
@@ -7038,12 +7147,12 @@ function adfToText(doc) {
|
|
|
7038
7147
|
}
|
|
7039
7148
|
|
|
7040
7149
|
// src/commands/jira/fetchIssue.ts
|
|
7041
|
-
import { execSync as
|
|
7150
|
+
import { execSync as execSync26 } from "child_process";
|
|
7042
7151
|
import chalk91 from "chalk";
|
|
7043
7152
|
function fetchIssue(issueKey, fields) {
|
|
7044
7153
|
let result;
|
|
7045
7154
|
try {
|
|
7046
|
-
result =
|
|
7155
|
+
result = execSync26(
|
|
7047
7156
|
`acli jira workitem view ${issueKey} -f ${fields} --json`,
|
|
7048
7157
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
7049
7158
|
);
|
|
@@ -7089,7 +7198,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
7089
7198
|
}
|
|
7090
7199
|
|
|
7091
7200
|
// src/commands/jira/jiraAuth.ts
|
|
7092
|
-
import { execSync as
|
|
7201
|
+
import { execSync as execSync27 } from "child_process";
|
|
7093
7202
|
|
|
7094
7203
|
// src/shared/loadJson.ts
|
|
7095
7204
|
import { existsSync as existsSync27, mkdirSync as mkdirSync6, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "fs";
|
|
@@ -7153,7 +7262,7 @@ async function jiraAuth() {
|
|
|
7153
7262
|
console.error("All fields are required.");
|
|
7154
7263
|
process.exit(1);
|
|
7155
7264
|
}
|
|
7156
|
-
|
|
7265
|
+
execSync27(`acli jira auth login --site ${site} --email "${email}" --token`, {
|
|
7157
7266
|
encoding: "utf-8",
|
|
7158
7267
|
input: token,
|
|
7159
7268
|
stdio: ["pipe", "inherit", "inherit"]
|
|
@@ -7434,7 +7543,7 @@ import { tmpdir as tmpdir3 } from "os";
|
|
|
7434
7543
|
import { join as join25 } from "path";
|
|
7435
7544
|
|
|
7436
7545
|
// src/commands/prs/shared.ts
|
|
7437
|
-
import { execSync as
|
|
7546
|
+
import { execSync as execSync28 } from "child_process";
|
|
7438
7547
|
function isGhNotInstalled(error) {
|
|
7439
7548
|
if (error instanceof Error) {
|
|
7440
7549
|
const msg = error.message.toLowerCase();
|
|
@@ -7450,14 +7559,14 @@ function isNotFound(error) {
|
|
|
7450
7559
|
}
|
|
7451
7560
|
function getRepoInfo() {
|
|
7452
7561
|
const repoInfo = JSON.parse(
|
|
7453
|
-
|
|
7562
|
+
execSync28("gh repo view --json owner,name", { encoding: "utf-8" })
|
|
7454
7563
|
);
|
|
7455
7564
|
return { org: repoInfo.owner.login, repo: repoInfo.name };
|
|
7456
7565
|
}
|
|
7457
7566
|
function getCurrentPrNumber() {
|
|
7458
7567
|
try {
|
|
7459
7568
|
const prInfo = JSON.parse(
|
|
7460
|
-
|
|
7569
|
+
execSync28("gh pr view --json number", { encoding: "utf-8" })
|
|
7461
7570
|
);
|
|
7462
7571
|
return prInfo.number;
|
|
7463
7572
|
} catch (error) {
|
|
@@ -7471,7 +7580,7 @@ function getCurrentPrNumber() {
|
|
|
7471
7580
|
function getCurrentPrNodeId() {
|
|
7472
7581
|
try {
|
|
7473
7582
|
const prInfo = JSON.parse(
|
|
7474
|
-
|
|
7583
|
+
execSync28("gh pr view --json id", { encoding: "utf-8" })
|
|
7475
7584
|
);
|
|
7476
7585
|
return prInfo.id;
|
|
7477
7586
|
} catch (error) {
|
|
@@ -7542,10 +7651,10 @@ function comment2(path50, line, body) {
|
|
|
7542
7651
|
}
|
|
7543
7652
|
|
|
7544
7653
|
// src/commands/prs/fixed.ts
|
|
7545
|
-
import { execSync as
|
|
7654
|
+
import { execSync as execSync30 } from "child_process";
|
|
7546
7655
|
|
|
7547
7656
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
7548
|
-
import { execSync as
|
|
7657
|
+
import { execSync as execSync29 } from "child_process";
|
|
7549
7658
|
import { unlinkSync as unlinkSync8, writeFileSync as writeFileSync22 } from "fs";
|
|
7550
7659
|
import { tmpdir as tmpdir4 } from "os";
|
|
7551
7660
|
import { join as join27 } from "path";
|
|
@@ -7575,7 +7684,7 @@ function deleteCommentsCache(prNumber) {
|
|
|
7575
7684
|
|
|
7576
7685
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
7577
7686
|
function replyToComment(org, repo, prNumber, commentId, message) {
|
|
7578
|
-
|
|
7687
|
+
execSync29(
|
|
7579
7688
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, '\\"')}" -F in_reply_to=${commentId}`,
|
|
7580
7689
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
7581
7690
|
);
|
|
@@ -7585,7 +7694,7 @@ function resolveThread(threadId) {
|
|
|
7585
7694
|
const queryFile = join27(tmpdir4(), `gh-mutation-${Date.now()}.graphql`);
|
|
7586
7695
|
writeFileSync22(queryFile, mutation);
|
|
7587
7696
|
try {
|
|
7588
|
-
|
|
7697
|
+
execSync29(
|
|
7589
7698
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
7590
7699
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
7591
7700
|
);
|
|
@@ -7637,7 +7746,7 @@ function resolveCommentWithReply(commentId, message) {
|
|
|
7637
7746
|
// src/commands/prs/fixed.ts
|
|
7638
7747
|
function verifySha(sha) {
|
|
7639
7748
|
try {
|
|
7640
|
-
return
|
|
7749
|
+
return execSync30(`git rev-parse --verify ${sha}`, {
|
|
7641
7750
|
encoding: "utf-8"
|
|
7642
7751
|
}).trim();
|
|
7643
7752
|
} catch {
|
|
@@ -7651,7 +7760,7 @@ function fixed(commentId, sha) {
|
|
|
7651
7760
|
const { org, repo } = getRepoInfo();
|
|
7652
7761
|
const repoUrl = `https://github.com/${org}/${repo}`;
|
|
7653
7762
|
const message = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
|
|
7654
|
-
|
|
7763
|
+
execSync30("git push", { stdio: "inherit" });
|
|
7655
7764
|
resolveCommentWithReply(commentId, message);
|
|
7656
7765
|
} catch (error) {
|
|
7657
7766
|
if (isGhNotInstalled(error)) {
|
|
@@ -7669,7 +7778,7 @@ import { join as join29 } from "path";
|
|
|
7669
7778
|
import { stringify } from "yaml";
|
|
7670
7779
|
|
|
7671
7780
|
// src/commands/prs/fetchThreadIds.ts
|
|
7672
|
-
import { execSync as
|
|
7781
|
+
import { execSync as execSync31 } from "child_process";
|
|
7673
7782
|
import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync23 } from "fs";
|
|
7674
7783
|
import { tmpdir as tmpdir5 } from "os";
|
|
7675
7784
|
import { join as join28 } from "path";
|
|
@@ -7678,7 +7787,7 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
7678
7787
|
const queryFile = join28(tmpdir5(), `gh-query-${Date.now()}.graphql`);
|
|
7679
7788
|
writeFileSync23(queryFile, THREAD_QUERY);
|
|
7680
7789
|
try {
|
|
7681
|
-
const result =
|
|
7790
|
+
const result = execSync31(
|
|
7682
7791
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
7683
7792
|
{ encoding: "utf-8" }
|
|
7684
7793
|
);
|
|
@@ -7700,9 +7809,9 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
7700
7809
|
}
|
|
7701
7810
|
|
|
7702
7811
|
// src/commands/prs/listComments/fetchReviewComments.ts
|
|
7703
|
-
import { execSync as
|
|
7812
|
+
import { execSync as execSync32 } from "child_process";
|
|
7704
7813
|
function fetchJson(endpoint) {
|
|
7705
|
-
const result =
|
|
7814
|
+
const result = execSync32(`gh api --paginate ${endpoint}`, {
|
|
7706
7815
|
encoding: "utf-8"
|
|
7707
7816
|
});
|
|
7708
7817
|
if (!result.trim()) return [];
|
|
@@ -7841,7 +7950,7 @@ async function listComments() {
|
|
|
7841
7950
|
}
|
|
7842
7951
|
|
|
7843
7952
|
// src/commands/prs/prs/index.ts
|
|
7844
|
-
import { execSync as
|
|
7953
|
+
import { execSync as execSync33 } from "child_process";
|
|
7845
7954
|
|
|
7846
7955
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
7847
7956
|
import enquirer9 from "enquirer";
|
|
@@ -7947,7 +8056,7 @@ async function displayPaginated(pullRequests) {
|
|
|
7947
8056
|
async function prs(options2) {
|
|
7948
8057
|
const state = options2.open ? "open" : options2.closed ? "closed" : "all";
|
|
7949
8058
|
try {
|
|
7950
|
-
const result =
|
|
8059
|
+
const result = execSync33(
|
|
7951
8060
|
`gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100`,
|
|
7952
8061
|
{ encoding: "utf-8" }
|
|
7953
8062
|
);
|
|
@@ -7970,7 +8079,7 @@ async function prs(options2) {
|
|
|
7970
8079
|
}
|
|
7971
8080
|
|
|
7972
8081
|
// src/commands/prs/wontfix.ts
|
|
7973
|
-
import { execSync as
|
|
8082
|
+
import { execSync as execSync34 } from "child_process";
|
|
7974
8083
|
function validateReason(reason) {
|
|
7975
8084
|
const lowerReason = reason.toLowerCase();
|
|
7976
8085
|
if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
|
|
@@ -7987,7 +8096,7 @@ function validateShaReferences(reason) {
|
|
|
7987
8096
|
const invalidShas = [];
|
|
7988
8097
|
for (const sha of shas) {
|
|
7989
8098
|
try {
|
|
7990
|
-
|
|
8099
|
+
execSync34(`git cat-file -t ${sha}`, { stdio: "pipe" });
|
|
7991
8100
|
} catch {
|
|
7992
8101
|
invalidShas.push(sha);
|
|
7993
8102
|
}
|
|
@@ -8101,10 +8210,10 @@ import chalk100 from "chalk";
|
|
|
8101
8210
|
import Enquirer2 from "enquirer";
|
|
8102
8211
|
|
|
8103
8212
|
// src/commands/ravendb/searchItems.ts
|
|
8104
|
-
import { execSync as
|
|
8213
|
+
import { execSync as execSync35 } from "child_process";
|
|
8105
8214
|
import chalk99 from "chalk";
|
|
8106
8215
|
function opExec(args) {
|
|
8107
|
-
return
|
|
8216
|
+
return execSync35(`op ${args}`, {
|
|
8108
8217
|
encoding: "utf-8",
|
|
8109
8218
|
stdio: ["pipe", "pipe", "pipe"]
|
|
8110
8219
|
}).trim();
|
|
@@ -8256,7 +8365,7 @@ ${errorText}`
|
|
|
8256
8365
|
}
|
|
8257
8366
|
|
|
8258
8367
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
8259
|
-
import { execSync as
|
|
8368
|
+
import { execSync as execSync36 } from "child_process";
|
|
8260
8369
|
import chalk104 from "chalk";
|
|
8261
8370
|
function resolveOpSecret(reference) {
|
|
8262
8371
|
if (!reference.startsWith("op://")) {
|
|
@@ -8264,7 +8373,7 @@ function resolveOpSecret(reference) {
|
|
|
8264
8373
|
process.exit(1);
|
|
8265
8374
|
}
|
|
8266
8375
|
try {
|
|
8267
|
-
return
|
|
8376
|
+
return execSync36(`op read "${reference}"`, {
|
|
8268
8377
|
encoding: "utf-8",
|
|
8269
8378
|
stdio: ["pipe", "pipe", "pipe"]
|
|
8270
8379
|
}).trim();
|
|
@@ -8513,7 +8622,7 @@ Refactor check failed:
|
|
|
8513
8622
|
}
|
|
8514
8623
|
|
|
8515
8624
|
// src/commands/refactor/check/getViolations/index.ts
|
|
8516
|
-
import { execSync as
|
|
8625
|
+
import { execSync as execSync37 } from "child_process";
|
|
8517
8626
|
import fs16 from "fs";
|
|
8518
8627
|
import { minimatch as minimatch4 } from "minimatch";
|
|
8519
8628
|
|
|
@@ -8563,7 +8672,7 @@ function getGitFiles(options2) {
|
|
|
8563
8672
|
}
|
|
8564
8673
|
const files = /* @__PURE__ */ new Set();
|
|
8565
8674
|
if (options2.staged || options2.modified) {
|
|
8566
|
-
const staged =
|
|
8675
|
+
const staged = execSync37("git diff --cached --name-only", {
|
|
8567
8676
|
encoding: "utf-8"
|
|
8568
8677
|
});
|
|
8569
8678
|
for (const file of staged.trim().split("\n").filter(Boolean)) {
|
|
@@ -8571,7 +8680,7 @@ function getGitFiles(options2) {
|
|
|
8571
8680
|
}
|
|
8572
8681
|
}
|
|
8573
8682
|
if (options2.unstaged || options2.modified) {
|
|
8574
|
-
const unstaged =
|
|
8683
|
+
const unstaged = execSync37("git diff --name-only", { encoding: "utf-8" });
|
|
8575
8684
|
for (const file of unstaged.trim().split("\n").filter(Boolean)) {
|
|
8576
8685
|
files.add(file);
|
|
8577
8686
|
}
|
|
@@ -10961,7 +11070,7 @@ import { mkdirSync as mkdirSync11 } from "fs";
|
|
|
10961
11070
|
import { join as join39 } from "path";
|
|
10962
11071
|
|
|
10963
11072
|
// src/commands/voice/checkLockFile.ts
|
|
10964
|
-
import { execSync as
|
|
11073
|
+
import { execSync as execSync38 } from "child_process";
|
|
10965
11074
|
import { existsSync as existsSync36, mkdirSync as mkdirSync10, readFileSync as readFileSync30, writeFileSync as writeFileSync26 } from "fs";
|
|
10966
11075
|
import { join as join38 } from "path";
|
|
10967
11076
|
function isProcessAlive2(pid) {
|
|
@@ -10990,7 +11099,7 @@ function bootstrapVenv() {
|
|
|
10990
11099
|
if (existsSync36(getVenvPython())) return;
|
|
10991
11100
|
console.log("Setting up Python environment...");
|
|
10992
11101
|
const pythonDir = getPythonDir();
|
|
10993
|
-
|
|
11102
|
+
execSync38(
|
|
10994
11103
|
`uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
|
|
10995
11104
|
{
|
|
10996
11105
|
stdio: "inherit",
|
|
@@ -11157,11 +11266,11 @@ import { randomBytes } from "crypto";
|
|
|
11157
11266
|
import chalk128 from "chalk";
|
|
11158
11267
|
|
|
11159
11268
|
// src/lib/openBrowser.ts
|
|
11160
|
-
import { execSync as
|
|
11269
|
+
import { execSync as execSync39 } from "child_process";
|
|
11161
11270
|
function tryExec(commands) {
|
|
11162
11271
|
for (const cmd of commands) {
|
|
11163
11272
|
try {
|
|
11164
|
-
|
|
11273
|
+
execSync39(cmd);
|
|
11165
11274
|
return true;
|
|
11166
11275
|
} catch {
|
|
11167
11276
|
}
|
|
@@ -11387,7 +11496,7 @@ function registerRoam(program2) {
|
|
|
11387
11496
|
}
|
|
11388
11497
|
|
|
11389
11498
|
// src/commands/run/index.ts
|
|
11390
|
-
import { execSync as
|
|
11499
|
+
import { execSync as execSync40 } from "child_process";
|
|
11391
11500
|
|
|
11392
11501
|
// src/commands/run/formatConfiguredCommands.ts
|
|
11393
11502
|
function formatConfiguredCommands() {
|
|
@@ -11552,7 +11661,7 @@ function listRunConfigs() {
|
|
|
11552
11661
|
function runPreCommands(pre) {
|
|
11553
11662
|
for (const cmd of pre) {
|
|
11554
11663
|
try {
|
|
11555
|
-
|
|
11664
|
+
execSync40(cmd, { stdio: "inherit" });
|
|
11556
11665
|
} catch (err) {
|
|
11557
11666
|
const code = err && typeof err === "object" && "status" in err ? err.status : 1;
|
|
11558
11667
|
process.exit(code);
|
|
@@ -11575,7 +11684,7 @@ function run3(name, args) {
|
|
|
11575
11684
|
}
|
|
11576
11685
|
|
|
11577
11686
|
// src/commands/screenshot/index.ts
|
|
11578
|
-
import { execSync as
|
|
11687
|
+
import { execSync as execSync41 } from "child_process";
|
|
11579
11688
|
import { existsSync as existsSync39, mkdirSync as mkdirSync14, unlinkSync as unlinkSync11, writeFileSync as writeFileSync29 } from "fs";
|
|
11580
11689
|
import { tmpdir as tmpdir6 } from "os";
|
|
11581
11690
|
import { join as join43, resolve as resolve5 } from "path";
|
|
@@ -11718,7 +11827,7 @@ function runPowerShellScript(processName, outputPath) {
|
|
|
11718
11827
|
const scriptPath = join43(tmpdir6(), `assist-screenshot-${Date.now()}.ps1`);
|
|
11719
11828
|
writeFileSync29(scriptPath, captureWindowPs1, "utf-8");
|
|
11720
11829
|
try {
|
|
11721
|
-
|
|
11830
|
+
execSync41(
|
|
11722
11831
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
11723
11832
|
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }
|
|
11724
11833
|
);
|
|
@@ -11919,7 +12028,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
11919
12028
|
}
|
|
11920
12029
|
|
|
11921
12030
|
// src/commands/update.ts
|
|
11922
|
-
import { execSync as
|
|
12031
|
+
import { execSync as execSync42 } from "child_process";
|
|
11923
12032
|
import * as path49 from "path";
|
|
11924
12033
|
function isGlobalNpmInstall(dir) {
|
|
11925
12034
|
try {
|
|
@@ -11927,7 +12036,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
11927
12036
|
if (resolved.split(path49.sep).includes("node_modules")) {
|
|
11928
12037
|
return true;
|
|
11929
12038
|
}
|
|
11930
|
-
const globalPrefix =
|
|
12039
|
+
const globalPrefix = execSync42("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
11931
12040
|
return resolved.toLowerCase().startsWith(path49.resolve(globalPrefix).toLowerCase());
|
|
11932
12041
|
} catch {
|
|
11933
12042
|
return false;
|
|
@@ -11938,18 +12047,18 @@ async function update2() {
|
|
|
11938
12047
|
console.log(`Assist is installed at: ${installDir}`);
|
|
11939
12048
|
if (isGitRepo(installDir)) {
|
|
11940
12049
|
console.log("Detected git repo installation, pulling latest...");
|
|
11941
|
-
|
|
12050
|
+
execSync42("git pull", { cwd: installDir, stdio: "inherit" });
|
|
11942
12051
|
console.log("Installing dependencies...");
|
|
11943
|
-
|
|
12052
|
+
execSync42("npm i", { cwd: installDir, stdio: "inherit" });
|
|
11944
12053
|
console.log("Building...");
|
|
11945
|
-
|
|
12054
|
+
execSync42("npm run build", { cwd: installDir, stdio: "inherit" });
|
|
11946
12055
|
console.log("Syncing commands...");
|
|
11947
|
-
|
|
12056
|
+
execSync42("assist sync", { stdio: "inherit" });
|
|
11948
12057
|
} else if (isGlobalNpmInstall(installDir)) {
|
|
11949
12058
|
console.log("Detected global npm installation, updating...");
|
|
11950
|
-
|
|
12059
|
+
execSync42("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
|
|
11951
12060
|
console.log("Syncing commands...");
|
|
11952
|
-
|
|
12061
|
+
execSync42("assist sync", { stdio: "inherit" });
|
|
11953
12062
|
} else {
|
|
11954
12063
|
console.error(
|
|
11955
12064
|
"Could not determine installation method. Expected a git repo or global npm install."
|
|
@@ -11964,10 +12073,7 @@ program.name("assist").description("CLI application").version(package_default.ve
|
|
|
11964
12073
|
program.command("sync").description("Copy command files to ~/.claude/commands").option("-y, --yes", "Overwrite settings.json without prompting").action((options2) => sync(options2));
|
|
11965
12074
|
program.command("init").description("Initialize VS Code and verify configurations").action(init4);
|
|
11966
12075
|
program.command("commit").description("Create a git commit with validation").argument("<args...>", "status | <message> [files...]").action(commit);
|
|
11967
|
-
|
|
11968
|
-
configCommand.command("set <key> <value>").description("Set a config value (e.g. commit.push true)").option("-g, --global", "Write to global ~/.assist.yml").action((key, value, options2) => configSet(key, value, options2));
|
|
11969
|
-
configCommand.command("get <key>").description("Get a config value").action(configGet);
|
|
11970
|
-
configCommand.command("list").description("List all config values").action(configList);
|
|
12076
|
+
registerConfig(program);
|
|
11971
12077
|
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().addHelpText("after", () => formatConfiguredCommands()).action((name, args) => run3(name, args));
|
|
11972
12078
|
runCommand.command("list").description("List configured run commands").action(listRunConfigs);
|
|
11973
12079
|
runCommand.command("add").description("Add a new run configuration to assist.yml").argument("<name>", "Name for the run configuration").argument("<command>", "Command to execute").argument("[args...]", "Static args to pass to the command").addHelpText(
|
|
@@ -11986,6 +12092,7 @@ program.command("notify").description(
|
|
|
11986
12092
|
program.command("update").description("Update assist to the latest version and sync commands").action(update2);
|
|
11987
12093
|
program.command("coverage").description("Print global statement coverage percentage").action(coverage);
|
|
11988
12094
|
program.command("screenshot").description("Capture a screenshot of a running application window").argument("<process>", "Name of the running process (e.g. notepad, code)").action(screenshot);
|
|
12095
|
+
registerActivity(program);
|
|
11989
12096
|
registerCliHook(program);
|
|
11990
12097
|
registerJira(program);
|
|
11991
12098
|
registerPrs(program);
|