@quikcommit/cli 4.1.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +63 -25
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -46,7 +46,7 @@ var init_constants = __esm({
|
|
|
46
46
|
CREDENTIALS_FILE = "credentials";
|
|
47
47
|
CONFIG_FILE = "config.json";
|
|
48
48
|
DEFAULT_API_URL = "https://api.quikcommit.dev";
|
|
49
|
-
DEVICE_POLL_INTERVAL =
|
|
49
|
+
DEVICE_POLL_INTERVAL = 1e3;
|
|
50
50
|
DEVICE_FLOW_TIMEOUT = 6e5;
|
|
51
51
|
}
|
|
52
52
|
});
|
|
@@ -295,6 +295,15 @@ function hasStagedChanges() {
|
|
|
295
295
|
});
|
|
296
296
|
return output.trim().length > 0;
|
|
297
297
|
}
|
|
298
|
+
function getUnstagedFiles() {
|
|
299
|
+
const output = (0, import_child_process.execFileSync)("git", ["status", "--porcelain"], {
|
|
300
|
+
encoding: "utf-8"
|
|
301
|
+
});
|
|
302
|
+
return output.trim().split("\n").filter(Boolean).filter((line) => !line.startsWith("??"));
|
|
303
|
+
}
|
|
304
|
+
function stageAll() {
|
|
305
|
+
(0, import_child_process.execFileSync)("git", ["add", "-u"], { stdio: "pipe" });
|
|
306
|
+
}
|
|
298
307
|
function gitCommit(message) {
|
|
299
308
|
const tmpDir = (0, import_fs2.mkdtempSync)((0, import_path2.join)((0, import_os2.tmpdir)(), "qc-"));
|
|
300
309
|
const tmpFile = (0, import_path2.join)(tmpDir, "commit.txt");
|
|
@@ -574,26 +583,39 @@ async function runLogin() {
|
|
|
574
583
|
console.log(authUrl);
|
|
575
584
|
console.log("");
|
|
576
585
|
}
|
|
586
|
+
let frame = 0;
|
|
587
|
+
const spinner = setInterval(() => {
|
|
588
|
+
const elapsed = Math.floor((Date.now() - startTime) / 1e3);
|
|
589
|
+
process.stderr.write(
|
|
590
|
+
`\r${SPINNER_FRAMES[frame++ % SPINNER_FRAMES.length]} Waiting for authorization... (${elapsed}s)`
|
|
591
|
+
);
|
|
592
|
+
}, 80);
|
|
577
593
|
const startTime = Date.now();
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
594
|
+
try {
|
|
595
|
+
while (Date.now() - startTime < DEVICE_FLOW_TIMEOUT) {
|
|
596
|
+
try {
|
|
597
|
+
const res = await fetch(
|
|
598
|
+
`${API_URL}/v1/auth/device/poll?code=${encodeURIComponent(code)}`
|
|
599
|
+
);
|
|
600
|
+
const data = await res.json();
|
|
601
|
+
if (data.status === "complete" && data.api_key) {
|
|
602
|
+
saveApiKey(data.api_key);
|
|
603
|
+
process.stderr.write("\r\x1B[2K");
|
|
604
|
+
console.log("Successfully logged in!");
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
} catch {
|
|
588
608
|
}
|
|
589
|
-
|
|
609
|
+
await new Promise((r) => setTimeout(r, DEVICE_POLL_INTERVAL));
|
|
590
610
|
}
|
|
591
|
-
|
|
611
|
+
process.stderr.write("\r\x1B[2K");
|
|
612
|
+
console.error("Login timed out. Please try again.");
|
|
613
|
+
process.exit(1);
|
|
614
|
+
} finally {
|
|
615
|
+
clearInterval(spinner);
|
|
592
616
|
}
|
|
593
|
-
console.error("Login timed out. Please try again.");
|
|
594
|
-
process.exit(1);
|
|
595
617
|
}
|
|
596
|
-
var import_child_process3, import_os3, API_URL, DASHBOARD_URL;
|
|
618
|
+
var import_child_process3, import_os3, API_URL, DASHBOARD_URL, SPINNER_FRAMES;
|
|
597
619
|
var init_login = __esm({
|
|
598
620
|
"src/commands/login.ts"() {
|
|
599
621
|
"use strict";
|
|
@@ -603,6 +625,7 @@ var init_login = __esm({
|
|
|
603
625
|
init_dist();
|
|
604
626
|
API_URL = process.env.QC_API_URL ?? DEFAULT_API_URL;
|
|
605
627
|
DASHBOARD_URL = "https://app.quikcommit.dev";
|
|
628
|
+
SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
606
629
|
}
|
|
607
630
|
});
|
|
608
631
|
|
|
@@ -1319,7 +1342,7 @@ function config(args) {
|
|
|
1319
1342
|
const value = args[2];
|
|
1320
1343
|
if (!key || !value) {
|
|
1321
1344
|
console.error("Usage: qc config set <key> <value>");
|
|
1322
|
-
console.error(" Keys: model, api_url, provider");
|
|
1345
|
+
console.error(" Keys: model, api_url, provider, auto_stage");
|
|
1323
1346
|
process.exit(1);
|
|
1324
1347
|
}
|
|
1325
1348
|
setConfig(key, value);
|
|
@@ -1339,8 +1362,9 @@ function showConfig() {
|
|
|
1339
1362
|
console.log("Current configuration:");
|
|
1340
1363
|
console.log(` model: ${cfg.model ?? "(default for plan)"}`);
|
|
1341
1364
|
console.log(` api_url: ${cfg.apiUrl ?? DEFAULT_API_URL}`);
|
|
1342
|
-
console.log(` provider:
|
|
1343
|
-
console.log(`
|
|
1365
|
+
console.log(` provider: ${cfg.provider ?? "(default)"}`);
|
|
1366
|
+
console.log(` auto_stage: ${cfg.autoStage ? "true" : "false"}`);
|
|
1367
|
+
console.log(` auth: ${apiKey ? "****" : "not set"}`);
|
|
1344
1368
|
if (cfg.excludes?.length) {
|
|
1345
1369
|
console.log(` excludes: ${cfg.excludes.join(", ")}`);
|
|
1346
1370
|
}
|
|
@@ -1365,9 +1389,11 @@ function setConfig(key, value) {
|
|
|
1365
1389
|
console.error("Invalid URL:", value);
|
|
1366
1390
|
process.exit(1);
|
|
1367
1391
|
}
|
|
1392
|
+
} else if (key === "auto_stage") {
|
|
1393
|
+
updates.autoStage = value === "true" || value === "1";
|
|
1368
1394
|
} else {
|
|
1369
1395
|
console.error(`Unknown key: ${key}`);
|
|
1370
|
-
console.error(" Keys: model, api_url, provider");
|
|
1396
|
+
console.error(" Keys: model, api_url, provider, auto_stage");
|
|
1371
1397
|
process.exit(1);
|
|
1372
1398
|
}
|
|
1373
1399
|
saveConfig({ ...cfg, ...updates });
|
|
@@ -1686,6 +1712,7 @@ Usage:
|
|
|
1686
1712
|
|
|
1687
1713
|
Options:
|
|
1688
1714
|
-h, --help Show this help
|
|
1715
|
+
-a, --all Stage all tracked changes before generating
|
|
1689
1716
|
-m, --message-only Generate message only
|
|
1690
1717
|
-p, --push Commit and push after generating
|
|
1691
1718
|
--api-key <key> Use this API key (overrides credentials file)
|
|
@@ -1706,6 +1733,7 @@ Commands:
|
|
|
1706
1733
|
`;
|
|
1707
1734
|
function parseArgs(args) {
|
|
1708
1735
|
let command = "commit";
|
|
1736
|
+
let all = false;
|
|
1709
1737
|
let messageOnly = false;
|
|
1710
1738
|
let push = false;
|
|
1711
1739
|
let apiKey;
|
|
@@ -1723,6 +1751,8 @@ function parseArgs(args) {
|
|
|
1723
1751
|
const arg = args[i];
|
|
1724
1752
|
if (arg === "-h" || arg === "--help") {
|
|
1725
1753
|
command = "help";
|
|
1754
|
+
} else if (arg === "-a" || arg === "--all") {
|
|
1755
|
+
all = true;
|
|
1726
1756
|
} else if (arg === "-m" || arg === "--message-only") {
|
|
1727
1757
|
messageOnly = true;
|
|
1728
1758
|
} else if (arg === "-p" || arg === "--push") {
|
|
@@ -1788,17 +1818,26 @@ function parseArgs(args) {
|
|
|
1788
1818
|
}
|
|
1789
1819
|
}
|
|
1790
1820
|
}
|
|
1791
|
-
return { command, messageOnly, push, apiKey, base, create, from, to, write, version, uninstall, hookMode, model, local };
|
|
1821
|
+
return { command, all, messageOnly, push, apiKey, base, create, from, to, write, version, uninstall, hookMode, model, local };
|
|
1792
1822
|
}
|
|
1793
|
-
async function runCommit(messageOnly, push, apiKeyFlag, hookMode = false, modelFlag) {
|
|
1823
|
+
async function runCommit(messageOnly, push, apiKeyFlag, hookMode = false, modelFlag, stageAll_) {
|
|
1794
1824
|
const log = hookMode ? () => {
|
|
1795
1825
|
} : (msg) => console.error(msg);
|
|
1796
1826
|
if (!isGitRepo()) {
|
|
1797
1827
|
log("Error: Not a git repository.");
|
|
1798
1828
|
process.exit(1);
|
|
1799
1829
|
}
|
|
1830
|
+
const config2 = getConfig();
|
|
1831
|
+
if (stageAll_ || config2.autoStage) {
|
|
1832
|
+
stageAll();
|
|
1833
|
+
}
|
|
1800
1834
|
if (!hasStagedChanges()) {
|
|
1801
|
-
|
|
1835
|
+
const unstaged = getUnstagedFiles();
|
|
1836
|
+
if (unstaged.length > 0) {
|
|
1837
|
+
log("Error: No staged changes. Use `qc -a` to stage tracked files, or `git add` manually.");
|
|
1838
|
+
} else {
|
|
1839
|
+
log("Error: No changes to commit.");
|
|
1840
|
+
}
|
|
1802
1841
|
process.exit(1);
|
|
1803
1842
|
}
|
|
1804
1843
|
const apiKey = apiKeyFlag ?? getApiKey();
|
|
@@ -1806,7 +1845,6 @@ async function runCommit(messageOnly, push, apiKeyFlag, hookMode = false, modelF
|
|
|
1806
1845
|
log("Error: Not authenticated. Run `qc login` first.");
|
|
1807
1846
|
process.exit(1);
|
|
1808
1847
|
}
|
|
1809
|
-
const config2 = getConfig();
|
|
1810
1848
|
const model = modelFlag ?? config2.model;
|
|
1811
1849
|
const excludes = config2.excludes ?? [];
|
|
1812
1850
|
const diff = getStagedDiff(excludes);
|
|
@@ -1933,7 +1971,7 @@ async function main() {
|
|
|
1933
1971
|
return;
|
|
1934
1972
|
}
|
|
1935
1973
|
}
|
|
1936
|
-
await runCommit(messageOnly, push, apiKey, values.hookMode, values.model);
|
|
1974
|
+
await runCommit(messageOnly, push, apiKey, values.hookMode, values.model, values.all);
|
|
1937
1975
|
}
|
|
1938
1976
|
main().catch((err) => {
|
|
1939
1977
|
const args = process.argv.slice(2);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quikcommit/cli",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "AI-powered conventional commit messages",
|
|
5
5
|
"bin": {
|
|
6
6
|
"qc": "./dist/index.js"
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"esbuild": "^0.27.3",
|
|
31
31
|
"typescript": "^5.9.3",
|
|
32
32
|
"vitest": "^4.0.18",
|
|
33
|
-
"@quikcommit/shared": "4.
|
|
33
|
+
"@quikcommit/shared": "4.3.0"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "node build.mjs",
|