vde-worktree 0.0.18 → 0.0.19

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.ja.md CHANGED
@@ -142,6 +142,7 @@ vw list --full-path
142
142
 
143
143
  - Git の porcelain 情報から worktree 一覧を取得
144
144
  - branch/path/dirty/lock/merged/PR/upstream を表示
145
+ - JSON メタデータには non-base branch ごとに `pr.status` と `pr.url` を含む
145
146
  - テーブル表示では長い `path` は端末幅に合わせて `…` で省略
146
147
  - `--full-path` でテーブル表示の path 省略を無効化
147
148
  - `--no-gh` 指定時は PR 状態判定をスキップ(`pr.status` は `unknown`、`merged.byPR` は `null`)
@@ -428,6 +429,7 @@ vw completion zsh --install
428
429
  - `merged.byPR`: GitHub PR merged 判定(`gh`)
429
430
  - `merged.overall`: 最終判定
430
431
  - `pr.status`: PR 状態(`none` / `open` / `merged` / `closed_unmerged` / `unknown`)
432
+ - `pr.url`: branch の最新 PR URL(取得不可時は `null`)
431
433
 
432
434
  `overall` ポリシー:
433
435
 
package/README.md CHANGED
@@ -142,6 +142,7 @@ What it does:
142
142
 
143
143
  - Lists all worktrees from Git porcelain output
144
144
  - Includes metadata such as branch, path, dirty, lock, merged, PR status, and upstream status
145
+ - JSON metadata includes `pr.status` and `pr.url` for each non-base branch
145
146
  - In table output, long `path` values are truncated with `…` to fit terminal width by default
146
147
  - Use `--full-path` to disable path truncation in table output
147
148
  - With `--no-gh`, skips PR status checks (`pr.status` becomes `unknown`, `merged.byPR` becomes `null`)
@@ -428,6 +429,7 @@ Each worktree reports:
428
429
  - `merged.byPR`: PR-based merged check via GitHub CLI
429
430
  - `merged.overall`: final decision
430
431
  - `pr.status`: PR state (`none` / `open` / `merged` / `closed_unmerged` / `unknown`)
432
+ - `pr.url`: latest PR URL for the branch (`null` when unavailable)
431
433
 
432
434
  Overall policy:
433
435
 
package/dist/index.mjs CHANGED
@@ -853,8 +853,11 @@ const toTargetBranches = ({ branches, baseBranch }) => {
853
853
  }
854
854
  return [...uniqueBranches];
855
855
  };
