Skip to content

Commit 7224baa

Browse files
committed
fix(lint): eliminate all noNonNullAssertion warnings
Biome forbids `\!` postfix assertions. Restructure to narrow naturally: - git-inventory-tool.ts: replace loose fixedRemote/fixedBranch + useFixed boolean with a discriminated Upstream union ({mode:"fixed", remote, branch} | {mode:"auto"}). TS narrows on `upstream.mode === "fixed"`, eliminating all six `\!` sites. - git.ts (asyncPool): restore the `item === undefined` guard that was removed in a3d1731 — it's the only biome-compliant way to narrow under noUncheckedIndexedAccess. - inventory.ts: extract `single` variable with a ternary + undefined check instead of `lines[0]\!`.
1 parent 3224a08 commit 7224baa

File tree

3 files changed

+32
-49
lines changed

3 files changed

+32
-49
lines changed

src/server/git-inventory-tool.ts

Lines changed: 26 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,27 @@ export function registerGitInventoryTool(server: FastMCP): void {
4242
return jsonRespond(pre.error);
4343
}
4444

45-
const fixedRemote = args.remote;
46-
const fixedBranch = args.branch;
47-
const hasRemote = fixedRemote !== undefined && fixedRemote.trim() !== "";
48-
const hasBranch = fixedBranch !== undefined && fixedBranch.trim() !== "";
45+
const rawRemote = args.remote?.trim();
46+
const rawBranch = args.branch?.trim();
47+
const hasRemote = rawRemote !== undefined && rawRemote !== "";
48+
const hasBranch = rawBranch !== undefined && rawBranch !== "";
4949
if (hasRemote !== hasBranch) {
5050
return jsonRespond({ error: "remote_branch_mismatch" });
5151
}
52-
const useFixed = hasRemote && hasBranch;
53-
if (useFixed) {
54-
if (
55-
!isSafeGitUpstreamToken(fixedRemote!.trim()) ||
56-
!isSafeGitUpstreamToken(fixedBranch!.trim())
57-
) {
52+
53+
type Upstream =
54+
| { mode: "fixed"; remote: string; branch: string }
55+
| { mode: "auto"; remote?: undefined; branch?: undefined };
56+
57+
let upstream: Upstream = { mode: "auto" };
58+
if (hasRemote && hasBranch && rawRemote && rawBranch) {
59+
if (!isSafeGitUpstreamToken(rawRemote) || !isSafeGitUpstreamToken(rawBranch)) {
5860
return jsonRespond({ error: "invalid_remote_or_branch" });
5961
}
62+
upstream = { mode: "fixed", remote: rawRemote, branch: rawBranch };
6063
}
61-
const upstreamMode: "auto" | "fixed" = useFixed ? "fixed" : "auto";
64+
65+
const useFixed = upstream.mode === "fixed";
6266

6367
const allJson: {
6468
workspace_root: string;
@@ -76,17 +80,9 @@ export function registerGitInventoryTool(server: FastMCP): void {
7680
if (args.format === "json") {
7781
allJson.push({
7882
workspace_root: workspaceRoot,
79-
...(useFixed
80-
? {
81-
upstream: {
82-
mode: "fixed" as const,
83-
remote: fixedRemote!,
84-
branch: fixedBranch!,
85-
},
86-
}
87-
: {}),
83+
...(upstream.mode === "fixed" ? { upstream } : {}),
8884
entries: [
89-
makeSkipEntry(workspaceRoot, workspaceRoot, upstreamMode, JSON.stringify(err)),
85+
makeSkipEntry(workspaceRoot, workspaceRoot, upstream.mode, JSON.stringify(err)),
9086
],
9187
});
9288
} else {
@@ -117,7 +113,7 @@ export function registerGitInventoryTool(server: FastMCP): void {
117113
}
118114

119115
const headerNote = useFixed
120-
? `upstream (fixed): ${fixedRemote}/${fixedBranch}`
116+
? `upstream (fixed): ${upstream.remote}/${upstream.branch}`
121117
: "upstream: @{u}";
122118

123119
const entries: InventoryEntryJson[] = [];
@@ -128,34 +124,26 @@ export function registerGitInventoryTool(server: FastMCP): void {
128124
const { abs, underTop } = validateRepoPath(rel, top);
129125
if (!underTop) {
130126
entries.push(
131-
makeSkipEntry(rel, abs, upstreamMode, "(path escapes git toplevel — rejected)"),
127+
makeSkipEntry(rel, abs, upstream.mode, "(path escapes git toplevel — rejected)"),
132128
);
133129
continue;
134130
}
135131
if (!gitRevParseGitDir(abs)) {
136-
entries.push(makeSkipEntry(rel, abs, upstreamMode, "(not a git work tree — skip)"));
132+
entries.push(makeSkipEntry(rel, abs, upstream.mode, "(not a git work tree — skip)"));
137133
continue;
138134
}
139135
jobs.push({ label: rel, abs });
140136
}
141137
const computed = await asyncPool(jobs, GIT_SUBPROCESS_PARALLELISM, (j) =>
142-
collectInventoryEntry(
143-
j.label,
144-
j.abs,
145-
useFixed ? fixedRemote : undefined,
146-
useFixed ? fixedBranch : undefined,
147-
),
138+
collectInventoryEntry(j.label, j.abs, upstream.remote, upstream.branch),
148139
);
149140
entries.push(...computed);
150141
} else if (!gitRevParseGitDir(top)) {
151-
entries.push(makeSkipEntry(".", top, upstreamMode, "(not a git work tree — unexpected)"));
152-
} else {
153-
const one = await collectInventoryEntry(
154-
".",
155-
top,
156-
useFixed ? fixedRemote : undefined,
157-
useFixed ? fixedBranch : undefined,
142+
entries.push(
143+
makeSkipEntry(".", top, upstream.mode, "(not a git work tree — unexpected)"),
158144
);
145+
} else {
146+
const one = await collectInventoryEntry(".", top, upstream.remote, upstream.branch);
159147
entries.push(one);
160148
}
161149

@@ -167,15 +155,7 @@ export function registerGitInventoryTool(server: FastMCP): void {
167155
nestedRootsTruncated: true,
168156
nestedRootsOmittedCount,
169157
}),
170-
...(useFixed
171-
? {
172-
upstream: {
173-
mode: "fixed" as const,
174-
remote: fixedRemote!,
175-
branch: fixedBranch!,
176-
},
177-
}
178-
: {}),
158+
...(upstream.mode === "fixed" ? { upstream } : {}),
179159
entries,
180160
});
181161
} else {

src/server/git.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ export async function asyncPool<T, R>(
110110
for (;;) {
111111
const i = next++;
112112
if (i >= items.length) break;
113-
results[i] = await fn(items[i]!);
113+
const item = items[i];
114+
if (item === undefined) break;
115+
results[i] = await fn(item);
114116
}
115117
}
116118
const n = Math.min(Math.max(1, concurrency), Math.max(1, items.length));

src/server/inventory.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ export function buildInventorySectionMarkdown(e: InventoryEntryJson): string[] {
4343
} else if (e.upstreamNote) {
4444
lines.push(`upstream: ${e.upstreamNote}`);
4545
}
46-
if (lines.length === 1 && !lines[0]!.includes("\n")) {
47-
return ["", header, lines[0]!];
46+
const single = lines.length === 1 ? lines[0] : undefined;
47+
if (single !== undefined && !single.includes("\n")) {
48+
return ["", header, single];
4849
}
4950
return ["", header, "```text", lines.join("\n"), "```"];
5051
}

0 commit comments

Comments
 (0)