qkpr 1.0.5 → 1.0.6

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 CHANGED
@@ -48,6 +48,8 @@ You can directly access the PR creation feature:
48
48
 
49
49
  ```bash
50
50
  qkpr pr
51
+ # or specify the target branch directly
52
+ qkpr pr main
51
53
  ```
52
54
 
53
55
  The CLI will interactively guide you through creating a pull request:
@@ -189,7 +191,11 @@ Shows an interactive menu to choose from all available features
189
191
  qkpr pr
190
192
  ```
191
193
 
192
- Directly create a pull request with interactive branch selection
194
+ Directly create a pull request with interactive branch selection. You can also specify the target branch directly:
195
+
196
+ ```bash
197
+ qkpr pr [branch]
198
+ ```
193
199
 
194
200
  ### Generate Commit Message
195
201
 
package/dist/index.mjs CHANGED
@@ -133,9 +133,10 @@ function getBranchCategory(branchName) {
133
133
  return "other";
134
134
  }
135
135
  /**
136
- * 获取分支详细信息(包含时间和分类)
136
+ * 获取分支详细信息(包含时间和分类)- 优化版本
137
137
  */
138
138
  function getBranchesWithInfo(branches) {
139
+ if (branches.length > 50) return getBranchesWithInfoBatch(branches);
139
140
  return branches.map((branchName) => {
140
141
  const { timestamp, formatted } = getBranchLastCommitTime(branchName);
141
142
  return {
@@ -147,6 +148,75 @@ function getBranchesWithInfo(branches) {
147
148
  });
148
149
  }
149
150
  /**
151
+ * 批量获取分支信息,性能优化版本
152
+ */
153
+ function getBranchesWithInfoBatch(branches) {
154
+ try {
155
+ const timestamps = execSync(branches.map((branch) => {
156
+ return `git log -1 --format=%ct origin/${branch} 2>/dev/null || echo "0"`;
157
+ }).join("; echo \"---\";"), {
158
+ encoding: "utf-8",
159
+ stdio: [
160
+ "pipe",
161
+ "pipe",
162
+ "ignore"
163
+ ]
164
+ }).split("---").map((line) => {
165
+ const timestamp = Number.parseInt(line.trim(), 10);
166
+ return Number.isNaN(timestamp) ? 0 : timestamp;
167
+ });
168
+ return branches.map((branchName, index) => {
169
+ const timestamp = timestamps[index] || 0;
170
+ const { formatted } = formatTimestamp(timestamp);
171
+ return {
172
+ name: branchName,
173
+ lastCommitTime: timestamp,
174
+ lastCommitTimeFormatted: formatted,
175
+ category: getBranchCategory(branchName)
176
+ };
177
+ });
178
+ } catch (error) {
179
+ console.warn("Batch fetch failed, falling back to individual fetch:", error);
180
+ return branches.map((branchName) => {
181
+ const { timestamp, formatted } = getBranchLastCommitTime(branchName);
182
+ return {
183
+ name: branchName,
184
+ lastCommitTime: timestamp,
185
+ lastCommitTimeFormatted: formatted,
186
+ category: getBranchCategory(branchName)
187
+ };
188
+ });
189
+ }
190
+ }
191
+ /**
192
+ * 格式化时间戳 - 提取为独立函数供批量版本使用
193
+ */
194
+ function formatTimestamp(timestamp) {
195
+ if (timestamp === 0) return {
196
+ timestamp: 0,
197
+ formatted: "unknown"
198
+ };
199
+ const date = /* @__PURE__ */ new Date(timestamp * 1e3);
200
+ const diffMs = (/* @__PURE__ */ new Date()).getTime() - date.getTime();
201
+ const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
202
+ let formatted;
203
+ if (diffDays === 0) {
204
+ const diffHours = Math.floor(diffMs / (1e3 * 60 * 60));
205
+ if (diffHours === 0) {
206
+ const diffMinutes = Math.floor(diffMs / (1e3 * 60));
207
+ formatted = diffMinutes <= 1 ? "just now" : `${diffMinutes}m ago`;
208
+ } else formatted = `${diffHours}h ago`;
209
+ } else if (diffDays === 1) formatted = "yesterday";
210
+ else if (diffDays < 7) formatted = `${diffDays}d ago`;
211
+ else if (diffDays < 30) formatted = `${Math.floor(diffDays / 7)}w ago`;
212
+ else if (diffDays < 365) formatted = `${Math.floor(diffDays / 30)}mo ago`;
213
+ else formatted = `${Math.floor(diffDays / 365)}y ago`;
214
+ return {
215
+ timestamp,
216
+ formatted
217
+ };
218
+ }
219
+ /**
150
220
  * 解析 Git remote URL
151
221
  */
152
222
  function parseRemoteUrl(remote) {
@@ -1506,10 +1576,7 @@ var AutocompletePinPrompt = class extends Base {
1506
1576
  this.selected = this.selected > 0 ? this.selected - 1 : len - 1;
1507
1577
  this.ensureSelectedInRange();
1508
1578
  this.render();
1509
- } else {
1510
- this.render();
1511
- if (this.lastSearchTerm !== this.rl.line) this.search(this.rl.line);
1512
- }
1579
+ } else if (this.lastSearchTerm !== this.rl.line) this.search(this.rl.line);
1513
1580
  }
1514
1581
  };
1515
1582
  /**
@@ -1567,6 +1634,21 @@ async function promptBranchSelection(branches, options) {
1567
1634
  const sortingPinnedBranches = getPinnedBranches();
1568
1635
  const searchBranches = async (_answers, input = "") => {
1569
1636
  const currentPinnedBranches = getPinnedBranches();
1637
+ const addCancelOption = (list) => {
1638
+ list.push(new inquirer.Separator(" "));
1639
+ list.push({
1640
+ name: dim(" [Cancel PR creation]"),
1641
+ value: "__CANCEL__",
1642
+ short: "Cancel"
1643
+ });
1644
+ };
1645
+ const createBranchChoice = (branch) => {
1646
+ return {
1647
+ name: `${currentPinnedBranches.includes(branch.name) ? "📌" : " "} ${branch.name.padEnd(45)} ${dim(`(${branch.lastCommitTimeFormatted})`)}`,
1648
+ value: branch.name,
1649
+ short: branch.name
1650
+ };
1651
+ };
1570
1652
  const topGroupBranches = branchInfos.filter((b) => sortingPinnedBranches.includes(b.name));
1571
1653
  const bottomGroupBranches = branchInfos.filter((b) => !sortingPinnedBranches.includes(b.name));
1572
1654
  const effectiveTopGroup = filterPinned ? [] : topGroupBranches;
@@ -1577,22 +1659,15 @@ async function promptBranchSelection(branches, options) {
1577
1659
  const displayBottomGroup = bottomGroupBranches.slice(0, 100);
1578
1660
  const choices = [];
1579
1661
  [...effectiveTopGroup, ...displayBottomGroup].forEach((branch) => {
1580
- const isPinnedNow = currentPinnedBranches.includes(branch.name);
1581
- choices.push({
1582
- name: `${isPinnedNow ? "📌" : " "} ${branch.name.padEnd(45)} ${dim(`(${branch.lastCommitTimeFormatted})`)}`,
1583
- value: branch.name,
1584
- short: branch.name
1585
- });
1662
+ choices.push(createBranchChoice(branch));
1586
1663
  });
1587
- if (!filterPinned) {
1588
- choices.push(new inquirer.Separator(" "));
1589
- choices.push({
1590
- name: dim(" [Cancel PR creation]"),
1591
- value: "__CANCEL__",
1592
- short: "Cancel"
1593
- });
1594
- }
1664
+ if (!filterPinned) addCancelOption(choices);
1595
1665
  const lowerInput = input.toLowerCase();
1666
+ if (lowerInput.trim()) {
1667
+ const searchChoices = branchInfos.filter((branch) => branch.name.toLowerCase().includes(lowerInput)).map(createBranchChoice);
1668
+ addCancelOption(searchChoices);
1669
+ return searchChoices;
1670
+ }
1596
1671
  return choices.filter((choice) => {
1597
1672
  if (!choice.value || choice.value === "__CANCEL__") return true;
1598
1673
  return choice.value.toLowerCase().includes(lowerInput);
@@ -1736,7 +1811,7 @@ async function handlePinCommand(branchName) {
1736
1811
  addPinnedBranch(branchName);
1737
1812
  console.log(green(`✅ Branch '${branchName}' has been pinned`));
1738
1813
  } else {
1739
- const { getAllBranches: getAllBranches$1 } = await import("./pr-C2AR97YR.mjs");
1814
+ const { getAllBranches: getAllBranches$1 } = await import("./pr-Cv5LeZ_A.mjs");
1740
1815
  const branches = getAllBranches$1();
1741
1816
  if (branches.length === 0) {
1742
1817
  console.log(yellow("⚠️ No branches found"));
@@ -1895,7 +1970,7 @@ async function promptForUpdate(packageName$1, result) {
1895
1970
  type: "confirm",
1896
1971
  name: "shouldUpdate",
1897
1972
  message: "Would you like to update now?",
1898
- default: false
1973
+ default: true
1899
1974
  }, {
1900
1975
  type: "list",
1901
1976
  name: "packageManager",
@@ -2134,7 +2209,7 @@ async function promptPushBranch(branchName) {
2134
2209
  /**
2135
2210
  * 处理 PR 命令
2136
2211
  */
2137
- async function handlePRCommand() {
2212
+ async function handlePRCommand(targetBranchArg) {
2138
2213
  printPRBanner();
2139
2214
  const gitInfo = getGitInfo();
2140
2215
  if (!gitInfo.isGitRepo) {
@@ -2163,7 +2238,12 @@ async function handlePRCommand() {
2163
2238
  console.log(yellow("⚠️ No branches found."));
2164
2239
  return;
2165
2240
  }
2166
- const targetBranch = await promptTargetBranch(branches, gitInfo.currentBranch);
2241
+ let targetBranch = null;
2242
+ if (targetBranchArg) if (branches.includes(targetBranchArg)) {
2243
+ targetBranch = targetBranchArg;
2244
+ console.log(green(`✅ Using specified target branch: ${targetBranch}\n`));
2245
+ } else console.log(yellow(`⚠️ Branch '${targetBranchArg}' not found. Falling back to interactive selection.`));
2246
+ if (!targetBranch) targetBranch = await promptTargetBranch(branches, gitInfo.currentBranch);
2167
2247
  if (!targetBranch) return;
2168
2248
  const prInfo = createPullRequest(gitInfo.currentBranch, targetBranch, gitInfo.remoteUrl);
2169
2249
  if (!prInfo) {
@@ -2207,8 +2287,13 @@ async function handlePRCommand() {
2207
2287
  }
2208
2288
  yargs(hideBin(process.argv)).scriptName("qkpr").usage("Usage: $0 <command> [options]").command("$0", "Show interactive menu to choose features", () => {}, async () => {
2209
2289
  await showMainMenu();
2210
- }).command("pr", "🔧 Create a Pull Request with interactive branch selection", () => {}, async () => {
2211
- await handlePRCommand();
2290
+ }).command("pr [branch]", "🔧 Create a Pull Request with interactive branch selection", (yargs$1) => {
2291
+ return yargs$1.positional("branch", {
2292
+ describe: "Target branch name",
2293
+ type: "string"
2294
+ });
2295
+ }, async (argv) => {
2296
+ await handlePRCommand(argv.branch);
2212
2297
  await checkAndNotifyUpdate(packageName, version);
2213
2298
  }).command("commit", "🤖 Generate commit message using AI", () => {}, async () => {
2214
2299
  await handleCommitCommand();
@@ -2250,4 +2335,4 @@ yargs(hideBin(process.argv)).scriptName("qkpr").usage("Usage: $0 <command> [opti
2250
2335
  }).version(version).alias("v", "version").help("h").alias("h", "help").epilog("For more information, visit https://github.com/KazooTTT/qkpr").argv;
2251
2336
 
2252
2337
  //#endregion
2253
- export { generatePRMessage as a, getBranchCategory as c, getCommitsBetweenBranches as d, getGitInfo as f, generateMergeBranchName as i, getBranchLastCommitTime as l, parseRemoteUrl as m, createMergeBranch as n, generatePRUrl as o, mergeSourceToMergeBranch as p, createPullRequest as r, getAllBranches as s, copyToClipboard as t, getBranchesWithInfo as u };
2338
+ export { generateMergeBranchName as a, getAllBranches as c, getBranchesWithInfo as d, getBranchesWithInfoBatch as f, parseRemoteUrl as g, mergeSourceToMergeBranch as h, formatTimestamp as i, getBranchCategory as l, getGitInfo as m, createMergeBranch as n, generatePRMessage as o, getCommitsBetweenBranches as p, createPullRequest as r, generatePRUrl as s, copyToClipboard as t, getBranchLastCommitTime as u };
@@ -0,0 +1,3 @@
1
+ import { a as generateMergeBranchName, c as getAllBranches, d as getBranchesWithInfo, f as getBranchesWithInfoBatch, g as parseRemoteUrl, h as mergeSourceToMergeBranch, i as formatTimestamp, l as getBranchCategory, m as getGitInfo, n as createMergeBranch, o as generatePRMessage, p as getCommitsBetweenBranches, r as createPullRequest, s as generatePRUrl, t as copyToClipboard, u as getBranchLastCommitTime } from "./index.mjs";
2
+
3
+ export { copyToClipboard, createMergeBranch, createPullRequest, formatTimestamp, generateMergeBranchName, generatePRMessage, generatePRUrl, getAllBranches, getBranchCategory, getBranchLastCommitTime, getBranchesWithInfo, getBranchesWithInfoBatch, getCommitsBetweenBranches, getGitInfo, mergeSourceToMergeBranch, parseRemoteUrl };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "qkpr",
3
3
  "type": "module",
4
- "version": "1.0.5",
4
+ "version": "1.0.6",
5
5
  "description": "Create a Pull Request with interactive branch selection",
6
6
  "author": "KazooTTT <work@kazoottt.top>",
7
7
  "license": "MIT",
@@ -1,3 +0,0 @@
1
- import { a as generatePRMessage, c as getBranchCategory, d as getCommitsBetweenBranches, f as getGitInfo, i as generateMergeBranchName, l as getBranchLastCommitTime, m as parseRemoteUrl, n as createMergeBranch, o as generatePRUrl, p as mergeSourceToMergeBranch, r as createPullRequest, s as getAllBranches, t as copyToClipboard, u as getBranchesWithInfo } from "./index.mjs";
2
-
3
- export { copyToClipboard, createMergeBranch, createPullRequest, generateMergeBranchName, generatePRMessage, generatePRUrl, getAllBranches, getBranchCategory, getBranchLastCommitTime, getBranchesWithInfo, getCommitsBetweenBranches, getGitInfo, mergeSourceToMergeBranch, parseRemoteUrl };