856
- const buildUnknownPrStatusMap = (branches) => {
857
- return new Map(branches.map((branch) => [branch, "unknown"]));
856
+ const buildUnknownPrStateMap = (branches) => {
857
+ return new Map(branches.map((branch) => [branch, {
858
+ status: "unknown",
859
+ url: null
860
+ }]));
858
861
  };
859
862
  const parseUpdatedAtMillis = (value) => {
860
863
  if (typeof value !== "string" || value.length === 0) return Number.NEGATIVE_INFINITY;
@@ -870,7 +873,11 @@ const toPrStatus = (record) => {
870
873
  if (state === "CLOSED") return "closed_unmerged";
871
874
  return "unknown";
872
875
  };
873
- const parsePrStatusByBranch = ({ raw, targetBranches }) => {
876
+ const toPrUrl = (record) => {
877
+ if (typeof record.url === "string" && record.url.length > 0) return record.url;
878
+ return null;
879
+ };
880
+ const parsePrStateByBranch = ({ raw, targetBranches }) => {
874
881
  try {
875
882
  const parsed = JSON.parse(raw);
876
883
  if (Array.isArray(parsed) !== true) return null;
@@ -882,31 +889,43 @@ const parsePrStatusByBranch = ({ raw, targetBranches }) => {
882
889
  if (targetBranchSet.has(record.headRefName) !== true) continue;
883
890
  const updatedAtMillis = parseUpdatedAtMillis(record.updatedAt);
884
891
  const status = toPrStatus(record);
892
+ const url = toPrUrl(record);
885
893
  const current = latestByBranch.get(record.headRefName);
886
894
  if (current === void 0 || updatedAtMillis > current.updatedAtMillis || updatedAtMillis === current.updatedAtMillis && index > current.index) latestByBranch.set(record.headRefName, {
887
895
  updatedAtMillis,
888
896
  index,
889
- status
897
+ status,
898
+ url
890
899
  });
891
900
  }
892
901
  const result = /* @__PURE__ */ new Map();
893
902
  for (const branch of targetBranches) {
894
903
  const latest = latestByBranch.get(branch);
895
- result.set(branch, latest?.status ?? "none");
904
+ if (latest === void 0) {
905
+ result.set(branch, {
906
+ status: "none",
907
+ url: null
908
+ });
909
+ continue;
910
+ }
911
+ result.set(branch, {
912
+ status: latest.status,
913
+ url: latest.url
914
+ });
896
915
  }
897
916
  return result;
898
917
  } catch {
899
918
  return null;
900
919
  }
901
920
  };
902
- const resolvePrStatusByBranchBatch = async ({ repoRoot, baseBranch, branches, enabled = true, runGh = defaultRunGh }) => {
921
+ const resolvePrStateByBranchBatch = async ({ repoRoot, baseBranch, branches, enabled = true, runGh = defaultRunGh }) => {
903
922
  if (baseBranch === null) return /* @__PURE__ */ new Map();
904
923
  const targetBranches = toTargetBranches({
905
924
  branches,
906
925
  baseBranch
907
926
  });
908
927
  if (targetBranches.length === 0) return /* @__PURE__ */ new Map();
909
- if (enabled !== true) return buildUnknownPrStatusMap(targetBranches);
928
+ if (enabled !== true) return buildUnknownPrStateMap(targetBranches);
910
929
  try {
911
930
  const result = await runGh({
912
931
  cwd: repoRoot,
@@ -922,19 +941,19 @@ const resolvePrStatusByBranchBatch = async ({ repoRoot, baseBranch, branches, en
922
941
  "--limit",
923
942
  "1000",
924
943
  "--json",
925
- "headRefName,state,mergedAt,updatedAt"
944
+ "headRefName,state,mergedAt,updatedAt,url"
926
945
  ]
927
946
  });
928
- if (result.exitCode !== 0) return buildUnknownPrStatusMap(targetBranches);
929
- const prStatusByBranch = parsePrStatusByBranch({
947
+ if (result.exitCode !== 0) return buildUnknownPrStateMap(targetBranches);
948
+ const prStatusByBranch = parsePrStateByBranch({
930
949
  raw: result.stdout,
931
950
  targetBranches
932
951
  });
933
- if (prStatusByBranch === null) return buildUnknownPrStatusMap(targetBranches);
952
+ if (prStatusByBranch === null) return buildUnknownPrStateMap(targetBranches);
934
953
  return prStatusByBranch;
935
954
  } catch (error) {
936
- if (error.code === "ENOENT") return buildUnknownPrStatusMap(targetBranches);
937
- return buildUnknownPrStatusMap(targetBranches);
955
+ if (error.code === "ENOENT") return buildUnknownPrStateMap(targetBranches);
956
+ return buildUnknownPrStateMap(targetBranches);
938
957
  }
939
958
  };
940
959
 
@@ -1133,7 +1152,7 @@ const resolveLifecycleFromReflog = async ({ repoRoot, branch, baseBranch }) => {
1133
1152
  divergedHead: latestWorkHead
1134
1153
  };
1135
1154
  };
1136
- const resolveMergedState = async ({ repoRoot, branch, head, baseBranch, prStatusByBranch }) => {
1155
+ const resolveMergedState = async ({ repoRoot, branch, head, baseBranch, prStateByBranch }) => {
1137
1156
  if (branch === null) return {
1138
1157
  byAncestry: null,
1139
1158
  byPR: null,
@@ -1154,7 +1173,7 @@ const resolveMergedState = async ({ repoRoot, branch, head, baseBranch, prStatus
1154
1173
  if (result.exitCode === 0) byAncestry = true;
1155
1174
  else if (result.exitCode === 1) byAncestry = false;
1156
1175
  }
1157
- const prStatus = branch === baseBranch ? null : prStatusByBranch.get(branch) ?? null;
1176
+ const prStatus = branch === baseBranch ? null : prStateByBranch.get(branch)?.status ?? null;
1158
1177
  let byPR = null;
1159
1178
  if (prStatus === "merged") byPR = true;
1160
1179
  else if (prStatus === "none" || prStatus === "open" || prStatus === "closed_unmerged") byPR = false;
@@ -1208,9 +1227,16 @@ const resolveMergedState = async ({ repoRoot, branch, head, baseBranch, prStatus
1208
1227
  })
1209
1228
  };
1210
1229
  };
1211
- const resolvePrState = ({ branch, baseBranch, prStatusByBranch }) => {
1212
- if (branch === null || branch === baseBranch) return { status: null };
1213
- return { status: prStatusByBranch.get(branch) ?? null };
1230
+ const resolveWorktreePrState = ({ branch, baseBranch, prStateByBranch }) => {
1231
+ if (branch === null || branch === baseBranch) return {
1232
+ status: null,
1233
+ url: null
1234
+ };
1235
+ const prState = prStateByBranch.get(branch);
1236
+ return {
1237
+ status: prState?.status ?? null,
1238
+ url: prState?.url ?? null
1239
+ };
1214
1240
  };
1215
1241
  const resolveMergedOverall = ({ byAncestry, byPR, byLifecycle }) => {
1216
1242
  if (byPR === true || byLifecycle === true) return true;
@@ -1258,7 +1284,7 @@ const resolveUpstreamState = async (worktreePath) => {
1258
1284
  remote: upstreamRef.stdout.trim()
1259
1285
  };
1260
1286
  };
1261
- const enrichWorktree = async ({ repoRoot, worktree, baseBranch, prStatusByBranch }) => {
1287
+ const enrichWorktree = async ({ repoRoot, worktree, baseBranch, prStateByBranch }) => {
1262
1288
  const [dirty, locked, merged, upstream] = await Promise.all([
1263
1289
  resolveDirty(worktree.path),
1264
1290
  resolveLockState({
@@ -1270,14 +1296,14 @@ const enrichWorktree = async ({ repoRoot, worktree, baseBranch, prStatusByBranch
1270
1296
  branch: worktree.branch,
1271
1297
  head: worktree.head,
1272
1298
  baseBranch,
1273
- prStatusByBranch
1299
+ prStateByBranch
1274
1300
  }),
1275
1301
  resolveUpstreamState(worktree.path)
1276
1302
  ]);
1277
- const pr = resolvePrState({
1303
+ const pr = resolveWorktreePrState({
1278
1304
  branch: worktree.branch,
1279
1305
  baseBranch,
1280
- prStatusByBranch
1306
+ prStateByBranch
1281
1307
  });
1282
1308
  return {
1283
1309
  branch: worktree.branch,
@@ -1296,7 +1322,7 @@ const collectWorktreeSnapshot = async (repoRoot, { noGh = false } = {}) => {
1296
1322
  listGitWorktrees(repoRoot),
1297
1323
  resolveEnableGh(repoRoot)
1298
1324
  ]);
1299
- const prStatusByBranch = await resolvePrStatusByBranchBatch({
1325
+ const prStateByBranch = await resolvePrStateByBranchBatch({
1300
1326
  repoRoot,
1301
1327
  baseBranch,
1302
1328
  branches: worktrees.map((worktree) => worktree.branch),
@@ -1310,7 +1336,7 @@ const collectWorktreeSnapshot = async (repoRoot, { noGh = false } = {}) => {
1310
1336
  repoRoot,
1311
1337
  worktree,
1312
1338
  baseBranch,
1313
- prStatusByBranch
1339
+ prStateByBranch
1314
1340
  });
1315
1341
  }))
1316
1342
  };
@@ -1665,7 +1691,7 @@ const commandHelpEntries = [
1665
1691
  details: [
1666
1692
  "Table output includes branch, path, dirty, lock, merged, PR state, and ahead/behind vs base branch.",
1667
1693
  "By default, long path values are truncated to fit terminal width.",
1668
- "JSON output includes PR and upstream metadata fields."
1694
+ "JSON output includes PR status/url and upstream metadata fields."
1669
1695
  ],
1670
1696
  options: ["--full-path"]
1671
1697
  },